1 /*
2  *  Copyright (c) 2022, The OpenThread Authors.
3  *  All rights reserved.
4  *
5  *  Redistribution and use in source and binary forms, with or without
6  *  modification, are permitted provided that the following conditions are met:
7  *  1. Redistributions of source code must retain the above copyright
8  *     notice, this list of conditions and the following disclaimer.
9  *  2. Redistributions in binary form must reproduce the above copyright
10  *     notice, this list of conditions and the following disclaimer in the
11  *     documentation and/or other materials provided with the distribution.
12  *  3. Neither the name of the copyright holder nor the
13  *     names of its contributors may be used to endorse or promote products
14  *     derived from this software without specific prior written permission.
15  *
16  *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
17  *  AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18  *  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19  *  ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
20  *  LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21  *  CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22  *  SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23  *  INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24  *  CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25  *  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26  *  POSSIBILITY OF SUCH DAMAGE.
27  */
28 
29 /**
30  * @file
31  *  This file implements a generic binary search.
32  */
33 
34 #include "binary_search.hpp"
35 
36 #include "common/code_utils.hpp"
37 
38 namespace ot {
39 
Find(const void * aKey,const void * aTable,uint16_t aLength,uint16_t aEntrySize,Comparator aComparator)40 const void *BinarySearch::Find(const void *aKey,
41                                const void *aTable,
42                                uint16_t    aLength,
43                                uint16_t    aEntrySize,
44                                Comparator  aComparator)
45 {
46     const void *entry;
47     uint16_t    left  = 0;
48     uint16_t    right = aLength;
49 
50     while (left < right)
51     {
52         uint16_t middle = (left + right) / 2;
53         int      compare;
54 
55         // Note that `aTable` array entry type is not known here and
56         // only its size is given as `aEntrySize`. Based on this, we
57         // can calculate the pointer to the table entry at any index
58         // (such as `[middle]`) which is then passed to the given
59         // `aComparator` function which knows how to cast the void
60         // pointer to proper entry type and compare it with `aKey`.
61         // This model keeps the implementation generic and reusable
62         // allowing it to be used with any entry type.
63 
64         entry = reinterpret_cast<const uint8_t *>(aTable) + aEntrySize * middle;
65 
66         compare = aComparator(aKey, entry);
67 
68         if (compare == 0)
69         {
70             ExitNow();
71         }
72         else if (compare > 0)
73         {
74             left = middle + 1;
75         }
76         else
77         {
78             right = middle;
79         }
80     }
81 
82     entry = nullptr;
83 
84 exit:
85     return entry;
86 }
87 
88 } // namespace ot
89