<commit_before>// Copyright (c) 2018 Chris Ohk, Youngjoong Kim, SeungHyun Jeon

// We are making my contributions/submissions to this project solely in our
// personal capacity and are not conveying any rights to any intellectual
// property of any third parties.

#include <Rosetta/Cards/Cards.hpp>
#include <RosettaTorch/GameToVec.hpp>

namespace RosettaTorch
{
GameToVec::GameToVec(size_t seed) : m_seed(seed)
{
    // Reproducibility
    torch::manual_seed(static_cast<uint64_t>(m_seed));

    // Making embedding tables for the task
    auto make_table = [&](torch::nn::Embedding embedding, size_t idx_size, size_t vec_size) {
        embedding = torch::nn::Embedding(idx_size, vec_size);
        embedding->weight = torch::randn(
            { static_cast<int>(idx_size), static_cast<int>(vec_size) },
            torch::kFloat32
        );
        embedding->weight.set_requires_grad(false);
    };

    // Generates an embedding table for the Aura task
    make_table(AuraEmbeddingTable, AuraIndexSize, AuraVectorSize);

    // Generates an embedding table for the Enchant task
    make_table(EnchantEmbeddingTable, EnchantIndexSize, EnchantVectorSize);

    // Generates an embedding table for the Deathrattle task
    make_table(DeathrattleEmbeddingTable, DeathrattleIndexSize, DeathrattleVectorSize);

    // Generates an embedding table for the Power task
    make_table(PowerEmbeddingTable, PowerIndexSize, PowerVectorSize);
}

torch::Tensor GameToVec::CardToTensor(Entity* entity)
{
    torch::Tensor CardVector = torch::empty(CardVectorSize, torch::kFloat32);

    Character* character = dynamic_cast<Character*>(entity);

    auto cost = static_cast<float>(character->GetCost());
    auto attack = static_cast<float>(character->GetAttack());
    auto health = static_cast<float>(character->GetHealth());

    // Write cost of the card
    CardVector[0] = cost / 10;

    // Write attack of the card
    CardVector[1] = (attack >= CLIP_NORM) ? 1. : attack / CLIP_NORM;

    // Write health of the card
    CardVector[2] = (health >= CLIP_NORM) ? 1. : health / CLIP_NORM;

    return CardVector;
}

torch::Tensor GameToVec::GenerateTensor(const Game& game)
{
    // vector shape : [1 + 1 + 1 + n * 7 + n * 7 + n * 10 = 3 + n * 24]
    // # 1      : number of opponent player's cards on hand.
    // # 1      : number of opponent player's left cards at deck.
    // # 1      : number of current player's left cards at deck.
    // # n * 7  : opponent player's representation vectors of card at the deck.
    //            each card has a dimensionality of n.
    // # n * 7  : current player's representation vectors of card at the deck.
    //            each card has a dimensionality of n.
    // # n * 10 : current player's representation vectors of card in the hand.
    //            each card has a dimensionality of n.

    // each card is represented as a vector which has n dimensionality.
    // it includes, cost, attack, health, ability.
    // vector shape : [1 + 1 + 1 + m = n]
    // # 1 : cost
    // # 1 : attack
    // # 1 : health
    // # m : tasks

    // each card's abilities are represented as a vector which has m
    // dimensionality. it includes, ... vector shape : [m]
    torch::Tensor tensor = torch::empty(GameVectorSize, torch::kFloat32);

    Player& curPlayer = game.GetCurrentPlayer();
    Player& oppPlayer = game.GetOpponentPlayer();

    // Write number of opponent player's cards, normalized, on the hand.
    tensor[0] =
        static_cast<float>(oppPlayer.GetHand().GetNumOfCards()) / HAND_SIZE;

    // Write number of opponent player's cards, normalized, on the deck.
    tensor[1] =
        static_cast<float>(oppPlayer.GetDeck().GetNumOfCards()) / MAX_DECK_SIZE;

    // Write number of current player's cards, normalized, on the deck.
    tensor[2] =
        static_cast<float>(curPlayer.GetDeck().GetNumOfCards()) / MAX_DECK_SIZE;

    auto field_write = [&](size_t start, Player& player) {
        auto field = player.GetField();
        size_t NumOfMinions = field.GetNumOfMinions();

        size_t i = 0;
        for (; i < NumOfMinions; ++i)
        {
           tensor[start + i] = CardToTensor(field.GetMinion(i));
        }

        for (; i < FIELD_SIZE; ++i)
        {
            tensor[start + i] = torch::zeros(CardVectorSize);
        }
    };

    auto hand_write = [&](size_t start, Player& player) {
        auto hand = player.GetHand();
        size_t NumOfCards = hand.GetNumOfCards();

        size_t i = 0;
        for (; i < NumOfCards; ++i)
        {
            tensor[start + i] = CardToTensor(hand.GetCard(i));
        }

        for (; i < HAND_SIZE; ++i)
        {
            tensor[start + i] = torch::zeros(CardVectorSize);
        }
    };

    // Write opponent player's field cards
    field_write(PlayerMetaSize, oppPlayer);

    // Write current player's field cards
    field_write(PlayerMetaSize + 1 * FIELD_SIZE, curPlayer);

    // Write current player's hand cards
    hand_write(PlayerMetaSize + 2 * FIELD_SIZE, curPlayer);

    return tensor;
}
}  // namespace RosettaTorch<commit_msg>refactor: Change a fixed value to the meaningful variable<commit_after>// Copyright (c) 2018 Chris Ohk, Youngjoong Kim, SeungHyun Jeon

// We are making my contributions/submissions to this project solely in our
// personal capacity and are not conveying any rights to any intellectual
// property of any third parties.

#include <Rosetta/Cards/Cards.hpp>
#include <RosettaTorch/GameToVec.hpp>

namespace RosettaTorch
{
GameToVec::GameToVec(size_t seed) : m_seed(seed)
{
    // Reproducibility
    torch::manual_seed(static_cast<uint64_t>(m_seed));

    // Making embedding tables for the task
    auto make_table = [&](torch::nn::Embedding embedding, size_t idx_size, size_t vec_size) {
        embedding = torch::nn::Embedding(idx_size, vec_size);
        embedding->weight = torch::randn(
            { static_cast<int>(idx_size), static_cast<int>(vec_size) },
            torch::kFloat32
        );
        embedding->weight.set_requires_grad(false);
    };

    // Generates an embedding table for the Aura task
    make_table(AuraEmbeddingTable, AuraIndexSize, AuraVectorSize);

    // Generates an embedding table for the Enchant task
    make_table(EnchantEmbeddingTable, EnchantIndexSize, EnchantVectorSize);

    // Generates an embedding table for the Deathrattle task
    make_table(DeathrattleEmbeddingTable, DeathrattleIndexSize, DeathrattleVectorSize);

    // Generates an embedding table for the Power task
    make_table(PowerEmbeddingTable, PowerIndexSize, PowerVectorSize);
}

torch::Tensor GameToVec::CardToTensor(Entity* entity)
{
    torch::Tensor CardVector = torch::empty(CardVectorSize, torch::kFloat32);

    Character* character = dynamic_cast<Character*>(entity);

    auto cost = static_cast<float>(character->GetCost());
    auto attack = static_cast<float>(character->GetAttack());
    auto health = static_cast<float>(character->GetHealth());

    // Write cost of the card
    CardVector[0] = cost / MANA_UPPER_LIMIT;

    // Write attack of the card
    CardVector[1] = (attack >= CLIP_NORM) ? 1. : attack / CLIP_NORM;

    // Write health of the card
    CardVector[2] = (health >= CLIP_NORM) ? 1. : health / CLIP_NORM;

    return CardVector;
}

torch::Tensor GameToVec::GenerateTensor(const Game& game)
{
    // vector shape : [1 + 1 + 1 + n * 7 + n * 7 + n * 10 = 3 + n * 24]
    // # 1      : number of opponent player's cards on hand.
    // # 1      : number of opponent player's left cards at deck.
    // # 1      : number of current player's left cards at deck.
    // # n * 7  : opponent player's representation vectors of card at the deck.
    //            each card has a dimensionality of n.
    // # n * 7  : current player's representation vectors of card at the deck.
    //            each card has a dimensionality of n.
    // # n * 10 : current player's representation vectors of card in the hand.
    //            each card has a dimensionality of n.

    // each card is represented as a vector which has n dimensionality.
    // it includes, cost, attack, health, ability.
    // vector shape : [1 + 1 + 1 + m = n]
    // # 1 : cost
    // # 1 : attack
    // # 1 : health
    // # m : tasks

    // each card's abilities are represented as a vector which has m
    // dimensionality. it includes, ... vector shape : [m]
    torch::Tensor tensor = torch::empty(GameVectorSize, torch::kFloat32);

    Player& curPlayer = game.GetCurrentPlayer();
    Player& oppPlayer = game.GetOpponentPlayer();

    // Write number of opponent player's cards, normalized, on the hand.
    tensor[0] =
        static_cast<float>(oppPlayer.GetHand().GetNumOfCards()) / HAND_SIZE;

    // Write number of opponent player's cards, normalized, on the deck.
    tensor[1] =
        static_cast<float>(oppPlayer.GetDeck().GetNumOfCards()) / MAX_DECK_SIZE;

    // Write number of current player's cards, normalized, on the deck.
    tensor[2] =
        static_cast<float>(curPlayer.GetDeck().GetNumOfCards()) / MAX_DECK_SIZE;

    auto field_write = [&](size_t start, Player& player) {
        auto field = player.GetField();
        size_t NumOfMinions = field.GetNumOfMinions();

        size_t i = 0;
        for (; i < NumOfMinions; ++i)
        {
           tensor[start + i] = CardToTensor(field.GetMinion(i));
        }

        for (; i < FIELD_SIZE; ++i)
        {
            tensor[start + i] = torch::zeros(CardVectorSize);
        }
    };

    auto hand_write = [&](size_t start, Player& player) {
        auto hand = player.GetHand();
        size_t NumOfCards = hand.GetNumOfCards();

        size_t i = 0;
        for (; i < NumOfCards; ++i)
        {
            tensor[start + i] = CardToTensor(hand.GetCard(i));
        }

        for (; i < HAND_SIZE; ++i)
        {
            tensor[start + i] = torch::zeros(CardVectorSize);
        }
    };

    // Write opponent player's field cards
    field_write(PlayerMetaSize, oppPlayer);

    // Write current player's field cards
    field_write(PlayerMetaSize + 1 * FIELD_SIZE, curPlayer);

    // Write current player's hand cards
    hand_write(PlayerMetaSize + 2 * FIELD_SIZE, curPlayer);

    return tensor;
}
}  // namespace RosettaTorch<|endoftext|>


