<commit_before>/*
* Copyright (C) 2008-2013 The Communi Project
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program 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 General Public License for more details.
*/

#include "treedelegate.h"
#include "treerole.h"
#include <QStyleOptionViewItem>
#include <QStyleOptionHeader>
#include <QStylePainter>
#include <QApplication>
#include <QPalette>
#include <QPainter>
#include <QPointer>
#include <QStyle>
#include <QColor>

class TreeHeader : public QWidget
{
    Q_OBJECT

public:
    TreeHeader(QWidget* parent = 0) : QWidget(parent) { d.highlighted = false; d.state = QStyle::State_None; }

    void setText(const QString& text) { d.text = text; }
    void setIcon(const QIcon& icon) { d.icon = icon; }
    void setState(QStyle::State state) { d.state = state; }
    void setHighlighted(bool highlighted) { d.highlighted = highlighted; }

protected:
    void paintEvent(QPaintEvent*)
    {
        QStyleOptionHeader option;
        option.init(this);
#ifdef Q_OS_WIN
        option.rect.adjust(0, 0, 0, 1);
#endif
        option.state = (d.state | QStyle::State_Raised | QStyle::State_Horizontal);
        if (d.state & QStyle::State_Selected)
            option.state |= QStyle::State_On;
        option.icon = d.icon;
        option.text = d.text;
        option.position = QStyleOptionHeader::OnlyOneSection;
        if (d.highlighted) {
            option.palette.setColor(QPalette::Text, option.palette.color(QPalette::HighlightedText));
            option.palette.setColor(QPalette::ButtonText, option.palette.color(QPalette::HighlightedText));
            option.palette.setColor(QPalette::WindowText, option.palette.color(QPalette::HighlightedText));
        }
        QStylePainter painter(this);
        painter.drawControl(QStyle::CE_Header, option);
    }

private:
    struct Private {
        QIcon icon;
        QString text;
        bool highlighted;
        QStyle::State state;
    } d;
};

class TreeBadge : public QWidget
{
    Q_OBJECT

public:
    TreeBadge(QWidget* parent = 0) : QWidget(parent) { }

protected:
    void paintEvent(QPaintEvent*)
    {
        QStyleOption option;
        option.init(this);
        QStylePainter painter(this);
        painter.drawPrimitive(QStyle::PE_Widget, option);
    }
};

TreeDelegate::TreeDelegate(QObject* parent) : QStyledItemDelegate(parent)
{
}

void TreeDelegate::paint(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index) const
{
    bool active = index.data(TreeRole::Active).toBool();
    bool hilite = index.data(TreeRole::Highlight).toBool();

    if (!index.parent().isValid()) {
        static QPointer<TreeHeader> header;
        if (!header) {
            header = new TreeHeader(const_cast<QWidget*>(option.widget));
            header->setVisible(false);
        }

        header->setEnabled(active);
        header->setHighlighted(hilite);
        header->setText(index.data(Qt::DisplayRole).toString());
        header->setIcon(index.data(Qt::DecorationRole).value<QIcon>());
        header->setState(option.state);
        header->setGeometry(option.rect);
        painter->translate(option.rect.topLeft());
        header->render(painter);
        painter->translate(-option.rect.topLeft());
    } else {
        static QPointer<TreeBadge> badge;
        if (!badge) {
            badge = new TreeBadge(const_cast<QWidget*>(option.widget));
            badge->setVisible(false);
        }

        int num = index.data(TreeRole::Badge).toInt();
        if (num > 0) {
            QRect rect;
            rect.setWidth(option.rect.width() - 2);
            const int ascent = option.fontMetrics.ascent();
            rect.setHeight(ascent + qMax(option.rect.height() % 2, ascent % 2));
            rect.moveCenter(option.rect.center());

            painter->save();
            painter->setPen(Qt::NoPen);
            painter->setBrush(badge->palette().color(hilite ? QPalette::Highlight : QPalette::Base));
            painter->setRenderHint(QPainter::Antialiasing);
            painter->drawRoundedRect(rect, 40, 80, Qt::RelativeSize);
            painter->restore();
        }

        if (hilite)
            const_cast<QStyleOptionViewItem&>(option).palette.setColor(QPalette::Text, QApplication::palette("TreeItem").color(QPalette::HighlightedText));
        else
            const_cast<QStyleOptionViewItem&>(option).palette.setColor(QPalette::Text, QApplication::palette("TreeItem").color(QPalette::Text));
        if (!active)
            const_cast<QStyleOptionViewItem&>(option).palette.setColor(QPalette::Text, option.palette.color(QPalette::Disabled, QPalette::Text));

        QStyledItemDelegate::paint(painter, option, index);

        if (num > 0) {
            painter->save();
            QFont font;
            if (font.pointSize() != -1)
                font.setPointSizeF(0.8 * font.pointSizeF());
            painter->setFont(font);

            QString txt;
            if (num > 999)
                txt = QLatin1String("...");
            else
                txt = QFontMetrics(font).elidedText(QString::number(num), Qt::ElideRight, option.rect.width());

            painter->setPen(badge->palette().color(hilite ? QPalette::HighlightedText : QPalette::Text));
            painter->drawText(option.rect, Qt::AlignCenter, txt);
            painter->restore();
        }
    }
}

void TreeDelegate::initStyleOption(QStyleOptionViewItem* option, const QModelIndex& index) const
{
    QStyledItemDelegate::initStyleOption(option, index);
    if (index.parent().isValid()) {
        QStyleOptionViewItemV4* v4 = qstyleoption_cast<QStyleOptionViewItemV4*>(option);
        if (v4)
            v4->backgroundBrush = Qt::transparent;
    }
}

#include "treedelegate.moc"
<commit_msg>TreeDelegate: move badge drawing to TreeBadge<commit_after>/*
* Copyright (C) 2008-2013 The Communi Project
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program 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 General Public License for more details.
*/

#include "treedelegate.h"
#include "treerole.h"
#include <QStyleOptionViewItem>
#include <QStyleOptionHeader>
#include <QStylePainter>
#include <QApplication>
#include <QPalette>
#include <QPainter>
#include <QPointer>
#include <QStyle>
#include <QColor>

class TreeHeader : public QWidget
{
    Q_OBJECT

public:
    TreeHeader(QWidget* parent = 0) : QWidget(parent) { d.highlighted = false; d.state = QStyle::State_None; }

    void setText(const QString& text) { d.text = text; }
    void setIcon(const QIcon& icon) { d.icon = icon; }
    void setState(QStyle::State state) { d.state = state; }
    void setHighlighted(bool highlighted) { d.highlighted = highlighted; }

protected:
    void paintEvent(QPaintEvent*)
    {
        QStyleOptionHeader option;
        option.init(this);
#ifdef Q_OS_WIN
        option.rect.adjust(0, 0, 0, 1);
#endif
        option.state = (d.state | QStyle::State_Raised | QStyle::State_Horizontal);
        if (d.state & QStyle::State_Selected)
            option.state |= QStyle::State_On;
        option.icon = d.icon;
        option.text = d.text;
        option.position = QStyleOptionHeader::OnlyOneSection;
        if (d.highlighted) {
            option.palette.setColor(QPalette::Text, option.palette.color(QPalette::HighlightedText));
            option.palette.setColor(QPalette::ButtonText, option.palette.color(QPalette::HighlightedText));
            option.palette.setColor(QPalette::WindowText, option.palette.color(QPalette::HighlightedText));
        }
        QStylePainter painter(this);
        painter.drawControl(QStyle::CE_Header, option);
    }

private:
    struct Private {
        QIcon icon;
        QString text;
        bool highlighted;
        QStyle::State state;
    } d;
};

class TreeBadge : public QWidget
{
    Q_OBJECT

public:
    TreeBadge(QWidget* parent = 0) : QWidget(parent) { badge = 0; hilite = false; }

    void setNum(int num) { badge = num; }
    void setHighlighted(int highlighted) { hilite = highlighted; }

protected:
    void paintEvent(QPaintEvent*)
    {
        QStyleOption option;
        option.init(this);
        QStylePainter painter(this);
        painter.drawPrimitive(QStyle::PE_Widget, option);

        if (badge > 0) {
            QRect rect;
            rect.setWidth(option.rect.width() - 2);
            const int ascent = option.fontMetrics.ascent();
            rect.setHeight(ascent + qMax(option.rect.height() % 2, ascent % 2));
            rect.moveCenter(option.rect.center());

            painter.setPen(Qt::NoPen);
            painter.setBrush(palette().color(hilite ? QPalette::Highlight : QPalette::Base));
            painter.setRenderHint(QPainter::Antialiasing);
            painter.drawRoundedRect(rect, 40, 80, Qt::RelativeSize);

            QFont font;
            if (font.pointSize() != -1)
                font.setPointSizeF(0.8 * font.pointSizeF());
            painter.setFont(font);

            QString txt;
            if (badge > 999)
                txt = QLatin1String("...");
            else
                txt = QFontMetrics(font).elidedText(QString::number(badge), Qt::ElideRight, option.rect.width());

            painter.setPen(palette().color(hilite ? QPalette::HighlightedText : QPalette::Text));
            painter.drawText(option.rect, Qt::AlignCenter, txt);
        }
    }

private:
    int badge;
    bool hilite;
};

TreeDelegate::TreeDelegate(QObject* parent) : QStyledItemDelegate(parent)
{
}

void TreeDelegate::paint(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index) const
{
    bool active = index.data(TreeRole::Active).toBool();
    bool hilite = index.data(TreeRole::Highlight).toBool();

    if (!index.parent().isValid()) {
        static QPointer<TreeHeader> header;
        if (!header) {
            header = new TreeHeader(const_cast<QWidget*>(option.widget));
            header->setVisible(false);
        }

        header->setEnabled(active);
        header->setHighlighted(hilite);
        header->setText(index.data(Qt::DisplayRole).toString());
        header->setIcon(index.data(Qt::DecorationRole).value<QIcon>());
        header->setState(option.state);
        header->setGeometry(option.rect);
        painter->translate(option.rect.topLeft());
        header->render(painter);
        painter->translate(-option.rect.topLeft());
    } else {
        static QPointer<TreeBadge> badge;
        if (!badge) {
            badge = new TreeBadge(const_cast<QWidget*>(option.widget));
            badge->setAttribute(Qt::WA_NoBackground);
            badge->setVisible(false);
        }

        if (hilite)
            const_cast<QStyleOptionViewItem&>(option).palette.setColor(QPalette::Text, QApplication::palette("TreeItem").color(QPalette::HighlightedText));
        else
            const_cast<QStyleOptionViewItem&>(option).palette.setColor(QPalette::Text, QApplication::palette("TreeItem").color(QPalette::Text));
        if (!active)
            const_cast<QStyleOptionViewItem&>(option).palette.setColor(QPalette::Text, option.palette.color(QPalette::Disabled, QPalette::Text));

        QStyledItemDelegate::paint(painter, option, index);

        int num = index.data(TreeRole::Badge).toInt();
        if (num > 0) {
            badge->setNum(num);
            badge->setHighlighted(hilite);

            badge->setGeometry(option.rect);
            painter->translate(option.rect.topLeft());
            badge->render(painter);
            painter->translate(-option.rect.topLeft());
        }
    }
}

