Newer
Older
bremer-ios-app / Pods / Realm / core / realm-monorepo.xcframework / macos-x86_64_arm64 / Headers / realm / array_integer_tpl.hpp
/*************************************************************************
 *
 * Copyright 2021 Realm Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 **************************************************************************/

#ifndef REALM_ARRAY_INTEGER_TPL_HPP
#define REALM_ARRAY_INTEGER_TPL_HPP

#include <realm/array_integer.hpp>
#include <realm/array_with_find.hpp>

namespace realm {

template <class cond, class Callback>
bool ArrayInteger::find(value_type value, size_t start, size_t end, QueryStateBase* state, Callback callback) const
{
    return ArrayWithFind(*this).find<cond, Callback>(value, start, end, 0, state, callback);
}

template <class Callback>
inline bool ArrayIntNull::find_impl(int cond, value_type value, size_t start, size_t end, QueryStateBase* state,
                                    Callback callback) const
{
    switch (cond) {
        case cond_Equal:
            return find_impl<Equal>(value, start, end, state, callback);
        case cond_NotEqual:
            return find_impl<NotEqual>(value, start, end, state, callback);
        case cond_Greater:
            return find_impl<Greater>(value, start, end, state, callback);
        case cond_Less:
            return find_impl<Less>(value, start, end, state, callback);
        case cond_None:
            return find_impl<None>(value, start, end, state, callback);
        case cond_LeftNotNull:
            return find_impl<NotNull>(value, start, end, state, callback);
    }
    REALM_ASSERT_DEBUG(false);
    return false;
}

template <class cond, class Callback>
bool ArrayIntNull::find_impl(value_type opt_value, size_t start, size_t end, QueryStateBase* state,
                             Callback callback) const
{
    int64_t null_value = Array::get(0);
    bool find_null = !bool(opt_value);
    int64_t value;

    size_t end2 = (end == npos ? size() : end) + 1;
    size_t start2 = start + 1;
    size_t baseindex2 = size_t(-1);

    if constexpr (std::is_same_v<cond, Equal>) {
        if (find_null) {
            value = null_value;
        }
        else {
            if (*opt_value == null_value) {
                // If the value to search for is equal to the null value, the value cannot be in the array
                return true;
            }
            else {
                value = *opt_value;
            }
        }

        // Fall back to plain Array find.
        return ArrayWithFind(*this).find<cond>(value, start2, end2, baseindex2, state, callback);
    }
    else {
        cond c;

        if (opt_value) {
            value = *opt_value;
        }
        else {
            value = null_value;
        }

        for (size_t i = start2; i < end2; ++i) {
            int64_t v = Array::get(i);
            bool value_is_null = (v == null_value);
            if (c(v, value, value_is_null, find_null)) {
                util::Optional<int64_t> v2 = value_is_null ? util::none : util::make_optional(v);
                if (!ArrayWithFind(*this).find_action(i + baseindex2, v2, state, callback)) {
                    return false; // tell caller to stop aggregating/search
                }
            }
        }
        return true; // tell caller to continue aggregating/search (on next array leafs)
    }
}

template <class cond>
size_t ArrayIntNull::find_first(value_type value, size_t start, size_t end) const
{
    QueryStateFindFirst state;
    find_impl<cond>(value, start, end, &state, nullptr);

    if (state.match_count() > 0)
        return to_size_t(state.m_state);
    else
        return not_found;
}

template <class cond, class Callback>
inline bool ArrayIntNull::find(value_type value, size_t start, size_t end, QueryStateBase* state,
                               Callback callback) const
{
    return find_impl<cond, Callback>(value, start, end, state, callback);
}

} // namespace realm

#endif /* REALM_ARRAY_INTEGER_TPL_HPP */