<commit_before>/**************************************************************************
**
** This file is part of Qt Creator
**
** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
**
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** Commercial Usage
**
** Licensees holding valid Qt Commercial licenses may use this file in
** accordance with the Qt Commercial License Agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Nokia.
**
** 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.
**
** If you are unsure which license is appropriate for your use, please
** contact the sales department at http://qt.nokia.com/contact.
**
**************************************************************************/

#include "qtoutputformatter.h"

#include <texteditor/basetexteditor.h>
#include <qt4projectmanager/qt4project.h>

#include <QtCore/QFileInfo>
#include <QtCore/QUrl>
#include <QtGui/QPlainTextEdit>
#include <QtGui/QTextCursor>

using namespace ProjectExplorer;
using namespace Qt4ProjectManager;

QtOutputFormatter::QtOutputFormatter(ProjectExplorer::Project *project)
    : OutputFormatter()
    , m_qmlError(QLatin1String("(file:///.+:\\d+:\\d+):"))
    , m_qtError(QLatin1String("Object::.*in (.*:\\d+)"))
    , m_qtAssert(QLatin1String("^ASSERT: .* in file (.+, line \\d+)$"))
    , m_qtTestFail(QLatin1String("^   Loc: \\[(.*)\\]$"))
    , m_project(project)
{
}

LinkResult QtOutputFormatter::matchLine(const QString &line) const
{
    LinkResult lr;
    lr.start = -1;
    lr.end = -1;

    if (m_qmlError.indexIn(line) != -1) {
        lr.href = m_qmlError.cap(1);
        lr.start = m_qmlError.pos(1);
        lr.end = lr.start + lr.href.length();
    } else if (m_qtError.indexIn(line) != -1) {
        lr.href = m_qtError.cap(1);
        lr.start = m_qtError.pos(1);
        lr.end = lr.start + lr.href.length();
    } else if (m_qtAssert.indexIn(line) != -1) {
        lr.href = m_qtAssert.cap(1);
        lr.start = m_qtAssert.pos(1);
        lr.end = lr.start + lr.href.length();
    } else if (m_qtTestFail.indexIn(line) != -1) {
        lr.href = m_qtTestFail.cap(1);
        lr.start = m_qtTestFail.pos(1);
        lr.end = lr.start + lr.href.length();
    }
    return lr;
}

void QtOutputFormatter::appendApplicationOutput(const QString &txt, bool onStdErr)
{
    QTextCursor cursor(plainTextEdit()->document());
    cursor.movePosition(QTextCursor::End);
    cursor.beginEditBlock();

    QString text = txt;
    text.remove(QLatin1Char('\r'));

    QString deferedText;

    int start = 0;
    int pos = txt.indexOf(QLatin1Char('\n'));
    while (pos != -1) {
        // Line identified
        if (!m_lastLine.isEmpty()) {
            // Line continuation
            const QString newPart = txt.mid(start, pos - start + 1);
            const QString line = m_lastLine + newPart;
            LinkResult lr = matchLine(line);
            if (!lr.href.isEmpty()) {
                // Found something && line continuation
                cursor.insertText(deferedText, format(onStdErr ? StdErrFormat : StdOutFormat));
                deferedText.clear();
                clearLastLine();
                appendLine(cursor, lr, line, onStdErr);
            } else {
                // Found nothing, just emit the new part
                deferedText += newPart;
            }
            // Handled line continuation
            m_lastLine.clear();
        } else {
            const QString line = txt.mid(start, pos - start + 1);
            LinkResult lr = matchLine(line);
            if (!lr.href.isEmpty()) {
                cursor.insertText(deferedText, format(onStdErr ? StdErrFormat : StdOutFormat));
                deferedText.clear();
                appendLine(cursor, lr, line, onStdErr);
            } else {
                deferedText += line;
            }
        }
        start = pos + 1;
        pos = txt.indexOf(QLatin1Char('\n'), start);
    }

    // Handle left over stuff
    if (start < txt.length()) {
        if (!m_lastLine.isEmpty()) {
            // Line continuation
            const QString newPart = txt.mid(start);
            m_lastLine.append(newPart);
            LinkResult lr = matchLine(m_lastLine);
            if (!lr.href.isEmpty()) {
                // Found something && line continuation
                cursor.insertText(deferedText, format(onStdErr ? StdErrFormat : StdOutFormat));
                deferedText.clear();
                clearLastLine();
                appendLine(cursor, lr, m_lastLine, onStdErr);
            } else {
                // Found nothing, just emit the new part
                deferedText += newPart;
            }
        } else {
            m_lastLine = txt.mid(start);
            LinkResult lr = matchLine(m_lastLine);
            if (!lr.href.isEmpty()) {
                cursor.insertText(deferedText, format(onStdErr ? StdErrFormat : StdOutFormat));
                deferedText.clear();
                appendLine(cursor, lr, m_lastLine, onStdErr);
            } else {
                deferedText += m_lastLine;
            }
        }
    }
    cursor.insertText(deferedText, format(onStdErr ? StdErrFormat : StdOutFormat));
    // deferedText.clear();
    cursor.endEditBlock();
}

void QtOutputFormatter::appendLine(QTextCursor &cursor, LinkResult lr, const QString &line, bool onStdErr)
{
    const QTextCharFormat normalFormat = format(onStdErr ? StdErrFormat : StdOutFormat);
    cursor.insertText(line.left(lr.start), normalFormat);

    QTextCharFormat linkFormat = normalFormat;
    const QColor textColor = plainTextEdit()->palette().color(QPalette::Text);
    linkFormat.setForeground(mixColors(textColor, QColor(Qt::blue)));
    linkFormat.setUnderlineStyle(QTextCharFormat::SingleUnderline);
    linkFormat.setAnchor(true);
    linkFormat.setAnchorHref(lr.href);
    cursor.insertText(line.mid(lr.start, lr.end - lr.start), linkFormat);

    cursor.insertText(line.mid(lr.end), normalFormat);
}

void QtOutputFormatter::handleLink(const QString &href)
{
    if (!href.isEmpty()) {
        const QRegExp qmlErrorLink(QLatin1String("^(file:///.+):(\\d+):(\\d+)"));

        if (qmlErrorLink.indexIn(href) != -1) {
            const QString fileName = QUrl(qmlErrorLink.cap(1)).toLocalFile();
            const int line = qmlErrorLink.cap(2).toInt();
            const int column = qmlErrorLink.cap(3).toInt();
            TextEditor::BaseTextEditor::openEditorAt(fileName, line, column - 1);
            return;
        }

        QString fileName;
        int line = -1;

        QRegExp qtErrorLink(QLatin1String("^(.*):(\\d+)$"));
        if (qtErrorLink.indexIn(href) != -1) {
            fileName = qtErrorLink.cap(1);
            line = qtErrorLink.cap(2).toInt();
        }

        QRegExp qtAssertLink(QLatin1String("^(.+), line (\\d+)$"));
        if (qtAssertLink.indexIn(href) != -1) {
            fileName = qtAssertLink.cap(1);
            line = qtAssertLink.cap(2).toInt();
        }

        QRegExp qtTestFailLink(QLatin1String("^(.*)\\((\\d+)\\)$"));
        if (qtTestFailLink.indexIn(href) != -1) {
            fileName = qtTestFailLink.cap(1);
            line = qtTestFailLink.cap(2).toInt();
        }

        if (!fileName.isEmpty()) {
            QFileInfo fi(fileName);
            if (fi.isRelative()) {
                // Yeah fileName is relative, no surprise
                ProjectExplorer::Project *pro = m_project.data();
                if (pro) {
                    QString baseName = fi.fileName();
                    foreach (const QString &file, pro->files(Project::AllFiles)) {
                        if (file.endsWith(baseName)) {
                            // pick the first one...
                            fileName = file;
                            break;
                        }
                    }
                }
            }
            TextEditor::BaseTextEditor::openEditorAt(fileName, line, 0);
            return;
        }
    }
}
<commit_msg>ApplicationOutput: Also linkify qml errors without column.<commit_after>/**************************************************************************
**
** This file is part of Qt Creator
**
** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
**
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** Commercial Usage
**
** Licensees holding valid Qt Commercial licenses may use this file in
** accordance with the Qt Commercial License Agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Nokia.
**
** 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.
**
** If you are unsure which license is appropriate for your use, please
** contact the sales department at http://qt.nokia.com/contact.
**
**************************************************************************/

#include "qtoutputformatter.h"

#include <texteditor/basetexteditor.h>
#include <qt4projectmanager/qt4project.h>

#include <QtCore/QFileInfo>
#include <QtCore/QUrl>
#include <QtGui/QPlainTextEdit>
#include <QtGui/QTextCursor>

using namespace ProjectExplorer;
using namespace Qt4ProjectManager;

QtOutputFormatter::QtOutputFormatter(ProjectExplorer::Project *project)
    : OutputFormatter()
    , m_qmlError(QLatin1String("^(file:///.+"    // file url
                               ":\\d+"           // colon, line
                               "(?::\\d+)?)"     // colon, column (optional)
                               ":"))             // colon
    , m_qtError(QLatin1String("Object::.*in (.*:\\d+)"))
    , m_qtAssert(QLatin1String("^ASSERT: .* in file (.+, line \\d+)$"))
    , m_qtTestFail(QLatin1String("^   Loc: \\[(.*)\\]$"))
    , m_project(project)
{
}

LinkResult QtOutputFormatter::matchLine(const QString &line) const
{
    LinkResult lr;
    lr.start = -1;
    lr.end = -1;

    if (m_qmlError.indexIn(line) != -1) {
        lr.href = m_qmlError.cap(1);
        lr.start = m_qmlError.pos(1);
        lr.end = lr.start + lr.href.length();
    } else if (m_qtError.indexIn(line) != -1) {
        lr.href = m_qtError.cap(1);
        lr.start = m_qtError.pos(1);
        lr.end = lr.start + lr.href.length();
    } else if (m_qtAssert.indexIn(line) != -1) {
        lr.href = m_qtAssert.cap(1);
        lr.start = m_qtAssert.pos(1);
        lr.end = lr.start + lr.href.length();
    } else if (m_qtTestFail.indexIn(line) != -1) {
        lr.href = m_qtTestFail.cap(1);
        lr.start = m_qtTestFail.pos(1);
        lr.end = lr.start + lr.href.length();
    }
    return lr;
}

void QtOutputFormatter::appendApplicationOutput(const QString &txt, bool onStdErr)
{
    QTextCursor cursor(plainTextEdit()->document());
    cursor.movePosition(QTextCursor::End);
    cursor.beginEditBlock();

    QString text = txt;
    text.remove(QLatin1Char('\r'));

    QString deferedText;

    int start = 0;
    int pos = txt.indexOf(QLatin1Char('\n'));
    while (pos != -1) {
        // Line identified
        if (!m_lastLine.isEmpty()) {
            // Line continuation
            const QString newPart = txt.mid(start, pos - start + 1);
            const QString line = m_lastLine + newPart;
            LinkResult lr = matchLine(line);
            if (!lr.href.isEmpty()) {
                // Found something && line continuation
                cursor.insertText(deferedText, format(onStdErr ? StdErrFormat : StdOutFormat));
                deferedText.clear();
                clearLastLine();
                appendLine(cursor, lr, line, onStdErr);
            } else {
                // Found nothing, just emit the new part
                deferedText += newPart;
            }
            // Handled line continuation
            m_lastLine.clear();
        } else {
            const QString line = txt.mid(start, pos - start + 1);
            LinkResult lr = matchLine(line);
            if (!lr.href.isEmpty()) {
                cursor.insertText(deferedText, format(onStdErr ? StdErrFormat : StdOutFormat));
                deferedText.clear();
                appendLine(cursor, lr, line, onStdErr);
            } else {
                deferedText += line;
            }
        }
        start = pos + 1;
        pos = txt.indexOf(QLatin1Char('\n'), start);
    }

    // Handle left over stuff
    if (start < txt.length()) {
        if (!m_lastLine.isEmpty()) {
            // Line continuation
            const QString newPart = txt.mid(start);
            m_lastLine.append(newPart);
            LinkResult lr = matchLine(m_lastLine);
            if (!lr.href.isEmpty()) {
                // Found something && line continuation
                cursor.insertText(deferedText, format(onStdErr ? StdErrFormat : StdOutFormat));
                deferedText.clear();
                clearLastLine();
                appendLine(cursor, lr, m_lastLine, onStdErr);
            } else {
                // Found nothing, just emit the new part
                deferedText += newPart;
            }
        } else {
            m_lastLine = txt.mid(start);
            LinkResult lr = matchLine(m_lastLine);
            if (!lr.href.isEmpty()) {
                cursor.insertText(deferedText, format(onStdErr ? StdErrFormat : StdOutFormat));
                deferedText.clear();
                appendLine(cursor, lr, m_lastLine, onStdErr);
            } else {
                deferedText += m_lastLine;
            }
        }
    }
    cursor.insertText(deferedText, format(onStdErr ? StdErrFormat : StdOutFormat));
    // deferedText.clear();
    cursor.endEditBlock();
}

