<commit_before>/*
 * Copyright (c) 2012 Google
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met: redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer;
 * redistributions in binary form must reproduce the above copyright
 * notice, this list of conditions and the following disclaimer in the
 * documentation and/or other materials provided with the distribution;
 * neither the name of the copyright holders nor the names of its
 * contributors may be used to endorse or promote products derived from
 * this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 * Authors: Gabe Black
 */

#include <cassert>
#include <iostream>

#include "base/cprintf.hh"
#include "base/trie.hh"
#include "base/types.hh"
#include "unittest/unittest.hh"

using UnitTest::setCase;

typedef Trie<Addr, uint32_t> TestTrie;

int
main()
{
    // Create an empty Ptr and verify it's data pointer is NULL.
    setCase("An empty trie.");
    TestTrie trie1;
    trie1.dump("Empty");
    cprintf("\n\n");

    setCase("A single entry.");
    trie1.insert(0x0123456789abcdef, 40, (uint32_t *)(uintptr_t)(1));
    trie1.dump("One entry");
    cprintf("\n\n");

    setCase("Two entries, one on the way to the other.");
    TestTrie trie2;
    trie2.insert(0x0123456789abcdef, 40, (uint32_t *)(uintptr_t)(1));
    trie2.insert(0x0123456789abcdef, 36, (uint32_t *)(uintptr_t)(2));
    trie2.dump("Two entries inline v1");
    cprintf("\n\n");

    TestTrie trie3;
    trie3.insert(0x0123456789abcdef, 36, (uint32_t *)(uintptr_t)(2));
    trie3.insert(0x0123456789abcdef, 40, (uint32_t *)(uintptr_t)(1));
    trie3.dump("Two entries inline v2");
    cprintf("\n\n");

    setCase("Two entries on different paths.");
    TestTrie trie4;
    trie4.insert(0x0123456789abcdef, 40, (uint32_t *)(uintptr_t)(2));
    trie4.insert(0x0123456776543210, 40, (uint32_t *)(uintptr_t)(1));
    trie4.dump("Two split entries");
    cprintf("\n\n");

    setCase("Skipping past an entry but not two.");
    TestTrie trie5;
    trie5.insert(0x0123456789000000, 40, (uint32_t *)(uintptr_t)(4));
    trie5.insert(0x0123000000000000, 40, (uint32_t *)(uintptr_t)(1));
    trie5.insert(0x0123456780000000, 40, (uint32_t *)(uintptr_t)(3));
    trie5.insert(0x0123456700000000, 40, (uint32_t *)(uintptr_t)(2));
    trie5.dump("Complex insertion");
    cprintf("\n\n");

    setCase("Looking things up.");
    EXPECT_EQ((uintptr_t)trie5.lookup(0x0123000000000000), 1);
    EXPECT_EQ((uintptr_t)trie5.lookup(0x0123456700000000), 2);
    EXPECT_EQ((uintptr_t)trie5.lookup(0x0123456780000000), 3);
    EXPECT_EQ((uintptr_t)trie5.lookup(0x0123456789000000), 4);

    setCase("Removing entries.");
    TestTrie trie6;
    TestTrie::Handle node1, node2;
    trie6.insert(0x0123456789000000, 40, (uint32_t *)(uintptr_t)(4));
    trie6.insert(0x0123000000000000, 40, (uint32_t *)(uintptr_t)(1));
    trie6.insert(0x0123456780000000, 40, (uint32_t *)(uintptr_t)(3));
    node1 = trie6.insert(0x0123456700000000, 40, (uint32_t *)(uintptr_t)(2));
    node2 = trie6.insert(0x0123456700000000, 32, (uint32_t *)(uintptr_t)(10));
    trie6.dump("Fill before removal");
    cprintf("\n\n");

    EXPECT_EQ((uintptr_t)trie6.lookup(0x0123000000000000), 1);
    EXPECT_EQ((uintptr_t)trie6.lookup(0x0123456700000000), 10);
    EXPECT_EQ((uintptr_t)trie6.lookup(0x0123456780000000), 10);
    EXPECT_EQ((uintptr_t)trie6.lookup(0x0123456789000000), 10);

    trie6.remove(node2);
    trie6.dump("One node removed");
    cprintf("\n\n");

    EXPECT_EQ((uintptr_t)trie6.lookup(0x0123000000000000), 1);
    EXPECT_EQ((uintptr_t)trie6.lookup(0x0123456700000000), 2);
    EXPECT_EQ((uintptr_t)trie6.lookup(0x0123456780000000), 3);
    EXPECT_EQ((uintptr_t)trie6.lookup(0x0123456789000000), 4);

    trie6.remove(node1);
    trie6.dump("Two nodes removed");
    cprintf("\n\n");

    EXPECT_EQ((uintptr_t)trie6.lookup(0x0123000000000000), 1);
    EXPECT_EQ(trie6.lookup(0x0123456700000000), NULL);
    EXPECT_EQ((uintptr_t)trie6.lookup(0x0123456780000000), 3);
    EXPECT_EQ((uintptr_t)trie6.lookup(0x0123456789000000), 4);

    return UnitTest::printResults();
}
<commit_msg>tests: Add a ptr helper function trietest.<commit_after>/*
 * Copyright (c) 2012 Google
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met: redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer;
 * redistributions in binary form must reproduce the above copyright
 * notice, this list of conditions and the following disclaimer in the
 * documentation and/or other materials provided with the distribution;
 * neither the name of the copyright holders nor the names of its
 * contributors may be used to endorse or promote products derived from
 * this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 * Authors: Gabe Black
 */

#include <iostream>

#include "base/cprintf.hh"
#include "base/trie.hh"
#include "base/types.hh"
#include "unittest/unittest.hh"

using UnitTest::setCase;

typedef Trie<Addr, uint32_t> TestTrie;

namespace {

static inline uint32_t *ptr(uintptr_t val)
{
    return (uint32_t *)val;
}

} // anonymous namespace

int
main()
{
    // Create an empty Ptr and verify it's data pointer is NULL.
    setCase("An empty trie.");
    TestTrie trie1;
    trie1.dump("Empty");
    cprintf("\n\n");

    setCase("A single entry.");
    trie1.insert(0x0123456789abcdef, 40, ptr(1));
    trie1.dump("One entry");
    cprintf("\n\n");

    setCase("Two entries, one on the way to the other.");
    TestTrie trie2;
    trie2.insert(0x0123456789abcdef, 40, ptr(1));
    trie2.insert(0x0123456789abcdef, 36, ptr(2));
    trie2.dump("Two entries inline v1");
    cprintf("\n\n");

    TestTrie trie3;
    trie3.insert(0x0123456789abcdef, 36, ptr(2));
    trie3.insert(0x0123456789abcdef, 40, ptr(1));
    trie3.dump("Two entries inline v2");
    cprintf("\n\n");

    setCase("Two entries on different paths.");
    TestTrie trie4;
    trie4.insert(0x0123456789abcdef, 40, ptr(2));
    trie4.insert(0x0123456776543210, 40, ptr(1));
    trie4.dump("Two split entries");
    cprintf("\n\n");

    setCase("Skipping past an entry but not two.");
    TestTrie trie5;
    trie5.insert(0x0123456789000000, 40, ptr(4));
    trie5.insert(0x0123000000000000, 40, ptr(1));
    trie5.insert(0x0123456780000000, 40, ptr(3));
    trie5.insert(0x0123456700000000, 40, ptr(2));
    trie5.dump("Complex insertion");
    cprintf("\n\n");

    setCase("Looking things up.");
    EXPECT_EQ(trie5.lookup(0x0123000000000000), ptr(1));
    EXPECT_EQ(trie5.lookup(0x0123456700000000), ptr(2));
    EXPECT_EQ(trie5.lookup(0x0123456780000000), ptr(3));
    EXPECT_EQ(trie5.lookup(0x0123456789000000), ptr(4));

    setCase("Removing entries.");
    TestTrie trie6;
    TestTrie::Handle node1, node2;
    trie6.insert(0x0123456789000000, 40, ptr(4));
    trie6.insert(0x0123000000000000, 40, ptr(1));
    trie6.insert(0x0123456780000000, 40, ptr(3));
    node1 = trie6.insert(0x0123456700000000, 40, ptr(2));
    node2 = trie6.insert(0x0123456700000000, 32, ptr(10));
    trie6.dump("Fill before removal");
    cprintf("\n\n");

    EXPECT_EQ(trie6.lookup(0x0123000000000000), ptr(1));
    EXPECT_EQ(trie6.lookup(0x0123456700000000), ptr(10));
    EXPECT_EQ(trie6.lookup(0x0123456780000000), ptr(10));
    EXPECT_EQ(trie6.lookup(0x0123456789000000), ptr(10));

    trie6.remove(node2);
    trie6.dump("One node removed");
    cprintf("\n\n");

    EXPECT_EQ(trie6.lookup(0x0123000000000000), ptr(1));
    EXPECT_EQ(trie6.lookup(0x0123456700000000), ptr(2));
    EXPECT_EQ(trie6.lookup(0x0123456780000000), ptr(3));
    EXPECT_EQ(trie6.lookup(0x0123456789000000), ptr(4));

    trie6.remove(node1);
    trie6.dump("Two nodes removed");
    cprintf("\n\n");

    EXPECT_EQ(trie6.lookup(0x0123000000000000), ptr(1));
    EXPECT_EQ(trie6.lookup(0x0123456700000000), NULL);
    EXPECT_EQ(trie6.lookup(0x0123456780000000), ptr(3));
    EXPECT_EQ(trie6.lookup(0x0123456789000000), ptr(4));

    return UnitTest::printResults();
}
<|endoftext|>


<commit_before>#include "Base.h"
#include "Gamepad.h"
#include "Game.h"
#include "Button.h"

