<commit_before>/**
 * @file dewpoint.cpp
 *
 * @date Jan 21, 2012
 * @author partio
 */

#include "dewpoint.h"
#include "plugin_factory.h"
#include "logger_factory.h"
#include <boost/lexical_cast.hpp>

#define HIMAN_AUXILIARY_INCLUDE

#include "fetcher.h"

#undef HIMAN_AUXILIARY_INCLUDE

#include "dewpoint_cuda.h"
#include "cuda_helper.h"

using namespace std;
using namespace himan::plugin;

const double RW = 461.5; // Vesihoyryn kaasuvakio (J / K kg)
const double L = 2.5e6; // Veden hoyrystymislampo (J / kg)
const double RW_div_L = RW / L;

dewpoint::dewpoint()
{
	itsClearTextFormula = "Td = T / (1 - (T * ln(RH)*(Rw/L)))";

	itsLogger = std::unique_ptr<logger> (logger_factory::Instance()->GetLog("dewpoint"));

}

void dewpoint::Process(shared_ptr<const plugin_configuration> conf)
{

	unique_ptr<timer> aTimer;

	// Get number of threads to use

	short threadCount = ThreadCount(conf->ThreadCount());

	if (conf->StatisticsEnabled())
	{
		aTimer = unique_ptr<timer> (timer_factory::Instance()->GetTimer());
		aTimer->Start();
		conf->Statistics()->UsedThreadCount(threadCount);
		conf->Statistics()->UsedGPUCount(conf->CudaDeviceCount());
	}

	boost::thread_group g;

	shared_ptr<info> targetInfo = conf->Info();

	/*
	 * Set target parameter to potential temperature
	 *
	 * We need to specify grib and querydata parameter information
	 * since we don't know which one will be the output format.
	 *
	 */

	vector<param> params;

	param requestedParam ("TD-C", 10);

	// GRIB 2

	requestedParam.GribDiscipline(0);
	requestedParam.GribCategory(0);
	requestedParam.GribParameter(6);

	params.push_back(requestedParam);

	// GRIB 1

	if (conf->OutputFileType() == kGRIB1)
	{
		StoreGrib1ParameterDefinitions(params, targetInfo->Producer().TableVersion());
	}

	targetInfo->Params(params);

	/*
	 * Create data structures.
	 */

	targetInfo->Create();

	/*
	 * Initialize parent class functions for dimension handling
	 */

	Dimension(conf->LeadingDimension());
	FeederInfo(shared_ptr<info> (new info(*targetInfo)));
	FeederInfo()->Param(requestedParam);

	if (conf->StatisticsEnabled())
	{
		aTimer->Stop();
		conf->Statistics()->AddToInitTime(aTimer->GetTime());
		aTimer->Start();
	}

	/*
	 * Each thread will have a copy of the target info.
	 */

	for (short i = 0; i < threadCount; i++)
	{

		itsLogger->Info("Thread " + boost::lexical_cast<string> (i + 1) + " starting");

		boost::thread* t = new boost::thread(&dewpoint::Run,
											 this,
											 shared_ptr<info> (new info(*targetInfo)),
											 conf,
											 i + 1);

		g.add_thread(t);

	}

	g.join_all();

	if (conf->StatisticsEnabled())
	{
		aTimer->Stop();
		conf->Statistics()->AddToProcessingTime(aTimer->GetTime());
	}

	if (conf->FileWriteOption() == kSingleFile)
	{
		WriteToFile(conf, targetInfo);
	}
}

void dewpoint::Run(shared_ptr<info> myTargetInfo,
			   const shared_ptr<const plugin_configuration> conf,
			   unsigned short threadIndex)
{
	while (AdjustLeadingDimension(myTargetInfo))
	{
		Calculate(myTargetInfo, conf, threadIndex);
	}

}

/*
 * Calculate()
 *
 * This function does the actual calculation.
 */

void dewpoint::Calculate(shared_ptr<info> myTargetInfo,
					 const shared_ptr<const plugin_configuration> conf,
					 unsigned short threadIndex)
{

	shared_ptr<fetcher> f = dynamic_pointer_cast <fetcher> (plugin_factory::Instance()->Plugin("fetcher"));

	// Required source parameters

	param TParam("T-K");
	param RHParam("RH-PRCNT");

	unique_ptr<logger> myThreadedLogger = std::unique_ptr<logger> (logger_factory::Instance()->GetLog("dewpointThread #" + boost::lexical_cast<string> (threadIndex)));

	ResetNonLeadingDimension(myTargetInfo);

	myTargetInfo->FirstParam();

	bool useCudaInThisThread = compiled_plugin_base::GetAndSetCuda(conf, threadIndex);

	while (AdjustNonLeadingDimension(myTargetInfo))
	{

		myThreadedLogger->Debug("Calculating time " + myTargetInfo->Time().ValidDateTime()->String("%Y%m%d%H%M") +
								" level " + boost::lexical_cast<string> (myTargetInfo->Level().Value()));

		double TBase = 0;

		shared_ptr<info> TInfo;
		shared_ptr<info> RHInfo;

		try
		{
			TInfo = f->Fetch(conf,
								myTargetInfo->Time(),
								myTargetInfo->Level(),
								TParam,
								conf->UseCudaForPacking() && useCudaInThisThread);

			RHInfo = f->Fetch(conf,
								myTargetInfo->Time(),
								myTargetInfo->Level(),
								RHParam,
								conf->UseCudaForPacking() && useCudaInThisThread);

		}
		catch (HPExceptionType e)
		{
			switch (e)
			{
				case kFileDataNotFound:
					itsLogger->Info("Skipping step " + boost::lexical_cast<string> (myTargetInfo->Time().Step()) + ", level " + boost::lexical_cast<string> (myTargetInfo->Level().Value()));
					myTargetInfo->Data()->Fill(kFloatMissing); // Fill data with missing value

					if (conf->StatisticsEnabled())
					{
						conf->Statistics()->AddToMissingCount(myTargetInfo->Grid()->Size());
						conf->Statistics()->AddToValueCount(myTargetInfo->Grid()->Size());
					}

					continue;
					break;

				default:
					throw runtime_error(ClassName() + ": Unable to proceed");
					break;
			}
		}

		assert(TInfo->Grid()->AB() == RHInfo->Grid()->AB());

		SetAB(myTargetInfo, TInfo);

		assert(RHInfo->Param().Unit() == kPrcnt);

		if (TInfo->Param().Unit() == kC)
		{
			TBase = 273.15;
		}

		shared_ptr<NFmiGrid> targetGrid(myTargetInfo->Grid()->ToNewbaseGrid());
		shared_ptr<NFmiGrid> TGrid(TInfo->Grid()->ToNewbaseGrid());
		shared_ptr<NFmiGrid> RHGrid(RHInfo->Grid()->ToNewbaseGrid());

		size_t missingCount = 0;
		size_t count = 0;

		assert(targetGrid->Size() == myTargetInfo->Data()->Size());

		bool equalGrids = (*myTargetInfo->Grid() == *TInfo->Grid() && *myTargetInfo->Grid() == *RHInfo->Grid());

		string deviceType;

#ifdef HAVE_CUDA

		if (useCudaInThisThread && equalGrids)
		{

			deviceType = "GPU";

			dewpoint_cuda::dewpoint_cuda_options opts;
			dewpoint_cuda::dewpoint_cuda_data datas;

			opts.N = TInfo->Data()->Size();
			opts.cudaDeviceIndex = static_cast<unsigned short> (threadIndex-1);

			opts.TBase = TBase;

			CUDA_CHECK(cudaHostAlloc(reinterpret_cast<void**> (&datas.TD), opts.N * sizeof(double), cudaHostAllocMapped));

			if (TInfo->Grid()->DataIsPacked())
			{
				assert(TInfo->Grid()->PackedData()->ClassName() == "simple_packed");

				shared_ptr<simple_packed> t = dynamic_pointer_cast<simple_packed> (TInfo->Grid()->PackedData());

				CUDA_CHECK(cudaHostAlloc(reinterpret_cast<void**> (&datas.T), opts.N * sizeof(double), cudaHostAllocMapped));

				datas.pT = t.get();

				opts.pT = true;
			}
			else
			{
				datas.T = const_cast<double*> (TInfo->Grid()->Data()->Values());
			}

			if (RHInfo->Grid()->DataIsPacked())
			{
				assert(RHInfo->Grid()->PackedData()->ClassName() == "simple_packed");

				shared_ptr<simple_packed> rh = dynamic_pointer_cast<simple_packed> (RHInfo->Grid()->PackedData());

				CUDA_CHECK(cudaHostAlloc(reinterpret_cast<void**> (&datas.RH), opts.N * sizeof(double), cudaHostAllocMapped));

				datas.pRH = rh.get();

				opts.pRH = true;
			}
			else
			{
				datas.RH = const_cast<double*> (RHInfo->Grid()->Data()->Values());
			}

			dewpoint_cuda::DoCuda(opts, datas);

			myTargetInfo->Data()->Set(datas.TD, opts.N);
			assert(TInfo->Grid()->ScanningMode() == RHInfo->Grid()->ScanningMode());

			missingCount = opts.missingValuesCount;
			count = opts.N;

			CUDA_CHECK(cudaFreeHost(datas.TD));

			if (TInfo->Grid()->DataIsPacked())
			{
				TInfo->Data()->Set(datas.T, opts.N);
				TInfo->Grid()->PackedData()->Clear();
				CUDA_CHECK(cudaFreeHost(datas.T));
			}

			if (RHInfo->Grid()->DataIsPacked())
			{
				RHInfo->Data()->Set(datas.RH, opts.N);
				RHInfo->Grid()->PackedData()->Clear();
				CUDA_CHECK(cudaFreeHost(datas.RH));
			}

			SwapTo(myTargetInfo, TInfo->Grid()->ScanningMode());

		}
		else
#endif
		{
			deviceType = "CPU";

			myTargetInfo->ResetLocation();

			targetGrid->Reset();

			while (myTargetInfo->NextLocation() && targetGrid->Next())
			{
				count++;

				double T = kFloatMissing;
				double RH = kFloatMissing;

				InterpolateToPoint(targetGrid, TGrid, equalGrids, T);
				InterpolateToPoint(targetGrid, RHGrid, equalGrids, RH);

				if (T == kFloatMissing || RH == kFloatMissing)
				{
					missingCount++;

					myTargetInfo->Value(kFloatMissing);
					continue;
				}

				double TD = ((T+TBase) / (1 - ((T+TBase) * log(RH) * (RW_div_L)))) - 273.15 + TBase;

				if (!myTargetInfo->Value(TD))
				{
					throw runtime_error(ClassName() + ": Failed to set value to matrix");
				}

			}

			/*
			 * Newbase normalizes scanning mode to bottom left -- if that's not what
			 * the target scanning mode is, we have to swap the data back.
			 */

			SwapTo(myTargetInfo, kBottomLeft);
		}

		if (conf->StatisticsEnabled())
		{
			conf->Statistics()->AddToMissingCount(missingCount);
			conf->Statistics()->AddToValueCount(count);
		}

		/*
		 * Now we are done for this level
		 *
		 * Clone info-instance to writer since it might change our descriptor places
		 */

		myThreadedLogger->Info("Missing values: " + boost::lexical_cast<string> (missingCount) + "/" + boost::lexical_cast<string> (count));

		if (conf->FileWriteOption() != kSingleFile)
		{
			WriteToFile(conf, myTargetInfo);
		}
	}
}
<commit_msg>Use RHScale -- Harmonie provides RH as values 0 .. 1<commit_after>/**
 * @file dewpoint.cpp
 *
 * @date Jan 21, 2012
 * @author partio
 */

#include "dewpoint.h"
#include "plugin_factory.h"
#include "logger_factory.h"
#include <boost/lexical_cast.hpp>

#define HIMAN_AUXILIARY_INCLUDE

#include "fetcher.h"

#undef HIMAN_AUXILIARY_INCLUDE

#include "dewpoint_cuda.h"
#include "cuda_helper.h"

using namespace std;
using namespace himan::plugin;

const double RW = 461.5; // Vesihoyryn kaasuvakio (J / K kg)
const double L = 2.5e6; // Veden hoyrystymislampo (J / kg)
const double RW_div_L = RW / L;

dewpoint::dewpoint()
{
	itsClearTextFormula = "Td = T / (1 - (T * ln(RH)*(Rw/L)))";

	itsLogger = std::unique_ptr<logger> (logger_factory::Instance()->GetLog("dewpoint"));

}

void dewpoint::Process(shared_ptr<const plugin_configuration> conf)
{

	unique_ptr<timer> aTimer;

	// Get number of threads to use

	short threadCount = ThreadCount(conf->ThreadCount());

	if (conf->StatisticsEnabled())
	{
		aTimer = unique_ptr<timer> (timer_factory::Instance()->GetTimer());
		aTimer->Start();
		conf->Statistics()->UsedThreadCount(threadCount);
		conf->Statistics()->UsedGPUCount(conf->CudaDeviceCount());
	}

	boost::thread_group g;

	shared_ptr<info> targetInfo = conf->Info();

	/*
	 * Set target parameter to potential temperature
	 *
	 * We need to specify grib and querydata parameter information
	 * since we don't know which one will be the output format.
	 *
	 */

	vector<param> params;

	param requestedParam ("TD-C", 10);

	// GRIB 2

	requestedParam.GribDiscipline(0);
	requestedParam.GribCategory(0);
	requestedParam.GribParameter(6);

	params.push_back(requestedParam);

	// GRIB 1

	if (conf->OutputFileType() == kGRIB1)
	{
		StoreGrib1ParameterDefinitions(params, targetInfo->Producer().TableVersion());
	}

	targetInfo->Params(params);

	/*
	 * Create data structures.
	 */

	targetInfo->Create();

	/*
	 * Initialize parent class functions for dimension handling
	 */

	Dimension(conf->LeadingDimension());
	FeederInfo(shared_ptr<info> (new info(*targetInfo)));
	FeederInfo()->Param(requestedParam);

	if (conf->StatisticsEnabled())
	{
		aTimer->Stop();
		conf->Statistics()->AddToInitTime(aTimer->GetTime());
		aTimer->Start();
	}

	/*
	 * Each thread will have a copy of the target info.
	 */

	for (short i = 0; i < threadCount; i++)
	{

		itsLogger->Info("Thread " + boost::lexical_cast<string> (i + 1) + " starting");

		boost::thread* t = new boost::thread(&dewpoint::Run,
											 this,
											 shared_ptr<info> (new info(*targetInfo)),
											 conf,
											 i + 1);

		g.add_thread(t);

	}

	g.join_all();

	if (conf->StatisticsEnabled())
	{
		aTimer->Stop();
		conf->Statistics()->AddToProcessingTime(aTimer->GetTime());
	}

	if (conf->FileWriteOption() == kSingleFile)
	{
		WriteToFile(conf, targetInfo);
	}
}

