<commit_before>/******************************************************************************
 * This file is part of the Gluon Development Platform
 * Copyright (C) 2010 Arjen Hiemstra <>
 * Copyright (C) 2010 Dan Leinir Turthra Jensen <admin@leinir.dk>
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 */

#include "gameobject.h"
#include "gameobjectprivate.h"
#include "component.h"
#include "core/debughelper.h"

REGISTER_OBJECTTYPE(GluonEngine, GameObject)

using namespace GluonEngine;

GameObject::GameObject(QObject * parent)
        : GluonObject(parent)
{
    d = new GameObjectPrivate;

    updateTransform();
}

GameObject::GameObject(const GameObject &other, QObject * parent)
        : GluonObject(parent)
        , d(other.d)
{
    updateTransform();
}

GameObject::~GameObject()
{
}

void
GameObject::sanitize()
{
    if (this->parent())
    {
        if (this->parent()->metaObject())
        {
            if (QString::compare(this->parent()->metaObject()->className(), "GameObject"))
            {
                GameObject * theParent = qobject_cast<GameObject*>(this->parent());
                if (theParent)
                {
                    theParent->addChild(this);
                }
            }
        }
    }
    GluonObject::sanitize();
}

void
GameObject::start()
{
    foreach(Component * component, d->components)
    if (component->enabled())
        component->start();

    foreach(GameObject * child, d->children)
    child->start();
}

void
GameObject::update(int elapsedMilliseconds)
{
    if(!d->enabled)
        return;

    foreach(Component * component, d->components)
    if (component->enabled())
        component->update(elapsedMilliseconds);

    //DEBUG_TEXT(QString("Updating %1 children").arg(d->children.count()))
    foreach(GameObject * child, d->children)
    child->update(elapsedMilliseconds);
}

void
GameObject::draw(int timeLapse)
{
    if(!d->enabled)
        return;

    foreach(Component * component, d->components)
    if (component->enabled())
        component->draw(timeLapse);

    foreach(GameObject * child, d->children)
    child->draw(timeLapse);
}

void GameObject::stop()
{
    foreach(Component * component, d->components)
    component->stop();

    foreach(GameObject * child, d->children)
    child->stop();
}

void
GameObject::runCommand(const QString &functionName)
{
    #ifdef __GNUC__
    #warning TODO: Implement - QMetaObject::invokeMethod does lots of magic, and we really ought to support it all... postponing implementation for a little while until the rest is complete
    #endif
}

void
GameObject::runCommandInChildren(const QString &functionName)
{
    foreach(GameObject * child, d->children)
    child->runCommand(functionName);
}

// ----------------------------------------------------------------------------
// Component management

Component *
GameObject::findComponent(const QString &name) const
{
    Component * found = 0;
    foreach(Component * component, d->components)
    {
        if (component->name() == name)
        {
            found = component;
            break;
        }
    }
    return found;
}

Component *
GameObject::findComponentByType(const QString &typeName) const
{
    Component * found = 0;
    const QMetaObject * metaObject;
    foreach(Component * component, d->components)
    {
        metaObject = component->metaObject();
        if (metaObject)
        {
            if (metaObject->className() == typeName)
            {
                found = component;
                break;
            }
        }
    }
    return found;
}

Component *
GameObject::findComponentInChildren(const QString &name) const
{
    Component * found = 0;
    foreach(GameObject * child, d->children)
    {
        found = child->findComponent(name);
        if (found)
            break;
        found = child->findComponentInChildren(name);
        if (found)
            break;
    }
    return found;
}

Component *
GameObject::findComponentInChildrenByType(const QString &typeName) const
{
    Component * found = 0;
    foreach(GameObject * child, d->children)
    {
        found = child->findComponentByType(typeName);
        if (found)
            break;
        found = child->findComponentInChildrenByType(typeName);
        if (found)
            break;
    }
    return found;
}

QList<Component *>
GameObject::findComponentsInChildren(const QString &name) const
{
    QList<Component *> found;
    Component * tempFound;
    foreach(GameObject * child, d->children)
    {
        tempFound = child->findComponent(name);
        if (tempFound)
            found.append(tempFound);
        found.append(child->findComponentInChildren(name));
    }
    return found;
}

QList<Component *>
GameObject::findComponentsInChildrenByType(const QString &typeName) const
{
    QList<Component *> found;
    Component * tempFound;
    foreach(GameObject * child, d->children)
    {
        tempFound = child->findComponentByType(typeName);
        if (tempFound)
            found.append(tempFound);
        found.append(child->findComponentsInChildrenByType(typeName));
    }
    return found;
}

void
GameObject::addComponent(Component * addThis)
{
    DEBUG_FUNC_NAME
    if (addThis)
    {
        DEBUG_TEXT(QString("Adding %2 to %1").arg(name()).arg(addThis->metaObject()->className()));
        if (!d->components.contains(addThis))
        {
            d->components.append(addThis);
            addThis->setParent(this);
            addThis->setGameObject(this);
        }
    }
    else
    {
        DEBUG_TEXT("Attempting to add a null component");
    }
}

bool
GameObject::removeComponent(Component * removeThis)
{
    return d->components.removeOne(removeThis);
}

// ----------------------------------------------------------------
// GameObject tree management

GameObject *
GameObject::childGameObject(int index) const
{
    return d->children.at(index);
}

GameObject *
GameObject::childGameObject(const QString &name) const
{
    GameObject * found = 0;
    foreach(GameObject * child, d->children)
    {
        if (child->name() == name)
        {
            found = child;
            break;
        }
    }
    return found;
}

void GameObject::addChild(GluonObject* child)
{
    GluonCore::GluonObject::addChild(child);
}

void
GameObject::addChild(GameObject * addThis)
{
    DEBUG_FUNC_NAME
    if (!addThis)
    {
        DEBUG_TEXT(QString("Fail-add! you're trying to add a NULL GameObject"));
    }
    else if (!d->children.contains(addThis))
    {
        d->children.append(addThis);

        if (addThis->d->parentGameObject)
            addThis->d->parentGameObject->removeChild(addThis);

        addThis->d->parentGameObject = this;
        GluonCore::GluonObject::addChild(addThis);
    }
}

void
GameObject::addChildAt(GameObject * addThis, int index)
{
    DEBUG_FUNC_NAME
    if (!addThis || index >= d->children.count())
    {
        DEBUG_TEXT(QString("Fail-add! you're trying to add a NULL GameObject or specified an index that is out of range."));
    }
    else if (!d->children.contains(addThis))
    {
        d->children.insert(index, addThis);

        if (addThis->d->parentGameObject)
            addThis->d->parentGameObject->removeChild(addThis);

        addThis->d->parentGameObject = this;
        GluonCore::GluonObject::addChild(addThis);
    }
}

bool
GameObject::removeChild(GameObject * removeThis)
{
    removeThis->d->parentGameObject = 0;
    return d->children.removeOne(removeThis);
}

bool GameObject::removeChild(GluonObject* child)
{
    return GluonObject::removeChild(child);
}

int
GameObject::childCount() const
{
    return d->children.count();
}

int
GameObject::childIndex(GameObject* child) const
{
    return d->children.indexOf(child);
}

void
GameObject::setParentGameObject(GameObject * newParent)
{
    //Do nothing if the new parent is the same as the old one.
    if (d->parentGameObject == newParent)
        return;

    // Clean up... We shouldn't be a child of more than one GameObject, or things will BLOW UP
    if (d->parentGameObject)
        d->parentGameObject->removeChild(this);

    // We could potentially be setting ourselves as a top level GameObject... Don't die!
    if (newParent)
        newParent->addChild(this);

    d->parentGameObject = newParent;
}

GameObject *
GameObject::parentGameObject()
{
    return d->parentGameObject;
}

// ----------------------------------------------------------------------------
// Property getter-setters

void
GameObject::setDescription(const QString &newDescription)
{
    d->description = newDescription;
}

QString
GameObject::description() const
{
    return d->description;
}

bool
GameObject::enabled() const
{
    return d->enabled;
}

void
GameObject::setEnabled(bool newEnabled)
{
    d->enabled = newEnabled;
}

//// Translation ////

QVector3D
GameObject::position() const
{
    return d->position;
}

QVector3D
GameObject::worldPosition() const
{
    return d->worldPosition;
}

void
GameObject::setPosition(const QVector3D& newPosition)
{
    d->position = newPosition;

    d->transformInvalidated = true;
    updateTransform();
}

void GameObject::setPosition(float x, float y, float z)
{
    setPosition(QVector3D(x, y, z));
}

void
GameObject::translate(const QVector3D& translation, GameObject::TransformSpace ts)
{
    if(ts == TS_LOCAL)
    {
        setPosition(position() + translation);
    }
    else
    {
        #ifdef __GNUC__
        #warning This probably needs fixing to account for world scale/orientation
        #endif
        setPosition((worldPosition() + translation) - position());
    }
}

void
GameObject::translate(float x, float y, float z, GameObject::TransformSpace ts)
{
    translate(QVector3D(x, y, z), ts);
}

//// Scaling ////

QVector3D
GameObject::scale() const
{
    return d->scale;
}

QVector3D
GameObject::worldScale() const
{
    return d->worldScale;
}

void
GameObject::setScale(const QVector3D& newScale)
{
    d->scale = newScale;

    d->transformInvalidated = true;
    updateTransform();
}

void GameObject::setScale(float x, float y, float z)
{
    setScale(QVector3D(x, y, z));
}

void GameObject::scaleRelative(QVector3D scaling, GameObject::TransformSpace ts)
{
    if(ts == TS_LOCAL)
    {
        setScale(scale() + scaling);
    }
    else
    {
        setScale((worldScale() + scaling) - scale());
    }
}

void GameObject::scaleRelative(float x, float y, float z, GameObject::TransformSpace ts)
{
    scaleRelative(QVector3D(x, y, z), ts);
}

//// Orientation ////

QQuaternion GameObject::orientation() const
{
    return d->orientation;
}

QQuaternion
GameObject::worldOrientation() const
{
    return d->worldOrientation;
}

void GameObject::setOrientation(const QQuaternion& newOrientation)
{
    d->orientation = newOrientation;

    d->transformInvalidated = true;
    updateTransform();
}