void QtOutputFormatter::appendLine(QTextCursor &cursor, LinkResult lr, const QString &line, bool onStdErr)
{
    const QTextCharFormat normalFormat = format(onStdErr ? StdErrFormat : StdOutFormat);
    cursor.insertText(line.left(lr.start), normalFormat);

    QTextCharFormat linkFormat = normalFormat;
    const QColor textColor = plainTextEdit()->palette().color(QPalette::Text);
    linkFormat.setForeground(mixColors(textColor, QColor(Qt::blue)));
    linkFormat.setUnderlineStyle(QTextCharFormat::SingleUnderline);
    linkFormat.setAnchor(true);
    linkFormat.setAnchorHref(lr.href);
    cursor.insertText(line.mid(lr.start, lr.end - lr.start), linkFormat);

    cursor.insertText(line.mid(lr.end), normalFormat);
}

void QtOutputFormatter::handleLink(const QString &href)
{
    if (!href.isEmpty()) {
        const QRegExp qmlLineColumnLink(QLatin1String("^(file:///.+)" // file url
                                                 ":(\\d+)"            // line
                                                 ":(\\d+)$"));        // column

        if (qmlLineColumnLink.indexIn(href) != -1) {
            const QString fileName = QUrl(qmlLineColumnLink.cap(1)).toLocalFile();
            const int line = qmlLineColumnLink.cap(2).toInt();
            const int column = qmlLineColumnLink.cap(3).toInt();
            TextEditor::BaseTextEditor::openEditorAt(fileName, line, column - 1);
            return;
        }

        const QRegExp qmlLineLink(QLatin1String("^(file:///.+)" // file url
                                                 ":(\\d+)$"));  // line

        if (qmlLineLink.indexIn(href) != -1) {
            const QString fileName = QUrl(qmlLineLink.cap(1)).toLocalFile();
            const int line = qmlLineLink.cap(2).toInt();
            TextEditor::BaseTextEditor::openEditorAt(fileName, line);
            return;
        }

        QString fileName;
        int line = -1;

        QRegExp qtErrorLink(QLatin1String("^(.*):(\\d+)$"));
        if (qtErrorLink.indexIn(href) != -1) {
            fileName = qtErrorLink.cap(1);
            line = qtErrorLink.cap(2).toInt();
        }

        QRegExp qtAssertLink(QLatin1String("^(.+), line (\\d+)$"));
        if (qtAssertLink.indexIn(href) != -1) {
            fileName = qtAssertLink.cap(1);
            line = qtAssertLink.cap(2).toInt();
        }

        QRegExp qtTestFailLink(QLatin1String("^(.*)\\((\\d+)\\)$"));
        if (qtTestFailLink.indexIn(href) != -1) {
            fileName = qtTestFailLink.cap(1);
            line = qtTestFailLink.cap(2).toInt();
        }

        if (!fileName.isEmpty()) {
            QFileInfo fi(fileName);
            if (fi.isRelative()) {
                // Yeah fileName is relative, no surprise
                ProjectExplorer::Project *pro = m_project.data();
                if (pro) {
                    QString baseName = fi.fileName();
                    foreach (const QString &file, pro->files(Project::AllFiles)) {
                        if (file.endsWith(baseName)) {
                            // pick the first one...
                            fileName = file;
                            break;
                        }
                    }
                }
            }
            TextEditor::BaseTextEditor::openEditorAt(fileName, line, 0);
            return;
        }
    }
}
<|endoftext|>


<commit_before>/*
	Flexisip, a flexible SIP proxy server with media capabilities.
	Copyright (C) 2010-2015  Belledonne Communications SARL, All rights reserved.

	This program is free software: you can redistribute it and/or modify
	it under the terms of the GNU Affero General Public License as
	published by the Free Software Foundation, either version 3 of the
	License, or (at your option) any later version.

	This program is distributed in the hope that it will be useful,
	but WITHOUT ANY WARRANTY; without even the implied warranty of
	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
	GNU Affero General Public License for more details.

	You should have received a copy of the GNU Affero General Public License
	along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/

#ifndef flexisip_rls_subscription_hh
#define flexisip_rls_subscription_hh

#include <chrono>
#include <unordered_map>

#include "rlmi+xml.hh"
#include "subscription.hh"

typedef struct _belle_sip_uri belle_sip_uri_t;
typedef struct belle_sip_server_transaction belle_sip_server_transaction_t;

namespace flexisip {

class ListSubscription;

/*
 * this class instanciate a resource as defined by rfc4662 (I.E a presentity from a resource-list)
 */
class PresentityResourceListener : public PresentityPresenceInformationListener {
  public:
	PresentityResourceListener(ListSubscription &aListSubscription, const belle_sip_uri_t *presentity, const std::string &name = "");
	PresentityResourceListener(const PresentityResourceListener &);
	~PresentityResourceListener();

	const belle_sip_uri_t *getPresentityUri() const;
	std::string getName() const {return mName;}
	/*
	 * This function is call every time Presentity information need to be notified to a UA
	 */
	void onInformationChanged(PresentityPresenceInformation &presenceInformation, bool extended);
	void onExpired(PresentityPresenceInformation &presenceInformation);
	const belle_sip_uri_t* getFrom();
	const belle_sip_uri_t* getTo();

  private:
	ListSubscription &mListSubscription;
	belle_sip_uri_t *mPresentity;
	std::string mName;
};

/*
 * This class manage a subscription for a list of presentities.
 */
class ListSubscription : public Subscription {
public:
	// ListSubscription(unsigned int expires,list<const belle_sip_uri_t *> resources,belle_sip_dialog_t*
	// aDialog,belle_sip_provider_t* aProv);
	ListSubscription(
		unsigned int expires,
		belle_sip_server_transaction_t *ist,
		belle_sip_provider_t *aProv,
		size_t maxPresenceInfoNotifiedAtATime,
		std::function<void(std::shared_ptr<ListSubscription>)> listAvailable
	);

	virtual ~ListSubscription();
	std::list<std::shared_ptr<PresentityPresenceInformationListener>> &getListeners();
	/* Notify taking state from all pending Presentity listener*/
	void notify(bool isFullState);

protected:
	// this function is call by each PresentityResourceListener to centralize notifications
	friend PresentityResourceListener;
	void onInformationChanged(PresentityPresenceInformation &presenceInformation, bool extended);
	void finishCreation(belle_sip_server_transaction_t *ist);

	std::list<std::shared_ptr<PresentityPresenceInformationListener>> mListeners;
	/*
	 * rfc 4662
	 * 5.2.  List Attributes
	 * ....
	 * The first mandatory <list> attribute is "uri", which contains the uri
	 * that corresponds to the list.  Typically, this is the URI to which
	 * the SUBSCRIBE request was sent.
	 **/
	const belle_sip_uri_t * = nullptr;;

private:
	ListSubscription(const ListSubscription &);
	// return true if a real notify can be sent.
	bool isTimeToNotify();
	void addInstanceToResource(Xsd::Rlmi::Resource &resource, std::list<belle_sip_body_handler_t *> &multipartList,
							   PresentityPresenceInformation &presentityInformation, bool extended);

	typedef std::unordered_map<const belle_sip_uri_t *, std::pair<std::shared_ptr<PresentityPresenceInformation>,bool>,
						  std::hash<const belle_sip_uri_t *>, bellesip::UriComparator> PendingStateType;
	PendingStateType mPendingStates; // map of Presentity to be notified by uri
	std::chrono::time_point<std::chrono::system_clock> mLastNotify;
	std::chrono::seconds mMinNotifyInterval;

	/*
	 * rfc 4662
	 * 5.2.  List Attributes
	 * ....
	 * The second mandatory <list> attribute is "version", which contains a
	 * number from 0 to 2^32-1.  This version number MUST be 0 for the first
	 * NOTIFY message sent within a subscription, and MUST increase by
	 * exactly one for each subsequent NOTIFY sent within a subscription.
	 */
	uint32_t mVersion;
	belle_sip_source_t *mTimer;
	size_t mMaxPresenceInfoNotifiedAtATime; //maximum number of presentity available in a sigle notify
	std::function<void(std::shared_ptr<ListSubscription>)> mListAvailable;
};

} // namespace flexisip

#endif
<commit_msg>fix silly mistake<commit_after>/*
	Flexisip, a flexible SIP proxy server with media capabilities.
	Copyright (C) 2010-2015  Belledonne Communications SARL, All rights reserved.

	This program is free software: you can redistribute it and/or modify
	it under the terms of the GNU Affero General Public License as
	published by the Free Software Foundation, either version 3 of the
	License, or (at your option) any later version.

	This program is distributed in the hope that it will be useful,
	but WITHOUT ANY WARRANTY; without even the implied warranty of
	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
	GNU Affero General Public License for more details.

	You should have received a copy of the GNU Affero General Public License
	along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/

#ifndef flexisip_rls_subscription_hh
#define flexisip_rls_subscription_hh

#include <chrono>
#include <unordered_map>

#include "rlmi+xml.hh"
#include "subscription.hh"

typedef struct _belle_sip_uri belle_sip_uri_t;
typedef struct belle_sip_server_transaction belle_sip_server_transaction_t;

namespace flexisip {

class ListSubscription;

/*
 * this class instanciate a resource as defined by rfc4662 (I.E a presentity from a resource-list)
 */
class PresentityResourceListener : public PresentityPresenceInformationListener {
  public:
	PresentityResourceListener(ListSubscription &aListSubscription, const belle_sip_uri_t *presentity, const std::string &name = "");
	PresentityResourceListener(const PresentityResourceListener &);
	~PresentityResourceListener();

	const belle_sip_uri_t *getPresentityUri() const;
	std::string getName() const {return mName;}
	/*
	 * This function is call every time Presentity information need to be notified to a UA
	 */
	void onInformationChanged(PresentityPresenceInformation &presenceInformation, bool extended);
	void onExpired(PresentityPresenceInformation &presenceInformation);
	const belle_sip_uri_t* getFrom();
	const belle_sip_uri_t* getTo();

  private:
	ListSubscription &mListSubscription;
	belle_sip_uri_t *mPresentity;
	std::string mName;
};

/*
 * This class manage a subscription for a list of presentities.
 */
class ListSubscription : public Subscription {
public:
	// ListSubscription(unsigned int expires,list<const belle_sip_uri_t *> resources,belle_sip_dialog_t*
	// aDialog,belle_sip_provider_t* aProv);
	ListSubscription(
		unsigned int expires,
		belle_sip_server_transaction_t *ist,
		belle_sip_provider_t *aProv,
		size_t maxPresenceInfoNotifiedAtATime,
		std::function<void(std::shared_ptr<ListSubscription>)> listAvailable
	);

	virtual ~ListSubscription();
	std::list<std::shared_ptr<PresentityPresenceInformationListener>> &getListeners();
	/* Notify taking state from all pending Presentity listener*/
	void notify(bool isFullState);

protected:
	// this function is call by each PresentityResourceListener to centralize notifications
	friend PresentityResourceListener;
	void onInformationChanged(PresentityPresenceInformation &presenceInformation, bool extended);
	void finishCreation(belle_sip_server_transaction_t *ist);

	std::list<std::shared_ptr<PresentityPresenceInformationListener>> mListeners;
	/*
	 * rfc 4662
	 * 5.2.  List Attributes
	 * ....
	 * The first mandatory <list> attribute is "uri", which contains the uri
	 * that corresponds to the list.  Typically, this is the URI to which
	 * the SUBSCRIBE request was sent.
	 **/
	const belle_sip_uri_t *mName = nullptr;

private:
	ListSubscription(const ListSubscription &);
	// return true if a real notify can be sent.
	bool isTimeToNotify();
	void addInstanceToResource(Xsd::Rlmi::Resource &resource, std::list<belle_sip_body_handler_t *> &multipartList,
							   PresentityPresenceInformation &presentityInformation, bool extended);

	typedef std::unordered_map<const belle_sip_uri_t *, std::pair<std::shared_ptr<PresentityPresenceInformation>,bool>,
						  std::hash<const belle_sip_uri_t *>, bellesip::UriComparator> PendingStateType;
	PendingStateType mPendingStates; // map of Presentity to be notified by uri
	std::chrono::time_point<std::chrono::system_clock> mLastNotify;
	std::chrono::seconds mMinNotifyInterval;

