<commit_before>//
// Created by Sam on 9/25/2017.
//

#include <utility>
#include <iostream>

#include "../../../include/Game/Core/Card.h"
#include "../../../include/Game/Core/Player.h"
#include "../../../include/Game/Core/Game.h"
#include "../../../include/Game/Derived/Card/Creature.h"
#include "../../../include/Game/Derived/Containers/Deck.h"
#include "../../../include/Game/Derived/Containers/Hand.h"
#include "../../../include/Game/Derived/Containers/CreatureZone.h"
#include "../../../include/Game/Derived/Event/PlayerEvents/PlayCardEvent.h"
#include "../../../include/Network/Client.h"
#include "../../../include/Network/Derived/ChatMessage.h"
#include "../../../include/Network/Derived/PlayCardMessage.h"
#include "../../../include/Network/Derived/FightPlayerMessage.h"

void Player::draw()
{
    hand->addCard(board->deck->draw());
}

void Player::draw(int count)
{
    for (int i = 0; i < count; i++)
    {
        draw();
    }
}

void Player::startTurn()
{
    refillMana();
    refreshCreatures();
    draw();
}

void Player::refillMana()
{
    availableMana = totalMana;
}

void Player::refreshCreatures()
{
    for (const auto& card : board->creatures->cards)
    {
        const auto& creature = std::dynamic_pointer_cast<Creature>(card);
        creature->availableAttacks = creature->attacks;
        creature->usedAttacks = 0;
    }
}

void Player::playCard(const json &rawJSON)
{
    if (shared_from_this() == game->activePlayer)
    {
        PlayCardMessage moveCardMessage(rawJSON);
        auto card = hand->findCard(moveCardMessage.cardTag);

        if (availableMana.canPay(card->mana))
        {
            availableMana.payMana(card->mana);
            board->playCard(card);
            hand->removeCard(card);

            if (totalMana.getTotalCount() <= 15 && totalMana.withinIndividualLimit())
            {
                totalMana.increaseMana(card->mana);
            }

            game->cardOrder.push_back(card);

            PlayCardEvent playCardEvent(game, card);
            game->eventHandler(std::make_shared<PlayCardEvent>(playCardEvent));
        }
    }
}

void Player::endTurn(const json &rawJSON)
{
    game->changeTurn();
}

void Player::sendChatMessage(const json &rawJSON)
{
    // Format chat message with the sender name before broadcasting it to all players
    ChatMessage chatMessage(rawJSON);
    chatMessage.rawJSON[Message::DATA_KEY]["text"] = name + ": " + chatMessage.text;

    game->writePlayers(chatMessage.getJSON());
}

void Player::fightPlayer(const json &rawJSON)
{
    FightPlayerMessage fightPlayerMessage(rawJSON);
    auto player = game->findPlayer(fightPlayerMessage.attackingPlayerTag);
    auto card = board->creatures->findCard(fightPlayerMessage.cardTag);
    auto creature = std::dynamic_pointer_cast<Creature>(card);

    // You can't attack yourself!
    if (player == shared_from_this())
    {
        throw std::runtime_error("You cannot attack yourself");
    }

    creature->attack(player);

    if (player->health <= 0)
    {
        // End the game
    }
}

json Player::getState()
{
    json playerJSON;

    playerJSON["playerTag"] = tag;
    playerJSON["hand"] = hand->getJSON();
    playerJSON["health"] = health;
    playerJSON["deckCount"] = board->deck->count();
    playerJSON["mana"] = getManaJSON();
    playerJSON["board"] = board->getJSON();

    return playerJSON;
}

json Player::getOpponentState()
{
    json opponentJSON;

    opponentJSON["playerTag"] = tag;
    opponentJSON["name"] = name;
    opponentJSON["health"] = health;
    opponentJSON["handCount"] = hand->count();
    opponentJSON["deckCount"] = board->deck->count();
    opponentJSON["mana"] = getManaJSON();
    opponentJSON["board"] = board->getJSON();

    return opponentJSON;
}

json Player::getManaJSON()
{
    json manaJSON;
    manaJSON["available"] = availableMana.getJSON();
    manaJSON["total"] = totalMana.getJSON();

    return manaJSON;
}

Player::Player(std::shared_ptr<Client> client)
        : client(client),
          name(client->name),
          availableMana(1,1,1,1,1,1),
          totalMana(1,1,1,1,1,1),
          board(std::make_shared<Board>()),
          hand(std::make_shared<Hand>()),
          health(30)
{
}

Player::~Player()
= default;
<commit_msg>Pass the new PlayerAttackedEvent to the games eventHandler function<commit_after>//
// Created by Sam on 9/25/2017.
//

#include <utility>
#include <iostream>

#include "../../../include/Game/Core/Card.h"
#include "../../../include/Game/Core/Player.h"
#include "../../../include/Game/Core/Game.h"
#include "../../../include/Game/Derived/Card/Creature.h"
#include "../../../include/Game/Derived/Containers/Deck.h"
#include "../../../include/Game/Derived/Containers/Hand.h"
#include "../../../include/Game/Derived/Containers/CreatureZone.h"
#include "../../../include/Game/Derived/Event/PlayerEvents/PlayCardEvent.h"
#include "../../../include/Network/Client.h"
#include "../../../include/Network/Derived/ChatMessage.h"
#include "../../../include/Network/Derived/PlayCardMessage.h"
#include "../../../include/Network/Derived/FightPlayerMessage.h"
#include "../../../include/Game/Derived/Event/PlayerEvents/PlayerAttackedEvent.h"

void Player::draw()
{
    hand->addCard(board->deck->draw());
}

void Player::draw(int count)
{
    for (int i = 0; i < count; i++)
    {
        draw();
    }
}

void Player::startTurn()
{
    refillMana();
    refreshCreatures();
    draw();
}

void Player::refillMana()
{
    availableMana = totalMana;
}

void Player::refreshCreatures()
{
    for (const auto& card : board->creatures->cards)
    {
        const auto& creature = std::dynamic_pointer_cast<Creature>(card);
        creature->availableAttacks = creature->attacks;
        creature->usedAttacks = 0;
    }
}

void Player::playCard(const json &rawJSON)
{
    if (shared_from_this() == game->activePlayer)
    {
        PlayCardMessage moveCardMessage(rawJSON);
        auto card = hand->findCard(moveCardMessage.cardTag);

        if (availableMana.canPay(card->mana))
        {
            availableMana.payMana(card->mana);
            board->playCard(card);
            hand->removeCard(card);

            if (totalMana.getTotalCount() <= 15 && totalMana.withinIndividualLimit())
            {
                totalMana.increaseMana(card->mana);
            }

            game->cardOrder.push_back(card);

            PlayCardEvent playCardEvent(game, card);
            game->eventHandler(std::make_shared<PlayCardEvent>(playCardEvent));
        }
    }
}

void Player::endTurn(const json &rawJSON)
{
    game->changeTurn();
}

void Player::sendChatMessage(const json &rawJSON)
{
    // Format chat message with the sender name before broadcasting it to all players
    ChatMessage chatMessage(rawJSON);
    chatMessage.rawJSON[Message::DATA_KEY]["text"] = name + ": " + chatMessage.text;

    game->writePlayers(chatMessage.getJSON());
}

void Player::fightPlayer(const json &rawJSON)
{
    FightPlayerMessage fightPlayerMessage(rawJSON);
    auto player = game->findPlayer(fightPlayerMessage.attackingPlayerTag);
    auto card = board->creatures->findCard(fightPlayerMessage.cardTag);
    auto creature = std::dynamic_pointer_cast<Creature>(card);

    // You can't attack yourself!
    if (player == shared_from_this())
    {
        throw std::runtime_error("You cannot attack yourself");
    }

    creature->attack(player);

    PlayerAttackedEvent playerAttackedEvent(game, card, player);
    game->eventHandler(std::make_shared<PlayerAttackedEvent>(playerAttackedEvent));

    if (player->health <= 0)
    {
        // End the game
    }
}

json Player::getState()
{
    json playerJSON;

    playerJSON["playerTag"] = tag;
    playerJSON["hand"] = hand->getJSON();
    playerJSON["health"] = health;
    playerJSON["deckCount"] = board->deck->count();
    playerJSON["mana"] = getManaJSON();
    playerJSON["board"] = board->getJSON();

    return playerJSON;
}

json Player::getOpponentState()
{
    json opponentJSON;

    opponentJSON["playerTag"] = tag;
    opponentJSON["name"] = name;
    opponentJSON["health"] = health;
    opponentJSON["handCount"] = hand->count();
    opponentJSON["deckCount"] = board->deck->count();
    opponentJSON["mana"] = getManaJSON();
    opponentJSON["board"] = board->getJSON();

    return opponentJSON;
}

json Player::getManaJSON()
{
    json manaJSON;
    manaJSON["available"] = availableMana.getJSON();
    manaJSON["total"] = totalMana.getJSON();

    return manaJSON;
}

Player::Player(std::shared_ptr<Client> client)
        : client(client),
          name(client->name),
          availableMana(1,1,1,1,1,1),
          totalMana(1,1,1,1,1,1),
          board(std::make_shared<Board>()),
          hand(std::make_shared<Hand>()),
          health(30)
{
}

Player::~Player()
= default;
<|endoftext|>


