<commit_before>#include "creader.h"
#include "../parser/cfiledecoder.h"
#include "../parser/ctextparser.h"
#include "settings/csettings.h"
#include "settings.h"
#include "assert/advanced_assert.h"
#include "cpausehandler.h"

#include <math.h>

#include <algorithm>
#include <map>
#include <iterator>

DISABLE_COMPILER_WARNINGS
#include <QDebug>
#include <QTime>
RESTORE_COMPILER_WARNINGS

CReader::CReader(ReaderInterface* interface) : _interface(interface)
{
	assert_r(_interface);

	CPauseHandler::instance().addOnPauseValuesChangedListener(this);

	_readingTimer.setSingleShot(true);
	QObject::connect(&_readingTimer, &QTimer::timeout, [this](){
		readNextFragment();
	});

	_speedWpm = CSettings().value(READER_READING_SPEED_SETTING, READER_READING_SPEED_DEFAULT).toUInt();
}

void CReader::load(const CStructuredText& text)
{
	resetAndStop();

	QTime timer;
	timer.start();
	_text = text;
	qDebug() << "Assigning the text took" << timer.elapsed() << "ms";
	timer.restart();
	updatePauseValues();
	qDebug() << "updatePauseValues took" << timer.elapsed() << "ms";

	auto stats = _text.stats();
	qDebug()
		<< "Stats:"
		<< "\n\tChapters:" << stats.chapterCount
		<< "\n\tParagraphs:" << stats.paragraphCount
		<< "\n\tWords:" << stats.wordCount

		<< "\n\tAvg. paragraphs per chapter:" << stats.avgParagrapsPerChapter
		<< "\n\tMax. paragraphs per chapter:" << stats.maxParagrapsPerChapter

		<< "\n\tAvg. words per paragraph:" << stats.avgWordsPerParagraph
		<< "\n\tMax. words per paragraph:" << stats.maxWordsPerParagraph;
}

bool CReader::loadFromFile(const QString& filePath)
{
	CTextParser parser;
	parser.setAddEmptyFragmentAfterSentence(_clearScreenAfterSentenceEnd);

	QTime timer;
	timer.start();
	load(parser.parse(CFileDecoder::readDataAndDecodeText(filePath)));
	qDebug() << "Loading the file" << filePath << "took" << QString::number(timer.elapsed() / 1000.0f, 'f', 1) << "seconds";

	if (!_text.empty())
	{
		_filePath = filePath;
		return true;
	}
	else
		return false;
}

void CReader::setClearScreenAfterSentenceEnd(bool clear)
{
	_clearScreenAfterSentenceEnd = clear;
}

void CReader::setLongWordPauseScaling(unsigned lengthThreshold, float scaleFactor)
{
	if (lengthThreshold != _longWordThreshold || scaleFactor != _longWordDelayScaleFactor)
	{
		_longWordThreshold = lengthThreshold;
		_longWordDelayScaleFactor = scaleFactor;

		updatePauseValues();
	}
}

CReader::State CReader::state() const
{
	return _state;
}

QString CReader::filePath() const
{
	return _filePath;
}

size_t CReader::position() const
{
	return _position;
}

long double CReader::progress() const
{
	const size_t numWords = _text.totalFragmentsCount();
	return numWords ? _position / (long double)numWords : 0.0;
}

size_t CReader::timeRemainingSeconds() const
{
	const size_t actualTimeMs = std::accumulate(_pauseForFragment.cbegin() + _position, _pauseForFragment.cend(), 0) / 1000;
	return actualTimeMs / 1000;
}

const CReader::ChapterProgress CReader::currentChapterProgress() const
{
	const auto chapter = _text.chapterByWordIndex(_position);
	if (chapter == _text.chapters().cend())
		return{ 0, 0 };

	const size_t chapterWordsRead = _position - chapter->firstFragmentNumber();
	return{ chapterWordsRead, chapter->wordCount() };
}

size_t CReader::currentChapterTimeRemainingSeconds() const
{
	const auto chapter = _text.chapterByWordIndex(_position);
	if (chapter == _text.chapters().cend())
		return 0;

	size_t timeMs = 0;
	for (size_t fragment = _position, lastChapterFragment = chapter->lastFragmentNumber(); fragment <= lastChapterFragment; ++fragment)
		timeMs += _pauseForFragment[fragment];

	return timeMs / 1000;
}

void CReader::updateInterface() const
{
	_interface->stateChanged(_state);
	_interface->updateDisplay(_position);
}

size_t CReader::totalNumWords() const
{
	return _text.totalFragmentsCount();
}

const CStructuredText& CReader::text() const
{
	return _text;
}

void CReader::resumeReading()
{
	_state = Reading;
	_interface->stateChanged(_state);
	readNextFragment();
}

void CReader::pauseReading()
{
	_readingTimer.stop();

	_state = Paused;
	_interface->stateChanged(_state);
}

void CReader::togglePause()
{
	if (_state == Reading)
		pauseReading();
	else
		resumeReading();
}

void CReader::resetAndStop()
{
	pauseReading();
	_position = 0;
	_currentWordRead = false;
	_interface->updateInfo();
}

void CReader::goToWord(size_t wordIndex)
{
	if (_position >= _text.totalFragmentsCount())
		return;

	_position = wordIndex;
	_interface->updateDisplay(_position);
	_interface->updateInfo();
	_currentWordRead = true;
}

void CReader::toPreviousChapter()
{
	goToWord(_text.previousChapterStartIndex(_position));
}

void CReader::toPreviousParagraph()
{
	goToWord(_text.previousParagraphStartIndex(_position));
}

void CReader::toNextParagraph()
{
	goToWord(_text.nextParagraphStartIndex(_position));
}

void CReader::toNextChapter()
{
	goToWord(_text.nextChapterStartIndex(_position));
}

size_t CReader::readingSpeed() const
{
	return _speedWpm;
}

void CReader::setReadingSpeed(size_t wpm)
{
	CSettings().setValue(READER_READING_SPEED_SETTING, (quint64)wpm);
	_speedWpm = wpm;
	updatePauseValues();
}

void CReader::readNextFragment()
{
	if (_position >= _text.totalFragmentsCount())
	{
		resetAndStop();
	}
	else if (_state == Reading)
	{
		if (_currentWordRead)
			++_position;
		else
			_currentWordRead = true;

		_interface->updateDisplay(_position);
		_interface->updateInfo();
		// Queue up the next word
		_readingTimer.start(_pauseForFragment[_position]);
	}
}

// Calculates the pause after the specific fragment in ms
size_t CReader::pauseForFragment(const TextFragment& fragment) const
{
	const float basePause = 60e3f / _speedWpm;
	const unsigned wordLength = (unsigned)fragment.word().length();

	const float pauseFactor = CPauseHandler::instance().pauseFactorForDelimiter(fragment.delimiter());
	const float longWordFactor = wordLength > _longWordThreshold ? pow(_longWordDelayScaleFactor, float(wordLength - _longWordThreshold)) : 1.0f;
	return (size_t)round(basePause * pauseFactor * longWordFactor);
}

// Recalculate all the pauses for the entire text
void CReader::updatePauseValues()
{
	_pauseForFragment.resize(_text.totalFragmentsCount());
	for (const IndexedFragment& fragment: _text)
		_pauseForFragment[fragment.fragmentIndex] = pauseForFragment(fragment.fragment);

#ifdef _DEBUG
	const size_t totalTime = std::accumulate(_pauseForFragment.begin(), _pauseForFragment.end(), 0) / 1000;
	if (totalTime > 0)
	{
		const size_t actualWPM = 60 * totalNumWords() / totalTime;
		qDebug() << "Actual WPM:" << actualWPM;
	}
#endif

	_interface->updateInfo();
}

void CReader::onPauseScalingValuesChanged()
{
	updatePauseValues();
}
<commit_msg>CReader::timeRemainingSeconds fixed<commit_after>#include "creader.h"
#include "../parser/cfiledecoder.h"
#include "../parser/ctextparser.h"
#include "settings/csettings.h"
#include "settings.h"
#include "assert/advanced_assert.h"
#include "cpausehandler.h"

#include <math.h>

#include <algorithm>
#include <map>
#include <iterator>

DISABLE_COMPILER_WARNINGS
#include <QDebug>
#include <QTime>
RESTORE_COMPILER_WARNINGS

CReader::CReader(ReaderInterface* interface) : _interface(interface)
{
	assert_r(_interface);

	CPauseHandler::instance().addOnPauseValuesChangedListener(this);

	_readingTimer.setSingleShot(true);
	QObject::connect(&_readingTimer, &QTimer::timeout, [this](){
		readNextFragment();
	});

	_speedWpm = CSettings().value(READER_READING_SPEED_SETTING, READER_READING_SPEED_DEFAULT).toUInt();
}

void CReader::load(const CStructuredText& text)
{
	resetAndStop();

	QTime timer;
	timer.start();
	_text = text;
	qDebug() << "Assigning the text took" << timer.elapsed() << "ms";
	timer.restart();
	updatePauseValues();
	qDebug() << "updatePauseValues took" << timer.elapsed() << "ms";

	auto stats = _text.stats();
	qDebug()
		<< "Stats:"
		<< "\n\tChapters:" << stats.chapterCount
		<< "\n\tParagraphs:" << stats.paragraphCount
		<< "\n\tWords:" << stats.wordCount

		<< "\n\tAvg. paragraphs per chapter:" << stats.avgParagrapsPerChapter
		<< "\n\tMax. paragraphs per chapter:" << stats.maxParagrapsPerChapter

		<< "\n\tAvg. words per paragraph:" << stats.avgWordsPerParagraph
		<< "\n\tMax. words per paragraph:" << stats.maxWordsPerParagraph;
}

bool CReader::loadFromFile(const QString& filePath)
{
	CTextParser parser;
	parser.setAddEmptyFragmentAfterSentence(_clearScreenAfterSentenceEnd);

	QTime timer;
	timer.start();
	load(parser.parse(CFileDecoder::readDataAndDecodeText(filePath)));
	qDebug() << "Loading the file" << filePath << "took" << QString::number(timer.elapsed() / 1000.0f, 'f', 1) << "seconds";

	if (!_text.empty())
	{
		_filePath = filePath;
		return true;
	}
	else
		return false;
}

void CReader::setClearScreenAfterSentenceEnd(bool clear)
{
	_clearScreenAfterSentenceEnd = clear;
}

void CReader::setLongWordPauseScaling(unsigned lengthThreshold, float scaleFactor)
{
	if (lengthThreshold != _longWordThreshold || scaleFactor != _longWordDelayScaleFactor)
	{
		_longWordThreshold = lengthThreshold;
		_longWordDelayScaleFactor = scaleFactor;

		updatePauseValues();
	}
}

CReader::State CReader::state() const
{
	return _state;
}

QString CReader::filePath() const
{
	return _filePath;
}

size_t CReader::position() const
{
	return _position;
}

long double CReader::progress() const
{
	const size_t numWords = _text.totalFragmentsCount();
	return numWords ? _position / (long double)numWords : 0.0;
}

size_t CReader::timeRemainingSeconds() const
{
	const size_t actualTimeMs = std::accumulate(_pauseForFragment.cbegin() + _position, _pauseForFragment.cend(), 0);
	return actualTimeMs / 1000;
}

