<commit_before>/**************************************************************************
**
** This file is part of Qt Creator
**
** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).
**
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** No Commercial Usage
**
** This file contains pre-release code and may not be distributed.
** You may use this file in accordance with the terms and conditions
** contained in the Technology Preview License Agreement accompanying
** this package.
**
** GNU Lesser General Public License Usage
**
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file.  Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights.  These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
**
**************************************************************************/

#include "qmlprofilersummaryview.h"

#include <QtCore/QUrl>
#include <QtCore/QHash>

#include <QtGui/QHeaderView>
#include <QtGui/QStandardItemModel>

using namespace QmlProfiler::Internal;

struct BindingData {
    QString displayname;
    QString filename;
    int line;
    qint64 duration;
    qint64 calls;
    qint64 minTime;
    qint64 maxTime;
    double tpc;
    double percent;
};

class QmlProfilerSummaryView::QmlProfilerSummaryViewPrivate
{
public:
    QmlProfilerSummaryViewPrivate(QmlProfilerSummaryView *qq):q(qq) {}
    ~QmlProfilerSummaryViewPrivate() {}

    QmlProfilerSummaryView *q;

    QStandardItemModel *m_model;
    QHash<QString, BindingData *> m_bindingHash;

    enum RangeType {
        Painting,
        Compiling,
        Creating,
        Binding,
        HandlingSignal,

        MaximumRangeType
    };
};

class ProfilerItem : public QStandardItem
{
public:
    ProfilerItem(const QString &text):QStandardItem ( text ) {}

    virtual bool operator< ( const QStandardItem & other ) const
    {
        if (data().type() == QVariant::String) {
            // first column
            return data(Qt::UserRole+2).toString() == other.data(Qt::UserRole+2).toString() ?
                        data(Qt::UserRole+3).toInt() < other.data(Qt::UserRole+3).toInt() :
                        data(Qt::UserRole+2).toString() < other.data(Qt::UserRole+2).toString();
        }

        return data().toDouble() < other.data().toDouble();
    }
};

QmlProfilerSummaryView::QmlProfilerSummaryView(QWidget *parent) :
    QTreeView(parent), d(new QmlProfilerSummaryViewPrivate(this))
{
    setRootIsDecorated(false);
    header()->setResizeMode(QHeaderView::Interactive);
    header()->setMinimumSectionSize(100);
    setSortingEnabled(false);

    d->m_model = new QStandardItemModel(this);

    setModel(d->m_model);

    d->m_model->setColumnCount(7);
    setHeaderLabels();

    connect(this,SIGNAL(clicked(QModelIndex)), this,SLOT(jumpToItem(QModelIndex)));
}

QmlProfilerSummaryView::~QmlProfilerSummaryView()
{
    delete d->m_model;
}

void QmlProfilerSummaryView::clean()
{
    d->m_model->clear();
    d->m_model->setColumnCount(7);

    // clean the hash
    QHashIterator<QString, BindingData *>it(d->m_bindingHash);
    while (it.hasNext()) {
        it.next();
        delete it.value();
    }
    d->m_bindingHash.clear();

    setHeaderLabels();
    setSortingEnabled(false);
}

void QmlProfilerSummaryView::addRangedEvent(int type, qint64 startTime, qint64 length, const QStringList &data, const QString &fileName, int line)
{
    Q_UNUSED(startTime);
    Q_UNUSED(data);

    if (type != QmlProfilerSummaryViewPrivate::Binding && type != QmlProfilerSummaryViewPrivate::HandlingSignal)
        return;

    if (fileName.isEmpty())
        return;
    QString localName = QUrl(fileName).toLocalFile();
    QString displayName = localName.mid(localName.lastIndexOf(QChar('/'))+1)+QLatin1String(":")+QString::number(line);
    QString location = fileName+":"+QString::number(line);

    QHash<QString, BindingData *>::iterator it = d->m_bindingHash.find(location);
    if (it != d->m_bindingHash.end()) {
        BindingData *bindingInfo = it.value();
        bindingInfo->duration += length;
        bindingInfo->calls++;
        if (bindingInfo->maxTime < length)
            bindingInfo->maxTime = length;
        if (bindingInfo->minTime > length)
            bindingInfo->minTime = length;
    } else {
        BindingData *newBinding = new BindingData;
        newBinding->calls = 1;
        newBinding->duration = length;
        newBinding->displayname = displayName;
        newBinding->filename = fileName;
        newBinding->line = line;
        newBinding->minTime = length;
        newBinding->maxTime = length;

        d->m_bindingHash.insert(location, newBinding);
    }
}

void QmlProfilerSummaryView::complete()
{
    // compute percentages
    double totalTime = 0;

    QHashIterator<QString, BindingData *> it(d->m_bindingHash);

    while (it.hasNext()) {
        it.next();
        totalTime += it.value()->duration;
    }

    it.toFront();

    while (it.hasNext()) {
        it.next();
        BindingData *binding = it.value();
        binding->percent = binding->duration * 100.0 / totalTime;
        binding->tpc = binding->calls>0? (double)binding->duration / binding->calls : 0;

        appendRow(binding->displayname,
                  binding->filename,
                  binding->line,
                  binding->percent,
                  binding->duration,
                  binding->calls,
                  binding->tpc,
                  binding->maxTime,
                  binding->minTime);

    }
    setSortingEnabled(true);
    sortByColumn(1,Qt::DescendingOrder);
    resizeColumnToContents(0);
}

void QmlProfilerSummaryView::jumpToItem(const QModelIndex &index)
{
    int line = d->m_model->item(index.row(),0)->data(Qt::UserRole+3).toInt();
    if (line == -1)
        return;
    QString fileName = d->m_model->item(index.row(),0)->data(Qt::UserRole+2).toString();
    emit gotoSourceLocation(fileName, line);
}

void QmlProfilerSummaryView::appendRow(const QString &displayName,
                const QString &fileName,
                int line,
                double percentTime,
                double totalTime,
                int nCalls,
                double timePerCall,
                double maxTime,
                double minTime)
{
    QString location =fileName+":"+QString::number(line);
    ProfilerItem *locationColumn = new ProfilerItem(displayName);
    locationColumn->setData(QVariant(location),Qt::UserRole+1);
    locationColumn->setData(QVariant(fileName),Qt::UserRole+2);
    locationColumn->setData(QVariant(line),Qt::UserRole+3);
    locationColumn->setEditable(false);
    ProfilerItem *percentColumn = new ProfilerItem(QString::number(percentTime,'f',2)+QLatin1String(" %"));
    percentColumn->setData(QVariant(percentTime));
    percentColumn->setEditable(false);
    ProfilerItem *timeColumn = new ProfilerItem(displayTime(totalTime));
    timeColumn->setData(QVariant(totalTime));
    timeColumn->setEditable(false);
    ProfilerItem *callsColumn = new ProfilerItem(QString::number(nCalls));
    callsColumn->setData(QVariant(nCalls));
    callsColumn->setEditable(false);
    ProfilerItem *tpcColumn = new ProfilerItem(displayTime(timePerCall));
    tpcColumn->setData(QVariant(timePerCall));
    tpcColumn->setEditable(false);
    ProfilerItem *maxTimeColumn = new ProfilerItem(displayTime(maxTime));
    maxTimeColumn->setData(QVariant(maxTime));
    maxTimeColumn->setEditable(false);
    ProfilerItem *minTimeColumn = new ProfilerItem(displayTime(minTime));
    minTimeColumn->setData(QVariant(minTime));
    minTimeColumn->setEditable(false);

    QList<QStandardItem *> newRow;
    newRow << locationColumn << percentColumn << timeColumn << callsColumn << tpcColumn << maxTimeColumn << minTimeColumn;
    d->m_model->appendRow(newRow);
}

QString QmlProfilerSummaryView::displayTime(double time) const
{
    if (time<1e6)
        return QString::number(time/1e3,'f',3) + QString::fromUtf8(" \u03BCs");//(" \u03BCs");
    if (time<1e9)
        return QString::number(time/1e6,'f',3) + QLatin1String(" ms");

    return QString::number(time/1e9,'f',3) + QLatin1String(" s");
}

void QmlProfilerSummaryView::setHeaderLabels()
{
    d->m_model->setHeaderData(0,Qt::Horizontal,QVariant(tr("location")));
    d->m_model->setHeaderData(1,Qt::Horizontal,QVariant(tr("% time")));
    d->m_model->setHeaderData(2,Qt::Horizontal,QVariant(tr("total time")));
    d->m_model->setHeaderData(3,Qt::Horizontal,QVariant(tr("calls")));
    d->m_model->setHeaderData(4,Qt::Horizontal,QVariant(tr("time per call")));
    d->m_model->setHeaderData(5,Qt::Horizontal,QVariant(tr("longest time")));
    d->m_model->setHeaderData(6,Qt::Horizontal,QVariant(tr("shortest time")));
}
<commit_msg>QmlProfiler: Fix MSVC warning about character encoding<commit_after>/**************************************************************************
**
** This file is part of Qt Creator
**
** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).
**
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** No Commercial Usage
**
** This file contains pre-release code and may not be distributed.
** You may use this file in accordance with the terms and conditions
** contained in the Technology Preview License Agreement accompanying
** this package.
**
** GNU Lesser General Public License Usage
**
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file.  Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights.  These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
**
**************************************************************************/

#include "qmlprofilersummaryview.h"

#include <QtCore/QUrl>
#include <QtCore/QHash>

#include <QtGui/QHeaderView>
#include <QtGui/QStandardItemModel>

using namespace QmlProfiler::Internal;

struct BindingData {
    QString displayname;
    QString filename;
    int line;
    qint64 duration;
    qint64 calls;
    qint64 minTime;
    qint64 maxTime;
    double tpc;
    double percent;
};

class QmlProfilerSummaryView::QmlProfilerSummaryViewPrivate
{
public:
    QmlProfilerSummaryViewPrivate(QmlProfilerSummaryView *qq):q(qq) {}
    ~QmlProfilerSummaryViewPrivate() {}

    QmlProfilerSummaryView *q;

    QStandardItemModel *m_model;
    QHash<QString, BindingData *> m_bindingHash;

    enum RangeType {
        Painting,
        Compiling,
        Creating,
        Binding,
        HandlingSignal,

        MaximumRangeType
    };
};

class ProfilerItem : public QStandardItem
{
public:
    ProfilerItem(const QString &text):QStandardItem ( text ) {}

    virtual bool operator< ( const QStandardItem & other ) const
    {
        if (data().type() == QVariant::String) {
            // first column
            return data(Qt::UserRole+2).toString() == other.data(Qt::UserRole+2).toString() ?
                        data(Qt::UserRole+3).toInt() < other.data(Qt::UserRole+3).toInt() :
                        data(Qt::UserRole+2).toString() < other.data(Qt::UserRole+2).toString();
        }

        return data().toDouble() < other.data().toDouble();
    }
};

QmlProfilerSummaryView::QmlProfilerSummaryView(QWidget *parent) :
    QTreeView(parent), d(new QmlProfilerSummaryViewPrivate(this))
{
    setRootIsDecorated(false);
    header()->setResizeMode(QHeaderView::Interactive);
    header()->setMinimumSectionSize(100);
    setSortingEnabled(false);

    d->m_model = new QStandardItemModel(this);

    setModel(d->m_model);

    d->m_model->setColumnCount(7);
    setHeaderLabels();

    connect(this,SIGNAL(clicked(QModelIndex)), this,SLOT(jumpToItem(QModelIndex)));
}