<commit_before>/* Copyright (c) 2016 PaddlePaddle Authors. All Rights Reserve.

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 "paddle/operators/feed_op.h"

namespace paddle {
namespace operators {

class FeedOp : public framework::OperatorWithKernel {
 public:
  using framework::OperatorWithKernel::OperatorWithKernel;

 protected:
  void InferShape(framework::InferShapeContext* ctx) const override {
    PADDLE_ENFORCE(ctx->HasOutput("Out"), "Output should be not null.");
    int col = ctx->Attrs().Get<int>("col");
    framework::Variable* g_feed_variable =
        framework::GetGlobalScope()->FindVar("feed_value");

    const auto& tensors =
        g_feed_variable->Get<std::vector<framework::Tensor>>();

    PADDLE_ENFORCE_GT(tensors.size(), static_cast<size_t>(col));
    auto in_dim = tensors[col].dims();
    ctx->SetOutputDim("Out", in_dim);
    // TODO(qijun): need to handle LodTensor later
  }

  framework::DataType IndicateDataType(
      const framework::ExecutionContext& ctx) const override {
    return static_cast<framework::DataType>(Attr<int>("data_type"));
  }
};

class FeedOpMaker : public framework::OpProtoAndCheckerMaker {
 public:
  FeedOpMaker(framework::OpProto* proto, framework::OpAttrChecker* op_checker)
      : OpProtoAndCheckerMaker(proto, op_checker) {
    AddAttr<int>("data_type", "output data type")
        .SetDefault(framework::DataType::FP32);
    AddAttr<int>("col", "The col in global feed variable").SetDefault(0);
    AddAttr<std::vector<int>>("dims", "The dimension of feed tensor.");
    AddOutput("Out", "The output of feed op.");
    AddComment(R"DOC(Feed data from global feed variable)DOC");
  }
};

}  // namespace operators
}  // namespace paddle

namespace ops = paddle::operators;
REGISTER_OP_WITHOUT_GRADIENT(feed, ops::FeedOp, ops::FeedOpMaker);
REGISTER_OP_CPU_KERNEL(feed, ops::FeedKernel<float>);
<commit_msg>infer feed operator output variable shape with dims attribute<commit_after>/* Copyright (c) 2016 PaddlePaddle Authors. All Rights Reserve.

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 "paddle/operators/feed_op.h"

namespace paddle {
namespace operators {

class FeedOp : public framework::OperatorWithKernel {
 public:
  using framework::OperatorWithKernel::OperatorWithKernel;

 protected:
  void InferShape(framework::InferShapeContext* ctx) const override {
    PADDLE_ENFORCE(ctx->HasOutput("Out"), "Output should be not null.");
    int col = ctx->Attrs().Get<int>("col");
    framework::Variable* g_feed_variable =
        framework::GetGlobalScope()->FindVar("feed_value");

    const auto& tensors =
        g_feed_variable->Get<std::vector<framework::Tensor>>();

    PADDLE_ENFORCE_GT(tensors.size(), static_cast<size_t>(col));

    auto& shape = ctx->Attrs().Get<std::vector<int>>("dims");
    std::vector<int64_t> shape_int64(shape.size(), 0);
    std::transform(shape.begin(), shape.end(), shape_int64.begin(),
                   [](int a) { return static_cast<int64_t>(a); });
    ctx->SetOutputDim("Out", framework::make_ddim(shape_int64));
    // TODO(qijun): need to handle LodTensor later
  }

  framework::DataType IndicateDataType(
      const framework::ExecutionContext& ctx) const override {
    return static_cast<framework::DataType>(Attr<int>("data_type"));
  }
};

class FeedOpMaker : public framework::OpProtoAndCheckerMaker {
 public:
  FeedOpMaker(framework::OpProto* proto, framework::OpAttrChecker* op_checker)
      : OpProtoAndCheckerMaker(proto, op_checker) {
    AddAttr<int>("data_type", "output data type")
        .SetDefault(framework::DataType::FP32);
    AddAttr<int>("col", "The col in global feed variable").SetDefault(0);
    AddAttr<std::vector<int>>("dims", "The dimension of feed tensor.");
    AddOutput("Out", "The output of feed op.");
    AddComment(R"DOC(Feed data from global feed variable)DOC");
  }
};

}  // namespace operators
}  // namespace paddle

namespace ops = paddle::operators;
REGISTER_OP_WITHOUT_GRADIENT(feed, ops::FeedOp, ops::FeedOpMaker);
REGISTER_OP_CPU_KERNEL(feed, ops::FeedKernel<float>);
<|endoftext|>


<commit_before>#pragma once

#include <QMap>
#include <QMutex>
#include <QMutexLocker>

#include <functional>
#include <map>
#include <memory>

namespace chatterino {
namespace util {

template <typename TKey, typename TValue>
class ConcurrentMap
{
public:
    ConcurrentMap() = default;

    bool tryGet(const TKey &name, TValue &value) const
    {
        QMutexLocker lock(&this->mutex);

        auto a = this->data.find(name);
        if (a == this->data.end()) {
            return false;
        }

        value = a.value();

        return true;
    }

    TValue getOrAdd(const TKey &name, std::function<TValue()> addLambda)
    {
        QMutexLocker lock(&this->mutex);

        auto a = this->data.find(name);
        if (a == this->data.end()) {
            TValue value = addLambda();
            this->data.insert(name, value);
            return value;
        }

        return a.value();
    }

    TValue &operator[](const TKey &name)
    {
        QMutexLocker lock(&this->mutex);

        return this->data[name];
    }

    void clear()
    {
        QMutexLocker lock(&this->mutex);

        this->data.clear();
    }

    void insert(const TKey &name, const TValue &value)
    {
        QMutexLocker lock(&this->mutex);

        this->data.insert(name, value);
    }

    void each(std::function<void(const TKey &name, const TValue &value)> func) const
    {
        QMutexLocker lock(&this->mutex);

        QMapIterator<TKey, TValue> it(this->data);

        while (it.hasNext()) {
            it.next();
            func(it.key(), it.value());
        }
    }

private:
    mutable QMutex mutex;
    QMap<TKey, TValue> data;
};

}  // namespace util
}  // namespace chatterino
<commit_msg>Add a mutable each function<commit_after>#pragma once

#include <QMap>
#include <QMutex>
#include <QMutexLocker>

#include <functional>
#include <map>
#include <memory>

namespace chatterino {
namespace util {

template <typename TKey, typename TValue>
class ConcurrentMap
{
public:
    ConcurrentMap() = default;

    bool tryGet(const TKey &name, TValue &value) const
    {
        QMutexLocker lock(&this->mutex);

        auto a = this->data.find(name);
        if (a == this->data.end()) {
            return false;
        }

        value = a.value();

        return true;
    }

    TValue getOrAdd(const TKey &name, std::function<TValue()> addLambda)
    {
        QMutexLocker lock(&this->mutex);

        auto a = this->data.find(name);
        if (a == this->data.end()) {
            TValue value = addLambda();
            this->data.insert(name, value);
            return value;
        }

        return a.value();
    }

    TValue &operator[](const TKey &name)
    {
        QMutexLocker lock(&this->mutex);

        return this->data[name];
    }

    void clear()
    {
        QMutexLocker lock(&this->mutex);

        this->data.clear();
    }

    void insert(const TKey &name, const TValue &value)
    {
        QMutexLocker lock(&this->mutex);

        this->data.insert(name, value);
    }

    void each(std::function<void(const TKey &name, const TValue &value)> func) const
    {
        QMutexLocker lock(&this->mutex);

        QMapIterator<TKey, TValue> it(this->data);

        while (it.hasNext()) {
            it.next();
            func(it.key(), it.value());
        }
    }

    void each(std::function<void(const TKey &name, TValue &value)> func)
    {
        QMutexLocker lock(&this->mutex);

        QMutableMapIterator<TKey, TValue> it(this->data);

        while (it.hasNext()) {
            it.next();
            func(it.key(), it.value());
        }
    }

private:
    mutable QMutex mutex;
    QMap<TKey, TValue> data;
};

}  // namespace util
}  // namespace chatterino
<|endoftext|>


<commit_before>/****************************************************************************
**
** Copyright (C) 2013 Jolla Ltd.
** Contact: Petri M. Gerdt <petri.gerdt@jollamobile.com>
**
****************************************************************************/

#include "declarativetabmodel.h"

#include "dbmanager.h"
#include <QFile>
#ifdef DEBUG_LOGS
#include <QDebug>
#endif

DeclarativeTabModel::DeclarativeTabModel(QObject *parent) :
    QAbstractListModel(parent), m_currentTabIndex(-1)
{
    connect(DBManager::instance(), SIGNAL(tabsAvailable(QList<Tab>)),
            this, SLOT(tabsAvailable(QList<Tab>)));

    connect(DBManager::instance(), SIGNAL(tabChanged(Tab)),
            this, SLOT(tabChanged(Tab)));

    connect(DBManager::instance(), SIGNAL(thumbPathChanged(QString,QString,int)),
            this, SLOT(updateThumbPath(QString,QString,int)));
    connect(DBManager::instance(), SIGNAL(titleChanged(QString,QString)),
            this, SLOT(updateTitle(QString,QString)));
}

QHash<int, QByteArray> DeclarativeTabModel::roleNames() const
{
    QHash<int, QByteArray> roles;
    roles[ThumbPathRole] = "thumbnailPath";
    roles[TitleRole] = "title";
    roles[UrlRole] = "url";
    roles[TabIdRole] = "tabId";
    return roles;
}

void DeclarativeTabModel::addTab(const QString& url, bool foreground) {
    int tabId = DBManager::instance()->createTab();
    Tab tab(tabId, Link(0, url, "", ""), 0, 0);
    beginInsertRows(QModelIndex(), rowCount(), rowCount());
    m_tabs.append(tab);
    endInsertRows();
    emit countChanged();
    if (foreground) {
        setCurrentTabIndex(m_tabs.count() - 1);
    }
}

int DeclarativeTabModel::currentTabId() const
{
    if (!m_tabs.isEmpty() && m_currentTabIndex >= 0 && m_currentTabIndex < m_tabs.count()) {
        return m_tabs.at(m_currentTabIndex).tabId();
    }
    return 0;
}

void DeclarativeTabModel::remove(const int index) {
    if (!m_tabs.isEmpty() && index >= 0 && index < m_tabs.count()) {
        beginRemoveRows(QModelIndex(), index, index);
        int tabId = m_tabs.at(index).tabId();
        removeTab(index);
        endRemoveRows();
        DBManager::instance()->removeTab(tabId);
        emit countChanged();

        if (m_tabs.empty()) {
            return;
        }

        int newIndex = -1;
        // handle removing indexes: 0 .. currentTabIndex - 1
        if (index < m_currentTabIndex) {
            // Keep current tab as active
            newIndex = --m_currentTabIndex;
        }

        // handle removing indexes: m_currentTabIndex .. new count
        else if (index < m_tabs.count()) {
            newIndex = index;
        }

        // handle removing indexes: close last index
        else {
            newIndex = m_tabs.count() - 1;
        }

        // If bigger than current tab index gets closed, ignore it.
        if (newIndex >= 0 && newIndex <= m_currentTabIndex) {
#ifdef DEBUG_LOGS
            qDebug() << "DeclarativeTabModel::remove index: " << index << "new index: " << newIndex << "currentTabIndex: " << m_currentTabIndex;
#endif
            m_currentTabIndex = newIndex;
            DBManager::instance()->saveSetting("currentTab", QString("%1").arg(m_currentTabIndex));
            emit currentTabChanged();
        }
    }
}

void DeclarativeTabModel::clear()
{
    if (m_tabs.count() == 0)
        return;

    beginResetModel();
    for (int i = m_tabs.count() - 1; i >= 0; --i) {
        removeTab(i);
    }
    endResetModel();

    DBManager::instance()->removeAllTabs();
    emit countChanged();
    m_currentTabIndex = -1;
    DBManager::instance()->saveSetting("currentTab", QString("%1").arg(m_currentTabIndex));
}

bool DeclarativeTabModel::activateTab(const QString& url)
{
    if (m_currentTabIndex >= 0 && m_tabs.at(m_currentTabIndex).currentLink().url() == url) {
        return true;
    }
    for (int i = 0; i < m_tabs.size(); i++) {
        if (m_tabs.at(i).currentLink().url() == url) {
            setCurrentTabIndex(i);
            return true;
        }
    }
    return false;
}

int DeclarativeTabModel::rowCount(const QModelIndex & parent) const {
    Q_UNUSED(parent);
    return m_tabs.count();
}

QVariant DeclarativeTabModel::data(const QModelIndex & index, int role) const {
    if (index.row() < 0 || index.row() > m_tabs.count())
        return QVariant();

    const Tab tab = m_tabs[index.row()];
    if (role == ThumbPathRole) {
        return tab.currentLink().thumbPath();
    } else if (role == TitleRole) {
        return tab.currentLink().title();
    } else if (role == UrlRole) {
        return tab.currentLink().url();
    } else if (role == TabIdRole) {
        return tab.tabId();
    }
    return QVariant();
}

void DeclarativeTabModel::componentComplete()
{
}

void DeclarativeTabModel::setCurrentTabIndex(const int index)
{
    if (index >= 0 && index < m_tabs.count() && index != m_currentTabIndex) {
        m_currentTabIndex = index;
        emit currentTabChanged();
        DBManager::instance()->saveSetting("currentTab", QString("%1").arg(m_currentTabIndex));
    }
}

int DeclarativeTabModel::currentTabIndex() const
{
    return m_currentTabIndex;
}

void DeclarativeTabModel::classBegin()
{
    DBManager::instance()->getAllTabs();
}

