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

#include "qremoteserviceregister_p.h"
#include "qremoteserviceregister_ls_p.h"
#include "ipcendpoint_p.h"
#include "objectendpoint_p.h"

#include <QLocalServer>
#include <QLocalSocket>
#include <QDataStream>
#include <QTimer>
#include <QProcess>
#include <QFile>

#include <time.h>
#include <sys/types.h>          /* See NOTES */

#ifndef Q_OS_WIN
#include <sys/un.h>
#include <sys/socket.h>
#else
// Needed for ::Sleep, while we wait for a better solution
#include <Windows.h>
#include <Winbase.h>
#endif

#ifdef LOCAL_PEERCRED /* from sys/un.h */
#include <sys/ucred.h>
#endif

QTM_BEGIN_NAMESPACE

//IPC based on QLocalSocket

class LocalSocketEndPoint : public QServiceIpcEndPoint
{
    Q_OBJECT
public:
    LocalSocketEndPoint(QLocalSocket* s, QObject* parent = 0)
        : QServiceIpcEndPoint(parent), socket(s)
    {
        Q_ASSERT(socket);
        socket->setParent(this);
        connect(s, SIGNAL(readyRead()), this, SLOT(readIncoming()));
        connect(s, SIGNAL(disconnected()), this, SIGNAL(disconnected()));
        connect(s, SIGNAL(disconnected()), this, SLOT(ipcfault()));

        if (socket->bytesAvailable())
            QTimer::singleShot(0, this, SLOT(readIncoming()));
    }

    ~LocalSocketEndPoint()
    {
        disconnect(this, SLOT(ipcfault()));
        socket->close();
    }

Q_SIGNALS:
    void errorUnrecoverableIPCFault(QService::UnrecoverableIPCError);

protected:
    void flushPackage(const QServicePackage& package)
    {
        QByteArray block;
        QDataStream out(&block, QIODevice::WriteOnly);
        out.setVersion(QDataStream::Qt_4_6);
        out << package;
        socket->write(block);
    }

protected slots:
    void readIncoming()
    {
        QDataStream in(socket);
        in.setVersion(QDataStream::Qt_4_6);

        while(socket->bytesAvailable()) {
            QServicePackage package;
            in >> package;
            incoming.enqueue(package);
        }

        emit readyRead();
    }
    void ipcfault()
    {
        emit errorUnrecoverableIPCFault(QService::ErrorServiceNoLongerAvailable);
    }

private:
    QLocalSocket* socket;
};

struct PROXY
{
public:
    ObjectEndPoint*      pObjectEndPoint;
    QLocalSocket*        pSocket;
    QString servicename;

    void init(){
        pObjectEndPoint = 0;
        pSocket = 0;
        servicename = "";
    }

    bool operator==(const PROXY& other)
    {
        if(pObjectEndPoint == other.pObjectEndPoint
            && servicename == other.servicename)
            return true;
        return false;
    }
};
static QList<PROXY>proxylist;

QRemoteServiceRegisterLocalSocketPrivate::QRemoteServiceRegisterLocalSocketPrivate(QObject* parent)
    : QRemoteServiceRegisterPrivate(parent)
{
}

void QRemoteServiceRegisterLocalSocketPrivate::publishServices( const QString& ident)
{
    createServiceEndPoint(ident) ;
}

void QRemoteServiceRegisterLocalSocketPrivate::processIncoming()
{
    if (localServer->hasPendingConnections()) {
        QLocalSocket* s = localServer->nextPendingConnection();
        //LocalSocketEndPoint owns socket
        int fd = s->socketDescriptor();
        if(getSecurityFilter()){
            QRemoteServiceRegisterCredentials qcred;
            memset(&qcred, 0, sizeof(QRemoteServiceRegisterCredentials));
            qcred.fd = fd;

#if defined(LOCAL_PEERCRED)
            struct xucred xuc;
            socklen_t len = sizeof(struct xucred);

            if(getsockopt(fd, SOL_SOCKET, LOCAL_PEERCRED, &xuc, &len) == 0) {
                qcred.pid = -1; // No PID on bsd
                qcred.uid = xuc.cr_uid;
                qcred.gid = xuc.cr_gid;

            }

#elif defined(SO_PEERCRED)
            struct ucred uc;
            socklen_t len = sizeof(struct ucred);

            if(getsockopt(fd, SOL_SOCKET, SO_PEERCRED, &uc, &len) == 0) {
                qcred.pid = uc.pid;
                qcred.uid = uc.uid;
                qcred.gid = uc.gid;
            }
            else {
                s->close();
                perror("Failed to get peer credential");
                return;
            }
#else
            s->close();
            qWarning("Credentials check unsupprted on this platform");
            return;
#endif
            qDebug() << "Security filter call";
            if(!getSecurityFilter()(reinterpret_cast<const void *>(&qcred))){
                s->close();
                return;
            }
        }
        LocalSocketEndPoint* ipcEndPoint = new LocalSocketEndPoint(s);
        ObjectEndPoint* endpoint = new ObjectEndPoint(ObjectEndPoint::Service, ipcEndPoint, this);
        Q_UNUSED(endpoint);
    }
}

/*
    Creates endpoint on service side.
*/
bool QRemoteServiceRegisterLocalSocketPrivate::createServiceEndPoint(const QString& ident)
{
    //other IPC mechanisms such as dbus may have to publish the
    //meta object definition for all registered service types
    QLocalServer::removeServer(ident);
    localServer = new QLocalServer(this);
    if ( !localServer->listen(ident) ) {
        qWarning() << "Cannot create local socket endpoint";
        return false;
    }
    connect(localServer, SIGNAL(newConnection()), this, SLOT(processIncoming()));
    if (localServer->hasPendingConnections())
        QTimer::singleShot(0, this, SLOT(processIncoming()));

    return true;
}

QRemoteServiceRegisterPrivate* QRemoteServiceRegisterPrivate::constructPrivateObject(QObject *parent)
{
  return new QRemoteServiceRegisterLocalSocketPrivate(parent);
}

/*
    Creates endpoint on client side.
*/
QObject* QRemoteServiceRegisterPrivate::proxyForService(const QRemoteServiceRegister::Entry& entry, const QString& location)
{
    QLocalSocket* socket = new QLocalSocket();
    socket->connectToServer(location);
    if(!socket->waitForConnected()){
        if (!socket->isValid()) {
            QString path = location;
            qWarning() << "Cannot connect to remote service, trying to start service " << path;
            // If we have autotests enable, check for the service in .
#ifdef QTM_BUILD_UNITTESTS
            QFile file("./" + path);
            if(file.exists()){
                path.prepend("./");
            }
#endif
            qint64 pid = 0;
            // Start the service as a detached process
            if(QProcess::startDetached(path, QStringList(), QString(), &pid)){
                int i;
                socket->connectToServer(location);
                for(i = 0; !socket->isValid() && i < 1000; i++){
                    // Temporary hack till we can improve startup signaling
#ifdef Q_OS_WIN
                    ::Sleep(10);
#else
                    struct timespec tm;
                    tm.tv_sec = 0;
                    tm.tv_nsec = 1000000;
                    nanosleep(&tm, 0x0);
#endif
                    socket->connectToServer(location);
                    // keep trying for a while
                }
                if(!socket->isValid()){
                    qWarning() << "Server failed to start within waiting period";
                    return false;
                }
            }
            else
                qWarning() << "Server could not be started";
        }
    }
    if (socket->isValid()){
        LocalSocketEndPoint* ipcEndPoint = new LocalSocketEndPoint(socket);
        ObjectEndPoint* endPoint = new ObjectEndPoint(ObjectEndPoint::Client, ipcEndPoint);

        QObject *proxy = endPoint->constructProxy(entry);
        if(proxy){
            QObject::connect(proxy, SIGNAL(destroyed()), endPoint, SLOT(deleteLater()));
            QObject::connect(ipcEndPoint, SIGNAL(errorUnrecoverableIPCFault(QService::UnrecoverableIPCError)),
                             proxy, SIGNAL(errorUnrecoverableIPCFault(QService::UnrecoverableIPCError)));
        }
        ipcEndPoint->setParent(proxy);
        endPoint->setParent(proxy);
        return proxy;
    }
    return 0;
}

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

#include "qremoteserviceregister_p.h"
#include "qremoteserviceregister_ls_p.h"
#include "ipcendpoint_p.h"
#include "objectendpoint_p.h"

#include <QLocalServer>
#include <QLocalSocket>
#include <QDataStream>
#include <QTimer>
#include <QProcess>
#include <QFile>

#include <time.h>
#include <sys/types.h>          /* See NOTES */

#ifndef Q_OS_WIN
#include <sys/un.h>
#include <sys/socket.h>
#else
// Needed for ::Sleep, while we wait for a better solution
#include <Windows.h>
#include <Winbase.h>
#endif

#ifdef LOCAL_PEERCRED /* from sys/un.h */
#include <sys/ucred.h>
#endif

QTM_BEGIN_NAMESPACE

//IPC based on QLocalSocket

class LocalSocketEndPoint : public QServiceIpcEndPoint
{
    Q_OBJECT
public:
    LocalSocketEndPoint(QLocalSocket* s, QObject* parent = 0)
        : QServiceIpcEndPoint(parent), socket(s)
    {
        Q_ASSERT(socket);
        socket->setParent(this);
        connect(s, SIGNAL(readyRead()), this, SLOT(readIncoming()));
        connect(s, SIGNAL(disconnected()), this, SIGNAL(disconnected()));
        connect(s, SIGNAL(disconnected()), this, SLOT(ipcfault()));

        if (socket->bytesAvailable())
            QTimer::singleShot(0, this, SLOT(readIncoming()));
    }

    ~LocalSocketEndPoint()
    {
        disconnect(this, SLOT(ipcfault()));
        socket->close();
    }

Q_SIGNALS:
    void errorUnrecoverableIPCFault(QService::UnrecoverableIPCError);

protected:
    void flushPackage(const QServicePackage& package)
    {
        QByteArray block;
        QDataStream out(&block, QIODevice::WriteOnly);
        out.setVersion(QDataStream::Qt_4_6);
        out << package;
        socket->write(block);
    }

protected slots:
    void readIncoming()
    {
        QDataStream in(socket);
        in.setVersion(QDataStream::Qt_4_6);

        while(socket->bytesAvailable()) {
            QServicePackage package;
            in >> package;
            incoming.enqueue(package);
        }

        emit readyRead();
    }
    void ipcfault()
    {
        emit errorUnrecoverableIPCFault(QService::ErrorServiceNoLongerAvailable);
    }

private:
    QLocalSocket* socket;
};

QRemoteServiceRegisterLocalSocketPrivate::QRemoteServiceRegisterLocalSocketPrivate(QObject* parent)
    : QRemoteServiceRegisterPrivate(parent)
{
}