const CReader::ChapterProgress CReader::currentChapterProgress() const
{
	const auto chapter = _text.chapterByWordIndex(_position);
	if (chapter == _text.chapters().cend())
		return{ 0, 0 };

	const size_t chapterWordsRead = _position - chapter->firstFragmentNumber();
	return{ chapterWordsRead, chapter->wordCount() };
}

size_t CReader::currentChapterTimeRemainingSeconds() const
{
	const auto chapter = _text.chapterByWordIndex(_position);
	if (chapter == _text.chapters().cend())
		return 0;

	size_t timeMs = 0;
	for (size_t fragment = _position, lastChapterFragment = chapter->lastFragmentNumber(); fragment <= lastChapterFragment; ++fragment)
		timeMs += _pauseForFragment[fragment];

	return timeMs / 1000;
}

void CReader::updateInterface() const
{
	_interface->stateChanged(_state);
	_interface->updateDisplay(_position);
}

size_t CReader::totalNumWords() const
{
	return _text.totalFragmentsCount();
}

const CStructuredText& CReader::text() const
{
	return _text;
}

void CReader::resumeReading()
{
	_state = Reading;
	_interface->stateChanged(_state);
	readNextFragment();
}

void CReader::pauseReading()
{
	_readingTimer.stop();

	_state = Paused;
	_interface->stateChanged(_state);
}

void CReader::togglePause()
{
	if (_state == Reading)
		pauseReading();
	else
		resumeReading();
}

void CReader::resetAndStop()
{
	pauseReading();
	_position = 0;
	_currentWordRead = false;
	_interface->updateInfo();
}

void CReader::goToWord(size_t wordIndex)
{
	if (_position >= _text.totalFragmentsCount())
		return;

	_position = wordIndex;
	_interface->updateDisplay(_position);
	_interface->updateInfo();
	_currentWordRead = true;
}

void CReader::toPreviousChapter()
{
	goToWord(_text.previousChapterStartIndex(_position));
}

void CReader::toPreviousParagraph()
{
	goToWord(_text.previousParagraphStartIndex(_position));
}

void CReader::toNextParagraph()
{
	goToWord(_text.nextParagraphStartIndex(_position));
}

void CReader::toNextChapter()
{
	goToWord(_text.nextChapterStartIndex(_position));
}

size_t CReader::readingSpeed() const
{
	return _speedWpm;
}

void CReader::setReadingSpeed(size_t wpm)
{
	CSettings().setValue(READER_READING_SPEED_SETTING, (quint64)wpm);
	_speedWpm = wpm;
	updatePauseValues();
}

void CReader::readNextFragment()
{
	if (_position >= _text.totalFragmentsCount())
	{
		resetAndStop();
	}
	else if (_state == Reading)
	{
		if (_currentWordRead)
			++_position;
		else
			_currentWordRead = true;

		_interface->updateDisplay(_position);
		_interface->updateInfo();
		// Queue up the next word
		_readingTimer.start(_pauseForFragment[_position]);
	}
}

// Calculates the pause after the specific fragment in ms
size_t CReader::pauseForFragment(const TextFragment& fragment) const
{
	const float basePause = 60e3f / _speedWpm;
	const unsigned wordLength = (unsigned)fragment.word().length();

	const float pauseFactor = CPauseHandler::instance().pauseFactorForDelimiter(fragment.delimiter());
	const float longWordFactor = wordLength > _longWordThreshold ? pow(_longWordDelayScaleFactor, float(wordLength - _longWordThreshold)) : 1.0f;
	return (size_t)round(basePause * pauseFactor * longWordFactor);
}

// Recalculate all the pauses for the entire text
void CReader::updatePauseValues()
{
	_pauseForFragment.resize(_text.totalFragmentsCount());
	for (const IndexedFragment& fragment: _text)
		_pauseForFragment[fragment.fragmentIndex] = pauseForFragment(fragment.fragment);

#ifdef _DEBUG
	const size_t totalTime = std::accumulate(_pauseForFragment.begin(), _pauseForFragment.end(), 0) / 1000;
	if (totalTime > 0)
	{
		const size_t actualWPM = 60 * totalNumWords() / totalTime;
		qDebug() << "Actual WPM:" << actualWPM;
	}
#endif

	_interface->updateInfo();
}

void CReader::onPauseScalingValuesChanged()
{
	updatePauseValues();
}
<|endoftext|>


<commit_before>#ifndef UDR_PACKAGE_HPP
#define UDR_PACKAGE_HPP
#pragma once

#include <boost/variant/variant.hpp>
#include <string>
#include <vector>

namespace udr
{
    template <typename N, typename V>
    struct package
    {
        N name;
        V version;
        std::string location;
    };
    typedef std::vector<std::string> emessages_type;
    template <typename N, typename V>
    using result_type = boost::variant<
        emessages_type,
        std::vector<package<N, V> > >;
}

#endif // UDR_PACKAGE_HPP
<commit_msg>Add parts necessary for version relation to package<commit_after>#ifndef UDR_PACKAGE_HPP
#define UDR_PACKAGE_HPP
#pragma once

#include <boost/variant/variant.hpp>
#include <string>
#include <vector>
#include <unordered_map>

namespace udr
{

    template <typename N, typename V> class spec;

    template <
        typename N,
        typename V,
        typename L = std::string>
    struct package
    {
        N name;
        V version;
        // Provides can be used by a repo implementation to present the location
        // assigned to this package and present it with differerent name/version
        // pairs, provided in this `provides` map.
        std::unordered_map<N,V> provides;
        std::unique_ptr<spec<N,V>> requirements;
        L location;
    };
    typedef std::vector<std::string> emessages_type;
    template <typename N, typename V, typename L = std::string>
    using result_type = boost::variant<
        emessages_type,
        std::vector<package<N,V,L>>
        >;
}

#endif // UDR_PACKAGE_HPP
<|endoftext|>


<commit_before>#include "physics.hpp"
#include <glm/glm.hpp>

namespace Physics
{
    // Compute the cross product AB x AC
    f32 CrossProduct(const glm::vec2& pointA, const glm::vec2& pointB, const glm::vec2& pointC)
    {
        glm::vec2 AB = pointB - pointA;
        glm::vec2 AC = pointC - pointA;
        f32 cross = AB.x * AC.y - AB.y * AC.x;
        return cross;
    }

    bool IsLineSegmentsIntersecting(const glm::vec2& line1p1, const glm::vec2& line1p2, const glm::vec2& line2p1, const glm::vec2& line2p2, raycast_collision * collision)
    {
        //bool lines_intersect = false;
        bool segments_intersect = false;
        glm::vec2 intersection;
        glm::vec2 close_p1;
        glm::vec2 close_p2;

        // Get the segments' parameters.
        float dx12 = line1p2.x - line1p1.x;
        float dy12 = line1p2.y - line1p1.y;
        float dx34 = line2p2.x - line2p1.x;
        float dy34 = line2p2.y - line2p1.y;

        // Solve for t1 and t2
        float denominator = (dy12 * dx34 - dx12 * dy34);

        float t1 =
            ((line1p1.x - line2p1.x) * dy34 + (line2p1.y - line1p1.y) * dx34)
            / denominator;
        if (glm::isinf(t1))
        {
            // The lines are parallel (or close enough to it).
            //lines_intersect = false;
            segments_intersect = false;
            const float fnan = nanf("");
            intersection = glm::vec2(fnan, fnan);
            close_p1 = glm::vec2(fnan, fnan);
            close_p2 = glm::vec2(fnan, fnan);
            if (collision)
                collision->intersection = intersection;

            return segments_intersect;
        }
        //lines_intersect = true;

        float t2 =
            ((line2p1.x - line1p1.x) * dy12 + (line1p1.y - line2p1.y) * dx12)
            / -denominator;

        // Find the point of intersection.
        intersection = glm::vec2(line1p1.x + dx12 * t1, line1p1.y + dy12 * t1);
        if (collision)
            collision->intersection = intersection;

        // The segments intersect if t1 and t2 are between 0 and 1.
        segments_intersect =
            ((t1 >= 0) && (t1 <= 1) &&
            (t2 >= 0) && (t2 <= 1));

        // Find the closest points on the segments.
        if (t1 < 0)
        {
            t1 = 0;
        }
        else if (t1 > 1)
        {
            t1 = 1;
        }

        if (t2 < 0)
        {
            t2 = 0;
        }
        else if (t2 > 1)
        {
            t2 = 1;
        }

        close_p1 = glm::vec2(line1p1.x + dx12 * t1, line1p1.y + dy12 * t1);
        close_p2 = glm::vec2(line2p1.x + dx34 * t2, line2p1.y + dy34 * t2);

        return segments_intersect;
    }

    // Compute the dot product AB . BC
    f32 DotProduct(const glm::vec2& pointA, const glm::vec2& pointB, const glm::vec2& pointC)
    {
        glm::vec2 AB = pointB - pointA;
        glm::vec2 BC = pointC - pointB;
        return glm::dot(AB, BC);
    }

    f32 LineToPointDistance(const glm::vec2& pointA, const glm::vec2& pointB, const glm::vec2& pointC)
    {
        const f32 dot1 = DotProduct(pointA, pointB, pointC);
        if (dot1 > 0.0f)
        {
            return glm::distance(pointB, pointC);
        }

        const f32 dot2 = DotProduct(pointB, pointA, pointC);
        if (dot2 > 0.0f)
        {
            return glm::distance(pointA, pointC);
        }

        const f32 dist = CrossProduct(pointA, pointB, pointC) / glm::distance(pointA, pointB);
        return glm::abs(dist);
    }

    bool IsPointInTriangle(const glm::vec2& triPointA, const glm::vec2& triPointB, const glm::vec2& triPointC, const glm::vec2& point)
    {
        const bool b1 = CrossProduct(point, triPointA, triPointB) < 0.0f;
        const bool b2 = CrossProduct(point, triPointB, triPointC) < 0.0f;
        const bool b3 = CrossProduct(point, triPointC, triPointA) < 0.0f;
        return (b1 == b2) && (b2 == b3);
    }

    bool IsPointInThickLine(const glm::vec2& pointA, const glm::vec2& pointB, const glm::vec2& pointC, f32 width)
    {
        const f32 dist = LineToPointDistance(pointA, pointB, pointC);
        if (dist < width / 2.0f)
        {
            return true;
        }
        return false;
    }
}
<commit_msg>remove dead parts of IsLineSegmentsIntersecting<commit_after>#include "physics.hpp"
#include <glm/glm.hpp>

namespace Physics
{
    // Compute the cross product AB x AC
    f32 CrossProduct(const glm::vec2& pointA, const glm::vec2& pointB, const glm::vec2& pointC)
    {
        glm::vec2 AB = pointB - pointA;
        glm::vec2 AC = pointC - pointA;
        f32 cross = AB.x * AC.y - AB.y * AC.x;
        return cross;
    }