void DeclarativeTabModel::tabsAvailable(QList<Tab> tabs)
{
    beginResetModel();
    m_tabs.clear();
    m_tabs = tabs;
    endResetModel();

    if (m_tabs.count() > 0) {
        emit countChanged();
    }

    QString currentTabIndexSetting = DBManager::instance()->getSetting("currentTab");
    bool ok;
    int currentTabIndex = currentTabIndexSetting.toInt(&ok);
    if (ok && currentTabIndex >= 0 && currentTabIndex < m_tabs.count()) {
        m_currentTabIndex = currentTabIndex;
        emit currentTabChanged();
    } else {
        if (m_tabs.count() > 1) {
            setCurrentTabIndex(0);
        }
    }
}

void DeclarativeTabModel::tabChanged(Tab tab)
{
    int i = m_tabs.indexOf(tab); // match based on tab_id
    if (i > -1) {
        QVector<int> roles;
        Tab oldTab = m_tabs[i];
        if (oldTab.currentLink().url() != tab.currentLink().url()) {
            roles << UrlRole;
        }
        if (oldTab.currentLink().title() != tab.currentLink().title()) {
            roles << TitleRole;
        }
        if (oldTab.currentLink().thumbPath() != tab.currentLink().thumbPath()) {
            roles << ThumbPathRole;
        }
        m_tabs[i] = tab;
        QModelIndex start = index(i, 0);
        QModelIndex end = index(i, 0);
        emit dataChanged(start, end, roles);
    }
}

void DeclarativeTabModel::removeTab(int index)
{
    // Both clear and remove(index) handles bounds checking.
    QString thumbPath = m_tabs.at(index).currentLink().thumbPath();
    m_tabs.removeAt(index);

    QFile f(thumbPath);
    if (f.exists()) {
        f.remove();
    }
}

void DeclarativeTabModel::updateThumbPath(QString url, QString path, int tabId)
{
    Q_UNUSED(url)
    QVector<int> roles;
    roles << ThumbPathRole;
    for (int i = 0; i < m_tabs.count(); i++) {
        if (m_tabs.at(i).tabId() == tabId) {
            Link link = m_tabs.at(i).currentLink();
            link.setThumbPath(path);
            m_tabs[i].setCurrentLink(link);
            QModelIndex start = index(i, 0);
            QModelIndex end = index(i, 0);
            emit dataChanged(start, end, roles);
        }
    }
}

void DeclarativeTabModel::updateTitle(QString url, QString title)
{
    QVector<int> roles;
    roles << TitleRole;
    for (int i = 0; i < m_tabs.count(); i++) {
        if (m_tabs.at(i).currentLink().url() == url) {
            if (m_tabs.at(i).currentLink().title() != title) {
                Link tmp = m_tabs[i].currentLink();
                tmp.setTitle(title);
                m_tabs[i].setCurrentLink(tmp);
                QModelIndex start = index(i, 0);
                QModelIndex end = index(i, 0);
                emit dataChanged(start, end, roles);
            }
        }
    }
}
<commit_msg>Reset currentTabIndex when last tab gets closed.<commit_after>/****************************************************************************
**
** Copyright (C) 2013 Jolla Ltd.
** Contact: Petri M. Gerdt <petri.gerdt@jollamobile.com>
**
****************************************************************************/

#include "declarativetabmodel.h"

#include "dbmanager.h"
#include <QFile>
#ifdef DEBUG_LOGS
#include <QDebug>
#endif

DeclarativeTabModel::DeclarativeTabModel(QObject *parent) :
    QAbstractListModel(parent), m_currentTabIndex(-1)
{
    connect(DBManager::instance(), SIGNAL(tabsAvailable(QList<Tab>)),
            this, SLOT(tabsAvailable(QList<Tab>)));

    connect(DBManager::instance(), SIGNAL(tabChanged(Tab)),
            this, SLOT(tabChanged(Tab)));

    connect(DBManager::instance(), SIGNAL(thumbPathChanged(QString,QString,int)),
            this, SLOT(updateThumbPath(QString,QString,int)));
    connect(DBManager::instance(), SIGNAL(titleChanged(QString,QString)),
            this, SLOT(updateTitle(QString,QString)));
}

QHash<int, QByteArray> DeclarativeTabModel::roleNames() const
{
    QHash<int, QByteArray> roles;
    roles[ThumbPathRole] = "thumbnailPath";
    roles[TitleRole] = "title";
    roles[UrlRole] = "url";
    roles[TabIdRole] = "tabId";
    return roles;
}

void DeclarativeTabModel::addTab(const QString& url, bool foreground) {
    int tabId = DBManager::instance()->createTab();
    Tab tab(tabId, Link(0, url, "", ""), 0, 0);
    beginInsertRows(QModelIndex(), rowCount(), rowCount());
    m_tabs.append(tab);
    endInsertRows();
    emit countChanged();
    if (foreground) {
        setCurrentTabIndex(m_tabs.count() - 1);
    }
}

int DeclarativeTabModel::currentTabId() const
{
    if (!m_tabs.isEmpty() && m_currentTabIndex >= 0 && m_currentTabIndex < m_tabs.count()) {
        return m_tabs.at(m_currentTabIndex).tabId();
    }
    return 0;
}

void DeclarativeTabModel::remove(const int index) {
    if (!m_tabs.isEmpty() && index >= 0 && index < m_tabs.count()) {
        beginRemoveRows(QModelIndex(), index, index);
        int tabId = m_tabs.at(index).tabId();
        removeTab(index);
        endRemoveRows();
        DBManager::instance()->removeTab(tabId);
        emit countChanged();

        int newIndex = -1;
        // handle removing indexes: 0 .. currentTabIndex - 1. At least one tab left after
        // removing a tab from internal tabs list.
        if (!m_tabs.empty() && index < m_currentTabIndex) {
            // Keep current tab as active
            newIndex = --m_currentTabIndex;
        }

        // handle removing indexes: m_currentTabIndex .. new count. At least one tab left after
        // removing a tab from internal tabs list
        else if (!m_tabs.empty() && index < m_tabs.count()) {
            newIndex = index;
        }

        // handle removing indexes: close last index.
        // This also handles closing of the last tab by setting new currentTabIndex
        // to -1.
        else {
            newIndex = m_tabs.count() - 1;
        }

        // If bigger than current tab index gets closed, ignore it.
        // Closing last open tab resets currentTabIndex (-1).
        if (newIndex <= m_currentTabIndex) {
#ifdef DEBUG_LOGS
            qDebug() << "DeclarativeTabModel::remove index: " << index << "new index: " << newIndex << "currentTabIndex: " << m_currentTabIndex;
#endif
            m_currentTabIndex = newIndex;
            DBManager::instance()->saveSetting("currentTab", QString("%1").arg(m_currentTabIndex));
            emit currentTabChanged();
        }
    }
}

void DeclarativeTabModel::clear()
{
    if (m_tabs.count() == 0)
        return;

    beginResetModel();
    for (int i = m_tabs.count() - 1; i >= 0; --i) {
        removeTab(i);
    }
    endResetModel();

    DBManager::instance()->removeAllTabs();
    emit countChanged();
    m_currentTabIndex = -1;
    DBManager::instance()->saveSetting("currentTab", QString("%1").arg(m_currentTabIndex));
}

bool DeclarativeTabModel::activateTab(const QString& url)
{
    if (m_currentTabIndex >= 0 && m_tabs.at(m_currentTabIndex).currentLink().url() == url) {
        return true;
    }
    for (int i = 0; i < m_tabs.size(); i++) {
        if (m_tabs.at(i).currentLink().url() == url) {
            setCurrentTabIndex(i);
            return true;
        }
    }
    return false;
}

int DeclarativeTabModel::rowCount(const QModelIndex & parent) const {
    Q_UNUSED(parent);
    return m_tabs.count();
}

QVariant DeclarativeTabModel::data(const QModelIndex & index, int role) const {
    if (index.row() < 0 || index.row() > m_tabs.count())
        return QVariant();

    const Tab tab = m_tabs[index.row()];
    if (role == ThumbPathRole) {
        return tab.currentLink().thumbPath();
    } else if (role == TitleRole) {
        return tab.currentLink().title();
    } else if (role == UrlRole) {
        return tab.currentLink().url();
    } else if (role == TabIdRole) {
        return tab.tabId();
    }
    return QVariant();
}

void DeclarativeTabModel::componentComplete()
{
}

void DeclarativeTabModel::setCurrentTabIndex(const int index)
{
    if (index >= 0 && index < m_tabs.count() && index != m_currentTabIndex) {
        m_currentTabIndex = index;
        emit currentTabChanged();
        DBManager::instance()->saveSetting("currentTab", QString("%1").arg(m_currentTabIndex));
    }
}

int DeclarativeTabModel::currentTabIndex() const
{
    return m_currentTabIndex;
}

void DeclarativeTabModel::classBegin()
{
    DBManager::instance()->getAllTabs();
}

void DeclarativeTabModel::tabsAvailable(QList<Tab> tabs)
{
    beginResetModel();
    m_tabs.clear();
    m_tabs = tabs;
    endResetModel();

    if (m_tabs.count() > 0) {
        emit countChanged();
    }

    QString currentTabIndexSetting = DBManager::instance()->getSetting("currentTab");
    bool ok;
    int currentTabIndex = currentTabIndexSetting.toInt(&ok);
    if (ok && currentTabIndex >= 0 && currentTabIndex < m_tabs.count()) {
        m_currentTabIndex = currentTabIndex;
        emit currentTabChanged();
    } else {
        if (m_tabs.count() > 1) {
            setCurrentTabIndex(0);
        }
    }
}

void DeclarativeTabModel::tabChanged(Tab tab)
{
    int i = m_tabs.indexOf(tab); // match based on tab_id
    if (i > -1) {
        QVector<int> roles;
        Tab oldTab = m_tabs[i];
        if (oldTab.currentLink().url() != tab.currentLink().url()) {
            roles << UrlRole;
        }
        if (oldTab.currentLink().title() != tab.currentLink().title()) {
            roles << TitleRole;
        }
        if (oldTab.currentLink().thumbPath() != tab.currentLink().thumbPath()) {
            roles << ThumbPathRole;
        }
        m_tabs[i] = tab;
        QModelIndex start = index(i, 0);
        QModelIndex end = index(i, 0);
        emit dataChanged(start, end, roles);
    }
}

void DeclarativeTabModel::removeTab(int index)
{
    // Both clear and remove(index) handles bounds checking.
    QString thumbPath = m_tabs.at(index).currentLink().thumbPath();
    m_tabs.removeAt(index);

    QFile f(thumbPath);
    if (f.exists()) {
        f.remove();
    }
}

void DeclarativeTabModel::updateThumbPath(QString url, QString path, int tabId)
{
    Q_UNUSED(url)
    QVector<int> roles;
    roles << ThumbPathRole;
    for (int i = 0; i < m_tabs.count(); i++) {
        if (m_tabs.at(i).tabId() == tabId) {
            Link link = m_tabs.at(i).currentLink();
            link.setThumbPath(path);
            m_tabs[i].setCurrentLink(link);
            QModelIndex start = index(i, 0);
            QModelIndex end = index(i, 0);
            emit dataChanged(start, end, roles);
        }
    }
}

void DeclarativeTabModel::updateTitle(QString url, QString title)
{
    QVector<int> roles;
    roles << TitleRole;
    for (int i = 0; i < m_tabs.count(); i++) {
        if (m_tabs.at(i).currentLink().url() == url) {
            if (m_tabs.at(i).currentLink().title() != title) {
                Link tmp = m_tabs[i].currentLink();
                tmp.setTitle(title);
                m_tabs[i].setCurrentLink(tmp);
                QModelIndex start = index(i, 0);
                QModelIndex end = index(i, 0);
                emit dataChanged(start, end, roles);
            }
        }
    }
}
<|endoftext|>