QmlProfilerSummaryView::~QmlProfilerSummaryView()
{
    delete d->m_model;
}

void QmlProfilerSummaryView::clean()
{
    d->m_model->clear();
    d->m_model->setColumnCount(7);

    // clean the hash
    QHashIterator<QString, BindingData *>it(d->m_bindingHash);
    while (it.hasNext()) {
        it.next();
        delete it.value();
    }
    d->m_bindingHash.clear();

    setHeaderLabels();
    setSortingEnabled(false);
}

void QmlProfilerSummaryView::addRangedEvent(int type, qint64 startTime, qint64 length, const QStringList &data, const QString &fileName, int line)
{
    Q_UNUSED(startTime);
    Q_UNUSED(data);

    if (type != QmlProfilerSummaryViewPrivate::Binding && type != QmlProfilerSummaryViewPrivate::HandlingSignal)
        return;

    if (fileName.isEmpty())
        return;
    QString localName = QUrl(fileName).toLocalFile();
    QString displayName = localName.mid(localName.lastIndexOf(QChar('/'))+1)+QLatin1String(":")+QString::number(line);
    QString location = fileName+":"+QString::number(line);

    QHash<QString, BindingData *>::iterator it = d->m_bindingHash.find(location);
    if (it != d->m_bindingHash.end()) {
        BindingData *bindingInfo = it.value();
        bindingInfo->duration += length;
        bindingInfo->calls++;
        if (bindingInfo->maxTime < length)
            bindingInfo->maxTime = length;
        if (bindingInfo->minTime > length)
            bindingInfo->minTime = length;
    } else {
        BindingData *newBinding = new BindingData;
        newBinding->calls = 1;
        newBinding->duration = length;
        newBinding->displayname = displayName;
        newBinding->filename = fileName;
        newBinding->line = line;
        newBinding->minTime = length;
        newBinding->maxTime = length;

        d->m_bindingHash.insert(location, newBinding);
    }
}

void QmlProfilerSummaryView::complete()
{
    // compute percentages
    double totalTime = 0;

    QHashIterator<QString, BindingData *> it(d->m_bindingHash);

    while (it.hasNext()) {
        it.next();
        totalTime += it.value()->duration;
    }

    it.toFront();

    while (it.hasNext()) {
        it.next();
        BindingData *binding = it.value();
        binding->percent = binding->duration * 100.0 / totalTime;
        binding->tpc = binding->calls>0? (double)binding->duration / binding->calls : 0;

        appendRow(binding->displayname,
                  binding->filename,
                  binding->line,
                  binding->percent,
                  binding->duration,
                  binding->calls,
                  binding->tpc,
                  binding->maxTime,
                  binding->minTime);

    }
    setSortingEnabled(true);
    sortByColumn(1,Qt::DescendingOrder);
    resizeColumnToContents(0);
}

void QmlProfilerSummaryView::jumpToItem(const QModelIndex &index)
{
    int line = d->m_model->item(index.row(),0)->data(Qt::UserRole+3).toInt();
    if (line == -1)
        return;
    QString fileName = d->m_model->item(index.row(),0)->data(Qt::UserRole+2).toString();
    emit gotoSourceLocation(fileName, line);
}

void QmlProfilerSummaryView::appendRow(const QString &displayName,
                const QString &fileName,
                int line,
                double percentTime,
                double totalTime,
                int nCalls,
                double timePerCall,
                double maxTime,
                double minTime)
{
    QString location =fileName+":"+QString::number(line);
    ProfilerItem *locationColumn = new ProfilerItem(displayName);
    locationColumn->setData(QVariant(location),Qt::UserRole+1);
    locationColumn->setData(QVariant(fileName),Qt::UserRole+2);
    locationColumn->setData(QVariant(line),Qt::UserRole+3);
    locationColumn->setEditable(false);
    ProfilerItem *percentColumn = new ProfilerItem(QString::number(percentTime,'f',2)+QLatin1String(" %"));
    percentColumn->setData(QVariant(percentTime));
    percentColumn->setEditable(false);
    ProfilerItem *timeColumn = new ProfilerItem(displayTime(totalTime));
    timeColumn->setData(QVariant(totalTime));
    timeColumn->setEditable(false);
    ProfilerItem *callsColumn = new ProfilerItem(QString::number(nCalls));
    callsColumn->setData(QVariant(nCalls));
    callsColumn->setEditable(false);
    ProfilerItem *tpcColumn = new ProfilerItem(displayTime(timePerCall));
    tpcColumn->setData(QVariant(timePerCall));
    tpcColumn->setEditable(false);
    ProfilerItem *maxTimeColumn = new ProfilerItem(displayTime(maxTime));
    maxTimeColumn->setData(QVariant(maxTime));
    maxTimeColumn->setEditable(false);
    ProfilerItem *minTimeColumn = new ProfilerItem(displayTime(minTime));
    minTimeColumn->setData(QVariant(minTime));
    minTimeColumn->setEditable(false);

    QList<QStandardItem *> newRow;
    newRow << locationColumn << percentColumn << timeColumn << callsColumn << tpcColumn << maxTimeColumn << minTimeColumn;
    d->m_model->appendRow(newRow);
}

QString QmlProfilerSummaryView::displayTime(double time) const
{
    if (time<1e6)
        return QString::number(time/1e3,'f',3) + QString::fromWCharArray(L" \u03BCs");
    if (time<1e9)
        return QString::number(time/1e6,'f',3) + QLatin1String(" ms");

    return QString::number(time/1e9,'f',3) + QLatin1String(" s");
}

void QmlProfilerSummaryView::setHeaderLabels()
{
    d->m_model->setHeaderData(0,Qt::Horizontal,QVariant(tr("location")));
    d->m_model->setHeaderData(1,Qt::Horizontal,QVariant(tr("% time")));
    d->m_model->setHeaderData(2,Qt::Horizontal,QVariant(tr("total time")));
    d->m_model->setHeaderData(3,Qt::Horizontal,QVariant(tr("calls")));
    d->m_model->setHeaderData(4,Qt::Horizontal,QVariant(tr("time per call")));
    d->m_model->setHeaderData(5,Qt::Horizontal,QVariant(tr("longest time")));
    d->m_model->setHeaderData(6,Qt::Horizontal,QVariant(tr("shortest time")));
}
<|endoftext|>


<commit_before>/* bzflag
 * Copyright (c) 1993 - 2008 Tim Riker
 *
 * This package is free software;  you can redistribute it and/or
 * modify it under the terms of the license found in the file
 * named COPYING that should have accompanied this file.
 *
 * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
 */

// BZFlag common header
#include "common.h"

// interface header
#include "TextUtils.h"

// system headers
#include <string.h>
#include <string>
#include <algorithm>
#include <sstream>
#include <stdarg.h>
#include <vector>
#include <stdio.h>

#ifndef _TEXT_UTIL_NO_REGEX_
// common headers
#include "bzregex.h"
#endif //_TEXT_UTIL_NO_REGEX_

namespace TextUtils
{
  std::string vformat(const char* fmt, va_list args) {
    const int fixedbs = 8192;
    char buffer[fixedbs];
    const int bs = vsnprintf(buffer, fixedbs, fmt, args) + 1;
    if (bs > fixedbs) {
      char *bufp = new char[bs];
      vsnprintf(bufp, bs, fmt, args);
      std::string ret = bufp;
      delete[] bufp;
      return ret;
    }

    return buffer;
  }

  std::string format(const char* fmt, ...) {
    va_list args;
    va_start(args, fmt);
    std::string result = vformat(fmt, args);
    va_end(args);
    return result;
  }

  std::wstring convert_to_wide(const std::string& string)
  {
#ifdef _WIN32    // Get the required size for the new array and allocate the memory for it
    int neededSize = MultiByteToWideChar(CP_ACP, 0, string.c_str(), -1, 0, 0);
    wchar_t* wideCharString = new wchar_t[neededSize];

    MultiByteToWideChar(CP_ACP, 0, string.c_str(), -1, wideCharString, neededSize);

    std::wstring wideString(wideCharString);
    delete[] wideCharString;
    return wideString;
#else
    // borrowed from a message by Paul McKenzie at
    // http://www.codeguru.com/forum/archive/index.php/t-193852.html
    // FIXME: This probably does not perform the desired conversion, but
    // at least it compiles cleanly.  Probably, mbstowcs() should be used.
    std::wstring temp(string.length(),L' ');
    std::copy(string.begin(), string.end(), temp.begin());
    return temp;
#endif // _WIN32
  }

  std::string replace_all(const std::string& in, const std::string& replaceMe, const std::string& withMe)
  {
    std::string result;
    std::string::size_type beginPos = 0;
    std::string::size_type endPos = 0;
    std::ostringstream tempStream;

    endPos = in.find(replaceMe);
    if (endPos == std::string::npos)
      return in; // can't find anything to replace
    if (replaceMe.empty()) return in; // can't replace nothing with something -- can do reverse

    while (endPos != std::string::npos) {
      // push the  part up to
      tempStream << in.substr(beginPos,endPos-beginPos);
      tempStream << withMe;
      beginPos = endPos + replaceMe.size();
      endPos = in.find(replaceMe,beginPos);
    }
    tempStream << in.substr(beginPos);
    return tempStream.str();
  }

  std::string no_whitespace(const std::string &s)
  {
    const int sourcesize = (int)s.size();

    int count = 0, i = 0, j = 0;
    for (i = 0; i < sourcesize; i++)
      if (!isWhitespace(s[i]))
	count++;

    // create result string of correct size
    std::string result(count, ' ');

    for (i = 0, j = 0; i < sourcesize; i++)
      if (!isWhitespace(s[i]))
	result[j++] = s[i];

    return result;
  }

  std::vector<std::string> tokenize(const std::string& in, const std::string &delims, const int maxTokens, const bool useQuotes){
    std::vector<std::string> tokens;
    int numTokens = 0;
    bool inQuote = false;

    std::ostringstream currentToken;

    const std::string::size_type len = in.size();
    std::string::size_type pos = in.find_first_not_of(delims);

    int currentChar  = (pos == std::string::npos) ? -1 : in[pos];
    bool enoughTokens = (maxTokens && (numTokens >= (maxTokens-1)));

    while (pos < len && pos != std::string::npos && !enoughTokens) {

      // get next token
      bool tokenDone = false;
      bool foundSlash = false;

      currentChar = (pos < len) ? in[pos] : -1;
      while ((currentChar != -1) && !tokenDone){

	tokenDone = false;

	if (delims.find(currentChar) != std::string::npos && !inQuote) { // currentChar is a delim
	  pos ++;
	  break; // breaks out of inner while loop
	}

	if (!useQuotes){
	  currentToken << char(currentChar);
	} else {

	  switch (currentChar){
	    case '\\' : // found a backslash
	      if (foundSlash){
		currentToken << char(currentChar);
		foundSlash = false;
	      } else {
		foundSlash = true;
	      }
	      break;
	    case '\"' : // found a quote
	      if (foundSlash){ // found \"
		currentToken << char(currentChar);
		foundSlash = false;
	      } else { // found unescaped "
		if (inQuote){ // exiting a quote
		  // finish off current token
		  tokenDone = true;
		  inQuote = false;
		  //slurp off one additional delimeter if possible
		  if (pos+1 < len &&
		      delims.find(in[pos+1]) != std::string::npos) {
		    pos++;
		  }

		} else { // entering a quote
		  // finish off current token
		  tokenDone = true;
		  inQuote = true;
		}
	      }
	      break;
	    default:
	      if (foundSlash){ // don't care about slashes except for above cases
		currentToken << '\\';
		foundSlash = false;
	      }
	      currentToken << char(currentChar);
	      break;
	  }
	}

	pos++;
	currentChar = (pos < len) ? in[pos] : -1;
      } // end of getting a Token

      if (currentToken.str().size() > 0){ // if the token is something add to list
	tokens.push_back(currentToken.str());
	currentToken.str("");
	numTokens ++;
      }

      enoughTokens = (maxTokens && (numTokens >= (maxTokens-1)));
      if ((pos < len) && (pos != std::string::npos)) {
	pos = in.find_first_not_of(delims,pos);
      }

    } // end of getting all tokens -- either EOL or max tokens reached

    if (enoughTokens && pos != std::string::npos) {
      std::string lastToken = in.substr(pos);
      if (lastToken.size() > 0)
	tokens.push_back(lastToken);
    }

    return tokens;
  }