<commit_before>/******************************************************************************
 * Copyright (C) 2018 Kitsune Ral <kitsune-ral@users.sf.net>
 *
 * 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 "util.h"

#include <QtCore/QCryptographicHash>
#include <QtCore/QDataStream>
#include <QtCore/QDir>
#include <QtCore/QRegularExpression>
#include <QtCore/QStandardPaths>
#include <QtCore/QStringBuilder>
#include <QtCore/QtEndian>

static const auto RegExpOptions =
    QRegularExpression::CaseInsensitiveOption
    | QRegularExpression::OptimizeOnFirstUsageOption
    | QRegularExpression::UseUnicodePropertiesOption;

// Converts all that looks like a URL into HTML links
void Quotient::linkifyUrls(QString& htmlEscapedText)
{
    // Note: outer parentheses are a part of C++ raw string delimiters, not of
    // the regex (see http://en.cppreference.com/w/cpp/language/string_literal).
    // Note2: the next-outer parentheses are \N in the replacement.

    // generic url:
    // regexp is originally taken from Konsole (https://github.com/KDE/konsole)
    // protocolname:// or www. followed by anything other than whitespaces,
    // <, >, ' or ", and ends before whitespaces, <, >, ', ", ], !, ), :,
    // comma or dot
    static const QRegularExpression FullUrlRegExp(
        QStringLiteral(
            R"(\b((www\.(?!\.)(?!(\w|\.|-)+@)|(https?|ftp|magnet|matrix):(//)?)(&(?![lg]t;)|[^&\s<>'"])+(&(?![lg]t;)|[^&!,.\s<>'"\]):])))"),
        RegExpOptions);
    // email address:
    // [word chars, dots or dashes]@[word chars, dots or dashes].[word chars]
    static const QRegularExpression EmailAddressRegExp(
        QStringLiteral(R"(\b(mailto:)?((\w|\.|-)+@(\w|\.|-)+\.\w+\b))"),
        RegExpOptions);
    // An interim liberal implementation of
    // https://matrix.org/docs/spec/appendices.html#identifier-grammar
    static const QRegularExpression MxIdRegExp(
        QStringLiteral(
            R"((^|[^<>/])([!#@][-a-z0-9_=#/.]{1,252}:(?:\w|\.|-)+\.\w+(?::\d{1,5})?))"),
        RegExpOptions);

    // NOTE: htmlEscapedText is already HTML-escaped! No literal <,>,&,"

    htmlEscapedText.replace(EmailAddressRegExp,
                            QStringLiteral(R"(\1\2)"));
    htmlEscapedText.replace(FullUrlRegExp,
                            QStringLiteral(R"(\1)"));
    htmlEscapedText.replace(
        MxIdRegExp,
        QStringLiteral(R"(\1\2)"));
}

QString Quotient::sanitized(const QString& plainText)
{
    auto text = plainText;
    text.remove(QChar(0x202e)); // RLO
    text.remove(QChar(0x202d)); // LRO
    text.remove(QChar(0xfffc)); // Object replacement character
    return text;
}

QString Quotient::prettyPrint(const QString& plainText)
{
    auto pt = plainText.toHtmlEscaped();
    linkifyUrls(pt);
    pt.replace('\n', QStringLiteral("
"));
    return QStringLiteral("") + pt
           + QStringLiteral("");
}

QString Quotient::cacheLocation(const QString& dirName)
{
    const QString cachePath =
        QStandardPaths::writableLocation(QStandardPaths::CacheLocation) % '/'
        % dirName % '/';
    QDir dir;
    if (!dir.exists(cachePath))
        dir.mkpath(cachePath);
    return cachePath;
}

qreal Quotient::stringToHueF(const QString& s)
{
    Q_ASSERT(!s.isEmpty());
    QByteArray hash = QCryptographicHash::hash(s.toUtf8(),
                                               QCryptographicHash::Sha1);
    QDataStream dataStream(hash.left(2));
    dataStream.setByteOrder(QDataStream::LittleEndian);
    quint16 hashValue;
    dataStream >> hashValue;
    const auto hueF = qreal(hashValue) / std::numeric_limits<quint16>::max();
    Q_ASSERT((0 <= hueF) && (hueF <= 1));
    return hueF;
}

static const auto ServerPartRegEx = QStringLiteral(
    "(\\[[^]]+\\]|[^:@]+)" // Either IPv6 address or hostname/IPv4 address
    "(?::(\\d{1,5}))?" // Optional port
);

QString Quotient::serverPart(const QString& mxId)
{
    static QString re = "^[@!#$+].+?:(" // Localpart and colon
                        % ServerPartRegEx % ")$";
    static QRegularExpression parser(
        re,
        QRegularExpression::UseUnicodePropertiesOption); // Because Asian
                                                         // digits
    return parser.match(mxId).captured(1);
}

// Tests for function_traits<>

#ifdef Q_CC_CLANG
#    pragma clang diagnostic push
#    pragma ide diagnostic ignored "OCSimplifyInspection"
#endif
using namespace Quotient;

int f();
static_assert(std::is_same<fn_return_t<decltype(f)>, int>::value,
              "Test fn_return_t<>");

void f1(int, QString);
static_assert(std::is_same<fn_arg_t<decltype(f1), 1>, QString>::value,
              "Test fn_arg_t<>");

struct Fo {
    int operator()();
};
static_assert(std::is_same<fn_return_t<Fo>, int>::value,
              "Test return type of function object");

struct Fo1 {
    void operator()(int);
};
static_assert(std::is_same<fn_arg_t<Fo1>, int>(),
              "Test fn_arg_t defaulting to first argument");

#if (!defined(_MSC_VER) || _MSC_VER >= 1910)
static auto l = [] { return 1; };
static_assert(std::is_same<fn_return_t<decltype(l)>, int>::value,
              "Test fn_return_t<> with lambda");
#endif

template <typename T>
QString ft(T&&)
{
    return {};
}
static_assert(std::is_same<fn_arg_t<decltype(ft<QString>)>, QString&&>(),
              "Test function templates");

#ifdef Q_CC_CLANG
#    pragma clang diagnostic pop
#endif
<commit_msg>util.cpp: drop OptimizeOnFirstUsage option on newer Qt<commit_after>/******************************************************************************
 * Copyright (C) 2018 Kitsune Ral <kitsune-ral@users.sf.net>
 *
 * 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 "util.h"

#include <QtCore/QCryptographicHash>
#include <QtCore/QDataStream>
#include <QtCore/QDir>
#include <QtCore/QRegularExpression>
#include <QtCore/QStandardPaths>
#include <QtCore/QStringBuilder>
#include <QtCore/QtEndian>

static const auto RegExpOptions =
    QRegularExpression::CaseInsensitiveOption
#if QT_VERSION < QT_VERSION_CHECK(5, 12, 0)
    | QRegularExpression::OptimizeOnFirstUsageOption // Default since 5.12
#endif
    | QRegularExpression::UseUnicodePropertiesOption;

// Converts all that looks like a URL into HTML links
void Quotient::linkifyUrls(QString& htmlEscapedText)
{
    // Note: outer parentheses are a part of C++ raw string delimiters, not of
    // the regex (see http://en.cppreference.com/w/cpp/language/string_literal).
    // Note2: the next-outer parentheses are \N in the replacement.

    // generic url:
    // regexp is originally taken from Konsole (https://github.com/KDE/konsole)
    // protocolname:// or www. followed by anything other than whitespaces,
    // <, >, ' or ", and ends before whitespaces, <, >, ', ", ], !, ), :,
    // comma or dot
    static const QRegularExpression FullUrlRegExp(
        QStringLiteral(
            R"(\b((www\.(?!\.)(?!(\w|\.|-)+@)|(https?|ftp|magnet|matrix):(//)?)(&(?![lg]t;)|[^&\s<>'"])+(&(?![lg]t;)|[^&!,.\s<>'"\]):])))"),
        RegExpOptions);
    // email address:
    // [word chars, dots or dashes]@[word chars, dots or dashes].[word chars]
    static const QRegularExpression EmailAddressRegExp(
        QStringLiteral(R"(\b(mailto:)?((\w|\.|-)+@(\w|\.|-)+\.\w+\b))"),
        RegExpOptions);
    // An interim liberal implementation of
    // https://matrix.org/docs/spec/appendices.html#identifier-grammar
    static const QRegularExpression MxIdRegExp(
        QStringLiteral(
            R"((^|[^<>/])([!#@][-a-z0-9_=#/.]{1,252}:(?:\w|\.|-)+\.\w+(?::\d{1,5})?))"),
        RegExpOptions);

    // NOTE: htmlEscapedText is already HTML-escaped! No literal <,>,&,"

    htmlEscapedText.replace(EmailAddressRegExp,
                            QStringLiteral(R"(\1\2)"));
    htmlEscapedText.replace(FullUrlRegExp,
                            QStringLiteral(R"(\1)"));
    htmlEscapedText.replace(
        MxIdRegExp,
        QStringLiteral(R"(\1\2)"));
}

QString Quotient::sanitized(const QString& plainText)
{
    auto text = plainText;
    text.remove(QChar(0x202e)); // RLO
    text.remove(QChar(0x202d)); // LRO
    text.remove(QChar(0xfffc)); // Object replacement character
    return text;
}

QString Quotient::prettyPrint(const QString& plainText)
{
    auto pt = plainText.toHtmlEscaped();
    linkifyUrls(pt);
    pt.replace('\n', QStringLiteral("
"));
    return QStringLiteral("") + pt
           + QStringLiteral("");
}

QString Quotient::cacheLocation(const QString& dirName)
{
    const QString cachePath =
        QStandardPaths::writableLocation(QStandardPaths::CacheLocation) % '/'
        % dirName % '/';
    QDir dir;
    if (!dir.exists(cachePath))
        dir.mkpath(cachePath);
    return cachePath;
}

qreal Quotient::stringToHueF(const QString& s)
{
    Q_ASSERT(!s.isEmpty());
    QByteArray hash = QCryptographicHash::hash(s.toUtf8(),
                                               QCryptographicHash::Sha1);
    QDataStream dataStream(hash.left(2));
    dataStream.setByteOrder(QDataStream::LittleEndian);
    quint16 hashValue;
    dataStream >> hashValue;
    const auto hueF = qreal(hashValue) / std::numeric_limits<quint16>::max();
    Q_ASSERT((0 <= hueF) && (hueF <= 1));
    return hueF;
}

static const auto ServerPartRegEx = QStringLiteral(
    "(\\[[^]]+\\]|[^:@]+)" // Either IPv6 address or hostname/IPv4 address
    "(?::(\\d{1,5}))?" // Optional port
);

QString Quotient::serverPart(const QString& mxId)
{
    static QString re = "^[@!#$+].+?:(" // Localpart and colon
                        % ServerPartRegEx % ")$";
    static QRegularExpression parser(
        re,
        QRegularExpression::UseUnicodePropertiesOption); // Because Asian
                                                         // digits
    return parser.match(mxId).captured(1);
}

// Tests for function_traits<>

#ifdef Q_CC_CLANG
#    pragma clang diagnostic push
#    pragma ide diagnostic ignored "OCSimplifyInspection"
#endif
using namespace Quotient;

int f();
static_assert(std::is_same<fn_return_t<decltype(f)>, int>::value,
              "Test fn_return_t<>");

void f1(int, QString);
static_assert(std::is_same<fn_arg_t<decltype(f1), 1>, QString>::value,
              "Test fn_arg_t<>");

struct Fo {
    int operator()();
};
static_assert(std::is_same<fn_return_t<Fo>, int>::value,
              "Test return type of function object");

struct Fo1 {
    void operator()(int);
};
static_assert(std::is_same<fn_arg_t<Fo1>, int>(),
              "Test fn_arg_t defaulting to first argument");

#if (!defined(_MSC_VER) || _MSC_VER >= 1910)
static auto l = [] { return 1; };
static_assert(std::is_same<fn_return_t<decltype(l)>, int>::value,
              "Test fn_return_t<> with lambda");
#endif

template <typename T>
QString ft(T&&)
{
    return {};
}
static_assert(std::is_same<fn_arg_t<decltype(ft<QString>)>, QString&&>(),
              "Test function templates");

#ifdef Q_CC_CLANG
#    pragma clang diagnostic pop
#endif
<|endoftext|>


<commit_before>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: slidechangebase.hxx,v $
 *
 *  $Revision: 1.5 $
 *
 *  last change: $Author: obo $ $Date: 2006-01-19 18:00:25 $
 *
 *  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
 *
 ************************************************************************/