    bool IsLineSegmentsIntersecting(const glm::vec2& line1p1, const glm::vec2& line1p2, const glm::vec2& line2p1, const glm::vec2& line2p2, raycast_collision * collision)
    {
        bool segments_intersect = false;
        glm::vec2 intersection;

        // Get the segments' parameters.
        float dx12 = line1p2.x - line1p1.x;
        float dy12 = line1p2.y - line1p1.y;
        float dx34 = line2p2.x - line2p1.x;
        float dy34 = line2p2.y - line2p1.y;

        // Solve for t1 and t2
        float denominator = (dy12 * dx34 - dx12 * dy34);

        float t1 = ((line1p1.x - line2p1.x) * dy34 + (line2p1.y - line1p1.y) * dx34) / denominator;
        if (glm::isinf(t1))
        {
            // The lines are parallel (or close enough to it).
            //lines_intersect = false;
            segments_intersect = false;
            const float fnan = nanf("");
            intersection = glm::vec2(fnan, fnan);
            if (collision)
            {
                collision->intersection = intersection;
            }
            return segments_intersect;
        }

        float t2 = ((line2p1.x - line1p1.x) * dy12 + (line1p1.y - line2p1.y) * dx12) / -denominator;

        // Find the point of intersection.
        intersection = glm::vec2(line1p1.x + dx12 * t1, line1p1.y + dy12 * t1);
        if (collision)
        {
            collision->intersection = intersection;
        }

        // The segments intersect if t1 and t2 are between 0 and 1.
        segments_intersect = ((t1 >= 0) && (t1 <= 1) && (t2 >= 0) && (t2 <= 1));

        // Find the closest points on the segments.
        if (t1 < 0)
        {
            t1 = 0;
        }
        else if (t1 > 1)
        {
            t1 = 1;
        }

        if (t2 < 0)
        {
            t2 = 0;
        }
        else if (t2 > 1)
        {
            t2 = 1;
        }

        return segments_intersect;
    }

    // Compute the dot product AB . BC
    f32 DotProduct(const glm::vec2& pointA, const glm::vec2& pointB, const glm::vec2& pointC)
    {
        glm::vec2 AB = pointB - pointA;
        glm::vec2 BC = pointC - pointB;
        return glm::dot(AB, BC);
    }

    f32 LineToPointDistance(const glm::vec2& pointA, const glm::vec2& pointB, const glm::vec2& pointC)
    {
        const f32 dot1 = DotProduct(pointA, pointB, pointC);
        if (dot1 > 0.0f)
        {
            return glm::distance(pointB, pointC);
        }

        const f32 dot2 = DotProduct(pointB, pointA, pointC);
        if (dot2 > 0.0f)
        {
            return glm::distance(pointA, pointC);
        }

        const f32 dist = CrossProduct(pointA, pointB, pointC) / glm::distance(pointA, pointB);
        return glm::abs(dist);
    }

    bool IsPointInTriangle(const glm::vec2& triPointA, const glm::vec2& triPointB, const glm::vec2& triPointC, const glm::vec2& point)
    {
        const bool b1 = CrossProduct(point, triPointA, triPointB) < 0.0f;
        const bool b2 = CrossProduct(point, triPointB, triPointC) < 0.0f;
        const bool b3 = CrossProduct(point, triPointC, triPointA) < 0.0f;
        return (b1 == b2) && (b2 == b3);
    }

    bool IsPointInThickLine(const glm::vec2& pointA, const glm::vec2& pointB, const glm::vec2& pointC, f32 width)
    {
        const f32 dist = LineToPointDistance(pointA, pointB, pointC);
        if (dist < width / 2.0f)
        {
            return true;
        }
        return false;
    }
}
<|endoftext|>


<commit_before>#include "process.h"

using namespace vm;

namespace {

unsigned
mangledSize(int8_t c)
{
  switch (c) {
  case '_':
  case ';':
  case '[':
    return 2;

  case '$':
    return 6;

  default:
    return 1;
  }
}

unsigned
mangle(int8_t c, char* dst)
{
  switch (c) {
  case '/':
    dst[0] = '_';
    return 1;

  case '_':
    dst[0] = '_';
    dst[1] = '1';
    return 2;

  case ';':
    dst[0] = '_';
    dst[1] = '2';
    return 2;

  case '[':
    dst[0] = '_';
    dst[1] = '3';
    return 2;

  case '$':
    memcpy(dst, "_00024", 6);
    return 6;

  default:
    dst[0] = c;
    return 1;
  }
}

unsigned
jniNameLength(Thread* t, object method, bool decorate)
{
  unsigned size = 5;

  object className = ::className(t, methodClass(t, method));
  for (unsigned i = 0; i < byteArrayLength(t, className) - 1; ++i) {
    size += mangledSize(byteArrayBody(t, className, i));
  }

  ++ size;

  object methodName = ::methodName(t, method);
  for (unsigned i = 0; i < byteArrayLength(t, methodName) - 1; ++i) {
    size += mangledSize(byteArrayBody(t, methodName, i));
  }

  if (decorate) {
    size += 2;

    object methodSpec = ::methodSpec(t, method);
    for (unsigned i = 1; i < byteArrayLength(t, methodSpec) - 1
           and byteArrayBody(t, methodSpec, i) != ')'; ++i)
    {
      size += mangledSize(byteArrayBody(t, methodSpec, i));
    }
  }

  return size;
}

void
makeJNIName(Thread* t, char* name, object method, bool decorate)
{
  memcpy(name, "Java_", 5);
  name += 5;

  object className = ::className(t, methodClass(t, method));
  for (unsigned i = 0; i < byteArrayLength(t, className) - 1; ++i) {
    name += mangle(byteArrayBody(t, className, i), name);
  }

  *(name++) = '_';

  object methodName = ::methodName(t, method);
  for (unsigned i = 0; i < byteArrayLength(t, methodName) - 1; ++i) {
    name += mangle(byteArrayBody(t, methodName, i), name);
  }

  if (decorate) {
    *(name++) = '_';
    *(name++) = '_';

    object methodSpec = ::methodSpec(t, method);
    for (unsigned i = 1; i < byteArrayLength(t, methodSpec) - 1
           and byteArrayBody(t, methodSpec, i) != ')'; ++i)
    {
      name += mangle(byteArrayBody(t, methodSpec, i), name);
    }
  }

  *(name++) = 0;
}

void*
resolveNativeMethod(Thread* t, const char* undecorated, const char* decorated)
{
  for (System::Library* lib = t->m->libraries; lib; lib = lib->next()) {
    void* p = lib->resolve(undecorated);
    if (p) {
      return p;
    } else {
      p = lib->resolve(decorated);
      if (p) {
        return p;
      }
    }
  }

  return 0;
}

} // namespace

namespace vm {

void*
resolveNativeMethod2(Thread* t, object method)
{
  unsigned undecoratedSize = jniNameLength(t, method, false);
  char undecorated[undecoratedSize + 5]; // extra 5 is for code below
  makeJNIName(t, undecorated, method, false);

  unsigned decoratedSize = jniNameLength(t, method, true);
  char decorated[decoratedSize + 5]; // extra 5 is for code below
  makeJNIName(t, decorated, method, true);

  void* p = ::resolveNativeMethod(t, undecorated, decorated);
  if (p) {
    return p;
  }

#ifdef __MINGW32__
  // on windows, we also try the _%s@%d variant, since the SWT
  // libraries use it.
  unsigned footprint = methodParameterFootprint(t, method) + 1;
  if (methodFlags(t, method) & ACC_STATIC) {
    ++ footprint;
  }

  snprintf(undecorated + undecoratedSize - 1, 5, "@%d",
           footprint * BytesPerWord);

  snprintf(decorated + decoratedSize - 1, 5, "@%d",
           footprint * BytesPerWord);

  p = ::resolveNativeMethod(t, undecorated, decorated);
  if (p) {
    return p;
  }
#endif

  return 0;
}

ExceptionHandler*
findExceptionHandler(Thread* t, object method, unsigned ip)
{
  PROTECT(t, method);

  object eht = codeExceptionHandlerTable(t, methodCode(t, method));

  if (eht) {
    for (unsigned i = 0; i < exceptionHandlerTableLength(t, eht); ++i) {
      ExceptionHandler* eh = exceptionHandlerTableBody(t, eht, i);

      if (ip - 1 >= exceptionHandlerStart(eh)
          and ip - 1 < exceptionHandlerEnd(eh))
      {
        object catchType = 0;
        if (exceptionHandlerCatchType(eh)) {
          object e = t->exception;
          t->exception = 0;
          PROTECT(t, e);

          PROTECT(t, eht);
          catchType = resolveClassInPool
            (t, codePool(t, methodCode(t, method)),
             exceptionHandlerCatchType(eh) - 1);

          if (catchType) {
            eh = exceptionHandlerTableBody(t, eht, i);
            t->exception = e;
          } else {
            // can't find what we're supposed to catch - move on.
            continue;
          }
        }

        if (catchType == 0 or instanceOf(t, catchType, t->exception)) {
          return eh;
        }
      }
    }
  }

  return 0;
}

int
findLineNumber(Thread* t, object method, unsigned ip)
{
  if (methodFlags(t, method) & ACC_NATIVE) {
    return NativeLine;
  }

  // our parameter indicates the instruction following the one we care
  // about, so we back up first:
  -- ip;

  object code = methodCode(t, method);
  object lnt = codeLineNumberTable(t, code);
  if (lnt) {
    unsigned bottom = 0;
    unsigned top = lineNumberTableLength(t, lnt);
    for (unsigned span = top - bottom; span; span = top - bottom) {
      unsigned middle = bottom + (span / 2);
      LineNumber* ln = lineNumberTableBody(t, lnt, middle);

      if (ip >= lineNumberIp(ln)
          and (middle + 1 == lineNumberTableLength(t, lnt)
               or ip < lineNumberIp(lineNumberTableBody(t, lnt, middle + 1))))
      {
        return lineNumberLine(ln);
      } else if (ip < lineNumberIp(ln)) {
        top = middle;
      } else if (ip > lineNumberIp(ln)) {
        bottom = middle + 1;
      }
    }

    abort(t);
  } else {
    return UnknownLine;
  }
}

} // namespace vm
<commit_msg>fix recent regression in native method lookup on Windows<commit_after>#include "process.h"

using namespace vm;

namespace {

unsigned
mangledSize(int8_t c)
{
  switch (c) {
  case '_':
  case ';':
  case '[':
    return 2;

  case '$':
    return 6;

  default:
    return 1;
  }
}

unsigned
mangle(int8_t c, char* dst)
{
  switch (c) {
  case '/':
    dst[0] = '_';
    return 1;

  case '_':
    dst[0] = '_';
    dst[1] = '1';
    return 2;

  case ';':
    dst[0] = '_';
    dst[1] = '2';
    return 2;

  case '[':
    dst[0] = '_';
    dst[1] = '3';
    return 2;

  case '$':
    memcpy(dst, "_00024", 6);
    return 6;

  default:
    dst[0] = c;
    return 1;
  }
}

unsigned
jniNameLength(Thread* t, object method, bool decorate)
{
  unsigned size = 5;

  object className = ::className(t, methodClass(t, method));
  for (unsigned i = 0; i < byteArrayLength(t, className) - 1; ++i) {
    size += mangledSize(byteArrayBody(t, className, i));
  }

  ++ size;

  object methodName = ::methodName(t, method);
  for (unsigned i = 0; i < byteArrayLength(t, methodName) - 1; ++i) {
    size += mangledSize(byteArrayBody(t, methodName, i));
  }

  if (decorate) {
    size += 2;

    object methodSpec = ::methodSpec(t, method);
    for (unsigned i = 1; i < byteArrayLength(t, methodSpec) - 1
           and byteArrayBody(t, methodSpec, i) != ')'; ++i)
    {
      size += mangledSize(byteArrayBody(t, methodSpec, i));
    }
  }

  return size;
}

void
makeJNIName(Thread* t, char* name, object method, bool decorate)
{
  memcpy(name, "Java_", 5);
  name += 5;

  object className = ::className(t, methodClass(t, method));
  for (unsigned i = 0; i < byteArrayLength(t, className) - 1; ++i) {
    name += mangle(byteArrayBody(t, className, i), name);
  }

  *(name++) = '_';

  object methodName = ::methodName(t, method);
  for (unsigned i = 0; i < byteArrayLength(t, methodName) - 1; ++i) {
    name += mangle(byteArrayBody(t, methodName, i), name);
  }

  if (decorate) {
    *(name++) = '_';
    *(name++) = '_';

    object methodSpec = ::methodSpec(t, method);
    for (unsigned i = 1; i < byteArrayLength(t, methodSpec) - 1
           and byteArrayBody(t, methodSpec, i) != ')'; ++i)
    {
      name += mangle(byteArrayBody(t, methodSpec, i), name);
    }
  }

  *(name++) = 0;
}

void*
resolveNativeMethod(Thread* t, const char* undecorated, const char* decorated)
{
  for (System::Library* lib = t->m->libraries; lib; lib = lib->next()) {
    void* p = lib->resolve(undecorated);
    if (p) {
      return p;
    } else {
      p = lib->resolve(decorated);
      if (p) {
        return p;
      }
    }
  }

  return 0;
}

} // namespace