void TreeDelegate::initStyleOption(QStyleOptionViewItem* option, const QModelIndex& index) const
{
    QStyledItemDelegate::initStyleOption(option, index);
    if (index.parent().isValid()) {
        QStyleOptionViewItemV4* v4 = qstyleoption_cast<QStyleOptionViewItemV4*>(option);
        if (v4)
            v4->backgroundBrush = Qt::transparent;
    }
}

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


<commit_before>/*
 * The BENG request struct.  This is only used by the handlers
 * (handler.c, file-handler.c etc.).
 *
 * author: Max Kellermann <mk@cm4all.com>
 */

#include "request.hxx"
#include "bp_connection.hxx"
#include "bp_instance.hxx"
#include "session.hxx"
#include "session_manager.hxx"
#include "http_server/Request.hxx"
#include "cookie_server.hxx"
#include "bot.h"
#include "shm/dpool.hxx"
#include "pbuffer.hxx"
#include "strmap.hxx"
#include "crc.h"
#include "format.h"
#include "expiry.h"

#include <daemon/log.h>

static const struct strmap *
request_get_cookies(Request &request)
{
    if (request.cookies != nullptr)
        return request.cookies;

    const char *cookie = request.request.headers->Get("cookie");
    if (cookie == nullptr)
        return nullptr;

    request.cookies = strmap_new(&request.pool);
    cookie_map_parse(request.cookies, cookie, &request.pool);

    return request.cookies;
}

static Session *
request_load_session(Request &request, const char *session_id)
{
    assert(!request.stateless);
    assert(!request.session_id.IsDefined());
    assert(session_id != nullptr);

    if (!request.session_id.Parse(session_id))
        return nullptr;

    auto *session = request.GetSession();
    if (session == nullptr)
        return nullptr;

    if (!session->translate.IsNull())
        request.translate.request.session = DupBuffer(request.pool,
                                                      session->translate);

    if (session->site != nullptr)
        request.connection.site_name = p_strdup(&request.pool,
                                                session->site);

    if (!session->cookie_sent)
        request.send_session_cookie = true;

    session->is_new = false;

    return session;
}

static const char *
build_session_cookie_name(struct pool *pool, const BpConfig *config,
                          const struct strmap *headers)
{
    if (headers == nullptr || !config->dynamic_session_cookie)
        return config->session_cookie;

    const char *host = headers->Get("host");
    if (host == nullptr || *host == 0)
        return config->session_cookie;

    size_t length = strlen(config->session_cookie);
    char *name = PoolAlloc<char>(*pool, length + 5);
    memcpy(name, config->session_cookie, length);
    format_uint16_hex_fixed(name + length, crc16_string(0, host));
    name[length + 4] = 0;
    return name;
}

static const char *
request_get_uri_session_id(const Request &request)
{
    assert(!request.stateless);

    return strmap_get_checked(request.args, "session");
}

static const char *
request_get_cookie_session_id(Request &request)
{
    assert(!request.stateless);
    assert(request.session_cookie != nullptr);

    const auto *cookies = request_get_cookies(request);

    return strmap_get_checked(cookies, request.session_cookie);
}

void
Request::DetermineSession()
{
    session_realm = nullptr;

    const char *user_agent = request.headers->Get("user-agent");
    stateless = user_agent == nullptr || user_agent_is_bot(user_agent);
    if (stateless) {
        /* don't propagate a stale session id to processed URIs */
        if (args != nullptr)
            args->Remove("session");
        return;
    }

    session_cookie = build_session_cookie_name(&pool,
                                               &instance.config,
                                               request.headers);

    const char *sid = request_get_uri_session_id(*this);
    bool cookie_received = false;
    if (sid == nullptr || *sid == 0) {
        sid = request_get_cookie_session_id(*this);
        if (sid == nullptr)
            return;

        cookie_received = true;
    }

    auto *session = request_load_session(*this, sid);
    if (session == nullptr) {
        if (!cookie_received && args != nullptr)
            /* remove invalid session id from URI args */
            args->Remove("session");

        return;
    }

    if (!cookie_received) {
        const char *p = request_get_cookie_session_id(*this);
        if (p != nullptr && strcmp(p, sid) == 0)
            cookie_received = true;
    }

    if (cookie_received) {
        session->cookie_received = true;

        if (args != nullptr)
            /* we're using cookies, and we can safely remove the
               session id from the args */
            args->Remove("session");
    }

    session_realm = p_strdup(&pool, session->realm);

    session_put(session);
}

Session *
Request::MakeSession()
{
    if (stateless)
        return nullptr;

    auto *session = GetSession();
    if (session != nullptr)
        return session;

    session = session_new(realm);
    if (session == nullptr) {
        daemon_log(1, "Failed to allocate a session\n");
        return nullptr;
    }

    session->realm = d_strdup(&session->pool, realm);

    session_id = session->id;
    send_session_cookie = true;

    if (args == nullptr)
        args = strmap_new(&pool);
    args->Set("session", session_id.Format(session_id_string));

    return session;
}

void
Request::IgnoreSession()
{
    if (!session_id.IsDefined())
        return;

    assert(!stateless);

    if (args != nullptr)
        args->Remove("session");

    session_id.Clear();
    send_session_cookie = false;
}

void
Request::DiscardSession()
{
    if (!session_id.IsDefined())
        return;

    assert(!stateless);

    if (args != nullptr)
        args->Remove("session");

    session_delete(session_id);
    session_id.Clear();
    send_session_cookie = false;
}

/**
 * Determine the realm name, consider the override by the translation
 * server.  Guaranteed to return non-nullptr.
 */
static const char *
get_request_realm(struct pool *pool, const struct strmap *request_headers,
                  const TranslateResponse &response,
                  ConstBuffer<void> auth_base)
{
    if (response.realm != nullptr)
        return response.realm;

    if (response.realm_from_auth_base) {
        assert(!auth_base.IsNull());
        // TODO: what if AUTH contains null bytes?
        return p_strndup(pool, (const char *)auth_base.data, auth_base.size);
    }

    const char *host = strmap_get_checked(request_headers, "host");
    if (host != nullptr)
        return p_strdup_lower(pool, host);

    /* fall back to empty string as the default realm if there is no
       "Host" header */
    return "";
}

void
Request::ApplyTranslateRealm(const TranslateResponse &response,
                             ConstBuffer<void> auth_base)
{
    if (realm != nullptr)
        /* was already called by Request::HandleAuth(), and no need to
           check again */
        return;

    realm = get_request_realm(&pool, request.headers, response, auth_base);

    if (session_realm != nullptr && strcmp(realm, session_realm) != 0) {
        daemon_log(2, "ignoring spoofed session id from another realm (session='%s', request='%s', uri='%s')\n",
                   session_realm, realm, request.uri);
        IgnoreSession();
    }
}

Session *
Request::ApplyTranslateSession(const TranslateResponse &response)
{
    if (response.session.IsNull() && response.user == nullptr &&
        response.session_site == nullptr &&
        response.language == nullptr)
        return nullptr;

    auto *session = GetSession();

    if (!response.session.IsNull()) {
        if (response.session.IsEmpty()) {
            /* clear translate session */

            if (session != nullptr)
                session->ClearTranslate();
        } else {
            /* set new translate session */

            if (session == nullptr)
                session = MakeSession();

            if (session != nullptr)
                session->SetTranslate(response.session);
        }
    }

    if (response.session_site != nullptr) {
        if (*response.session_site == 0) {
            /* clear site */

            if (session != nullptr)
                session->ClearSite();
        } else {
            /* set new site */

            if (session == nullptr)
                session = MakeSession();

            if (session != nullptr)
                session->SetSite(response.session_site);

            connection.site_name = response.session_site;
        }
    }

    if (response.user != nullptr) {
        if (*response.user == 0) {
            /* log out */

            if (session != nullptr)
                session->ClearUser();
        } else {
            /* log in */

            if (session == nullptr)
                session = MakeSession();

            if (session != nullptr)
                session->SetUser(response.user, response.user_max_age);
        }
    } else if (session != nullptr && session->user != nullptr &&
               session->user_expires > 0 &&
               is_expired(session->user_expires)) {
        daemon_log(4, "user '%s' has expired\n", session->user);
        d_free(&session->pool, session->user);
        session->user = nullptr;
    }

    if (response.language != nullptr) {
        if (*response.language == 0) {
            /* reset language setting */

            if (session != nullptr)
                session->ClearLanguage();
        } else {
            /* override language */

            if (session == nullptr)
                session = MakeSession();

            if (session != nullptr)
                session->SetLanguage(response.language);
        }
    }

    return session;
}
<commit_msg>request_session: remove duplicate realm assignment<commit_after>/*
 * The BENG request struct.  This is only used by the handlers
 * (handler.c, file-handler.c etc.).
 *
 * author: Max Kellermann <mk@cm4all.com>
 */

#include "request.hxx"
#include "bp_connection.hxx"
#include "bp_instance.hxx"
#include "session.hxx"
#include "session_manager.hxx"
#include "http_server/Request.hxx"
#include "cookie_server.hxx"
#include "bot.h"
#include "shm/dpool.hxx"
#include "pbuffer.hxx"
#include "strmap.hxx"
#include "crc.h"
#include "format.h"
#include "expiry.h"

#include <daemon/log.h>

static const struct strmap *
request_get_cookies(Request &request)
{
    if (request.cookies != nullptr)
        return request.cookies;

    const char *cookie = request.request.headers->Get("cookie");
    if (cookie == nullptr)
        return nullptr;

    request.cookies = strmap_new(&request.pool);
    cookie_map_parse(request.cookies, cookie, &request.pool);

    return request.cookies;
}