void QRemoteServiceRegisterLocalSocketPrivate::publishServices( const QString& ident)
{
    createServiceEndPoint(ident) ;
}

void QRemoteServiceRegisterLocalSocketPrivate::processIncoming()
{
    if (localServer->hasPendingConnections()) {
        QLocalSocket* s = localServer->nextPendingConnection();
        //LocalSocketEndPoint owns socket
        int fd = s->socketDescriptor();
        if(getSecurityFilter()){
            QRemoteServiceRegisterCredentials qcred;
            memset(&qcred, 0, sizeof(QRemoteServiceRegisterCredentials));
            qcred.fd = fd;

#if defined(LOCAL_PEERCRED)
            struct xucred xuc;
            socklen_t len = sizeof(struct xucred);

            if(getsockopt(fd, SOL_SOCKET, LOCAL_PEERCRED, &xuc, &len) == 0) {
                qcred.pid = -1; // No PID on bsd
                qcred.uid = xuc.cr_uid;
                qcred.gid = xuc.cr_gid;

            }

#elif defined(SO_PEERCRED)
            struct ucred uc;
            socklen_t len = sizeof(struct ucred);

            if(getsockopt(fd, SOL_SOCKET, SO_PEERCRED, &uc, &len) == 0) {
                qcred.pid = uc.pid;
                qcred.uid = uc.uid;
                qcred.gid = uc.gid;
            }
            else {
                s->close();
                perror("Failed to get peer credential");
                return;
            }
#else
            s->close();
            qWarning("Credentials check unsupprted on this platform");
            return;
#endif
            qDebug() << "Security filter call";
            if(!getSecurityFilter()(reinterpret_cast<const void *>(&qcred))){
                s->close();
                return;
            }
        }
        LocalSocketEndPoint* ipcEndPoint = new LocalSocketEndPoint(s);
        ObjectEndPoint* endpoint = new ObjectEndPoint(ObjectEndPoint::Service, ipcEndPoint, this);
        Q_UNUSED(endpoint);
    }
}

/*
    Creates endpoint on service side.
*/
bool QRemoteServiceRegisterLocalSocketPrivate::createServiceEndPoint(const QString& ident)
{
    //other IPC mechanisms such as dbus may have to publish the
    //meta object definition for all registered service types
    QLocalServer::removeServer(ident);
    localServer = new QLocalServer(this);
    if ( !localServer->listen(ident) ) {
        qWarning() << "Cannot create local socket endpoint";
        return false;
    }
    connect(localServer, SIGNAL(newConnection()), this, SLOT(processIncoming()));
    if (localServer->hasPendingConnections())
        QTimer::singleShot(0, this, SLOT(processIncoming()));

    return true;
}

QRemoteServiceRegisterPrivate* QRemoteServiceRegisterPrivate::constructPrivateObject(QObject *parent)
{
  return new QRemoteServiceRegisterLocalSocketPrivate(parent);
}

/*
    Creates endpoint on client side.
*/
QObject* QRemoteServiceRegisterPrivate::proxyForService(const QRemoteServiceRegister::Entry& entry, const QString& location)
{
    QLocalSocket* socket = new QLocalSocket();
    socket->connectToServer(location);
    if(!socket->waitForConnected()){
        if (!socket->isValid()) {
            QString path = location;
            qWarning() << "Cannot connect to remote service, trying to start service " << path;
            // If we have autotests enable, check for the service in .
#ifdef QTM_BUILD_UNITTESTS
            QFile file("./" + path);
            if(file.exists()){
                path.prepend("./");
            }
#endif
            qint64 pid = 0;
            // Start the service as a detached process
            if(QProcess::startDetached(path, QStringList(), QString(), &pid)){
                int i;
                socket->connectToServer(location);
                for(i = 0; !socket->isValid() && i < 1000; i++){
                    // Temporary hack till we can improve startup signaling
#ifdef Q_OS_WIN
                    ::Sleep(10);
#else
                    struct timespec tm;
                    tm.tv_sec = 0;
                    tm.tv_nsec = 1000000;
                    nanosleep(&tm, 0x0);
#endif
                    socket->connectToServer(location);
                    // keep trying for a while
                }
                if(!socket->isValid()){
                    qWarning() << "Server failed to start within waiting period";
                    return false;
                }
            }
            else
                qWarning() << "Server could not be started";
        }
    }
    if (socket->isValid()){
        LocalSocketEndPoint* ipcEndPoint = new LocalSocketEndPoint(socket);
        ObjectEndPoint* endPoint = new ObjectEndPoint(ObjectEndPoint::Client, ipcEndPoint);

        QObject *proxy = endPoint->constructProxy(entry);
        if(proxy){
            QObject::connect(proxy, SIGNAL(destroyed()), endPoint, SLOT(deleteLater()));
            QObject::connect(ipcEndPoint, SIGNAL(errorUnrecoverableIPCFault(QService::UnrecoverableIPCError)),
                             proxy, SIGNAL(errorUnrecoverableIPCFault(QService::UnrecoverableIPCError)));
        }
        ipcEndPoint->setParent(proxy);
        endPoint->setParent(proxy);
        return proxy;
    }
    return 0;
}

#include "moc_qremoteserviceregister_ls_p.cpp"
#include "qremoteserviceregister_ls_p.moc"
QTM_END_NAMESPACE
<|endoftext|>


<commit_before>/** @file
    @brief Implementation

    @date 2015

    @author
    Sensics, Inc.
    <http://sensics.com/osvr>
*/

// Copyright 2015 Sensics, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

// Internal Includes
#include <osvr/PluginHost/SearchPath.h>
#include <osvr/PluginHost/PathConfig.h>
#include "BinaryLocation.h"
#include <osvr/Util/Verbosity.h>

// Library/third-party includes
#include <boost/filesystem.hpp>
#include <boost/range/iterator_range.hpp>

// Standard includes
// - none

namespace osvr {
namespace pluginhost {
    SearchPath getPluginSearchPath() {
        boost::filesystem::path exeLocation(getBinaryLocation());
#ifdef __ANDROID__
        OSVR_DEV_VERBOSE("Binary location: " << exeLocation);
#endif
        // Should be something like PREFIX/bin or PREFIX/bin/Release (depending
        // on if we're installed or in a build tree)
        auto binDir = exeLocation.parent_path();
#ifdef _MSC_VER
        /// CMAKE_INTDIR is a string like "Debug", defined automatically
        if (binDir.filename() == CMAKE_INTDIR) {
            binDir = binDir.parent_path();
        }
#endif
        // binDir now normalized to PREFIX/bin
        auto root = binDir.parent_path();

        SearchPath paths;
#ifdef _MSC_VER
        paths.push_back((root / OSVR_PLUGIN_DIR / CMAKE_INTDIR).string());
#endif
        paths.push_back((root / OSVR_PLUGIN_DIR).string());

        /// @todo add user's home directory to search path

        return paths;
    }

    FileList getAllFilesWithExt(SearchPath dirPath, const std::string &ext) {
        FileList filesPaths;

        for (const auto &path : dirPath) {
            using boost::filesystem::directory_iterator;
            using boost::make_iterator_range;
            boost::filesystem::path directoryPath(path);

            // Make sure that directory exists
            if (!boost::filesystem::exists(directoryPath)) {
                continue;
            }

            // Get a list of files inside the dir that match the extension
            for (const auto &pathName : make_iterator_range(
                     directory_iterator(directoryPath), directory_iterator())) {
                if (!boost::filesystem::is_regular_file(pathName) ||
                    pathName.path().extension() != ext)
                    continue;

                filesPaths.push_back(pathName.path().generic_string());
            }
        }

        return filesPaths;
    }

    std::string findPlugin(const std::string &pluginName) {
        auto searchPaths = getPluginSearchPath();
        for (const auto &searchPath : searchPaths) {
            if (!boost::filesystem::exists(searchPath))
                continue;

            using boost::filesystem::directory_iterator;
            using boost::make_iterator_range;

            for (const auto &pluginPathName : make_iterator_range(
                     directory_iterator(searchPath), directory_iterator())) {
                /// Must be a regular file
                /// @todo does this mean symlinks get excluded?
                if (!boost::filesystem::is_regular_file(pluginPathName))
                    continue;

                const auto pluginCandidate =
                    boost::filesystem::path(pluginPathName);

                /// Needs right extension
                if (pluginCandidate.extension().generic_string() !=
                    OSVR_PLUGIN_EXTENSION) {
                    continue;
                }
                const auto pluginBaseName =
                    pluginCandidate.filename().stem().generic_string();
                /// If the name is right or has the manual load suffix, this is
                /// a good one.
                if ((pluginBaseName == pluginName) ||
                    (pluginBaseName ==
                     pluginName + OSVR_PLUGIN_IGNORE_SUFFIX)) {
                    return pluginPathName.path().generic_string();
                }
            }
        }

        return std::string();
    }

} // namespace pluginhost
} // namespace osvr
<commit_msg>Added the current working directory (plus the plugin subdir from CMAKE) to the plugin search path.<commit_after>/** @file
    @brief Implementation

    @date 2015

    @author
    Sensics, Inc.
    <http://sensics.com/osvr>
*/

// Copyright 2015 Sensics, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

// Internal Includes
#include <osvr/PluginHost/SearchPath.h>
#include <osvr/PluginHost/PathConfig.h>
#include "BinaryLocation.h"
#include <osvr/Util/Verbosity.h>

// Library/third-party includes
#include <boost/filesystem.hpp>
#include <boost/range/iterator_range.hpp>

// Standard includes
// - none

namespace osvr {
namespace pluginhost {
    SearchPath getPluginSearchPath() {
        boost::filesystem::path exeLocation(getBinaryLocation());
#ifdef __ANDROID__
        OSVR_DEV_VERBOSE("Binary location: " << exeLocation);
#endif
        // Should be something like PREFIX/bin or PREFIX/bin/Release (depending
        // on if we're installed or in a build tree)
        auto binDir = exeLocation.parent_path();
#ifdef _MSC_VER
        /// CMAKE_INTDIR is a string like "Debug", defined automatically
        if (binDir.filename() == CMAKE_INTDIR) {
            binDir = binDir.parent_path();
        }
#endif
        // binDir now normalized to PREFIX/bin
        auto root = binDir.parent_path();

        // current working directory
        auto currentWorkingDirectory = boost::filesystem::current_path();

        SearchPath paths;

        // current working directory, if different from root
        if (currentWorkingDirectory != root) {
            paths.push_back((currentWorkingDirectory / OSVR_PLUGIN_DIR).string());
        }

#ifdef _MSC_VER
        paths.push_back((root / OSVR_PLUGIN_DIR / CMAKE_INTDIR).string());
#endif
        paths.push_back((root / OSVR_PLUGIN_DIR).string());

        /// @todo add user's home directory to search path

        return paths;
    }