namespace vm {

void*
resolveNativeMethod2(Thread* t, object method)
{
  unsigned undecoratedSize = jniNameLength(t, method, false);
  char undecorated[undecoratedSize + 1 + 6]; // extra 6 is for code below
  makeJNIName(t, undecorated + 1, method, false);

  unsigned decoratedSize = jniNameLength(t, method, true);
  char decorated[decoratedSize + 1 + 6]; // extra 6 is for code below
  makeJNIName(t, decorated + 1, method, true);

  void* p = ::resolveNativeMethod(t, undecorated + 1, decorated + 1);
  if (p) {
    return p;
  }

#ifdef __MINGW32__
  // on windows, we also try the _%s@%d variant, since the SWT
  // libraries use it.
  unsigned footprint = methodParameterFootprint(t, method) + 1;
  if (methodFlags(t, method) & ACC_STATIC) {
    ++ footprint;
  }

  *undecorated = '_';
  snprintf(undecorated + undecoratedSize + 1, 5, "@%d",
           footprint * BytesPerWord);

  *decorated = '_';
  snprintf(decorated + decoratedSize + 1, 5, "@%d",
           footprint * BytesPerWord);

  p = ::resolveNativeMethod(t, undecorated, decorated);
  if (p) {
    return p;
  }
#endif

  return 0;
}

ExceptionHandler*
findExceptionHandler(Thread* t, object method, unsigned ip)
{
  PROTECT(t, method);

  object eht = codeExceptionHandlerTable(t, methodCode(t, method));

  if (eht) {
    for (unsigned i = 0; i < exceptionHandlerTableLength(t, eht); ++i) {
      ExceptionHandler* eh = exceptionHandlerTableBody(t, eht, i);

      if (ip - 1 >= exceptionHandlerStart(eh)
          and ip - 1 < exceptionHandlerEnd(eh))
      {
        object catchType = 0;
        if (exceptionHandlerCatchType(eh)) {
          object e = t->exception;
          t->exception = 0;
          PROTECT(t, e);

          PROTECT(t, eht);
          catchType = resolveClassInPool
            (t, codePool(t, methodCode(t, method)),
             exceptionHandlerCatchType(eh) - 1);

          if (catchType) {
            eh = exceptionHandlerTableBody(t, eht, i);
            t->exception = e;
          } else {
            // can't find what we're supposed to catch - move on.
            continue;
          }
        }

        if (catchType == 0 or instanceOf(t, catchType, t->exception)) {
          return eh;
        }
      }
    }
  }

  return 0;
}

int
findLineNumber(Thread* t, object method, unsigned ip)
{
  if (methodFlags(t, method) & ACC_NATIVE) {
    return NativeLine;
  }

  // our parameter indicates the instruction following the one we care
  // about, so we back up first:
  -- ip;

  object code = methodCode(t, method);
  object lnt = codeLineNumberTable(t, code);
  if (lnt) {
    unsigned bottom = 0;
    unsigned top = lineNumberTableLength(t, lnt);
    for (unsigned span = top - bottom; span; span = top - bottom) {
      unsigned middle = bottom + (span / 2);
      LineNumber* ln = lineNumberTableBody(t, lnt, middle);

      if (ip >= lineNumberIp(ln)
          and (middle + 1 == lineNumberTableLength(t, lnt)
               or ip < lineNumberIp(lineNumberTableBody(t, lnt, middle + 1))))
      {
        return lineNumberLine(ln);
      } else if (ip < lineNumberIp(ln)) {
        top = middle;
      } else if (ip > lineNumberIp(ln)) {
        bottom = middle + 1;
      }
    }

    abort(t);
  } else {
    return UnknownLine;
  }
}

} // namespace vm
<|endoftext|>


<commit_before>#define PTR_MAP_ENABLE_MULTI_MAP 1

typedef u32 MapIndex;

struct MapFindResult {
	MapIndex hash_index;
	MapIndex entry_prev;
	MapIndex entry_index;
};

enum : MapIndex { MAP_SENTINEL = ~(MapIndex)0 };

template <typename K, typename V>
struct PtrMapEntry {
	static_assert(sizeof(K) == sizeof(void *), "Key size must be pointer size");

	u32      hash;
	MapIndex next;
	K        key;
	V        value;
};

template <typename K, typename V>
struct PtrMap {
	Slice<MapIndex>           hashes;
	Array<PtrMapEntry<K, V> > entries;
};

u32 ptr_map_hash_key(void const *key) {
	// TODO(bill): Improve ptr_map_hash_key
	return fnv32a(&key, gb_size_of(key));
}
u32 ptr_map_hash_key(uintptr key) {
	// TODO(bill): Improve ptr_map_hash_key
	return fnv32a(&key, gb_size_of(key));
}

template <typename K, typename V> void map_init             (PtrMap<K, V> *h, gbAllocator a, isize capacity = 16);
template <typename K, typename V> void map_destroy          (PtrMap<K, V> *h);
template <typename K, typename V> V *  map_get              (PtrMap<K, V> *h, K key);
template <typename K, typename V> void map_set              (PtrMap<K, V> *h, K key, V const &value);
template <typename K, typename V> void map_remove           (PtrMap<K, V> *h, K key);
template <typename K, typename V> void map_clear            (PtrMap<K, V> *h);
template <typename K, typename V> void map_grow             (PtrMap<K, V> *h);
template <typename K, typename V> void map_rehash           (PtrMap<K, V> *h, isize new_count);
template <typename K, typename V> void map_reserve          (PtrMap<K, V> *h, isize cap);

#if PTR_MAP_ENABLE_MULTI_MAP
// Mutlivalued map procedure
template <typename K, typename V> PtrMapEntry<K, V> * multi_map_find_first(PtrMap<K, V> *h, K key);
template <typename K, typename V> PtrMapEntry<K, V> * multi_map_find_next (PtrMap<K, V> *h, PtrMapEntry<K, V> *e);

template <typename K, typename V> isize multi_map_count     (PtrMap<K, V> *h, K key);
template <typename K, typename V> void  multi_map_get_all   (PtrMap<K, V> *h, K key, V *items);
template <typename K, typename V> void  multi_map_insert    (PtrMap<K, V> *h, K key, V const &value);
template <typename K, typename V> void  multi_map_remove    (PtrMap<K, V> *h, K key, PtrMapEntry<K, V> *e);
template <typename K, typename V> void  multi_map_remove_all(PtrMap<K, V> *h, K key);
#endif

template <typename K, typename V>
gb_inline void map_init(PtrMap<K, V> *h, gbAllocator a, isize capacity) {
	capacity = next_pow2_isize(capacity);
	slice_init(&h->hashes,  a, capacity);
	array_init(&h->entries, a, 0, capacity);
	for (isize i = 0; i < capacity; i++) {
		h->hashes.data[i] = MAP_SENTINEL;
	}
}

template <typename K, typename V>
gb_inline void map_destroy(PtrMap<K, V> *h) {
	slice_free(&h->hashes, h->entries.allocator);
	array_free(&h->entries);
}

template <typename K, typename V>
gb_internal MapIndex map__add_entry(PtrMap<K, V> *h, K key) {
	PtrMapEntry<K, V> e = {};
	e.hash = ptr_map_hash_key(key);
	e.key = key;
	e.next = MAP_SENTINEL;
	array_add(&h->entries, e);
	return cast(MapIndex)(h->entries.count-1);
}

template <typename K, typename V>
gb_internal MapFindResult map__find(PtrMap<K, V> *h, K key) {
	MapFindResult fr = {MAP_SENTINEL, MAP_SENTINEL, MAP_SENTINEL};
	if (h->hashes.count == 0) {
		return fr;
	}
	u32 hash = ptr_map_hash_key(key);
	fr.hash_index = cast(MapIndex)(hash & (h->hashes.count-1));
	fr.entry_index = h->hashes.data[fr.hash_index];
	while (fr.entry_index != MAP_SENTINEL) {
		if (h->entries.data[fr.entry_index].key == key) {
			return fr;
		}
		fr.entry_prev = fr.entry_index;
		fr.entry_index = h->entries.data[fr.entry_index].next;
	}
	return fr;
}

template <typename K, typename V>
gb_internal MapFindResult map__find_from_entry(PtrMap<K, V> *h, PtrMapEntry<K, V> *e) {
	MapFindResult fr = {MAP_SENTINEL, MAP_SENTINEL, MAP_SENTINEL};
	if (h->hashes.count == 0) {
		return fr;
	}
	fr.hash_index  = cast(MapIndex)(e->hash & (h->hashes.count-1));
	fr.entry_index = h->hashes.data[fr.hash_index];
	while (fr.entry_index != MAP_SENTINEL) {
		if (&h->entries.data[fr.entry_index] == e) {
			return fr;
		}
		fr.entry_prev = fr.entry_index;
		fr.entry_index = h->entries.data[fr.entry_index].next;
	}
	return fr;
}

template <typename K, typename V>
gb_internal b32 map__full(PtrMap<K, V> *h) {
	return 0.75f * h->hashes.count <= h->entries.count;
}

template <typename K, typename V>
gb_inline void map_grow(PtrMap<K, V> *h) {
	isize new_count = gb_max(h->hashes.count<<1, 16);
	map_rehash(h, new_count);
}

template <typename K, typename V>
void map_reset_entries(PtrMap<K, V> *h) {
	for (isize i = 0; i < h->hashes.count; i++) {
		h->hashes.data[i] = MAP_SENTINEL;
	}
	for (isize i = 0; i < h->entries.count; i++) {
		MapFindResult fr;
		PtrMapEntry<K, V> *e = &h->entries.data[i];
		e->next = MAP_SENTINEL;
		fr = map__find_from_entry(h, e);
		if (fr.entry_prev == MAP_SENTINEL) {
			h->hashes[fr.hash_index] = cast(MapIndex)i;
		} else {
			h->entries[fr.entry_prev].next = cast(MapIndex)i;
		}
	}
}

template <typename K, typename V>
void map_reserve(PtrMap<K, V> *h, isize cap) {
	array_reserve(&h->entries, cap);
	if (h->entries.count*2 < h->hashes.count) {
		return;
	}
	slice_resize(&h->hashes, h->entries.allocator, cap*2);
	map_reset_entries(h);
}