	/*
	 * rfc 4662
	 * 5.2.  List Attributes
	 * ....
	 * The second mandatory <list> attribute is "version", which contains a
	 * number from 0 to 2^32-1.  This version number MUST be 0 for the first
	 * NOTIFY message sent within a subscription, and MUST increase by
	 * exactly one for each subsequent NOTIFY sent within a subscription.
	 */
	uint32_t mVersion;
	belle_sip_source_t *mTimer;
	size_t mMaxPresenceInfoNotifiedAtATime; //maximum number of presentity available in a sigle notify
	std::function<void(std::shared_ptr<ListSubscription>)> mListAvailable;
};

} // namespace flexisip

#endif
<|endoftext|>


<commit_before><commit_msg>fixed 64bit build<commit_after><|endoftext|>


<commit_before>#include <iostream>
#include "ctvm.h"
#include "ctvm_util.h"
#include <boost/numeric/ublas/vector.hpp>
#include <boost/numeric/ublas/matrix.hpp>
#include <boost/numeric/ublas/io.hpp>
#include <Magick++.h>

int main(int argc, char **argv)
{
	/* Test CTVM.dylib Link */
	std::cout << std::endl;
	std::cout << "Testing libctvm Link." << std::endl;
	BoostDoubleMatrix DummySinogram(0, 0);
	BoostDoubleVector DummyAngles(0);
	// BoostDoubleMatrix DummyReconstruction = tval3_reconstruction(DummySinogram,DummyAngles);
	std::cout << "    " << "Passed." << std::endl;

	/* Test CTVM_util.dylib Link */
	std::cout << std::endl;
	std::cout << "Allocating tiny(3x3) random matrix..." << std::endl;
	BoostDoubleMatrix RandomMatrix = CreateRandomMatrix(3, 3);
	std::cout << "    " << RandomMatrix << std::endl;
	std::cout << "    " << "Passed." << std::endl;

	std::cout << "Rasterized Version..." << std::endl;
	std::cout << "    " << MatrixToVector(RandomMatrix) << std::endl;
	std::cout << "    " << "Passed." << std::endl;

	std::cout << "Back to Matrix..." << std::endl;
	std::cout << "    " << VectorToMatrix(MatrixToVector(RandomMatrix), 3, 3) << std::endl;
	std::cout << "    " << "Passed." << std::endl;

	std::cout << "Allocating large(1000x1000) random matrix..." << std::endl;
	BoostDoubleMatrix RandomMatrixLarge = CreateRandomMatrix(1000, 1000);
	std::cout << "    " << "Passed." << std::endl;

	std::cout << "Testing Normalization" << std::endl;
	BoostDoubleMatrix TestMatrix(3, 3);
	TestMatrix(0, 0) = 1; TestMatrix(0, 1) = 5; TestMatrix(0, 2) = 3;
	TestMatrix(1, 0) = 2; TestMatrix(1, 1) = 11; TestMatrix(1, 2) = 5;
	TestMatrix(2, 0) = 1; TestMatrix(2, 1) = 10; TestMatrix(2, 2) = 6;
	std::cout << "Original Matrix: " << TestMatrix << std::endl;
	std::cout << "Normalized: " << NormalizeMatrix(TestMatrix) << std::endl;

	/* Test ImageMagick */
	std::cout << std::endl;
	using namespace Magick;
	InitializeMagick("");

	std::cout << "Testing ImageMagick Link." << std::endl;
	Image someImage;
	someImage.read("C:\\data\\peppers.jpg");
	std::cout << "    " << "Passed." << std::endl;

	std::cout << "Creating Novel Image" << std::endl;
	Image anotherImage;
	anotherImage.size(Geometry(32, 32));         // Specify the dimensionality
	Pixels anotherImageView(anotherImage);      // Get a view of the image
	PixelPacket aPixel;
	aPixel.red = ColorGray::scaleDoubleToQuantum(0.5);
	aPixel.green = ColorGray::scaleDoubleToQuantum(0.5);
	aPixel.blue = ColorGray::scaleDoubleToQuantum(0.5);
	*(anotherImageView.get(16, 16, 1, 1)) = aPixel;
	anotherImage.type(GrayscaleType);           // Specify the color type
	anotherImageView.sync();
	anotherImage.write("C:\\data\\testoutimage.png");
	std::cout << "    " << "Passed." << std::endl;

	/* Test CTVM Image Load */
	std::cout << std::endl;
	std::cout << "Testing CTVM Image Load." << std::endl;
	BoostDoubleMatrix ImageMatrix = LoadImage("C:\\data\\peppers.jpg");
	std::cout << "Image Data:" << std::endl;
	std::cout << ImageMatrix(0, 0) << " " << ImageMatrix(0, 1) << " " << ImageMatrix(0, 3) << std::endl;
	std::cout << ImageMatrix(1, 0) << " " << ImageMatrix(1, 1) << " " << ImageMatrix(1, 3) << std::endl;
	std::cout << ImageMatrix(2, 0) << " " << ImageMatrix(2, 1) << " " << ImageMatrix(2, 3) << std::endl;
	std::cout << "    " << "Passed." << std::endl;

	std::cout << "Testing CTVM Image Write." << std::endl;
	WriteImage(ImageMatrix, "C:\\data\\test_peppers.jpg");
	std::cout << "    " << "Passed." << std::endl;

	/* Initialisation */
	BoostDoubleMatrix A(2, 4), W(4, 2), NU(4, 2);
	BoostDoubleVector U(4), U1(9), B(2), LAMBDA(2);

	A(0, 0) = 1; A(0, 1) = 0; A(0, 2) = 1; A(0, 3) = 0;
	A(1, 0) = 0; A(1, 1) = 1; A(1, 2) = 1; A(1, 3) = 1;

	W(0, 0) = -1; W(0, 1) = 1;
	W(1, 0) = 0; W(1, 1) = 1;
	W(2, 0) = -1; W(2, 1) = 0;
	W(3, 0) = 0; W(3, 1) = 1;

	NU(0, 0) = 2; NU(0, 1) = 1;
	NU(1, 0) = 1; NU(1, 1) = 0;
	NU(2, 0) = 0; NU(2, 1) = 2;
	NU(3, 0) = 1; NU(3, 1) = 3;

	U(0) = 1;
	U(1) = 2;
	U(2) = 0;
	U(3) = 1;

	U1(0) = 1;
	U1(1) = 2;
	U1(2) = 0;
	U1(3) = 1;
	U1(4) = 3;
	U1(5) = -2;
	U1(6) = 0;
	U1(7) = -1;
	U1(8) = 0;

	B(0) = 1;
	B(1) = 2;

	LAMBDA(0) = 2;
	LAMBDA(1) = 1;

	double beta = sqrt(2);
	double mu = 3;

	/* Test Gradient2DMatrix */
	std::cout << std::endl;
	std::cout << "Testing CTVM 2D Gradient for all i." << std::endl;
	BoostDoubleMatrix X = VectorToMatrix(U, 2, 2);
	BoostDoubleMatrix GradientMatrix = Gradient2DMatrix(U);
	BoostDoubleMatrix Di = Unit_Gradient2DMatrix(U1, 4);
	std::cout << "Original Matrix: " << X << std::endl;
	std::cout << "Gradients DiU (right gradient, down gradient): " << GradientMatrix << std::endl;
	std::cout << "Original Vector: " << U1 << std::endl;
	std::cout << " D(4) times U: " << prod(Di,U1) << std::endl;
	std::cout << "    " << "Passed." << std::endl;

	/*Test Lagrangian function*/
	std::cout << std::endl;
	double L = Lagrangian(A, U, B, W, NU, LAMBDA, beta, mu);

	std::cout << "Lagrangian: " << L << std::endl; // expected result L = 8.6213
	std::cout << "    " << "Passed." << std::endl;

	/*Test Shrinke function*/
	std::cout << std::endl;
	int ii = 1;
	BoostDoubleVector DiUk = Gradient2D(U, ii);
	BoostDoubleVector NUi (2);
	for (int jj = 0; jj < 2; ++jj) { NUi(jj) = NU(ii, jj); }
	BoostDoubleVector SHRIKE = Shrike(DiUk, NUi, beta);

	std::cout << "W(i,l+1): " << SHRIKE << std::endl; // expected result SHRIKE = ( -0.2988585, -0.42265)
	std::cout << "    " << "Passed." << std::endl;

return 0;
}<commit_msg>Expected Result for Direction<commit_after>#include <iostream>
#include "ctvm.h"
#include "ctvm_util.h"
#include <boost/numeric/ublas/vector.hpp>
#include <boost/numeric/ublas/matrix.hpp>
#include <boost/numeric/ublas/io.hpp>
#include <Magick++.h>

int main(int argc, char **argv)
{
	/* Test CTVM.dylib Link */
	std::cout << std::endl;
	std::cout << "Testing libctvm Link." << std::endl;
	BoostDoubleMatrix DummySinogram(0, 0);
	BoostDoubleVector DummyAngles(0);
	// BoostDoubleMatrix DummyReconstruction = tval3_reconstruction(DummySinogram,DummyAngles);
	std::cout << "    " << "Passed." << std::endl;

	/* Test CTVM_util.dylib Link */
	std::cout << std::endl;
	std::cout << "Allocating tiny(3x3) random matrix..." << std::endl;
	BoostDoubleMatrix RandomMatrix = CreateRandomMatrix(3, 3);
	std::cout << "    " << RandomMatrix << std::endl;
	std::cout << "    " << "Passed." << std::endl;

	std::cout << "Rasterized Version..." << std::endl;
	std::cout << "    " << MatrixToVector(RandomMatrix) << std::endl;
	std::cout << "    " << "Passed." << std::endl;

	std::cout << "Back to Matrix..." << std::endl;
	std::cout << "    " << VectorToMatrix(MatrixToVector(RandomMatrix), 3, 3) << std::endl;
	std::cout << "    " << "Passed." << std::endl;

	std::cout << "Allocating large(1000x1000) random matrix..." << std::endl;
	BoostDoubleMatrix RandomMatrixLarge = CreateRandomMatrix(1000, 1000);
	std::cout << "    " << "Passed." << std::endl;

	std::cout << "Testing Normalization" << std::endl;
	BoostDoubleMatrix TestMatrix(3, 3);
	TestMatrix(0, 0) = 1; TestMatrix(0, 1) = 5; TestMatrix(0, 2) = 3;
	TestMatrix(1, 0) = 2; TestMatrix(1, 1) = 11; TestMatrix(1, 2) = 5;
	TestMatrix(2, 0) = 1; TestMatrix(2, 1) = 10; TestMatrix(2, 2) = 6;
	std::cout << "Original Matrix: " << TestMatrix << std::endl;
	std::cout << "Normalized: " << NormalizeMatrix(TestMatrix) << std::endl;

	/* Test ImageMagick */
	std::cout << std::endl;
	using namespace Magick;
	InitializeMagick("");

	std::cout << "Testing ImageMagick Link." << std::endl;
	Image someImage;
	someImage.read("C:\\data\\peppers.jpg");
	std::cout << "    " << "Passed." << std::endl;

	std::cout << "Creating Novel Image" << std::endl;
	Image anotherImage;
	anotherImage.size(Geometry(32, 32));         // Specify the dimensionality
	Pixels anotherImageView(anotherImage);      // Get a view of the image
	PixelPacket aPixel;
	aPixel.red = ColorGray::scaleDoubleToQuantum(0.5);
	aPixel.green = ColorGray::scaleDoubleToQuantum(0.5);
	aPixel.blue = ColorGray::scaleDoubleToQuantum(0.5);
	*(anotherImageView.get(16, 16, 1, 1)) = aPixel;
	anotherImage.type(GrayscaleType);           // Specify the color type
	anotherImageView.sync();
	anotherImage.write("C:\\data\\testoutimage.png");
	std::cout << "    " << "Passed." << std::endl;

	/* Test CTVM Image Load */
	std::cout << std::endl;
	std::cout << "Testing CTVM Image Load." << std::endl;
	BoostDoubleMatrix ImageMatrix = LoadImage("C:\\data\\peppers.jpg");
	std::cout << "Image Data:" << std::endl;
	std::cout << ImageMatrix(0, 0) << " " << ImageMatrix(0, 1) << " " << ImageMatrix(0, 3) << std::endl;
	std::cout << ImageMatrix(1, 0) << " " << ImageMatrix(1, 1) << " " << ImageMatrix(1, 3) << std::endl;
	std::cout << ImageMatrix(2, 0) << " " << ImageMatrix(2, 1) << " " << ImageMatrix(2, 3) << std::endl;
	std::cout << "    " << "Passed." << std::endl;

	std::cout << "Testing CTVM Image Write." << std::endl;
	WriteImage(ImageMatrix, "C:\\data\\test_peppers.jpg");
	std::cout << "    " << "Passed." << std::endl;

	/* Initialisation */
	BoostDoubleMatrix A(2, 4), W(4, 2), NU(4, 2);
	BoostDoubleVector U(4), U1(9), B(2), LAMBDA(2);

	A(0, 0) = 1; A(0, 1) = 0; A(0, 2) = 1; A(0, 3) = 0;
	A(1, 0) = 0; A(1, 1) = 1; A(1, 2) = 1; A(1, 3) = 1;

	W(0, 0) = -1; W(0, 1) = 1;
	W(1, 0) = 0; W(1, 1) = 1;
	W(2, 0) = -1; W(2, 1) = 0;
	W(3, 0) = 0; W(3, 1) = 1;

	NU(0, 0) = 2; NU(0, 1) = 1;
	NU(1, 0) = 1; NU(1, 1) = 0;
	NU(2, 0) = 0; NU(2, 1) = 2;
	NU(3, 0) = 1; NU(3, 1) = 3;

	U(0) = 1;
	U(1) = 2;
	U(2) = 0;
	U(3) = 1;

	U1(0) = 1;
	U1(1) = 2;
	U1(2) = 0;
	U1(3) = 1;
	U1(4) = 3;
	U1(5) = -2;
	U1(6) = 0;
	U1(7) = -1;
	U1(8) = 0;

	B(0) = 1;
	B(1) = 2;

	LAMBDA(0) = 2;
	LAMBDA(1) = 1;

	double beta = sqrt(2);
	double mu = 3;

	/* Test Gradient2DMatrix */
	std::cout << std::endl;
	std::cout << "Testing CTVM 2D Gradient for all i." << std::endl;
	BoostDoubleMatrix X = VectorToMatrix(U, 2, 2);
	BoostDoubleMatrix GradientMatrix = Gradient2DMatrix(U);
	BoostDoubleMatrix Di = Unit_Gradient2DMatrix(U1, 4);
	std::cout << "Original Matrix: " << X << std::endl;
	std::cout << "Gradients DiU (right gradient, down gradient): " << GradientMatrix << std::endl;
	std::cout << "Original Vector: " << U1 << std::endl;
	std::cout << " D(4) times U: " << prod(Di,U1) << std::endl;
	std::cout << "    " << "Passed." << std::endl;

	/*Test Lagrangian function*/
	std::cout << std::endl;
	double L = Lagrangian(A, U, B, W, NU, LAMBDA, beta, mu);

	std::cout << "Lagrangian: " << L << std::endl; // expected result L = 8.6213
	std::cout << "    " << "Passed." << std::endl;

	/* Test One-step Direction */
	// U = [1 2 3 4];
	// A = [1 1 1 1; 2 2 2 2; 3 3 3 3];
	// b = [3 3 3];
	// lambda = [0.5 0.5 0.5];
	// mu = 0.5;
	// beta = 0.25;
	// Nu = [0.25 0.25; 0.25 0.25; 0.25 0.25; 0.25 0.25];
	// W = [-1 -1; -1 -1; -1 -1; -1 -1];
	// Expected result: d_k = [58.7500   58.2500   57.7500   57.2500]

	/*Test Shrinke function*/
	std::cout << std::endl;
	int ii = 1;
	BoostDoubleVector DiUk = Gradient2D(U, ii);
	BoostDoubleVector NUi (2);
	for (int jj = 0; jj < 2; ++jj) { NUi(jj) = NU(ii, jj); }
	BoostDoubleVector SHRIKE = Shrike(DiUk, NUi, beta);

	std::cout << "W(i,l+1): " << SHRIKE << std::endl; // expected result SHRIKE = ( -0.2988585, -0.42265)
	std::cout << "    " << "Passed." << std::endl;

return 0;
}<|endoftext|>