namespace gameplay
{

static std::vector<Gamepad*> __gamepads;

Gamepad::Gamepad(const char* formPath)
    : _id(""), _handle(0), _vendorId(0), _productId(0), _buttonCount(0), _joystickCount(0), _triggerCount(0), _form(NULL)
{
    GP_ASSERT(formPath);
    _form = Form::create(formPath);
    GP_ASSERT(_form);
    _form->setConsumeInputEvents(false);
    _id = _form->getId();
    _vendorString = "GamePlay";
    _productString = "Virtual Gamepad";

    for (int i = 0; i < 2; ++i)
    {
        _uiJoysticks[i] = NULL;
    }

    for (int i = 0; i < 20; ++i)
    {
        _uiButtons[i] = NULL;
    }

    bindGamepadControls(_form);
}

Gamepad::Gamepad(const char* id, GamepadHandle handle, unsigned int buttonCount, unsigned int joystickCount, unsigned int triggerCount,
                 unsigned int vendorId, unsigned int productId, char* vendorString, char* productString)
    : _id(id), _handle(handle), _vendorId(vendorId), _productId(productId), _vendorString(vendorString), _productString(productString),
      _buttonCount(buttonCount), _joystickCount(joystickCount), _triggerCount(triggerCount), _form(NULL)
{
}

Gamepad::~Gamepad()
{
    if (_form)
    {
        SAFE_RELEASE(_form);
    }
}

Gamepad* Gamepad::add(const char* id, GamepadHandle handle, unsigned int buttonCount, unsigned int joystickCount, unsigned int triggerCount,
    unsigned int vendorId, unsigned int productId, char* vendorString, char* productString)
{
    Gamepad* gamepad = new Gamepad(id, handle, buttonCount, joystickCount, triggerCount, vendorId, productId, vendorString, productString);

    __gamepads.push_back(gamepad);
    Game::getInstance()->gamepadEvent(CONNECTED_EVENT, gamepad);
    return gamepad;
}

Gamepad* Gamepad::add(const char* formPath)
{
    Gamepad* gamepad = new Gamepad(formPath);

    __gamepads.push_back(gamepad);
    Game::getInstance()->gamepadEvent(CONNECTED_EVENT, gamepad);
    return gamepad;
}

void Gamepad::remove(GamepadHandle handle)
{
    std::vector<Gamepad*>::iterator it = __gamepads.begin();
    do
    {
        Gamepad* gamepad = *it;
        if (gamepad->_handle == handle)
        {
            Game::getInstance()->gamepadEvent(DISCONNECTED_EVENT, gamepad);
            it = __gamepads.erase(it);
        }
        else
        {
        	it++;
        }
    } while (it != __gamepads.end());
}

void Gamepad::remove(Gamepad* gamepad)
{
    std::vector<Gamepad*>::iterator it = __gamepads.begin();
    do
    {
        Gamepad* g = *it;
        if (g == gamepad)
        {
            Game::getInstance()->gamepadEvent(DISCONNECTED_EVENT, g);
            it = __gamepads.erase(it);
        }
        else
        {
        	it++;
        }
    } while (it != __gamepads.end());
}

void Gamepad::bindGamepadControls(Container* container)
{
    std::vector<Control*> controls = container->getControls();
    std::vector<Control*>::iterator itr = controls.begin();

    for (; itr != controls.end(); itr++)
    {
        Control* control = *itr;
        GP_ASSERT(control);

        if (control->isContainer())
        {
            bindGamepadControls((Container*) control);
        }
        else if (std::strcmp("joystick", control->getType()) == 0)
        {
            Joystick* joystick = (Joystick*)control;
            _uiJoysticks[joystick->getIndex()] = joystick;
            _joystickCount++;
        }
        else if (std::strcmp("button", control->getType()) == 0)
        {
            Button* button = (Button*)control;
            _uiButtons[button->getDataBinding()] = button;
            _buttonCount++;
        }
    }
}

Gamepad* Gamepad::getGamepad(GamepadHandle handle)
{
    std::vector<Gamepad*>::const_iterator it;
    for (it = __gamepads.begin(); it != __gamepads.end(); it++)
    {
        Gamepad* gamepad = *it;
        if (!gamepad->isVirtual() && gamepad->_handle == handle)
        {
            return gamepad;
        }
    }

    return NULL;
}

std::vector<Gamepad*>* Gamepad::getGamepads()
{
    return &__gamepads;
}

Gamepad::ButtonMapping Gamepad::getButtonMappingFromString(const char* string)
{
    if (strcmp(string, "A") == 0 || strcmp(string, "BUTTON_A") == 0)
        return BUTTON_A;
    else if (strcmp(string, "B") == 0 || strcmp(string, "BUTTON_B") == 0)
        return BUTTON_B;
    else if (strcmp(string, "C") == 0 || strcmp(string, "BUTTON_C") == 0)
        return BUTTON_C;
    else if (strcmp(string, "X") == 0 || strcmp(string, "BUTTON_X") == 0)
        return BUTTON_X;
    else if (strcmp(string, "Y") == 0 || strcmp(string, "BUTTON_Y") == 0)
        return BUTTON_Y;
    else if (strcmp(string, "Z") == 0 || strcmp(string, "BUTTON_Z") == 0)
        return BUTTON_Z;
    else if (strcmp(string, "MENU1") == 0 || strcmp(string, "BUTTON_MENU1") == 0)
        return BUTTON_MENU1;
    else if (strcmp(string, "MENU2") == 0 || strcmp(string, "BUTTON_MENU2") == 0)
        return BUTTON_MENU2;
    else if (strcmp(string, "MENU3") == 0 || strcmp(string, "BUTTON_MENU3") == 0)
        return BUTTON_MENU3;
    else if (strcmp(string, "MENU4") == 0 || strcmp(string, "BUTTON_MENU4") == 0)
        return BUTTON_MENU4;
    else if (strcmp(string, "L1") == 0 || strcmp(string, "BUTTON_L1") == 0)
        return BUTTON_L1;
    else if (strcmp(string, "L2") == 0 || strcmp(string, "BUTTON_L2") == 0)
        return BUTTON_L2;
    else if (strcmp(string, "L3") == 0 || strcmp(string, "BUTTON_L3") == 0)
        return BUTTON_L3;
    else if (strcmp(string, "R1") == 0 || strcmp(string, "BUTTON_R1") == 0)
        return BUTTON_R1;
    else if (strcmp(string, "R2") == 0 || strcmp(string, "BUTTON_R2") == 0)
        return BUTTON_R2;
    else if (strcmp(string, "R3") == 0 || strcmp(string, "BUTTON_R3") == 0)
        return BUTTON_R3;
    else if (strcmp(string, "UP") == 0 || strcmp(string, "BUTTON_UP") == 0)
        return BUTTON_UP;
    else if (strcmp(string, "DOWN") == 0 || strcmp(string, "BUTTON_DOWN") == 0)
        return BUTTON_DOWN;
    else if (strcmp(string, "LEFT") == 0 || strcmp(string, "BUTTON_LEFT") == 0)
        return BUTTON_LEFT;
    else if (strcmp(string, "RIGHT") == 0 || strcmp(string, "BUTTON_RIGHT") == 0)
        return BUTTON_RIGHT;

    GP_WARN("Unknown GamepadButton string.");
    return BUTTON_A;
}

const char* Gamepad::getId() const
{
    return _id.c_str();
}

const unsigned int Gamepad::getVendorId() const
{
    return _vendorId;
}

const unsigned int Gamepad::getProductId() const
{
    return _productId;
}

const char* Gamepad::getVendorString() const
{
    return _vendorString.c_str();
}

const char* Gamepad::getProductString() const
{
    return _productString.c_str();
}

void Gamepad::update(float elapsedTime)
{
    if (_form && _form->isEnabled())
    {
        _form->update(elapsedTime);
    }
    else
    {
        Platform::pollGamepadState(this);
    }
}

void Gamepad::draw()
{
    if (_form && _form->isEnabled())
    {
        _form->draw();
    }
}

unsigned int Gamepad::getButtonCount() const
{
    return _buttonCount;
}

bool Gamepad::isButtonDown(ButtonMapping mapping) const
{
    if (_form)
    {
        Button* button = _uiButtons[mapping];
        if (button)
        {
            return (button->getState() == Control::ACTIVE);
        }
        else
        {
            return false;
        }
    }
    else if (_buttons & (1 << mapping))
    {
        return true;
    }

    return false;
}

unsigned int Gamepad::getJoystickCount() const
{
    return _joystickCount;
}

void Gamepad::getJoystickValues(unsigned int joystickId, Vector2* outValue) const
{
    GP_ASSERT(joystickId < _joystickCount);

    if (_form)
    {
        Joystick* joystick = _uiJoysticks[joystickId];
        if (joystick)
        {
            const Vector2& value = joystick->getValue();
            outValue->set(value.x, value.y);
        }
        else
        {
            outValue->set(0.0f, 0.0f);
        }
    }
    else
    {
        outValue->set(_joysticks[joystickId]);
    }
}

unsigned int Gamepad::getTriggerCount() const
{
    return _triggerCount;
}

float Gamepad::getTriggerValue(unsigned int triggerId) const
{
    GP_ASSERT(triggerId < _triggerCount);

    if (_form)
    {
        // Triggers are currently not available for virtual gamepads.
        return 0.0f;
    }
    else
    {
        return _triggers[triggerId];
    }
}

bool Gamepad::isVirtual() const
{
    return _form;
}

Form* Gamepad::getForm() const
{
    return _form;
}

}
<commit_msg>Minor fixes to Gamepad and LightTest.<commit_after>#include "Base.h"
#include "Gamepad.h"
#include "Game.h"
#include "Button.h"

