File: sort.c

package info (click to toggle)
gup 0.5.11
  • links: PTS
  • area: main
  • in suites: etch, etch-m68k, sarge
  • size: 188 kB
  • ctags: 168
  • sloc: ansic: 1,606; sh: 213; makefile: 56
file content (78 lines) | stat: -rw-r--r-- 1,944 bytes parent folder | download | duplicates (5)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
/*
 * Sort a list of wildmat groupname in a sorted ASCII order. Well,
 * it's sortof sorted. The basic idea is that only the characters
 * upto the first wildmat special character are compared.
 *
 * It is *not safe, as you might assume to accept matching wildmat
 * chars and continue. Consider:
 *
 * A.*.A3
 * A.[.A2
 * A.*.A1
 *
 * This routine uses qsort() and does not rely on it being stable
 * (which it's not) to maintain order. Pity really, a stable qsort()
 * would make my life a bit easier. Instead they made qsort()'s life a
 * bit easier - sigh.
 *
 * Note that the inbound list is worthless after this routine.
 */

#include "gup.h"

static int mat_compare(const GROUP **g1, const GROUP **g2);

extern LIST *sort_groups(LIST *glist)
{
    LIST *slist;
    GROUP **stab;
    GROUP *gp;
    int st_ix;

    /* Construct the sort table */
    stab = calloc(LIST_LENGTH(glist), sizeof(GROUP *));
    if (!stab)
	gupout(1, "Malloc of sort table failed");

    st_ix = 0;
    TRAVERSE(glist, gp) {
	gp->order = st_ix;	/* Maintain order for exact matches */
	stab[st_ix++] = gp;
    }

    /* Do the sort */
    qsort(stab, LIST_LENGTH(glist), sizeof(GROUP *), mat_compare);

    /* Build the results list */
    slist = create_list();

    for (st_ix = 0; st_ix < LIST_LENGTH(glist); st_ix++)
	add_group(slist, stab[st_ix]);

    free(stab);
    free(glist);

    return slist;
}


static int mat_compare(const GROUP **g1, const GROUP **g2)
{
    register char c1, c2;
    const char *cp1, *cp2;

    for (cp1 = (*g1)->name, cp2 = (*g2)->name;; cp1++, cp2++) {
	c1 = *cp1;
	c2 = *cp2;

	if (!c1 || !c2)
	    return c1 - c2;	/* Hit end of string */

	/* If either character is a meta character, return original order */
	if ((c1 == '\\') || (c1 == '?') || (c1 == '*') || (c1 == '[') ||
	    (c2 == '\\') || (c2 == '?') || (c2 == '*') || (c2 == '['))
	    return (*g1)->order - (*g2)->order;
	if (c1 != c2)
	    return c1 - c2;
    }
}