<commit_before><commit_msg>always do a 200fps cap so we don't get very small time steps. This is just a temporary holdover until the entire sim system can be reviewed.<commit_after><|endoftext|>


<commit_before><commit_msg>change auto join team names to be in english, not engrish.<commit_after><|endoftext|>


<commit_before><commit_msg>src/runtime: prepare for client boost.program_options<commit_after><|endoftext|>


<commit_before>#include <iostream>

#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/wait.h>
#include <fcntl.h>
#include <fstream>
#include <iostream>
#include <signal.h>
#include <chrono>

#include <sdk/IPcmVisualizer.h>
#include <sdk/IPlugin.h>

#include "Utility.h"

static const char* PCM_PIPE = "/tmp/musikcube_pcm.pipe";
static const long long PID_CHECK_INTERVAL_MILLIS = 2000;

using namespace std::chrono;

static int64 now() {
    return duration_cast<milliseconds>(
        system_clock::now().time_since_epoch()).count();
}

class Visualizer : public musik::core::audio::IPcmVisualizer {
    private:
        int pipeFd;
        pid_t pid;
        long long lastPidCheck;

    public:
        Visualizer() {
            mkfifo(PCM_PIPE, 0666);
            pipeFd = 0;
            pid = 0;
            lastPidCheck = now();
        }

        virtual ~Visualizer() {
            close(pipeFd);
            unlink(PCM_PIPE);
        }

        virtual const char* Name() {
            return "projectM IPcmVisualizer";
        };

        virtual const char* Version() {
            return "0.1";
        };

        virtual const char* Author() {
            return "clangen";
        };

        virtual void Destroy() {
            this->Hide();
            delete this;
        }

        virtual void Write(musik::core::audio::IBuffer* buffer) {
            if (pid) {
                if (pipeFd <= 0) {
                    pipeFd = open(PCM_PIPE, O_WRONLY | O_NONBLOCK);
                }

                if (pipeFd > 0) {
                    if (write(pipeFd, (void *) buffer->BufferPointer(), buffer->Bytes()) < 0) {
                        close(pipeFd);
                        pipeFd = 0;
                    }
                }
            }
        }

        virtual void Show() {
            if (!Visible()) {
                pid_t pid;
                if ((pid = fork()) == 0) {
                    const std::string command =
                        util::getModuleDirectory(NULL) +
                        "/plugins/projectM_musikcube";

                    execl(command.c_str(), command.c_str(), "", NULL);
                    exit(-1);
                }
                else {
                    this->pid = pid;
                }
            }
        }

        virtual void Hide() {
            if (Visible()) {
                if (this->pid > 0) {
                    kill((pid_t) pid, SIGKILL);
                    int status;
                    waitpid(pid, &status, 0);
                    this->pid = 0;
                }
            }
        }

        virtual bool Visible() {
            long long t = now();
            if (pid != 0 && t - lastPidCheck > PID_CHECK_INTERVAL_MILLIS) {
                int status;
                if (waitpid(pid, &status, WNOHANG) != 0) {
                    pid = 0;
                }
                lastPidCheck = t;
            }

            return this->pid != 0;
        }
};

extern "C" musik::core::IPlugin* GetPlugin() {
    return new Visualizer();
}

extern "C" musik::core::audio::IPcmVisualizer* GetPcmVisualizer() {
    return new Visualizer();
}<commit_msg>Tweaked the visualizer plugin name.<commit_after>#include <iostream>

#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/wait.h>
#include <fcntl.h>
#include <fstream>
#include <iostream>
#include <signal.h>
#include <chrono>

#include <sdk/IPcmVisualizer.h>
#include <sdk/IPlugin.h>

#include "Utility.h"

static const char* PCM_PIPE = "/tmp/musikcube_pcm.pipe";
static const long long PID_CHECK_INTERVAL_MILLIS = 2000;

using namespace std::chrono;

static int64 now() {
    return duration_cast<milliseconds>(
        system_clock::now().time_since_epoch()).count();
}

class Visualizer : public musik::core::audio::IPcmVisualizer {
    private:
        int pipeFd;
        pid_t pid;
        long long lastPidCheck;

    public:
        Visualizer() {
            mkfifo(PCM_PIPE, 0666);
            pipeFd = 0;
            pid = 0;
            lastPidCheck = now();
        }

        virtual ~Visualizer() {
            close(pipeFd);
            unlink(PCM_PIPE);
        }

        virtual const char* Name() {
            return "projectM";
        };

        virtual const char* Version() {
            return "0.1";
        };

        virtual const char* Author() {
            return "clangen";
        };

        virtual void Destroy() {
            this->Hide();
            delete this;
        }

        virtual void Write(musik::core::audio::IBuffer* buffer) {
            if (pid) {
                if (pipeFd <= 0) {
                    pipeFd = open(PCM_PIPE, O_WRONLY | O_NONBLOCK);
                }

                if (pipeFd > 0) {
                    if (write(pipeFd, (void *) buffer->BufferPointer(), buffer->Bytes()) < 0) {
                        close(pipeFd);
                        pipeFd = 0;
                    }
                }
            }
        }

        virtual void Show() {
            if (!Visible()) {
                pid_t pid;
                if ((pid = fork()) == 0) {
                    const std::string command =
                        util::getModuleDirectory(NULL) +
                        "/plugins/projectM_musikcube";

                    execl(command.c_str(), command.c_str(), "", NULL);
                    exit(-1);
                }
                else {
                    this->pid = pid;
                }
            }
        }

        virtual void Hide() {
            if (Visible()) {
                if (this->pid > 0) {
                    kill((pid_t) pid, SIGKILL);
                    int status;
                    waitpid(pid, &status, 0);
                    this->pid = 0;
                }
            }
        }

        virtual bool Visible() {
            long long t = now();
            if (pid != 0 && t - lastPidCheck > PID_CHECK_INTERVAL_MILLIS) {
                int status;
                if (waitpid(pid, &status, WNOHANG) != 0) {
                    pid = 0;
                }
                lastPidCheck = t;
            }

            return this->pid != 0;
        }
};

extern "C" musik::core::IPlugin* GetPlugin() {
    return new Visualizer();
}

extern "C" musik::core::audio::IPcmVisualizer* GetPcmVisualizer() {
    return new Visualizer();
}<|endoftext|>


<commit_before>// =============================================================================
// PROJECT CHRONO - http://projectchrono.org
//
// Copyright (c) 2014 projectchrono.org
// All rights reserved.
//
// Use of this source code is governed by a BSD-style license that can be found
// in the LICENSE file at the top level of the distribution and at
// http://projectchrono.org/license-chrono.txt.
//
// =============================================================================
// Authors: Radu Serban
// =============================================================================
//
// Test for TNB frame on Bezier curves
//
// =============================================================================

#include <cmath>
#include <cstdio>
#include <fstream>
#include <vector>

#include "chrono_vehicle/utils/ChVehiclePath.h"

#include "chrono_thirdparty/filesystem/path.h"

using namespace chrono;
using namespace vehicle;

const std::string out_dir = "../TEST_BEZIER";

void plot(std::shared_ptr<ChBezierCurve> path, int n, const char* name) {
    std::ofstream outp(out_dir + "/" + name + "_P.dat", std::ios::out);
    std::ofstream outf(out_dir + "/" + name + "_F.dat", std::ios::out);

    // Generate points on the path
    std::vector<double> x(n);
    std::vector<double> y(n);
    std::vector<double> z(n);
    for (int i = 0; i < n; i++) {
        ChVector<> pos = path->eval(0.01 * i);
        x[i] = pos.x();
        y[i] = pos.y();
        z[i] = pos.z();
        outp << x[i] << " " << y[i] << " " << z[i] << std::endl;
    }

    // Create a tracker
    ChBezierCurveTracker tracker(path);
    tracker.reset(ChVector<>(x[5], y[5], z[5]));

    // Find TNB frame and curvature at points on path
    ChFrame<> tnb;
    double curvature;
    for (int i = 2; i < n; i++) {
        ChVector<> loc(x[i], y[i], z[i]);
        tracker.calcClosestPoint(loc, tnb, curvature);
        auto r = tnb.GetPos();
        auto T = tnb.GetA().Get_A_Xaxis();
        auto N = tnb.GetA().Get_A_Yaxis();
        auto B = tnb.GetA().Get_A_Zaxis();
        outf << r.x() << " " << r.y() << " " << r.z() << " ";
        outf << T.x() << " " << T.y() << " " << T.z() << " ";
        outf << N.x() << " " << N.y() << " " << N.z() << " ";
        outf << B.x() << " " << B.y() << " " << B.z() << " ";
        outf << curvature << std::endl;
    }
}

int main(int argc, char* argv[]) {
    // Create (if needed) output directory
    if (!filesystem::create_directory(filesystem::path(out_dir))) {
        std::cout << "Error creating directory " << out_dir << std::endl;
        return 1;
    }

    // Circle path (left)
    auto path1 = CirclePath(ChVector<>(1, 2, 0), 3.0, 5.0, true, 1);
    plot(path1, 100, "left_circle");

    // Circle path (right)
    auto path2 = CirclePath(ChVector<>(1, 2, 0), 3.0, 5.0, false, 1);
    plot(path2, 100, "right_circle");

    // NATO double lane change path (left)
    auto path3 = DoubleLaneChangePath(ChVector<>(-100, 0, 0.1), 28.93, 3.6105, 25.0, 100.0, true);
    plot(path3, 600, "left_DLC");

    // double lane change path (right)
    auto path4 = DoubleLaneChangePath(ChVector<>(-10, 0, 0.1), 5, 3, 5.0, 10.0, false);
    plot(path4, 600, "right_DLC");

    return 0;
}
<commit_msg>Include required header<commit_after>// =============================================================================
// PROJECT CHRONO - http://projectchrono.org
//
// Copyright (c) 2014 projectchrono.org
// All rights reserved.
//
// Use of this source code is governed by a BSD-style license that can be found
// in the LICENSE file at the top level of the distribution and at
// http://projectchrono.org/license-chrono.txt.
//
// =============================================================================
// Authors: Radu Serban
// =============================================================================
//
// Test for TNB frame on Bezier curves
//
// =============================================================================