namespace gameplay
{

static std::vector<Gamepad*> __gamepads;

Gamepad::Gamepad(const char* formPath)
    : _id(""), _handle(0), _vendorId(0), _productId(0), _buttonCount(0), _joystickCount(0), _triggerCount(0), _form(NULL)
{
    GP_ASSERT(formPath);
    _form = Form::create(formPath);
    GP_ASSERT(_form);
    _form->setConsumeInputEvents(false);
    _id = _form->getId();
    _vendorString = "None";
    _productString = "Virtual";

    for (int i = 0; i < 2; ++i)
    {
        _uiJoysticks[i] = NULL;
    }

    for (int i = 0; i < 20; ++i)
    {
        _uiButtons[i] = NULL;
    }

    bindGamepadControls(_form);
}

Gamepad::Gamepad(const char* id, GamepadHandle handle, unsigned int buttonCount, unsigned int joystickCount, unsigned int triggerCount,
                 unsigned int vendorId, unsigned int productId, char* vendorString, char* productString)
    : _id(id), _handle(handle), _vendorId(vendorId), _productId(productId), _vendorString(vendorString), _productString(productString),
      _buttonCount(buttonCount), _joystickCount(joystickCount), _triggerCount(triggerCount), _form(NULL)
{
}

Gamepad::~Gamepad()
{
    if (_form)
    {
        SAFE_RELEASE(_form);
    }
}

Gamepad* Gamepad::add(const char* id, GamepadHandle handle, unsigned int buttonCount, unsigned int joystickCount, unsigned int triggerCount,
    unsigned int vendorId, unsigned int productId, char* vendorString, char* productString)
{
    Gamepad* gamepad = new Gamepad(id, handle, buttonCount, joystickCount, triggerCount, vendorId, productId, vendorString, productString);

    __gamepads.push_back(gamepad);
    Game::getInstance()->gamepadEvent(CONNECTED_EVENT, gamepad);
    return gamepad;
}

Gamepad* Gamepad::add(const char* formPath)
{
    Gamepad* gamepad = new Gamepad(formPath);

    __gamepads.push_back(gamepad);
    Game::getInstance()->gamepadEvent(CONNECTED_EVENT, gamepad);
    return gamepad;
}

void Gamepad::remove(GamepadHandle handle)
{
    std::vector<Gamepad*>::iterator it = __gamepads.begin();
    do
    {
        Gamepad* gamepad = *it;
        if (gamepad->_handle == handle)
        {
            Game::getInstance()->gamepadEvent(DISCONNECTED_EVENT, gamepad);
            it = __gamepads.erase(it);
        }
        else
        {
        	it++;
        }
    } while (it != __gamepads.end());
}

void Gamepad::remove(Gamepad* gamepad)
{
    std::vector<Gamepad*>::iterator it = __gamepads.begin();
    do
    {
        Gamepad* g = *it;
        if (g == gamepad)
        {
            Game::getInstance()->gamepadEvent(DISCONNECTED_EVENT, g);
            it = __gamepads.erase(it);
        }
        else
        {
        	it++;
        }
    } while (it != __gamepads.end());
}

void Gamepad::bindGamepadControls(Container* container)
{
    std::vector<Control*> controls = container->getControls();
    std::vector<Control*>::iterator itr = controls.begin();

    for (; itr != controls.end(); itr++)
    {
        Control* control = *itr;
        GP_ASSERT(control);

        if (control->isContainer())
        {
            bindGamepadControls((Container*) control);
        }
        else if (std::strcmp("joystick", control->getType()) == 0)
        {
            Joystick* joystick = (Joystick*)control;
            _uiJoysticks[joystick->getIndex()] = joystick;
            _joystickCount++;
        }
        else if (std::strcmp("button", control->getType()) == 0)
        {
            Button* button = (Button*)control;
            _uiButtons[button->getDataBinding()] = button;
            _buttonCount++;
        }
    }
}

Gamepad* Gamepad::getGamepad(GamepadHandle handle)
{
    std::vector<Gamepad*>::const_iterator it;
    for (it = __gamepads.begin(); it != __gamepads.end(); it++)
    {
        Gamepad* gamepad = *it;
        if (!gamepad->isVirtual() && gamepad->_handle == handle)
        {
            return gamepad;
        }
    }

    return NULL;
}

std::vector<Gamepad*>* Gamepad::getGamepads()
{
    return &__gamepads;
}

Gamepad::ButtonMapping Gamepad::getButtonMappingFromString(const char* string)
{
    if (strcmp(string, "A") == 0 || strcmp(string, "BUTTON_A") == 0)
        return BUTTON_A;
    else if (strcmp(string, "B") == 0 || strcmp(string, "BUTTON_B") == 0)
        return BUTTON_B;
    else if (strcmp(string, "C") == 0 || strcmp(string, "BUTTON_C") == 0)
        return BUTTON_C;
    else if (strcmp(string, "X") == 0 || strcmp(string, "BUTTON_X") == 0)
        return BUTTON_X;
    else if (strcmp(string, "Y") == 0 || strcmp(string, "BUTTON_Y") == 0)
        return BUTTON_Y;
    else if (strcmp(string, "Z") == 0 || strcmp(string, "BUTTON_Z") == 0)
        return BUTTON_Z;
    else if (strcmp(string, "MENU1") == 0 || strcmp(string, "BUTTON_MENU1") == 0)
        return BUTTON_MENU1;
    else if (strcmp(string, "MENU2") == 0 || strcmp(string, "BUTTON_MENU2") == 0)
        return BUTTON_MENU2;
    else if (strcmp(string, "MENU3") == 0 || strcmp(string, "BUTTON_MENU3") == 0)
        return BUTTON_MENU3;
    else if (strcmp(string, "MENU4") == 0 || strcmp(string, "BUTTON_MENU4") == 0)
        return BUTTON_MENU4;
    else if (strcmp(string, "L1") == 0 || strcmp(string, "BUTTON_L1") == 0)
        return BUTTON_L1;
    else if (strcmp(string, "L2") == 0 || strcmp(string, "BUTTON_L2") == 0)
        return BUTTON_L2;
    else if (strcmp(string, "L3") == 0 || strcmp(string, "BUTTON_L3") == 0)
        return BUTTON_L3;
    else if (strcmp(string, "R1") == 0 || strcmp(string, "BUTTON_R1") == 0)
        return BUTTON_R1;
    else if (strcmp(string, "R2") == 0 || strcmp(string, "BUTTON_R2") == 0)
        return BUTTON_R2;
    else if (strcmp(string, "R3") == 0 || strcmp(string, "BUTTON_R3") == 0)
        return BUTTON_R3;
    else if (strcmp(string, "UP") == 0 || strcmp(string, "BUTTON_UP") == 0)
        return BUTTON_UP;
    else if (strcmp(string, "DOWN") == 0 || strcmp(string, "BUTTON_DOWN") == 0)
        return BUTTON_DOWN;
    else if (strcmp(string, "LEFT") == 0 || strcmp(string, "BUTTON_LEFT") == 0)
        return BUTTON_LEFT;
    else if (strcmp(string, "RIGHT") == 0 || strcmp(string, "BUTTON_RIGHT") == 0)
        return BUTTON_RIGHT;

    GP_WARN("Unknown GamepadButton string.");
    return BUTTON_A;
}

const char* Gamepad::getId() const
{
    return _id.c_str();
}

const unsigned int Gamepad::getVendorId() const
{
    return _vendorId;
}

const unsigned int Gamepad::getProductId() const
{
    return _productId;
}

const char* Gamepad::getVendorString() const
{
    return _vendorString.c_str();
}

const char* Gamepad::getProductString() const
{
    return _productString.c_str();
}

void Gamepad::update(float elapsedTime)
{
    if (_form && _form->isEnabled())
    {
        _form->update(elapsedTime);
    }
    else
    {
        Platform::pollGamepadState(this);
    }
}

void Gamepad::draw()
{
    if (_form && _form->isEnabled())
    {
        _form->draw();
    }
}

unsigned int Gamepad::getButtonCount() const
{
    return _buttonCount;
}

bool Gamepad::isButtonDown(ButtonMapping mapping) const
{
    if (_form)
    {
        Button* button = _uiButtons[mapping];
        if (button)
        {
            return (button->getState() == Control::ACTIVE);
        }
        else
        {
            return false;
        }
    }
    else if (_buttons & (1 << mapping))
    {
        return true;
    }

    return false;
}

unsigned int Gamepad::getJoystickCount() const
{
    return _joystickCount;
}

void Gamepad::getJoystickValues(unsigned int joystickId, Vector2* outValue) const
{
    GP_ASSERT(joystickId < _joystickCount);

    if (_form)
    {
        Joystick* joystick = _uiJoysticks[joystickId];
        if (joystick)
        {
            const Vector2& value = joystick->getValue();
            outValue->set(value.x, value.y);
        }
        else
        {
            outValue->set(0.0f, 0.0f);
        }
    }
    else
    {
        outValue->set(_joysticks[joystickId]);
    }
}

unsigned int Gamepad::getTriggerCount() const
{
    return _triggerCount;
}

float Gamepad::getTriggerValue(unsigned int triggerId) const
{
    GP_ASSERT(triggerId < _triggerCount);

    if (_form)
    {
        // Triggers are currently not available for virtual gamepads.
        return 0.0f;
    }
    else
    {
        return _triggers[triggerId];
    }
}

bool Gamepad::isVirtual() const
{
    return _form;
}

Form* Gamepad::getForm() const
{
    return _form;
}

}
<|endoftext|>


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

#include "card.hpp"
#include "game.hpp"
#include "input_helper.hpp"

using namespace std;

bool check_play_again();

int main() {

  int num_decks = 1;
  int shuffle_shoe = 15;
  Game game(num_decks, shuffle_shoe);

  cout << "Welcome to the game of blackjack!" << endl;

  bool play_again = true;
  while(play_again) {

    game.play_new_hand();

    int chips = game.get_player_chip_count();
    cout << "You have " << chips << " chips" << endl;

    if (chips > 0)
      play_again = check_play_again();
    else {
      cout << "You are out of chips." << endl;
      play_again = false;
    }
  }
  cout << "Thank you for playing!" << endl;

  return 0;
}

bool check_play_again() {

  string prompt = "Would you like to keep playing? (y/n) ";
  char play_again = get_y_or_n_from_user(prompt);
  if (play_again == 'y')
    return true;
  else
    return false;
}
<commit_msg>Changed the default number of decks to 3.<commit_after>#include <iostream>
#include <vector>

#include "card.hpp"
#include "game.hpp"
#include "input_helper.hpp"

using namespace std;

bool check_play_again();

int main() {

  int num_decks = 3;
  int shuffle_shoe = 15;
  Game game(num_decks, shuffle_shoe);

  cout << "Welcome to the game of blackjack!" << endl;

  bool play_again = true;
  while(play_again) {

    game.play_new_hand();

    int chips = game.get_player_chip_count();
    cout << "You have " << chips << " chips" << endl;

    if (chips > 0)
      play_again = check_play_again();
    else {
      cout << "You are out of chips." << endl;
      play_again = false;
    }
  }
  cout << "Thank you for playing!" << endl;

  return 0;
}

bool check_play_again() {

  string prompt = "Would you like to keep playing? (y/n) ";
  char play_again = get_y_or_n_from_user(prompt);
  if (play_again == 'y')
    return true;
  else
    return false;
}
<|endoftext|>


<commit_before>#include <gtest/gtest.h>
#include <iostream>
#include <fstream>
#include <istream>
#include <exception>
#include <stdexcept>

#include "stan/gm/ast.hpp"
#include "stan/gm/parser.hpp"
#include <stan/gm/generator.hpp>
#include <stan/gm/grammars/program_grammar.hpp>
#include <stan/gm/grammars/whitespace_grammar.hpp>
#include <stan/gm/grammars/expression_grammar.hpp>
#include <stan/gm/grammars/statement_grammar.hpp>
#include <stan/gm/grammars/var_decls_grammar.hpp>

bool is_parsable(const std::string& file_name) {
  stan::gm::program prog;
  std::ifstream fs(file_name.c_str());
  bool parsable = stan::gm::parse(0, fs, file_name, prog);
  return parsable;
}

TEST(gm_parser,eight_schools) {
  EXPECT_TRUE(is_parsable("src/models/misc/eight_schools/eight_schools.stan"));
}

TEST(gm_parser,bugs_1_kidney) {
  EXPECT_TRUE(is_parsable("src/models/bugs_examples/vol1/kidney/kidney.stan"));
}
/*TEST(gm_parser,bugs_1_leuk) {
  EXPECT_TRUE(is_parsable("src/models/bugs_examples/vol1/leuk/leuk.stan"));
  }*/
/*TEST(gm_parser,bugs_1_leukfr) {
  EXPECT_TRUE(is_parsable("src/models/bugs_examples/vol1/leukfr/leukfr.stan"));
}*/
TEST(gm_parser,bugs_1_mice) {
  EXPECT_TRUE(is_parsable("src/models/bugs_examples/vol1/mice/mice.stan"));
}
TEST(gm_parser,bugs_1_oxford) {
  EXPECT_TRUE(is_parsable("src/models/bugs_examples/vol1/oxford/oxford.stan"));
}
TEST(gm_parser,bugs_1_rats) {
  EXPECT_TRUE(is_parsable("src/models/bugs_examples/vol1/rats/rats.stan"));
}
TEST(gm_parser,bugs_1_salm) {
  EXPECT_TRUE(is_parsable("src/models/bugs_examples/vol1/salm/salm.stan"));
}
TEST(gm_parser,bugs_1_seeds) {
  EXPECT_TRUE(is_parsable("src/models/bugs_examples/vol1/seeds/seeds.stan"));
}
TEST(gm_parser,bugs_1_surgical) {
  EXPECT_TRUE(is_parsable("src/models/bugs_examples/vol1/surgical/surgical.stan"));
}

TEST(gm_parser,bugs_2_beetles_cloglog) {
  EXPECT_TRUE(is_parsable("src/models/bugs_examples/vol2/beetles/beetles_cloglog.stan"));
}
TEST(gm_parser,bugs_2_beetles_logit) {
  EXPECT_TRUE(is_parsable("src/models/bugs_examples/vol2/beetles/beetles_logit.stan"));
}
TEST(gm_parser,bugs_2_beetles_probit) {
  EXPECT_TRUE(is_parsable("src/models/bugs_examples/vol2/beetles/beetles_probit.stan"));
}
TEST(gm_parser,bugs_2_birats) {
  EXPECT_TRUE(is_parsable("src/models/bugs_examples/vol2/birats/birats.stan"));
}
TEST(gm_parser,bugs_2_dugongs) {
  EXPECT_TRUE(is_parsable("src/models/bugs_examples/vol2/dugongs/dugongs.stan"));
}
TEST(gm_parser,bugs_2_eyes) {
  EXPECT_TRUE(is_parsable("src/models/bugs_examples/vol2/eyes/eyes.stan"));
}
TEST(gm_parser,bugs_2_ice) {
  EXPECT_TRUE(is_parsable("src/models/bugs_examples/vol2/ice/ice.stan"));
}
/*TEST(gm_parser,bugs_2_stagnant) {
  EXPECT_TRUE(is_parsable("src/models/bugs_examples/vol2/stagnant/stagnant.stan"));
  }*/

