<commit_before>#include <plasp/pddl/Problem.h>

#include <algorithm>

#include <plasp/pddl/Domain.h>
#include <plasp/pddl/ExpressionContext.h>
#include <plasp/pddl/Identifier.h>
#include <plasp/pddl/IO.h>
#include <plasp/pddl/expressions/Constant.h>
#include <plasp/utils/IO.h>
#include <plasp/utils/ParserException.h>

namespace plasp
{
namespace pddl
{

////////////////////////////////////////////////////////////////////////////////////////////////////
//
// Problem
//
////////////////////////////////////////////////////////////////////////////////////////////////////

Problem::Problem(Context &context, Domain &domain)
:	m_context(context),
	m_domain(domain),
	m_domainPosition{-1},
	m_requirementsPosition{-1},
	m_objectsPosition{-1},
	m_initialStatePosition{-1},
	m_goalPosition{-1}
{
}

////////////////////////////////////////////////////////////////////////////////////////////////////

void Problem::findSections()
{
	auto &parser = m_context.parser;

	parser.expect<std::string>("(");
	parser.expect<std::string>("define");
	parser.expect<std::string>("(");
	parser.expect<std::string>("problem");

	m_name = parser.parseIdentifier(isIdentifier);

	std::cout << "Found problem " << m_name << std::endl;

	parser.expect<std::string>(")");

	const auto setSectionPosition =
	[&](const std::string &sectionName, auto &sectionPosition, const auto value, bool unique = false)
	{
		if (unique && sectionPosition != -1)
		{
			parser.seek(value);
			throw utils::ParserException(parser, "Only one \":" + sectionName + "\" section allowed");
		}

		sectionPosition = value;
	};

	parser.skipWhiteSpace();

	while (parser.currentCharacter() != ')')
	{
		const auto position = parser.position();

		parser.expect<std::string>("(");
		parser.expect<std::string>(":");

		const auto sectionIdentifierPosition = parser.position();

		// TODO: check order of the sections
		if (parser.probeIdentifier("domain", isIdentifier))
			setSectionPosition("domain", m_domainPosition, position, true);
		else if (parser.probeIdentifier("requirements", isIdentifier))
			setSectionPosition("requirements", m_requirementsPosition, position, true);
		else if (parser.probeIdentifier("objects", isIdentifier))
			setSectionPosition("objects", m_objectsPosition, position, true);
		else if (parser.probeIdentifier("init", isIdentifier))
			setSectionPosition("init", m_initialStatePosition, position, true);
		else if (parser.probeIdentifier("goal", isIdentifier))
			setSectionPosition("goal", m_goalPosition, position, true);
		else if (parser.probeIdentifier("constraints", isIdentifier)
			|| parser.probeIdentifier("metric", isIdentifier)
			|| parser.probeIdentifier("length", isIdentifier))
		{
			parser.seek(sectionIdentifierPosition);

			const auto sectionIdentifier = parser.parseIdentifier(isIdentifier);

			m_context.logger.parserWarning(parser, "Section type \"" + sectionIdentifier + "\" currently unsupported");

			parser.seek(sectionIdentifierPosition);
		}
		else
		{
			const auto sectionIdentifier = parser.parseIdentifier(isIdentifier);

			parser.seek(position);
			throw utils::ParserException(m_context.parser, "Unknown problem section \"" + sectionIdentifier + "\"");
		}

		// Skip section for now and parse it later
		skipSection(parser);

		parser.skipWhiteSpace();
	}

	parser.expect<std::string>(")");
}

////////////////////////////////////////////////////////////////////////////////////////////////////

void Problem::parse()
{
	auto &parser = m_context.parser;

	if (m_domainPosition == -1)
		throw ConsistencyException("Problem description does not specify the corresponding domain");

	parser.seek(m_domainPosition);
	parseDomainSection();

	if (m_requirementsPosition != -1)
	{
		parser.seek(m_requirementsPosition);
		parseRequirementSection();
	}

	if (m_objectsPosition != -1)
	{
		parser.seek(m_objectsPosition);
		parseObjectSection();
	}

	if (m_initialStatePosition == -1)
		throw ConsistencyException("Problem description does not specify an initial state");

	parser.seek(m_initialStatePosition);
	parseInitialStateSection();

	if (m_goalPosition == -1)
		throw ConsistencyException("Problem description does not specify a goal");

	parser.seek(m_goalPosition);
	parseGoalSection();
}

////////////////////////////////////////////////////////////////////////////////////////////////////

Domain &Problem::domain()
{
	return m_domain;
}

////////////////////////////////////////////////////////////////////////////////////////////////////

const Domain &Problem::domain() const
{
	return m_domain;
}

////////////////////////////////////////////////////////////////////////////////////////////////////

const std::string &Problem::name() const
{
	return m_name;
}

////////////////////////////////////////////////////////////////////////////////////////////////////

const Requirements &Problem::requirements() const
{
	return m_requirements;
}

////////////////////////////////////////////////////////////////////////////////////////////////////

expressions::Constants &Problem::objects()
{
	return m_objects;
}

////////////////////////////////////////////////////////////////////////////////////////////////////

const expressions::Constants &Problem::objects() const
{
	return m_objects;
}

////////////////////////////////////////////////////////////////////////////////////////////////////

void Problem::parseDomainSection()
{
	auto &parser = m_context.parser;

	parser.expect<std::string>("(");
	parser.expect<std::string>(":");
	parser.expect<std::string>("domain");

	parser.skipWhiteSpace();

	const auto domainName = parser.parseIdentifier(isIdentifier);

	if (m_domain.name() != domainName)
		throw utils::ParserException(parser, "Domains do not match (\"" + m_domain.name() + "\" and \"" + domainName + "\")");

	parser.expect<std::string>(")");
}

////////////////////////////////////////////////////////////////////////////////////////////////////

void Problem::parseRequirementSection()
{
	auto &parser = m_context.parser;

	parser.expect<std::string>("(");
	parser.expect<std::string>(":");
	parser.expect<std::string>("requirements");

	parser.skipWhiteSpace();

	while (parser.currentCharacter() != ')')
	{
		parser.expect<std::string>(":");

		m_requirements.emplace_back(Requirement::parse(m_context));

		parser.skipWhiteSpace();
	}

	// TODO: do this check only once the domain is parsed
	// If no requirements are specified, assume STRIPS
	if (m_requirements.empty())
		m_requirements.emplace_back(Requirement::Type::STRIPS);

	parser.expect<std::string>(")");
}

////////////////////////////////////////////////////////////////////////////////////////////////////

bool Problem::hasRequirement(Requirement::Type requirementType) const
{
	const auto match = std::find_if(m_requirements.cbegin(), m_requirements.cend(),
		[&](const auto &requirement)
		{
			return requirement.type() == requirementType;
		});

	if (match != m_requirements.cend())
		return true;

	return m_domain.hasRequirement(requirementType);
}

////////////////////////////////////////////////////////////////////////////////////////////////////

void Problem::checkRequirement(Requirement::Type requirementType) const
{
	if (hasRequirement(requirementType))
		return;

	throw ConsistencyException("Requirement \"" + Requirement(requirementType).toPDDL() + "\" used but never declared");
}

////////////////////////////////////////////////////////////////////////////////////////////////////

void Problem::computeDerivedRequirements()
{
	const auto addRequirementUnique =
		[&](const auto requirement)
		{
			if (hasRequirement(requirement))
				return;

			m_requirements.push_back(Requirement(requirement));
		};

	if (hasRequirement(Requirement::Type::ADL))
	{
		addRequirementUnique(Requirement::Type::STRIPS);
		addRequirementUnique(Requirement::Type::Typing);
		addRequirementUnique(Requirement::Type::NegativePreconditions);
		addRequirementUnique(Requirement::Type::DisjunctivePreconditions);
		addRequirementUnique(Requirement::Type::Equality);
		addRequirementUnique(Requirement::Type::QuantifiedPreconditions);
		addRequirementUnique(Requirement::Type::ConditionalEffects);
	}

	if (hasRequirement(Requirement::Type::QuantifiedPreconditions))
	{
		addRequirementUnique(Requirement::Type::ExistentialPreconditions);
		addRequirementUnique(Requirement::Type::UniversalPreconditions);
	}

	if (hasRequirement(Requirement::Type::Fluents))
	{
		addRequirementUnique(Requirement::Type::NumericFluents);
		addRequirementUnique(Requirement::Type::ObjectFluents);
	}

	if (hasRequirement(Requirement::Type::TimedInitialLiterals))
		addRequirementUnique(Requirement::Type::DurativeActions);
}

////////////////////////////////////////////////////////////////////////////////////////////////////

void Problem::parseObjectSection()
{
	auto &parser = m_context.parser;

	parser.expect<std::string>("(");
	parser.expect<std::string>(":");
	parser.expect<std::string>("objects");

	parser.skipWhiteSpace();

	// Store constants
	expressions::Constant::parseTypedDeclarations(m_context, *this);

	parser.expect<std::string>(")");
}

////////////////////////////////////////////////////////////////////////////////////////////////////

void Problem::parseInitialStateSection()
{
	auto &parser = m_context.parser;

	parser.expect<std::string>("(");
	parser.expect<std::string>(":");
	parser.expect<std::string>("init");

	m_initialState = InitialState::parseDeclaration(m_context, *this);

	parser.expect<std::string>(")");
}

////////////////////////////////////////////////////////////////////////////////////////////////////

void Problem::parseGoalSection()
{
	auto &parser = m_context.parser;

	parser.expect<std::string>("(");
	parser.expect<std::string>(":");
	parser.expect<std::string>("goal");

	expressions::Variables noParameters;

	ExpressionContext expressionContext(m_domain, this, noParameters);

	m_goal = parsePreconditionExpression(m_context, expressionContext);

	parser.expect<std::string>(")");
}

////////////////////////////////////////////////////////////////////////////////////////////////////

InitialState &Problem::initialState()
{
	BOOST_ASSERT(m_initialState);

	return *m_initialState;
}

////////////////////////////////////////////////////////////////////////////////////////////////////

const InitialState &Problem::initialState() const
{
	BOOST_ASSERT(m_initialState);

	return *m_initialState;
}

////////////////////////////////////////////////////////////////////////////////////////////////////

const Expression &Problem::goal() const
{
	BOOST_ASSERT(m_goal);

	return *m_goal;
}

////////////////////////////////////////////////////////////////////////////////////////////////////

void Problem::checkConsistency()
{
}

////////////////////////////////////////////////////////////////////////////////////////////////////

}
}
<commit_msg>Added to-do.<commit_after>#include <plasp/pddl/Problem.h>

#include <algorithm>

#include <plasp/pddl/Domain.h>
#include <plasp/pddl/ExpressionContext.h>
#include <plasp/pddl/Identifier.h>
#include <plasp/pddl/IO.h>
#include <plasp/pddl/expressions/Constant.h>
#include <plasp/utils/IO.h>
#include <plasp/utils/ParserException.h>