    FileList getAllFilesWithExt(SearchPath dirPath, const std::string &ext) {
        FileList filesPaths;

        for (const auto &path : dirPath) {
            using boost::filesystem::directory_iterator;
            using boost::make_iterator_range;
            boost::filesystem::path directoryPath(path);

            // Make sure that directory exists
            if (!boost::filesystem::exists(directoryPath)) {
                continue;
            }

            // Get a list of files inside the dir that match the extension
            for (const auto &pathName : make_iterator_range(
                     directory_iterator(directoryPath), directory_iterator())) {
                if (!boost::filesystem::is_regular_file(pathName) ||
                    pathName.path().extension() != ext)
                    continue;

                filesPaths.push_back(pathName.path().generic_string());
            }
        }

        return filesPaths;
    }

    std::string findPlugin(const std::string &pluginName) {
        auto searchPaths = getPluginSearchPath();
        for (const auto &searchPath : searchPaths) {
            if (!boost::filesystem::exists(searchPath))
                continue;

            using boost::filesystem::directory_iterator;
            using boost::make_iterator_range;

            for (const auto &pluginPathName : make_iterator_range(
                     directory_iterator(searchPath), directory_iterator())) {
                /// Must be a regular file
                /// @todo does this mean symlinks get excluded?
                if (!boost::filesystem::is_regular_file(pluginPathName))
                    continue;

                const auto pluginCandidate =
                    boost::filesystem::path(pluginPathName);

                /// Needs right extension
                if (pluginCandidate.extension().generic_string() !=
                    OSVR_PLUGIN_EXTENSION) {
                    continue;
                }
                const auto pluginBaseName =
                    pluginCandidate.filename().stem().generic_string();
                /// If the name is right or has the manual load suffix, this is
                /// a good one.
                if ((pluginBaseName == pluginName) ||
                    (pluginBaseName ==
                     pluginName + OSVR_PLUGIN_IGNORE_SUFFIX)) {
                    return pluginPathName.path().generic_string();
                }
            }
        }

        return std::string();
    }

} // namespace pluginhost
} // namespace osvr
<|endoftext|>


<commit_before>//-----------------------------------------------------------------------bl-
//--------------------------------------------------------------------------
//
// GRINS - General Reacting Incompressible Navier-Stokes
//
// Copyright (C) 2010-2013 The PECOS Development Team
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the Version 2.1 GNU Lesser General
// Public License as published by the Free Software Foundation.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc. 51 Franklin Street, Fifth Floor,
// Boston, MA  02110-1301  USA
//
//-----------------------------------------------------------------------el-

// This class
#include "grins/velocity_penalty.h"

// GRINS
#include "grins/generic_ic_handler.h"

// libMesh
#include "libmesh/quadrature.h"
#include "libmesh/boundary_info.h"
#include "libmesh/parsed_function.h"
#include "libmesh/zero_function.h"

namespace GRINS
{

  VelocityPenalty::VelocityPenalty( const std::string& physics_name, const GetPot& input )
    : IncompressibleNavierStokesBase(physics_name, input)
  {
    this->read_input_options(input);

    return;
  }

  VelocityPenalty::~VelocityPenalty()
  {
    return;
  }

  void VelocityPenalty::read_input_options( const GetPot& input )
  {
    std::string penalty_function =
      input("Physics/"+velocity_penalty+"/penalty_function",
        std::string("0"));

    if (penalty_function == "0")
      this->normal_vector_function.reset
        (new libMesh::ZeroFunction<libMesh::Number>());
    else
      this->normal_vector_function.reset
        (new libMesh::ParsedFunction<libMesh::Number>(penalty_function));

    std::string base_function =
      input("Physics/"+velocity_penalty+"/base_velocity",
        std::string("0"));

    if (penalty_function == "0" && base_function == "0")
      std::cout << "Warning! Zero VelocityPenalty specified!" << std::endl;

    if (base_function == "0")
      this->base_velocity_function.reset
        (new libMesh::ZeroFunction<libMesh::Number>());
    else
      this->base_velocity_function.reset
        (new libMesh::ParsedFunction<libMesh::Number>(base_function));

  }

  void VelocityPenalty::element_constraint( bool compute_jacobian,
					    AssemblyContext& context,
					    CachedValues& cache )
  {
#ifdef GRINS_USE_GRVY_TIMERS
    this->_timer->BeginTimer("VelocityPenalty::element_constraint");
#endif

    // Element Jacobian * quadrature weights for interior integration
    const std::vector<libMesh::Real> &JxW =
      context.get_element_fe(this->_flow_vars.u_var())->get_JxW();

    // The shape functions at interior quadrature points.
    const std::vector<std::vector<libMesh::Real> >& u_phi =
      context.get_element_fe(this->_flow_vars.u_var())->get_phi();

    const std::vector<std::vector<libMesh::Real> >& p_phi =
      context.get_element_fe(this->_flow_vars.p_var())->get_phi();

    const std::vector<libMesh::Point>& u_qpoint =
      context.get_element_fe(this->_flow_vars.u_var())->get_xyz();

    // The number of local degrees of freedom in each variable
    const unsigned int n_u_dofs = context.get_dof_indices(_flow_vars.u_var()).size();
    const unsigned int n_p_dofs = context.get_dof_indices(_flow_vars.p_var()).size();

    // The subvectors and submatrices we need to fill:
    libMesh::DenseSubMatrix<libMesh::Number> &Kup = context.get_elem_jacobian(_flow_vars.u_var(), _flow_vars.p_var()); // R_{u},{p}
    libMesh::DenseSubMatrix<libMesh::Number> &Kpu = context.get_elem_jacobian(_flow_vars.p_var(), _flow_vars.u_var()); // R_{p},{u}

    libMesh::DenseSubMatrix<libMesh::Number> &Kvp = context.get_elem_jacobian(_flow_vars.v_var(), _flow_vars.p_var()); // R_{v},{p}
    libMesh::DenseSubMatrix<libMesh::Number> &Kpv = context.get_elem_jacobian(_flow_vars.p_var(), _flow_vars.v_var()); // R_{p},{v}

    libMesh::DenseSubMatrix<libMesh::Number>* Kwp = NULL;
    libMesh::DenseSubMatrix<libMesh::Number>* Kpw = NULL;

    libMesh::DenseSubVector<libMesh::Number> &Fp = context.get_elem_residual(_flow_vars.p_var()); // R_{p}
    libMesh::DenseSubVector<libMesh::Number> &Fu = context.get_elem_residual(_flow_vars.u_var()); // R_{u}
    libMesh::DenseSubVector<libMesh::Number> &Fv = context.get_elem_residual(_flow_vars.v_var()); // R_{v}
    libMesh::DenseSubVector<libMesh::Number>* Fw = NULL;

    if( this->_dim == 3 )
      {
        Kpw = &context.get_elem_jacobian(_flow_vars.p_var(), _flow_vars.w_var()); // R_{p},{w}
        Kwp = &context.get_elem_jacobian(_flow_vars.w_var(), _flow_vars.p_var()); // R_{w},{p}
        Fw  = &context.get_elem_residual(_flow_vars.w_var()); // R_{w}
      }

    unsigned int n_qpoints = context.get_element_qrule().n_points();

    for (unsigned int qp=0; qp != n_qpoints; qp++)
      {
        // Compute the solution & its gradient at the old Newton iterate.
        libMesh::Number p, u, v;
        p = context.interior_value(_flow_vars.p_var(), qp);
        u = context.interior_value(_flow_vars.u_var(), qp);
        v = context.interior_value(_flow_vars.v_var(), qp);

        libMesh::NumberVectorValue U(u,v);
        if (_dim == 3)
          U(2) = context.interior_value(_flow_vars.w_var(), qp); // w

        // Velocity discrepancy (current velocity minus base velocity)
        // normal to constraint plane, scaled by constraint penalty
        // value
        libmesh_assert(normal_vector_function.get());
        libmesh_assert(base_velocity_function.get());

        libMesh::DenseVector<libMesh::Number> output_vec(3);

        (*normal_vector_function)(u_qpoint[qp], context.time,
                                  output_vec);

        libMesh::NumberVectorValue U_N(output_vec(0),
                                       output_vec(1),
                                       output_vec(2));

        (*base_velocity_function)(u_qpoint[qp], context.time,
                                  output_vec);

        libMesh::NumberVectorValue U_B(output_vec(0),
                                       output_vec(1),
                                       output_vec(2));

        libMesh::Real jac = JxW[qp];

        for (unsigned int i=0; i != n_p_dofs; i++)
          {
            Fp(i) += jac *
              (((U-U_B)*U_N)*p_phi[i][qp]);

	    if( compute_jacobian )
              {
                for (unsigned int j=0; j != n_u_dofs; j++)
                  {
                    Kpu(i,j) += jac *
                      ((u_phi[j][qp]*U_N(0))*p_phi[i][qp]);
                    Kpv(i,j) += jac *
                      ((u_phi[j][qp]*U_N(1))*p_phi[i][qp]);

                    if( this->_dim == 3 )
                      {
                        (*Kpw)(i,j) += jac *
                          ((u_phi[j][qp]*U_N(2))*p_phi[i][qp]);
                      }
                  }
              }
          }

        if (true) // make this optional?
          {
            for (unsigned int i=0; i != n_u_dofs; i++)
              {
                Fu(i) += jac *
                  ((u_phi[i][qp]*U_N(0))*p);
                Fv(i) += jac *
                  ((u_phi[i][qp]*U_N(1))*p);
                if( this->_dim == 3 )
                  {
                    (*Fw)(i) += jac *
                      ((u_phi[i][qp]*U_N(2))*p);
                  }

	        if( compute_jacobian )
                  {
                    for (unsigned int j=0; j != n_p_dofs; j++)
                      {
                        Kup(i,j) += jac *
                          ((u_phi[i][qp]*U_N(0))*p_phi[j][qp]);
                        Kvp(i,j) += jac *
                          ((u_phi[i][qp]*U_N(1))*p_phi[j][qp]);

                        if( this->_dim == 3 )
                          {
                            (*Kwp)(i,j) += jac *
                              ((u_phi[i][qp]*U_N(2))*p_phi[j][qp]);
                          }
                      }
                  }
              }
          }
      }

#ifdef GRINS_USE_GRVY_TIMERS
    this->_timer->EndTimer("VelocityPenalty::element_constraint");
#endif

    return;
  }

} // namespace GRINS
<commit_msg>Fix unused variable warning<commit_after>//-----------------------------------------------------------------------bl-
//--------------------------------------------------------------------------
//
// GRINS - General Reacting Incompressible Navier-Stokes
//
// Copyright (C) 2010-2013 The PECOS Development Team
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the Version 2.1 GNU Lesser General
// Public License as published by the Free Software Foundation.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc. 51 Franklin Street, Fifth Floor,
// Boston, MA  02110-1301  USA
//
//-----------------------------------------------------------------------el-