void GameObject::orient(QQuaternion rotation, GameObject::TransformSpace ts)
{
    if(ts == TS_LOCAL)
    {
        setOrientation(orientation() * rotation);
    }
    else
    {
        //setOrientation((worldOrientation() * rotation) / orientation());
    }
}

void GameObject::updateTransform()

{
    if (!d->transformInvalidated) return;

    GameObject* parent = parentGameObject();

    if (parent)
    {
        //Calculate the new world position
        d->worldPosition = parent->worldPosition() + parent->worldOrientation().rotatedVector(parent->worldScale() * d->position);
        d->worldOrientation = parent->worldOrientation() * d->orientation;
        d->worldScale = parent->worldScale() * d->scale;
    }
    else
    {
        //Apparently we do not have a parent, just set our local position to world then
        d->worldPosition = d->position;
        d->worldOrientation = d->orientation;
        d->worldScale = d->scale;
    }

    //Calculate the new transform matrix
    d->transform.setToIdentity();
    d->transform.translate(d->worldPosition);
    d->transform.rotate(d->worldOrientation);
    d->transform.scale(d->worldScale);

    // Finally, update the child objects' position
    foreach(GameObject *child, d->children)
    {
        child->invalidateTransform();
        child->updateTransform();
    }

    d->transformInvalidated = false;
}

void GameObject::invalidateTransform()
{
    d->transformInvalidated = true;
}

QMatrix4x4
GameObject::transform() const
{
    return d->transform;
}

void
GameObject::postCloneSanitize()
{
    foreach(QObject* child, children())
    {
        if(qobject_cast<GameObject*>(child))
        {
            GameObject* gaob = qobject_cast<GameObject*>(child);
            if (!d->children.contains(gaob))
            {
                d->children.append(gaob);

                if (gaob->d->parentGameObject)
                    gaob->d->parentGameObject->removeChild(gaob);

                gaob->d->parentGameObject = this;
            }
        }
        else if(qobject_cast<Component*>(child))
        {
            Component* comp = qobject_cast<Component*>(child);
            d->components.append(comp);
            comp->setParent(this);
            comp->setGameObject(this);
        }
    }
    GluonCore::GluonObject::postCloneSanitize();
}

#include "gameobject.moc"
<commit_msg>Start should be called on all objects, including those that are disabled<commit_after>/******************************************************************************
 * This file is part of the Gluon Development Platform
 * Copyright (C) 2010 Arjen Hiemstra <>
 * Copyright (C) 2010 Dan Leinir Turthra Jensen <admin@leinir.dk>
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 */

#include "gameobject.h"
#include "gameobjectprivate.h"
#include "component.h"
#include "core/debughelper.h"

REGISTER_OBJECTTYPE(GluonEngine, GameObject)

using namespace GluonEngine;

GameObject::GameObject(QObject * parent)
        : GluonObject(parent)
{
    d = new GameObjectPrivate;

    updateTransform();
}

GameObject::GameObject(const GameObject &other, QObject * parent)
        : GluonObject(parent)
        , d(other.d)
{
    updateTransform();
}

GameObject::~GameObject()
{
}

void
GameObject::sanitize()
{
    if (this->parent())
    {
        if (this->parent()->metaObject())
        {
            if (QString::compare(this->parent()->metaObject()->className(), "GameObject"))
            {
                GameObject * theParent = qobject_cast<GameObject*>(this->parent());
                if (theParent)
                {
                    theParent->addChild(this);
                }
            }
        }
    }
    GluonObject::sanitize();
}

void
GameObject::start()
{
    foreach(Component * component, d->components)
        component->start();

    foreach(GameObject * child, d->children)
        child->start();
}

void
GameObject::update(int elapsedMilliseconds)
{
    if(!d->enabled)
        return;

    foreach(Component * component, d->components)
        if (component->enabled())
            component->update(elapsedMilliseconds);

    //DEBUG_TEXT(QString("Updating %1 children").arg(d->children.count()))
    foreach(GameObject * child, d->children)
        child->update(elapsedMilliseconds);
}

void
GameObject::draw(int timeLapse)
{
    if(!d->enabled)
        return;

    foreach(Component * component, d->components)
        if (component->enabled())
            component->draw(timeLapse);

    foreach(GameObject * child, d->children)
        child->draw(timeLapse);
}

void GameObject::stop()
{
    foreach(Component * component, d->components)
        component->stop();

    foreach(GameObject * child, d->children)
        child->stop();
}

void
GameObject::runCommand(const QString &functionName)
{
    #ifdef __GNUC__
    #warning TODO: Implement - QMetaObject::invokeMethod does lots of magic, and we really ought to support it all... postponing implementation for a little while until the rest is complete
    #endif
}

void
GameObject::runCommandInChildren(const QString &functionName)
{
    foreach(GameObject * child, d->children)
    child->runCommand(functionName);
}

// ----------------------------------------------------------------------------
// Component management

Component *
GameObject::findComponent(const QString &name) const
{
    Component * found = 0;
    foreach(Component * component, d->components)
    {
        if (component->name() == name)
        {
            found = component;
            break;
        }
    }
    return found;
}

Component *
GameObject::findComponentByType(const QString &typeName) const
{
    Component * found = 0;
    const QMetaObject * metaObject;
    foreach(Component * component, d->components)
    {
        metaObject = component->metaObject();
        if (metaObject)
        {
            if (metaObject->className() == typeName)
            {
                found = component;
                break;
            }
        }
    }
    return found;
}

Component *
GameObject::findComponentInChildren(const QString &name) const
{
    Component * found = 0;
    foreach(GameObject * child, d->children)
    {
        found = child->findComponent(name);
        if (found)
            break;
        found = child->findComponentInChildren(name);
        if (found)
            break;
    }
    return found;
}

Component *
GameObject::findComponentInChildrenByType(const QString &typeName) const
{
    Component * found = 0;
    foreach(GameObject * child, d->children)
    {
        found = child->findComponentByType(typeName);
        if (found)
            break;
        found = child->findComponentInChildrenByType(typeName);
        if (found)
            break;
    }
    return found;
}

QList<Component *>
GameObject::findComponentsInChildren(const QString &name) const
{
    QList<Component *> found;
    Component * tempFound;
    foreach(GameObject * child, d->children)
    {
        tempFound = child->findComponent(name);
        if (tempFound)
            found.append(tempFound);
        found.append(child->findComponentInChildren(name));
    }
    return found;
}

QList<Component *>
GameObject::findComponentsInChildrenByType(const QString &typeName) const
{
    QList<Component *> found;
    Component * tempFound;
    foreach(GameObject * child, d->children)
    {
        tempFound = child->findComponentByType(typeName);
        if (tempFound)
            found.append(tempFound);
        found.append(child->findComponentsInChildrenByType(typeName));
    }
    return found;
}

void
GameObject::addComponent(Component * addThis)
{
    DEBUG_FUNC_NAME
    if (addThis)
    {
        DEBUG_TEXT(QString("Adding %2 to %1").arg(name()).arg(addThis->metaObject()->className()));
        if (!d->components.contains(addThis))
        {
            d->components.append(addThis);
            addThis->setParent(this);
            addThis->setGameObject(this);
        }
    }
    else
    {
        DEBUG_TEXT("Attempting to add a null component");
    }
}

bool
GameObject::removeComponent(Component * removeThis)
{
    return d->components.removeOne(removeThis);
}

// ----------------------------------------------------------------
// GameObject tree management

GameObject *
GameObject::childGameObject(int index) const
{
    return d->children.at(index);
}

GameObject *
GameObject::childGameObject(const QString &name) const
{
    GameObject * found = 0;
    foreach(GameObject * child, d->children)
    {
        if (child->name() == name)
        {
            found = child;
            break;
        }
    }
    return found;
}

void GameObject::addChild(GluonObject* child)
{
    GluonCore::GluonObject::addChild(child);
}

void
GameObject::addChild(GameObject * addThis)
{
    DEBUG_FUNC_NAME
    if (!addThis)
    {
        DEBUG_TEXT(QString("Fail-add! you're trying to add a NULL GameObject"));
    }
    else if (!d->children.contains(addThis))
    {
        d->children.append(addThis);

        if (addThis->d->parentGameObject)
            addThis->d->parentGameObject->removeChild(addThis);

        addThis->d->parentGameObject = this;
        GluonCore::GluonObject::addChild(addThis);
    }
}

void
GameObject::addChildAt(GameObject * addThis, int index)
{
    DEBUG_FUNC_NAME
    if (!addThis || index >= d->children.count())
    {
        DEBUG_TEXT(QString("Fail-add! you're trying to add a NULL GameObject or specified an index that is out of range."));
    }
    else if (!d->children.contains(addThis))
    {
        d->children.insert(index, addThis);

        if (addThis->d->parentGameObject)
            addThis->d->parentGameObject->removeChild(addThis);

        addThis->d->parentGameObject = this;
        GluonCore::GluonObject::addChild(addThis);
    }
}

bool
GameObject::removeChild(GameObject * removeThis)
{
    removeThis->d->parentGameObject = 0;
    return d->children.removeOne(removeThis);
}

bool GameObject::removeChild(GluonObject* child)
{
    return GluonObject::removeChild(child);
}

int
GameObject::childCount() const
{
    return d->children.count();
}

int
GameObject::childIndex(GameObject* child) const
{
    return d->children.indexOf(child);
}

void
GameObject::setParentGameObject(GameObject * newParent)
{
    //Do nothing if the new parent is the same as the old one.
    if (d->parentGameObject == newParent)
        return;

    // Clean up... We shouldn't be a child of more than one GameObject, or things will BLOW UP
    if (d->parentGameObject)
        d->parentGameObject->removeChild(this);

    // We could potentially be setting ourselves as a top level GameObject... Don't die!
    if (newParent)
        newParent->addChild(this);

    d->parentGameObject = newParent;
}

GameObject *
GameObject::parentGameObject()
{
    return d->parentGameObject;
}

// ----------------------------------------------------------------------------
// Property getter-setters

void
GameObject::setDescription(const QString &newDescription)
{
    d->description = newDescription;
}

QString
GameObject::description() const
{
    return d->description;
}

bool
GameObject::enabled() const
{
    return d->enabled;
}

