/*
 * Licensed under BSD license.  See LICENCE.TXT  
 *
 * Produced by:	Jeff Lait
 *
 *      	7DRL Development
 *
 * NAME:        blocklist.cpp ( Pointless Library, C++ )
 *
 * COMMENTS:
 * 	Implementation of the blocklist functions
 */

#include <string.h>
#include "assert.h"
#include "blocklist.h"
#include "rand.h"

#include <algorithm>

template <typename PTR>
BLOCKLIST<PTR>::BLOCKLIST()
{
    myEntries = 0;
}

template <typename PTR>
BLOCKLIST<PTR>::~BLOCKLIST()
{
}

template <typename PTR>
BLOCKLIST<PTR>::BLOCKLIST(const BLOCKLIST<PTR> &ref)
{
    *this = ref;
}

template <typename PTR>
BLOCKLIST<PTR> &
BLOCKLIST<PTR>::operator=(const BLOCKLIST<PTR> &ref)
{
    int			i;

    if (this == &ref)
	return *this;

    myBlocks = ref.myBlocks;
    myEntries = ref.myEntries;
    // Blocks did a soft copy, so harden.
    for (auto && block : myBlocks)
	block.harden();

    return *this;
}

template <typename PTR>
int
BLOCKLIST<PTR>::append()
{
    return append(PTR{});
}

template <typename PTR>
int
BLOCKLIST<PTR>::append(PTR item)
{
    myEntries++;
    {
	int minblocks, lclindex;
	splitIndex(myEntries-1, minblocks, lclindex);
	while (myBlocks.entries() <= minblocks)
	{
	    myBlocks.append();
	}
    }
    set(myEntries-1, item);
    return myEntries-1;
}

template <typename PTR>
void
BLOCKLIST<PTR>::append(const BLOCKLIST<PTR> &list)
{
    int		i;

    for (i = 0; i < list.entries(); i++)
	append(list(i));
}

template <typename PTR>
void
BLOCKLIST<PTR>::resize(int size)
{
    while (myEntries < size)
	append(PTR{});

    // Clear out the now freed
    for (int i = size; i < myEntries; i++)
	set(i, PTR{});
    myEntries = size;
}

template <typename PTR>
void
BLOCKLIST<PTR>::set(int idx, PTR item)
{
    J_ASSERT(idx < entries());
    J_ASSERT(idx >= 0);
    if (idx < 0)
	return;
    if (idx >= entries())
	return;

    int		blockidx, lclidx;
    splitIndex(idx, blockidx, lclidx);
    myBlocks(blockidx).set(lclidx, item);
}

template <typename PTR>
PTR
BLOCKLIST<PTR>::operator()(int idx) const
{
    J_ASSERT(idx >= 0 && idx < myEntries);

    int		blockidx, lclidx;
    splitIndex(idx, blockidx, lclidx);

    return myBlocks(blockidx).get(lclidx);
}

template <typename PTR>
int
BLOCKLIST<PTR>::entries() const
{
    return myEntries;
}

template <typename PTR>
void
BLOCKLIST<PTR>::clear()
{
    myBlocks.clear();
    myEntries = 0;
}

template <typename PTR>
void
BLOCKLIST<PTR>::zero()
{
    for (auto && block : myBlocks)
    {
	block.zero();
    }
}