// This class
#include "grins/velocity_penalty.h"

// GRINS
#include "grins/generic_ic_handler.h"

// libMesh
#include "libmesh/quadrature.h"
#include "libmesh/boundary_info.h"
#include "libmesh/parsed_function.h"
#include "libmesh/zero_function.h"

namespace GRINS
{

  VelocityPenalty::VelocityPenalty( const std::string& physics_name, const GetPot& input )
    : IncompressibleNavierStokesBase(physics_name, input)
  {
    this->read_input_options(input);

    return;
  }

  VelocityPenalty::~VelocityPenalty()
  {
    return;
  }

  void VelocityPenalty::read_input_options( const GetPot& input )
  {
    std::string penalty_function =
      input("Physics/"+velocity_penalty+"/penalty_function",
        std::string("0"));

    if (penalty_function == "0")
      this->normal_vector_function.reset
        (new libMesh::ZeroFunction<libMesh::Number>());
    else
      this->normal_vector_function.reset
        (new libMesh::ParsedFunction<libMesh::Number>(penalty_function));

    std::string base_function =
      input("Physics/"+velocity_penalty+"/base_velocity",
        std::string("0"));

    if (penalty_function == "0" && base_function == "0")
      std::cout << "Warning! Zero VelocityPenalty specified!" << std::endl;

    if (base_function == "0")
      this->base_velocity_function.reset
        (new libMesh::ZeroFunction<libMesh::Number>());
    else
      this->base_velocity_function.reset
        (new libMesh::ParsedFunction<libMesh::Number>(base_function));

  }

  void VelocityPenalty::element_constraint( bool compute_jacobian,
					    AssemblyContext& context,
					    CachedValues& /* cache */ )
  {
#ifdef GRINS_USE_GRVY_TIMERS
    this->_timer->BeginTimer("VelocityPenalty::element_constraint");
#endif

    // Element Jacobian * quadrature weights for interior integration
    const std::vector<libMesh::Real> &JxW =
      context.get_element_fe(this->_flow_vars.u_var())->get_JxW();

    // The shape functions at interior quadrature points.
    const std::vector<std::vector<libMesh::Real> >& u_phi =
      context.get_element_fe(this->_flow_vars.u_var())->get_phi();

    const std::vector<std::vector<libMesh::Real> >& p_phi =
      context.get_element_fe(this->_flow_vars.p_var())->get_phi();

    const std::vector<libMesh::Point>& u_qpoint =
      context.get_element_fe(this->_flow_vars.u_var())->get_xyz();

    // The number of local degrees of freedom in each variable
    const unsigned int n_u_dofs = context.get_dof_indices(_flow_vars.u_var()).size();
    const unsigned int n_p_dofs = context.get_dof_indices(_flow_vars.p_var()).size();

    // The subvectors and submatrices we need to fill:
    libMesh::DenseSubMatrix<libMesh::Number> &Kup = context.get_elem_jacobian(_flow_vars.u_var(), _flow_vars.p_var()); // R_{u},{p}
    libMesh::DenseSubMatrix<libMesh::Number> &Kpu = context.get_elem_jacobian(_flow_vars.p_var(), _flow_vars.u_var()); // R_{p},{u}

    libMesh::DenseSubMatrix<libMesh::Number> &Kvp = context.get_elem_jacobian(_flow_vars.v_var(), _flow_vars.p_var()); // R_{v},{p}
    libMesh::DenseSubMatrix<libMesh::Number> &Kpv = context.get_elem_jacobian(_flow_vars.p_var(), _flow_vars.v_var()); // R_{p},{v}

    libMesh::DenseSubMatrix<libMesh::Number>* Kwp = NULL;
    libMesh::DenseSubMatrix<libMesh::Number>* Kpw = NULL;

    libMesh::DenseSubVector<libMesh::Number> &Fp = context.get_elem_residual(_flow_vars.p_var()); // R_{p}
    libMesh::DenseSubVector<libMesh::Number> &Fu = context.get_elem_residual(_flow_vars.u_var()); // R_{u}
    libMesh::DenseSubVector<libMesh::Number> &Fv = context.get_elem_residual(_flow_vars.v_var()); // R_{v}
    libMesh::DenseSubVector<libMesh::Number>* Fw = NULL;

    if( this->_dim == 3 )
      {
        Kpw = &context.get_elem_jacobian(_flow_vars.p_var(), _flow_vars.w_var()); // R_{p},{w}
        Kwp = &context.get_elem_jacobian(_flow_vars.w_var(), _flow_vars.p_var()); // R_{w},{p}
        Fw  = &context.get_elem_residual(_flow_vars.w_var()); // R_{w}
      }

    unsigned int n_qpoints = context.get_element_qrule().n_points();

    for (unsigned int qp=0; qp != n_qpoints; qp++)
      {
        // Compute the solution & its gradient at the old Newton iterate.
        libMesh::Number p, u, v;
        p = context.interior_value(_flow_vars.p_var(), qp);
        u = context.interior_value(_flow_vars.u_var(), qp);
        v = context.interior_value(_flow_vars.v_var(), qp);

        libMesh::NumberVectorValue U(u,v);
        if (_dim == 3)
          U(2) = context.interior_value(_flow_vars.w_var(), qp); // w

        // Velocity discrepancy (current velocity minus base velocity)
        // normal to constraint plane, scaled by constraint penalty
        // value
        libmesh_assert(normal_vector_function.get());
        libmesh_assert(base_velocity_function.get());

        libMesh::DenseVector<libMesh::Number> output_vec(3);

        (*normal_vector_function)(u_qpoint[qp], context.time,
                                  output_vec);

        libMesh::NumberVectorValue U_N(output_vec(0),
                                       output_vec(1),
                                       output_vec(2));

        (*base_velocity_function)(u_qpoint[qp], context.time,
                                  output_vec);

        libMesh::NumberVectorValue U_B(output_vec(0),
                                       output_vec(1),
                                       output_vec(2));

        libMesh::Real jac = JxW[qp];

        for (unsigned int i=0; i != n_p_dofs; i++)
          {
            Fp(i) += jac *
              (((U-U_B)*U_N)*p_phi[i][qp]);

	    if( compute_jacobian )
              {
                for (unsigned int j=0; j != n_u_dofs; j++)
                  {
                    Kpu(i,j) += jac *
                      ((u_phi[j][qp]*U_N(0))*p_phi[i][qp]);
                    Kpv(i,j) += jac *
                      ((u_phi[j][qp]*U_N(1))*p_phi[i][qp]);

                    if( this->_dim == 3 )
                      {
                        (*Kpw)(i,j) += jac *
                          ((u_phi[j][qp]*U_N(2))*p_phi[i][qp]);
                      }
                  }
              }
          }

        if (true) // make this optional?
          {
            for (unsigned int i=0; i != n_u_dofs; i++)
              {
                Fu(i) += jac *
                  ((u_phi[i][qp]*U_N(0))*p);
                Fv(i) += jac *
                  ((u_phi[i][qp]*U_N(1))*p);
                if( this->_dim == 3 )
                  {
                    (*Fw)(i) += jac *
                      ((u_phi[i][qp]*U_N(2))*p);
                  }

	        if( compute_jacobian )
                  {
                    for (unsigned int j=0; j != n_p_dofs; j++)
                      {
                        Kup(i,j) += jac *
                          ((u_phi[i][qp]*U_N(0))*p_phi[j][qp]);
                        Kvp(i,j) += jac *
                          ((u_phi[i][qp]*U_N(1))*p_phi[j][qp]);

                        if( this->_dim == 3 )
                          {
                            (*Kwp)(i,j) += jac *
                              ((u_phi[i][qp]*U_N(2))*p_phi[j][qp]);
                          }
                      }
                  }
              }
          }
      }

#ifdef GRINS_USE_GRVY_TIMERS
    this->_timer->EndTimer("VelocityPenalty::element_constraint");
#endif

    return;
  }

} // namespace GRINS
<|endoftext|>


<commit_before>// Copyright (c) 2014-2019 Crown Core developers
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.

#include "platform/nf-token/nf-token-protocol.h"
#include "platform/nf-token/nft-protocol-reg-tx-builder.h"
#include "platform/nf-token/nft-protocols-manager.h"
#include "primitives/transaction.h"
#include "platform/specialtx.h"
#include "platform/platform-utils.h"
#include "specialtx-rpc-utils.h"
#include "rpc-nft-proto.h"
#include "rpcserver.h"

json_spirit::Value nftproto(const json_spirit::Array& params, bool fHelp)
{
    std::string command = Platform::GetCommand(params, "usage: nftproto register|list|get");

    if (command == "register")
        return Platform::RegisterNftProtocol(params, fHelp);
    else if (command == "list")
        return Platform::ListNftProtocols(params, fHelp);
    else if (command == "get")
        return Platform::GetNftProtocol(params, fHelp);

    throw std::runtime_error("Invalid command: " + command);
}

namespace Platform
{
    json_spirit::Value RegisterNftProtocol(const json_spirit::Array& params, bool fHelp)
    {
        if (params.size() < 4 || params.size() > 10)
            RegisterNftProtocolHelp();

        CKey ownerKey;
        NftProtocolRegTxBuilder txBuilder;
        txBuilder.SetTokenProtocol(params[1]).SetTokenProtocolName(params[2]).SetTokenProtocolOwnerKey(params[3], ownerKey);

        if (params.size() > 4)
            txBuilder.SetNftRegSign(params[4]);
        if (params.size() > 5)
            txBuilder.SetMetadataMimeType(params[5]);
        if (params.size() > 6)
            txBuilder.SetMetadataSchemaUri(params[6]);
        if (params.size() > 7)
            txBuilder.SetIsTokenTransferable(params[7]);
        if (params.size() > 8)
            txBuilder.SetIsTokenImmutable(params[8]);
        if (params.size() > 9)
            txBuilder.SetIsMetadataEmbedded(params[9]);

        auto nftProtoRegTx = txBuilder.BuildTx();

        CMutableTransaction tx;
        tx.nVersion = 3;
        tx.nType = TRANSACTION_NF_TOKEN_PROTOCOL_REGISTER;

        FundSpecialTx(tx, nftProtoRegTx);
        SignSpecialTxPayload(tx, nftProtoRegTx, ownerKey);
        SetTxPayload(tx, nftProtoRegTx);

        std::string result = SignAndSendSpecialTx(tx);
        return result;
    }