static Session *
request_load_session(Request &request, const char *session_id)
{
    assert(!request.stateless);
    assert(!request.session_id.IsDefined());
    assert(session_id != nullptr);

    if (!request.session_id.Parse(session_id))
        return nullptr;

    auto *session = request.GetSession();
    if (session == nullptr)
        return nullptr;

    if (!session->translate.IsNull())
        request.translate.request.session = DupBuffer(request.pool,
                                                      session->translate);

    if (session->site != nullptr)
        request.connection.site_name = p_strdup(&request.pool,
                                                session->site);

    if (!session->cookie_sent)
        request.send_session_cookie = true;

    session->is_new = false;

    return session;
}

static const char *
build_session_cookie_name(struct pool *pool, const BpConfig *config,
                          const struct strmap *headers)
{
    if (headers == nullptr || !config->dynamic_session_cookie)
        return config->session_cookie;

    const char *host = headers->Get("host");
    if (host == nullptr || *host == 0)
        return config->session_cookie;

    size_t length = strlen(config->session_cookie);
    char *name = PoolAlloc<char>(*pool, length + 5);
    memcpy(name, config->session_cookie, length);
    format_uint16_hex_fixed(name + length, crc16_string(0, host));
    name[length + 4] = 0;
    return name;
}

static const char *
request_get_uri_session_id(const Request &request)
{
    assert(!request.stateless);

    return strmap_get_checked(request.args, "session");
}

static const char *
request_get_cookie_session_id(Request &request)
{
    assert(!request.stateless);
    assert(request.session_cookie != nullptr);

    const auto *cookies = request_get_cookies(request);

    return strmap_get_checked(cookies, request.session_cookie);
}

void
Request::DetermineSession()
{
    session_realm = nullptr;

    const char *user_agent = request.headers->Get("user-agent");
    stateless = user_agent == nullptr || user_agent_is_bot(user_agent);
    if (stateless) {
        /* don't propagate a stale session id to processed URIs */
        if (args != nullptr)
            args->Remove("session");
        return;
    }

    session_cookie = build_session_cookie_name(&pool,
                                               &instance.config,
                                               request.headers);

    const char *sid = request_get_uri_session_id(*this);
    bool cookie_received = false;
    if (sid == nullptr || *sid == 0) {
        sid = request_get_cookie_session_id(*this);
        if (sid == nullptr)
            return;

        cookie_received = true;
    }

    auto *session = request_load_session(*this, sid);
    if (session == nullptr) {
        if (!cookie_received && args != nullptr)
            /* remove invalid session id from URI args */
            args->Remove("session");

        return;
    }

    if (!cookie_received) {
        const char *p = request_get_cookie_session_id(*this);
        if (p != nullptr && strcmp(p, sid) == 0)
            cookie_received = true;
    }

    if (cookie_received) {
        session->cookie_received = true;

        if (args != nullptr)
            /* we're using cookies, and we can safely remove the
               session id from the args */
            args->Remove("session");
    }

    session_realm = p_strdup(&pool, session->realm);

    session_put(session);
}

Session *
Request::MakeSession()
{
    if (stateless)
        return nullptr;

    auto *session = GetSession();
    if (session != nullptr)
        return session;

    session = session_new(realm);
    if (session == nullptr) {
        daemon_log(1, "Failed to allocate a session\n");
        return nullptr;
    }

    session_id = session->id;
    send_session_cookie = true;

    if (args == nullptr)
        args = strmap_new(&pool);
    args->Set("session", session_id.Format(session_id_string));

    return session;
}

void
Request::IgnoreSession()
{
    if (!session_id.IsDefined())
        return;

    assert(!stateless);

    if (args != nullptr)
        args->Remove("session");

    session_id.Clear();
    send_session_cookie = false;
}

void
Request::DiscardSession()
{
    if (!session_id.IsDefined())
        return;

    assert(!stateless);

    if (args != nullptr)
        args->Remove("session");

    session_delete(session_id);
    session_id.Clear();
    send_session_cookie = false;
}

/**
 * Determine the realm name, consider the override by the translation
 * server.  Guaranteed to return non-nullptr.
 */
static const char *
get_request_realm(struct pool *pool, const struct strmap *request_headers,
                  const TranslateResponse &response,
                  ConstBuffer<void> auth_base)
{
    if (response.realm != nullptr)
        return response.realm;

    if (response.realm_from_auth_base) {
        assert(!auth_base.IsNull());
        // TODO: what if AUTH contains null bytes?
        return p_strndup(pool, (const char *)auth_base.data, auth_base.size);
    }

    const char *host = strmap_get_checked(request_headers, "host");
    if (host != nullptr)
        return p_strdup_lower(pool, host);

    /* fall back to empty string as the default realm if there is no
       "Host" header */
    return "";
}

void
Request::ApplyTranslateRealm(const TranslateResponse &response,
                             ConstBuffer<void> auth_base)
{
    if (realm != nullptr)
        /* was already called by Request::HandleAuth(), and no need to
           check again */
        return;

    realm = get_request_realm(&pool, request.headers, response, auth_base);

    if (session_realm != nullptr && strcmp(realm, session_realm) != 0) {
        daemon_log(2, "ignoring spoofed session id from another realm (session='%s', request='%s', uri='%s')\n",
                   session_realm, realm, request.uri);
        IgnoreSession();
    }
}

Session *
Request::ApplyTranslateSession(const TranslateResponse &response)
{
    if (response.session.IsNull() && response.user == nullptr &&
        response.session_site == nullptr &&
        response.language == nullptr)
        return nullptr;

    auto *session = GetSession();

    if (!response.session.IsNull()) {
        if (response.session.IsEmpty()) {
            /* clear translate session */

            if (session != nullptr)
                session->ClearTranslate();
        } else {
            /* set new translate session */

            if (session == nullptr)
                session = MakeSession();

            if (session != nullptr)
                session->SetTranslate(response.session);
        }
    }

    if (response.session_site != nullptr) {
        if (*response.session_site == 0) {
            /* clear site */

            if (session != nullptr)
                session->ClearSite();
        } else {
            /* set new site */

            if (session == nullptr)
                session = MakeSession();

            if (session != nullptr)
                session->SetSite(response.session_site);

            connection.site_name = response.session_site;
        }
    }

    if (response.user != nullptr) {
        if (*response.user == 0) {
            /* log out */

            if (session != nullptr)
                session->ClearUser();
        } else {
            /* log in */

            if (session == nullptr)
                session = MakeSession();

            if (session != nullptr)
                session->SetUser(response.user, response.user_max_age);
        }
    } else if (session != nullptr && session->user != nullptr &&
               session->user_expires > 0 &&
               is_expired(session->user_expires)) {
        daemon_log(4, "user '%s' has expired\n", session->user);
        d_free(&session->pool, session->user);
        session->user = nullptr;
    }

    if (response.language != nullptr) {
        if (*response.language == 0) {
            /* reset language setting */

            if (session != nullptr)
                session->ClearLanguage();
        } else {
            /* override language */

            if (session == nullptr)
                session = MakeSession();

            if (session != nullptr)
                session->SetLanguage(response.language);
        }
    }

    return session;
}
<|endoftext|>


<commit_before>#pragma once

#include "geometry/grassmann.hpp"
#include "geometry/linear_map.hpp"
#include "geometry/quaternion.hpp"
#include "geometry/r3_element.hpp"
#include "geometry/sign.hpp"
#include "quantities/dimensionless.hpp"

namespace principia {
namespace geometry {

template<typename FromFrame, typename ToFrame>
class Rotation : public LinearMap<FromFrame, ToFrame> {
 public:

  template<typename Scalar>
  Rotation(quantities::Angle const& angle,
           Vector<Scalar, FromFrame> const& axis);
  virtual ~Rotation() = default;

  Sign Determinant() const override;

  Rotation<ToFrame, FromFrame> Inverse() const;

  template<typename Scalar>
  Vector<Scalar, ToFrame> operator()(
      Vector<Scalar, FromFrame> const& vector) const;

  template<typename Scalar>
  Bivector<Scalar, ToFrame> operator()(
      Bivector<Scalar, FromFrame> const& bivector) const;

  template<typename Scalar>
  Trivector<Scalar, ToFrame> operator()(
      Trivector<Scalar, FromFrame> const& trivector) const;

  // TODO(phl): Add Forget.

  static Rotation Identity();

 private:
  explicit Rotation(Quaternion const& quaternion);

  template<typename Scalar>
  R3Element<Scalar> operator()(R3Element<Scalar> const& r3_element) const;

  Quaternion quaternion_;

  template<typename FromFrame, typename ThroughFrame, typename ToFrame>
  friend Rotation<FromFrame, ToFrame> operator*(
      Rotation<ThroughFrame, ToFrame> const& left,
      Rotation<FromFrame, ThroughFrame> const& right);
  friend class RotationTests;
};

template<typename FromFrame, typename ThroughFrame, typename ToFrame>
Rotation<FromFrame, ToFrame> operator*(
    Rotation<ThroughFrame, ToFrame> const& left,
    Rotation<FromFrame, ThroughFrame> const& right);

}  // namespace geometry
}  // namespace principia

#include "geometry/rotation_body.hpp"
<commit_msg>Did gyre and gimble in the wabe;<commit_after>#pragma once

#include "geometry/grassmann.hpp"
#include "geometry/linear_map.hpp"
#include "geometry/quaternion.hpp"
#include "geometry/r3_element.hpp"
#include "geometry/sign.hpp"
#include "quantities/dimensionless.hpp"

namespace principia {
namespace geometry {

template<typename FromFrame, typename ToFrame>
class Rotation : public LinearMap<FromFrame, ToFrame> {
 public:
  template<typename Scalar>
  Rotation(quantities::Angle const& angle,
           Vector<Scalar, FromFrame> const& axis);
  virtual ~Rotation() = default;

  Sign Determinant() const override;

  Rotation<ToFrame, FromFrame> Inverse() const;

  template<typename Scalar>
  Vector<Scalar, ToFrame> operator()(
      Vector<Scalar, FromFrame> const& vector) const;

  template<typename Scalar>
  Bivector<Scalar, ToFrame> operator()(
      Bivector<Scalar, FromFrame> const& bivector) const;

  template<typename Scalar>
  Trivector<Scalar, ToFrame> operator()(
      Trivector<Scalar, FromFrame> const& trivector) const;

  // TODO(phl): Add Forget.

  static Rotation Identity();

 private:
  explicit Rotation(Quaternion const& quaternion);

  template<typename Scalar>
  R3Element<Scalar> operator()(R3Element<Scalar> const& r3_element) const;

  Quaternion quaternion_;