TEST(gm_parser,good_trunc) {
  EXPECT_TRUE(is_parsable("src/test/gm/model_specs/good_trunc.stan"));
}

TEST(gm_parser,good_vec_constraints) {
  EXPECT_TRUE(is_parsable("src/test/gm/model_specs/good_trunc.stan"));
}

TEST(gm_parser,good_const) {
  EXPECT_TRUE(is_parsable("src/test/gm/model_specs/good_const.stan"));
}

TEST(gm_parser,good_matrix_ops) {
  EXPECT_TRUE(is_parsable("src/test/gm/model_specs/good_matrix_ops.stan"));
}

TEST(gm_parser,good_funs) {
  EXPECT_TRUE(is_parsable("src/test/gm/model_specs/good_funs.stan"));
}

TEST(gm_parser,triangle_lp) {
  EXPECT_TRUE(is_parsable("src/models/basic_distributions/triangle.stan"));
}

TEST(gm_parser,good_vars) {
  EXPECT_TRUE(is_parsable("src/test/gm/model_specs/good_vars.stan"));
}

TEST(gm_parser,good_intercept_var) {
  EXPECT_TRUE(is_parsable("src/test/gm/model_specs/good_intercept_var.stan"));
}

TEST(gm_parser,good_cov) {
  EXPECT_TRUE(is_parsable("src/test/gm/model_specs/good_cov.stan"));
}

TEST(gm_parser,parsable_test_bad1) {
  EXPECT_THROW(is_parsable("src/test/gm/model_specs/bad1.stan"),
               std::invalid_argument);
}
TEST(gm_parser,parsable_test_bad2) {
  EXPECT_THROW(is_parsable("src/test/gm/model_specs/bad2.stan"),
               std::invalid_argument);
}

TEST(gm_parser,parsable_test_bad3) {
  EXPECT_THROW(is_parsable("src/test/gm/model_specs/bad3.stan"),
               std::invalid_argument);
}

TEST(gm_parser,parsable_test_bad4) {
  EXPECT_THROW(is_parsable("src/test/gm/model_specs/bad4.stan"),
               std::invalid_argument);
}
// TEST(gm_parser,parsable_test_bad5) {
//    EXPECT_THROW(is_parsable("src/test/gm/model_specs/bad5.stan"),
//                 std::invalid_argument);
// }

TEST(gm_parser,parsable_test_bad6) {
  EXPECT_THROW(is_parsable("src/test/gm/model_specs/bad6.stan"),
               std::invalid_argument);
}

TEST(gm_parser,parsable_test_bad7) {
  EXPECT_THROW(is_parsable("src/test/gm/model_specs/bad7.stan"),
               std::invalid_argument);
}
TEST(gm_parser,parsable_test_bad8) {
  EXPECT_THROW(is_parsable("src/test/gm/model_specs/bad8.stan"),
               std::invalid_argument);
}
TEST(gm_parser,parsable_test_bad9) {
  EXPECT_THROW(is_parsable("src/test/gm/model_specs/bad9.stan"),
               std::invalid_argument);
}
TEST(gm_parser,parsable_test_bad10) {
  EXPECT_THROW(is_parsable("src/test/gm/model_specs/bad10.stan"),
               std::invalid_argument);
}
TEST(gm_parser,parsable_test_bad11) {
  EXPECT_THROW(is_parsable("src/test/gm/model_specs/bad11.stan"),
               std::invalid_argument);
}
TEST(gm_parser,parsable_test_bad_trunc) {
  EXPECT_THROW(is_parsable("src/test/gm/model_specs/bad_trunc1.stan"),
               std::invalid_argument);
  EXPECT_THROW(is_parsable("src/test/gm/model_specs/bad_trunc2.stan"),
               std::invalid_argument);
  EXPECT_THROW(is_parsable("src/test/gm/model_specs/bad_trunc3.stan"),
               std::invalid_argument);
}
TEST(gm_parser,function_signatures) {
  EXPECT_TRUE(is_parsable("src/test/gm/model_specs/compiled/function_signatures1.stan"));
  EXPECT_TRUE(is_parsable("src/test/gm/model_specs/compiled/function_signatures2.stan"));
  EXPECT_TRUE(is_parsable("src/test/gm/model_specs/compiled/function_signatures3.stan"));
  EXPECT_TRUE(is_parsable("src/test/gm/model_specs/compiled/function_signatures4.stan"));
  EXPECT_TRUE(is_parsable("src/test/gm/model_specs/compiled/function_signatures5.stan"));
  EXPECT_TRUE(is_parsable("src/test/gm/model_specs/compiled/function_signatures6.stan"));
  EXPECT_TRUE(is_parsable("src/test/gm/model_specs/compiled/function_signatures7.stan"));
}
<commit_msg>updating parser test<commit_after>#include <gtest/gtest.h>
#include <iostream>
#include <fstream>
#include <istream>
#include <exception>
#include <stdexcept>

#include "stan/gm/ast.hpp"
#include "stan/gm/parser.hpp"
#include <stan/gm/generator.hpp>
#include <stan/gm/grammars/program_grammar.hpp>
#include <stan/gm/grammars/whitespace_grammar.hpp>
#include <stan/gm/grammars/expression_grammar.hpp>
#include <stan/gm/grammars/statement_grammar.hpp>
#include <stan/gm/grammars/var_decls_grammar.hpp>

bool is_parsable(const std::string& file_name) {
  stan::gm::program prog;
  std::ifstream fs(file_name.c_str());
  bool parsable = stan::gm::parse(0, fs, file_name, prog);
  return parsable;
}

TEST(gm_parser,eight_schools) {
  EXPECT_TRUE(is_parsable("src/models/misc/eight_schools/eight_schools.stan"));
}

TEST(gm_parser,bugs_1_kidney) {
  EXPECT_TRUE(is_parsable("src/models/bugs_examples/vol1/kidney/kidney.stan"));
}
/*TEST(gm_parser,bugs_1_leuk) {
  EXPECT_TRUE(is_parsable("src/models/bugs_examples/vol1/leuk/leuk.stan"));
  }*/
/*TEST(gm_parser,bugs_1_leukfr) {
  EXPECT_TRUE(is_parsable("src/models/bugs_examples/vol1/leukfr/leukfr.stan"));
}*/
TEST(gm_parser,bugs_1_mice) {
  EXPECT_TRUE(is_parsable("src/models/bugs_examples/vol1/mice/mice.stan"));
}
TEST(gm_parser,bugs_1_oxford) {
  EXPECT_TRUE(is_parsable("src/models/bugs_examples/vol1/oxford/oxford.stan"));
}
TEST(gm_parser,bugs_1_rats) {
  EXPECT_TRUE(is_parsable("src/models/bugs_examples/vol1/rats/rats.stan"));
}
TEST(gm_parser,bugs_1_salm) {
  EXPECT_TRUE(is_parsable("src/models/bugs_examples/vol1/salm/salm.stan"));
}
TEST(gm_parser,bugs_1_seeds) {
  EXPECT_TRUE(is_parsable("src/models/bugs_examples/vol1/seeds/seeds.stan"));
}
TEST(gm_parser,bugs_1_surgical) {
  EXPECT_TRUE(is_parsable("src/models/bugs_examples/vol1/surgical/surgical.stan"));
}

TEST(gm_parser,bugs_2_beetles_cloglog) {
  EXPECT_TRUE(is_parsable("src/models/bugs_examples/vol2/beetles/beetles_cloglog.stan"));
}
TEST(gm_parser,bugs_2_beetles_logit) {
  EXPECT_TRUE(is_parsable("src/models/bugs_examples/vol2/beetles/beetles_logit.stan"));
}
TEST(gm_parser,bugs_2_beetles_probit) {
  EXPECT_TRUE(is_parsable("src/models/bugs_examples/vol2/beetles/beetles_probit.stan"));
}
TEST(gm_parser,bugs_2_birats) {
  EXPECT_TRUE(is_parsable("src/models/bugs_examples/vol2/birats/birats.stan"));
}
TEST(gm_parser,bugs_2_dugongs) {
  EXPECT_TRUE(is_parsable("src/models/bugs_examples/vol2/dugongs/dugongs.stan"));
}
TEST(gm_parser,bugs_2_eyes) {
  EXPECT_TRUE(is_parsable("src/models/bugs_examples/vol2/eyes/eyes.stan"));
}
TEST(gm_parser,bugs_2_ice) {
  EXPECT_TRUE(is_parsable("src/models/bugs_examples/vol2/ice/ice.stan"));
}
/*TEST(gm_parser,bugs_2_stagnant) {
  EXPECT_TRUE(is_parsable("src/models/bugs_examples/vol2/stagnant/stagnant.stan"));
  }*/

TEST(gm_parser,good_trunc) {
  EXPECT_TRUE(is_parsable("src/test/gm/model_specs/good_trunc.stan"));
}

TEST(gm_parser,good_vec_constraints) {
  EXPECT_TRUE(is_parsable("src/test/gm/model_specs/good_trunc.stan"));
}

TEST(gm_parser,good_const) {
  EXPECT_TRUE(is_parsable("src/test/gm/model_specs/good_const.stan"));
}

TEST(gm_parser,good_matrix_ops) {
  EXPECT_TRUE(is_parsable("src/test/gm/model_specs/good_matrix_ops.stan"));
}

TEST(gm_parser,good_funs) {
  EXPECT_TRUE(is_parsable("src/test/gm/model_specs/good_funs.stan"));
}

TEST(gm_parser,triangle_lp) {
  EXPECT_TRUE(is_parsable("src/models/basic_distributions/triangle.stan"));
}

TEST(gm_parser,good_vars) {
  EXPECT_TRUE(is_parsable("src/test/gm/model_specs/good_vars.stan"));
}

TEST(gm_parser,good_intercept_var) {
  EXPECT_TRUE(is_parsable("src/test/gm/model_specs/good_intercept_var.stan"));
}

TEST(gm_parser,good_cov) {
  EXPECT_TRUE(is_parsable("src/test/gm/model_specs/good_cov.stan"));
}

TEST(gm_parser,parsable_test_bad1) {
  EXPECT_THROW(is_parsable("src/test/gm/model_specs/bad1.stan"),
               std::invalid_argument);
}
TEST(gm_parser,parsable_test_bad2) {
  EXPECT_THROW(is_parsable("src/test/gm/model_specs/bad2.stan"),
               std::invalid_argument);
}

TEST(gm_parser,parsable_test_bad3) {
  EXPECT_THROW(is_parsable("src/test/gm/model_specs/bad3.stan"),
               std::invalid_argument);
}

TEST(gm_parser,parsable_test_bad4) {
  EXPECT_THROW(is_parsable("src/test/gm/model_specs/bad4.stan"),
               std::invalid_argument);
}
// TEST(gm_parser,parsable_test_bad5) {
//    EXPECT_THROW(is_parsable("src/test/gm/model_specs/bad5.stan"),
//                 std::invalid_argument);
// }