namespace plasp
{
namespace pddl
{

////////////////////////////////////////////////////////////////////////////////////////////////////
//
// Problem
//
////////////////////////////////////////////////////////////////////////////////////////////////////

Problem::Problem(Context &context, Domain &domain)
:	m_context(context),
	m_domain(domain),
	m_domainPosition{-1},
	m_requirementsPosition{-1},
	m_objectsPosition{-1},
	m_initialStatePosition{-1},
	m_goalPosition{-1}
{
}

////////////////////////////////////////////////////////////////////////////////////////////////////

void Problem::findSections()
{
	auto &parser = m_context.parser;

	parser.expect<std::string>("(");
	parser.expect<std::string>("define");
	parser.expect<std::string>("(");
	parser.expect<std::string>("problem");

	m_name = parser.parseIdentifier(isIdentifier);

	std::cout << "Found problem " << m_name << std::endl;

	parser.expect<std::string>(")");

	const auto setSectionPosition =
	[&](const std::string &sectionName, auto &sectionPosition, const auto value, bool unique = false)
	{
		if (unique && sectionPosition != -1)
		{
			parser.seek(value);
			throw utils::ParserException(parser, "Only one \":" + sectionName + "\" section allowed");
		}

		sectionPosition = value;
	};

	parser.skipWhiteSpace();

	while (parser.currentCharacter() != ')')
	{
		const auto position = parser.position();

		parser.expect<std::string>("(");
		parser.expect<std::string>(":");

		const auto sectionIdentifierPosition = parser.position();

		// TODO: check order of the sections
		if (parser.probeIdentifier("domain", isIdentifier))
			setSectionPosition("domain", m_domainPosition, position, true);
		else if (parser.probeIdentifier("requirements", isIdentifier))
			setSectionPosition("requirements", m_requirementsPosition, position, true);
		else if (parser.probeIdentifier("objects", isIdentifier))
			setSectionPosition("objects", m_objectsPosition, position, true);
		else if (parser.probeIdentifier("init", isIdentifier))
			setSectionPosition("init", m_initialStatePosition, position, true);
		else if (parser.probeIdentifier("goal", isIdentifier))
			setSectionPosition("goal", m_goalPosition, position, true);
		else if (parser.probeIdentifier("constraints", isIdentifier)
			|| parser.probeIdentifier("metric", isIdentifier)
			|| parser.probeIdentifier("length", isIdentifier))
		{
			parser.seek(sectionIdentifierPosition);

			const auto sectionIdentifier = parser.parseIdentifier(isIdentifier);

			m_context.logger.parserWarning(parser, "Section type \"" + sectionIdentifier + "\" currently unsupported");

			parser.seek(sectionIdentifierPosition);
		}
		else
		{
			const auto sectionIdentifier = parser.parseIdentifier(isIdentifier);

			parser.seek(position);
			throw utils::ParserException(m_context.parser, "Unknown problem section \"" + sectionIdentifier + "\"");
		}

		// Skip section for now and parse it later
		skipSection(parser);

		parser.skipWhiteSpace();
	}

	parser.expect<std::string>(")");
}

////////////////////////////////////////////////////////////////////////////////////////////////////

void Problem::parse()
{
	auto &parser = m_context.parser;

	if (m_domainPosition == -1)
		throw ConsistencyException("Problem description does not specify the corresponding domain");

	parser.seek(m_domainPosition);
	parseDomainSection();

	if (m_requirementsPosition != -1)
	{
		parser.seek(m_requirementsPosition);
		parseRequirementSection();
	}

	if (m_objectsPosition != -1)
	{
		parser.seek(m_objectsPosition);
		parseObjectSection();
	}

	if (m_initialStatePosition == -1)
		throw ConsistencyException("Problem description does not specify an initial state");

	parser.seek(m_initialStatePosition);
	parseInitialStateSection();

	if (m_goalPosition == -1)
		throw ConsistencyException("Problem description does not specify a goal");

	parser.seek(m_goalPosition);
	parseGoalSection();
}

////////////////////////////////////////////////////////////////////////////////////////////////////

Domain &Problem::domain()
{
	return m_domain;
}

////////////////////////////////////////////////////////////////////////////////////////////////////

const Domain &Problem::domain() const
{
	return m_domain;
}

////////////////////////////////////////////////////////////////////////////////////////////////////

const std::string &Problem::name() const
{
	return m_name;
}

////////////////////////////////////////////////////////////////////////////////////////////////////

const Requirements &Problem::requirements() const
{
	return m_requirements;
}

////////////////////////////////////////////////////////////////////////////////////////////////////

expressions::Constants &Problem::objects()
{
	return m_objects;
}

////////////////////////////////////////////////////////////////////////////////////////////////////

const expressions::Constants &Problem::objects() const
{
	return m_objects;
}

////////////////////////////////////////////////////////////////////////////////////////////////////

void Problem::parseDomainSection()
{
	auto &parser = m_context.parser;

	parser.expect<std::string>("(");
	parser.expect<std::string>(":");
	parser.expect<std::string>("domain");

	parser.skipWhiteSpace();

	const auto domainName = parser.parseIdentifier(isIdentifier);

	if (m_domain.name() != domainName)
		throw utils::ParserException(parser, "Domains do not match (\"" + m_domain.name() + "\" and \"" + domainName + "\")");

	parser.expect<std::string>(")");
}

////////////////////////////////////////////////////////////////////////////////////////////////////

void Problem::parseRequirementSection()
{
	auto &parser = m_context.parser;

	parser.expect<std::string>("(");
	parser.expect<std::string>(":");
	parser.expect<std::string>("requirements");

	parser.skipWhiteSpace();

	while (parser.currentCharacter() != ')')
	{
		parser.expect<std::string>(":");

		m_requirements.emplace_back(Requirement::parse(m_context));

		parser.skipWhiteSpace();
	}

	// TODO: do this check only once the domain is parsed
	// If no requirements are specified, assume STRIPS
	if (m_requirements.empty())
		m_requirements.emplace_back(Requirement::Type::STRIPS);

	parser.expect<std::string>(")");
}

////////////////////////////////////////////////////////////////////////////////////////////////////

bool Problem::hasRequirement(Requirement::Type requirementType) const
{
	const auto match = std::find_if(m_requirements.cbegin(), m_requirements.cend(),
		[&](const auto &requirement)
		{
			return requirement.type() == requirementType;
		});

	if (match != m_requirements.cend())
		return true;

	return m_domain.hasRequirement(requirementType);
}

////////////////////////////////////////////////////////////////////////////////////////////////////

void Problem::checkRequirement(Requirement::Type requirementType) const
{
	if (hasRequirement(requirementType))
		return;

	throw ConsistencyException("Requirement \"" + Requirement(requirementType).toPDDL() + "\" used but never declared");
}

////////////////////////////////////////////////////////////////////////////////////////////////////

void Problem::computeDerivedRequirements()
{
	const auto addRequirementUnique =
		[&](const auto requirement)
		{
			if (hasRequirement(requirement))
				return;

			m_requirements.push_back(Requirement(requirement));
		};

	if (hasRequirement(Requirement::Type::ADL))
	{
		addRequirementUnique(Requirement::Type::STRIPS);
		addRequirementUnique(Requirement::Type::Typing);
		addRequirementUnique(Requirement::Type::NegativePreconditions);
		addRequirementUnique(Requirement::Type::DisjunctivePreconditions);
		addRequirementUnique(Requirement::Type::Equality);
		addRequirementUnique(Requirement::Type::QuantifiedPreconditions);
		addRequirementUnique(Requirement::Type::ConditionalEffects);
	}

	if (hasRequirement(Requirement::Type::QuantifiedPreconditions))
	{
		addRequirementUnique(Requirement::Type::ExistentialPreconditions);
		addRequirementUnique(Requirement::Type::UniversalPreconditions);
	}

	if (hasRequirement(Requirement::Type::Fluents))
	{
		addRequirementUnique(Requirement::Type::NumericFluents);
		addRequirementUnique(Requirement::Type::ObjectFluents);
	}

	if (hasRequirement(Requirement::Type::TimedInitialLiterals))
		addRequirementUnique(Requirement::Type::DurativeActions);
}

////////////////////////////////////////////////////////////////////////////////////////////////////

void Problem::parseObjectSection()
{
	auto &parser = m_context.parser;

	parser.expect<std::string>("(");
	parser.expect<std::string>(":");
	parser.expect<std::string>("objects");

	parser.skipWhiteSpace();

	// Store constants
	expressions::Constant::parseTypedDeclarations(m_context, *this);

	parser.expect<std::string>(")");
}

////////////////////////////////////////////////////////////////////////////////////////////////////

void Problem::parseInitialStateSection()
{
	auto &parser = m_context.parser;

	parser.expect<std::string>("(");
	parser.expect<std::string>(":");
	parser.expect<std::string>("init");

	m_initialState = InitialState::parseDeclaration(m_context, *this);

	parser.expect<std::string>(")");
}

////////////////////////////////////////////////////////////////////////////////////////////////////

void Problem::parseGoalSection()
{
	auto &parser = m_context.parser;

	parser.expect<std::string>("(");
	parser.expect<std::string>(":");
	parser.expect<std::string>("goal");

	// TODO: remove workaround
	expressions::Variables noParameters;

	ExpressionContext expressionContext(m_domain, this, noParameters);

	m_goal = parsePreconditionExpression(m_context, expressionContext);

	parser.expect<std::string>(")");
}

////////////////////////////////////////////////////////////////////////////////////////////////////

InitialState &Problem::initialState()
{
	BOOST_ASSERT(m_initialState);

	return *m_initialState;
}

////////////////////////////////////////////////////////////////////////////////////////////////////

const InitialState &Problem::initialState() const
{
	BOOST_ASSERT(m_initialState);

	return *m_initialState;
}

////////////////////////////////////////////////////////////////////////////////////////////////////

const Expression &Problem::goal() const
{
	BOOST_ASSERT(m_goal);

	return *m_goal;
}

////////////////////////////////////////////////////////////////////////////////////////////////////

void Problem::checkConsistency()
{
}

////////////////////////////////////////////////////////////////////////////////////////////////////

}
}
<|endoftext|>


<commit_before>#include "interface/usb.h"
#include "util/bytebuffer.h"
#include "util/log.h"
#include "config.h"
#include "gpio.h"

#ifdef CHIPKIT

#define USB_VBUS_ANALOG_INPUT A0

#endif

#define USB_HANDLE_MAX_WAIT_COUNT 35000

namespace gpio = openxc::gpio;
namespace commands = openxc::commands;

using openxc::util::log::debug;
using openxc::interface::usb::UsbDevice;
using openxc::interface::usb::UsbEndpoint;
using openxc::interface::usb::UsbEndpointDirection;
using openxc::gpio::GPIO_DIRECTION_INPUT;
using openxc::util::bytebuffer::processQueue;
using openxc::config::getConfiguration;

// This is a reference to the last packet read
extern volatile CTRL_TRF_SETUP SetupPkt;

boolean usbCallback(USB_EVENT event, void *pdata, word size) {
    // initial connection up to configure will be handled by the default
    // callback routine.
    getConfiguration()->usb.device.DefaultCBEventHandler(event, pdata, size);

    switch(event) {
    case EVENT_CONFIGURED:
        debug("USB Configured");
        getConfiguration()->usb.configured = true;

        for(int i = 0; i < ENDPOINT_COUNT; i++) {
            UsbEndpoint* endpoint = &getConfiguration()->usb.endpoints[i];
            if(endpoint->direction == UsbEndpointDirection::USB_ENDPOINT_DIRECTION_OUT) {
                getConfiguration()->usb.device.EnableEndpoint(endpoint->address,
                        USB_OUT_ENABLED|USB_HANDSHAKE_ENABLED|USB_DISALLOW_SETUP);
            } else {
                getConfiguration()->usb.device.EnableEndpoint(endpoint->address,
                        USB_IN_ENABLED|USB_HANDSHAKE_ENABLED|USB_DISALLOW_SETUP);
            }
        }
        break;

    case EVENT_EP0_REQUEST:
        // TODO read payload
        commands::handleControlCommand(commands::Command(SetupPkt.bRequest),
                NULL, 0);
        break;

    default:
        break;
    }
    return true;
}

bool openxc::interface::usb::sendControlMessage(UsbDevice* usbDevice,
        uint8_t* data, size_t length) {
    if(usbDevice->configured) {
        usbDevice->device.EP0SendRAMPtr(data, length, USB_EP0_INCLUDE_ZERO);
        return true;
    }
    return false;
}

bool vbusEnabled() {
#ifdef USB_VBUS_ANALOG_INPUT
    return analogRead(USB_VBUS_ANALOG_INPUT) > 100;
#else
    return true;
#endif
}

bool waitForHandle(UsbDevice* usbDevice, UsbEndpoint* endpoint) {
    int i = 0;
    while(usbDevice->configured &&
            usbDevice->device.HandleBusy(endpoint->deviceToHostHandle)) {
        ++i;
        if(i > USB_HANDLE_MAX_WAIT_COUNT) {
            // The reason we want to exit this loop early is that if USB is
            // attached and configured, but the host isn't sending an IN
            // requests, we will block here forever. As it is, it still slows
            // down UART transfers quite a bit, so setting configured = false
            // ASAP is important.

            // This can get really noisy when running but I want to leave it in
            // because it' useful to enable when debugging.
            // debug("USB most likely not connected or at least not requesting "
                    // "IN transfers - bailing out of handle waiting");
            return false;
        }
    }
    return true;
}