void dewpoint::Run(shared_ptr<info> myTargetInfo,
			   const shared_ptr<const plugin_configuration> conf,
			   unsigned short threadIndex)
{
	while (AdjustLeadingDimension(myTargetInfo))
	{
		Calculate(myTargetInfo, conf, threadIndex);
	}

}

/*
 * Calculate()
 *
 * This function does the actual calculation.
 */

void dewpoint::Calculate(shared_ptr<info> myTargetInfo,
					 const shared_ptr<const plugin_configuration> conf,
					 unsigned short threadIndex)
{

	shared_ptr<fetcher> f = dynamic_pointer_cast <fetcher> (plugin_factory::Instance()->Plugin("fetcher"));

	// Required source parameters

	param TParam("T-K");
	param RHParam("RH-PRCNT");

	unique_ptr<logger> myThreadedLogger = std::unique_ptr<logger> (logger_factory::Instance()->GetLog("dewpointThread #" + boost::lexical_cast<string> (threadIndex)));

	ResetNonLeadingDimension(myTargetInfo);

	myTargetInfo->FirstParam();

	bool useCudaInThisThread = compiled_plugin_base::GetAndSetCuda(conf, threadIndex);

	// Force use of CPU since cuda does not handle RHScale yet!
	useCudaInThisThread = false;

	while (AdjustNonLeadingDimension(myTargetInfo))
	{

		myThreadedLogger->Debug("Calculating time " + myTargetInfo->Time().ValidDateTime()->String("%Y%m%d%H%M") +
								" level " + boost::lexical_cast<string> (myTargetInfo->Level().Value()));

		double TBase = 0;
		double RHScale = 1;

		shared_ptr<info> TInfo;
		shared_ptr<info> RHInfo;

		try
		{
			TInfo = f->Fetch(conf,
								myTargetInfo->Time(),
								myTargetInfo->Level(),
								TParam,
								conf->UseCudaForPacking() && useCudaInThisThread);

			RHInfo = f->Fetch(conf,
								myTargetInfo->Time(),
								myTargetInfo->Level(),
								RHParam,
								conf->UseCudaForPacking() && useCudaInThisThread);

		}
		catch (HPExceptionType e)
		{
			switch (e)
			{
				case kFileDataNotFound:
					itsLogger->Info("Skipping step " + boost::lexical_cast<string> (myTargetInfo->Time().Step()) + ", level " + boost::lexical_cast<string> (myTargetInfo->Level().Value()));
					myTargetInfo->Data()->Fill(kFloatMissing); // Fill data with missing value

					if (conf->StatisticsEnabled())
					{
						conf->Statistics()->AddToMissingCount(myTargetInfo->Grid()->Size());
						conf->Statistics()->AddToValueCount(myTargetInfo->Grid()->Size());
					}

					continue;
					break;

				default:
					throw runtime_error(ClassName() + ": Unable to proceed");
					break;
			}
		}

		assert(TInfo->Grid()->AB() == RHInfo->Grid()->AB());

		SetAB(myTargetInfo, TInfo);

		if (RHInfo->Param().Unit() != kPrcnt)
		{
			// If unit cannot be detected, assume the values are from 0 .. 1
			RHScale = 100;
			myThreadedLogger->Warning("Unable to determine unit for relative humidity -- assuming values are from 0 to 1");
		}

		if (TInfo->Param().Unit() == kC)
		{
			TBase = 273.15;
		}

		shared_ptr<NFmiGrid> targetGrid(myTargetInfo->Grid()->ToNewbaseGrid());
		shared_ptr<NFmiGrid> TGrid(TInfo->Grid()->ToNewbaseGrid());
		shared_ptr<NFmiGrid> RHGrid(RHInfo->Grid()->ToNewbaseGrid());

		size_t missingCount = 0;
		size_t count = 0;

		assert(targetGrid->Size() == myTargetInfo->Data()->Size());

		bool equalGrids = (*myTargetInfo->Grid() == *TInfo->Grid() && *myTargetInfo->Grid() == *RHInfo->Grid());

		string deviceType;

#ifdef HAVE_CUDA
		if (useCudaInThisThread && equalGrids)
		{

			deviceType = "GPU";

			dewpoint_cuda::dewpoint_cuda_options opts;
			dewpoint_cuda::dewpoint_cuda_data datas;

			opts.N = TInfo->Data()->Size();
			opts.cudaDeviceIndex = static_cast<unsigned short> (threadIndex-1);

			opts.TBase = TBase;

			CUDA_CHECK(cudaHostAlloc(reinterpret_cast<void**> (&datas.TD), opts.N * sizeof(double), cudaHostAllocMapped));

			if (TInfo->Grid()->DataIsPacked())
			{
				assert(TInfo->Grid()->PackedData()->ClassName() == "simple_packed");

				shared_ptr<simple_packed> t = dynamic_pointer_cast<simple_packed> (TInfo->Grid()->PackedData());

				CUDA_CHECK(cudaHostAlloc(reinterpret_cast<void**> (&datas.T), opts.N * sizeof(double), cudaHostAllocMapped));

				datas.pT = t.get();

				opts.pT = true;
			}
			else
			{
				datas.T = const_cast<double*> (TInfo->Grid()->Data()->Values());
			}

			if (RHInfo->Grid()->DataIsPacked())
			{
				assert(RHInfo->Grid()->PackedData()->ClassName() == "simple_packed");

				shared_ptr<simple_packed> rh = dynamic_pointer_cast<simple_packed> (RHInfo->Grid()->PackedData());

				CUDA_CHECK(cudaHostAlloc(reinterpret_cast<void**> (&datas.RH), opts.N * sizeof(double), cudaHostAllocMapped));

				datas.pRH = rh.get();

				opts.pRH = true;
			}
			else
			{
				datas.RH = const_cast<double*> (RHInfo->Grid()->Data()->Values());
			}

			dewpoint_cuda::DoCuda(opts, datas);

			myTargetInfo->Data()->Set(datas.TD, opts.N);
			assert(TInfo->Grid()->ScanningMode() == RHInfo->Grid()->ScanningMode());

			missingCount = opts.missingValuesCount;
			count = opts.N;

			CUDA_CHECK(cudaFreeHost(datas.TD));

			if (TInfo->Grid()->DataIsPacked())
			{
				TInfo->Data()->Set(datas.T, opts.N);
				TInfo->Grid()->PackedData()->Clear();
				CUDA_CHECK(cudaFreeHost(datas.T));
			}

			if (RHInfo->Grid()->DataIsPacked())
			{
				RHInfo->Data()->Set(datas.RH, opts.N);
				RHInfo->Grid()->PackedData()->Clear();
				CUDA_CHECK(cudaFreeHost(datas.RH));
			}

			SwapTo(myTargetInfo, TInfo->Grid()->ScanningMode());

		}
		else
#endif
		{
			deviceType = "CPU";

			myTargetInfo->ResetLocation();

			targetGrid->Reset();

			while (myTargetInfo->NextLocation() && targetGrid->Next())
			{
				count++;

				double T = kFloatMissing;
				double RH = kFloatMissing;

				InterpolateToPoint(targetGrid, TGrid, equalGrids, T);
				InterpolateToPoint(targetGrid, RHGrid, equalGrids, RH);

				if (T == kFloatMissing || RH == kFloatMissing)
				{
					missingCount++;

					myTargetInfo->Value(kFloatMissing);
					continue;
				}

				double TD = ((T+TBase) / (1 - ((T+TBase) * log(RHScale * RH) * (RW_div_L)))) - 273.15 + TBase;

				if (!myTargetInfo->Value(TD))
				{
					throw runtime_error(ClassName() + ": Failed to set value to matrix");
				}

			}

			/*
			 * Newbase normalizes scanning mode to bottom left -- if that's not what
			 * the target scanning mode is, we have to swap the data back.
			 */

			SwapTo(myTargetInfo, kBottomLeft);
		}

		if (conf->StatisticsEnabled())
		{
			conf->Statistics()->AddToMissingCount(missingCount);
			conf->Statistics()->AddToValueCount(count);
		}

		/*
		 * Now we are done for this level
		 *
		 * Clone info-instance to writer since it might change our descriptor places
		 */

		myThreadedLogger->Info("Missing values: " + boost::lexical_cast<string> (missingCount) + "/" + boost::lexical_cast<string> (count));

		if (conf->FileWriteOption() != kSingleFile)
		{
			WriteToFile(conf, myTargetInfo);
		}
	}
}
<|endoftext|>


<commit_before>#ifndef __QUEUE_HPP_INCLUDED__
#define __QUEUE_HPP_INCLUDED__

#include <cstdint>
#include <fstream>
#include <mutex>

#include <boost/algorithm/string.hpp>
#include <boost/filesystem.hpp>

#include "serialization.hpp"

namespace fs = boost::filesystem;

template <typename T>
class BaseQueue
{
private:

    virtual T getElementAt(int64_t index) = 0;

    virtual int64_t getElementSizeAt(int64_t index) = 0;

    virtual int64_t getFirstElementIndex() = 0;

    virtual int64_t getLastElementIndex() = 0;

    class Iterator
    {
    public:

        Iterator(BaseQueue<T> *queue_, int64_t index_)
            : queue(queue_), index(index_)
        {
        }

        T operator*()
        {
            return queue->getElementAt(index);
        }

        Iterator& operator++()
        {
            int64_t size = queue->getElementSizeAt(index);
            index += size;
            return *this;
        }

        bool operator!=(const Iterator& iterator)
        {
            return index != iterator.index;
        }

    private:

        BaseQueue<T> *queue;

        int64_t index;
    };

public:

    virtual void Enqueue(T e) = 0;

    virtual void Dequeue() = 0;

    virtual T Last() = 0;

    Iterator begin()
    {
        return Iterator(this, getFirstElementIndex());
    }

    Iterator end()
    {
        return Iterator(this, getLastElementIndex());
    }
};

template <typename T>
class VolatileQueue : public BaseQueue<T>
{
public:

    void Enqueue(T e)
    {
        data.push_back(e);
    }

    void Dequeue()
    {
        if (!data.empty())
        {
            data.erase(data.begin());
        }
    }

    T Last()
    {
        T empty;
        return data.size() > 0 ? data[data.size() - 1 ] : empty;
    }

private:

    T getElementAt(int64_t index)
    {
        return data[index];
    }

    int64_t getElementSizeAt(int64_t index)
    {
        return 1;
    }

    int64_t getFirstElementIndex()
    {
        return 0;
    }

    int64_t getLastElementIndex()
    {
        return data.size();
    }

    std::vector<T> data;
};

template <typename T>
class PersistentQueue : public BaseQueue<T>
{
public:

    PersistentQueue(std::string filename)
        : PersistentQueue(".", filename)
    {
    }

    PersistentQueue(std::string dirname, std::string filename)
        : file((fs::path(dirname) / fs::path(filename)).string(),
               std::ios::out | std::ios::in | std::ios::app | std::ios::binary),
          stream(file),
          insert_file((fs::path(dirname) / fs::path(filename)).string(),
                       std::ios::in | std::ios::out | std::ios::binary),
          insert_stream(insert_file),
          start_position(0),
          end_position(0),
          mutex()
    {
        SaveOffsets();
        LoadOffsets();
    }

    PersistentQueue(std::iostream& stream)
        : stream(stream),
          insert_stream(stream),
          start_position(0),
          end_position(0),
          mutex()
    {
        SaveOffsets();
        LoadOffsets();
    }

    ~PersistentQueue()
    {
        stream.flush();
    }

    void SaveOffsets()
    {
        stream.seekg(0, std::ios::end);
        if (stream.tellg() < HEADER_SIZE)
        {
            start_position = HEADER_SIZE;
            end_position = UNINITIALIZED;
        }

        //insert_stream.seekp(0, std::ios::beg);
        insert_stream << std::setw(INDEX_SIZE) << start_position;
        insert_stream << std::setw(INDEX_SIZE) << end_position;
        insert_stream.flush();
    }

    void LoadOffsets()
    {
        stream.seekg(0, std::ios::beg);

        std::string buffer;
        stream.read(&buffer[0], INDEX_SIZE);
        boost::trim(buffer);
        start_position = std::stoi(buffer);

        stream.read(&buffer[0], INDEX_SIZE);
        boost::trim(buffer);
        end_position = std::stoi(buffer);
    }

    void Enqueue(T e)
    {
        std::lock_guard<std::recursive_mutex> lock(mutex);

        std::string element_as_string = Serialize<T>(e);

        LoadOffsets();

        stream.seekg(0, std::ios::end);
        end_position = stream.tellg();

        insert_stream.seekp(INDEX_SIZE, std::ios::beg);
        insert_stream << std::setw(INDEX_SIZE) << end_position;
        insert_stream.flush();

        stream.seekp(0, std::ios::end);
        stream << element_as_string;
        stream.flush();
    }