void
GameObject::setEnabled(bool newEnabled)
{
    d->enabled = newEnabled;
}

//// Translation ////

QVector3D
GameObject::position() const
{
    return d->position;
}

QVector3D
GameObject::worldPosition() const
{
    return d->worldPosition;
}

void
GameObject::setPosition(const QVector3D& newPosition)
{
    d->position = newPosition;

    d->transformInvalidated = true;
    updateTransform();
}

void GameObject::setPosition(float x, float y, float z)
{
    setPosition(QVector3D(x, y, z));
}

void
GameObject::translate(const QVector3D& translation, GameObject::TransformSpace ts)
{
    if(ts == TS_LOCAL)
    {
        setPosition(position() + translation);
    }
    else
    {
        #ifdef __GNUC__
        #warning This probably needs fixing to account for world scale/orientation
        #endif
        setPosition((worldPosition() + translation) - position());
    }
}

void
GameObject::translate(float x, float y, float z, GameObject::TransformSpace ts)
{
    translate(QVector3D(x, y, z), ts);
}

//// Scaling ////

QVector3D
GameObject::scale() const
{
    return d->scale;
}

QVector3D
GameObject::worldScale() const
{
    return d->worldScale;
}

void
GameObject::setScale(const QVector3D& newScale)
{
    d->scale = newScale;

    d->transformInvalidated = true;
    updateTransform();
}

void GameObject::setScale(float x, float y, float z)
{
    setScale(QVector3D(x, y, z));
}

void GameObject::scaleRelative(QVector3D scaling, GameObject::TransformSpace ts)
{
    if(ts == TS_LOCAL)
    {
        setScale(scale() + scaling);
    }
    else
    {
        setScale((worldScale() + scaling) - scale());
    }
}

void GameObject::scaleRelative(float x, float y, float z, GameObject::TransformSpace ts)
{
    scaleRelative(QVector3D(x, y, z), ts);
}

//// Orientation ////

QQuaternion GameObject::orientation() const
{
    return d->orientation;
}

QQuaternion
GameObject::worldOrientation() const
{
    return d->worldOrientation;
}

void GameObject::setOrientation(const QQuaternion& newOrientation)
{
    d->orientation = newOrientation;

    d->transformInvalidated = true;
    updateTransform();
}

void GameObject::orient(QQuaternion rotation, GameObject::TransformSpace ts)
{
    if(ts == TS_LOCAL)
    {
        setOrientation(orientation() * rotation);
    }
    else
    {
        //setOrientation((worldOrientation() * rotation) / orientation());
    }
}

void GameObject::updateTransform()

{
    if (!d->transformInvalidated) return;

    GameObject* parent = parentGameObject();

    if (parent)
    {
        //Calculate the new world position
        d->worldPosition = parent->worldPosition() + parent->worldOrientation().rotatedVector(parent->worldScale() * d->position);
        d->worldOrientation = parent->worldOrientation() * d->orientation;
        d->worldScale = parent->worldScale() * d->scale;
    }
    else
    {
        //Apparently we do not have a parent, just set our local position to world then
        d->worldPosition = d->position;
        d->worldOrientation = d->orientation;
        d->worldScale = d->scale;
    }

    //Calculate the new transform matrix
    d->transform.setToIdentity();
    d->transform.translate(d->worldPosition);
    d->transform.rotate(d->worldOrientation);
    d->transform.scale(d->worldScale);

    // Finally, update the child objects' position
    foreach(GameObject *child, d->children)
    {
        child->invalidateTransform();
        child->updateTransform();
    }

    d->transformInvalidated = false;
}

void GameObject::invalidateTransform()
{
    d->transformInvalidated = true;
}

QMatrix4x4
GameObject::transform() const
{
    return d->transform;
}

void
GameObject::postCloneSanitize()
{
    foreach(QObject* child, children())
    {
        if(qobject_cast<GameObject*>(child))
        {
            GameObject* gaob = qobject_cast<GameObject*>(child);
            if (!d->children.contains(gaob))
            {
                d->children.append(gaob);

                if (gaob->d->parentGameObject)
                    gaob->d->parentGameObject->removeChild(gaob);

                gaob->d->parentGameObject = this;
            }
        }
        else if(qobject_cast<Component*>(child))
        {
            Component* comp = qobject_cast<Component*>(child);
            d->components.append(comp);
            comp->setParent(this);
            comp->setGameObject(this);
        }
    }
    GluonCore::GluonObject::postCloneSanitize();
}

#include "gameobject.moc"
<|endoftext|>


<commit_before>#include "voyager/http/http_request_parser.h"

#include <stdio.h>
#include <string>

#include "voyager/core/buffer.h"

namespace voyager {

HttpRequestParser::HttpRequestParser()
    : state_(kLine), request_(new HttpRequest()) {
}

bool HttpRequestParser::ParseBuffer(Buffer* buf) {
  bool ok = true;
  bool flag = true;
  while (flag && ok) {
    if (state_ == kLine) {
      const char* crlf = buf->FindCRLF();
      if (crlf) {
        ok = ParseRequestLine(buf->Peek(), crlf);
        if (ok) {
          buf->RetrieveUntil(crlf+2);
          state_ = kHeaders;
        } else {
          flag = false;
        }
      } else {
        flag = false;
      }
    } else if (state_ == kHeaders) {
      const char* crlf = buf->FindCRLF();
      if (crlf) {
        const char* colon = buf->Peek();
        if (colon == crlf) {
          state_ = kBody;
        } else {
          while (colon != crlf && *colon != ':') {
            ++colon;
          }
          if (colon == buf->Peek() || colon == crlf) {
            ok = false;
          } else {
            request_->AddHeader(buf->Peek(), colon, crlf);
          }
        }
        buf->RetrieveUntil(crlf + 2);
      } else {
        flag = false;
      }
    } else if (state_ == kBody) {
      if (ParseRequestBody(buf)) {
        state_ = kEnd;
      }
      flag = false;
    } else {
    }
  }
  return ok;
}

void HttpRequestParser::Reset() {
  request_.reset(new HttpRequest());
}

bool HttpRequestParser::ParseRequestLine(const char* begin, const char* end) {
  bool ok = false;
  const char* tmp = begin;
  while (tmp != end && !isspace(*tmp)) {
    ++tmp;
  }
  if (tmp != end && request_->SetMethod(begin, tmp)) {
    ++tmp;
    const char* start = tmp;
    const char* p = nullptr;
    while (tmp != end && !isspace(*tmp)) {
      if (*tmp == '?') {
        p = tmp;
      }
      ++tmp;
    }
    if (tmp != end) {
      if (p != nullptr) {
        request_->SetPath(start, p);
        request_->SetQuery(p, tmp);
      } else {
        request_->SetPath(start, tmp);
      }
      start = tmp + 1;
      ok = request_->SetVersion(start, end);
    }
  }
  return ok;
}

bool HttpRequestParser::ParseRequestBody(Buffer* buf) {
  const std::string& s = request_->Value(HttpMessage::kContentLength);
  if (request_->GetMethod() != HttpRequest::kPost || s.empty()) {
    return true;
  }
  if (static_cast<int>(buf->ReadableSize()) == atoi(&*(s.begin()))) {
    request_->SetBody(buf->RetrieveAllAsString());
    return true;
  }
  return false;
}

}  // namespace voyager
<commit_msg>fix bug<commit_after>#include "voyager/http/http_request_parser.h"

#include <stdio.h>
#include <string>

#include "voyager/core/buffer.h"

namespace voyager {

HttpRequestParser::HttpRequestParser()
    : state_(kLine), request_(new HttpRequest()) {
}

bool HttpRequestParser::ParseBuffer(Buffer* buf) {
  bool ok = true;
  bool flag = true;
  while (flag && ok) {
    if (state_ == kLine) {
      const char* crlf = buf->FindCRLF();
      if (crlf) {
        ok = ParseRequestLine(buf->Peek(), crlf);
        if (ok) {
          buf->RetrieveUntil(crlf+2);
          state_ = kHeaders;
        } else {
          flag = false;
        }
      } else {
        flag = false;
      }
    } else if (state_ == kHeaders) {
      const char* crlf = buf->FindCRLF();
      if (crlf) {
        const char* colon = buf->Peek();
        if (colon == crlf) {
          state_ = kBody;
        } else {
          while (colon != crlf && *colon != ':') {
            ++colon;
          }
          if (colon == buf->Peek() || colon == crlf) {
            ok = false;
          } else {
            request_->AddHeader(buf->Peek(), colon, crlf);
          }
        }
        buf->RetrieveUntil(crlf + 2);
      } else {
        flag = false;
      }
    } else if (state_ == kBody) {
      if (ParseRequestBody(buf)) {
        state_ = kEnd;
      }
      flag = false;
    } else {
    }
  }
  return ok;
}

void HttpRequestParser::Reset() {
  state_ = kLine;
  request_.reset(new HttpRequest());
}

bool HttpRequestParser::ParseRequestLine(const char* begin, const char* end) {
  bool ok = false;
  const char* tmp = begin;
  while (tmp != end && !isspace(*tmp)) {
    ++tmp;
  }
  if (tmp != end && request_->SetMethod(begin, tmp)) {
    ++tmp;
    const char* start = tmp;
    const char* p = nullptr;
    while (tmp != end && !isspace(*tmp)) {
      if (*tmp == '?') {
        p = tmp;
      }
      ++tmp;
    }
    if (tmp != end) {
      if (p != nullptr) {
        request_->SetPath(start, p);
        request_->SetQuery(p, tmp);
      } else {
        request_->SetPath(start, tmp);
      }
      start = tmp + 1;
      ok = request_->SetVersion(start, end);
    }
  }
  return ok;
}

bool HttpRequestParser::ParseRequestBody(Buffer* buf) {
  const std::string& s = request_->Value(HttpMessage::kContentLength);
  if (request_->GetMethod() != HttpRequest::kPost || s.empty()) {
    return true;
  }
  if (static_cast<int>(buf->ReadableSize()) == atoi(&*(s.begin()))) {
    request_->SetBody(buf->RetrieveAllAsString());
    return true;
  }
  return false;
}

}  // namespace voyager
<|endoftext|>