template <typename K, typename V>
void map_rehash(PtrMap<K, V> *h, isize new_count) {
	map_reserve(h, new_count);
}

template <typename K, typename V>
V *map_get(PtrMap<K, V> *h, K key) {
	isize index = map__find(h, key).entry_index;
	if (index != MAP_SENTINEL) {
		return &h->entries.data[index].value;
	}
	return nullptr;
}

template <typename K, typename V>
V &map_must_get(PtrMap<K, V> *h, K key) {
	isize index = map__find(h, key).entry_index;
	GB_ASSERT(index != MAP_SENTINEL);
	return h->entries.data[index].value;
}

template <typename K, typename V>
void map_set(PtrMap<K, V> *h, K key, V const &value) {
	MapIndex index;
	MapFindResult fr;
	if (h->hashes.count == 0) {
		map_grow(h);
	}
	fr = map__find(h, key);
	if (fr.entry_index != MAP_SENTINEL) {
		index = fr.entry_index;
	} else {
		index = map__add_entry(h, key);
		if (fr.entry_prev != MAP_SENTINEL) {
			h->entries.data[fr.entry_prev].next = index;
		} else {
			h->hashes.data[fr.hash_index] = index;
		}
	}
	h->entries.data[index].value = value;

	if (map__full(h)) {
		map_grow(h);
	}
}

template <typename K, typename V>
void map__erase(PtrMap<K, V> *h, MapFindResult const &fr) {
	MapFindResult last;
	if (fr.entry_prev == MAP_SENTINEL) {
		h->hashes.data[fr.hash_index] = h->entries.data[fr.entry_index].next;
	} else {
		h->entries.data[fr.entry_prev].next = h->entries.data[fr.entry_index].next;
	}
	if (fr.entry_index == h->entries.count-1) {
		array_pop(&h->entries);
		return;
	}
	h->entries.data[fr.entry_index] = h->entries.data[h->entries.count-1];
	array_pop(&h->entries);

	last = map__find(h, h->entries.data[fr.entry_index].key);
	if (last.entry_prev != MAP_SENTINEL) {
		h->entries.data[last.entry_prev].next = fr.entry_index;
	} else {
		h->hashes.data[last.hash_index] = fr.entry_index;
	}
}

template <typename K, typename V>
void map_remove(PtrMap<K, V> *h, K key) {
	MapFindResult fr = map__find(h, key);
	if (fr.entry_index != MAP_SENTINEL) {
		map__erase(h, fr);
	}
}

template <typename K, typename V>
gb_inline void map_clear(PtrMap<K, V> *h) {
	array_clear(&h->entries);
	for (isize i = 0; i < h->hashes.count; i++) {
		h->hashes.data[i] = MAP_SENTINEL;
	}
}

#if PTR_MAP_ENABLE_MULTI_MAP
template <typename K, typename V>
PtrMapEntry<K, V> *multi_map_find_first(PtrMap<K, V> *h, K key) {
	isize i = map__find(h, key).entry_index;
	if (i == MAP_SENTINEL) {
		return nullptr;
	}
	return &h->entries.data[i];
}

template <typename K, typename V>
PtrMapEntry<K, V> *multi_map_find_next(PtrMap<K, V> *h, PtrMapEntry<K, V> *e) {
	isize i = e->next;
	while (i != MAP_SENTINEL) {
		if (h->entries.data[i].key == e->key) {
			return &h->entries.data[i];
		}
		i = h->entries.data[i].next;
	}
	return nullptr;
}

template <typename K, typename V>
isize multi_map_count(PtrMap<K, V> *h, K key) {
	isize count = 0;
	PtrMapEntry<K, V> *e = multi_map_find_first(h, key);
	while (e != nullptr) {
		count++;
		e = multi_map_find_next(h, e);
	}
	return count;
}

template <typename K, typename V>
void multi_map_get_all(PtrMap<K, V> *h, K key, V *items) {
	isize i = 0;
	PtrMapEntry<K, V> *e = multi_map_find_first(h, key);
	while (e != nullptr) {
		items[i++] = e->value;
		e = multi_map_find_next(h, e);
	}
}

template <typename K, typename V>
void multi_map_insert(PtrMap<K, V> *h, K key, V const &value) {
	MapFindResult fr;
	MapIndex i;
	if (h->hashes.count == 0) {
		map_grow(h);
	}
	// Make
	fr = map__find(h, key);
	i = map__add_entry(h, key);
	if (fr.entry_prev == MAP_SENTINEL) {
		h->hashes.data[fr.hash_index] = i;
	} else {
		h->entries.data[fr.entry_prev].next = i;
	}
	h->entries.data[i].next = fr.entry_index;
	h->entries.data[i].value = value;
	// Grow if needed
	if (map__full(h)) {
		map_grow(h);
	}
}

template <typename K, typename V>
void multi_map_remove(PtrMap<K, V> *h, K key, PtrMapEntry<K, V> *e) {
	MapFindResult fr = map__find_from_entry(h, e);
	if (fr.entry_index != MAP_SENTINEL) {
		map__erase(h, fr);
	}
}

template <typename K, typename V>
void multi_map_remove_all(PtrMap<K, V> *h, K key) {
	while (map_get(h, key) != nullptr) {
		map_remove(h, key);
	}
}
#endif
<commit_msg>Be more correct with `MapIndex` usage<commit_after>#define PTR_MAP_ENABLE_MULTI_MAP 1

typedef u32 MapIndex;

struct MapFindResult {
	MapIndex hash_index;
	MapIndex entry_prev;
	MapIndex entry_index;
};

enum : MapIndex { MAP_SENTINEL = ~(MapIndex)0 };

template <typename K, typename V>
struct PtrMapEntry {
	static_assert(sizeof(K) == sizeof(void *), "Key size must be pointer size");

	u32      hash;
	MapIndex next;
	K        key;
	V        value;
};

template <typename K, typename V>
struct PtrMap {
	Slice<MapIndex>           hashes;
	Array<PtrMapEntry<K, V> > entries;
};

u32 ptr_map_hash_key(void const *key) {
	// TODO(bill): Improve ptr_map_hash_key
	return fnv32a(&key, gb_size_of(key));
}
u32 ptr_map_hash_key(uintptr key) {
	// TODO(bill): Improve ptr_map_hash_key
	return fnv32a(&key, gb_size_of(key));
}

template <typename K, typename V> void map_init             (PtrMap<K, V> *h, gbAllocator a, isize capacity = 16);
template <typename K, typename V> void map_destroy          (PtrMap<K, V> *h);
template <typename K, typename V> V *  map_get              (PtrMap<K, V> *h, K key);
template <typename K, typename V> void map_set              (PtrMap<K, V> *h, K key, V const &value);
template <typename K, typename V> void map_remove           (PtrMap<K, V> *h, K key);
template <typename K, typename V> void map_clear            (PtrMap<K, V> *h);
template <typename K, typename V> void map_grow             (PtrMap<K, V> *h);
template <typename K, typename V> void map_rehash           (PtrMap<K, V> *h, isize new_count);
template <typename K, typename V> void map_reserve          (PtrMap<K, V> *h, isize cap);

#if PTR_MAP_ENABLE_MULTI_MAP
// Mutlivalued map procedure
template <typename K, typename V> PtrMapEntry<K, V> * multi_map_find_first(PtrMap<K, V> *h, K key);
template <typename K, typename V> PtrMapEntry<K, V> * multi_map_find_next (PtrMap<K, V> *h, PtrMapEntry<K, V> *e);

template <typename K, typename V> isize multi_map_count     (PtrMap<K, V> *h, K key);
template <typename K, typename V> void  multi_map_get_all   (PtrMap<K, V> *h, K key, V *items);
template <typename K, typename V> void  multi_map_insert    (PtrMap<K, V> *h, K key, V const &value);
template <typename K, typename V> void  multi_map_remove    (PtrMap<K, V> *h, K key, PtrMapEntry<K, V> *e);
template <typename K, typename V> void  multi_map_remove_all(PtrMap<K, V> *h, K key);
#endif

template <typename K, typename V>
gb_inline void map_init(PtrMap<K, V> *h, gbAllocator a, isize capacity) {
	capacity = next_pow2_isize(capacity);
	slice_init(&h->hashes,  a, capacity);
	array_init(&h->entries, a, 0, capacity);
	for (isize i = 0; i < capacity; i++) {
		h->hashes.data[i] = MAP_SENTINEL;
	}
}

template <typename K, typename V>
gb_inline void map_destroy(PtrMap<K, V> *h) {
	slice_free(&h->hashes, h->entries.allocator);
	array_free(&h->entries);
}

template <typename K, typename V>
gb_internal MapIndex map__add_entry(PtrMap<K, V> *h, K key) {
	PtrMapEntry<K, V> e = {};
	e.hash = ptr_map_hash_key(key);
	e.key = key;
	e.next = MAP_SENTINEL;
	array_add(&h->entries, e);
	return cast(MapIndex)(h->entries.count-1);
}

template <typename K, typename V>
gb_internal MapFindResult map__find(PtrMap<K, V> *h, K key) {
	MapFindResult fr = {MAP_SENTINEL, MAP_SENTINEL, MAP_SENTINEL};
	if (h->hashes.count == 0) {
		return fr;
	}
	u32 hash = ptr_map_hash_key(key);
	fr.hash_index = cast(MapIndex)(hash & (h->hashes.count-1));
	fr.entry_index = h->hashes.data[fr.hash_index];
	while (fr.entry_index != MAP_SENTINEL) {
		if (h->entries.data[fr.entry_index].key == key) {
			return fr;
		}
		fr.entry_prev = fr.entry_index;
		fr.entry_index = h->entries.data[fr.entry_index].next;
	}
	return fr;
}

template <typename K, typename V>
gb_internal MapFindResult map__find_from_entry(PtrMap<K, V> *h, PtrMapEntry<K, V> *e) {
	MapFindResult fr = {MAP_SENTINEL, MAP_SENTINEL, MAP_SENTINEL};
	if (h->hashes.count == 0) {
		return fr;
	}
	fr.hash_index  = cast(MapIndex)(e->hash & (h->hashes.count-1));
	fr.entry_index = h->hashes.data[fr.hash_index];
	while (fr.entry_index != MAP_SENTINEL) {
		if (&h->entries.data[fr.entry_index] == e) {
			return fr;
		}
		fr.entry_prev = fr.entry_index;
		fr.entry_index = h->entries.data[fr.entry_index].next;
	}
	return fr;
}

template <typename K, typename V>
gb_internal b32 map__full(PtrMap<K, V> *h) {
	return 0.75f * h->hashes.count <= h->entries.count;
}

template <typename K, typename V>
gb_inline void map_grow(PtrMap<K, V> *h) {
	isize new_count = gb_max(h->hashes.count<<1, 16);
	map_rehash(h, new_count);
}

template <typename K, typename V>
void map_reset_entries(PtrMap<K, V> *h) {
	for (isize i = 0; i < h->hashes.count; i++) {
		h->hashes.data[i] = MAP_SENTINEL;
	}
	for (isize i = 0; i < h->entries.count; i++) {
		MapFindResult fr;
		PtrMapEntry<K, V> *e = &h->entries.data[i];
		e->next = MAP_SENTINEL;
		fr = map__find_from_entry(h, e);
		if (fr.entry_prev == MAP_SENTINEL) {
			h->hashes[fr.hash_index] = cast(MapIndex)i;
		} else {
			h->entries[fr.entry_prev].next = cast(MapIndex)i;
		}
	}
}