    void Dequeue()
    {
        std::lock_guard<std::recursive_mutex> lock(mutex);

        LoadOffsets();

        for (T element : *this)
        {
            start_position += Serialize<T>(element).length();
            stream.seekp(0, std::ios::beg);
            stream << std::setw(INDEX_SIZE) << start_position;
            break;
        }
    }

    T Last()
    {
        std::lock_guard<std::recursive_mutex> lock(mutex);

        T empty;
        stream.seekg(0, std::ios::end);
        if (stream.tellg() <= HEADER_SIZE)
        {
            return empty;
        }

        LoadOffsets();

        stream.seekg(end_position, std::ios::beg);

        return Deserialize<T>(stream);
    }

private:

    T getElementAt(int64_t index)
    {
        std::lock_guard<std::recursive_mutex> lock(mutex);

        stream.seekg(index, std::ios::beg);
        return Deserialize<T>(stream);
    }

    int64_t getElementSizeAt(int64_t index)
    {
        std::lock_guard<std::recursive_mutex> lock(mutex);

        stream.seekg(index, std::ios::beg);
        return Serialize<T>(Deserialize<T>(stream)).length();
    }

    int64_t getFirstElementIndex()
    {
        std::lock_guard<std::recursive_mutex> lock(mutex);

        LoadOffsets();

        return start_position;
    }

    int64_t getLastElementIndex()
    {
        std::lock_guard<std::recursive_mutex> lock(mutex);

        stream.seekg(0, std::ios::end);
        return stream.tellg();
    }

    std::fstream file;

    std::iostream& stream;

    std::fstream insert_file;

    std::iostream& insert_stream;

    std::streampos start_position;

    std::streampos end_position;

    std::recursive_mutex mutex;

    constexpr static const int64_t INDEX_SIZE = 10;

    constexpr static const int64_t HEADER_SIZE = INDEX_SIZE * 2;

    constexpr static const int64_t UNINITIALIZED = -1;
};

template <typename T>
class RolloverQueue
{
private:

    std::streampos get_start_position()
    {
        stream.seekg(0 * INDEX_SIZE, std::ios::beg);
        std::string buffer;
        stream.read(&buffer[0], INDEX_SIZE);
        boost::trim(buffer);
        return static_cast<std::streampos>(std::stoi(buffer));
    }

    std::streampos get_end_position()
    {
        stream.seekg(1 * INDEX_SIZE, std::ios::beg);
        std::string buffer;
        stream.read(&buffer[0], INDEX_SIZE);
        boost::trim(buffer);
        return static_cast<std::streampos>(std::stoi(buffer));
    }

    std::streampos get_eof_position()
    {
        stream.seekg(0, std::ios::end);
        return stream.tellg();
    }

    std::iostream& stream;

    std::iostream& insert_stream;

    std::streampos rollover_size;

    constexpr static const int64_t INDEX_SIZE = 10;

    constexpr static const int64_t UNINITIALIZED = 0;

    constexpr static const int64_t HEADER_SIZE = INDEX_SIZE * 2;

    class Iterator
    {
    public:

        Iterator(
            std::iostream& stream,
            std::streampos position,
            std::streampos rollover
        )
            : stream(stream),
              position(position),
              rollover(rollover)
        {
        }

        T operator*()
        {
            stream.seekg(position, std::ios::beg);

            return Deserialize<T>(stream);
        }

        Iterator& operator++()
        {
            if (position <= rollover)
            {
                stream.seekg(position, std::ios::beg);
                position += Serialize<T>(Deserialize<T>(stream)).length();
            }
            else
            {
                position = HEADER_SIZE;
            }

            return *this;
        }

        bool operator!=(const Iterator& iterator)
        {
            return position != iterator.position;
        }

    private:

        std::iostream& stream;

        std::streampos position;

        std::streampos rollover;

        constexpr static const int64_t INDEX_SIZE = 10;

        constexpr static const int64_t HEADER_SIZE = INDEX_SIZE * 3;
    };

public:

    RolloverQueue(std::iostream& stream, std::streampos rollover_size=65536)
        : stream(stream),
          insert_stream(stream),
          rollover_size(rollover_size)
    {
        stream.seekg(0, std::ios::end);
        if (stream.tellg() < HEADER_SIZE)
        {
            insert_stream << std::setw(INDEX_SIZE) << HEADER_SIZE;
            insert_stream << std::setw(INDEX_SIZE) << UNINITIALIZED;
        }
    }

    void Enqueue(T e)
    {
        std::string element_as_string = Serialize<T>(e);
        auto size = element_as_string.length();

        std::streampos position = get_end_position();
        if (position == UNINITIALIZED)
        {
            position = HEADER_SIZE;
        }
        else if (rollover_size < position + static_cast<std::streampos>(size))
        {
            // rollover and over-write existing entries
        }

        // flush element
        stream.seekp(position, std::ios::beg);
        stream << element_as_string;
        stream.flush();

        // update indexes
        insert_stream.seekp(1 * INDEX_SIZE, std::ios::beg);
        insert_stream << std::setw(INDEX_SIZE) << position;
        insert_stream.flush();
    }

    void Dequeue()
    {
        auto position = get_start_position();
        stream.seekg(position, std::ios::beg);

        auto next = position + Serialize<T>(Deserialize<T>(stream)).length();

        insert_stream << std::setw(INDEX_SIZE) << next;
        // TODO: close and reset insert_stream?
    }

    T Last()
    {
        return *end();
    }

    Iterator begin()
    {
        return Iterator(stream, get_start_position(), rollover_size);
    }

    Iterator end()
    {
        auto start = get_start_position();
        auto end = get_end_position();
        auto eof = get_eof_position();
        if (end == UNINITIALIZED || end == eof)
        {
            end = start;
        }
        else
        {
            stream.seekg(end, std::ios::beg);
            end += Serialize<T>(Deserialize<T>(stream)).length();
        }
        return Iterator(stream, end, rollover_size);
    }
};

#endif
<commit_msg>Rollover queue adjusts start position on overwrite<commit_after>#ifndef __QUEUE_HPP_INCLUDED__
#define __QUEUE_HPP_INCLUDED__

#include <cstdint>
#include <fstream>
#include <mutex>

#include <boost/algorithm/string.hpp>
#include <boost/filesystem.hpp>

#include "serialization.hpp"

namespace fs = boost::filesystem;

template <typename T>
class BaseQueue
{
private:

    virtual T getElementAt(int64_t index) = 0;

    virtual int64_t getElementSizeAt(int64_t index) = 0;

    virtual int64_t getFirstElementIndex() = 0;

    virtual int64_t getLastElementIndex() = 0;

    class Iterator
    {
    public:

        Iterator(BaseQueue<T> *queue_, int64_t index_)
            : queue(queue_), index(index_)
        {
        }

        T operator*()
        {
            return queue->getElementAt(index);
        }

        Iterator& operator++()
        {
            int64_t size = queue->getElementSizeAt(index);
            index += size;
            return *this;
        }

        bool operator!=(const Iterator& iterator)
        {
            return index != iterator.index;
        }

    private:

        BaseQueue<T> *queue;

        int64_t index;
    };

public:

    virtual void Enqueue(T e) = 0;

    virtual void Dequeue() = 0;

    virtual T Last() = 0;

    Iterator begin()
    {
        return Iterator(this, getFirstElementIndex());
    }

    Iterator end()
    {
        return Iterator(this, getLastElementIndex());
    }
};

template <typename T>
class VolatileQueue : public BaseQueue<T>
{
public:

    void Enqueue(T e)
    {
        data.push_back(e);
    }

    void Dequeue()
    {
        if (!data.empty())
        {
            data.erase(data.begin());
        }
    }

    T Last()
    {
        T empty;
        return data.size() > 0 ? data[data.size() - 1 ] : empty;
    }

private:

    T getElementAt(int64_t index)
    {
        return data[index];
    }

    int64_t getElementSizeAt(int64_t index)
    {
        return 1;
    }

    int64_t getFirstElementIndex()
    {
        return 0;
    }

    int64_t getLastElementIndex()
    {
        return data.size();
    }

    std::vector<T> data;
};

template <typename T>
class PersistentQueue : public BaseQueue<T>
{
public:

    PersistentQueue(std::string filename)
        : PersistentQueue(".", filename)
    {
    }

    PersistentQueue(std::string dirname, std::string filename)
        : file((fs::path(dirname) / fs::path(filename)).string(),
               std::ios::out | std::ios::in | std::ios::app | std::ios::binary),
          stream(file),
          insert_file((fs::path(dirname) / fs::path(filename)).string(),
                       std::ios::in | std::ios::out | std::ios::binary),
          insert_stream(insert_file),
          start_position(0),
          end_position(0),
          mutex()
    {
        SaveOffsets();
        LoadOffsets();
    }

    PersistentQueue(std::iostream& stream)
        : stream(stream),
          insert_stream(stream),
          start_position(0),
          end_position(0),
          mutex()
    {
        SaveOffsets();
        LoadOffsets();
    }

    ~PersistentQueue()
    {
        stream.flush();
    }

    void SaveOffsets()
    {
        stream.seekg(0, std::ios::end);
        if (stream.tellg() < HEADER_SIZE)
        {
            start_position = HEADER_SIZE;
            end_position = UNINITIALIZED;
        }

        //insert_stream.seekp(0, std::ios::beg);
        insert_stream << std::setw(INDEX_SIZE) << start_position;
        insert_stream << std::setw(INDEX_SIZE) << end_position;
        insert_stream.flush();
    }

    void LoadOffsets()
    {
        stream.seekg(0, std::ios::beg);

        std::string buffer;
        stream.read(&buffer[0], INDEX_SIZE);
        boost::trim(buffer);
        start_position = std::stoi(buffer);

        stream.read(&buffer[0], INDEX_SIZE);
        boost::trim(buffer);
        end_position = std::stoi(buffer);
    }

    void Enqueue(T e)
    {
        std::lock_guard<std::recursive_mutex> lock(mutex);

        std::string element_as_string = Serialize<T>(e);

        LoadOffsets();

        stream.seekg(0, std::ios::end);
        end_position = stream.tellg();

        insert_stream.seekp(INDEX_SIZE, std::ios::beg);
        insert_stream << std::setw(INDEX_SIZE) << end_position;
        insert_stream.flush();

        stream.seekp(0, std::ios::end);
        stream << element_as_string;
        stream.flush();
    }

    void Dequeue()
    {
        std::lock_guard<std::recursive_mutex> lock(mutex);

        LoadOffsets();

        for (T element : *this)
        {
            start_position += Serialize<T>(element).length();
            stream.seekp(0, std::ios::beg);
            stream << std::setw(INDEX_SIZE) << start_position;
            break;
        }
    }

    T Last()
    {
        std::lock_guard<std::recursive_mutex> lock(mutex);

        T empty;
        stream.seekg(0, std::ios::end);
        if (stream.tellg() <= HEADER_SIZE)
        {
            return empty;
        }

        LoadOffsets();

        stream.seekg(end_position, std::ios::beg);

        return Deserialize<T>(stream);
    }

private:

    T getElementAt(int64_t index)
    {
        std::lock_guard<std::recursive_mutex> lock(mutex);

        stream.seekg(index, std::ios::beg);
        return Deserialize<T>(stream);
    }

    int64_t getElementSizeAt(int64_t index)
    {
        std::lock_guard<std::recursive_mutex> lock(mutex);

        stream.seekg(index, std::ios::beg);
        return Serialize<T>(Deserialize<T>(stream)).length();
    }

    int64_t getFirstElementIndex()
    {
        std::lock_guard<std::recursive_mutex> lock(mutex);

        LoadOffsets();

        return start_position;
    }

    int64_t getLastElementIndex()
    {
        std::lock_guard<std::recursive_mutex> lock(mutex);

        stream.seekg(0, std::ios::end);
        return stream.tellg();
    }

    std::fstream file;

    std::iostream& stream;

    std::fstream insert_file;

    std::iostream& insert_stream;

    std::streampos start_position;

    std::streampos end_position;

    std::recursive_mutex mutex;

    constexpr static const int64_t INDEX_SIZE = 10;

    constexpr static const int64_t HEADER_SIZE = INDEX_SIZE * 2;

    constexpr static const int64_t UNINITIALIZED = -1;
};

template <typename T>
class RolloverQueue
{
private:

    std::streampos get_start_position()
    {
        stream.seekg(0 * INDEX_SIZE, std::ios::beg);
        std::string buffer;
        stream.read(&buffer[0], INDEX_SIZE);
        boost::trim(buffer);
        return static_cast<std::streampos>(std::stoi(buffer));
    }

    std::streampos get_end_position()
    {
        stream.seekg(1 * INDEX_SIZE, std::ios::beg);
        std::string buffer;
        stream.read(&buffer[0], INDEX_SIZE);
        boost::trim(buffer);
        return static_cast<std::streampos>(std::stoi(buffer));
    }

    std::streampos get_eof_position()
    {
        stream.seekg(0, std::ios::end);
        return stream.tellg();
    }

    std::fstream file;

    std::iostream& stream;

    std::streampos rollover_size;

    constexpr static const int64_t INDEX_SIZE = 10;

    constexpr static const int64_t UNINITIALIZED = 0;

    constexpr static const int64_t HEADER_SIZE = INDEX_SIZE * 2;

    constexpr static const int64_t DEFAULT_ROLLOVER_SIZE = 1000000000;

    class Iterator
    {
    public:

        Iterator(
            std::iostream& stream,
            std::streampos position,
            std::streampos rollover
        )
            : stream(stream),
              position(position),
              rollover(rollover)
        {
        }

        T operator*()
        {
            stream.seekg(position, std::ios::beg);

            return Deserialize<T>(stream);
        }

        Iterator& operator++()
        {
            if (position <= rollover)
            {
                stream.seekg(position, std::ios::beg);
                position += Serialize<T>(Deserialize<T>(stream)).length();
            }
            else
            {
                position = HEADER_SIZE;
            }

            return *this;
        }

        bool operator!=(const Iterator& iterator)
        {
            return position != iterator.position;
        }

    private:

        std::iostream& stream;

        std::streampos position;

        std::streampos rollover;

        constexpr static const int64_t INDEX_SIZE = 10;

        constexpr static const int64_t HEADER_SIZE = INDEX_SIZE * 3;
    };

public:

    RolloverQueue(std::string filename)
        : RolloverQueue(".", filename)
    {
    }

    RolloverQueue(
        std::string dirname,
        std::string filename,
        std::streampos rollover_size=DEFAULT_ROLLOVER_SIZE
    ) : file((fs::path(dirname) / fs::path(filename)).string(),
               std::ios::out | std::ios::in | std::ios::binary),
          stream(file),
          rollover_size(rollover_size)
    {
        stream.seekg(0, std::ios::end);
        if (stream.tellg() < HEADER_SIZE)
        {
            stream << std::setw(INDEX_SIZE) << HEADER_SIZE;
            stream << std::setw(INDEX_SIZE) << UNINITIALIZED;
        }
    }

    RolloverQueue(
        std::iostream& stream,
        std::streampos rollover_size=DEFAULT_ROLLOVER_SIZE
    ) : stream(stream),
        rollover_size(rollover_size)
    {
        stream.seekg(0, std::ios::end);
        if (stream.tellg() < HEADER_SIZE)
        {
            stream << std::setw(INDEX_SIZE) << HEADER_SIZE;
            stream << std::setw(INDEX_SIZE) << UNINITIALIZED;
        }
    }

    void Enqueue(T e)
    {
        std::string element_as_string = Serialize<T>(e);
        auto size = element_as_string.length();

        std::streampos position = get_end_position();
        if (position == UNINITIALIZED)
        {
            position = HEADER_SIZE;
        }
        else
        {
            stream.seekg(position, std::ios::beg);
            position += Serialize<T>(Deserialize<T>(stream)).length();
        }

        if (rollover_size < position + static_cast<std::streampos>(size))
        {
            std::streampos eof = get_eof_position();

            // rollover and over-write existing entries
            auto start = static_cast<std::streampos>(HEADER_SIZE);
            while (start - HEADER_SIZE < size && start != eof)
            {
                stream.seekg(start, std::ios::beg);
                start += Serialize<T>(Deserialize<T>(stream)).length();
            }

            if (start == eof)
            {
                start = HEADER_SIZE;
            }

            // update start position
            stream.seekp(0 * INDEX_SIZE, std::ios::beg);
            stream << std::setw(INDEX_SIZE) << start;
            stream.flush();
            position = start;
        }

        // flush element
        stream.seekp(position, std::ios::beg);
        stream << element_as_string;
        stream.flush();

        // update end position
        stream.seekp(1 * INDEX_SIZE, std::ios::beg);
        stream << std::setw(INDEX_SIZE) << position;
        stream.flush();
    }

    void Dequeue()
    {
        auto position = get_start_position();
        stream.seekg(position, std::ios::beg);

        auto next = position + static_cast<std::streampos>(
            Serialize<T>(Deserialize<T>(stream)).length());

        stream.seekp(0 * INDEX_SIZE, std::ios::beg);
        stream << std::setw(INDEX_SIZE) << next;
    }

    T Last()
    {
        auto position = get_end_position();
        stream.seekg(position, std::ios::beg);

        return Deserialize<T>(stream);
    }

    Iterator begin()
    {
        return Iterator(stream, get_start_position(), rollover_size);
    }

    Iterator end()
    {
        auto start = get_start_position();
        auto end = get_end_position();
        auto eof = get_eof_position();
        if (end == UNINITIALIZED || end == eof)
        {
            end = start;
        }
        else
        {
            stream.seekg(end, std::ios::beg);
            end += Serialize<T>(Deserialize<T>(stream)).length();
        }
        return Iterator(stream, end, rollover_size);
    }
};

#endif
<|endoftext|>


<commit_before>#include <Watchdog.h>

void Watchdog::enable() {
	WDTCONSET = 1<<15; // Turn on
}

void Watchdog::disable() {
	WDTCONCLR = 1<<15; // Turn off
}

void Watchdog::kick() {
	WDTCONSET = 0x01; // Kick the dog!
}

void Watchdog::enableSleepMode() {
	// Standard unlock sequence
	SYSKEY = 0x0;
	SYSKEY = 0xAA996655;
	SYSKEY = 0x556699AA;
	OSCCONSET = 0x10; // Enable sleep mode
	SYSKEY = 0x0;
}

void Watchdog::enableIdleMode() {
	// Standard unlock sequence
	SYSKEY = 0x0;
	SYSKEY = 0xAA996655;
	SYSKEY = 0x556699AA;
	OSCCONCLR = 0x10; // Disable sleep mode
	SYSKEY = 0x0;
}

void __attribute__((nomips16)) Watchdog::wait() {
	kick();
	uint32_t i = disableInterrupts(); // We don't want any old interrupt waking us up
    asm volatile("mfc0 $26, $12");
    asm volatile("ins $26, $0, 10, 3");
    asm volatile("mtc0 $26, $12");
	asm volatile("wait");
	restoreInterrupts(i);
}

void Watchdog::sleep() {
	enableSleepMode();
	enable();
	kick();
	wait();
	disable();
	enableIdleMode();
}

void Watchdog::idle() {
	enableIdleMode();
	enable();
	kick();
	wait();
	disable();
}
<commit_msg>Added MZ kick code<commit_after>#include <Watchdog.h>

void Watchdog::enable() {
	WDTCONbits.ON = 1;
}

void Watchdog::disable() {
	WDTCONbits.ON = 0;
}

void Watchdog::kick() {
#ifdef __PIC32MZ__
    WDTCONbits.WDTCLRKEY = 0x5743;
#else
	WDTCONbits.WDTCLR = 1;
#endif
}

void Watchdog::enableSleepMode() {
	// Standard unlock sequence
	SYSKEY = 0x0;
	SYSKEY = 0xAA996655;
	SYSKEY = 0x556699AA;
	OSCCONSET = 0x10; // Enable sleep mode
	SYSKEY = 0x0;
}

void Watchdog::enableIdleMode() {
	// Standard unlock sequence
	SYSKEY = 0x0;
	SYSKEY = 0xAA996655;
	SYSKEY = 0x556699AA;
	OSCCONCLR = 0x10; // Disable sleep mode
	SYSKEY = 0x0;
}

void __attribute__((nomips16)) Watchdog::wait() {
	kick();
	uint32_t i = disableInterrupts(); // We don't want any old interrupt waking us up
    asm volatile("mfc0 $26, $12");
    asm volatile("ins $26, $0, 10, 3");
    asm volatile("mtc0 $26, $12");
	asm volatile("wait");
	restoreInterrupts(i);
}

void Watchdog::sleep() {
	enableSleepMode();
	enable();
	kick();
	wait();
	disable();
	enableIdleMode();
}

void Watchdog::idle() {
	enableIdleMode();
	enable();
	kick();
	wait();
	disable();
}
<|endoftext|>


<commit_before>#include "OpenGL.hpp"

std::fstream * debugstream;

void util::initShaderHandler(std::fstream * ds)
{
	debugstream = ds;
}

bool util::shaderFromFile(GLuint shader, std::string filename, std::string shadername)
{
	std::fstream in;
	in.open(filename, std::ios_base::in);
	if(!in.is_open())
	{
		*debugstream << "File " << filename << " could not be opened, and consequently <<" << shadername << ">> couldn't be compiled." << std::endl;
		return false;
	}
	in.seekg(0, std::ios::end);
	int length = in.tellg();
	in.seekg(0, std::ios::beg);
	char * file = new char[length + 1];
	file[length] = 0;
	in.read(file, length);
	in.close();
#ifdef _WIN32
	char * end = std::remove_if(file, file + length + 1, [](const char & c) -> bool { return !(isprint(c) || isspace(c)) });
	if(end != file + length + 1) *end = 0;
	end = NULL; //Not valid as soon as file is deleted. Putting inside the #ifdef for convenience.
#endif
	glShaderSource(shader, 1, (const char **)&file, NULL);
	glCompileShader(shader);
	delete[] file;
	//Check for proper compilation:
	GLint _compiled = 0;
	glGetShaderiv(shader, GL_COMPILE_STATUS, &_compiled);
	if(_compiled == GL_FALSE)
	{
		GLint length;
		GLchar* log;
		glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &length);
		log = new GLchar[length];
		glGetShaderInfoLog(shader, length, &length, log);
		*debugstream << "There was a problem with shader <<" << shadername << ">>\n" << log << "----------------------------------------" << std::endl;
		delete log;
		return false;
	}
	return true;
}

struct CharTrait
{
	float advance_x, advance_y;
	short bitmap_width, bitmap_rows;
	float bitmap_left, bitmap_top;
	float texture_width, texture_height;
	float texture_x;
};

std::set<int> fontSizes;
std::map< int, std::pair<GLuint, CharTrait * > > atlases;
std::string currentFont = "";

GLuint shaderProgram;
FT_Library ft;
FT_Face face;
int screenWidth, screenHeight;

void util::setScreenSize(int w, int h)
{
	screenWidth = w;
	screenHeight = h;
}

bool util::initText()
{
	shaderProgram = glCreateProgram();
	GLuint vs = glCreateShader(GL_VERTEX_SHADER);
	util::shaderFromFile(vs, "shaders/text/vertex.glsl", "Text Vertex Shader");
	GLuint fs = glCreateShader(GL_FRAGMENT_SHADER);
	util::shaderFromFile(fs, "shaders/text/fragment.glsl", "Text Fragment Shader");
	glAttachShader(shaderProgram, fs);
	glAttachShader(shaderProgram, vs);
	glLinkProgram(shaderProgram);
	glDetachShader(shaderProgram, fs);
	glDetachShader(shaderProgram, vs);
	glDeleteShader(vs);
	glDeleteShader(fs);

	glUniform1i(glGetUniformLocation(shaderProgram, "textureSampler"), 0);

	return FT_Init_FreeType(&ft) == 0;
}

void util::addFontSize(int s)
{
	if(std::count(fontSizes.begin(), fontSizes.end(), s)) return;

	fontSizes.insert(s);

	FT_Set_Pixel_Sizes(face, s, s);

	atlases[s] = { 0, 0 }; //Insert
	atlases[s].second = new CharTrait[128];
	unsigned int texWidth = 0, texHeight = 0;
	FT_GlyphSlot g = face->glyph;
	for(int i = 32; i < 128; i++)
	{
		if(FT_Load_Char(face, i, FT_LOAD_RENDER))
		{
			*debugstream << "Loading character " << char(i) << " failed in font " << currentFont << ".\n";
			continue;
		}

		texWidth += g->bitmap.width;
		if(texHeight < g->bitmap.rows) texHeight = g->bitmap.rows;
	}
	glDeleteTextures(1, &atlases[s].first);
	glGenTextures(1, &atlases[s].first);
	glBindTexture(GL_TEXTURE_2D, atlases[s].first);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
	glActiveTexture(GL_TEXTURE0);
	glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
	glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, texWidth, texHeight, 0, GL_RED, GL_UNSIGNED_BYTE, 0);

	int x = 0;
	for(int i = 32; i < 128; i++)
	{
		if(FT_Load_Char(face, i, FT_LOAD_RENDER)) continue;

		glTexSubImage2D(GL_TEXTURE_2D, 0, x, 0, g->bitmap.width, g->bitmap.rows, GL_RED, GL_UNSIGNED_BYTE, g->bitmap.buffer);

		atlases[s].second[i] = { float(g->advance.x) / 64 / screenWidth, float(g->advance.y) / 64 / screenHeight, short(g->bitmap.width), short(g->bitmap.rows), float(g->bitmap_left), float(g->bitmap_top), (float(g->bitmap.width) / texWidth), (float(g->bitmap.rows) / texHeight), float(x) / texWidth };

		x += g->bitmap.width;
	}
}

void util::removeAllFontSizes()
{
	for(auto a = fontSizes.begin(); a != fontSizes.end(); a++)
	{
		glDeleteTextures(1, &atlases[*a].first);
		delete[] atlases[*a].second;
	}
	fontSizes.clear();
	atlases.clear();
}

bool util::setFont(std::string path)
{
	if(path == currentFont) return true;
	if(FT_New_Face(ft, path.c_str(), 0, &face) != 0) return false;

	currentFont = path;
	for(auto a = fontSizes.begin(); a != fontSizes.end(); a++)
	{
		FT_Set_Pixel_Sizes(face, 0, *a);

		delete[] atlases[*a].second;
		atlases[*a].second = new CharTrait[128];

		unsigned int texWidth = 0, texHeight = 0;
		FT_GlyphSlot g = face->glyph;
		for(int i = 32; i < 128; i++)
		{
			if(FT_Load_Char(face, i, FT_LOAD_RENDER))
			{
				*debugstream << "Loading character " << char(i) << " failed in font " << path << ".\n";
				continue;
			}

			texWidth += g->bitmap.width;
			if(texHeight < g->bitmap.rows) texHeight = g->bitmap.rows;
		}
		glDeleteTextures(1, &atlases[*a].first);
		glGenTextures(1, &atlases[*a].first);
		glBindTexture(GL_TEXTURE_2D, atlases[*a].first);
		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
		glActiveTexture(GL_TEXTURE0);
		glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
		glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, texWidth, texHeight, 0, GL_RED, GL_UNSIGNED_BYTE, 0);

		int x = 0;
		for(int i = 32; i < 128; i++)
		{
			if(FT_Load_Char(face, i, FT_LOAD_RENDER)) continue;

			glTexSubImage2D(GL_TEXTURE_2D, 0, x, 0, g->bitmap.width, g->bitmap.rows, GL_RED, GL_UNSIGNED_BYTE, g->bitmap.buffer);

			atlases[*a].second[i] = { float(g->advance.x) / 64 / screenWidth, float(g->advance.y) / 64 / screenHeight, short(g->bitmap.width), short(g->bitmap.rows), float(g->bitmap_left), float(g->bitmap_top), (float(g->bitmap.width) / texWidth), (float(g->bitmap.rows) / texHeight), float(x) / texWidth };

			x += g->bitmap.width;
		}
	}

	return true;
}