TEST(gm_parser,parsable_test_bad6) {
  EXPECT_THROW(is_parsable("src/test/gm/model_specs/bad6.stan"),
               std::invalid_argument);
}

TEST(gm_parser,parsable_test_bad7) {
  EXPECT_THROW(is_parsable("src/test/gm/model_specs/bad7.stan"),
               std::invalid_argument);
}
TEST(gm_parser,parsable_test_bad8) {
  EXPECT_THROW(is_parsable("src/test/gm/model_specs/bad8.stan"),
               std::invalid_argument);
}
TEST(gm_parser,parsable_test_bad9) {
  EXPECT_THROW(is_parsable("src/test/gm/model_specs/bad9.stan"),
               std::invalid_argument);
}
TEST(gm_parser,parsable_test_bad10) {
  EXPECT_THROW(is_parsable("src/test/gm/model_specs/bad10.stan"),
               std::invalid_argument);
}
TEST(gm_parser,parsable_test_bad11) {
  EXPECT_THROW(is_parsable("src/test/gm/model_specs/bad11.stan"),
               std::invalid_argument);
}
TEST(gm_parser,parsable_test_bad_trunc) {
  EXPECT_THROW(is_parsable("src/test/gm/model_specs/bad_trunc1.stan"),
               std::invalid_argument);
  EXPECT_THROW(is_parsable("src/test/gm/model_specs/bad_trunc2.stan"),
               std::invalid_argument);
  EXPECT_THROW(is_parsable("src/test/gm/model_specs/bad_trunc3.stan"),
               std::invalid_argument);
}
TEST(gm_parser,function_signatures) {
  EXPECT_TRUE(is_parsable("src/test/gm/model_specs/compiled/function_signatures1.stan"));
  EXPECT_TRUE(is_parsable("src/test/gm/model_specs/compiled/function_signatures6.stan"));
  EXPECT_TRUE(is_parsable("src/test/gm/model_specs/compiled/function_signatures7.stan"));
  EXPECT_TRUE(is_parsable("src/test/gm/model_specs/compiled/function_signatures_bernoulli.stan"));
  EXPECT_TRUE(is_parsable("src/test/gm/model_specs/compiled/function_signatures_beta.stan"));
  EXPECT_TRUE(is_parsable("src/test/gm/model_specs/compiled/function_signatures_beta_binomial.stan"));
  EXPECT_TRUE(is_parsable("src/test/gm/model_specs/compiled/function_signatures_binomial.stan"));
  EXPECT_TRUE(is_parsable("src/test/gm/model_specs/compiled/function_signatures_categorical.stan"));
  EXPECT_TRUE(is_parsable("src/test/gm/model_specs/compiled/function_signatures_cauchy.stan"));
  EXPECT_TRUE(is_parsable("src/test/gm/model_specs/compiled/function_signatures_chi_square.stan"));
  EXPECT_TRUE(is_parsable("src/test/gm/model_specs/compiled/function_signatures_dirichlet.stan"));
  EXPECT_TRUE(is_parsable("src/test/gm/model_specs/compiled/function_signatures_double_exponential.stan"));
  EXPECT_TRUE(is_parsable("src/test/gm/model_specs/compiled/function_signatures_exponential.stan"));
  EXPECT_TRUE(is_parsable("src/test/gm/model_specs/compiled/function_signatures_gamma.stan"));
  EXPECT_TRUE(is_parsable("src/test/gm/model_specs/compiled/function_signatures_hypergeometric.stan"));
  EXPECT_TRUE(is_parsable("src/test/gm/model_specs/compiled/function_signatures_inv_chi_square.stan"));
  EXPECT_TRUE(is_parsable("src/test/gm/model_specs/compiled/function_signatures_inv_gamma.stan"));
  EXPECT_TRUE(is_parsable("src/test/gm/model_specs/compiled/function_signatures_logistic.stan"));
  EXPECT_TRUE(is_parsable("src/test/gm/model_specs/compiled/function_signatures_lognormal.stan"));
  EXPECT_TRUE(is_parsable("src/test/gm/model_specs/compiled/function_signatures_multinomial.stan"));
  EXPECT_TRUE(is_parsable("src/test/gm/model_specs/compiled/function_signatures_neg_binomial.stan"));
  EXPECT_TRUE(is_parsable("src/test/gm/model_specs/compiled/function_signatures_normal.stan"));
  EXPECT_TRUE(is_parsable("src/test/gm/model_specs/compiled/function_signatures_ordered_logistic.stan"));
  EXPECT_TRUE(is_parsable("src/test/gm/model_specs/compiled/function_signatures_pareto.stan"));
  EXPECT_TRUE(is_parsable("src/test/gm/model_specs/compiled/function_signatures_poisson.stan"));
  EXPECT_TRUE(is_parsable("src/test/gm/model_specs/compiled/function_signatures_scaled_inv_chi_square.stan"));
  EXPECT_TRUE(is_parsable("src/test/gm/model_specs/compiled/function_signatures_student_t.stan"));
  EXPECT_TRUE(is_parsable("src/test/gm/model_specs/compiled/function_signatures_uniform.stan"));
  EXPECT_TRUE(is_parsable("src/test/gm/model_specs/compiled/function_signatures_weibull.stan"));
}
<|endoftext|>


<commit_before>// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*-
// Copyright 2009 Google Inc. All Rights Reserved.
// Author: fikes@google.com (Andrew Fikes)
//
// Use of this source code is governed by a BSD-style license that can
// be found in the LICENSE file.

#include "config_for_unittests.h"
#include "page_heap.h"
#include "system-alloc.h"
#include <stdio.h>
#include "base/logging.h"
#include "common.h"

DECLARE_int64(tcmalloc_heap_limit_mb);

namespace {

// The system will only release memory if the block size is equal or hight than
// system page size.
static bool HaveSystemRelease =
    TCMalloc_SystemRelease(
      TCMalloc_SystemAlloc(getpagesize(), NULL, 0), getpagesize());

static void CheckStats(const tcmalloc::PageHeap* ph,
                       uint64_t system_pages,
                       uint64_t free_pages,
                       uint64_t unmapped_pages) {
  tcmalloc::PageHeap::Stats stats = ph->stats();

  if (!HaveSystemRelease) {
    free_pages += unmapped_pages;
    unmapped_pages = 0;
  }

  EXPECT_EQ(system_pages, stats.system_bytes >> kPageShift);
  EXPECT_EQ(free_pages, stats.free_bytes >> kPageShift);
  EXPECT_EQ(unmapped_pages, stats.unmapped_bytes >> kPageShift);
}

static void TestPageHeap_Stats() {
  tcmalloc::PageHeap* ph = new tcmalloc::PageHeap();

  // Empty page heap
  CheckStats(ph, 0, 0, 0);

  // Allocate a span 's1'
  tcmalloc::Span* s1 = ph->New(256);
  CheckStats(ph, 256, 0, 0);

  // Split span 's1' into 's1', 's2'.  Delete 's2'
  tcmalloc::Span* s2 = ph->Split(s1, 128);
  ph->Delete(s2);
  CheckStats(ph, 256, 128, 0);

  // Unmap deleted span 's2'
  ph->ReleaseAtLeastNPages(1);
  CheckStats(ph, 256, 0, 128);

  // Delete span 's1'
  ph->Delete(s1);
  CheckStats(ph, 256, 128, 128);

  delete ph;
}

static void TestPageHeap_Limit() {
  tcmalloc::PageHeap* ph = new tcmalloc::PageHeap();

  CHECK_EQ(kMaxPages, 1 << (20 - kPageShift));

  // We do not know much is taken from the system for other purposes,
  // so we detect the proper limit:
  {
    FLAGS_tcmalloc_heap_limit_mb = 1;
    tcmalloc::Span* s = NULL;
    while((s = ph->New(kMaxPages)) == NULL) {
      FLAGS_tcmalloc_heap_limit_mb++;
    }
    FLAGS_tcmalloc_heap_limit_mb += 9;
    ph->Delete(s);
    // We are [10, 11) mb from the limit now.
  }

  // Test AllocLarge and GrowHeap first:
  {
    tcmalloc::Span * spans[10];
    for (int i=0; i<10; ++i) {
      spans[i] = ph->New(kMaxPages);
      EXPECT_NE(spans[i], NULL);
    }
    EXPECT_EQ(ph->New(kMaxPages), NULL);

    for (int i=0; i<10; i += 2) {
      ph->Delete(spans[i]);
    }

    tcmalloc::Span *defragmented = ph->New(5 * kMaxPages);

    if (HaveSystemRelease) {
      // EnsureLimit should release deleted normal spans
      EXPECT_NE(defragmented, NULL);
      EXPECT_TRUE(ph->CheckExpensive());
      ph->Delete(defragmented);
    }
    else
    {
      EXPECT_EQ(defragmented, NULL);
      EXPECT_TRUE(ph->CheckExpensive());
    }

    for (int i=1; i<10; i += 2) {
      ph->Delete(spans[i]);
    }
  }

  // Once again, testing small lists this time (twice smaller spans):
  {
    tcmalloc::Span * spans[20];
    for (int i=0; i<20; ++i) {
      spans[i] = ph->New(kMaxPages >> 1);
      EXPECT_NE(spans[i], NULL);
    }
    // one more half size allocation may be possible:
    tcmalloc::Span * lastHalf = ph->New(kMaxPages >> 1);
    EXPECT_EQ(ph->New(kMaxPages >> 1), NULL);

    for (int i=0; i<20; i += 2) {
      ph->Delete(spans[i]);
    }

    for(Length len = kMaxPages >> 2; len < 5 * kMaxPages; len = len << 1)
    {
      if(len <= kMaxPages >> 1 || HaveSystemRelease) {
        tcmalloc::Span *s = ph->New(len);
        EXPECT_NE(s, NULL);
        ph->Delete(s);
      }
    }

    EXPECT_TRUE(ph->CheckExpensive());

    for (int i=1; i<20; i += 2) {
      ph->Delete(spans[i]);
    }

    if (lastHalf != NULL) {
      ph->Delete(lastHalf);
    }
  }

  delete ph;
}

}  // namespace

int main(int argc, char **argv) {
  TestPageHeap_Stats();
  TestPageHeap_Limit();
  printf("PASS\n");
  // on windows as part of library destructors we call getenv which
  // calls malloc which fails due to our exhausted heap limit. It then
  // causes fancy stack overflow because log message we're printing
  // for failed allocation somehow cause malloc calls too
  //
  // To keep us out of trouble we just drop malloc limit
  FLAGS_tcmalloc_heap_limit_mb = 0;
  return 0;
}
<commit_msg>Fix page_heap_test flakiness<commit_after>// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*-
// Copyright 2009 Google Inc. All Rights Reserved.
// Author: fikes@google.com (Andrew Fikes)
//
// Use of this source code is governed by a BSD-style license that can
// be found in the LICENSE file.

#include "config_for_unittests.h"

#include <stdio.h>

#include <memory>

#include "page_heap.h"
#include "system-alloc.h"
#include "base/logging.h"
#include "common.h"

DECLARE_int64(tcmalloc_heap_limit_mb);

