1 /* sort.c -- LDAP library entry and value sort routines */
2 /* $OpenLDAP: pkg/ldap/libraries/libldap/sort.c,v 1.27.2.4 2008/02/11 23:26:41 kurt Exp $ */
3 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
5 * Copyright 1998-2008 The OpenLDAP Foundation.
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted only as authorized by the OpenLDAP
12 * A copy of this license is available in the file LICENSE in the
13 * top-level directory of the distribution or, alternatively, at
14 * <http://www.OpenLDAP.org/license.html>.
16 /* Portions Copyright (c) 1994 Regents of the University of Michigan.
17 * All rights reserved.
19 * Redistribution and use in source and binary forms are permitted
20 * provided that this notice is preserved and that due credit is given
21 * to the University of Michigan at Ann Arbor. The name of the University
22 * may not be used to endorse or promote products derived from this
23 * software without specific prior written permission. This software
24 * is provided ``as is'' without express or implied warranty.
30 #include <ac/stdlib.h>
33 #include <ac/string.h>
42 int (*et_cmp_fn
) LDAP_P((const char *a
, const char *b
));
45 static int et_cmp
LDAP_P(( const void *aa
, const void *bb
));
54 return( strcasecmp( *(char *const *)a
, *(char *const *)b
) );
64 const struct entrything
*a
= (const struct entrything
*)aa
;
65 const struct entrything
*b
= (const struct entrything
*)bb
;
67 if ( a
->et_vals
== NULL
&& b
->et_vals
== NULL
)
69 if ( a
->et_vals
== NULL
)
71 if ( b
->et_vals
== NULL
)
74 for ( i
= 0; a
->et_vals
[i
] && b
->et_vals
[i
]; i
++ ) {
75 if ( (rc
= a
->et_cmp_fn( a
->et_vals
[i
], b
->et_vals
[i
] )) != 0 ) {
80 if ( a
->et_vals
[i
] == NULL
&& b
->et_vals
[i
] == NULL
)
82 if ( a
->et_vals
[i
] == NULL
)
91 LDAP_CONST
char *attr
, /* NULL => sort by DN */
92 int (*cmp
) (LDAP_CONST
char *, LDAP_CONST
char *)
96 struct entrything
*et
;
97 LDAPMessage
*e
, *ehead
= NULL
, *etail
= NULL
;
98 LDAPMessage
*ohead
= NULL
, *otail
= NULL
;
101 assert( ld
!= NULL
);
103 /* Separate entries from non-entries */
104 for ( e
= *chain
; e
; e
=e
->lm_chain
) {
105 if ( e
->lm_msgtype
== LDAP_RES_SEARCH_ENTRY
) {
107 if ( !ehead
) ehead
= e
;
108 if ( etail
) etail
->lm_chain
= e
;
111 if ( !ohead
) ohead
= e
;
112 if ( otail
) otail
->lm_chain
= e
;
118 /* zero or one entries -- already sorted! */
120 etail
->lm_chain
= ohead
;
128 if ( (et
= (struct entrything
*) LDAP_MALLOC( count
*
129 sizeof(struct entrything
) )) == NULL
) {
130 ld
->ld_errno
= LDAP_NO_MEMORY
;
135 for ( i
= 0; i
< count
; i
++ ) {
136 et
[i
].et_cmp_fn
= cmp
;
138 if ( attr
== NULL
) {
141 dn
= ldap_get_dn( ld
, e
);
142 et
[i
].et_vals
= ldap_explode_dn( dn
, 1 );
145 et
[i
].et_vals
= ldap_get_values( ld
, e
, attr
);
151 qsort( et
, count
, sizeof(struct entrything
), et_cmp
);
154 for ( i
= 0; i
< count
; i
++ ) {
156 ep
= &(*ep
)->lm_chain
;
158 LDAP_VFREE( et
[i
].et_vals
);
161 (*chain
)->lm_chain_tail
= otail
? otail
: etail
;
163 LDAP_FREE( (char *) et
);
172 int (*cmp
) (LDAP_CONST
void *, LDAP_CONST
void *)
177 for ( nel
= 0; vals
[nel
] != NULL
; nel
++ )
180 qsort( vals
, nel
, sizeof(char *), cmp
);