#include <iostream>

char util::renderText(float x, float y, int size, Color c, const std::string & text)
{
	//Get currently bound program:
	GLint currentProgram;
	glGetIntegerv(GL_CURRENT_PROGRAM, &currentProgram);

	//Create initial buffer:
	float points[] = { 0, 0, 0, 0, 0, 0, 0, 0 }; //Zero-initialize
	GLuint vbo = 0;
	glGenBuffers(1, &vbo);
	glBindBuffer(GL_ARRAY_BUFFER, vbo);
	glBufferData(GL_ARRAY_BUFFER, 8 * sizeof(float), points, GL_DYNAMIC_DRAW);

	float tpoints[] = { 0, 0, 0, 0, 0, 0, 0, 0 }; //Zero-initialize
	GLuint vbot = 0;
	glGenBuffers(1, &vbot);
	glBindBuffer(GL_ARRAY_BUFFER, vbot);
	glBufferData(GL_ARRAY_BUFFER, 8 * sizeof(float), tpoints, GL_DYNAMIC_DRAW);

	GLuint vao = 0;
	glGenVertexArrays(1, &vao);
	glBindVertexArray(vao);
	glBindBuffer(GL_ARRAY_BUFFER, vbo);
	glEnableVertexAttribArray(0);
	glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, NULL);
	glBindBuffer(GL_ARRAY_BUFFER, vbot);
	glEnableVertexAttribArray(1);
	glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 0, NULL);

	glUseProgram(shaderProgram);
	glUniform3fv(glGetUniformLocation(shaderProgram, "color"), 1, (GLfloat *)&c);
	glBindVertexArray(vao);
	glEnableVertexAttribArray(0);
	glEnableVertexAttribArray(1);

	addFontSize(size);
	CharTrait * charTraits = atlases[size].second;
	glBindTexture(GL_TEXTURE_2D, atlases[size].first);
	glActiveTexture(GL_TEXTURE0);

	//Skip blank characters, load the position:
	for(int a = 0; a < text.size(); a++)
	{
		CharTrait t = charTraits[text[a]];
		//if(t.bitmap_width == 0 || t.bitmap_rows == 0) continue;

		float left = x + float(t.bitmap_left) / screenWidth, top = y + float(t.bitmap_top) / screenHeight, right = left + (float(t.bitmap_width) / screenWidth), bottom = top - (float(t.bitmap_rows) / screenHeight);
		points[0] = left; points[1] = top; points[2] = right; points[3] = top; points[4] = left; points[5] = bottom; points[6] = right; points[7] = bottom;
		glBindBuffer(GL_ARRAY_BUFFER, vbo);
		glBufferData(GL_ARRAY_BUFFER, 8 * sizeof(float), points, GL_DYNAMIC_DRAW);
		tpoints[0] = t.texture_x; tpoints[1] = 0; tpoints[2] = t.texture_x + t.texture_width; tpoints[3] = 0; tpoints[4] = t.texture_x; tpoints[5] = t.texture_height; tpoints[6] = t.texture_x + t.texture_width; tpoints[7] = t.texture_height;
		glBindBuffer(GL_ARRAY_BUFFER, vbot);
		glBufferData(GL_ARRAY_BUFFER, 8 * sizeof(float), tpoints, GL_DYNAMIC_DRAW);

		glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);

		x += t.advance_x;
		y += t.advance_y;
	}

	glDeleteBuffers(1, &vbo);
	glDeleteBuffers(1, &vbot);
	glDeleteVertexArrays(1, &vao);

	//Set program back to previous program:
	glUseProgram(currentProgram);

	return 0;
}

void util::cleanup()
{
	glDeleteProgram(shaderProgram);
	util::removeAllFontSizes();
	FT_Done_FreeType(ft);
}
<commit_msg>Removed preprocessor definitions from removal of odd characters in shaders<commit_after>#include "OpenGL.hpp"

std::fstream * debugstream;

void util::initShaderHandler(std::fstream * ds)
{
	debugstream = ds;
}

bool util::shaderFromFile(GLuint shader, std::string filename, std::string shadername)
{
	std::fstream in;
	in.open(filename, std::ios_base::in);
	if(!in.is_open())
	{
		*debugstream << "File " << filename << " could not be opened, and consequently <<" << shadername << ">> couldn't be compiled." << std::endl;
		return false;
	}
	in.seekg(0, std::ios::end);
	int length = in.tellg();
	in.seekg(0, std::ios::beg);
	char * file = new char[length + 1];
	file[length] = 0;
	in.read(file, length);
	in.close();
	char * end = std::remove_if(file, file + length + 1, [](const char & c) -> bool { return !(isprint(c) || isspace(c)); });
	if(end != file + length + 1) *end = 0;
	end = NULL; //Not valid as soon as file is deleted. Putting inside the #ifdef for convenience.
	glShaderSource(shader, 1, (const char **)&file, NULL);
	glCompileShader(shader);
	delete[] file;
	//Check for proper compilation:
	GLint _compiled = 0;
	glGetShaderiv(shader, GL_COMPILE_STATUS, &_compiled);
	if(_compiled == GL_FALSE)
	{
		GLint length;
		GLchar* log;
		glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &length);
		log = new GLchar[length];
		glGetShaderInfoLog(shader, length, &length, log);
		*debugstream << "There was a problem with shader <<" << shadername << ">>\n" << log << "----------------------------------------" << std::endl;
		delete log;
		return false;
	}
	return true;
}

struct CharTrait
{
	float advance_x, advance_y;
	short bitmap_width, bitmap_rows;
	float bitmap_left, bitmap_top;
	float texture_width, texture_height;
	float texture_x;
};

std::set<int> fontSizes;
std::map< int, std::pair<GLuint, CharTrait * > > atlases;
std::string currentFont = "";

GLuint shaderProgram;
FT_Library ft;
FT_Face face;
int screenWidth, screenHeight;

void util::setScreenSize(int w, int h)
{
	screenWidth = w;
	screenHeight = h;
}

bool util::initText()
{
	shaderProgram = glCreateProgram();
	GLuint vs = glCreateShader(GL_VERTEX_SHADER);
	util::shaderFromFile(vs, "shaders/text/vertex.glsl", "Text Vertex Shader");
	GLuint fs = glCreateShader(GL_FRAGMENT_SHADER);
	util::shaderFromFile(fs, "shaders/text/fragment.glsl", "Text Fragment Shader");
	glAttachShader(shaderProgram, fs);
	glAttachShader(shaderProgram, vs);
	glLinkProgram(shaderProgram);
	glDetachShader(shaderProgram, fs);
	glDetachShader(shaderProgram, vs);
	glDeleteShader(vs);
	glDeleteShader(fs);

	glUniform1i(glGetUniformLocation(shaderProgram, "textureSampler"), 0);

	return FT_Init_FreeType(&ft) == 0;
}

void util::addFontSize(int s)
{
	if(std::count(fontSizes.begin(), fontSizes.end(), s)) return;

	fontSizes.insert(s);

	FT_Set_Pixel_Sizes(face, s, s);

	atlases[s] = { 0, 0 }; //Insert
	atlases[s].second = new CharTrait[128];
	unsigned int texWidth = 0, texHeight = 0;
	FT_GlyphSlot g = face->glyph;
	for(int i = 32; i < 128; i++)
	{
		if(FT_Load_Char(face, i, FT_LOAD_RENDER))
		{
			*debugstream << "Loading character " << char(i) << " failed in font " << currentFont << ".\n";
			continue;
		}

		texWidth += g->bitmap.width;
		if(texHeight < g->bitmap.rows) texHeight = g->bitmap.rows;
	}
	glDeleteTextures(1, &atlases[s].first);
	glGenTextures(1, &atlases[s].first);
	glBindTexture(GL_TEXTURE_2D, atlases[s].first);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
	glActiveTexture(GL_TEXTURE0);
	glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
	glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, texWidth, texHeight, 0, GL_RED, GL_UNSIGNED_BYTE, 0);

	int x = 0;
	for(int i = 32; i < 128; i++)
	{
		if(FT_Load_Char(face, i, FT_LOAD_RENDER)) continue;

		glTexSubImage2D(GL_TEXTURE_2D, 0, x, 0, g->bitmap.width, g->bitmap.rows, GL_RED, GL_UNSIGNED_BYTE, g->bitmap.buffer);

		atlases[s].second[i] = { float(g->advance.x) / 64 / screenWidth, float(g->advance.y) / 64 / screenHeight, short(g->bitmap.width), short(g->bitmap.rows), float(g->bitmap_left), float(g->bitmap_top), (float(g->bitmap.width) / texWidth), (float(g->bitmap.rows) / texHeight), float(x) / texWidth };

		x += g->bitmap.width;
	}
}

void util::removeAllFontSizes()
{
	for(auto a = fontSizes.begin(); a != fontSizes.end(); a++)
	{
		glDeleteTextures(1, &atlases[*a].first);
		delete[] atlases[*a].second;
	}
	fontSizes.clear();
	atlases.clear();
}

bool util::setFont(std::string path)
{
	if(path == currentFont) return true;
	if(FT_New_Face(ft, path.c_str(), 0, &face) != 0) return false;

	currentFont = path;
	for(auto a = fontSizes.begin(); a != fontSizes.end(); a++)
	{
		FT_Set_Pixel_Sizes(face, 0, *a);

		delete[] atlases[*a].second;
		atlases[*a].second = new CharTrait[128];

		unsigned int texWidth = 0, texHeight = 0;
		FT_GlyphSlot g = face->glyph;
		for(int i = 32; i < 128; i++)
		{
			if(FT_Load_Char(face, i, FT_LOAD_RENDER))
			{
				*debugstream << "Loading character " << char(i) << " failed in font " << path << ".\n";
				continue;
			}

			texWidth += g->bitmap.width;
			if(texHeight < g->bitmap.rows) texHeight = g->bitmap.rows;
		}
		glDeleteTextures(1, &atlases[*a].first);
		glGenTextures(1, &atlases[*a].first);
		glBindTexture(GL_TEXTURE_2D, atlases[*a].first);
		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
		glActiveTexture(GL_TEXTURE0);
		glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
		glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, texWidth, texHeight, 0, GL_RED, GL_UNSIGNED_BYTE, 0);

		int x = 0;
		for(int i = 32; i < 128; i++)
		{
			if(FT_Load_Char(face, i, FT_LOAD_RENDER)) continue;

			glTexSubImage2D(GL_TEXTURE_2D, 0, x, 0, g->bitmap.width, g->bitmap.rows, GL_RED, GL_UNSIGNED_BYTE, g->bitmap.buffer);

			atlases[*a].second[i] = { float(g->advance.x) / 64 / screenWidth, float(g->advance.y) / 64 / screenHeight, short(g->bitmap.width), short(g->bitmap.rows), float(g->bitmap_left), float(g->bitmap_top), (float(g->bitmap.width) / texWidth), (float(g->bitmap.rows) / texHeight), float(x) / texWidth };

			x += g->bitmap.width;
		}
	}

	return true;
}

#include <iostream>