void openxc::interface::usb::processSendQueue(UsbDevice* usbDevice) {
    if(usbDevice->configured && !vbusEnabled()) {
        debug("USB no longer detected - marking unconfigured");
        usbDevice->configured = false;
        return;
    }

    for(int i = 0; i < ENDPOINT_COUNT; i++) {
        UsbEndpoint* endpoint = &usbDevice->endpoints[i];

        // Don't touch usbDevice->sendBuffer if there's still a pending transfer
        if(!waitForHandle(usbDevice, endpoint)) {
            return;
        }

        while(usbDevice->configured &&
                !QUEUE_EMPTY(uint8_t, &endpoint->queue)) {
            int byteCount = 0;
            while(!QUEUE_EMPTY(uint8_t, &endpoint->queue) &&
                    byteCount < USB_SEND_BUFFER_SIZE) {
                endpoint->sendBuffer[byteCount++] = QUEUE_POP(uint8_t,
                        &endpoint->queue);
            }

            int nextByteIndex = 0;
            while(nextByteIndex < byteCount) {
                // Make sure the USB write is 100% complete before messing with this
                // buffer after we copy the message into it - the Microchip library
                // doesn't copy the data to its own internal buffer. See #171 for
                // background on this issue.
                // TODO instead of dropping, replace POP above with a SNAPSHOT
                // and POP off only exactly how many bytes were sent after the
                // fact.
                // TODO in order for this not to fail too often I had to increase
                // the USB_HANDLE_MAX_WAIT_COUNT. that may be OK since now we have
                // VBUS detection.
                if(!waitForHandle(usbDevice, endpoint)) {
                    debug("USB not responding in a timely fashion, dropped data");
                    return;
                }

                int bytesToTransfer = min(MAX_USB_PACKET_SIZE_BYTES,
                        byteCount - nextByteIndex);
                endpoint->deviceToHostHandle = usbDevice->device.GenWrite(
                        endpoint->address,
                        &endpoint->sendBuffer[nextByteIndex], bytesToTransfer);
                nextByteIndex += bytesToTransfer;
            }
        }
    }
}

void openxc::interface::usb::initialize(UsbDevice* usbDevice) {
    usb::initializeCommon(usbDevice);
    usbDevice->device = USBDevice(usbCallback);
    usbDevice->device.InitializeSystem(false);
#ifdef USB_VBUS_ANALOG_INPUT
    gpio::setDirection(0, USB_VBUS_ANALOG_INPUT, GPIO_DIRECTION_INPUT);
#endif
    debug("Done.");
}

void openxc::interface::usb::deinitialize(UsbDevice* usbDevice) {
    // disable USB (notifies stack we are disabling)
    USBModuleDisable();

    // Could not find a ready-made function or macro
    // in the USB library to actually turn off the module.
    // USBModuleDisable() is close to what we want, but it
    // sets the ON bit to 1 for some reason.
    // So, easy solution is just go right to the control register to power off
    // the USB peripheral.
    U1PWRCCLR = (1 << 0);
}

/* Private: Arm the given endpoint for a read from the device to host.
 *
 * This also puts a NUL char in the beginning of the buffer so you don't get
 * confused that it's still a valid message.
 *
 * device - the CAN USB device to arm the endpoint on
 * endpoint - the endpoint to arm.
 * buffer - the destination buffer for the next OUT transfer.
 */
void armForRead(UsbDevice* usbDevice, UsbEndpoint* endpoint) {
    endpoint->receiveBuffer[0] = 0;
    endpoint->hostToDeviceHandle = usbDevice->device.GenRead(
            endpoint->address, (uint8_t*)endpoint->receiveBuffer,
            endpoint->size);
}

void openxc::interface::usb::read(UsbDevice* device, UsbEndpoint* endpoint,
        commands::IncomingMessageCallback callback) {
    if(!device->device.HandleBusy(endpoint->hostToDeviceHandle)) {
        if(endpoint->receiveBuffer[0] != '\0') {
            for(int i = 0; i < endpoint->size; i++) {
                if(!QUEUE_PUSH(uint8_t, &endpoint->queue,
                            endpoint->receiveBuffer[i])) {
                    debug("Dropped write from host -- queue is full");
                }
            }
            processQueue(&endpoint->queue, callback);
        }
        armForRead(device, endpoint);
    }
}
<commit_msg>Work around watchdog issues on PIC32 by feeding when USB is blocked.<commit_after>#include "interface/usb.h"
#include "util/bytebuffer.h"
#include "util/log.h"
#include "power.h"
#include "config.h"
#include "gpio.h"

#ifdef CHIPKIT

#define USB_VBUS_ANALOG_INPUT A0

#endif

#define USB_HANDLE_MAX_WAIT_COUNT 35000

namespace gpio = openxc::gpio;
namespace commands = openxc::commands;

using openxc::util::log::debug;
using openxc::interface::usb::UsbDevice;
using openxc::interface::usb::UsbEndpoint;
using openxc::interface::usb::UsbEndpointDirection;
using openxc::gpio::GPIO_DIRECTION_INPUT;
using openxc::util::bytebuffer::processQueue;
using openxc::config::getConfiguration;

// This is a reference to the last packet read
extern volatile CTRL_TRF_SETUP SetupPkt;

boolean usbCallback(USB_EVENT event, void *pdata, word size) {
    // initial connection up to configure will be handled by the default
    // callback routine.
    getConfiguration()->usb.device.DefaultCBEventHandler(event, pdata, size);

    switch(event) {
    case EVENT_CONFIGURED:
        debug("USB Configured");
        getConfiguration()->usb.configured = true;

        for(int i = 0; i < ENDPOINT_COUNT; i++) {
            UsbEndpoint* endpoint = &getConfiguration()->usb.endpoints[i];
            if(endpoint->direction == UsbEndpointDirection::USB_ENDPOINT_DIRECTION_OUT) {
                getConfiguration()->usb.device.EnableEndpoint(endpoint->address,
                        USB_OUT_ENABLED|USB_HANDSHAKE_ENABLED|USB_DISALLOW_SETUP);
            } else {
                getConfiguration()->usb.device.EnableEndpoint(endpoint->address,
                        USB_IN_ENABLED|USB_HANDSHAKE_ENABLED|USB_DISALLOW_SETUP);
            }
        }
        break;

    case EVENT_EP0_REQUEST:
        // TODO read payload
        commands::handleControlCommand(commands::Command(SetupPkt.bRequest),
                NULL, 0);
        break;

    default:
        break;
    }
    return true;
}

bool openxc::interface::usb::sendControlMessage(UsbDevice* usbDevice,
        uint8_t* data, size_t length) {
    if(usbDevice->configured) {
        usbDevice->device.EP0SendRAMPtr(data, length, USB_EP0_INCLUDE_ZERO);
        return true;
    }
    return false;
}

bool vbusEnabled() {
#ifdef USB_VBUS_ANALOG_INPUT
    return analogRead(USB_VBUS_ANALOG_INPUT) > 100;
#else
    return true;
#endif
}

bool waitForHandle(UsbDevice* usbDevice, UsbEndpoint* endpoint) {
    int i = 0;
    while(usbDevice->configured &&
            usbDevice->device.HandleBusy(endpoint->deviceToHostHandle)) {
        ++i;
        if(i > USB_HANDLE_MAX_WAIT_COUNT) {
            // The reason we want to exit this loop early is that if USB is
            // attached and configured, but the host isn't sending an IN
            // requests, we will block here forever. As it is, it still slows
            // down UART transfers quite a bit, so setting configured = false
            // ASAP is important.

            // This can get really noisy when running but I want to leave it in
            // because it' useful to enable when debugging.
            // debug("USB most likely not connected or at least not requesting "
                    // "IN transfers - bailing out of handle waiting");
            // TODO if USB is attached but not reading, this can block so much
            // that the watchdog doesn't get fed. There has to be a better way
            // to use USB on the PIC32!
            openxc::power::feedWatchdog();
            return false;
        }
    }
    return true;
}

void openxc::interface::usb::processSendQueue(UsbDevice* usbDevice) {
    if(usbDevice->configured && !vbusEnabled()) {
        debug("USB no longer detected - marking unconfigured");
        usbDevice->configured = false;
        return;
    }

    for(int i = 0; i < ENDPOINT_COUNT; i++) {
        UsbEndpoint* endpoint = &usbDevice->endpoints[i];

        // Don't touch usbDevice->sendBuffer if there's still a pending transfer
        if(!waitForHandle(usbDevice, endpoint)) {
            return;
        }

        while(usbDevice->configured &&
                !QUEUE_EMPTY(uint8_t, &endpoint->queue)) {
            int byteCount = 0;
            while(!QUEUE_EMPTY(uint8_t, &endpoint->queue) &&
                    byteCount < USB_SEND_BUFFER_SIZE) {
                endpoint->sendBuffer[byteCount++] = QUEUE_POP(uint8_t,
                        &endpoint->queue);
            }

            int nextByteIndex = 0;
            while(nextByteIndex < byteCount) {
                // Make sure the USB write is 100% complete before messing with this
                // buffer after we copy the message into it - the Microchip library
                // doesn't copy the data to its own internal buffer. See #171 for
                // background on this issue.
                // TODO instead of dropping, replace POP above with a SNAPSHOT
                // and POP off only exactly how many bytes were sent after the
                // fact.
                // TODO in order for this not to fail too often I had to increase
                // the USB_HANDLE_MAX_WAIT_COUNT. that may be OK since now we have
                // VBUS detection.
                if(!waitForHandle(usbDevice, endpoint)) {
                    debug("USB not responding in a timely fashion, dropped data");
                    return;
                }

                int bytesToTransfer = min(MAX_USB_PACKET_SIZE_BYTES,
                        byteCount - nextByteIndex);
                endpoint->deviceToHostHandle = usbDevice->device.GenWrite(
                        endpoint->address,
                        &endpoint->sendBuffer[nextByteIndex], bytesToTransfer);
                nextByteIndex += bytesToTransfer;
            }
        }
    }
}

void openxc::interface::usb::initialize(UsbDevice* usbDevice) {
    usb::initializeCommon(usbDevice);
    usbDevice->device = USBDevice(usbCallback);
    usbDevice->device.InitializeSystem(false);
#ifdef USB_VBUS_ANALOG_INPUT
    gpio::setDirection(0, USB_VBUS_ANALOG_INPUT, GPIO_DIRECTION_INPUT);
#endif
    debug("Done.");
}

void openxc::interface::usb::deinitialize(UsbDevice* usbDevice) {
    // disable USB (notifies stack we are disabling)
    USBModuleDisable();

    // Could not find a ready-made function or macro
    // in the USB library to actually turn off the module.
    // USBModuleDisable() is close to what we want, but it
    // sets the ON bit to 1 for some reason.
    // So, easy solution is just go right to the control register to power off
    // the USB peripheral.
    U1PWRCCLR = (1 << 0);
}

/* Private: Arm the given endpoint for a read from the device to host.
 *
 * This also puts a NUL char in the beginning of the buffer so you don't get
 * confused that it's still a valid message.
 *
 * device - the CAN USB device to arm the endpoint on
 * endpoint - the endpoint to arm.
 * buffer - the destination buffer for the next OUT transfer.
 */
void armForRead(UsbDevice* usbDevice, UsbEndpoint* endpoint) {
    endpoint->receiveBuffer[0] = 0;
    endpoint->hostToDeviceHandle = usbDevice->device.GenRead(
            endpoint->address, (uint8_t*)endpoint->receiveBuffer,
            endpoint->size);
}

void openxc::interface::usb::read(UsbDevice* device, UsbEndpoint* endpoint,
        commands::IncomingMessageCallback callback) {
    if(!device->device.HandleBusy(endpoint->hostToDeviceHandle)) {
        if(endpoint->receiveBuffer[0] != '\0') {
            for(int i = 0; i < endpoint->size; i++) {
                if(!QUEUE_PUSH(uint8_t, &endpoint->queue,
                            endpoint->receiveBuffer[i])) {
                    debug("Dropped write from host -- queue is full");
                }
            }
            processQueue(&endpoint->queue, callback);
        }
        armForRead(device, endpoint);
    }
}
<|endoftext|>


<commit_before>// Scintilla source code edit control
/** @file CallTip.cxx
 ** Code for displaying call tips.
 **/
// Copyright 1998-2001 by Neil Hodgson <neilh@scintilla.org>
// The License.txt file describes the conditions under which this software may be distributed.

#include <stdlib.h>
#include <string.h>

#include "Platform.h"

#include "Scintilla.h"
#include "CallTip.h"
#include <stdio.h>

#ifdef SCI_NAMESPACE
using namespace Scintilla;
#endif

static const int insetX = 5;    // text inset in x from calltip border
static const int widthArrow = 14;

