src/fsmblockmap.h
author rubidium
Sun, 05 Aug 2007 00:39:42 +0000
branchNewGRF_ports
changeset 6751 08176dfe64b7
parent 6739 3f2ca4d0abda
child 6758 1545d187ab64
permissions -rw-r--r--
(svn r10790) [NewGRF_ports] -Codechange: constify the fsmblockmaps where possible.
[NewGRF_ports] -Fix: a memleak.
/* $Id$ */

/** @file FSMblockmap.h Definition of FSMblockmap class for use in state machines*/

#ifndef FSMBLOCKMAP_H
#define FSMBLOCKMAP_H

#include "stdafx.h"

uint64 inline GetBlockAsBits(byte blocknumber)
{
	if (blocknumber == 0) return 0ULL;
	if (blocknumber > 63) blocknumber -= 64;
	uint64 result = 1ULL << blocknumber;
	return result;
}

/**
 * This class provides functions and internal storage for blockmaps used in Finite State Machine
 *
*/
struct FSMblockmap {
	public:
		void inline ResetAll()
		{
			block_lower = 0x0000000000000000;
			block_upper = 0x0000000000000000;
		};

		void Initialise(const byte *blocklist, int num_bytes)
		{
			ResetAll();
			for (int i = 0; i < num_bytes; i++)
			{
				if (blocklist[i] < 64) {
					block_lower |= GetBlockAsBits(blocklist[i]);
				} else {
					block_upper |= GetBlockAsBits(blocklist[i]);
				}
			}
		}

		uint64 inline GetLower() const
		{
			return block_lower;
		}

		uint64 inline GetUpper() const
		{
			return block_upper;
		}

		void inline ReserveBlocks(const FSMblockmap *blockmap)
		{
			/* OR with blockmap to reserve blocks */
			block_lower |= blockmap->GetLower();
			block_upper |= blockmap->GetUpper();
		}

		void inline ReleaseBlocks(const FSMblockmap *blockmap)
		{
			/* AND with ones-complement to clear set bits in blockmap from block_lower and block_upper */
			block_lower &= ~blockmap->GetLower();
			block_upper &= ~blockmap->GetUpper();
		}

		bool inline BlocksAreFree(const FSMblockmap *blockmap) const
		{
			uint64 test_lower = blockmap->GetLower();
			uint64 test_upper = blockmap->GetUpper();

			if ((~block_lower & test_lower) != test_lower)  return false;
			if ((~block_upper & test_upper) != test_upper)  return false;

			return true;
		}

		bool inline HasBlocks(const FSMblockmap *blockmap) const
		{
			uint64 test_lower = blockmap->GetLower();
			uint64 test_upper = blockmap->GetUpper();

			if ((block_lower & test_lower) != test_lower)  return false;
			if ((block_upper & test_upper) != test_upper)  return false;

			return true;
		}

		bool inline HasBlock(byte blocknumber) const
		{
			FSMblockmap test_blockmap;
			test_blockmap.Initialise(&blocknumber, 1);
			return HasBlocks(&test_blockmap);
		}

		//bool inline HasBlock(byte blocknumber)
		//{
		//	uint64 test_block = GetBlockAsBits(blocknumber);
		//	if (blocknumber < 64) return ((block_lower & test_block) == test_block);
		//	return ((block_upper & test_block) == test_block);
		//}

		bool inline IsNotZero(void) const
		{
			return ((block_lower != 0) || (block_upper != 0));
		}

		void PrintBlock(bool newline = true) const;

	private:
		uint64 block_lower;
		uint64 block_upper;
};

FSMblockmap* SetFSMSingleBlock(const byte *blocklist);

#endif /* FSMBLOCKMAP_H */