// ID: bitmask.h
// This is a C++ wrapper for the bitmask system released already. 
// You need that installed as well.
// To use this just include "bitmask.h" and make sure to do using
// namespace jhb; if you don't want to scope in with it.
//
// What this does: 
// This will allow you to use the old code released in a smarter,
// object oriented way. The following code is a good example.
/*

bitmask<int> list; // list of int type variables.
int *serialized_list; // array of ints

// add 0 - 10 to our list.
for(int i = 0;i < 10;++i) 
    list.add(i);

serialized_list = list.serialize();

// iterate through your list and remove them
for(int i = 0;serialized_list[i];++i) 
    list.remove(i);
*/
// Some other included functions of this code:
// You can construct your bitmask by passing another bitmask 
// to make it spawn a new copy. 
// bitmask<int> list(some_bitmask);
//
// list.size() returns number of elements.
// list.read() and list.write() is equivilant of old saving system. 
// Should only be used when writing list in int mode and not on pointers.
// 
// + and - operators will add or remove bits contained on one from the other.
// 
// If you want to free your serialized list yourself then pass true to 
// serialize. list.serialize(true);
// 
// If you have any comments, questions, or suggestions then please send me a message.

namespace jhb {
    typedef struct bitmas                   BITMASK;
    typedef struct bmlist                   BMlist;

    template <class Tee>
    class bitmask {
        protected:
            BITMASK bm; // raw bitmask for our main list
            BITMASK s_bm; // raw bitmask for our pointers that need be freed for internal funtions.
        public:
            // constructors
            bitmask() { init_bitmask(&bm); init_bitmask(&s_bm); }
            bitmask(BITMASK *bm_copy);
            bitmask(BITMASK bm_copy);
            bitmask(bitmask<Tee> &bm_copy);
            // destructors
            ~bitmask() {
                void **vpl = serialize_bitmask(&s_bm);
                free_bitmask(&bm);
                for(int i = 0;vpl[i];++i)
                    free(vpl[i]);
                free(vpl);
                free_bitmask(&s_bm);
            }

            // Over-loaded operators.
            void operator+(const bitmask<Tee> &ato);
            void operator-(const bitmask<Tee> &ato);

            // Class member functions
            bool in_list(Tee element);
            void add(Tee element);
            void remove(Tee element);
            int size() { return bm.bits; }
            Tee *serialize(bool somebool = false);
            void write(FILE *fp);
            void read(FILE *fp);
    };

    struct bmlist {
        BMlist *next;
        int set;
        long tar_mask;
    };

    struct bitmas {
        int bits; // number of bits set in total.
        int masks; // number of masks in all.
        BMlist *int_list;
    };

    template <class Tee>
    void bitmask<Tee>::operator+(const bitmask<Tee> &ato) {
        Tee *vser = ato.serialize();
        for(int i =0;vser[i];++i)
            this->add(vser[i]);
    };
    template <class Tee>
    void bitmask<Tee>::operator-(const bitmask<Tee> &ato) {
        Tee *vser = ato.serialize();
        for(int i =0;vser[i];++i)
            if (this->in_list)
                this->remove(vser[i]);
    };

    template <class Tee>
    Tee * bitmask<Tee>::serialize(bool somebool = false) {
        Tee *sv = (Tee *)serialize_bitmask(&bm);
        // Sets a bit for freeing later.
        if (somebool == false)
            set_bit(&s_bm, (int)sv);
        return sv;
    }
    template <class Tee>
    void bitmask<Tee>::write(FILE *fp) {
        save_bitmask(fp, &bm);
    }

    template <class Tee>
    void bitmask<Tee>::read(FILE *fp) {
        load_bitmask(fp, &bm);
    }

    template <class Tee>
    bitmask<Tee>::bitmask(BITMASK *bm_copy) {
        Tee vlist = (Tee *)serialize_bitmask(bm_copy);
        init_bitmask(&bm);
        init_bitmask(&s_bm);
        for(int i = 0;vlist[i];++i)
            this->add(vlist[i]);
        free(vlist);
    }


    template <class Tee>
    bitmask<Tee>::bitmask(BITMASK bm_copy) {
        Tee vlist[] = (Tee *)serialize_bitmask(&bm_copy);
        init_bitmask(&bm);
        init_bitmask(&s_bm);
        for(int i = 0;vlist[i];++i)
           this->add(vlist[i]);
        free(vlist);
    }

    template <class Tee>
    bitmask<Tee>::bitmask(bitmask<Tee> &bm_copy) {
        Tee vlist[] = bm_copy.serialize();
        init_bitmask(&bm);
        init_bitmask(&s_bm);
        for(int i = 0;vlist[i];++i)
            this->add(vlist[i]);
        free(vlist);
    }

    template <class some_var>
    bool bitmask<some_var>::in_list(some_var var) {
        if (is_set(&bm, (int)var))
            return true;
        else
            return false;
    }

    template <class some_var>
    void bitmask<some_var>::add(some_var var) {
        set_bit(&bm, (int)var);
    }

    template <class some_var>
    void bitmask<some_var>::remove(some_var var) {
        remove_bit(&bm, (int)var);
    }
}