template <typename K, typename V>
void map_reserve(PtrMap<K, V> *h, isize cap) {
	array_reserve(&h->entries, cap);
	if (h->entries.count*2 < h->hashes.count) {
		return;
	}
	slice_resize(&h->hashes, h->entries.allocator, cap*2);
	map_reset_entries(h);
}

template <typename K, typename V>
void map_rehash(PtrMap<K, V> *h, isize new_count) {
	map_reserve(h, new_count);
}

template <typename K, typename V>
V *map_get(PtrMap<K, V> *h, K key) {
	MapIndex index = map__find(h, key).entry_index;
	if (index != MAP_SENTINEL) {
		return &h->entries.data[index].value;
	}
	return nullptr;
}

template <typename K, typename V>
V &map_must_get(PtrMap<K, V> *h, K key) {
	MapIndex index = map__find(h, key).entry_index;
	GB_ASSERT(index != MAP_SENTINEL);
	return h->entries.data[index].value;
}

template <typename K, typename V>
void map_set(PtrMap<K, V> *h, K key, V const &value) {
	MapIndex index;
	MapFindResult fr;
	if (h->hashes.count == 0) {
		map_grow(h);
	}
	fr = map__find(h, key);
	if (fr.entry_index != MAP_SENTINEL) {
		index = fr.entry_index;
	} else {
		index = map__add_entry(h, key);
		if (fr.entry_prev != MAP_SENTINEL) {
			h->entries.data[fr.entry_prev].next = index;
		} else {
			h->hashes.data[fr.hash_index] = index;
		}
	}
	h->entries.data[index].value = value;

	if (map__full(h)) {
		map_grow(h);
	}
}

template <typename K, typename V>
void map__erase(PtrMap<K, V> *h, MapFindResult const &fr) {
	MapFindResult last;
	if (fr.entry_prev == MAP_SENTINEL) {
		h->hashes.data[fr.hash_index] = h->entries.data[fr.entry_index].next;
	} else {
		h->entries.data[fr.entry_prev].next = h->entries.data[fr.entry_index].next;
	}
	if (fr.entry_index == h->entries.count-1) {
		array_pop(&h->entries);
		return;
	}
	h->entries.data[fr.entry_index] = h->entries.data[h->entries.count-1];
	array_pop(&h->entries);

	last = map__find(h, h->entries.data[fr.entry_index].key);
	if (last.entry_prev != MAP_SENTINEL) {
		h->entries.data[last.entry_prev].next = fr.entry_index;
	} else {
		h->hashes.data[last.hash_index] = fr.entry_index;
	}
}

template <typename K, typename V>
void map_remove(PtrMap<K, V> *h, K key) {
	MapFindResult fr = map__find(h, key);
	if (fr.entry_index != MAP_SENTINEL) {
		map__erase(h, fr);
	}
}

template <typename K, typename V>
gb_inline void map_clear(PtrMap<K, V> *h) {
	array_clear(&h->entries);
	for (isize i = 0; i < h->hashes.count; i++) {
		h->hashes.data[i] = MAP_SENTINEL;
	}
}

#if PTR_MAP_ENABLE_MULTI_MAP
template <typename K, typename V>
PtrMapEntry<K, V> *multi_map_find_first(PtrMap<K, V> *h, K key) {
	MapIndex i = map__find(h, key).entry_index;
	if (i == MAP_SENTINEL) {
		return nullptr;
	}
	return &h->entries.data[i];
}

template <typename K, typename V>
PtrMapEntry<K, V> *multi_map_find_next(PtrMap<K, V> *h, PtrMapEntry<K, V> *e) {
	MapIndex i = e->next;
	while (i != MAP_SENTINEL) {
		if (h->entries.data[i].key == e->key) {
			return &h->entries.data[i];
		}
		i = h->entries.data[i].next;
	}
	return nullptr;
}

template <typename K, typename V>
isize multi_map_count(PtrMap<K, V> *h, K key) {
	isize count = 0;
	PtrMapEntry<K, V> *e = multi_map_find_first(h, key);
	while (e != nullptr) {
		count++;
		e = multi_map_find_next(h, e);
	}
	return count;
}

template <typename K, typename V>
void multi_map_get_all(PtrMap<K, V> *h, K key, V *items) {
	isize i = 0;
	PtrMapEntry<K, V> *e = multi_map_find_first(h, key);
	while (e != nullptr) {
		items[i++] = e->value;
		e = multi_map_find_next(h, e);
	}
}

template <typename K, typename V>
void multi_map_insert(PtrMap<K, V> *h, K key, V const &value) {
	MapFindResult fr;
	MapIndex i;
	if (h->hashes.count == 0) {
		map_grow(h);
	}
	// Make
	fr = map__find(h, key);
	i = map__add_entry(h, key);
	if (fr.entry_prev == MAP_SENTINEL) {
		h->hashes.data[fr.hash_index] = i;
	} else {
		h->entries.data[fr.entry_prev].next = i;
	}
	h->entries.data[i].next = fr.entry_index;
	h->entries.data[i].value = value;
	// Grow if needed
	if (map__full(h)) {
		map_grow(h);
	}
}

template <typename K, typename V>
void multi_map_remove(PtrMap<K, V> *h, K key, PtrMapEntry<K, V> *e) {
	MapFindResult fr = map__find_from_entry(h, e);
	if (fr.entry_index != MAP_SENTINEL) {
		map__erase(h, fr);
	}
}

template <typename K, typename V>
void multi_map_remove_all(PtrMap<K, V> *h, K key) {
	while (map_get(h, key) != nullptr) {
		map_remove(h, key);
	}
}
#endif
<|endoftext|>


<commit_before>#include <iostream>
#include <vector>
#include <algorithm>

#include "randgen.h"

using namespace std;

double randgen(char rand_type, double para1, double para2)
{
  switch (rand_type)
    {
    case 'U':
      {
	boost::random::uniform_01<boost::mt19937 &> zeroone(rng);
	return zeroone();
	break;
      }
    case 'N':
      {
	double mean = para1;
	double std_dev = para2;
	boost::normal_distribution<> nd(mean,std_dev);
	boost::variate_generator<boost::mt19937 &,boost::normal_distribution<> > norm_rnd(rng,nd);
	return norm_rnd();
	break;
      }
    case 'P':
      {
	double lambda = (para1 == 0? para2:para1);
	boost::poisson_distribution<> pd(lambda);
	boost::variate_generator<boost::mt19937 &,boost::poisson_distribution<> > poisson_rnd(rng,pd);
	return poisson_rnd();
	break;
      }
    case 'E':
      {
	double lambda = (para1 == 0? para2:para1);
	boost::exponential_distribution<> expd(lambda);
	boost::variate_generator<boost::mt19937 &,boost::exponential_distribution<> > exp_rnd(rng,expd);
	return exp_rnd();
	break;
      }
    default:
	  return -9999.0;
      break;
    }

	// EJF -- return dummy value to avoid warning
    return -9999.0;
}
<commit_msg>Remove consecutive `break`s after `return`s<commit_after>#include <iostream>
#include <vector>
#include <algorithm>

#include "randgen.h"

using namespace std;

double randgen(char rand_type, double para1, double para2)
{
  switch (rand_type)
    {
    case 'U':
      {
	boost::random::uniform_01<boost::mt19937 &> zeroone(rng);
	return zeroone();
      }
    case 'N':
      {
	double mean = para1;
	double std_dev = para2;
	boost::normal_distribution<> nd(mean,std_dev);
	boost::variate_generator<boost::mt19937 &,boost::normal_distribution<> > norm_rnd(rng,nd);
	return norm_rnd();
      }
    case 'P':
      {
	double lambda = (para1 == 0? para2:para1);
	boost::poisson_distribution<> pd(lambda);
	boost::variate_generator<boost::mt19937 &,boost::poisson_distribution<> > poisson_rnd(rng,pd);
	return poisson_rnd();
      }
    case 'E':
      {
	double lambda = (para1 == 0? para2:para1);
	boost::exponential_distribution<> expd(lambda);
	boost::variate_generator<boost::mt19937 &,boost::exponential_distribution<> > exp_rnd(rng,expd);
	return exp_rnd();
      }
    default:
	  return -9999.0;
    }

	// EJF -- return dummy value to avoid warning
    return -9999.0;
}
<|endoftext|>


<commit_before>/*
 * Adplug - Replayer for many OPL2/OPL3 audio file formats.
 * Copyright (C) 1999 - 2007 Simon Peter, <dn.tlp@gmx.net>, et al.
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * 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., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 *
 * realopl.cpp - Real hardware OPL, by Simon Peter <dn.tlp@gmx.net>
 */

#ifdef _MSC_VER			// Microsoft Visual C++
#if (_MSC_VER >= 1900) // VS2015+
// _inp and _outp are no longer part of the C runtime from VS2015/Win8.1
int INP(int dummy) { return 0; }
void OUTP(int dummy, int dummy2) { return; }
#else // _MSC_VER < 1900
#	include <conio.h>
#	define INP	_inp
#	define OUTP	_outp
#endif // _MSC_VER < 1900
#elif defined(__WATCOMC__)	// Watcom C/C++ and OpenWatcom
#	include <conio.h>
#	define INP	inp
#	define OUTP	outp
#elif defined(WIN32) && defined(__MSVCRT__) && defined(__MINGW32__)	// MinGW32
/*
int __cdecl _inp(unsigned short);
int __cdecl _outp(unsigned short, int);
#	define INP	_inp
#	define OUTP	_outp
*/
#	define INP		inb
#	define OUTP(reg, val)	outb(val, reg)
#elif defined(DJGPP)		// DJGPP
#	include <pc.h>
#	define INP	inportb
#	define OUTP	outportb
#elif defined(linux)
# include <sys/io.h>
# define INP inb
# define OUTP(reg,val) outb(val,reg)
#else				// no support on other platforms
#	define INP(reg)		0
#	define OUTP(reg, val)
#endif

#include "realopl.h"

#define SHORTDELAY		6	// short delay in I/O port-reads after OPL hardware output
#define LONGDELAY		35	// long delay in I/O port-reads after OPL hardware output

const unsigned char CRealopl::op_table[9] =
  {0x00, 0x01, 0x02, 0x08, 0x09, 0x0a, 0x10, 0x11, 0x12};

#if defined(WIN32) && defined(__MINGW32__)
static __inline unsigned char inb(unsigned short int port)
{
  unsigned char _v;

  __asm__ __volatile__ ("inb %w1,%0":"=a" (_v):"Nd" (port));
  return _v;
}

static __inline void outb(unsigned char value, unsigned short int port)
{
  __asm__ __volatile__ ("outb %b0,%w1": :"a" (value), "Nd" (port));
}
#endif

CRealopl::CRealopl(unsigned short initport)
  : adlport(initport), hardvol(0), bequiet(false), nowrite(false)
{
  for(int i=0;i<22;i++) {
    hardvols[0][i][0] = 0;
    hardvols[0][i][1] = 0;
    hardvols[1][i][0] = 0;
    hardvols[1][i][1] = 0;
  }

  currType = TYPE_OPL3;
}