  template<typename FromFrame, typename ThroughFrame, typename ToFrame>
  friend Rotation<FromFrame, ToFrame> operator*(
      Rotation<ThroughFrame, ToFrame> const& left,
      Rotation<FromFrame, ThroughFrame> const& right);
  friend class RotationTests;
};

template<typename FromFrame, typename ThroughFrame, typename ToFrame>
Rotation<FromFrame, ToFrame> operator*(
    Rotation<ThroughFrame, ToFrame> const& left,
    Rotation<FromFrame, ThroughFrame> const& right);

}  // namespace geometry
}  // namespace principia

#include "geometry/rotation_body.hpp"
<|endoftext|>


<commit_before>/************************************************************************************
 *   Copyright (C) 2014-2016 by Savoir-faire Linux                                       *
 *   Author : Emmanuel Lepage Vallee <emmanuel.lepage@savoirfairelinux.com>         *
 *                                                                                *
 *   This library is free software; you can redistribute it and/or                  *
 *   modify it under the terms of the GNU Lesser General Public                     *
 *   License as published by the Free Software Foundation; either                   *
 *   version 2.1 of the License, or (at your option) any later version.             *
 *                                                                                *
 *   This library is distributed in the hope that it will be useful,                *
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of                 *
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU              *
 *   Lesser General Public License for more details.                                *
 *                                                                                *
 *   You should have received a copy of the GNU Lesser General Public               *
 *   License along with this library; if not, write to the Free Software            *
 *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA *
 ***********************************************************************************/
#include "localhistorycollection.h"

//Qt
#include <QtCore/QFile>
#include <QtCore/QDir>
#include <QtCore/QHash>
#include <QtCore/QStandardPaths>
#include <QtCore/QStandardPaths>
#include <QtCore/QUrl>

//Ring
#include "call.h"
#include "media/media.h"
#include "media/recording.h"
#include "media/avrecording.h"
#include "account.h"
#include "person.h"
#include "certificate.h"
#include "contactmethod.h"
#include "categorizedhistorymodel.h"
#include "globalinstances.h"
#include "interfaces/pixmapmanipulatori.h"

class LocalHistoryEditor final : public CollectionEditor<Call>
{
public:
   LocalHistoryEditor(CollectionMediator<Call>* m, LocalHistoryCollection* parent);
   virtual bool save       ( const Call* item ) override;
   virtual bool remove     ( const Call* item ) override;
   virtual bool edit       ( Call*       item ) override;
   virtual bool addNew     ( Call*       item ) override;
   virtual bool addExisting( const Call* item ) override;

private:
   virtual QVector<Call*> items() const override;

   //Helpers
   void saveCall(QTextStream& stream, const Call* call);
   bool regenFile(const Call* toIgnore);

   //Attributes
   QVector<Call*> m_lItems;
   LocalHistoryCollection* m_pCollection;
};

LocalHistoryEditor::LocalHistoryEditor(CollectionMediator<Call>* m, LocalHistoryCollection* parent) :
CollectionEditor<Call>(m),m_pCollection(parent)
{

}

LocalHistoryCollection::LocalHistoryCollection(CollectionMediator<Call>* mediator) :
CollectionInterface(new LocalHistoryEditor(mediator,this)),m_pMediator(mediator)
{
//    setObjectName("LocalHistoryCollection");
}

LocalHistoryCollection::~LocalHistoryCollection()
{

}

void LocalHistoryEditor::saveCall(QTextStream& stream, const Call* call)
{
   if (!CategorizedHistoryModel::instance().isHistoryEnabled())
      return;

   stream.setCodec("UTF-8");
   const QString direction = (call->direction()==Call::Direction::INCOMING)?
      Call::HistoryStateName::INCOMING : Call::HistoryStateName::OUTGOING;

   const Account* a = call->account();
   stream << QString("%1=%2\n").arg(Call::HistoryMapFields::CALLID          ).arg(call->historyId()                     );
   stream << QString("%1=%2\n").arg(Call::HistoryMapFields::TIMESTAMP_START ).arg(call->startTimeStamp()         );
   stream << QString("%1=%2\n").arg(Call::HistoryMapFields::TIMESTAMP_STOP  ).arg(call->stopTimeStamp()          );
   stream << QString("%1=%2\n").arg(Call::HistoryMapFields::ACCOUNT_ID      ).arg(a?QString(a->id()):""          );
   stream << QString("%1=%2\n").arg(Call::HistoryMapFields::DISPLAY_NAME    ).arg(call->peerName()               );
   stream << QString("%1=%2\n").arg(Call::HistoryMapFields::PEER_NUMBER     ).arg(call->peerContactMethod()->uri() );
   stream << QString("%1=%2\n").arg(Call::HistoryMapFields::DIRECTION       ).arg(direction                      );
   stream << QString("%1=%2\n").arg(Call::HistoryMapFields::MISSED          ).arg(call->isMissed()               );
   stream << QString("%1=%2\n").arg(Call::HistoryMapFields::CONTACT_USED    ).arg(false                          );//TODO

   //TODO handle more than one recording
   if (call->hasRecording(Media::Media::Type::AUDIO,Media::Media::Direction::IN)) {
      stream << QString("%1=%2\n").arg(Call::HistoryMapFields::RECORDING_PATH  ).arg(((Media::AVRecording*)call->recordings(Media::Media::Type::AUDIO,Media::Media::Direction::IN)[0])->path().path());
   }

   if (call->peerContactMethod()->contact()) {
      stream << QString("%1=%2\n").arg(Call::HistoryMapFields::CONTACT_UID  ).arg(
         QString(call->peerContactMethod()->contact()->uid())
      );
   }
   if (call->certificate())
      stream << QString("%1=%2\n").arg(Call::HistoryMapFields::CERT_PATH).arg(call->certificate()->path());
   stream << "\n";
   stream.flush();
}

bool LocalHistoryEditor::regenFile(const Call* toIgnore)
{
   QDir dir(QString('/'));
   dir.mkpath(QStandardPaths::writableLocation(QStandardPaths::DataLocation) + QLatin1Char('/') + QString());

   QFile file(QStandardPaths::writableLocation(QStandardPaths::DataLocation) + QLatin1Char('/') +"history.ini");
   if ( file.open(QIODevice::WriteOnly | QIODevice::Text) ) {
      QTextStream stream(&file);
      for (const Call* c : CategorizedHistoryModel::instance().getHistoryCalls()) {
         if (c != toIgnore)
            saveCall(stream, c);
      }
      file.close();
      return true;
   }
   return false;
}

bool LocalHistoryEditor::save(const Call* call)
{
   if (call->collection()->editor<Call>() != this)
      return addNew(const_cast<Call*>(call));

   return regenFile(nullptr);
}

bool LocalHistoryEditor::remove(const Call* item)
{
   if (regenFile(item)) {
      mediator()->removeItem(item);
      return true;
   }
   return false;
}

bool LocalHistoryEditor::edit( Call* item)
{
   Q_UNUSED(item)
   return false;
}

bool LocalHistoryEditor::addNew( Call* call)
{
   QDir dir(QString('/'));
   dir.mkpath(QStandardPaths::writableLocation(QStandardPaths::DataLocation) + QLatin1Char('/') + QString());

   if ((call->collection() && call->collection()->editor<Call>() == this)  || call->historyId().isEmpty()) return false;
   //TODO support \r and \n\r end of line
   QFile file(QStandardPaths::writableLocation(QStandardPaths::DataLocation) + QLatin1Char('/')+"history.ini");

   if ( file.open(QIODevice::Append | QIODevice::Text) ) {
      QTextStream streamFileOut(&file);
      saveCall(streamFileOut, call);
      file.close();

      const_cast<Call*>(call)->setCollection(m_pCollection);
      addExisting(call);
      return true;
   }
   else
      qWarning() << "Unable to save history";
   return false;
}

bool LocalHistoryEditor::addExisting(const Call* item)
{
   m_lItems << const_cast<Call*>(item);
   mediator()->addItem(item);
   return true;
}

QVector<Call*> LocalHistoryEditor::items() const
{
   return m_lItems;
}

QString LocalHistoryCollection::name () const
{
   return QObject::tr("Local history");
}

QString LocalHistoryCollection::category () const
{
   return QObject::tr("History");
}

QVariant LocalHistoryCollection::icon() const
{
   return GlobalInstances::pixmapManipulator().collectionIcon(this,Interfaces::PixmapManipulatorI::CollectionIconHint::HISTORY);
}

bool LocalHistoryCollection::isEnabled() const
{
   return true;
}

bool LocalHistoryCollection::load()
{
   if (!CategorizedHistoryModel::instance().isHistoryEnabled())
      return false;

   QFile file(QStandardPaths::writableLocation(QStandardPaths::DataLocation) + QLatin1Char('/') +"history.ini");
   if ( file.open(QIODevice::ReadOnly | QIODevice::Text) ) {
      QMap<QString,QString> hc;
      QStringList lines;

      while (!file.atEnd())
         lines << file.readLine().trimmed();
      file.close();

      const bool      isLimited = CategorizedHistoryModel::instance().isHistoryLimited();
      const long long dayLimit  = CategorizedHistoryModel::instance().historyLimit() * 24 * 3600;

      time_t now = time(0); // get time now

      for (const QString& line : lines) {
         //The item is complete
         if ((line.isEmpty() || !line.size()) && hc.size()) {
            Call* pastCall = Call::buildHistoryCall(hc);

            if (!isLimited || ( (now - pastCall->startTimeStamp()) < dayLimit) ) {
               pastCall->setCollection(this);
               editor<Call>()->addExisting(pastCall);
            }

            hc.clear();
         }
         // Add to the current set
         else {
            const int idx = line.indexOf("=");
            if (idx >= 0)
               hc[line.left(idx)] = line.right(line.size()-idx-1);
         }
      }
      return true;
   }
   else
      qWarning() << "History doesn't exist or is not readable";
   return false;
}

bool LocalHistoryCollection::reload()
{
   return false;
}

FlagPack<CollectionInterface::SupportedFeatures> LocalHistoryCollection::supportedFeatures() const
{
   return
      CollectionInterface::SupportedFeatures::NONE       |
      CollectionInterface::SupportedFeatures::LOAD       |
      CollectionInterface::SupportedFeatures::CLEAR      |
      CollectionInterface::SupportedFeatures::REMOVE     |
      CollectionInterface::SupportedFeatures::MANAGEABLE |
      CollectionInterface::SupportedFeatures::ADD        ;
}

bool LocalHistoryCollection::clear()
{
   QFile::remove(QStandardPaths::writableLocation(QStandardPaths::DataLocation) + QLatin1Char('/') +"history.ini");
   return true;
}