  bool parseDuration(const char *duration, int &durationInt)
  {
#ifndef _TEXT_UTIL_NO_REGEX_
    if (strcasecmp(duration,"short") == 0
	|| strcasecmp(duration,"default") == 0) {
      durationInt = -1;
      return true;
    }
    if (strcasecmp(duration,"forever") == 0
	|| strcasecmp(duration,"max") == 0) {
      durationInt = 0;
      return true;
    }

    regex_t preg;
    int res = regcomp(&preg, "^([[:digit:]]+[hwdm]?)+$",
		      REG_ICASE | REG_NOSUB | REG_EXTENDED);
    res = regexec(&preg, duration, 0, NULL, 0);
    regfree(&preg);
    if (res == REG_NOMATCH)
      return false;

    durationInt = 0;
    int t = 0;
    int len = (int)strlen(duration);
    for (int i = 0; i < len; i++) {
      if (isdigit(duration[i])) {
	t = t * 10 + (duration[i] - '0');
      } else if(duration[i] == 'h' || duration[i] == 'H') {
	durationInt += (t * 60);
	t = 0;
      } else if(duration[i] == 'd' || duration[i] == 'D') {
	durationInt += (t * 1440);
	t = 0;
      } else if(duration[i] == 'w' || duration[i] == 'W') {
	durationInt += (t * 10080);
	t = 0;
      } else if(duration[i] == 'm' || duration[i] == 'M') {
	durationInt += (t);
	t = 0;
      }
    }
    durationInt += t;
    return true;
#else
    return false;
#endif //_TEXT_UTIL_NO_REGEX_
  }

  std::string url_encode(const std::string &text)
  {
    char hex[5];
    std::string destination;
    for (size_t i=0;  i < text.size(); ++i) {
      unsigned char c = text[i];
      if (isAlphanumeric(c)) {
	destination+=c;
      } else if (isWhitespace(c)) {
	destination+='+';
      } else {
	destination+='%';
	sprintf(hex, "%-2.2X", c);
	destination.append(hex);
      }
    }
    return destination;
  }

  std::string escape(const std::string &text, char escaper)
  {
    std::string destination;
    for (int i = 0; i < (int) text.size(); i++) {
      char c = text[i];
      if (!isAlphanumeric(c))
	destination += escaper;
      destination += c;
    }
    return destination;
  }

  std::string unescape(const std::string &text, char escaper)
  {
    const int len = (int) text.size();
    std::string destination;
    for (int i = 0; i < len; i++) {
      char c = text[i];
      if (c == escaper) {
	if (i < len - 1)
	  destination += text[++i];
	// Otherwise should print an error
      } else {
	destination += c;
      }
    }
    return destination;
  }

  int unescape_lookup(const std::string &text, char escaper, char sep)
  {
    int position = -1;
    for (int i = 0; i < (int) text.size(); i++) {
      char c = text[i];
      if (c == sep) {
	position = i;
	break;
      }
      if (c == escaper)
	i++;
    }
    return position;
  }

  // return a copy of a string, truncated to specified length,
  //    make last char a '`' if truncation took place
  std::string str_trunc_continued (const std::string &text, int len)
  {
    std::string retstr = std::string (text, 0, len);
    if ( retstr.size() == (unsigned int)len  )
      retstr[len-1] = '~';
    return retstr;
  }

}

// Local Variables: ***
// mode: C++ ***
// tab-width: 8 ***
// c-basic-offset: 2 ***
// indent-tabs-mode: t ***
// End: ***
// ex: shiftwidth=2 tabstop=8
<commit_msg>Implement wide-string-ization on nonwindows platforms<commit_after>/* bzflag
 * Copyright (c) 1993 - 2008 Tim Riker
 *
 * This package is free software;  you can redistribute it and/or
 * modify it under the terms of the license found in the file
 * named COPYING that should have accompanied this file.
 *
 * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
 */

// BZFlag common header
#include "common.h"

// interface header
#include "TextUtils.h"

// system headers
#include <string.h>
#include <string>
#include <algorithm>
#include <sstream>
#include <stdarg.h>
#include <vector>
#include <stdio.h>
#include <functional>
#include <locale>

#ifndef _TEXT_UTIL_NO_REGEX_
// common headers
#include "bzregex.h"
#endif //_TEXT_UTIL_NO_REGEX_

namespace TextUtils
{
  std::string vformat(const char* fmt, va_list args) {
    const int fixedbs = 8192;
    char buffer[fixedbs];
    const int bs = vsnprintf(buffer, fixedbs, fmt, args) + 1;
    if (bs > fixedbs) {
      char *bufp = new char[bs];
      vsnprintf(bufp, bs, fmt, args);
      std::string ret = bufp;
      delete[] bufp;
      return ret;
    }

    return buffer;
  }

  std::string format(const char* fmt, ...) {
    va_list args;
    va_start(args, fmt);
    std::string result = vformat(fmt, args);
    va_end(args);
    return result;
  }

  std::wstring convert_to_wide(const std::string& string)
  {
#ifdef _WIN32    // Get the required size for the new array and allocate the memory for it
    int neededSize = MultiByteToWideChar(CP_ACP, 0, string.c_str(), -1, 0, 0);
    wchar_t* wideCharString = new wchar_t[neededSize];

    MultiByteToWideChar(CP_ACP, 0, string.c_str(), -1, wideCharString, neededSize);

    std::wstring wideString(wideCharString);
    delete[] wideCharString;
    return wideString;
#else
    std::wstring out;
    wchar_t* buf = new wchar_t[string.size() + 1];
    mbstowcs(buf, string.c_str(), string.size());
    buf[string.size()] = 0;
    out = buf;
    delete[] buf;
    return out;
#endif // _WIN32
  }

  std::string replace_all(const std::string& in, const std::string& replaceMe, const std::string& withMe)
  {
    std::string result;
    std::string::size_type beginPos = 0;
    std::string::size_type endPos = 0;
    std::ostringstream tempStream;

    endPos = in.find(replaceMe);
    if (endPos == std::string::npos)
      return in; // can't find anything to replace
    if (replaceMe.empty()) return in; // can't replace nothing with something -- can do reverse

    while (endPos != std::string::npos) {
      // push the  part up to
      tempStream << in.substr(beginPos,endPos-beginPos);
      tempStream << withMe;
      beginPos = endPos + replaceMe.size();
      endPos = in.find(replaceMe,beginPos);
    }
    tempStream << in.substr(beginPos);
    return tempStream.str();
  }

  std::string no_whitespace(const std::string &s)
  {
    const int sourcesize = (int)s.size();

    int count = 0, i = 0, j = 0;
    for (i = 0; i < sourcesize; i++)
      if (!isWhitespace(s[i]))
	count++;

    // create result string of correct size
    std::string result(count, ' ');

    for (i = 0, j = 0; i < sourcesize; i++)
      if (!isWhitespace(s[i]))
	result[j++] = s[i];

    return result;
  }

  std::vector<std::string> tokenize(const std::string& in, const std::string &delims, const int maxTokens, const bool useQuotes){
    std::vector<std::string> tokens;
    int numTokens = 0;
    bool inQuote = false;

    std::ostringstream currentToken;

    const std::string::size_type len = in.size();
    std::string::size_type pos = in.find_first_not_of(delims);

    int currentChar  = (pos == std::string::npos) ? -1 : in[pos];
    bool enoughTokens = (maxTokens && (numTokens >= (maxTokens-1)));

    while (pos < len && pos != std::string::npos && !enoughTokens) {

      // get next token
      bool tokenDone = false;
      bool foundSlash = false;

      currentChar = (pos < len) ? in[pos] : -1;
      while ((currentChar != -1) && !tokenDone){

	tokenDone = false;

	if (delims.find(currentChar) != std::string::npos && !inQuote) { // currentChar is a delim
	  pos ++;
	  break; // breaks out of inner while loop
	}

	if (!useQuotes){
	  currentToken << char(currentChar);
	} else {

	  switch (currentChar){
	    case '\\' : // found a backslash
	      if (foundSlash){
		currentToken << char(currentChar);
		foundSlash = false;
	      } else {
		foundSlash = true;
	      }
	      break;
	    case '\"' : // found a quote
	      if (foundSlash){ // found \"
		currentToken << char(currentChar);
		foundSlash = false;
	      } else { // found unescaped "
		if (inQuote){ // exiting a quote
		  // finish off current token
		  tokenDone = true;
		  inQuote = false;
		  //slurp off one additional delimeter if possible
		  if (pos+1 < len &&
		      delims.find(in[pos+1]) != std::string::npos) {
		    pos++;
		  }

		} else { // entering a quote
		  // finish off current token
		  tokenDone = true;
		  inQuote = true;
		}
	      }
	      break;
	    default:
	      if (foundSlash){ // don't care about slashes except for above cases
		currentToken << '\\';
		foundSlash = false;
	      }
	      currentToken << char(currentChar);
	      break;
	  }
	}

	pos++;
	currentChar = (pos < len) ? in[pos] : -1;
      } // end of getting a Token

      if (currentToken.str().size() > 0){ // if the token is something add to list
	tokens.push_back(currentToken.str());
	currentToken.str("");
	numTokens ++;
      }

      enoughTokens = (maxTokens && (numTokens >= (maxTokens-1)));
      if ((pos < len) && (pos != std::string::npos)) {
	pos = in.find_first_not_of(delims,pos);
      }

    } // end of getting all tokens -- either EOL or max tokens reached

    if (enoughTokens && pos != std::string::npos) {
      std::string lastToken = in.substr(pos);
      if (lastToken.size() > 0)
	tokens.push_back(lastToken);
    }

    return tokens;
  }

  bool parseDuration(const char *duration, int &durationInt)
  {
#ifndef _TEXT_UTIL_NO_REGEX_
    if (strcasecmp(duration,"short") == 0
	|| strcasecmp(duration,"default") == 0) {
      durationInt = -1;
      return true;
    }
    if (strcasecmp(duration,"forever") == 0
	|| strcasecmp(duration,"max") == 0) {
      durationInt = 0;
      return true;
    }

    regex_t preg;
    int res = regcomp(&preg, "^([[:digit:]]+[hwdm]?)+$",
		      REG_ICASE | REG_NOSUB | REG_EXTENDED);
    res = regexec(&preg, duration, 0, NULL, 0);
    regfree(&preg);
    if (res == REG_NOMATCH)
      return false;

    durationInt = 0;
    int t = 0;
    int len = (int)strlen(duration);
    for (int i = 0; i < len; i++) {
      if (isdigit(duration[i])) {
	t = t * 10 + (duration[i] - '0');
      } else if(duration[i] == 'h' || duration[i] == 'H') {
	durationInt += (t * 60);
	t = 0;
      } else if(duration[i] == 'd' || duration[i] == 'D') {
	durationInt += (t * 1440);
	t = 0;
      } else if(duration[i] == 'w' || duration[i] == 'W') {
	durationInt += (t * 10080);
	t = 0;
      } else if(duration[i] == 'm' || duration[i] == 'M') {
	durationInt += (t);
	t = 0;
      }
    }
    durationInt += t;
    return true;
#else
    return false;
#endif //_TEXT_UTIL_NO_REGEX_
  }