char util::renderText(float x, float y, int size, Color c, const std::string & text)
{
	//Get currently bound program:
	GLint currentProgram;
	glGetIntegerv(GL_CURRENT_PROGRAM, &currentProgram);

	//Create initial buffer:
	float points[] = { 0, 0, 0, 0, 0, 0, 0, 0 }; //Zero-initialize
	GLuint vbo = 0;
	glGenBuffers(1, &vbo);
	glBindBuffer(GL_ARRAY_BUFFER, vbo);
	glBufferData(GL_ARRAY_BUFFER, 8 * sizeof(float), points, GL_DYNAMIC_DRAW);

	float tpoints[] = { 0, 0, 0, 0, 0, 0, 0, 0 }; //Zero-initialize
	GLuint vbot = 0;
	glGenBuffers(1, &vbot);
	glBindBuffer(GL_ARRAY_BUFFER, vbot);
	glBufferData(GL_ARRAY_BUFFER, 8 * sizeof(float), tpoints, GL_DYNAMIC_DRAW);

	GLuint vao = 0;
	glGenVertexArrays(1, &vao);
	glBindVertexArray(vao);
	glBindBuffer(GL_ARRAY_BUFFER, vbo);
	glEnableVertexAttribArray(0);
	glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, NULL);
	glBindBuffer(GL_ARRAY_BUFFER, vbot);
	glEnableVertexAttribArray(1);
	glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 0, NULL);

	glUseProgram(shaderProgram);
	glUniform3fv(glGetUniformLocation(shaderProgram, "color"), 1, (GLfloat *)&c);
	glBindVertexArray(vao);
	glEnableVertexAttribArray(0);
	glEnableVertexAttribArray(1);

	addFontSize(size);
	CharTrait * charTraits = atlases[size].second;
	glBindTexture(GL_TEXTURE_2D, atlases[size].first);
	glActiveTexture(GL_TEXTURE0);

	//Skip blank characters, load the position:
	for(int a = 0; a < text.size(); a++)
	{
		CharTrait t = charTraits[text[a]];
		//if(t.bitmap_width == 0 || t.bitmap_rows == 0) continue;

		float left = x + float(t.bitmap_left) / screenWidth, top = y + float(t.bitmap_top) / screenHeight, right = left + (float(t.bitmap_width) / screenWidth), bottom = top - (float(t.bitmap_rows) / screenHeight);
		points[0] = left; points[1] = top; points[2] = right; points[3] = top; points[4] = left; points[5] = bottom; points[6] = right; points[7] = bottom;
		glBindBuffer(GL_ARRAY_BUFFER, vbo);
		glBufferData(GL_ARRAY_BUFFER, 8 * sizeof(float), points, GL_DYNAMIC_DRAW);
		tpoints[0] = t.texture_x; tpoints[1] = 0; tpoints[2] = t.texture_x + t.texture_width; tpoints[3] = 0; tpoints[4] = t.texture_x; tpoints[5] = t.texture_height; tpoints[6] = t.texture_x + t.texture_width; tpoints[7] = t.texture_height;
		glBindBuffer(GL_ARRAY_BUFFER, vbot);
		glBufferData(GL_ARRAY_BUFFER, 8 * sizeof(float), tpoints, GL_DYNAMIC_DRAW);

		glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);

		x += t.advance_x;
		y += t.advance_y;
	}

	glDeleteBuffers(1, &vbo);
	glDeleteBuffers(1, &vbot);
	glDeleteVertexArrays(1, &vao);

	//Set program back to previous program:
	glUseProgram(currentProgram);

	return 0;
}

void util::cleanup()
{
	glDeleteProgram(shaderProgram);
	util::removeAllFontSizes();
	FT_Done_FreeType(ft);
}
<|endoftext|>


<commit_before>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: insys.cxx,v $
 *
 *  $Revision: 1.3 $
 *
 *  last change: $Author: obo $ $Date: 2006-09-17 09:20:22 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    This library is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *    Lesser General Public License for more details.
 *
 *    You should have received a copy of the GNU Lesser General Public
 *    License along with this library; if not, write to the Free Software
 *    Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/

// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_i18npool.hxx"

#if defined( WNT )

#include "inwnt.cxx"

#elif defined( MAC )

#include "inmac.cxx"

#elif defined( UNX )

#include "inunx.cxx"

#else

#error unknown platform

#endif
<commit_msg>INTEGRATION: CWS locales23 (1.3.54); FILE MERGED 2007/06/20 11:12:13 er 1.3.54.1: #i78464# remove MacOS9 specifics<commit_after>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: insys.cxx,v $
 *
 *  $Revision: 1.4 $
 *
 *  last change: $Author: rt $ $Date: 2007-07-03 14:03:43 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    This library is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *    Lesser General Public License for more details.
 *
 *    You should have received a copy of the GNU Lesser General Public
 *    License along with this library; if not, write to the Free Software
 *    Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/

// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_i18npool.hxx"

#if defined( WNT )

#include "inwnt.cxx"

#elif defined( UNX )

#include "inunx.cxx"

#else

#error unknown platform

#endif
<|endoftext|>


<commit_before>/*
  Stepper.cpp - - Stepper library for Wiring/Arduino - Version 0.4

  Original library     (0.1) by Tom Igoe.
  Two-wire modifications   (0.2) by Sebastian Gassner
  Combination version   (0.3) by Tom Igoe and David Mellis
  Bug fix for four-wire   (0.4) by Tom Igoe, bug fix from Noah Shibley

  Drives a unipolar or bipolar stepper motor using  2 wires or 4 wires

  When wiring multiple stepper motors to a microcontroller,
  you quickly run out of output pins, with each motor requiring 4 connections.

  By making use of the fact that at any time two of the four motor
  coils are the inverse  of the other two, the number of
  control connections can be reduced from 4 to 2.

  A slightly modified circuit around a Darlington transistor array or an L293 H-bridge
  connects to only 2 microcontroler pins, inverts the signals received,
  and delivers the 4 (2 plus 2 inverted ones) output signals required
  for driving a stepper motor.

  The sequence of control signals for 4 control wires is as follows:

  Step C0 C1 C2 C3
     1  1  0  1  0
     2  0  1  1  0
     3  0  1  0  1
     4  1  0  0  1

  The sequence of controls signals for 2 control wires is as follows
  (columns C1 and C2 from above):

  Step C0 C1
     1  0  1
     2  1  1
     3  1  0
     4  0  0

  The circuits can be found at

http://www.arduino.cc/en/Tutorial/Stepper

 */

#include "WProgram.h"
#include "Stepper.h"

/*
 * two-wire constructor.
 * Sets which wires should control the motor.
 */
Stepper::Stepper(int number_of_steps, int motor_pin_1, int motor_pin_2)
{
  this->step_number = 0;      // which step the motor is on
  this->speed = 0;        // the motor speed, in revolutions per minute
  this->direction = 0;      // motor direction
  this->last_step_time = 0;    // time stamp in ms of the last step taken
  this->number_of_steps = number_of_steps;    // total number of steps for this motor

  // Arduino pins for the motor control connection:
  this->motor_pin_1 = motor_pin_1;
  this->motor_pin_2 = motor_pin_2;

  // setup the pins on the microcontroller:
  pinMode(this->motor_pin_1, OUTPUT);
  pinMode(this->motor_pin_2, OUTPUT);

  // When there are only 2 pins, set the other two to 0:
  this->motor_pin_3 = 0;
  this->motor_pin_4 = 0;

  // pin_count is used by the stepMotor() method:
  this->pin_count = 2;
}

/*
 *   constructor for four-pin version
 *   Sets which wires should control the motor.
 */

Stepper::Stepper(int number_of_steps, int motor_pin_1, int motor_pin_2, int motor_pin_3, int motor_pin_4)
{
  this->step_number = 0;      // which step the motor is on
  this->speed = 0;        // the motor speed, in revolutions per minute
  this->direction = 0;      // motor direction
  this->last_step_time = 0;    // time stamp in ms of the last step taken
  this->number_of_steps = number_of_steps;    // total number of steps for this motor

  // Arduino pins for the motor control connection:
  this->motor_pin_1 = motor_pin_1;
  this->motor_pin_2 = motor_pin_2;
  this->motor_pin_3 = motor_pin_3;
  this->motor_pin_4 = motor_pin_4;

  // setup the pins on the microcontroller:
  pinMode(this->motor_pin_1, OUTPUT);
  pinMode(this->motor_pin_2, OUTPUT);
  pinMode(this->motor_pin_3, OUTPUT);
  pinMode(this->motor_pin_4, OUTPUT);

  // pin_count is used by the stepMotor() method:
  this->pin_count = 4;
}

/*
  Sets the speed in revs per minute

*/
void Stepper::setSpeed(long whatSpeed)
{
  this->step_delay = 60L * 1000L / this->number_of_steps / whatSpeed;
}

/*
  Moves the motor steps_to_move steps.  If the number is negative,
   the motor moves in the reverse direction.
 */
void Stepper::step(int steps_to_move)
{
  int steps_left = abs(steps_to_move);  // how many steps to take

  // determine direction based on whether steps_to_mode is + or -:
  if (steps_to_move > 0) {this->direction = 1;}
  if (steps_to_move < 0) {this->direction = 0;}

  // decrement the number of steps, moving one step each time:
  while(steps_left > 0) {
  // move only if the appropriate delay has passed:
  if (millis() - this->last_step_time >= this->step_delay) {
      // step the motor to step number 0, 1, 2, or 3:
      stepMotor(this->step_number % 4);
      // get the timeStamp of when you stepped:
      this->last_step_time = millis();
      // increment or decrement the step number,
      // depending on direction:
      if (this->direction == 1) {
        this->step_number++;
        if (this->step_number == this->number_of_steps) {
          this->step_number = 0;
        }
      }
      else {
        if (this->step_number == 0) {
          this->step_number = this->number_of_steps;
        }
        this->step_number--;
      }
      // decrement the steps left:
      steps_left--;
    }
  }
}

/*
 * Moves the motor forward or backwards.
 */
void Stepper::stepMotor(int thisStep)
{
  if (this->pin_count == 2) {
    switch (thisStep) {
      case 0: /* 01 */
      digitalWrite(motor_pin_1, LOW);
      digitalWrite(motor_pin_2, HIGH);
      break;
      case 1: /* 11 */
      digitalWrite(motor_pin_1, HIGH);
      digitalWrite(motor_pin_2, HIGH);
      break;
      case 2: /* 10 */
      digitalWrite(motor_pin_1, HIGH);
      digitalWrite(motor_pin_2, LOW);
      break;
      case 3: /* 00 */
      digitalWrite(motor_pin_1, LOW);
      digitalWrite(motor_pin_2, LOW);
      break;
    }
  }
  if (this->pin_count == 4) {
    switch (thisStep) {
      case 0:    // 1010
      digitalWrite(motor_pin_1, HIGH);
      digitalWrite(motor_pin_2, LOW);
      digitalWrite(motor_pin_3, HIGH);
      digitalWrite(motor_pin_4, LOW);
      break;
      case 1:    // 0110
      digitalWrite(motor_pin_1, LOW);
      digitalWrite(motor_pin_2, HIGH);
      digitalWrite(motor_pin_3, HIGH);
      digitalWrite(motor_pin_4, LOW);
      break;
      case 2:    //0101
      digitalWrite(motor_pin_1, LOW);
      digitalWrite(motor_pin_2, HIGH);
      digitalWrite(motor_pin_3, LOW);
      digitalWrite(motor_pin_4, HIGH);
      break;
      case 3:    //1001
      digitalWrite(motor_pin_1, HIGH);
      digitalWrite(motor_pin_2, LOW);
      digitalWrite(motor_pin_3, LOW);
      digitalWrite(motor_pin_4, HIGH);
      break;
    }
  }
}

/*
  version() returns the version of the library:
*/
int Stepper::version(void)
{
  return 4;
}
<commit_msg>Moving actual stepping to the end of the step() function so that the first step isn't in the wrong direction.<commit_after>/*
  Stepper.cpp - - Stepper library for Wiring/Arduino - Version 0.4

  Original library     (0.1) by Tom Igoe.
  Two-wire modifications   (0.2) by Sebastian Gassner
  Combination version   (0.3) by Tom Igoe and David Mellis
  Bug fix for four-wire   (0.4) by Tom Igoe, bug fix from Noah Shibley

  Drives a unipolar or bipolar stepper motor using  2 wires or 4 wires

  When wiring multiple stepper motors to a microcontroller,
  you quickly run out of output pins, with each motor requiring 4 connections.

  By making use of the fact that at any time two of the four motor
  coils are the inverse  of the other two, the number of
  control connections can be reduced from 4 to 2.

  A slightly modified circuit around a Darlington transistor array or an L293 H-bridge
  connects to only 2 microcontroler pins, inverts the signals received,
  and delivers the 4 (2 plus 2 inverted ones) output signals required
  for driving a stepper motor.

  The sequence of control signals for 4 control wires is as follows:

  Step C0 C1 C2 C3
     1  1  0  1  0
     2  0  1  1  0
     3  0  1  0  1
     4  1  0  0  1

  The sequence of controls signals for 2 control wires is as follows
  (columns C1 and C2 from above):

  Step C0 C1
     1  0  1
     2  1  1
     3  1  0
     4  0  0

  The circuits can be found at

http://www.arduino.cc/en/Tutorial/Stepper

 */

#include "WProgram.h"
#include "Stepper.h"

/*
 * two-wire constructor.
 * Sets which wires should control the motor.
 */
Stepper::Stepper(int number_of_steps, int motor_pin_1, int motor_pin_2)
{
  this->step_number = 0;      // which step the motor is on
  this->speed = 0;        // the motor speed, in revolutions per minute
  this->direction = 0;      // motor direction
  this->last_step_time = 0;    // time stamp in ms of the last step taken
  this->number_of_steps = number_of_steps;    // total number of steps for this motor

  // Arduino pins for the motor control connection:
  this->motor_pin_1 = motor_pin_1;
  this->motor_pin_2 = motor_pin_2;

  // setup the pins on the microcontroller:
  pinMode(this->motor_pin_1, OUTPUT);
  pinMode(this->motor_pin_2, OUTPUT);

  // When there are only 2 pins, set the other two to 0:
  this->motor_pin_3 = 0;
  this->motor_pin_4 = 0;

  // pin_count is used by the stepMotor() method:
  this->pin_count = 2;
}

/*
 *   constructor for four-pin version
 *   Sets which wires should control the motor.
 */

Stepper::Stepper(int number_of_steps, int motor_pin_1, int motor_pin_2, int motor_pin_3, int motor_pin_4)
{
  this->step_number = 0;      // which step the motor is on
  this->speed = 0;        // the motor speed, in revolutions per minute
  this->direction = 0;      // motor direction
  this->last_step_time = 0;    // time stamp in ms of the last step taken
  this->number_of_steps = number_of_steps;    // total number of steps for this motor

  // Arduino pins for the motor control connection:
  this->motor_pin_1 = motor_pin_1;
  this->motor_pin_2 = motor_pin_2;
  this->motor_pin_3 = motor_pin_3;
  this->motor_pin_4 = motor_pin_4;

  // setup the pins on the microcontroller:
  pinMode(this->motor_pin_1, OUTPUT);
  pinMode(this->motor_pin_2, OUTPUT);
  pinMode(this->motor_pin_3, OUTPUT);
  pinMode(this->motor_pin_4, OUTPUT);

  // pin_count is used by the stepMotor() method:
  this->pin_count = 4;
}