namespace {

// The system will only release memory if the block size is equal or hight than
// system page size.
static bool HaveSystemRelease =
    TCMalloc_SystemRelease(
      TCMalloc_SystemAlloc(getpagesize(), NULL, 0), getpagesize());

static void CheckStats(const tcmalloc::PageHeap* ph,
                       uint64_t system_pages,
                       uint64_t free_pages,
                       uint64_t unmapped_pages) {
  tcmalloc::PageHeap::Stats stats = ph->stats();

  if (!HaveSystemRelease) {
    free_pages += unmapped_pages;
    unmapped_pages = 0;
  }

  EXPECT_EQ(system_pages, stats.system_bytes >> kPageShift);
  EXPECT_EQ(free_pages, stats.free_bytes >> kPageShift);
  EXPECT_EQ(unmapped_pages, stats.unmapped_bytes >> kPageShift);
}

static void TestPageHeap_Stats() {
  std::unique_ptr<tcmalloc::PageHeap> ph(new tcmalloc::PageHeap());

  // Empty page heap
  CheckStats(ph.get(), 0, 0, 0);

  // Allocate a span 's1'
  tcmalloc::Span* s1 = ph->New(256);
  CheckStats(ph.get(), 256, 0, 0);

  // Split span 's1' into 's1', 's2'.  Delete 's2'
  tcmalloc::Span* s2 = ph->Split(s1, 128);
  ph->Delete(s2);
  CheckStats(ph.get(), 256, 128, 0);

  // Unmap deleted span 's2'
  ph->ReleaseAtLeastNPages(1);
  CheckStats(ph.get(), 256, 0, 128);

  // Delete span 's1'
  ph->Delete(s1);
  CheckStats(ph.get(), 256, 128, 128);
}

// The number of kMaxPages-sized Spans we will allocate and free during the
// tests.
// We will also do twice this many kMaxPages/2-sized ones.
static constexpr int kNumberMaxPagesSpans = 10;

// Allocates all the last-level page tables we will need. Doing this before
// calculating the base heap usage is necessary, because otherwise if any of
// these are allocated during the main test it will throw the heap usage
// calculations off and cause the test to fail.
static void AllocateAllPageTables() {
  // Make a separate PageHeap from the main test so the test can start without
  // any pages in the lists.
  std::unique_ptr<tcmalloc::PageHeap> ph(new tcmalloc::PageHeap());
  tcmalloc::Span *spans[kNumberMaxPagesSpans * 2];
  for (int i = 0; i < kNumberMaxPagesSpans; ++i) {
    spans[i] = ph->New(kMaxPages);
    EXPECT_NE(spans[i], NULL);
  }
  for (int i = 0; i < kNumberMaxPagesSpans; ++i) {
    ph->Delete(spans[i]);
  }
  for (int i = 0; i < kNumberMaxPagesSpans * 2; ++i) {
    spans[i] = ph->New(kMaxPages >> 1);
    EXPECT_NE(spans[i], NULL);
  }
  for (int i = 0; i < kNumberMaxPagesSpans * 2; ++i) {
    ph->Delete(spans[i]);
  }
}

static void TestPageHeap_Limit() {
  AllocateAllPageTables();

  std::unique_ptr<tcmalloc::PageHeap> ph(new tcmalloc::PageHeap());

  CHECK_EQ(kMaxPages, 1 << (20 - kPageShift));

  // We do not know much is taken from the system for other purposes,
  // so we detect the proper limit:
  {
    FLAGS_tcmalloc_heap_limit_mb = 1;
    tcmalloc::Span* s = NULL;
    while((s = ph->New(kMaxPages)) == NULL) {
      FLAGS_tcmalloc_heap_limit_mb++;
    }
    FLAGS_tcmalloc_heap_limit_mb += kNumberMaxPagesSpans - 1;
    ph->Delete(s);
    // We are [10, 11) mb from the limit now.
  }

  // Test AllocLarge and GrowHeap first:
  {
    tcmalloc::Span * spans[kNumberMaxPagesSpans];
    for (int i=0; i<kNumberMaxPagesSpans; ++i) {
      spans[i] = ph->New(kMaxPages);
      EXPECT_NE(spans[i], NULL);
    }
    EXPECT_EQ(ph->New(kMaxPages), NULL);

    for (int i=0; i<kNumberMaxPagesSpans; i += 2) {
      ph->Delete(spans[i]);
    }

    tcmalloc::Span *defragmented =
        ph->New(kNumberMaxPagesSpans / 2 * kMaxPages);

    if (HaveSystemRelease) {
      // EnsureLimit should release deleted normal spans
      EXPECT_NE(defragmented, NULL);
      EXPECT_TRUE(ph->CheckExpensive());
      ph->Delete(defragmented);
    }
    else
    {
      EXPECT_EQ(defragmented, NULL);
      EXPECT_TRUE(ph->CheckExpensive());
    }

    for (int i=1; i<kNumberMaxPagesSpans; i += 2) {
      ph->Delete(spans[i]);
    }
  }

  // Once again, testing small lists this time (twice smaller spans):
  {
    tcmalloc::Span * spans[kNumberMaxPagesSpans * 2];
    for (int i=0; i<kNumberMaxPagesSpans * 2; ++i) {
      spans[i] = ph->New(kMaxPages >> 1);
      EXPECT_NE(spans[i], NULL);
    }
    // one more half size allocation may be possible:
    tcmalloc::Span * lastHalf = ph->New(kMaxPages >> 1);
    EXPECT_EQ(ph->New(kMaxPages >> 1), NULL);

    for (int i=0; i<kNumberMaxPagesSpans * 2; i += 2) {
      ph->Delete(spans[i]);
    }

    for (Length len = kMaxPages >> 2;
         len < kNumberMaxPagesSpans / 2 * kMaxPages; len = len << 1) {
      if(len <= kMaxPages >> 1 || HaveSystemRelease) {
        tcmalloc::Span *s = ph->New(len);
        EXPECT_NE(s, NULL);
        ph->Delete(s);
      }
    }

    EXPECT_TRUE(ph->CheckExpensive());

    for (int i=1; i<kNumberMaxPagesSpans * 2; i += 2) {
      ph->Delete(spans[i]);
    }

    if (lastHalf != NULL) {
      ph->Delete(lastHalf);
    }
  }
}

}  // namespace

int main(int argc, char **argv) {
  TestPageHeap_Stats();
  TestPageHeap_Limit();
  printf("PASS\n");
  // on windows as part of library destructors we call getenv which
  // calls malloc which fails due to our exhausted heap limit. It then
  // causes fancy stack overflow because log message we're printing
  // for failed allocation somehow cause malloc calls too
  //
  // To keep us out of trouble we just drop malloc limit
  FLAGS_tcmalloc_heap_limit_mb = 0;
  return 0;
}
<|endoftext|>


<commit_before>/*
 *  Copyright (c) 2013 The WebRTC project authors. All Rights Reserved.
 *
 *  Use of this source code is governed by a BSD-style license
 *  that can be found in the LICENSE file in the root of the source
 *  tree. An additional intellectual property rights grant can be found
 *  in the file PATENTS.  All contributing project authors may
 *  be found in the AUTHORS file in the root of the source tree.
 */

#include "webrtc/modules/audio_processing/transient/wpd_tree.h"

#include <assert.h>
#include <math.h>
#include <string.h>

#include "webrtc/base/scoped_ptr.h"
#include "webrtc/modules/audio_processing/transient/dyadic_decimator.h"
#include "webrtc/modules/audio_processing/transient/wpd_node.h"

namespace webrtc {

WPDTree::WPDTree(size_t data_length, const float* high_pass_coefficients,
                 const float* low_pass_coefficients, size_t coefficients_length,
                 int levels)
    : data_length_(data_length),
      levels_(levels),
      num_nodes_((1 << (levels + 1)) - 1) {
  assert(data_length > (static_cast<size_t>(1) << levels) &&
         high_pass_coefficients &&
         low_pass_coefficients &&
         levels > 0);
  // Size is 1 more, so we can use the array as 1-based. nodes_[0] is never
  // allocated.
  nodes_.reset(new rtc::scoped_ptr<WPDNode>[num_nodes_ + 1]);

  // Create the first node
  const float kRootCoefficient = 1.f;  // Identity Coefficient.
  nodes_[1].reset(new WPDNode(data_length, &kRootCoefficient, 1));
  // Variables used to create the rest of the nodes.
  size_t index = 1;
  size_t index_left_child = 0;
  size_t index_right_child = 0;

  int num_nodes_at_curr_level = 0;

  // Branching each node in each level to create its children. The last level is
  // not branched (all the nodes of that level are leaves).
  for (int current_level = 0; current_level < levels; ++current_level) {
    num_nodes_at_curr_level = 1 << current_level;
    for (int i = 0; i < num_nodes_at_curr_level; ++i) {
      index = (1 << current_level) + i;
      // Obtain the index of the current node children.
      index_left_child = index * 2;
      index_right_child = index_left_child + 1;
      nodes_[index_left_child].reset(new WPDNode(nodes_[index]->length() / 2,
                                                 low_pass_coefficients,
                                                 coefficients_length));
      nodes_[index_right_child].reset(new WPDNode(nodes_[index]->length() / 2,
                                                  high_pass_coefficients,
                                                  coefficients_length));
    }
  }
}

WPDTree::~WPDTree() {}

WPDNode* WPDTree::NodeAt(int level, int index) {
  const int kNumNodesAtLevel = 1 << level;
  if (level < 0 || level > levels_ || index < 0 || index >= kNumNodesAtLevel) {
    return NULL;
  }
  return nodes_[(1 << level) + index].get();
}

int WPDTree::Update(const float* data, size_t data_length) {
  if (!data || data_length != data_length_) {
    return -1;
  }

  // Update the root node.
  int update_result = nodes_[1]->set_data(data, data_length);
  if (update_result != 0) {
    return -1;
  }

  // Variables used to update the rest of the nodes.
  size_t index = 1;
  size_t index_left_child = 0;
  size_t index_right_child = 0;

  int num_nodes_at_curr_level = 0;

  for (int current_level = 0; current_level < levels_; ++current_level) {
    num_nodes_at_curr_level = 1 << current_level;
    for (int i = 0; i < num_nodes_at_curr_level; ++i) {
      index = (1 << current_level) + i;
      // Obtain the index of the current node children.
      index_left_child = index * 2;
      index_right_child = index_left_child + 1;

      update_result = nodes_[index_left_child]->Update(
          nodes_[index]->data(), nodes_[index]->length());
      if (update_result != 0) {
        return -1;
      }

      update_result = nodes_[index_right_child]->Update(
          nodes_[index]->data(), nodes_[index]->length());
      if (update_result != 0) {
        return -1;
      }
    }
  }

  return 0;
}

}  // namespace webrtc
<commit_msg>Fix negative shift exponent in WPDTree<commit_after>/*
 *  Copyright (c) 2013 The WebRTC project authors. All Rights Reserved.
 *
 *  Use of this source code is governed by a BSD-style license
 *  that can be found in the LICENSE file in the root of the source
 *  tree. An additional intellectual property rights grant can be found
 *  in the file PATENTS.  All contributing project authors may
 *  be found in the AUTHORS file in the root of the source tree.
 */

#include "webrtc/modules/audio_processing/transient/wpd_tree.h"

#include <assert.h>
#include <math.h>
#include <string.h>

#include "webrtc/base/scoped_ptr.h"
#include "webrtc/modules/audio_processing/transient/dyadic_decimator.h"
#include "webrtc/modules/audio_processing/transient/wpd_node.h"