<commit_before>/*
 * Copyright 2014 Open Connectome Project (http://openconnecto.me)
 * Written by Disa Mhembere (disa@jhu.edu)
 *
 * This file is part of FlashGraph.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "libgraph-algs/sem_kmeans.h"
#include "libgraph-algs/sem_kmeans_util.h"
#include "libgraph-algs/dist_matrix.h"

static std::vector<prune_cluster::ptr> g_clusters;
constexpr unsigned NCOL = 5;

// Any item with an iterator can be tested for equivalence
template <typename T>
bool all_equal(const T& arg0, const T& arg1) {
    return std::equal(arg0.begin(), arg0.end(), arg1.begin());
}

std::vector<std::vector<double>> test_init_g_clusters(const size_t k=4) {
    BOOST_LOG_TRIVIAL(info) << "Running init g_clusters";
    BOOST_VERIFY(k == 4);

    const std::vector<double> v1 {1, 2, 3, 4, 5};
    const std::vector<double> v2 {6, 7, 8, 9, 10};
    const std::vector<double> v3 {6E-12, -23423.7, .82342342432, 93., 10};
    const std::vector<double> v4 {-.2342, -23.342, -.000003232, -3.234232, 1};

    std::vector<std::vector<double>> means = {v1, v2, v3, v4};

    for (size_t cl = 0; cl < k; cl++) {
        g_clusters.push_back(prune_cluster::create(means[cl])); // ctor & init

        printf("c:%lu =>\n", cl);
        print_vector(g_clusters[cl]->get_mean());
        print_vector(means[cl]);

        BOOST_VERIFY(all_equal(means[cl], g_clusters[cl]->get_mean()));
    }
    printf("Exiting test_init_g_clusters!\n");
    return means;
}

void test_cluster() {
    size_t k = 4;
    std::vector<std::vector<double>> means = test_init_g_clusters(k);
    /* test prev_mean */

    // NOTE: Rotate means clockwise: 0 => 1; 1 => 2; 2 => 3; 3 => 0
    // dist(3,0), (1, 0), (1,2), (2,3)
    const std::vector<double> pdists =
        {ceil(sqrt(721.074)), ceil(sqrt(125)),
            ceil(sqrt(549004845.993)), ceil(sqrt(547586097.288))};

    std::vector<double> tmp;
    std::vector<double> prev = g_clusters.back()->get_mean();
    for (size_t cl = 0; cl < k; cl++) {
        tmp = g_clusters[cl]->get_mean();
        g_clusters[cl]->set_prev_mean();
        g_clusters[cl]->set_mean(prev);

        // Compute dist to prev
        g_clusters[cl]->set_prev_dist(eucl_dist(&((g_clusters[cl]->get_mean())[0]),
                    &((g_clusters[cl]->get_prev_mean())[0]), NCOL) );

        /* test prev_dist */
        BOOST_VERIFY(ceil(g_clusters[cl]->get_prev_dist()) == pdists[cl]);
        prev = tmp;
    }

    /* Test operator [] */
    for (unsigned i = 0; i < g_clusters[0]->size(); i++) {
        BOOST_VERIFY((*(g_clusters[1]))[i]  == means[0][i]);
    }

    /* Test add member */
    class data_seq_it {
        private:
            std::vector<double> data;
            unsigned pos;
        public:
            data_seq_it(std::vector<double>& data) {
                pos = 0;
                this->data = data;
            }
            bool has_next() { return pos < data.size(); }
            double next() { return data[pos++]; }
    };

    // Add 0 to 1
    data_seq_it dsi0(means[0]);
    data_seq_it dsi1(means[1]);

    g_clusters[2]->add_member(dsi0);
    g_clusters[1]->add_member(dsi1);

    BOOST_VERIFY(all_equal(g_clusters[2]->get_mean(),
                g_clusters[1]->get_mean()));

    std::cout << "\nMembers in 2 = " <<
        g_clusters[2]->get_num_members() << std::endl;
    std::cout << "Members in 1 = " <<
        g_clusters[1]->get_num_members() << std::endl;

    BOOST_VERIFY(g_clusters[2]->get_num_members() == 1);
    BOOST_VERIFY(g_clusters[1]->get_num_members() == 1);

    // Test remove member
    dsi0 = data_seq_it(means[0]);
    dsi1 = data_seq_it(means[1]);
    g_clusters[1]->remove_member(dsi1);
    g_clusters[1]->remove_member(dsi0);
    std::vector<double> zeros {0,0,0,0,0};

    BOOST_VERIFY(all_equal(g_clusters[1]->get_mean(), zeros));
    BOOST_VERIFY(g_clusters[1]->get_num_members() == -1);
    printf("Exiting test_cluster ==> ");
}

void test_eucl() {
    // Positive
    std::vector<double> v1 {1, 2, 3, 4, 5};
    std::vector<double> v2 {6, 7, 8, 9, 10};
    BOOST_VERIFY(eucl_dist(&v1[0], &v2[0], NCOL) == sqrt(125.0));
    BOOST_VERIFY(eucl_dist(&v2[0], &v1[0], NCOL) == sqrt(125.0));

    // Neg-pos, Pos-neg
    std::vector<double> v3 {6E-12, -23423.7, .82342342432, 93., 10};
    BOOST_VERIFY(ceil(eucl_dist(&v1[0], &v3[0], NCOL)) ==
            ceil(sqrt(548771372.227)));
    BOOST_VERIFY(ceil(eucl_dist(&v3[0], &v1[0], NCOL))
            == ceil(sqrt(548771372.227)));

    // No-op
    std::vector<double> v4 {0, 0, 0, 0, 0};
    BOOST_VERIFY(eucl_dist(&v1[0], &v4[0], NCOL) ==
            eucl_dist(&v4[0], &v1[0], NCOL));
    BOOST_VERIFY(eucl_dist(&v4[0], &v1[0], NCOL) == sqrt(55));

    // Neg-neg
    std::vector<double> v5 {-.2342, -23.342, -.000003232, -3.234232, 1};
    BOOST_VERIFY(ceil(eucl_dist(&v5[0], &v3[0], NCOL))
            == ceil(sqrt(547586097.2884537)));
    BOOST_VERIFY(ceil(eucl_dist(&v3[0], &v5[0], NCOL))
            == ceil(sqrt(547586097.2884537)));

    double arr1[10] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
    double arr2[10] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
    BOOST_VERIFY(eucl_dist(&arr1[0], &arr2[5], NCOL) == sqrt(125));

    printf("Exiting test_eucl ==> ");
}

void test_dist_matrix() {
    constexpr unsigned k = 4;
    test_init_g_clusters();
    dist_matrix::ptr test_mat = dist_matrix::create(k);

    /* Test compute_dist */
    test_mat->compute_dist(g_clusters, k);

    printf("Clusters:\n"); print_clusters<prune_cluster>(g_clusters);
    printf("Cluster distance :\n"); test_mat->print();

    /* Test s_val */
    printf("Printing s_vals:\n");
    for (unsigned i = 0; i < k; i++) {
        BOOST_VERIFY(g_clusters[i]->get_s_val() ==
                test_mat->get_min_dist(i));
    }
    printf("\n");
    printf("Exiting test_dist_matrix ==> ");
}

int main(int argc, char* argv[]) {
    if (argc > 1) {
        if (std::string(argv[1]) == "-e") {
            test_eucl(); std::cout << "Test eucl Success ...\n";
        } else if (std::string(argv[1]) == "-d") {
            test_dist_matrix(); std::cout << "Test distance matrix Success ...\n";
        } else if (std::string(argv[1]) == "-c") {
            test_cluster(); std::cout << "Test cluster Success ...\n";
        } else {
            fprintf(stderr, "Unknown test option '%s'", argv[1]);
        }
    } else { /* Do all tests */
        test_eucl(); std::cout << "Test eucl Success ...\n";
        test_dist_matrix(); std::cout << "Test distance matrix Success ...\n";
        test_cluster(); std::cout << "Test cluster Success ...\n";
    }
    return EXIT_SUCCESS;

}
<commit_msg>[Test]: Removed cluster test since it is stand alone and used clusters.h header<commit_after>/*
 * Copyright 2014 Open Connectome Project (http://openconnecto.me)
 * Written by Disa Mhembere (disa@jhu.edu)
 *
 * This file is part of FlashGraph.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "libgraph-algs/sem_kmeans.h"
#include "libgraph-algs/sem_kmeans_util.h"
#include "libgraph-algs/dist_matrix.h"

static prune_clusters::ptr g_clusters;
constexpr unsigned NCOL = 5;

// Any item with an iterator can be tested for equivalence
template <typename T>
bool all_equal(const T* arg0, const T* arg1, const unsigned numel) {
    return std::equal(arg0, arg0+numel, arg1);
}

std::vector<double> test_init_g_clusters(const size_t k=4) {
    BOOST_LOG_TRIVIAL(info) << "Running init g_clusters";
    BOOST_VERIFY(k == 4);

    const std::vector<double> v1 {1, 2, 3, 4, 5};
    const std::vector<double> v2 {6, 7, 8, 9, 10};
    const std::vector<double> v3 {6E-12, -23423.7, .82342342432, 93., 10};
    const std::vector<double> v4 {-.2342, -23.342, -.000003232, -3.234232, 1};

    const std::vector<double> v {1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
        6E-12, -23423.7, .82342342432, 93., 10, -.2342, -23.342, -.000003232, -3.234232, 1};
    g_clusters = prune_clusters::create(k, NCOL, v); // ctor & init

    printf("Set clusters: \n");
    g_clusters->print_means();

    for (size_t cl = 0; cl < k; cl++) {
        printf("c:%lu =>\n", cl);
        print_arr(&(v[cl*NCOL]), NCOL);

        BOOST_VERIFY(all_equal<double>(&v[0], &(g_clusters->get_means()[0]), NCOL*k));
    }
    printf("Exiting test_init_g_clusters!\n");
    return v;
}

void test_eucl() {
    // Positive
    std::vector<double> v1 {1, 2, 3, 4, 5};
    std::vector<double> v2 {6, 7, 8, 9, 10};
    BOOST_VERIFY(eucl_dist(&v1[0], &v2[0], NCOL) == sqrt(125.0));
    BOOST_VERIFY(eucl_dist(&v2[0], &v1[0], NCOL) == sqrt(125.0));

    // Neg-pos, Pos-neg
    std::vector<double> v3 {6E-12, -23423.7, .82342342432, 93., 10};
    BOOST_VERIFY(ceil(eucl_dist(&v1[0], &v3[0], NCOL)) ==
            ceil(sqrt(548771372.227)));
    BOOST_VERIFY(ceil(eucl_dist(&v3[0], &v1[0], NCOL))
            == ceil(sqrt(548771372.227)));

    // No-op
    std::vector<double> v4 {0, 0, 0, 0, 0};
    BOOST_VERIFY(eucl_dist(&v1[0], &v4[0], NCOL) ==
            eucl_dist(&v4[0], &v1[0], NCOL));
    BOOST_VERIFY(eucl_dist(&v4[0], &v1[0], NCOL) == sqrt(55));

    // Neg-neg
    std::vector<double> v5 {-.2342, -23.342, -.000003232, -3.234232, 1};
    BOOST_VERIFY(ceil(eucl_dist(&v5[0], &v3[0], NCOL))
            == ceil(sqrt(547586097.2884537)));
    BOOST_VERIFY(ceil(eucl_dist(&v3[0], &v5[0], NCOL))
            == ceil(sqrt(547586097.2884537)));

    double arr1[10] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
    double arr2[10] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
    BOOST_VERIFY(eucl_dist(&arr1[0], &arr2[5], NCOL) == sqrt(125));

    printf("Exiting test_eucl ==> ");
}

void test_dist_matrix() {
    constexpr unsigned k = 4;
    test_init_g_clusters();
    dist_matrix::ptr test_mat = dist_matrix::create(k);

    /* Test compute_dist */
    compute_dist(g_clusters, test_mat, NCOL);

    printf("Clusters:\n"); g_clusters->print_means();
    printf("Cluster distance :\n"); test_mat->print();

    /* Test s_val */
    printf("Printing s_vals:\n");
    for (unsigned i = 0; i < k; i++) {
        BOOST_VERIFY(g_clusters->get_s_val(i) ==
                test_mat->get_min_dist(i));
    }
    printf("\n");
    printf("Exiting test_dist_matrix ==> ");
}

