1 //
2 // Copyright (C) 2024 The Android Open Source Project
3 //
4 // Licensed under the Apache License, Version 2.0 (the "License");
5 // you may not use this file except in compliance with the License.
6 // You may obtain a copy of the License at
7 //
8 //      http://www.apache.org/licenses/LICENSE-2.0
9 //
10 // Unless required by applicable law or agreed to in writing, software
11 // distributed under the License is distributed on an "AS IS" BASIS,
12 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 // See the License for the specific language governing permissions and
14 // limitations under the License.
15 //
16 
17 #ifndef BERBERIS_ANDROID_API_LIBVULKAN_SEARCH_H_
18 #define BERBERIS_ANDROID_API_LIBVULKAN_SEARCH_H_
19 
20 #include <string.h>
21 
22 #include <algorithm>
23 #include <type_traits>
24 
25 namespace berberis {
26 
27 // This is essentially std::sorted as in C++20.
28 template <class ForwardIterator, class Compare>
IsSorted(ForwardIterator first,ForwardIterator last,Compare comp)29 inline constexpr bool IsSorted(ForwardIterator first, ForwardIterator last, Compare comp) {
30   // Advancing past last may be undefined behavior. Handle that separately here.
31   if (first == last) {
32     return true;
33   }
34   for (auto tmp = first; ++tmp != last; first = tmp) {
35     if (comp(*tmp, *first)) {
36       return false;
37     }
38   }
39   return true;
40 }
41 
StrCmpLess(const char * lhs,const char * rhs)42 inline constexpr bool StrCmpLess(const char* lhs, const char* rhs) {
43   if (__builtin_is_constant_evaluated()) {
44     for (;;) {
45       unsigned char lc = *lhs++;
46       unsigned char rc = *rhs++;
47       if (lc < rc) {
48         return true;
49       }
50       if (lc > rc) {
51         return false;
52       }
53       if (lc == '\0') {
54         return false;
55       }
56     }
57   } else {
58     return strcmp(lhs, rhs) < 0;
59   }
60 }
61 
62 inline constexpr class StrCmpLessName {
63  public:
64   using is_transparent = void;
65 
66   template <typename Type1, typename Type2>
operator()67   constexpr bool operator()(const Type1& lhs, const Type2& rhs) {
68     return StrCmpLess(lhs.name, rhs.name);
69   }
70   template <typename Type1>
operator()71   constexpr bool operator()(const Type1& lhs, const char* rhs) {
72     return StrCmpLess(lhs.name, rhs);
73   }
74   template <typename Type1>
operator()75   constexpr bool operator()(const char* lhs, const Type1& rhs) {
76     return StrCmpLess(lhs, rhs.name);
77   }
78 } StrCmpLessName;
79 
80 template <typename Array>
FindElementByName(const Array & array,const char * name)81 auto FindElementByName(const Array& array, const char* name) {
82   auto element = std::lower_bound(std::begin(array), std::end(array), name, StrCmpLessName);
83   if (element != std::end(array) and strcmp(element->name, name) == 0) {
84     return element;
85   }
86   return decltype(element){};
87 }
88 
89 }  // namespace berberis
90 
91 #endif  // BERBERIS_ANDROID_API_LIBVULKAN_SEARCH_H_
92