  std::string url_encode(const std::string &text)
  {
    char hex[5];
    std::string destination;
    for (size_t i=0;  i < text.size(); ++i) {
      unsigned char c = text[i];
      if (isAlphanumeric(c)) {
	destination+=c;
      } else if (isWhitespace(c)) {
	destination+='+';
      } else {
	destination+='%';
	sprintf(hex, "%-2.2X", c);
	destination.append(hex);
      }
    }
    return destination;
  }

  std::string escape(const std::string &text, char escaper)
  {
    std::string destination;
    for (int i = 0; i < (int) text.size(); i++) {
      char c = text[i];
      if (!isAlphanumeric(c))
	destination += escaper;
      destination += c;
    }
    return destination;
  }

  std::string unescape(const std::string &text, char escaper)
  {
    const int len = (int) text.size();
    std::string destination;
    for (int i = 0; i < len; i++) {
      char c = text[i];
      if (c == escaper) {
	if (i < len - 1)
	  destination += text[++i];
	// Otherwise should print an error
      } else {
	destination += c;
      }
    }
    return destination;
  }

  int unescape_lookup(const std::string &text, char escaper, char sep)
  {
    int position = -1;
    for (int i = 0; i < (int) text.size(); i++) {
      char c = text[i];
      if (c == sep) {
	position = i;
	break;
      }
      if (c == escaper)
	i++;
    }
    return position;
  }

  // return a copy of a string, truncated to specified length,
  //    make last char a '`' if truncation took place
  std::string str_trunc_continued (const std::string &text, int len)
  {
    std::string retstr = std::string (text, 0, len);
    if ( retstr.size() == (unsigned int)len  )
      retstr[len-1] = '~';
    return retstr;
  }

}

// Local Variables: ***
// mode: C++ ***
// tab-width: 8 ***
// c-basic-offset: 2 ***
// indent-tabs-mode: t ***
// End: ***
// ex: shiftwidth=2 tabstop=8
<|endoftext|>


<commit_before>// This file is part of the dune-stuff project:
//   https://github.com/wwu-numerik/dune-stuff/
// Copyright holders: Rene Milk, Felix Schindler
// License: BSD 2-Clause License (http://opensource.org/licenses/BSD-2-Clause)

// This one has to come first (includes the config.h)!
#include "main.hxx"

#include <tuple>

#include <dune/stuff/common/exceptions.hh>
#include <dune/stuff/common/logging.hh>
#include <dune/stuff/la/container.hh>
#include <dune/stuff/la/solver.hh>

#include "la_container.hh"

// toggle output
//std::ostream& out = std::cout;
std::ostream& out = DSC_LOG.devnull();

using namespace Dune::Stuff;
using namespace Dune::Stuff::LA;

typedef testing::Types< std::tuple< CommonDenseMatrix< double >, CommonDenseVector< double >, CommonDenseVector< double > >
                      , std::tuple< CommonDenseMatrix< std::complex<double> >, CommonDenseVector< std::complex<double> >, CommonDenseVector< std::complex<double> > >
#if HAVE_EIGEN
                      , std::tuple< EigenDenseMatrix< double >, EigenDenseVector< double >, EigenDenseVector< double > >
                      , std::tuple< EigenDenseMatrix< std::complex<double> >, EigenDenseVector< std::complex<double> >, EigenDenseVector< std::complex<double> > >
                      , std::tuple< EigenDenseMatrix< double >, EigenDenseVector< double >, EigenMappedDenseVector< double > >
                      , std::tuple< EigenDenseMatrix< std::complex<double> >, EigenDenseVector< std::complex<double> >, EigenMappedDenseVector< std::complex<double> > >
                      , std::tuple< EigenDenseMatrix< double >, EigenMappedDenseVector< double >, EigenDenseVector< double > >
                      , std::tuple< EigenDenseMatrix< std::complex<double> >, EigenMappedDenseVector< std::complex<double> >, EigenDenseVector< std::complex<double> > >
                      , std::tuple< EigenDenseMatrix< double >, EigenMappedDenseVector< double >, EigenMappedDenseVector< double > >
                      , std::tuple< EigenDenseMatrix< std::complex<double> >, EigenMappedDenseVector< std::complex<double> >, EigenMappedDenseVector< std::complex<double> > >
                      , std::tuple< EigenRowMajorSparseMatrix< double >, EigenDenseVector< double >, EigenDenseVector< double > >
                      , std::tuple< EigenRowMajorSparseMatrix< std::complex<double> >, EigenDenseVector< std::complex<double> >, EigenDenseVector< std::complex<double> > >
#endif // HAVE_EIGEN
#if HAVE_DUNE_ISTL
                      , std::tuple< IstlRowMajorSparseMatrix< double >, IstlDenseVector< double >, IstlDenseVector< double > >
#endif
                      > MatrixVectorCombinations;

template< class MatrixVectorCombination >
struct SolverTest
  : public ::testing::Test
{
  typedef typename std::tuple_element< 0, MatrixVectorCombination >::type MatrixType;
  typedef typename std::tuple_element< 1, MatrixVectorCombination >::type RhsType;
  typedef typename std::tuple_element< 2, MatrixVectorCombination >::type SolutionType;

  typedef Solver< MatrixType > SolverType;

  static void produces_correct_results()
  {
    const size_t dim = 10;
    const MatrixType matrix = ContainerFactory< MatrixType >::create(dim);
    const RhsType rhs = ContainerFactory< RhsType >::create(dim);
    SolutionType solution = ContainerFactory< SolutionType >::create(dim);
    solution.scal(0);

    // dynamic test
    const SolverType solver(matrix);
    solver.apply(rhs, solution);
    EXPECT_TRUE(solution.almost_equal(rhs));
    solution.scal(0);

    // static tests
    typedef typename SolverType::MatrixType M;
    std::vector< std::string > types = SolverType::types();
    if (types.size() == 0) DUNE_THROW(Exceptions::results_are_not_as_expected, "Solver has no types!");
    for (auto type : types) {
      out << "solving with type '" << type << "' and options" << std::endl;
      Common::Configuration options = SolverType::options(type);
      options.report(out, "  ");

      // dynamic tests
      solver.apply(rhs, solution, type);
      EXPECT_TRUE(solution.almost_equal(rhs));
      solution.scal(0);

      solver.apply(rhs, solution, options);
      EXPECT_TRUE(solution.almost_equal(rhs));
    }
  } // ... produces_correct_results(...)
}; // struct SolverTest

TYPED_TEST_CASE(SolverTest, MatrixVectorCombinations);
TYPED_TEST(SolverTest, behaves_correctly) {
  this->produces_correct_results();
}

<commit_msg>[solver] remove unsopprted vector imps from testing for std::complex compat<commit_after>// This file is part of the dune-stuff project:
//   https://github.com/wwu-numerik/dune-stuff/
// Copyright holders: Rene Milk, Felix Schindler
// License: BSD 2-Clause License (http://opensource.org/licenses/BSD-2-Clause)

// This one has to come first (includes the config.h)!
#include "main.hxx"

#include <tuple>

#include <dune/stuff/common/exceptions.hh>
#include <dune/stuff/common/logging.hh>
#include <dune/stuff/la/container.hh>
#include <dune/stuff/la/solver.hh>

#include "la_container.hh"

// toggle output
//std::ostream& out = std::cout;
std::ostream& out = DSC_LOG.devnull();

using namespace Dune::Stuff;
using namespace Dune::Stuff::LA;

typedef testing::Types< std::tuple< CommonDenseMatrix< double >, CommonDenseVector< double >, CommonDenseVector< double > >
                      , std::tuple< CommonDenseMatrix< std::complex<double> >, CommonDenseVector< std::complex<double> >, CommonDenseVector< std::complex<double> > >
#if HAVE_EIGEN
                      , std::tuple< EigenDenseMatrix< double >, EigenDenseVector< double >, EigenDenseVector< double > >
                      , std::tuple< EigenDenseMatrix< std::complex<double> >, EigenDenseVector< std::complex<double> >, EigenDenseVector< std::complex<double> > >
                      , std::tuple< EigenDenseMatrix< double >, EigenDenseVector< double >, EigenMappedDenseVector< double > >
                      , std::tuple< EigenDenseMatrix< double >, EigenMappedDenseVector< double >, EigenDenseVector< double > >
                      , std::tuple< EigenDenseMatrix< double >, EigenMappedDenseVector< double >, EigenMappedDenseVector< double > >
                      , std::tuple< EigenRowMajorSparseMatrix< double >, EigenDenseVector< double >, EigenDenseVector< double > >
                      , std::tuple< EigenRowMajorSparseMatrix< std::complex<double> >, EigenDenseVector< std::complex<double> >, EigenDenseVector< std::complex<double> > >
#endif // HAVE_EIGEN
#if HAVE_DUNE_ISTL
                      , std::tuple< IstlRowMajorSparseMatrix< double >, IstlDenseVector< double >, IstlDenseVector< double > >
#endif
                      > MatrixVectorCombinations;

template< class MatrixVectorCombination >
struct SolverTest
  : public ::testing::Test
{
  typedef typename std::tuple_element< 0, MatrixVectorCombination >::type MatrixType;
  typedef typename std::tuple_element< 1, MatrixVectorCombination >::type RhsType;
  typedef typename std::tuple_element< 2, MatrixVectorCombination >::type SolutionType;

  typedef Solver< MatrixType > SolverType;

  static void produces_correct_results()
  {
    const size_t dim = 10;
    const MatrixType matrix = ContainerFactory< MatrixType >::create(dim);
    const RhsType rhs = ContainerFactory< RhsType >::create(dim);
    SolutionType solution = ContainerFactory< SolutionType >::create(dim);
    solution.scal(0);

    // dynamic test
    const SolverType solver(matrix);
    solver.apply(rhs, solution);
    EXPECT_TRUE(solution.almost_equal(rhs));
    solution.scal(0);

    // static tests
    typedef typename SolverType::MatrixType M;
    std::vector< std::string > types = SolverType::types();
    if (types.size() == 0) DUNE_THROW(Exceptions::results_are_not_as_expected, "Solver has no types!");
    for (auto type : types) {
      out << "solving with type '" << type << "' and options" << std::endl;
      Common::Configuration options = SolverType::options(type);
      options.report(out, "  ");

      // dynamic tests
      solver.apply(rhs, solution, type);
      EXPECT_TRUE(solution.almost_equal(rhs));
      solution.scal(0);

      solver.apply(rhs, solution, options);
      EXPECT_TRUE(solution.almost_equal(rhs));
    }
  } // ... produces_correct_results(...)
}; // struct SolverTest

TYPED_TEST_CASE(SolverTest, MatrixVectorCombinations);
TYPED_TEST(SolverTest, behaves_correctly) {
  this->produces_correct_results();
}

<|endoftext|>


<commit_before>//===----------------------------------------------------------------------===//
// LLVM 'GCCAS' UTILITY
//
//  This utility is designed to be used by the GCC frontend for creating
// bytecode files from it's intermediate llvm assembly.  The requirements for
// this utility are thus slightly different than that of the standard as util.
//
//===----------------------------------------------------------------------===//