bool CRealopl::harddetect()
{
  unsigned char		stat1, stat2, i;
  unsigned short	adp = (currChip == 0 ? adlport : adlport + 2);

  hardwrite(4,0x60); hardwrite(4,0x80);
  stat1 = INP(adp);
  hardwrite(2,0xff); hardwrite(4,0x21);
  for(i=0;i<80;i++)			// wait for adlib
    INP(adp);
  stat2 = INP(adp);
  hardwrite(4,0x60); hardwrite(4,0x80);

  if(((stat1 & 0xe0) == 0) && ((stat2 & 0xe0) == 0xc0))
    return true;
  else
    return false;
}

bool CRealopl::detect()
{
  unsigned char	stat;

#ifdef linux // see whether we can access the port
  if ((ioperm(adlport, 2, 1) != 0) && (ioperm(adlport + 2, 2, 1) != 0)) {
    return false;
  }
#endif

  setchip(0);
  if(harddetect()) {
    // is at least OPL2, check for OPL3
    currType = TYPE_OPL2;

    stat = INP(adlport);
    if(stat & 6) {
      // not OPL3, try dual-OPL2
      setchip(1);
      if(harddetect())
	currType = TYPE_DUAL_OPL2;
    } else
      currType = TYPE_OPL3;

    setchip(0);
    return true;
  } else
    return false;
}

void CRealopl::setvolume(int volume)
{
  int i, j;

  hardvol = volume;
  for(j = 0; j < 2; j++)
    for(i = 0; i < 9; i++) {
      hardwrite(0x43+op_table[i],((hardvols[j][op_table[i]+3][0] & 63) + volume) > 63 ? 63 : hardvols[j][op_table[i]+3][0] + volume);
      if(hardvols[j][i][1] & 1)	// modulator too?
	hardwrite(0x40+op_table[i],((hardvols[j][op_table[i]][0] & 63) + volume) > 63 ? 63 : hardvols[j][op_table[i]][0] + volume);
    }
}

void CRealopl::setquiet(bool quiet)
{
  bequiet = quiet;

  if(quiet) {
    oldvol = hardvol;
    setvolume(63);
  } else
    setvolume(oldvol);
}

void CRealopl::hardwrite(int reg, int val)
{
  int 			i;
  unsigned short	adp = (currChip == 0 ? adlport : adlport + 2);

  if(nowrite)
    return;

  OUTP(adp,reg);		// set register
  for(i=0;i<SHORTDELAY;i++)	// wait for adlib
    INP(adp);
  OUTP(adp+1,val);		// set value
  for(i=0;i<LONGDELAY;i++)	// wait for adlib
    INP(adp);
}

void CRealopl::write(int reg, int val)
{
  int i;

  if(nowrite)
    return;

  if(currType == TYPE_OPL2 && currChip > 0)
    return;

  if(bequiet && (reg >= 0xb0 && reg <= 0xb8))	// filter all key-on commands
    val &= ~32;
  if(reg >= 0x40 && reg <= 0x55)		// cache volumes
    hardvols[currChip][reg-0x40][0] = val;
  if(reg >= 0xc0 && reg <= 0xc8)
    hardvols[currChip][reg-0xc0][1] = val;
  if(hardvol)					// reduce volume
    for(i=0;i<9;i++) {
      if(reg == 0x43 + op_table[i])
	val = ((val & 63) + hardvol) > 63 ? 63 : val + hardvol;
      else
	if((reg == 0x40 + op_table[i]) && (hardvols[currChip][i][1] & 1))
	  val = ((val & 63) + hardvol) > 63 ? 63 : val + hardvol;
    }

  hardwrite(reg,val);
}

void CRealopl::init()
{
  int i, j;

  for(j = 0; j < 2; j++) {
    setchip(j);

    for(i=0;i<9;i++) {				// stop instruments
      hardwrite(0xb0 + i,0);			// key off
      hardwrite(0x80 + op_table[i],0xff);	// fastest release
    }

    hardwrite(0xbd,0);	// clear misc. register
  }

  setchip(0);
}
<commit_msg>Duh. Get ioperms in Linux the right way<commit_after>/*
 * Adplug - Replayer for many OPL2/OPL3 audio file formats.
 * Copyright (C) 1999 - 2007 Simon Peter, <dn.tlp@gmx.net>, et al.
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * 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., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 *
 * realopl.cpp - Real hardware OPL, by Simon Peter <dn.tlp@gmx.net>
 */

#ifdef _MSC_VER			// Microsoft Visual C++
#if (_MSC_VER >= 1900) // VS2015+
// _inp and _outp are no longer part of the C runtime from VS2015/Win8.1
int INP(int dummy) { return 0; }
void OUTP(int dummy, int dummy2) { return; }
#else // _MSC_VER < 1900
#	include <conio.h>
#	define INP	_inp
#	define OUTP	_outp
#endif // _MSC_VER < 1900
#elif defined(__WATCOMC__)	// Watcom C/C++ and OpenWatcom
#	include <conio.h>
#	define INP	inp
#	define OUTP	outp
#elif defined(WIN32) && defined(__MSVCRT__) && defined(__MINGW32__)	// MinGW32
/*
int __cdecl _inp(unsigned short);
int __cdecl _outp(unsigned short, int);
#	define INP	_inp
#	define OUTP	_outp
*/
#	define INP		inb
#	define OUTP(reg, val)	outb(val, reg)
#elif defined(DJGPP)		// DJGPP
#	include <pc.h>
#	define INP	inportb
#	define OUTP	outportb
#elif defined(linux)
# include <sys/io.h>
# define INP inb
# define OUTP(reg,val) outb(val,reg)
#else				// no support on other platforms
#	define INP(reg)		0
#	define OUTP(reg, val)
#endif

#include "realopl.h"

#define SHORTDELAY		6	// short delay in I/O port-reads after OPL hardware output
#define LONGDELAY		35	// long delay in I/O port-reads after OPL hardware output

const unsigned char CRealopl::op_table[9] =
  {0x00, 0x01, 0x02, 0x08, 0x09, 0x0a, 0x10, 0x11, 0x12};

#if defined(WIN32) && defined(__MINGW32__)
static __inline unsigned char inb(unsigned short int port)
{
  unsigned char _v;

  __asm__ __volatile__ ("inb %w1,%0":"=a" (_v):"Nd" (port));
  return _v;
}

static __inline void outb(unsigned char value, unsigned short int port)
{
  __asm__ __volatile__ ("outb %b0,%w1": :"a" (value), "Nd" (port));
}
#endif

CRealopl::CRealopl(unsigned short initport)
  : adlport(initport), hardvol(0), bequiet(false), nowrite(false)
{
  for(int i=0;i<22;i++) {
    hardvols[0][i][0] = 0;
    hardvols[0][i][1] = 0;
    hardvols[1][i][0] = 0;
    hardvols[1][i][1] = 0;
  }

  currType = TYPE_OPL3;
}

bool CRealopl::harddetect()
{
  unsigned char		stat1, stat2, i;
  unsigned short	adp = (currChip == 0 ? adlport : adlport + 2);

  hardwrite(4,0x60); hardwrite(4,0x80);
  stat1 = INP(adp);
  hardwrite(2,0xff); hardwrite(4,0x21);
  for(i=0;i<80;i++)			// wait for adlib
    INP(adp);
  stat2 = INP(adp);
  hardwrite(4,0x60); hardwrite(4,0x80);

  if(((stat1 & 0xe0) == 0) && ((stat2 & 0xe0) == 0xc0))
    return true;
  else
    return false;
}

bool CRealopl::detect()
{
  unsigned char	stat;

#ifdef linux // see whether we can access the port
  if ((ioperm(adlport, 2, 1) != 0) || (ioperm(adlport + 2, 2, 1) != 0)) {
    return false;
  }
#endif

  setchip(0);
  if(harddetect()) {
    // is at least OPL2, check for OPL3
    currType = TYPE_OPL2;

    stat = INP(adlport);
    if(stat & 6) {
      // not OPL3, try dual-OPL2
      setchip(1);
      if(harddetect())
	currType = TYPE_DUAL_OPL2;
    } else
      currType = TYPE_OPL3;

    setchip(0);
    return true;
  } else
    return false;
}

void CRealopl::setvolume(int volume)
{
  int i, j;

  hardvol = volume;
  for(j = 0; j < 2; j++)
    for(i = 0; i < 9; i++) {
      hardwrite(0x43+op_table[i],((hardvols[j][op_table[i]+3][0] & 63) + volume) > 63 ? 63 : hardvols[j][op_table[i]+3][0] + volume);
      if(hardvols[j][i][1] & 1)	// modulator too?
	hardwrite(0x40+op_table[i],((hardvols[j][op_table[i]][0] & 63) + volume) > 63 ? 63 : hardvols[j][op_table[i]][0] + volume);
    }
}

void CRealopl::setquiet(bool quiet)
{
  bequiet = quiet;

  if(quiet) {
    oldvol = hardvol;
    setvolume(63);
  } else
    setvolume(oldvol);
}

void CRealopl::hardwrite(int reg, int val)
{
  int 			i;
  unsigned short	adp = (currChip == 0 ? adlport : adlport + 2);

  if(nowrite)
    return;

  OUTP(adp,reg);		// set register
  for(i=0;i<SHORTDELAY;i++)	// wait for adlib
    INP(adp);
  OUTP(adp+1,val);		// set value
  for(i=0;i<LONGDELAY;i++)	// wait for adlib
    INP(adp);
}

void CRealopl::write(int reg, int val)
{
  int i;

  if(nowrite)
    return;

  if(currType == TYPE_OPL2 && currChip > 0)
    return;

  if(bequiet && (reg >= 0xb0 && reg <= 0xb8))	// filter all key-on commands
    val &= ~32;
  if(reg >= 0x40 && reg <= 0x55)		// cache volumes
    hardvols[currChip][reg-0x40][0] = val;
  if(reg >= 0xc0 && reg <= 0xc8)
    hardvols[currChip][reg-0xc0][1] = val;
  if(hardvol)					// reduce volume
    for(i=0;i<9;i++) {
      if(reg == 0x43 + op_table[i])
	val = ((val & 63) + hardvol) > 63 ? 63 : val + hardvol;
      else
	if((reg == 0x40 + op_table[i]) && (hardvols[currChip][i][1] & 1))
	  val = ((val & 63) + hardvol) > 63 ? 63 : val + hardvol;
    }

  hardwrite(reg,val);
}

void CRealopl::init()
{
  int i, j;

  for(j = 0; j < 2; j++) {
    setchip(j);

    for(i=0;i<9;i++) {				// stop instruments
      hardwrite(0xb0 + i,0);			// key off
      hardwrite(0x80 + op_table[i],0xff);	// fastest release
    }

    hardwrite(0xbd,0);	// clear misc. register
  }

  setchip(0);
}
<|endoftext|>


<commit_before>// renderer.cc
// This implements the Renderer class.
// It is used to render and display the UI in a GTK window.

#include "renderer.h"

using namespace WDE;
using namespace std;

gboolean Renderer::DestroyWebView(WebKitWebView* webView, GtkWidget* window)
{
	gtk_widget_destroy(window);
	return TRUE;
}

Renderer::Renderer(unsigned short width, unsigned short height, char* argv[])
{
	m_IsFullscreen = false;

	m_Window = GTK_WINDOW(gtk_window_new(GTK_WINDOW_TOPLEVEL));
	gtk_window_resize(m_Window, width, height);
	g_signal_connect(GTK_WIDGET(m_Window), "destroy", G_CALLBACK(gtk_main_quit), NULL);

	m_WebView = WEBKIT_WEB_VIEW(webkit_web_view_new());
	g_signal_connect(GTK_WIDGET(m_WebView), "close", G_CALLBACK(DestroyWebView), m_Window);
	gtk_container_add(GTK_CONTAINER(m_Window), GTK_WIDGET(m_WebView));

	m_HTMLSource = new HTMLSource(argv[1]);
	webkit_web_view_load_string(m_WebView, m_HTMLSource->GetHTML(), NULL, NULL, NULL);
}

