#ifndef JGADGET_SEARCH_H #define JGADGET_SEARCH_H #include #include #include #include namespace JGadget { namespace search { template struct TExpandStride_ {}; template <> struct TExpandStride_ { static s32 get(s32 n) { return n << 3; } }; struct TPR1IsEqual_string_ { TPR1IsEqual_string_(const char* sz) { string_ = sz; } bool operator()(const char* sz) const { bool ret; if (string_ == NULL) { ret = sz == NULL; } else { ret = sz != NULL && strcmp(string_, sz) == 0; } return ret; } const char* string_; }; } // namespace search const char* toStringFromIndex(int index, const char* const* pValue, u32 count, const char* fallback); int toIndexFromString_linear(const char*, const char* const*, u32, int); template inline const T& toValueFromIndex(int idx, const T* pValue, u32 count, const T& fallback) { JUT_ASSERT(200, pValue!=NULL); u32 index = idx; if (index >= count) { return fallback; } else { return pValue[index]; } } template inline int toIndexFromValue_linear_if(Predicate p, const T* pValue, u32 count, int fallback) { JUT_ASSERT(212, pValue!=NULL); const T* first = pValue; const T* last = pValue + count; const T* found = std::find_if(first, last, p); if (found == last) { return fallback; } return std::distance(first, found); } template struct TIterator : public std::iterator { }; template struct TIterator_reverse : public std::reverse_iterator { TIterator_reverse() {} TIterator_reverse(Iterator it) : std::reverse_iterator(it) {} }; template inline Iterator findUpperBound_binary_all(Iterator first, Iterator last, const T& val, Predicate p) { return std::upper_bound(first, last, val, p); } template inline Iterator findUpperBound_binary_begin(Iterator first, Iterator last, const T& val, Predicate p) { if (first == last) { return last; } typedef typename std::iterator_traits::difference_type difference_type; difference_type dist = std::distance(first, last); difference_type stride = 1; search::TExpandStride_ 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 inline Iterator findUpperBound_binary_end(Iterator first, Iterator last, const T& val, Predicate p) { if (first == last) { return last; } typedef typename std::iterator_traits::difference_type difference_type; --last; difference_type dist = std::distance(first, last); difference_type stride = 1; search::TExpandStride_ 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 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 inline Iterator findUpperBound_binary_current(Iterator first, Iterator last, Iterator current, const T& val) { return findUpperBound_binary_current(first, last, current, val, std::less()); } } // namespace JGadget #endif /* JGADGET_SEARCH_H */