CallTip::CallTip() {
	wCallTip = 0;
	inCallTipMode = false;
	posStartCallTip = 0;
	val = 0;
	rectUp = PRectangle(0,0,0,0);
	rectDown = PRectangle(0,0,0,0);
	lineHeight = 1;
	startHighlight = 0;
	endHighlight = 0;
	tabSize = 0;
	useStyleCallTip = false;    // for backwards compatibility

#ifdef __APPLE__
	// proper apple colours for the default
	colourBG.desired = ColourDesired(0xff, 0xff, 0xc6);
	colourUnSel.desired = ColourDesired(0, 0, 0);
#else
	colourBG.desired = ColourDesired(0xff, 0xff, 0xff);
	colourUnSel.desired = ColourDesired(0x80, 0x80, 0x80);
#endif
	colourSel.desired = ColourDesired(0, 0, 0x80);
	colourShade.desired = ColourDesired(0, 0, 0);
	colourLight.desired = ColourDesired(0xc0, 0xc0, 0xc0);
}

CallTip::~CallTip() {
	font.Release();
	wCallTip.Destroy();
	delete []val;
	val = 0;
}

void CallTip::RefreshColourPalette(Palette &pal, bool want) {
	pal.WantFind(colourBG, want);
	pal.WantFind(colourUnSel, want);
	pal.WantFind(colourSel, want);
	pal.WantFind(colourShade, want);
	pal.WantFind(colourLight, want);
}

// Although this test includes 0, we should never see a \0 character.
static bool IsArrowCharacter(char ch) {
	return (ch == 0) || (ch == '\001') || (ch == '\002');
}

// We ignore tabs unless a tab width has been set.
bool CallTip::IsTabCharacter(char ch) {
	return (tabSize > 0) && (ch == '\t');
}

int CallTip::NextTabPos(int x) {
	if (tabSize > 0) {              // paranoia... not called unless this is true
		x -= insetX;                // position relative to text
		x = (x + tabSize) / tabSize;  // tab "number"
		return tabSize*x + insetX;  // position of next tab
	} else {
		return x + 1;                 // arbitrary
	}
}

// Draw a section of the call tip that does not include \n in one colour.
// The text may include up to numEnds tabs or arrow characters.
void CallTip::DrawChunk(Surface *surface, int &x, const char *s,
	int posStart, int posEnd, int ytext, PRectangle rcClient,
	bool highlight, bool draw) {
	s += posStart;
	int len = posEnd - posStart;

	// Divide the text into sections that are all text, or that are
	// single arrows or single tab characters (if tabSize > 0).
	int maxEnd = 0;
	const int numEnds = 10;
	int ends[numEnds + 2];
	for (int i=0;i<len;i++) {
		if ((maxEnd < numEnds) &&
		        (IsArrowCharacter(s[i]) || IsTabCharacter(s[i])) ) {
			if (i > 0)
				ends[maxEnd++] = i;
			ends[maxEnd++] = i+1;
		}
	}
	ends[maxEnd++] = len;
	int startSeg = 0;
	int xEnd;
	for (int seg = 0; seg<maxEnd; seg++) {
		int endSeg = ends[seg];
		if (endSeg > startSeg) {
			if (IsArrowCharacter(s[startSeg])) {
				bool upArrow = s[startSeg] == '\001';
				rcClient.left = x;
				rcClient.right = rcClient.left + widthArrow;
				if (draw) {
					const int halfWidth = widthArrow / 2 - 3;
					const int centreX = rcClient.left + widthArrow / 2 - 1;
					const int centreY = (rcClient.top + rcClient.bottom) / 2;
					surface->FillRectangle(rcClient, colourBG.allocated);
					PRectangle rcClientInner(rcClient.left + 1, rcClient.top + 1,
					                         rcClient.right - 2, rcClient.bottom - 1);
					surface->FillRectangle(rcClientInner, colourUnSel.allocated);

					if (upArrow) {      // Up arrow
						Point pts[] = {
    						Point(centreX - halfWidth, centreY + halfWidth / 2),
    						Point(centreX + halfWidth, centreY + halfWidth / 2),
    						Point(centreX, centreY - halfWidth + halfWidth / 2),
						};
						surface->Polygon(pts, sizeof(pts) / sizeof(pts[0]),
                 						colourBG.allocated, colourBG.allocated);
					} else {            // Down arrow
						Point pts[] = {
    						Point(centreX - halfWidth, centreY - halfWidth / 2),
    						Point(centreX + halfWidth, centreY - halfWidth / 2),
    						Point(centreX, centreY + halfWidth - halfWidth / 2),
						};
						surface->Polygon(pts, sizeof(pts) / sizeof(pts[0]),
                 						colourBG.allocated, colourBG.allocated);
					}
				}
				xEnd = rcClient.right;
				offsetMain = xEnd;
				if (upArrow) {
					rectUp = rcClient;
				} else {
					rectDown = rcClient;
				}
			} else if (IsTabCharacter(s[startSeg])) {
				xEnd = NextTabPos(x);
			} else {
				xEnd = x + surface->WidthText(font, s + startSeg, endSeg - startSeg);
				if (draw) {
					rcClient.left = x;
					rcClient.right = xEnd;
					surface->DrawTextTransparent(rcClient, font, ytext,
										s+startSeg, endSeg - startSeg,
					                             highlight ? colourSel.allocated : colourUnSel.allocated);
				}
			}
			x = xEnd;
			startSeg = endSeg;
		}
	}
}

int CallTip::PaintContents(Surface *surfaceWindow, bool draw) {
	PRectangle rcClientPos = wCallTip.GetClientPosition();
	PRectangle rcClientSize(0, 0, rcClientPos.right - rcClientPos.left,
	                        rcClientPos.bottom - rcClientPos.top);
	PRectangle rcClient(1, 1, rcClientSize.right - 1, rcClientSize.bottom - 1);

	// To make a nice small call tip window, it is only sized to fit most normal characters without accents
	int ascent = surfaceWindow->Ascent(font) - surfaceWindow->InternalLeading(font);

	// For each line...
	// Draw the definition in three parts: before highlight, highlighted, after highlight
	int ytext = rcClient.top + ascent + 1;
	rcClient.bottom = ytext + surfaceWindow->Descent(font) + 1;
	char *chunkVal = val;
	bool moreChunks = true;
	int maxWidth = 0;

	while (moreChunks) {
		char *chunkEnd = strchr(chunkVal, '\n');
		if (chunkEnd == NULL) {
			chunkEnd = chunkVal + strlen(chunkVal);
			moreChunks = false;
		}
		int chunkOffset = chunkVal - val;
		int chunkLength = chunkEnd - chunkVal;
		int chunkEndOffset = chunkOffset + chunkLength;
		int thisStartHighlight = Platform::Maximum(startHighlight, chunkOffset);
		thisStartHighlight = Platform::Minimum(thisStartHighlight, chunkEndOffset);
		thisStartHighlight -= chunkOffset;
		int thisEndHighlight = Platform::Maximum(endHighlight, chunkOffset);
		thisEndHighlight = Platform::Minimum(thisEndHighlight, chunkEndOffset);
		thisEndHighlight -= chunkOffset;
		rcClient.top = ytext - ascent - 1;

		int x = insetX;     // start each line at this inset

		DrawChunk(surfaceWindow, x, chunkVal, 0, thisStartHighlight,
			ytext, rcClient, false, draw);
		DrawChunk(surfaceWindow, x, chunkVal, thisStartHighlight, thisEndHighlight,
			ytext, rcClient, true, draw);
		DrawChunk(surfaceWindow, x, chunkVal, thisEndHighlight, chunkLength,
			ytext, rcClient, false, draw);

		chunkVal = chunkEnd + 1;
		ytext += lineHeight;
		rcClient.bottom += lineHeight;
		maxWidth = Platform::Maximum(maxWidth, x);
	}
	return maxWidth;
}

void CallTip::PaintCT(Surface *surfaceWindow) {
	if (!val)
		return;
	PRectangle rcClientPos = wCallTip.GetClientPosition();
	PRectangle rcClientSize(0, 0, rcClientPos.right - rcClientPos.left,
	                        rcClientPos.bottom - rcClientPos.top);
	PRectangle rcClient(1, 1, rcClientSize.right - 1, rcClientSize.bottom - 1);

	surfaceWindow->FillRectangle(rcClient, colourBG.allocated);

	offsetMain = insetX;    // initial alignment assuming no arrows
	PaintContents(surfaceWindow, true);

#ifndef __APPLE__
	// OSX doesn't put borders on "help tags"
	// Draw a raised border around the edges of the window
	surfaceWindow->MoveTo(0, rcClientSize.bottom - 1);
	surfaceWindow->PenColour(colourShade.allocated);
	surfaceWindow->LineTo(rcClientSize.right - 1, rcClientSize.bottom - 1);
	surfaceWindow->LineTo(rcClientSize.right - 1, 0);
	surfaceWindow->PenColour(colourLight.allocated);
	surfaceWindow->LineTo(0, 0);
	surfaceWindow->LineTo(0, rcClientSize.bottom - 1);
#endif
}

void CallTip::MouseClick(Point pt) {
	clickPlace = 0;
	if (rectUp.Contains(pt))
		clickPlace = 1;
	if (rectDown.Contains(pt))
		clickPlace = 2;
}

PRectangle CallTip::CallTipStart(int pos, Point pt, const char *defn,
                                 const char *faceName, int size,
                                 int codePage_, int characterSet, Window &wParent) {
	clickPlace = 0;
	if (val)
		delete []val;
	val = 0;
	val = new char[strlen(defn) + 1];
	strcpy(val, defn);
	codePage = codePage_;
	Surface *surfaceMeasure = Surface::Allocate();
	if (!surfaceMeasure)
		return PRectangle();
	surfaceMeasure->Init(wParent.GetID());
	surfaceMeasure->SetUnicodeMode(SC_CP_UTF8 == codePage);
	surfaceMeasure->SetDBCSMode(codePage);
	startHighlight = 0;
	endHighlight = 0;
	inCallTipMode = true;
	posStartCallTip = pos;
	int deviceHeight = surfaceMeasure->DeviceHeightFont(size);
	font.Create(faceName, characterSet, deviceHeight, false, false);
	// Look for multiple lines in the text
	// Only support \n here - simply means container must avoid \r!
	int numLines = 1;
	const char *newline;
	const char *look = val;
	rectUp = PRectangle(0,0,0,0);
	rectDown = PRectangle(0,0,0,0);
	offsetMain = insetX;            // changed to right edge of any arrows
	int width = PaintContents(surfaceMeasure, false) + insetX;
	while ((newline = strchr(look, '\n')) != NULL) {
		look = newline + 1;
		numLines++;
	}
	lineHeight = surfaceMeasure->Height(font);

	// Extra line for border and an empty line at top and bottom. The returned
	// rectangle is aligned to the right edge of the last arrow encountered in
	// the tip text, else to the tip text left edge.
	int height = lineHeight * numLines - surfaceMeasure->InternalLeading(font) + 2 + 2;
	delete surfaceMeasure;
	return PRectangle(pt.x - offsetMain, pt.y + 1, pt.x + width - offsetMain, pt.y + 1 + height);
}

void CallTip::CallTipCancel() {
	inCallTipMode = false;
	if (wCallTip.Created()) {
		wCallTip.Destroy();
	}
}

void CallTip::SetHighlight(int start, int end) {
	// Avoid flashing by checking something has really changed
	if ((start != startHighlight) || (end != endHighlight)) {
		startHighlight = start;
		endHighlight = end;
		if (wCallTip.Created()) {
			wCallTip.InvalidateAll();
		}
	}
}

// Set the tab size (sizes > 0 enable the use of tabs). This also enables the
// use of the STYLE_CALLTIP.
void CallTip::SetTabSize(int tabSz) {
	tabSize = tabSz;
	useStyleCallTip = true;
}

// It might be better to have two access functions for this and to use
// them for all settings of colours.
void CallTip::SetForeBack(const ColourPair &fore, const ColourPair &back) {
	colourBG = back;
	colourUnSel = fore;
}
<commit_msg>Removed unnecessary check for NULL.<commit_after>// Scintilla source code edit control
/** @file CallTip.cxx
 ** Code for displaying call tips.
 **/
// Copyright 1998-2001 by Neil Hodgson <neilh@scintilla.org>
// The License.txt file describes the conditions under which this software may be distributed.

#include <stdlib.h>
#include <string.h>

