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