#include <cmath>
#include <cstdio>
#include <fstream>
#include <vector>

#include "chrono/core/ChMatrixDynamic.h"
#include "chrono_vehicle/utils/ChVehiclePath.h"
#include "chrono_thirdparty/filesystem/path.h"

using namespace chrono;
using namespace vehicle;

const std::string out_dir = "../TEST_BEZIER";

void plot(std::shared_ptr<ChBezierCurve> path, int n, const char* name) {
    std::ofstream outp(out_dir + "/" + name + "_P.dat", std::ios::out);
    std::ofstream outf(out_dir + "/" + name + "_F.dat", std::ios::out);

    // Generate points on the path
    std::vector<double> x(n);
    std::vector<double> y(n);
    std::vector<double> z(n);
    for (int i = 0; i < n; i++) {
        ChVector<> pos = path->eval(0.01 * i);
        x[i] = pos.x();
        y[i] = pos.y();
        z[i] = pos.z();
        outp << x[i] << " " << y[i] << " " << z[i] << std::endl;
    }

    // Create a tracker
    ChBezierCurveTracker tracker(path);
    tracker.reset(ChVector<>(x[5], y[5], z[5]));

    // Find TNB frame and curvature at points on path
    ChFrame<> tnb;
    double curvature;
    for (int i = 2; i < n; i++) {
        ChVector<> loc(x[i], y[i], z[i]);
        tracker.calcClosestPoint(loc, tnb, curvature);
        auto r = tnb.GetPos();
        auto T = tnb.GetA().Get_A_Xaxis();
        auto N = tnb.GetA().Get_A_Yaxis();
        auto B = tnb.GetA().Get_A_Zaxis();
        outf << r.x() << " " << r.y() << " " << r.z() << " ";
        outf << T.x() << " " << T.y() << " " << T.z() << " ";
        outf << N.x() << " " << N.y() << " " << N.z() << " ";
        outf << B.x() << " " << B.y() << " " << B.z() << " ";
        outf << curvature << std::endl;
    }
}

int main(int argc, char* argv[]) {
    // Create (if needed) output directory
    if (!filesystem::create_directory(filesystem::path(out_dir))) {
        std::cout << "Error creating directory " << out_dir << std::endl;
        return 1;
    }

    // Circle path (left)
    auto path1 = CirclePath(ChVector<>(1, 2, 0), 3.0, 5.0, true, 1);
    plot(path1, 100, "left_circle");

    // Circle path (right)
    auto path2 = CirclePath(ChVector<>(1, 2, 0), 3.0, 5.0, false, 1);
    plot(path2, 100, "right_circle");

    // NATO double lane change path (left)
    auto path3 = DoubleLaneChangePath(ChVector<>(-100, 0, 0.1), 28.93, 3.6105, 25.0, 100.0, true);
    plot(path3, 600, "left_DLC");

    // double lane change path (right)
    auto path4 = DoubleLaneChangePath(ChVector<>(-10, 0, 0.1), 5, 3, 5.0, 10.0, false);
    plot(path4, 600, "right_DLC");

    return 0;
}
<|endoftext|>


<commit_before>#ifndef ATL_HELPERS_HH
#define ATL_HELPERS_HH

#include <algorithm>

#include "./gc.hpp"
#include "./type.hpp"
#include "./conversion.hpp"

namespace atl
{
	typedef Range<Any*> AnyRange;

	namespace byte_code
	{
		typedef typename vm_stack::value_type value_type;
		template<class T>
		vm_stack::value_type to_bytes(T input)
		{ return reinterpret_cast<vm_stack::value_type>(input); }

		// TODO: use the `std::is_integral` and static cast for all integral (and floating?) types.
		value_type to_bytes(long input)
		{ return static_cast<value_type>(input); }

		value_type to_bytes(bool input)
		{ return static_cast<value_type>(input); }

		value_type to_bytes(void* input)
		{ return reinterpret_cast<value_type>(input); }

		value_type to_bytes(Pointer input)
		{ return reinterpret_cast<value_type>(input.value); }

		template<class R>
		struct PntrCaster
		{
			typedef PntrCaster<R> type;
			static R a(value_type input)
			{ return reinterpret_cast<R>(input); }
		};

		template<class I>
		struct StaticCaster
		{
			typedef StaticCaster<I> type;
			static I a(value_type input)
			{ return static_cast<I>(input); }
		};

		template<class T>
		struct Caster
			: public std::conditional<std::is_integral<T>::value,
			                          StaticCaster<T>,
			                          PntrCaster<T>
			                          >::type
		{};

		template<class R>
		R from_bytes(value_type input) { return Caster<R>::a(input); }
	}

	/// Work-alike wrapper for Any so which is safe to pass around by
	/// value (ie wrap AstData with an Ast).
	struct PassByValue
	{
		tag_t _tag;
		void* value;

		PassByValue& _store_value(Any& input)
		{
			if(is<AstData>(input))
				{
					_tag = tag<Ast>::value;
					value = &input;
				}
			else
				{
					_tag = input._tag;
					value = input.value;
				}
			return *this;
		}

		PassByValue(tag_t tt, void* vv)
			: _tag(tt), value(vv)
		{}

		PassByValue(Any& input)
		{ _store_value(input); }

		PassByValue(Ast& input)
		{
			_tag = tag<Ast>::value;
			value = input.value;
		}

		PassByValue(AstData& input)
		{
			_tag = tag<Ast>::value;
			value = &input;
		}

		PassByValue() = default;

		PassByValue& operator=(Any& input)
		{
			_store_value(input);
			return *this;
		}

		Any& as_Any() { return *reinterpret_cast<Any*>(this); }
		Any as_Any() const { return *reinterpret_cast<Any const*>(this); }
	};

	PassByValue pass_value(Any&& input)
	{ return PassByValue(input); }

	PassByValue pass_value(Any& input)
	{ return PassByValue(input); }

	template<class T>
	PassByValue pass_value(T&& input)
	{
		typedef typename std::remove_reference<T>::type Type;
		static_assert(!((tag<Type>::value == tag<AstData>::value)
		                || (tag<Type>::value == tag<Any>::value)),
		              "Use the overloads for AstData and Any");
		return PassByValue(tag<Type>::value, wrap(input).value);
	}

	template<class T>
	PassByValue pass_value()
	{ return PassByValue(tag<T>::value, nullptr); }

	namespace unwrap_PBV
	{
		template<class T>
		struct Unwrap
		{
			static_assert(!std::is_same<AstData, T>::value,
			              "PassByValue should not directly contain an AstData.");

			static inline constexpr T& a(atl::PassByValue& aa)
			{ return explicit_unwrap<T>(aa.as_Any()); }

			static inline constexpr T const& a(atl::PassByValue const& aa)
			{ return explicit_unwrap<T>(aa.as_Any()); }
		};
	}

	template<class T>
	T& unwrap(PassByValue& input)
	{ return unwrap_PBV::Unwrap<T>::a(input); }

	template<class T>
	T unwrap(PassByValue const& input)
	{ return unwrap_PBV::Unwrap<T>::a(input); }

	template<class T>
	bool is(PassByValue const& value)
	{ return is<T>(reinterpret_cast<Any const&>(value)); }

	namespace make_ast
	{
		// Maintains one 'dynamic_seq` for use with the make_ast functions
		using ast_hof::AstAllocator;

		AstAllocator ast_alloc(AllocatorBase& aa)
		{ return AstAllocator(aa); }

		typedef std::function<void (AstAllocator)> ast_composer;

		ast_composer lift(Any tt)
		{
			return [tt](AstAllocator space)
				{ space.push_back(tt); };
		}

		template<class T, class ... Args>
		ast_composer lift(Args ... args)
		{
			return [args ...](AstAllocator space)
				{ space.push_back(wrap<T>(args ...)); };
		}

		ast_composer sym(std::string const& name)
		{
			return [name](AstAllocator heap)
				{ heap.push_back(wrap(heap.symbol(name))); };
		}

		struct _Run
		{
			AstAllocator space;
			_Run(AstAllocator ss) : space(ss) {}

			template<class Fn>
			void operator()(Fn &fn) { fn(space); }
		};

		template<class ... Args>
		std::function<Ast (AstAllocator)>
		make(Args ... args)
		{
			auto tup = make_tuple(args...);
			return [tup](AstAllocator space) -> Ast
				{
					ast_hof::NestAst nested(space);

					_Run do_apply(space);
					foreach_tuple(do_apply, tup);

					return *nested.ast;
				};
		}

		template<class Fn>
		std::function<Ast (AstAllocator)>
		map(Fn&& fn, Ast const& input)
		{
			return [fn, input](AstAllocator store) -> Ast
				{ return ast_hof::map(fn, input, store); };
		}
	}

	namespace pattern_matcher
	{
		struct Match
		{
			bool is_match;
			typedef std::vector<Any*> Matches;
			Matches matches;

			Any& operator[](off_t pos) { return *matches[pos]; }
			operator bool() { return is_match; }

			Match(bool is_match_, Matches&& matches_)
				: is_match(is_match_), matches(matches_)
			{}

			Match(bool is_match_)
				: is_match(is_match_)
			{}

			Match(Match && other)
				: is_match(other.is_match), matches(std::move(other.matches))
			{}
		};

		typedef std::function<Match (Any&)> Matcher;

		template<class T>
		Matcher capture()
		{
			return [](Any& expr) -> Match
				{
					if(is<T>(expr))
						{ return Match(true, Match::Matches({&expr})); }
					else
						{ return Match(false); }
				};
		}

		Matcher capture_whatever()
		{
			return [](Any& expr) -> Match
				{
					return Match(true, Match::Matches({&expr}));
				};
		}

		template<class T>
		Matcher match_is()
		{
			return [](Any& expr) -> Match
				{ return Match(is<T>(expr)); };
		}

		Matcher whatever()
		{
			return [](Any& expr) -> Match
				{ return Match(true); };
		}

		template<class ... Args>
		Matcher match_ast(Args ... args)
		{
			auto tup = make_tuple(args...);
			return [tup](Any& expr) -> Match
				{
					AstData* ast;

					switch(expr._tag)
						{
						case tag<AstData>::value:
							ast = &explicit_unwrap<AstData>(expr);
							break;
						case tag<Ast>::value:
							ast = explicit_unwrap<Ast>(expr).value;
							break;
						default:
							return Match(false);
						}

					Match match(true);
					auto itr = ast->begin();

					auto accume = [&](Matcher const& fn) -> bool
						{
							if(itr == ast->end())
								{ return false; }

							auto inner_result = fn(*itr);
							if(inner_result.is_match)
								{
									++itr;
									match.matches.insert(match.matches.end(),
									                     inner_result.matches.begin(),
									                     inner_result.matches.end());
									return true;
								}
							else
								{ return false; }
						};

					match.is_match = and_tuple(accume, tup);
					if(itr != ast->end())
						{ return Match(false); }
					else
						{ return match; }
				};
		}
	}

	/* Pass through an ast or wrap an AstData */
	Ast unwrap_ast(Any& input)
	{
		if(is<AstData>(input))
			return Ast(&explicit_unwrap<AstData>(input));
		else
			return explicit_unwrap<Ast>(input);
	}

	struct AstSubscriter
	{
		PassByValue value;
		AstSubscriter(PassByValue const& in) : value(in) {}
		AstSubscriter() = delete;

		AstSubscriter operator[](off_t pos)
		{ return AstSubscriter(pass_value(unwrap<Ast>(value)[pos])); }
	};

	template<class T>
	AstSubscriter subscripter(T&& ast)
	{ return AstSubscriter(pass_value(ast)); }

	template<class T>
	AstSubscriter subscripter(PassByValue const& value)
	{ return AstSubscriter(value); }

	template<class T>
	struct Unwrapped
	{
		template<class Input, class Fn>
		static void a(Input&& in, Fn fn)
		{ return fn(unwrap<T>(in)); };
	};
}

#endif
<commit_msg>Add higher order functions for Ast<commit_after>#ifndef ATL_HELPERS_HH
#define ATL_HELPERS_HH

#include <algorithm>

#include "./gc.hpp"
#include "./type.hpp"
#include "./conversion.hpp"

namespace atl
{
	typedef Range<Any*> AnyRange;