<commit_before>/* Copyright (C) 2008-2011 Xavier Pujol
   (C) 2015 Michael Walter.
   (C) 2016 Marc Stevens. (generic improvements, auxiliary solutions, subsolutions)

   This file is part of fplll. fplll 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.

   fplll 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 fplll. If not, see <http://www.gnu.org/licenses/>. */

#include "enumerate_base.h"

FPLLL_BEGIN_NAMESPACE

#ifdef FPLLL_WITH_RECURSIVE_ENUM
template<int kk, int kk_start, bool dualenum, bool findsubsols>
inline void EnumerationBase::enumerate_recursive( EnumerationBase::opts<kk, kk_start, dualenum, findsubsols> )
{
    enumf alphak = x[kk] - center[kk];
    enumf newdist = partdist[kk] + alphak*alphak*rdiag[kk];

    if (!(newdist <= partdistbounds[kk]))
        return;
    ++nodes;

    alpha[kk] = alphak;
    if (findsubsols && newdist < subsoldists[kk])
    {
        subsoldists[kk] = newdist;
        process_subsolution(kk, newdist);
    }

    if (kk == 0)
    {
        if (newdist > 0.0 /* || !is_svp */)
            process_solution(newdist);
    }
    else
    {
        partdist[kk-1] = newdist;
        if (dualenum)
        {
            for (int j = center_partsum_begin[kk]; j > kk-1; --j)
                center_partsums[kk-1][j] = center_partsums[kk-1][j+1] - alpha[j] * mut[kk-1][j];
        }
        else
        {
            for (int j = center_partsum_begin[kk]; j > kk-1; --j)
                center_partsums[kk-1][j] = center_partsums[kk-1][j+1] - x[j] * mut[kk-1][j];
        }
        if (center_partsum_begin[kk] > center_partsum_begin[kk-1])
            center_partsum_begin[kk-1] = center_partsum_begin[kk];
        center_partsum_begin[kk] = kk;
        center[kk-1] = center_partsums[kk-1][kk];
        roundto(x[kk-1], center[kk-1]);
        dx[kk-1] = ddx[kk-1] = (((int)(center[kk-1] >= x[kk-1]) & 1) << 1) - 1;
    }

    while (true)
    {
        enumerate_recursive( opts<kk-1,kk_start,dualenum,findsubsols>() );

        if (partdist[kk] != 0.0)
        {
            x[kk] += dx[kk];
            ddx[kk] = -ddx[kk];
            dx[kk] = ddx[kk] - dx[kk];

            enumf alphak2 = x[kk] - center[kk];
            enumf newdist2 = partdist[kk] + alphak2*alphak2*rdiag[kk];
            if (!(newdist2 <= partdistbounds[kk]))
                return;
            ++nodes;
            alpha[kk] = alphak2;
            if (kk == 0)
            {
                if (newdist2 > 0.0 /* || !is_svp */)
                    process_solution(newdist2);
            }
            else
            {
                partdist[kk-1] = newdist2;
                if (dualenum)
                    center_partsums[kk-1][kk-1+1] = center_partsums[kk-1][kk-1+1+1] - alpha[kk-1+1] * mut[kk-1][kk-1+1];
                else
                    center_partsums[kk-1][kk-1+1] = center_partsums[kk-1][kk-1+1+1] - x[kk-1+1] * mut[kk-1][kk-1+1];
                if (kk > center_partsum_begin[kk-1])
                    center_partsum_begin[kk-1] = kk;
                center[kk-1] = center_partsums[kk-1][kk-1+1];
                roundto(x[kk-1], center[kk-1]);
                dx[kk-1] = ddx[kk-1] = (((int)(center[kk-1] >= x[kk-1]) & 1) << 1) - 1;
            }
        }
        else
        {
            ++x[kk];

            enumf alphak2 = x[kk] - center[kk];
            enumf newdist2 = partdist[kk] + alphak2*alphak2*rdiag[kk];
            if (!(newdist2 <= partdistbounds[kk]))
                return;
            ++nodes;
            alpha[kk] = alphak2;
            if (kk == 0)
            {
                if (newdist2 > 0.0 /* || !is_svp */)
                    process_solution(newdist2);
            }
            else
            {
                partdist[kk-1] = newdist2;
                if (dualenum)
                    center_partsums[kk-1][kk-1+1] = center_partsums[kk-1][kk-1+1+1] - alpha[kk-1+1] * mut[kk-1][kk-1+1];
                else
                    center_partsums[kk-1][kk-1+1] = center_partsums[kk-1][kk-1+1+1] - x[kk-1+1] * mut[kk-1][kk-1+1];
                if (kk > center_partsum_begin[kk-1])
                    center_partsum_begin[kk-1] = kk;
                center[kk-1] = center_partsums[kk-1][kk-1+1];
                roundto(x[kk-1], center[kk-1]);
                dx[kk-1] = ddx[kk-1] = (((int)(center[kk-1] >= x[kk-1]) & 1) << 1) - 1;
            }
        }
    }
}

#define ENUM_TABLE_FILL8(a) \
            & EnumerationBase::enumerate_recursive_wrapper< a+0,dualenum,findsubsols>, \
            & EnumerationBase::enumerate_recursive_wrapper< a+1,dualenum,findsubsols>, \
            & EnumerationBase::enumerate_recursive_wrapper< a+2,dualenum,findsubsols>, \
            & EnumerationBase::enumerate_recursive_wrapper< a+3,dualenum,findsubsols>, \
            & EnumerationBase::enumerate_recursive_wrapper< a+4,dualenum,findsubsols>, \
            & EnumerationBase::enumerate_recursive_wrapper< a+5,dualenum,findsubsols>, \
            & EnumerationBase::enumerate_recursive_wrapper< a+6,dualenum,findsubsols>, \
            & EnumerationBase::enumerate_recursive_wrapper< a+7,dualenum,findsubsols>
#define ENUM_TABLE_FILL64(a) \
            ENUM_TABLE_FILL8(a), ENUM_TABLE_FILL8(a+8), ENUM_TABLE_FILL8(a+16), ENUM_TABLE_FILL8(a+24), \
            ENUM_TABLE_FILL8(a+32), ENUM_TABLE_FILL8(a+40), ENUM_TABLE_FILL8(a+48), ENUM_TABLE_FILL8(a+56)
#define ENUM_TABLE_FILL256(a) \
            ENUM_TABLE_FILL64(a), ENUM_TABLE_FILL64(a+64), ENUM_TABLE_FILL64(a+128), ENUM_TABLE_FILL64(a+192)

template<bool dualenum, bool findsubsols>
inline void EnumerationBase::enumerate_recursive_dispatch(int kk)
{
    typedef void (EnumerationBase::*enum_recur_type)();
    static const enum_recur_type lookup[] = {
        ENUM_TABLE_FILL256(0),
        ENUM_TABLE_FILL256(256),
        ENUM_TABLE_FILL256(512),
        ENUM_TABLE_FILL256(768),
        ENUM_TABLE_FILL256(1024),
        ENUM_TABLE_FILL256(1280),
        ENUM_TABLE_FILL256(1536),
        ENUM_TABLE_FILL256(1792),
    };
    (this->*lookup[kk])();
}

#endif

template<bool dualenum, bool findsubsols>
void EnumerationBase::enumerate_loop()
{
    if (k >= k_end)
        return;

    for (int i = 0; i < k_end; ++i)
    {
        center_partsum_begin[i+1] = k_end - 1;
        center_partsums[i][k_end] = center_partsum[i];
    }

    partdist[k_end] = 0.0; // needed to make next_pos_up() work properly

    nodes -= k_end - k;
    k = k_end - 1;
#ifdef FPLLL_WITH_RECURSIVE_ENUM
    enumerate_recursive_dispatch<dualenum, findsubsols>(k);
    return;
#endif

    finished = false;
    while (!finished)
    {
        enumf alphak = x[k] - center[k];
        enumf newdist = partdist[k] + alphak * alphak * rdiag[k];
        FPLLL_TRACE("Level k=" << k << " dist_k=" << partdist[k] << " x_k=" << x[k] << " newdist=" << newdist << " partdistbounds_k=" << partdistbounds[k]);
        if (newdist <= partdistbounds[k])
        {
            ++nodes;
            alpha[k] = alphak;
            if (findsubsols && newdist < subsoldists[k])
            {
                subsoldists[k] = newdist;
                process_subsolution(k, newdist);
            }
            --k;
            if (k < 0)
            {
                if (newdist > 0.0 /* || !is_svp */)
                    process_solution(newdist);
                finished = !next_pos_up();
                continue;
            }
            if (!_max_indices.empty() && _max_indices[k+1] == k+1)   //in CVP, at max GS vector, we reset the partial distance
            {
                reset(newdist);
                finished = !next_pos_up();
                continue;
            }
            if (dualenum)
            {
                for (int j = center_partsum_begin[k+1]; j > k; --j)
                    center_partsums[k][j] = center_partsums[k][j+1] - alpha[j] * mut[k][j];
            }
            else
            {
                for (int j = center_partsum_begin[k+1]; j > k; --j)
                    center_partsums[k][j] = center_partsums[k][j+1] - x[j] * mut[k][j];
            }
            center_partsum_begin[k] = max(center_partsum_begin[k], center_partsum_begin[k+1]);
            center_partsum_begin[k+1] = k+1;

            enumf newcenter =  center_partsums[k][k+1];
            center[k] = newcenter;
            partdist[k] = newdist;
            roundto(x[k], newcenter);
            dx[k] = ddx[k] = (((int)(newcenter >= x[k]) & 1) << 1) - 1;
        }
        else
        {
            finished = !next_pos_up();
        }
    }
}

template void EnumerationBase::enumerate_loop<false,false>();
template void EnumerationBase::enumerate_loop<false,true>();
template void EnumerationBase::enumerate_loop<true,false>();
template void EnumerationBase::enumerate_loop<true,true>();

FPLLL_END_NAMESPACE
<commit_msg>Very minor stuffs<commit_after>/* Copyright (C) 2008-2011 Xavier Pujol
   (C) 2015 Michael Walter.
   (C) 2016 Marc Stevens. (generic improvements, auxiliary solutions, subsolutions)

   This file is part of fplll. fplll 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.

   fplll 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 fplll. If not, see <http://www.gnu.org/licenses/>. */

#include "enumerate_base.h"

FPLLL_BEGIN_NAMESPACE