#include "llvm/Module.h"
#include "llvm/PassManager.h"
#include "llvm/Assembly/Parser.h"
#include "llvm/Transforms/CleanupGCCOutput.h"
#include "llvm/Transforms/LevelChange.h"
#include "llvm/Transforms/ConstantMerge.h"
#include "llvm/Transforms/ChangeAllocations.h"
#include "llvm/Transforms/Scalar.h"
#include "llvm/Analysis/Verifier.h"
#include "llvm/Bytecode/WriteBytecodePass.h"
#include "Support/CommandLine.h"
#include "Support/Signals.h"
#include <memory>
#include <fstream>
using std::cerr;

static cl::String InputFilename   ("", "Parse <arg> file, compile to bytecode",
                                   cl::Required, "");
static cl::String OutputFilename  ("o", "Override output filename");
static cl::Int    RunNPasses      ("stopAfterNPasses", "Only run the first N "
                                   "passes of gccas", cl::Hidden);
static cl::Flag   StopAtLevelRaise("stopraise", "Stop optimization before "
                                   "level raise", cl::Hidden);
static cl::Flag   Verify          ("verify", "Verify each pass result");

static inline void addPass(PassManager &PM, Pass *P) {
  static int NumPassesCreated = 0;

  // If we haven't already created the number of passes that was requested...
  if (RunNPasses == 0 || RunNPasses > NumPassesCreated) {
    // Add the pass to the pass manager...
    PM.add(P);

    // If we are verifying all of the intermediate steps, add the verifier...
    if (Verify) PM.add(createVerifierPass());

    // Keep track of how many passes we made for -stopAfterNPasses
    ++NumPassesCreated;
  }
}

void AddConfiguredTransformationPasses(PassManager &PM) {
  if (Verify) PM.add(createVerifierPass());

  addPass(PM, createFunctionResolvingPass());     // Resolve (...) functions
  addPass(PM, createConstantMergePass());         // Merge dup global constants
  addPass(PM, createDeadInstEliminationPass());   // Remove Dead code/vars
  addPass(PM, createRaiseAllocationsPass());      // call %malloc -> malloc inst
  addPass(PM, createCleanupGCCOutputPass());      // Fix gccisms
  addPass(PM, createIndVarSimplifyPass());        // Simplify indvars

  // Level raise is eternally buggy/in need of enhancements.  Allow
  // transformation to stop right before it runs.
  if (StopAtLevelRaise) return;

  addPass(PM, createRaisePointerReferencesPass());// Eliminate casts
  addPass(PM, createPromoteMemoryToRegister());   // Promote alloca's to regs
  /* addPass(PM, createReassociatePass());*/           // Reassociate expressions
  addPass(PM, createInstructionCombiningPass());  // Combine silly seq's
  addPass(PM, createDeadInstEliminationPass());   // Kill InstCombine remnants
  addPass(PM, createLICMPass());                  // Hoist loop invariants
  addPass(PM, createGCSEPass());                  // Remove common subexprs
  addPass(PM, createSCCPPass());                  // Constant prop with SCCP

  // Run instcombine after redundancy elimination to exploit opportunities
  // opened up by them.
  addPass(PM, createInstructionCombiningPass());
  addPass(PM, createAggressiveDCEPass());          // SSA based 'Agressive DCE'
  addPass(PM, createCFGSimplificationPass());      // Merge & remove BBs
}

int main(int argc, char **argv) {
  cl::ParseCommandLineOptions(argc, argv, " llvm .s -> .o assembler for GCC\n");

  std::auto_ptr<Module> M;
  try {
    // Parse the file now...
    M.reset(ParseAssemblyFile(InputFilename));
  } catch (const ParseException &E) {
    cerr << E.getMessage() << std::endl;
    return 1;
  }

  if (M.get() == 0) {
    cerr << "assembly didn't read correctly.\n";
    return 1;
  }

  if (OutputFilename == "") {   // Didn't specify an output filename?
    std::string IFN = InputFilename;
    int Len = IFN.length();
    if (IFN[Len-2] == '.' && IFN[Len-1] == 's') {   // Source ends in .s?
      OutputFilename = std::string(IFN.begin(), IFN.end()-2);
    } else {
      OutputFilename = IFN;   // Append a .o to it
    }
    OutputFilename += ".o";
  }

  std::ofstream Out(OutputFilename.c_str(), std::ios::out);
  if (!Out.good()) {
    cerr << "Error opening " << OutputFilename << "!\n";
    return 1;
  }

  // Make sure that the Out file gets unlink'd from the disk if we get a SIGINT
  RemoveFileOnSignal(OutputFilename);

  // In addition to just parsing the input from GCC, we also want to spiff it up
  // a little bit.  Do this now.
  //
  PassManager Passes;

  // Add all of the transformation passes to the pass manager to do the cleanup
  // and optimization of the GCC output.
  //
  AddConfiguredTransformationPasses(Passes);

  // Write bytecode to file...
  Passes.add(new WriteBytecodePass(&Out));

  // Run our queue of passes all at once now, efficiently.
  Passes.run(*M.get());
  return 0;
}
<commit_msg>Yes, we REALLY DO want to run the reassociate pass.<commit_after>//===----------------------------------------------------------------------===//
// LLVM 'GCCAS' UTILITY
//
//  This utility is designed to be used by the GCC frontend for creating
// bytecode files from it's intermediate llvm assembly.  The requirements for
// this utility are thus slightly different than that of the standard as util.
//
//===----------------------------------------------------------------------===//

#include "llvm/Module.h"
#include "llvm/PassManager.h"
#include "llvm/Assembly/Parser.h"
#include "llvm/Transforms/CleanupGCCOutput.h"
#include "llvm/Transforms/LevelChange.h"
#include "llvm/Transforms/ConstantMerge.h"
#include "llvm/Transforms/ChangeAllocations.h"
#include "llvm/Transforms/Scalar.h"
#include "llvm/Analysis/Verifier.h"
#include "llvm/Bytecode/WriteBytecodePass.h"
#include "Support/CommandLine.h"
#include "Support/Signals.h"
#include <memory>
#include <fstream>
using std::cerr;

static cl::String InputFilename   ("", "Parse <arg> file, compile to bytecode",
                                   cl::Required, "");
static cl::String OutputFilename  ("o", "Override output filename");
static cl::Int    RunNPasses      ("stopAfterNPasses", "Only run the first N "
                                   "passes of gccas", cl::Hidden);
static cl::Flag   StopAtLevelRaise("stopraise", "Stop optimization before "
                                   "level raise", cl::Hidden);
static cl::Flag   Verify          ("verify", "Verify each pass result");

static inline void addPass(PassManager &PM, Pass *P) {
  static int NumPassesCreated = 0;

  // If we haven't already created the number of passes that was requested...
  if (RunNPasses == 0 || RunNPasses > NumPassesCreated) {
    // Add the pass to the pass manager...
    PM.add(P);

    // If we are verifying all of the intermediate steps, add the verifier...
    if (Verify) PM.add(createVerifierPass());

    // Keep track of how many passes we made for -stopAfterNPasses
    ++NumPassesCreated;
  }
}

void AddConfiguredTransformationPasses(PassManager &PM) {
  if (Verify) PM.add(createVerifierPass());

  addPass(PM, createFunctionResolvingPass());     // Resolve (...) functions
  addPass(PM, createConstantMergePass());         // Merge dup global constants
  addPass(PM, createDeadInstEliminationPass());   // Remove Dead code/vars
  addPass(PM, createRaiseAllocationsPass());      // call %malloc -> malloc inst
  addPass(PM, createCleanupGCCOutputPass());      // Fix gccisms
  addPass(PM, createIndVarSimplifyPass());        // Simplify indvars

  // Level raise is eternally buggy/in need of enhancements.  Allow
  // transformation to stop right before it runs.
  if (StopAtLevelRaise) return;

  addPass(PM, createRaisePointerReferencesPass());// Eliminate casts
  addPass(PM, createPromoteMemoryToRegister());   // Promote alloca's to regs
  addPass(PM, createReassociatePass());           // Reassociate expressions
  addPass(PM, createInstructionCombiningPass());  // Combine silly seq's
  addPass(PM, createDeadInstEliminationPass());   // Kill InstCombine remnants
  addPass(PM, createLICMPass());                  // Hoist loop invariants
  addPass(PM, createGCSEPass());                  // Remove common subexprs
  addPass(PM, createSCCPPass());                  // Constant prop with SCCP

  // Run instcombine after redundancy elimination to exploit opportunities
  // opened up by them.
  addPass(PM, createInstructionCombiningPass());
  addPass(PM, createAggressiveDCEPass());          // SSA based 'Agressive DCE'
  addPass(PM, createCFGSimplificationPass());      // Merge & remove BBs
}

int main(int argc, char **argv) {
  cl::ParseCommandLineOptions(argc, argv, " llvm .s -> .o assembler for GCC\n");

  std::auto_ptr<Module> M;
  try {
    // Parse the file now...
    M.reset(ParseAssemblyFile(InputFilename));
  } catch (const ParseException &E) {
    cerr << E.getMessage() << "\n";
    return 1;
  }

  if (M.get() == 0) {
    cerr << "assembly didn't read correctly.\n";
    return 1;
  }

  if (OutputFilename == "") {   // Didn't specify an output filename?
    std::string IFN = InputFilename;
    int Len = IFN.length();
    if (IFN[Len-2] == '.' && IFN[Len-1] == 's') {   // Source ends in .s?
      OutputFilename = std::string(IFN.begin(), IFN.end()-2);
    } else {
      OutputFilename = IFN;   // Append a .o to it
    }
    OutputFilename += ".o";
  }

  std::ofstream Out(OutputFilename.c_str(), std::ios::out);
  if (!Out.good()) {
    cerr << "Error opening " << OutputFilename << "!\n";
    return 1;
  }

  // Make sure that the Out file gets unlink'd from the disk if we get a SIGINT
  RemoveFileOnSignal(OutputFilename);

  // In addition to just parsing the input from GCC, we also want to spiff it up
  // a little bit.  Do this now.
  //
  PassManager Passes;

  // Add all of the transformation passes to the pass manager to do the cleanup
  // and optimization of the GCC output.
  //
  AddConfiguredTransformationPasses(Passes);

  // Write bytecode to file...
  Passes.add(new WriteBytecodePass(&Out));

  // Run our queue of passes all at once now, efficiently.
  Passes.run(*M.get());
  return 0;
}
<|endoftext|>


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

#include "TracksEdit.h"
#include "ui_TracksEdit.h"

#include <QColor>
#include <QtMidi.h>

#include "../Selectors/SelectInstrument.h"

TrackItem::TrackItem(QTreeWidget *tree, int track)
    : QTreeWidgetItem(tree)
{
    this->setText(TrackNumber,QString::number(track));

    volSL = new TrackSlider(this->treeWidget());
    volSL->setTracking(false);
    volSL->setMinimum(0);
    volSL->setValue(100);
    volSL->setMaximum(100);
    this->treeWidget()->setItemWidget(this,Vol,volSL);

    balSL = new TrackSlider(this->treeWidget());
    balSL->setTracking(false);
    balSL->setMinimum(-50);
    balSL->setMaximum(50);
    this->treeWidget()->setItemWidget(this,Bal,balSL);
}

