1 /* the Music Player Daemon (MPD)
2 * Copyright (C) 2003-2007 by Warren Dukes (warren.dukes@gmail.com)
3 * This project's homepage is: http://www.musicpd.org
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
28 static void makeListNodesArray(List
* list
)
30 ListNode
*node
= list
->firstNode
;
33 if (!list
->numberOfNodes
)
36 list
->nodesArray
= xrealloc(list
->nodesArray
,
37 sizeof(ListNode
*) * list
->numberOfNodes
);
39 for (i
= 0; i
< list
->numberOfNodes
; i
++) {
40 list
->nodesArray
[i
] = node
;
41 node
= node
->nextNode
;
45 static void freeListNodesArray(List
* list
)
47 if (!list
->nodesArray
)
49 free(list
->nodesArray
);
50 list
->nodesArray
= NULL
;
53 List
*makeList(ListFreeDataFunc
* freeDataFunc
, int strdupKeys
)
55 List
*list
= xmalloc(sizeof(List
));
60 list
->firstNode
= NULL
;
61 list
->lastNode
= NULL
;
62 list
->freeDataFunc
= freeDataFunc
;
63 list
->numberOfNodes
= 0;
64 list
->nodesArray
= NULL
;
65 list
->strdupKeys
= strdupKeys
;
70 ListNode
*insertInListBeforeNode(List
* list
, ListNode
* beforeNode
, int pos
,
71 char *key
, void *data
)
77 /*assert(data!=NULL); */
79 node
= xmalloc(sizeof(ListNode
));
82 node
->nextNode
= beforeNode
;
83 if (beforeNode
== list
->firstNode
) {
84 if (list
->firstNode
== NULL
) {
85 assert(list
->lastNode
== NULL
);
86 list
->lastNode
= node
;
88 assert(list
->lastNode
!= NULL
);
89 assert(list
->lastNode
->nextNode
== NULL
);
90 list
->firstNode
->prevNode
= node
;
92 node
->prevNode
= NULL
;
93 list
->firstNode
= node
;
96 node
->prevNode
= beforeNode
->prevNode
;
97 beforeNode
->prevNode
= node
;
99 node
->prevNode
= list
->lastNode
;
100 list
->lastNode
= node
;
102 node
->prevNode
->nextNode
= node
;
105 if (list
->strdupKeys
)
106 node
->key
= xstrdup(key
);
112 list
->numberOfNodes
++;
115 list
->nodesArray
= xrealloc(list
->nodesArray
,
116 list
->numberOfNodes
*
118 if (node
== list
->lastNode
) {
119 list
->nodesArray
[list
->numberOfNodes
- 1] = node
;
121 makeListNodesArray(list
);
123 memmove(list
->nodesArray
+ pos
+ 1,
124 list
->nodesArray
+ pos
,
125 sizeof(ListNode
*) * (list
->numberOfNodes
-
127 list
->nodesArray
[pos
] = node
;
134 ListNode
*insertInList(List
* list
, char *key
, void *data
)
138 assert(list
!= NULL
);
140 /*assert(data!=NULL); */
142 node
= xmalloc(sizeof(ListNode
));
143 assert(node
!= NULL
);
145 if (list
->nodesArray
)
146 freeListNodesArray(list
);
148 if (list
->firstNode
== NULL
) {
149 assert(list
->lastNode
== NULL
);
150 list
->firstNode
= node
;
152 assert(list
->lastNode
!= NULL
);
153 assert(list
->lastNode
->nextNode
== NULL
);
154 list
->lastNode
->nextNode
= node
;
157 if (list
->strdupKeys
)
158 node
->key
= xstrdup(key
);
163 node
->nextNode
= NULL
;
164 node
->prevNode
= list
->lastNode
;
166 list
->lastNode
= node
;
168 list
->numberOfNodes
++;
173 int insertInListWithoutKey(List
* list
, void *data
)
177 assert(list
!= NULL
);
178 assert(data
!= NULL
);
180 node
= xmalloc(sizeof(ListNode
));
181 assert(node
!= NULL
);
183 if (list
->nodesArray
)
184 freeListNodesArray(list
);
186 if (list
->firstNode
== NULL
) {
187 assert(list
->lastNode
== NULL
);
188 list
->firstNode
= node
;
190 assert(list
->lastNode
!= NULL
);
191 assert(list
->lastNode
->nextNode
== NULL
);
192 list
->lastNode
->nextNode
= node
;
197 node
->nextNode
= NULL
;
198 node
->prevNode
= list
->lastNode
;
200 list
->lastNode
= node
;
202 list
->numberOfNodes
++;
207 /* if _key_ is not found, *_node_ is assigned to the node before which
208 the info would be found */
209 int findNodeInList(List
* list
, char *key
, ListNode
** node
, int *pos
)
217 assert(list
!= NULL
);
219 if (list
->sorted
&& list
->nodesArray
) {
220 high
= list
->numberOfNodes
- 1;
225 cur
= (high
+ low
) / 2;
226 tmpNode
= list
->nodesArray
[cur
];
227 cmp
= strcmp(tmpNode
->key
, key
);
243 tmpNode
= list
->nodesArray
[cur
];
246 cmp
= tmpNode
? strcmp(tmpNode
->key
, key
) : -1;
258 *node
= list
->firstNode
;
262 tmpNode
= list
->firstNode
;
264 while (tmpNode
!= NULL
&& strcmp(tmpNode
->key
, key
) != 0) {
265 tmpNode
= tmpNode
->nextNode
;
276 int findInList(List
* list
, char *key
, void **data
)
281 if (findNodeInList(list
, key
, &node
, &pos
)) {
290 ListNode
*getNodeByPosition(List
*list
, int pos
)
294 assert(list
!= NULL
);
295 if (pos
< 0 || pos
>= list
->numberOfNodes
)
298 tmpNode
= list
->firstNode
;
300 tmpNode
= tmpNode
->nextNode
;
305 int deleteFromList(List
* list
, char *key
)
309 assert(list
!= NULL
);
311 tmpNode
= list
->firstNode
;
313 while (tmpNode
!= NULL
&& strcmp(tmpNode
->key
, key
) != 0) {
314 tmpNode
= tmpNode
->nextNode
;
318 deleteNodeFromList(list
, tmpNode
);
325 void deleteNodeFromList(List
* list
, ListNode
* node
)
327 assert(list
!= NULL
);
328 assert(node
!= NULL
);
330 if (node
->prevNode
== NULL
) {
331 list
->firstNode
= node
->nextNode
;
333 node
->prevNode
->nextNode
= node
->nextNode
;
335 if (node
->nextNode
== NULL
) {
336 list
->lastNode
= node
->prevNode
;
338 node
->nextNode
->prevNode
= node
->prevNode
;
340 if (list
->freeDataFunc
) {
341 list
->freeDataFunc(node
->data
);
344 if (list
->strdupKeys
)
347 list
->numberOfNodes
--;
349 if (list
->nodesArray
) {
350 freeListNodesArray(list
);
352 makeListNodesArray(list
);
357 void freeList(void *list
)
362 assert(list
!= NULL
);
364 tmpNode
= ((List
*) list
)->firstNode
;
366 if (((List
*) list
)->nodesArray
)
367 free(((List
*) list
)->nodesArray
);
369 while (tmpNode
!= NULL
) {
370 tmpNode2
= tmpNode
->nextNode
;
371 if (((List
*) list
)->strdupKeys
)
373 if (((List
*) list
)->freeDataFunc
) {
374 ((List
*) list
)->freeDataFunc(tmpNode
->data
);
383 static void swapNodes(ListNode
* nodeA
, ListNode
* nodeB
)
388 assert(nodeA
!= NULL
);
389 assert(nodeB
!= NULL
);
394 nodeB
->key
= nodeA
->key
;
395 nodeB
->data
= nodeA
->data
;
401 static void bubbleSort(ListNode
** nodesArray
, long start
, long end
)
410 for (j
= start
; j
< end
; j
++) {
411 for (i
= end
- 1; i
>= start
; i
--) {
412 node
= nodesArray
[i
];
413 if (strcmp(node
->key
, node
->nextNode
->key
) > 0) {
414 swapNodes(node
, node
->nextNode
);
420 static void quickSort(ListNode
** nodesArray
, long start
, long end
)
424 else if (end
- start
< 5)
425 bubbleSort(nodesArray
, start
, end
);
433 List
*startList
= makeList(free
, 0);
434 List
*endList
= makeList(free
, 0);
435 long *startPtr
= xmalloc(sizeof(long));
436 long *endPtr
= xmalloc(sizeof(long));
439 insertInListWithoutKey(startList
, (void *)startPtr
);
440 insertInListWithoutKey(endList
, (void *)endPtr
);
442 while (startList
->numberOfNodes
) {
443 start
= *((long *)startList
->lastNode
->data
);
444 end
= *((long *)endList
->lastNode
->data
);
446 if (end
- start
< 5) {
447 bubbleSort(nodesArray
, start
, end
);
448 deleteNodeFromList(startList
,
449 startList
->lastNode
);
450 deleteNodeFromList(endList
, endList
->lastNode
);
452 pivot
= (start
+ end
) / 2;
453 pivotNode
= nodesArray
[pivot
];
454 pivotKey
= pivotNode
->key
;
456 for (i
= pivot
- 1; i
>= start
; i
--) {
457 node
= nodesArray
[i
];
458 if (strcmp(node
->key
, pivotKey
) > 0) {
467 pivotNode
= nodesArray
[pivot
];
470 for (i
= pivot
+ 1; i
<= end
; i
++) {
471 node
= nodesArray
[i
];
472 if (strcmp(pivotKey
, node
->key
) > 0) {
481 pivotNode
= nodesArray
[pivot
];
485 deleteNodeFromList(startList
,
486 startList
->lastNode
);
487 deleteNodeFromList(endList
, endList
->lastNode
);
489 if (pivot
- 1 - start
> 0) {
490 startPtr
= xmalloc(sizeof(long));
491 endPtr
= xmalloc(sizeof(long));
494 insertInListWithoutKey(startList
,
497 insertInListWithoutKey(endList
,
501 if (end
- pivot
- 1 > 0) {
502 startPtr
= xmalloc(sizeof(long));
503 endPtr
= xmalloc(sizeof(long));
504 *startPtr
= pivot
+ 1;
506 insertInListWithoutKey(startList
,
509 insertInListWithoutKey(endList
,
520 void sortList(List
* list
)
522 assert(list
!= NULL
);
526 if (list
->numberOfNodes
< 2)
529 if (list
->nodesArray
)
530 freeListNodesArray(list
);
531 makeListNodesArray(list
);
533 quickSort(list
->nodesArray
, 0, list
->numberOfNodes
- 1);