#if ! defined(INCLUDED_PRESENTATION_INTERNAL_TRANSITIONS_SLIDECHANGEBASE_HXX)
#define INCLUDED_PRESENTATION_INTERNAL_TRANSITIONS_SLIDECHANGEBASE_HXX

#include "unoview.hxx"
#include "slidechangeanimation.hxx"
#include "slide.hxx"
#include "soundplayer.hxx"
#include "rtl/ref.hxx"
#include "osl/mutex.hxx"
#include "cppuhelper/compbase1.hxx"
#include "comphelper/broadcasthelper.hxx"
#include "com/sun/star/util/XModifyListener.hpp"
#include "com/sun/star/presentation/XSlideShowView.hpp"
#include "boost/utility.hpp" // for boost::noncopyable
#include "boost/optional.hpp"
#include "boost/bind.hpp"

namespace presentation {
namespace internal {

typedef ::cppu::WeakComponentImplHelper1<
    ::com::sun::star::util::XModifyListener > UnoBaseT;

/** Base class for all slide change effects.

    This class provides the basic sprite and view handling
    functionality.  Derived classes should normally only need to
    implement the perform() method.
*/
class SlideChangeBase : private ::comphelper::OBaseMutex,
                        public SlideChangeAnimation,
                        public UnoBaseT,
                        private ::boost::noncopyable
{
public:
    // NumberAnimation
    virtual bool operator()( double x );
    virtual double getUnderlyingValue() const;

    // Animation
    virtual void start( const AnimatableShapeSharedPtr&,
                        const ShapeAttributeLayerSharedPtr& );
    virtual void end();

    // SlideChangeAnimation
    virtual void addView( UnoViewSharedPtr const & pView );
    virtual bool removeView( UnoViewSharedPtr const & pView );

protected:
    virtual ~SlideChangeBase();

    /** Create a new SlideChanger, for the given leaving and
        entering slides.
    */
    SlideChangeBase(
        ::boost::optional<SlideSharedPtr> const & leavingSlide,
        const SlideSharedPtr& pEnteringSlide,
        const SoundPlayerSharedPtr& pSoundPlayer,
        bool bCreateLeavingSprites = true, bool bCreateEnteringSprites = true );

    SlideBitmapSharedPtr getLeavingBitmap() const;
    SlideBitmapSharedPtr getEnteringBitmap() const;

    SlideBitmapSharedPtr createBitmap(
        ::boost::optional<SlideSharedPtr> const & rSlide_ ) const;

    /// Query the size of the bitmaps in device pixel
    ::basegfx::B2ISize getEnteringSizePixel(
        UnoViewSharedPtr const & pView ) const;
    /// Query the XDrawPage's size
    ::basegfx::B2DSize getEnteringSize() const;

    void renderBitmap( SlideBitmapSharedPtr const & pSlideBitmap,
                       ::cppcanvas::CanvasSharedPtr const & pCanvas );

    /** Loop over each View, and call func with that
     */
    template <typename FuncT>
    void for_each_view( FuncT const& func ) const {
        ::std::for_each( maViews.begin(), maViews.end(), func );
    }

    /** Loop over each View's canvas, and call func with that
     */
    template <typename FuncT>
    void for_each_canvas( FuncT const& func ) const {
        UnoViewVector::const_iterator const iEnd( maViews.end() );
        for ( UnoViewVector::const_iterator iPos( maViews.begin() );
              iPos != iEnd; ++iPos )
        {
            ::cppcanvas::CanvasSharedPtr const pCanvas( (*iPos)->getCanvas() );
            func( pCanvas );
        }
    }

    /** Called on derived classes to implement actual slide change.

        This method is called with the sprite of the slide coming 'in'

        @param rSprite
        Current sprite to operate on. This is the sprite of the
        'entering' slide

        @param x
        Current parameter value
    */
    virtual void performIn(
        const ::cppcanvas::CustomSpriteSharedPtr&   rSprite,
        UnoViewSharedPtr const &                    pView,
        const ::cppcanvas::CanvasSharedPtr&         rDestinationCanvas,
        double                                      t );

    /** Called on derived classes to implement actual slide change.

        This method is called with the sprite of the slide moving 'out'

        @param rSprite
        Current sprite to operate on. This is the sprite of the
        'leaving' slide

        @param x
        Current parameter value
    */
    virtual void performOut(
        const ::cppcanvas::CustomSpriteSharedPtr&  rSprite,
        UnoViewSharedPtr const &                   pView,
        const ::cppcanvas::CanvasSharedPtr&        rDestinationCanvas,
        double                                     t );

private:
    // XModifyListener
    virtual void SAL_CALL modified(
        ::com::sun::star::lang::EventObject const& evt )
        throw (::com::sun::star::uno::RuntimeException);
    // XEventListener
    virtual void SAL_CALL disposing(
        ::com::sun::star::lang::EventObject const& evt )
        throw (::com::sun::star::uno::RuntimeException);

    /// WeakComponentImplHelperBase:
    virtual void SAL_CALL disposing();

private:

    // view mangement:
    UnoViewVector maViews;
    UnoViewSharedPtr findUnoView(
        ::com::sun::star::uno::Reference<
        ::com::sun::star::presentation::XSlideShowView> const & xSlideShowView )
        const;
    bool removeView_( UnoViewSharedPtr const& pView,
                      bool bDisposedView = false );
    void removeTransformationChangedListenerFrom(UnoViewSharedPtr const& pView);

    SoundPlayerSharedPtr mpSoundPlayer;

    ::boost::optional<SlideSharedPtr> mLeavingSlide;
    SlideSharedPtr mpEnteringSlide;
    mutable SlideBitmapSharedPtr mpLeavingBitmap;
    mutable SlideBitmapSharedPtr mpEnteringBitmap;

    typedef ::std::vector< ::cppcanvas::CustomSpriteSharedPtr > SpriteVector;
    SpriteVector maOutSprites;
    SpriteVector maInSprites;
    const bool mbCreateLeavingSprites;
    const bool mbCreateEnteringSprites;
    bool mbSpritesVisible;

    ::cppcanvas::CustomSpriteSharedPtr createSprite(
        UnoViewSharedPtr const & pView,
        ::basegfx::B2DSize const & rSpriteSize ) const;
    void addSprites( UnoViewSharedPtr const & pView );
};

} // namespace internal
} // namespace presentation

#endif
<commit_msg>INTEGRATION: CWS presfixes09 (1.4.16); FILE MERGED 2006/09/18 15:26:50 thb 1.4.16.6: #i10000# Fixed post-MERGE breakages 2006/04/24 13:25:33 thb 1.4.16.5: #i53194# Unified include statements (local headers always have double quotes; external headers angle brackets); reverted EventMultiplexer pause events to shared_ptr; removed EventMultiplexer::removeViewHandler(), since the handler is held weakly, anyway. 2006/04/03 16:19:01 thb 1.4.16.4: #i37778# Now passing down ComponentContext to all interested parties; building a second, all-exports version of the slideshow component (to facilitate unit testing also for internal classes) - this made necessary renaming ImportFailedException to ShapeLoadFailedException (because of silly i63703); applied relevant parts of #i63770# (const-correctness); reworked view handling in such a way that views are now kept in one central repository (and are not duplicated across all interested objects); moved code from namespace presentation to namespace slideshow 2006/03/24 18:23:26 thb 1.4.16.3: #i37778# Moved whole slideshow engine from namespace presentation (which conflicts with one of the UNO subnamespaces) to slideshow 2006/03/07 00:00:54 thb 1.4.16.2: RESYNC: (1.4-1.5); FILE MERGED 2006/03/06 22:14:32 thb 1.4.16.1: #i53194# #i55294# #i59324# Overhauled IntrinsicAnimationActivity; fixes GIF animation import; corrected rehearse timings sprite size; several cosmetic changes (removed external header guards); prepared scene for sprite prio<commit_after>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: slidechangebase.hxx,v $
 *
 *  $Revision: 1.6 $
 *
 *  last change: $Author: kz $ $Date: 2006-12-13 15:45:39 $
 *
 *  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
 *
 ************************************************************************/

#if ! defined(INCLUDED_PRESENTATION_INTERNAL_TRANSITIONS_SLIDECHANGEBASE_HXX)
#define INCLUDED_PRESENTATION_INTERNAL_TRANSITIONS_SLIDECHANGEBASE_HXX

#include <osl/mutex.hxx>

#include "unoview.hxx"
#include "vieweventhandler.hxx"
#include "numberanimation.hxx"
#include "slide.hxx"
#include "soundplayer.hxx"

#include <boost/enable_shared_from_this.hpp>
#include <boost/utility.hpp>
#include <boost/optional.hpp>