int main(int argc, char* argv[]) {
    if (argc > 1) {
        if (std::string(argv[1]) == "-e") {
            test_eucl(); std::cout << "Test eucl Success ...\n";
        } else if (std::string(argv[1]) == "-d") {
            test_dist_matrix(); std::cout << "Test distance matrix Success ...\n";
        } else {
            fprintf(stderr, "Unknown test option '%s'", argv[1]);
        }
    } else { /* Do all tests */
        test_eucl(); std::cout << "Test eucl Success ...\n";
        test_dist_matrix(); std::cout << "Test distance matrix Success ...\n";
    }
    return EXIT_SUCCESS;
}
<|endoftext|>


<commit_before>#include "main_window.hpp"
#include <QVBoxLayout>
#include <QMessageBox>
#include "executable_viewer.hpp"

MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent)
{
    setWindowTitle(QString("Interactive Executable Mangler"));

    mdiArea = new QMdiArea();
    menuBar = new QMenuBar();

    QVBoxLayout *layout = new QVBoxLayout();
    layout->addWidget(menuBar);
    layout->addWidget(mdiArea);

    QMenu *file = menuBar->addMenu(QString("File"));
    QWidget *central = new QWidget(this);
    central->setLayout(layout);
    setCentralWidget(central);

    createActions();

    file->addAction(newAction);
    file->addAction(aboutAction);
}

void MainWindow::createActions()
{
    newAction = new QAction(QString("New"), this);
    aboutAction = new QAction(QString("About"), this);
    connect(newAction, SIGNAL(triggered()), this, SLOT(newFile()));
    connect(aboutAction, SIGNAL(triggered()), this, SLOT(about()));
}

void MainWindow::newFile()
{
    QString filename("hacker.out");
    ExecutableViewer *viewer = new ExecutableViewer(filename, mdiAresa);
    mdiArea->addSubWindow(viewer);
    viewer->show();
    mdiArea->tileSubWindows();
}

