summaryrefslogtreecommitdiff
path: root/include/JSystem/JGadget/search.h
blob: 7c2e594abf44f5a3261e5d864f9567730fc05740 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
#ifndef SEARCH_H
#define SEARCH_H

#include <iterator.h>
#include <functional.h>
#include <algorithm.h>

namespace JGadget {

namespace search {

template <typename T>
struct TExpandStride_ {};

template <>
struct TExpandStride_<s32> {
    static s32 get(s32 n) { return n << 3; }
};

}  // namespace search

//! @todo: mangled name isn't correct, fix this
//! Current: toValueFromIndex<PFdd_d>__7JGadgetFiPCPFdd_dUlRCPFdd_d
//!  Target: toValueFromIndex<PFdd_d>__7JGadgetFiPCPFdd_dUlRCPFdd_d_RCPFdd_d
template <typename T>
inline const T& toValueFromIndex(int idx, const T* pValue, u32 count, const T& fallback) {
    ASSERT(pValue != NULL);
    return (idx < count) ? pValue[idx] : fallback;
}

template <typename Category, typename T, typename Distance, typename Pointer, typename Reference>
struct TIterator : public std::iterator<Category, T, Distance, Pointer, Reference> {
};

template <typename Iterator, typename T, typename Predicate>
inline Iterator findUpperBound_binary_all(Iterator first, Iterator last, const T& val, Predicate p) {
    return std::upper_bound(first, last, val, p);
}

template <typename Iterator, typename T, typename Predicate>
inline Iterator findUpperBound_binary_begin(Iterator first, Iterator last, const T& val, Predicate p) {
    if (first == last) {
        return last;
    }

    typedef typename std::iterator_traits<Iterator>::difference_type difference_type;
    difference_type dist = std::distance(first, last);
    difference_type stride = 1;
    search::TExpandStride_<difference_type> expand;
    Iterator i = first;

    while (true) {
        if (p(val, *i)) {
            if (stride == 1) {
                return i;
            } else {
                break;
            }
        }
        first = i;
        dist -= stride;
        if (dist <= 0) {
            i = last;
            break;
        }
        i += stride;
        stride = expand.get(stride);
    }

    return findUpperBound_binary_all(first, i, val, p);
}

template <typename Iterator, typename T, typename Predicate>
inline Iterator findUpperBound_binary_end(Iterator first, Iterator last, const T& val, Predicate p) {
    if (first == last) {
        return last;
    }

    typedef typename std::iterator_traits<Iterator>::difference_type difference_type;
    --last;
    difference_type dist = std::distance(first, last);
    difference_type stride = 1;
    search::TExpandStride_<difference_type> expand;
    Iterator i = last;

    while (true) {
        if (!p(val, *i)) {
            if (stride == 1) {
                return ++i;
            } else {
                break;
            }
        }
        last = i;
        dist -= stride;
        if (dist <= 0) {
            i = first;
            break;
        }
        i -= stride;
        stride = expand.get(stride);
    }

    return findUpperBound_binary_all(i, ++last, val, p);
}

template <typename Iterator, typename T, typename Predicate>
inline Iterator findUpperBound_binary_current(Iterator first, Iterator last, Iterator current, const T& val, Predicate p) {
    return current == last || p(val, *current) ?
        findUpperBound_binary_end(first, current, val, p) :
        findUpperBound_binary_begin(current, last, val, p);
}

template <typename Iterator, typename T>
inline Iterator findUpperBound_binary_current(Iterator first, Iterator last, Iterator current, const T& val) {
    return findUpperBound_binary_current(first, last, current, val, std::less<T>());
}

}  // namespace JGadget

#endif /* SEARCH_H */