	namespace byte_code
	{
		typedef typename vm_stack::value_type value_type;
		template<class T>
		vm_stack::value_type to_bytes(T input)
		{ return reinterpret_cast<vm_stack::value_type>(input); }

		// TODO: use the `std::is_integral` and static cast for all integral (and floating?) types.
		value_type to_bytes(long input)
		{ return static_cast<value_type>(input); }

		value_type to_bytes(bool input)
		{ return static_cast<value_type>(input); }

		value_type to_bytes(void* input)
		{ return reinterpret_cast<value_type>(input); }

		value_type to_bytes(Pointer input)
		{ return reinterpret_cast<value_type>(input.value); }

		template<class R>
		struct PntrCaster
		{
			typedef PntrCaster<R> type;
			static R a(value_type input)
			{ return reinterpret_cast<R>(input); }
		};

		template<class I>
		struct StaticCaster
		{
			typedef StaticCaster<I> type;
			static I a(value_type input)
			{ return static_cast<I>(input); }
		};

		template<class T>
		struct Caster
			: public std::conditional<std::is_integral<T>::value,
			                          StaticCaster<T>,
			                          PntrCaster<T>
			                          >::type
		{};

		template<class R>
		R from_bytes(value_type input) { return Caster<R>::a(input); }
	}

	/// Work-alike wrapper for Any so which is safe to pass around by
	/// value (ie wrap AstData with an Ast).
	struct PassByValue
	{
		tag_t _tag;
		void* value;

		PassByValue& _store_value(Any& input)
		{
			if(is<AstData>(input))
				{
					_tag = tag<Ast>::value;
					value = &input;
				}
			else
				{
					_tag = input._tag;
					value = input.value;
				}
			return *this;
		}

		PassByValue(tag_t tt, void* vv)
			: _tag(tt), value(vv)
		{}

		PassByValue(Any& input)
		{ _store_value(input); }

		PassByValue(Ast& input)
		{
			_tag = tag<Ast>::value;
			value = input.value;
		}

		PassByValue(AstData& input)
		{
			_tag = tag<Ast>::value;
			value = &input;
		}

		PassByValue() = default;

		PassByValue& operator=(Any& input)
		{
			_store_value(input);
			return *this;
		}

		Any& as_Any() { return *reinterpret_cast<Any*>(this); }
		Any as_Any() const { return *reinterpret_cast<Any const*>(this); }
	};

	PassByValue pass_value(Any&& input)
	{ return PassByValue(input); }

	PassByValue pass_value(Any& input)
	{ return PassByValue(input); }

	template<class T>
	PassByValue pass_value(T&& input)
	{
		typedef typename std::remove_reference<T>::type Type;
		static_assert(!((tag<Type>::value == tag<AstData>::value)
		                || (tag<Type>::value == tag<Any>::value)),
		              "Use the overloads for AstData and Any");
		return PassByValue(tag<Type>::value, wrap(input).value);
	}

	template<class T>
	PassByValue pass_value()
	{ return PassByValue(tag<T>::value, nullptr); }

	namespace unwrap_PBV
	{
		template<class T>
		struct Unwrap
		{
			static_assert(!std::is_same<AstData, T>::value,
			              "PassByValue should not directly contain an AstData.");

			static inline constexpr T& a(atl::PassByValue& aa)
			{ return explicit_unwrap<T>(aa.as_Any()); }

			static inline constexpr T const& a(atl::PassByValue const& aa)
			{ return explicit_unwrap<T>(aa.as_Any()); }
		};
	}

	template<class T>
	T& unwrap(PassByValue& input)
	{ return unwrap_PBV::Unwrap<T>::a(input); }

	template<class T>
	T unwrap(PassByValue const& input)
	{ return unwrap_PBV::Unwrap<T>::a(input); }

	template<class T>
	bool is(PassByValue const& value)
	{ return is<T>(reinterpret_cast<Any const&>(value)); }

	/* higher order functions for Asts */
	namespace ast_hof
	{
		struct AstAllocator
		{
			AllocatorBase &allocator;
			AstSubstrate &buffer;

			AstAllocator(AllocatorBase &aa)
				: allocator(aa), buffer(aa.sequence())
			{}

			Symbol* symbol(std::string const& name)
			{ return allocator.symbol(name); }

			AstAllocator& push_back(Any value)
			{
				buffer.push_back(value);
				return *this;
			}

			AstAllocator& push_back(PassByValue value)
			{
				buffer.push_back(value.as_Any());
				return *this;
			}

			MovableAstPointer nest_ast()
			{ return push_nested_ast(buffer); }

			size_t size()
			{ return buffer.size(); }
		};

		struct NestAst
		{
			AstAllocator& store;
			MovableAstPointer ast;

			NestAst(AstAllocator& store_)
				: store(store_), ast(store.nest_ast())
			{}

			~NestAst() { ast.end_ast(); }
		};

		/** Builds a new Ast in `store` by mapping `fn` over `ast`
		 * @tparam Fn: -> Any Any
		 * @param store: an AstAllocator
		 * @param fn: the Fn to apply
		 * @param ast: the ast to apply over
		 * @return: A MovableAstPointer which will be updated if store
		 *   is resized.
		 */
		template<class Fn>
		MovableAstPointer map(Fn&& fn, Ast const& input, AstAllocator store)
		{
			NestAst nest(store);
			for(auto& vv : input)
				{ nest.store.push_back(fn(vv)); }
			return nest.ast;
		}

		MovableAstPointer copy(Ast const& input, AstAllocator store)
		{
			NestAst nest(store);
			for(auto& vv : input)
				{ nest.store.push_back(vv); }
			return nest.ast;
		}
	}

	namespace make_ast
	{
		// Maintains one 'dynamic_seq` for use with the make_ast functions
		using ast_hof::AstAllocator;

		AstAllocator ast_alloc(AllocatorBase& aa)
		{ return AstAllocator(aa); }

		typedef std::function<void (AstAllocator)> ast_composer;

		ast_composer lift(Any tt)
		{
			return [tt](AstAllocator space)
				{ space.push_back(tt); };
		}

		template<class T, class ... Args>
		ast_composer lift(Args ... args)
		{
			return [args ...](AstAllocator space)
				{ space.push_back(wrap<T>(args ...)); };
		}

		ast_composer sym(std::string const& name)
		{
			return [name](AstAllocator heap)
				{ heap.push_back(wrap(heap.symbol(name))); };
		}

		struct _Run
		{
			AstAllocator space;
			_Run(AstAllocator ss) : space(ss) {}

			template<class Fn>
			void operator()(Fn &fn) { fn(space); }
		};

		template<class ... Args>
		std::function<Ast (AstAllocator)>
		make(Args ... args)
		{
			auto tup = make_tuple(args...);
			return [tup](AstAllocator space) -> Ast
				{
					ast_hof::NestAst nested(space);

					_Run do_apply(space);
					foreach_tuple(do_apply, tup);

					return *nested.ast;
				};
		}

		template<class Fn>
		std::function<Ast (AstAllocator)>
		map(Fn&& fn, Ast const& input)
		{
			return [fn, input](AstAllocator store) -> Ast
				{ return ast_hof::map(fn, input, store); };
		}
	}

	namespace pattern_matcher
	{
		struct Match
		{
			bool is_match;
			typedef std::vector<Any*> Matches;
			Matches matches;

			Any& operator[](off_t pos) { return *matches[pos]; }
			operator bool() { return is_match; }

			Match(bool is_match_, Matches&& matches_)
				: is_match(is_match_), matches(matches_)
			{}

			Match(bool is_match_)
				: is_match(is_match_)
			{}

			Match(Match && other)
				: is_match(other.is_match), matches(std::move(other.matches))
			{}
		};

		typedef std::function<Match (Any&)> Matcher;

		template<class T>
		Matcher capture()
		{
			return [](Any& expr) -> Match
				{
					if(is<T>(expr))
						{ return Match(true, Match::Matches({&expr})); }
					else
						{ return Match(false); }
				};
		}

		Matcher capture_whatever()
		{
			return [](Any& expr) -> Match
				{
					return Match(true, Match::Matches({&expr}));
				};
		}

		template<class T>
		Matcher match_is()
		{
			return [](Any& expr) -> Match
				{ return Match(is<T>(expr)); };
		}

		Matcher whatever()
		{
			return [](Any& expr) -> Match
				{ return Match(true); };
		}

		template<class ... Args>
		Matcher match_ast(Args ... args)
		{
			auto tup = make_tuple(args...);
			return [tup](Any& expr) -> Match
				{
					AstData* ast;

					switch(expr._tag)
						{
						case tag<AstData>::value:
							ast = &explicit_unwrap<AstData>(expr);
							break;
						case tag<Ast>::value:
							ast = explicit_unwrap<Ast>(expr).value;
							break;
						default:
							return Match(false);
						}

					Match match(true);
					auto itr = ast->begin();

					auto accume = [&](Matcher const& fn) -> bool
						{
							if(itr == ast->end())
								{ return false; }

							auto inner_result = fn(*itr);
							if(inner_result.is_match)
								{
									++itr;
									match.matches.insert(match.matches.end(),
									                     inner_result.matches.begin(),
									                     inner_result.matches.end());
									return true;
								}
							else
								{ return false; }
						};

					match.is_match = and_tuple(accume, tup);
					if(itr != ast->end())
						{ return Match(false); }
					else
						{ return match; }
				};
		}
	}

	/* Pass through an ast or wrap an AstData */
	Ast unwrap_ast(Any& input)
	{
		if(is<AstData>(input))
			return Ast(&explicit_unwrap<AstData>(input));
		else
			return explicit_unwrap<Ast>(input);
	}

	struct AstSubscriter
	{
		PassByValue value;
		AstSubscriter(PassByValue const& in) : value(in) {}
		AstSubscriter() = delete;

		AstSubscriter operator[](off_t pos)
		{ return AstSubscriter(pass_value(unwrap<Ast>(value)[pos])); }
	};

	template<class T>
	AstSubscriter subscripter(T&& ast)
	{ return AstSubscriter(pass_value(ast)); }

	template<class T>
	AstSubscriter subscripter(PassByValue const& value)
	{ return AstSubscriter(value); }

	template<class T>
	struct Unwrapped
	{
		template<class Input, class Fn>
		static void a(Input&& in, Fn fn)
		{ return fn(unwrap<T>(in)); };
	};
}

#endif
<|endoftext|>


<commit_before><commit_msg>make stored procedure work<commit_after><|endoftext|>