namespace slideshow {
namespace internal {

/** Base class for all slide change effects.

    This class provides the basic sprite and view handling
    functionality.  Derived classes should normally only need to
    implement the perform() method.
*/
class SlideChangeBase : public ViewEventHandler,
                        public NumberAnimation,
                        public boost::enable_shared_from_this<SlideChangeBase>,
                        private ::boost::noncopyable
{
public:
    // NumberAnimation
    virtual bool operator()( double x );
    virtual double getUnderlyingValue() const;

    // Animation
    virtual void start( const AnimatableShapeSharedPtr&,
                        const ShapeAttributeLayerSharedPtr& );
    virtual void end();

    // ViewEventHandler
    virtual void viewAdded( const UnoViewSharedPtr& rView );
    virtual void viewRemoved( const UnoViewSharedPtr& rView );
    virtual void viewChanged( const UnoViewSharedPtr& rView );

protected:
    /** Create a new SlideChanger, for the given leaving and
        entering slides.
    */
    SlideChangeBase(
        ::boost::optional<SlideSharedPtr> const & leavingSlide,
        const SlideSharedPtr&                     pEnteringSlide,
        const SoundPlayerSharedPtr&               pSoundPlayer,
        const UnoViewContainer&                   rViewContainer,
        EventMultiplexer&                         rEventMultiplexer,
        bool                                      bCreateLeavingSprites = true,
        bool                                      bCreateEnteringSprites = true );

    /// Info on a per-view basis
    struct ViewEntry
    {
        ViewEntry() {}

        explicit ViewEntry( const UnoViewSharedPtr& rView ) :
            mpView( rView )
        {
        }

        /// The view this entry is for
        UnoViewSharedPtr                    mpView;
        /// outgoing slide sprite
        cppcanvas::CustomSpriteSharedPtr    mpOutSprite;
        /// incoming slide sprite
        cppcanvas::CustomSpriteSharedPtr    mpInSprite;
        /// outgoing slide bitmap
        mutable SlideBitmapSharedPtr        mpLeavingBitmap;
        /// incoming slide bitmap
        mutable SlideBitmapSharedPtr        mpEnteringBitmap;

        // for algo access
        const UnoViewSharedPtr& getView() const { return mpView; }
    };

    typedef ::std::vector<ViewEntry> ViewsVecT;

    ViewsVecT::const_iterator beginViews() { return maViewData.begin(); }
    ViewsVecT::const_iterator endViews() { return maViewData.end(); }

    SlideBitmapSharedPtr getLeavingBitmap( const ViewEntry& rViewEntry ) const;
    SlideBitmapSharedPtr getEnteringBitmap( const ViewEntry& rViewEntry ) const;

    SlideBitmapSharedPtr createBitmap( const UnoViewSharedPtr&                pView,
                                       const boost::optional<SlideSharedPtr>& rSlide_ ) const;

    ::basegfx::B2ISize getEnteringSizePixel( const UnoViewSharedPtr& pView ) const;

    void renderBitmap( SlideBitmapSharedPtr const & pSlideBitmap,
                       ::cppcanvas::CanvasSharedPtr const & pCanvas );

    /** Called on derived classes to implement actual slide change.

        This method is called with the sprite of the slide coming 'in'

        @param rSprite
        Current sprite to operate on. This is the sprite of the
        'entering' slide

        @param t
        Current parameter value
    */
    virtual void performIn(
        const ::cppcanvas::CustomSpriteSharedPtr&   rSprite,
        const ViewEntry&                            rViewEntry,
        const ::cppcanvas::CanvasSharedPtr&         rDestinationCanvas,
        double                                      t );

    /** Called on derived classes to implement actual slide change.

        This method is called with the sprite of the slide moving 'out'

        @param rSprite
        Current sprite to operate on. This is the sprite of the
        'leaving' slide

        @param t
        Current parameter value
    */
    virtual void performOut(
        const ::cppcanvas::CustomSpriteSharedPtr&  rSprite,
        const ViewEntry&                           rViewEntry,
        const ::cppcanvas::CanvasSharedPtr&        rDestinationCanvas,
        double                                     t );

private:

    ::cppcanvas::CustomSpriteSharedPtr createSprite(
        UnoViewSharedPtr const &   pView,
        ::basegfx::B2DSize const & rSpriteSize,
        double                     nPrio ) const;

    void addSprites( ViewEntry& rEntry );

    ViewsVecT::iterator lookupView( UnoViewSharedPtr const & pView );
    ViewsVecT::const_iterator lookupView( UnoViewSharedPtr const & pView ) const;

    SoundPlayerSharedPtr                mpSoundPlayer;

    const UnoViewContainer&             mrViewContainer;
    EventMultiplexer&                   mrEventMultiplexer;

    ::boost::optional<SlideSharedPtr>   mLeavingSlide;
    SlideSharedPtr                      mpEnteringSlide;

    ViewsVecT                           maViewData;
    const bool                          mbCreateLeavingSprites;
    const bool                          mbCreateEnteringSprites;
    bool                                mbSpritesVisible;
};

} // namespace internal
} // namespace presentation

#endif
<|endoftext|>


<commit_before>#include <iostream>
#include "math.h"

int main() {
    const int rows = 3;
    const int cols = 4;
    unsigned int matrix[rows][cols] = {
        {1, 2, 3, 4},
        {5, 567, 7, 8},
        {9, 10, 11, 12}
    };

    unsigned int max = NAN;
    int max_row_index = NAN;
    int max_col_index = NAN;

    int max_sum_row = NAN;
    int max_sum_col = NAN;

    for(int row = 0; row < rows; ++row) {
        for(int col = 0; col < cols; ++col) {
            int sum_row = 0;
            sum_row += matrix[row][col];

            if (matrix[row][col] > max) {
                max = matrix[row][col];
                max_row_index = row;
                max_col_index = col;
            }
            if (sum_row > max_sum_row) {
                max_sum_row = row;
            }
        }
    }

    for(int col = 0; col < cols; ++col) {
        for(int row = 0; row < rows; ++row) {
            int sum_col = 0;
            sum_col += matrix[row][col];

            if (sum_col > max_sum_col) {
                max_sum_col = col;
            }
        }
    }

    std::cout <<  "Max value: " << max << " with indexes: " << max_row_index << ", " << max_col_index << std::endl;
    std::cout << "Max row: " << max_sum_row << ", " << "Max col: " << max_sum_col << std::endl;

    return 0;
}<commit_msg>Week 1, proper matrix<commit_after>#include <iostream>
#include "math.h"

int main() {
    const int rows = 3;
    const int cols = 4;
    unsigned int matrix[rows][cols] = {
        {1, 2, 3, 4},
        {5, 567, 7, 9},
        {9, 10, 100500, 12}
    };

    unsigned int max = NAN;
    int max_row_index = NAN;
    int max_col_index = NAN;

    int max_sum_row = 0;
    int max_sum_col = 0;

    int max_row = 0;
    int max_col = 0;

    for(int row = 0; row < rows; ++row) {
        int sum_row = 0;
        for(int col = 0; col < cols; ++col) {
            sum_row += matrix[row][col];

            if (matrix[row][col] > max) {
                max = matrix[row][col];
                max_row_index = row;
                max_col_index = col;
            }

        }
        if (sum_row > max_sum_row) {
            max_sum_row = sum_row;
            max_row = row;
        }
    }

    for(int col = 0; col < cols; ++col) {
        int sum_col = 0;
        for(int row = 0; row < rows; ++row) {
            sum_col += matrix[row][col];
        }
        if (sum_col > max_sum_col) {
            max_sum_col = sum_col;
            max_col = col;
        }
    }

    std::cout <<  "Max value: " << max << " with indexes: " << max_row_index << ", " << max_col_index << std::endl;
    std::cout << "Max row: " << max_row << ", " << "Max col: " << max_col << std::endl;

    return 0;
}<|endoftext|>


<commit_before>/* The MIT License (MIT)
 *
 * Copyright (c) 2016 Adrian Dobrică, Ștefan-Gabriel Mirea
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 */

#include "main_window.hpp"
#include "executable_viewer.hpp"
#include "elf_file.hpp"

#include <QMessageBox>

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

    mdiArea = new QMdiArea();
    setCentralWidget(mdiArea);
    connect(mdiArea, SIGNAL(subWindowActivated(QMdiSubWindow *)), this, SLOT(updateActions()));

    createActions();

    QMenu *fileMenu = menuBar()->addMenu(QString("File"));
    fileMenu->addAction(openAction);
    fileMenu->addAction(saveAction);
    fileMenu->addAction(saveAsAction);
    fileMenu->addSeparator();
    fileMenu->addAction(exitAction);

    QMenu *editMenu = menuBar()->addMenu(QString("Edit"));
    editMenu->addAction(undoAction);
    editMenu->addAction(redoAction);
    editMenu->addSeparator();
    editMenu->addAction(copyAction);
    editMenu->addAction(pasteAction);

    windowMenu = menuBar()->addMenu(QString("Window"));
    connect(windowMenu, SIGNAL(aboutToShow()), this, SLOT(updateCheckableWindows()));
    windowMenu->addAction(closeAction);
    windowMenu->addAction(closeAllAction);
    windowMenu->addSeparator();
    windowMenu->addAction(tileAction);
    windowMenu->addAction(cascadeAction);
    windowMenu->addSeparator();
    windowMenu->addAction(nextAction);
    windowMenu->addAction(previousAction);

    windowActionGroup = new QActionGroup(this);
    signalMapper = new QSignalMapper(this);
    connect(signalMapper, SIGNAL(mapped(QWidget *)), this, SLOT(selectWindow(QWidget *)));

    updateCheckableWindows();

    QMenu *helpMenu = menuBar()->addMenu(QString("Help"));
    helpMenu->addAction(aboutAction);

    QToolBar *fileToolBar = new QToolBar();
    addToolBar(fileToolBar);
    fileToolBar->addAction(openAction);
    fileToolBar->addAction(saveAction);

    QToolBar *editToolBar = new QToolBar();
    addToolBar(editToolBar);
    editToolBar->addAction(undoAction);
    editToolBar->addAction(redoAction);
    editToolBar->addAction(copyAction);
    editToolBar->addAction(pasteAction);
}

void MainWindow::createActions()
{
    /* File menu */
    openAction = new QAction(QString("Open"), this);
    openAction->setIcon(QIcon::fromTheme("document-open", QIcon(":/icons/open.png")));
    connect(openAction, SIGNAL(triggered()), this, SLOT(open()));

    saveAction = new QAction(QString("Save"), this);
    saveAction->setIcon(QIcon::fromTheme("document-save", QIcon(":/icons/save.png")));
    connect(saveAction, SIGNAL(triggered()), this, SLOT(save()));

    saveAsAction = new QAction(QString("Save As..."), this);
    saveAsAction->setIcon(QIcon::fromTheme("document-save-as", QIcon(":/icons/save.png")));
    connect(saveAsAction, SIGNAL(triggered()), this, SLOT(saveAs()));

    exitAction = new QAction(QString("Exit"), this);
    exitAction->setIcon(QIcon::fromTheme("application-exit", QIcon(":/icons/exit.png")));
    connect(exitAction, SIGNAL(triggered()), this, SLOT(exit()));

    /* Edit menu */
    undoAction = new QAction(QString("Undo"), this);
    undoAction->setIcon(QIcon::fromTheme("edit-undo", QIcon(":/icons/undo.png")));
    connect(undoAction, SIGNAL(triggered()), this, SLOT(undo()));

    redoAction = new QAction(QString("Redo"), this);
    redoAction->setIcon(QIcon::fromTheme("edit-redo", QIcon(":/icons/redo.png")));
    connect(redoAction, SIGNAL(triggered()), this, SLOT(redo()));

    copyAction = new QAction(QString("Copy Hex"), this);
    copyAction->setIcon(QIcon::fromTheme("edit-copy", QIcon(":/icons/copy.png")));
    connect(copyAction, SIGNAL(triggered()), this, SLOT(copy()));

    pasteAction = new QAction(QString("Paste Hex"), this);
    pasteAction->setIcon(QIcon::fromTheme("edit-paste", QIcon(":/icons/paste.png")));
    connect(pasteAction, SIGNAL(triggered()), this, SLOT(paste()));

    /* Window menu */
    closeAction = new QAction(QString("Close"), this);
    connect(closeAction, SIGNAL(triggered()), mdiArea, SLOT(closeActiveSubWindow()));

    closeAllAction = new QAction(QString("Close All"), this);
    connect(closeAllAction, SIGNAL(triggered()), mdiArea, SLOT(closeAllSubWindows()));

    tileAction = new QAction(QString("Tile"), this);
    connect(tileAction, SIGNAL(triggered()), mdiArea, SLOT(tileSubWindows()));

    cascadeAction = new QAction(QString("Cascade"), this);
    connect(cascadeAction, SIGNAL(triggered()), mdiArea, SLOT(cascadeSubWindows()));

    nextAction = new QAction(QString("Next"), this);
    connect(nextAction, SIGNAL(triggered()), mdiArea, SLOT(activateNextSubWindow()));

    previousAction = new QAction(QString("Previous"), this);
    connect(previousAction, SIGNAL(triggered()), mdiArea, SLOT(activatePreviousSubWindow()));

    /* Help menu */
    aboutAction = new QAction(QString("About"), this);
    connect(aboutAction, SIGNAL(triggered()), this, SLOT(about()));

    updateActions();
}

void MainWindow::open()
{
    QString filename = QFileDialog::getOpenFileName(this, QString("Open"));
    if (!filename.isEmpty())
        open(filename);
}