QByteArray LocalHistoryCollection::id() const
{
   return "mhb";
}
<commit_msg>localhistorycollection: save full uri<commit_after>/************************************************************************************
 *   Copyright (C) 2014-2016 by Savoir-faire Linux                                       *
 *   Author : Emmanuel Lepage Vallee <emmanuel.lepage@savoirfairelinux.com>         *
 *                                                                                *
 *   This library is free software; you can redistribute it and/or                  *
 *   modify it under the terms of the GNU Lesser General Public                     *
 *   License as published by the Free Software Foundation; either                   *
 *   version 2.1 of the License, or (at your option) any later version.             *
 *                                                                                *
 *   This library is distributed in the hope that it will be useful,                *
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of                 *
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU              *
 *   Lesser General Public License for more details.                                *
 *                                                                                *
 *   You should have received a copy of the GNU Lesser General Public               *
 *   License along with this library; if not, write to the Free Software            *
 *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA *
 ***********************************************************************************/
#include "localhistorycollection.h"

//Qt
#include <QtCore/QFile>
#include <QtCore/QDir>
#include <QtCore/QHash>
#include <QtCore/QStandardPaths>
#include <QtCore/QStandardPaths>
#include <QtCore/QUrl>

//Ring
#include "call.h"
#include "media/media.h"
#include "media/recording.h"
#include "media/avrecording.h"
#include "account.h"
#include "person.h"
#include "certificate.h"
#include "contactmethod.h"
#include "categorizedhistorymodel.h"
#include "globalinstances.h"
#include "interfaces/pixmapmanipulatori.h"

class LocalHistoryEditor final : public CollectionEditor<Call>
{
public:
   LocalHistoryEditor(CollectionMediator<Call>* m, LocalHistoryCollection* parent);
   virtual bool save       ( const Call* item ) override;
   virtual bool remove     ( const Call* item ) override;
   virtual bool edit       ( Call*       item ) override;
   virtual bool addNew     ( Call*       item ) override;
   virtual bool addExisting( const Call* item ) override;

private:
   virtual QVector<Call*> items() const override;

   //Helpers
   void saveCall(QTextStream& stream, const Call* call);
   bool regenFile(const Call* toIgnore);

   //Attributes
   QVector<Call*> m_lItems;
   LocalHistoryCollection* m_pCollection;
};

LocalHistoryEditor::LocalHistoryEditor(CollectionMediator<Call>* m, LocalHistoryCollection* parent) :
CollectionEditor<Call>(m),m_pCollection(parent)
{

}

LocalHistoryCollection::LocalHistoryCollection(CollectionMediator<Call>* mediator) :
CollectionInterface(new LocalHistoryEditor(mediator,this)),m_pMediator(mediator)
{
//    setObjectName("LocalHistoryCollection");
}

LocalHistoryCollection::~LocalHistoryCollection()
{

}

void LocalHistoryEditor::saveCall(QTextStream& stream, const Call* call)
{
   if (!CategorizedHistoryModel::instance().isHistoryEnabled())
      return;

   stream.setCodec("UTF-8");
   const QString direction = (call->direction()==Call::Direction::INCOMING)?
      Call::HistoryStateName::INCOMING : Call::HistoryStateName::OUTGOING;

   const Account* a = call->account();
   stream << QString("%1=%2\n").arg(Call::HistoryMapFields::CALLID          ).arg(call->historyId()                       );
   stream << QString("%1=%2\n").arg(Call::HistoryMapFields::TIMESTAMP_START ).arg(call->startTimeStamp()                  );
   stream << QString("%1=%2\n").arg(Call::HistoryMapFields::TIMESTAMP_STOP  ).arg(call->stopTimeStamp()                   );
   stream << QString("%1=%2\n").arg(Call::HistoryMapFields::ACCOUNT_ID      ).arg(a?QString(a->id()):""                   );
   stream << QString("%1=%2\n").arg(Call::HistoryMapFields::DISPLAY_NAME    ).arg(call->peerName()                        );
   stream << QString("%1=%2\n").arg(Call::HistoryMapFields::PEER_NUMBER     ).arg(call->peerContactMethod()->uri().full() );
   stream << QString("%1=%2\n").arg(Call::HistoryMapFields::DIRECTION       ).arg(direction                               );
   stream << QString("%1=%2\n").arg(Call::HistoryMapFields::MISSED          ).arg(call->isMissed()                        );
   stream << QString("%1=%2\n").arg(Call::HistoryMapFields::CONTACT_USED    ).arg(false                                   );//TODO

   //TODO handle more than one recording
   if (call->hasRecording(Media::Media::Type::AUDIO,Media::Media::Direction::IN)) {
      stream << QString("%1=%2\n").arg(Call::HistoryMapFields::RECORDING_PATH  ).arg(((Media::AVRecording*)call->recordings(Media::Media::Type::AUDIO,Media::Media::Direction::IN)[0])->path().path());
   }

   if (call->peerContactMethod()->contact()) {
      stream << QString("%1=%2\n").arg(Call::HistoryMapFields::CONTACT_UID  ).arg(
         QString(call->peerContactMethod()->contact()->uid())
      );
   }
   if (call->certificate())
      stream << QString("%1=%2\n").arg(Call::HistoryMapFields::CERT_PATH).arg(call->certificate()->path());
   stream << "\n";
   stream.flush();
}

bool LocalHistoryEditor::regenFile(const Call* toIgnore)
{
   QDir dir(QString('/'));
   dir.mkpath(QStandardPaths::writableLocation(QStandardPaths::DataLocation) + QLatin1Char('/') + QString());

   QFile file(QStandardPaths::writableLocation(QStandardPaths::DataLocation) + QLatin1Char('/') +"history.ini");
   if ( file.open(QIODevice::WriteOnly | QIODevice::Text) ) {
      QTextStream stream(&file);
      for (const Call* c : CategorizedHistoryModel::instance().getHistoryCalls()) {
         if (c != toIgnore)
            saveCall(stream, c);
      }
      file.close();
      return true;
   }
   return false;
}

bool LocalHistoryEditor::save(const Call* call)
{
   if (call->collection()->editor<Call>() != this)
      return addNew(const_cast<Call*>(call));

   return regenFile(nullptr);
}

bool LocalHistoryEditor::remove(const Call* item)
{
   if (regenFile(item)) {
      mediator()->removeItem(item);
      return true;
   }
   return false;
}

bool LocalHistoryEditor::edit( Call* item)
{
   Q_UNUSED(item)
   return false;
}

bool LocalHistoryEditor::addNew( Call* call)
{
   QDir dir(QString('/'));
   dir.mkpath(QStandardPaths::writableLocation(QStandardPaths::DataLocation) + QLatin1Char('/') + QString());

   if ((call->collection() && call->collection()->editor<Call>() == this)  || call->historyId().isEmpty()) return false;
   //TODO support \r and \n\r end of line
   QFile file(QStandardPaths::writableLocation(QStandardPaths::DataLocation) + QLatin1Char('/')+"history.ini");

   if ( file.open(QIODevice::Append | QIODevice::Text) ) {
      QTextStream streamFileOut(&file);
      saveCall(streamFileOut, call);
      file.close();

      const_cast<Call*>(call)->setCollection(m_pCollection);
      addExisting(call);
      return true;
   }
   else
      qWarning() << "Unable to save history";
   return false;
}

bool LocalHistoryEditor::addExisting(const Call* item)
{
   m_lItems << const_cast<Call*>(item);
   mediator()->addItem(item);
   return true;
}

QVector<Call*> LocalHistoryEditor::items() const
{
   return m_lItems;
}

QString LocalHistoryCollection::name () const
{
   return QObject::tr("Local history");
}

QString LocalHistoryCollection::category () const
{
   return QObject::tr("History");
}

QVariant LocalHistoryCollection::icon() const
{
   return GlobalInstances::pixmapManipulator().collectionIcon(this,Interfaces::PixmapManipulatorI::CollectionIconHint::HISTORY);
}

bool LocalHistoryCollection::isEnabled() const
{
   return true;
}

bool LocalHistoryCollection::load()
{
   if (!CategorizedHistoryModel::instance().isHistoryEnabled())
      return false;

   QFile file(QStandardPaths::writableLocation(QStandardPaths::DataLocation) + QLatin1Char('/') +"history.ini");
   if ( file.open(QIODevice::ReadOnly | QIODevice::Text) ) {
      QMap<QString,QString> hc;
      QStringList lines;

      while (!file.atEnd())
         lines << file.readLine().trimmed();
      file.close();

      const bool      isLimited = CategorizedHistoryModel::instance().isHistoryLimited();
      const long long dayLimit  = CategorizedHistoryModel::instance().historyLimit() * 24 * 3600;

      time_t now = time(0); // get time now

      for (const QString& line : lines) {
         //The item is complete
         if ((line.isEmpty() || !line.size()) && hc.size()) {
            Call* pastCall = Call::buildHistoryCall(hc);

            if (!isLimited || ( (now - pastCall->startTimeStamp()) < dayLimit) ) {
               pastCall->setCollection(this);
               editor<Call>()->addExisting(pastCall);
            }

            hc.clear();
         }
         // Add to the current set
         else {
            const int idx = line.indexOf("=");
            if (idx >= 0)
               hc[line.left(idx)] = line.right(line.size()-idx-1);
         }
      }
      return true;
   }
   else
      qWarning() << "History doesn't exist or is not readable";
   return false;
}

bool LocalHistoryCollection::reload()
{
   return false;
}

FlagPack<CollectionInterface::SupportedFeatures> LocalHistoryCollection::supportedFeatures() const
{
   return
      CollectionInterface::SupportedFeatures::NONE       |
      CollectionInterface::SupportedFeatures::LOAD       |
      CollectionInterface::SupportedFeatures::CLEAR      |
      CollectionInterface::SupportedFeatures::REMOVE     |
      CollectionInterface::SupportedFeatures::MANAGEABLE |
      CollectionInterface::SupportedFeatures::ADD        ;
}

bool LocalHistoryCollection::clear()
{
   QFile::remove(QStandardPaths::writableLocation(QStandardPaths::DataLocation) + QLatin1Char('/') +"history.ini");
   return true;
}

QByteArray LocalHistoryCollection::id() const
{
   return "mhb";
}
<|endoftext|>


<commit_before>///
/// @file  LoadBalancerP2.cpp
/// @brief This load balancer assigns work to the threads in the
///        computation of the 2nd partial sieve function.
///        It is used by the P2(x, a) and B(x, y) functions.
///
/// Copyright (C) 2020 Kim Walisch, <kim.walisch@gmail.com>
///
/// This file is distributed under the BSD License. See the COPYING
/// file in the top level directory.
///

