<commit_before>#include "trafficgraphwidget.h"
#include "clientmodel.h"
#include "optionsmodel.h"

#include <QPainter>
#include <QPainterPath>
#include <QColor>
#include <QTimer>

#include <cmath>

#define DESIRED_SAMPLES         800

#define XMARGIN                 10
#define YMARGIN                 10

TrafficGraphWidget::TrafficGraphWidget(QWidget *parent) :
    QWidget(parent),
    timer(0),
    fMax(0.0f),
    nMins(0),
    vSamplesIn(),
    vSamplesOut(),
    nLastBytesIn(0),
    nLastBytesOut(0),
    clientModel(0)
{
    timer = new QTimer(this);
    connect(timer, SIGNAL(timeout()), SLOT(updateRates()));
}

void TrafficGraphWidget::setClientModel(ClientModel *model)
{
    clientModel = model;
    if(model) {
        nLastBytesIn = model->getTotalBytesRecv();
        nLastBytesOut = model->getTotalBytesSent();
    }
}

int TrafficGraphWidget::getGraphRangeMins() const
{
    return nMins;
}

void TrafficGraphWidget::paintPath(QPainterPath &path, QQueue<float> &samples)
{
    int h = height() - YMARGIN * 2, w = width() - XMARGIN * 2;
    int sampleCount = samples.size(), x = XMARGIN + w, y;
    if(sampleCount > 0) {
        path.moveTo(x, YMARGIN + h);
        for(int i = 0; i < sampleCount; ++i) {
            x = XMARGIN + w - w * i / DESIRED_SAMPLES;
            y = YMARGIN + h - (int)(h * samples.at(i) / fMax);
            path.lineTo(x, y);
        }
        path.lineTo(x, YMARGIN + h);
    }
}

void TrafficGraphWidget::paintEvent(QPaintEvent *)
{
    QPainter painter(this);

    QColor background_color;
    QColor axisCol;

    // This is inelegant, but the easiest way to get the traffic graph to respect the stylesheets.
    // Qt does not provide an easy way to use stylesheets with the low level QPainter class.
    if (this->clientModel->getOptionsModel()->getCurrentStyle() == "dark")
    {
        background_color.setRgb(26, 38, 50);
        axisCol.setRgb(174, 180, 182);
    }
    else
    {
        background_color.setRgb(235, 236, 238);
        axisCol.setRgb(88, 92, 107);
    }

    painter.fillRect(rect(), background_color);

    if(fMax <= 0.0f) return;

    int h = height() - YMARGIN * 2;
    painter.setPen(axisCol);
    painter.drawLine(XMARGIN, YMARGIN + h, width() - XMARGIN, YMARGIN + h);

    // decide what order of magnitude we are
    int base = floor(log10(fMax));
    float val = pow(10.0f, base);

    // draw lines
    painter.setPen(axisCol);
    painter.drawText(XMARGIN, YMARGIN + h - h * val / fMax, QString("%1 kB/s").arg(val));
    for(float y = val; y < fMax; y += val) {
        int yy = YMARGIN + h - h * y / fMax;
        painter.drawLine(XMARGIN, yy, width() - XMARGIN, yy);
    }
    // if we drew 3 or fewer lines, break them up at the next lower order of magnitude
    if(fMax / val <= 3.0f) {
        axisCol = axisCol.darker();
        val = pow(10.0f, base - 1);
        painter.setPen(axisCol);
        painter.drawText(XMARGIN, YMARGIN + h - h * val / fMax, QString("%1 kB/s").arg(val));
        int count = 1;
        for(float y = val; y < fMax; y += val, count++) {
            // don't overwrite lines drawn above
            if(count % 10 == 0)
                continue;
            int yy = YMARGIN + h - h * y / fMax;
            painter.drawLine(XMARGIN, yy, width() - XMARGIN, yy);
        }
    }

    if(!vSamplesIn.empty()) {
        QPainterPath p;
        paintPath(p, vSamplesIn);
        painter.fillPath(p, QColor(0, 255, 0, 128));
        painter.setPen(Qt::green);
        painter.drawPath(p);
    }
    if(!vSamplesOut.empty()) {
        QPainterPath p;
        paintPath(p, vSamplesOut);
        painter.fillPath(p, QColor(255, 0, 0, 128));
        painter.setPen(Qt::red);
        painter.drawPath(p);
    }
}

void TrafficGraphWidget::updateRates()
{
    if(!clientModel) return;

    quint64 bytesIn = clientModel->getTotalBytesRecv(),
            bytesOut = clientModel->getTotalBytesSent();
    float inRate = (bytesIn - nLastBytesIn) / 1024.0f * 1000 / timer->interval();
    float outRate = (bytesOut - nLastBytesOut) / 1024.0f * 1000 / timer->interval();
    vSamplesIn.push_front(inRate);
    vSamplesOut.push_front(outRate);
    nLastBytesIn = bytesIn;
    nLastBytesOut = bytesOut;

    while(vSamplesIn.size() > DESIRED_SAMPLES) {
        vSamplesIn.pop_back();
    }
    while(vSamplesOut.size() > DESIRED_SAMPLES) {
        vSamplesOut.pop_back();
    }

    float tmax = 0.0f;
    foreach(float f, vSamplesIn) {
        if(f > tmax) tmax = f;
    }
    foreach(float f, vSamplesOut) {
        if(f > tmax) tmax = f;
    }
    fMax = tmax;
    update();
}

void TrafficGraphWidget::setGraphRangeMins(int mins)
{
    nMins = mins;
    int msecsPerSample = nMins * 60 * 1000 / DESIRED_SAMPLES;
    timer->stop();
    timer->setInterval(msecsPerSample);

    clear();
}

void TrafficGraphWidget::clear()
{
    timer->stop();

    vSamplesOut.clear();
    vSamplesIn.clear();
    fMax = 0.0f;

    if(clientModel) {
        nLastBytesIn = clientModel->getTotalBytesRecv();
        nLastBytesOut = clientModel->getTotalBytesSent();
    }
    timer->start();
}
<commit_msg>Qt: Add antialiasing to traffic graph widget<commit_after>#include "trafficgraphwidget.h"
#include "clientmodel.h"
#include "optionsmodel.h"

#include <QPainter>
#include <QPainterPath>
#include <QColor>
#include <QTimer>

#include <cmath>

#define DESIRED_SAMPLES         800

#define XMARGIN                 10
#define YMARGIN                 10

TrafficGraphWidget::TrafficGraphWidget(QWidget *parent) :
    QWidget(parent),
    timer(0),
    fMax(0.0f),
    nMins(0),
    vSamplesIn(),
    vSamplesOut(),
    nLastBytesIn(0),
    nLastBytesOut(0),
    clientModel(0)
{
    timer = new QTimer(this);
    connect(timer, SIGNAL(timeout()), SLOT(updateRates()));
}

void TrafficGraphWidget::setClientModel(ClientModel *model)
{
    clientModel = model;
    if(model) {
        nLastBytesIn = model->getTotalBytesRecv();
        nLastBytesOut = model->getTotalBytesSent();
    }
}

int TrafficGraphWidget::getGraphRangeMins() const
{
    return nMins;
}

void TrafficGraphWidget::paintPath(QPainterPath &path, QQueue<float> &samples)
{
    int h = height() - YMARGIN * 2, w = width() - XMARGIN * 2;
    int sampleCount = samples.size(), x = XMARGIN + w, y;
    if(sampleCount > 0) {
        path.moveTo(x, YMARGIN + h);
        for(int i = 0; i < sampleCount; ++i) {
            x = XMARGIN + w - w * i / DESIRED_SAMPLES;
            y = YMARGIN + h - (int)(h * samples.at(i) / fMax);
            path.lineTo(x, y);
        }
        path.lineTo(x, YMARGIN + h);
    }
}

void TrafficGraphWidget::paintEvent(QPaintEvent *)
{
    QPainter painter(this);

    QColor background_color;
    QColor axisCol;

    // This is inelegant, but the easiest way to get the traffic graph to respect the stylesheets.
    // Qt does not provide an easy way to use stylesheets with the low level QPainter class.
    if (this->clientModel->getOptionsModel()->getCurrentStyle() == "dark")
    {
        background_color.setRgb(26, 38, 50);
        axisCol.setRgb(174, 180, 182);
    }
    else
    {
        background_color.setRgb(235, 236, 238);
        axisCol.setRgb(88, 92, 107);
    }

    painter.fillRect(rect(), background_color);

    if(fMax <= 0.0f) return;

    int h = height() - YMARGIN * 2;
    painter.setPen(axisCol);
    painter.drawLine(XMARGIN, YMARGIN + h, width() - XMARGIN, YMARGIN + h);

    // decide what order of magnitude we are
    int base = floor(log10(fMax));
    float val = pow(10.0f, base);

    // draw lines
    painter.setPen(axisCol);
    painter.drawText(XMARGIN, YMARGIN + h - h * val / fMax, QString("%1 kB/s").arg(val));
    for(float y = val; y < fMax; y += val) {
        int yy = YMARGIN + h - h * y / fMax;
        painter.drawLine(XMARGIN, yy, width() - XMARGIN, yy);
    }
    // if we drew 3 or fewer lines, break them up at the next lower order of magnitude
    if(fMax / val <= 3.0f) {
        axisCol = axisCol.darker();
        val = pow(10.0f, base - 1);
        painter.setPen(axisCol);
        painter.drawText(XMARGIN, YMARGIN + h - h * val / fMax, QString("%1 kB/s").arg(val));
        int count = 1;
        for(float y = val; y < fMax; y += val, count++) {
            // don't overwrite lines drawn above
            if(count % 10 == 0)
                continue;
            int yy = YMARGIN + h - h * y / fMax;
            painter.drawLine(XMARGIN, yy, width() - XMARGIN, yy);
        }
    }

    painter.setRenderHint(QPainter::Antialiasing);
    if(!vSamplesIn.empty()) {
        QPainterPath p;
        paintPath(p, vSamplesIn);
        painter.fillPath(p, QColor(0, 255, 0, 128));
        painter.setPen(Qt::green);
        painter.drawPath(p);
    }
    if(!vSamplesOut.empty()) {
        QPainterPath p;
        paintPath(p, vSamplesOut);
        painter.fillPath(p, QColor(255, 0, 0, 128));
        painter.setPen(Qt::red);
        painter.drawPath(p);
    }
}

void TrafficGraphWidget::updateRates()
{
    if(!clientModel) return;

    quint64 bytesIn = clientModel->getTotalBytesRecv(),
            bytesOut = clientModel->getTotalBytesSent();
    float inRate = (bytesIn - nLastBytesIn) / 1024.0f * 1000 / timer->interval();
    float outRate = (bytesOut - nLastBytesOut) / 1024.0f * 1000 / timer->interval();
    vSamplesIn.push_front(inRate);
    vSamplesOut.push_front(outRate);
    nLastBytesIn = bytesIn;
    nLastBytesOut = bytesOut;

    while(vSamplesIn.size() > DESIRED_SAMPLES) {
        vSamplesIn.pop_back();
    }
    while(vSamplesOut.size() > DESIRED_SAMPLES) {
        vSamplesOut.pop_back();
    }

    float tmax = 0.0f;
    foreach(float f, vSamplesIn) {
        if(f > tmax) tmax = f;
    }
    foreach(float f, vSamplesOut) {
        if(f > tmax) tmax = f;
    }
    fMax = tmax;
    update();
}

void TrafficGraphWidget::setGraphRangeMins(int mins)
{
    nMins = mins;
    int msecsPerSample = nMins * 60 * 1000 / DESIRED_SAMPLES;
    timer->stop();
    timer->setInterval(msecsPerSample);

    clear();
}

void TrafficGraphWidget::clear()
{
    timer->stop();

    vSamplesOut.clear();
    vSamplesIn.clear();
    fMax = 0.0f;

    if(clientModel) {
        nLastBytesIn = clientModel->getTotalBytesRecv();
        nLastBytesOut = clientModel->getTotalBytesSent();
    }
    timer->start();
}
<|endoftext|>


<commit_before>/**
 * \file
 * \brief Definitions of clocks for STM32L4
 *
 * \author Copyright (C) 2017 Kamil Szczygiel http://www.distortec.com http://www.freddiechopin.info
 *
 * \par License
 * This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. If a copy of the MPL was not
 * distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
 */

#ifndef SOURCE_CHIP_STM32_STM32L4_INCLUDE_DISTORTOS_CHIP_CLOCKS_HPP_
#define SOURCE_CHIP_STM32_STM32L4_INCLUDE_DISTORTOS_CHIP_CLOCKS_HPP_

#include "distortos/distortosConfiguration.h"

#include <cstdint>