void MainWindow::open(const QString &filename)
{
    QString canonicalName = QFileInfo(filename).canonicalFilePath();
    if (canonicalName == "")
    {
        QMessageBox::critical(this, QString("Error"), QString("The file %1 does not exist.")
                              .arg(filename));
        return;
    }

    foreach (QMdiSubWindow *window, mdiArea->subWindowList())
    {
        ExecutableViewer *ev = qobject_cast<ExecutableViewer *>(window->widget());
        if (ev->getFileUnit()->getName() == canonicalName.toStdString())
        {
            mdiArea->setActiveSubWindow(window);
            return;
        }
    }

    /* check read access */
    QFile qFile(canonicalName);
    if (!qFile.open(QFile::ReadOnly))
    {
        QMessageBox::critical(this, QString("Error"), QString("Cannot read file %1:\n%2.")
                              .arg(canonicalName) .arg(qFile.errorString()));
        return;
    }
    qFile.close();

    /* check file type */
    FileUnit *file;
    do {
        file = new elf::ELFFile(canonicalName.toStdString());
        if (file->getOpenStatus())
            break;
        delete file;

        /* check other file types */

        /* unknown file format */
        QMessageBox::critical(this, QString("Error"), QString("%1: Unknown file format.")
                              .arg(canonicalName));
        return;
    } while (false);

    ExecutableViewer *viewer = new ExecutableViewer(file, mdiArea);
    mdiArea->addSubWindow(viewer);
    viewer->showMaximized();
}

void MainWindow::save() {}

void MainWindow::saveAs() {}

void MainWindow::exit() {}

void MainWindow::undo() {}

void MainWindow::redo() {}

void MainWindow::copy() {}

void MainWindow::paste() {}

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

Click!
"));
}

void MainWindow::updateActions()
{
    bool hasActiveSubWindow = mdiArea->activeSubWindow();

    saveAction->setEnabled(hasActiveSubWindow);
    saveAsAction->setEnabled(hasActiveSubWindow);

    undoAction->setEnabled(false);
    redoAction->setEnabled(false);
    copyAction->setEnabled(false);
    pasteAction->setEnabled(false);

    closeAction->setEnabled(hasActiveSubWindow);
    closeAllAction->setEnabled(hasActiveSubWindow);
    tileAction->setEnabled(hasActiveSubWindow);
    cascadeAction->setEnabled(hasActiveSubWindow);
    nextAction->setEnabled(hasActiveSubWindow);
    previousAction->setEnabled(hasActiveSubWindow);
}

void MainWindow::updateCheckableWindows()
{
    /* Remove the previous checkable actions. */
#ifdef DEBUG
    assert(!windowMenu->actions().isEmpty());
#endif
    QAction *last;
    while ((last = windowMenu->actions().back()) != previousAction)
    {
        windowMenu->removeAction(last);
        if (!last->isSeparator())
        {
            windowActionGroup->removeAction(last);
            /* signalMapper will automatically remove all the mappings for last if any. */
        }
        delete last;
#ifdef DEBUG
        assert(!windowMenu->actions().isEmpty());
#endif
    }

    if (!mdiArea->subWindowList().empty())
    {
        QAction *separator = new QAction(this);
        separator->setSeparator(true);
        windowMenu->addAction(separator);
    }

    int index = 0;
    foreach (QMdiSubWindow *window, mdiArea->subWindowList())
    {
        ++index;
        ExecutableViewer *ev = qobject_cast<ExecutableViewer *>(window->widget());
        QAction *action = new QAction(QString::fromStdString(ev->getFileUnit()->getName()), this);
        action->setActionGroup(windowActionGroup);
        action->setCheckable(true);
        QMdiSubWindow *activeSubWindow = mdiArea->activeSubWindow();

#ifdef DEBUG
        /* Reaching this point supposes there is at least one subwindow. Therefore, we also have an
         * active subwindow. */
        assert(activeSubWindow != nullptr);
#endif

        action->setChecked(ev == qobject_cast<ExecutableViewer *>(activeSubWindow->widget()));
        connect(action, SIGNAL(triggered()), signalMapper, SLOT(map()));
        signalMapper->setMapping(action, window);
        windowMenu->addAction(action);
    }
}

void MainWindow::selectWindow(QWidget *subWindow)
{
    QMdiSubWindow *mdiSubWindow = dynamic_cast<QMdiSubWindow *>(subWindow);

#ifdef DEBUG
    assert(mdiSubWindow != nullptr);
#endif

    mdiArea->setActiveSubWindow(mdiSubWindow);
}
<commit_msg>Disable Next and Previous Window menu items when there are not at least two subwindows<commit_after>/* The MIT License (MIT)
 *
 * Copyright (c) 2016 Adrian Dobrică, Ștefan-Gabriel Mirea
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 */

#include "main_window.hpp"
#include "executable_viewer.hpp"
#include "elf_file.hpp"

#include <QMessageBox>

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

    mdiArea = new QMdiArea();
    setCentralWidget(mdiArea);
    connect(mdiArea, SIGNAL(subWindowActivated(QMdiSubWindow *)), this, SLOT(updateActions()));

    createActions();

    QMenu *fileMenu = menuBar()->addMenu(QString("File"));
    fileMenu->addAction(openAction);
    fileMenu->addAction(saveAction);
    fileMenu->addAction(saveAsAction);
    fileMenu->addSeparator();
    fileMenu->addAction(exitAction);

    QMenu *editMenu = menuBar()->addMenu(QString("Edit"));
    editMenu->addAction(undoAction);
    editMenu->addAction(redoAction);
    editMenu->addSeparator();
    editMenu->addAction(copyAction);
    editMenu->addAction(pasteAction);

    windowMenu = menuBar()->addMenu(QString("Window"));
    connect(windowMenu, SIGNAL(aboutToShow()), this, SLOT(updateCheckableWindows()));
    windowMenu->addAction(closeAction);
    windowMenu->addAction(closeAllAction);
    windowMenu->addSeparator();
    windowMenu->addAction(tileAction);
    windowMenu->addAction(cascadeAction);
    windowMenu->addSeparator();
    windowMenu->addAction(nextAction);
    windowMenu->addAction(previousAction);

    windowActionGroup = new QActionGroup(this);
    signalMapper = new QSignalMapper(this);
    connect(signalMapper, SIGNAL(mapped(QWidget *)), this, SLOT(selectWindow(QWidget *)));

    updateCheckableWindows();

    QMenu *helpMenu = menuBar()->addMenu(QString("Help"));
    helpMenu->addAction(aboutAction);

    QToolBar *fileToolBar = new QToolBar();
    addToolBar(fileToolBar);
    fileToolBar->addAction(openAction);
    fileToolBar->addAction(saveAction);

    QToolBar *editToolBar = new QToolBar();
    addToolBar(editToolBar);
    editToolBar->addAction(undoAction);
    editToolBar->addAction(redoAction);
    editToolBar->addAction(copyAction);
    editToolBar->addAction(pasteAction);
}

void MainWindow::createActions()
{
    /* File menu */
    openAction = new QAction(QString("Open"), this);
    openAction->setIcon(QIcon::fromTheme("document-open", QIcon(":/icons/open.png")));
    connect(openAction, SIGNAL(triggered()), this, SLOT(open()));

    saveAction = new QAction(QString("Save"), this);
    saveAction->setIcon(QIcon::fromTheme("document-save", QIcon(":/icons/save.png")));
    connect(saveAction, SIGNAL(triggered()), this, SLOT(save()));

    saveAsAction = new QAction(QString("Save As..."), this);
    saveAsAction->setIcon(QIcon::fromTheme("document-save-as", QIcon(":/icons/save.png")));
    connect(saveAsAction, SIGNAL(triggered()), this, SLOT(saveAs()));

    exitAction = new QAction(QString("Exit"), this);
    exitAction->setIcon(QIcon::fromTheme("application-exit", QIcon(":/icons/exit.png")));
    connect(exitAction, SIGNAL(triggered()), this, SLOT(exit()));

    /* Edit menu */
    undoAction = new QAction(QString("Undo"), this);
    undoAction->setIcon(QIcon::fromTheme("edit-undo", QIcon(":/icons/undo.png")));
    connect(undoAction, SIGNAL(triggered()), this, SLOT(undo()));

    redoAction = new QAction(QString("Redo"), this);
    redoAction->setIcon(QIcon::fromTheme("edit-redo", QIcon(":/icons/redo.png")));
    connect(redoAction, SIGNAL(triggered()), this, SLOT(redo()));

    copyAction = new QAction(QString("Copy Hex"), this);
    copyAction->setIcon(QIcon::fromTheme("edit-copy", QIcon(":/icons/copy.png")));
    connect(copyAction, SIGNAL(triggered()), this, SLOT(copy()));

    pasteAction = new QAction(QString("Paste Hex"), this);
    pasteAction->setIcon(QIcon::fromTheme("edit-paste", QIcon(":/icons/paste.png")));
    connect(pasteAction, SIGNAL(triggered()), this, SLOT(paste()));

    /* Window menu */
    closeAction = new QAction(QString("Close"), this);
    connect(closeAction, SIGNAL(triggered()), mdiArea, SLOT(closeActiveSubWindow()));

    closeAllAction = new QAction(QString("Close All"), this);
    connect(closeAllAction, SIGNAL(triggered()), mdiArea, SLOT(closeAllSubWindows()));

    tileAction = new QAction(QString("Tile"), this);
    connect(tileAction, SIGNAL(triggered()), mdiArea, SLOT(tileSubWindows()));

    cascadeAction = new QAction(QString("Cascade"), this);
    connect(cascadeAction, SIGNAL(triggered()), mdiArea, SLOT(cascadeSubWindows()));

    nextAction = new QAction(QString("Next"), this);
    connect(nextAction, SIGNAL(triggered()), mdiArea, SLOT(activateNextSubWindow()));

    previousAction = new QAction(QString("Previous"), this);
    connect(previousAction, SIGNAL(triggered()), mdiArea, SLOT(activatePreviousSubWindow()));

    /* Help menu */
    aboutAction = new QAction(QString("About"), this);
    connect(aboutAction, SIGNAL(triggered()), this, SLOT(about()));

    updateActions();
}

void MainWindow::open()
{
    QString filename = QFileDialog::getOpenFileName(this, QString("Open"));
    if (!filename.isEmpty())
        open(filename);
}

void MainWindow::open(const QString &filename)
{
    QString canonicalName = QFileInfo(filename).canonicalFilePath();
    if (canonicalName == "")
    {
        QMessageBox::critical(this, QString("Error"), QString("The file %1 does not exist.")
                              .arg(filename));
        return;
    }

    foreach (QMdiSubWindow *window, mdiArea->subWindowList())
    {
        ExecutableViewer *ev = qobject_cast<ExecutableViewer *>(window->widget());
        if (ev->getFileUnit()->getName() == canonicalName.toStdString())
        {
            mdiArea->setActiveSubWindow(window);
            return;
        }
    }

    /* check read access */
    QFile qFile(canonicalName);
    if (!qFile.open(QFile::ReadOnly))
    {
        QMessageBox::critical(this, QString("Error"), QString("Cannot read file %1:\n%2.")
                              .arg(canonicalName) .arg(qFile.errorString()));
        return;
    }
    qFile.close();

    /* check file type */
    FileUnit *file;
    do {
        file = new elf::ELFFile(canonicalName.toStdString());
        if (file->getOpenStatus())
            break;
        delete file;

        /* check other file types */

        /* unknown file format */
        QMessageBox::critical(this, QString("Error"), QString("%1: Unknown file format.")
                              .arg(canonicalName));
        return;
    } while (false);

    ExecutableViewer *viewer = new ExecutableViewer(file, mdiArea);
    mdiArea->addSubWindow(viewer);
    viewer->showMaximized();
}