    void RegisterNftProtocolHelp()
    {
        static std::string helpMessage =
                R"(nftproto register
Register a new NFT protocol

Arguments:
1. "tokenProtocolId"         (string, required) A non-fungible token protocol ID/symbol
                             NF token protocol unique symbol/identifier, can be an a abbreviated name describing this NF token type.
                             Represented as a base32 string, can only contain characters: .abcdefghijklmnopqrstuvwxyz12345
                             Minimum length 3 symbols, maximum length 12 symbols
2. "tokenProtocolName"       (string, required) Full readable name for this NF token type/protocol.
                             Minimum length 3 symbols, maximum length 24 symbols
3. "tokenProtocolOwnerAddr"  (string, required) The NFT protocol owner address, it can be used to generate new NFTs or update the protocol settings
                             The private key belonging to this address MUST be known to your wallet.
4. "nftRegSign"              (numeric, optional) Defines who must sign an NFT registration transaction.
                             1 (SelfSign): every transaction should be signed by the NFT owner
                             2 (SignByCreator): every transaction should be signed by the owner/creator of the NFT protocol
                             3 (SignPayer): every transaction should be signed by a payer key
                             Default: SignByCreator
5. "tokenMetadataMimeType"   (string, optional) MIME type describing metadata content type
                             Examples: application/json, text/plain, application/octet-stream etc. Default: text/plain
6. "tokenMetadataSchemaUri"  (string, optional) URI to schema (json/xml/binary) describing metadata format.
                             Default: "". Arbitrary data can be written by default.

7. "isTokenTransferable"     (string, optional) Defines if this NF token type can be transferred. Default: true
8. "isTokenImmutable"        (string, optional) Defines if this NF token id can be changed during token lifetime. Default: true
9. "isMetadataEmbedded"      (string, optional) Defines if metadata is embedded or contains a URI
                             It's recommended to use embedded metadata only if it's shorter than the URI. Default: false
Examples:
)"
+ HelpExampleCli("nftproto", R"(register "doc" "Doc Proof" "CRWS78Yf5kbWAyfcES6RfiTVzP87csPNhZzc" 3 "text/plain" "" true true false)")
+ HelpExampleCli("nftproto", R"(register "crd" "Crown ID" "CRWS78Yf5kbWAyfcES6RfiTVzP87csPNhZzc" 1 "application/octet-stream" "https://binary-schema" false true false)")
+ HelpExampleRpc("nftproto", R"(register "doc" "Doc Proof" "CRWS78Yf5kbWAyfcES6RfiTVzP87csPNhZzc" 3 "text/plain" "" true true false)")
+ HelpExampleRpc("nftproto", R"(register "crd" "Crown ID" "CRWS78Yf5kbWAyfcES6RfiTVzP87csPNhZzc" 1 "application/octet-stream" "https://binary-schema" false true false)")
+ HelpExampleRpc("nftproto", R"(register "cks" "ERC721 CryptoKitties" "CRWS78Yf5kbWAyfcES6RfiTVzP87csPNhZzc" 2 "text/plain" "" true true false)");

        throw std::runtime_error(helpMessage);
    }

    json_spirit::Value ListNftProtocols(const json_spirit::Array& params, bool fHelp)
    {
        if (fHelp || params.empty() || params.size() > 5)
            ListNftProtocolsHelp();

        int height = (params.size() > 1) ? ParseInt32V(params[1], "height") : chainActive.Height();
        if (height < 0 || height > chainActive.Height())
            throw JSONRPCError(RPC_INVALID_PARAMETER, "Block height is out of range");

        static const int defaultTxsCount = 20;
        static const int defaultStartFrom = 20;
        int count = (params.size() > 2) ? ParseInt32V(params[2], "count") : defaultTxsCount;
        int startFrom = (params.size() > 3) ? ParseInt32V(params[3], "from") : defaultStartFrom;
        bool regTxOnly = (params.size() > 4) ? ParseBoolV(params[4], "regTxOnly") : false;

        json_spirit::Array protoList;

        auto protoHandler = [&](const NftProtoIndex & protoIndex) -> bool
        {
            if (regTxOnly)
            {
                json_spirit::Object hashObj;
                hashObj.push_back(json_spirit::Pair("registrationTxHash", protoIndex.RegTxHash().GetHex()));
                protoList.push_back(hashObj);
            }
            else
            {
                protoList.push_back(BuildNftProtoRecord(protoIndex));
            }
            return true;
        };

        NftProtocolsManager::Instance().ProcessNftProtoIndexRangeByHeight(protoHandler, height, count, startFrom);
        return protoList;
    }

    void ListNftProtocolsHelp()
    {
        static std::string helpMessage =
                R"(nftproto list
Lists all NFT protocol records on chain

Arguments:
1. height      (numeric, optional) If height is not specified, it defaults to the current chain-tip
2. count       (numeric, optional, default=20) The number of transactions to return
3. from        (numeric, optional, default=0) The number of transactions to skip
4. regTxOnly   (boolean, optional, default=false) false for a detailed list, true for an array of transaction IDs

Examples:
List the most recent 20 NFT protocol records
)"
+ HelpExampleCli("nftproto", R"(list)")
+ R"(List the most recent 20 NFT protocol records up to 5050st block
)"
+ HelpExampleCli("nftproto", R"(list 5050)")
+ R"(List records 100 to 150 up to 5050st block
)"
+ HelpExampleCli("nftproto", R"(list 5050 100 50)")
+ R"(List records 100 to 150 up to 5050st block. List only registration tx IDs.
)"
+ HelpExampleCli("nftoken", R"(list 5050 100 50 true)")
+ R"(As JSON-RPC calls
)"
+ HelpExampleRpc("nftoken", R"(list)")
+ HelpExampleRpc("nftoken", R"(list 5050)")
+ HelpExampleCli("nftoken", R"(list 5050 100 50)");

        throw std::runtime_error(helpMessage);
    }

    json_spirit::Object BuildNftProtoRecord(const NftProtoIndex & nftProtoIndex)
    {
        json_spirit::Object protoJsonObj;

        protoJsonObj.push_back(json_spirit::Pair("blockHash", nftProtoIndex.BlockIndex()->phashBlock->ToString()));
        protoJsonObj.push_back(json_spirit::Pair("registrationTxHash", nftProtoIndex.RegTxHash().ToString()));
        protoJsonObj.push_back(json_spirit::Pair("height", nftProtoIndex.BlockIndex()->nHeight));
        //auto blockTime = static_cast<time_t>(nftProtoIndex.BlockIndex()->nTime);
        //std::string timeStr(asctime(gmtime(&blockTime)));
        //protoJsonObj.push_back(json_spirit::Pair("timestamp", timeStr));
        protoJsonObj.push_back(json_spirit::Pair("timestamp", nftProtoIndex.BlockIndex()->GetBlockTime()));

        protoJsonObj.push_back(json_spirit::Pair("nftProtocolId", ProtocolName{nftProtoIndex.NftProtoPtr()->tokenProtocolId}.ToString()));
        protoJsonObj.push_back(json_spirit::Pair("tokenProtocolName", nftProtoIndex.NftProtoPtr()->tokenProtocolName));
        protoJsonObj.push_back(json_spirit::Pair("tokenMetadataSchemaUri", nftProtoIndex.NftProtoPtr()->tokenMetadataSchemaUri));
        protoJsonObj.push_back(json_spirit::Pair("tokenMetadataMimeType", nftProtoIndex.NftProtoPtr()->tokenMetadataMimeType));
        protoJsonObj.push_back(json_spirit::Pair("isTokenTransferable", nftProtoIndex.NftProtoPtr()->isTokenTransferable));
        protoJsonObj.push_back(json_spirit::Pair("isTokenImmutable", nftProtoIndex.NftProtoPtr()->isTokenImmutable));
        protoJsonObj.push_back(json_spirit::Pair("isMetadataEmbedded", nftProtoIndex.NftProtoPtr()->isMetadataEmbedded));
        protoJsonObj.push_back(json_spirit::Pair("nftRegSign", nftProtoIndex.NftProtoPtr()->nftRegSign));
        protoJsonObj.push_back(json_spirit::Pair("tokenProtocolOwnerId", CBitcoinAddress(nftProtoIndex.NftProtoPtr()->tokenProtocolOwnerId).ToString()));

        return protoJsonObj;
    }

    json_spirit::Value GetNftProtocol(const json_spirit::Array& params, bool fHelp)
    {
        if (fHelp || params.size() != 2)
            GetNftProtocolHelp();

        uint64_t tokenProtocolId = StringToProtocolName(params[1].get_str().c_str());

        auto nftProtoIndex = NftProtocolsManager::Instance().GetNftProtoIndex(tokenProtocolId);
        if (nftProtoIndex.IsNull())
            throw std::runtime_error("Can't find an NFT protocol record: " + params[1].get_str());

        return BuildNftProtoRecord(nftProtoIndex);
    }

    void GetNftProtocolHelp()
    {
        static std::string helpMessage =
                R"(nftproto get
Get an NFT protocol record by an NFT protocol ID
Arguments:

1. "nfTokenProtocol"  (string, required) The non-fungible token protocol symbol of the registered token record
                      The protocol name must be valid and registered previously.
Examples:
)"
+ HelpExampleCli("nftproto", R"(get "doc")")
+ HelpExampleRpc("nftproto", R"(get "cks")");

        throw std::runtime_error(helpMessage);
    }
}<commit_msg>fix rpc nft proto compile error<commit_after>// Copyright (c) 2014-2019 Crown Core developers
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.

#include "platform/nf-token/nf-token-protocol.h"
#include "platform/nf-token/nft-protocol-reg-tx-builder.h"
#include "platform/nf-token/nft-protocols-manager.h"
#include "primitives/transaction.h"
#include "platform/specialtx.h"
#include "platform/platform-utils.h"
#include "specialtx-rpc-utils.h"
#include "rpc-nft-proto.h"
#include "rpcserver.h"

json_spirit::Value nftproto(const json_spirit::Array& params, bool fHelp)
{
    std::string command = Platform::GetCommand(params, "usage: nftproto register|list|get");

    if (command == "register")
        return Platform::RegisterNftProtocol(params, fHelp);
    else if (command == "list")
        return Platform::ListNftProtocols(params, fHelp);
    else if (command == "get")
        return Platform::GetNftProtocol(params, fHelp);

    throw std::runtime_error("Invalid command: " + command);
}