void MainWindow::about()
{
    QMessageBox::about(this, QString("About"),
        QString("
Ștefan Mirea & Adrian Dobrică 2016.

Click!
"));
}
<commit_msg>Fix typo for mdiArea<commit_after>#include "main_window.hpp"
#include <QVBoxLayout>
#include <QMessageBox>
#include "executable_viewer.hpp"

MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent)
{
    setWindowTitle(QString("Interactive Executable Mangler"));

    mdiArea = new QMdiArea();
    menuBar = new QMenuBar();

    QVBoxLayout *layout = new QVBoxLayout();
    layout->addWidget(menuBar);
    layout->addWidget(mdiArea);

    QMenu *file = menuBar->addMenu(QString("File"));
    QWidget *central = new QWidget(this);
    central->setLayout(layout);
    setCentralWidget(central);

    createActions();

    file->addAction(newAction);
    file->addAction(aboutAction);
}

void MainWindow::createActions()
{
    newAction = new QAction(QString("New"), this);
    aboutAction = new QAction(QString("About"), this);
    connect(newAction, SIGNAL(triggered()), this, SLOT(newFile()));
    connect(aboutAction, SIGNAL(triggered()), this, SLOT(about()));
}

void MainWindow::newFile()
{
    QString filename("hacker.out");
    ExecutableViewer *viewer = new ExecutableViewer(filename, mdiArea);
    mdiArea->addSubWindow(viewer);
    viewer->show();
    mdiArea->tileSubWindows();
}

void MainWindow::about()
{
    QMessageBox::about(this, QString("About"),
        QString("
Ștefan Mirea & Adrian Dobrică 2016.

Click!
"));
}
<|endoftext|>


<commit_before>// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "ash/system/power/tray_power.h"

#include "ash/shell.h"
#include "ash/system/date/date_view.h"
#include "ash/system/power/power_supply_status.h"
#include "ash/system/tray/system_tray_delegate.h"
#include "ash/system/tray/tray_constants.h"
#include "base/utf_string_conversions.h"
#include "base/stringprintf.h"
#include "grit/ui_resources.h"
#include "third_party/skia/include/core/SkBitmap.h"
#include "third_party/skia/include/core/SkRect.h"
#include "ui/base/resource/resource_bundle.h"
#include "ui/gfx/image/image.h"
#include "ui/gfx/size.h"
#include "ui/views/controls/button/button.h"
#include "ui/views/controls/button/text_button.h"
#include "ui/views/controls/image_view.h"
#include "ui/views/controls/label.h"
#include "ui/views/layout/box_layout.h"
#include "ui/views/view.h"
#include "ui/views/widget/widget.h"
#include "unicode/fieldpos.h"
#include "unicode/fmtable.h"

namespace ash {
namespace internal {

namespace {
// Width and height of battery images.
const int kBatteryImageHeight = 25;
const int kBatteryImageWidth = 25;
// Number of different power states.
const int kNumPowerImages = 16;
}

namespace tray {

// This view is used only for the tray.
class PowerTrayView : public views::ImageView {
 public:
  PowerTrayView() {
    UpdateImage();
  }

  virtual ~PowerTrayView() {
  }

  void UpdatePowerStatus(const PowerSupplyStatus& status) {
    supply_status_ = status;
    // Sanitize.
    if (supply_status_.battery_is_full)
      supply_status_.battery_percentage = 100.0;

    UpdateImage();
  }

 private:
  void UpdateImage() {
    SkBitmap image;
    gfx::Image all = ui::ResourceBundle::GetSharedInstance().GetImageNamed(
        IDR_AURA_UBER_TRAY_POWER_SMALL);

    int image_index = 0;
    if (supply_status_.battery_percentage >= 100) {
      image_index = kNumPowerImages - 1;
    } else if (!supply_status_.battery_is_present) {
      image_index = kNumPowerImages;
    } else {
      image_index = static_cast<int> (
          supply_status_.battery_percentage / 100.0 *
          (kNumPowerImages - 1));
      image_index =
        std::max(std::min(image_index, kNumPowerImages - 2), 0);
    }

    SkIRect region = SkIRect::MakeXYWH(
        supply_status_.line_power_on ? kBatteryImageWidth : 0,
        image_index * kBatteryImageHeight,
        kBatteryImageWidth, kBatteryImageHeight);
    all.ToSkBitmap()->extractSubset(&image, region);

    SetImage(image);
  }

  PowerSupplyStatus supply_status_;

  DISALLOW_COPY_AND_ASSIGN(PowerTrayView);
};

// This view is used only for the popup.
class PowerPopupView : public views::Label {
 public:
  PowerPopupView() {
    SetHorizontalAlignment(ALIGN_RIGHT);
    UpdateText();
  }

  virtual ~PowerPopupView() {
  }

  void UpdatePowerStatus(const PowerSupplyStatus& status) {
    supply_status_ = status;
    // Sanitize.
    if (supply_status_.battery_is_full)
      supply_status_.battery_percentage = 100.0;

    UpdateText();
  }

 private:
  void UpdateText() {
    base::TimeDelta time = base::TimeDelta::FromSeconds(
        supply_status_.line_power_on ?
        supply_status_.battery_seconds_to_full :
        supply_status_.battery_seconds_to_empty);
    int hour = time.InHours();
    int min = (time - base::TimeDelta::FromHours(hour)).InMinutes();
    // TODO: Translation
    SetText(ASCIIToUTF16(base::StringPrintf("Battery: %.0lf%%\n%dh%02dm",
          supply_status_.battery_percentage,
          hour, min)));
  }

  PowerSupplyStatus supply_status_;

  DISALLOW_COPY_AND_ASSIGN(PowerPopupView);
};

}  // namespace tray

TrayPower::TrayPower()
    : power_(NULL),
      power_tray_(NULL) {
}

TrayPower::~TrayPower() {
}

views::View* TrayPower::CreateTrayView(user::LoginStatus status) {
  PowerSupplyStatus power_status =
      ash::Shell::GetInstance()->tray_delegate()->GetPowerSupplyStatus();
  if (power_status.battery_is_present) {
    power_tray_.reset(new tray::PowerTrayView());
    power_tray_->UpdatePowerStatus(power_status);
  } else {
    power_tray_.reset();
  }
  return power_tray_.get();
}

views::View* TrayPower::CreateDefaultView(user::LoginStatus status) {
  date_.reset(new tray::DateView(tray::DateView::DATE));
  if (status != user::LOGGED_IN_NONE)
    date_->set_actionable(true);

  views::View* container = new views::View;
  views::BoxLayout* layout = new views::BoxLayout(views::BoxLayout::kHorizontal,
      kTrayPopupPaddingHorizontal, 10, 0);
  layout->set_spread_blank_space(true);
  container->SetLayoutManager(layout);
  container->set_background(views::Background::CreateSolidBackground(
      SkColorSetRGB(245, 245, 245)));
  container->AddChildView(date_.get());

  PowerSupplyStatus power_status =
      ash::Shell::GetInstance()->tray_delegate()->GetPowerSupplyStatus();
  if (power_status.battery_is_present) {
    power_.reset(new tray::PowerPopupView());
    power_->UpdatePowerStatus(power_status);
    container->AddChildView(power_.get());
  }
  return container;
}

views::View* TrayPower::CreateDetailedView(user::LoginStatus status) {
  return NULL;
}

void TrayPower::DestroyTrayView() {
  power_tray_.reset();
}

void TrayPower::DestroyDefaultView() {
  date_.reset();
  power_.reset();
}

void TrayPower::DestroyDetailedView() {
}

void TrayPower::OnPowerStatusChanged(const PowerSupplyStatus& status) {
  if (power_tray_.get())
    power_tray_->UpdatePowerStatus(status);
  if (power_.get())
    power_->UpdatePowerStatus(status);
}

}  // namespace internal
}  // namespace ash
<commit_msg>ash: Fix battery icon showing up in the tray.<commit_after>// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "ash/system/power/tray_power.h"

#include "ash/shell.h"
#include "ash/system/date/date_view.h"
#include "ash/system/power/power_supply_status.h"
#include "ash/system/tray/system_tray_delegate.h"
#include "ash/system/tray/tray_constants.h"
#include "base/utf_string_conversions.h"
#include "base/stringprintf.h"
#include "grit/ui_resources.h"
#include "third_party/skia/include/core/SkBitmap.h"
#include "third_party/skia/include/core/SkRect.h"
#include "ui/base/resource/resource_bundle.h"
#include "ui/gfx/image/image.h"
#include "ui/gfx/size.h"
#include "ui/views/controls/button/button.h"
#include "ui/views/controls/button/text_button.h"
#include "ui/views/controls/image_view.h"
#include "ui/views/controls/label.h"
#include "ui/views/layout/box_layout.h"
#include "ui/views/view.h"
#include "ui/views/widget/widget.h"
#include "unicode/fieldpos.h"
#include "unicode/fmtable.h"

namespace ash {
namespace internal {

namespace {
// Width and height of battery images.
const int kBatteryImageHeight = 25;
const int kBatteryImageWidth = 25;
// Number of different power states.
const int kNumPowerImages = 16;
}

namespace tray {

// This view is used only for the tray.
class PowerTrayView : public views::ImageView {
 public:
  PowerTrayView() {
    UpdateImage();
  }

  virtual ~PowerTrayView() {
  }

  void UpdatePowerStatus(const PowerSupplyStatus& status) {
    supply_status_ = status;
    // Sanitize.
    if (supply_status_.battery_is_full)
      supply_status_.battery_percentage = 100.0;

    UpdateImage();
    SetVisible(status.battery_is_present);
  }

 private:
  void UpdateImage() {
    SkBitmap image;
    gfx::Image all = ui::ResourceBundle::GetSharedInstance().GetImageNamed(
        IDR_AURA_UBER_TRAY_POWER_SMALL);

    int image_index = 0;
    if (supply_status_.battery_percentage >= 100) {
      image_index = kNumPowerImages - 1;
    } else if (!supply_status_.battery_is_present) {
      image_index = kNumPowerImages;
    } else {
      image_index = static_cast<int> (
          supply_status_.battery_percentage / 100.0 *
          (kNumPowerImages - 1));
      image_index =
        std::max(std::min(image_index, kNumPowerImages - 2), 0);
    }

    SkIRect region = SkIRect::MakeXYWH(
        supply_status_.line_power_on ? kBatteryImageWidth : 0,
        image_index * kBatteryImageHeight,
        kBatteryImageWidth, kBatteryImageHeight);
    all.ToSkBitmap()->extractSubset(&image, region);

    SetImage(image);
  }

  PowerSupplyStatus supply_status_;

  DISALLOW_COPY_AND_ASSIGN(PowerTrayView);
};

// This view is used only for the popup.
class PowerPopupView : public views::Label {
 public:
  PowerPopupView() {
    SetHorizontalAlignment(ALIGN_RIGHT);
    UpdateText();
  }

  virtual ~PowerPopupView() {
  }

  void UpdatePowerStatus(const PowerSupplyStatus& status) {
    supply_status_ = status;
    // Sanitize.
    if (supply_status_.battery_is_full)
      supply_status_.battery_percentage = 100.0;

    UpdateText();
  }

 private:
  void UpdateText() {
    base::TimeDelta time = base::TimeDelta::FromSeconds(
        supply_status_.line_power_on ?
        supply_status_.battery_seconds_to_full :
        supply_status_.battery_seconds_to_empty);
    int hour = time.InHours();
    int min = (time - base::TimeDelta::FromHours(hour)).InMinutes();
    // TODO: Translation
    SetText(ASCIIToUTF16(base::StringPrintf("Battery: %.0lf%%\n%dh%02dm",
          supply_status_.battery_percentage,
          hour, min)));
  }

  PowerSupplyStatus supply_status_;

  DISALLOW_COPY_AND_ASSIGN(PowerPopupView);
};

}  // namespace tray

TrayPower::TrayPower()
    : power_(NULL),
      power_tray_(NULL) {
}

TrayPower::~TrayPower() {
}

views::View* TrayPower::CreateTrayView(user::LoginStatus status) {
  // There may not be enough information when this is created about whether
  // there is a battery or not. So always create this, and adjust visibility as
  // necessary.
  PowerSupplyStatus power_status =
      ash::Shell::GetInstance()->tray_delegate()->GetPowerSupplyStatus();
  power_tray_.reset(new tray::PowerTrayView());
  power_tray_->UpdatePowerStatus(power_status);
  return power_tray_.get();
}

views::View* TrayPower::CreateDefaultView(user::LoginStatus status) {
  date_.reset(new tray::DateView(tray::DateView::DATE));
  if (status != user::LOGGED_IN_NONE)
    date_->set_actionable(true);

  views::View* container = new views::View;
  views::BoxLayout* layout = new views::BoxLayout(views::BoxLayout::kHorizontal,
      kTrayPopupPaddingHorizontal, 10, 0);
  layout->set_spread_blank_space(true);
  container->SetLayoutManager(layout);
  container->set_background(views::Background::CreateSolidBackground(
      SkColorSetRGB(245, 245, 245)));
  container->AddChildView(date_.get());

  PowerSupplyStatus power_status =
      ash::Shell::GetInstance()->tray_delegate()->GetPowerSupplyStatus();
  if (power_status.battery_is_present) {
    power_.reset(new tray::PowerPopupView());
    power_->UpdatePowerStatus(power_status);
    container->AddChildView(power_.get());
  }
  return container;
}

views::View* TrayPower::CreateDetailedView(user::LoginStatus status) {
  return NULL;
}

void TrayPower::DestroyTrayView() {
  power_tray_.reset();
}

void TrayPower::DestroyDefaultView() {
  date_.reset();
  power_.reset();
}

void TrayPower::DestroyDetailedView() {
}

void TrayPower::OnPowerStatusChanged(const PowerSupplyStatus& status) {
  if (power_tray_.get())
    power_tray_->UpdatePowerStatus(status);
  if (power_.get())
    power_->UpdatePowerStatus(status);
}

}  // namespace internal
}  // namespace ash
<|endoftext|>


<commit_before><commit_msg>Improve exception messages (for debugging)<commit_after><|endoftext|>


<commit_before>#ifndef UTIL_HPP_
#define UTIL_HPP_

#include <SFML/Config.hpp>

namespace sf {
    class Color;

    Color operator*(const Color &color, float f);
#if SFML_VERSION_MAJOR == 2 && SFML_VERSION < 2
    Color operator-(const Color& left, const Color& right);
#endif

}  // namespacs sf

#endif  // UTIL_HPP_
<commit_msg>util: fix a typo<commit_after>#ifndef UTIL_HPP_
#define UTIL_HPP_

#include <SFML/Config.hpp>

namespace sf {
    class Color;

    Color operator*(const Color &color, float f);
#if SFML_VERSION_MAJOR == 2 && SFML_VERSION < 2
    Color operator-(const Color& left, const Color& right);
#endif

}  // namespace sf

#endif  // UTIL_HPP_
<|endoftext|>


<commit_before>/*************************************************************************
*
*  $RCSfile: StorageBridgeFactory.hxx,v $
*
*  $Revision: 1.6 $
*
*  last change: $Author: dfoster $ $Date: 2002-10-23 14:11:29 $
*
*  The Contents of this file are made available subject to the terms of
*  either of the following licenses
*
*         - GNU Lesser General Public License Version 2.1
*         - Sun Industry Standards Source License Version 1.1
*
*  Sun Microsystems Inc., October, 2000
*
*  GNU Lesser General Public License Version 2.1
*  =============================================
*  Copyright 2000 by Sun Microsystems, Inc.
*  901 San Antonio Road, Palo Alto, CA 94303, USA
*
*  This library is free software; you can redistribute it and/or
*  modify it under the terms of the GNU Lesser General Public
*  License version 2.1, as published by the Free Software Foundation.
*
*  This library is distributed in the hope that it will be useful,
*  but WITHOUT ANY WARRANTY; without even the implied warranty of
*  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
*  Lesser General Public License for more details.
*
*  You should have received a copy of the GNU Lesser General Public
*  License along with this library; if not, write to the Free Software
*  Foundation, Inc., 59 Temple Place, Suite 330, Boston,
*  MA  02111-1307  USA
*
*
*  Sun Industry Standards Source License Version 1.1
*  =================================================
*  The contents of this file are subject to the Sun Industry Standards
*  Source License Version 1.1 (the "License"); You may not use this file
*  except in compliance with the License. You may obtain a copy of the
*  License at http://www.openoffice.org/license.html.
*
*  Software provided under this License is provided on an "AS IS" basis,
*  WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
*  WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
*  MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
*  See the License for the specific provisions governing your rights and
*  obligations concerning the Software.
*
*  The Initial Developer of the Original Code is: Sun Microsystems, Inc.
*
*  Copyright: 2000 by Sun Microsystems, Inc.
*
*  All Rights Reserved.
*
*  Contributor(s): _______________________________________
*
*
************************************************************************/

#ifndef _FRAMEWORK_SCRIPT_STORAGEBRIDGEFACTORY_HXX_
#define _FRAMEWORK_SCRIPT_STORAGEBRIDGEFACTORY_HXX_

#include <rtl/ustring>

#include <com/sun/star/uno/XComponentContext.hpp>
#include <com/sun/star/uno/Reference.hxx>

#include <drafts/com/sun/star/script/framework/storage/XScriptInfoAccess.hpp>

namespace scripting_runtimemgr
{
// for simplification
#define css ::com::sun::star
#define dcsssf ::drafts::com::sun::star::script::framework

class StorageBridgeFactory
{

public:
    explicit StorageBridgeFactory(
        const css::uno::Reference < css::uno::XComponentContext > & xContext );
    css::uno::Reference < dcsssf::storage::XScriptInfoAccess >
        getStorageInstance( sal_Int32 sid );
private:
    StorageBridgeFactory(); // No definition for default ctor
    css::uno::Reference< css::uno::XComponentContext >  m_xContext;
};
} // scripting_runtimemgr
#endif //_FRAMEWORK_SCRIPT_NAMERESOLVER_HXX_
<commit_msg>INTEGRATION: CWS ooo19126 (1.6.90); FILE MERGED 2005/09/05 12:05:26 rt 1.6.90.1: #i54170# Change license header: remove SISSL<commit_after>/*************************************************************************
*
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: StorageBridgeFactory.hxx,v $
 *
 *  $Revision: 1.7 $
 *
 *  last change: $Author: rt $ $Date: 2005-09-09 02:34:55 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    This library is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *    Lesser General Public License for more details.
 *
 *    You should have received a copy of the GNU Lesser General Public
 *    License along with this library; if not, write to the Free Software
 *    Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
************************************************************************/

#ifndef _FRAMEWORK_SCRIPT_STORAGEBRIDGEFACTORY_HXX_
#define _FRAMEWORK_SCRIPT_STORAGEBRIDGEFACTORY_HXX_

#include <rtl/ustring>

#include <com/sun/star/uno/XComponentContext.hpp>
#include <com/sun/star/uno/Reference.hxx>

#include <drafts/com/sun/star/script/framework/storage/XScriptInfoAccess.hpp>

namespace scripting_runtimemgr
{
// for simplification
#define css ::com::sun::star
#define dcsssf ::drafts::com::sun::star::script::framework

class StorageBridgeFactory
{

public:
    explicit StorageBridgeFactory(
        const css::uno::Reference < css::uno::XComponentContext > & xContext );
    css::uno::Reference < dcsssf::storage::XScriptInfoAccess >
        getStorageInstance( sal_Int32 sid );
private:
    StorageBridgeFactory(); // No definition for default ctor
    css::uno::Reference< css::uno::XComponentContext >  m_xContext;
};
} // scripting_runtimemgr
#endif //_FRAMEWORK_SCRIPT_NAMERESOLVER_HXX_
<|endoftext|>


<commit_before>/*
 * Copyright (c) 2007-2008 The Regents of The University of Michigan
 * 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
 */

#ifndef __BASE_BITUNION_HH__
#define __BASE_BITUNION_HH__

#include "base/bitfield.hh"
#include "base/types.hh"

//      The following implements the BitUnion system of defining bitfields
//on top of an underlying class. This is done through the pervasive use of
//both named and unnamed unions which all contain the same actual storage.
//Since they're unioned with each other, all of these storage locations
//overlap. This allows all of the bitfields to manipulate the same data
//without having to have access to each other. More details are provided with
//the individual components.

//This namespace is for classes which implement the backend of the BitUnion
//stuff. Don't use any of these directly, except for the Bitfield classes in
//the *BitfieldTypes class(es).
namespace BitfieldBackend
{
    //A base class for all bitfields. It instantiates the actual storage,
    //and provides getBits and setBits functions for manipulating it. The
    //Data template parameter is type of the underlying storage.
    template<class Data>
    class BitfieldBase
    {
      protected:
        Data __data;

        //This function returns a range of bits from the underlying storage.
        //It relies on the "bits" function above. It's the user's
        //responsibility to make sure that there is a properly overloaded
        //version of this function for whatever type they want to overlay.
        inline uint64_t
        getBits(int first, int last) const
        {
            return bits(__data, first, last);
        }

        //Similar to the above, but for settings bits with replaceBits.
        inline void
        setBits(int first, int last, uint64_t val)
        {
            replaceBits(__data, first, last, val);
        }
    };

    //This class contains all the "regular" bitfield classes. It is inherited
    //by all BitUnions which give them access to those types.
    template<class Type>
    class RegularBitfieldTypes
    {
      protected:
        //This class implements ordinary bitfields, that is a span of bits
        //who's msb is "first", and who's lsb is "last".
        template<int first, int last=first>
        class Bitfield : public BitfieldBase<Type>
        {
          public:
            operator const uint64_t () const
            {
                return this->getBits(first, last);
            }

            uint64_t
            operator=(const uint64_t _data)
            {
                this->setBits(first, last, _data);
                return _data;
            }
        };

        //A class which specializes the above so that it can only be read
        //from. This is accomplished explicitly making sure the assignment
        //operator is blocked. The conversion operator is carried through
        //inheritance. This will unfortunately need to be copied into each
        //bitfield type due to limitations with how templates work
        template<int first, int last=first>
        class BitfieldRO : public Bitfield<first, last>
        {
          private:
            uint64_t
            operator=(const uint64_t _data);
        };

        //Similar to the above, but only allows writing.
        template<int first, int last=first>
        class BitfieldWO : public Bitfield<first, last>
        {
          private:
            operator const uint64_t () const;

          public:
            using Bitfield<first, last>::operator=;
        };
    };

    //This class contains all the "regular" bitfield classes. It is inherited
    //by all BitUnions which give them access to those types.
    template<class Type>
    class SignedBitfieldTypes
    {
      protected:
        //This class implements ordinary bitfields, that is a span of bits
        //who's msb is "first", and who's lsb is "last".
        template<int first, int last=first>
        class SignedBitfield : public BitfieldBase<Type>
        {
          public:
            operator const int64_t () const
            {
                return sext<first - last + 1>(this->getBits(first, last));
            }

            int64_t
            operator=(const int64_t _data)
            {
                this->setBits(first, last, _data);
                return _data;
            }
        };

        //A class which specializes the above so that it can only be read
        //from. This is accomplished explicitly making sure the assignment
        //operator is blocked. The conversion operator is carried through
        //inheritance. This will unfortunately need to be copied into each
        //bitfield type due to limitations with how templates work
        template<int first, int last=first>
        class SignedBitfieldRO : public SignedBitfield<first, last>
        {
          private:
            int64_t
            operator=(const int64_t _data);
        };

        //Similar to the above, but only allows writing.
        template<int first, int last=first>
        class SignedBitfieldWO : public SignedBitfield<first, last>
        {
          private:
            operator const int64_t () const;

          public:
            int64_t operator=(const int64_t _data)
            {
                *((SignedBitfield<first, last> *)this) = _data;
                return _data;
            }
        };
    };

    template<class Type>
    class BitfieldTypes : public RegularBitfieldTypes<Type>,
                          public SignedBitfieldTypes<Type>
    {};

    //When a BitUnion is set up, an underlying class is created which holds
    //the actual union. This class then inherits from it, and provids the
    //implementations for various operators. Setting things up this way
    //prevents having to redefine these functions in every different BitUnion
    //type. More operators could be implemented in the future, as the need
    //arises.
    template <class Type, class Base>
    class BitUnionOperators : public Base
    {
      public:
        BitUnionOperators(Type const & _data)
        {
            Base::__data = _data;
        }

        BitUnionOperators() {}

        operator const Type () const
        {
            return Base::__data;
        }

        Type
        operator=(Type const & _data)
        {
            Base::__data = _data;
            return _data;
        }

        bool
        operator<(Base const & base) const
        {
            return Base::__data < base.__data;
        }

        bool
        operator==(Base const & base) const
        {
            return Base::__data == base.__data;
        }
    };
}

//This macro is a backend for other macros that specialize it slightly.
//First, it creates/extends a namespace "BitfieldUnderlyingClasses" and
//sticks the class which has the actual union in it, which
//BitfieldOperators above inherits from. Putting these classes in a special
//namespace ensures that there will be no collisions with other names as long
//as the BitUnion names themselves are all distinct and nothing else uses
//the BitfieldUnderlyingClasses namespace, which is unlikely. The class itself
//creates a typedef of the "type" parameter called __DataType. This allows
//the type to propagate outside of the macro itself in a controlled way.
//Finally, the base storage is defined which BitfieldOperators will refer to
//in the operators it defines. This macro is intended to be followed by
//bitfield definitions which will end up inside it's union. As explained
//above, these is overlayed the __data member in its entirety by each of the
//bitfields which are defined in the union, creating shared storage with no
//overhead.
#define __BitUnion(type, name) \
    class BitfieldUnderlyingClasses##name : \
        public BitfieldBackend::BitfieldTypes<type> \
    { \
      public: \
        typedef type __DataType; \
        union { \
            type __data;\

//This closes off the class and union started by the above macro. It is
//followed by a typedef which makes "name" refer to a BitfieldOperator
//class inheriting from the class and union just defined, which completes
//building up the type for the user.
#define EndBitUnion(name) \
        }; \
    }; \
    typedef BitfieldBackend::BitUnionOperators< \
        BitfieldUnderlyingClasses##name::__DataType, \
        BitfieldUnderlyingClasses##name> name;

//This sets up a bitfield which has other bitfields nested inside of it. The
//__data member functions like the "underlying storage" of the top level
//BitUnion. Like everything else, it overlays with the top level storage, so
//making it a regular bitfield type makes the entire thing function as a
//regular bitfield when referred to by itself.
#define __SubBitUnion(fieldType, first, last, name) \
    class : public BitfieldBackend::BitfieldTypes<__DataType> \
    { \
      public: \
        union { \
            fieldType<first, last> __data;

//This closes off the union created above and gives it a name. Unlike the top
//level BitUnion, we're interested in creating an object instead of a type.
//The operators are defined in the macro itself instead of a class for
//technical reasons. If someone determines a way to move them to one, please
//do so.
#define EndSubBitUnion(name) \
        }; \
        inline operator const __DataType () const \
        { return __data; } \
        \
        inline const __DataType operator = (const __DataType & _data) \
        { return __data = _data;} \
    } name;

//Regular bitfields
//These define macros for read/write regular bitfield based subbitfields.
#define SubBitUnion(name, first, last) \
    __SubBitUnion(Bitfield, first, last, name)

//Regular bitfields
//These define macros for read/write regular bitfield based subbitfields.
#define SignedSubBitUnion(name, first, last) \
    __SubBitUnion(SignedBitfield, first, last, name)

//Use this to define an arbitrary type overlayed with bitfields.
#define BitUnion(type, name) __BitUnion(type, name)

//Use this to define conveniently sized values overlayed with bitfields.
#define BitUnion64(name) __BitUnion(uint64_t, name)
#define BitUnion32(name) __BitUnion(uint32_t, name)
#define BitUnion16(name) __BitUnion(uint16_t, name)
#define BitUnion8(name) __BitUnion(uint8_t, name)

#endif // __BASE_BITUNION_HH__
<commit_msg>base: Add a static assert to check bit union ranges<commit_after>/*
 * Copyright (c) 2007-2008 The Regents of The University of Michigan
 * 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
 */

#ifndef __BASE_BITUNION_HH__
#define __BASE_BITUNION_HH__

#include "base/bitfield.hh"
#include "base/types.hh"

//      The following implements the BitUnion system of defining bitfields
//on top of an underlying class. This is done through the pervasive use of
//both named and unnamed unions which all contain the same actual storage.
//Since they're unioned with each other, all of these storage locations
//overlap. This allows all of the bitfields to manipulate the same data
//without having to have access to each other. More details are provided with
//the individual components.

//This namespace is for classes which implement the backend of the BitUnion
//stuff. Don't use any of these directly, except for the Bitfield classes in
//the *BitfieldTypes class(es).
namespace BitfieldBackend
{
    //A base class for all bitfields. It instantiates the actual storage,
    //and provides getBits and setBits functions for manipulating it. The
    //Data template parameter is type of the underlying storage.
    template<class Data>
    class BitfieldBase
    {
      protected:
        Data __data;

        //This function returns a range of bits from the underlying storage.
        //It relies on the "bits" function above. It's the user's
        //responsibility to make sure that there is a properly overloaded
        //version of this function for whatever type they want to overlay.
        inline uint64_t
        getBits(int first, int last) const
        {
            return bits(__data, first, last);
        }

        //Similar to the above, but for settings bits with replaceBits.
        inline void
        setBits(int first, int last, uint64_t val)
        {
            replaceBits(__data, first, last, val);
        }
    };

    //This class contains all the "regular" bitfield classes. It is inherited
    //by all BitUnions which give them access to those types.
    template<class Type>
    class RegularBitfieldTypes
    {
      protected:
        //This class implements ordinary bitfields, that is a span of bits
        //who's msb is "first", and who's lsb is "last".
        template<int first, int last=first>
        class Bitfield : public BitfieldBase<Type>
        {
            static_assert(first >= last,
                          "Bitfield ranges must be specified as <msb, lsb>");

          public:
            operator const uint64_t () const
            {
                return this->getBits(first, last);
            }

            uint64_t
            operator=(const uint64_t _data)
            {
                this->setBits(first, last, _data);
                return _data;
            }
        };

        //A class which specializes the above so that it can only be read
        //from. This is accomplished explicitly making sure the assignment
        //operator is blocked. The conversion operator is carried through
        //inheritance. This will unfortunately need to be copied into each
        //bitfield type due to limitations with how templates work
        template<int first, int last=first>
        class BitfieldRO : public Bitfield<first, last>
        {
          private:
            uint64_t
            operator=(const uint64_t _data);
        };

        //Similar to the above, but only allows writing.
        template<int first, int last=first>
        class BitfieldWO : public Bitfield<first, last>
        {
          private:
            operator const uint64_t () const;

          public:
            using Bitfield<first, last>::operator=;
        };
    };

    //This class contains all the "regular" bitfield classes. It is inherited
    //by all BitUnions which give them access to those types.
    template<class Type>
    class SignedBitfieldTypes
    {
      protected:
        //This class implements ordinary bitfields, that is a span of bits
        //who's msb is "first", and who's lsb is "last".
        template<int first, int last=first>
        class SignedBitfield : public BitfieldBase<Type>
        {
          public:
            operator const int64_t () const
            {
                return sext<first - last + 1>(this->getBits(first, last));
            }

            int64_t
            operator=(const int64_t _data)
            {
                this->setBits(first, last, _data);
                return _data;
            }
        };

        //A class which specializes the above so that it can only be read
        //from. This is accomplished explicitly making sure the assignment
        //operator is blocked. The conversion operator is carried through
        //inheritance. This will unfortunately need to be copied into each
        //bitfield type due to limitations with how templates work
        template<int first, int last=first>
        class SignedBitfieldRO : public SignedBitfield<first, last>
        {
          private:
            int64_t
            operator=(const int64_t _data);
        };

        //Similar to the above, but only allows writing.
        template<int first, int last=first>
        class SignedBitfieldWO : public SignedBitfield<first, last>
        {
          private:
            operator const int64_t () const;

          public:
            int64_t operator=(const int64_t _data)
            {
                *((SignedBitfield<first, last> *)this) = _data;
                return _data;
            }
        };
    };

    template<class Type>
    class BitfieldTypes : public RegularBitfieldTypes<Type>,
                          public SignedBitfieldTypes<Type>
    {};

    //When a BitUnion is set up, an underlying class is created which holds
    //the actual union. This class then inherits from it, and provids the
    //implementations for various operators. Setting things up this way
    //prevents having to redefine these functions in every different BitUnion
    //type. More operators could be implemented in the future, as the need
    //arises.
    template <class Type, class Base>
    class BitUnionOperators : public Base
    {
      public:
        BitUnionOperators(Type const & _data)
        {
            Base::__data = _data;
        }

        BitUnionOperators() {}

        operator const Type () const
        {
            return Base::__data;
        }

        Type
        operator=(Type const & _data)
        {
            Base::__data = _data;
            return _data;
        }

        bool
        operator<(Base const & base) const
        {
            return Base::__data < base.__data;
        }

        bool
        operator==(Base const & base) const
        {
            return Base::__data == base.__data;
        }
    };
}

//This macro is a backend for other macros that specialize it slightly.
//First, it creates/extends a namespace "BitfieldUnderlyingClasses" and
//sticks the class which has the actual union in it, which
//BitfieldOperators above inherits from. Putting these classes in a special
//namespace ensures that there will be no collisions with other names as long
//as the BitUnion names themselves are all distinct and nothing else uses
//the BitfieldUnderlyingClasses namespace, which is unlikely. The class itself
//creates a typedef of the "type" parameter called __DataType. This allows
//the type to propagate outside of the macro itself in a controlled way.
//Finally, the base storage is defined which BitfieldOperators will refer to
//in the operators it defines. This macro is intended to be followed by
//bitfield definitions which will end up inside it's union. As explained
//above, these is overlayed the __data member in its entirety by each of the
//bitfields which are defined in the union, creating shared storage with no
//overhead.
#define __BitUnion(type, name) \
    class BitfieldUnderlyingClasses##name : \
        public BitfieldBackend::BitfieldTypes<type> \
    { \
      public: \
        typedef type __DataType; \
        union { \
            type __data;\

//This closes off the class and union started by the above macro. It is
//followed by a typedef which makes "name" refer to a BitfieldOperator
//class inheriting from the class and union just defined, which completes
//building up the type for the user.
#define EndBitUnion(name) \
        }; \
    }; \
    typedef BitfieldBackend::BitUnionOperators< \
        BitfieldUnderlyingClasses##name::__DataType, \
        BitfieldUnderlyingClasses##name> name;

//This sets up a bitfield which has other bitfields nested inside of it. The
//__data member functions like the "underlying storage" of the top level
//BitUnion. Like everything else, it overlays with the top level storage, so
//making it a regular bitfield type makes the entire thing function as a
//regular bitfield when referred to by itself.
#define __SubBitUnion(fieldType, first, last, name) \
    class : public BitfieldBackend::BitfieldTypes<__DataType> \
    { \
      public: \
        union { \
            fieldType<first, last> __data;

//This closes off the union created above and gives it a name. Unlike the top
//level BitUnion, we're interested in creating an object instead of a type.
//The operators are defined in the macro itself instead of a class for
//technical reasons. If someone determines a way to move them to one, please
//do so.
#define EndSubBitUnion(name) \
        }; \
        inline operator const __DataType () const \
        { return __data; } \
        \
        inline const __DataType operator = (const __DataType & _data) \
        { return __data = _data;} \
    } name;

//Regular bitfields
//These define macros for read/write regular bitfield based subbitfields.
#define SubBitUnion(name, first, last) \
    __SubBitUnion(Bitfield, first, last, name)

//Regular bitfields
//These define macros for read/write regular bitfield based subbitfields.
#define SignedSubBitUnion(name, first, last) \
    __SubBitUnion(SignedBitfield, first, last, name)

//Use this to define an arbitrary type overlayed with bitfields.
#define BitUnion(type, name) __BitUnion(type, name)

//Use this to define conveniently sized values overlayed with bitfields.
#define BitUnion64(name) __BitUnion(uint64_t, name)
#define BitUnion32(name) __BitUnion(uint32_t, name)
#define BitUnion16(name) __BitUnion(uint16_t, name)
#define BitUnion8(name) __BitUnion(uint8_t, name)

#endif // __BASE_BITUNION_HH__
<|endoftext|>