void MainWindow::save() {}

void MainWindow::saveAs() {}

void MainWindow::exit() {}

void MainWindow::undo() {}

void MainWindow::redo() {}

void MainWindow::copy() {}

void MainWindow::paste() {}

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

Click!
"));
}

void MainWindow::updateActions()
{
    bool hasActiveSubWindow = mdiArea->activeSubWindow();

    saveAction->setEnabled(hasActiveSubWindow);
    saveAsAction->setEnabled(hasActiveSubWindow);

    undoAction->setEnabled(false);
    redoAction->setEnabled(false);
    copyAction->setEnabled(false);
    pasteAction->setEnabled(false);

    closeAction->setEnabled(hasActiveSubWindow);
    closeAllAction->setEnabled(hasActiveSubWindow);
    tileAction->setEnabled(hasActiveSubWindow);
    cascadeAction->setEnabled(hasActiveSubWindow);

    int subWindowsNum = mdiArea->subWindowList().size();
    nextAction->setEnabled(subWindowsNum >= 2);
    previousAction->setEnabled(subWindowsNum >= 2);
}

void MainWindow::updateCheckableWindows()
{
    /* Remove the previous checkable actions. */
#ifdef DEBUG
    assert(!windowMenu->actions().isEmpty());
#endif
    QAction *last;
    while ((last = windowMenu->actions().back()) != previousAction)
    {
        windowMenu->removeAction(last);
        if (!last->isSeparator())
        {
            windowActionGroup->removeAction(last);
            /* signalMapper will automatically remove all the mappings for last if any. */
        }
        delete last;
#ifdef DEBUG
        assert(!windowMenu->actions().isEmpty());
#endif
    }

    if (!mdiArea->subWindowList().empty())
    {
        QAction *separator = new QAction(this);
        separator->setSeparator(true);
        windowMenu->addAction(separator);
    }

    int index = 0;
    foreach (QMdiSubWindow *window, mdiArea->subWindowList())
    {
        ++index;
        ExecutableViewer *ev = qobject_cast<ExecutableViewer *>(window->widget());
        QAction *action = new QAction(QString::fromStdString(ev->getFileUnit()->getName()), this);
        action->setActionGroup(windowActionGroup);
        action->setCheckable(true);
        QMdiSubWindow *activeSubWindow = mdiArea->activeSubWindow();

#ifdef DEBUG
        /* Reaching this point supposes there is at least one subwindow. Therefore, we also have an
         * active subwindow. */
        assert(activeSubWindow != nullptr);
#endif

        action->setChecked(ev == qobject_cast<ExecutableViewer *>(activeSubWindow->widget()));
        connect(action, SIGNAL(triggered()), signalMapper, SLOT(map()));
        signalMapper->setMapping(action, window);
        windowMenu->addAction(action);
    }
}

void MainWindow::selectWindow(QWidget *subWindow)
{
    QMdiSubWindow *mdiSubWindow = dynamic_cast<QMdiSubWindow *>(subWindow);

#ifdef DEBUG
    assert(mdiSubWindow != nullptr);
#endif

    mdiArea->setActiveSubWindow(mdiSubWindow);
}
<|endoftext|>


<commit_before>#include "server.h"

#include <config.h>
#include <utils/daemon.h>
#include <utils/mkdirp.h>
#include <utils/socket.h>

#include <err.h>
#include <signal.h>
#include <sys/stat.h>
#include <sys/types.h>

namespace clc { namespace server {

int main()
{
  const auto sp = config::sock_path();
  int fd;

  fd = utils::create_socket(sp.c_str());
  if (fd == -1)
    err(EXIT_FAILURE, "%s", sp.c_str());

  while (42);
}

bool is_running()
{
  const auto pp = config::pid_path();
  pid_t pid;

  if (!utils::read_pidfile(pp.c_str(), &pid))
    return false;

  return kill(pid, 0) == 0;
}

void start()
{
  const auto rp = config::run_path();
  const auto pp = config::pid_path();

  if (is_running()) {
    warnx("server already running");
    return;
  }

  /* Create run dir. */
  utils::mkdirp(rp.c_str());

  /* Create the server and run the main function. */
  if (utils::daemonize(pp.c_str()))
    exit(main());
}

void stop()
{
  const auto pp = config::pid_path();
  pid_t pid;

  if (!is_running()) {
    warnx("server not running");
    return;
  }

  if (!utils::read_pidfile(pp.c_str(), &pid))
    err(EXIT_FAILURE, "%s", pp.c_str());

  if (kill(pid, SIGTERM) == -1)
    err(EXIT_FAILURE, "process %d", pid);

  if (unlink(pp.c_str()) == -1)
    err(EXIT_FAILURE, "%s", pp.c_str());
}

}} // namespace clc::server
<commit_msg>Do socket accept stuff.<commit_after>#include "server.h"

#include <config.h>
#include <utils/daemon.h>
#include <utils/mkdirp.h>
#include <utils/socket.h>

#include <err.h>
#include <pthread.h>
#include <signal.h>
#include <sys/socket.h>
#include <sys/stat.h>
#include <sys/types.h>

namespace clc { namespace server {

int main()
{
  const auto sp = config::sock_path();
  int fd;
  int client_fd;

  fd = utils::create_socket(sp.c_str());
  if (fd == -1)
    err(EXIT_FAILURE, "%s", sp.c_str());

  while ((client_fd = accept(fd, NULL, NULL)) != -1) {
    close(client_fd);
  }

  return EXIT_FAILURE;
}

bool is_running()
{
  const auto pp = config::pid_path();
  pid_t pid;

  if (!utils::read_pidfile(pp.c_str(), &pid))
    return false;

  return kill(pid, 0) == 0;
}

void start()
{
  const auto rp = config::run_path();
  const auto pp = config::pid_path();

  if (is_running()) {
    warnx("server already running");
    return;
  }

  /* Create run dir. */
  utils::mkdirp(rp.c_str());

  /* Create the server and run the main function. */
  if (utils::daemonize(pp.c_str()))
    exit(main());
}

void stop()
{
  const auto pp = config::pid_path();
  pid_t pid;

  if (!is_running()) {
    warnx("server not running");
    return;
  }

  if (!utils::read_pidfile(pp.c_str(), &pid))
    err(EXIT_FAILURE, "%s", pp.c_str());

  if (kill(pid, SIGTERM) == -1)
    err(EXIT_FAILURE, "process %d", pid);

  if (unlink(pp.c_str()) == -1)
    err(EXIT_FAILURE, "%s", pp.c_str());
}

}} // namespace clc::server
<|endoftext|>


<commit_before>#ifndef ROOT_TFPBlock
#include "TFPBlock.h"
#endif
#include <cstdlib>
#include <malloc.h>

ClassImp(TFPBlock)

//__________________________________________________________________
//constructor
TFPBlock::TFPBlock(Long64_t* offset, Int_t* length, Int_t nb)
{
   Int_t aux = 0;

   fNblock = nb;
   fPos = new Long64_t[nb];
   fLen = new Int_t[nb];

   for (Int_t i=0; i < nb; i++){
      fPos[i] = offset[i];
      fLen[i] = length[i];
      aux += length[i];
   }
   fFullSize = aux;
   fBuffer = new char[fFullSize];
}

//__________________________________________________________________
//destructor
TFPBlock::~TFPBlock()
{
   delete[] fPos;
   delete[] fLen;
   delete[] fBuffer;
}

//__________________________________________________________________
Long64_t* TFPBlock::GetPos()
{
   // Get pointer to the array of postions.

   return fPos;
}

//__________________________________________________________________
Int_t* TFPBlock::GetLen()
{
   // Get pointer to the array of lengths.

   return fLen;
}

//__________________________________________________________________
Int_t TFPBlock::GetFullSize()
{
   // Return size of the block.

   return fFullSize;
}

//__________________________________________________________________
Int_t TFPBlock::GetNoElem()
{
   // Return number of elements in the block.

   return fNblock;
}

//__________________________________________________________________
Long64_t TFPBlock::GetPos(Int_t i)
{
   // Get position of the element at index i.

   return fPos[i];
}

//__________________________________________________________________
Int_t TFPBlock::GetLen(Int_t i)
{
  // Get length of the element at index i.

   return fLen[i];
}

//__________________________________________________________________
char* TFPBlock::GetBuffer()
{
   // Get block buffer.

   return fBuffer;
}

//__________________________________________________________________
void TFPBlock::SetBuffer(char* buf)
{
   //Set block buffer.

   fBuffer = buf;
}

//__________________________________________________________________
void TFPBlock::ReallocBlock(Long64_t* offset, Int_t* length, Int_t nb)
{
   // Reallocate the block's buffer based on the length
   // of the elements it will contain.

   Int_t aux = 0;

   fNblock = nb;
   fPos = new Long64_t[nb];
   fLen = new Int_t[nb];

   for(Int_t i=0; i < nb; i++){

      fPos[i] = offset[i];
      fLen[i] = length[i];
      aux += fLen[i];
   }

   fFullSize = aux;
   fBuffer = (char*) realloc(fBuffer, fFullSize);
}

<commit_msg>fix OSX compilation issue.<commit_after>#ifndef ROOT_TFPBlock
#include "TFPBlock.h"
#endif
#include <cstdlib>
#ifndef __APPLE__
#include <malloc.h>
#endif

ClassImp(TFPBlock)

//__________________________________________________________________
//constructor
TFPBlock::TFPBlock(Long64_t* offset, Int_t* length, Int_t nb)
{
   Int_t aux = 0;

   fNblock = nb;
   fPos = new Long64_t[nb];
   fLen = new Int_t[nb];

   for (Int_t i=0; i < nb; i++){
      fPos[i] = offset[i];
      fLen[i] = length[i];
      aux += length[i];
   }
   fFullSize = aux;
   fBuffer = new char[fFullSize];
}

//__________________________________________________________________
//destructor
TFPBlock::~TFPBlock()
{
   delete[] fPos;
   delete[] fLen;
   delete[] fBuffer;
}

//__________________________________________________________________
Long64_t* TFPBlock::GetPos()
{
   // Get pointer to the array of postions.

   return fPos;
}

//__________________________________________________________________
Int_t* TFPBlock::GetLen()
{
   // Get pointer to the array of lengths.

   return fLen;
}

//__________________________________________________________________
Int_t TFPBlock::GetFullSize()
{
   // Return size of the block.

   return fFullSize;
}

//__________________________________________________________________
Int_t TFPBlock::GetNoElem()
{
   // Return number of elements in the block.

   return fNblock;
}

//__________________________________________________________________
Long64_t TFPBlock::GetPos(Int_t i)
{
   // Get position of the element at index i.

   return fPos[i];
}

//__________________________________________________________________
Int_t TFPBlock::GetLen(Int_t i)
{
  // Get length of the element at index i.

   return fLen[i];
}

//__________________________________________________________________
char* TFPBlock::GetBuffer()
{
   // Get block buffer.

   return fBuffer;
}