#include "Platform.h"

#include "Scintilla.h"
#include "CallTip.h"
#include <stdio.h>

#ifdef SCI_NAMESPACE
using namespace Scintilla;
#endif

static const int insetX = 5;    // text inset in x from calltip border
static const int widthArrow = 14;

CallTip::CallTip() {
	wCallTip = 0;
	inCallTipMode = false;
	posStartCallTip = 0;
	val = 0;
	rectUp = PRectangle(0,0,0,0);
	rectDown = PRectangle(0,0,0,0);
	lineHeight = 1;
	startHighlight = 0;
	endHighlight = 0;
	tabSize = 0;
	useStyleCallTip = false;    // for backwards compatibility

#ifdef __APPLE__
	// proper apple colours for the default
	colourBG.desired = ColourDesired(0xff, 0xff, 0xc6);
	colourUnSel.desired = ColourDesired(0, 0, 0);
#else
	colourBG.desired = ColourDesired(0xff, 0xff, 0xff);
	colourUnSel.desired = ColourDesired(0x80, 0x80, 0x80);
#endif
	colourSel.desired = ColourDesired(0, 0, 0x80);
	colourShade.desired = ColourDesired(0, 0, 0);
	colourLight.desired = ColourDesired(0xc0, 0xc0, 0xc0);
}

CallTip::~CallTip() {
	font.Release();
	wCallTip.Destroy();
	delete []val;
	val = 0;
}

void CallTip::RefreshColourPalette(Palette &pal, bool want) {
	pal.WantFind(colourBG, want);
	pal.WantFind(colourUnSel, want);
	pal.WantFind(colourSel, want);
	pal.WantFind(colourShade, want);
	pal.WantFind(colourLight, want);
}

// Although this test includes 0, we should never see a \0 character.
static bool IsArrowCharacter(char ch) {
	return (ch == 0) || (ch == '\001') || (ch == '\002');
}

// We ignore tabs unless a tab width has been set.
bool CallTip::IsTabCharacter(char ch) {
	return (tabSize > 0) && (ch == '\t');
}

int CallTip::NextTabPos(int x) {
	if (tabSize > 0) {              // paranoia... not called unless this is true
		x -= insetX;                // position relative to text
		x = (x + tabSize) / tabSize;  // tab "number"
		return tabSize*x + insetX;  // position of next tab
	} else {
		return x + 1;                 // arbitrary
	}
}

// Draw a section of the call tip that does not include \n in one colour.
// The text may include up to numEnds tabs or arrow characters.
void CallTip::DrawChunk(Surface *surface, int &x, const char *s,
	int posStart, int posEnd, int ytext, PRectangle rcClient,
	bool highlight, bool draw) {
	s += posStart;
	int len = posEnd - posStart;

	// Divide the text into sections that are all text, or that are
	// single arrows or single tab characters (if tabSize > 0).
	int maxEnd = 0;
	const int numEnds = 10;
	int ends[numEnds + 2];
	for (int i=0;i<len;i++) {
		if ((maxEnd < numEnds) &&
		        (IsArrowCharacter(s[i]) || IsTabCharacter(s[i])) ) {
			if (i > 0)
				ends[maxEnd++] = i;
			ends[maxEnd++] = i+1;
		}
	}
	ends[maxEnd++] = len;
	int startSeg = 0;
	int xEnd;
	for (int seg = 0; seg<maxEnd; seg++) {
		int endSeg = ends[seg];
		if (endSeg > startSeg) {
			if (IsArrowCharacter(s[startSeg])) {
				bool upArrow = s[startSeg] == '\001';
				rcClient.left = x;
				rcClient.right = rcClient.left + widthArrow;
				if (draw) {
					const int halfWidth = widthArrow / 2 - 3;
					const int centreX = rcClient.left + widthArrow / 2 - 1;
					const int centreY = (rcClient.top + rcClient.bottom) / 2;
					surface->FillRectangle(rcClient, colourBG.allocated);
					PRectangle rcClientInner(rcClient.left + 1, rcClient.top + 1,
					                         rcClient.right - 2, rcClient.bottom - 1);
					surface->FillRectangle(rcClientInner, colourUnSel.allocated);

					if (upArrow) {      // Up arrow
						Point pts[] = {
    						Point(centreX - halfWidth, centreY + halfWidth / 2),
    						Point(centreX + halfWidth, centreY + halfWidth / 2),
    						Point(centreX, centreY - halfWidth + halfWidth / 2),
						};
						surface->Polygon(pts, sizeof(pts) / sizeof(pts[0]),
                 						colourBG.allocated, colourBG.allocated);
					} else {            // Down arrow
						Point pts[] = {
    						Point(centreX - halfWidth, centreY - halfWidth / 2),
    						Point(centreX + halfWidth, centreY - halfWidth / 2),
    						Point(centreX, centreY + halfWidth - halfWidth / 2),
						};
						surface->Polygon(pts, sizeof(pts) / sizeof(pts[0]),
                 						colourBG.allocated, colourBG.allocated);
					}
				}
				xEnd = rcClient.right;
				offsetMain = xEnd;
				if (upArrow) {
					rectUp = rcClient;
				} else {
					rectDown = rcClient;
				}
			} else if (IsTabCharacter(s[startSeg])) {
				xEnd = NextTabPos(x);
			} else {
				xEnd = x + surface->WidthText(font, s + startSeg, endSeg - startSeg);
				if (draw) {
					rcClient.left = x;
					rcClient.right = xEnd;
					surface->DrawTextTransparent(rcClient, font, ytext,
										s+startSeg, endSeg - startSeg,
					                             highlight ? colourSel.allocated : colourUnSel.allocated);
				}
			}
			x = xEnd;
			startSeg = endSeg;
		}
	}
}

int CallTip::PaintContents(Surface *surfaceWindow, bool draw) {
	PRectangle rcClientPos = wCallTip.GetClientPosition();
	PRectangle rcClientSize(0, 0, rcClientPos.right - rcClientPos.left,
	                        rcClientPos.bottom - rcClientPos.top);
	PRectangle rcClient(1, 1, rcClientSize.right - 1, rcClientSize.bottom - 1);

	// To make a nice small call tip window, it is only sized to fit most normal characters without accents
	int ascent = surfaceWindow->Ascent(font) - surfaceWindow->InternalLeading(font);

	// For each line...
	// Draw the definition in three parts: before highlight, highlighted, after highlight
	int ytext = rcClient.top + ascent + 1;
	rcClient.bottom = ytext + surfaceWindow->Descent(font) + 1;
	char *chunkVal = val;
	bool moreChunks = true;
	int maxWidth = 0;

	while (moreChunks) {
		char *chunkEnd = strchr(chunkVal, '\n');
		if (chunkEnd == NULL) {
			chunkEnd = chunkVal + strlen(chunkVal);
			moreChunks = false;
		}
		int chunkOffset = chunkVal - val;
		int chunkLength = chunkEnd - chunkVal;
		int chunkEndOffset = chunkOffset + chunkLength;
		int thisStartHighlight = Platform::Maximum(startHighlight, chunkOffset);
		thisStartHighlight = Platform::Minimum(thisStartHighlight, chunkEndOffset);
		thisStartHighlight -= chunkOffset;
		int thisEndHighlight = Platform::Maximum(endHighlight, chunkOffset);
		thisEndHighlight = Platform::Minimum(thisEndHighlight, chunkEndOffset);
		thisEndHighlight -= chunkOffset;
		rcClient.top = ytext - ascent - 1;

		int x = insetX;     // start each line at this inset

		DrawChunk(surfaceWindow, x, chunkVal, 0, thisStartHighlight,
			ytext, rcClient, false, draw);
		DrawChunk(surfaceWindow, x, chunkVal, thisStartHighlight, thisEndHighlight,
			ytext, rcClient, true, draw);
		DrawChunk(surfaceWindow, x, chunkVal, thisEndHighlight, chunkLength,
			ytext, rcClient, false, draw);

		chunkVal = chunkEnd + 1;
		ytext += lineHeight;
		rcClient.bottom += lineHeight;
		maxWidth = Platform::Maximum(maxWidth, x);
	}
	return maxWidth;
}

void CallTip::PaintCT(Surface *surfaceWindow) {
	if (!val)
		return;
	PRectangle rcClientPos = wCallTip.GetClientPosition();
	PRectangle rcClientSize(0, 0, rcClientPos.right - rcClientPos.left,
	                        rcClientPos.bottom - rcClientPos.top);
	PRectangle rcClient(1, 1, rcClientSize.right - 1, rcClientSize.bottom - 1);

	surfaceWindow->FillRectangle(rcClient, colourBG.allocated);

	offsetMain = insetX;    // initial alignment assuming no arrows
	PaintContents(surfaceWindow, true);

#ifndef __APPLE__
	// OSX doesn't put borders on "help tags"
	// Draw a raised border around the edges of the window
	surfaceWindow->MoveTo(0, rcClientSize.bottom - 1);
	surfaceWindow->PenColour(colourShade.allocated);
	surfaceWindow->LineTo(rcClientSize.right - 1, rcClientSize.bottom - 1);
	surfaceWindow->LineTo(rcClientSize.right - 1, 0);
	surfaceWindow->PenColour(colourLight.allocated);
	surfaceWindow->LineTo(0, 0);
	surfaceWindow->LineTo(0, rcClientSize.bottom - 1);
#endif
}

void CallTip::MouseClick(Point pt) {
	clickPlace = 0;
	if (rectUp.Contains(pt))
		clickPlace = 1;
	if (rectDown.Contains(pt))
		clickPlace = 2;
}

PRectangle CallTip::CallTipStart(int pos, Point pt, const char *defn,
                                 const char *faceName, int size,
                                 int codePage_, int characterSet, Window &wParent) {
	clickPlace = 0;
	delete []val;
	val = 0;
	val = new char[strlen(defn) + 1];
	strcpy(val, defn);
	codePage = codePage_;
	Surface *surfaceMeasure = Surface::Allocate();
	if (!surfaceMeasure)
		return PRectangle();
	surfaceMeasure->Init(wParent.GetID());
	surfaceMeasure->SetUnicodeMode(SC_CP_UTF8 == codePage);
	surfaceMeasure->SetDBCSMode(codePage);
	startHighlight = 0;
	endHighlight = 0;
	inCallTipMode = true;
	posStartCallTip = pos;
	int deviceHeight = surfaceMeasure->DeviceHeightFont(size);
	font.Create(faceName, characterSet, deviceHeight, false, false);
	// Look for multiple lines in the text
	// Only support \n here - simply means container must avoid \r!
	int numLines = 1;
	const char *newline;
	const char *look = val;
	rectUp = PRectangle(0,0,0,0);
	rectDown = PRectangle(0,0,0,0);
	offsetMain = insetX;            // changed to right edge of any arrows
	int width = PaintContents(surfaceMeasure, false) + insetX;
	while ((newline = strchr(look, '\n')) != NULL) {
		look = newline + 1;
		numLines++;
	}
	lineHeight = surfaceMeasure->Height(font);

	// Extra line for border and an empty line at top and bottom. The returned
	// rectangle is aligned to the right edge of the last arrow encountered in
	// the tip text, else to the tip text left edge.
	int height = lineHeight * numLines - surfaceMeasure->InternalLeading(font) + 2 + 2;
	delete surfaceMeasure;
	return PRectangle(pt.x - offsetMain, pt.y + 1, pt.x + width - offsetMain, pt.y + 1 + height);
}

void CallTip::CallTipCancel() {
	inCallTipMode = false;
	if (wCallTip.Created()) {
		wCallTip.Destroy();
	}
}

void CallTip::SetHighlight(int start, int end) {
	// Avoid flashing by checking something has really changed
	if ((start != startHighlight) || (end != endHighlight)) {
		startHighlight = start;
		endHighlight = end;
		if (wCallTip.Created()) {
			wCallTip.InvalidateAll();
		}
	}
}

// Set the tab size (sizes > 0 enable the use of tabs). This also enables the
// use of the STYLE_CALLTIP.
void CallTip::SetTabSize(int tabSz) {
	tabSize = tabSz;
	useStyleCallTip = true;
}

// It might be better to have two access functions for this and to use
// them for all settings of colours.
void CallTip::SetForeBack(const ColourPair &fore, const ColourPair &back) {
	colourBG = back;
	colourUnSel = fore;
}
<|endoftext|>


<commit_before>#ifndef CLIENT_WS_HPP
#define	CLIENT_WS_HPP