TracksEdit::TracksEdit(QWidget *parent) :
    QTreeWidget(parent),
    ui(new Ui::TracksEdit)
{
    ui->setupUi(this);
    this->hideColumn(TrackItem::TrackNumber);

    colorNames = QColor::colorNames();
    colorNames.removeOne("black");
    colorNames.removeOne("white");
    colorNames.removeOne("azure");
    colorNames.removeOne("aliceblue");

    connect(this,SIGNAL(itemDoubleClicked(QTreeWidgetItem*,int)),
            this,SLOT(tracksEdit_itemDoubleClicked(QTreeWidgetItem*,int)));
    connect(this,SIGNAL(itemClicked(QTreeWidgetItem*,int)),
            this,SLOT(tracksEdit_itemClicked(QTreeWidgetItem*,int)));

    resizeColsToContents();
}

TracksEdit::~TracksEdit()
{
    delete ui;
}

void TracksEdit::resizeColsToContents()
{
    for(int i = 0;i<this->columnCount();i++)
    { this->resizeColumnToContents(i); }
}

TrackItem* TracksEdit::createTrack(int trackNum)
{
    TrackItem* ret = new TrackItem(this,trackNum);
    ret->setBackgroundColor(TrackItem::Name,QColor(colorNames.at(trackNum)));
    myTrackColors.insert(trackNum,QColor(colorNames.at(trackNum)));
    ret->setType(tr("Instrument"));
    ret->setOn(tr("on"));
    ret->setDevice("<automatic>");

    ret->volSlider()->setTrack(trackNum);
    ret->balSlider()->setTrack(trackNum);
    connect(ret->volSlider(),SIGNAL(valueChanged(int)),this,SLOT(trackItem_volChanged(int)));
    connect(ret->balSlider(),SIGNAL(valueChanged(int)),this,SLOT(trackItem_balChanged(int)));

    return ret;
}

void TracksEdit::trackItem_volChanged(int v)
{
    if(ignoreEvents) { return; }
    TrackSlider* sl = qobject_cast<TrackSlider*>(sender());
    if(!sl) { return; }
    qDebug(QString::number(v).toAscii().constData());

    int trk = sl->track();
    int vel = 127.0*(v/100.0);
    /* TODO: warn if track has velocity different in different notes */
    foreach(QtMidiEvent* e, midiFile->eventsForTrack(trk))
    {
        if(e->type() != QtMidiEvent::NoteOn) { continue; }
        e->setVelocity(vel);
    }
    emit somethingChanged();
}
void TracksEdit::trackItem_balChanged(int b)
{
    /* TODO: implement balance change.
    if(ignoreEvents) { return; }
    TrackSlider* sl = qobject_cast<TrackSlider*>(sender());
    if(!sl) { return; }
    int trk = sl->track(); */
}

QList<TrackItem*> TracksEdit::tracks()
{
    QList<TrackItem*> ret;
    QTreeWidgetItem *c;
    for(int i = 0;i<this->topLevelItemCount();i++) {
        c = this->topLevelItem(i);
        ret.append(static_cast<TrackItem*>(c));
    }
    return ret;
}

void TracksEdit::init(VirtualPiano* p)
{
    piano = p;
}

void TracksEdit::setupTracks(QtMidiFile *f)
{
    ignoreEvents = true;
    midiFile = f;
    this->clear();
    foreach(int curTrack,midiFile->tracks())
    {
        TrackItem* i = this->createTrack(curTrack);

        bool didInstr = false, didVoice = false, didMeta = false, didVol = false;
        foreach(QtMidiEvent* e, midiFile->eventsForTrack(curTrack))
        {
            if(!didVoice && e->type() == QtMidiEvent::NoteOn)
            {
                i->setVoice(e->voice());
                if(e->voice() == 9) { i->setInst(tr("Drums")); didInstr = true; }
                didVoice = true;
            }
            if(!didVol && e->type() == QtMidiEvent::NoteOn)
            {
                i->setVol((e->velocity()/127.0)*100);
                didVol = true;
            }
            else if(!didInstr && e->type() == QtMidiEvent::ProgramChange)
            {
                int instr = e->number();
                SelectInstrument sel(this);
                sel.setInsNum(instr);
                i->setInst(sel.insName());
                QtMidi::outSetInstr(e->voice(),e->number());
                didInstr = true;
            }
            else if(!didMeta && (e->type() == QtMidiEvent::Meta) &&
                    (e->number() == 0x03))
            { i->setName(e->data()); didMeta = true; } // Name

            if(didInstr && didVoice && didMeta) { break; }
        }

        if(!didInstr)
        { i->setInst(tr("(no instrument)")); }
    }
    ignoreEvents = false;
    resizeColsToContents();
}

void TracksEdit::deleteCurTrack()
{
    TrackItem* i = static_cast<TrackItem*>(this->selectedItems().at(0));
    if(!i) { return; }

    int trackNum = i->track();
    i->~QTreeWidgetItem();
    foreach(QtMidiEvent*e,midiFile->eventsForTrack(trackNum))
    {
        midiFile->removeEvent(e);
        delete e;
    }
    midiFile->removeTrack(trackNum);
}

void TracksEdit::updateTrackOn()
{
    bool isOneSolo = false;
    int soloTrack = 0;
    foreach(TrackItem* itm,tracks()) {
        if((itm->on() == tr("solo")) && !isOneSolo) {
            isOneSolo = true;
            soloTrack = itm->track();
            piano->clearTrackColors(itm->track());
        }
        bool on = (itm->on() == tr("on"));
        myTrackStatus.insert(itm->track(),on);
        if(!on) { QtMidi::outStopAll(itm->voice()); }
    }

    if(!isOneSolo) { return; }

    foreach(int i,myTrackStatus.keys()) {
        if(i == soloTrack) {
            myTrackStatus.insert(i,true);
            continue;
        }
        myTrackStatus.insert(i,false);
    }
    QtMidi::outStopAll();
    piano->clearTrackColors();
}

void TracksEdit::tracksEdit_itemDoubleClicked(QTreeWidgetItem *item, int column)
{
    TrackItem* itm = static_cast<TrackItem*>(item);
    if(column == TrackItem::Name) {
        Qt::ItemFlags oldFlags = itm->flags();
        itm->setFlags(oldFlags | Qt::ItemIsEditable);
        this->editItem(itm,column);
        itm->setFlags(oldFlags);
    } else if(column == TrackItem::Inst) {
        if(itm->voice() == 9) { return; } // drums, don't change
        SelectInstrument* ins = new SelectInstrument(this);
        ins->setModal(true);
        ins->setInsName(itm->inst());
        if(ins->exec() == QDialog::Accepted) {
            itm->setInst(ins->insName());
            foreach(QtMidiEvent*e,midiFile->eventsForTrack(itm->track())) {
                if (e->type() == QtMidiEvent::ProgramChange)
                { e->setNumber(ins->insNum()); }
            }
            QtMidi::outSetInstr(itm->voice(),ins->insNum());
        }
    }
}

void TracksEdit::tracksEdit_itemClicked(QTreeWidgetItem *item, int column)
{
    TrackItem* itm = static_cast<TrackItem*>(item);
    if(column == TrackItem::On) {
        if(itm->on() == tr("on")) {
            itm->setOn(tr("mute"));
            itm->setBackgroundColor(TrackItem::On,QColor("#a52a2a"));
            itm->setForeground(TrackItem::On,QColor(Qt::white));
            updateTrackOn();
        } else if(itm->on() == tr("mute")) {
            itm->setOn(tr("solo"));
            item->setBackgroundColor(TrackItem::On,QColor(Qt::darkBlue));
            updateTrackOn();
        } else {
            itm->setOn(tr("on"));
            itm->setBackgroundColor(TrackItem::On,QColor(Qt::white));
            itm->setForeground(TrackItem::On,QColor(Qt::black));
            updateTrackOn();
        }
    }
    VirtualPiano::voiceToUse = itm->voice();
}

<commit_msg>Auto-resize the "on?" column when changed.<commit_after>/*
 * Raging MIDI (https://github.com/waddlesplash/ragingmidi).
 *
 * Copyright (c) 2012 WaddleSplash & contributors (see AUTHORS.txt).
 *
 * Permission is hereby granted, free of charge, to any person obtaining
 * a copy of this software and associated documentation files (the "Software"),
 * to deal in the Software without restriction, including without limitation
 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
 * and/or sell copies of the Software, and to permit persons to whom the Software
 * is furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall
 * be included in all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
 * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
 * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
 * DEALINGS IN THE SOFTWARE.
 */

#include "TracksEdit.h"
#include "ui_TracksEdit.h"

#include <QColor>
#include <QtMidi.h>

#include "../Selectors/SelectInstrument.h"

TrackItem::TrackItem(QTreeWidget *tree, int track)
    : QTreeWidgetItem(tree)
{
    this->setText(TrackNumber,QString::number(track));

    volSL = new TrackSlider(this->treeWidget());
    volSL->setTracking(false);
    volSL->setMinimum(0);
    volSL->setValue(100);
    volSL->setMaximum(100);
    this->treeWidget()->setItemWidget(this,Vol,volSL);

    balSL = new TrackSlider(this->treeWidget());
    balSL->setTracking(false);
    balSL->setMinimum(-50);
    balSL->setMaximum(50);
    this->treeWidget()->setItemWidget(this,Bal,balSL);
}

TracksEdit::TracksEdit(QWidget *parent) :
    QTreeWidget(parent),
    ui(new Ui::TracksEdit)
{
    ui->setupUi(this);
    this->hideColumn(TrackItem::TrackNumber);

    colorNames = QColor::colorNames();
    colorNames.removeOne("black");
    colorNames.removeOne("white");
    colorNames.removeOne("azure");
    colorNames.removeOne("aliceblue");

    connect(this,SIGNAL(itemDoubleClicked(QTreeWidgetItem*,int)),
            this,SLOT(tracksEdit_itemDoubleClicked(QTreeWidgetItem*,int)));
    connect(this,SIGNAL(itemClicked(QTreeWidgetItem*,int)),
            this,SLOT(tracksEdit_itemClicked(QTreeWidgetItem*,int)));

    resizeColsToContents();
}

TracksEdit::~TracksEdit()
{
    delete ui;
}

void TracksEdit::resizeColsToContents()
{
    for(int i = 0;i<this->columnCount();i++)
    { this->resizeColumnToContents(i); }
}

TrackItem* TracksEdit::createTrack(int trackNum)
{
    TrackItem* ret = new TrackItem(this,trackNum);
    ret->setBackgroundColor(TrackItem::Name,QColor(colorNames.at(trackNum)));
    myTrackColors.insert(trackNum,QColor(colorNames.at(trackNum)));
    ret->setType(tr("Instrument"));
    ret->setOn(tr("on"));
    ret->setDevice("<automatic>");

    ret->volSlider()->setTrack(trackNum);
    ret->balSlider()->setTrack(trackNum);
    connect(ret->volSlider(),SIGNAL(valueChanged(int)),this,SLOT(trackItem_volChanged(int)));
    connect(ret->balSlider(),SIGNAL(valueChanged(int)),this,SLOT(trackItem_balChanged(int)));

    return ret;
}

void TracksEdit::trackItem_volChanged(int v)
{
    if(ignoreEvents) { return; }
    TrackSlider* sl = qobject_cast<TrackSlider*>(sender());
    if(!sl) { return; }
    qDebug(QString::number(v).toAscii().constData());

    int trk = sl->track();
    int vel = 127.0*(v/100.0);
    /* TODO: warn if track has velocity different in different notes */
    foreach(QtMidiEvent* e, midiFile->eventsForTrack(trk))
    {
        if(e->type() != QtMidiEvent::NoteOn) { continue; }
        e->setVelocity(vel);
    }
    emit somethingChanged();
}
void TracksEdit::trackItem_balChanged(int b)
{
    /* TODO: implement balance change.
    if(ignoreEvents) { return; }
    TrackSlider* sl = qobject_cast<TrackSlider*>(sender());
    if(!sl) { return; }
    int trk = sl->track(); */
}

