Don't segfault when there's no target in If
[openbox.git] / obt / bsearch.h
blobceb53ff2854827e72d37b4e95e52f38d2e278a91
1 /* -*- indent-tabs-mode: nil; tab-width: 4; c-basic-offset: 4; -*-
3 obt/bsearch.h for the Openbox window manager
4 Copyright (c) 2010 Dana Jansens
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 See the COPYING file for a copy of the GNU General Public License.
19 #ifndef __obt_bsearch_h
20 #define __obt_bsearch_h
22 #include <glib.h>
24 G_BEGIN_DECLS
26 /*! Setup to do a binary search on an array. */
27 #define BSEARCH_SETUP() \
28 register guint l_BSEARCH, r_BSEARCH, out_BSEARCH; \
29 register gboolean nearest_BSEARCH; (void)nearest_BSEARCH;
31 /*! Helper macro that just returns the input */
32 #define BSEARCH_IS_T(t) (t)
34 /*! Search an array @ar holding elements of type @t, starting at index @start,
35 with @size elements, looking for value @val. */
36 #define BSEARCH(t, ar, start, size, val) \
37 BSEARCH_CMP(t, ar, start, size, val, BSEARCH_IS_T)
39 /*! Search an array @ar, starting at index @start,
40 with @size elements, looking for value @val of type @t,
41 using the macro @to_t to convert values in the arrau @ar to type @t.
43 If all elements in @ar are less than @val, then BSEARCH_AT() will be
44 the last element in @ar.
45 If all elements in @ar are greater than @val, then BSEARCH_AT() will be
46 the first element in @ar.
47 Otherwise, if the element @val is not found then BSEARCH_AT() will be set to
48 the position before the first element larger than @val.
50 #define BSEARCH_CMP(t, ar, start, size, val, to_t) \
51 do { \
52 out_BSEARCH = (start); \
53 l_BSEARCH = (size) > 0 ? (start) : (start + 1); \
54 r_BSEARCH = (size) > 0 ? (start)+(size)-1 : (start); \
55 nearest_BSEARCH = FALSE; \
56 while (l_BSEARCH <= r_BSEARCH) { \
57 /* m is in the middle, but to the left if there's an even number \
58 of elements */ \
59 out_BSEARCH = l_BSEARCH + (r_BSEARCH - l_BSEARCH)/2; \
60 if ((val) == to_t((ar)[out_BSEARCH])) { \
61 break; \
62 } \
63 else if ((val) < to_t((ar)[out_BSEARCH])) { \
64 if (out_BSEARCH > start) { \
65 r_BSEARCH = out_BSEARCH-1; /* search to the left side */ \
66 } else { \
67 /* reached the start of the array */ \
68 r_BSEARCH = out_BSEARCH; \
69 l_BSEARCH = out_BSEARCH + 1; \
70 } \
71 } \
72 else { \
73 l_BSEARCH = out_BSEARCH+1; /* search to the right side */ \
74 } \
75 } \
76 if ((size) > 0 && (val) != to_t((ar)[out_BSEARCH])) { \
77 if ((val) > to_t((ar)[out_BSEARCH])) { \
78 nearest_BSEARCH = TRUE; \
79 } \
80 else if (out_BSEARCH > start) { \
81 --out_BSEARCH; \
82 nearest_BSEARCH = (val) > to_t((ar)[out_BSEARCH]); \
83 } \
84 } \
85 } while (0)
87 /*! Returns true if the element last searched for was found in the array */
88 #define BSEARCH_FOUND() (l_BSEARCH <= r_BSEARCH)
90 /*! Returns the position in the array at which the element last searched for
91 was found. */
92 #define BSEARCH_AT() (out_BSEARCH)
94 /*! Returns true if the element at BSEARCH_AT() in the array is the largest
95 value in the array smaller than the search key. Returns false if there was
96 nothing in the array smaller than the search key.
98 Should only be used when BSEARCH_FOUND() is false.
100 #define BSEARCH_FOUND_NEAREST_SMALLER() (!BSEARCH_FOUND() && nearest_BSEARCH)
102 G_END_DECLS
104 #endif