namespace Platform
{
    json_spirit::Object BuildNftProtoRecord(const NftProtoIndex & nftProtoIndex)
    {
        json_spirit::Object protoJsonObj;

        protoJsonObj.push_back(json_spirit::Pair("blockHash", nftProtoIndex.BlockIndex()->phashBlock->ToString()));
        protoJsonObj.push_back(json_spirit::Pair("registrationTxHash", nftProtoIndex.RegTxHash().ToString()));
        protoJsonObj.push_back(json_spirit::Pair("height", nftProtoIndex.BlockIndex()->nHeight));
        //auto blockTime = static_cast<time_t>(nftProtoIndex.BlockIndex()->nTime);
        //std::string timeStr(asctime(gmtime(&blockTime)));
        //protoJsonObj.push_back(json_spirit::Pair("timestamp", timeStr));
        protoJsonObj.push_back(json_spirit::Pair("timestamp", nftProtoIndex.BlockIndex()->GetBlockTime()));

        protoJsonObj.push_back(json_spirit::Pair("nftProtocolId", ProtocolName{nftProtoIndex.NftProtoPtr()->tokenProtocolId}.ToString()));
        protoJsonObj.push_back(json_spirit::Pair("tokenProtocolName", nftProtoIndex.NftProtoPtr()->tokenProtocolName));
        protoJsonObj.push_back(json_spirit::Pair("tokenMetadataSchemaUri", nftProtoIndex.NftProtoPtr()->tokenMetadataSchemaUri));
        protoJsonObj.push_back(json_spirit::Pair("tokenMetadataMimeType", nftProtoIndex.NftProtoPtr()->tokenMetadataMimeType));
        protoJsonObj.push_back(json_spirit::Pair("isTokenTransferable", nftProtoIndex.NftProtoPtr()->isTokenTransferable));
        protoJsonObj.push_back(json_spirit::Pair("isTokenImmutable", nftProtoIndex.NftProtoPtr()->isTokenImmutable));
        protoJsonObj.push_back(json_spirit::Pair("isMetadataEmbedded", nftProtoIndex.NftProtoPtr()->isMetadataEmbedded));
        protoJsonObj.push_back(json_spirit::Pair("nftRegSign", nftProtoIndex.NftProtoPtr()->nftRegSign));
        protoJsonObj.push_back(json_spirit::Pair("tokenProtocolOwnerId", CBitcoinAddress(nftProtoIndex.NftProtoPtr()->tokenProtocolOwnerId).ToString()));

        return protoJsonObj;
    }

    json_spirit::Value RegisterNftProtocol(const json_spirit::Array& params, bool fHelp)
    {
        if (params.size() < 4 || params.size() > 10)
            RegisterNftProtocolHelp();

        CKey ownerKey;
        NftProtocolRegTxBuilder txBuilder;
        txBuilder.SetTokenProtocol(params[1]).SetTokenProtocolName(params[2]).SetTokenProtocolOwnerKey(params[3], ownerKey);

        if (params.size() > 4)
            txBuilder.SetNftRegSign(params[4]);
        if (params.size() > 5)
            txBuilder.SetMetadataMimeType(params[5]);
        if (params.size() > 6)
            txBuilder.SetMetadataSchemaUri(params[6]);
        if (params.size() > 7)
            txBuilder.SetIsTokenTransferable(params[7]);
        if (params.size() > 8)
            txBuilder.SetIsTokenImmutable(params[8]);
        if (params.size() > 9)
            txBuilder.SetIsMetadataEmbedded(params[9]);

        auto nftProtoRegTx = txBuilder.BuildTx();

        CMutableTransaction tx;
        tx.nVersion = 3;
        tx.nType = TRANSACTION_NF_TOKEN_PROTOCOL_REGISTER;

        FundSpecialTx(tx, nftProtoRegTx);
        SignSpecialTxPayload(tx, nftProtoRegTx, ownerKey);
        SetTxPayload(tx, nftProtoRegTx);

        std::string result = SignAndSendSpecialTx(tx);
        return result;
    }

    void RegisterNftProtocolHelp()
    {
        static std::string helpMessage =
                R"(nftproto register
Register a new NFT protocol

Arguments:
1. "tokenProtocolId"         (string, required) A non-fungible token protocol ID/symbol
                             NF token protocol unique symbol/identifier, can be an a abbreviated name describing this NF token type.
                             Represented as a base32 string, can only contain characters: .abcdefghijklmnopqrstuvwxyz12345
                             Minimum length 3 symbols, maximum length 12 symbols
2. "tokenProtocolName"       (string, required) Full readable name for this NF token type/protocol.
                             Minimum length 3 symbols, maximum length 24 symbols
3. "tokenProtocolOwnerAddr"  (string, required) The NFT protocol owner address, it can be used to generate new NFTs or update the protocol settings
                             The private key belonging to this address MUST be known to your wallet.
4. "nftRegSign"              (numeric, optional) Defines who must sign an NFT registration transaction.
                             1 (SelfSign): every transaction should be signed by the NFT owner
                             2 (SignByCreator): every transaction should be signed by the owner/creator of the NFT protocol
                             3 (SignPayer): every transaction should be signed by a payer key
                             Default: SignByCreator
5. "tokenMetadataMimeType"   (string, optional) MIME type describing metadata content type
                             Examples: application/json, text/plain, application/octet-stream etc. Default: text/plain
6. "tokenMetadataSchemaUri"  (string, optional) URI to schema (json/xml/binary) describing metadata format.
                             Default: "". Arbitrary data can be written by default.

7. "isTokenTransferable"     (string, optional) Defines if this NF token type can be transferred. Default: true
8. "isTokenImmutable"        (string, optional) Defines if this NF token id can be changed during token lifetime. Default: true
9. "isMetadataEmbedded"      (string, optional) Defines if metadata is embedded or contains a URI
                             It's recommended to use embedded metadata only if it's shorter than the URI. Default: false
Examples:
)"
+ HelpExampleCli("nftproto", R"(register "doc" "Doc Proof" "CRWS78Yf5kbWAyfcES6RfiTVzP87csPNhZzc" 3 "text/plain" "" true true false)")
+ HelpExampleCli("nftproto", R"(register "crd" "Crown ID" "CRWS78Yf5kbWAyfcES6RfiTVzP87csPNhZzc" 1 "application/octet-stream" "https://binary-schema" false true false)")
+ HelpExampleRpc("nftproto", R"(register "doc" "Doc Proof" "CRWS78Yf5kbWAyfcES6RfiTVzP87csPNhZzc" 3 "text/plain" "" true true false)")
+ HelpExampleRpc("nftproto", R"(register "crd" "Crown ID" "CRWS78Yf5kbWAyfcES6RfiTVzP87csPNhZzc" 1 "application/octet-stream" "https://binary-schema" false true false)")
+ HelpExampleRpc("nftproto", R"(register "cks" "ERC721 CryptoKitties" "CRWS78Yf5kbWAyfcES6RfiTVzP87csPNhZzc" 2 "text/plain" "" true true false)");

        throw std::runtime_error(helpMessage);
    }

    json_spirit::Value ListNftProtocols(const json_spirit::Array& params, bool fHelp)
    {
        if (fHelp || params.empty() || params.size() > 5)
            ListNftProtocolsHelp();

        int height = (params.size() > 1) ? ParseInt32V(params[1], "height") : chainActive.Height();
        if (height < 0 || height > chainActive.Height())
            throw JSONRPCError(RPC_INVALID_PARAMETER, "Block height is out of range");

        static const int defaultTxsCount = 20;
        static const int defaultStartFrom = 20;
        int count = (params.size() > 2) ? ParseInt32V(params[2], "count") : defaultTxsCount;
        int startFrom = (params.size() > 3) ? ParseInt32V(params[3], "from") : defaultStartFrom;
        bool regTxOnly = (params.size() > 4) ? ParseBoolV(params[4], "regTxOnly") : false;

        json_spirit::Array protoList;

        auto protoHandler = [&](const NftProtoIndex & protoIndex) -> bool
        {
            if (regTxOnly)
            {
                json_spirit::Object hashObj;
                hashObj.push_back(json_spirit::Pair("registrationTxHash", protoIndex.RegTxHash().GetHex()));
                protoList.push_back(hashObj);
            }
            else
            {
                protoList.push_back(BuildNftProtoRecord(protoIndex));
            }
            return true;
        };

        NftProtocolsManager::Instance().ProcessNftProtoIndexRangeByHeight(protoHandler, height, count, startFrom);
        return protoList;
    }

    void ListNftProtocolsHelp()
    {
        static std::string helpMessage =
                R"(nftproto list
Lists all NFT protocol records on chain

Arguments:
1. height      (numeric, optional) If height is not specified, it defaults to the current chain-tip
2. count       (numeric, optional, default=20) The number of transactions to return
3. from        (numeric, optional, default=0) The number of transactions to skip
4. regTxOnly   (boolean, optional, default=false) false for a detailed list, true for an array of transaction IDs

Examples:
List the most recent 20 NFT protocol records
)"
+ HelpExampleCli("nftproto", R"(list)")
+ R"(List the most recent 20 NFT protocol records up to 5050st block
)"
+ HelpExampleCli("nftproto", R"(list 5050)")
+ R"(List records 100 to 150 up to 5050st block
)"
+ HelpExampleCli("nftproto", R"(list 5050 100 50)")
+ R"(List records 100 to 150 up to 5050st block. List only registration tx IDs.
)"
+ HelpExampleCli("nftoken", R"(list 5050 100 50 true)")
+ R"(As JSON-RPC calls
)"
+ HelpExampleRpc("nftoken", R"(list)")
+ HelpExampleRpc("nftoken", R"(list 5050)")
+ HelpExampleCli("nftoken", R"(list 5050 100 50)");

        throw std::runtime_error(helpMessage);
    }

    json_spirit::Value GetNftProtocol(const json_spirit::Array& params, bool fHelp)
    {
        if (fHelp || params.size() != 2)
            GetNftProtocolHelp();

        uint64_t tokenProtocolId = StringToProtocolName(params[1].get_str().c_str());

        auto nftProtoIndex = NftProtocolsManager::Instance().GetNftProtoIndex(tokenProtocolId);
        if (nftProtoIndex.IsNull())
            throw std::runtime_error("Can't find an NFT protocol record: " + params[1].get_str());

        return BuildNftProtoRecord(nftProtoIndex);
    }

    void GetNftProtocolHelp()
    {
        static std::string helpMessage =
                R"(nftproto get
Get an NFT protocol record by an NFT protocol ID
Arguments:

1. "nfTokenProtocol"  (string, required) The non-fungible token protocol symbol of the registered token record
                      The protocol name must be valid and registered previously.
Examples:
)"
+ HelpExampleCli("nftproto", R"(get "doc")")
+ HelpExampleRpc("nftproto", R"(get "cks")");

        throw std::runtime_error(helpMessage);
    }
}<|endoftext|>


<commit_before>/** \file
 * \brief Morphology Operations for Gray Images
 *
 * See Copyright Notice in im_lib.h
 */

#include <im.h>
#include <im_util.h>
#include <im_convert.h>

#include "im_process_counter.h"
#include "im_process_loc.h"
#include "im_process_pnt.h"

#include <stdlib.h>
#include <stdio.h>
#include <memory.h>
#include <string.h>
#include <math.h>