#ifndef LOADBALANCERP2_HPP
#define LOADBALANCERP2_HPP

#include <stdint.h>

namespace primecount {

class LoadBalancerP2
{
public:
  LoadBalancerP2(int64_t z, int threads);
  int get_threads() const;
  int64_t get_thread_dist(int64_t low);

private:
  double time_ = -1;
  int64_t min_dist_ = 1 << 22;
  int64_t thread_dist_ = min_dist_;
  int threads_;
  int64_t z_;
};

} // namespace

#endif
<commit_msg>Refactor<commit_after>///
/// @file  LoadBalancerP2.cpp
/// @brief This load balancer assigns work to the threads in the
///        computation of the 2nd partial sieve function.
///        It is used by the P2(x, a) and B(x, y) functions.
///
/// Copyright (C) 2020 Kim Walisch, <kim.walisch@gmail.com>
///
/// This file is distributed under the BSD License. See the COPYING
/// file in the top level directory.
///

#ifndef LOADBALANCERP2_HPP
#define LOADBALANCERP2_HPP

#include <stdint.h>

namespace primecount {

class LoadBalancerP2
{
public:
  LoadBalancerP2(int64_t z, int threads);
  int64_t get_thread_dist(int64_t low);
  int get_threads() const;

private:
  double time_ = -1;
  int64_t min_dist_ = 1 << 22;
  int64_t thread_dist_ = min_dist_;
  int threads_;
  int64_t z_;
};

} // namespace

#endif
<|endoftext|>


<commit_before>/* Copyright 2019 The TensorFlow Authors. All Rights Reserved.

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 "tensorflow/compiler/mlir/lite/python/graphdef_to_tfl_flatbuffer.h"

#include <ostream>

#include "mlir/IR/MLIRContext.h"  // TF:local_config_mlir
#include "mlir/IR/Module.h"  // TF:local_config_mlir
#include "tensorflow/compiler/mlir/lite/common/tfl_pass_config.h"
#include "tensorflow/compiler/mlir/lite/tf_tfl_passes.h"
#include "tensorflow/compiler/mlir/lite/tf_to_tfl_flatbuffer.h"
#include "tensorflow/compiler/mlir/tensorflow/translate/import_model.h"
#include "tensorflow/compiler/mlir/tensorflow/translate/mlir_roundtrip_flags.h"
#include "tensorflow/core/framework/graph.pb.h"
#include "tensorflow/core/framework/types.pb.h"
#include "tensorflow/core/lib/core/errors.h"
#include "tensorflow/core/protobuf/graph_debug_info.pb.h"
#include "tensorflow/lite/toco/model_flags.pb.h"
#include "tensorflow/lite/toco/toco_flags.pb.h"
#include "tensorflow/lite/toco/types.pb.h"

namespace tensorflow {

// Converts the toco::IODataType to tensorflow::DataType. Only contains the
// conversion mapping for constants defined in TFLite Python API.
DataType ConvertIODataTypeToDataType(toco::IODataType dtype) {
  switch (dtype) {
    case toco::IODataType::FLOAT:
      return DT_FLOAT;
    case toco::IODataType::QUANTIZED_UINT8:
      return DT_QUINT8;
    case toco::IODataType::INT8:
      return DT_QINT8;
    case toco::IODataType::INT32:
      return DT_INT32;
    case toco::IODataType::INT64:
      return DT_INT64;
    case toco::IODataType::STRING:
      return DT_STRING;
    case toco::IODataType::BOOL:
      return DT_BOOL;
    default:
      return DT_INVALID;
  }
}

// Give a warning for any unused flags that have been specified.
void WarningUnusedFlags(const toco::ModelFlags& model_flags,
                        const toco::TocoFlags& toco_flags) {
  if (toco_flags.inference_input_type()) {
    LOG(WARNING) << "Ignored inference_input_type.";
  }
  if (toco_flags.output_format()) {
    LOG(WARNING) << "Ignored output_format.";
  }
  if (toco_flags.default_ranges_min() || toco_flags.default_ranges_max()) {
    LOG(WARNING) << "Ignored default_ranges_stats.";
  }
  if (toco_flags.drop_control_dependency()) {
    LOG(WARNING) << "Ignored drop_control_dependency.";
  }
  if (toco_flags.reorder_across_fake_quant()) {
    LOG(WARNING) << "Ignored reorder_across_fake_quant.";
  }
  if (model_flags.change_concat_input_ranges()) {
    LOG(WARNING) << "Ignored change_concat_input_ranges.";
  }
  if (toco_flags.dump_graphviz_dir().empty()) {
    LOG(WARNING) << "Ignored dump_graphviz_dir.";
  }
  if (toco_flags.dump_graphviz_include_video()) {
    LOG(WARNING) << "Ignored dump_graphviz_video.";
  }
  if (model_flags.allow_nonexistent_arrays()) {
    LOG(WARNING) << "Allow allow_nonexistent_arrays.";
  }
}

Status ConvertGraphDefToTFLiteFlatBuffer(const toco::ModelFlags& model_flags,
                                         const toco::TocoFlags& toco_flags,
                                         const GraphDebugInfo& debug_info,
                                         const GraphDef& input,
                                         string* result) {
  mlir::MLIRContext context;
  GraphImportConfig specs;
  mlir::TFL::QuantizationSpecs quant_specs;

  // Parse input arrays.
  std::vector<string> node_names;
  std::vector<string> node_dtypes;
  std::vector<std::vector<int>> node_shapes;
  std::vector<double> node_mins;
  std::vector<double> node_maxs;
  tensorflow::DataType inference_type =
      ConvertIODataTypeToDataType(toco_flags.inference_type());
  for (auto& flag : model_flags.input_arrays()) {
    node_names.push_back(flag.name());
    node_dtypes.push_back(
        DataType_Name(ConvertIODataTypeToDataType(flag.data_type())));
    node_shapes.push_back(std::vector<int>(flag.shape().dims().begin(),
                                           flag.shape().dims().end()));

    const double mean_value = flag.mean_value();
    const double std_value = flag.std_value();
    const double qmin = 0.0, qmax = 255.0;
    node_mins.push_back((qmin - mean_value) / std_value);
    node_maxs.push_back((qmax - mean_value) / std_value);
  }
  TF_RETURN_IF_ERROR(tensorflow::ParseInputArrayInfo(
      node_names, node_dtypes, node_shapes, &specs.inputs));
  if (mlir::TFL::GetInputNodeQuantSpecs(node_names, node_mins, node_maxs,
                                        inference_type, &quant_specs)) {
    return errors::InvalidArgument("Failed to get input quant spec.");
  }

  // Some extra flag related to post training quantization.
  if (toco_flags.post_training_quantize()) {
    quant_specs.weight_quantization = true;
    if (toco_flags.quantize_to_float16()) {
      quant_specs.inference_type = tensorflow::DT_HALF;
    } else {
      quant_specs.inference_type = tensorflow::DT_QINT8;
    }
  }

  // Parse output arrays.
  std::vector<string> output_arrays(model_flags.output_arrays().begin(),
                                    model_flags.output_arrays().end());
  TF_RETURN_IF_ERROR(tensorflow::ParseOutputArrayInfo(
      output_arrays, &specs.output_arrays, &specs.output_arrays_order));

  // Other flags.
  bool emit_builtin_tflite_ops = !toco_flags.force_select_tf_ops();
  bool emit_select_tf_ops = toco_flags.enable_select_tf_ops();
  bool emit_custom_ops = toco_flags.allow_custom_ops();
  specs.prune_unused_nodes = true;
  specs.convert_legacy_fed_inputs = true;
  specs.graph_as_function = false;
  WarningUnusedFlags(model_flags, toco_flags);

  TF_ASSIGN_OR_RETURN(
      auto module, ConvertGraphdefToMlir(input, debug_info, specs, &context));

  mlir::PassManager pm(module->getContext());
  mlir::TFL::PassConfig pass_config(quant_specs);
  pass_config.emit_builtin_tflite_ops = emit_builtin_tflite_ops;
  pass_config.lower_tensor_list_ops = true;

  tensorflow::AddTFToTFLConversionPasses(pass_config, &pm);

  return ConvertTFExecutorToTFLOrFlatbuffer(
      module.get(), /*export_to_mlir=*/false, emit_builtin_tflite_ops,
      emit_select_tf_ops, emit_custom_ops, /*emit_quant_adaptor_ops=*/false,
      /*lower_tensor_list_ops=*/true, quant_specs, result, &pm);
}

}  // namespace tensorflow
<commit_msg>Fix "Converting DataType 'INVALID' to MLIR Type" bug<commit_after>/* Copyright 2019 The TensorFlow Authors. All Rights Reserved.

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 "tensorflow/compiler/mlir/lite/python/graphdef_to_tfl_flatbuffer.h"

#include <ostream>

#include "mlir/IR/MLIRContext.h"  // TF:local_config_mlir
#include "mlir/IR/Module.h"  // TF:local_config_mlir
#include "tensorflow/compiler/mlir/lite/common/tfl_pass_config.h"
#include "tensorflow/compiler/mlir/lite/tf_tfl_passes.h"
#include "tensorflow/compiler/mlir/lite/tf_to_tfl_flatbuffer.h"
#include "tensorflow/compiler/mlir/tensorflow/translate/import_model.h"
#include "tensorflow/compiler/mlir/tensorflow/translate/mlir_roundtrip_flags.h"
#include "tensorflow/core/framework/graph.pb.h"
#include "tensorflow/core/framework/types.pb.h"
#include "tensorflow/core/lib/core/errors.h"
#include "tensorflow/core/protobuf/graph_debug_info.pb.h"
#include "tensorflow/lite/toco/model_flags.pb.h"
#include "tensorflow/lite/toco/toco_flags.pb.h"
#include "tensorflow/lite/toco/types.pb.h"

namespace tensorflow {

// Converts the toco::IODataType to tensorflow::DataType. Only contains the
// conversion mapping for constants defined in TFLite Python API.
DataType ConvertIODataTypeToDataType(toco::IODataType dtype) {
  switch (dtype) {
    case toco::IODataType::FLOAT:
      return DT_FLOAT;
    case toco::IODataType::QUANTIZED_UINT8:
      return DT_QUINT8;
    case toco::IODataType::INT8:
      return DT_QINT8;
    case toco::IODataType::INT32:
      return DT_INT32;
    case toco::IODataType::INT64:
      return DT_INT64;
    case toco::IODataType::STRING:
      return DT_STRING;
    case toco::IODataType::BOOL:
      return DT_BOOL;
    default:
      return DT_INVALID;
  }
}

// Give a warning for any unused flags that have been specified.
void WarningUnusedFlags(const toco::ModelFlags& model_flags,
                        const toco::TocoFlags& toco_flags) {
  if (toco_flags.inference_input_type()) {
    LOG(WARNING) << "Ignored inference_input_type.";
  }
  if (toco_flags.output_format()) {
    LOG(WARNING) << "Ignored output_format.";
  }
  if (toco_flags.default_ranges_min() || toco_flags.default_ranges_max()) {
    LOG(WARNING) << "Ignored default_ranges_stats.";
  }
  if (toco_flags.drop_control_dependency()) {
    LOG(WARNING) << "Ignored drop_control_dependency.";
  }
  if (toco_flags.reorder_across_fake_quant()) {
    LOG(WARNING) << "Ignored reorder_across_fake_quant.";
  }
  if (model_flags.change_concat_input_ranges()) {
    LOG(WARNING) << "Ignored change_concat_input_ranges.";
  }
  if (toco_flags.dump_graphviz_dir().empty()) {
    LOG(WARNING) << "Ignored dump_graphviz_dir.";
  }
  if (toco_flags.dump_graphviz_include_video()) {
    LOG(WARNING) << "Ignored dump_graphviz_video.";
  }
  if (model_flags.allow_nonexistent_arrays()) {
    LOG(WARNING) << "Allow allow_nonexistent_arrays.";
  }
}

Status ConvertGraphDefToTFLiteFlatBuffer(const toco::ModelFlags& model_flags,
                                         const toco::TocoFlags& toco_flags,
                                         const GraphDebugInfo& debug_info,
                                         const GraphDef& input,
                                         string* result) {
  mlir::MLIRContext context;
  GraphImportConfig specs;
  mlir::TFL::QuantizationSpecs quant_specs;

  // Parse input arrays.
  std::vector<string> node_names;
  std::vector<string> node_dtypes;
  std::vector<std::vector<int>> node_shapes;
  std::vector<double> node_mins;
  std::vector<double> node_maxs;
  tensorflow::DataType inference_type =
      ConvertIODataTypeToDataType(toco_flags.inference_type());

  // Build a map from placeholder to data types.
  llvm::StringMap<DataType> placeholder_data_type_map;
  for (const NodeDef& node_def : input.node()) {
    if (node_def.op() == "Placeholder" && node_def.attr().count("dtype") > 0) {
      placeholder_data_type_map[node_def.name()] =
          node_def.attr().at("dtype").type();
    }
  }

  for (auto& flag : model_flags.input_arrays()) {
    // TOCO doesn't required `data_type` to be filled for every input.
    // If it's not filled, try to get the data type from the placeholder.
    auto toco_data_type = flag.data_type();
    DataType data_type;
    if (toco_data_type == ::toco::IODataType::IO_DATA_TYPE_UNKNOWN &&
        placeholder_data_type_map.find(flag.name()) !=
            placeholder_data_type_map.end()) {
      data_type = placeholder_data_type_map[flag.name()];
    } else {
      data_type = ConvertIODataTypeToDataType(toco_data_type);
    }
    node_names.push_back(flag.name());
    node_dtypes.push_back(DataType_Name(data_type));
    node_shapes.push_back(std::vector<int>(flag.shape().dims().begin(),
                                           flag.shape().dims().end()));

    const double mean_value = flag.mean_value();
    const double std_value = flag.std_value();
    const double qmin = 0.0, qmax = 255.0;
    node_mins.push_back((qmin - mean_value) / std_value);
    node_maxs.push_back((qmax - mean_value) / std_value);
  }
  TF_RETURN_IF_ERROR(tensorflow::ParseInputArrayInfo(
      node_names, node_dtypes, node_shapes, &specs.inputs));
  if (mlir::TFL::GetInputNodeQuantSpecs(node_names, node_mins, node_maxs,
                                        inference_type, &quant_specs)) {
    return errors::InvalidArgument("Failed to get input quant spec.");
  }

  // Some extra flag related to post training quantization.
  if (toco_flags.post_training_quantize()) {
    quant_specs.weight_quantization = true;
    if (toco_flags.quantize_to_float16()) {
      quant_specs.inference_type = tensorflow::DT_HALF;
    } else {
      quant_specs.inference_type = tensorflow::DT_QINT8;
    }
  }

  // Parse output arrays.
  std::vector<string> output_arrays(model_flags.output_arrays().begin(),
                                    model_flags.output_arrays().end());
  TF_RETURN_IF_ERROR(tensorflow::ParseOutputArrayInfo(
      output_arrays, &specs.output_arrays, &specs.output_arrays_order));

  // Other flags.
  bool emit_builtin_tflite_ops = !toco_flags.force_select_tf_ops();
  bool emit_select_tf_ops = toco_flags.enable_select_tf_ops();
  bool emit_custom_ops = toco_flags.allow_custom_ops();
  specs.prune_unused_nodes = true;
  specs.convert_legacy_fed_inputs = true;
  specs.graph_as_function = false;
  WarningUnusedFlags(model_flags, toco_flags);

  TF_ASSIGN_OR_RETURN(
      auto module, ConvertGraphdefToMlir(input, debug_info, specs, &context));

  mlir::PassManager pm(module->getContext());
  mlir::TFL::PassConfig pass_config(quant_specs);
  pass_config.emit_builtin_tflite_ops = emit_builtin_tflite_ops;
  pass_config.lower_tensor_list_ops = true;

  tensorflow::AddTFToTFLConversionPasses(pass_config, &pm);

  return ConvertTFExecutorToTFLOrFlatbuffer(
      module.get(), /*export_to_mlir=*/false, emit_builtin_tflite_ops,
      emit_select_tf_ops, emit_custom_ops, /*emit_quant_adaptor_ops=*/false,
      /*lower_tensor_list_ops=*/true, quant_specs, result, &pm);
}

}  // namespace tensorflow
<|endoftext|>


