<commit_before>#pragma once

#include <bdtree/base_types.h>
#include <bdtree/forward_declarations.h>
#include <bdtree/logical_table_cache.h>
#include <bdtree/primitive_types.h>

#include <cassert>
#include <functional>
#include <limits>

namespace bdtree {

template<typename NodeType>
struct node_delete;

template<typename Key, typename Value>
struct node_delete<inner_node<Key, Value> > {
    template <typename Backend>
    static void rem(inner_node<Key, Value>& inner, physical_pointer pptr,
            operation_context<Key, Value, Backend>& context) {
        auto& node_table = context.get_node_table();
        node_table.remove(pptr);
    }
};

template<typename Key, typename Value>
struct node_delete<leaf_node<Key, Value> > {
    template <typename Backend>
    static void rem(leaf_node<Key, Value>& leaf, physical_pointer pptr,
            operation_context<Key, Value, Backend>& context) {
        auto& node_table = context.get_node_table();
        node_table.remove(leaf.leaf_pptr_);
        for (physical_pointer ptr : leaf.deltas_) {
            assert(ptr != leaf.leaf_pptr_);
            node_table.remove(ptr);
        }
    }
};

template<typename Key>
struct null_key {
    static_assert(std::numeric_limits<Key>::is_specialized, "null_key not defined");
    static constexpr Key value() {
        return std::numeric_limits<Key>::min();
    }
};

template<>
struct null_key<std::string> {
    static constexpr const char* value() {
        return "";
    }
};

template<typename T, typename U>
struct null_key<std::pair<T,U> > {
    static constexpr std::pair<T, U> value() {
        return std::make_pair(null_key<T>::value(),null_key<U>::value());
    }
};

template<typename T, typename... U>
struct null_key<std::tuple<T,U...> > {
    static constexpr std::tuple<T, U...> value() {
        return std::tuple_cat(std::forward_as_tuple(null_key<T>::value()),null_key<std::tuple<U...> >::value());
    }
};

template<typename T>
struct null_key<std::tuple<T> > {
    static constexpr std::tuple<T> value() {
        return std::forward_as_tuple(null_key<T>::value());
    }
};

template<typename ForwardIt, typename T, typename Compare>
ForwardIt last_smaller_equal(ForwardIt first, ForwardIt last, const T& value, Compare cmp) {
    return --std::upper_bound(first, last, value, cmp);
}

template<typename ForwardIt, typename T, typename Compare>
ForwardIt last_smaller(ForwardIt first, ForwardIt last, const T& value, Compare cmp) {
    return --std::lower_bound(first, last, value, cmp);
}

template<typename Node, typename Key>
bool is_in_range(Node& n, const Key& key, search_bound bound) {
    if (bound == search_bound::LAST_SMALLER) {
        bool high_key_ok = !n.high_key_ || key < n.high_key_ || key == n.high_key_;
        if (n.low_key_ == null_key<Key>::value())
            return high_key_ok;
        if (n.low_key_ < key)
            return high_key_ok;
    } else {
        if (key < n.low_key_)
            return false;
        if (!n.high_key_)//infinity
            return true;
        if (key < n.high_key_)
            return true;
    }
    return false;<commit_msg>Fix for when the iterator points to the beginning<commit_after>#pragma once

#include <bdtree/base_types.h>
#include <bdtree/forward_declarations.h>
#include <bdtree/logical_table_cache.h>
#include <bdtree/primitive_types.h>

#include <cassert>
#include <functional>
#include <limits>

namespace bdtree {

template<typename NodeType>
struct node_delete;

template<typename Key, typename Value>
struct node_delete<inner_node<Key, Value> > {
    template <typename Backend>
    static void rem(inner_node<Key, Value>& inner, physical_pointer pptr,
            operation_context<Key, Value, Backend>& context) {
        auto& node_table = context.get_node_table();
        node_table.remove(pptr);
    }
};

template<typename Key, typename Value>
struct node_delete<leaf_node<Key, Value> > {
    template <typename Backend>
    static void rem(leaf_node<Key, Value>& leaf, physical_pointer pptr,
            operation_context<Key, Value, Backend>& context) {
        auto& node_table = context.get_node_table();
        node_table.remove(leaf.leaf_pptr_);
        for (physical_pointer ptr : leaf.deltas_) {
            assert(ptr != leaf.leaf_pptr_);
            node_table.remove(ptr);
        }
    }
};

template<typename Key>
struct null_key {
    static_assert(std::numeric_limits<Key>::is_specialized, "null_key not defined");
    static constexpr Key value() {
        return std::numeric_limits<Key>::min();
    }
};

template<>
struct null_key<std::string> {
    static constexpr const char* value() {
        return "";
    }
};

template<typename T, typename U>
struct null_key<std::pair<T,U> > {
    static constexpr std::pair<T, U> value() {
        return std::make_pair(null_key<T>::value(),null_key<U>::value());
    }
};

template<typename T, typename... U>
struct null_key<std::tuple<T,U...> > {
    static constexpr std::tuple<T, U...> value() {
        return std::tuple_cat(std::forward_as_tuple(null_key<T>::value()),null_key<std::tuple<U...> >::value());
    }
};

template<typename T>
struct null_key<std::tuple<T> > {
    static constexpr std::tuple<T> value() {
        return std::forward_as_tuple(null_key<T>::value());
    }
};

template<typename ForwardIt, typename T, typename Compare>
ForwardIt last_smaller_equal(ForwardIt first, ForwardIt last, const T& value, Compare cmp) {
    auto iter = std::upper_bound(first, last, value, cmp);
    return (iter == first ? last : --iter);
}

template<typename ForwardIt, typename T, typename Compare>
ForwardIt last_smaller(ForwardIt first, ForwardIt last, const T& value, Compare cmp) {
    auto iter = std::lower_bound(first, last, value, cmp);
    return (iter == first ? last : --iter);
}

template<typename Node, typename Key>
bool is_in_range(Node& n, const Key& key, search_bound bound) {
    if (bound == search_bound::LAST_SMALLER) {
        bool high_key_ok = !n.high_key_ || key < n.high_key_ || key == n.high_key_;
        if (n.low_key_ == null_key<Key>::value())
            return high_key_ok;
        if (n.low_key_ < key)
            return high_key_ok;
    } else {
        if (key < n.low_key_)
            return false;
        if (!n.high_key_)//infinity
            return true;
        if (key < n.high_key_)
            return true;
    }
    return false;
{'fraction_non_alphanumeric': 0.13398180106683402, 'fraction_numerical': 0.0, 'mean_word_length': 3.5568263045032165, 'pattern_counts': {'":': 0, '<': 105, '<?xml version=': 0, '>': 97, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3250721', 'n_tokens_mistral': 2095, 'n_tokens_neox': 2049, 'n_words': 479}