namespace webrtc {

WPDTree::WPDTree(size_t data_length, const float* high_pass_coefficients,
                 const float* low_pass_coefficients, size_t coefficients_length,
                 int levels)
    : data_length_(data_length),
      levels_(levels),
      num_nodes_((1 << (levels + 1)) - 1) {
  assert(data_length > (static_cast<size_t>(1) << levels) &&
         high_pass_coefficients &&
         low_pass_coefficients &&
         levels > 0);
  // Size is 1 more, so we can use the array as 1-based. nodes_[0] is never
  // allocated.
  nodes_.reset(new rtc::scoped_ptr<WPDNode>[num_nodes_ + 1]);

  // Create the first node
  const float kRootCoefficient = 1.f;  // Identity Coefficient.
  nodes_[1].reset(new WPDNode(data_length, &kRootCoefficient, 1));
  // Variables used to create the rest of the nodes.
  size_t index = 1;
  size_t index_left_child = 0;
  size_t index_right_child = 0;

  int num_nodes_at_curr_level = 0;

  // Branching each node in each level to create its children. The last level is
  // not branched (all the nodes of that level are leaves).
  for (int current_level = 0; current_level < levels; ++current_level) {
    num_nodes_at_curr_level = 1 << current_level;
    for (int i = 0; i < num_nodes_at_curr_level; ++i) {
      index = (1 << current_level) + i;
      // Obtain the index of the current node children.
      index_left_child = index * 2;
      index_right_child = index_left_child + 1;
      nodes_[index_left_child].reset(new WPDNode(nodes_[index]->length() / 2,
                                                 low_pass_coefficients,
                                                 coefficients_length));
      nodes_[index_right_child].reset(new WPDNode(nodes_[index]->length() / 2,
                                                  high_pass_coefficients,
                                                  coefficients_length));
    }
  }
}

WPDTree::~WPDTree() {}

WPDNode* WPDTree::NodeAt(int level, int index) {
  if (level < 0 || level > levels_ || index < 0 || index >= 1 << level) {
    return NULL;
  }

  return nodes_[(1 << level) + index].get();
}

int WPDTree::Update(const float* data, size_t data_length) {
  if (!data || data_length != data_length_) {
    return -1;
  }

  // Update the root node.
  int update_result = nodes_[1]->set_data(data, data_length);
  if (update_result != 0) {
    return -1;
  }

  // Variables used to update the rest of the nodes.
  size_t index = 1;
  size_t index_left_child = 0;
  size_t index_right_child = 0;

  int num_nodes_at_curr_level = 0;

  for (int current_level = 0; current_level < levels_; ++current_level) {
    num_nodes_at_curr_level = 1 << current_level;
    for (int i = 0; i < num_nodes_at_curr_level; ++i) {
      index = (1 << current_level) + i;
      // Obtain the index of the current node children.
      index_left_child = index * 2;
      index_right_child = index_left_child + 1;

      update_result = nodes_[index_left_child]->Update(
          nodes_[index]->data(), nodes_[index]->length());
      if (update_result != 0) {
        return -1;
      }

      update_result = nodes_[index_right_child]->Update(
          nodes_[index]->data(), nodes_[index]->length());
      if (update_result != 0) {
        return -1;
      }
    }
  }

  return 0;
}

}  // namespace webrtc
<|endoftext|>


<commit_before>//
//  yas_ui_event.cpp
//

#include "yas_ui_event.h"
#include <unordered_map>
#include "yas_observing.h"
#include "yas_ui_types.h"

using namespace yas;

#pragma mark - event::impl

struct ui::event::impl_base : base::impl, manageable_event::impl {
    virtual std::type_info const &type() const = 0;

    void set_phase(event_phase &&st) override {
        this->phase = std::move(st);
    }

    event_phase phase = ui::event_phase::none;
};

template <typename T>
struct ui::event::impl : impl_base {
    typename T::type value;

    impl() {
    }

    impl(impl const &) = delete;
    impl(impl &&) = delete;
    impl &operator=(impl const &) = delete;
    impl &operator=(impl &&) = delete;

    ~impl() = default;

    virtual bool is_equal(std::shared_ptr<base::impl> const &rhs) const override {
        if (auto casted_rhs = std::dynamic_pointer_cast<impl>(rhs)) {
            auto &type_info = this->type();
            if (type_info == casted_rhs->type()) {
                return this->value == casted_rhs->value;
            }
        }

        return false;
    }

    std::type_info const &type() const override {
        return typeid(T);
    }
};

#pragma mark - event

ui::event::event(cursor const &) : base(std::make_shared<impl<ui::cursor>>()) {
}

ui::event::event(touch const &) : base(std::make_shared<impl<ui::touch>>()) {
}

ui::event::event(key const &) : base(std::make_shared<impl<ui::key>>()) {
}

ui::event::event(modifier const &) : base(std::make_shared<impl<ui::modifier>>()) {
}

ui::event::event(std::nullptr_t) : base(nullptr) {
}

ui::event::~event() = default;

ui::event_phase ui::event::phase() const {
    return impl_ptr<impl_base>()->phase;
}

std::type_info const &ui::event::type_info() const {
    return impl_ptr<impl_base>()->type();
}

template <typename T>
typename T::type const &ui::event::get() const {
    if (auto ip = std::dynamic_pointer_cast<impl<T>>(impl_ptr())) {
        return ip->value;
    }

    static const typename T::type _default{};
    return _default;
}

template ui::cursor::type const &ui::event::get<ui::cursor>() const;
template ui::touch::type const &ui::event::get<ui::touch>() const;
template ui::key::type const &ui::event::get<ui::key>() const;
template ui::modifier::type const &ui::event::get<ui::modifier>() const;

ui::manageable_event &ui::event::manageable() {
    if (!this->_manageable) {
        this->_manageable = ui::manageable_event{impl_ptr<ui::manageable_event::impl>()};
    }
    return this->_manageable;
}

#pragma mark - event_manager::impl

struct ui::event_manager::impl : base::impl, event_inputtable::impl {
    void input_cursor_event(cursor_event &&value) override {
        ui::event_phase phase;

        if (value.contains_in_window()) {
            if (this->_cursor_event) {
                phase = event_phase::changed;
            } else {
                phase = event_phase::began;
                this->_cursor_event = ui::event{cursor_tag};
            }
        } else {
            phase = event_phase::ended;
        }

        if (this->_cursor_event) {
            auto manageable_event = this->_cursor_event.manageable();
            manageable_event.set_phase(phase);
            manageable_event.set<cursor>(std::move(value));

            this->_sender.send_value({.method = event_manager::method::cursor_changed, .event = this->_cursor_event});

            if (phase == event_phase::ended) {
                this->_cursor_event = nullptr;
            }
        }
    }

    void input_touch_event(event_phase const phase, touch_event &&value) override {
        auto const identifer = value.identifier();

        if (phase == event_phase::began) {
            if (this->_touch_events.count(identifer) > 0) {
                return;
            }
            ui::event event{touch_tag};
            this->_touch_events.emplace(std::make_pair(identifer, std::move(event)));
        }

        if (this->_touch_events.count(identifer) > 0) {
            auto &event = this->_touch_events.at(identifer);
            auto manageable_event = event.manageable();
            manageable_event.set_phase(phase);
            manageable_event.set<touch>(std::move(value));

            this->_sender.send_value({.method = event_manager::method::touch_changed, .event = event});

            if (phase == event_phase::ended || phase == event_phase::canceled) {
                this->_touch_events.erase(identifer);
            }
        }
    }

    void input_key_event(event_phase const phase, key_event &&value) override {
        auto const key_code = value.key_code();

        if (phase == event_phase::began) {
            if (this->_key_events.count(key_code) > 0) {
                return;
            }
            ui::event event{key_tag};
            this->_key_events.emplace(std::make_pair(key_code, std::move(event)));
        }

        if (this->_key_events.count(key_code) > 0) {
            auto &event = this->_key_events.at(key_code);
            event.manageable().set_phase(phase);
            event.manageable().set<key>(value);

            this->_sender.send_value({.method = event_manager::method::key_changed, .event = event});

            if (phase == event_phase::ended || phase == event_phase::canceled) {
                this->_key_events.erase(key_code);
            }
        }
    }

    void input_modifier_event(modifier_flags &&flags, double const timestamp) override {
        static auto all_flags = {modifier_flags::alpha_shift, modifier_flags::shift,   modifier_flags::control,
                                 modifier_flags::alternate,   modifier_flags::command, modifier_flags::numeric_pad,
                                 modifier_flags::help,        modifier_flags::function};

        for (auto const &flag : all_flags) {
            if (flags & flag) {
                if (this->_modifier_events.count(flag) == 0) {
                    ui::event event{modifier_tag};
                    event.manageable().set<modifier>(ui::modifier_event{flag, timestamp});
                    event.manageable().set_phase(ui::event_phase::began);
                    this->_modifier_events.emplace(std::make_pair(flag, std::move(event)));

                    this->_sender.send_value(
                        {.method = event_manager::method::modifier_changed, .event = this->_modifier_events.at(flag)});
                }
            } else {
                if (this->_modifier_events.count(flag) > 0) {
                    auto &event = this->_modifier_events.at(flag);
                    event.manageable().set_phase(ui::event_phase::ended);

                    this->_sender.send_value({.method = event_manager::method::modifier_changed, .event = event});

                    this->_modifier_events.erase(flag);
                }
            }
        }
    }

    flow::node<event, context, context, false> begin_flow(method const &method) {
        return this->_sender.begin()
            .filter([method](context const &context) { return context.method == method; })
            .map([](ui::event_manager::context const &context) { return context.event; });
    }

    flow::node<context, context, context, false> begin_flow() {
        return this->_sender.begin();
    }

    event _cursor_event{nullptr};
    std::unordered_map<uintptr_t, event> _touch_events;
    std::unordered_map<uint16_t, event> _key_events;
    std::unordered_map<uint32_t, event> _modifier_events;

    flow::receiver<context> _receiver = nullptr;
    flow::sender<context> _sender;
};

#pragma mark - manageable_event

ui::manageable_event::manageable_event(std::shared_ptr<impl> impl) : protocol(std::move(impl)) {
}

ui::manageable_event::manageable_event(std::nullptr_t) : protocol(nullptr) {
}

template <typename T>
void ui::manageable_event::set(typename T::type value) {
    if (auto ip = std::dynamic_pointer_cast<event::impl<T>>(impl_ptr<impl>())) {
        ip->value = std::move(value);
    } else {
        throw "dynamic_pointer_cast failed";
    }
}

template void ui::manageable_event::set<ui::cursor>(ui::cursor::type);
template void ui::manageable_event::set<ui::touch>(ui::touch::type);
template void ui::manageable_event::set<ui::key>(ui::key::type);
template void ui::manageable_event::set<ui::modifier>(ui::modifier::type);

void ui::manageable_event::set_phase(event_phase phase) {
    impl_ptr<impl>()->set_phase(std::move(phase));
}

#pragma mark - event_manager

ui::event_manager::event_manager() : base(std::make_shared<impl>()) {
}

ui::event_manager::event_manager(std::nullptr_t) : base(nullptr) {
}

ui::event_manager::~event_manager() = default;

flow::node<ui::event, ui::event_manager::context, ui::event_manager::context, false> ui::event_manager::begin_flow(
    method const &method) const {
    return impl_ptr<impl>()->begin_flow(method);
}

flow::node<ui::event_manager::context, ui::event_manager::context, ui::event_manager::context, false>
ui::event_manager::begin_flow() const {
    return impl_ptr<impl>()->begin_flow();
}

ui::event_inputtable &ui::event_manager::inputtable() {
    if (!this->_inputtable) {
        this->_inputtable = ui::event_inputtable{impl_ptr<ui::event_inputtable::impl>()};
    }
    return this->_inputtable;
}