namespace distortos
{

namespace chip
{

/*---------------------------------------------------------------------------------------------------------------------+
| global constants
+---------------------------------------------------------------------------------------------------------------------*/

/// maximum allowed APB1 (low speed) frequency, Hz
constexpr uint32_t maxApb1Frequency {80000000};

/// maximum allowed APB2 (high speed) frequency, Hz
constexpr uint32_t maxApb2Frequency {80000000};

/// SYSCLK frequency, Hz
constexpr uint32_t sysclkFrequency {CONFIG_CHIP_STM32L4_RCC_SYSCLK_FREQUENCY};

/// AHB frequency, Hz
constexpr uint32_t ahbFrequency {sysclkFrequency / CONFIG_CHIP_STM32L4_RCC_HPRE};

/// APB1 frequency, Hz
constexpr uint32_t apb1Frequency {ahbFrequency / CONFIG_CHIP_STM32L4_RCC_PPRE1};

static_assert(apb1Frequency <= maxApb1Frequency, "Invalid APB1 (low speed) frequency!");

/// APB2 frequency, Hz
constexpr uint32_t apb2Frequency {ahbFrequency / CONFIG_CHIP_STM32L4_RCC_PPRE2};

static_assert(apb2Frequency <= maxApb2Frequency, "Invalid APB2 (high speed) frequency!");

}	// namespace chip

}	// namespace distortos

#endif	// SOURCE_CHIP_STM32_STM32L4_INCLUDE_DISTORTOS_CHIP_CLOCKS_HPP_
<commit_msg>Extend STM32L4's clocks.hpp in preparation for clock configuration<commit_after>/**
 * \file
 * \brief Definitions of clocks for STM32L4
 *
 * \author Copyright (C) 2017 Kamil Szczygiel http://www.distortec.com http://www.freddiechopin.info
 *
 * \par License
 * This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. If a copy of the MPL was not
 * distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
 */

#ifndef SOURCE_CHIP_STM32_STM32L4_INCLUDE_DISTORTOS_CHIP_CLOCKS_HPP_
#define SOURCE_CHIP_STM32_STM32L4_INCLUDE_DISTORTOS_CHIP_CLOCKS_HPP_

#include "distortos/distortosConfiguration.h"

#include <cstdint>

namespace distortos
{

namespace chip
{

/*---------------------------------------------------------------------------------------------------------------------+
| global constants
+---------------------------------------------------------------------------------------------------------------------*/

/// minimum allowed values for HSE frequency, Hz
/// [0] - "HSE Clock Bypass" disabled
/// [1] - "HSE Clock Bypass" enabled
constexpr uint32_t minHseFrequencies[2] {4000000, 1};

/// maximum allowed values for HSE frequency, Hz
/// [...][0] - voltage scaling range 1
/// [...][1] - voltage scaling range 2
/// [0][...] - "HSE Clock Bypass" disabled
/// [1][...] - "HSE Clock Bypass" enabled
constexpr uint32_t maxHseFrequencies[2][2]
{
		{48000000, 48000000},
		{48000000, 26000000},
};

/// HSI16 clock frequency, Hz
constexpr uint32_t hsi16Frequency {16000000};

/// MSI frequencies, Hz
/// [0] - range 0
/// [1] - range 1
/// [2] - range 2
/// [3] - range 3
/// [4] - range 4
/// [5] - range 5
/// [6] - range 6
/// [7] - range 7
/// [8] - range 8
/// [9] - range 9
/// [10] - range 10
/// [11] - range 11
constexpr uint32_t msiFrequencies[12]
{
		100000,
		200000,
		400000,
		800000,
		1000000,
		2000000,
		4000000,
		8000000,
		16000000,
		24000000,
		32000000,
		48000000,
};

/// minimum allowed value for VCO input frequency, Hz
constexpr uint32_t minVcoInFrequency {4000000};

/// maximum allowed value for VCO input frequency, Hz
constexpr uint32_t maxVcoInFrequency {16000000};

/// minimum allowed value for VCO output frequency, Hz
constexpr uint32_t minVcoOutFrequency {64000000};

/// maximum allowed values for VCO output frequency, Hz
/// [0] - voltage scaling range 1
/// [1] - voltage scaling range 2
constexpr uint32_t maxVcoOutFrequency[2] {344000000, 128000000};

/// minimum allowed value for PLL "P" output frequency, Hz
constexpr uint32_t minPllpOutFrequency {2064500};

/// maximum allowed values for PLL "P" output frequency, Hz
/// [0] - voltage scaling range 1
/// [1] - voltage scaling range 2
constexpr uint32_t maxPllpOutFrequencies[2] {80000000, 26000000};

/// minimum allowed value for PLL "Q" output frequency, Hz
constexpr uint32_t minPllqOutFrequency {8000000};

/// maximum allowed values for PLL "Q" output frequency, Hz
/// [0] - voltage scaling range 1
/// [1] - voltage scaling range 2
constexpr uint32_t maxPllqOutFrequencies[2] {80000000, 26000000};

/// minimum allowed value for PLL "R" output frequency, Hz
constexpr uint32_t minPllrOutFrequency {8000000};

/// maximum allowed values for PLL "R" output frequency, Hz
/// [0] - voltage scaling range 1
/// [1] - voltage scaling range 2
constexpr uint32_t maxPllrOutFrequencies[2] {80000000, 26000000};

/// maximum allowed values for SYSCLK frequency, Hz
/// [0] - voltage scaling range 1
/// [1] - voltage scaling range 2
constexpr uint32_t maxSysclkFrequencies[2] {80000000, 26000000};

/// maximum allowed values for AHB frequency, Hz
/// [0] - voltage scaling range 1
/// [1] - voltage scaling range 2
constexpr uint32_t maxAhbFrequencies[2] {80000000, 26000000};

/// maximum allowed values for APB1 (low speed) frequency, Hz
/// [0] - voltage scaling range 1
/// [1] - voltage scaling range 2
constexpr uint32_t maxApb1Frequencies[2] {80000000, 26000000};

/// maximum allowed values for APB2 (high speed) frequency, Hz
/// [0] - voltage scaling range 1
/// [1] - voltage scaling range 2
constexpr uint32_t maxApb2Frequencies[2] {80000000, 26000000};

#ifdef CONFIG_CHIP_STM32L4_STANDARD_CLOCK_CONFIGURATION_ENABLE

/// voltage scaling range index for arrays
constexpr uint8_t voltageScalingRangeIndex {CONFIG_CHIP_STM32L4_PWR_VOLTAGE_SCALING_RANGE - 1};

#ifdef CONFIG_CHIP_STM32L4_RCC_HSE_ENABLE

/// HSE frequency, Hz
constexpr uint32_t hseFrequency {CONFIG_CHIP_STM32L4_RCC_HSE_FREQUENCY};

/// HSE clock bypass
#ifdef CONFIG_CHIP_STM32L4_RCC_HSE_CLOCK_BYPASS
constexpr bool hseClockBypass {true};
#else	// !def CONFIG_CHIP_STM32L4_RCC_HSE_CLOCK_BYPASS
constexpr bool hseClockBypass {false};
#endif	// !def CONFIG_CHIP_STM32L4_RCC_HSE_CLOCK_BYPASS

static_assert(minHseFrequencies[hseClockBypass] <= hseFrequency &&
		hseFrequency <= maxHseFrequencies[hseClockBypass][voltageScalingRangeIndex], "Invalid HSE frequency!");

#endif	// def CONFIG_CHIP_STM32L4_RCC_HSE_ENABLE

#ifdef CONFIG_CHIP_STM32L4_RCC_MSI_ENABLE

/// MSI frequency, Hz
constexpr uint32_t msiFrequency {msiFrequencies[CONFIG_CHIP_STM32L4_RCC_MSI_RANGE]};

#endif	// def CONFIG_CHIP_STM32L4_RCC_MSI_ENABLE

#ifdef CONFIG_CHIP_STM32L4_RCC_PLL_ENABLE

/// PLL input frequency, Hz
#if defined(CONFIG_CHIP_STM32L4_RCC_PLLSRC_HSE)
constexpr uint32_t pllInFrequency {hseFrequency};
#elif defined(CONFIG_CHIP_STM32L4_RCC_PLLSRC_HSI16)
constexpr uint32_t pllInFrequency {hsi16Frequency};
#elif defined(CONFIG_CHIP_STM32L4_RCC_PLLSRC_MSI)
constexpr uint32_t pllInFrequency {msiFrequency};
#endif	// defined(CONFIG_CHIP_STM32L4_RCC_PLLSRC_MSI)

/// VCO input frequency, Hz
constexpr uint32_t vcoInFrequency {pllInFrequency / CONFIG_CHIP_STM32L4_RCC_PLLM};

static_assert(minVcoInFrequency <= vcoInFrequency && vcoInFrequency <= maxVcoInFrequency,
		"Invalid VCO input frequency!");

/// VCO output frequency, Hz
constexpr uint32_t vcoOutFrequency {vcoInFrequency * CONFIG_CHIP_STM32L4_RCC_PLLN};

static_assert(minVcoOutFrequency <= vcoOutFrequency && vcoOutFrequency <= maxVcoOutFrequency[voltageScalingRangeIndex],
		"Invalid VCO output frequency!");

/// PLL "P" output frequency, Hz
constexpr uint32_t pllpOutFrequency {vcoOutFrequency / CONFIG_CHIP_STM32L4_RCC_PLLP};

static_assert(minPllpOutFrequency <= pllpOutFrequency &&
		pllpOutFrequency <= maxPllpOutFrequencies[voltageScalingRangeIndex], "Invalid PLL \"P\" output frequency!");

/// PLL "Q" output frequency, Hz
constexpr uint32_t pllqOutFrequency {vcoOutFrequency / CONFIG_CHIP_STM32L4_RCC_PLLQ};

static_assert(minPllqOutFrequency <= pllqOutFrequency &&
		pllqOutFrequency <= maxPllqOutFrequencies[voltageScalingRangeIndex], "Invalid PLL \"Q\" output frequency!");

/// PLL "R" output frequency, Hz
constexpr uint32_t pllrOutFrequency {vcoOutFrequency / CONFIG_CHIP_STM32L4_RCC_PLLR};

static_assert(minPllrOutFrequency <= pllrOutFrequency &&
		pllrOutFrequency <= maxPllrOutFrequencies[voltageScalingRangeIndex], "Invalid PLL \"R\" output frequency!");

#endif	// def CONFIG_CHIP_STM32L4_RCC_PLL_ENABLE

/// SYSCLK frequency, Hz
#if defined(CONFIG_CHIP_STM32L4_RCC_SYSCLK_HSE)
constexpr uint32_t sysclkFrequency {hseFrequency};
#elif defined(CONFIG_CHIP_STM32L4_RCC_SYSCLK_HSI16)
constexpr uint32_t sysclkFrequency {hsi16Frequency};
#elif defined(CONFIG_CHIP_STM32L4_RCC_SYSCLK_MSI)
constexpr uint32_t sysclkFrequency {msiFrequency};
#elif defined(CONFIG_CHIP_STM32L4_RCC_SYSCLK_PLL)
constexpr uint32_t sysclkFrequency {pllrOutFrequency};
#else
#error "All SYSCLK sources disabled!"
#endif

#else	// !def CONFIG_CHIP_STM32L4_STANDARD_CLOCK_CONFIGURATION_ENABLE

/// voltage scaling range index for arrays
constexpr uint8_t voltageScalingRangeIndex {0};

/// SYSCLK frequency, Hz
constexpr uint32_t sysclkFrequency {CONFIG_CHIP_STM32L4_RCC_SYSCLK_FREQUENCY};

#endif	// !def CONFIG_CHIP_STM32L4_STANDARD_CLOCK_CONFIGURATION_ENABLE

static_assert(sysclkFrequency <= maxSysclkFrequencies[voltageScalingRangeIndex], "Invalid SYSCLK frequency!");

/// AHB frequency, Hz
constexpr uint32_t ahbFrequency {sysclkFrequency / CONFIG_CHIP_STM32L4_RCC_HPRE};

static_assert(ahbFrequency <= maxAhbFrequencies[voltageScalingRangeIndex], "Invalid AHB frequency!");

/// APB1 frequency, Hz
constexpr uint32_t apb1Frequency {ahbFrequency / CONFIG_CHIP_STM32L4_RCC_PPRE1};

static_assert(apb1Frequency <= maxApb1Frequencies[voltageScalingRangeIndex], "Invalid APB1 (low speed) frequency!");

/// APB2 frequency, Hz
constexpr uint32_t apb2Frequency {ahbFrequency / CONFIG_CHIP_STM32L4_RCC_PPRE2};

static_assert(apb2Frequency <= maxApb2Frequencies[voltageScalingRangeIndex], "Invalid APB2 (high speed) frequency!");

}	// namespace chip

}	// namespace distortos

#endif	// SOURCE_CHIP_STM32_STM32L4_INCLUDE_DISTORTOS_CHIP_CLOCKS_HPP_
<|endoftext|>


<commit_before>/*************************************************************************
 *
 * REALM CONFIDENTIAL
 * __________________
 *
 *  [2011] - [2015] Realm Inc
 *  All Rights Reserved.
 *
 * NOTICE:  All information contained herein is, and remains
 * the property of Realm Incorporated and its suppliers,
 * if any.  The intellectual and technical concepts contained
 * herein are proprietary to Realm Incorporated
 * and its suppliers and may be covered by U.S. and Foreign Patents,
 * patents in process, and are protected by trade secret or copyright law.
 * Dissemination of this information or reproduction of this material
 * is strictly forbidden unless prior written permission is obtained
 * from Realm Incorporated.
 *
 **************************************************************************/
#ifndef REALM_COLUMN_DATETIME_HPP
#define REALM_COLUMN_DATETIME_HPP

#include <realm/column.hpp>

namespace realm {

struct NewDate {
    NewDate(int64_t seconds, int32_t nanoseconds) : m_seconds(seconds), m_nanoseconds(nanoseconds), m_is_null(false) { }
    NewDate(const null&) : m_is_null(true) { }
    NewDate() : NewDate(null()) { }