template <class T, class DT>
static int DoGrayMorphConvolve(T *map, T* new_map, int width, int height, const imImage* kernel, int counter, int ismax, DT)
{
  int kw = kernel->width;
  int kh2 = kernel->height/2;
  int kw2 = kernel->width/2;

  DT* kernel_data = (DT*)kernel->data[0];

  IM_INT_PROCESSING;

#pragma omp parallel for if (IM_OMP_MINHEIGHT(height))
  for(int j = 0; j < height; j++)
  {
    #pragma omp flush (processing)
    IM_BEGIN_PROCESSING;

    int new_offset = j * width;

    for(int i = 0; i < width; i++)
    {
      DT value, max = 0, min = 0;
      int init = 0;

      for(int y = -kh2; y <= kh2; y++)
      {
        int line_offset;
        DT* kernel_line = kernel_data + (y+kh2)*kw;

        if ((j + y < 0) ||          // pass the bottom border
            (j + y >= height))      // pass the top border
          continue;
        else
          line_offset = (j + y) * width;

        for(int x = -kw2; x <= kw2; x++)
        {
          if (kernel_line[x+kw2] != -1)
          {
            if ((i + x < 0) ||      // pass the left border
                (i + x >= width))   // pass the right border
              continue;
            else
              value = kernel_line[x+kw2] + map[line_offset + (i + x)];

            if (init == 0)  // first time here for each pass
            {
              if (ismax)
                max = value;
              else
                min = value;

              init = 1;
            }
            else
            {
              if (ismax && value > max)
                max = value;

              if (!ismax && value < min)
                min = value;
            }
          }
        }
      }

      int size_of = sizeof(imbyte);
      if (sizeof(T) == size_of)
      {
        if (ismax)
          new_map[new_offset + i] = (T)IM_BYTECROP(max);
        else
          new_map[new_offset + i] = (T)IM_BYTECROP(min);
      }
      else
      {
        if (ismax)
          new_map[new_offset + i] = (T)max;
        else
          new_map[new_offset + i] = (T)min;
      }
    }

    IM_COUNT_PROCESSING;
    #pragma omp flush (processing)
    IM_END_PROCESSING;
  }

  return processing;
}

int imProcessGrayMorphConvolve(const imImage* src_image, imImage* dst_image, const imImage *kernel, int ismax)
{
  int ret = 0;

  int counter = imProcessCounterBegin("Gray Morphological Convolution");
  const char* msg = (const char*)imImageGetAttribute(kernel, "Description", NULL, NULL);
  if (!msg) msg = "Processing...";
  imCounterTotal(counter, src_image->depth*src_image->height, msg);

  imImage* fkernel = NULL;

  if (src_image->data_type == IM_FLOAT && kernel->data_type != IM_FLOAT)
  {
    fkernel = imImageCreate(kernel->width, kernel->height, IM_GRAY, IM_FLOAT);
    imConvertDataType(kernel, fkernel, 0, 0, 0, IM_CAST_DIRECT);
    kernel = fkernel;
  }

  for (int i = 0; i < src_image->depth; i++)
  {
    switch(src_image->data_type)
    {
    case IM_BYTE:
      ret = DoGrayMorphConvolve((imbyte*)src_image->data[i], (imbyte*)dst_image->data[i], src_image->width, src_image->height, kernel, counter, ismax, (int)0);
      break;
    case IM_USHORT:
      ret = DoGrayMorphConvolve((imushort*)src_image->data[i], (imushort*)dst_image->data[i], src_image->width, src_image->height, kernel, counter, ismax, (int)0);
      break;
    case IM_INT:
      ret = DoGrayMorphConvolve((int*)src_image->data[i], (int*)dst_image->data[i], src_image->width, src_image->height, kernel, counter, ismax, (int)0);
      break;
    case IM_FLOAT:
      ret = DoGrayMorphConvolve((float*)src_image->data[i], (float*)dst_image->data[i], src_image->width, src_image->height, kernel, counter, ismax, (float)0);
      break;
    }

    if (!ret)
      break;
  }

  if (fkernel) imImageDestroy(fkernel);
  imProcessCounterEnd(counter);

  return ret;
}

int imProcessGrayMorphErode(const imImage* src_image, imImage* dst_image, int kernel_size)
{
  imImage* kernel = imImageCreate(kernel_size, kernel_size, IM_GRAY, IM_INT);
  imImageSetAttribute(kernel, "Description", IM_BYTE, -1, (void*)"Erode");
  // Kernel is all zeros
  int ret = imProcessGrayMorphConvolve(src_image, dst_image, kernel, 0);
  imImageDestroy(kernel);
  return ret;
}

int imProcessGrayMorphDilate(const imImage* src_image, imImage* dst_image, int kernel_size)
{
  imImage* kernel = imImageCreate(kernel_size, kernel_size, IM_GRAY, IM_INT);
  imImageSetAttribute(kernel, "Description", IM_BYTE, -1, (void*)"Dilate");
  // Kernel is all zeros
  int ret = imProcessGrayMorphConvolve(src_image, dst_image, kernel, 1);
  imImageDestroy(kernel);
  return ret;
}

int imProcessGrayMorphOpen(const imImage* src_image, imImage* dst_image, int kernel_size)
{
  imImage*temp = imImageClone(src_image);
  if (!temp)
    return 0;

  if (!imProcessGrayMorphErode(src_image, temp, kernel_size))
    {imImageDestroy(temp); return 0;}
  if (!imProcessGrayMorphDilate(temp, dst_image, kernel_size))
    {imImageDestroy(temp); return 0;}

  imImageDestroy(temp);
  return 1;
}

int imProcessGrayMorphClose(const imImage* src_image, imImage* dst_image, int kernel_size)
{
  imImage*temp = imImageClone(src_image);
  if (!temp)
    return 0;

  if (!imProcessGrayMorphDilate(src_image, temp, kernel_size))
    {imImageDestroy(temp); return 0;}
  if (!imProcessGrayMorphErode(temp, dst_image, kernel_size))
    {imImageDestroy(temp); return 0;}

  imImageDestroy(temp);
  return 1;
}

int imProcessGrayMorphTopHat(const imImage* src_image, imImage* dst_image, int kernel_size)
{
  if (!imProcessGrayMorphOpen(src_image, dst_image, kernel_size))
    return 0;
  imProcessArithmeticOp(src_image, dst_image, dst_image, IM_BIN_DIFF);
  return 1;
}

int imProcessGrayMorphWell(const imImage* src_image, imImage* dst_image, int kernel_size)
{
  if (!imProcessGrayMorphClose(src_image, dst_image, kernel_size))
    return 0;
  imProcessArithmeticOp(src_image, dst_image, dst_image, IM_BIN_DIFF);
  return 1;
}

int imProcessGrayMorphGradient(const imImage* src_image, imImage* dst_image, int kernel_size)
{
  imImage*temp = imImageClone(src_image);
  if (!temp)
    return 0;

  if (!imProcessGrayMorphDilate(src_image, temp, kernel_size))
    {imImageDestroy(temp); return 0;}
  if (!imProcessGrayMorphErode(src_image, dst_image, kernel_size))
    {imImageDestroy(temp); return 0;}

  imProcessArithmeticOp(temp, dst_image, dst_image, IM_BIN_DIFF);

  imImageDestroy(temp);
  return 1;
}

<commit_msg>*** empty log message ***<commit_after>/** \file
 * \brief Morphology Operations for Gray Images
 *
 * See Copyright Notice in im_lib.h
 */

#include <im.h>
#include <im_util.h>
#include <im_convert.h>

#include "im_process_counter.h"
#include "im_process_loc.h"
#include "im_process_pnt.h"

#include <stdlib.h>
#include <stdio.h>
#include <memory.h>
#include <string.h>
#include <math.h>

template <class T, class DT>
static int DoGrayMorphConvolve(T *map, T* new_map, int width, int height, const imImage* kernel, int counter, int ismax, DT)
{
  int kw = kernel->width;
  int kh2 = kernel->height/2;
  int kw2 = kernel->width/2;

  DT* kernel_data = (DT*)kernel->data[0];

  IM_INT_PROCESSING;

#pragma omp parallel for if (IM_OMP_MINHEIGHT(height))
  for(int j = 0; j < height; j++)
  {
    #pragma omp flush (processing)
    IM_BEGIN_PROCESSING;

    int new_offset = j * width;

    for(int i = 0; i < width; i++)
    {
      DT value, max = 0, min = 0;
      int init = 0;

      for(int y = -kh2; y <= kh2; y++)
      {
        int line_offset;
        DT* kernel_line = kernel_data + (y+kh2)*kw;

        if ((j + y < 0) ||          // pass the bottom border
            (j + y >= height))      // pass the top border
          continue;
        else
          line_offset = (j + y) * width;

        for(int x = -kw2; x <= kw2; x++)
        {
          if (kernel_line[x+kw2] != -1)
          {
            if ((i + x < 0) ||      // pass the left border
                (i + x >= width))   // pass the right border
              continue;
            else
              value = kernel_line[x+kw2] + map[line_offset + (i + x)];

            if (init == 0)  // first time here for each pass
            {
              if (ismax)
                max = value;
              else
                min = value;

              init = 1;
            }
            else
            {
              if (ismax && value > max)
                max = value;

              if (!ismax && value < min)
                min = value;
            }
          }
        }
      }

      int size_of = sizeof(imbyte);
      if (sizeof(T) == size_of)
      {
        if (ismax)
          new_map[new_offset + i] = (T)IM_BYTECROP(max);
        else
          new_map[new_offset + i] = (T)IM_BYTECROP(min);
      }
      else
      {
        if (ismax)
          new_map[new_offset + i] = (T)max;
        else
          new_map[new_offset + i] = (T)min;
      }
    }

    IM_COUNT_PROCESSING;
    #pragma omp flush (processing)
    IM_END_PROCESSING;
  }

  return processing;
}

int imProcessGrayMorphConvolve(const imImage* src_image, imImage* dst_image, const imImage *kernel, int ismax)
{
  int ret = 0;

  int counter = imProcessCounterBegin("Gray Morphological Convolution");
  const char* msg = (const char*)imImageGetAttribute(kernel, "Description", NULL, NULL);
  if (!msg) msg = "Processing...";
  imCounterTotal(counter, src_image->depth*src_image->height, msg);

  imImage* fkernel = NULL;

  if (src_image->data_type == IM_FLOAT && kernel->data_type != IM_FLOAT)
  {
    fkernel = imImageCreate(kernel->width, kernel->height, IM_GRAY, IM_FLOAT);
    imProcessConvertDataType(kernel, fkernel, 0, 0, 0, IM_CAST_DIRECT);
    kernel = fkernel;
  }

  for (int i = 0; i < src_image->depth; i++)
  {
    switch(src_image->data_type)
    {
    case IM_BYTE:
      ret = DoGrayMorphConvolve((imbyte*)src_image->data[i], (imbyte*)dst_image->data[i], src_image->width, src_image->height, kernel, counter, ismax, (int)0);
      break;
    case IM_USHORT:
      ret = DoGrayMorphConvolve((imushort*)src_image->data[i], (imushort*)dst_image->data[i], src_image->width, src_image->height, kernel, counter, ismax, (int)0);
      break;
    case IM_INT:
      ret = DoGrayMorphConvolve((int*)src_image->data[i], (int*)dst_image->data[i], src_image->width, src_image->height, kernel, counter, ismax, (int)0);
      break;
    case IM_FLOAT:
      ret = DoGrayMorphConvolve((float*)src_image->data[i], (float*)dst_image->data[i], src_image->width, src_image->height, kernel, counter, ismax, (float)0);
      break;
    }

    if (!ret)
      break;
  }

  if (fkernel) imImageDestroy(fkernel);
  imProcessCounterEnd(counter);

  return ret;
}