#ifdef FPLLL_WITH_RECURSIVE_ENUM
template<int kk, int kk_start, bool dualenum, bool findsubsols>
inline void EnumerationBase::enumerate_recursive( EnumerationBase::opts<kk, kk_start, dualenum, findsubsols> )
{
    enumf alphak = x[kk] - center[kk];
    enumf newdist = partdist[kk] + alphak*alphak*rdiag[kk];

    if (!(newdist <= partdistbounds[kk]))
        return;
    ++nodes;

    alpha[kk] = alphak;
    if (findsubsols && newdist < subsoldists[kk])
    {
        subsoldists[kk] = newdist;
        process_subsolution(kk, newdist);
    }

    if (kk == 0)
    {
        if (newdist > 0.0 /* || !is_svp */)
            process_solution(newdist);
    }
    else
    {
        partdist[kk-1] = newdist;
        if (dualenum)
        {
            for (int j = center_partsum_begin[kk]; j > kk-1; --j)
                center_partsums[kk-1][j] = center_partsums[kk-1][j+1] - alpha[j] * mut[kk-1][j];
        }
        else
        {
            for (int j = center_partsum_begin[kk]; j > kk-1; --j)
                center_partsums[kk-1][j] = center_partsums[kk-1][j+1] - x[j] * mut[kk-1][j];
        }
        if (center_partsum_begin[kk] > center_partsum_begin[kk-1])
            center_partsum_begin[kk-1] = center_partsum_begin[kk];
        center_partsum_begin[kk] = kk;
        center[kk-1] = center_partsums[kk-1][kk];
        roundto(x[kk-1], center[kk-1]);
        dx[kk-1] = ddx[kk-1] = (((int)(center[kk-1] >= x[kk-1]) & 1) << 1) - 1;
    }

    while (true)
    {
        enumerate_recursive( opts<kk-1,kk_start,dualenum,findsubsols>() );

        if (partdist[kk] != 0.0)
        {
            x[kk] += dx[kk];
            ddx[kk] = -ddx[kk];
            dx[kk] = ddx[kk] - dx[kk];

            enumf alphak2 = x[kk] - center[kk];
            enumf newdist2 = partdist[kk] + alphak2*alphak2*rdiag[kk];
            if (!(newdist2 <= partdistbounds[kk]))
                return;
            ++nodes;
            alpha[kk] = alphak2;
            if (kk == 0)
            {
                if (newdist2 > 0.0 /* || !is_svp */)
                    process_solution(newdist2);
            }
            else
            {
                partdist[kk-1] = newdist2;
                if (dualenum)
                    center_partsums[kk-1][kk-1+1] = center_partsums[kk-1][kk-1+1+1] - alpha[kk-1+1] * mut[kk-1][kk-1+1];
                else
                    center_partsums[kk-1][kk-1+1] = center_partsums[kk-1][kk-1+1+1] - x[kk-1+1] * mut[kk-1][kk-1+1];
                if (kk > center_partsum_begin[kk-1])
                    center_partsum_begin[kk-1] = kk;
                center[kk-1] = center_partsums[kk-1][kk-1+1];
                roundto(x[kk-1], center[kk-1]);
                dx[kk-1] = ddx[kk-1] = (((int)(center[kk-1] >= x[kk-1]) & 1) << 1) - 1;
            }
        }
        else
        {
            ++x[kk];

            enumf alphak2 = x[kk] - center[kk];
            enumf newdist2 = partdist[kk] + alphak2*alphak2*rdiag[kk];
            if (!(newdist2 <= partdistbounds[kk]))
                return;
            ++nodes;
            alpha[kk] = alphak2;
            if (kk == 0)
            {
                if (newdist2 > 0.0 /* || !is_svp */)
                    process_solution(newdist2);
            }
            else
            {
                partdist[kk-1] = newdist2;
                if (dualenum)
                    center_partsums[kk-1][kk-1+1] = center_partsums[kk-1][kk-1+1+1] - alpha[kk-1+1] * mut[kk-1][kk-1+1];
                else
                    center_partsums[kk-1][kk-1+1] = center_partsums[kk-1][kk-1+1+1] - x[kk-1+1] * mut[kk-1][kk-1+1];
                if (kk > center_partsum_begin[kk-1])
                    center_partsum_begin[kk-1] = kk;
                center[kk-1] = center_partsums[kk-1][kk-1+1];
                roundto(x[kk-1], center[kk-1]);
                dx[kk-1] = ddx[kk-1] = (((int)(center[kk-1] >= x[kk-1]) & 1) << 1) - 1;
            }
        }
    }
}

#define ENUM_TABLE_FILL8(a) \
            & EnumerationBase::enumerate_recursive_wrapper< a+0,dualenum,findsubsols>, \
            & EnumerationBase::enumerate_recursive_wrapper< a+1,dualenum,findsubsols>, \
            & EnumerationBase::enumerate_recursive_wrapper< a+2,dualenum,findsubsols>, \
            & EnumerationBase::enumerate_recursive_wrapper< a+3,dualenum,findsubsols>, \
            & EnumerationBase::enumerate_recursive_wrapper< a+4,dualenum,findsubsols>, \
            & EnumerationBase::enumerate_recursive_wrapper< a+5,dualenum,findsubsols>, \
            & EnumerationBase::enumerate_recursive_wrapper< a+6,dualenum,findsubsols>, \
            & EnumerationBase::enumerate_recursive_wrapper< a+7,dualenum,findsubsols>
#define ENUM_TABLE_FILL64(a) \
            ENUM_TABLE_FILL8(a), ENUM_TABLE_FILL8(a+8), ENUM_TABLE_FILL8(a+16), ENUM_TABLE_FILL8(a+24), \
            ENUM_TABLE_FILL8(a+32), ENUM_TABLE_FILL8(a+40), ENUM_TABLE_FILL8(a+48), ENUM_TABLE_FILL8(a+56)
#define ENUM_TABLE_FILL256(a) \
            ENUM_TABLE_FILL64(a), ENUM_TABLE_FILL64(a+64), ENUM_TABLE_FILL64(a+128), ENUM_TABLE_FILL64(a+192)

template<bool dualenum, bool findsubsols>
inline void EnumerationBase::enumerate_recursive_dispatch(int kk)
{
    typedef void (EnumerationBase::*enum_recur_type)();
    static const enum_recur_type lookup[] = {
        ENUM_TABLE_FILL256(0),
        ENUM_TABLE_FILL256(256),
        ENUM_TABLE_FILL256(512),
        ENUM_TABLE_FILL256(768),
        ENUM_TABLE_FILL256(1024),
        ENUM_TABLE_FILL256(1280),
        ENUM_TABLE_FILL256(1536),
        ENUM_TABLE_FILL256(1792),
    };
    (this->*lookup[kk])();
}

#endif

template<bool dualenum, bool findsubsols>
void EnumerationBase::enumerate_loop()
{
    if (k >= k_end)
        return;

    for (int i = 0; i < k_end; ++i)
    {
        center_partsum_begin[i+1] = k_end - 1;
        center_partsums[i][k_end] = center_partsum[i];
    }

    partdist[k_end] = 0.0; // needed to make next_pos_up() work properly

    nodes -= k_end - k;
    k = k_end - 1;

#ifdef FPLLL_WITH_RECURSIVE_ENUM
    enumerate_recursive_dispatch<dualenum, findsubsols>(k);
    return;
#endif

    finished = false;
    while (!finished)
    {
        enumf alphak = x[k] - center[k];
        enumf newdist = partdist[k] + alphak * alphak * rdiag[k];
        FPLLL_TRACE("Level k=" << k << " dist_k=" << partdist[k] << " x_k=" << x[k] << " newdist=" << newdist << " partdistbounds_k=" << partdistbounds[k]);
        if (newdist <= partdistbounds[k])
        {
            ++nodes;
            alpha[k] = alphak;
            if (findsubsols && newdist < subsoldists[k])
            {
                subsoldists[k] = newdist;
                process_subsolution(k, newdist);
            }
            --k;
            if (k < 0)
            {
                if (newdist > 0.0 /* || !is_svp */)
                    process_solution(newdist);
                finished = !next_pos_up();
                continue;
            }
            if (!_max_indices.empty() && _max_indices[k+1] == k+1)   //in CVP, at max GS vector, we reset the partial distance
            {
                reset(newdist);
                finished = !next_pos_up();
                continue;
            }
            if (dualenum)
            {
                for (int j = center_partsum_begin[k+1]; j > k; --j)
                    center_partsums[k][j] = center_partsums[k][j+1] - alpha[j] * mut[k][j];
            }
            else
            {
                for (int j = center_partsum_begin[k+1]; j > k; --j)
                    center_partsums[k][j] = center_partsums[k][j+1] - x[j] * mut[k][j];
            }
            center_partsum_begin[k] = max(center_partsum_begin[k], center_partsum_begin[k+1]);
            center_partsum_begin[k+1] = k+1;

            enumf newcenter = center_partsums[k][k+1];
            center[k] = newcenter;
            partdist[k] = newdist;
            roundto(x[k], newcenter);
            dx[k] = ddx[k] = (((int)(newcenter >= x[k]) & 1) << 1) - 1;
        }
        else
        {
            finished = !next_pos_up();
        }
    }
}

template void EnumerationBase::enumerate_loop<false,false>();
template void EnumerationBase::enumerate_loop<false,true>();
template void EnumerationBase::enumerate_loop<true,false>();
template void EnumerationBase::enumerate_loop<true,true>();

FPLLL_END_NAMESPACE
<|endoftext|>


<commit_before>/* Copyright (c) 2019, NVIDIA CORPORATION. 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 NVIDIA CORPORATION 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 ``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.
 */

#pragma once

#include <algorithm>
#include <limits>
#include <cassert>

// This is meant to be a drop-in replacement for std::array
// that does not need a statically constant size,
// merely a size specified at construction time.
// There should be no good reason for this class to exist as std::vector
// can usually accomplish the same goals if you just set its capacity
// after constructing it, but std::vector<bool> is an abomination that prevents
// generic programming. This class avoids the problems of std::vector<bool>.
// Note that this means it does *not* store bitmaps efficiently.
template<class T>
class DynamicArray
{
 private:
  const size_t size_;
  T* data_;

 public:
  DynamicArray(size_t size) :
    size_(size),
    data_(new T[size])
  {
  }

  DynamicArray(const DynamicArray& other) :
    size_(other.size_),
    data_(new T[size_])
  {
    std::copy(other.begin(), other.end(), begin());
  }

  DynamicArray(std::initializer_list<T> l) :
    size_(l.size()),
    data_(new T[size_])
  {
    std::copy(l.begin(), l.end(), begin());
  }

  // This is the copy-and-swap idiom.
  DynamicArray<T>& operator=(DynamicArray other) {
    swap(*this, other);
    return *this;
  }

  friend void swap(DynamicArray& first, DynamicArray& second)
  {
    using std::swap;
    swap(first.data_, second.data_);
  }

  ~DynamicArray()
  {
    delete[] data_;
  }

  size_t size() { return size_; }

  void clear()
  {
    delete[] data_;
    data_ = new T[size_];
  }

  T & operator [] (size_t i)
  {
    return data_[i];
  }
  const T & operator [] (size_t i) const
  {
    return data_[i];
  }

  T & at(size_t i)
  {
    assert(i < size_);
    return data_[i];
  }
  const T & at(size_t i) const
  {
    assert(i < size_);
    return data_[i];
  }

  T* data() { return data_; }
  const T* data() const { return data_; }
  T* begin() { return data_; }
  const T* begin() const { return data_; }
  const T* cbegin() const { return data_; }
  T* end() { return data_ + size_; }
  const T* end() const { return data_ + size_; }
  const T* cend() const { return data_ + size_; }

  void fill(const T& value) { std::fill(begin(), end(), value); }
};
<commit_msg>Fixed a bug in the copy-and-swap implementation of DynamicArray, which resulted in mapping objects being copied incorrectly.<commit_after>/* Copyright (c) 2019, NVIDIA CORPORATION. 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 NVIDIA CORPORATION 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 ``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.
 */

#pragma once

#include <algorithm>
#include <limits>
#include <cassert>

// This is meant to be a drop-in replacement for std::array
// that does not need a statically constant size,
// merely a size specified at construction time.
// There should be no good reason for this class to exist as std::vector
// can usually accomplish the same goals if you just set its capacity
// after constructing it, but std::vector<bool> is an abomination that prevents
// generic programming. This class avoids the problems of std::vector<bool>.
// Note that this means it does *not* store bitmaps efficiently.
template<class T>
class DynamicArray
{
 private:
  size_t size_;
  T* data_;

 public:
  DynamicArray(size_t size) :
    size_(size),
    data_(new T[size])
  {
  }