    bool is_null() const { return m_is_null; }
    bool operator == (const NewDate& rhs) const { return m_seconds == rhs.m_seconds && m_nanoseconds == rhs.m_nanoseconds; }
    bool operator != (const NewDate& rhs) const { return m_seconds != rhs.m_seconds || m_nanoseconds != rhs.m_nanoseconds; }
    bool operator > (const NewDate& rhs) const { return (m_seconds > rhs.m_seconds) || (m_seconds == rhs.m_seconds && m_nanoseconds > rhs.m_nanoseconds); }
    bool operator < (const NewDate& rhs) const { return (m_seconds < rhs.m_seconds) || (m_seconds == rhs.m_seconds && m_nanoseconds < rhs.m_nanoseconds); }
    NewDate& operator = (const NewDate& rhs) = default;

    int64_t m_seconds;
    int32_t m_nanoseconds;
    bool m_is_null;
};

class DateTimeColumn : public ColumnBase, public ColumnTemplate<NewDate> {
public:
    DateTimeColumn();
    /// Get the number of entries in this column. This operation is relatively
    /// slow.
    size_t size() const noexcept override;
    /// Whether or not this column is nullable.
    bool is_nullable() const noexcept override;
    /// Whether or not the value at \a row_ndx is NULL. If the column is not
    /// nullable, always returns false.
    bool is_null(size_t row_ndx) const noexcept override;
    /// Sets the value at \a row_ndx to be NULL.
    /// \throw LogicError Thrown if this column is not nullable.
    void set_null(size_t row_ndx) override;
    void insert_rows(size_t row_ndx, size_t num_rows_to_insert, size_t prior_num_rows, bool nullable) override;
    void erase_rows(size_t row_ndx, size_t num_rows_to_erase, size_t prior_num_rows,
                    bool broken_reciprocal_backlinks) override;
    void move_last_row_over(size_t row_ndx, size_t prior_num_rows,
                            bool broken_reciprocal_backlinks) override;
    void clear(size_t num_rows, bool broken_reciprocal_backlinks) override;
    void swap_rows(size_t row_ndx_1, size_t row_ndx_2) override;
    void destroy() noexcept override;
    StringData get_index_data(size_t, StringIndex::StringConversionBuffer& buffer) const noexcept override;
    Allocator& get_alloc() const noexcept override;
    /// Returns the 'ref' of the root array.
    ref_type get_ref() const noexcept override;
    MemRef get_mem() const noexcept override;
    void replace_root_array(std::unique_ptr<Array> leaf) override;
    MemRef clone_deep(Allocator& alloc) const override;
    void detach() override;
    bool is_attached() const noexcept override;
    ref_type write(size_t slice_offset, size_t slice_size, size_t table_size, _impl::OutputStream&) const override;
    void set_parent(ArrayParent*, size_t ndx_in_parent) noexcept override;
    size_t get_ndx_in_parent() const noexcept override;
    void set_ndx_in_parent(size_t ndx_in_parent) noexcept override;
    void update_from_parent(size_t old_baseline) noexcept override;
    void refresh_accessor_tree(size_t new_col_ndx, const Spec&) override;
#ifdef REALM_DEBUG
    void verify() const override;
    void to_dot(std::ostream&, StringData title = StringData()) const override;
    void do_dump_node_structure(std::ostream&, int level) const override;
    void leaf_to_dot(MemRef, ArrayParent*, size_t ndx_in_parent, std::ostream&) const override;
#endif
    void add(const NewDate& ndt = NewDate{});
    NewDate get(size_t row_ndx) const noexcept;
    NewDate get_val(size_t row_ndx) const override;
    void set(size_t row_ndx, const NewDate& ndt);
private:
    IntNullColumn m_seconds;
    IntegerColumn m_nanoseconds;
};

// Implementation

inline DateTimeColumn::DateTimeColumn() :
    m_seconds(Allocator::get_default(), IntNullColumn::create(Allocator::get_default())),
    m_nanoseconds(Allocator::get_default(), IntegerColumn::create(Allocator::get_default()))
{
}

/// Get the number of entries in this column. This operation is relatively
/// slow.
inline size_t DateTimeColumn::size() const noexcept
{
    // FIXME: Consider debug asserts on the columns having the same size
    return m_seconds.size();
}

/// Whether or not this column is nullable.
inline bool DateTimeColumn::is_nullable() const noexcept
{
    return m_seconds.is_nullable();
}

/// Whether or not the value at \a row_ndx is NULL. If the column is not
/// nullable, always returns false.
inline bool DateTimeColumn::is_null(size_t row_ndx) const noexcept
{
    return m_seconds.is_null(row_ndx);
}

/// Sets the value at \a row_ndx to be NULL.
/// \throw LogicError Thrown if this column is not nullable.
inline void DateTimeColumn::set_null(size_t row_ndx)
{
    m_seconds.set_null(row_ndx);
}

inline void DateTimeColumn::insert_rows(size_t row_ndx, size_t num_rows_to_insert, size_t prior_num_rows,
                                        bool nullable)
{
    m_seconds.insert_rows(row_ndx, num_rows_to_insert, prior_num_rows, nullable);
    m_nanoseconds.insert_rows(row_ndx, num_rows_to_insert, prior_num_rows, nullable);
}

inline void DateTimeColumn::erase_rows(size_t row_ndx, size_t num_rows_to_erase, size_t prior_num_rows,
                                       bool broken_reciprocal_backlinks)
{
    m_seconds.erase_rows(row_ndx, num_rows_to_erase, prior_num_rows, broken_reciprocal_backlinks);
    m_nanoseconds.erase_rows(row_ndx, num_rows_to_erase, prior_num_rows, broken_reciprocal_backlinks);
}

inline void DateTimeColumn::move_last_row_over(size_t row_ndx, size_t prior_num_rows,
                                               bool broken_reciprocal_backlinks)
{
    m_seconds.move_last_row_over(row_ndx, prior_num_rows, broken_reciprocal_backlinks);
    m_nanoseconds.move_last_row_over(row_ndx, prior_num_rows, broken_reciprocal_backlinks);
}

inline void DateTimeColumn::clear(size_t num_rows, bool broken_reciprocal_backlinks)
{
    m_seconds.clear(num_rows, broken_reciprocal_backlinks);
    m_nanoseconds.clear(num_rows, broken_reciprocal_backlinks);
}

inline void DateTimeColumn::swap_rows(size_t row_ndx_1, size_t row_ndx_2)
{
    m_seconds.swap_rows(row_ndx_1, row_ndx_2);
    m_nanoseconds.swap_rows(row_ndx_1, row_ndx_2);
}

inline void DateTimeColumn::destroy() noexcept
{
    m_seconds.destroy();
    m_nanoseconds.destroy();
}

inline StringData DateTimeColumn::get_index_data(size_t, StringIndex::StringConversionBuffer& /*buffer*/) const noexcept
{
    // FIXME: Dummy implementation
    return null();
}

inline Allocator& DateTimeColumn::get_alloc() const noexcept
{
    // FIXME: Dummy implementation
    return Allocator::get_default();
}

inline ref_type DateTimeColumn::get_ref() const noexcept
{
    // FIXME: Dummy implementation
    return 0;
}

inline MemRef DateTimeColumn::get_mem() const noexcept
{
    // FIXME: Dummy implementation
    return MemRef();
}

inline void DateTimeColumn::replace_root_array(std::unique_ptr<Array> /*leaf*/)
{
    // FIXME: Dummy implementation
}

inline MemRef DateTimeColumn::clone_deep(Allocator& /*alloc*/) const
{
    // FIXME: Dummy implementation
    return MemRef();
}

inline void DateTimeColumn::detach()
{
    m_seconds.detach();
    m_nanoseconds.detach();
}

inline bool DateTimeColumn::is_attached() const noexcept
{
    // FIXME: Assert on both columns having same attached state?
    return m_seconds.is_attached();
}

inline ref_type DateTimeColumn::write(size_t /*slice_offset*/, size_t /*slice_size*/, size_t /*table_size*/,
                                      _impl::OutputStream&) const
{
    // FIXME: Dummy implementation
    return 0;
}

inline void DateTimeColumn::set_parent(ArrayParent*, size_t /*ndx_in_parent*/) noexcept
{
    // FIXME: Dummy implementation
}

inline size_t DateTimeColumn::get_ndx_in_parent() const noexcept
{
    // FIXME: Dummy implementation
    return 0;
}

inline void DateTimeColumn::set_ndx_in_parent(size_t /*ndx_in_parent*/) noexcept
{
    // FIXME: Dummy implementation
}

inline void DateTimeColumn::update_from_parent(size_t /*old_baseline*/) noexcept
{
    // FIXME: Dummy implementation
}

inline void DateTimeColumn::refresh_accessor_tree(size_t /*new_col_ndx*/, const Spec&)
{
    // FIXME: Dummy implementation
}

#ifdef REALM_DEBUG

inline void DateTimeColumn::verify() const
{
    // FIXME: Dummy implementation
}

inline void DateTimeColumn::to_dot(std::ostream&, StringData /*title*/) const
{
    // FIXME: Dummy implementation
}

inline void DateTimeColumn::do_dump_node_structure(std::ostream&, int /*level*/) const
{
    // FIXME: Dummy implementation
}

inline void DateTimeColumn::leaf_to_dot(MemRef, ArrayParent*, size_t /*ndx_in_parent*/, std::ostream&) const
{
    // FIXME: Dummy implementation
}

#endif

inline void DateTimeColumn::add(const NewDate& ndt)
{
    util::Optional<int64_t> seconds = ndt.is_null() ? util::none : util::make_optional(ndt.m_seconds);
    int32_t nanoseconds = ndt.is_null() ? 0 : ndt.m_nanoseconds;
    m_seconds.add(seconds);
    m_nanoseconds.add(nanoseconds);
}

inline NewDate DateTimeColumn::get(size_t row_ndx) const noexcept
{
    util::Optional<int64_t> seconds = m_seconds.get(row_ndx);
    return seconds ? NewDate(*seconds, int32_t(m_nanoseconds.get(row_ndx))) : NewDate(null());
}

inline NewDate DateTimeColumn::get_val(size_t row_ndx) const
{
    return get(row_ndx);
}

inline void DateTimeColumn::set(size_t row_ndx, const NewDate& ndt)
{
    util::Optional<int64_t> seconds = ndt.is_null() ? util::none : util::make_optional(ndt.m_seconds);
    int32_t nanoseconds = ndt.is_null() ? 0 : ndt.m_nanoseconds;
    m_seconds.set(row_ndx, seconds);
    m_nanoseconds.set(row_ndx, nanoseconds);
}

} // namespace realm

#endif // REALM_COLUMN_DATETIME_HPP
<commit_msg>Minor refactoring; extracted expression to variable<commit_after>/*************************************************************************
 *
 * REALM CONFIDENTIAL
 * __________________
 *
 *  [2011] - [2015] Realm Inc
 *  All Rights Reserved.
 *
 * NOTICE:  All information contained herein is, and remains
 * the property of Realm Incorporated and its suppliers,
 * if any.  The intellectual and technical concepts contained
 * herein are proprietary to Realm Incorporated
 * and its suppliers and may be covered by U.S. and Foreign Patents,
 * patents in process, and are protected by trade secret or copyright law.
 * Dissemination of this information or reproduction of this material
 * is strictly forbidden unless prior written permission is obtained
 * from Realm Incorporated.
 *
 **************************************************************************/
#ifndef REALM_COLUMN_DATETIME_HPP
#define REALM_COLUMN_DATETIME_HPP

#include <realm/column.hpp>

namespace realm {

struct NewDate {
    NewDate(int64_t seconds, int32_t nanoseconds) : m_seconds(seconds), m_nanoseconds(nanoseconds), m_is_null(false) { }
    NewDate(const null&) : m_is_null(true) { }
    NewDate() : NewDate(null()) { }

    bool is_null() const { return m_is_null; }
    bool operator == (const NewDate& rhs) const { return m_seconds == rhs.m_seconds && m_nanoseconds == rhs.m_nanoseconds; }
    bool operator != (const NewDate& rhs) const { return m_seconds != rhs.m_seconds || m_nanoseconds != rhs.m_nanoseconds; }
    bool operator > (const NewDate& rhs) const { return (m_seconds > rhs.m_seconds) || (m_seconds == rhs.m_seconds && m_nanoseconds > rhs.m_nanoseconds); }
    bool operator < (const NewDate& rhs) const { return (m_seconds < rhs.m_seconds) || (m_seconds == rhs.m_seconds && m_nanoseconds < rhs.m_nanoseconds); }
    NewDate& operator = (const NewDate& rhs) = default;