<commit_before>/*
Copyright (c) 2018 - present Advanced Micro Devices, Inc. All rights reserved.

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 <hip/hip_runtime.h>

#include "hip_internal.hpp"

hipError_t hipDeviceGet(hipDevice_t *device, int deviceId) {
  HIP_INIT_API(device, deviceId);

  if (device != nullptr) {
    *device = deviceId;
  } else {
    HIP_RETURN(hipErrorInvalidValue);
  }

  HIP_RETURN(hipSuccess);
};

hipError_t hipFuncSetCacheConfig (const void* func, hipFuncCache_t cacheConfig) {

  HIP_INIT_API(cacheConfig);

  // No way to set cache config yet.

  HIP_RETURN(hipSuccess);
}

hipError_t hipDeviceTotalMem (size_t *bytes, hipDevice_t device) {

  HIP_INIT_API(bytes, device);

  if (device < 0 || static_cast<size_t>(device) >= g_devices.size()) {
    HIP_RETURN(hipErrorInvalidDevice);
  }

  if (bytes == nullptr) {
    HIP_RETURN(hipErrorInvalidValue);
  }

  auto* deviceHandle = g_devices[device]->devices()[0];
  const auto& info = deviceHandle->info();

  *bytes = info.globalMemSize_;

  HIP_RETURN(hipSuccess);
}

hipError_t hipDeviceComputeCapability(int *major, int *minor, hipDevice_t device) {

  HIP_INIT_API(major, minor, device);

  if (device < 0 || static_cast<size_t>(device) >= g_devices.size()) {
    HIP_RETURN(hipErrorInvalidDevice);
  }

  if (major == nullptr || minor == nullptr) {
    HIP_RETURN(hipErrorInvalidValue);
  }

  auto* deviceHandle = g_devices[device]->devices()[0];
  const auto& info = deviceHandle->info();
  *major = info.gfxipVersion_ / 100;
  *minor = info.gfxipVersion_ % 100;

  HIP_RETURN(hipSuccess);
}

hipError_t hipDeviceGetCount(int* count) {
  HIP_INIT_API(count);

  HIP_RETURN(ihipDeviceGetCount(count));
}

hipError_t ihipDeviceGetCount(int* count) {
  if (count == nullptr) {
    return hipErrorInvalidValue;
  }

  // Get all available devices
  *count = g_devices.size();

  return hipSuccess;
}

hipError_t hipDeviceGetName(char *name, int len, hipDevice_t device) {

  HIP_INIT_API((void*)name, len, device);

  if (device < 0 || static_cast<size_t>(device) >= g_devices.size()) {
    HIP_RETURN(hipErrorInvalidDevice);
  }

  if (name == nullptr) {
    HIP_RETURN(hipErrorInvalidValue);
  }

  auto* deviceHandle = g_devices[device]->devices()[0];
  const auto& info = deviceHandle->info();

  len = ((cl_uint)len < ::strlen(info.boardName_)) ? len : 128;
  ::strncpy(name, info.boardName_, len);

  HIP_RETURN(hipSuccess);
}

hipError_t hipGetDeviceProperties ( hipDeviceProp_t* props, hipDevice_t device ) {
  HIP_INIT_API(props, device);

  if (props == nullptr) {
    HIP_RETURN(hipErrorInvalidValue);
  }

  if (unsigned(device) >= g_devices.size()) {
    HIP_RETURN(hipErrorInvalidDevice);
  }
  auto* deviceHandle = g_devices[device]->devices()[0];

  hipDeviceProp_t deviceProps = {0};

  const auto& info = deviceHandle->info();
  ::strncpy(deviceProps.name, info.boardName_, 128);
  deviceProps.totalGlobalMem = info.globalMemSize_;
  deviceProps.sharedMemPerBlock = info.localMemSizePerCU_;
  deviceProps.regsPerBlock = info.availableSGPRs_;
  deviceProps.warpSize = info.wavefrontWidth_;
  deviceProps.maxThreadsPerBlock = info.maxWorkGroupSize_;
  deviceProps.maxThreadsDim[0] = info.maxWorkItemSizes_[0];
  deviceProps.maxThreadsDim[1] = info.maxWorkItemSizes_[1];
  deviceProps.maxThreadsDim[2] = info.maxWorkItemSizes_[2];
  deviceProps.maxGridSize[0] = INT32_MAX;
  deviceProps.maxGridSize[1] = INT32_MAX;
  deviceProps.maxGridSize[2] = INT32_MAX;
  deviceProps.clockRate = info.maxEngineClockFrequency_ * 1000;
  deviceProps.memoryClockRate = info.maxMemoryClockFrequency_ * 1000;
  deviceProps.memoryBusWidth = info.globalMemChannels_ * 32;
  deviceProps.totalConstMem = info.maxConstantBufferSize_;
  deviceProps.major = info.gfxipVersion_ / 100;
  deviceProps.minor = info.gfxipVersion_ % 100;
  deviceProps.multiProcessorCount = info.maxComputeUnits_;
  deviceProps.l2CacheSize = info.l2CacheSize_;
  deviceProps.maxThreadsPerMultiProcessor = info.maxThreadsPerCU_;
  deviceProps.computeMode = 0;
  deviceProps.clockInstructionRate = info.timeStampFrequency_;
  deviceProps.arch.hasGlobalInt32Atomics       = 1;
  deviceProps.arch.hasGlobalFloatAtomicExch    = 1;
  deviceProps.arch.hasSharedInt32Atomics       = 1;
  deviceProps.arch.hasSharedFloatAtomicExch    = 1;
  deviceProps.arch.hasFloatAtomicAdd           = 0;
  deviceProps.arch.hasGlobalInt64Atomics       = 1;
  deviceProps.arch.hasSharedInt64Atomics       = 1;
  deviceProps.arch.hasDoubles                  = 1;
  deviceProps.arch.hasWarpVote                 = 0;
  deviceProps.arch.hasWarpBallot               = 0;
  deviceProps.arch.hasWarpShuffle              = 0;
  deviceProps.arch.hasFunnelShift              = 0;
  deviceProps.arch.hasThreadFenceSystem        = 1;
  deviceProps.arch.hasSyncThreadsExt           = 0;
  deviceProps.arch.hasSurfaceFuncs             = 0;
  deviceProps.arch.has3dGrid                   = 1;
  deviceProps.arch.hasDynamicParallelism       = 0;
  deviceProps.concurrentKernels = 1;
  deviceProps.pciDomainID = info.deviceTopology_.pcie.function;
  deviceProps.pciBusID = info.deviceTopology_.pcie.bus;
  deviceProps.pciDeviceID = info.deviceTopology_.pcie.device;
  deviceProps.maxSharedMemoryPerMultiProcessor = info.localMemSizePerCU_;
  //deviceProps.isMultiGpuBoard = info.;
  deviceProps.canMapHostMemory = 1;
  deviceProps.gcnArch = info.gfxipVersion_;

  *props = deviceProps;
  HIP_RETURN(hipSuccess);
}

hipError_t hipHccGetAccelerator(int deviceId, hc::accelerator* acc) {
  HIP_INIT_API(deviceId, acc);

  assert(0 && "Unimplemented");

  HIP_RETURN(hipErrorUnknown);
}

hipError_t hipHccGetAcceleratorView(hipStream_t stream, hc::accelerator_view** av) {
  HIP_INIT_API(stream, av);

  assert(0 && "Unimplemented");

  HIP_RETURN(hipErrorUnknown);
}
<commit_msg>P4 to Git Change 1772193 by mshivama@mshivama_tf on 2019/04/19 09:39:39<commit_after>/*
Copyright (c) 2018 - present Advanced Micro Devices, Inc. All rights reserved.

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 <hip/hip_runtime.h>

#include "hip_internal.hpp"

hipError_t hipDeviceGet(hipDevice_t *device, int deviceId) {
  HIP_INIT_API(device, deviceId);

  if (device != nullptr) {
    *device = deviceId;
  } else {
    HIP_RETURN(hipErrorInvalidValue);
  }

  HIP_RETURN(hipSuccess);
};

hipError_t hipFuncSetCacheConfig (const void* func, hipFuncCache_t cacheConfig) {

  HIP_INIT_API(cacheConfig);

  // No way to set cache config yet.

  HIP_RETURN(hipSuccess);
}

hipError_t hipDeviceTotalMem (size_t *bytes, hipDevice_t device) {

  HIP_INIT_API(bytes, device);

  if (device < 0 || static_cast<size_t>(device) >= g_devices.size()) {
    HIP_RETURN(hipErrorInvalidDevice);
  }

  if (bytes == nullptr) {
    HIP_RETURN(hipErrorInvalidValue);
  }

  auto* deviceHandle = g_devices[device]->devices()[0];
  const auto& info = deviceHandle->info();

  *bytes = info.globalMemSize_;

  HIP_RETURN(hipSuccess);
}

hipError_t hipDeviceComputeCapability(int *major, int *minor, hipDevice_t device) {

  HIP_INIT_API(major, minor, device);

  if (device < 0 || static_cast<size_t>(device) >= g_devices.size()) {
    HIP_RETURN(hipErrorInvalidDevice);
  }

  if (major == nullptr || minor == nullptr) {
    HIP_RETURN(hipErrorInvalidValue);
  }

  auto* deviceHandle = g_devices[device]->devices()[0];
  const auto& info = deviceHandle->info();
  *major = info.gfxipVersion_ / 100;
  *minor = info.gfxipVersion_ % 100;

  HIP_RETURN(hipSuccess);
}

hipError_t hipDeviceGetCount(int* count) {
  HIP_INIT_API(count);

  HIP_RETURN(ihipDeviceGetCount(count));
}

hipError_t ihipDeviceGetCount(int* count) {
  if (count == nullptr) {
    return hipErrorInvalidValue;
  }

  // Get all available devices
  *count = g_devices.size();

  return hipSuccess;
}

hipError_t hipDeviceGetName(char *name, int len, hipDevice_t device) {

  HIP_INIT_API((void*)name, len, device);

  if (device < 0 || static_cast<size_t>(device) >= g_devices.size()) {
    HIP_RETURN(hipErrorInvalidDevice);
  }

  if (name == nullptr || len <= 0) {
    HIP_RETURN(hipErrorInvalidValue);
  }

  auto* deviceHandle = g_devices[device]->devices()[0];
  const auto& info = deviceHandle->info();
  const auto nameLen = ::strlen(info.boardName_);

  if (nameLen > (cl_uint)len) {
    HIP_RETURN(hipErrorInvalidValue);
  }

  ::strncpy(name, info.boardName_, nameLen);

  HIP_RETURN(hipSuccess);
}

hipError_t hipGetDeviceProperties ( hipDeviceProp_t* props, hipDevice_t device ) {
  HIP_INIT_API(props, device);

  if (props == nullptr) {
    HIP_RETURN(hipErrorInvalidValue);
  }

  if (unsigned(device) >= g_devices.size()) {
    HIP_RETURN(hipErrorInvalidDevice);
  }
  auto* deviceHandle = g_devices[device]->devices()[0];

  hipDeviceProp_t deviceProps = {0};

  const auto& info = deviceHandle->info();
  ::strncpy(deviceProps.name, info.boardName_, 128);
  deviceProps.totalGlobalMem = info.globalMemSize_;
  deviceProps.sharedMemPerBlock = info.localMemSizePerCU_;
  deviceProps.regsPerBlock = info.availableSGPRs_;
  deviceProps.warpSize = info.wavefrontWidth_;
  deviceProps.maxThreadsPerBlock = info.maxWorkGroupSize_;
  deviceProps.maxThreadsDim[0] = info.maxWorkItemSizes_[0];
  deviceProps.maxThreadsDim[1] = info.maxWorkItemSizes_[1];
  deviceProps.maxThreadsDim[2] = info.maxWorkItemSizes_[2];
  deviceProps.maxGridSize[0] = INT32_MAX;
  deviceProps.maxGridSize[1] = INT32_MAX;
  deviceProps.maxGridSize[2] = INT32_MAX;
  deviceProps.clockRate = info.maxEngineClockFrequency_ * 1000;
  deviceProps.memoryClockRate = info.maxMemoryClockFrequency_ * 1000;
  deviceProps.memoryBusWidth = info.globalMemChannels_ * 32;
  deviceProps.totalConstMem = info.maxConstantBufferSize_;
  deviceProps.major = info.gfxipVersion_ / 100;
  deviceProps.minor = info.gfxipVersion_ % 100;
  deviceProps.multiProcessorCount = info.maxComputeUnits_;
  deviceProps.l2CacheSize = info.l2CacheSize_;
  deviceProps.maxThreadsPerMultiProcessor = info.maxThreadsPerCU_;
  deviceProps.computeMode = 0;
  deviceProps.clockInstructionRate = info.timeStampFrequency_;
  deviceProps.arch.hasGlobalInt32Atomics       = 1;
  deviceProps.arch.hasGlobalFloatAtomicExch    = 1;
  deviceProps.arch.hasSharedInt32Atomics       = 1;
  deviceProps.arch.hasSharedFloatAtomicExch    = 1;
  deviceProps.arch.hasFloatAtomicAdd           = 0;
  deviceProps.arch.hasGlobalInt64Atomics       = 1;
  deviceProps.arch.hasSharedInt64Atomics       = 1;
  deviceProps.arch.hasDoubles                  = 1;
  deviceProps.arch.hasWarpVote                 = 0;
  deviceProps.arch.hasWarpBallot               = 0;
  deviceProps.arch.hasWarpShuffle              = 0;
  deviceProps.arch.hasFunnelShift              = 0;
  deviceProps.arch.hasThreadFenceSystem        = 1;
  deviceProps.arch.hasSyncThreadsExt           = 0;
  deviceProps.arch.hasSurfaceFuncs             = 0;
  deviceProps.arch.has3dGrid                   = 1;
  deviceProps.arch.hasDynamicParallelism       = 0;
  deviceProps.concurrentKernels = 1;
  deviceProps.pciDomainID = info.deviceTopology_.pcie.function;
  deviceProps.pciBusID = info.deviceTopology_.pcie.bus;
  deviceProps.pciDeviceID = info.deviceTopology_.pcie.device;
  deviceProps.maxSharedMemoryPerMultiProcessor = info.localMemSizePerCU_;
  //deviceProps.isMultiGpuBoard = info.;
  deviceProps.canMapHostMemory = 1;
  deviceProps.gcnArch = info.gfxipVersion_;

  *props = deviceProps;
  HIP_RETURN(hipSuccess);
}

hipError_t hipHccGetAccelerator(int deviceId, hc::accelerator* acc) {
  HIP_INIT_API(deviceId, acc);

  assert(0 && "Unimplemented");

  HIP_RETURN(hipErrorUnknown);
}

hipError_t hipHccGetAcceleratorView(hipStream_t stream, hc::accelerator_view** av) {
  HIP_INIT_API(stream, av);

  assert(0 && "Unimplemented");

  HIP_RETURN(hipErrorUnknown);
}
<|endoftext|>


<commit_before>/*
Copyright (c) 2015 - present Advanced Micro Devices, Inc. All rights reserved.

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 <hip/hip_runtime.h>
#include <libelf.h>
#include <fstream>

#include "hip_internal.hpp"
#include "platform/program.hpp"

hipError_t ihipModuleLoadData(hipModule_t *module, const void *image);

static uint64_t ElfSize(const void *emi)
{
  const Elf64_Ehdr *ehdr = (const Elf64_Ehdr*)emi;
  const Elf64_Shdr *shdr = (const Elf64_Shdr*)((char*)emi + ehdr->e_shoff);

  uint64_t max_offset = ehdr->e_shoff;
  uint64_t total_size = max_offset + ehdr->e_shentsize * ehdr->e_shnum;

  for (uint16_t i=0; i < ehdr->e_shnum; ++i){
    uint64_t cur_offset = static_cast<uint64_t>(shdr[i].sh_offset);
    if (max_offset < cur_offset) {
      max_offset = cur_offset;
      total_size = max_offset;
      if(SHT_NOBITS != shdr[i].sh_type) {
        total_size += static_cast<uint64_t>(shdr[i].sh_size);
      }
    }
  }
  return total_size;
}

hipError_t hipModuleLoad(hipModule_t *module, const char *fname)
{
  HIP_INIT_API(module, fname);

  if (!fname) {
    return hipErrorInvalidValue;
  }

  std::ifstream file{fname};

  if (!file.is_open()) {
    return hipErrorFileNotFound;
  }

  std::vector<char> tmp{std::istreambuf_iterator<char>{file}, std::istreambuf_iterator<char>{}};

  return ihipModuleLoadData(module, tmp.data());
}

hipError_t hipModuleUnload(hipModule_t hmod)
{
  HIP_INIT_API(hmod);

  if (hmod == nullptr) {
    return hipErrorUnknown;
  }

  amd::Program* program = as_amd(reinterpret_cast<cl_program>(hmod));

  program->release();

  return hipSuccess;
}

hipError_t hipModuleLoadData(hipModule_t *module, const void *image)
{
  HIP_INIT_API(module, image);

  return ihipModuleLoadData(module, image);
}

hipError_t ihipModuleLoadData(hipModule_t *module, const void *image)
{
  amd::Program* program = new amd::Program(*g_context);
  if (program == NULL) {
    return hipErrorOutOfMemory;
  }

  if (CL_SUCCESS != program->addDeviceProgram(*g_context->devices()[0], image, ElfSize(image)) ||
    CL_SUCCESS != program->build(g_context->devices(), nullptr, nullptr, nullptr)) {
    return hipErrorUnknown;
  }

  *module = reinterpret_cast<hipModule_t>(as_cl(program));

  return hipSuccess;
}

hipError_t hipModuleGetFunction(hipFunction_t *hfunc, hipModule_t hmod, const char *name)
{
  HIP_INIT_API(hfunc, hmod, name);

  amd::Program* program = as_amd(reinterpret_cast<cl_program>(hmod));

  const amd::Symbol* symbol = program->findSymbol(name);
  if (!symbol) {
    return hipErrorNotFound;
  }

  amd::Kernel* kernel = new amd::Kernel(*program, *symbol, name);
  if (!kernel) {
    return hipErrorOutOfMemory;
  }

  *hfunc = reinterpret_cast<hipFunction_t>(as_cl(kernel));

  return hipSuccess;
}

hipError_t hipModuleLaunchKernel(hipFunction_t f,
                                 uint32_t gridDimX, uint32_t gridDimY, uint32_t gridDimZ,
                                 uint32_t blockDimX, uint32_t blockDimY, uint32_t blockDimZ,
                                 uint32_t sharedMemBytes, hipStream_t hStream,
                                 void **kernelParams, void **extra)
{
  HIP_INIT_API(f, gridDimX, gridDimY, gridDimZ,
               blockDimX, blockDimY, blockDimZ,
               sharedMemBytes, hStream,
               kernelParams, extra);

  amd::Kernel* kernel = as_amd(reinterpret_cast<cl_kernel>(f));
  amd::Device* device = g_context->devices()[0];

  amd::HostQueue* queue = as_amd(reinterpret_cast<cl_command_queue>(hStream))->asHostQueue();

  if (!queue) {
    return hipErrorOutOfMemory;
  }

  size_t globalWorkOffset[3] = {0};
  size_t globalWorkSize[3] = { gridDimX * blockDimX, gridDimY * blockDimY, gridDimZ * blockDimZ};
  size_t localWorkSize[3] = { blockDimX, blockDimY, blockDimZ };
  amd::NDRangeContainer ndrange(3, globalWorkOffset, globalWorkSize, localWorkSize);
  amd::Command::EventWaitList waitList;

  // 'extra' is a struct that contains the following info: {
  //   HIP_LAUNCH_PARAM_BUFFER_POINTER, kernargs,
  //   HIP_LAUNCH_PARAM_BUFFER_SIZE, &kernargs_size,
  //   HIP_LAUNCH_PARAM_END }
  if (extra[0] != HIP_LAUNCH_PARAM_BUFFER_POINTER ||
      extra[2] != HIP_LAUNCH_PARAM_BUFFER_SIZE || extra[4] != HIP_LAUNCH_PARAM_END) {
    return hipErrorNotInitialized;
  }
  address kernargs = reinterpret_cast<address>(extra[1]);

  const amd::KernelSignature& signature = kernel->signature();
  for (size_t i = 0; i < signature.numParameters(); ++i) {
    const amd::KernelParameterDescriptor& desc = signature.at(i);
    if (kernelParams == nullptr) {
      assert(extra);
      kernel->parameters().set(i, desc.size_, kernargs + desc.offset_,
                               desc.type_ == T_POINTER/*svmBound*/);
    } else {
      assert(!extra);
      kernel->parameters().set(i, desc.size_, kernelParams[i], desc.type_ == T_POINTER/*svmBound*/);
    }
  }

  amd::NDRangeKernelCommand* command = new amd::NDRangeKernelCommand(*queue, waitList, *kernel, ndrange);
  if (!command) {
    return hipErrorOutOfMemory;
  }

  // Make sure we have memory for the command execution
  if (CL_SUCCESS != command->validateMemory()) {
    delete command;
    return hipErrorMemoryAllocation;
  }

  command->enqueue();
  command->awaitCompletion();
  command->release();

  return hipSuccess;
}

