2 * The dhcpd-pools has BSD 2-clause license which also known as "Simplified
3 * BSD License" or "FreeBSD License".
5 * Copyright 2006- Sami Kerola. All rights reserved.
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions are
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in the
16 * documentation and/or other materials provided with the
19 * THIS SOFTWARE IS PROVIDED BY <COPYRIGHT HOLDER> ``AS IS'' AND ANY EXPRESS
20 * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
21 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
22 * DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> OR CONTRIBUTORS BE
23 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
29 * THE POSSIBILITY OF SUCH DAMAGE.
31 * The views and conclusions contained in the software and documentation are
32 * those of the authors and should not be interpreted as representing
33 * official policies, either expressed or implied, of Sami Kerola.
42 #include "dhcpd-pools.h"
44 /* Sort functions for range sorting */
45 int intcomp(const void *x, const void *y)
47 if (*(unsigned long int *) x < *(unsigned long int *) y)
49 else if (*(unsigned long int *) y < *(unsigned long int *) x)
55 int rangecomp(const void *r1, const void *r2)
57 if ((((struct range_t *) r1)->first_ip) <
58 (((struct range_t *) r2)->first_ip))
60 else if ((((struct range_t *) r2)->first_ip) <
61 (((struct range_t *) r1)->first_ip))
67 unsigned long int ret_ip(struct range_t r)
72 unsigned long int ret_cur(struct range_t r)
77 unsigned long int ret_max(struct range_t r)
79 return (r.last_ip - r.first_ip);
82 unsigned long int ret_percent(struct range_t r)
85 f = (float) r.count / (r.last_ip - r.first_ip - 1);
86 return ((unsigned long int) (f * 100000));
89 unsigned long int ret_touched(struct range_t r)
94 unsigned long int ret_tc(struct range_t r)
96 return (r.count + r.touched);
99 unsigned long int ret_tcperc(struct range_t r)
102 f = (float) (r.count + r.touched) / (r.last_ip - r.first_ip - 1);
103 return ((unsigned long int) (f * 10000));
106 void field_selector(char c)
121 returner = ret_percent;
124 returner = ret_touched;
130 returner = ret_tcperc;
133 warnx("field_selector: unknown sort order `%c'", c);
134 errx(EXIT_FAILURE, "Try `%s --help' for more information.",
135 program_invocation_short_name);
139 /* Needed to support multiple key sorting. */
140 int get_order(struct range_t *left, struct range_t *right)
143 unsigned long int lint, rint;
145 len = strlen(config.sort);
146 for (i = 0; i < len; i++) {
147 /* Handling strings is case of it's own */
148 if (config.sort[i] == 'n') {
150 strcmp(left->shared_net->name,
151 right->shared_net->name);
154 } else if (ret < 0) {
161 /* Select which function is pointed by returner */
162 field_selector(config.sort[i]);
163 lint = returner(*left);
164 rint = returner(*right);
165 /* If fields are equal use next sort method */
175 /* If all returners where equal */
179 void mergesort_ranges(struct range_t *orig, int size, struct range_t *temp)
183 /* Merge sort split size */
184 static const int MIN_MERGE_SIZE = 8;
186 if (size < MIN_MERGE_SIZE) {
187 for (left = 0; left < size; left++) {
188 hold = *(orig + left);
189 for (right = left - 1; 0 <= right; right--) {
190 if (get_order((orig + right), &hold)) {
193 *(orig + right + 1) = *(orig + right);
195 *(orig + right + 1) = hold;
200 mergesort_ranges(orig, size / 2, temp);
201 mergesort_ranges(orig + size / 2, size - size / 2, temp);
207 while (left < size / 2 && right < size) {
208 if (get_order((orig + left), (orig + right))) {
209 *(temp + i) = *(orig + left);
212 *(temp + i) = *(orig + right);
217 while (left < size / 2) {
218 *(temp + i) = *(orig + left);
222 while (right < size) {
223 *(temp + i) = *(orig + right);
228 memcpy(orig, temp, size * sizeof(struct range_t));