    int64_t m_seconds;
    int32_t m_nanoseconds;
    bool m_is_null;
};

class DateTimeColumn : public ColumnBase, public ColumnTemplate<NewDate> {
public:
    DateTimeColumn();
    /// Get the number of entries in this column. This operation is relatively
    /// slow.
    size_t size() const noexcept override;
    /// Whether or not this column is nullable.
    bool is_nullable() const noexcept override;
    /// Whether or not the value at \a row_ndx is NULL. If the column is not
    /// nullable, always returns false.
    bool is_null(size_t row_ndx) const noexcept override;
    /// Sets the value at \a row_ndx to be NULL.
    /// \throw LogicError Thrown if this column is not nullable.
    void set_null(size_t row_ndx) override;
    void insert_rows(size_t row_ndx, size_t num_rows_to_insert, size_t prior_num_rows, bool nullable) override;
    void erase_rows(size_t row_ndx, size_t num_rows_to_erase, size_t prior_num_rows,
                    bool broken_reciprocal_backlinks) override;
    void move_last_row_over(size_t row_ndx, size_t prior_num_rows,
                            bool broken_reciprocal_backlinks) override;
    void clear(size_t num_rows, bool broken_reciprocal_backlinks) override;
    void swap_rows(size_t row_ndx_1, size_t row_ndx_2) override;
    void destroy() noexcept override;
    StringData get_index_data(size_t, StringIndex::StringConversionBuffer& buffer) const noexcept override;
    Allocator& get_alloc() const noexcept override;
    /// Returns the 'ref' of the root array.
    ref_type get_ref() const noexcept override;
    MemRef get_mem() const noexcept override;
    void replace_root_array(std::unique_ptr<Array> leaf) override;
    MemRef clone_deep(Allocator& alloc) const override;
    void detach() override;
    bool is_attached() const noexcept override;
    ref_type write(size_t slice_offset, size_t slice_size, size_t table_size, _impl::OutputStream&) const override;
    void set_parent(ArrayParent*, size_t ndx_in_parent) noexcept override;
    size_t get_ndx_in_parent() const noexcept override;
    void set_ndx_in_parent(size_t ndx_in_parent) noexcept override;
    void update_from_parent(size_t old_baseline) noexcept override;
    void refresh_accessor_tree(size_t new_col_ndx, const Spec&) override;
#ifdef REALM_DEBUG
    void verify() const override;
    void to_dot(std::ostream&, StringData title = StringData()) const override;
    void do_dump_node_structure(std::ostream&, int level) const override;
    void leaf_to_dot(MemRef, ArrayParent*, size_t ndx_in_parent, std::ostream&) const override;
#endif
    void add(const NewDate& ndt = NewDate{});
    NewDate get(size_t row_ndx) const noexcept;
    NewDate get_val(size_t row_ndx) const override;
    void set(size_t row_ndx, const NewDate& ndt);
private:
    IntNullColumn m_seconds;
    IntegerColumn m_nanoseconds;
};

// Implementation

inline DateTimeColumn::DateTimeColumn() :
    m_seconds(Allocator::get_default(), IntNullColumn::create(Allocator::get_default())),
    m_nanoseconds(Allocator::get_default(), IntegerColumn::create(Allocator::get_default()))
{
}

/// Get the number of entries in this column. This operation is relatively
/// slow.
inline size_t DateTimeColumn::size() const noexcept
{
    // FIXME: Consider debug asserts on the columns having the same size
    return m_seconds.size();
}

/// Whether or not this column is nullable.
inline bool DateTimeColumn::is_nullable() const noexcept
{
    return m_seconds.is_nullable();
}

/// Whether or not the value at \a row_ndx is NULL. If the column is not
/// nullable, always returns false.
inline bool DateTimeColumn::is_null(size_t row_ndx) const noexcept
{
    return m_seconds.is_null(row_ndx);
}

/// Sets the value at \a row_ndx to be NULL.
/// \throw LogicError Thrown if this column is not nullable.
inline void DateTimeColumn::set_null(size_t row_ndx)
{
    m_seconds.set_null(row_ndx);
}

inline void DateTimeColumn::insert_rows(size_t row_ndx, size_t num_rows_to_insert, size_t prior_num_rows,
                                        bool nullable)
{
    m_seconds.insert_rows(row_ndx, num_rows_to_insert, prior_num_rows, nullable);
    m_nanoseconds.insert_rows(row_ndx, num_rows_to_insert, prior_num_rows, nullable);
}

inline void DateTimeColumn::erase_rows(size_t row_ndx, size_t num_rows_to_erase, size_t prior_num_rows,
                                       bool broken_reciprocal_backlinks)
{
    m_seconds.erase_rows(row_ndx, num_rows_to_erase, prior_num_rows, broken_reciprocal_backlinks);
    m_nanoseconds.erase_rows(row_ndx, num_rows_to_erase, prior_num_rows, broken_reciprocal_backlinks);
}

inline void DateTimeColumn::move_last_row_over(size_t row_ndx, size_t prior_num_rows,
                                               bool broken_reciprocal_backlinks)
{
    m_seconds.move_last_row_over(row_ndx, prior_num_rows, broken_reciprocal_backlinks);
    m_nanoseconds.move_last_row_over(row_ndx, prior_num_rows, broken_reciprocal_backlinks);
}

inline void DateTimeColumn::clear(size_t num_rows, bool broken_reciprocal_backlinks)
{
    m_seconds.clear(num_rows, broken_reciprocal_backlinks);
    m_nanoseconds.clear(num_rows, broken_reciprocal_backlinks);
}

inline void DateTimeColumn::swap_rows(size_t row_ndx_1, size_t row_ndx_2)
{
    m_seconds.swap_rows(row_ndx_1, row_ndx_2);
    m_nanoseconds.swap_rows(row_ndx_1, row_ndx_2);
}

inline void DateTimeColumn::destroy() noexcept
{
    m_seconds.destroy();
    m_nanoseconds.destroy();
}

inline StringData DateTimeColumn::get_index_data(size_t, StringIndex::StringConversionBuffer& /*buffer*/) const noexcept
{
    // FIXME: Dummy implementation
    return null();
}

inline Allocator& DateTimeColumn::get_alloc() const noexcept
{
    // FIXME: Dummy implementation
    return Allocator::get_default();
}

inline ref_type DateTimeColumn::get_ref() const noexcept
{
    // FIXME: Dummy implementation
    return 0;
}

inline MemRef DateTimeColumn::get_mem() const noexcept
{
    // FIXME: Dummy implementation
    return MemRef();
}

inline void DateTimeColumn::replace_root_array(std::unique_ptr<Array> /*leaf*/)
{
    // FIXME: Dummy implementation
}

inline MemRef DateTimeColumn::clone_deep(Allocator& /*alloc*/) const
{
    // FIXME: Dummy implementation
    return MemRef();
}

inline void DateTimeColumn::detach()
{
    m_seconds.detach();
    m_nanoseconds.detach();
}

inline bool DateTimeColumn::is_attached() const noexcept
{
    // FIXME: Assert on both columns having same attached state?
    return m_seconds.is_attached();
}

inline ref_type DateTimeColumn::write(size_t /*slice_offset*/, size_t /*slice_size*/, size_t /*table_size*/,
                                      _impl::OutputStream&) const
{
    // FIXME: Dummy implementation
    return 0;
}

inline void DateTimeColumn::set_parent(ArrayParent*, size_t /*ndx_in_parent*/) noexcept
{
    // FIXME: Dummy implementation
}

inline size_t DateTimeColumn::get_ndx_in_parent() const noexcept
{
    // FIXME: Dummy implementation
    return 0;
}

inline void DateTimeColumn::set_ndx_in_parent(size_t /*ndx_in_parent*/) noexcept
{
    // FIXME: Dummy implementation
}

inline void DateTimeColumn::update_from_parent(size_t /*old_baseline*/) noexcept
{
    // FIXME: Dummy implementation
}

inline void DateTimeColumn::refresh_accessor_tree(size_t /*new_col_ndx*/, const Spec&)
{
    // FIXME: Dummy implementation
}

#ifdef REALM_DEBUG

inline void DateTimeColumn::verify() const
{
    // FIXME: Dummy implementation
}

inline void DateTimeColumn::to_dot(std::ostream&, StringData /*title*/) const
{
    // FIXME: Dummy implementation
}

inline void DateTimeColumn::do_dump_node_structure(std::ostream&, int /*level*/) const
{
    // FIXME: Dummy implementation
}

inline void DateTimeColumn::leaf_to_dot(MemRef, ArrayParent*, size_t /*ndx_in_parent*/, std::ostream&) const
{
    // FIXME: Dummy implementation
}

#endif

inline void DateTimeColumn::add(const NewDate& ndt)
{
    bool is_null = ndt.is_null();
    util::Optional<int64_t> seconds = is_null ? util::none : util::make_optional(ndt.m_seconds);
    int32_t nanoseconds = is_null ? 0 : ndt.m_nanoseconds;
    m_seconds.add(seconds);
    m_nanoseconds.add(nanoseconds);
}

inline NewDate DateTimeColumn::get(size_t row_ndx) const noexcept
{
    util::Optional<int64_t> seconds = m_seconds.get(row_ndx);
    return seconds ? NewDate(*seconds, int32_t(m_nanoseconds.get(row_ndx))) : NewDate(null());
}

inline NewDate DateTimeColumn::get_val(size_t row_ndx) const
{
    return get(row_ndx);
}

inline void DateTimeColumn::set(size_t row_ndx, const NewDate& ndt)
{
    bool is_null = ndt.is_null();
    util::Optional<int64_t> seconds = is_null ? util::none : util::make_optional(ndt.m_seconds);
    int32_t nanoseconds = is_null ? 0 : ndt.m_nanoseconds;
    m_seconds.set(row_ndx, seconds);
    m_nanoseconds.set(row_ndx, nanoseconds);
}

} // namespace realm

#endif // REALM_COLUMN_DATETIME_HPP
<|endoftext|>


<commit_before>/*
@file is_transaction_safe

@Copyright Barrett Adair 2015-2017
Distributed under the Boost Software License, Version 1.0.
(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)

*/

#ifndef BOOST_CLBL_TRTS_IS_TRANSACTION_SAFE_HPP
#define BOOST_CLBL_TRTS_IS_TRANSACTION_SAFE_HPP

#include <boost/callable_traits/detail/core.hpp>

namespace boost { namespace callable_traits {

//[ is_transaction_safe_hpp
/*`[section:ref_is_transaction_safe is_transaction_safe]
[heading Header]
``#include <boost/callable_traits/is_transaction_safe.hpp>``
[heading Definition]
*/

// inherits from either std::true_type or std::false_type
template<typename T>
struct is_transaction_safe;

//<-
template<typename T>
struct is_transaction_safe : detail::traits<
    detail::shallow_decay<T>>::is_transaction_safe {

    using type = typename detail::traits<
        detail::shallow_decay<T>>::is_transaction_safe;
};

#ifdef BOOST_CLBL_TRTS_DISABLE_VARIABLE_TEMPLATES

template<typename T>
struct is_transaction_safe_v {
    static_assert(std::is_same<T, detail::dummy>::value,
        "Variable templates not supported on this compiler.");
};

#else
//->
// only available when variable templates are supported
template<typename T>
//<-
BOOST_CLBL_TRAITS_INLINE_VAR
//->
constexpr bool is_transaction_safe_v = //see below
//<-
    detail::traits<detail::shallow_decay<T>>::is_transaction_safe::value;

#endif

}} // namespace boost::callable_traits
//->

/*`
[heading Constraints]
* none
*
[heading Behavior]
* `is_transaction_safe<T>::value` is `true` when either:
  * `T` is a function type, function pointer type, function reference type, or member function pointer type where the function has a `transaction_safe` specifier
  * `T` is a function object with a non-overloaded `operator()`, where the `operator()` has a `transaction_safe` specifier
* On compilers that support variable templates, `is_transaction_safe_v<T>` is equivalent to `is_transaction_safe<T>::value`.

[heading Input/Output Examples]
[table
    [[`T`]                              [`is_transaction_safe_v<T>`]]
    [[`int() const transaction_safe`]   [`true`]]
    [[`int(*)() transaction_safe`]      [`true`]]
    [[`int(&)() transaction_safe`]      [`true`]]
    [[`int(foo::* const)() transaction_safe`] [`true`]]
    [[`int() const`]                    [`false`]]
    [[`int() volatile`]                 [`false`]]
    [[`int(foo::*)() const`]            [`false`]]
    [[`int() const`]                    [`false`]]
    [[`int() volatile`]                 [`false`]]
    [[`int() &`]                        [`false`]]
    [[`int(*)()`]                       [`false`]]
    [[`int`]                            [`false`]]
    [[`int foo::*`]                     [`false`]]
    [[`const int foo::*`]               [`false`]]
]

[heading Example Program]
[import ../example/is_transaction_safe.cpp]
[is_transaction_safe]
[endsect]
*/
//]

#endif // #ifndef BOOST_CLBL_TRTS_IS_TRANSACTION_SAFE_HPP
<commit_msg>Delete is_transaction_safe.hpp<commit_after><|endoftext|>


<commit_before>#include "connection.h"
#include "channel.cpp"

#ifndef SERVER_ROBOBO
#define SERVER_ROBOBO
Server::Server(std::string serverAddress, std::tr1::unordered_map<std::string, std::string> confVars, ModuleInterface* modFace) {
	serverName = serverAddress;
	serverConf = confVars;
	moduleData = modFace;
	std::istringstream portNumber (serverConf["port"]);
	unsigned int port;
	portNumber >> port;
	serverConnection.connectServer(serverAddress, port);
	sendLine("NICK " + serverConf["nick"]);
	sendLine("USER " + serverConf["ident"] + " here " + serverAddress + " :" + serverConf["gecos"]);
	handleData();
}