/*
  Sets the speed in revs per minute

*/
void Stepper::setSpeed(long whatSpeed)
{
  this->step_delay = 60L * 1000L / this->number_of_steps / whatSpeed;
}

/*
  Moves the motor steps_to_move steps.  If the number is negative,
   the motor moves in the reverse direction.
 */
void Stepper::step(int steps_to_move)
{
  int steps_left = abs(steps_to_move);  // how many steps to take

  // determine direction based on whether steps_to_mode is + or -:
  if (steps_to_move > 0) {this->direction = 1;}
  if (steps_to_move < 0) {this->direction = 0;}

  // decrement the number of steps, moving one step each time:
  while(steps_left > 0) {
  // move only if the appropriate delay has passed:
  if (millis() - this->last_step_time >= this->step_delay) {
      // get the timeStamp of when you stepped:
      this->last_step_time = millis();
      // increment or decrement the step number,
      // depending on direction:
      if (this->direction == 1) {
        this->step_number++;
        if (this->step_number == this->number_of_steps) {
          this->step_number = 0;
        }
      }
      else {
        if (this->step_number == 0) {
          this->step_number = this->number_of_steps;
        }
        this->step_number--;
      }
      // decrement the steps left:
      steps_left--;
      // step the motor to step number 0, 1, 2, or 3:
      stepMotor(this->step_number % 4);
    }
  }
}

/*
 * Moves the motor forward or backwards.
 */
void Stepper::stepMotor(int thisStep)
{
  if (this->pin_count == 2) {
    switch (thisStep) {
      case 0: /* 01 */
      digitalWrite(motor_pin_1, LOW);
      digitalWrite(motor_pin_2, HIGH);
      break;
      case 1: /* 11 */
      digitalWrite(motor_pin_1, HIGH);
      digitalWrite(motor_pin_2, HIGH);
      break;
      case 2: /* 10 */
      digitalWrite(motor_pin_1, HIGH);
      digitalWrite(motor_pin_2, LOW);
      break;
      case 3: /* 00 */
      digitalWrite(motor_pin_1, LOW);
      digitalWrite(motor_pin_2, LOW);
      break;
    }
  }
  if (this->pin_count == 4) {
    switch (thisStep) {
      case 0:    // 1010
      digitalWrite(motor_pin_1, HIGH);
      digitalWrite(motor_pin_2, LOW);
      digitalWrite(motor_pin_3, HIGH);
      digitalWrite(motor_pin_4, LOW);
      break;
      case 1:    // 0110
      digitalWrite(motor_pin_1, LOW);
      digitalWrite(motor_pin_2, HIGH);
      digitalWrite(motor_pin_3, HIGH);
      digitalWrite(motor_pin_4, LOW);
      break;
      case 2:    //0101
      digitalWrite(motor_pin_1, LOW);
      digitalWrite(motor_pin_2, HIGH);
      digitalWrite(motor_pin_3, LOW);
      digitalWrite(motor_pin_4, HIGH);
      break;
      case 3:    //1001
      digitalWrite(motor_pin_1, HIGH);
      digitalWrite(motor_pin_2, LOW);
      digitalWrite(motor_pin_3, LOW);
      digitalWrite(motor_pin_4, HIGH);
      break;
    }
  }
}

/*
  version() returns the version of the library:
*/
int Stepper::version(void)
{
  return 4;
}
<|endoftext|>


<commit_before>#include <mlopen/hipoc_program.hpp>
#include <mlopen/kernel.hpp>
#include <mlopen/errors.hpp>
#include <mlopen/replace.hpp>

#include <sstream>

#include <unistd.h>

namespace mlopen {

std::string quote(std::string s)
{
    return '"' + s + '"';
}

struct tmp_dir
{
    std::string name;
    tmp_dir(std::string prefix)
    {
        std::string s = "/tmp/miopen-" + std::move(prefix) + "-XXXXXX";
        std::vector<char> t(s.begin(), s.end());
        t.push_back(0);
        name = mkdtemp(t.data());
    }

    void execute(std::string exe, std::string args)
    {
        std::string cd = "cd " + this->name + "; ";
        std::string cmd = cd + exe + " " + args + " > /dev/null";
        // std::cout << cmd << std::endl;
        if (std::system(cmd.c_str()) != 0) MLOPEN_THROW("Can't execute " + cmd);
    }

    std::string path(std::string f)
    {
        return name + '/' + f;
    }

    ~tmp_dir()
    {
        if(!name.empty())
        {
            std::string cmd = "rm -rf " + name;
            if (std::system(cmd.c_str()) != 0) MLOPEN_THROW("Can't execute " + cmd);
        }
    }
};

void WriteFile(const std::string& content, const std::string& name)
{
    HIPOCProgram::FilePtr f{std::fopen(name.c_str(), "w")};
    if (std::fwrite(content.c_str(), 1, content.size(), f.get()) != content.size())
        MLOPEN_THROW("Failed to write to src file");
}

hipModulePtr CreateModule(const std::string& program_name, std::string params)
{
    tmp_dir dir{program_name};

    std::string src = GetKernelSrc(program_name);

    WriteFile(src, dir.path(program_name));

    std::string bin_file = dir.path(program_name) + ".bin";
    std::string hsaco_file = dir.path(program_name) + ".hsaco";
    std::string obj_file = dir.path(program_name) + ".obj";

#if 0
    execute(HIP_OC_COMPILER,
        "-march=hsail64 -mdevice=Fiji -output=" + bin_file +
        params + " " +
        src_file.name);

    execute("/usr/bin/objcopy",
        "-I elf32-little -j .text -O binary -S " + bin_file +
        " " + hsaco_file
    );
#else
    dir.execute(HIP_OC_COMPILER,
        "-march=hsail64 -mdevice=Fiji -save-temps=dump -nobin " +
        params + " " +
        program_name);
    dir.execute(HIP_OC_FINALIZER,
        "-target=8:0:3 -hsail dump_0_Fiji.hsail -output=" + hsaco_file
    );
#endif

    hipModule_t raw_m;
    auto status = hipModuleLoad(&raw_m, hsaco_file.c_str());
    hipModulePtr m{raw_m};
    if (status != hipSuccess) MLOPEN_THROW_HIP_STATUS(status, "Failed creating module");
    return m;
}

HIPOCProgram::HIPOCProgram()
{}
HIPOCProgram::HIPOCProgram(const std::string &program_name, std::string params)
{
    this->module = CreateModule(program_name, params);
}
}
<commit_msg>Adding the same flags / defines to aoc2 that the OCL runtime adds for calls to clBuildProgram(). This has been shown to significantly affect performance.<commit_after>#include <mlopen/hipoc_program.hpp>
#include <mlopen/kernel.hpp>
#include <mlopen/errors.hpp>
#include <mlopen/replace.hpp>

#include <sstream>

#include <unistd.h>

namespace mlopen {

std::string quote(std::string s)
{
    return '"' + s + '"';
}

struct tmp_dir
{
    std::string name;
    tmp_dir(std::string prefix)
    {
        std::string s = "/tmp/miopen-" + std::move(prefix) + "-XXXXXX";
        std::vector<char> t(s.begin(), s.end());
        t.push_back(0);
        name = mkdtemp(t.data());
    }

    void execute(std::string exe, std::string args)
    {
        std::string cd = "cd " + this->name + "; ";
        std::string cmd = cd + exe + " " + args + " > /dev/null";
        // std::cout << cmd << std::endl;
        if (std::system(cmd.c_str()) != 0) MLOPEN_THROW("Can't execute " + cmd);
    }

    std::string path(std::string f)
    {
        return name + '/' + f;
    }

    ~tmp_dir()
    {
        if(!name.empty())
        {
            std::string cmd = "rm -rf " + name;
            if (std::system(cmd.c_str()) != 0) MLOPEN_THROW("Can't execute " + cmd);
        }
    }
};

void WriteFile(const std::string& content, const std::string& name)
{
    HIPOCProgram::FilePtr f{std::fopen(name.c_str(), "w")};
    if (std::fwrite(content.c_str(), 1, content.size(), f.get()) != content.size())
        MLOPEN_THROW("Failed to write to src file");
}

hipModulePtr CreateModule(const std::string& program_name, std::string params)
{
    tmp_dir dir{program_name};

    std::string src = GetKernelSrc(program_name);

    WriteFile(src, dir.path(program_name));

    std::string bin_file = dir.path(program_name) + ".bin";
    std::string hsaco_file = dir.path(program_name) + ".hsaco";
    std::string obj_file = dir.path(program_name) + ".obj";

#if 1
    // Adding the same flags / defines to aoc2 that the OCL runtime adds for calls
    // to clBuildProgram(). This has been shown to significantly affect performance.
    params +=
      " "
      "-DCL_DEVICE_MAX_GLOBAL_VARIABLE_SIZE=2605857024 -DFP_FAST_FMA=1 "
      "-cl-denorms-are-zero -m64 -Dcl_khr_fp64=1 -Dcl_amd_fp64=1 "
      "-Dcl_khr_global_int32_base_atomics=1 -Dcl_khr_global_int32_extended_atomics=1 "
      "-Dcl_khr_local_int32_base_atomics=1 -Dcl_khr_local_int32_extended_atomics=1 "
      "-Dcl_khr_int64_base_atomics=1 -Dcl_khr_int64_extended_atomics=1 "
      "-Dcl_khr_3d_image_writes=1 -Dcl_khr_byte_addressable_store=1 -Dcl_khr_fp16=1 "
      "-Dcl_khr_gl_sharing=1 -Dcl_khr_gl_depth_images=1 "
      "-Dcl_amd_device_attribute_query=1 -Dcl_amd_vec3=1 -Dcl_amd_printf=1 "
      "-Dcl_amd_media_ops=1 -Dcl_amd_media_ops2=1 -Dcl_amd_popcnt=1 "
      "-Dcl_khr_image2d_from_buffer=1 -Dcl_khr_spir=1 -Dcl_khr_subgroups=1 "
      "-Dcl_khr_gl_event=1 -Dcl_khr_depth_images=1 -Dcl_khr_mipmap_image=1 "
      "-Dcl_khr_mipmap_image_writes=1"
      " ";
#endif

#if 0
    execute(HIP_OC_COMPILER,
        "-march=hsail64 -mdevice=Fiji -output=" + bin_file +
        params + " " +
        src_file.name);

    execute("/usr/bin/objcopy",
        "-I elf32-little -j .text -O binary -S " + bin_file +
        " " + hsaco_file
    );
#else
    dir.execute(HIP_OC_COMPILER,
        "-march=hsail64 -mdevice=Fiji -save-temps=dump -nobin " +
        params + " " +
        program_name);
    dir.execute(HIP_OC_FINALIZER,
        "-target=8:0:3 -hsail dump_0_Fiji.hsail -output=" + hsaco_file
    );
#endif

    hipModule_t raw_m;
    auto status = hipModuleLoad(&raw_m, hsaco_file.c_str());
    hipModulePtr m{raw_m};
    if (status != hipSuccess) MLOPEN_THROW_HIP_STATUS(status, "Failed creating module");
    return m;
}

HIPOCProgram::HIPOCProgram()
{}
HIPOCProgram::HIPOCProgram(const std::string &program_name, std::string params)
{
    this->module = CreateModule(program_name, params);
}
}
<|endoftext|>


<commit_before>// See LICENSE file for copyright and license details.

#include <cstdlib>
#include <cmath>
#include <cstring>
#include <cassert>
#include <ctime>
#include "core/core.h"

Core::Core()
  : mPathfinder(*this),
    mMap(V2i(20, 18))
{
  srand(time(nullptr));
  initUnitTypes();
  mPathfinder.cleanMap();
  cleanFow();
  initPlayers();
  initObstacles();
  initUnits();
  calculateFow();
}

Core::~Core() {
}

const std::list<Player*>& Core::players() {
  return mPlayers;
}

Event& Core::currentEvent() {
  return *mCurrentEvent;
}

const Player& Core::currentPlayer() {
  return *mCurrentPlayer;
}

Unit* Core::selectedUnit() {
  return mSelectedUnit;
}

std::list<Unit*>& Core::units() {
  return mUnits;
}

Pathfinder& Core::pathfinder() {
  return mPathfinder;
}

const Map& Core::map() const {
  return mMap;
}

Map& Core::map() {
  return mMap;
}

void Core::setSelectedUnit(Unit* unit) {
  mSelectedUnit = unit;
}

void Core::setCurrentEvent(Event* event) {
  mCurrentEvent = event;
}

void Core::setCurrentPlayer(Player* player) {
  mCurrentPlayer = player;
}

void Core::createLocalHuman(int id) {
  auto p = new Player;
  mPlayers.push_back(p);
  p->id = id;
  p->lastSeenEventID = HAVE_NOT_SEEN_ANY_EVENTS;
}

void Core::initLocalPlayers(std::vector<int> unitIDs) {
  for (int id : unitIDs) {
    createLocalHuman(id);
  }
  mCurrentPlayer = mPlayers.back();
}

bool Core::inboard(const V2i& p) const {
  return map().isInboard(p);
}

Tile& Core::tile(const V2i& p) {
  return map().tile(p);
}

int Core::getNewEventID() {
  if (!mEvents.empty()) {
    return mEvents.back()->id + 1;
  } else {
    return 0;
  }
}

void Core::refreshUnits(int playerID) {
  for (auto u : units()) {
    if (u->playerID == playerID) {
      u->actionPoints = getUnitType(u->typeID).actionPoints;
    }
  }
}

// Undo all events that this player have not seen yet
void Core::undoUnshownEvents() {
  if (mEvents.size() == 0) {
    return;
  }
  auto i = mEvents.end();
  --i;
  while (i != mEvents.begin()) {
    auto event = *i;
    if (event->id == mCurrentPlayer->lastSeenEventID) {
      break;
    }
    undoEvent(*event);
    --i;
  }
}