#include <boost/asio.hpp>

#include <unordered_map>
#include <map>
#include <iostream>
#include <regex>
#include <random>

namespace SimpleWeb {
    template <class socket_type>
    class ClientBase {
    public:
        class Response {
            friend class ClientBase<socket_type>;

        public:
            std::string http_version, status_code;

            std::istream content;

            std::unordered_map<std::string, std::string> header;

        private:
            boost::asio::streambuf content_buffer;

            Response(): content(&content_buffer) {};
        };

        std::shared_ptr<Response> request(const std::string& request_type, const std::string& path="/",
                const std::map<std::string, std::string>& header={{}}) {
            std::stringstream empty_ss;
            return request(request_type, path, empty_ss, header);
        }

        std::shared_ptr<Response> request(const std::string& request_type, const std::string& path, std::ostream& content,
                const std::map<std::string, std::string>& header={{}}) {
            std::string corrected_path=path;
            if(corrected_path=="")
                corrected_path="/";

            content.seekp(0, std::ios::end);
            size_t content_length=content.tellp();
            content.seekp(0, std::ios::beg);

            boost::asio::streambuf write_buffer;
            std::ostream write_stream(&write_buffer);
            write_stream << request_type << " " << corrected_path << " HTTP/1.1\r\n";
            write_stream << "Host: " << host << "\r\n";
            for(auto& h: header) {
                write_stream << h.first << ": " << h.second << "\r\n";
            }
            if(content_length>0)
                write_stream << "Content-Length: " << std::to_string(content_length) << "\r\n";
            write_stream << "\r\n";
            if(content_length>0)
                write_stream << content.rdbuf();

            std::shared_ptr<Response> response(new Response());

            try {
                connect();

                boost::asio::write(*socket, write_buffer);

                size_t bytes_transferred = boost::asio::read_until(*socket, response->content_buffer, "\r\n\r\n");

                size_t num_additional_bytes=response->content_buffer.size()-bytes_transferred;

                parse_response_header(response, response->content);

                if(response->header.count("Content-Length")>0) {
                    boost::asio::read(*socket, response->content_buffer,
                            boost::asio::transfer_exactly(stoull(response->header["Content-Length"])-num_additional_bytes));
                }
                else if(response->header.count("Transfer-Encoding")>0 && response->header["Transfer-Encoding"]=="chunked") {
                    boost::asio::streambuf streambuf;
                    std::ostream content(&streambuf);

                    size_t length;
                    std::string buffer;
                    do {
                        size_t bytes_transferred = boost::asio::read_until(*socket, response->content_buffer, "\r\n");
                        std::string line;
                        getline(response->content, line);
                        bytes_transferred-=line.size()+1;
                        line.pop_back();
                        length=stoull(line, 0, 16);

                        size_t num_additional_bytes=response->content_buffer.size()-bytes_transferred;

                        if((2+length)>num_additional_bytes) {
                            boost::asio::read(*socket, response->content_buffer,
                                boost::asio::transfer_exactly(2+length-num_additional_bytes));
                        }

                        buffer.resize(length);
                        response->content.read(&buffer[0], length);
                        content.write(&buffer[0], length);

                        //Remove "\r\n"
                        response->content.get();
                        response->content.get();
                    } while(length>0);

                    std::ostream response_content_output_stream(&response->content_buffer);
                    response_content_output_stream << content.rdbuf();
                }
            }
            catch(const std::exception& e) {
                socket_error=true;
                throw std::invalid_argument(e.what());
            }

            return response;
        }

    protected:
        boost::asio::io_service asio_io_service;
        boost::asio::ip::tcp::endpoint asio_endpoint;
        boost::asio::ip::tcp::resolver asio_resolver;

        std::shared_ptr<socket_type> socket;
        bool socket_error;

        std::string host;
        unsigned short port;

        ClientBase(const std::string& host_port, unsigned short default_port) :
                asio_resolver(asio_io_service), socket_error(false) {
            std::regex e("^([^:/]+):?([0-9]*)$");

            std::smatch sm;

            if(std::regex_match(host_port, sm, e)) {
                host=sm[1];
                port=default_port;
                if(sm[2]!="")
                    port=(unsigned short)std::stoul(sm[2]);
                asio_endpoint=boost::asio::ip::tcp::endpoint(boost::asio::ip::tcp::v4(), port);
            }
            else {
                throw std::invalid_argument("Error parsing host_port");
            }
        }

        virtual void connect()=0;

        void parse_response_header(std::shared_ptr<Response> response, std::istream& stream) const {
            std::smatch sm;

            //Parse the first line
            std::string line;
            getline(stream, line);
            line.pop_back();

            std::regex e("^HTTP/([^ ]*) (.*)$");
            if(std::regex_match(line, sm, e)) {
                response->http_version=sm[1];
                response->status_code=sm[2];

                e="^([^:]*): ?(.*)$";
                //Parse the rest of the header
                bool matched;
                do {
                    getline(stream, line);
                    line.pop_back();
                    matched=std::regex_match(line, sm, e);
                    if(matched) {
                        response->header[sm[1]]=sm[2];
                    }

                } while(matched==true);
            }
        }
    };

    template<class socket_type>
    class Client : public ClientBase<socket_type> {};

    typedef boost::asio::ip::tcp::socket HTTP;

    template<>
    class Client<HTTP> : public ClientBase<HTTP> {
    public:
        Client(const std::string& server_port_path) : ClientBase<HTTP>::ClientBase(server_port_path, 80) {
            socket=std::make_shared<HTTP>(asio_io_service);
        };

    private:
        void connect() {
            if(socket_error || !socket->is_open()) {
                boost::asio::ip::tcp::resolver::query query(host, std::to_string(port));
                boost::asio::connect(*socket, asio_resolver.resolve(query));
                socket_error=false;
            }
        }
    };
}

#endif	/* CLIENT_WS_HPP */<commit_msg>Fixed default parameter of header for ClientBase::request<commit_after>#ifndef CLIENT_WS_HPP
#define	CLIENT_WS_HPP

#include <boost/asio.hpp>

#include <unordered_map>
#include <map>
#include <iostream>
#include <regex>
#include <random>

namespace SimpleWeb {
    template <class socket_type>
    class ClientBase {
    public:
        class Response {
            friend class ClientBase<socket_type>;

        public:
            std::string http_version, status_code;

            std::istream content;

            std::unordered_map<std::string, std::string> header;

        private:
            boost::asio::streambuf content_buffer;

            Response(): content(&content_buffer) {};
        };

        std::shared_ptr<Response> request(const std::string& request_type, const std::string& path="/",
                const std::map<std::string, std::string>& header=std::map<std::string, std::string>()) {
            std::stringstream empty_ss;
            return request(request_type, path, empty_ss, header);
        }

        std::shared_ptr<Response> request(const std::string& request_type, const std::string& path, std::ostream& content,
                const std::map<std::string, std::string>& header=std::map<std::string, std::string>()) {
            std::string corrected_path=path;
            if(corrected_path=="")
                corrected_path="/";

            content.seekp(0, std::ios::end);
            size_t content_length=content.tellp();
            content.seekp(0, std::ios::beg);

            boost::asio::streambuf write_buffer;
            std::ostream write_stream(&write_buffer);
            write_stream << request_type << " " << corrected_path << " HTTP/1.1\r\n";
            write_stream << "Host: " << host << "\r\n";
            for(auto& h: header) {
                write_stream << h.first << ": " << h.second << "\r\n";
            }
            if(content_length>0)
                write_stream << "Content-Length: " << std::to_string(content_length) << "\r\n";
            write_stream << "\r\n";
            if(content_length>0)
                write_stream << content.rdbuf();

            std::shared_ptr<Response> response(new Response());

            try {
                connect();

                boost::asio::write(*socket, write_buffer);

                size_t bytes_transferred = boost::asio::read_until(*socket, response->content_buffer, "\r\n\r\n");

                size_t num_additional_bytes=response->content_buffer.size()-bytes_transferred;

                parse_response_header(response, response->content);

                if(response->header.count("Content-Length")>0) {
                    boost::asio::read(*socket, response->content_buffer,
                            boost::asio::transfer_exactly(stoull(response->header["Content-Length"])-num_additional_bytes));
                }
                else if(response->header.count("Transfer-Encoding")>0 && response->header["Transfer-Encoding"]=="chunked") {
                    boost::asio::streambuf streambuf;
                    std::ostream content(&streambuf);

                    size_t length;
                    std::string buffer;
                    do {
                        size_t bytes_transferred = boost::asio::read_until(*socket, response->content_buffer, "\r\n");
                        std::string line;
                        getline(response->content, line);
                        bytes_transferred-=line.size()+1;
                        line.pop_back();
                        length=stoull(line, 0, 16);

                        size_t num_additional_bytes=response->content_buffer.size()-bytes_transferred;

                        if((2+length)>num_additional_bytes) {
                            boost::asio::read(*socket, response->content_buffer,
                                boost::asio::transfer_exactly(2+length-num_additional_bytes));
                        }

                        buffer.resize(length);
                        response->content.read(&buffer[0], length);
                        content.write(&buffer[0], length);

                        //Remove "\r\n"
                        response->content.get();
                        response->content.get();
                    } while(length>0);

                    std::ostream response_content_output_stream(&response->content_buffer);
                    response_content_output_stream << content.rdbuf();
                }
            }
            catch(const std::exception& e) {
                socket_error=true;
                throw std::invalid_argument(e.what());
            }

            return response;
        }

    protected:
        boost::asio::io_service asio_io_service;
        boost::asio::ip::tcp::endpoint asio_endpoint;
        boost::asio::ip::tcp::resolver asio_resolver;

        std::shared_ptr<socket_type> socket;
        bool socket_error;

        std::string host;
        unsigned short port;

        ClientBase(const std::string& host_port, unsigned short default_port) :
                asio_resolver(asio_io_service), socket_error(false) {
            std::regex e("^([^:/]+):?([0-9]*)$");

            std::smatch sm;

            if(std::regex_match(host_port, sm, e)) {
                host=sm[1];
                port=default_port;
                if(sm[2]!="")
                    port=(unsigned short)std::stoul(sm[2]);
                asio_endpoint=boost::asio::ip::tcp::endpoint(boost::asio::ip::tcp::v4(), port);
            }
            else {
                throw std::invalid_argument("Error parsing host_port");
            }
        }

        virtual void connect()=0;

        void parse_response_header(std::shared_ptr<Response> response, std::istream& stream) const {
            std::smatch sm;

            //Parse the first line
            std::string line;
            getline(stream, line);
            line.pop_back();

            std::regex e("^HTTP/([^ ]*) (.*)$");
            if(std::regex_match(line, sm, e)) {
                response->http_version=sm[1];
                response->status_code=sm[2];

                e="^([^:]*): ?(.*)$";
                //Parse the rest of the header
                bool matched;
                do {
                    getline(stream, line);
                    line.pop_back();
                    matched=std::regex_match(line, sm, e);
                    if(matched) {
                        response->header[sm[1]]=sm[2];
                    }

                } while(matched==true);
            }
        }
    };

    template<class socket_type>
    class Client : public ClientBase<socket_type> {};

    typedef boost::asio::ip::tcp::socket HTTP;

    template<>
    class Client<HTTP> : public ClientBase<HTTP> {
    public:
        Client(const std::string& server_port_path) : ClientBase<HTTP>::ClientBase(server_port_path, 80) {
            socket=std::make_shared<HTTP>(asio_io_service);
        };

    private:
        void connect() {
            if(socket_error || !socket->is_open()) {
                boost::asio::ip::tcp::resolver::query query(host, std::to_string(port));
                boost::asio::connect(*socket, asio_resolver.resolve(query));
                socket_error=false;
            }
        }
    };
}

#endif	/* CLIENT_WS_HPP */<|endoftext|>


<commit_before>#ifndef __STAN__PROB__DISTRIBUTIONS__UNIVARIATE__DISCRETE__POISSON_HPP__
#define __STAN__PROB__DISTRIBUTIONS__UNIVARIATE__DISCRETE__POISSON_HPP__

#include <limits>

#include <stan/agrad.hpp>
#include <stan/math/error_handling.hpp>
#include <stan/math/special_functions.hpp>
#include <stan/meta/traits.hpp>
#include <stan/prob/traits.hpp>
#include <stan/prob/constants.hpp>

namespace stan {

  namespace prob {