<commit_before>///
/// @file  aligned_vector.hpp
///
/// Copyright (C) 2020 Kim Walisch, <kim.walisch@gmail.com>
///
/// This file is distributed under the BSD License. See the COPYING
/// file in the top level directory.
///

#ifndef ALIGNED_VECTOR_HPP
#define ALIGNED_VECTOR_HPP

#include <pod_vector.hpp>
#include <cstddef>
#include <cstring>

/// Maximum cache line size of current CPUs.
/// Note that in 2019 all x86 CPU have a cache line size of 64 bytes.
/// However there are CPUs out there that have much larger cache line
/// sizes e.g. IBM z13 CPUs from 2015 have a cache line size of 256
/// bytes. Hence in order to be future-proof we set the maximum cache
/// line size to 512 bytes.
///
#ifndef CACHE_LINE_SIZE
  #define CACHE_LINE_SIZE (1 << 9)
#endif

namespace primecount {

/// The aligned_vector class aligns each of its
/// elements on a new cache line in order to avoid
/// false sharing (cache trashing) when multiple
/// threads write to adjacent elements
///
template <typename T>
class aligned_vector
{
  static_assert(sizeof(T) < CACHE_LINE_SIZE,
                "sizeof(T) must be < CACHE_LINE_SIZE");

public:
  void resize(std::size_t size)
  {
    vect_.resize(size);

    // Do not initialize the padding memory
    for (std::size_t i = 0; i < size; i++)
      std::memset(&vect_[i], 0, sizeof(T));
  }
  char unused()
  {
    vect_[0].pad[0] = 123;
    return vect_[0].pad[0];
  }

  aligned_vector() = default;
  aligned_vector(std::size_t size) { resize(size); }
  std::size_t size() const { return vect_.size(); }
  T& operator[](std::size_t pos) { return vect_[pos].val; }

private:
  struct CacheLine {
    T val;
    // We cannot use alignas(CACHE_LINE_SIZE) for the
    // CacheLine struct as GCC does not yet support
    // alignas(n) with n > 128. Also alignas(n) for
    // over-aligned data and dynamic memory allocation
    // is only supported since C++17.
    char pad[CACHE_LINE_SIZE - sizeof(T)];
  };

  pod_vector<CacheLine> vect_;
};

} // namespace

#endif
<commit_msg>Refactor<commit_after>///
/// @file  aligned_vector.hpp
///
/// Copyright (C) 2020 Kim Walisch, <kim.walisch@gmail.com>
///
/// This file is distributed under the BSD License. See the COPYING
/// file in the top level directory.
///

#ifndef ALIGNED_VECTOR_HPP
#define ALIGNED_VECTOR_HPP

#include <pod_vector.hpp>
#include <cstddef>

/// Maximum cache line size of current CPUs.
/// Note that in 2019 all x86 CPU have a cache line size of 64 bytes.
/// However there are CPUs out there that have much larger cache line
/// sizes e.g. IBM z13 CPUs from 2015 have a cache line size of 256
/// bytes. Hence in order to be future-proof we set the maximum cache
/// line size to 512 bytes.
///
#ifndef CACHE_LINE_SIZE
  #define CACHE_LINE_SIZE (1 << 9)
#endif

namespace primecount {

/// The aligned_vector class aligns each of its
/// elements on a new cache line in order to avoid
/// false sharing (cache trashing) when multiple
/// threads write to adjacent elements
///
template <typename T>
class aligned_vector
{
  static_assert(sizeof(T) < CACHE_LINE_SIZE,
                "sizeof(T) must be < CACHE_LINE_SIZE");

public:
  void resize(std::size_t size)
  {
    vect_.resize(size);

    // Default initialize values.
    // Do not initialize the padding memory.
    for (std::size_t i = 0; i < size; i++)
      vect_[i].val = {};
  }
  char unused()
  {
    vect_[0].pad[0] = 123;
    return vect_[0].pad[0];
  }

  aligned_vector() = default;
  aligned_vector(std::size_t size) { resize(size); }
  std::size_t size() const { return vect_.size(); }
  T& operator[](std::size_t pos) { return vect_[pos].val; }

private:
  struct CacheLine {
    T val;
    // We cannot use alignas(CACHE_LINE_SIZE) for the
    // CacheLine struct as GCC does not yet support
    // alignas(n) with n > 128. Also alignas(n) for
    // over-aligned data and dynamic memory allocation
    // is only supported since C++17.
    char pad[CACHE_LINE_SIZE - sizeof(T)];
  };

  pod_vector<CacheLine> vect_;
};

} // namespace

#endif
<|endoftext|>