void Server::sendLine(std::string line) {
	serverConnection.sendData(line);
	std::cout << " -> " << line << std::endl;
	moduleData->callHookOut(serverName, parseLine(line));
}

std::tr1::unordered_map<std::string, std::string> Server::getInfo() {
	return serverConf;
}

std::tr1::unordered_map<char, char> Server::getPrefixes() {
	return prefix;
}

std::vector<std::vector<char> > Server::getChanModes() {
	return chanModes;
}

std::vector<char> Server::getChanTypes() {
	return chanTypes;
}

void Server::resyncChannels() {
	for (std::tr1::unordered_map<std::string, Channel>::iterator iter = inChannels.begin(); iter != inChannels.end(); iter++)
		sendLine("NAMES " + iter->first);
}

void Server::handleData() {
	std::string receivedLine = "";
	std::vector<std::string> parsedLine;
	while (true) {
		receivedLine = serverConnection.receive();
		std::cout << receivedLine << std::endl;
		parsedLine = parseLine(receivedLine);
		if (parsedLine.size() >= 1)
			moduleData->callHook(serverName, parsedLine); // call module hooks for the received message
		if (parsedLine[1] == "001") { // welcome to the network
			if (serverConf["channels"] != "")
				sendLine("JOIN " + serverConf["channels"]);
		} else if (parsedLine[1] == "005") // server features
			parse005(parsedLine);
		else if (parsedLine[1] == "332") { // channel topic
			for (std::tr1::unordered_map<std::string, Channel>::iterator it = inChannels.begin(); it != inChannels.end(); it++) {
				if (it->first == parsedLine[3])
					it->second.setTopic(parsedLine[4]);
			}
		} else if (parsedLine[1] == "353") { // NAMES reply
			for (std::tr1::unordered_map<std::string, Channel>::iterator it = inChannels.begin(); it != inChannels.end(); it++) {
				if (it->first == parsedLine[4])
					it->second.parseNames(separateBySpace(parsedLine[5]));
			}
		} else if (parsedLine[1] == "366") { // end of NAMES reply
			for (std::tr1::unordered_map<std::string, Channel>::iterator it = inChannels.begin(); it != inChannels.end(); it++) {
				if (it->first == parsedLine[3])
					it->second.numeric366();
			}
		} else if (parsedLine[1] == "MODE") {
			bool addMode = true;
			if (parsedLine[2] == serverConf["nick"]) { // if it's a user mode
				for (unsigned int i = 0; i < parsedLine[3].size(); i++) {
					if (parsedLine[3][i] == '+')
						addMode = true;
					else if (parsedLine[3][i] == '-')
						addMode = false;
					else {
						if (addMode)
							userModes.push_back(parsedLine[3][i]);
						else {
							for (std::vector<char>::iterator uModeIter = userModes.begin(); uModeIter != userModes.end(); uModeIter++) {
								if (parsedLine[3][i] == *uModeIter) {
									userModes.erase(uModeIter);
									break;
								}
							}
						}
					}
				}
			} else { // it's a channel mode
				int currParam = 4;
				for (unsigned int i = 0; i < parsedLine[3].size(); i++) {
					if (parsedLine[3][i] == '+')
						addMode = true;
					else if (parsedLine[3][i] == '-')
						addMode = false;
					else {
						bool found = false;
						int category;
						for (unsigned int j = 0; j < chanModes[0].size(); j++) {
							if (parsedLine[3][i] == chanModes[0][j]) {
								found = true;
								category = 0;
							}
						}
						if (!found) {
							for (unsigned int j = 0; j < chanModes[1].size(); j++) {
								if (parsedLine[3][i] == chanModes[1][j]) {
									found = true;
									category = 1;
								}
							}
						}
						if (!found) {
							for (unsigned int j = 0; j < chanModes[2].size(); j++) {
								if (parsedLine[3][i] == chanModes[2][j]) {
									found = true;
									category = 2;
								}
							}
						}
						if (!found) {
							for (unsigned int j = 0; j < chanModes[3].size(); j++) {
								if (parsedLine[3][i] == chanModes[3][j]) {
									found = true;
									category = 3;
								}
							}
						}
						if (!found)
							category = 4;

						if (category == 0 || category == 1 || (category == 2 && addMode)) {
							for (std::tr1::unordered_map<std::string, Channel>::iterator chanIter = inChannels.begin(); chanIter != inChannels.end(); chanIter++) {
								if (chanIter->first == parsedLine[2])
									chanIter->second.setMode(addMode, parsedLine[3][i], parsedLine[currParam++]);
							}
						} else {
							for (std::tr1::unordered_map<std::string, Channel>::iterator chanIter = inChannels.begin(); chanIter != inChannels.end(); chanIter++) {
								if (chanIter->first == parsedLine[2])
									chanIter->second.setMode(addMode, parsedLine[3][i], "");
							}
						}
					}
				}
			}
		} else if (parsedLine[1] == "NICK" && serverConf["nick"] == separateNickFromFullHostmask(parsedLine[0].substr(1))) // bot's nick changed
			serverConf["nick"] = parsedLine[2];
		else if (parsedLine[1] == "JOIN" && serverConf["nick"] == separateNickFromFullHostmask(parsedLine[0].substr(1))) // bot joined a channel
			inChannels.insert(std::pair<std::string, Channel> (parsedLine[2], Channel (this)));
		else if (parsedLine[1] == "PART" && serverConf["nick"] == separateNickFromFullHostmask(parsedLine[0].substr(1)))
			inChannels.erase(parsedLine[2]);
		else if (parsedLine[1] == "QUIT" && serverConf["nick"] == separateNickFromFullHostmask(parsedLine[0].substr(1))) {
			serverConnection.closeConnection();
			break;
		} else if (parsedLine[0] == "PING") // server ping
			sendLine("PONG " + parsedLine[1]);
		else if (parsedLine[0] == "ERROR") {
			if (parsedLine[1].size() > 12) {
				if (parsedLine[1].substr(0,12) == "Closing Link") {
					serverConnection.closeConnection();
					break;
				}
			}
		}
	}
}

void Server::parse005(std::vector<std::string> parsedLine) {
	for (unsigned int i = 3; i < parsedLine.size(); i++) {
		if (parsedLine[i] == "NAMESX") // RoBoBo supports NAMESX
			sendLine("PROTOCTL NAMESX"); // NAMESX
		if (parsedLine[i].size() > 8) { // Network name
			if (parsedLine[i].substr(0,8) == "NETWORK=") // NETWORK=NameOfNetwork
				network = parsedLine[i].substr(8);
		}
		if (parsedLine[i].size() > 7) { // Channel statuses
			if (parsedLine[i].substr(0,7) == "PREFIX=") { // PREFIX=(qaohv)~&@%+
				std::string data = parsedLine[i].substr(8);
				std::string modes = data.substr(0, data.find_first_of(')'));
				std::string chars = data.substr(data.find_first_of(')') + 1);
				for (unsigned int i = 0; i < modes.size(); i++)
					prefix.insert(std::pair<char, char> (modes[i], chars[i]));
			}
		}
		if (parsedLine[i].size() > 10) { // Channel types
			if (parsedLine[i].substr(0,10) == "CHANTYPES=") { // CHANTYPES=#&
				std::string types = parsedLine[i].substr(10);
				for (unsigned int i = 0; i < types.size(); i++)
					chanTypes.push_back(types[i]);
			}
		}
		if (parsedLine[i].size() > 10) { // Channel modes
			if (parsedLine[i].substr(0,10) == "CHANMODES=") { // CHANMODES=Ibeg,k,FJLfjl,ABCGKMNOPQRSTcimnprst
				std::string modeList = parsedLine[i].substr(10);
				std::vector<char> currSet;
				unsigned int i;
				for (i = 0; i < modeList.size(); i++) { // list modes
					if (modeList[i] == ',')
						break;
					currSet.push_back(modeList[i]);
				}
				chanModes.push_back(currSet);
				currSet.clear();
				for (i++; i < modeList.size(); i++) { // param for set and unset; increment i off comma before continuing
					if (modeList[i] == ',')
						break;
					currSet.push_back(modeList[i]);
				}
				chanModes.push_back(currSet);
				currSet.clear();
				for (i++; i < modeList.size(); i++) { // param for set; increment i off comma
					if (modeList[i] == ',')
						break;
					currSet.push_back(modeList[i]);
				}
				chanModes.push_back(currSet);
				currSet.clear();
				for (i++; i < modeList.size(); i++) // no param; increment i off comma
					currSet.push_back(modeList[i]); // no more commas
				chanModes.push_back(currSet);
			}
		}
	}
}

std::vector<std::string> Server::parseLine(std::string unformattedLine) {
	std::vector<std::string> parsedLine;
	std::string linePart = "";
	for (unsigned int i = 0; i < unformattedLine.size(); i++) {
		if (unformattedLine[i] == ' ') {
			parsedLine.push_back(linePart);
			linePart = "";
			continue;
		}
		if (i > 0) {
			if (unformattedLine[i] == ':' && unformattedLine[i-1] == ' ') {
				for (i++; i < unformattedLine.size(); i++)
					linePart += unformattedLine[i];
				parsedLine.push_back(linePart);
				linePart = "";
				break;
			}
		}
		linePart += unformattedLine[i];
	}
	if (linePart != "")
		parsedLine.push_back(linePart);
	return parsedLine;
}

std::vector<std::string> Server::separateBySpace(std::string joinedLine) {
	std::vector<std::string> words;
	std::string wordPart;
	for (unsigned int i = 0; i < joinedLine.size(); i++) {
		if (joinedLine[i] == ' ') {
			words.push_back(wordPart);
			wordPart = "";
			continue;
		}
		wordPart += joinedLine[i];
	}
	if (wordPart != "")
		words.push_back(wordPart);
	return words;
}

std::string Server::separateNickFromFullHostmask(std::string hostmask) {
	return hostmask.substr(0, hostmask.find_first_of('!'));
}
#endif<commit_msg>Add kill message to reasons the bot's connection can close.<commit_after>#include "connection.h"
#include "channel.cpp"

#ifndef SERVER_ROBOBO
#define SERVER_ROBOBO
Server::Server(std::string serverAddress, std::tr1::unordered_map<std::string, std::string> confVars, ModuleInterface* modFace) {
	serverName = serverAddress;
	serverConf = confVars;
	moduleData = modFace;
	std::istringstream portNumber (serverConf["port"]);
	unsigned int port;
	portNumber >> port;
	serverConnection.connectServer(serverAddress, port);
	sendLine("NICK " + serverConf["nick"]);
	sendLine("USER " + serverConf["ident"] + " here " + serverAddress + " :" + serverConf["gecos"]);
	handleData();
}

void Server::sendLine(std::string line) {
	serverConnection.sendData(line);
	std::cout << " -> " << line << std::endl;
	moduleData->callHookOut(serverName, parseLine(line));
}

std::tr1::unordered_map<std::string, std::string> Server::getInfo() {
	return serverConf;
}

std::tr1::unordered_map<char, char> Server::getPrefixes() {
	return prefix;
}

std::vector<std::vector<char> > Server::getChanModes() {
	return chanModes;
}

std::vector<char> Server::getChanTypes() {
	return chanTypes;
}

void Server::resyncChannels() {
	for (std::tr1::unordered_map<std::string, Channel>::iterator iter = inChannels.begin(); iter != inChannels.end(); iter++)
		sendLine("NAMES " + iter->first);
}