#pragma mark -

std::string yas::to_string(ui::event const &event) {
    std::string type = "unknown";
    std::string values;

    if (event.type_info() == typeid(ui::cursor)) {
        type = "cursor";
        values = to_string(event.get<ui::cursor>());
    } else if (event.type_info() == typeid(ui::touch)) {
        type = "touch";
        values = to_string(event.get<ui::touch>());
    } else if (event.type_info() == typeid(ui::key)) {
        type = "key";
        values = to_string(event.get<ui::key>());
    } else if (event.type_info() == typeid(ui::modifier)) {
        type = "modifier";
        values = to_string(event.get<ui::modifier>());
    }

    return "{phase:" + to_string(event.phase()) + ", type:" + type + ", values:" + values + "}";
}

std::string yas::to_string(ui::event_manager::method const &method) {
    switch (method) {
        case ui::event_manager::method::cursor_changed:
            return "cursor_changed";
        case ui::event_manager::method::touch_changed:
            return "touch_changed";
        case ui::event_manager::method::key_changed:
            return "key_changed";
        case ui::event_manager::method::modifier_changed:
            return "modifier_changed";
    }
}

std::ostream &operator<<(std::ostream &os, yas::ui::event const &event) {
    os << to_string(event);
    return os;
}

std::ostream &operator<<(std::ostream &os, yas::ui::event_manager::method const &method) {
    os << to_string(method);
    return os;
}
<commit_msg>fix event<commit_after>//
//  yas_ui_event.cpp
//

#include "yas_ui_event.h"
#include <unordered_map>
#include "yas_ui_types.h"

using namespace yas;

#pragma mark - event::impl

struct ui::event::impl_base : base::impl, manageable_event::impl {
    virtual std::type_info const &type() const = 0;

    void set_phase(event_phase &&st) override {
        this->phase = std::move(st);
    }

    event_phase phase = ui::event_phase::none;
};

template <typename T>
struct ui::event::impl : impl_base {
    typename T::type value;

    impl() {
    }

    impl(impl const &) = delete;
    impl(impl &&) = delete;
    impl &operator=(impl const &) = delete;
    impl &operator=(impl &&) = delete;

    ~impl() = default;

    virtual bool is_equal(std::shared_ptr<base::impl> const &rhs) const override {
        if (auto casted_rhs = std::dynamic_pointer_cast<impl>(rhs)) {
            auto &type_info = this->type();
            if (type_info == casted_rhs->type()) {
                return this->value == casted_rhs->value;
            }
        }

        return false;
    }

    std::type_info const &type() const override {
        return typeid(T);
    }
};

#pragma mark - event

ui::event::event(cursor const &) : base(std::make_shared<impl<ui::cursor>>()) {
}

ui::event::event(touch const &) : base(std::make_shared<impl<ui::touch>>()) {
}

ui::event::event(key const &) : base(std::make_shared<impl<ui::key>>()) {
}

ui::event::event(modifier const &) : base(std::make_shared<impl<ui::modifier>>()) {
}

ui::event::event(std::nullptr_t) : base(nullptr) {
}

ui::event::~event() = default;

ui::event_phase ui::event::phase() const {
    return impl_ptr<impl_base>()->phase;
}

std::type_info const &ui::event::type_info() const {
    return impl_ptr<impl_base>()->type();
}

template <typename T>
typename T::type const &ui::event::get() const {
    if (auto ip = std::dynamic_pointer_cast<impl<T>>(impl_ptr())) {
        return ip->value;
    }

    static const typename T::type _default{};
    return _default;
}

template ui::cursor::type const &ui::event::get<ui::cursor>() const;
template ui::touch::type const &ui::event::get<ui::touch>() const;
template ui::key::type const &ui::event::get<ui::key>() const;
template ui::modifier::type const &ui::event::get<ui::modifier>() const;

ui::manageable_event &ui::event::manageable() {
    if (!this->_manageable) {
        this->_manageable = ui::manageable_event{impl_ptr<ui::manageable_event::impl>()};
    }
    return this->_manageable;
}

#pragma mark - event_manager::impl

struct ui::event_manager::impl : base::impl, event_inputtable::impl {
    void input_cursor_event(cursor_event &&value) override {
        ui::event_phase phase;

        if (value.contains_in_window()) {
            if (this->_cursor_event) {
                phase = event_phase::changed;
            } else {
                phase = event_phase::began;
                this->_cursor_event = ui::event{cursor_tag};
            }
        } else {
            phase = event_phase::ended;
        }

        if (this->_cursor_event) {
            auto manageable_event = this->_cursor_event.manageable();
            manageable_event.set_phase(phase);
            manageable_event.set<cursor>(std::move(value));

            this->_sender.send_value({.method = event_manager::method::cursor_changed, .event = this->_cursor_event});

            if (phase == event_phase::ended) {
                this->_cursor_event = nullptr;
            }
        }
    }

    void input_touch_event(event_phase const phase, touch_event &&value) override {
        auto const identifer = value.identifier();

        if (phase == event_phase::began) {
            if (this->_touch_events.count(identifer) > 0) {
                return;
            }
            ui::event event{touch_tag};
            this->_touch_events.emplace(std::make_pair(identifer, std::move(event)));
        }

        if (this->_touch_events.count(identifer) > 0) {
            auto &event = this->_touch_events.at(identifer);
            auto manageable_event = event.manageable();
            manageable_event.set_phase(phase);
            manageable_event.set<touch>(std::move(value));

            this->_sender.send_value({.method = event_manager::method::touch_changed, .event = event});

            if (phase == event_phase::ended || phase == event_phase::canceled) {
                this->_touch_events.erase(identifer);
            }
        }
    }

    void input_key_event(event_phase const phase, key_event &&value) override {
        auto const key_code = value.key_code();

        if (phase == event_phase::began) {
            if (this->_key_events.count(key_code) > 0) {
                return;
            }
            ui::event event{key_tag};
            this->_key_events.emplace(std::make_pair(key_code, std::move(event)));
        }

        if (this->_key_events.count(key_code) > 0) {
            auto &event = this->_key_events.at(key_code);
            event.manageable().set_phase(phase);
            event.manageable().set<key>(value);

            this->_sender.send_value({.method = event_manager::method::key_changed, .event = event});

            if (phase == event_phase::ended || phase == event_phase::canceled) {
                this->_key_events.erase(key_code);
            }
        }
    }

    void input_modifier_event(modifier_flags &&flags, double const timestamp) override {
        static auto all_flags = {modifier_flags::alpha_shift, modifier_flags::shift,   modifier_flags::control,
                                 modifier_flags::alternate,   modifier_flags::command, modifier_flags::numeric_pad,
                                 modifier_flags::help,        modifier_flags::function};

        for (auto const &flag : all_flags) {
            if (flags & flag) {
                if (this->_modifier_events.count(flag) == 0) {
                    ui::event event{modifier_tag};
                    event.manageable().set<modifier>(ui::modifier_event{flag, timestamp});
                    event.manageable().set_phase(ui::event_phase::began);
                    this->_modifier_events.emplace(std::make_pair(flag, std::move(event)));

                    this->_sender.send_value(
                        {.method = event_manager::method::modifier_changed, .event = this->_modifier_events.at(flag)});
                }
            } else {
                if (this->_modifier_events.count(flag) > 0) {
                    auto &event = this->_modifier_events.at(flag);
                    event.manageable().set_phase(ui::event_phase::ended);

                    this->_sender.send_value({.method = event_manager::method::modifier_changed, .event = event});

                    this->_modifier_events.erase(flag);
                }
            }
        }
    }

    flow::node<event, context, context, false> begin_flow(method const &method) {
        return this->_sender.begin()
            .filter([method](context const &context) { return context.method == method; })
            .map([](ui::event_manager::context const &context) { return context.event; });
    }

    flow::node<context, context, context, false> begin_flow() {
        return this->_sender.begin();
    }

    event _cursor_event{nullptr};
    std::unordered_map<uintptr_t, event> _touch_events;
    std::unordered_map<uint16_t, event> _key_events;
    std::unordered_map<uint32_t, event> _modifier_events;

    flow::receiver<context> _receiver = nullptr;
    flow::sender<context> _sender;
};

#pragma mark - manageable_event

ui::manageable_event::manageable_event(std::shared_ptr<impl> impl) : protocol(std::move(impl)) {
}

ui::manageable_event::manageable_event(std::nullptr_t) : protocol(nullptr) {
}

template <typename T>
void ui::manageable_event::set(typename T::type value) {
    if (auto ip = std::dynamic_pointer_cast<event::impl<T>>(impl_ptr<impl>())) {
        ip->value = std::move(value);
    } else {
        throw "dynamic_pointer_cast failed";
    }
}

template void ui::manageable_event::set<ui::cursor>(ui::cursor::type);
template void ui::manageable_event::set<ui::touch>(ui::touch::type);
template void ui::manageable_event::set<ui::key>(ui::key::type);
template void ui::manageable_event::set<ui::modifier>(ui::modifier::type);

void ui::manageable_event::set_phase(event_phase phase) {
    impl_ptr<impl>()->set_phase(std::move(phase));
}

#pragma mark - event_manager

ui::event_manager::event_manager() : base(std::make_shared<impl>()) {
}

ui::event_manager::event_manager(std::nullptr_t) : base(nullptr) {
}

ui::event_manager::~event_manager() = default;

flow::node<ui::event, ui::event_manager::context, ui::event_manager::context, false> ui::event_manager::begin_flow(
    method const &method) const {
    return impl_ptr<impl>()->begin_flow(method);
}

flow::node<ui::event_manager::context, ui::event_manager::context, ui::event_manager::context, false>
ui::event_manager::begin_flow() const {
    return impl_ptr<impl>()->begin_flow();
}

ui::event_inputtable &ui::event_manager::inputtable() {
    if (!this->_inputtable) {
        this->_inputtable = ui::event_inputtable{impl_ptr<ui::event_inputtable::impl>()};
    }
    return this->_inputtable;
}

#pragma mark -

std::string yas::to_string(ui::event const &event) {
    std::string type = "unknown";
    std::string values;

    if (event.type_info() == typeid(ui::cursor)) {
        type = "cursor";
        values = to_string(event.get<ui::cursor>());
    } else if (event.type_info() == typeid(ui::touch)) {
        type = "touch";
        values = to_string(event.get<ui::touch>());
    } else if (event.type_info() == typeid(ui::key)) {
        type = "key";
        values = to_string(event.get<ui::key>());
    } else if (event.type_info() == typeid(ui::modifier)) {
        type = "modifier";
        values = to_string(event.get<ui::modifier>());
    }

    return "{phase:" + to_string(event.phase()) + ", type:" + type + ", values:" + values + "}";
}

std::string yas::to_string(ui::event_manager::method const &method) {
    switch (method) {
        case ui::event_manager::method::cursor_changed:
            return "cursor_changed";
        case ui::event_manager::method::touch_changed:
            return "touch_changed";
        case ui::event_manager::method::key_changed:
            return "key_changed";
        case ui::event_manager::method::modifier_changed:
            return "modifier_changed";
    }
}

std::ostream &operator<<(std::ostream &os, yas::ui::event const &event) {
    os << to_string(event);
    return os;
}

std::ostream &operator<<(std::ostream &os, yas::ui::event_manager::method const &method) {
    os << to_string(method);
    return os;
}
<|endoftext|>