void Core::applyEvent(Event& e) {
  mCurrentPlayer->lastSeenEventID = e.id;
  e.apply(*this);
}

bool Core::isEventVisible(const Event& e) const {
  return e.isVisible(*this);
}

// TODO simplify
void Core::applyInvisibleEvents() {
  Event* e = getNextEventNode();
  while (e) {
    assert(e);
    if (!isEventVisible(*e)) {
      applyEvent(*e);
    } else {
      break;
    }
    e = getNext(mEvents, e);
    assert(e);
  }
}

// TODO: Called before getNextEvent
bool Core::unshownEventsLeft() {
  applyInvisibleEvents();
  if (mEvents.size() == 0) {
    return false;
  } else {
    auto e = mEvents.back();
    return e->id != mCurrentPlayer->lastSeenEventID;
  }
}

// Always called after applyInvisibleEvents
Event* Core::getNextEvent() {
  int id = mCurrentPlayer->lastSeenEventID; // shortcut
  assert(mEvents.size() > 0);
  if (id == HAVE_NOT_SEEN_ANY_EVENTS) {
    return mEvents.front();
  }
  for (auto e : mEvents) {
    if (e->id == id) {
      return getNext(mEvents, e);
    }
  }
  return nullptr;
}

void Core::addEvent(Event* e) {
  assert(e);
  e->id = getNewEventID();
  mEvents.push_back(e);
  // event2log(*e);
#if 0
  // TODO
  if (!isLocal) {
    sendEvent(e);
  }
#else
  // UNUSED(sendEvent);
#endif
}

bool Core::isLosClear(const V2i& from, const V2i& to) {
  Los los(from, to);
  for (V2i p = los.getNext(); !los.isFinished(); p = los.getNext()) {
    if (unitAt(p) || tile(p).obstacle) {
      return false;
    }
  }
  return true;
}

void Core::cleanFow() {
  V2i p;
  FOR_EACH_TILE(map(), p) {
    tile(p).fow = 0;
  }
}

void Core::calculateFow() {
  assert(mCurrentPlayer);
  cleanFow();
  V2i p;
  FOR_EACH_TILE(map(), p) {
    for (auto u : mUnits) {
      int maxDist = getUnitType(u->typeID).rangeOfVision;
      bool isPlayerOk = (u->playerID == mCurrentPlayer->id);
      bool isDistanceOk = (p.distance(u->pos) < maxDist);
      bool isLosOk = isLosClear(p, u->pos);
      if (isPlayerOk && isDistanceOk && isLosOk) {
        tile(p).fow++;
      }
    }
  }
}

Unit* Core::unitAt(const V2i& pos) {
  for (auto u : mUnits) {
    if (u->pos == pos) {
      return u;
    }
  }
  return nullptr;
}

Unit* Core::id2unit(int id) {
  for (auto u : mUnits) {
    if (u->id == id) {
      return u;
    }
  }
  return nullptr;
}

int Core::getNewUnitID() {
  if (mUnits.size() > 0) {
    auto lastUnit = mUnits.back();
    return lastUnit->id + 1;
  } else {
    return 0;
  }
}

void Core::addUnit(const V2i& p, int playerID) {
  auto u = new Unit;
  assert(inboard(p));
  assert(playerID >= 0 && playerID < 16);
  u->id = getNewUnitID();
  u->pos = p;
  u->playerID = playerID;
  u->dir = static_cast<Dir>(rnd(0, 6 - 1));
  u->typeID = rnd(0, (int)UnitTypeID::COUNT - 1);
  u->actionPoints = getUnitType(u->typeID).actionPoints;
  mUnits.push_back(u);
  calculateFow();
#if 0
  buildFowArray(&vaFogOfWar);
#endif
}

void Core::killUnit(Unit* u) {
  mUnits.remove(u);
  delete u;
  if (mSelectedUnit) {
    mPathfinder.fillMap(*mSelectedUnit);
    calculateFow();
#if 0
    buildWalkableArray(&vaWalkableMap);
    buildFowArray(&vaFogOfWar);
#endif
  }
}

void Core::shoot(Unit *shooter, Unit *target) {
  if (isLosClear(shooter->pos, target->pos)) {
    killUnit(target);
  }
}

void Core::initUnits() {
  mSelectedUnit = nullptr;
  for (int i = 0; i < 8; i++) {
    V2i p(rnd(0, map().size().x() - 1), rnd(0, map().size().y() - 1));
    if (!tile(p).obstacle && !unitAt(p)) {
      addUnit(p, rnd(0, 1));
    } else {
      i--;
    }
  }
}

void Core::initObstacles() {
  V2i p;
  FOR_EACH_TILE(map(), p) {
    tile(p).obstacle = ((rand() % 100) > 85);
  }
}

void Core::initPlayers() {
  initLocalPlayers({0, 1});
}

void Core::undoEvent(Event& e) {
  e.undo(*this);
}

// TODO: rename.
Event* Core::getNextEventNode() {
  int id = mCurrentPlayer->lastSeenEventID; // shortcut
  if (mEvents.size() == 0) {
    return nullptr;
  }
  if (id == HAVE_NOT_SEEN_ANY_EVENTS) {
    return mEvents.front();
  }
  // find last seen event
  for (auto e : mEvents) {
    if (e->id == id) {
      return getNext(mEvents, e);
    }
  }
  return nullptr; // if there is no event with that id
}

void Core::event2log(const Event& e) {
  UNUSED(e);
  // TODO
}

void Core::sendEvent(const Event& e) {
  UNUSED(e);
  // TODO
}
<commit_msg>core.cpp: Removed unneeded empty line<commit_after>// See LICENSE file for copyright and license details.

#include <cstdlib>
#include <cmath>
#include <cstring>
#include <cassert>
#include <ctime>
#include "core/core.h"

Core::Core()
  : mPathfinder(*this),
    mMap(V2i(20, 18))
{
  srand(time(nullptr));
  initUnitTypes();
  mPathfinder.cleanMap();
  cleanFow();
  initPlayers();
  initObstacles();
  initUnits();
  calculateFow();
}

Core::~Core() {
}

const std::list<Player*>& Core::players() {
  return mPlayers;
}

Event& Core::currentEvent() {
  return *mCurrentEvent;
}

const Player& Core::currentPlayer() {
  return *mCurrentPlayer;
}

Unit* Core::selectedUnit() {
  return mSelectedUnit;
}

std::list<Unit*>& Core::units() {
  return mUnits;
}

Pathfinder& Core::pathfinder() {
  return mPathfinder;
}

const Map& Core::map() const {
  return mMap;
}

Map& Core::map() {
  return mMap;
}

void Core::setSelectedUnit(Unit* unit) {
  mSelectedUnit = unit;
}

void Core::setCurrentEvent(Event* event) {
  mCurrentEvent = event;
}

void Core::setCurrentPlayer(Player* player) {
  mCurrentPlayer = player;
}

void Core::createLocalHuman(int id) {
  auto p = new Player;
  mPlayers.push_back(p);
  p->id = id;
  p->lastSeenEventID = HAVE_NOT_SEEN_ANY_EVENTS;
}

void Core::initLocalPlayers(std::vector<int> unitIDs) {
  for (int id : unitIDs) {
    createLocalHuman(id);
  }
  mCurrentPlayer = mPlayers.back();
}

bool Core::inboard(const V2i& p) const {
  return map().isInboard(p);
}

Tile& Core::tile(const V2i& p) {
  return map().tile(p);
}

int Core::getNewEventID() {
  if (!mEvents.empty()) {
    return mEvents.back()->id + 1;
  } else {
    return 0;
  }
}

void Core::refreshUnits(int playerID) {
  for (auto u : units()) {
    if (u->playerID == playerID) {
      u->actionPoints = getUnitType(u->typeID).actionPoints;
    }
  }
}

// Undo all events that this player have not seen yet
void Core::undoUnshownEvents() {
  if (mEvents.size() == 0) {
    return;
  }
  auto i = mEvents.end();
  --i;
  while (i != mEvents.begin()) {
    auto event = *i;
    if (event->id == mCurrentPlayer->lastSeenEventID) {
      break;
    }
    undoEvent(*event);
    --i;
  }
}

void Core::applyEvent(Event& e) {
  mCurrentPlayer->lastSeenEventID = e.id;
  e.apply(*this);
}

bool Core::isEventVisible(const Event& e) const {
  return e.isVisible(*this);
}

// TODO simplify
void Core::applyInvisibleEvents() {
  Event* e = getNextEventNode();
  while (e) {
    assert(e);
    if (!isEventVisible(*e)) {
      applyEvent(*e);
    } else {
      break;
    }
    e = getNext(mEvents, e);
    assert(e);
  }
}

// TODO: Called before getNextEvent
bool Core::unshownEventsLeft() {
  applyInvisibleEvents();
  if (mEvents.size() == 0) {
    return false;
  } else {
    auto e = mEvents.back();
    return e->id != mCurrentPlayer->lastSeenEventID;
  }
}

// Always called after applyInvisibleEvents
Event* Core::getNextEvent() {
  int id = mCurrentPlayer->lastSeenEventID; // shortcut
  assert(mEvents.size() > 0);
  if (id == HAVE_NOT_SEEN_ANY_EVENTS) {
    return mEvents.front();
  }
  for (auto e : mEvents) {
    if (e->id == id) {
      return getNext(mEvents, e);
    }
  }
  return nullptr;
}

void Core::addEvent(Event* e) {
  assert(e);
  e->id = getNewEventID();
  mEvents.push_back(e);
  // event2log(*e);
#if 0
  // TODO
  if (!isLocal) {
    sendEvent(e);
  }
#else
  // UNUSED(sendEvent);
#endif
}

bool Core::isLosClear(const V2i& from, const V2i& to) {
  Los los(from, to);
  for (V2i p = los.getNext(); !los.isFinished(); p = los.getNext()) {
    if (unitAt(p) || tile(p).obstacle) {
      return false;
    }
  }
  return true;
}

void Core::cleanFow() {
  V2i p;
  FOR_EACH_TILE(map(), p) {
    tile(p).fow = 0;
  }
}

void Core::calculateFow() {
  assert(mCurrentPlayer);
  cleanFow();
  V2i p;
  FOR_EACH_TILE(map(), p) {
    for (auto u : mUnits) {
      int maxDist = getUnitType(u->typeID).rangeOfVision;
      bool isPlayerOk = (u->playerID == mCurrentPlayer->id);
      bool isDistanceOk = (p.distance(u->pos) < maxDist);
      bool isLosOk = isLosClear(p, u->pos);
      if (isPlayerOk && isDistanceOk && isLosOk) {
        tile(p).fow++;
      }
    }
  }
}

Unit* Core::unitAt(const V2i& pos) {
  for (auto u : mUnits) {
    if (u->pos == pos) {
      return u;
    }
  }
  return nullptr;
}

Unit* Core::id2unit(int id) {
  for (auto u : mUnits) {
    if (u->id == id) {
      return u;
    }
  }
  return nullptr;
}

int Core::getNewUnitID() {
  if (mUnits.size() > 0) {
    auto lastUnit = mUnits.back();
    return lastUnit->id + 1;
  } else {
    return 0;
  }
}

void Core::addUnit(const V2i& p, int playerID) {
  auto u = new Unit;
  assert(inboard(p));
  assert(playerID >= 0 && playerID < 16);
  u->id = getNewUnitID();
  u->pos = p;
  u->playerID = playerID;
  u->dir = static_cast<Dir>(rnd(0, 6 - 1));
  u->typeID = rnd(0, (int)UnitTypeID::COUNT - 1);
  u->actionPoints = getUnitType(u->typeID).actionPoints;
  mUnits.push_back(u);
  calculateFow();
#if 0
  buildFowArray(&vaFogOfWar);
#endif
}

void Core::killUnit(Unit* u) {
  mUnits.remove(u);
  delete u;
  if (mSelectedUnit) {
    mPathfinder.fillMap(*mSelectedUnit);
    calculateFow();
#if 0
    buildWalkableArray(&vaWalkableMap);
    buildFowArray(&vaFogOfWar);
#endif
  }
}

void Core::shoot(Unit *shooter, Unit *target) {
  if (isLosClear(shooter->pos, target->pos)) {
    killUnit(target);
  }
}

void Core::initUnits() {
  mSelectedUnit = nullptr;
  for (int i = 0; i < 8; i++) {
    V2i p(rnd(0, map().size().x() - 1), rnd(0, map().size().y() - 1));
    if (!tile(p).obstacle && !unitAt(p)) {
      addUnit(p, rnd(0, 1));
    } else {
      i--;
    }
  }
}

void Core::initObstacles() {
  V2i p;
  FOR_EACH_TILE(map(), p) {
    tile(p).obstacle = ((rand() % 100) > 85);
  }
}

void Core::initPlayers() {
  initLocalPlayers({0, 1});
}

void Core::undoEvent(Event& e) {
  e.undo(*this);
}

// TODO: rename.
Event* Core::getNextEventNode() {
  int id = mCurrentPlayer->lastSeenEventID; // shortcut
  if (mEvents.size() == 0) {
    return nullptr;
  }
  if (id == HAVE_NOT_SEEN_ANY_EVENTS) {
    return mEvents.front();
  }
  // find last seen event
  for (auto e : mEvents) {
    if (e->id == id) {
      return getNext(mEvents, e);
    }
  }
  return nullptr; // if there is no event with that id
}

void Core::event2log(const Event& e) {
  UNUSED(e);
  // TODO
}

void Core::sendEvent(const Event& e) {
  UNUSED(e);
  // TODO
}
<|endoftext|>