int imProcessGrayMorphErode(const imImage* src_image, imImage* dst_image, int kernel_size)
{
  imImage* kernel = imImageCreate(kernel_size, kernel_size, IM_GRAY, IM_INT);
  imImageSetAttribute(kernel, "Description", IM_BYTE, -1, (void*)"Erode");
  // Kernel is all zeros
  int ret = imProcessGrayMorphConvolve(src_image, dst_image, kernel, 0);
  imImageDestroy(kernel);
  return ret;
}

int imProcessGrayMorphDilate(const imImage* src_image, imImage* dst_image, int kernel_size)
{
  imImage* kernel = imImageCreate(kernel_size, kernel_size, IM_GRAY, IM_INT);
  imImageSetAttribute(kernel, "Description", IM_BYTE, -1, (void*)"Dilate");
  // Kernel is all zeros
  int ret = imProcessGrayMorphConvolve(src_image, dst_image, kernel, 1);
  imImageDestroy(kernel);
  return ret;
}

int imProcessGrayMorphOpen(const imImage* src_image, imImage* dst_image, int kernel_size)
{
  imImage*temp = imImageClone(src_image);
  if (!temp)
    return 0;

  if (!imProcessGrayMorphErode(src_image, temp, kernel_size))
    {imImageDestroy(temp); return 0;}
  if (!imProcessGrayMorphDilate(temp, dst_image, kernel_size))
    {imImageDestroy(temp); return 0;}

  imImageDestroy(temp);
  return 1;
}

int imProcessGrayMorphClose(const imImage* src_image, imImage* dst_image, int kernel_size)
{
  imImage*temp = imImageClone(src_image);
  if (!temp)
    return 0;

  if (!imProcessGrayMorphDilate(src_image, temp, kernel_size))
    {imImageDestroy(temp); return 0;}
  if (!imProcessGrayMorphErode(temp, dst_image, kernel_size))
    {imImageDestroy(temp); return 0;}

  imImageDestroy(temp);
  return 1;
}

int imProcessGrayMorphTopHat(const imImage* src_image, imImage* dst_image, int kernel_size)
{
  if (!imProcessGrayMorphOpen(src_image, dst_image, kernel_size))
    return 0;
  imProcessArithmeticOp(src_image, dst_image, dst_image, IM_BIN_DIFF);
  return 1;
}

int imProcessGrayMorphWell(const imImage* src_image, imImage* dst_image, int kernel_size)
{
  if (!imProcessGrayMorphClose(src_image, dst_image, kernel_size))
    return 0;
  imProcessArithmeticOp(src_image, dst_image, dst_image, IM_BIN_DIFF);
  return 1;
}

int imProcessGrayMorphGradient(const imImage* src_image, imImage* dst_image, int kernel_size)
{
  imImage*temp = imImageClone(src_image);
  if (!temp)
    return 0;

  if (!imProcessGrayMorphDilate(src_image, temp, kernel_size))
    {imImageDestroy(temp); return 0;}
  if (!imProcessGrayMorphErode(src_image, dst_image, kernel_size))
    {imImageDestroy(temp); return 0;}

  imProcessArithmeticOp(temp, dst_image, dst_image, IM_BIN_DIFF);

  imImageDestroy(temp);
  return 1;
}

<|endoftext|>


<commit_before>/**
 * projectM -- Milkdrop-esque visualisation SDK
 * Copyright (C)2003-2007 projectM Team
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 * See 'LICENSE.txt' included within this release
 *
 */
/**
 * $Id$
 *
 * Encapsulation of a custom wave
 *
 * $Log$
 */

#ifndef _CUSTOM_WAVE_H
#define _CUSTOM_WAVE_H

#define CUSTOM_WAVE_DEBUG 0

#define X_POINT_OP 0
#define Y_POINT_OP 1
#define R_POINT_OP 2
#define G_POINT_OP 3
#define B_POINT_OP 4
#define A_POINT_OP 5
#define NUM_POINT_OPS 6

class CustomWave;
class GenExpr;
class PerPointEqn;
class Preset;

#include "Common.hpp"
#include "Param.hpp"
#include "PerFrameEqn.hpp"

#include <map>

class CustomWave {
public:

     /** Empty constructor leaves wave in undefined state **/
     CustomWave() {}

     /** Initializes a custom wave id given the integer id */
     CustomWave(int id);

    /** Destructor is necessary so we can free the per point matrices **/
    ~CustomWave();

    /* Numerical id */
    int id;
    int per_frame_count;

    /* Parameter tree associated with this custom wave */
    std::map<std::string,Param*> param_tree;

    /* Engine variables */
    float x; /* x position for per point equations */
    float y; /* y position for per point equations */
    float r; /* red color value */
    float g; /* green color value */
    float b; /* blue color value */
    float a; /* alpha color value */
    float * x_mesh;
    float * y_mesh;
    float * r_mesh;
    float * b_mesh;
    float * g_mesh;
    float * a_mesh;
    float * value1;
    float * value2;
    float * sample_mesh;

    bool enabled; /* if nonzero then wave is visible, hidden otherwise */
    int samples; /* number of samples associated with this wave form. Usually powers of 2 */
    float sample;
    bool bSpectrum; /* spectrum data or pcm data */
    bool bUseDots; /* draw wave as dots or lines */
    bool bDrawThick; /* draw thicker lines */
    bool bAdditive; /* add color values together */

    float scaling; /* scale factor of waveform */
    float smoothing; /* smooth factor of waveform */
    int sep;  /* no idea what this is yet... */

    /* stupid t variables */
    float t1;
    float t2;
    float t3;
    float t4;
    float t5;
    float t6;
    float t7;
    float t8;

    /* stupider q variables */
    float q1;
    float q2;
    float q3;
    float q4;
    float q5;
    float q6;
    float q7;
    float q8;

    float v1,v2;

    /* Data structures to hold per frame and per point equations */
    std::map<std::string,InitCond*>  init_cond_tree;
    std::map<int, PerFrameEqn*>  per_frame_eqn_tree;
    std::map<int, PerPointEqn*>  per_point_eqn_tree;
    std::map<std::string,InitCond*>  per_frame_init_eqn_tree;

    /* Denotes the index of the last character for each string buffer */
    int per_point_eqn_string_index;
    int per_frame_eqn_string_index;
    int per_frame_init_eqn_string_index;

    /* String buffers for per point and per frame equations */
    char per_point_eqn_string_buffer[STRING_BUFFER_SIZE];
    char per_frame_eqn_string_buffer[STRING_BUFFER_SIZE];
    char per_frame_init_eqn_string_buffer[STRING_BUFFER_SIZE];

    int add_per_point_eqn(char * name, GenExpr * gen_expr);
    void evalCustomWaveInitConditions(Preset *preset);
    void evalPerPointEqns();

    void loadUnspecInitConds();

    void evalInitConds();

};

#endif /** !_CUSTOM_WAVE_H */
<commit_msg>removed unnecessary defines in custom wave code<commit_after>/**
 * projectM -- Milkdrop-esque visualisation SDK
 * Copyright (C)2003-2007 projectM Team
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 * See 'LICENSE.txt' included within this release
 *
 */
/**
 * $Id$
 *
 * Encapsulation of a custom wave
 *
 * $Log$
 */

#ifndef _CUSTOM_WAVE_H
#define _CUSTOM_WAVE_H

#define CUSTOM_WAVE_DEBUG 0

class CustomWave;
class GenExpr;
class PerPointEqn;
class Preset;

#include "Common.hpp"
#include "Param.hpp"
#include "PerFrameEqn.hpp"

#include <map>

class CustomWave {
public:

     /** Empty constructor leaves wave in undefined state **/
     CustomWave() {}

     /** Initializes a custom wave id given the integer id */
     CustomWave(int id);

    /** Destructor is necessary so we can free the per point matrices **/
    ~CustomWave();

    /* Numerical id */
    int id;
    int per_frame_count;

    /* Parameter tree associated with this custom wave */
    std::map<std::string,Param*> param_tree;

    /* Engine variables */
    float x; /* x position for per point equations */
    float y; /* y position for per point equations */
    float r; /* red color value */
    float g; /* green color value */
    float b; /* blue color value */
    float a; /* alpha color value */
    float * x_mesh;
    float * y_mesh;
    float * r_mesh;
    float * b_mesh;
    float * g_mesh;
    float * a_mesh;
    float * value1;
    float * value2;
    float * sample_mesh;

    bool enabled; /* if nonzero then wave is visible, hidden otherwise */
    int samples; /* number of samples associated with this wave form. Usually powers of 2 */
    float sample;
    bool bSpectrum; /* spectrum data or pcm data */
    bool bUseDots; /* draw wave as dots or lines */
    bool bDrawThick; /* draw thicker lines */
    bool bAdditive; /* add color values together */

    float scaling; /* scale factor of waveform */
    float smoothing; /* smooth factor of waveform */
    int sep;  /* no idea what this is yet... */

    /* stupid t variables */
    float t1;
    float t2;
    float t3;
    float t4;
    float t5;
    float t6;
    float t7;
    float t8;

    /* stupider q variables */
    float q1;
    float q2;
    float q3;
    float q4;
    float q5;
    float q6;
    float q7;
    float q8;

    float v1,v2;

    /* Data structures to hold per frame and per point equations */
    std::map<std::string,InitCond*>  init_cond_tree;
    std::map<int, PerFrameEqn*>  per_frame_eqn_tree;
    std::map<int, PerPointEqn*>  per_point_eqn_tree;
    std::map<std::string,InitCond*>  per_frame_init_eqn_tree;

    /* Denotes the index of the last character for each string buffer */
    int per_point_eqn_string_index;
    int per_frame_eqn_string_index;
    int per_frame_init_eqn_string_index;

    /* String buffers for per point and per frame equations */
    char per_point_eqn_string_buffer[STRING_BUFFER_SIZE];
    char per_frame_eqn_string_buffer[STRING_BUFFER_SIZE];
    char per_frame_init_eqn_string_buffer[STRING_BUFFER_SIZE];

    int add_per_point_eqn(char * name, GenExpr * gen_expr);
    void evalCustomWaveInitConditions(Preset *preset);
    void evalPerPointEqns();

    void loadUnspecInitConds();

    void evalInitConds();

};

#endif /** !_CUSTOM_WAVE_H */
<|endoftext|>