void Server::handleData() {
	std::string receivedLine = "";
	std::vector<std::string> parsedLine;
	while (true) {
		receivedLine = serverConnection.receive();
		std::cout << receivedLine << std::endl;
		parsedLine = parseLine(receivedLine);
		if (parsedLine.size() >= 1)
			moduleData->callHook(serverName, parsedLine); // call module hooks for the received message
		if (parsedLine[1] == "001") { // welcome to the network
			if (serverConf["channels"] != "")
				sendLine("JOIN " + serverConf["channels"]);
		} else if (parsedLine[1] == "005") // server features
			parse005(parsedLine);
		else if (parsedLine[1] == "332") { // channel topic
			for (std::tr1::unordered_map<std::string, Channel>::iterator it = inChannels.begin(); it != inChannels.end(); it++) {
				if (it->first == parsedLine[3])
					it->second.setTopic(parsedLine[4]);
			}
		} else if (parsedLine[1] == "353") { // NAMES reply
			for (std::tr1::unordered_map<std::string, Channel>::iterator it = inChannels.begin(); it != inChannels.end(); it++) {
				if (it->first == parsedLine[4])
					it->second.parseNames(separateBySpace(parsedLine[5]));
			}
		} else if (parsedLine[1] == "366") { // end of NAMES reply
			for (std::tr1::unordered_map<std::string, Channel>::iterator it = inChannels.begin(); it != inChannels.end(); it++) {
				if (it->first == parsedLine[3])
					it->second.numeric366();
			}
		} else if (parsedLine[1] == "MODE") {
			bool addMode = true;
			if (parsedLine[2] == serverConf["nick"]) { // if it's a user mode
				for (unsigned int i = 0; i < parsedLine[3].size(); i++) {
					if (parsedLine[3][i] == '+')
						addMode = true;
					else if (parsedLine[3][i] == '-')
						addMode = false;
					else {
						if (addMode)
							userModes.push_back(parsedLine[3][i]);
						else {
							for (std::vector<char>::iterator uModeIter = userModes.begin(); uModeIter != userModes.end(); uModeIter++) {
								if (parsedLine[3][i] == *uModeIter) {
									userModes.erase(uModeIter);
									break;
								}
							}
						}
					}
				}
			} else { // it's a channel mode
				int currParam = 4;
				for (unsigned int i = 0; i < parsedLine[3].size(); i++) {
					if (parsedLine[3][i] == '+')
						addMode = true;
					else if (parsedLine[3][i] == '-')
						addMode = false;
					else {
						bool found = false;
						int category;
						for (unsigned int j = 0; j < chanModes[0].size(); j++) {
							if (parsedLine[3][i] == chanModes[0][j]) {
								found = true;
								category = 0;
							}
						}
						if (!found) {
							for (unsigned int j = 0; j < chanModes[1].size(); j++) {
								if (parsedLine[3][i] == chanModes[1][j]) {
									found = true;
									category = 1;
								}
							}
						}
						if (!found) {
							for (unsigned int j = 0; j < chanModes[2].size(); j++) {
								if (parsedLine[3][i] == chanModes[2][j]) {
									found = true;
									category = 2;
								}
							}
						}
						if (!found) {
							for (unsigned int j = 0; j < chanModes[3].size(); j++) {
								if (parsedLine[3][i] == chanModes[3][j]) {
									found = true;
									category = 3;
								}
							}
						}
						if (!found)
							category = 4;

						if (category == 0 || category == 1 || (category == 2 && addMode)) {
							for (std::tr1::unordered_map<std::string, Channel>::iterator chanIter = inChannels.begin(); chanIter != inChannels.end(); chanIter++) {
								if (chanIter->first == parsedLine[2])
									chanIter->second.setMode(addMode, parsedLine[3][i], parsedLine[currParam++]);
							}
						} else {
							for (std::tr1::unordered_map<std::string, Channel>::iterator chanIter = inChannels.begin(); chanIter != inChannels.end(); chanIter++) {
								if (chanIter->first == parsedLine[2])
									chanIter->second.setMode(addMode, parsedLine[3][i], "");
							}
						}
					}
				}
			}
		} else if (parsedLine[1] == "NICK" && serverConf["nick"] == separateNickFromFullHostmask(parsedLine[0].substr(1))) // bot's nick changed
			serverConf["nick"] = parsedLine[2];
		else if (parsedLine[1] == "JOIN" && serverConf["nick"] == separateNickFromFullHostmask(parsedLine[0].substr(1))) // bot joined a channel
			inChannels.insert(std::pair<std::string, Channel> (parsedLine[2], Channel (this)));
		else if (parsedLine[1] == "PART" && serverConf["nick"] == separateNickFromFullHostmask(parsedLine[0].substr(1)))
			inChannels.erase(parsedLine[2]);
		else if (parsedLine[1] == "QUIT" && serverConf["nick"] == separateNickFromFullHostmask(parsedLine[0].substr(1))) {
			serverConnection.closeConnection();
			break;
		} else if (parsedLine[1] == "KILL" && serverConf["nick"] == separateNickFromFullHostmask(parsedLine[0].substr(1))) {
			serverConnection.closeConnection();
			break;
		} else if (parsedLine[0] == "PING") // server ping
			sendLine("PONG " + parsedLine[1]);
		else if (parsedLine[0] == "ERROR") {
			if (parsedLine[1].size() > 12) {
				if (parsedLine[1].substr(0,12) == "Closing Link") {
					serverConnection.closeConnection();
					break;
				}
			}
		}
	}
}

void Server::parse005(std::vector<std::string> parsedLine) {
	for (unsigned int i = 3; i < parsedLine.size(); i++) {
		if (parsedLine[i] == "NAMESX") // RoBoBo supports NAMESX
			sendLine("PROTOCTL NAMESX"); // NAMESX
		if (parsedLine[i].size() > 8) { // Network name
			if (parsedLine[i].substr(0,8) == "NETWORK=") // NETWORK=NameOfNetwork
				network = parsedLine[i].substr(8);
		}
		if (parsedLine[i].size() > 7) { // Channel statuses
			if (parsedLine[i].substr(0,7) == "PREFIX=") { // PREFIX=(qaohv)~&@%+
				std::string data = parsedLine[i].substr(8);
				std::string modes = data.substr(0, data.find_first_of(')'));
				std::string chars = data.substr(data.find_first_of(')') + 1);
				for (unsigned int i = 0; i < modes.size(); i++)
					prefix.insert(std::pair<char, char> (modes[i], chars[i]));
			}
		}
		if (parsedLine[i].size() > 10) { // Channel types
			if (parsedLine[i].substr(0,10) == "CHANTYPES=") { // CHANTYPES=#&
				std::string types = parsedLine[i].substr(10);
				for (unsigned int i = 0; i < types.size(); i++)
					chanTypes.push_back(types[i]);
			}
		}
		if (parsedLine[i].size() > 10) { // Channel modes
			if (parsedLine[i].substr(0,10) == "CHANMODES=") { // CHANMODES=Ibeg,k,FJLfjl,ABCGKMNOPQRSTcimnprst
				std::string modeList = parsedLine[i].substr(10);
				std::vector<char> currSet;
				unsigned int i;
				for (i = 0; i < modeList.size(); i++) { // list modes
					if (modeList[i] == ',')
						break;
					currSet.push_back(modeList[i]);
				}
				chanModes.push_back(currSet);
				currSet.clear();
				for (i++; i < modeList.size(); i++) { // param for set and unset; increment i off comma before continuing
					if (modeList[i] == ',')
						break;
					currSet.push_back(modeList[i]);
				}
				chanModes.push_back(currSet);
				currSet.clear();
				for (i++; i < modeList.size(); i++) { // param for set; increment i off comma
					if (modeList[i] == ',')
						break;
					currSet.push_back(modeList[i]);
				}
				chanModes.push_back(currSet);
				currSet.clear();
				for (i++; i < modeList.size(); i++) // no param; increment i off comma
					currSet.push_back(modeList[i]); // no more commas
				chanModes.push_back(currSet);
			}
		}
	}
}

std::vector<std::string> Server::parseLine(std::string unformattedLine) {
	std::vector<std::string> parsedLine;
	std::string linePart = "";
	for (unsigned int i = 0; i < unformattedLine.size(); i++) {
		if (unformattedLine[i] == ' ') {
			parsedLine.push_back(linePart);
			linePart = "";
			continue;
		}
		if (i > 0) {
			if (unformattedLine[i] == ':' && unformattedLine[i-1] == ' ') {
				for (i++; i < unformattedLine.size(); i++)
					linePart += unformattedLine[i];
				parsedLine.push_back(linePart);
				linePart = "";
				break;
			}
		}
		linePart += unformattedLine[i];
	}
	if (linePart != "")
		parsedLine.push_back(linePart);
	return parsedLine;
}

std::vector<std::string> Server::separateBySpace(std::string joinedLine) {
	std::vector<std::string> words;
	std::string wordPart;
	for (unsigned int i = 0; i < joinedLine.size(); i++) {
		if (joinedLine[i] == ' ') {
			words.push_back(wordPart);
			wordPart = "";
			continue;
		}
		wordPart += joinedLine[i];
	}
	if (wordPart != "")
		words.push_back(wordPart);
	return words;
}

std::string Server::separateNickFromFullHostmask(std::string hostmask) {
	return hostmask.substr(0, hostmask.find_first_of('!'));
}
#endif<|endoftext|>


<commit_before>//////////////////////////////////////////////////////////////////////////
//
//  Copyright (c) 2010, Image Engine Design Inc. 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 Image Engine Design nor the names of any
//       other contributors to this software may be used to endorse or
//       promote products derived from this software without specific prior
//       written permission.
//
//  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
//  IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
//  THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
//  PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
//  CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
//  EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
//  PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
//  PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
//  LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
//  NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
//  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
//////////////////////////////////////////////////////////////////////////

#include "IECoreMaya/NumericTraits.h"
#include "IECoreMaya/ToMayaObjectConverter.h"
#include "IECoreMaya/FromMayaObjectConverter.h"
#include "IECoreMaya/TransformationMatrixParameterHandler.h"

#include "IECore/MessageHandler.h"
#include "IECore/SimpleTypedData.h"
#include "IECore/TransformationMatrix.h"

#include "maya/MFnCompoundAttribute.h"
#include "maya/MFnNumericAttribute.h"
#include "maya/MFnUnitAttribute.h"

using namespace IECoreMaya;
using namespace Imath;

// T & R should be kept first, to make iteration easier later on
// as they are the only two with special attribute types.
#define TRANSLATE_INDEX 0
#define ROTATE_INDEX 1
#define SCALE_INDEX 2
#define SHEAR_INDEX 3
#define SCALEPIVOT_INDEX 4
#define SCALEPIVOTTRANS_INDEX 5
#define ROTATEPIVOT_INDEX 6
#define ROTATEPIVOTTRANS_INDEX 7

// We keep this in an array to allow a bunch of tasks to be done in a loop later.
// The order here should correlate with the defines above.
template<typename T>
MString TransformationMatrixParameterHandler<T>::g_attributeNames[] = {
	"translate",
	"rotate",
	"scale",
	"shear",
	"scalePivot",
	"scalePivotTranslation",
	"rotatePivot",
	"rotatePivotTranslation"
};

static ParameterHandler::Description< TransformationMatrixParameterHandler<float> > floatRegistrar( IECore::TransformationMatrixfParameter::staticTypeId() );
static ParameterHandler::Description< TransformationMatrixParameterHandler<double> > doubleRegistrar( IECore::TransformationMatrixdParameter::staticTypeId() );

template<typename T>
MStatus TransformationMatrixParameterHandler<T>::doUpdate( IECore::ConstParameterPtr parameter, MPlug &plug ) const
{
	typename IECore::TypedParameter<IECore::TransformationMatrix<T> >::ConstPtr p = IECore::runTimeCast<const IECore::TypedParameter<IECore::TransformationMatrix<T> > >( parameter );
	if( !p )
	{
		return MS::kFailure;
	}

	MObject attribute = plug.attribute();
	MFnCompoundAttribute fnCAttr( attribute );
	if( !fnCAttr.hasObj( attribute ) )
	{
		return MS::kFailure;
	}

	if( plug.numChildren() != 8 )
	{
		return MS::kFailure;
	}

	MStatus stat;
	MPlug tmpPlug;

	for( unsigned int i=0; i<8; i++ )
	{
		tmpPlug = plug.child( i, &stat );

		// Verify the naming of the child plugs.

		const MString name = tmpPlug.partialName();
		const unsigned int len = name.length() - 1;
		const unsigned int nlen = g_attributeNames[i].length() - 1;
		const MString nameEnd = name.substringW( len - nlen, len );

		if( !stat || nameEnd != g_attributeNames[i] )
		{
			return MS::kFailure;
		}

		MObject attr = tmpPlug.attribute();
		fnCAttr.setObject( attr );
		if( !fnCAttr.hasObj( attr ) )
		{
			return MS::kFailure;
		}
	}

	IECore::TransformationMatrix<T> tMatrix = p->typedDefaultValue();

	if( !setUnitVecDefaultValues( plug.child( TRANSLATE_INDEX ), tMatrix.translate ) )
		return MS::kFailure;

	if( !setUnitVecDefaultValues( plug.child( ROTATE_INDEX ), tMatrix.rotate ) )
		return MS::kFailure;

	if( !setVecDefaultValues( plug.child( SCALE_INDEX ), tMatrix.scale ) )
		return MS::kFailure;

	if( !setVecDefaultValues( plug.child( SHEAR_INDEX ), tMatrix.shear ) )
		return MS::kFailure;

	if( !setVecDefaultValues( plug.child( SCALEPIVOT_INDEX ), tMatrix.scalePivot ) )
		return MS::kFailure;

	if( !setVecDefaultValues( plug.child( SCALEPIVOTTRANS_INDEX ), tMatrix.scalePivotTranslation ) )
		 return MS::kFailure;

	if( !setVecDefaultValues( plug.child( ROTATEPIVOT_INDEX ), tMatrix.rotatePivot ) )
		return MS::kFailure;

	if( !setVecDefaultValues( plug.child( ROTATEPIVOTTRANS_INDEX ), tMatrix.rotatePivotTranslation ) )
		return MS::kFailure;

	return finishUpdating( parameter, plug );
}