void Renderer::GoFullscreen()
{
	m_IsFullscreen = true;
	gtk_window_fullscreen(m_Window);
}

void Renderer::GoWindowed()
{
	m_IsFullscreen = false;
	gtk_window_unfullscreen(m_Window);
}

void Renderer::ToggleFullscreen()
{
	if(m_IsFullscreen)
		GoWindowed();
	else
		GoFullscreen();
}

void Renderer::MainLoop()
{
	gtk_window_present(m_Window);
	gtk_widget_show_all(GTK_WIDGET(m_Window));
    gtk_main();
}

// Initialise GTK+ before using it.
gboolean Renderer::InitGTK(int &argc, char* argv[])
{
	gboolean success = gtk_init_check(&argc, &argv);
	if(success)
		cout << "GTK+ initialised successfully." << endl;
	else
		cout << "There was a problem initialising GTK+." << endl;
	return success;
}

Renderer::~Renderer()
{
	delete m_WebView;
	delete m_Window;
	delete m_HTMLSource;
}
<commit_msg>Added fullscreen for root window<commit_after>// renderer.cc
// This implements the Renderer class.
// It is used to render and display the UI in a GTK window.

#include "renderer.h"

using namespace WDE;
using namespace std;

gboolean Renderer::DestroyWebView(WebKitWebView* webView, GtkWidget* window)
{
	gtk_widget_destroy(window);
	return TRUE;
}

Renderer::Renderer(unsigned short width, unsigned short height, char* argv[])
{
	m_IsFullscreen = false;

	m_Window = GTK_WINDOW(gtk_window_new(GTK_WINDOW_TOPLEVEL));
	gtk_window_resize(m_Window, width, height);
	g_signal_connect(GTK_WIDGET(m_Window), "destroy", G_CALLBACK(gtk_main_quit), NULL);

	m_WebView = WEBKIT_WEB_VIEW(webkit_web_view_new());
	g_signal_connect(GTK_WIDGET(m_WebView), "close", G_CALLBACK(DestroyWebView), m_Window);
	gtk_container_add(GTK_CONTAINER(m_Window), GTK_WIDGET(m_WebView));

	m_HTMLSource = new HTMLSource(argv[1]);
	webkit_web_view_load_string(m_WebView, m_HTMLSource->GetHTML(), NULL, NULL, NULL);
}

void Renderer::GoFullscreen()
{
	m_IsFullscreen = true;
	gtk_window_fullscreen(m_Window);
	GdkScreen* defScreen = gdk_screen_get_default();
	gtk_window_resize(m_Window, gdk_screen_get_width(defScreen), gdk_screen_get_height(defScreen));
}

void Renderer::GoWindowed()
{
	m_IsFullscreen = false;
	gtk_window_unfullscreen(m_Window);
}

void Renderer::ToggleFullscreen()
{
	if(m_IsFullscreen)
		GoWindowed();
	else
		GoFullscreen();
}

void Renderer::MainLoop()
{
	gtk_window_present(m_Window);
	gtk_widget_show_all(GTK_WIDGET(m_Window));
    gtk_main();
}

// Initialise GTK+ before using it.
gboolean Renderer::InitGTK(int &argc, char* argv[])
{
	gboolean success = gtk_init_check(&argc, &argv);
	if(success)
		cout << "GTK+ initialised successfully." << endl;
	else
		cout << "There was a problem initialising GTK+." << endl;
	return success;
}

Renderer::~Renderer()
{
	delete m_WebView;
	delete m_Window;
	delete m_HTMLSource;
}
<|endoftext|>


<commit_before>// Copyright (c) 2009-2012 Bitcoin Developers
// Copyright (c) 2012-2013 The PPCoin developers
// Copyright (c) 2015 The Grantcoin developers
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.

#include "init.h" // for pwalletMain
#include "bitcoinrpc.h"
#include "ui_interface.h"

#include <boost/lexical_cast.hpp>

#include "json/json_spirit_reader_template.h"
#include "json/json_spirit_writer_template.h"
#include "json/json_spirit_utils.h"

#define printf OutputDebugStringF

// using namespace boost::asio;
using namespace json_spirit;
using namespace std;

extern Object JSONRPCError(int code, const string& message);

class CTxDump
{
public:
    CBlockIndex *pindex;
    int64 nValue;
    bool fSpent;
    CWalletTx* ptx;
    int nOut;
    CTxDump(CWalletTx* ptx = NULL, int nOut = -1)
    {
        pindex = NULL;
        nValue = 0;
        fSpent = false;
        this->ptx = ptx;
        this->nOut = nOut;
    }
};

Value importprivkey(const Array& params, bool fHelp)
{
    if (fHelp || params.size() < 1 || params.size() > 2)
        throw runtime_error(
            "importprivkey <grantcoinprivkey> [label]\n"
            "Adds a private key (as returned by dumpprivkey) to your wallet.");

    string strSecret = params[0].get_str();
    string strLabel = "";
    if (params.size() > 1)
        strLabel = params[1].get_str();
    CBitcoinSecret vchSecret;
    bool fGood = vchSecret.SetString(strSecret);

    if (!fGood) throw JSONRPCError(-5,"Invalid private key");
    if (pwalletMain->IsLocked())
        throw JSONRPCError(-13, "Error: Please enter the wallet passphrase with walletpassphrase first.");
    if (fWalletUnlockMintOnly) // grantcoin: no importprivkey in mint-only mode
        throw JSONRPCError(-102, "Wallet is unlocked for minting only.");

    CKey key;
    bool fCompressed;
    CSecret secret = vchSecret.GetSecret(fCompressed);
    key.SetSecret(secret, fCompressed);
    CBitcoinAddress vchAddress = CBitcoinAddress(key.GetPubKey());

    {
        LOCK2(cs_main, pwalletMain->cs_wallet);

        pwalletMain->MarkDirty();
        pwalletMain->SetAddressBookName(vchAddress, strLabel);

        if (!pwalletMain->AddKey(key))
            throw JSONRPCError(-4,"Error adding key to wallet");

        pwalletMain->ScanForWalletTransactions(pindexGenesisBlock, true);
        pwalletMain->ReacceptWalletTransactions();
    }

    MainFrameRepaint();

    return Value::null;
}

Value dumpprivkey(const Array& params, bool fHelp)
{
    if (fHelp || params.size() != 1)
        throw runtime_error(
            "dumpprivkey <grantcoinaddress>\n"
            "Reveals the private key corresponding to <grantcoinaddress>.");

    string strAddress = params[0].get_str();
    CBitcoinAddress address;
    if (!address.SetString(strAddress))
        throw JSONRPCError(-5, "Invalid grantcoin address");
    if (pwalletMain->IsLocked())
        throw JSONRPCError(-13, "Error: Please enter the wallet passphrase with walletpassphrase first.");
    if (fWalletUnlockMintOnly) // grantcoin: no dumpprivkey in mint-only mode
        throw JSONRPCError(-102, "Wallet is unlocked for minting only.");
    CSecret vchSecret;
    bool fCompressed;
    if (!pwalletMain->GetSecret(address, vchSecret, fCompressed))
        throw JSONRPCError(-4,"Private key for address " + strAddress + " is not known");
    return CBitcoinSecret(vchSecret, fCompressed).ToString();
}
<commit_msg>change comments: grantcoin to peercoin<commit_after>// Copyright (c) 2009-2012 Bitcoin Developers
// Copyright (c) 2012-2013 The PPCoin developers
// Copyright (c) 2015 The Grantcoin developers
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.

#include "init.h" // for pwalletMain
#include "bitcoinrpc.h"
#include "ui_interface.h"

#include <boost/lexical_cast.hpp>

#include "json/json_spirit_reader_template.h"
#include "json/json_spirit_writer_template.h"
#include "json/json_spirit_utils.h"

#define printf OutputDebugStringF

// using namespace boost::asio;
using namespace json_spirit;
using namespace std;

extern Object JSONRPCError(int code, const string& message);

class CTxDump
{
public:
    CBlockIndex *pindex;
    int64 nValue;
    bool fSpent;
    CWalletTx* ptx;
    int nOut;
    CTxDump(CWalletTx* ptx = NULL, int nOut = -1)
    {
        pindex = NULL;
        nValue = 0;
        fSpent = false;
        this->ptx = ptx;
        this->nOut = nOut;
    }
};

Value importprivkey(const Array& params, bool fHelp)
{
    if (fHelp || params.size() < 1 || params.size() > 2)
        throw runtime_error(
            "importprivkey <grantcoinprivkey> [label]\n"
            "Adds a private key (as returned by dumpprivkey) to your wallet.");

    string strSecret = params[0].get_str();
    string strLabel = "";
    if (params.size() > 1)
        strLabel = params[1].get_str();
    CBitcoinSecret vchSecret;
    bool fGood = vchSecret.SetString(strSecret);

    if (!fGood) throw JSONRPCError(-5,"Invalid private key");
    if (pwalletMain->IsLocked())
        throw JSONRPCError(-13, "Error: Please enter the wallet passphrase with walletpassphrase first.");
    if (fWalletUnlockMintOnly) // peercoin: no importprivkey in mint-only mode
        throw JSONRPCError(-102, "Wallet is unlocked for minting only.");

    CKey key;
    bool fCompressed;
    CSecret secret = vchSecret.GetSecret(fCompressed);
    key.SetSecret(secret, fCompressed);
    CBitcoinAddress vchAddress = CBitcoinAddress(key.GetPubKey());

    {
        LOCK2(cs_main, pwalletMain->cs_wallet);

        pwalletMain->MarkDirty();
        pwalletMain->SetAddressBookName(vchAddress, strLabel);

        if (!pwalletMain->AddKey(key))
            throw JSONRPCError(-4,"Error adding key to wallet");

        pwalletMain->ScanForWalletTransactions(pindexGenesisBlock, true);
        pwalletMain->ReacceptWalletTransactions();
    }

    MainFrameRepaint();

    return Value::null;
}

Value dumpprivkey(const Array& params, bool fHelp)
{
    if (fHelp || params.size() != 1)
        throw runtime_error(
            "dumpprivkey <grantcoinaddress>\n"
            "Reveals the private key corresponding to <grantcoinaddress>.");

    string strAddress = params[0].get_str();
    CBitcoinAddress address;
    if (!address.SetString(strAddress))
        throw JSONRPCError(-5, "Invalid grantcoin address");
    if (pwalletMain->IsLocked())
        throw JSONRPCError(-13, "Error: Please enter the wallet passphrase with walletpassphrase first.");
    if (fWalletUnlockMintOnly) // peercoin: no dumpprivkey in mint-only mode
        throw JSONRPCError(-102, "Wallet is unlocked for minting only.");
    CSecret vchSecret;
    bool fCompressed;
    if (!pwalletMain->GetSecret(address, vchSecret, fCompressed))
        throw JSONRPCError(-4,"Private key for address " + strAddress + " is not known");
    return CBitcoinSecret(vchSecret, fCompressed).ToString();
}
<|endoftext|>