]> git.sur5r.net Git - openldap/blob - libraries/libldap/sort.c
706f8a768dfbf3e98157a2b950d93061eac7cf88
[openldap] / libraries / libldap / sort.c
1 /* $OpenLDAP$ */
2 /*
3  * Copyright 1998-2002 The OpenLDAP Foundation, All Rights Reserved.
4  * COPYING RESTRICTIONS APPLY, see COPYRIGHT file
5  */
6 /* Portions
7  * Copyright (c) 1994 Regents of the University of Michigan.
8  * All rights reserved.
9  *
10  * Redistribution and use in source and binary forms are permitted
11  * provided that this notice is preserved and that due credit is given
12  * to the University of Michigan at Ann Arbor. The name of the University
13  * may not be used to endorse or promote products derived from this
14  * software without specific prior written permission. This software
15  * is provided ``as is'' without express or implied warranty.
16  *
17  * sort.c:  LDAP library entry and value sort routines
18  */
19
20 #include "portable.h"
21
22 #include <stdio.h>
23 #include <ac/stdlib.h>
24
25 #include <ac/ctype.h>
26 #include <ac/string.h>
27 #include <ac/time.h>
28
29
30 #include "ldap-int.h"
31
32 struct entrything {
33         char            **et_vals;
34         LDAPMessage     *et_msg;
35         int             (*et_cmp_fn) LDAP_P((const char *a, const char *b));
36 };
37
38 static int      et_cmp LDAP_P(( const void *aa, const void *bb));
39
40
41 int
42 ldap_sort_strcasecmp(
43         LDAP_CONST void *a,
44         LDAP_CONST void *b
45 )
46 {
47         return( strcasecmp( *(char *const *)a, *(char *const *)b ) );
48 }
49
50 static int
51 et_cmp(
52         const void      *aa,
53         const void      *bb
54 )
55 {
56         int                     i, rc;
57         const struct entrything *a = (const struct entrything *)aa;
58         const struct entrything *b = (const struct entrything *)bb;
59
60         if ( a->et_vals == NULL && b->et_vals == NULL )
61                 return( 0 );
62         if ( a->et_vals == NULL )
63                 return( -1 );
64         if ( b->et_vals == NULL )
65                 return( 1 );
66
67         for ( i = 0; a->et_vals[i] && b->et_vals[i]; i++ ) {
68                 if ( (rc = a->et_cmp_fn( a->et_vals[i], b->et_vals[i] )) != 0 ) {
69                         return( rc );
70                 }
71         }
72
73         if ( a->et_vals[i] == NULL && b->et_vals[i] == NULL )
74                 return( 0 );
75         if ( a->et_vals[i] == NULL )
76                 return( -1 );
77         return( 1 );
78 }
79
80 int
81 ldap_sort_entries(
82     LDAP        *ld,
83     LDAPMessage **chain,
84     LDAP_CONST char     *attr,          /* NULL => sort by DN */
85     int         (*cmp) (LDAP_CONST  char *, LDAP_CONST char *)
86 )
87 {
88         int                     i, count;
89         struct entrything       *et;
90         LDAPMessage             *e, *last;
91         LDAPMessage             **ep;
92
93         count = ldap_count_entries( ld, *chain );
94
95
96         if ( count < 0 ) {
97                 if( ld != NULL ) {
98                         ld->ld_errno = LDAP_PARAM_ERROR;
99                 }
100                 return -1;
101
102         } else if ( count < 2 ) {
103                 /* zero or one entries -- already sorted! */
104                 return 0;
105         }
106
107         if ( (et = (struct entrything *) LDAP_MALLOC( count *
108             sizeof(struct entrything) )) == NULL ) {
109                 ld->ld_errno = LDAP_NO_MEMORY;
110                 return( -1 );
111         }
112
113         e = *chain;
114         for ( i = 0; i < count; i++ ) {
115                 et[i].et_cmp_fn = cmp;
116                 et[i].et_msg = e;
117                 if ( attr == NULL ) {
118                         char    *dn;
119
120                         dn = ldap_get_dn( ld, e );
121                         et[i].et_vals = ldap_explode_dn( dn, 1 );
122                         LDAP_FREE( dn );
123                 } else {
124                         et[i].et_vals = ldap_get_values( ld, e, attr );
125                 }
126
127                 e = e->lm_chain;
128         }
129         last = e;
130
131         qsort( et, count, sizeof(struct entrything), et_cmp );
132
133         ep = chain;
134         for ( i = 0; i < count; i++ ) {
135                 *ep = et[i].et_msg;
136                 ep = &(*ep)->lm_chain;
137
138                 LDAP_VFREE( et[i].et_vals );
139         }
140         *ep = last;
141         LDAP_FREE( (char *) et );
142
143         return( 0 );
144 }
145
146 int
147 ldap_sort_values(
148     LDAP        *ld,
149     char        **vals,
150     int         (*cmp) (LDAP_CONST void *, LDAP_CONST void *)
151 )
152 {
153         int     nel;
154
155         for ( nel = 0; vals[nel] != NULL; nel++ )
156                 ;       /* NULL */
157
158         qsort( vals, nel, sizeof(char *), cmp );
159
160         return( 0 );
161 }