template<typename T>
MPlug TransformationMatrixParameterHandler<T>::doCreate( IECore::ConstParameterPtr parameter, const MString &plugName, MObject &node ) const
{
	typename IECore::TypedParameter<IECore::TransformationMatrix<T> >::ConstPtr p = IECore::runTimeCast<const IECore::TypedParameter<IECore::TransformationMatrix<T> > >( parameter );
	if( !p )
	{
		return MPlug();
	}

	MFnCompoundAttribute fnCAttr;
	MObject attribute = fnCAttr.create( plugName, plugName );

	MFnNumericAttribute fnNAttr;
	MFnUnitAttribute fnUAttr;

	// As TransformationMatrix embodies a fairly comprehensive rotation model, were going to be a little
	// more basic here, and just supply a V3f rotation and pretend that the Quartonean isn't there.
	///\todo Expose rotation order and rotationOrientation.

	MObject p1 = fnUAttr.create( plugName + g_attributeNames[ TRANSLATE_INDEX ] + "0", plugName + g_attributeNames[ TRANSLATE_INDEX ] + "0", MFnUnitAttribute::kDistance );
	MObject p2 = fnUAttr.create( plugName + g_attributeNames[ TRANSLATE_INDEX ] + "1", plugName + g_attributeNames[ TRANSLATE_INDEX ] + "1", MFnUnitAttribute::kDistance );
	MObject p3 = fnUAttr.create( plugName + g_attributeNames[ TRANSLATE_INDEX ] + "2", plugName + g_attributeNames[ TRANSLATE_INDEX ] + "2", MFnUnitAttribute::kDistance );
	fnCAttr.addChild( fnNAttr.create( plugName + g_attributeNames[ TRANSLATE_INDEX ], plugName + g_attributeNames[ TRANSLATE_INDEX ], p1, p2, p3 ) );

	p1 = fnUAttr.create( plugName + g_attributeNames[ ROTATE_INDEX ] + "0", plugName + g_attributeNames[ ROTATE_INDEX ] + "0", MFnUnitAttribute::kAngle );
	p2 = fnUAttr.create( plugName + g_attributeNames[ ROTATE_INDEX ] + "1", plugName + g_attributeNames[ ROTATE_INDEX ] + "1", MFnUnitAttribute::kAngle );
	p3 = fnUAttr.create( plugName + g_attributeNames[ ROTATE_INDEX ] + "2", plugName + g_attributeNames[ ROTATE_INDEX ] + "2", MFnUnitAttribute::kAngle );
	fnCAttr.addChild( fnNAttr.create( plugName + g_attributeNames[ ROTATE_INDEX ], plugName + g_attributeNames[ ROTATE_INDEX ], p1, p2, p3 ) );

	for( unsigned int i=2; i<8; i++ )
	{
		fnCAttr.addChild( fnNAttr.create( plugName + g_attributeNames[i], plugName + g_attributeNames[i], NumericTraits<Imath::Vec3<T> >::dataType() ) );
	}

	MPlug result = finishCreating( parameter, attribute, node );

	if( !doUpdate( parameter, result ) )
	{
		return MPlug(); // failure
	}

	if( !finishUpdating( parameter, result ) )
	{
		return MPlug(); // failure
	}

	return result;
}

template<typename T>
MStatus TransformationMatrixParameterHandler<T>::doSetValue( IECore::ConstParameterPtr parameter, MPlug &plug ) const
{
	typename IECore::TypedParameter<IECore::TransformationMatrix<T> >::ConstPtr p = IECore::runTimeCast<const IECore::TypedParameter<IECore::TransformationMatrix<T> > >( parameter );
	if( !p )
	{
		return MS::kFailure;
	}

	IECore::TransformationMatrix<T> tMatrix = p->getTypedValue();

	if( tMatrix.rotate.order() != Imath::Euler<T>::XYZ )
	{
		IECore::msg(
			IECore::Msg::Error,
			"TransformationMatrixParameterHandler::doSetValue",
			"The rotation order of the parameter '"+parameter->name()+"' is not XYZ, unable to set value."
		);
		return MS::kFailure;
	}

	if( !setVecValues( plug.child( TRANSLATE_INDEX ), tMatrix.translate ) )
		return MS::kFailure;

	if( !setVecValues( plug.child( ROTATE_INDEX ), tMatrix.rotate ) )
		return MS::kFailure;

	if( !setVecValues( plug.child( SCALE_INDEX ), tMatrix.scale ) )
		return MS::kFailure;

	if( !setVecValues( plug.child( SHEAR_INDEX ), tMatrix.shear ) )
		return MS::kFailure;

	if( !setVecValues( plug.child( SCALEPIVOT_INDEX ), tMatrix.scalePivot ) )
		return MS::kFailure;

	if( !setVecValues( plug.child( SCALEPIVOTTRANS_INDEX ), tMatrix.scalePivotTranslation ) )
		return MS::kFailure;

	if( !setVecValues( plug.child( ROTATEPIVOT_INDEX ), tMatrix.rotatePivot ) )
		return MS::kFailure;

	if( !setVecValues( plug.child( ROTATEPIVOTTRANS_INDEX ), tMatrix.rotatePivotTranslation ) )
		return MS::kFailure;

	return MS::kSuccess;
}

template<typename T>
MStatus TransformationMatrixParameterHandler<T>::doSetValue( const MPlug &plug, IECore::ParameterPtr parameter ) const
{
	typename IECore::TypedParameter<IECore::TransformationMatrix<T> >::Ptr p = IECore::runTimeCast<IECore::TypedParameter<IECore::TransformationMatrix<T> > >( parameter );
	if( !p )
	{
		return MS::kFailure;
	}

	IECore::TransformationMatrix<T> tMatrix = p->getTypedValue();

	if( tMatrix.rotate.order() != Imath::Euler<T>::XYZ )
	{
		IECore::msg(
			IECore::Msg::Error,
			"TransformationMatrixParameterHandler::doSetValue",
			"The rotation order of the parameter '"+parameter->name()+"' is not XYZ, unable to set value."
		);
		return MS::kFailure;
	}

	std::vector<Imath::Vec3<T> > v;
	v.resize(8);

	for( unsigned int i=0; i<8; i++ )
	{
		if( !getVecValues( plug.child(i), v[i] ) )
			return MS::kFailure;
	}

	tMatrix.translate = v[ TRANSLATE_INDEX ];
	tMatrix.rotate = Imath::Euler<T>(v[ ROTATE_INDEX ]);
	tMatrix.scale = v[ SCALE_INDEX ];
	tMatrix.shear = v[ SHEAR_INDEX ];
	tMatrix.scalePivot = v[ SCALEPIVOT_INDEX ];
	tMatrix.scalePivotTranslation = v[ SCALEPIVOTTRANS_INDEX ];
	tMatrix.rotatePivot = v[ ROTATEPIVOT_INDEX ];
	tMatrix.rotatePivotTranslation = v[ ROTATEPIVOTTRANS_INDEX ];

	p->setTypedValue( tMatrix );

	return MS::kSuccess;
}

template<typename T>
MStatus TransformationMatrixParameterHandler<T>::setVecValues( MPlug vecPlug, Imath::Vec3<T> &values ) const
{
	if( vecPlug.numChildren() != 3 )
	{
		return MS::kFailure;
	}

	for( unsigned int i=0; i<3; i++ )
	{
		if( !vecPlug.child(i).setValue( values[i] ) )
		{
			return MS::kFailure;
		}
	}

	return MS::kSuccess;
}

template<typename T>
MStatus TransformationMatrixParameterHandler<T>::getVecValues( MPlug vecPlug, Imath::Vec3<T> &values ) const
{
	if( vecPlug.numChildren() != 3 )
	{
		return MS::kFailure;
	}

	for( unsigned int i=0; i<3; i++ )
	{
		if( !vecPlug.child(i).getValue( values[i] ) )
		{
			return MS::kFailure;
		}
	}

	return MS::kSuccess;
}

template<typename T>
MStatus TransformationMatrixParameterHandler<T>::setVecDefaultValues( MPlug vecPlug, Imath::Vec3<T> &defaultValue ) const
{
	if( vecPlug.numChildren() != 3 )
	{
		return MS::kFailure;
	}

	MFnNumericAttribute fnN;
	for( unsigned int i=0; i<3; i++ )
	{
		fnN.setObject( vecPlug.child(i).attribute() );
		if( !fnN.setDefault( defaultValue[i] ) )
		{
			return MS::kFailure;
		}
	}

	return MS::kSuccess;
}

template<typename T>
MStatus TransformationMatrixParameterHandler<T>::setUnitVecDefaultValues( MPlug vecPlug, Imath::Vec3<T> &defaultValue ) const
{
	if( vecPlug.numChildren() != 3 )
	{
		return MS::kFailure;
	}

	MFnUnitAttribute fnU;
	for( unsigned int i=0; i<3; i++ )
	{
		fnU.setObject( vecPlug.child(i).attribute() );
		if( !fnU.setDefault( defaultValue[i] ) )
		{
			return MS::kFailure;
		}
	}

	return MS::kSuccess;
}
<commit_msg>Adding comment<commit_after>//////////////////////////////////////////////////////////////////////////
//
//  Copyright (c) 2010, Image Engine Design Inc. 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 Image Engine Design nor the names of any
//       other contributors to this software may be used to endorse or
//       promote products derived from this software without specific prior
//       written permission.
//
//  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
//  IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
//  THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
//  PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
//  CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
//  EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
//  PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
//  PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
//  LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
//  NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
//  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
//////////////////////////////////////////////////////////////////////////

#include "IECoreMaya/NumericTraits.h"
#include "IECoreMaya/ToMayaObjectConverter.h"
#include "IECoreMaya/FromMayaObjectConverter.h"
#include "IECoreMaya/TransformationMatrixParameterHandler.h"

#include "IECore/MessageHandler.h"
#include "IECore/SimpleTypedData.h"
#include "IECore/TransformationMatrix.h"

#include "maya/MFnCompoundAttribute.h"
#include "maya/MFnNumericAttribute.h"
#include "maya/MFnUnitAttribute.h"

using namespace IECoreMaya;
using namespace Imath;

// T & R should be kept first, to make iteration easier later on
// as they are the only two with special attribute types.
#define TRANSLATE_INDEX 0
#define ROTATE_INDEX 1
#define SCALE_INDEX 2
#define SHEAR_INDEX 3
#define SCALEPIVOT_INDEX 4
#define SCALEPIVOTTRANS_INDEX 5
#define ROTATEPIVOT_INDEX 6
#define ROTATEPIVOTTRANS_INDEX 7

// We keep this in an array to allow a bunch of tasks to be done in a loop later.
// The order here should correlate with the defines above.
template<typename T>
MString TransformationMatrixParameterHandler<T>::g_attributeNames[] = {
	"translate",
	"rotate",
	"scale",
	"shear",
	"scalePivot",
	"scalePivotTranslation",
	"rotatePivot",
	"rotatePivotTranslation"
};

static ParameterHandler::Description< TransformationMatrixParameterHandler<float> > floatRegistrar( IECore::TransformationMatrixfParameter::staticTypeId() );
static ParameterHandler::Description< TransformationMatrixParameterHandler<double> > doubleRegistrar( IECore::TransformationMatrixdParameter::staticTypeId() );

template<typename T>
MStatus TransformationMatrixParameterHandler<T>::doUpdate( IECore::ConstParameterPtr parameter, MPlug &plug ) const
{
	typename IECore::TypedParameter<IECore::TransformationMatrix<T> >::ConstPtr p = IECore::runTimeCast<const IECore::TypedParameter<IECore::TransformationMatrix<T> > >( parameter );
	if( !p )
	{
		return MS::kFailure;
	}

	MObject attribute = plug.attribute();
	MFnCompoundAttribute fnCAttr( attribute );
	if( !fnCAttr.hasObj( attribute ) )
	{
		return MS::kFailure;
	}

	if( plug.numChildren() != 8 )
	{
		return MS::kFailure;
	}

	MStatus stat;
	MPlug tmpPlug;

	for( unsigned int i=0; i<8; i++ )
	{
		tmpPlug = plug.child( i, &stat );

		// Verify the naming of the child plugs.

		const MString name = tmpPlug.partialName();
		const unsigned int len = name.length() - 1;
		const unsigned int nlen = g_attributeNames[i].length() - 1;
		const MString nameEnd = name.substringW( len - nlen, len );

		if( !stat || nameEnd != g_attributeNames[i] )
		{
			return MS::kFailure;
		}

		MObject attr = tmpPlug.attribute();
		fnCAttr.setObject( attr );
		if( !fnCAttr.hasObj( attr ) )
		{
			return MS::kFailure;
		}
	}

	IECore::TransformationMatrix<T> tMatrix = p->typedDefaultValue();

	if( !setUnitVecDefaultValues( plug.child( TRANSLATE_INDEX ), tMatrix.translate ) )
		return MS::kFailure;

	if( !setUnitVecDefaultValues( plug.child( ROTATE_INDEX ), tMatrix.rotate ) )
		return MS::kFailure;

	if( !setVecDefaultValues( plug.child( SCALE_INDEX ), tMatrix.scale ) )
		return MS::kFailure;

	if( !setVecDefaultValues( plug.child( SHEAR_INDEX ), tMatrix.shear ) )
		return MS::kFailure;

	if( !setVecDefaultValues( plug.child( SCALEPIVOT_INDEX ), tMatrix.scalePivot ) )
		return MS::kFailure;

	if( !setVecDefaultValues( plug.child( SCALEPIVOTTRANS_INDEX ), tMatrix.scalePivotTranslation ) )
		 return MS::kFailure;

	if( !setVecDefaultValues( plug.child( ROTATEPIVOT_INDEX ), tMatrix.rotatePivot ) )
		return MS::kFailure;

	if( !setVecDefaultValues( plug.child( ROTATEPIVOTTRANS_INDEX ), tMatrix.rotatePivotTranslation ) )
		return MS::kFailure;

	return finishUpdating( parameter, plug );
}