  DynamicArray(const DynamicArray& other) :
    size_(other.size_),
    data_(new T[size_])
  {
    std::copy(other.begin(), other.end(), begin());
  }

  DynamicArray(std::initializer_list<T> l) :
    size_(l.size()),
    data_(new T[size_])
  {
    std::copy(l.begin(), l.end(), begin());
  }

  // This is the copy-and-swap idiom.
  DynamicArray<T>& operator=(DynamicArray other) {
    swap(*this, other);
    return *this;
  }

  friend void swap(DynamicArray& first, DynamicArray& second)
  {
    using std::swap;
    swap(first.size_, second.size_);
    swap(first.data_, second.data_);
  }

  ~DynamicArray()
  {
    delete[] data_;
  }

  size_t size() { return size_; }

  void clear()
  {
    delete[] data_;
    data_ = new T[size_];
  }

  T & operator [] (size_t i)
  {
    return data_[i];
  }
  const T & operator [] (size_t i) const
  {
    return data_[i];
  }

  T & at(size_t i)
  {
    assert(i < size_);
    return data_[i];
  }
  const T & at(size_t i) const
  {
    assert(i < size_);
    return data_[i];
  }

  T* data() { return data_; }
  const T* data() const { return data_; }
  T* begin() { return data_; }
  const T* begin() const { return data_; }
  const T* cbegin() const { return data_; }
  T* end() { return data_ + size_; }
  const T* end() const { return data_ + size_; }
  const T* cend() const { return data_ + size_; }

  void fill(const T& value) { std::fill(begin(), end(), value); }
};
<|endoftext|>


<commit_before><commit_msg>Coverity: Initialize the remaining DropInfo members in the constructor.<commit_after><|endoftext|>


<commit_before>
#include "sieve_main.h"
#include "fplll.h"
//#include "LatticePoint.h"
//#include "PointList.h"
#include <thread>
#include <chrono>
#include "SieveGauss.h"

using namespace fplll;

int main(int argc, char **argv)
{

    cout << "Hello " << endl;
    //cout << "B[1] = " << B[1] << endl;
    //auto start = std::chrono::high_resolution_clock::now();
//    auto finish = std::chrono::high_resolution_clock::now();
//    auto microseconds = std::chrono::duration_cast<std::chrono::microseconds>(finish-start);
//    cout << " Time taken: " << microseconds.count()/1000000.0 << "sec" << endl;
  return 1;
}
<commit_msg>test_newsieve<commit_after>
#include "sieve_main.h"
#include "fplll.h"
//#include "LatticePoint.h"
//#include "PointList.h"
#include <thread>
#include <chrono>
#include "SieveGauss.h"

using namespace fplll;

// Z_NR can be either long, double, or mpz_t

template <class ZT>
void test_run_sieve(int dim)
{
    TerminationConditions< Z_NR<ZT> > term_cond; //sets target-legnth as Mink. bound
    ZZ_mat<ZT> B;
    B.resize(dim, dim);
    B.gen_trg(1.1);
    lll_reduction(B, LLL_DEF_DELTA, LLL_DEF_ETA, LM_WRAPPER);
    Sieve<Z_NR<ZT>, false> Test_Queue (B);

}

int main(int argc, char **argv)
{

    cout << "Hello " << endl;

    bool longflag = false; //to be read_in as input
    int dim[] = {25, 30, 35, 40, 42, 44, 46, 48, 50, 52, 54, 56};

    if (longflag)
    {
        test_run_sieve<long>(dim[0]);
    }

    else
    {
        test_run_sieve<mpz_t>(dim[0]);
    }

    //auto start = std::chrono::high_resolution_clock::now();
//    auto finish = std::chrono::high_resolution_clock::now();
//    auto microseconds = std::chrono::duration_cast<std::chrono::microseconds>(finish-start);
//    cout << " Time taken: " << microseconds.count()/1000000.0 << "sec" << endl;
  return 1;
}
<|endoftext|>


<commit_before>/*
* Copyright (C) 2008-2013 The Communi Project
*
* 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 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.
*/

/*
  Parts of this code come from Konversation and are copyrighted to:
  Copyright (C) 2002 Dario Abatianni <eisfuchs@tigress.com>
  Copyright (C) 2004 Peter Simonsson <psn@linux.se>
  Copyright (C) 2006-2008 Eike Hein <hein@kde.org>
  Copyright (C) 2004-2009 Eli Mackenzie <argonel@gmail.com>
*/

#include "irctextformat.h"
#include "ircpalette.h"
#include <QStringList>
#include <QRegExp>
#include "irc.h"

IRC_BEGIN_NAMESPACE

/*!
    \file irctextformat.h
    \brief \#include <IrcTextFormat>
 */

/*!
    \class IrcTextFormat irctextformat.h <IrcTextFormat>
    \ingroup util
    \brief Provides methods for text formatting.

    IrcTextFormat is used to convert IRC-style formatted messages to either
    plain text or HTML. When converting to plain text, the IRC-style formatting
    (colors, bold, underline etc.) are simply stripped away. When converting
    to HTML, the IRC-style formatting is converted to the corresponding HTML
    formatting.

    \code
    IrcTextFormat format;
    QString text = format.toPlainText(message);

    format.palette()->setColorName(Irc::Red, "#ff3333");
    format.palette()->setColorName(Irc::Green, "#33ff33");
    format.palette()->setColorName(Irc::Blue, "#3333ff");
    // ...
    QString html = format.toHtml(message);
    \endcode

    \sa IrcPalette
 */

class IrcTextFormatPrivate
{
public:
    QString urlPattern;
    IrcPalette* palette;
};

/*!
    Constructs a new text format with \a parent.
 */
IrcTextFormat::IrcTextFormat(QObject* parent) : QObject(parent), d_ptr(new IrcTextFormatPrivate)
{
    Q_D(IrcTextFormat);
    d->palette = new IrcPalette(this);
    d->urlPattern = QString("\\b((?:(?:([a-z][\\w\\.-]+:/{1,3})|www|ftp\\d{0,3}[.]|[a-z0-9.\\-]+[.][a-z]{2,4}/)(?:[^\\s()<>]+|\\(([^\\s()<>]+|(\\([^\\s()<>]+\\)))*\\))+(?:\\(([^\\s()<>]+|(\\([^\\s()<>]+\\)))*\\)|\\}\\]|[^\\s`!()\\[\\]{};:'\".,<>?%1%2%3%4%5%6])|[a-z0-9.\\-+_]+@[a-z0-9.\\-]+[.][a-z]{1,5}[^\\s/`!()\\[\\]{};:'\".,<>?%1%2%3%4%5%6]))").arg(QChar(0x00AB)).arg(QChar(0x00BB)).arg(QChar(0x201C)).arg(QChar(0x201D)).arg(QChar(0x2018)).arg(QChar(0x2019));
}

/*!
    Destructs the text format.
 */
IrcTextFormat::~IrcTextFormat()
{
}

/*!
    This property holds the palette used for color formatting.

    \par Access function:
    \li \ref IrcPalette* palette() const
 */
IrcPalette* IrcTextFormat::palette() const
{
    Q_D(const IrcTextFormat);
    return d->palette;
}

/*!
    This property holds the regular expression pattern used for matching URLs.

    \par Access functions:
    \li QString urlPattern() const
    \li void setUrlPattern(const QString& pattern)
 */
QString IrcTextFormat::urlPattern() const
{
    Q_D(const IrcTextFormat);
    return d->urlPattern;
}

void IrcTextFormat::setUrlPattern(const QString& pattern)
{
    Q_D(IrcTextFormat);
    d->urlPattern = pattern;
}

static bool parseColors(const QString& message, int pos, int* len, int* fg = 0, int* bg = 0)
{
    // fg(,bg)
    *len = 0;
    if (fg)
        *fg = -1;
    if (bg)
        *bg = -1;
    QRegExp rx(QLatin1String("(\\d{1,2})(?:,(\\d{1,2}))?"));
    int idx = rx.indexIn(message, pos);
    if (idx == pos) {
        *len = rx.matchedLength();
        if (fg)
            *fg = rx.cap(1).toInt();
        if (bg) {
            bool ok = false;
            int tmp = rx.cap(2).toInt(&ok);
            if (ok)
                *bg = tmp;
        }
    }
    return *len > 0;
}

/*!
    Converts \a text to HTML. This function parses the text and replaces
    IRC-style formatting (colors, bold, underline etc.) to the corresponding
    HTML formatting. Furthermore, this function detects URLs and replaces
    them with appropriate HTML hyperlinks.

    \note URL detection can be disabled by setting an empty
          regular expression pattern used for matching URLs.

    \sa palette, urlPattern, toPlainText()
*/
QString IrcTextFormat::toHtml(const QString& text) const
{
    Q_D(const IrcTextFormat);
    QString processed = text;

    // TODO:
    //processed.replace(QLatin1Char('&'), QLatin1String("&"));
    processed.replace(QLatin1Char('<'), QLatin1String("<"));
    //processed.replace(QLatin1Char('>'), QLatin1String(">"));
    //processed.replace(QLatin1Char('"'), QLatin1String("""));
    //processed.replace(QLatin1Char('\''), QLatin1String("'"));
    //processed.replace(QLatin1Char('\t'), QLatin1String(" "));

    enum {
        None            = 0x0,
        Bold            = 0x1,
        Italic          = 0x4,
        StrikeThrough   = 0x8,
        Underline       = 0x10,
        Inverse         = 0x20
    };
    int state = None;

    int pos = 0;
    int len = 0;
    int fg = -1;
    int bg = -1;
    int depth = 0;
    bool potentialUrl = false;
    while (pos < processed.size()) {
        QString replacement;
        switch (processed.at(pos).unicode()) {
            case '\x02': // bold
                if (state & Bold) {
                    depth--;
                    replacement = QLatin1String("");
                } else {
                    depth++;
                    replacement = QLatin1String("");
                }
                state ^= Bold;
                break;

            case '\x03': // color
                if (parseColors(processed, pos + 1, &len, &fg, &bg)) {
                    depth++;
                    QStringList styles;
                    styles += QString(QLatin1String("color:%1")).arg(d->palette->colorName(fg, QLatin1String("black")));
                    if (bg != -1)
                        styles += QString(QLatin1String("background-color:%1")).arg(d->palette->colorName(bg, QLatin1String("transparent")));
                    replacement = QString(QLatin1String("")).arg(styles.join(QLatin1String(";")));
                    // \x03FF(,BB)
                    processed.replace(pos, len + 1, replacement);
                    pos += replacement.length();
                    continue;
                } else {
                    depth--;
                    replacement = QLatin1String("");
                }
                break;

                //case '\x09': // italic
            case '\x1d': // italic
                if (state & Italic) {
                    depth--;
                    replacement = QLatin1String("");
                } else {
                    depth++;
                    replacement = QLatin1String("");
                }
                state ^= Italic;
                break;

            case '\x13': // strike-through
                if (state & StrikeThrough) {
                    depth--;
                    replacement = QLatin1String("");
                } else {
                    depth++;
                    replacement = QLatin1String("");
                }
                state ^= StrikeThrough;
                break;

            case '\x15': // underline
            case '\x1f': // underline
                if (state & Underline) {
                    depth--;
                    replacement = QLatin1String("");
                } else {
                    depth++;
                    replacement = QLatin1String("");
                }
                state ^= Underline;
                break;

            case '\x16': // inverse
                if (state & Inverse) {
                    depth--;
                    replacement = QLatin1String("");
                } else {
                    depth++;
                    replacement = QLatin1String("");
                }
                state ^= Inverse;
                break;

            case '\x0f': // none
                if (depth > 0)
                    replacement = QString(QLatin1String("")).repeated(depth);
                else
                    processed.remove(pos--, 1); // must rewind back for ++pos below...
                state = None;
                depth = 0;
                break;

            case '.':
            case '/':
            case ':':
                // a dot, slash or colon NOT surrounded by a space indicates a potential URL
                if (!potentialUrl && pos > 0 && !processed.at(pos - 1).isSpace()
                        && pos < processed.length() - 1 && !processed.at(pos + 1).isSpace())
                    potentialUrl = true;
                break;

            default:
                break;
        }

        if (!replacement.isEmpty()) {
            processed.replace(pos, 1, replacement);
            pos += replacement.length();
        } else {
            ++pos;
        }
    }

    if (potentialUrl && !d->urlPattern.isEmpty()) {
        pos = 0;
        QRegExp rx(d->urlPattern);
        while ((pos = rx.indexIn(processed, pos)) >= 0) {
            int len = rx.matchedLength();
            QString href = processed.mid(pos, len);

            QString protocol;
            if (rx.cap(2).isEmpty())
            {
                if (rx.cap(1).contains(QLatin1Char('@')))
                    protocol = QLatin1String("mailto:");
                else if (rx.cap(1).startsWith(QLatin1String("ftp."), Qt::CaseInsensitive))
                    protocol = QLatin1String("ftp://");
                else
                    protocol = QLatin1String("http://");
            }

            QString link = QString(QLatin1String("%3")).arg(protocol, href, href);
            processed.replace(pos, len, link);
            pos += link.length();
        }
    }

    return processed;
}