QList<TrackItem*> TracksEdit::tracks()
{
    QList<TrackItem*> ret;
    QTreeWidgetItem *c;
    for(int i = 0;i<this->topLevelItemCount();i++) {
        c = this->topLevelItem(i);
        ret.append(static_cast<TrackItem*>(c));
    }
    return ret;
}

void TracksEdit::init(VirtualPiano* p)
{
    piano = p;
}

void TracksEdit::setupTracks(QtMidiFile *f)
{
    ignoreEvents = true;
    midiFile = f;
    this->clear();
    foreach(int curTrack,midiFile->tracks())
    {
        TrackItem* i = this->createTrack(curTrack);

        bool didInstr = false, didVoice = false, didMeta = false, didVol = false;
        foreach(QtMidiEvent* e, midiFile->eventsForTrack(curTrack))
        {
            if(!didVoice && e->type() == QtMidiEvent::NoteOn)
            {
                i->setVoice(e->voice());
                if(e->voice() == 9) { i->setInst(tr("Drums")); didInstr = true; }
                didVoice = true;
            }
            if(!didVol && e->type() == QtMidiEvent::NoteOn)
            {
                i->setVol((e->velocity()/127.0)*100);
                didVol = true;
            }
            else if(!didInstr && e->type() == QtMidiEvent::ProgramChange)
            {
                int instr = e->number();
                SelectInstrument sel(this);
                sel.setInsNum(instr);
                i->setInst(sel.insName());
                QtMidi::outSetInstr(e->voice(),e->number());
                didInstr = true;
            }
            else if(!didMeta && (e->type() == QtMidiEvent::Meta) &&
                    (e->number() == 0x03))
            { i->setName(e->data()); didMeta = true; } // Name

            if(didInstr && didVoice && didMeta) { break; }
        }

        if(!didInstr)
        { i->setInst(tr("(no instrument)")); }
    }
    ignoreEvents = false;
    resizeColsToContents();
}

void TracksEdit::deleteCurTrack()
{
    TrackItem* i = static_cast<TrackItem*>(this->selectedItems().at(0));
    if(!i) { return; }

    int trackNum = i->track();
    i->~QTreeWidgetItem();
    foreach(QtMidiEvent*e,midiFile->eventsForTrack(trackNum))
    {
        midiFile->removeEvent(e);
        delete e;
    }
    midiFile->removeTrack(trackNum);
}

void TracksEdit::updateTrackOn()
{
    bool isOneSolo = false;
    int soloTrack = 0;
    foreach(TrackItem* itm,tracks()) {
        if((itm->on() == tr("solo")) && !isOneSolo) {
            isOneSolo = true;
            soloTrack = itm->track();
            piano->clearTrackColors(itm->track());
        }
        bool on = (itm->on() == tr("on"));
        myTrackStatus.insert(itm->track(),on);
        if(!on) { QtMidi::outStopAll(itm->voice()); }
    }

    if(!isOneSolo) { return; }

    foreach(int i,myTrackStatus.keys()) {
        if(i == soloTrack) {
            myTrackStatus.insert(i,true);
            continue;
        }
        myTrackStatus.insert(i,false);
    }
    QtMidi::outStopAll();
    piano->clearTrackColors();
}

void TracksEdit::tracksEdit_itemDoubleClicked(QTreeWidgetItem *item, int column)
{
    TrackItem* itm = static_cast<TrackItem*>(item);
    if(column == TrackItem::Name) {
        Qt::ItemFlags oldFlags = itm->flags();
        itm->setFlags(oldFlags | Qt::ItemIsEditable);
        this->editItem(itm,column);
        itm->setFlags(oldFlags);
    } else if(column == TrackItem::Inst) {
        if(itm->voice() == 9) { return; } // drums, don't change
        SelectInstrument* ins = new SelectInstrument(this);
        ins->setModal(true);
        ins->setInsName(itm->inst());
        if(ins->exec() == QDialog::Accepted) {
            itm->setInst(ins->insName());
            foreach(QtMidiEvent*e,midiFile->eventsForTrack(itm->track())) {
                if (e->type() == QtMidiEvent::ProgramChange)
                { e->setNumber(ins->insNum()); }
            }
            QtMidi::outSetInstr(itm->voice(),ins->insNum());
        }
    }
}

void TracksEdit::tracksEdit_itemClicked(QTreeWidgetItem *item, int column)
{
    TrackItem* itm = static_cast<TrackItem*>(item);
    if(column == TrackItem::On) {
        if(itm->on() == tr("on")) {
            itm->setOn(tr("mute"));
            itm->setBackgroundColor(TrackItem::On,QColor("#a52a2a"));
            itm->setForeground(TrackItem::On,QColor(Qt::white));
            updateTrackOn();
        } else if(itm->on() == tr("mute")) {
            itm->setOn(tr("solo"));
            item->setBackgroundColor(TrackItem::On,QColor(Qt::darkBlue));
            updateTrackOn();
        } else {
            itm->setOn(tr("on"));
            itm->setBackgroundColor(TrackItem::On,QColor(Qt::white));
            itm->setForeground(TrackItem::On,QColor(Qt::black));
            updateTrackOn();
        }
        this->resizeColumnToContents(TrackItem::On);
    }
    VirtualPiano::voiceToUse = itm->voice();
}

<|endoftext|>


<commit_before>
//
// This source file is part of appleseed.
// Visit http://appleseedhq.net/ for additional information and resources.
//
// This software is released under the MIT license.
//
// Copyright (c) 2015 Esteban Tovagliari, The appleseedhq Organization
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
//

// Interface header.
#include "oslbssrdf.h"

// appleseed.renderer headers.
#include "renderer/kernel/shading/closures.h"
#include "renderer/kernel/shading/shadingpoint.h"
#include "renderer/modeling/bssrdf/betterdipolebssrdf.h"
#include "renderer/modeling/bssrdf/bssrdf.h"
#include "renderer/modeling/bssrdf/bssrdfsample.h"
#include "renderer/modeling/bssrdf/directionaldipolebssrdf.h"
#ifdef APPLESEED_WITH_NORMALIZED_DIFFUSION_BSSRDF
#include "renderer/modeling/bssrdf/normalizeddiffusionbssrdf.h"
#endif
#include "renderer/modeling/bssrdf/standarddipolebssrdf.h"
#include "renderer/modeling/input/inputevaluator.h"

// appleseed.foundation headers.
#include "foundation/utility/containers/dictionary.h"
#include "foundation/utility/containers/specializedarrays.h"

// Standard headers.
#include <cassert>

using namespace foundation;

namespace renderer
{

namespace
{

    //
    // OSL BSSRDF.
    //

    class OSLBSSRDF
      : public BSSRDF
    {
      public:
        OSLBSSRDF(
            const char*             name,
            const ParamArray&       params)
          : BSSRDF(name, params)
        {
            memset(m_all_bssrdfs, 0, sizeof(BSSRDF*) * NumClosuresIDs);

            m_better_dipole =
                create_and_register_bssrdf<BetterDipoleBSSRDFFactory>(
                    SubsurfaceBetterDipoleID,
                    "better_dipole");

            m_dir_dipole =
                create_and_register_bssrdf<DirectionalDipoleBSSRDFFactory>(
                    SubsurfaceDirectionalDipoleID,
                    "dir_dipole");

#ifdef APPLESEED_WITH_NORMALIZED_DIFFUSION_BSSRDF
            m_normalized =
                create_and_register_bssrdf<NormalizedDiffusionBSSRDFFactory>(
                    SubsurfaceNormalizedDiffusionID,
                    "normalized");
#endif

            m_std_dipole =
                create_and_register_bssrdf<StandardDipoleBSSRDFFactory>(
                    SubsurfaceStandardDipoleID,
                    "std_dipole");
        }

        virtual void release() APPLESEED_OVERRIDE
        {
            delete this;
        }

        virtual const char* get_model() const APPLESEED_OVERRIDE
        {
            return "osl_bssrdf";
        }

        virtual bool on_frame_begin(
            const Project&          project,
            const Assembly&         assembly,
            IAbortSwitch*           abort_switch = 0) APPLESEED_OVERRIDE
        {
            if (!BSSRDF::on_frame_begin(project, assembly, abort_switch))
                return false;

            for (int i = 0; i < NumClosuresIDs; ++i)
            {
                if (BSSRDF* bsrsdf = m_all_bssrdfs[i])
                {
                    if (!bsrsdf->on_frame_begin(project, assembly))
                        return false;
                }
            }

            return true;
        }

        virtual void on_frame_end(
            const Project&          project,
            const Assembly&         assembly) APPLESEED_OVERRIDE
        {
            for (int i = 0; i < NumClosuresIDs; ++i)
            {
                if (BSSRDF* bsrsdf = m_all_bssrdfs[i])
                    bsrsdf->on_frame_end(project, assembly);
            }

            BSSRDF::on_frame_end(project, assembly);
        }

        virtual size_t compute_input_data_size(
            const Assembly&         assembly) const
        {
            return sizeof(CompositeSubsurfaceClosure);
        }

        virtual void evaluate_inputs(
            const ShadingContext&   shading_context,
            InputEvaluator&         input_evaluator,
            const ShadingPoint&     shading_point,
            const size_t            offset = 0) const APPLESEED_OVERRIDE
        {
            CompositeSubsurfaceClosure* c = reinterpret_cast<CompositeSubsurfaceClosure*>(input_evaluator.data());
            new (c) CompositeSubsurfaceClosure(
                shading_point.get_shading_basis(),
                shading_point.get_osl_shader_globals().Ci);

            prepare_inputs(input_evaluator.data());
        }

        virtual void prepare_inputs(void* data) const APPLESEED_OVERRIDE
        {
            const CompositeSubsurfaceClosure* c =
                reinterpret_cast<const CompositeSubsurfaceClosure*>(data);

            for (size_t i = 0, e = c->get_num_closures(); i < e; ++i)
            {
                bssrdf_from_closure_id(c->get_closure_type(i)).prepare_inputs(
                    c->get_closure_input_values(i));
            }
        }

        virtual bool sample(
            SamplingContext&        sampling_context,
            const void*             data,
            BSSRDFSample&           sample) const APPLESEED_OVERRIDE
        {
            const CompositeSubsurfaceClosure* c =
                reinterpret_cast<const CompositeSubsurfaceClosure*>(data);

            if (c->get_num_closures() > 0)
            {
                sampling_context.split_in_place(1, 1);
                const double s = sampling_context.next_double2();
                const size_t closure_index = c->choose_closure(s);

                sample.m_shading_basis =
                    &c->get_closure_shading_basis(closure_index);

                return
                    bssrdf_from_closure_id(c->get_closure_type(closure_index)).sample(
                        sampling_context,
                        c->get_closure_input_values(closure_index),
                        sample);
            }

            return false;
        }

        virtual void evaluate(
            const void*             data,
            const ShadingPoint&     outgoing_point,
            const Vector3d&         outgoing_dir,
            const ShadingPoint&     incoming_point,
            const Vector3d&         incoming_dir,
            Spectrum&               value) const APPLESEED_OVERRIDE
        {
            const CompositeSubsurfaceClosure* c =
                reinterpret_cast<const CompositeSubsurfaceClosure*>(data);

            value.set(0.0f);

            for (size_t i = 0, e = c->get_num_closures(); i < e; ++i)
            {
                Spectrum s;
                bssrdf_from_closure_id(c->get_closure_type(i)).evaluate(
                    c->get_closure_input_values(i),
                    outgoing_point,
                    outgoing_dir,
                    incoming_point,
                    incoming_dir,
                    s);

                s *= static_cast<float>(c->get_closure_pdf_weight(i));
                value += s;
            }
        }

        virtual double evaluate_pdf(
            const void*             data,
            const size_t            channel,
            const double            dist) const APPLESEED_OVERRIDE
        {
            const CompositeSubsurfaceClosure* c =
                reinterpret_cast<const CompositeSubsurfaceClosure*>(data);

            double pdf = 0.0;

            for (size_t i = 0, e = c->get_num_closures(); i < e; ++i)
            {
                pdf +=
                    bssrdf_from_closure_id(c->get_closure_type(i)).evaluate_pdf(
                        c->get_closure_input_values(i),
                        channel,
                        dist) * c->get_closure_pdf_weight(i);
            }

            return pdf;
        }

      private:
        template <typename BSSRDFFactory>
        auto_release_ptr<BSSRDF> create_and_register_bssrdf(
            const ClosureID         cid,
            const char*             name)
        {
            auto_release_ptr<BSSRDF> bssrdf = BSSRDFFactory().create(name, ParamArray());
            m_all_bssrdfs[cid] = bssrdf.get();
            return bssrdf;
        }

        const BSSRDF& bssrdf_from_closure_id(const ClosureID cid) const
        {
            const BSSRDF* bssrdf = m_all_bssrdfs[cid];
            assert(bssrdf);
            return *bssrdf;
        }

        BSSRDF& bssrdf_from_closure_id(const ClosureID cid)
        {
            BSSRDF* bssrdf = m_all_bssrdfs[cid];
            assert(bssrdf);
            return *bssrdf;
        }

        auto_release_ptr<BSSRDF>    m_better_dipole;
        auto_release_ptr<BSSRDF>    m_dir_dipole;
        auto_release_ptr<BSSRDF>    m_gaussian;
#ifdef APPLESEED_WITH_NORMALIZED_DIFFUSION_BSSRDF
        auto_release_ptr<BSSRDF>    m_normalized;
#endif
        auto_release_ptr<BSSRDF>    m_std_dipole;

        BSSRDF*                     m_all_bssrdfs[NumClosuresIDs];
    };
}

//
// OSLBSSRDFFactory class implementation.
//

auto_release_ptr<BSSRDF> OSLBSSRDFFactory::create() const
{
    return auto_release_ptr<BSSRDF>(new OSLBSSRDF("osl_bssrdf", ParamArray()));
}

}   // namespace renderer
<commit_msg>Fixed wrong OSL subsurface closures weights.<commit_after>
//
// This source file is part of appleseed.
// Visit http://appleseedhq.net/ for additional information and resources.
//
// This software is released under the MIT license.
//
// Copyright (c) 2015 Esteban Tovagliari, The appleseedhq Organization
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
//