<commit_before>/* Copyright 2018 The TensorFlow Authors. All Rights Reserved.

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 "tensorflow/compiler/xla/service/hlo_element_type_converter.h"
#include "tensorflow/compiler/xla/service/hlo_matchers.h"
#include "tensorflow/compiler/xla/tests/hlo_test_base.h"

namespace xla {
namespace {

namespace op = xla::testing::opcode_matchers;

class HloElementTypeConverterTest : public HloTestBase {
 public:
  std::unique_ptr<HloModule> CreateModuleFromHloString(
      const string& hlo_string) {
    return HloRunner::CreateModuleFromString(hlo_string,
                                             GetDebugOptionsForTest())
        .ValueOrDie();
  }
};

TEST_F(HloElementTypeConverterTest, CustomCallsNotConverted) {
  const string& hlo_string = R"(
    HloModule custom_call
    ENTRY CustomCall {
      constant = bf16[1]{0} constant({12345})
      ROOT custom-call = bf16[1,2,3]{0,2,1} custom-call(constant),
           custom_call_target="foo"
    }
  )";
  auto module = CreateModuleFromHloString(hlo_string);
  HloElementTypeConverter type_converter(BF16, F32);
  auto converted = type_converter.Run(module.get()).ConsumeValueOrDie();
  EXPECT_TRUE(converted == false);
}

TEST_F(HloElementTypeConverterTest, InfeedsOutfeedsNotConverted) {
  const string& hlo_string = R"(
    HloModule InfeedOutfeed
    ENTRY RoundTrip16MiBR1.v2 {
      ROOT infeed = bf16[4]{0} infeed()
      outfeed = () outfeed(infeed)
    }
  )";
  auto module = CreateModuleFromHloString(hlo_string);
  HloElementTypeConverter type_converter(BF16, F32);
  auto converted = type_converter.Run(module.get()).ConsumeValueOrDie();
  EXPECT_TRUE(converted == false);
}

TEST_F(HloElementTypeConverterTest, OperationsInNestedTuplesConverted) {
  const string& hlo_string = R"(
    HloModule NestedTuples
    ENTRY NestedTuples.v5 {
      constant.4 = bf16[] constant(42)
      constant.2 = f32[2]{0} constant({1, 2})
      constant.3 = bf16[] constant(42)
      add = bf16[] add(constant.2, constant.3)
      tuple = (f32[2]{0}, bf16[]) tuple(constant.2, add)
      constant.5 = bf16[2]{0} constant({22, 44})
      ROOT tuple.1 = ((f32[2]{0}, bf16[]), bf16[2]{0}) tuple(tuple, constant.5)
    }
  )";

  auto module = CreateModuleFromHloString(hlo_string);
  HloElementTypeConverter type_converter(BF16, F32);
  auto converted = type_converter.Run(module.get()).ConsumeValueOrDie();
  EXPECT_TRUE(converted == true);

  const HloInstruction* bf16_op =
      module->entry_computation()->root_instruction()->operand(0)->operand(1);
  EXPECT_THAT(bf16_op, op::Convert(op::Add(op::Constant(), op::Convert())));
}

TEST_F(HloElementTypeConverterTest, BatchNormGradBF16Converted) {
  const string& hlo_string = R"(
    HloModule BatchNormGrad
    ENTRY BatchNormGrad.v6 {
      constant.4 = bf16[2,2,2,1]{3,2,1,0} constant(bf16[2,2,2,1] { { /*i0=0*/
      { /*i1=0*/ {0}, {0} }, { /*i1=1*/ {0}, {0} } }, { /*i0=1*/ { /*i1=0*/ {0},
      {0} }, { /*i1=1*/ {0}, {0} } } })
      constant.5 = bf16[2]{0} constant({1, 1})
      constant.6 = bf16[2]{0} constant({0, 0})
      constant.7 = bf16[2]{0} constant({1, 1})
      constant.8 = bf16[2,2,2,1]{3,2,1,0} constant(bf16[2,2,2,1] { { /*i0=0*/
      { /*i1=0*/ {1}, {2} }, { /*i1=1*/ {3}, {4} } }, { /*i0=1*/ { /*i1=0*/
      {5}, {6} }, { /*i1=1*/ {7}, {8} } } })
      ROOT batch-norm-grad = (bf16[2,2,2,1]{3,2,1,0}, bf16[2]{0}, bf16[2]{0})
      batch-norm-grad(constant.4, constant.5, constant.6, constant.7,
      constant.8), epsilon=0, feature_index=2
    }
  )";

  auto module = CreateModuleFromHloString(hlo_string);
  HloElementTypeConverter type_converter(BF16, F32);
  auto converted = type_converter.Run(module.get()).ConsumeValueOrDie();
  EXPECT_TRUE(converted == true);

  const HloInstruction* tuple_instr =
      module->entry_computation()->root_instruction();
  ::testing::Matcher<const ::xla::HloInstruction*> batch_norm =
      op::BatchNormGrad();
  EXPECT_THAT(tuple_instr,
              op::Tuple(op::Convert(op::GetTupleElement(batch_norm, 0)),
                        op::Convert(op::GetTupleElement(batch_norm, 1)),
                        op::Convert(op::GetTupleElement(batch_norm, 2))));
}

}  // namespace
}  // namespace xla
<commit_msg>Replace the use of ConsumeValueOrDie with TF_ASSERT_OK_AND_ASSIGN.<commit_after>/* Copyright 2018 The TensorFlow Authors. All Rights Reserved.

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 "tensorflow/compiler/xla/service/hlo_element_type_converter.h"
#include "tensorflow/compiler/xla/service/hlo_matchers.h"
#include "tensorflow/compiler/xla/tests/hlo_test_base.h"

namespace xla {
namespace {

namespace op = xla::testing::opcode_matchers;

class HloElementTypeConverterTest : public HloTestBase {
 public:
  std::unique_ptr<HloModule> CreateModuleFromHloString(
      const string& hlo_string) {
    return HloRunner::CreateModuleFromString(hlo_string,
                                             GetDebugOptionsForTest())
        .ValueOrDie();
  }
};

TEST_F(HloElementTypeConverterTest, CustomCallsNotConverted) {
  const string& hlo_string = R"(
    HloModule custom_call
    ENTRY CustomCall {
      constant = bf16[1]{0} constant({12345})
      ROOT custom-call = bf16[1,2,3]{0,2,1} custom-call(constant),
           custom_call_target="foo"
    }
  )";
  auto module = CreateModuleFromHloString(hlo_string);
  HloElementTypeConverter type_converter(BF16, F32);
  TF_ASSERT_OK_AND_ASSIGN(bool converted, type_converter.Run(module.get()));
  EXPECT_FALSE(converted);
}

TEST_F(HloElementTypeConverterTest, InfeedsOutfeedsNotConverted) {
  const string& hlo_string = R"(
    HloModule InfeedOutfeed
    ENTRY RoundTrip16MiBR1.v2 {
      ROOT infeed = bf16[4]{0} infeed()
      outfeed = () outfeed(infeed)
    }
  )";
  auto module = CreateModuleFromHloString(hlo_string);
  HloElementTypeConverter type_converter(BF16, F32);
  TF_ASSERT_OK_AND_ASSIGN(bool converted, type_converter.Run(module.get()));
  EXPECT_FALSE(converted);
}

TEST_F(HloElementTypeConverterTest, OperationsInNestedTuplesConverted) {
  const string& hlo_string = R"(
    HloModule NestedTuples
    ENTRY NestedTuples.v5 {
      constant.4 = bf16[] constant(42)
      constant.2 = f32[2]{0} constant({1, 2})
      constant.3 = bf16[] constant(42)
      add = bf16[] add(constant.2, constant.3)
      tuple = (f32[2]{0}, bf16[]) tuple(constant.2, add)
      constant.5 = bf16[2]{0} constant({22, 44})
      ROOT tuple.1 = ((f32[2]{0}, bf16[]), bf16[2]{0}) tuple(tuple, constant.5)
    }
  )";

  auto module = CreateModuleFromHloString(hlo_string);
  HloElementTypeConverter type_converter(BF16, F32);
  TF_ASSERT_OK_AND_ASSIGN(bool converted, type_converter.Run(module.get()));
  EXPECT_TRUE(converted);
  const HloInstruction* bf16_op =
      module->entry_computation()->root_instruction()->operand(0)->operand(1);
  EXPECT_THAT(bf16_op, op::Convert(op::Add(op::Constant(), op::Convert())));
}

TEST_F(HloElementTypeConverterTest, BatchNormGradBF16Converted) {
  const string& hlo_string = R"(
    HloModule BatchNormGrad
    ENTRY BatchNormGrad.v6 {
      constant.4 = bf16[2,2,2,1]{3,2,1,0} constant(bf16[2,2,2,1] { { /*i0=0*/
      { /*i1=0*/ {0}, {0} }, { /*i1=1*/ {0}, {0} } }, { /*i0=1*/ { /*i1=0*/ {0},
      {0} }, { /*i1=1*/ {0}, {0} } } })
      constant.5 = bf16[2]{0} constant({1, 1})
      constant.6 = bf16[2]{0} constant({0, 0})
      constant.7 = bf16[2]{0} constant({1, 1})
      constant.8 = bf16[2,2,2,1]{3,2,1,0} constant(bf16[2,2,2,1] { { /*i0=0*/
      { /*i1=0*/ {1}, {2} }, { /*i1=1*/ {3}, {4} } }, { /*i0=1*/ { /*i1=0*/
      {5}, {6} }, { /*i1=1*/ {7}, {8} } } })
      ROOT batch-norm-grad = (bf16[2,2,2,1]{3,2,1,0}, bf16[2]{0}, bf16[2]{0})
      batch-norm-grad(constant.4, constant.5, constant.6, constant.7,
      constant.8), epsilon=0, feature_index=2
    }
  )";

  auto module = CreateModuleFromHloString(hlo_string);
  HloElementTypeConverter type_converter(BF16, F32);
  TF_ASSERT_OK_AND_ASSIGN(bool converted, type_converter.Run(module.get()));
  EXPECT_TRUE(converted);
  const HloInstruction* tuple_instr =
      module->entry_computation()->root_instruction();
  ::testing::Matcher<const ::xla::HloInstruction*> batch_norm =
      op::BatchNormGrad();
  EXPECT_THAT(tuple_instr,
              op::Tuple(op::Convert(op::GetTupleElement(batch_norm, 0)),
                        op::Convert(op::GetTupleElement(batch_norm, 1)),
                        op::Convert(op::GetTupleElement(batch_norm, 2))));
}

}  // namespace
}  // namespace xla
<|endoftext|>