/*!
    Converts \a text to plain text. This function parses the text and
    strips away IRC-style formatting (colors, bold, underline etc.)

    \sa toHtml()
*/
QString IrcTextFormat::toPlainText(const QString& text) const
{
    QString processed = text;

    int pos = 0;
    int len = 0;
    while (pos < processed.size()) {
        switch (processed.at(pos).unicode()) {
            case '\x02': // bold
            case '\x0f': // none
            case '\x13': // strike-through
            case '\x15': // underline
            case '\x16': // inverse
            case '\x1d': // italic
            case '\x1f': // underline
                processed.remove(pos, 1);
                break;

            case '\x03': // color
                if (parseColors(processed, pos + 1, &len))
                    processed.remove(pos, len + 1);
                else
                    processed.remove(pos, 1);
                break;

            default:
                ++pos;
                break;
        }
    }

    return processed;
}

#include "moc_irctextformat.cpp"

IRC_END_NAMESPACE
<commit_msg>Properly handled all known percent encoding cases and exclusions using QURL::toPercentEncoding().<commit_after>/*
* Copyright (C) 2008-2013 The Communi Project
*
* 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 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.
*/

/*
  Parts of this code come from Konversation and are copyrighted to:
  Copyright (C) 2002 Dario Abatianni <eisfuchs@tigress.com>
  Copyright (C) 2004 Peter Simonsson <psn@linux.se>
  Copyright (C) 2006-2008 Eike Hein <hein@kde.org>
  Copyright (C) 2004-2009 Eli Mackenzie <argonel@gmail.com>
*/

#include "irctextformat.h"
#include "ircpalette.h"
#include <QStringList>
#include <QRegExp>
#include <QUrl>
#include "irc.h"

IRC_BEGIN_NAMESPACE

/*!
    \file irctextformat.h
    \brief \#include <IrcTextFormat>
 */

/*!
    \class IrcTextFormat irctextformat.h <IrcTextFormat>
    \ingroup util
    \brief Provides methods for text formatting.

    IrcTextFormat is used to convert IRC-style formatted messages to either
    plain text or HTML. When converting to plain text, the IRC-style formatting
    (colors, bold, underline etc.) are simply stripped away. When converting
    to HTML, the IRC-style formatting is converted to the corresponding HTML
    formatting.

    \code
    IrcTextFormat format;
    QString text = format.toPlainText(message);

    format.palette()->setColorName(Irc::Red, "#ff3333");
    format.palette()->setColorName(Irc::Green, "#33ff33");
    format.palette()->setColorName(Irc::Blue, "#3333ff");
    // ...
    QString html = format.toHtml(message);
    \endcode

    \sa IrcPalette
 */

class IrcTextFormatPrivate
{
public:
    QString urlPattern;
    IrcPalette* palette;
};

/*!
    Constructs a new text format with \a parent.
 */
IrcTextFormat::IrcTextFormat(QObject* parent) : QObject(parent), d_ptr(new IrcTextFormatPrivate)
{
    Q_D(IrcTextFormat);
    d->palette = new IrcPalette(this);
    d->urlPattern = QString("\\b((?:(?:([a-z][\\w\\.-]+:/{1,3})|www|ftp\\d{0,3}[.]|[a-z0-9.\\-]+[.][a-z]{2,4}/)(?:[^\\s()<>]+|\\(([^\\s()<>]+|(\\([^\\s()<>]+\\)))*\\))+(?:\\(([^\\s()<>]+|(\\([^\\s()<>]+\\)))*\\)|\\}\\]|[^\\s`!()\\[\\]{};:'\".,<>?%1%2%3%4%5%6])|[a-z0-9.\\-+_]+@[a-z0-9.\\-]+[.][a-z]{1,5}[^\\s/`!()\\[\\]{};:'\".,<>?%1%2%3%4%5%6]))").arg(QChar(0x00AB)).arg(QChar(0x00BB)).arg(QChar(0x201C)).arg(QChar(0x201D)).arg(QChar(0x2018)).arg(QChar(0x2019));
}

/*!
    Destructs the text format.
 */
IrcTextFormat::~IrcTextFormat()
{
}

/*!
    This property holds the palette used for color formatting.

    \par Access function:
    \li \ref IrcPalette* palette() const
 */
IrcPalette* IrcTextFormat::palette() const
{
    Q_D(const IrcTextFormat);
    return d->palette;
}

/*!
    This property holds the regular expression pattern used for matching URLs.

    \par Access functions:
    \li QString urlPattern() const
    \li void setUrlPattern(const QString& pattern)
 */
QString IrcTextFormat::urlPattern() const
{
    Q_D(const IrcTextFormat);
    return d->urlPattern;
}

void IrcTextFormat::setUrlPattern(const QString& pattern)
{
    Q_D(IrcTextFormat);
    d->urlPattern = pattern;
}

static bool parseColors(const QString& message, int pos, int* len, int* fg = 0, int* bg = 0)
{
    // fg(,bg)
    *len = 0;
    if (fg)
        *fg = -1;
    if (bg)
        *bg = -1;
    QRegExp rx(QLatin1String("(\\d{1,2})(?:,(\\d{1,2}))?"));
    int idx = rx.indexIn(message, pos);
    if (idx == pos) {
        *len = rx.matchedLength();
        if (fg)
            *fg = rx.cap(1).toInt();
        if (bg) {
            bool ok = false;
            int tmp = rx.cap(2).toInt(&ok);
            if (ok)
                *bg = tmp;
        }
    }
    return *len > 0;
}

/*!
    Converts \a text to HTML. This function parses the text and replaces
    IRC-style formatting (colors, bold, underline etc.) to the corresponding
    HTML formatting. Furthermore, this function detects URLs and replaces
    them with appropriate HTML hyperlinks.

    \note URL detection can be disabled by setting an empty
          regular expression pattern used for matching URLs.

    \sa palette, urlPattern, toPlainText()
*/
QString IrcTextFormat::toHtml(const QString& text) const
{
    Q_D(const IrcTextFormat);
    QString processed = text;

    // TODO:
    //processed.replace(QLatin1Char('&'), QLatin1String("&"));
    processed.replace(QLatin1Char('<'), QLatin1String("<"));
    //processed.replace(QLatin1Char('>'), QLatin1String(">"));
    //processed.replace(QLatin1Char('"'), QLatin1String("""));
    //processed.replace(QLatin1Char('\''), QLatin1String("'"));
    //processed.replace(QLatin1Char('\t'), QLatin1String(" "));

    enum {
        None            = 0x0,
        Bold            = 0x1,
        Italic          = 0x4,
        StrikeThrough   = 0x8,
        Underline       = 0x10,
        Inverse         = 0x20
    };
    int state = None;

    int pos = 0;
    int len = 0;
    int fg = -1;
    int bg = -1;
    int depth = 0;
    bool potentialUrl = false;
    while (pos < processed.size()) {
        QString replacement;
        switch (processed.at(pos).unicode()) {
            case '\x02': // bold
                if (state & Bold) {
                    depth--;
                    replacement = QLatin1String("");
                } else {
                    depth++;
                    replacement = QLatin1String("");
                }
                state ^= Bold;
                break;

            case '\x03': // color
                if (parseColors(processed, pos + 1, &len, &fg, &bg)) {
                    depth++;
                    QStringList styles;
                    styles += QString(QLatin1String("color:%1")).arg(d->palette->colorName(fg, QLatin1String("black")));
                    if (bg != -1)
                        styles += QString(QLatin1String("background-color:%1")).arg(d->palette->colorName(bg, QLatin1String("transparent")));
                    replacement = QString(QLatin1String("")).arg(styles.join(QLatin1String(";")));
                    // \x03FF(,BB)
                    processed.replace(pos, len + 1, replacement);
                    pos += replacement.length();
                    continue;
                } else {
                    depth--;
                    replacement = QLatin1String("");
                }
                break;

                //case '\x09': // italic
            case '\x1d': // italic
                if (state & Italic) {
                    depth--;
                    replacement = QLatin1String("");
                } else {
                    depth++;
                    replacement = QLatin1String("");
                }
                state ^= Italic;
                break;

            case '\x13': // strike-through
                if (state & StrikeThrough) {
                    depth--;
                    replacement = QLatin1String("");
                } else {
                    depth++;
                    replacement = QLatin1String("");
                }
                state ^= StrikeThrough;
                break;

            case '\x15': // underline
            case '\x1f': // underline
                if (state & Underline) {
                    depth--;
                    replacement = QLatin1String("");
                } else {
                    depth++;
                    replacement = QLatin1String("");
                }
                state ^= Underline;
                break;

            case '\x16': // inverse
                if (state & Inverse) {
                    depth--;
                    replacement = QLatin1String("");
                } else {
                    depth++;
                    replacement = QLatin1String("");
                }
                state ^= Inverse;
                break;

            case '\x0f': // none
                if (depth > 0)
                    replacement = QString(QLatin1String("")).repeated(depth);
                else
                    processed.remove(pos--, 1); // must rewind back for ++pos below...
                state = None;
                depth = 0;
                break;

            case '.':
            case '/':
            case ':':
                // a dot, slash or colon NOT surrounded by a space indicates a potential URL
                if (!potentialUrl && pos > 0 && !processed.at(pos - 1).isSpace()
                        && pos < processed.length() - 1 && !processed.at(pos + 1).isSpace())
                    potentialUrl = true;
                break;

            default:
                break;
        }

        if (!replacement.isEmpty()) {
            processed.replace(pos, 1, replacement);
            pos += replacement.length();
        } else {
            ++pos;
        }
    }

    if (potentialUrl && !d->urlPattern.isEmpty()) {
        pos = 0;
        QRegExp rx(d->urlPattern);
        while ((pos = rx.indexIn(processed, pos)) >= 0) {
            int len = rx.matchedLength();
            QString href = processed.mid(pos, len);

            QString protocol;
            if (rx.cap(2).isEmpty())
            {
                if (rx.cap(1).contains(QLatin1Char('@')))
                    protocol = QLatin1String("mailto:");
                else if (rx.cap(1).startsWith(QLatin1String("ftp."), Qt::CaseInsensitive))
                    protocol = QLatin1String("ftp://");
                else
                    protocol = QLatin1String("http://");
            }

            QString link = QString(QLatin1String("%3")).arg(protocol, QUrl::toPercentEncoding(href, ":/@%"), href);
            processed.replace(pos, len, link);
            pos += link.length();
        }
    }

    return processed;
}