//__________________________________________________________________
void TFPBlock::SetBuffer(char* buf)
{
   //Set block buffer.

   fBuffer = buf;
}

//__________________________________________________________________
void TFPBlock::ReallocBlock(Long64_t* offset, Int_t* length, Int_t nb)
{
   // Reallocate the block's buffer based on the length
   // of the elements it will contain.

   Int_t aux = 0;

   fNblock = nb;
   fPos = new Long64_t[nb];
   fLen = new Int_t[nb];

   for(Int_t i=0; i < nb; i++){

      fPos[i] = offset[i];
      fLen[i] = length[i];
      aux += fLen[i];
   }

   fFullSize = aux;
   fBuffer = (char*) realloc(fBuffer, fFullSize);
}

<|endoftext|>


<commit_before>#include "BasicBlock.h"

#include <iostream>

#include "preprocessor/llvm_includes_start.h"
#include <llvm/IR/CFG.h>
#include <llvm/IR/Module.h>
#include <llvm/IR/Function.h>
#include <llvm/IR/Instructions.h>
#include <llvm/IR/IntrinsicInst.h>
#include <llvm/IR/IRBuilder.h>
#include <llvm/Support/raw_os_ostream.h>
#include "preprocessor/llvm_includes_end.h"

#include "RuntimeManager.h"
#include "Type.h"
#include "Utils.h"

namespace dev
{
namespace eth
{
namespace jit
{

BasicBlock::BasicBlock(instr_idx _firstInstrIdx, code_iterator _begin, code_iterator _end, llvm::Function* _mainFunc):
	m_firstInstrIdx{_firstInstrIdx},
	m_begin(_begin),
	m_end(_end),
	m_llvmBB(llvm::BasicBlock::Create(_mainFunc->getContext(), {".", std::to_string(_firstInstrIdx)}, _mainFunc))
{}

LocalStack::LocalStack(IRBuilder& _builder, RuntimeManager& _runtimeManager):
	CompilerHelper(_builder)
{
	// Call stack.prepare. min, max, size args will be filled up in finalize().
	auto undef = llvm::UndefValue::get(Type::Size);
	m_sp = m_builder.CreateCall(getStackPrepareFunc(),
			{_runtimeManager.getStackBase(), _runtimeManager.getStackSize(), undef, undef, undef, _runtimeManager.getJmpBuf()},
			{"sp", m_builder.GetInsertBlock()->getName()});
}

void LocalStack::push(llvm::Value* _value)
{
	assert(_value->getType() == Type::Word);
	m_local.push_back(_value);
	m_maxSize = std::max(m_maxSize, size());
}

llvm::Value* LocalStack::pop()
{
	auto item = get(0);
	assert(!m_local.empty() || !m_input.empty());

	if (m_local.size() > 0)
		m_local.pop_back();
	else
		++m_globalPops;

	m_minSize = std::min(m_minSize, size());
	return item;
}

/**
 *  Pushes a copy of _index-th element (tos is 0-th elem).
 */
void LocalStack::dup(size_t _index)
{
	auto val = get(_index);
	push(val);
}

/**
 *  Swaps tos with _index-th element (tos is 0-th elem).
 *  _index must be > 0.
 */
void LocalStack::swap(size_t _index)
{
	assert(_index > 0);
	auto val = get(_index);
	auto tos = get(0);
	set(_index, tos);
	set(0, val);
}

llvm::Value* LocalStack::get(size_t _index)
{
	if (_index < m_local.size())
		return *(m_local.rbegin() + _index); // count from back

	auto idx = _index - m_local.size() + m_globalPops;
	if (idx >= m_input.size())
		m_input.resize(idx + 1);
	auto& item = m_input[idx];

	if (!item)
	{
		// Fetch an item from global stack
		ssize_t globalIdx = -static_cast<ssize_t>(idx) - 1;
		auto slot = m_builder.CreateConstGEP1_64(m_sp, globalIdx);
		item = m_builder.CreateAlignedLoad(slot, 16); // TODO: Handle malloc alignment. Also for 32-bit systems.
		m_minSize = std::min(m_minSize, globalIdx); 	// remember required stack size
	}

	return item;
}

void LocalStack::set(size_t _index, llvm::Value* _word)
{
	if (_index < m_local.size())
	{
		*(m_local.rbegin() + _index) = _word;
		return;
	}

	auto idx = _index - m_local.size() + m_globalPops;
	assert(idx < m_input.size());
	m_input[idx] = _word;
}

void LocalStack::finalize()
{
	m_sp->setArgOperand(2, m_builder.getInt64(minSize()));
	m_sp->setArgOperand(3, m_builder.getInt64(maxSize()));
	m_sp->setArgOperand(4, m_builder.getInt64(size()));

	if (auto term = m_builder.GetInsertBlock()->getTerminator())
		m_builder.SetInsertPoint(term); // Insert before terminator

	auto inputIt = m_input.rbegin();
	auto localIt = m_local.begin();
	for (auto globalIdx = -static_cast<ssize_t>(m_input.size()); globalIdx < size(); ++globalIdx)
	{
		llvm::Value* item = nullptr;
		if (globalIdx < -m_globalPops)
		{
			item = *inputIt++;	// update input items (might contain original value)
			if (!item)			// some items are skipped
				continue;
		}
		else
			item = *localIt++;	// store new items

		auto slot = m_builder.CreateConstGEP1_64(m_sp, globalIdx);
		m_builder.CreateAlignedStore(item, slot, 16); // TODO: Handle malloc alignment. Also for 32-bit systems.
	}
}

llvm::Function* LocalStack::getStackPrepareFunc()
{
	static const auto c_funcName = "stack.prepare";
	if (auto func = getModule()->getFunction(c_funcName))
		return func;

	llvm::Type* argsTys[] = {Type::WordPtr, Type::Size->getPointerTo(), Type::Size, Type::Size, Type::Size, Type::BytePtr};
	auto func = llvm::Function::Create(llvm::FunctionType::get(Type::WordPtr, argsTys, false), llvm::Function::PrivateLinkage, c_funcName, getModule());
	func->setDoesNotThrow();
	func->setDoesNotAccessMemory(1);
	func->setDoesNotAlias(2);
	func->setDoesNotCapture(2);

	auto checkBB = llvm::BasicBlock::Create(func->getContext(), "Check", func);
	auto updateBB = llvm::BasicBlock::Create(func->getContext(), "Update", func);
	auto outOfStackBB = llvm::BasicBlock::Create(func->getContext(), "OutOfStack", func);

	auto base = &func->getArgumentList().front();
	base->setName("base");
	auto sizePtr = base->getNextNode();
	sizePtr->setName("size.ptr");
	auto min = sizePtr->getNextNode();
	min->setName("min");
	auto max = min->getNextNode();
	max->setName("max");
	auto diff = max->getNextNode();
	diff->setName("diff");
	auto jmpBuf = diff->getNextNode();
	jmpBuf->setName("jmpBuf");

	InsertPointGuard guard{m_builder};
	m_builder.SetInsertPoint(checkBB);
	auto sizeAlignment = getModule()->getDataLayout().getABITypeAlignment(Type::Size);
	auto size = m_builder.CreateAlignedLoad(sizePtr, sizeAlignment, "size");
	auto minSize = m_builder.CreateAdd(size, min, "size.min", false, true);
	auto maxSize = m_builder.CreateAdd(size, max, "size.max", true, true);
	auto minOk = m_builder.CreateICmpSGE(minSize, m_builder.getInt64(0), "ok.min");
	auto maxOk = m_builder.CreateICmpULE(maxSize, m_builder.getInt64(RuntimeManager::stackSizeLimit), "ok.max");
	auto ok = m_builder.CreateAnd(minOk, maxOk, "ok");
	m_builder.CreateCondBr(ok, updateBB, outOfStackBB, Type::expectTrue);

	m_builder.SetInsertPoint(updateBB);
	auto newSize = m_builder.CreateNSWAdd(size, diff, "size.next");
	m_builder.CreateAlignedStore(newSize, sizePtr, sizeAlignment);
	auto sp = m_builder.CreateGEP(base, size, "sp");
	m_builder.CreateRet(sp);

	m_builder.SetInsertPoint(outOfStackBB);
	auto longjmp = llvm::Intrinsic::getDeclaration(getModule(), llvm::Intrinsic::eh_sjlj_longjmp);
	m_builder.CreateCall(longjmp, {jmpBuf});
	m_builder.CreateUnreachable();

	return func;
}

}
}
}
<commit_msg>Update comments.<commit_after>#include "BasicBlock.h"

#include <iostream>

#include "preprocessor/llvm_includes_start.h"
#include <llvm/IR/CFG.h>
#include <llvm/IR/Module.h>
#include <llvm/IR/Function.h>
#include <llvm/IR/Instructions.h>
#include <llvm/IR/IntrinsicInst.h>
#include <llvm/IR/IRBuilder.h>
#include <llvm/Support/raw_os_ostream.h>
#include "preprocessor/llvm_includes_end.h"

#include "RuntimeManager.h"
#include "Type.h"
#include "Utils.h"

