<commit_before>#include <string>
#include <sstream>
#include <unordered_map>
#include <memory>
#include <variant>
#include <optional>

template<typename Value,
         typename ValueStorage,
         typename MatchResult,
         typename Context>
class QlobberBase {
public:
    QlobberBase(const char separator = '.',
                const char wildcard_one = '*',
                const char wildcard_some = '#') :
        separator(1, separator),
        wildcard_one(1, wildcard_one),
        wildcard_some(1, wildcard_some) {
        // TODO: cache_adds/shortcuts        
    }

    void add(const std::string& topic, const Value& val) {
        add(val, 0, split(topic), trie);
    }

    void remove(const std::string& topic,
                const std::optional<const Value>& val) {
        remove(val, 0, split(topic), trie);
    }

    MatchResult match(const std::string& topic,
                      Context& ctx) {
        MatchResult r;
        match(r, 0, split(topic), trie, ctx);
        return r;
    }

    bool test(const std::string& topic, const Value& val) {
        return test(val, 0, split(topic), trie);
    }

    void clear() {
        std::get<0>(trie).clear();
    }

    virtual bool test_values(const ValueStorage& vals,
                             const Value& val) = 0;

private:
    std::string separator;
    std::string wildcard_one;
    std::string wildcard_some;

    struct Trie {
        Trie() {}
        Trie(const Value& val) : v(std::in_place_index<1>, val) {}
        typedef std::unordered_map<std::string, struct Trie> map_type;
        typedef std::unique_ptr<map_type> map_ptr;
        std::variant<map_ptr, ValueStorage> v;
    } trie;<commit_msg>Remove separator from constructor<commit_after>#include <string>
#include <sstream>
#include <unordered_map>
#include <memory>
#include <variant>
#include <optional>

template<typename Value,
         typename ValueStorage,
         typename MatchResult,
         typename Context>
class QlobberBase {
public:
    QlobberBase() {
        // TODO: cache_adds/shortcuts        
    }

    void add(const std::string& topic, const Value& val) {
        add(val, 0, split(topic), trie);
    }

    void remove(const std::string& topic,
                const std::optional<const Value>& val) {
        remove(val, 0, split(topic), trie);
    }

    MatchResult match(const std::string& topic,
                      Context& ctx) {
        MatchResult r;
        match(r, 0, split(topic), trie, ctx);
        return r;
    }

    bool test(const std::string& topic, const Value& val) {
        return test(val, 0, split(topic), trie);
    }

    void clear() {
        std::get<0>(trie).clear();
    }

    virtual bool test_values(const ValueStorage& vals,
                             const Value& val) = 0;

protected:
    std::string separator = ".";
    std::string wildcard_one = "*";
    std::string wildcard_some = "#";

private:
    struct Trie {
        Trie() {}
        Trie(const Value& val) : v(std::in_place_index<1>, val) {}
        typedef std::unordered_map<std::string, struct Trie> map_type;
        typedef std::unique_ptr<map_type> map_ptr;
        std::variant<map_ptr, ValueStorage> v;
    } trie;
{'fraction_non_alphanumeric': 0.12468905472636815, 'fraction_numerical': 0.005286069651741294, 'mean_word_length': 2.4223404255319148, 'pattern_counts': {'":': 0, '<': 29, '<?xml version=': 0, '>': 29, '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': '1311737', 'n_tokens_mistral': 1025, 'n_tokens_neox': 979, 'n_words': 247}