<commit_msg>P4 to Git Change 1548145 by cpaquot@cpaquot-ocl-lc-lnx on 2018/04/30 21:15:56<commit_after>/*
Copyright (c) 2015 - present Advanced Micro Devices, Inc. All rights reserved.

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 <hip/hip_runtime.h>
#include <libelf.h>
#include <fstream>

#include "hip_internal.hpp"
#include "platform/program.hpp"

hipError_t ihipModuleLoadData(hipModule_t *module, const void *image);

static uint64_t ElfSize(const void *emi)
{
  const Elf64_Ehdr *ehdr = (const Elf64_Ehdr*)emi;
  const Elf64_Shdr *shdr = (const Elf64_Shdr*)((char*)emi + ehdr->e_shoff);

  uint64_t max_offset = ehdr->e_shoff;
  uint64_t total_size = max_offset + ehdr->e_shentsize * ehdr->e_shnum;

  for (uint16_t i=0; i < ehdr->e_shnum; ++i){
    uint64_t cur_offset = static_cast<uint64_t>(shdr[i].sh_offset);
    if (max_offset < cur_offset) {
      max_offset = cur_offset;
      total_size = max_offset;
      if(SHT_NOBITS != shdr[i].sh_type) {
        total_size += static_cast<uint64_t>(shdr[i].sh_size);
      }
    }
  }
  return total_size;
}

hipError_t hipModuleLoad(hipModule_t *module, const char *fname)
{
  HIP_INIT_API(module, fname);

  if (!fname) {
    return hipErrorInvalidValue;
  }

  std::ifstream file{fname};

  if (!file.is_open()) {
    return hipErrorFileNotFound;
  }

  std::vector<char> tmp{std::istreambuf_iterator<char>{file}, std::istreambuf_iterator<char>{}};

  return ihipModuleLoadData(module, tmp.data());
}

hipError_t hipModuleUnload(hipModule_t hmod)
{
  HIP_INIT_API(hmod);

  if (hmod == nullptr) {
    return hipErrorUnknown;
  }

  amd::Program* program = as_amd(reinterpret_cast<cl_program>(hmod));

  program->release();

  return hipSuccess;
}

hipError_t hipModuleLoadData(hipModule_t *module, const void *image)
{
  HIP_INIT_API(module, image);

  return ihipModuleLoadData(module, image);
}

hipError_t ihipModuleLoadData(hipModule_t *module, const void *image)
{
  amd::Program* program = new amd::Program(*g_context);
  if (program == NULL) {
    return hipErrorOutOfMemory;
  }

  if (CL_SUCCESS != program->addDeviceProgram(*g_context->devices()[0], image, ElfSize(image)) ||
    CL_SUCCESS != program->build(g_context->devices(), nullptr, nullptr, nullptr)) {
    return hipErrorUnknown;
  }

  *module = reinterpret_cast<hipModule_t>(as_cl(program));

  return hipSuccess;
}

hipError_t hipModuleGetFunction(hipFunction_t *hfunc, hipModule_t hmod, const char *name)
{
  HIP_INIT_API(hfunc, hmod, name);

  amd::Program* program = as_amd(reinterpret_cast<cl_program>(hmod));

  const amd::Symbol* symbol = program->findSymbol(name);
  if (!symbol) {
    return hipErrorNotFound;
  }

  amd::Kernel* kernel = new amd::Kernel(*program, *symbol, name);
  if (!kernel) {
    return hipErrorOutOfMemory;
  }

  *hfunc = reinterpret_cast<hipFunction_t>(as_cl(kernel));

  return hipSuccess;
}

hipError_t hipModuleLaunchKernel(hipFunction_t f,
                                 uint32_t gridDimX, uint32_t gridDimY, uint32_t gridDimZ,
                                 uint32_t blockDimX, uint32_t blockDimY, uint32_t blockDimZ,
                                 uint32_t sharedMemBytes, hipStream_t hStream,
                                 void **kernelParams, void **extra)
{
  HIP_INIT_API(f, gridDimX, gridDimY, gridDimZ,
               blockDimX, blockDimY, blockDimZ,
               sharedMemBytes, hStream,
               kernelParams, extra);

  amd::Kernel* kernel = as_amd(reinterpret_cast<cl_kernel>(f));
  amd::Device* device = g_context->devices()[0];

  amd::HostQueue* queue;
  if (hStream == nullptr) {
    queue = new amd::HostQueue(*g_context, *device, 0,
                               amd::CommandQueue::RealTimeDisabled,
                               amd::CommandQueue::Priority::Normal);
  } else {
    queue = as_amd(reinterpret_cast<cl_command_queue>(hStream))->asHostQueue();
  }
  if (!queue) {
    return hipErrorOutOfMemory;
  }

  size_t globalWorkOffset[3] = {0};
  size_t globalWorkSize[3] = { gridDimX * blockDimX, gridDimY * blockDimY, gridDimZ * blockDimZ};
  size_t localWorkSize[3] = { blockDimX, blockDimY, blockDimZ };
  amd::NDRangeContainer ndrange(3, globalWorkOffset, globalWorkSize, localWorkSize);
  amd::Command::EventWaitList waitList;

  // 'extra' is a struct that contains the following info: {
  //   HIP_LAUNCH_PARAM_BUFFER_POINTER, kernargs,
  //   HIP_LAUNCH_PARAM_BUFFER_SIZE, &kernargs_size,
  //   HIP_LAUNCH_PARAM_END }
  if (extra[0] != HIP_LAUNCH_PARAM_BUFFER_POINTER ||
      extra[2] != HIP_LAUNCH_PARAM_BUFFER_SIZE || extra[4] != HIP_LAUNCH_PARAM_END) {
    return hipErrorNotInitialized;
  }
  address kernargs = reinterpret_cast<address>(extra[1]);

  const amd::KernelSignature& signature = kernel->signature();
  for (size_t i = 0; i < signature.numParameters(); ++i) {
    const amd::KernelParameterDescriptor& desc = signature.at(i);
    if (kernelParams == nullptr) {
      assert(extra);
      kernel->parameters().set(i, desc.size_, kernargs + desc.offset_,
                               desc.type_ == T_POINTER/*svmBound*/);
    } else {
      assert(!extra);
      kernel->parameters().set(i, desc.size_, kernelParams[i], desc.type_ == T_POINTER/*svmBound*/);
    }
  }

  amd::NDRangeKernelCommand* command = new amd::NDRangeKernelCommand(*queue, waitList, *kernel, ndrange);
  if (!command) {
    return hipErrorOutOfMemory;
  }

  // Make sure we have memory for the command execution
  if (CL_SUCCESS != command->validateMemory()) {
    delete command;
    return hipErrorMemoryAllocation;
  }

  command->enqueue();
  command->awaitCompletion();
  command->release();

  if (hStream == nullptr) {
    queue->release();
  }

  return hipSuccess;
}

<|endoftext|>