    // Poisson(n|lambda)  [lambda > 0;  n >= 0]
    template <bool propto,
              typename T_n, typename T_rate,
              class Policy>
    typename return_type<T_rate>::type
    poisson_log(const T_n& n, const T_rate& lambda,
                const Policy&) {

      static const char* function = "stan::prob::poisson_log(%1%)";

      using stan::math::check_not_nan;
      using stan::math::check_nonnegative;
      using stan::math::value_of;
      using stan::math::check_consistent_sizes;
      using stan::prob::include_summand;

      // check if any vectors are zero length
      if (!(stan::length(n)
            && stan::length(lambda)))
        return 0.0;

      // set up return value accumulator
      double logp(0.0);

      // validate args
      if (!check_nonnegative(function, n, "Random variable", &logp, Policy()))
        return logp;
      if (!check_not_nan(function, lambda,
                         "Rate parameter", &logp, Policy()))
        return logp;
      if (!check_nonnegative(function, lambda,
                             "Rate parameter", &logp, Policy()))
        return logp;
      if (!(check_consistent_sizes(function,
                                   n,lambda,
                                   "Random variable","Rate parameter",
                                   &logp, Policy())))
        return logp;

      // check if no variables are involved and prop-to
      if (!include_summand<propto,T_rate>::value)
        return 0.0;

      // set up expression templates wrapping scalars/vecs into vector views
      VectorView<const T_n> n_vec(n);
      VectorView<const T_rate> lambda_vec(lambda);
      size_t size = max_size(n, lambda);

      for (size_t i = 0; i < size; i++)
        if (std::isinf(lambda_vec[i]))
          return LOG_ZERO;
      for (size_t i = 0; i < size; i++)
        if (lambda_vec[i] == 0 && n_vec[i] != 0)
          return LOG_ZERO;

      // return accumulator with gradients
      agrad::OperandsAndPartials<T_rate> operands_and_partials(lambda);

      using stan::math::multiply_log;
      for (size_t i = 0; i < size; i++) {
        if (!(lambda_vec[i] == 0 && n_vec[i] == 0)) {
          if (include_summand<propto>::value)
            logp -= lgamma(n_vec[i] + 1.0);
          if (include_summand<propto,T_rate>::value)
            logp += multiply_log(n_vec[i], value_of(lambda_vec[i]))
              - value_of(lambda_vec[i]);
        }

        // gradients
        if (!is_constant_struct<T_rate>::value)
          operands_and_partials.d_x1[i] += n_vec[i] / value_of(lambda_vec[i]) - 1.0;

      }

      return operands_and_partials.to_var(logp);
    }

    template <bool propto,
              typename T_n,
              typename T_rate>
    inline
    typename return_type<T_rate>::type
    poisson_log(const T_n& n, const T_rate& lambda) {
      return poisson_log<propto>(n,lambda,stan::math::default_policy());
    }

    template <typename T_n,
              typename T_rate,
              class Policy>
    inline
    typename return_type<T_rate>::type
    poisson_log(const T_n& n, const T_rate& lambda,
                const Policy&) {
      return poisson_log<false>(n,lambda,Policy());
    }

    template <typename T_n,
              typename T_rate>
    inline
    typename return_type<T_rate>::type
    poisson_log(const T_n& n, const T_rate& lambda) {
      return poisson_log<false>(n,lambda,stan::math::default_policy());
    }

    // PoissonLog(n|alpha)  [n >= 0]   = Poisson(n|exp(alpha))
    template <bool propto,
              typename T_n, typename T_log_rate,
              class Policy>
    typename return_type<T_log_rate>::type
    poisson_log_log(const T_n& n, const T_log_rate& alpha,
		    const Policy&) {

      static const char* function = "stan::prob::poisson_log_log(%1%)";

      using std::exp;
      using stan::math::check_not_nan;
      using stan::math::check_nonnegative;
      using stan::math::value_of;
      using stan::math::check_consistent_sizes;
      using stan::prob::include_summand;

      // check if any vectors are zero length
      if (!(stan::length(n)
            && stan::length(alpha)))
        return 0.0;

      // set up return value accumulator
      double logp(0.0);

      // validate args
      if (!check_nonnegative(function, n, "Random variable", &logp, Policy()))
        return logp;
      if (!check_not_nan(function, alpha,
                         "Log rate parameter", &logp, Policy()))
        return logp;
      if (!(check_consistent_sizes(function,
                                   n,alpha,
                                   "Random variable","Log rate parameter",
                                   &logp, Policy())))
        return logp;

      // check if no variables are involved and prop-to
      if (!include_summand<propto,T_log_rate>::value)
        return 0.0;

      // set up expression templates wrapping scalars/vecs into vector views
      VectorView<const T_n> n_vec(n);
      VectorView<const T_log_rate> alpha_vec(alpha);
      size_t size = max_size(n, alpha);

      // FIXME: first loop size of alpha_vec, second loop if-ed for size==1
      for (size_t i = 0; i < size; i++)
        if (std::numeric_limits<double>::infinity() == alpha_vec[i])
          return LOG_ZERO;
      for (size_t i = 0; i < size; i++)
        if (-std::numeric_limits<double>::infinity() == alpha_vec[i]
            && n_vec[i] != 0)
          return LOG_ZERO;

      // return accumulator with gradients
      agrad::OperandsAndPartials<T_log_rate> operands_and_partials(alpha);

      // FIXME: cache value_of for alpha_vec?  faster if only one?

      using stan::math::multiply_log;
      for (size_t i = 0; i < size; i++) {
        if (!(alpha_vec[i] == -std::numeric_limits<double>::infinity()
              && n_vec[i] == 0)) {
          if (include_summand<propto>::value)
            logp -= lgamma(n_vec[i] + 1.0);
          if (include_summand<propto,T_log_rate>::value)
            logp += n_vec[i] * value_of(alpha_vec[i]) - exp(value_of(alpha_vec[i]));
        }

        // gradients
        if (!is_constant_struct<T_log_rate>::value)
          operands_and_partials.d_x1[i] += n_vec[i] - exp(value_of(alpha_vec[i]));
      }
      return operands_and_partials.to_var(logp);
    }

    template <bool propto,
              typename T_n,
              typename T_log_rate>
    inline
    typename return_type<T_log_rate>::type
    poisson_log_log(const T_n& n, const T_log_rate& alpha) {
      return poisson_log_log<propto>(n,alpha,stan::math::default_policy());
    }

    template <typename T_n,
              typename T_log_rate,
              class Policy>
    inline
    typename return_type<T_log_rate>::type
    poisson_log_log(const T_n& n, const T_log_rate& alpha,
		    const Policy&) {
      return poisson_log_log<false>(n,alpha,Policy());
    }

    template <typename T_n,
              typename T_log_rate>
    inline
    typename return_type<T_log_rate>::type
    poisson_log_log(const T_n& n, const T_log_rate& alpha) {
      return poisson_log_log<false>(n,alpha,stan::math::default_policy());
    }

    // Poisson CDF
    template <bool propto, typename T_n, typename T_rate, class Policy>
    typename return_type<T_rate>::type
    poisson_cdf(const T_n& n, const T_rate& lambda, const Policy&) {

      static const char* function = "stan::prob::poisson_cdf(%1%)";

      using stan::math::check_not_nan;
      using stan::math::check_nonnegative;
      using stan::math::value_of;
      using stan::math::check_consistent_sizes;
      using stan::prob::include_summand;

      // Ensure non-zero argument slengths
      if (!(stan::length(n) && stan::length(lambda)))
        return 0.0;

      double P(1.0);

      // Validate arguments
      if (!check_nonnegative(function, n, "Random variable", &P, Policy()))
        return P;

      if (!check_not_nan(function, lambda, "Rate parameter", &P, Policy()))
	return P;

      if (!check_nonnegative(function, lambda, "Rate parameter", &P, Policy()))
	return P;

      if (!(check_consistent_sizes(function, n,lambda,
				   "Random variable","Rate parameter",
				   &P, Policy())))
	return P;

      // Return if everything is constant and only proportionality is required
      if (!include_summand<propto,T_rate>::value)
	return 0.0;

      // Wrap arguments into vector views
      VectorView<const T_n> n_vec(n);
      VectorView<const T_rate> lambda_vec(lambda);
      size_t size = max_size(n, lambda);

      // Validate vector views - redundant with the above validations?
      for (size_t i = 0; i < size; i++)
	if (std::isinf(lambda_vec[i]))
	  return LOG_ZERO;

      for (size_t i = 0; i < size; i++)
	if (lambda_vec[i] == 0 && n_vec[i] != 0)
	  return LOG_ZERO;

      // Compute vectorized CDF and gradient
      using stan::math::value_of;
      using boost::math::gamma_p_derivative;
      using boost::math::gamma_q;

      agrad::OperandsAndPartials<T_rate> operands_and_partials(lambda);

      for (size_t i = 0; i < size; i++) {
	const double n_dbl = value_of(n_vec[i]);
	const double lambda_dbl = value_of(lambda_vec[i]);

	const double Pi = gamma_q(n_dbl+1, lambda_dbl);
	P *= Pi;

	if (!is_constant_struct<T_rate>::value)
	  operands_and_partials.d_x1[i] -= gamma_p_derivative(n_dbl+1, lambda_dbl) / Pi;
      }
      if (!is_constant_struct<T_rate>::value) {
	for (size_t i = 0; i < stan::length(lambda); i++) {
	  operands_and_partials.d_x1[i] *= P;
	}
      }

      return operands_and_partials.to_var(P);
    }

    template <bool propto, typename T_n, typename T_rate>
    inline typename return_type<T_rate>::type
    poisson_cdf(const T_n& n, const T_rate& lambda) {
      return poisson_cdf<propto>(n, lambda, stan::math::default_policy());
    }

    template <typename T_n, typename T_rate, class Policy>
    inline typename return_type<T_rate>::type
    poisson_cdf(const T_n& n, const T_rate& lambda, const Policy&) {
      return poisson_cdf<false>(n, lambda, Policy());
    }

    template <typename T_n, typename T_rate>
    inline typename return_type<T_rate>::type
    poisson_cdf(const T_n& n, const T_rate& lambda) {
      return poisson_cdf<false>(n, lambda, stan::math::default_policy());
    }

  }
}
#endif
<commit_msg>Fixed boundary value behavior<commit_after>#ifndef __STAN__PROB__DISTRIBUTIONS__UNIVARIATE__DISCRETE__POISSON_HPP__
#define __STAN__PROB__DISTRIBUTIONS__UNIVARIATE__DISCRETE__POISSON_HPP__

#include <limits>

#include <stan/agrad.hpp>
#include <stan/math/error_handling.hpp>
#include <stan/math/special_functions.hpp>
#include <stan/meta/traits.hpp>
#include <stan/prob/traits.hpp>
#include <stan/prob/constants.hpp>

namespace stan {

  namespace prob {

    // Poisson(n|lambda)  [lambda > 0;  n >= 0]
    template <bool propto,
              typename T_n, typename T_rate,
              class Policy>
    typename return_type<T_rate>::type
    poisson_log(const T_n& n, const T_rate& lambda,
                const Policy&) {

      static const char* function = "stan::prob::poisson_log(%1%)";

      using stan::math::check_not_nan;
      using stan::math::check_nonnegative;
      using stan::math::value_of;
      using stan::math::check_consistent_sizes;
      using stan::prob::include_summand;

      // check if any vectors are zero length
      if (!(stan::length(n)
            && stan::length(lambda)))
        return 0.0;

      // set up return value accumulator
      double logp(0.0);

      // validate args
      if (!check_nonnegative(function, n, "Random variable", &logp, Policy()))
        return logp;
      if (!check_not_nan(function, lambda,
                         "Rate parameter", &logp, Policy()))
        return logp;
      if (!check_nonnegative(function, lambda,
                             "Rate parameter", &logp, Policy()))
        return logp;
      if (!(check_consistent_sizes(function,
                                   n,lambda,
                                   "Random variable","Rate parameter",
                                   &logp, Policy())))
        return logp;

      // check if no variables are involved and prop-to
      if (!include_summand<propto,T_rate>::value)
        return 0.0;

      // set up expression templates wrapping scalars/vecs into vector views
      VectorView<const T_n> n_vec(n);
      VectorView<const T_rate> lambda_vec(lambda);
      size_t size = max_size(n, lambda);

      for (size_t i = 0; i < size; i++)
        if (std::isinf(lambda_vec[i]))
          return LOG_ZERO;
      for (size_t i = 0; i < size; i++)
        if (lambda_vec[i] == 0 && n_vec[i] != 0)
          return LOG_ZERO;

      // return accumulator with gradients
      agrad::OperandsAndPartials<T_rate> operands_and_partials(lambda);

      using stan::math::multiply_log;
      for (size_t i = 0; i < size; i++) {
        if (!(lambda_vec[i] == 0 && n_vec[i] == 0)) {
          if (include_summand<propto>::value)
            logp -= lgamma(n_vec[i] + 1.0);
          if (include_summand<propto,T_rate>::value)
            logp += multiply_log(n_vec[i], value_of(lambda_vec[i]))
              - value_of(lambda_vec[i]);
        }

        // gradients
        if (!is_constant_struct<T_rate>::value)
          operands_and_partials.d_x1[i] += n_vec[i] / value_of(lambda_vec[i]) - 1.0;

      }

      return operands_and_partials.to_var(logp);
    }

