1 /* @source ajlist *************************************************************
2 **
3 ** AJAX List functions
4 ** These functions create and control linked lists.
5 **
6 ** @author Copyright (C) 1998 Ian Longden
7 ** @version $Revision: 1.92 $
8 ** @modified 2001 Alan Bleasby
9 ** Changed lists to be double-linked, completely rewrote
10 ** iterator handling and added back-iteration functions.
11 ** Operation of ajListInsert made more intuitive.
12 ** @modified $Date: 2012/07/03 16:21:04 $ by $Author: rice $
13 ** @@
14 **
15 ** This library is free software; you can redistribute it and/or
16 ** modify it under the terms of the GNU Lesser General Public
17 ** License as published by the Free Software Foundation; either
18 ** version 2.1 of the License, or (at your option) any later version.
19 **
20 ** This library is distributed in the hope that it will be useful,
21 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
22 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
23 ** Lesser General Public License for more details.
24 **
25 ** You should have received a copy of the GNU Lesser General Public
26 ** License along with this library; if not, write to the Free Software
27 ** Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
28 ** MA 02110-1301, USA.
29 **
30 ******************************************************************************/
31
32
33
34
35 /*Library* List Library *******************************************************
36 **
37 ** All lists consist of an initial header followed by the body
38 ** of the list. The Header has three variables:-
39 ** 1) First - a pointer to the linked list (see body)
40 ** 2) Last - a pointer to the a dummy last node object with next = self
41 ** 3) Count - which holds the number of objects in the linked list
42 ** (NOT including the header)
43 ** 4) Type - the list type
44 **
45 ** The body of the linked list contains three variables:-
46 ** 1) Next - a pointer to the next linked list object or NULL
47 ** 2) Prev - a pointer to the previous linked list object or NULL
48 ** 3) item - a void pointer to the data.
49 ******************************************************************************/
50
51 /* ========================================================================= */
52 /* ============================= include files ============================= */
53 /* ========================================================================= */
54
55
56 #include "ajlib.h"
57
58 #include "ajlist.h"
59 #include "ajassert.h"
60
61 #include <stddef.h>
62 #include <stdarg.h>
63 #include <stdio.h>
64 #include <stdlib.h>
65
66
67
68
69 /* ========================================================================= */
70 /* =============================== constants =============================== */
71 /* ========================================================================= */
72
73
74
75
76 /* ========================================================================= */
77 /* =========================== global variables ============================ */
78 /* ========================================================================= */
79
80
81
82
83 /* ========================================================================= */
84 /* ============================= private data ============================== */
85 /* ========================================================================= */
86
87
88
89
90 /* ========================================================================= */
91 /* =========================== private constants =========================== */
92 /* ========================================================================= */
93
94
95
96
97 /* ========================================================================= */
98 /* =========================== private variables =========================== */
99 /* ========================================================================= */
100
101 #ifdef AJ_SAVESTATS
102 static ajint listNewCnt = 0;
103 static ajint listDelCnt = 0;
104 static ajulong listMaxNum = 0UL;
105 static ajulong listNodeCnt = 0UL;
106 static ajint listIterNewCnt = 0;
107 static ajint listIterDelCnt = 0;
108 #endif
109
110 static ajulong listFreeNext = 0UL;
111 static ajulong listFreeMax = 0UL;
112 static AjPListNode* listFreeSet = NULL;
113
114
115
116
117 /* ========================================================================= */
118 /* =========================== private functions =========================== */
119 /* ========================================================================= */
120
121 static AjPList listNew(void (*itemdel)(void** Pitem));
122 static void listInsertNode(AjPListNode* Pnode, void* item);
123 static AjPListNode listDummyNode(AjPListNode* Pnode);
124 static void listNodesTrace(const AjPListNode node);
125 static AjBool listNodeDel(AjPListNode* Pnode);
126 static void* listNodeItem(const AjPListNode node);
127 static void listArrayTrace(void** array);
128 static void listFreeSetExpand(void);
129 static void listDelStr(void** Pstr);
130
131
132
133
134 /* ========================================================================= */
135 /* ======================= All functions by section ======================== */
136 /* ========================================================================= */
137
138
139
140
141 /* @filesection ajlist ********************************************************
142 **
143 ** @nam1rule aj Function belongs to the AJAX library.
144 **
145 ******************************************************************************/
146
147
148
149
150 /* @datasection [AjPList] Lists ***********************************************
151 **
152 ** @nam2rule List Function is for manipulating lists with any value type.
153 **
154 ** Some functions are specially designed to understand string (AjPStr) values.
155 **
156 ******************************************************************************/
157
158
159
160
161 /* @section Constructors ******************************************************
162 **
163 ** Constructors for lists
164 **
165 ** @fdata [AjPList]
166 **
167 ** @fcategory new
168 **
169 ** @nam3rule New Constructor
170 ** @nam4rule NewListref Copy constructor with pointers to source data
171 ** @nam4rule NewRef New reference to an existing list
172 **
173 ** @argrule NewListref list [const AjPList] Source list
174 ** @argrule NewRef list [AjPList] Source list
175 **
176 ** @valrule * [AjPList] New list
177 **
178 ******************************************************************************/
179
180
181
182
183
184 /* @func ajListNew ************************************************************
185 **
186 ** Creates a new general list.
187 **
188 ** @return [AjPList] new list;
189 **
190 ** @release 1.0.0
191 ** @@
192 ******************************************************************************/
193
ajListNew(void)194 AjPList ajListNew(void)
195 {
196 return listNew(NULL);
197 }
198
199
200
201
202 /* @func ajListNewListref *****************************************************
203 **
204 ** Copy a list.
205 **
206 ** WARNING: pointers to the data are copied, NOT the data
207 ** so be careful when cleaning up after copy.
208 **
209 ** @param [r] list [const AjPList] list to be copied
210 ** @return [AjPList] new copied list.
211 **
212 ** @release 5.0.0
213 ** @@
214 ******************************************************************************/
215
ajListNewListref(const AjPList list)216 AjPList ajListNewListref(const AjPList list)
217 {
218 AjPList newlist = NULL;
219
220 AjPListNode node = NULL;
221
222 if(!list)
223 return NULL;
224
225 newlist = ajListNew();
226
227 for(node = list->First; node->Next; node = node->Next)
228 ajListPushAppend(newlist, node->Item);
229
230
231 return newlist;
232 }
233
234
235
236
237 /* @func ajListNewRef *********************************************************
238 **
239 ** Makes a reference-counted copy of any list
240 **
241 ** @param [u] list [AjPList] list to be given a new reference
242 ** @return [AjPList] new list;
243 **
244 ** @release 6.4.0
245 ** @@
246 ******************************************************************************/
247
ajListNewRef(AjPList list)248 AjPList ajListNewRef(AjPList list)
249 {
250 list->Use++;
251
252 return list;
253 }
254
255
256
257
258 /* @funcstatic listNew ********************************************************
259 **
260 ** Creates a new list.
261 **
262 ** @param [f] itemdel [void function] Data destructor
263 ** @return [AjPList] new list;
264 **
265 ** @release 1.0.0
266 ** @@
267 ******************************************************************************/
268
listNew(void (* itemdel)(void ** Pitem))269 static AjPList listNew (void (*itemdel)(void** Pitem))
270 {
271 AjPList list = NULL;
272
273 AJNEW0(list);
274 list->Fitemdel = itemdel;
275 list->Last = listDummyNode(&list->First);
276
277 #ifdef AJ_SAVESTATS
278 listNodeCnt--; /* dummy */
279 listNewCnt++;
280 #endif
281
282 list->Use = 1;
283
284 return list;
285 }
286
287
288
289
290 /* @funcstatic listInsertNode *************************************************
291 **
292 ** Inserts a new node in a list at the current node position.
293 **
294 ** @param [u] Pnode [AjPListNode*] Current AJAX List Node address
295 ** @param [u] item [void*] Data item to insert.
296 ** @return [void]
297 **
298 ** @release 1.0.0
299 ** @@
300 ******************************************************************************/
301
listInsertNode(AjPListNode * Pnode,void * item)302 static void listInsertNode(AjPListNode* Pnode, void* item)
303 {
304 AjPListNode node = NULL;
305
306 if(listFreeNext)
307 node = listFreeSet[--listFreeNext];
308 else
309 AJNEW0(node);
310
311 node->Item = item;
312 node->Next = (*Pnode);
313 node->Prev = (*Pnode)->Prev;
314
315 node->Next->Prev = node;
316
317 *Pnode = node;
318
319 #ifdef AJ_SAVESTATS
320 listNodeCnt++;
321 #endif
322
323 return;
324 }
325
326
327
328
329 /* @funcstatic listDummyNode **************************************************
330 **
331 ** Creates a new empty node.
332 **
333 ** @param [u] Pnode [AjPListNode*] New AJAX List Node address
334 ** @return [AjPListNode] Copy of current node
335 **
336 ** @release 1.0.0
337 ** @@
338 ******************************************************************************/
339
listDummyNode(AjPListNode * Pnode)340 static AjPListNode listDummyNode(AjPListNode* Pnode)
341 {
342 if(listFreeNext)
343 {
344 *Pnode = listFreeSet[--listFreeNext];
345 (*Pnode)->Item = NULL;
346 (*Pnode)->Prev = NULL;
347 (*Pnode)->Next = NULL;
348 }
349 else
350 AJNEW0(*Pnode);
351
352 #ifdef AJ_SAVESTATS
353 listNodeCnt++;
354 #endif
355
356 return *Pnode;
357 }
358
359
360
361
362 /* @section Adding values *****************************************************
363 **
364 ** @fdata [AjPList]
365 **
366 ** @nam3rule Push Add new value
367 ** @nam4rule PushAppend Add new value to end of list
368 ** @nam3rule Pushlist Add new list of values
369 **
370 ** @argrule * list [AjPList] List
371 ** @argrule Push item [void*] Pointer to data.
372 ** @argrule Pushlist Plist [AjPList*] Source AJAX List address to be deleted
373 **
374 ** @valrule * [void]
375 **
376 ** @fcategory modify
377 ******************************************************************************/
378
379
380
381
382 /* @func ajListPush ***********************************************************
383 **
384 ** Add a new node at the start of the list and add the
385 ** data pointer.
386 **
387 ** @param [u] list [AjPList] list to be changed.
388 ** @param [u] item [void*] Pointer to data.
389 ** @return [void]
390 **
391 ** @release 1.0.0
392 ** @@
393 ******************************************************************************/
394
ajListPush(AjPList list,void * item)395 void ajListPush(AjPList list, void* item)
396 {
397 assert(list);
398
399 listInsertNode(&list->First, item);
400
401 if(!list->Count++)
402 list->Last->Prev = list->First;
403
404 #ifdef AJ_SAVESTATS
405 if(list->Count > listMaxNum)
406 listMaxNum = list->Count;
407 #endif
408
409 return;
410 }
411
412
413
414
415 /* @func ajListPushAppend *****************************************************
416 **
417 ** Add a new node at the end of the list and add the
418 ** data pointer.
419 **
420 ** @param [u] list [AjPList] List to be changed.
421 ** @param [u] item [void*] Pointer to data to append.
422 ** @return [void]
423 **
424 ** @release 5.0.0
425 ** @@
426 ******************************************************************************/
427
ajListPushAppend(AjPList list,void * item)428 void ajListPushAppend(AjPList list, void* item)
429 {
430 /*
431 ** cannot use listInsertNode because that needs a pointer to the
432 ** penultimate node, so we use the dummy node and make a new dummy node
433 ** instead
434 */
435 AjPListNode tmp = NULL;
436
437 assert(list);
438
439 if(!list->Count)
440 {
441 ajListPush(list, item);
442 return;
443 }
444
445 list->Last->Item = item;
446
447 tmp = list->Last;
448 list->Last = listDummyNode(&list->Last->Next);
449 list->Last->Prev = tmp;
450
451 list->Count++;
452
453 #ifdef AJ_SAVESTATS
454 if(list->Count > listMaxNum)
455 listMaxNum = list->Count;
456 #endif
457
458 return;
459 }
460
461
462
463
464 /* @func ajListPushlist *******************************************************
465 **
466 ** Adds a list to the start of the current list, then deletes the second list.
467 **
468 ** @param [u] list [AjPList] List.
469 ** @param [d] Plist [AjPList*] AJAX List address to be merged.
470 ** @return [void]
471 **
472 ** @release 5.0.0
473 ** @@
474 ******************************************************************************/
475
ajListPushlist(AjPList list,AjPList * Plist)476 void ajListPushlist(AjPList list, AjPList* Plist)
477 {
478 AjPList more = *Plist;
479
480 if(more->Count)
481 {
482 /* more list has items */
483 if(list->Count)
484 {
485 /* master list has items */
486 more->Last->Item = list->First->Item;
487 more->Last->Next = list->First->Next;
488 list->First->Next->Prev = more->Last;
489 }
490 else
491 {
492 /* master list is empty */
493 list->Last = more->Last;
494 }
495
496 if(listFreeNext >= listFreeMax)
497 listFreeSetExpand();
498
499 if(listFreeNext >= listFreeMax)
500 AJFREE(list->First);
501 else if(list->First)
502 listFreeSet[listFreeNext++] = list->First;
503
504 list->First = more->First;
505 list->Count += more->Count;
506 list->First->Prev = NULL;
507 more->First = NULL;
508 more->Count=0;
509
510 #ifdef AJ_SAVESTATS
511 if(list->Count > listMaxNum)
512 listMaxNum = list->Count;
513 #endif
514 }
515
516 ajListFree(Plist); /* free the list but not the nodes */
517
518 return;
519 }
520
521
522
523
524 /* @section Modifiers *********************************************************
525 **
526 ** @fdata [AjPList]
527 **
528 ** Modifies a list
529 **
530 ** @nam3rule Map Apply function to each node
531 ** @nam3rule Purge Select and remove unwanted nodes
532 ** @nam3rule Reverse Reverse the order of nodes
533 ** @nam3rule Sort Apply function to each node
534 ** @nam4rule Two Apply second function to each equal node
535 ** @nam5rule Three Apply third function to each equal node
536 ** @suffix Unique Remove non-unique values from the list
537 **
538 ** @argrule * list [AjPList] List
539 ** @argrule Map apply [void function] Function to apply
540 ** @argrule Map cl [void*] Data (usually NULL) to be passed to apply.
541 ** @argrule Purge test [AjBool function] Function to find unwanted values
542 ** @argrule Purge itemdel [void function] Function to remove a value
543 ** @argrule Sort compar1 [int function]
544 ** First function to compare values
545 ** @argrule Two compar2 [int function]
546 ** Second function to compare equal values
547 ** @argrule Three compar3 [int function]
548 ** Third function to compare equal values
549 ** @argrule Unique itemdel [void function] Function to remove a value
550 **
551 ** @valrule * [void]
552 **
553 ** @fcategory modify
554 **
555 ******************************************************************************/
556
557
558
559
560 /* @func ajListMap ************************************************************
561 **
562 ** For each node in the list call function apply.
563 **
564 ** @param [u] list [AjPList] List.
565 ** @param [f] apply [void function] Function to call for each list item.
566 ** @param [u] cl [void*] Standard, usually NULL.
567 ** @return [void]
568 **
569 ** @release 1.0.0
570 ** @@
571 ******************************************************************************/
572
ajListMap(AjPList list,void (* apply)(void ** Pitem,void * cl),void * cl)573 void ajListMap(AjPList list, void (*apply)(void** Pitem, void* cl), void* cl)
574 {
575 AjPListNode rest;
576
577 assert(apply);
578
579 for(rest = list->First; rest->Next; rest = rest->Next)
580 (*apply)(&rest->Item, cl);
581
582 return;
583 }
584
585
586
587
588 /* @func ajListPurge **********************************************************
589 **
590 ** Garbage collect a list
591 **
592 ** @param [u] list [AjPList] List.
593 ** @param [f] test [AjBool function] Function to test whether to delete
594 ** @param [f] itemdel [void function] Wrapper function for item destructor
595 ** @return [void]
596 **
597 ** @release 5.0.0
598 ** @@
599 ******************************************************************************/
600
ajListPurge(AjPList list,AjBool (* test)(const void * item),void (* itemdel)(void ** Pitem))601 void ajListPurge(AjPList list,
602 AjBool (*test)(const void* item),
603 void (*itemdel)(void** Pitem))
604 {
605 void* item = NULL;
606
607 AjIList iter = NULL;
608
609
610 iter = ajListIterNew(list);
611
612 while((item = ajListIterGet(iter)))
613 if((*test)(item))
614 {
615 (*itemdel)(&item);
616 ajListIterRemove(iter);
617 }
618
619
620 ajListIterDel(&iter);
621
622 return;
623 }
624
625
626
627
628 /* @func ajListReverse ********************************************************
629 **
630 ** Reverse the order of the nodes in an abstract list.
631 **
632 ** @param [u] list [AjPList] List
633 ** @return [void]
634 **
635 ** @release 1.0.0
636 ** @@
637 ******************************************************************************/
638
ajListReverse(AjPList list)639 void ajListReverse(AjPList list)
640 {
641 AjPListNode head = NULL;
642 AjPListNode savenext = NULL;
643 AjPListNode node = NULL;
644
645 if(!list)
646 return;
647
648 if(list->Count <= 1)
649 return;
650
651 head = list->Last;
652
653 list->Last->Prev = list->First;
654
655 for(node = list->First; node->Next; node = savenext)
656 {
657 savenext = node->Next;
658 node->Prev = node->Next;
659 node->Next = head;
660 head = node;
661 }
662
663 list->First = head;
664
665 list->First->Prev = NULL;
666
667 return;
668 }
669
670
671
672
673 /* @func ajListSort ***********************************************************
674 **
675 ** Sort the items in a list.
676 **
677 ** @param [u] list [AjPList] List.
678 ** @param [f] compar1 [int function] Function to compare two list items.
679 ** @return [void]
680 **
681 ** @release 1.0.0
682 ** @@
683 ******************************************************************************/
684
ajListSort(AjPList list,int (* compar1)(const void * item1,const void * item2))685 void ajListSort(AjPList list,
686 int (*compar1)(const void* item1,
687 const void* item2))
688 {
689 void** array = NULL;
690
691 ajulong i = 0UL;
692
693 AjPListNode node = NULL;
694
695 /*ajDebug("ajListSort %Lu items\n", list->Count);*/
696 /*ajListTrace(list);*/
697
698 node = list->First;
699
700 if(list->Count <= 1)
701 return;
702
703 ajListToarray(list, &array);
704 /* listArrayTrace(array);*/
705
706 qsort(array, (size_t) list->Count, sizeof(void*), compar1);
707
708 while(node->Next)
709 {
710 node->Item = array[i++];
711 node = node->Next;
712 }
713
714 AJFREE(array);
715
716 return;
717 }
718
719
720
721
722 /* @func ajListSortTwo ********************************************************
723 **
724 ** Sort the items in a list using 2 fields in the same object hierarchy.
725 **
726 ** @param [u] list [AjPList] List.
727 ** @param [f] compar1 [int function] 1st function to compare two list items.
728 ** @param [f] compar2 [int function] 2nd function to compare two list items.
729 ** @return [void]
730 **
731 ** @release 5.0.0
732 ** @@
733 ******************************************************************************/
734
ajListSortTwo(AjPList list,int (* compar1)(const void * item1,const void * item2),int (* compar2)(const void * item1,const void * item2))735 void ajListSortTwo(AjPList list,
736 int (*compar1)(const void* item1,
737 const void* item2),
738 int (*compar2)(const void* item1,
739 const void* item2))
740 {
741 AjPListNode node = NULL;
742
743 void** items = NULL;
744
745 ajulong len = 0UL;
746 ajulong limit = 0UL;
747 ajulong pos = 0UL;
748 ajulong base = 0UL;
749 ajulong n = 0UL;
750
751 node = list->First;
752
753 ajListSort(list, compar1);
754
755 len = ajListToarray(list, &items);
756
757 if(len < 2)
758 return;
759
760 pos = base = 0UL;
761 limit = len - 2;
762
763 while(pos < limit)
764 {
765 while((*compar1)(&items[pos], &items[pos + 1]) == 0)
766 {
767 ++pos;
768
769 if(pos > limit)
770 break;
771 }
772 ++pos;
773
774 n = pos - base;
775
776 if(n > 1)
777 qsort((void*) &items[base], (size_t) n, sizeof(void*), compar2);
778
779 base = pos;
780 }
781
782 pos = 0UL;
783
784 while(node->Next)
785 {
786 node->Item = items[pos++];
787 node = node->Next;
788 }
789
790 AJFREE(items);
791
792 return;
793 }
794
795
796
797
798 /* @func ajListSortTwoThree ***************************************************
799 **
800 ** Sort the items in a list using 3 fields in the same object hierarchy.
801 **
802 ** @param [u] list [AjPList] List.
803 ** @param [f] compar1 [int function] 1st function to compare two list items.
804 ** @param [f] compar2 [int function] 2nd function to compare two list items.
805 ** @param [f] compar3 [int function] 3rd function to compare two list items.
806 ** @return [void]
807 **
808 ** @release 5.0.0
809 ** @@
810 ******************************************************************************/
811
ajListSortTwoThree(AjPList list,int (* compar1)(const void * item1,const void * item2),int (* compar2)(const void * item1,const void * item2),int (* compar3)(const void * item1,const void * item2))812 void ajListSortTwoThree(AjPList list,
813 int (*compar1)(const void* item1,
814 const void* item2),
815 int (*compar2)(const void* item1,
816 const void* item2),
817 int (*compar3)(const void* item1,
818 const void* item2))
819 {
820 AjPListNode node = NULL;
821
822 void** items = NULL;
823
824 ajulong len = 0UL;
825 ajulong limit = 0UL;
826 ajulong pos = 0UL;
827 ajulong base = 0UL;
828 ajulong n = 0UL;
829
830 node = list->First;
831 len = ajListGetLength(list);
832
833 if(len < 2)
834 return;
835
836 ajListSortTwo(list, compar1, compar2);
837
838 len = ajListToarray(list, &items);
839
840 pos = base = 0UL;
841 limit = len - 2;
842
843 while(pos < limit)
844 {
845 while(((*compar1)(&items[pos],&items[pos+1]) == 0) &&
846 ((*compar2)(&items[pos],&items[pos+1]) == 0))
847 {
848 ++pos;
849
850 if(pos > limit)
851 break;
852 }
853
854 ++pos;
855 n = pos - base;
856
857 if(n > 1)
858 qsort((void*) &items[base], (size_t) n, sizeof(void*), compar3);
859
860 base = pos;
861 }
862
863 pos = 0UL;
864
865 while(node->Next)
866 {
867 node->Item = items[pos++];
868 node = node->Next;
869 }
870
871 AJFREE(items);
872
873 return;
874 }
875
876
877
878
879 /* @func ajListSortTwoUnique **************************************************
880 **
881 ** Double-sort the items in a list, and remove duplicates
882 **
883 ** @param [u] list [AjPList] List.
884 ** @param [f] compar1 [int function] Function to compare two list items.
885 ** @param [f] compar2 [int function] Function to compare two list items.
886 ** @param [f] itemdel [void function] Function to delete an item
887 ** @return [void]
888 **
889 ** @release 5.0.0
890 ** @@
891 ******************************************************************************/
892
ajListSortTwoUnique(AjPList list,int (* compar1)(const void * item1,const void * item2),int (* compar2)(const void * item1,const void * item2),void (* itemdel)(void ** Pitem,void * cl))893 void ajListSortTwoUnique(AjPList list,
894 int (*compar1)(const void* item1,
895 const void* item2),
896 int (*compar2)(const void* item1,
897 const void* item2),
898 void (*itemdel)(void** Pitem,
899 void* cl))
900 {
901 void* item = NULL;
902 void* previtem = NULL;
903
904 AjIList iter = NULL;
905
906 ajDebug("ajListSortTwoUnique %Lu items\n", list->Count);
907
908 if(list->Count <= 1) /* no duplicates */
909 return;
910
911 ajListSortTwo(list, compar1, compar2);
912 /*ajListTrace(list);*/
913
914 iter = ajListIterNew(list);
915
916 while(!ajListIterDone(iter))
917 {
918 item = ajListIterGet(iter);
919
920 if(previtem &&
921 ((*compar1)(&item, &previtem) == 0) &&
922 ((*compar2)(&item, &previtem) == 0))
923 {
924 (*itemdel)(&item, NULL);
925 ajListIterRemove(iter);
926 }
927 else
928 previtem = item;
929 }
930
931 ajListIterDel(&iter);
932
933 ajDebug("ajListUnique result %Lu items\n", list->Count);
934 /*ajListTrace(list);*/
935
936 return;
937 }
938
939
940
941
942 /* @func ajListSortUnique *****************************************************
943 **
944 ** Sort the items in a list, and remove duplicates
945 **
946 ** @param [u] list [AjPList] List.
947 ** @param [f] compar1 [int function] Function to compare two list items.
948 ** @param [f] itemdel [void function] Function to delete an item
949 ** @return [void]
950 **
951 ** @release 5.0.0
952 ** @@
953 ******************************************************************************/
954
ajListSortUnique(AjPList list,int (* compar1)(const void * item1,const void * item2),void (* itemdel)(void ** Pitem,void * cl))955 void ajListSortUnique(AjPList list,
956 int (*compar1)(const void* item1,
957 const void* item2),
958 void (*itemdel)(void** Pitem,
959 void* cl))
960 {
961 void* item = NULL;
962 void* previtem = NULL;
963
964 AjIList iter = NULL;
965
966 ajDebug("ajListSortUnique %Lu items\n", list->Count);
967
968 if(list->Count <= 1) /* no duplicates */
969 return;
970
971 ajListSort(list, compar1);
972 /*ajListTrace(list);*/
973
974 iter = ajListIterNew(list);
975
976 while(!ajListIterDone(iter))
977 {
978 item = ajListIterGet(iter);
979
980 if(previtem && ((*compar1)(&item, &previtem) == 0))
981 {
982 (*itemdel)(&item, NULL);
983 ajListIterRemove(iter);
984 }
985 else
986 previtem = item;
987 }
988
989 ajListIterDel(&iter);
990
991 ajDebug("ajListSortUnique result %d items\n", list->Count);
992 /*ajListTrace(list);*/
993
994 return;
995 }
996
997
998
999
1000 /* @section Removing data *****************************************************
1001 **
1002 ** @fdata [AjPList]
1003 **
1004 ** Retrieves values from a list
1005 **
1006 ** @nam3rule Pop Retrieve next value
1007 ** @nam4rule PopLast Retrieve last value
1008 ** @nam3rule Drop Remove value by reference
1009 **
1010 ** @argrule * list [AjPList] List
1011 ** @argrule Drop item [void*] Value
1012 ** @argrule Pop Pitem [void**] Value
1013 **
1014 ** @valrule *Drop [void*] Removed value or NULL if not found
1015 ** @valrule *Pop [AjBool] True on success
1016 ** @fcategory cast
1017 **
1018 ******************************************************************************/
1019
1020
1021
1022
1023 /* @funcstatic listFreeSetExpand **********************************************
1024 **
1025 ** Expand the list of free nodes
1026 **
1027 ** @return [void]
1028 **
1029 ** @release 6.0.0
1030 ******************************************************************************/
1031
listFreeSetExpand(void)1032 static void listFreeSetExpand(void)
1033 {
1034 ajulong newsize;
1035
1036 if(!listFreeSet)
1037 {
1038 listFreeMax = 1024;
1039 AJCNEW0(listFreeSet,listFreeMax);
1040
1041 return;
1042 }
1043
1044 if(listFreeMax >= 65536)
1045 return;
1046
1047 newsize = listFreeMax + listFreeMax;
1048 AJCRESIZE0(listFreeSet, (size_t) listFreeMax, (size_t) newsize);
1049 listFreeMax = newsize;
1050
1051 return;
1052 }
1053
1054
1055
1056
1057 /* @func ajListDrop ***********************************************************
1058 **
1059 ** Removes a data value from a list if the address matches data for a node
1060 **
1061 ** @param [u] list [AjPList] List
1062 ** @param [r] item [void*] Data item
1063 ** @return [void*] Dropped data item.
1064 **
1065 ** @release 6.5.0
1066 ** @@
1067 ******************************************************************************/
1068
ajListDrop(AjPList list,void * item)1069 void* ajListDrop(AjPList list, void* item)
1070 {
1071 void* ret = NULL;
1072
1073 AjIList iter = NULL;
1074
1075 ajDebug("ajListDrop %p\n", item);
1076
1077 iter = ajListIterNewBack(list);
1078
1079 while(!ajListIterDoneBack(iter))
1080 {
1081 ret = ajListIterGetBack(iter);
1082
1083 ajDebug("test %p\n", ret);
1084
1085 if(ret == item)
1086 {
1087 ajListIterRemove(iter);
1088 ajListIterDel(&iter);
1089 return ret;
1090 }
1091 }
1092 ajListIterDel(&iter);
1093
1094 return NULL;
1095 }
1096
1097
1098
1099
1100 /* @func ajListPop ************************************************************
1101 **
1102 ** remove the first node but set pointer to data first.
1103 **
1104 ** @param [u] list [AjPList] List
1105 ** @param [w] Pitem [void**] pointer to pointer to data
1106 ** @return [AjBool] ajTrue on success.
1107 **
1108 ** @release 1.0.0
1109 ** @@
1110 ******************************************************************************/
1111
ajListPop(AjPList list,void ** Pitem)1112 AjBool ajListPop(AjPList list, void** Pitem)
1113 {
1114 if(!list)
1115 {
1116 if(Pitem)
1117 *Pitem = NULL;
1118
1119 return ajFalse;
1120 }
1121
1122 if(Pitem)
1123 *Pitem = listNodeItem(list->First);
1124
1125 if(!listNodeDel(&list->First))
1126 return ajFalse;
1127
1128 list->First->Prev = NULL;
1129 list->Count--;
1130
1131 return ajTrue;
1132 }
1133
1134
1135
1136
1137 /* @func ajListPopLast ********************************************************
1138 **
1139 ** remove the last node but set pointer to data first.
1140 **
1141 ** @param [u] list [AjPList] List
1142 ** @param [w] Pitem [void**] pointer to pointer to data
1143 ** @return [AjBool] ajTrue on success.
1144 **
1145 ** @release 5.0.0
1146 ** @@
1147 ******************************************************************************/
1148
ajListPopLast(AjPList list,void ** Pitem)1149 AjBool ajListPopLast(AjPList list, void** Pitem)
1150 {
1151 AjPListNode node = NULL;
1152
1153 if(!list)
1154 {
1155 if(Pitem)
1156 *Pitem = NULL;
1157
1158 return ajFalse;
1159 }
1160
1161
1162 if(!list->Count)
1163 return ajFalse;
1164
1165 node = list->Last->Prev;
1166
1167 if(Pitem)
1168 *Pitem = listNodeItem(node);
1169
1170
1171 if(list->Count==1)
1172 {
1173 list->Last->Prev = NULL;
1174
1175 if(listFreeNext >= listFreeMax)
1176 listFreeSetExpand();
1177
1178 if(listFreeNext >= listFreeMax)
1179 AJFREE(list->First);
1180 else if(list->First)
1181 listFreeSet[listFreeNext++] = list->First;
1182
1183 list->First = list->Last;
1184 }
1185 else
1186 {
1187 node->Prev->Next = list->Last;
1188 list->Last->Prev = node->Prev;
1189
1190 if(listFreeNext >= listFreeMax)
1191 listFreeSetExpand();
1192
1193 if(listFreeNext >= listFreeMax)
1194 AJFREE(node);
1195 else if(node)
1196 {
1197 listFreeSet[listFreeNext++] = node;
1198 node = NULL;
1199 }
1200 }
1201
1202 --list->Count;
1203
1204 return ajTrue;
1205 }
1206
1207
1208
1209
1210 /* @section Element retrieval *************************************************
1211 **
1212 ** @fdata [AjPList]
1213 **
1214 ** Retrieves attributes or values from a list without changing it
1215 **
1216 ** @nam3rule Get Retrieve attribute
1217 ** @nam4rule GetLength Retrieve list length
1218 ** @nam3rule Mapread Apply function to each node without modifying list or data
1219 ** @nam3rule Mapfind Apply function to each node without modifying list
1220 ** or data
1221 ** @nam3rule Peek Pointer to next value
1222 ** @nam4rule PeekFirst Pointer to first value
1223 ** @nam4rule PeekLast Pointer to last value
1224 ** @nam4rule PeekNumber Pointer to numbered value
1225 ** @nam3rule Toarray Build array of values
1226 ** @nam3rule Toindex Sort index array by list node values
1227 **
1228 ** @argrule * list [const AjPList] List
1229 ** @argrule Mapfind apply [AjBool function] Function to apply
1230 ** @argrule Mapread apply [void function] Function to apply
1231 ** @argrule Mapfind cl [void*] Data (usually NULL) to be passed to apply.
1232 ** @argrule Mapread cl [void*] Data (usually NULL) to be passed to apply.
1233 ** @argrule PeekNumber ipos [ajulong] Position in list
1234 ** @argrule Peek Pitem [void**] Value
1235 ** @argrule Toarray array [void***] Array of values, ending with NULL
1236 ** @argrule Toindex lind [ajuint*] Populated index array to be sorted
1237 ** @argrule Toindex compar1 [int function] Function to compare two list items.
1238 **
1239 ** @valrule * [AjBool] True on success
1240 ** @valrule *Length [ajulong] List length
1241 ** @valrule *Mapfind [AjBool] True if function returns true
1242 ** @valrule *Mapread [void]
1243 ** @valrule *Toarray [ajulong] Array size, excluding final NULL
1244 ** @valrule *Toindex [ajulong] Array size, excluding final NULL
1245 **
1246 ** @fcategory cast
1247 **
1248 ******************************************************************************/
1249
1250
1251
1252
1253 /* @func ajListGetLength ******************************************************
1254 **
1255 ** get the number of nodes in the linked list.
1256 **
1257 ** @param [r] list [const AjPList] List
1258 ** @return [ajulong] Number of nodes in list.
1259 **
1260 ** @release 5.0.0
1261 ** @@
1262 ******************************************************************************/
1263
ajListGetLength(const AjPList list)1264 ajulong ajListGetLength(const AjPList list)
1265 {
1266 if(!list)
1267 return 0UL;
1268
1269 return list->Count;
1270 }
1271
1272
1273
1274
1275 /* @func ajListMapfind ********************************************************
1276 **
1277 ** For each node in the list call function 'apply' and return
1278 ** ajTrue when any node is matched by the function.
1279 **
1280 ** @param [r] list [const AjPList] List
1281 ** @param [f] apply [AjBool function] Function to call to test each list item.
1282 ** @param [u] cl [void*] Standard, usually NULL.
1283 ** @return [AjBool] ajTrue on success.
1284 **
1285 ** @release 5.0.0
1286 ** @@
1287 ******************************************************************************/
1288
ajListMapfind(const AjPList list,AjBool (* apply)(void ** Pitem,void * cl),void * cl)1289 AjBool ajListMapfind(const AjPList list,
1290 AjBool (*apply)(void** Pitem, void* cl), void* cl)
1291 {
1292 AjPListNode listnode = NULL;
1293
1294 assert(list);
1295
1296 assert(apply);
1297
1298 for( listnode = list->First; listnode->Next; listnode = listnode->Next)
1299 if((*apply)(&listnode->Item, cl))
1300 return ajTrue;
1301
1302 return ajFalse;
1303 }
1304
1305
1306
1307
1308 /* @func ajListMapread ********************************************************
1309 **
1310 ** For each node in the list call function apply.
1311 ** The apply function must not modify the list elements.
1312 **
1313 ** @param [r] list [const AjPList] List.
1314 ** @param [f] apply [void function] Function to call for each list item.
1315 ** @param [u] cl [void*] Standard, usually NULL.
1316 ** @return [void]
1317 **
1318 ** @release 5.0.0
1319 ** @@
1320 ******************************************************************************/
1321
ajListMapread(const AjPList list,void (* apply)(void * item,void * cl),void * cl)1322 void ajListMapread(const AjPList list,
1323 void (*apply)(void* item, void* cl), void* cl)
1324 {
1325 AjPListNode rest = NULL;
1326
1327 assert(apply);
1328
1329 for(rest = list->First; rest->Next; rest = rest->Next)
1330 (*apply)(rest->Item, cl);
1331
1332 return;
1333 }
1334
1335
1336
1337
1338 /* @func ajListPeek ***********************************************************
1339 **
1340 ** Return the first node but keep it on the list
1341 **
1342 ** @param [r] list [const AjPList] List
1343 ** @param [w] Pitem [void**] pointer to pointer to data
1344 ** @return [AjBool] ajTrue on success.
1345 **
1346 ** @release 2.7.0
1347 ** @@
1348 ******************************************************************************/
1349
ajListPeek(const AjPList list,void ** Pitem)1350 AjBool ajListPeek(const AjPList list, void** Pitem)
1351 {
1352 if(!list)
1353 return ajFalse;
1354
1355 if(!list->Count)
1356 return ajFalse;
1357
1358 if(Pitem)
1359 *Pitem = listNodeItem(list->First);
1360
1361 return ajTrue;
1362 }
1363
1364
1365
1366
1367 /* @func ajListPeekFirst ******************************************************
1368 **
1369 ** Set pointer to first node's data. Does NOT remove the first node.
1370 **
1371 ** @param [r] list [const AjPList] List
1372 ** @param [w] Pitem [void**] pointer to pointer to data
1373 ** @return [AjBool] ajTrue on success.
1374 **
1375 ** @release 5.0.0
1376 ** @@
1377 ******************************************************************************/
1378
ajListPeekFirst(const AjPList list,void ** Pitem)1379 AjBool ajListPeekFirst(const AjPList list, void** Pitem)
1380 {
1381 if(!list)
1382 return ajFalse;
1383
1384 if(!list->Count)
1385 return ajFalse;
1386
1387 if(Pitem)
1388 *Pitem = listNodeItem(list->First);
1389
1390 return ajTrue;
1391 }
1392
1393
1394
1395
1396 /* @func ajListPeekLast *******************************************************
1397 **
1398 ** Set pointer to last node's data. Does NOT remove the last node.
1399 **
1400 ** @param [r] list [const AjPList] List
1401 ** @param [w] Pitem [void**] pointer to pointer to data
1402 ** @return [AjBool] ajTrue on success.
1403 **
1404 ** @release 5.0.0
1405 ** @@
1406 ******************************************************************************/
1407
ajListPeekLast(const AjPList list,void ** Pitem)1408 AjBool ajListPeekLast(const AjPList list, void** Pitem)
1409 {
1410 AjPListNode rest = NULL;
1411
1412 if(!list)
1413 return ajFalse;
1414
1415 if(!list->Count)
1416 return ajFalse;
1417
1418 if(list->Last)
1419 rest = list->Last->Prev;
1420 else
1421 rest = list->First;
1422
1423 if(Pitem)
1424 *Pitem = listNodeItem(rest);
1425
1426 return ajTrue;
1427 }
1428
1429
1430
1431
1432 /* @func ajListPeekNumber *****************************************************
1433 **
1434 ** Set pointer to last node's nth data item. 0 <= n < number of elements.
1435 **
1436 ** @param [r] list [const AjPList] List
1437 ** @param [r] ipos [ajulong] element of the list
1438 ** @param [w] Pitem [void**] pointer to pointer to data
1439 ** @return [AjBool] ajTrue on success.
1440 **
1441 ** @release 5.0.0
1442 ** @@
1443 ******************************************************************************/
1444
ajListPeekNumber(const AjPList list,ajulong ipos,void ** Pitem)1445 AjBool ajListPeekNumber(const AjPList list, ajulong ipos, void** Pitem)
1446 {
1447 ajulong len = 0UL;
1448 ajulong i = 0UL;
1449
1450 AjPListNode rest = NULL;
1451
1452 if(!list)
1453 return ajFalse;
1454
1455 len = ajListGetLength(list);
1456
1457 if(ipos>=len)
1458 return ajFalse;
1459
1460 for(i = 0Ul, rest = list->First; i < ipos ; rest = rest->Next)
1461 i++;
1462
1463 if(Pitem)
1464 *Pitem = listNodeItem(rest);
1465
1466 return ajTrue;
1467 }
1468
1469
1470
1471
1472 /* @func ajListToarray ********************************************************
1473 **
1474 ** Create an array of the pointers to the data.
1475 **
1476 ** @param [r] list [const AjPList] List
1477 ** @param [w] array [void***] Array of pointers to list items.
1478 ** @return [ajulong] Size of array of pointers.
1479 **
1480 ** @release 5.0.0
1481 ** @@
1482 ******************************************************************************/
1483
ajListToarray(const AjPList list,void *** array)1484 ajulong ajListToarray(const AjPList list, void*** array)
1485 {
1486 ajulong i = 0UL;
1487 ajulong n = 0UL;
1488
1489 AjPListNode rest = NULL;
1490
1491 n = list->Count;
1492 rest = list->First;
1493
1494 if(!n)
1495 {
1496 *array = NULL;
1497
1498 return 0UL;
1499 }
1500
1501 if(*array)
1502 AJFREE(*array);
1503
1504 *array = AJALLOC((size_t)(n + 1) * sizeof(array));
1505
1506 for(i = 0UL; i < n; i++)
1507 {
1508 (*array)[i] = rest->Item;
1509 rest = rest->Next;
1510 }
1511
1512 (*array)[n] = NULL;
1513
1514 return n;
1515 }
1516
1517
1518
1519
1520 /* @funcstatic listArrayTrace *************************************************
1521 **
1522 ** Writes debug messages to trace an array generated from a list.
1523 **
1524 ** @param [r] array [void**] Array to trace
1525 ** @return [void]
1526 **
1527 ** @release 1.0.0
1528 ** @@
1529 ******************************************************************************/
1530
listArrayTrace(void ** array)1531 static void listArrayTrace(void** array)
1532 {
1533 void** v = array;
1534
1535 ajuint i = 0UL;
1536
1537 while(*v)
1538 ajDebug("array[%Lu] %p\n", i++, *v++);
1539
1540 return;
1541 }
1542
1543
1544
1545
1546 /* @func ajListToindex ********************************************************
1547 **
1548 ** Create an array of the pointers to the data.
1549 **
1550 ** @param [r] list [const AjPList] List
1551 ** @param [w] lind [ajuint*] Populated index array to be sorted
1552 ** @param [f] compar1 [int function] Function to compare two list items.
1553 ** @return [ajulong] Size of index array.
1554 **
1555 ** @release 6.3.0
1556 ** @@
1557 ******************************************************************************/
1558
ajListToindex(const AjPList list,ajuint * lind,int (* compar1)(const void * item1,const void * item2))1559 ajulong ajListToindex(const AjPList list, ajuint* lind,
1560 int (*compar1)(const void* item1, const void* item2))
1561 {
1562 ajulong n = 0UL;
1563 ajulong s = 0UL;
1564 ajulong i = 0UL;
1565 ajlong j = 0L;
1566 ajuint it = 0U;
1567 ajulong lt = 0UL;
1568
1569 AjPListNode* nodes = NULL;
1570 ajulong* idx = NULL;
1571
1572 n = list->Count;
1573
1574 if(!n)
1575 return 0UL;
1576
1577 ajListToarray(list, (void***) &nodes);
1578 AJCNEW0(idx, n);
1579
1580 for(i = 0UL; i < n; i++)
1581 idx[i] = i;
1582
1583 for(s = n / 2; s > 0; s /= 2)
1584 for(i = s; i < n; ++i)
1585 {
1586 for(j = i - s;
1587 j >= 0 && ((*compar1)(&nodes[idx[j]], &nodes[idx[j+s]]) > 0);
1588 j -= s)
1589 {
1590 it = lind[j];
1591 lind[j] = lind[j + s];
1592 lind[j + s] = it;
1593 lt = idx[j];
1594 idx[j] = idx[j + s];
1595 idx[j + s] = lt;
1596 }
1597 }
1598
1599 AJFREE(nodes);
1600 AJFREE(idx);
1601
1602 return n;
1603 }
1604
1605
1606
1607
1608 /* @section Trace functions ***************************************************
1609 **
1610 ** @fdata [AjPList]
1611 **
1612 ** @nam3rule Probe Test for memory allocation conflicts
1613 ** @nam4rule ProbeData Test data for memory allocation conflicts
1614 ** @nam3rule Print Trace contents to standard error
1615 ** @nam3rule Trace Trace contents to debug file
1616 **
1617 ** @argrule Probe Plist [AjPList const*] Pointer to list
1618 ** @argrule Trace list [const AjPList] List
1619 **
1620 ** @valrule * [void]
1621 **
1622 ** @fcategory misc
1623 **
1624 ******************************************************************************/
1625
1626
1627
1628
1629 /* @func ajListProbe **********************************************************
1630 **
1631 ** Test list for memory allocation conflicts
1632 **
1633 ** @param [r] Plist [AjPList const*] List
1634 ** @return [void]
1635 **
1636 ** @release 6.0.0
1637 ** @@
1638 ******************************************************************************/
1639
ajListProbe(AjPList const * Plist)1640 void ajListProbe(AjPList const* Plist)
1641 {
1642 AjPList list = NULL;
1643
1644 AjPListNode next = NULL;
1645 AjPListNode* rest = NULL;
1646
1647 if(!Plist)
1648 return;
1649
1650 if(!*Plist)
1651 return;
1652
1653 list = *Plist;
1654 rest = &list->First;
1655
1656 /* don't free the data in the list (we don't know how) */
1657 /* just free the nodes */
1658 if(list->Count)
1659 for(; (*rest)->Next; *rest = next)
1660 {
1661 next = (*rest)->Next;
1662 AJMPROBE(*rest);
1663 }
1664
1665 AJMPROBE(*rest);
1666 AJMPROBE(*Plist);
1667
1668 return;
1669 }
1670
1671
1672
1673
1674 /* @func ajListProbeData ******************************************************
1675 **
1676 ** Test list and data for memory allocation conflicts
1677 **
1678 ** @param [r] Plist [AjPList const*] List
1679 ** @return [void]
1680 **
1681 ** @release 6.0.0
1682 ** @@
1683 ******************************************************************************/
1684
ajListProbeData(AjPList const * Plist)1685 void ajListProbeData(AjPList const* Plist)
1686 {
1687 AjPListNode next = NULL;
1688 AjPListNode* rest = NULL;
1689
1690 AjPList list = NULL;
1691
1692 if(!Plist)
1693 return;
1694
1695 if(!*Plist)
1696 return;
1697
1698 list = *Plist;
1699 rest = &list->First;
1700
1701
1702 /* free the data for each node (just a simple free) */
1703 /* as we free the nodes */
1704
1705 if(list->Count)
1706 {
1707 for(; (*rest)->Next; *rest = next)
1708 {
1709 AJMPROBE((*rest)->Item);
1710 next = (*rest)->Next;
1711 AJMPROBE(*rest);
1712 }
1713 AJMPROBE((*rest)->Item);
1714 }
1715
1716 AJMPROBE(*rest);
1717 AJMPROBE(*Plist);
1718
1719 return;
1720 }
1721
1722
1723
1724
1725 /* @func ajListTrace **********************************************************
1726 **
1727 ** Traces through a list and validates it
1728 **
1729 ** @param [r] list [const AjPList] list to be traced.
1730 ** @return [void]
1731 ** @category output [AjPList] Traces through a list and validates it
1732 **
1733 ** @release 1.0.0
1734 ** @@
1735 ******************************************************************************/
1736
ajListTrace(const AjPList list)1737 void ajListTrace(const AjPList list)
1738 {
1739 ajulong i = 0UL;
1740
1741 AjPListNode node = NULL;
1742
1743 if(!list)
1744 return;
1745
1746 ajDebug("\nList Trace %p count %d\n",
1747 list, list->Count);
1748 ajDebug("first-> %p last-> %p\n", list->First, list->Last);
1749
1750 for(node = list->First; node->Next; node = node->Next)
1751 {
1752 i++;
1753 ajDebug("Item[%Lu] item %p (data %p) rest -> %p prev -> %p\n",
1754 i, node, node->Item, node->Next, node->Prev);
1755 }
1756
1757 if(i != list->Count)
1758 {
1759 ajErr("*** list error expect %Lu items, found %Lu",
1760 list->Count, i);
1761 }
1762
1763 if(list->Last != node)
1764 {
1765 ajDebug("*** list error expect end at %p, found at %p\n",
1766 list->Last, node);
1767 ajErr("*** list error expect end at %p, found at %p",
1768 list->Last, node);
1769 }
1770
1771 return;
1772 }
1773
1774
1775
1776
1777 /* @funcstatic listNodesTrace *************************************************
1778 **
1779 ** Writes debug messages to trace from the current list node.
1780 **
1781 ** @param [r] node [const AjPListNode] Current node.
1782 ** @return [void]
1783 **
1784 ** @release 1.0.0
1785 ** @@
1786 ******************************************************************************/
1787
listNodesTrace(const AjPListNode node)1788 static void listNodesTrace(const AjPListNode node)
1789 {
1790 ajDebug("listNodesTrace %p\n", node);
1791
1792 while(node->Next)
1793 {
1794 ajDebug("node %p item %p -> %p\n", node, node->Item, node->Next);
1795 node = node->Next;
1796 }
1797
1798 return;
1799 }
1800
1801
1802
1803
1804
1805 /* @funcstatic listNodeItem ***************************************************
1806 **
1807 ** Return the data item for a list node.
1808 **
1809 ** @param [r] node [const AjPListNode] Current node.
1810 ** @return [void*] Data item.
1811 **
1812 ** @release 1.0.0
1813 ** @@
1814 ******************************************************************************/
1815
listNodeItem(const AjPListNode node)1816 static void* listNodeItem(const AjPListNode node)
1817 {
1818 if(!node || !node->Next)
1819 return NULL;
1820
1821 return node->Item;
1822 }
1823
1824
1825
1826
1827 /* @section Destructors *******************************************************
1828 **
1829 ** @fdata [AjPList]
1830 **
1831 ** Destructors can only deal with the list and cannot free complex data
1832 **
1833 ** @nam3rule Del Delete list
1834 ** @nam3rule Free Delete list
1835 ** @nam4rule FreeData Delete list and free values
1836 **
1837 ** @argrule * Plist [AjPList*] AJAX List address
1838 **
1839 ** @valrule * [void]
1840 **
1841 ** @fcategory delete
1842 **
1843 ******************************************************************************/
1844
1845
1846
1847
1848 /* @func ajListFree ***********************************************************
1849 **
1850 ** Free all nodes in the list.
1851 ** NOTE: The data is only freed with a specified list type.
1852 ** For undefined data types we recommend you to
1853 ** use ajListMap with a routine to free the memory.
1854 **
1855 ** @param [d] Plist [AjPList*] AJAX List address
1856 ** @return [void]
1857 **
1858 ** @release 1.0.0
1859 ** @@
1860 ******************************************************************************/
1861
ajListFree(AjPList * Plist)1862 void ajListFree(AjPList* Plist)
1863 {
1864 AjPList list = NULL;
1865
1866 AjPListNode next = NULL;
1867 AjPListNode* rest = NULL;
1868
1869 if(!Plist)
1870 return;
1871
1872 if(!*Plist)
1873 return;
1874
1875 #ifdef AJ_SAVESTATS
1876 listDelCnt++;
1877 #endif
1878
1879 list = *Plist;
1880
1881 if(!list->Use)
1882 ajErr("trying to delete unused list");
1883
1884 --list->Use;
1885
1886 if(!list->Use)
1887 { /* any other references? */
1888 rest = &list->First;
1889
1890 /* don't free the data in the list (we don't know how) */
1891 /* just free the nodes */
1892 if(list->Count)
1893 for(; (*rest)->Next; *rest = next)
1894 {
1895 next = (*rest)->Next;
1896
1897 if(listFreeNext >= listFreeMax)
1898 listFreeSetExpand();
1899
1900 if(listFreeNext >= listFreeMax)
1901 AJFREE(*rest);
1902 else if(*rest)
1903 {
1904 listFreeSet[listFreeNext++] = *rest;
1905 *rest = NULL;
1906 }
1907 }
1908
1909 if(listFreeNext >= listFreeMax)
1910 listFreeSetExpand();
1911
1912 if(listFreeNext >= listFreeMax)
1913 AJFREE(*rest);
1914 else if(*rest)
1915 {
1916 listFreeSet[listFreeNext++] = *rest;
1917 *rest = NULL;
1918 }
1919
1920 AJFREE(*Plist);
1921 }
1922
1923 *Plist = NULL;
1924
1925 return;
1926 }
1927
1928
1929
1930
1931 /* @func ajListFreeData *******************************************************
1932 **
1933 ** Free all nodes in the list. Free all the data values.
1934 ** For more complex data objects use ajListMap with a routine to
1935 ** free the object memory.
1936 **
1937 ** @param [d] Plist [AjPList*] AJAX List address
1938 ** @return [void]
1939 **
1940 ** @release 4.1.0
1941 ** @@
1942 ******************************************************************************/
1943
ajListFreeData(AjPList * Plist)1944 void ajListFreeData(AjPList* Plist)
1945 {
1946 AjPList list = NULL;
1947
1948 AjPListNode next = NULL;
1949 AjPListNode* rest = NULL;
1950
1951 if(!Plist)
1952 return;
1953
1954 if(!*Plist)
1955 return;
1956
1957 #ifdef AJ_SAVESTATS
1958 listDelCnt++;
1959 #endif
1960
1961 list = *Plist;
1962
1963 if(!list->Use)
1964 ajErr("trying to delete unused list");
1965
1966 --list->Use;
1967
1968 if(!list->Use)
1969 { /* any other references? */
1970 rest = &list->First;
1971
1972 /* free the data for each node (just a simple free) */
1973 /* as we free the nodes */
1974
1975 if(list->Count)
1976 {
1977 for(; (*rest)->Next; *rest = next)
1978 {
1979 AJFREE((*rest)->Item);
1980 next = (*rest)->Next;
1981
1982 if(listFreeNext >= listFreeMax)
1983 listFreeSetExpand();
1984
1985 if(listFreeNext >= listFreeMax)
1986 AJFREE(*rest);
1987 else if(*rest)
1988 {
1989 listFreeSet[listFreeNext++] = *rest;
1990 *rest = NULL;
1991 }
1992 }
1993 AJFREE((*rest)->Item);
1994 }
1995
1996 if(listFreeNext >= listFreeMax)
1997 listFreeSetExpand();
1998
1999 if(listFreeNext >= listFreeMax)
2000 AJFREE(*rest);
2001 else if(*rest)
2002 {
2003 listFreeSet[listFreeNext++] = *rest;
2004 *rest = NULL;
2005 }
2006
2007 AJFREE(*Plist);
2008 }
2009
2010 *Plist = NULL;
2011
2012 return;
2013 }
2014
2015
2016
2017
2018 /* @funcstatic listDelStr *****************************************************
2019 **
2020 ** Delete a string object value
2021 **
2022 ** @param [d] Pstr [void**] AJAX String object to be deleted
2023 ** @return [void]
2024 **
2025 ** @release 6.4.0
2026 ******************************************************************************/
2027
listDelStr(void ** Pstr)2028 static void listDelStr(void** Pstr)
2029 {
2030 if(!Pstr)
2031 return;
2032
2033 if(!*Pstr)
2034 return;
2035
2036 ajStrDel((AjPStr*) Pstr);
2037
2038 return;
2039 }
2040
2041
2042
2043
2044 /* @funcstatic listNodeDel ****************************************************
2045 **
2046 ** Remove a node from the list.
2047 **
2048 ** @param [d] Pnode [AjPListNode*] Current AJAX List Node address
2049 ** @return [AjBool] ajTrue on success
2050 **
2051 ** @release 1.0.0
2052 ** @@
2053 ******************************************************************************/
2054
listNodeDel(AjPListNode * Pnode)2055 static AjBool listNodeDel(AjPListNode* Pnode)
2056 {
2057 AjPListNode node = NULL;
2058 AjPListNode tmp = NULL;
2059
2060 node = *Pnode;
2061
2062 if(!node || !node->Next)
2063 return ajFalse;
2064
2065 tmp = node->Prev;
2066 node = node->Next;
2067 node->Prev = tmp;
2068
2069 if(listFreeNext >= listFreeMax)
2070 listFreeSetExpand();
2071
2072 if(listFreeNext >= listFreeMax)
2073 AJFREE(*Pnode);
2074 else if(*Pnode)
2075 listFreeSet[listFreeNext++] = *Pnode;
2076
2077 *Pnode = node;
2078
2079 return ajTrue;
2080 }
2081
2082
2083
2084
2085 /* @section unused ************************************************************
2086 **
2087 ** @fdata [AjPList]
2088 **
2089 ** @nam3rule Unused Contains dummy calls to unused functions to keep
2090 ** compilers happy
2091 **
2092 ** @argrule Unused array [void**] Dummy array
2093 **
2094 ** @valrule * [void]
2095 ** @fcategory misc
2096 **
2097 ******************************************************************************/
2098
2099
2100
2101
2102 /* @func ajListUnused *********************************************************
2103 **
2104 ** Dummy function to catch all unused functions defined in ajlist
2105 **
2106 ** @param [r] array [void**] Array needed by ajListArrayTrace
2107 ** @return [void]
2108 **
2109 ** @release 5.0.0
2110 ******************************************************************************/
2111
ajListUnused(void ** array)2112 void ajListUnused(void** array)
2113 {
2114 const AjPListNode node = NULL;
2115 listNodesTrace(node);
2116 listArrayTrace(array);
2117
2118 return;
2119 }
2120
2121
2122
2123
2124 /* @section exit **************************************************************
2125 **
2126 ** Functions called on exit from the program by ajExit to do
2127 ** any necessary cleanup and to report internal statistics to the debug file
2128 **
2129 ** @fdata [AjPList]
2130 ** @fnote general exit functions, no arguments
2131 **
2132 ** @nam3rule Exit Cleanup and report on exit
2133 **
2134 ** @valrule * [void]
2135 **
2136 ** @fcategory misc
2137 ******************************************************************************/
2138
2139
2140
2141
2142 /* @func ajListExit ***********************************************************
2143 **
2144 ** Prints a summary of list usage with debug calls
2145 **
2146 ** @return [void]
2147 **
2148 ** @release 2.8.0
2149 ** @@
2150 ******************************************************************************/
2151
ajListExit(void)2152 void ajListExit(void)
2153 {
2154 ajulong i = 0UL;
2155
2156 #ifdef AJ_SAVESTATS
2157 ajDebug("List usage : %d opened, %d closed, %Ld maxsize %Ld nodes\n",
2158 listNewCnt, listDelCnt, listMaxNum, listNodeCnt);
2159 ajDebug("List iterator usage : %d opened, %d closed\n",
2160 listIterNewCnt, listIterDelCnt);
2161 #endif
2162 if(listFreeNext)
2163 for(i = 0UL; i < listFreeNext; i++)
2164 AJFREE(listFreeSet[i]);
2165
2166
2167 if(listFreeSet)
2168 AJFREE(listFreeSet);
2169
2170 listFreeNext = 0UL;
2171 listFreeMax = 0UL;
2172
2173 return;
2174 }
2175
2176
2177
2178
2179 /* @datasection [AjIList] List iterators **************************************
2180 **
2181 ** Function is for manipulating lists with any value type.
2182 **
2183 ** Some functions are specially designed to understand string (AjPStr) values.
2184 **
2185 ** @nam2rule List List data
2186 ** @nam3rule Iter Iterator
2187 **
2188 ******************************************************************************/
2189
2190
2191
2192
2193 /* @section constructors ******************************************************
2194 **
2195 ** @fdata [AjIList]
2196 **
2197 ** @nam4rule New List iterator constructor.
2198 ** @nam5rule NewBack List iterator reverse direction constructor.
2199 ** @nam4rule Newread List iterator read-only constructor.
2200 ** @nam5rule NewreadBack List iterator read-only reverse direction constructor.
2201 **
2202 ** @argrule New list [AjPList] Original list
2203 ** @argrule Newread list [const AjPList] Original list
2204 **
2205 ** @valrule * [AjIList] List iterator
2206 **
2207 ** @fcategory new
2208 ******************************************************************************/
2209
2210
2211
2212
2213 /* @func ajListIterNew ********************************************************
2214 **
2215 ** Creates an iterator to operate from start to end of list.
2216 **
2217 ** @param [u] list [AjPList] List
2218 ** Not const in practice - the iterator can insert
2219 ** and delete entries
2220 ** @return [AjIList] New list iterator
2221 **
2222 ** @release 5.0.0
2223 ** @@
2224 ******************************************************************************/
2225
ajListIterNew(AjPList list)2226 AjIList ajListIterNew(AjPList list)
2227 {
2228 AjIList iter = NULL;
2229
2230 if(!list)
2231 return NULL;
2232
2233 AJNEW0(iter);
2234 iter->Head = list;
2235 iter->Back = ajFalse;
2236 iter->Here = list->First;
2237 iter->Modify = ajTrue;
2238
2239 #ifdef AJ_SAVESTATS
2240 listIterNewCnt++;
2241 #endif
2242
2243 return iter;
2244 }
2245
2246
2247
2248
2249 /* @func ajListIterNewBack ****************************************************
2250 **
2251 ** Creates an iterator to operate from end to start of the list.
2252 **
2253 ** @param [u] list [AjPList] List
2254 ** Not const - the iterator can insert and delete entries
2255 ** @return [AjIList] New list iterator
2256 **
2257 ** @release 5.0.0
2258 ** @@
2259 ******************************************************************************/
2260
ajListIterNewBack(AjPList list)2261 AjIList ajListIterNewBack(AjPList list)
2262 {
2263 AjIList iter = NULL;
2264
2265 AjPListNode node = NULL;
2266 AjPListNode tmp = NULL;
2267
2268 if(!list)
2269 return NULL;
2270
2271 if(!list->Count)
2272 return NULL;
2273
2274 for(node=list->First; node->Next; node = node->Next)
2275 tmp = node;
2276
2277 list->Last->Prev = tmp;
2278
2279 AJNEW0(iter);
2280 iter->Head = list;
2281 iter->Back = ajTrue;
2282 iter->Here = tmp->Next;
2283 iter->Modify = ajTrue;
2284
2285 #ifdef AJ_SAVESTATS
2286 listIterNewCnt++;
2287 #endif
2288
2289 return iter;
2290 }
2291
2292
2293
2294
2295 /* @func ajListIterNewread ****************************************************
2296 **
2297 ** Creates an iterator to operate from start to end of read-only list.
2298 **
2299 ** @param [r] list [const AjPList] List
2300 ** Not const in practice - the iterator can insert
2301 ** and delete entries
2302 ** @return [AjIList] New list iterator
2303 **
2304 ** @release 5.0.0
2305 ** @@
2306 ******************************************************************************/
2307
ajListIterNewread(const AjPList list)2308 AjIList ajListIterNewread(const AjPList list)
2309 {
2310 AjIList iter = NULL;
2311
2312 if(!list)
2313 return NULL;
2314
2315 AJNEW0(iter);
2316 iter->ReadHead = list;
2317 iter->Back = ajFalse;
2318 iter->Here = list->First;
2319 iter->Modify = ajFalse;
2320
2321 #ifdef AJ_SAVESTATS
2322 listIterNewCnt++;
2323 #endif
2324
2325 return iter;
2326 }
2327
2328
2329
2330
2331 /* @func ajListIterNewreadBack ************************************************
2332 **
2333 ** Creates an iterator to operate from end to start of the list.
2334 **
2335 ** @param [r] list [const AjPList] List
2336 ** @return [AjIList] New list iterator
2337 **
2338 ** @release 5.0.0
2339 ** @@
2340 ******************************************************************************/
2341
ajListIterNewreadBack(const AjPList list)2342 AjIList ajListIterNewreadBack(const AjPList list)
2343 {
2344 AjIList iter = NULL;
2345
2346 AjPListNode node = NULL;
2347 AjPListNode tmp = NULL;
2348
2349 if(!list)
2350 return NULL;
2351
2352 if(!list->Count)
2353 return NULL;
2354
2355 for(node=list->First; node->Next; node = node->Next)
2356 tmp = node;
2357
2358 list->Last->Prev = tmp;
2359
2360 AJNEW0(iter);
2361 iter->ReadHead = list;
2362 iter->Back = ajTrue;
2363 iter->Here = tmp->Next;
2364 iter->Modify = ajFalse;
2365
2366 #ifdef AJ_SAVESTATS
2367 listIterNewCnt++;
2368 #endif
2369
2370 return iter;
2371 }
2372
2373
2374
2375
2376 /* @section tests *************************************************************
2377 ** @fdata [AjIList]
2378 ** @nam4rule Done Check whether iteration has ended (no more
2379 ** characters).
2380 ** @nam5rule DoneBack Reverse iterator
2381 **
2382 ** @argrule Done iter [const AjIList] Iterator
2383 **
2384 ** @valrule * [AjBool] Result of test
2385 **
2386 ** @fcategory use
2387 ******************************************************************************/
2388
2389
2390
2391
2392 /* @func ajListIterDone *******************************************************
2393 **
2394 ** Tests whether an iterator has completed yet.
2395 **
2396 ** @param [r] iter [const AjIList] List iterator.
2397 ** @return [AjBool] ajTrue if the iterator is exhausted.
2398 **
2399 ** @release 1.0.0
2400 ** @@
2401 ******************************************************************************/
2402
ajListIterDone(const AjIList iter)2403 AjBool ajListIterDone(const AjIList iter)
2404 {
2405 AjPListNode node = NULL;
2406
2407 if(!iter)
2408 return ajTrue;
2409
2410 node = iter->Here;
2411
2412 if(!iter->Back)
2413 {
2414 if(!node->Next)
2415 return ajTrue;
2416 }
2417 else
2418 if(!node->Next->Next || !node->Next->Next->Next)
2419 return ajTrue;
2420
2421 return ajFalse;
2422 }
2423
2424
2425
2426
2427 /* @func ajListIterDoneBack ***************************************************
2428 **
2429 ** Tests whether a backwards iterator has completed yet.
2430 **
2431 ** @param [r] iter [const AjIList] List iterator.
2432 ** @return [AjBool] ajTrue if the iterator is exhausted.
2433 **
2434 ** @release 5.0.0
2435 ** @@
2436 ******************************************************************************/
2437
ajListIterDoneBack(const AjIList iter)2438 AjBool ajListIterDoneBack(const AjIList iter)
2439 {
2440 AjPListNode node = NULL;
2441
2442 if(!iter)
2443 return ajTrue;
2444
2445 node = iter->Here;
2446
2447 if(!node->Prev)
2448 return ajTrue;
2449
2450 return ajFalse;
2451 }
2452
2453
2454
2455
2456 /* @section destructors *******************************************************
2457 ** @fdata [AjIList]
2458 **
2459 ** @nam4rule Del Destructor
2460 **
2461 ** @argrule Del iter [AjIList*] List iterator
2462 **
2463 ** @valrule * [void]
2464 **
2465 ** @fcategory delete
2466 ******************************************************************************/
2467
2468
2469
2470
2471 /* @func ajListIterDel ********************************************************
2472 **
2473 ** Destructor for a list iterator.
2474 **
2475 ** @param [d] iter [AjIList*] List iterator.
2476 ** @return [void]
2477 **
2478 ** @release 5.0.0
2479 ** @@
2480 ******************************************************************************/
2481
ajListIterDel(AjIList * iter)2482 void ajListIterDel(AjIList* iter)
2483 {
2484 AJFREE(*iter);
2485
2486 #ifdef AJ_SAVESTATS
2487 listIterDelCnt++;
2488 #endif
2489
2490 return;
2491 }
2492
2493
2494
2495
2496 /* @section stepping **********************************************************
2497 **
2498 ** @fdata [AjIList]
2499 **
2500 ** @nam4rule Get Next value.
2501 ** @nam5rule GetBack Next value in reverse direction
2502 **
2503 ** @argrule * iter [AjIList] String iterator
2504 **
2505 ** @valrule * [void*] Value
2506 **
2507 ** @fcategory modify
2508 ******************************************************************************/
2509
2510
2511
2512
2513 /* @func ajListIterGet ********************************************************
2514 **
2515 ** Returns next item using iterator, or steps off the end.
2516 **
2517 ** @param [u] iter [AjIList] List iterator.
2518 ** @return [void*] Data item returned.
2519 **
2520 ** @release 5.0.0
2521 ** @@
2522 ******************************************************************************/
2523
ajListIterGet(AjIList iter)2524 void* ajListIterGet(AjIList iter)
2525 {
2526 void* item = NULL;
2527
2528 AjPListNode node = NULL;
2529
2530 if(!iter)
2531 return NULL;
2532
2533 node = iter->Here;
2534
2535 if(!iter->Back)
2536 {
2537 if(!node->Next)
2538 return NULL;
2539
2540 item = node->Item;
2541 iter->Here = node->Next;
2542 }
2543 else
2544 {
2545 if(!node->Next->Next || !node->Next->Next->Next)
2546 return NULL;
2547
2548 iter->Back = ajFalse;
2549 item = node->Next->Item;
2550 iter->Here = node->Next->Next;
2551 }
2552
2553 return item;
2554 }
2555
2556
2557
2558
2559 /* @func ajListIterGetBack ****************************************************
2560 **
2561 ** Returns next item using back iterator.
2562 **
2563 ** @param [u] iter [AjIList] List iterator.
2564 ** @return [void*] Data item returned.
2565 **
2566 ** @release 5.0.0
2567 ** @@
2568 ******************************************************************************/
2569
ajListIterGetBack(AjIList iter)2570 void* ajListIterGetBack(AjIList iter)
2571 {
2572 void* item = NULL;
2573
2574 AjPListNode node = NULL;
2575
2576 if(!iter)
2577 return NULL;
2578
2579 node = iter->Here;
2580
2581 if(!node->Prev)
2582 return NULL;
2583
2584 if(!iter->Back && node->Prev->Prev)
2585 {
2586 item = node->Prev->Prev->Item;
2587 iter->Here = node->Prev->Prev;
2588 iter->Back = ajTrue;
2589 }
2590 else
2591 {
2592 item = node->Prev->Item;
2593 iter->Here = node->Prev;
2594 }
2595
2596 return item;
2597 }
2598
2599
2600
2601
2602 /* @section modifiers *********************************************************
2603 **
2604 ** @fdata [AjIList]
2605 **
2606 ** @nam4rule Insert Insert a new value at iterator position
2607 ** @nam4rule Remove Remove value at iterator position
2608 ** @nam4rule Rewind Rewind list to start
2609 **
2610 ** @argrule * iter [AjIList] String iterator
2611 ** @argrule Insert item [void*] Value
2612 **
2613 ** @valrule * [void]
2614 **
2615 ** @fcategory modify
2616 ******************************************************************************/
2617
2618
2619
2620
2621 /* @func ajListIterInsert *****************************************************
2622 **
2623 ** Insert an item in a list, using an iterator (if not null)
2624 ** to show which position to insert. Otherwise, simply push.
2625 **
2626 ** @param [u] iter [AjIList] List iterator.
2627 ** @param [u] item [void*] Data item to insert.
2628 ** @return [void]
2629 **
2630 ** @release 5.0.0
2631 ** @@
2632 ******************************************************************************/
2633
ajListIterInsert(AjIList iter,void * item)2634 void ajListIterInsert(AjIList iter, void* item)
2635 {
2636 AjPList list = iter->Head;
2637
2638 AjPListNode node = NULL;
2639
2640 /* ajDebug("ajListInsert\n");*/
2641
2642 if(!iter->Modify)
2643 {
2644 ajErr("ajListIterInsert called on a read-only iterator");
2645 return;
2646 }
2647
2648 node = iter->Here;
2649
2650 if(!iter->Back)
2651 {
2652 if(!node->Prev)
2653 listInsertNode(&list->First, item);
2654 else
2655 listInsertNode(&node->Prev->Next, item);
2656
2657 iter->Here = node->Prev;
2658 }
2659 else
2660 {
2661 if(!node->Next)
2662 ajFatal("Cannot add a new node for unused back iterator\n");
2663
2664 if(!node->Prev)
2665 listInsertNode(&list->First, item);
2666 else
2667 listInsertNode(&node->Prev->Next, item);
2668 }
2669
2670 list->Count++;
2671 #ifdef AJ_SAVESTATS
2672 if(list->Count > listMaxNum)
2673 listMaxNum = list->Count;
2674 #endif
2675
2676 /*ajListTrace(list);*/
2677 /*ajListIterTrace(iter);*/
2678
2679 return;
2680 }
2681
2682
2683
2684
2685 /* @func ajListIterRemove *****************************************************
2686 **
2687 ** Remove an item from a list, using an iterator (if not null)
2688 ** to show which item. Otherwise remove the first item.
2689 **
2690 ** We want to remove the item just fetched by the iterator.
2691 **
2692 ** @param [u] iter [AjIList] List iterator.
2693 ** @return [void]
2694 **
2695 ** @release 5.0.0
2696 ** @@
2697 ******************************************************************************/
2698
ajListIterRemove(AjIList iter)2699 void ajListIterRemove(AjIList iter)
2700 {
2701 AjPListNode node = NULL;
2702
2703 /* ajDebug("ajListIterRemove\n");*/
2704
2705 if(!iter->Modify)
2706 {
2707 ajDie("Attempt to modify read-only iterator with ajListIterRemove\n");
2708 return;
2709 }
2710
2711 node = iter->Here;
2712
2713 if(!iter->Back)
2714 {
2715 if(!node->Prev)
2716 ajDie("Attempt to delete from unused iterator\n");
2717
2718 if(!node->Prev->Prev)
2719 listNodeDel(&(iter->Head->First));
2720 else
2721 listNodeDel(&node->Prev->Prev->Next);
2722 }
2723 else
2724 listNodeDel(&node->Prev->Prev->Next);
2725
2726
2727 iter->Head->Count--;
2728
2729 return;
2730 }
2731
2732
2733
2734
2735 /* @func ajListIterRewind *****************************************************
2736 **
2737 ** Resets iterator to start position
2738 **
2739 ** @param [u] iter [AjIList] List iterator.
2740 ** @return [void]
2741 **
2742 ** @release 6.0.0
2743 ** @@
2744 ******************************************************************************/
2745
ajListIterRewind(AjIList iter)2746 void ajListIterRewind(AjIList iter)
2747 {
2748 const AjPList list = NULL;
2749
2750 AjPListNode node = NULL;
2751 AjPListNode tmp = NULL;
2752
2753 if(!iter)
2754 return;
2755
2756 if(iter->Modify)
2757 list = iter->Head;
2758 else
2759 list = iter->ReadHead;
2760
2761 if(iter->Back)
2762 {
2763 for(node=list->First; node->Next; node = node->Next)
2764 tmp = node;
2765
2766 iter->Here = tmp->Next;
2767 }
2768 else
2769 {
2770 iter->Here = list->First;
2771 }
2772
2773 return;
2774 }
2775
2776
2777
2778
2779 /* @section Trace functions ***************************************************
2780 **
2781 ** @fdata [AjIList]
2782 **
2783 ** @nam4rule Trace Trace contents to debug file
2784 **
2785 ** @argrule * iter [const AjIList] List
2786 **
2787 ** @valrule * [void]
2788 **
2789 ** @fcategory misc
2790 **
2791 ******************************************************************************/
2792
2793
2794
2795
2796 /* @func ajListIterTrace ******************************************************
2797 **
2798 ** Traces a list iterator and validates it.
2799 **
2800 ** @param [r] iter [const AjIList] list iterator to be traced.
2801 ** @return [void]
2802 **
2803 ** @release 1.0.0
2804 ** @@
2805 ******************************************************************************/
2806
ajListIterTrace(const AjIList iter)2807 void ajListIterTrace(const AjIList iter)
2808 {
2809 ajulong icount = 0;
2810
2811 if(!iter)
2812 {
2813 ajDebug("\nIterator NULL\n");
2814 return;
2815 }
2816
2817 if(iter->Head)
2818 icount = iter->Head->Count;
2819 else if(iter->ReadHead)
2820 icount = iter->ReadHead->Count;
2821
2822 ajDebug("\nIter Head %p ReadHead %p Here %p Back %B Modify %B Len: %Ld\n",
2823 iter->Head,iter->ReadHead,iter->Here,iter->Back,
2824 iter->Modify, icount);
2825
2826 return;
2827 }
2828
2829
2830
2831
2832 /* @datasection [AjPList] String lists ****************************************
2833 **
2834 ** Functions working on lists of string values
2835 **
2836 ** @nam2rule Liststr
2837 **
2838 ******************************************************************************/
2839
2840
2841
2842
2843 /* @section Constructors ******************************************************
2844 **
2845 ** Constructors for lists
2846 **
2847 ** @fdata [AjPList]
2848 **
2849 ** @fcategory new
2850 **
2851 ** @nam3rule New Constructor
2852 ** @nam4rule NewList Copy constructor with its own copy of the data
2853 ** @nam4rule NewListref Copy constructor with pointers to source data
2854 **
2855 ** @argrule NewList list [const AjPList] Source list
2856 ** @argrule NewListref list [const AjPList] Source list
2857 **
2858 ** @valrule * [AjPList] New list
2859 **
2860 ******************************************************************************/
2861
2862
2863
2864
2865 /* @func ajListstrNew *********************************************************
2866 **
2867 ** Creates a new string list.
2868 **
2869 ** @return [AjPList] new list;
2870 **
2871 ** @release 1.0.0
2872 ** @@
2873 ******************************************************************************/
2874
ajListstrNew(void)2875 AjPList ajListstrNew(void)
2876 {
2877 return listNew(&listDelStr);
2878 }
2879
2880
2881
2882
2883 /* @func ajListstrNewList *****************************************************
2884 **
2885 ** Copy a list, with copies of all the string values.
2886 **
2887 ** General data cannot be copied so this is a string-only function
2888 **
2889 ** @param [r] list [const AjPList] list to be copied
2890 ** @return [AjPList] new copied list.
2891 **
2892 ** @release 5.0.0
2893 ** @@
2894 ******************************************************************************/
2895
ajListstrNewList(const AjPList list)2896 AjPList ajListstrNewList(const AjPList list)
2897 {
2898 AjPList newlist = NULL;
2899
2900 AjPListNode node = NULL;
2901
2902 AjPStr tmpstr = NULL;
2903
2904 if(!list)
2905 return NULL;
2906
2907 newlist = listNew(&listDelStr);
2908 newlist->Fitemdel = list->Fitemdel;
2909
2910 for( node=list->First; node->Next; node=node->Next)
2911 {
2912 tmpstr = ajStrNewS(node->Item);
2913 ajListstrPushAppend(newlist, tmpstr);
2914 }
2915
2916
2917 return newlist;
2918 }
2919
2920
2921
2922
2923 /* @func ajListstrNewListref **************************************************
2924 **
2925 ** Copy a string list.
2926 **
2927 ** WARNING: pointers to the data are copied, NOT the data
2928 ** so be careful when cleaning up after copy.
2929 **
2930 ** @param [r] list [const AjPList] List to be copied
2931 ** @return [AjPList] New, copied, list.
2932 **
2933 ** @release 5.0.0
2934 ** @@
2935 ******************************************************************************/
2936
ajListstrNewListref(const AjPList list)2937 AjPList ajListstrNewListref(const AjPList list)
2938 {
2939 return ajListNewListref(list);
2940 }
2941
2942
2943
2944
2945 /* @section Adding values *****************************************************
2946 **
2947 ** @fdata [AjPList]
2948 **
2949 ** @nam3rule Push Add new key and value
2950 ** @nam4rule PushAppend Add to end of list
2951 ** @nam3rule Pushlist Add new list of values
2952 **
2953 ** @argrule * list [AjPList] List
2954 ** @argrule Push str [AjPStr] Pointer to data.
2955 ** @argrule Pushlist Plist [AjPList*] Source AJAX List address to be deleted
2956 **
2957 ** @valrule * [void]
2958 **
2959 ** @fcategory modify
2960 ******************************************************************************/
2961
2962
2963
2964
2965 /* @func ajListstrPush ********************************************************
2966 **
2967 ** Add a new node at the start of a string list.
2968 **
2969 ** @param [u] list [AjPList] list to be changed.
2970 ** @param [u] str [AjPStr] String data.
2971 ** @return [void]
2972 **
2973 ** @release 1.0.0
2974 ** @@
2975 ******************************************************************************/
2976
ajListstrPush(AjPList list,AjPStr str)2977 void ajListstrPush(AjPList list, AjPStr str)
2978 {
2979 ajListPush(list, (void*) str);
2980
2981 return;
2982 }
2983
2984
2985
2986
2987 /* @func ajListstrPushAppend **************************************************
2988 **
2989 ** Add a new node at the end of the list and add the
2990 ** data pointer.
2991 **
2992 ** @param [u] list [AjPList] List to be changed.
2993 ** @param [u] str [AjPStr] String to append.
2994 ** @return [void]
2995 **
2996 ** @release 5.0.0
2997 ** @@
2998 ******************************************************************************/
2999
ajListstrPushAppend(AjPList list,AjPStr str)3000 void ajListstrPushAppend(AjPList list, AjPStr str)
3001 {
3002 ajListPushAppend(list, (void*) str);
3003
3004 return;
3005 }
3006
3007
3008
3009
3010 /* @func ajListstrPushlist ****************************************************
3011 **
3012 ** Adds a list to the start of the current list, then deletes the second list.
3013 **
3014 ** @param [u] list [AjPList] List.
3015 ** @param [d] Plist [AjPList*] AJAX List address to be merged.
3016 ** @return [void]
3017 **
3018 ** @release 5.0.0
3019 ** @@
3020 ******************************************************************************/
3021
ajListstrPushlist(AjPList list,AjPList * Plist)3022 void ajListstrPushlist(AjPList list, AjPList* Plist)
3023 {
3024 ajListPushlist(list, Plist);
3025
3026 return;
3027 }
3028
3029
3030
3031
3032 /* @section Modifiers *********************************************************
3033 **
3034 ** @fdata [AjPList]
3035 **
3036 ** Modifies a list
3037 **
3038 ** @nam3rule Map Apply function to each node
3039 ** @nam3rule Reverse Reverse the order of nodes
3040 **
3041 ** @argrule * list [AjPList] List
3042 ** @argrule Map apply [void function] Function to apply
3043 ** @argrule Map cl [void*] Data (usually NULL) to be passed to apply.
3044 **
3045 ** @valrule * [void]
3046 **
3047 ** @fcategory modify
3048 **
3049 ******************************************************************************/
3050
3051
3052
3053
3054 /* @func ajListstrMap *********************************************************
3055 **
3056 ** For each node in the list call function apply,
3057 ** with the address of the string and a client pointer.
3058 **
3059 ** @param [u] list [AjPList] List.
3060 ** @param [f] apply [void function] Function to call for each list item.
3061 ** @param [u] cl [void*] Standard, usually NULL.
3062 ** @return [void]
3063 **
3064 ** @release 1.0.0
3065 ** @@
3066 ******************************************************************************/
3067
ajListstrMap(AjPList list,void (* apply)(AjPStr * str,void * cl),void * cl)3068 void ajListstrMap(AjPList list,
3069 void (*apply)(AjPStr* str, void* cl), void* cl)
3070 {
3071 AjPListNode rest = NULL;
3072
3073 assert(apply);
3074
3075 for(rest = list->First; rest->Next; rest = rest->Next)
3076 (*apply)((AjPStr*) &rest->Item, cl);
3077
3078 return;
3079 }
3080
3081
3082
3083
3084 /* @func ajListstrReverse *****************************************************
3085 **
3086 ** Reverse the order of the nodes in a string list.
3087 **
3088 ** @param [u] list [AjPList] List
3089 ** @return [void]
3090 **
3091 ** @release 1.0.0
3092 ** @@
3093 ******************************************************************************/
3094
ajListstrReverse(AjPList list)3095 void ajListstrReverse(AjPList list)
3096 {
3097 ajListReverse(list);
3098
3099 return;
3100 }
3101
3102
3103
3104
3105 /* @section Removing data *****************************************************
3106 **
3107 ** @fdata [AjPList]
3108 **
3109 ** Retrieves values from a list
3110 **
3111 ** @nam3rule Pop Retrieve next value
3112 ** @nam4rule PopLast Retrieve last value
3113 **
3114 ** @argrule * list [AjPList] List
3115 ** @argrule Pop Pstr [AjPStr*] Value
3116 **
3117 ** @valrule * [AjBool] True on success
3118 ** @fcategory cast
3119 **
3120 ******************************************************************************/
3121
3122
3123
3124
3125 /* @func ajListstrPop *********************************************************
3126 **
3127 ** Remove the first node but set pointer to data first.
3128 **
3129 ** @param [u] list [AjPList] List
3130 ** @param [w] Pstr [AjPStr*] String
3131 ** @return [AjBool] ajTrue on success.
3132 **
3133 ** @release 1.0.0
3134 ** @@
3135 ******************************************************************************/
3136
ajListstrPop(AjPList list,AjPStr * Pstr)3137 AjBool ajListstrPop(AjPList list, AjPStr* Pstr)
3138 {
3139 if(!list)
3140 return ajFalse;
3141
3142 if(Pstr)
3143 {
3144 ajStrDel(Pstr);
3145 *Pstr = (AjPStr) listNodeItem(list->First);
3146 }
3147
3148 if(!listNodeDel(&list->First))
3149 return ajFalse;
3150
3151 list->First->Prev = NULL;
3152 list->Count--;
3153
3154 return ajTrue;
3155 }
3156
3157
3158
3159
3160 /* @func ajListstrPopLast *****************************************************
3161 **
3162 ** Remove the last node but set pointer to data first.
3163 **
3164 ** @param [u] list [AjPList] List
3165 ** @param [w] Pstr [AjPStr*] String
3166 ** @return [AjBool] ajTrue on success.
3167 **
3168 ** @release 5.0.0
3169 ** @@
3170 ******************************************************************************/
3171
ajListstrPopLast(AjPList list,AjPStr * Pstr)3172 AjBool ajListstrPopLast(AjPList list, AjPStr* Pstr)
3173 {
3174 AjPListNode node = NULL;
3175
3176 if(!list)
3177 return ajFalse;
3178
3179 if(!list->Count)
3180 return ajFalse;
3181
3182 node = list->Last->Prev;
3183
3184 if(Pstr)
3185 {
3186 ajStrDel(Pstr);
3187 *Pstr = (AjPStr) listNodeItem(node);
3188 }
3189
3190 if(list->Count == 1)
3191 {
3192 list->Last->Prev = NULL;
3193
3194 if(listFreeNext >= listFreeMax)
3195 listFreeSetExpand();
3196
3197 if(listFreeNext >= listFreeMax)
3198 AJFREE(list->First);
3199 else if(list->First)
3200 listFreeSet[listFreeNext++] = list->First;
3201
3202 list->First = list->Last;
3203 }
3204 else
3205 {
3206 node->Prev->Next = list->Last;
3207 list->Last->Prev = node->Prev;
3208
3209 if(listFreeNext >= listFreeMax)
3210 listFreeSetExpand();
3211
3212 if(listFreeNext >= listFreeMax)
3213 AJFREE(node);
3214 else if(node)
3215 {
3216 listFreeSet[listFreeNext++] = node;
3217 node = NULL;
3218 }
3219 }
3220
3221 --list->Count;
3222
3223 return ajTrue;
3224 }
3225
3226
3227
3228
3229 /* @section Element retrieval *************************************************
3230 **
3231 ** @fdata [AjPList]
3232 **
3233 ** Retrieves attributes or values from a list without changing it
3234 **
3235 ** @nam3rule Get Retrieve attribute
3236 ** @nam4rule GetLength Retrieve list length
3237 ** @nam4rule GetMemsize Retrieve memory used by list
3238 ** @nam3rule Mapfind Apply function to each node without modifying list
3239 ** or data
3240 ** @nam3rule Mapread Apply function to each node without modifying list or data
3241 ** @nam3rule Peek Pointer to next value
3242 ** @nam4rule PeekFirst Pointer to first value
3243 ** @nam4rule PeekLast Pointer to last value
3244 ** @nam4rule PeekNumber Pointer to numbered value
3245 ** @nam3rule Toarray Build array of values
3246 ** @nam4rule ToarrayAppend Append to array of values
3247 **
3248 ** @argrule * list [const AjPList] List
3249 ** @argrule Mapfind apply [AjBool function] Function to apply
3250 ** @argrule Mapfind cl [void*] Data (usually NULL) to be passed to apply.
3251 ** @argrule Mapread apply [void function] Function to apply
3252 ** @argrule Mapread cl [void*] Data (usually NULL) to be passed to apply.
3253 ** @argrule PeekNumber ipos [ajuint] Position in list
3254 ** @argrule Peek Pstr [AjPStr*] Value
3255 ** @argrule Toarray array [AjPStr**] Array of values, ending with NULL
3256 **
3257 ** @valrule * [AjBool] True on success
3258 ** @valrule *Length [ajulong] List length
3259 ** @valrule *Memsize [ajulong] Memory used
3260 ** @valrule *Mapfind [AjBool]
3261 ** @valrule *Mapread [void]
3262 ** @valrule *Toarray [ajulong] Array size, excluding final NULL
3263 **
3264 ** @fcategory cast
3265 **
3266 ******************************************************************************/
3267
3268
3269
3270
3271 /* @func ajListstrGetLength ***************************************************
3272 **
3273 ** get the number of nodes in the linked list.
3274 **
3275 ** @param [r] list [const AjPList] List
3276 ** @return [ajulong] Number of nodes in list.
3277 **
3278 ** @release 5.0.0
3279 ** @@
3280 ******************************************************************************/
3281
ajListstrGetLength(const AjPList list)3282 ajulong ajListstrGetLength(const AjPList list)
3283 {
3284 return ajListGetLength(list);
3285 }
3286
3287
3288
3289
3290 /* @func ajListstrGetMemsize **************************************************
3291 **
3292 ** get the memory used nodes in the linked string list.
3293 **
3294 ** @param [r] list [const AjPList] List
3295 ** @return [ajulong] Number of bytes allocated in list.
3296 **
3297 ** @release 6.5.0
3298 ** @@
3299 ******************************************************************************/
3300
ajListstrGetMemsize(const AjPList list)3301 ajulong ajListstrGetMemsize(const AjPList list)
3302 {
3303 ajulong lbytes = 0L;
3304 AjPListNode node = NULL;
3305 AjPStr tmpstr;
3306
3307 if(!list)
3308 return lbytes;
3309
3310 for(node = list->First; node->Next; node=node->Next)
3311 {
3312 tmpstr = (AjPStr) listNodeItem(node);
3313 lbytes += (sizeof(*node) + sizeof(*tmpstr) + tmpstr->Res);
3314 }
3315
3316 lbytes += sizeof(*node);
3317 lbytes += sizeof(*list);
3318
3319 return lbytes;
3320 }
3321
3322
3323
3324
3325 /* @func ajListstrMapfind *****************************************************
3326 **
3327 ** For each node in the list call function apply and return
3328 ** ajTrue when any node is matched by the function.
3329 **
3330 ** @param [r] list [const AjPList] List
3331 ** @param [f] apply [AjBool function] Function to call to test each list item.
3332 ** @param [u] cl [void*] Standard, usually NULL.
3333 ** @return [AjBool] ajTrue on success.
3334 **
3335 ** @release 5.0.0
3336 ** @@
3337 ******************************************************************************/
3338
ajListstrMapfind(const AjPList list,AjBool (* apply)(AjPStr * Pstr,void * cl),void * cl)3339 AjBool ajListstrMapfind(const AjPList list,
3340 AjBool (*apply)(AjPStr* Pstr, void* cl),
3341 void* cl)
3342 {
3343 AjPListNode listnode = NULL;
3344
3345 assert(list);
3346
3347 assert(apply);
3348
3349 for(listnode = list->First; listnode->Next; listnode = listnode->Next)
3350 if((*apply)((AjPStr*) &listnode->Item, cl))
3351 return ajTrue;
3352
3353 return ajFalse;
3354 }
3355
3356
3357
3358
3359 /* @func ajListstrMapread *****************************************************
3360 **
3361 ** For each node in the list call function apply,
3362 ** with the address of the string and a client pointer.
3363 ** The apply function must not modify the list elements.
3364 **
3365 ** @param [r] list [const AjPList] List.
3366 ** @param [f] apply [void function] Function to call for each list item.
3367 ** @param [u] cl [void*] Standard, usually NULL.
3368 ** @return [void]
3369 **
3370 ** @release 5.0.0
3371 ** @@
3372 ******************************************************************************/
3373
ajListstrMapread(const AjPList list,void (* apply)(AjPStr str,void * cl),void * cl)3374 void ajListstrMapread(const AjPList list,
3375 void (*apply)(AjPStr str, void* cl), void* cl)
3376 {
3377 AjPListNode rest = NULL;
3378
3379 assert(apply);
3380
3381 for(rest = list->First; rest->Next; rest = rest->Next)
3382 (*apply)((AjPStr) rest->Item, cl);
3383
3384
3385 return;
3386 }
3387
3388
3389
3390
3391 /* @func ajListstrPeek ********************************************************
3392 **
3393 ** Return the first node but keep it on the list.
3394 **
3395 ** @param [r] list [const AjPList] List
3396 ** @param [w] Pstr [AjPStr*] String
3397 ** @return [AjBool] ajTrue on success.
3398 **
3399 ** @release 2.7.0
3400 ** @@
3401 ******************************************************************************/
3402
ajListstrPeek(const AjPList list,AjPStr * Pstr)3403 AjBool ajListstrPeek(const AjPList list, AjPStr* Pstr)
3404 {
3405 if(!list)
3406 return ajFalse;
3407
3408 if(!list->Count)
3409 return ajFalse;
3410
3411 if(Pstr)
3412 *Pstr = (AjPStr) listNodeItem(list->First);
3413
3414 return ajTrue;
3415 }
3416
3417
3418
3419
3420 /* @func ajListstrToarray *****************************************************
3421 **
3422 ** create an array of the pointers to the data.
3423 **
3424 ** @param [r] list [const AjPList] List
3425 ** @param [w] array [AjPStr**] Array of Strings.
3426 **
3427 ** @return [ajulong] Size of array of pointers.
3428 **
3429 ** @release 5.0.0
3430 ** @@
3431 ******************************************************************************/
3432
ajListstrToarray(const AjPList list,AjPStr ** array)3433 ajulong ajListstrToarray(const AjPList list, AjPStr** array)
3434 {
3435 ajulong i = 0UL;
3436 ajulong n = 0UL;
3437
3438 AjPListNode rest = NULL;
3439
3440 n = list->Count;
3441 rest = list->First;
3442
3443 if(!n)
3444 {
3445 *array = NULL;
3446
3447 return 0UL;
3448 }
3449
3450 *array = AJALLOC((size_t) (n + 1) * sizeof(array));
3451
3452 for(i = 0UL; i < n; i++)
3453 {
3454 (*array)[i] = (AjPStr) rest->Item;
3455 rest = rest->Next;
3456 }
3457
3458 (*array)[n] = (AjPStr) NULL;
3459
3460 return n;
3461 }
3462
3463
3464
3465
3466 /* @func ajListstrToarrayAppend ***********************************************
3467 **
3468 ** append to an array of the pointers to the data.
3469 **
3470 ** @param [r] list [const AjPList] List
3471 ** @param [w] array [AjPStr**] Array of Strings.
3472 **
3473 ** @return [ajulong] Size of array of pointers.
3474 **
3475 **
3476 ** @release 5.0.0
3477 ** @@
3478 ******************************************************************************/
3479
ajListstrToarrayAppend(const AjPList list,AjPStr ** array)3480 ajulong ajListstrToarrayAppend(const AjPList list, AjPStr** array)
3481 {
3482 ajulong i = 0UL;
3483 ajulong n = 0UL;
3484 ajulong j = 0UL;
3485
3486 AjPListNode rest = NULL;
3487
3488 rest = list->First;
3489
3490 if(*array)
3491 {
3492 for(j = 0UL; array[j]; j++)
3493 continue;
3494 }
3495 else
3496 j = 0UL;
3497
3498 n = list->Count + j;
3499
3500 if(!n)
3501 {
3502 *array = NULL;
3503
3504 return 0UL;
3505 }
3506
3507 AJCRESIZE(*array, (size_t) (n + 1));
3508
3509 for(i = j; i < n; i++)
3510 {
3511 (*array)[i] = (AjPStr) rest->Item;
3512 rest = rest->Next;
3513 }
3514
3515 (*array)[n] = (AjPStr) NULL;
3516
3517 return n;
3518 }
3519
3520
3521
3522
3523 /* @section Trace functions ***************************************************
3524 **
3525 ** @fdata [AjPList]
3526 **
3527 ** @nam3rule Print Trace contents to standard error
3528 ** @nam3rule Trace Trace contents to debug file
3529 **
3530 ** @argrule * list [const AjPList] List
3531 **
3532 ** @valrule * [void]
3533 **
3534 ** @fcategory misc
3535 **
3536 ******************************************************************************/
3537
3538
3539
3540
3541 /* @func ajListstrTrace *******************************************************
3542 **
3543 ** Traces through a string list and validates it
3544 **
3545 ** @param [r] list [const AjPList] list to be traced.
3546 ** @return [void]
3547 **
3548 ** @release 1.0.0
3549 ** @@
3550 ******************************************************************************/
3551
ajListstrTrace(const AjPList list)3552 void ajListstrTrace(const AjPList list)
3553 {
3554 ajulong i = 0UL;
3555
3556 AjPListNode node = NULL;
3557
3558 if(!list)
3559 return;
3560
3561 ajDebug("\nList Trace %p count %Lu\n",
3562 list, list->Count);
3563 ajDebug("rest-> %p last-> %p\n",
3564 list->First, list->Last);
3565
3566 for(node = list->First; node->Next; node = node->Next)
3567 {
3568 i++;
3569 ajDebug("Item[%Lu] item %p '%S' rest -> %p prev -> %p\n",
3570 i, node, (AjPStr) node->Item, node->Next, node->Prev);
3571 }
3572
3573 if(i != list->Count)
3574 {
3575 ajErr("*** list error expect %Lu items, found %Lu",
3576 list->Count, i);
3577 }
3578
3579 if(list->Last != node)
3580 {
3581 ajErr("*** list error expect end at %p, found at %p",
3582 list->Last, node);
3583 }
3584
3585 return;
3586 }
3587
3588
3589
3590
3591 /* @section Destructors *******************************************************
3592 **
3593 ** @fdata [AjPList]
3594 **
3595 ** Destructors can only deal with the list and cannot free complex data
3596 **
3597 ** @nam3rule Del Delete list
3598 ** @nam3rule Free Delete list
3599 ** @nam4rule FreeData Delete list and free values
3600 **
3601 ** @argrule * Plist [AjPList*] AJAX List address
3602 **
3603 ** @valrule * [void]
3604 **
3605 ** @fcategory delete
3606 **
3607 ******************************************************************************/
3608
3609
3610
3611
3612 /* @func ajListstrFree ********************************************************
3613 **
3614 ** Free the list. Do not attempt to free the nodes.
3615 ** For use where the node data has been saved elsewhere, for example
3616 ** by ajListToarray or where the list is a temporary structure
3617 ** referring to permanent data.
3618 **
3619 ** @param [d] Plist [AjPList*] AJAX List address
3620 ** @return [void]
3621 **
3622 ** @release 1.0.0
3623 ** @@
3624 ******************************************************************************/
3625
ajListstrFree(AjPList * Plist)3626 void ajListstrFree(AjPList* Plist)
3627 {
3628 ajListFree(Plist);
3629
3630 return;
3631 }
3632
3633
3634
3635
3636 /* @func ajListstrFreeData ****************************************************
3637 **
3638 ** Free all nodes in a string list.
3639 ** Also deletes all the strings. If these are to be preserved,
3640 ** use ajListstrDel instead.
3641 **
3642 ** @param [d] Plist [AjPList*] AJAX List address
3643 ** @return [void]
3644 **
3645 ** @release 5.0.0
3646 ** @@
3647 ******************************************************************************/
3648
ajListstrFreeData(AjPList * Plist)3649 void ajListstrFreeData(AjPList* Plist)
3650 {
3651 AjPList list = NULL;
3652
3653 AjPListNode next = NULL;
3654 AjPListNode* rest = NULL;
3655
3656 if(!Plist)
3657 return;
3658
3659 if(!*Plist)
3660 return;
3661
3662 #ifdef AJ_SAVESTATS
3663 listDelCnt++;
3664 #endif
3665
3666 list = *Plist;
3667 rest = &list->First;
3668
3669 if(list->Count)
3670 {
3671 /* free the data in the list (if we know how) */
3672 for(; (*rest)->Next; *rest = next)
3673 {
3674 next = (*rest)->Next;
3675 ajStrDel((AjPStr*) &(*rest)->Item);
3676
3677 if(listFreeNext >= listFreeMax)
3678 listFreeSetExpand();
3679
3680 if(listFreeNext >= listFreeMax)
3681 AJFREE(*rest);
3682 else if(*rest)
3683 {
3684 listFreeSet[listFreeNext++] = *rest;
3685 *rest=NULL;
3686 }
3687 }
3688
3689 ajStrDel((AjPStr*) &(*rest)->Item);
3690 }
3691
3692
3693 if(listFreeNext >= listFreeMax)
3694 listFreeSetExpand();
3695
3696 if(listFreeNext >= listFreeMax)
3697 AJFREE(*rest);
3698 else if(*rest)
3699 {
3700 listFreeSet[listFreeNext++] = *rest;
3701 *rest = NULL;
3702 }
3703
3704 AJFREE(*Plist);
3705
3706 return;
3707 }
3708
3709
3710
3711
3712 /* @datasection [AjIList] String list iterators *******************************
3713 **
3714 ** Function is for manipulating lists with string values.
3715 **
3716 ** Some functions are specially designed to understand string (AjPStr) values.
3717 **
3718 ** @nam2rule Liststr String list data
3719 ** @nam3rule Iter Iterator
3720 **
3721 ******************************************************************************/
3722
3723
3724
3725
3726 /* @section stepping **********************************************************
3727 **
3728 ** @fdata [AjIList]
3729 **
3730 ** @nam4rule Get Next value.
3731 ** @nam5rule GetBack Next value in reverse direction
3732 **
3733 ** @argrule * iter [AjIList] String iterator
3734 **
3735 ** @valrule * [AjPStr] Value
3736 **
3737 ** @fcategory modify
3738 ******************************************************************************/
3739
3740
3741
3742
3743 /* @func ajListstrIterGet *****************************************************
3744 **
3745 ** Returns next item using iterator, or steps off the end.
3746 **
3747 ** @param [u] iter [AjIList] List iterator.
3748 ** @return [AjPStr] Data item returned.
3749 **
3750 ** @release 6.0.0
3751 ** @@
3752 ******************************************************************************/
3753
ajListstrIterGet(AjIList iter)3754 AjPStr ajListstrIterGet(AjIList iter)
3755 {
3756 void* item = NULL;
3757
3758 AjPListNode node = NULL;
3759
3760 if(!iter)
3761 return NULL;
3762
3763 node = iter->Here;
3764
3765 if(!iter->Back)
3766 {
3767 if(!node->Next)
3768 return NULL;
3769
3770 item = node->Item;
3771 iter->Here = node->Next;
3772 }
3773 else
3774 {
3775 if(!node->Next->Next || !node->Next->Next->Next)
3776 return NULL;
3777
3778 iter->Back = ajFalse;
3779 item = node->Next->Item;
3780 iter->Here = node->Next->Next;
3781 }
3782
3783 return (AjPStr) item;
3784 }
3785
3786
3787
3788
3789 /* @func ajListstrIterGetBack *************************************************
3790 **
3791 ** Returns next item using back iterator.
3792 **
3793 ** @param [u] iter [AjIList] List iterator.
3794 ** @return [AjPStr] Data item returned.
3795 **
3796 ** @release 6.0.0
3797 ** @@
3798 ******************************************************************************/
3799
ajListstrIterGetBack(AjIList iter)3800 AjPStr ajListstrIterGetBack(AjIList iter)
3801 {
3802 void* item = NULL;
3803
3804 AjPListNode node = NULL;
3805
3806 if(!iter)
3807 return NULL;
3808
3809 node = iter->Here;
3810
3811 if(!node->Prev)
3812 return NULL;
3813
3814 if(!iter->Back)
3815 {
3816 item = node->Prev->Prev->Item;
3817 iter->Here = node->Prev->Prev;
3818 iter->Back = ajTrue;
3819 }
3820 else
3821 {
3822 item = node->Prev->Item;
3823 iter->Here = node->Prev;
3824 }
3825
3826 return (AjPStr) item;
3827 }
3828
3829
3830
3831
3832 /* @section modifiers *********************************************************
3833 **
3834 ** @fdata [AjIList]
3835 **
3836 ** @nam4rule Insert Insert a new value at iterator position
3837 ** @nam4rule Remove Remove value at iterator position
3838 **
3839 ** @argrule * iter [AjIList] String iterator
3840 ** @argrule Insert str [AjPStr] Value
3841 **
3842 ** @valrule * [void]
3843 **
3844 ** @fcategory modify
3845 ******************************************************************************/
3846
3847
3848
3849
3850 /* @func ajListstrIterInsert **************************************************
3851 **
3852 ** Insert an item in a list, using an iterator (if not null)
3853 ** to show which position to insert. Otherwise, simply push.
3854 **
3855 ** @param [u] iter [AjIList] List iterator.
3856 ** @param [u] str [AjPStr] String to insert.
3857 ** @return [void]
3858 **
3859 ** @release 5.0.0
3860 ** @@
3861 ******************************************************************************/
3862
ajListstrIterInsert(AjIList iter,AjPStr str)3863 void ajListstrIterInsert(AjIList iter, AjPStr str)
3864 {
3865 AjPList list = iter->Head;
3866
3867 AjPListNode node = NULL;
3868
3869 /*ajDebug("ajListstrInsert\n");*/
3870 ajListstrTrace(list);
3871 ajListstrIterTrace(iter);
3872
3873 if(!iter->Modify)
3874 {
3875 ajErr("ajListInsert called on a read-only iterator");
3876 return;
3877 }
3878
3879 node = iter->Here;
3880
3881
3882 if(!iter->Back)
3883 {
3884 if(!node->Prev)
3885 listInsertNode(&list->First, str);
3886 else
3887 listInsertNode(&node->Prev->Next, str);
3888 iter->Here = node->Prev;
3889 }
3890 else
3891 {
3892 if(!node->Next)
3893 ajFatal("Cannot add a new node for unused back iterator\n");
3894
3895 if(!node->Prev)
3896 listInsertNode(&list->First, str);
3897 else
3898 listInsertNode(&node->Prev->Next, str);
3899 }
3900
3901 list->Count++;
3902 #ifdef AJ_SAVESTATS
3903 if(list->Count > listMaxNum)
3904 listMaxNum = list->Count;
3905 #endif
3906
3907 ajListstrTrace(list);
3908 ajListstrIterTrace(iter);
3909
3910 return;
3911 }
3912
3913
3914
3915
3916 /* @func ajListstrIterRemove **************************************************
3917 **
3918 ** Remove an item from a list, using an iterator (if not null)
3919 ** to show which item. Otherwise remove the first item.
3920 **
3921 ** We want to remove the item just fetched by the iterator.
3922 **
3923 ** @param [u] iter [AjIList] List iterator.
3924 ** @return [void]
3925 **
3926 ** @release 5.0.0
3927 ** @@
3928 ******************************************************************************/
3929
ajListstrIterRemove(AjIList iter)3930 void ajListstrIterRemove(AjIList iter)
3931 {
3932 AjPListNode node = NULL;
3933
3934 /* ajDebug("ajListstrIterRemove\n");*/
3935
3936 if(!iter->Modify)
3937 {
3938 ajErr("ajListstrIterRemove called on a read-only iterator");
3939 return;
3940 }
3941
3942 node = iter->Here;
3943
3944 if(!iter->Back)
3945 {
3946 if(!node->Prev)
3947 ajFatal("Attempt to delete from unused iterator\n");
3948
3949 if(!node->Prev->Prev)
3950 {
3951 ajStrDel((AjPStr*) &(iter->Head->First->Item));
3952 listNodeDel(&(iter->Head->First));
3953 }
3954 else
3955 {
3956 ajStrDel((AjPStr*) &node->Prev->Prev->Next->Item);
3957 listNodeDel(&node->Prev->Prev->Next);
3958 }
3959 }
3960 else
3961 {
3962 ajStrDel((AjPStr*) &node->Prev->Prev->Next->Item);
3963 listNodeDel(&node->Prev->Prev->Next);
3964 }
3965
3966 iter->Head->Count--;
3967
3968 return;
3969 }
3970
3971
3972
3973
3974 /* @section Trace functions ***************************************************
3975 **
3976 ** @fdata [AjIList]
3977 **
3978 ** @nam4rule Trace Trace contents to debug file
3979 **
3980 ** @argrule * iter [const AjIList] List
3981 **
3982 ** @valrule * [void]
3983 **
3984 ** @fcategory misc
3985 **
3986 ******************************************************************************/
3987
3988
3989
3990
3991 /* @func ajListstrIterTrace ***************************************************
3992 **
3993 ** Traces a list iterator and validates it
3994 **
3995 ** @param [r] iter [const AjIList] List iterator to be traced.
3996 ** @return [void]
3997 **
3998 ** @release 1.0.0
3999 ** @@
4000 ******************************************************************************/
4001
ajListstrIterTrace(const AjIList iter)4002 void ajListstrIterTrace(const AjIList iter)
4003 {
4004 if(!iter)
4005 return;
4006
4007 ajDebug("\nIterator Head %p ReadHead %p Here %p Back %B Item %S\n",
4008 iter->Head, iter->ReadHead, iter->Here,iter->Back,
4009 (AjPStr)iter->Here->Item);
4010
4011 return;
4012 }
4013
4014
4015
4016
4017 #ifdef AJ_COMPILE_DEPRECATED_BOOK
4018 #endif
4019
4020
4021
4022
4023 #ifdef AJ_COMPILE_DEPRECATED
4024 /* @obsolete ajListCopy
4025 ** @rename ajListNewListref
4026 */
4027
ajListCopy(const AjPList list)4028 __deprecated AjPList ajListCopy(const AjPList list)
4029 {
4030 return ajListNewListref(list);
4031 }
4032
4033
4034
4035
4036 /* @obsolete ajListNewArgs
4037 ** @remove Use explicit ajListPush calls instead
4038 */
4039
ajListNewArgs(void * x,...)4040 __deprecated AjPList ajListNewArgs(void* x, ...)
4041 {
4042 AjPList list;
4043 va_list ap;
4044 ajint i = 0;
4045 void* y;
4046
4047 list = ajListNew();
4048
4049 if(!x)
4050 return list;
4051
4052 va_start(ap, x);
4053 y = x;
4054
4055 for( i=0; y; y = va_arg(ap, void*),i++)
4056 ajListPushAppend(list, y);
4057
4058 va_end(ap);
4059
4060 return list;
4061 }
4062
4063
4064
4065
4066 /* @obsolete ajListPushApp
4067 ** @rename ajListPushAppend
4068 */
4069
ajListPushApp(AjPList list,void * item)4070 __deprecated void ajListPushApp(AjPList list, void* item)
4071 {
4072 ajListPushAppend(list, item);
4073 return;
4074 }
4075
4076
4077
4078
4079 /* @obsolete ajListPushList
4080 ** @rename ajListPushlist
4081 */
4082
ajListPushList(AjPList list,AjPList * Plist)4083 __deprecated void ajListPushList(AjPList list, AjPList* Plist)
4084 {
4085 ajListPushlist(list, Plist);
4086 return;
4087 }
4088
4089
4090
4091
4092 /* @obsolete ajListGarbageCollect
4093 ** @replace ajListPurge (1,2,3/1,3,2)
4094 */
4095
ajListGarbageCollect(AjPList list,void (* itemdel)(void ** Pitem),AjBool (* test)(const void * item))4096 __deprecated void ajListGarbageCollect(AjPList list,
4097 void (*itemdel)(void** Pitem),
4098 AjBool (*test)(const void* item))
4099 {
4100 ajListPurge(list, test, itemdel);
4101 return;
4102 }
4103
4104
4105
4106
4107 /* @obsolete ajListSort2
4108 ** @rename ajListSortTwo
4109 */
4110
ajListSort2(AjPList list,int (* compar1)(const void * item1,const void * item2),int (* compar2)(const void * item1,const void * item2))4111 __deprecated void ajListSort2(AjPList list,
4112 int (*compar1)(const void* item1,
4113 const void* item2),
4114 int (*compar2)(const void* item1,
4115 const void* item2))
4116 {
4117 ajListSortTwo(list, compar1, compar2);
4118
4119 return;
4120 }
4121
4122
4123
4124
4125 /* @obsolete ajListSort3
4126 ** @rename ajListSortTwoThree
4127 */
4128
ajListSort3(AjPList list,int (* compar1)(const void * item1,const void * item2),int (* compar2)(const void * item1,const void * item2),int (* compar3)(const void * item1,const void * item2))4129 __deprecated void ajListSort3(AjPList list,
4130 int (*compar1)(const void* item1,
4131 const void* item2),
4132 int (*compar2)(const void* item1,
4133 const void* item2),
4134 int (*compar3)(const void* item1,
4135 const void* item2))
4136 {
4137 ajListSortTwoThree(list, compar1, compar2, compar3);
4138
4139 return;
4140 }
4141
4142
4143
4144
4145 /* @obsolete ajListUnique2
4146 ** @rename ajListSortTwoUnique
4147 */
4148
ajListUnique2(AjPList list,int (* compar1)(const void * item1,const void * item2),int (* compar2)(const void * item1,const void * item2),void (* itemdel)(void ** Pitem,void * cl))4149 __deprecated void ajListUnique2(AjPList list,
4150 int (*compar1)(const void* item1,
4151 const void* item2),
4152 int (*compar2)(const void* item1,
4153 const void* item2),
4154 void (*itemdel)(void** Pitem,
4155 void* cl))
4156 {
4157 ajListSortTwoUnique(list, compar1, compar2, itemdel);
4158
4159 return;
4160 }
4161
4162
4163
4164
4165 /* @obsolete ajListUnique
4166 ** @rename ajListSortUnique
4167 */
4168
ajListUnique(AjPList list,int (* compar)(const void * item1,const void * item2),void (* itemdel)(void ** Pitem,void * cl))4169 __deprecated void ajListUnique(AjPList list,
4170 int (*compar)(const void* item1,
4171 const void* item2),
4172 void (*itemdel)(void** Pitem,
4173 void* cl))
4174 {
4175 ajListSortUnique(list, compar, itemdel);
4176
4177 return;
4178 }
4179
4180
4181
4182
4183 /* @obsolete ajListPopEnd
4184 ** @rename ajListPopLast
4185 */
4186
ajListPopEnd(AjPList list,void ** Pitem)4187 __deprecated AjBool ajListPopEnd(AjPList list, void** Pitem)
4188 {
4189 return ajListPopLast(list, Pitem);
4190 }
4191
4192
4193
4194
4195 /* @obsolete ajListLength
4196 ** @rename ajListGetLength
4197 */
4198
ajListLength(const AjPList list)4199 __deprecated ajuint ajListLength(const AjPList list)
4200 {
4201 return ajListGetLength(list);
4202 }
4203
4204
4205
4206
4207 /* @obsolete ajListFind
4208 ** @rename ajListMapfind
4209 */
4210
ajListFind(const AjPList list,AjBool (* apply)(void ** Pitem,void * cl),void * cl)4211 __deprecated AjBool ajListFind(const AjPList list,
4212 AjBool (*apply)(void** Pitem, void* cl),
4213 void* cl)
4214 {
4215 return ajListMapfind(list, apply, cl);
4216 }
4217
4218
4219
4220
4221 /* @obsolete ajListMapRead
4222 ** @rename ajListMapread
4223 */
4224
ajListMapRead(const AjPList list,void (* apply)(void * item,void * cl),void * cl)4225 __deprecated void ajListMapRead(const AjPList list,
4226 void (*apply)(void* item, void* cl), void* cl)
4227 {
4228 ajListMapread(list, apply, cl);
4229 return;
4230 }
4231
4232
4233
4234
4235 /* @obsolete ajListFirst
4236 ** @rename ajListPeekFirst
4237 */
4238
ajListFirst(const AjPList list,void ** Pitem)4239 __deprecated AjBool ajListFirst(const AjPList list, void** Pitem)
4240 {
4241 return ajListPeekFirst(list, Pitem);
4242 }
4243
4244
4245
4246
4247 /* @obsolete ajListLast
4248 ** @rename ajListPeekLast
4249 */
4250
ajListLast(const AjPList list,void ** Pitem)4251 __deprecated AjBool ajListLast(const AjPList list, void** Pitem)
4252 {
4253 return ajListPeekLast(list, Pitem);
4254 }
4255
4256
4257
4258
4259 /* @obsolete ajListNth
4260 ** @rename ajListPeekNumber
4261 */
4262
ajListNth(const AjPList list,ajuint ipos,void ** Pitem)4263 __deprecated AjBool ajListNth(const AjPList list, ajuint ipos, void** Pitem)
4264 {
4265 return ajListPeekNumber(list, ipos, Pitem);
4266 }
4267
4268
4269
4270
4271 /* @obsolete ajListToArray
4272 ** @rename ajListToarray
4273 */
4274
ajListToArray(const AjPList list,void *** array)4275 __deprecated ajuint ajListToArray(const AjPList list, void*** array)
4276 {
4277 return ajListToarray(list, array);
4278 }
4279
4280
4281
4282
4283 /* @obsolete ajListDel
4284 ** @rename ajListFree
4285 */
4286
ajListDel(AjPList * Plist)4287 __deprecated void ajListDel(AjPList* Plist)
4288 {
4289 AjPList list = NULL;
4290
4291 AjPListNode* rest = NULL;
4292 AjPListNode next = NULL;
4293
4294 if(!Plist)
4295 return;
4296
4297 if(!*Plist)
4298 return;
4299
4300 #ifdef AJ_SAVESTATS
4301 listDelCnt++;
4302 #endif
4303
4304 list = *Plist;
4305
4306 if(!list->Use)
4307 ajErr("trying to delete unused list");
4308
4309 --list->Use;
4310
4311 if(!list->Use)
4312 { /* any other references? */
4313 rest = &list->First;
4314
4315 if(list->Count)
4316 for(; (*rest)->Next; *rest = next)
4317 {
4318 next = (*rest)->Next;
4319
4320 if(listFreeNext >= listFreeMax)
4321 listFreeSetExpand();
4322
4323 if(listFreeNext >= listFreeMax)
4324 AJFREE(*rest);
4325 else if(*rest)
4326 {
4327 listFreeSet[listFreeNext++] = *rest;
4328 *rest = NULL;
4329 }
4330 }
4331
4332 if(listFreeNext >= listFreeMax)
4333 listFreeSetExpand();
4334
4335 if(listFreeNext >= listFreeMax)
4336 AJFREE(*rest);
4337 else if(*rest)
4338 {
4339 listFreeSet[listFreeNext++] = *rest;
4340 *rest = NULL;
4341 }
4342
4343 AJFREE(*Plist);
4344 }
4345
4346 *Plist = NULL;
4347
4348 return;
4349 }
4350
4351
4352
4353
4354 /* @obsolete ajListIter
4355 ** @rename ajListIterNew
4356 */
4357
ajListIter(AjPList list)4358 __deprecated AjIList ajListIter(AjPList list)
4359 {
4360 return ajListIterNew(list);
4361 }
4362
4363
4364
4365
4366 /* @obsolete ajListIterBack
4367 ** @rename ajListIterNewBack
4368 */
4369
ajListIterBack(AjPList list)4370 __deprecated AjIList ajListIterBack(AjPList list)
4371 {
4372 return ajListIterNewBack(list);
4373 }
4374
4375
4376
4377
4378 /* @obsolete ajListIterRead
4379 ** @rename ajListIterNewread
4380 */
4381
ajListIterRead(const AjPList list)4382 __deprecated AjIList ajListIterRead(const AjPList list)
4383 {
4384 return ajListIterNewread(list);
4385 }
4386
4387
4388
4389
4390 /* @obsolete ajListIterBackRead
4391 ** @rename ajListIterNewreadBack
4392 */
4393
ajListIterBackRead(const AjPList list)4394 __deprecated AjIList ajListIterBackRead(const AjPList list)
4395 {
4396 return ajListIterNewreadBack(list);
4397 }
4398
4399
4400
4401
4402 /* @obsolete ajListNodesNew
4403 ** @remove Use calls to ajListPush
4404 */
ajListNodesNew(void * x,...)4405 __deprecated AjPListNode ajListNodesNew(void* x, ...)
4406 {
4407 va_list ap;
4408
4409 AjPListNode topnode = NULL;
4410 AjPListNode node = NULL;
4411
4412 va_start(ap, x);
4413
4414 topnode = listDummyNode(&node);
4415
4416 /*ajDebug("ajListNodesNew topnode: %p -> %p\n",
4417 topnode, topnode->Next);*/
4418 for(; x; x = va_arg(ap, void*))
4419 {
4420 node->Item = x;
4421 listDummyNode(&node->Next);
4422 node->Next->Prev = node;
4423 /*ajDebug("topnode: %p node: %p, item: %p -> %p\n",
4424 topnode, node, x, node->Next);*/
4425 }
4426
4427 va_end(ap);
4428
4429 topnode->Prev = NULL;
4430
4431 /*listNodesTrace(node);*/
4432
4433 return node;
4434 }
4435
4436
4437
4438
4439 /* @obsolete ajListAppend
4440 ** @remove append data with ajListPushAppend
4441 */
4442
ajListAppend(AjPList list,AjPListNode * morenodes)4443 __deprecated void ajListAppend(AjPList list, AjPListNode* morenodes)
4444 {
4445 AjPListNode more = *morenodes;
4446
4447 assert(list);
4448 /*listNodesTrace(*morenodes);*/
4449
4450 more->Next->Prev = list->Last;
4451 list->Last->Next = more->Next;
4452 list->Last->Item = more->Item;
4453
4454 while(more->Next)
4455 { /* need to get to the end of the list */
4456 more = more->Next;
4457 list->Count++;
4458 #ifdef AJ_SAVESTATS
4459 if(list->Count > listMaxNum)
4460 listMaxNum = list->Count;
4461 #endif
4462 }
4463
4464 list->Last = more; /* now we can set the end of the list */
4465 AJFREE(*morenodes); /* first extra node (only) was duplicated */
4466
4467 return;
4468 }
4469
4470
4471
4472
4473 /* @obsolete ajListIterMoreBack
4474 ** @remove use ajListIterDoneBack
4475 */
4476
ajListIterMoreBack(const AjIList iter)4477 __deprecated AjBool ajListIterMoreBack(const AjIList iter)
4478 {
4479 return (!ajListIterDoneBack(iter));
4480 }
4481
4482
4483
4484
4485 /* @obsolete ajListIterBackDone
4486 ** @rename ajListIterDoneBack
4487 */
4488
ajListIterBackDone(const AjIList iter)4489 __deprecated AjBool ajListIterBackDone(const AjIList iter)
4490 {
4491 return ajListIterDoneBack(iter);
4492 }
4493
4494
4495
4496
4497 /* @obsolete ajListIterFree
4498 ** @rename ajListIterDel
4499 */
4500
ajListIterFree(AjIList * iter)4501 __deprecated void ajListIterFree(AjIList* iter)
4502 {
4503 ajListIterDel(iter);
4504 return;
4505 }
4506
4507
4508
4509
4510 /* @obsolete ajListIterBackMore
4511 ** @remove use ajListIterDoneBack
4512 */
4513
ajListIterBackMore(const AjIList iter)4514 __deprecated AjBool ajListIterBackMore(const AjIList iter)
4515 {
4516 return (!ajListIterDoneBack(iter));
4517 }
4518
4519
4520
4521
4522 /* @obsolete ajListIterNext
4523 ** @rename ajListIterGet
4524 */
4525
ajListIterNext(AjIList iter)4526 __deprecated void* ajListIterNext(AjIList iter)
4527 {
4528 return ajListIterGet(iter);
4529 }
4530
4531
4532
4533
4534 /* @obsolete ajListIterBackNext
4535 ** @rename ajListIterGetBack
4536 */
4537
ajListIterBackNext(AjIList iter)4538 __deprecated void* ajListIterBackNext(AjIList iter)
4539 {
4540 return ajListIterGetBack(iter);
4541 }
4542
4543
4544
4545
4546 /* @obsolete ajListInsert
4547 ** @rename ajListIterInsert
4548 */
4549
ajListInsert(AjIList iter,void * item)4550 __deprecated void ajListInsert(AjIList iter, void* item)
4551 {
4552 ajListIterInsert(iter, item);
4553 return;
4554 }
4555
4556
4557
4558
4559 /* @obsolete ajListRemove
4560 ** @rename ajListIterRemove
4561 */
4562
ajListRemove(AjIList iter)4563 __deprecated void ajListRemove(AjIList iter)
4564 {
4565
4566 ajListIterRemove(iter);
4567 return;
4568 }
4569
4570
4571
4572
4573 /* @obsolete ajListstrClone
4574 ** @remove use ajListstrNewList
4575 */
4576
ajListstrClone(const AjPList list,AjPList newlist)4577 __deprecated ajuint ajListstrClone(const AjPList list, AjPList newlist)
4578 {
4579 ajint ret = 0;
4580
4581 AjPListNode node = NULL;
4582
4583 AjPStr newstr = NULL;
4584
4585 if(!list)
4586 return 0U;
4587
4588 if(!newlist)
4589 return 0U;
4590
4591 for(node = list->First; node->Next; node = node->Next)
4592 {
4593 newstr = NULL;
4594 ajStrAssignS(&newstr, node->Item);
4595 ajListPushAppend(newlist, newstr);
4596 ret++;
4597 }
4598
4599 return ret;
4600 }
4601
4602
4603
4604
4605 /* @obsolete ajListstrCopy
4606 ** @rename ajListstrNewList
4607 */
4608
ajListstrCopy(const AjPList list)4609 __deprecated AjPList ajListstrCopy(const AjPList list)
4610 {
4611 return ajListstrNewListref(list);
4612 }
4613
4614
4615
4616
4617 /* @obsolete ajListstrPushApp
4618 ** @rename ajListstrPushAppend
4619 */
4620
ajListstrPushApp(AjPList list,AjPStr str)4621 __deprecated void ajListstrPushApp(AjPList list, AjPStr str)
4622 {
4623
4624 ajListstrPushAppend(list, str);
4625
4626 return;
4627 }
4628
4629
4630
4631
4632 /* @obsolete ajListstrPushList
4633 ** @rename ajListstrPushlist
4634 */
4635
ajListstrPushList(AjPList list,AjPList * Plist)4636 __deprecated void ajListstrPushList(AjPList list, AjPList* Plist)
4637 {
4638 ajListstrPushlist(list, Plist);
4639
4640 return;
4641 }
4642
4643
4644
4645
4646 /* @obsolete ajListstrPopEnd
4647 ** @rename ajListstrPopLast
4648 */
4649
ajListstrPopEnd(AjPList list,AjPStr * Pstr)4650 __deprecated AjBool ajListstrPopEnd(AjPList list, AjPStr* Pstr)
4651 {
4652 return ajListstrPopLast(list, Pstr);
4653 }
4654
4655
4656
4657
4658 /* @obsolete ajListstrLength
4659 ** @rename ajListstrGetLength
4660 */
4661
ajListstrLength(const AjPList list)4662 __deprecated ajuint ajListstrLength(const AjPList list)
4663 {
4664 return ajListstrGetLength(list);
4665 }
4666
4667
4668
4669
4670 /* @obsolete ajListstrFind
4671 ** @rename ajListstrMapfind
4672 */
4673
ajListstrFind(const AjPList list,AjBool (* apply)(AjPStr * Pstr,void * cl),void * cl)4674 __deprecated AjBool ajListstrFind(const AjPList list,
4675 AjBool (*apply)(AjPStr* Pstr, void* cl),
4676 void* cl)
4677 {
4678 return ajListstrMapfind(list, apply, cl);
4679 }
4680
4681
4682
4683
4684 /* @obsolete ajListstrMapRead
4685 ** @rename ajListstrMapread
4686 */
4687
ajListstrMapRead(const AjPList list,void (* apply)(AjPStr str,void * cl),void * cl)4688 __deprecated void ajListstrMapRead(const AjPList list,
4689 void (*apply)(AjPStr str, void* cl),
4690 void* cl)
4691 {
4692
4693 ajListstrMapread(list, apply, cl);
4694
4695 return;
4696 }
4697
4698
4699
4700
4701 /* @obsolete ajListstrToArray
4702 ** @rename ajListstrToarray
4703 */
4704
ajListstrToArray(const AjPList list,AjPStr ** array)4705 __deprecated ajuint ajListstrToArray(const AjPList list, AjPStr** array)
4706 {
4707 return ajListstrToarray(list, array);
4708 }
4709
4710
4711
4712
4713 /* @obsolete ajListstrToArrayApp
4714 ** @rename ajListstrToarrayAppend
4715 */
4716
ajListstrToArrayApp(const AjPList list,AjPStr ** array)4717 __deprecated ajuint ajListstrToArrayApp(const AjPList list, AjPStr** array)
4718 {
4719 return ajListstrToarrayAppend(list, array);
4720 }
4721
4722
4723
4724
4725 /* @obsolete ajListstrNewArgs
4726 ** @remove Use ajListstrNew and ajListPush
4727 */
ajListstrNewArgs(AjPStr x,...)4728 __deprecated AjPList ajListstrNewArgs(AjPStr x, ...)
4729 {
4730 va_list ap;
4731 ajint i = 0;
4732
4733 AjPList list = NULL;
4734
4735 AjPStr y = NULL;
4736
4737 list = ajListstrNew();
4738
4739 if(!x)
4740 return list;
4741
4742 va_start(ap, x);
4743 y = x;
4744
4745 for( i=0; y; y = va_arg(ap, AjPStr),i++)
4746 ajListstrPushAppend(list, y);
4747
4748 va_end(ap);
4749
4750 return list;
4751 }
4752
4753
4754
4755
4756 /* @obsolete ajListstrDel
4757 ** @rename ajListstrFree
4758 */
4759
ajListstrDel(AjPList * Plist)4760 __deprecated void ajListstrDel(AjPList* Plist)
4761 {
4762 ajListstrFree(Plist);
4763
4764 return;
4765 }
4766
4767
4768
4769
4770 /* @obsolete ajListstrInsert
4771 ** @rename ajListstrIterInsert
4772 */
4773
ajListstrInsert(AjIList iter,AjPStr str)4774 __deprecated void ajListstrInsert(AjIList iter, AjPStr str)
4775 {
4776 ajListstrIterInsert(iter, str);
4777
4778 return;
4779 }
4780
4781
4782
4783
4784 /* @obsolete ajListstrRemove
4785 ** @rename ajListstrIterRemove
4786 */
4787
ajListstrRemove(AjIList iter)4788 __deprecated void ajListstrRemove(AjIList iter)
4789 {
4790 ajListstrIterRemove(iter);
4791
4792 return;
4793 }
4794 #endif
4795