#ifndef COVERAGE_MANAGER_H_
#define COVERAGE_MANAGER_H_

#undef UNICODE
#include <stdio.h>
#include <windows.h>

class CoverageManager
{
private:
	static HANDLE _hMemory;
	static char *_memory;
	
	static bool initialize(int nameNumberHigh, int nameNumberLow, int size) {
		char name[256];
		sprintf(name, "%d-%d-%d", nameNumberHigh, nameNumberLow, size);

		_hMemory = CreateFileMapping(
			(HANDLE)-1,			// ファイルのハンドル(0xFFFFFFFFだとファイルを生成しない)
			NULL,				// セキュリティ
			PAGE_READWRITE,		// 保護
			0,					// サイズを表す上位 DWORD
			size,				// サイズを表す下位 DWORD
			name);				// オブジェクト名（識別子）
		if (GetLastError() == ERROR_ALREADY_EXISTS) {
			_hMemory = OpenFileMapping(
				FILE_MAP_ALL_ACCESS,	// アクセスモード
				FALSE,					// 継承フラグ（子プロセスに継承するか否か）
				name);					// オブジェクト名（識別子）
		}
		if (_hMemory == NULL)
			return false;

		_memory = (char*)MapViewOfFile(
			_hMemory,				// ファイルマッピングオブジェクトのハンドル
			FILE_MAP_ALL_ACCESS,	// アクセスモード
			0,						// オフセットの上位 DWORD
			0,						// オフセットの下位 DWORD
			0);						// マップ対象のバイト数
		if (_memory == NULL)
			return false;
		return true;
	}

	static void write(int nameNumberHigh, int nameNumberLow, int size, int id, char value) {
		if (_memory == NULL && initialize(nameNumberHigh, nameNumberLow, size) == false) {
			return;
		}
		_memory[id] |= value;
	}

public:
	static int read(int nameNumberHigh, int nameNumberLow, int size, int id) {
		if (_memory == NULL && initialize(nameNumberHigh, nameNumberLow, size) == false) {
			return -1;
		}
		return _memory[id];
	}
	
	static bool branch(int nameNumberHigh, int nameNumberLow, int size, int id, bool value) {
		write(nameNumberHigh, nameNumberLow, size, id, value ? 1 : 2);
		return value;
	}
	
	static void statement(int nameNumberHigh, int nameNumberLow, int size, int id) {
		write(nameNumberHigh, nameNumberLow, size, id, 3);
	}
};

extern int read(int nameNumberHigh, int nameNumberLow, int size, int id);
extern bool branch(int nameNumberHigh, int nameNumberLow, int size, int id, bool value);
extern void statement(int nameNumberHigh, int nameNumberLow, int size, int id);

#endif //COVERAGE_MANAGER_H_