template<typename T>
MPlug TransformationMatrixParameterHandler<T>::doCreate( IECore::ConstParameterPtr parameter, const MString &plugName, MObject &node ) const
{
	typename IECore::TypedParameter<IECore::TransformationMatrix<T> >::ConstPtr p = IECore::runTimeCast<const IECore::TypedParameter<IECore::TransformationMatrix<T> > >( parameter );
	if( !p )
	{
		return MPlug();
	}

	MFnCompoundAttribute fnCAttr;
	MObject attribute = fnCAttr.create( plugName, plugName );

	MFnNumericAttribute fnNAttr;
	MFnUnitAttribute fnUAttr;

	// As TransformationMatrix embodies a fairly comprehensive rotation model, were going to be a little
	// more basic here, and just supply a V3f rotation and pretend that the Quartonean isn't there.
	///\todo Expose rotation order and rotationOrientation.

	// These use the '0', '1' and '2' child suffixes instead of 'X' 'Y' and 'Z' to match those created by fnNAttr.create() @ L188.
	MObject p1 = fnUAttr.create( plugName + g_attributeNames[ TRANSLATE_INDEX ] + "0", plugName + g_attributeNames[ TRANSLATE_INDEX ] + "0", MFnUnitAttribute::kDistance );
	MObject p2 = fnUAttr.create( plugName + g_attributeNames[ TRANSLATE_INDEX ] + "1", plugName + g_attributeNames[ TRANSLATE_INDEX ] + "1", MFnUnitAttribute::kDistance );
	MObject p3 = fnUAttr.create( plugName + g_attributeNames[ TRANSLATE_INDEX ] + "2", plugName + g_attributeNames[ TRANSLATE_INDEX ] + "2", MFnUnitAttribute::kDistance );
	fnCAttr.addChild( fnNAttr.create( plugName + g_attributeNames[ TRANSLATE_INDEX ], plugName + g_attributeNames[ TRANSLATE_INDEX ], p1, p2, p3 ) );

	p1 = fnUAttr.create( plugName + g_attributeNames[ ROTATE_INDEX ] + "0", plugName + g_attributeNames[ ROTATE_INDEX ] + "0", MFnUnitAttribute::kAngle );
	p2 = fnUAttr.create( plugName + g_attributeNames[ ROTATE_INDEX ] + "1", plugName + g_attributeNames[ ROTATE_INDEX ] + "1", MFnUnitAttribute::kAngle );
	p3 = fnUAttr.create( plugName + g_attributeNames[ ROTATE_INDEX ] + "2", plugName + g_attributeNames[ ROTATE_INDEX ] + "2", MFnUnitAttribute::kAngle );
	fnCAttr.addChild( fnNAttr.create( plugName + g_attributeNames[ ROTATE_INDEX ], plugName + g_attributeNames[ ROTATE_INDEX ], p1, p2, p3 ) );

	for( unsigned int i=2; i<8; i++ )
	{
		fnCAttr.addChild( fnNAttr.create( plugName + g_attributeNames[i], plugName + g_attributeNames[i], NumericTraits<Imath::Vec3<T> >::dataType() ) );
	}

	MPlug result = finishCreating( parameter, attribute, node );

	if( !doUpdate( parameter, result ) )
	{
		return MPlug(); // failure
	}

	if( !finishUpdating( parameter, result ) )
	{
		return MPlug(); // failure
	}

	return result;
}

template<typename T>
MStatus TransformationMatrixParameterHandler<T>::doSetValue( IECore::ConstParameterPtr parameter, MPlug &plug ) const
{
	typename IECore::TypedParameter<IECore::TransformationMatrix<T> >::ConstPtr p = IECore::runTimeCast<const IECore::TypedParameter<IECore::TransformationMatrix<T> > >( parameter );
	if( !p )
	{
		return MS::kFailure;
	}

	IECore::TransformationMatrix<T> tMatrix = p->getTypedValue();

	if( tMatrix.rotate.order() != Imath::Euler<T>::XYZ )
	{
		IECore::msg(
			IECore::Msg::Error,
			"TransformationMatrixParameterHandler::doSetValue",
			"The rotation order of the parameter '"+parameter->name()+"' is not XYZ, unable to set value."
		);
		return MS::kFailure;
	}

	if( !setVecValues( plug.child( TRANSLATE_INDEX ), tMatrix.translate ) )
		return MS::kFailure;

	if( !setVecValues( plug.child( ROTATE_INDEX ), tMatrix.rotate ) )
		return MS::kFailure;

	if( !setVecValues( plug.child( SCALE_INDEX ), tMatrix.scale ) )
		return MS::kFailure;

	if( !setVecValues( plug.child( SHEAR_INDEX ), tMatrix.shear ) )
		return MS::kFailure;

	if( !setVecValues( plug.child( SCALEPIVOT_INDEX ), tMatrix.scalePivot ) )
		return MS::kFailure;

	if( !setVecValues( plug.child( SCALEPIVOTTRANS_INDEX ), tMatrix.scalePivotTranslation ) )
		return MS::kFailure;

	if( !setVecValues( plug.child( ROTATEPIVOT_INDEX ), tMatrix.rotatePivot ) )
		return MS::kFailure;

	if( !setVecValues( plug.child( ROTATEPIVOTTRANS_INDEX ), tMatrix.rotatePivotTranslation ) )
		return MS::kFailure;

	return MS::kSuccess;
}

template<typename T>
MStatus TransformationMatrixParameterHandler<T>::doSetValue( const MPlug &plug, IECore::ParameterPtr parameter ) const
{
	typename IECore::TypedParameter<IECore::TransformationMatrix<T> >::Ptr p = IECore::runTimeCast<IECore::TypedParameter<IECore::TransformationMatrix<T> > >( parameter );
	if( !p )
	{
		return MS::kFailure;
	}

	IECore::TransformationMatrix<T> tMatrix = p->getTypedValue();

	if( tMatrix.rotate.order() != Imath::Euler<T>::XYZ )
	{
		IECore::msg(
			IECore::Msg::Error,
			"TransformationMatrixParameterHandler::doSetValue",
			"The rotation order of the parameter '"+parameter->name()+"' is not XYZ, unable to set value."
		);
		return MS::kFailure;
	}

	std::vector<Imath::Vec3<T> > v;
	v.resize(8);

	for( unsigned int i=0; i<8; i++ )
	{
		if( !getVecValues( plug.child(i), v[i] ) )
			return MS::kFailure;
	}

	tMatrix.translate = v[ TRANSLATE_INDEX ];
	tMatrix.rotate = Imath::Euler<T>(v[ ROTATE_INDEX ]);
	tMatrix.scale = v[ SCALE_INDEX ];
	tMatrix.shear = v[ SHEAR_INDEX ];
	tMatrix.scalePivot = v[ SCALEPIVOT_INDEX ];
	tMatrix.scalePivotTranslation = v[ SCALEPIVOTTRANS_INDEX ];
	tMatrix.rotatePivot = v[ ROTATEPIVOT_INDEX ];
	tMatrix.rotatePivotTranslation = v[ ROTATEPIVOTTRANS_INDEX ];

	p->setTypedValue( tMatrix );

	return MS::kSuccess;
}

template<typename T>
MStatus TransformationMatrixParameterHandler<T>::setVecValues( MPlug vecPlug, Imath::Vec3<T> &values ) const
{
	if( vecPlug.numChildren() != 3 )
	{
		return MS::kFailure;
	}

	for( unsigned int i=0; i<3; i++ )
	{
		if( !vecPlug.child(i).setValue( values[i] ) )
		{
			return MS::kFailure;
		}
	}

	return MS::kSuccess;
}

template<typename T>
MStatus TransformationMatrixParameterHandler<T>::getVecValues( MPlug vecPlug, Imath::Vec3<T> &values ) const
{
	if( vecPlug.numChildren() != 3 )
	{
		return MS::kFailure;
	}

	for( unsigned int i=0; i<3; i++ )
	{
		if( !vecPlug.child(i).getValue( values[i] ) )
		{
			return MS::kFailure;
		}
	}

	return MS::kSuccess;
}

template<typename T>
MStatus TransformationMatrixParameterHandler<T>::setVecDefaultValues( MPlug vecPlug, Imath::Vec3<T> &defaultValue ) const
{
	if( vecPlug.numChildren() != 3 )
	{
		return MS::kFailure;
	}

	MFnNumericAttribute fnN;
	for( unsigned int i=0; i<3; i++ )
	{
		fnN.setObject( vecPlug.child(i).attribute() );
		if( !fnN.setDefault( defaultValue[i] ) )
		{
			return MS::kFailure;
		}
	}

	return MS::kSuccess;
}

template<typename T>
MStatus TransformationMatrixParameterHandler<T>::setUnitVecDefaultValues( MPlug vecPlug, Imath::Vec3<T> &defaultValue ) const
{
	if( vecPlug.numChildren() != 3 )
	{
		return MS::kFailure;
	}

	MFnUnitAttribute fnU;
	for( unsigned int i=0; i<3; i++ )
	{
		fnU.setObject( vecPlug.child(i).attribute() );
		if( !fnU.setDefault( defaultValue[i] ) )
		{
			return MS::kFailure;
		}
	}

	return MS::kSuccess;
}
<|endoftext|>


<commit_before>// RUN: %clang_cc1 -triple i686-pc-win32 -x c++ -O2 -disable-llvm-optzns -emit-llvm < %s | FileCheck %s

#define DLLEXPORT __declspec(dllexport)

void DLLEXPORT a();
// CHECK-DAG: declare dllexport void @"\01?a@@YAXXZ"()

inline void DLLEXPORT b() {}
// CHECK-DAG: define weak_odr dllexport void @"\01?b@@YAXXZ"()

template <typename T> void c() {}
template void DLLEXPORT c<int>();
// CHECK-DAG: define weak_odr dllexport void @"\01??$c@H@@YAXXZ"()

struct S {
  void DLLEXPORT a() {}
  // CHECK-DAG: define weak_odr dllexport x86_thiscallcc void @"\01?a@S@@QAEXXZ"
};

void user() {
  // FIXME: dllexported functions must be emitted even if they're not referenced in this TU.
  a();
  b();
  &S::a;
}
<commit_msg>test/CodeGenCXX/dllexport.cpp: we already correctly emit b() even when it's not used, because CodeGenModule::EmitGlobal consults ASTContext::DeclMustBeEmitted via CodeGenModule::MayDeferGeneration.<commit_after>// RUN: %clang_cc1 -triple i686-pc-win32 -x c++ -O2 -disable-llvm-optzns -emit-llvm < %s | FileCheck %s

#define DLLEXPORT __declspec(dllexport)

void DLLEXPORT a();
// CHECK-DAG: declare dllexport void @"\01?a@@YAXXZ"()

inline void DLLEXPORT b() {}
// CHECK-DAG: define weak_odr dllexport void @"\01?b@@YAXXZ"()

template <typename T> void c() {}
template void DLLEXPORT c<int>();
// CHECK-DAG: define weak_odr dllexport void @"\01??$c@H@@YAXXZ"()

struct S {
  void DLLEXPORT a() {}
  // CHECK-DAG: define weak_odr dllexport x86_thiscallcc void @"\01?a@S@@QAEXXZ"
};

void user() {
  a();
  // FIXME: dllexported methods must be emitted even if they're not referenced in this TU.
  &S::a;
}
<|endoftext|>


<commit_before>#include <iostream>

#include <sauce/sauce.h>

/**
 * The purpose of this test is to enforce ansi c++ compatibility within the source.
 *
 * It does so by first pulling in all desired includes, instantiating templates and then asserting
 * that it was compiled with -ansi.
 */
int main() {
  #ifdef __STRICT_ANSI__
  return 0;
  #else
  std::cerr << "This file was not compiled with -ansi." << std::endl;
  return 1;
  #endif
}
<commit_msg>Give the ansi checker something to do.<commit_after>#include <iostream>

#include <sauce/sauce.h>

/**
 * The purpose of this test is to enforce ansi c++ compatibility within the source.
 *
 * It does so by first pulling in all desired includes, instantiating templates and then asserting
 * that it was compiled with -ansi.
 */

using ::sauce::AbstractProvider;
using ::sauce::Binder;
using ::sauce::Injector;
using ::sauce::Modules;
using ::sauce::Named;

struct Animal {
  virtual std::string says() = 0;
};

struct Cat: Animal {
  std::string says() { return "Meow"; }
};

struct LieutenantShinysides {};
struct Fish: Animal {
  std::string says() { return "Blub blub"; }
};

struct Meatloaf {};
struct Cow: Animal {
  std::string says() { return "Moo"; }
};

struct CowProvider: AbstractProvider<Animal> {
  Animal * provide() {
    return new Cow();
  }

  void dispose(Animal * cow) {
    delete cow;
  }
};

struct Pond {
  sauce::shared_ptr<Animal> animal;

  Pond(sauce::shared_ptr<Animal> animal):
    animal(animal) {}
};

void AnimalModule(Binder & binder) {
  binder.bind<Animal>().to<Cat()>();
  binder.bind<Animal>().named<LieutenantShinysides>().to<Fish()>();
  binder.bind<Animal>().named<Meatloaf>().toProvider<CowProvider()>();

  binder.bind<Pond>().to<Pond(Named<Animal, LieutenantShinysides>)>();
}

int main() {
  sauce::shared_ptr<Injector> injector(Modules().add(&AnimalModule).createInjector());

  #ifdef __STRICT_ANSI__
  return 0;
  #else
  std::cerr << "This file was not compiled with -ansi." << std::endl;
  return 1;
  #endif
}
<|endoftext|>