// A simple but fast data structure for sets of integers.
// Only supported operations are insert, remove and membership test.
//
// It's implemented via a bitmap so the memory usage increases linearly
// with max(set).

#pragma once

#include <cstring>

namespace zeek::detail
	{

class IntSet
	{
public:
	// n is a hint for the value of the largest integer.
	explicit IntSet(unsigned int n = 1);
	~IntSet();

	void Insert(unsigned int i);
	void Remove(unsigned int i);
	bool Contains(unsigned int i) const;

	void Clear();

private:
	void Expand(unsigned int i);

	unsigned int size;
	unsigned char* set;
	};

inline IntSet::IntSet(unsigned int n)
	{
	size = n / 8 + 1;
	set = new unsigned char[size];
	memset(set, 0, size);
	}

inline IntSet::~IntSet()
	{
	delete[] set;
	}

inline void IntSet::Insert(unsigned int i)
	{
	if ( i / 8 >= size )
		Expand(i);

	set[i / 8] |= (1 << (i % 8));
	}

inline void IntSet::Remove(unsigned int i)
	{
	if ( i / 8 >= size )
		Expand(i);
	else
		set[i / 8] &= ~(1 << (i % 8));
	}

inline bool IntSet::Contains(unsigned int i) const
	{
	return i / 8 < size ? set[i / 8] & (1 << (i % 8)) : false;
	}

inline void IntSet::Clear()
	{
	memset(set, 0, size);
	}

	} // namespace zeek::detail
