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