    template <bool propto,
              typename T_n,
              typename T_rate>
    inline
    typename return_type<T_rate>::type
    poisson_log(const T_n& n, const T_rate& lambda) {
      return poisson_log<propto>(n,lambda,stan::math::default_policy());
    }

    template <typename T_n,
              typename T_rate,
              class Policy>
    inline
    typename return_type<T_rate>::type
    poisson_log(const T_n& n, const T_rate& lambda,
                const Policy&) {
      return poisson_log<false>(n,lambda,Policy());
    }

    template <typename T_n,
              typename T_rate>
    inline
    typename return_type<T_rate>::type
    poisson_log(const T_n& n, const T_rate& lambda) {
      return poisson_log<false>(n,lambda,stan::math::default_policy());
    }

    // PoissonLog(n|alpha)  [n >= 0]   = Poisson(n|exp(alpha))
    template <bool propto,
              typename T_n, typename T_log_rate,
              class Policy>
    typename return_type<T_log_rate>::type
    poisson_log_log(const T_n& n, const T_log_rate& alpha,
		    const Policy&) {

      static const char* function = "stan::prob::poisson_log_log(%1%)";

      using std::exp;
      using stan::math::check_not_nan;
      using stan::math::check_nonnegative;
      using stan::math::value_of;
      using stan::math::check_consistent_sizes;
      using stan::prob::include_summand;

      // check if any vectors are zero length
      if (!(stan::length(n)
            && stan::length(alpha)))
        return 0.0;

      // set up return value accumulator
      double logp(0.0);

      // validate args
      if (!check_nonnegative(function, n, "Random variable", &logp, Policy()))
        return logp;
      if (!check_not_nan(function, alpha,
                         "Log rate parameter", &logp, Policy()))
        return logp;
      if (!(check_consistent_sizes(function,
                                   n,alpha,
                                   "Random variable","Log rate parameter",
                                   &logp, Policy())))
        return logp;

      // check if no variables are involved and prop-to
      if (!include_summand<propto,T_log_rate>::value)
        return 0.0;

      // set up expression templates wrapping scalars/vecs into vector views
      VectorView<const T_n> n_vec(n);
      VectorView<const T_log_rate> alpha_vec(alpha);
      size_t size = max_size(n, alpha);

      // FIXME: first loop size of alpha_vec, second loop if-ed for size==1
      for (size_t i = 0; i < size; i++)
        if (std::numeric_limits<double>::infinity() == alpha_vec[i])
          return LOG_ZERO;
      for (size_t i = 0; i < size; i++)
        if (-std::numeric_limits<double>::infinity() == alpha_vec[i]
            && n_vec[i] != 0)
          return LOG_ZERO;

      // return accumulator with gradients
      agrad::OperandsAndPartials<T_log_rate> operands_and_partials(alpha);

      // FIXME: cache value_of for alpha_vec?  faster if only one?

      using stan::math::multiply_log;
      for (size_t i = 0; i < size; i++) {
        if (!(alpha_vec[i] == -std::numeric_limits<double>::infinity()
              && n_vec[i] == 0)) {
          if (include_summand<propto>::value)
            logp -= lgamma(n_vec[i] + 1.0);
          if (include_summand<propto,T_log_rate>::value)
            logp += n_vec[i] * value_of(alpha_vec[i]) - exp(value_of(alpha_vec[i]));
        }

        // gradients
        if (!is_constant_struct<T_log_rate>::value)
          operands_and_partials.d_x1[i] += n_vec[i] - exp(value_of(alpha_vec[i]));
      }
      return operands_and_partials.to_var(logp);
    }

    template <bool propto,
              typename T_n,
              typename T_log_rate>
    inline
    typename return_type<T_log_rate>::type
    poisson_log_log(const T_n& n, const T_log_rate& alpha) {
      return poisson_log_log<propto>(n,alpha,stan::math::default_policy());
    }

    template <typename T_n,
              typename T_log_rate,
              class Policy>
    inline
    typename return_type<T_log_rate>::type
    poisson_log_log(const T_n& n, const T_log_rate& alpha,
		    const Policy&) {
      return poisson_log_log<false>(n,alpha,Policy());
    }

    template <typename T_n,
              typename T_log_rate>
    inline
    typename return_type<T_log_rate>::type
    poisson_log_log(const T_n& n, const T_log_rate& alpha) {
      return poisson_log_log<false>(n,alpha,stan::math::default_policy());
    }

    // Poisson CDF
    template <bool propto, typename T_n, typename T_rate, class Policy>
    typename return_type<T_rate>::type
    poisson_cdf(const T_n& n, const T_rate& lambda, const Policy&) {

      static const char* function = "stan::prob::poisson_cdf(%1%)";

      using stan::math::check_not_nan;
      using stan::math::check_nonnegative;
      using stan::math::value_of;
      using stan::math::check_consistent_sizes;

      // Ensure non-zero argument slengths
      if (!(stan::length(n) && stan::length(lambda)))
        return 0.0;

      double P(1.0);

      // Validate arguments
      if (!check_not_nan(function, lambda, "Rate parameter", &P, Policy()))
          return P;

      if (!check_nonnegative(function, lambda, "Rate parameter", &P, Policy()))
          return P;

      if (!(check_consistent_sizes(function, n,lambda,
				   "Random variable","Rate parameter",
				   &P, Policy())))
          return P;

      // Return if everything is constant and only proportionality is required
      if (!include_summand<propto,T_rate>::value)
          return 0.0;

      // Wrap arguments into vector views
      VectorView<const T_n> n_vec(n);
      VectorView<const T_rate> lambda_vec(lambda);
      size_t size = max_size(n, lambda);

      // Compute vectorized CDF and gradient
      using stan::math::value_of;
      using boost::math::gamma_p_derivative;
      using boost::math::gamma_q;

      agrad::OperandsAndPartials<T_rate> operands_and_partials(lambda);

      std::fill(operands_and_partials.all_partials,
                  operands_and_partials.all_partials
                  + operands_and_partials.nvaris, 0.0);

      // Explicit return for extreme values
      // The gradients are technically ill-defined, but treated as zero
      for (size_t i = 0; i < stan::length(n); i++) {
          if (value_of(n_vec[i]) < 0)
              return operands_and_partials.to_var(0.0);
      }

      for (size_t i = 0; i < size; i++) {

          // Explicit results for extreme values
          // The gradients are technically ill-defined, but treated as zero
          if (value_of(n_vec[i]) == std::numeric_limits<double>::infinity()) {
              continue;
          }

          const double n_dbl = value_of(n_vec[i]);
          const double lambda_dbl = value_of(lambda_vec[i]);

          const double Pi = gamma_q(n_dbl+1, lambda_dbl);
          P *= Pi;

          if (!is_constant_struct<T_rate>::value) {
              operands_and_partials.d_x1[i] -= gamma_p_derivative(n_dbl + 1, lambda_dbl) / Pi;
          }

      }

      if (!is_constant_struct<T_rate>::value) {
          for(size_t i = 0; i < stan::length(lambda); ++i) operands_and_partials.d_x1[i] *= P;
      }

      return operands_and_partials.to_var(P);

    }

    template <bool propto, typename T_n, typename T_rate>
    inline typename return_type<T_rate>::type
    poisson_cdf(const T_n& n, const T_rate& lambda) {
      return poisson_cdf<propto>(n, lambda, stan::math::default_policy());
    }

    template <typename T_n, typename T_rate, class Policy>
    inline typename return_type<T_rate>::type
    poisson_cdf(const T_n& n, const T_rate& lambda, const Policy&) {
      return poisson_cdf<false>(n, lambda, Policy());
    }

    template <typename T_n, typename T_rate>
    inline typename return_type<T_rate>::type
    poisson_cdf(const T_n& n, const T_rate& lambda) {
      return poisson_cdf<false>(n, lambda, stan::math::default_policy());
    }

  }
}
#endif
<|endoftext|>


<commit_before>#include <memory>
#include <iostream>
#include <stdexcept>
#include "gamestates/playstate.hh"
#include "gamestates/startstate.hh"
#include "gamestates/playstate.hh"

StartState::StartState()
    : logo_load_time_{1000}, logo_size_{0}, logo_final_size_{0.8},
    logo_x_{0}, logo_y_{0}, wait_time_{1000}
{
    if (!logo_.loadFromFile("resources/logo.png"))
        throw std::logic_error("Could not load logo.");
    sf::Sprite s(logo_);
    logo_sprite_ = s;
    logo_sprite_.setPosition(logo_x_, logo_y_);
    logo_sprite_.setScale(logo_size_, logo_size_);
}

void StartState::draw(sf::RenderWindow& w)
{
    w.draw(logo_sprite_);
}

void StartState::update(unsigned elapsed_ms)
{
    // Initialisation of
    if (logo_size_ < logo_final_size_)
    {
        logo_size_ += logo_final_size_ * elapsed_ms / logo_load_time_;
        if (logo_size_ > logo_final_size_)
            logo_size_ = logo_final_size_;
    }
    else
        wait_time_ -= elapsed_ms;
    auto vect = logo_.getSize();
    float x = logo_x_ + (1 - logo_size_) * vect.x / 2;
    float y = logo_y_ + (1 - logo_size_) * vect.y / 2;
    logo_sprite_.setPosition(x, y);
    logo_sprite_.setScale(logo_size_, logo_size_);
    if (wait_time_ <= 0)
    {
        GameState::stack.pop_back();
        GameState::stack.push_back(
            std::make_shared<PlayState>("resources/map0.td42"));
    }
}
<commit_msg>Adding the possibilty to enter the path of a map file from the command line<commit_after>#include <memory>
#include <iostream>
#include <stdexcept>
#include "gamestates/playstate.hh"
#include "gamestates/startstate.hh"
#include "gamestates/playstate.hh"

StartState::StartState()
    : logo_load_time_{1000}, logo_size_{0}, logo_final_size_{0.8},
    logo_x_{0}, logo_y_{0}, wait_time_{1000}
{
    if (!logo_.loadFromFile("resources/logo.png"))
        throw std::logic_error("Could not load logo.");
    sf::Sprite s(logo_);
    logo_sprite_ = s;
    logo_sprite_.setPosition(logo_x_, logo_y_);
    logo_sprite_.setScale(logo_size_, logo_size_);
}

void StartState::draw(sf::RenderWindow& w)
{
    w.draw(logo_sprite_);
}

void StartState::update(unsigned elapsed_ms)
{
    // Initialisation of
    if (logo_size_ < logo_final_size_)
    {
        logo_size_ += logo_final_size_ * elapsed_ms / logo_load_time_;
        if (logo_size_ > logo_final_size_)
            logo_size_ = logo_final_size_;
    }
    else
        wait_time_ -= elapsed_ms;
    auto vect = logo_.getSize();
    float x = logo_x_ + (1 - logo_size_) * vect.x / 2;
    float y = logo_y_ + (1 - logo_size_) * vect.y / 2;
    logo_sprite_.setPosition(x, y);
    logo_sprite_.setScale(logo_size_, logo_size_);
    if (wait_time_ <= 0)
    {
        std::string default_map_path = "resources/map0.td42";
        std::string map_path;
        std::cout << "Enter map path (defaults to 'resources/map0.td42')";
        getline(std::cin, map_path);
        GameState::stack.pop_back();
        GameState::stack.push_back(std::make_shared<PlayState>(
            map_path.length() > 0 ? map_path : default_map_path));
    }
}
<|endoftext|>