/*!
    Converts \a text to plain text. This function parses the text and
    strips away IRC-style formatting (colors, bold, underline etc.)

    \sa toHtml()
*/
QString IrcTextFormat::toPlainText(const QString& text) const
{
    QString processed = text;

    int pos = 0;
    int len = 0;
    while (pos < processed.size()) {
        switch (processed.at(pos).unicode()) {
            case '\x02': // bold
            case '\x0f': // none
            case '\x13': // strike-through
            case '\x15': // underline
            case '\x16': // inverse
            case '\x1d': // italic
            case '\x1f': // underline
                processed.remove(pos, 1);
                break;

            case '\x03': // color
                if (parseColors(processed, pos + 1, &len))
                    processed.remove(pos, len + 1);
                else
                    processed.remove(pos, 1);
                break;

            default:
                ++pos;
                break;
        }
    }

    return processed;
}

#include "moc_irctextformat.cpp"

IRC_END_NAMESPACE
<|endoftext|>


<commit_before>// Copyright (c) 2006-2008 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 "testing/gtest/include/gtest/gtest.h"

#include "base/ref_counted.h"
#include "chrome/renderer/render_widget.h"
#include "chrome/renderer/render_thread.h"

// This class is very simple mock of RenderThread. It simulates an IPC channel
// which supports only two messages:
// ViewHostMsg_CreateWidget : sync message sent by the Widget.
// ViewMsg_Close : async, send to the Widget.
class MockRenderThread : public RenderThreadBase {
 public:
  MockRenderThread()
      : routing_id_(0), opener_id_(0), widget_(NULL),
        reply_deserializer_(NULL) {
  }
  virtual ~MockRenderThread() {
  }

  // Called by the Widget. Not used in the test.
  virtual bool InSend() const {
    return false;
  }

  // Called by the Widget. The routing_id must match the routing id assigned
  // to the Widget in reply to ViewHostMsg_CreateWidget message.
  virtual void AddRoute(int32 routing_id, IPC::Channel::Listener* listener) {
    EXPECT_EQ(routing_id_, routing_id);
    widget_ = listener;
  }

  // Called by the Widget. The routing id must match the routing id of AddRoute.
  virtual void RemoveRoute(int32 routing_id) {
    EXPECT_EQ(routing_id_, routing_id);
    widget_ = NULL;
  }

  // Called by the Widget. Used to send messages to the browser.
  // We short-circuit the mechanim and handle the messages right here on this
  // class.
  virtual bool Send(IPC::Message* msg) {
    // We need to simulate a synchronous channel, thus we are going to receive
    // through this function messages, messages with reply and reply messages.
    // We can only handle one synchronous message at a time.
    if (msg->is_reply()) {
      if (reply_deserializer_)
        reply_deserializer_->SerializeOutputParameters(*msg);
        reply_deserializer_ = NULL;
    } else {
      if (msg->is_sync()) {
        reply_deserializer_ =
            static_cast<IPC::SyncMessage*>(msg)->GetReplyDeserializer();
      }
      OnMessageReceived(*msg);
    }
    delete msg;
    return true;
  }

  //////////////////////////////////////////////////////////////////////////
  // The following functions are called by the test itself.

  void set_routing_id(int32 id) {
    routing_id_ = id;
  }

  int32 opener_id() const {
    return opener_id_;
  }

  bool has_widget() const {
    return widget_ ? true : false;
  }

  // Simulates the Widget receiving a close message. This should result
  // on releasing the internal reference counts and destroying the internal
  // state.
  void SendCloseMessage() {
    ViewMsg_Close msg(routing_id_);
    widget_->OnMessageReceived(msg);
  }

 private:

  // This function operates as a regular IPC listener.
  void OnMessageReceived(const IPC::Message& msg) {
    bool handled = true;
    bool msg_is_ok = true;
    IPC_BEGIN_MESSAGE_MAP_EX(MockRenderThread, msg, msg_is_ok)
      IPC_MESSAGE_HANDLER(ViewHostMsg_CreateWidget, OnMsgCreateWidget);
      IPC_MESSAGE_UNHANDLED(handled = false)
    IPC_END_MESSAGE_MAP_EX()

    // This test must handle all messages that RenderWidget generates.
    EXPECT_TRUE(handled);
  }

  // The Widget expects to be returned valid route_id.
  void OnMsgCreateWidget(int opener_id, int* route_id) {
    opener_id_ = opener_id;
    *route_id = routing_id_;
  }

  // Routing id what will be assigned to the Widget.
  int32 routing_id_;
  // Opener id reported by the Widget.
  int32 opener_id_;
  // We only keep track of one Widget, we learn its pointer when it
  // adds a new route.
  IPC::Channel::Listener* widget_;
  // The last known good deserializer for sync messages.
  IPC::MessageReplyDeserializer* reply_deserializer_;
};

TEST(RenderWidgetTest, DISABLED_CreateAndCloseWidget) {
  MessageLoop msg_loop;
  MockRenderThread render_thread;

  const int32 kRouteId = 5;
  const int32 kOpenerId = 7;

  render_thread.set_routing_id(kRouteId);
  scoped_refptr<RenderWidget> rw =
      RenderWidget::Create(kOpenerId, &render_thread);
  ASSERT_TRUE(rw != NULL);

  // After the RenderWidget it must have sent a message to the render thread
  // that sets the opener id.
  EXPECT_EQ(kOpenerId, render_thread.opener_id());
  ASSERT_TRUE(render_thread.has_widget());

  // Now simulate a close of the Widget.
  render_thread.SendCloseMessage();
  EXPECT_FALSE(render_thread.has_widget());
}

<commit_msg>Modify renderwidget unittest to make purify happy - Some posted task was not being processed. - It needed a mock of RenderProcess.<commit_after>// Copyright (c) 2006-2008 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 "testing/gtest/include/gtest/gtest.h"

#include "base/ref_counted.h"
#include "chrome/common/child_process.h"
#include "chrome/renderer/render_widget.h"
#include "chrome/renderer/render_thread.h"

// This class is a trivial mock of the child process singleton. It is necessary
// so we don't trip DCHECKs in ChildProcess::ReleaseProcess() when destroying
// a render widget instance.
class MockProcess : public ChildProcess {
 public:
  explicit MockProcess(const std::wstring& channel_name) {}
  static void GlobalInit() {
    ChildProcessFactory<MockProcess> factory;
    ChildProcess::GlobalInit(L"dummy", &factory);
  }
};

// This class is very simple mock of RenderThread. It simulates an IPC channel
// which supports only two messages:
// ViewHostMsg_CreateWidget : sync message sent by the Widget.
// ViewMsg_Close : async, send to the Widget.
class MockRenderThread : public RenderThreadBase {
 public:
  MockRenderThread()
      : routing_id_(0), opener_id_(0), widget_(NULL),
        reply_deserializer_(NULL) {
  }
  virtual ~MockRenderThread() {
  }

  // Called by the Widget. Not used in the test.
  virtual bool InSend() const {
    return false;
  }

  // Called by the Widget. The routing_id must match the routing id assigned
  // to the Widget in reply to ViewHostMsg_CreateWidget message.
  virtual void AddRoute(int32 routing_id, IPC::Channel::Listener* listener) {
    EXPECT_EQ(routing_id_, routing_id);
    widget_ = listener;
  }

  // Called by the Widget. The routing id must match the routing id of AddRoute.
  virtual void RemoveRoute(int32 routing_id) {
    EXPECT_EQ(routing_id_, routing_id);
    widget_ = NULL;
  }

  // Called by the Widget. Used to send messages to the browser.
  // We short-circuit the mechanim and handle the messages right here on this
  // class.
  virtual bool Send(IPC::Message* msg) {
    // We need to simulate a synchronous channel, thus we are going to receive
    // through this function messages, messages with reply and reply messages.
    // We can only handle one synchronous message at a time.
    if (msg->is_reply()) {
      if (reply_deserializer_)
        reply_deserializer_->SerializeOutputParameters(*msg);
        delete reply_deserializer_;
        reply_deserializer_ = NULL;
    } else {
      if (msg->is_sync()) {
        reply_deserializer_ =
            static_cast<IPC::SyncMessage*>(msg)->GetReplyDeserializer();
      }
      OnMessageReceived(*msg);
    }
    delete msg;
    return true;
  }

  //////////////////////////////////////////////////////////////////////////
  // The following functions are called by the test itself.

  void set_routing_id(int32 id) {
    routing_id_ = id;
  }

  int32 opener_id() const {
    return opener_id_;
  }

  bool has_widget() const {
    return widget_ ? true : false;
  }

  // Simulates the Widget receiving a close message. This should result
  // on releasing the internal reference counts and destroying the internal
  // state.
  void SendCloseMessage() {
    ViewMsg_Close msg(routing_id_);
    widget_->OnMessageReceived(msg);
  }

 private:

  // This function operates as a regular IPC listener.
  void OnMessageReceived(const IPC::Message& msg) {
    bool handled = true;
    bool msg_is_ok = true;
    IPC_BEGIN_MESSAGE_MAP_EX(MockRenderThread, msg, msg_is_ok)
      IPC_MESSAGE_HANDLER(ViewHostMsg_CreateWidget, OnMsgCreateWidget);
      IPC_MESSAGE_UNHANDLED(handled = false)
    IPC_END_MESSAGE_MAP_EX()

    // This test must handle all messages that RenderWidget generates.
    EXPECT_TRUE(handled);
  }

  // The Widget expects to be returned valid route_id.
  void OnMsgCreateWidget(int opener_id, int* route_id) {
    opener_id_ = opener_id;
    *route_id = routing_id_;
  }

  // Routing id what will be assigned to the Widget.
  int32 routing_id_;
  // Opener id reported by the Widget.
  int32 opener_id_;
  // We only keep track of one Widget, we learn its pointer when it
  // adds a new route.
  IPC::Channel::Listener* widget_;
  // The last known good deserializer for sync messages.
  IPC::MessageReplyDeserializer* reply_deserializer_;
};

TEST(RenderWidgetTest, CreateAndCloseWidget) {
  MessageLoop msg_loop;
  MockRenderThread render_thread;
  MockProcess::GlobalInit();

  const int32 kRouteId = 5;
  const int32 kOpenerId = 7;
  render_thread.set_routing_id(kRouteId);

  {
  scoped_refptr<RenderWidget> rw =
      RenderWidget::Create(kOpenerId, &render_thread);
  ASSERT_TRUE(rw != NULL);

  // After the RenderWidget it must have sent a message to the render thread
  // that sets the opener id.
  EXPECT_EQ(kOpenerId, render_thread.opener_id());
  ASSERT_TRUE(render_thread.has_widget());

  // Now simulate a close of the Widget.
  render_thread.SendCloseMessage();
  EXPECT_FALSE(render_thread.has_widget());

    // Run the loop so the release task from the renderwidget executes.
    msg_loop.PostTask(FROM_HERE, new MessageLoop::QuitTask());
    msg_loop.Run();
}

  // There is a delayed task that the child process posts to terminate the
  // message loop so we need to spin the message loop to delete the task.
  MockProcess::GlobalCleanup();
  msg_loop.Run();
}
<|endoftext|>