]> git.sur5r.net Git - openldap/blob - libraries/libldap/sort.c
Added check for sendmsg(). Added hack to use BSD sendmsg()/recvmsg() to
[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         assert( ld != NULL );
94
95         count = ldap_count_entries( ld, *chain );
96
97         if ( count < 0 ) {
98                 return -1;
99
100         } else if ( count < 2 ) {
101                 /* zero or one entries -- already sorted! */
102                 return 0;
103         }
104
105         if ( (et = (struct entrything *) LDAP_MALLOC( count *
106             sizeof(struct entrything) )) == NULL ) {
107                 ld->ld_errno = LDAP_NO_MEMORY;
108                 return( -1 );
109         }
110
111         e = *chain;
112         for ( i = 0; i < count; i++ ) {
113                 et[i].et_cmp_fn = cmp;
114                 et[i].et_msg = e;
115                 if ( attr == NULL ) {
116                         char    *dn;
117
118                         dn = ldap_get_dn( ld, e );
119                         et[i].et_vals = ldap_explode_dn( dn, 1 );
120                         LDAP_FREE( dn );
121                 } else {
122                         et[i].et_vals = ldap_get_values( ld, e, attr );
123                 }
124
125                 e = e->lm_chain;
126         }
127         last = e;
128
129         qsort( et, count, sizeof(struct entrything), et_cmp );
130
131         ep = chain;
132         for ( i = 0; i < count; i++ ) {
133                 *ep = et[i].et_msg;
134                 ep = &(*ep)->lm_chain;
135
136                 LDAP_VFREE( et[i].et_vals );
137         }
138         *ep = last;
139         LDAP_FREE( (char *) et );
140
141         return( 0 );
142 }
143
144 int
145 ldap_sort_values(
146     LDAP        *ld,
147     char        **vals,
148     int         (*cmp) (LDAP_CONST void *, LDAP_CONST void *)
149 )
150 {
151         int     nel;
152
153         for ( nel = 0; vals[nel] != NULL; nel++ )
154                 ;       /* NULL */
155
156         qsort( vals, nel, sizeof(char *), cmp );
157
158         return( 0 );
159 }