namespace dev
{
namespace eth
{
namespace jit
{

BasicBlock::BasicBlock(instr_idx _firstInstrIdx, code_iterator _begin, code_iterator _end, llvm::Function* _mainFunc):
	m_firstInstrIdx{_firstInstrIdx},
	m_begin(_begin),
	m_end(_end),
	m_llvmBB(llvm::BasicBlock::Create(_mainFunc->getContext(), {".", std::to_string(_firstInstrIdx)}, _mainFunc))
{}

LocalStack::LocalStack(IRBuilder& _builder, RuntimeManager& _runtimeManager):
	CompilerHelper(_builder)
{
	// Call stack.prepare. min, max, size args will be filled up in finalize().
	auto undef = llvm::UndefValue::get(Type::Size);
	m_sp = m_builder.CreateCall(getStackPrepareFunc(),
			{_runtimeManager.getStackBase(), _runtimeManager.getStackSize(), undef, undef, undef, _runtimeManager.getJmpBuf()},
			{"sp", m_builder.GetInsertBlock()->getName()});
}

void LocalStack::push(llvm::Value* _value)
{
	assert(_value->getType() == Type::Word);
	m_local.push_back(_value);
	m_maxSize = std::max(m_maxSize, size());
}

llvm::Value* LocalStack::pop()
{
	auto item = get(0);
	assert(!m_local.empty() || !m_input.empty());

	if (m_local.size() > 0)
		m_local.pop_back();
	else
		++m_globalPops;

	m_minSize = std::min(m_minSize, size());
	return item;
}

/// Copies the _index-th element of the local stack and pushes it back on the top.
void LocalStack::dup(size_t _index)
{
	auto val = get(_index);
	push(val);
}

/// Swaps the top element with the _index-th element of the local stack.
void LocalStack::swap(size_t _index)
{
	assert(_index > 0); ///< _index must not be 0.
	auto val = get(_index);
	auto tos = get(0);
	set(_index, tos);
	set(0, val);
}

llvm::Value* LocalStack::get(size_t _index)
{
	if (_index < m_local.size())
		return *(m_local.rbegin() + _index); // count from back

	auto idx = _index - m_local.size() + m_globalPops;
	if (idx >= m_input.size())
		m_input.resize(idx + 1);
	auto& item = m_input[idx];

	if (!item)
	{
		// Fetch an item from global stack
		ssize_t globalIdx = -static_cast<ssize_t>(idx) - 1;
		auto slot = m_builder.CreateConstGEP1_64(m_sp, globalIdx);
		item = m_builder.CreateAlignedLoad(slot, 16); // TODO: Handle malloc alignment. Also for 32-bit systems.
		m_minSize = std::min(m_minSize, globalIdx); 	// remember required stack size
	}

	return item;
}

void LocalStack::set(size_t _index, llvm::Value* _word)
{
	if (_index < m_local.size())
	{
		*(m_local.rbegin() + _index) = _word;
		return;
	}

	auto idx = _index - m_local.size() + m_globalPops;
	assert(idx < m_input.size());
	m_input[idx] = _word;
}

void LocalStack::finalize()
{
	m_sp->setArgOperand(2, m_builder.getInt64(minSize()));
	m_sp->setArgOperand(3, m_builder.getInt64(maxSize()));
	m_sp->setArgOperand(4, m_builder.getInt64(size()));

	if (auto term = m_builder.GetInsertBlock()->getTerminator())
		m_builder.SetInsertPoint(term); // Insert before terminator

	auto inputIt = m_input.rbegin();
	auto localIt = m_local.begin();
	for (auto globalIdx = -static_cast<ssize_t>(m_input.size()); globalIdx < size(); ++globalIdx)
	{
		llvm::Value* item = nullptr;
		if (globalIdx < -m_globalPops)
		{
			item = *inputIt++;	// update input items (might contain original value)
			if (!item)			// some items are skipped
				continue;
		}
		else
			item = *localIt++;	// store new items

		auto slot = m_builder.CreateConstGEP1_64(m_sp, globalIdx);
		m_builder.CreateAlignedStore(item, slot, 16); // TODO: Handle malloc alignment. Also for 32-bit systems.
	}
}

llvm::Function* LocalStack::getStackPrepareFunc()
{
	static const auto c_funcName = "stack.prepare";
	if (auto func = getModule()->getFunction(c_funcName))
		return func;

	llvm::Type* argsTys[] = {Type::WordPtr, Type::Size->getPointerTo(), Type::Size, Type::Size, Type::Size, Type::BytePtr};
	auto func = llvm::Function::Create(llvm::FunctionType::get(Type::WordPtr, argsTys, false), llvm::Function::PrivateLinkage, c_funcName, getModule());
	func->setDoesNotThrow();
	func->setDoesNotAccessMemory(1);
	func->setDoesNotAlias(2);
	func->setDoesNotCapture(2);

	auto checkBB = llvm::BasicBlock::Create(func->getContext(), "Check", func);
	auto updateBB = llvm::BasicBlock::Create(func->getContext(), "Update", func);
	auto outOfStackBB = llvm::BasicBlock::Create(func->getContext(), "OutOfStack", func);

	auto base = &func->getArgumentList().front();
	base->setName("base");
	auto sizePtr = base->getNextNode();
	sizePtr->setName("size.ptr");
	auto min = sizePtr->getNextNode();
	min->setName("min");
	auto max = min->getNextNode();
	max->setName("max");
	auto diff = max->getNextNode();
	diff->setName("diff");
	auto jmpBuf = diff->getNextNode();
	jmpBuf->setName("jmpBuf");

	InsertPointGuard guard{m_builder};
	m_builder.SetInsertPoint(checkBB);
	auto sizeAlignment = getModule()->getDataLayout().getABITypeAlignment(Type::Size);
	auto size = m_builder.CreateAlignedLoad(sizePtr, sizeAlignment, "size");
	auto minSize = m_builder.CreateAdd(size, min, "size.min", false, true);
	auto maxSize = m_builder.CreateAdd(size, max, "size.max", true, true);
	auto minOk = m_builder.CreateICmpSGE(minSize, m_builder.getInt64(0), "ok.min");
	auto maxOk = m_builder.CreateICmpULE(maxSize, m_builder.getInt64(RuntimeManager::stackSizeLimit), "ok.max");
	auto ok = m_builder.CreateAnd(minOk, maxOk, "ok");
	m_builder.CreateCondBr(ok, updateBB, outOfStackBB, Type::expectTrue);

	m_builder.SetInsertPoint(updateBB);
	auto newSize = m_builder.CreateNSWAdd(size, diff, "size.next");
	m_builder.CreateAlignedStore(newSize, sizePtr, sizeAlignment);
	auto sp = m_builder.CreateGEP(base, size, "sp");
	m_builder.CreateRet(sp);

	m_builder.SetInsertPoint(outOfStackBB);
	auto longjmp = llvm::Intrinsic::getDeclaration(getModule(), llvm::Intrinsic::eh_sjlj_longjmp);
	m_builder.CreateCall(longjmp, {jmpBuf});
	m_builder.CreateUnreachable();

	return func;
}

}
}
}
<|endoftext|>


<commit_before>namespace factor
{

/* The compiled code heap is structured into blocks. */
struct code_block
{
	// header format (bits indexed with least significant as zero):
	// bit   0  : free?
	// bits  1-2: type (as a code_block_type)
	// if not free:
	//   bits  3-23: code size / 8
	//   bits 24-31: stack frame size / 16
	// if free:
	//   bits  3-end: code size / 8
	cell header;
	cell owner; /* tagged pointer to word, quotation or f */
	cell parameters; /* tagged pointer to array or f */
	cell relocation; /* tagged pointer to byte-array or f */

	bool free_p() const
	{
		return (header & 1) == 1;
	}

	code_block_type type() const
	{
		return (code_block_type)((header >> 1) & 0x3);
	}

	void set_type(code_block_type type)
	{
		header = ((header & ~0x7) | (type << 1));
	}

	bool pic_p() const
	{
		return type() == code_block_pic;
	}

	bool optimized_p() const
	{
		return type() == code_block_optimized;
	}

	cell size() const
	{
		cell size;
		if (free_p())
			size = header & ~7;
		else
			size = header & 0xFFFFF8;
		FACTOR_ASSERT(size > 0);
		return size;
	}

	cell stack_frame_size() const
	{
		if (free_p())
			return 0;
		else
			return (header >> 20) & 0xFF0;
	}

	void set_stack_frame_size(cell frame_size)
	{
		FACTOR_ASSERT(size() < 0xFFFFFF);
		FACTOR_ASSERT(!free_p());
		FACTOR_ASSERT(frame_size % 16 == 0);
		FACTOR_ASSERT(frame_size <= 0xFF0);
		header = (header & 0xFFFFFF) | (frame_size << 20);
	}

	template<typename Fixup> cell size(Fixup fixup) const
	{
		return size();
	}

	void *entry_point() const
	{
		return (void *)(this + 1);
	}

	/* GC info is stored at the end of the block */
	gc_info *block_gc_info() const
	{
		return (gc_info *)((u8 *)this + size() - sizeof(gc_info));
	}

	void flush_icache()
	{
		factor::flush_icache((cell)this,size());
	}

	template<typename Iterator> void each_instruction_operand(Iterator &iter)
	{
		if(to_boolean(relocation))
		{
			byte_array *rels = (byte_array *)UNTAG(relocation);

			cell index = 0;
			cell length = (rels->capacity >> TAG_BITS) / sizeof(relocation_entry);

			for(cell i = 0; i < length; i++)
			{
				relocation_entry rel = rels->data<relocation_entry>()[i];
				iter(instruction_operand(rel,this,index));
				index += rel.number_of_parameters();
			}
		}
	}
};

VM_C_API void undefined_symbol(void);

inline code_block *word::code() const {
	FACTOR_ASSERT(entry_point != NULL);
	return (code_block*)entry_point - 1;
}

inline code_block *quotation::code() const {
	FACTOR_ASSERT(entry_point != NULL);
	return (code_block*)entry_point - 1;
}

}

<commit_msg>vm: method to calculate frame size for address If we're before the prolog or or in a leaf procedure, the stack frame is really a leaf frame created by the signal handler, with a known fixed size, instead of the real stack frame (if any) with a different size.<commit_after>namespace factor
{

/* The compiled code heap is structured into blocks. */
struct code_block
{
	// header format (bits indexed with least significant as zero):
	// bit   0  : free?
	// bits  1-2: type (as a code_block_type)
	// if not free:
	//   bits  3-23: code size / 8
	//   bits 24-31: stack frame size / 16
	// if free:
	//   bits  3-end: code size / 8
	cell header;
	cell owner; /* tagged pointer to word, quotation or f */
	cell parameters; /* tagged pointer to array or f */
	cell relocation; /* tagged pointer to byte-array or f */

	bool free_p() const
	{
		return (header & 1) == 1;
	}

	code_block_type type() const
	{
		return (code_block_type)((header >> 1) & 0x3);
	}

	void set_type(code_block_type type)
	{
		header = ((header & ~0x7) | (type << 1));
	}

	bool pic_p() const
	{
		return type() == code_block_pic;
	}

	bool optimized_p() const
	{
		return type() == code_block_optimized;
	}

	cell size() const
	{
		cell size;
		if (free_p())
			size = header & ~7;
		else
			size = header & 0xFFFFF8;
		FACTOR_ASSERT(size > 0);
		return size;
	}

	cell stack_frame_size() const
	{
		if (free_p())
			return 0;
		else
			return (header >> 20) & 0xFF0;
	}

	cell stack_frame_size_for_address(cell addr) const
	{
		cell natural_frame_size = stack_frame_size();
		/* The first instruction in a code block is the prolog safepoint,
		and a leaf procedure code block will record a frame size of zero.
		If we're seeing a stack frame in either of these cases, it's a
		fake "leaf frame" set up by the signal handler. */
		if (natural_frame_size == 0 || (void*)addr == entry_point())
			return LEAF_FRAME_SIZE;
		else
			return natural_frame_size;
	}

	void set_stack_frame_size(cell frame_size)
	{
		FACTOR_ASSERT(size() < 0xFFFFFF);
		FACTOR_ASSERT(!free_p());
		FACTOR_ASSERT(frame_size % 16 == 0);
		FACTOR_ASSERT(frame_size <= 0xFF0);
		header = (header & 0xFFFFFF) | (frame_size << 20);
	}

	template<typename Fixup> cell size(Fixup fixup) const
	{
		return size();
	}

	void *entry_point() const
	{
		return (void *)(this + 1);
	}

	/* GC info is stored at the end of the block */
	gc_info *block_gc_info() const
	{
		return (gc_info *)((u8 *)this + size() - sizeof(gc_info));
	}

	void flush_icache()
	{
		factor::flush_icache((cell)this,size());
	}

	template<typename Iterator> void each_instruction_operand(Iterator &iter)
	{
		if(to_boolean(relocation))
		{
			byte_array *rels = (byte_array *)UNTAG(relocation);

			cell index = 0;
			cell length = (rels->capacity >> TAG_BITS) / sizeof(relocation_entry);

			for(cell i = 0; i < length; i++)
			{
				relocation_entry rel = rels->data<relocation_entry>()[i];
				iter(instruction_operand(rel,this,index));
				index += rel.number_of_parameters();
			}
		}
	}
};

VM_C_API void undefined_symbol(void);

inline code_block *word::code() const {
	FACTOR_ASSERT(entry_point != NULL);
	return (code_block*)entry_point - 1;
}

inline code_block *quotation::code() const {
	FACTOR_ASSERT(entry_point != NULL);
	return (code_block*)entry_point - 1;
}

}

<|endoftext|>