<commit_before>#ifndef __RPC_CORE_SEMILATTICE_MAP_HPP__
#define __RPC_CORE_SEMILATTICE_MAP_HPP__

#include <map>
#include <set>

#include "errors.hpp"
#include "rpc/core/semilattice/semilattice.hpp"

/*
TODO! Describe semantics and interface
value_t must be a constructive_semilattice_t
*/

template<typename key_t, typename value_t> class sl_map_t :
    public constructive_semilattice_t<sl_map_t<key_t, value_t> > {

public:
    const std::map<key_t, value_t> &get_map() const {
        return members;
    }
    
    void insert(const key_t &key, const value_t &value) {
        if (members.find(key) == members.end()) {
            members[key] = value;
        } else {
            members[key].sl_join(value);
        }
    }
    
    void remove(const key_t &key) {
        rassert(members.find(key) != members.end());
        members.erase(key);
        defunct.insert(key);
    }

    void sl_join(const sl_map_t<key_t, value_t> &x) {
        for(typename std::set<key_t>::const_iterator def = x.defunct.begin(); def != x.defunct.end(); ++def) {
            members.erase(*def);
        }
        defunct.insert(x.defunct.begin(), x.defunct.end());
    }

private:
    std::map<key_t, value_t> members;
    std::set<key_t> defunct;
};

// TODO: Would an sl_unique_map_t be useful?
// It would be implemented as an sl_map_t where value_t is such that
// it always fails on calls to value_t::sl_join().

#endif // __RPC_CORE_SEMILATTICE_MAP_HPP__<commit_msg>Complete sl_map_t::sl_join and fix its insert()<commit_after>#ifndef __RPC_CORE_SEMILATTICE_MAP_HPP__
#define __RPC_CORE_SEMILATTICE_MAP_HPP__

#include <map>
#include <set>

#include "errors.hpp"
#include "rpc/core/semilattice/semilattice.hpp"

/*
TODO! Describe semantics and interface
value_t must be a constructive_semilattice_t
*/

template<typename key_t, typename value_t> class sl_map_t :
    public constructive_semilattice_t<sl_map_t<key_t, value_t> > {

public:
    // TODO! We need some nice constructor that can be used when reading metadata messages

    const std::map<key_t, value_t> &get_map() const {
        return members;
    }
    
    void insert(const key_t &key, const value_t &value) {
        typename std::map<key_t, value_t>::iterator existing_member = members.find(key);
        if (existing_member == members.end()) {
            members.insert(std::pair<key_t, value_t>(key, value));
        } else {
            existing_member->second.sl_join(value);
        }
    }
    
    void remove(const key_t &key) {
        rassert(members.find(key) != members.end());
        members.erase(key);
        defunct.insert(key);
    }

    void sl_join(const sl_map_t<key_t, value_t> &x) {
        for (typename std::set<key_t>::const_iterator def = x.defunct.begin(); def != x.defunct.end(); ++def) {
            members.erase(*def);
        }
        
        for (typename std::map<key_t, value_t>::const_iterator mem = x.members.begin(); mem != x.members.end(); ++mem) {
            if (defunct.find(mem->first) == defunct.end()) {
                insert(mem->first, mem->second);
            }
        }
        
        defunct.insert(x.defunct.begin(), x.defunct.end());
    }

private:
    std::map<key_t, value_t> members;
    std::set<key_t> defunct;
};

// TODO: Would an sl_unique_map_t be useful?
// It would be implemented as an sl_map_t where value_t is such that
// it always fails on calls to value_t::sl_join().

#endif // __RPC_CORE_SEMILATTICE_MAP_HPP__
{'fraction_non_alphanumeric': 0.12770875469517481, 'fraction_numerical': 0.0, 'mean_word_length': 3.0873671782762693, 'pattern_counts': {'":': 0, '<': 26, '<?xml version=': 0, '>': 30, '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': '1861596', 'n_tokens_mistral': 1214, 'n_tokens_neox': 1192, 'n_words': 257}