// Interface header.
#include "oslbssrdf.h"

// appleseed.renderer headers.
#include "renderer/kernel/shading/closures.h"
#include "renderer/kernel/shading/shadingpoint.h"
#include "renderer/modeling/bssrdf/betterdipolebssrdf.h"
#include "renderer/modeling/bssrdf/bssrdf.h"
#include "renderer/modeling/bssrdf/bssrdfsample.h"
#include "renderer/modeling/bssrdf/directionaldipolebssrdf.h"
#ifdef APPLESEED_WITH_NORMALIZED_DIFFUSION_BSSRDF
#include "renderer/modeling/bssrdf/normalizeddiffusionbssrdf.h"
#endif
#include "renderer/modeling/bssrdf/standarddipolebssrdf.h"
#include "renderer/modeling/input/inputevaluator.h"

// appleseed.foundation headers.
#include "foundation/utility/containers/dictionary.h"
#include "foundation/utility/containers/specializedarrays.h"

// Standard headers.
#include <cassert>

using namespace foundation;

namespace renderer
{

namespace
{

    //
    // OSL BSSRDF.
    //

    class OSLBSSRDF
      : public BSSRDF
    {
      public:
        OSLBSSRDF(
            const char*             name,
            const ParamArray&       params)
          : BSSRDF(name, params)
        {
            memset(m_all_bssrdfs, 0, sizeof(BSSRDF*) * NumClosuresIDs);

            m_better_dipole =
                create_and_register_bssrdf<BetterDipoleBSSRDFFactory>(
                    SubsurfaceBetterDipoleID,
                    "better_dipole");

            m_dir_dipole =
                create_and_register_bssrdf<DirectionalDipoleBSSRDFFactory>(
                    SubsurfaceDirectionalDipoleID,
                    "dir_dipole");

#ifdef APPLESEED_WITH_NORMALIZED_DIFFUSION_BSSRDF
            m_normalized =
                create_and_register_bssrdf<NormalizedDiffusionBSSRDFFactory>(
                    SubsurfaceNormalizedDiffusionID,
                    "normalized");
#endif

            m_std_dipole =
                create_and_register_bssrdf<StandardDipoleBSSRDFFactory>(
                    SubsurfaceStandardDipoleID,
                    "std_dipole");
        }

        virtual void release() APPLESEED_OVERRIDE
        {
            delete this;
        }

        virtual const char* get_model() const APPLESEED_OVERRIDE
        {
            return "osl_bssrdf";
        }

        virtual bool on_frame_begin(
            const Project&          project,
            const Assembly&         assembly,
            IAbortSwitch*           abort_switch = 0) APPLESEED_OVERRIDE
        {
            if (!BSSRDF::on_frame_begin(project, assembly, abort_switch))
                return false;

            for (int i = 0; i < NumClosuresIDs; ++i)
            {
                if (BSSRDF* bsrsdf = m_all_bssrdfs[i])
                {
                    if (!bsrsdf->on_frame_begin(project, assembly))
                        return false;
                }
            }

            return true;
        }

        virtual void on_frame_end(
            const Project&          project,
            const Assembly&         assembly) APPLESEED_OVERRIDE
        {
            for (int i = 0; i < NumClosuresIDs; ++i)
            {
                if (BSSRDF* bsrsdf = m_all_bssrdfs[i])
                    bsrsdf->on_frame_end(project, assembly);
            }

            BSSRDF::on_frame_end(project, assembly);
        }

        virtual size_t compute_input_data_size(
            const Assembly&         assembly) const
        {
            return sizeof(CompositeSubsurfaceClosure);
        }

        virtual void evaluate_inputs(
            const ShadingContext&   shading_context,
            InputEvaluator&         input_evaluator,
            const ShadingPoint&     shading_point,
            const size_t            offset = 0) const APPLESEED_OVERRIDE
        {
            CompositeSubsurfaceClosure* c = reinterpret_cast<CompositeSubsurfaceClosure*>(input_evaluator.data());
            new (c) CompositeSubsurfaceClosure(
                shading_point.get_shading_basis(),
                shading_point.get_osl_shader_globals().Ci);

            prepare_inputs(input_evaluator.data());
        }

        virtual void prepare_inputs(void* data) const APPLESEED_OVERRIDE
        {
            const CompositeSubsurfaceClosure* c =
                reinterpret_cast<const CompositeSubsurfaceClosure*>(data);

            for (size_t i = 0, e = c->get_num_closures(); i < e; ++i)
            {
                bssrdf_from_closure_id(c->get_closure_type(i)).prepare_inputs(
                    c->get_closure_input_values(i));
            }
        }

        virtual bool sample(
            SamplingContext&        sampling_context,
            const void*             data,
            BSSRDFSample&           sample) const APPLESEED_OVERRIDE
        {
            const CompositeSubsurfaceClosure* c =
                reinterpret_cast<const CompositeSubsurfaceClosure*>(data);

            if (c->get_num_closures() > 0)
            {
                sampling_context.split_in_place(1, 1);
                const double s = sampling_context.next_double2();
                const size_t closure_index = c->choose_closure(s);

                sample.m_shading_basis =
                    &c->get_closure_shading_basis(closure_index);

                return
                    bssrdf_from_closure_id(c->get_closure_type(closure_index)).sample(
                        sampling_context,
                        c->get_closure_input_values(closure_index),
                        sample);
            }

            return false;
        }

        virtual void evaluate(
            const void*             data,
            const ShadingPoint&     outgoing_point,
            const Vector3d&         outgoing_dir,
            const ShadingPoint&     incoming_point,
            const Vector3d&         incoming_dir,
            Spectrum&               value) const APPLESEED_OVERRIDE
        {
            const CompositeSubsurfaceClosure* c =
                reinterpret_cast<const CompositeSubsurfaceClosure*>(data);

            value.set(0.0f);

            for (size_t i = 0, e = c->get_num_closures(); i < e; ++i)
            {
                Spectrum s;
                bssrdf_from_closure_id(c->get_closure_type(i)).evaluate(
                    c->get_closure_input_values(i),
                    outgoing_point,
                    outgoing_dir,
                    incoming_point,
                    incoming_dir,
                    s);

                s *= c->get_closure_weight(i);
                value += s;
            }
        }

        virtual double evaluate_pdf(
            const void*             data,
            const size_t            channel,
            const double            dist) const APPLESEED_OVERRIDE
        {
            const CompositeSubsurfaceClosure* c =
                reinterpret_cast<const CompositeSubsurfaceClosure*>(data);

            double pdf = 0.0;

            for (size_t i = 0, e = c->get_num_closures(); i < e; ++i)
            {
                pdf +=
                    bssrdf_from_closure_id(c->get_closure_type(i)).evaluate_pdf(
                        c->get_closure_input_values(i),
                        channel,
                        dist) * c->get_closure_pdf_weight(i);
            }

            return pdf;
        }

      private:
        template <typename BSSRDFFactory>
        auto_release_ptr<BSSRDF> create_and_register_bssrdf(
            const ClosureID         cid,
            const char*             name)
        {
            auto_release_ptr<BSSRDF> bssrdf = BSSRDFFactory().create(name, ParamArray());
            m_all_bssrdfs[cid] = bssrdf.get();
            return bssrdf;
        }

        const BSSRDF& bssrdf_from_closure_id(const ClosureID cid) const
        {
            const BSSRDF* bssrdf = m_all_bssrdfs[cid];
            assert(bssrdf);
            return *bssrdf;
        }

        BSSRDF& bssrdf_from_closure_id(const ClosureID cid)
        {
            BSSRDF* bssrdf = m_all_bssrdfs[cid];
            assert(bssrdf);
            return *bssrdf;
        }

        auto_release_ptr<BSSRDF>    m_better_dipole;
        auto_release_ptr<BSSRDF>    m_dir_dipole;
        auto_release_ptr<BSSRDF>    m_gaussian;
#ifdef APPLESEED_WITH_NORMALIZED_DIFFUSION_BSSRDF
        auto_release_ptr<BSSRDF>    m_normalized;
#endif
        auto_release_ptr<BSSRDF>    m_std_dipole;

        BSSRDF*                     m_all_bssrdfs[NumClosuresIDs];
    };
}

//
// OSLBSSRDFFactory class implementation.
//

auto_release_ptr<BSSRDF> OSLBSSRDFFactory::create() const
{
    return auto_release_ptr<BSSRDF>(new OSLBSSRDF("osl_bssrdf", ParamArray()));
}

}   // namespace renderer
<|endoftext|>