<commit_before>#include "Player.h"

#include <QDebug>

#include "Channel/Channel.h"

Player::Player(QObject *parent) :
    QObject(parent),
    m_channel(NULL)
{
}

void Player::play(Channel *channel)
{
    setChannel(channel);
    setIsPlaying(true);
    emit playStarted();
}

void Player::play()
{
    if (!hasCurrentChannel()) return;
    setIsPlaying(true);
    emit playStarted();
}

void Player::pause()
{
    if (!hasCurrentChannel()) return;
    setIsPlaying(false);
    emit pauseStarted();
}

bool Player::isPlaying(QString id)
{
    return isPlaying() && channelId() == id;
}

QString Player::channelId()
{
    if (!hasCurrentChannel()) return "";

    return channel()->data(Channel::IdRole).toString();
}

QString Player::channelName()
{
    if (!hasCurrentChannel()) return "";

    return channel()->data(Channel::NameRole).toString();
}

QString Player::channelImageUrl()
{
    if (!hasCurrentChannel()) return "";

    return channel()->data(Channel::ImageUrlRole).toString();
}

QString Player::channelImageMediumUrl()
{
    if (!hasCurrentChannel()) return "";

    return channel()->data(Channel::ImageMediumUrlRole).toString();
}

bool Player::hasCurrentChannel()
{
    return m_channel != NULL;
}
<commit_msg>some channels have no medium image (for the cover)<commit_after>#include "Player.h"

#include <QDebug>

#include "Channel/Channel.h"

Player::Player(QObject *parent) :
    QObject(parent),
    m_channel(NULL)
{
}

void Player::play(Channel *channel)
{
    setChannel(channel);
    setIsPlaying(true);
    emit playStarted();
}

void Player::play()
{
    if (!hasCurrentChannel()) return;
    setIsPlaying(true);
    emit playStarted();
}

void Player::pause()
{
    if (!hasCurrentChannel()) return;
    setIsPlaying(false);
    emit pauseStarted();
}

bool Player::isPlaying(QString id)
{
    return isPlaying() && channelId() == id;
}

QString Player::channelId()
{
    if (!hasCurrentChannel()) return "";

    return channel()->data(Channel::IdRole).toString();
}

QString Player::channelName()
{
    if (!hasCurrentChannel()) return "";

    return channel()->data(Channel::NameRole).toString();
}

QString Player::channelImageUrl()
{
    if (!hasCurrentChannel()) return "";

    return channel()->data(Channel::ImageUrlRole).toString();
}

QString Player::channelImageMediumUrl()
{
    if (!hasCurrentChannel()) return "";

    QString imageMediumUrl = channel()->data(Channel::ImageMediumUrlRole).toString();

    if (imageMediumUrl.isEmpty())
        return channel()->data(Channel::ImageBigUrlRole).toString();

    return imageMediumUrl;
}

bool Player::hasCurrentChannel()
{
    return m_channel != NULL;
}
<|endoftext|>


<commit_before>#include <iostream> // debug output
#include <codecvt> // debug output
#include <locale> // debug output
#include "gvfsdlg.h"
#include "LngStringIDs.h"
#include "Plugin.h"

Plugin& Plugin::getInstance()
{
    static Plugin instance;
    return instance;
}

Plugin::Plugin()
{
    Opt.AddToDisksMenu = true;
    Opt.AddToPluginsMenu = true;
//    m_keyBar.setNormalKey(7, L"MkMount");
//    m_keyBar.setNormalKey(4, L"EdMount");
}

Plugin::~Plugin()
{
    clearPanelItems();
}

int Plugin::getVersion()
{
    return 1;
}

void Plugin::setStartupInfo(const PluginStartupInfo *psi)
{
    this->m_pPsi = *psi;
}

void Plugin::exitFar()
{
    // unmount all VFS, mounted in current session
    for (auto& mntPoint : m_mountPoints)
    {
        if (mntPoint.second.isMounted())
            try
            {
                mntPoint.second.unmount();
            }
            catch (const GvfsServiceException& error)
            {
                // ignore error here
            }
    }
}

void Plugin::getPluginInfo(PluginInfo *info)
{

    info->StructSize = sizeof(*info);
    info->Flags = PF_PRELOAD;

    static const wchar_t *DiskMenuStrings[1];
    DiskMenuStrings[0] = m_pPsi.GetMsg(m_pPsi.ModuleNumber, MDiskMenuString);
    info->DiskMenuStrings = DiskMenuStrings;
    info->DiskMenuStringsNumber = Opt.AddToDisksMenu ? ARRAYSIZE(DiskMenuStrings) : 0;

    static const wchar_t *PluginMenuStrings[1];
    PluginMenuStrings[0] = m_pPsi.GetMsg(m_pPsi.ModuleNumber, MGvfsPanel);
    info->PluginMenuStrings = Opt.AddToPluginsMenu ? PluginMenuStrings : NULL;
    info->PluginMenuStringsNumber = Opt.AddToPluginsMenu ? ARRAYSIZE(PluginMenuStrings) : 0;

    static const wchar_t *PluginCfgStrings[1];
    PluginCfgStrings[0] = m_pPsi.GetMsg(m_pPsi.ModuleNumber, MGvfsPanel);
    info->PluginConfigStrings = PluginCfgStrings;
    info->PluginConfigStringsNumber = ARRAYSIZE(PluginCfgStrings);
    info->CommandPrefix = Opt.Prefix;
}

int Plugin::configure(int item)
{
  (void)item;
  return FALSE;
}

HANDLE Plugin::openPlugin(int openFrom, intptr_t item)
{
    return static_cast<HANDLE>(this);
}

void Plugin::closePlugin(HANDLE Plugin)
{

}

void Plugin::getOpenPluginInfo(HANDLE Plugin, OpenPluginInfo *pluginInfo)
{
//    pluginInfo->KeyBar = &(m_keyBar.getKeyBar());

    static const wchar_t *pluginPanelTitle = m_pPsi.GetMsg(m_pPsi.ModuleNumber, MGvfsPanel);
    pluginInfo->PanelTitle = pluginPanelTitle;
}

int Plugin::getFindData(HANDLE Plugin, PluginPanelItem **PanelItem, int *itemsNumber, int OpMode)
{
    updatePanelItems();
    *PanelItem = m_items.empty() ? nullptr : &(m_items[0]);
    *itemsNumber = m_items.size();
    return 1;
}

void Plugin::freeFindData(HANDLE Plugin, PluginPanelItem *PanelItem, int itemsNumber)
{

}

int Plugin::processHostFile(HANDLE Plugin, PluginPanelItem *PanelItem, int ItemsNumber, int OpMode)
{
    return 0;
}

int Plugin::processKey(HANDLE Plugin, int key, unsigned int controlState)
{
fprintf(stderr, "Gvfs processKey(): key = %d controlState = %d\n", key, controlState);
fflush(stderr);
    if ((key == VK_F3) || (key == VK_F5) || (key == VK_F6))
    {
        // block keys
        return 1;
    }
    else if ((key == VK_F4) && (controlState == 0))
    {
        // edit mount record
        if (m_items.empty()) return 1; // no items, drop key
        struct PanelInfo pInfo;
        m_pPsi.Control(Plugin, FCTL_GETPANELINFO, 0, (LONG_PTR)&pInfo);
        auto currentItem = pInfo.CurrentItem;
        PluginPanelItem item = m_items[currentItem];
        std::wstring name = item.FindData.lpwszFileName;
        auto it = m_mountPoints.find(name);
        if (it != m_mountPoints.end())
        {
            if (GetLoginData(m_pPsi, it->second))
            {
                MountPoint changedMountPt = it->second;
                m_mountPoints.erase(it);
                m_mountPoints.insert(std::pair<std::wstring, MountPoint>(
                    changedMountPt.getResPath(), changedMountPt
                ));
                m_pPsi.Control(Plugin, FCTL_UPDATEPANEL, 0, 0);
            }
        }
        return 1; // return 1: far should not handel this key
    }
    else if ((key == VK_F4) && (controlState & PKF_SHIFT))
    {
        // add new mount record
        MountPoint mntPoint;
        if (GetLoginData(m_pPsi, mntPoint))
        {
            m_mountPoints.insert(std::pair<std::wstring, MountPoint>(
                mntPoint.getResPath(), mntPoint
            ));
            m_pPsi.Control(Plugin, FCTL_UPDATEPANEL, 0, 0);
        }
        return 1;
    }
    return 0; // all other keys left to far
}

int Plugin::processEvent(HANDLE Plugin, int Event, void *Param)
{
    return 0;
}

int Plugin::setDirectory(HANDLE Plugin, const wchar_t *Dir, int OpMode)
{
    if(OpMode == 0)
    {
        auto it = m_mountPoints.find(std::wstring(Dir));
        if (it != m_mountPoints.end())
        {
            if (!it->second.isMounted())
                try
                {
                    if(!it->second.mount())
                        return 0;
                }
                catch (const GvfsServiceException& error)
                {
                    const wchar_t *msgItems[2];
                    std::wstring buf =
                        std::wstring_convert<std::codecvt_utf8<wchar_t> >().from_bytes(error.what().raw());
                    msgItems[0] = m_pPsi.GetMsg(m_pPsi.ModuleNumber, MMountError);
                    msgItems[1] = buf.c_str();
                    m_pPsi.Message(m_pPsi.ModuleNumber, FMSG_WARNING | FMSG_MB_OK,
                                   NULL, msgItems, 2, 0);
                    return 0;
                }
            // change directory to:
            std::wstring dir = it->second.getFsPath();
            if (!dir.empty())
            {
                m_pPsi.Control(Plugin, FCTL_SETPANELDIR, 0, (LONG_PTR)(dir.c_str()));
            }
        }
    }

    return 0;
}

int Plugin::makeDirectory(HANDLE Plugin, const wchar_t **Name, int OpMode)
{
    // add new mount record
    MountPoint mountPoint;
    if(GetLoginData(this->m_pPsi, mountPoint))
    {
        m_mountPoints.insert(std::pair<std::wstring, MountPoint>(mountPoint.getResPath(), mountPoint));
    }
    return 1;
}

int Plugin::deleteFiles(HANDLE Plugin, PluginPanelItem *PanelItem, int itemsNumber, int OpMode)
{
    const unsigned N = 2;
    const wchar_t *msgItems[N] =
    {
        L"Delete selected mounts",
        L"Do you really want to delete mount point?"
    };

    auto msgCode = m_pPsi.Message(m_pPsi.ModuleNumber, FMSG_WARNING | FMSG_MB_YESNO, NULL, msgItems, N, 0);
    // if no or canceled msg box, do nothing
    if ((msgCode == -1) || (msgCode == 1))
    {
        return -1;
    }

    for (int i = 0; i < itemsNumber; ++i)
    {
        auto name = PanelItem[i].FindData.lpwszFileName;
        auto it = m_mountPoints.find(name);
        if (it != m_mountPoints.end())
        {
            if (it->second.isMounted())
                try
                {
                    it->second.unmount();
                }
                catch (const GvfsServiceException& error)
                {
                    const wchar_t *msgItems[2];
                    std::wstring buf =
                        std::wstring_convert<std::codecvt_utf8<wchar_t> >().from_bytes(error.what().raw());
                    msgItems[0] = m_pPsi.GetMsg(m_pPsi.ModuleNumber, MUnmountError);
                    msgItems[1] = buf.c_str();
                    m_pPsi.Message(m_pPsi.ModuleNumber, FMSG_WARNING | FMSG_MB_OK,
                                   NULL, msgItems, 2, 0);
                }
            m_mountPoints.erase(it);
        }
    }
    return 0;
}

int Plugin::getFiles(HANDLE Plugin, PluginPanelItem *PanelItem, int itemsNumber, int Move, const wchar_t **destPath, int OpMode)
{
    return 0;
}

int Plugin::putFiles(HANDLE Plugin, PluginPanelItem *PanelItem, int itemsNumber, int Move, const wchar_t *SrcPath, int OpMode)
{
    return 0;
}

int Plugin::processEditorEvent(int Event, void *Param)
{
    return 0;
}

int Plugin::processEditorInput(const INPUT_RECORD *Rec)
{
    return 0;
}

void Plugin::clearPanelItems()
{
    for (PluginPanelItem& item : m_items)
    {
        free((void*)item.FindData.lpwszFileName);
    }
    m_items.clear();
}

void Plugin::updatePanelItems()
{
    clearPanelItems();
    for (const auto& mountPt : m_mountPoints)
    {
        PluginPanelItem item { };
        item.FindData.lpwszFileName = wcsdup(mountPt.second.getResPath().c_str());
        item.FindData.dwFileAttributes = FILE_ATTRIBUTE_DIRECTORY | FILE_ATTRIBUTE_ARCHIVE;
        item.CustomColumnNumber = 0;
        m_items.push_back(item);
    }
}
<commit_msg>Add Glib::Error catch.<commit_after>#include <iostream> // debug output
#include <codecvt> // debug output
#include <locale> // debug output
#include "gvfsdlg.h"
#include "LngStringIDs.h"
#include "Plugin.h"

Plugin& Plugin::getInstance()
{
    static Plugin instance;
    return instance;
}

Plugin::Plugin()
{
    Opt.AddToDisksMenu = true;
    Opt.AddToPluginsMenu = true;
//    m_keyBar.setNormalKey(7, L"MkMount");
//    m_keyBar.setNormalKey(4, L"EdMount");
}

Plugin::~Plugin()
{
    clearPanelItems();
}

int Plugin::getVersion()
{
    return 1;
}

void Plugin::setStartupInfo(const PluginStartupInfo *psi)
{
    this->m_pPsi = *psi;
}

void Plugin::exitFar()
{
    // unmount all VFS, mounted in current session
    for (auto& mntPoint : m_mountPoints)
    {
        if (mntPoint.second.isMounted())
            try
            {
                mntPoint.second.unmount();
            }
            catch (const GvfsServiceException& error)
            {
                // ignore error here
            }
            catch (const Glib::Error& error)
            {
                // ignore error here
            }
    }
}

void Plugin::getPluginInfo(PluginInfo *info)
{

    info->StructSize = sizeof(*info);
    info->Flags = PF_PRELOAD;

    static const wchar_t *DiskMenuStrings[1];
    DiskMenuStrings[0] = m_pPsi.GetMsg(m_pPsi.ModuleNumber, MDiskMenuString);
    info->DiskMenuStrings = DiskMenuStrings;
    info->DiskMenuStringsNumber = Opt.AddToDisksMenu ? ARRAYSIZE(DiskMenuStrings) : 0;

    static const wchar_t *PluginMenuStrings[1];
    PluginMenuStrings[0] = m_pPsi.GetMsg(m_pPsi.ModuleNumber, MGvfsPanel);
    info->PluginMenuStrings = Opt.AddToPluginsMenu ? PluginMenuStrings : NULL;
    info->PluginMenuStringsNumber = Opt.AddToPluginsMenu ? ARRAYSIZE(PluginMenuStrings) : 0;

    static const wchar_t *PluginCfgStrings[1];
    PluginCfgStrings[0] = m_pPsi.GetMsg(m_pPsi.ModuleNumber, MGvfsPanel);
    info->PluginConfigStrings = PluginCfgStrings;
    info->PluginConfigStringsNumber = ARRAYSIZE(PluginCfgStrings);
    info->CommandPrefix = Opt.Prefix;
}

int Plugin::configure(int item)
{
  (void)item;
  return FALSE;
}

HANDLE Plugin::openPlugin(int openFrom, intptr_t item)
{
    return static_cast<HANDLE>(this);
}

void Plugin::closePlugin(HANDLE Plugin)
{

}

void Plugin::getOpenPluginInfo(HANDLE Plugin, OpenPluginInfo *pluginInfo)
{
//    pluginInfo->KeyBar = &(m_keyBar.getKeyBar());

    static const wchar_t *pluginPanelTitle = m_pPsi.GetMsg(m_pPsi.ModuleNumber, MGvfsPanel);
    pluginInfo->PanelTitle = pluginPanelTitle;
}

int Plugin::getFindData(HANDLE Plugin, PluginPanelItem **PanelItem, int *itemsNumber, int OpMode)
{
    updatePanelItems();
    *PanelItem = m_items.empty() ? nullptr : &(m_items[0]);
    *itemsNumber = m_items.size();
    return 1;
}

void Plugin::freeFindData(HANDLE Plugin, PluginPanelItem *PanelItem, int itemsNumber)
{

}

int Plugin::processHostFile(HANDLE Plugin, PluginPanelItem *PanelItem, int ItemsNumber, int OpMode)
{
    return 0;
}

int Plugin::processKey(HANDLE Plugin, int key, unsigned int controlState)
{
fprintf(stderr, "Gvfs processKey(): key = %d controlState = %d\n", key, controlState);
fflush(stderr);
    if ((key == VK_F3) || (key == VK_F5) || (key == VK_F6))
    {
        // block keys
        return 1;
    }
    else if ((key == VK_F4) && (controlState == 0))
    {
        // edit mount record
        if (m_items.empty()) return 1; // no items, drop key
        struct PanelInfo pInfo;
        m_pPsi.Control(Plugin, FCTL_GETPANELINFO, 0, (LONG_PTR)&pInfo);
        auto currentItem = pInfo.CurrentItem;
        PluginPanelItem item = m_items[currentItem];
        std::wstring name = item.FindData.lpwszFileName;
        auto it = m_mountPoints.find(name);
        if (it != m_mountPoints.end())
        {
            if (GetLoginData(m_pPsi, it->second))
            {
                MountPoint changedMountPt = it->second;
                m_mountPoints.erase(it);
                m_mountPoints.insert(std::pair<std::wstring, MountPoint>(
                    changedMountPt.getResPath(), changedMountPt
                ));
                m_pPsi.Control(Plugin, FCTL_UPDATEPANEL, 0, 0);
            }
        }
        return 1; // return 1: far should not handel this key
    }
    else if ((key == VK_F4) && (controlState & PKF_SHIFT))
    {
        // add new mount record
        MountPoint mntPoint;
        if (GetLoginData(m_pPsi, mntPoint))
        {
            m_mountPoints.insert(std::pair<std::wstring, MountPoint>(
                mntPoint.getResPath(), mntPoint
            ));
            m_pPsi.Control(Plugin, FCTL_UPDATEPANEL, 0, 0);
        }
        return 1;
    }
    return 0; // all other keys left to far
}

int Plugin::processEvent(HANDLE Plugin, int Event, void *Param)
{
    return 0;
}

int Plugin::setDirectory(HANDLE Plugin, const wchar_t *Dir, int OpMode)
{
    if(OpMode == 0)
    {
        auto it = m_mountPoints.find(std::wstring(Dir));
        if (it != m_mountPoints.end())
        {
            if (!it->second.isMounted())
                try
                {
                    if(!it->second.mount())
                        return 0;
                }
                catch (const GvfsServiceException& error)
                {
                    const wchar_t *msgItems[2];
                    std::wstring buf =
                        std::wstring_convert<std::codecvt_utf8<wchar_t> >().from_bytes(error.what().raw());
                    msgItems[0] = m_pPsi.GetMsg(m_pPsi.ModuleNumber, MMountError);
                    msgItems[1] = buf.c_str();
                    m_pPsi.Message(m_pPsi.ModuleNumber, FMSG_WARNING | FMSG_MB_OK,
                                   NULL, msgItems, 2, 0);
                    return 0;
                }
                catch (const Glib::Error& error)
                {
                    const wchar_t *msgItems[2];
                    std::wstring buf =
                        std::wstring_convert<std::codecvt_utf8<wchar_t> >().from_bytes(error.what().raw());
                    msgItems[0] = m_pPsi.GetMsg(m_pPsi.ModuleNumber, MMountError);
                    msgItems[1] = buf.c_str();
                    m_pPsi.Message(m_pPsi.ModuleNumber, FMSG_WARNING | FMSG_MB_OK,
                                   NULL, msgItems, 2, 0);
                    return 0;
                }
            // change directory to:
            std::wstring dir = it->second.getFsPath();
            if (!dir.empty())
            {
                m_pPsi.Control(Plugin, FCTL_SETPANELDIR, 0, (LONG_PTR)(dir.c_str()));
            }
        }
    }

    return 0;
}

int Plugin::makeDirectory(HANDLE Plugin, const wchar_t **Name, int OpMode)
{
    // add new mount record
    MountPoint mountPoint;
    if(GetLoginData(this->m_pPsi, mountPoint))
    {
        m_mountPoints.insert(std::pair<std::wstring, MountPoint>(mountPoint.getResPath(), mountPoint));
    }
    return 1;
}

int Plugin::deleteFiles(HANDLE Plugin, PluginPanelItem *PanelItem, int itemsNumber, int OpMode)
{
    const unsigned N = 2;
    const wchar_t *msgItems[N] =
    {
        L"Delete selected mounts",
        L"Do you really want to delete mount point?"
    };

    auto msgCode = m_pPsi.Message(m_pPsi.ModuleNumber, FMSG_WARNING | FMSG_MB_YESNO, NULL, msgItems, N, 0);
    // if no or canceled msg box, do nothing
    if ((msgCode == -1) || (msgCode == 1))
    {
        return -1;
    }

    for (int i = 0; i < itemsNumber; ++i)
    {
        auto name = PanelItem[i].FindData.lpwszFileName;
        auto it = m_mountPoints.find(name);
        if (it != m_mountPoints.end())
        {
            if (it->second.isMounted())
                try
                {
                    it->second.unmount();
                }
                catch (const GvfsServiceException& error)
                {
                    const wchar_t *msgItems[2];
                    std::wstring buf =
                        std::wstring_convert<std::codecvt_utf8<wchar_t> >().from_bytes(error.what().raw());
                    msgItems[0] = m_pPsi.GetMsg(m_pPsi.ModuleNumber, MUnmountError);
                    msgItems[1] = buf.c_str();
                    m_pPsi.Message(m_pPsi.ModuleNumber, FMSG_WARNING | FMSG_MB_OK,
                                   NULL, msgItems, 2, 0);
                }
                catch (const Glib::Error& error)
                {
                    const wchar_t *msgItems[2];
                    std::wstring buf =
                        std::wstring_convert<std::codecvt_utf8<wchar_t> >().from_bytes(error.what().raw());
                    msgItems[0] = m_pPsi.GetMsg(m_pPsi.ModuleNumber, MUnmountError);
                    msgItems[1] = buf.c_str();
                    m_pPsi.Message(m_pPsi.ModuleNumber, FMSG_WARNING | FMSG_MB_OK,
                                   NULL, msgItems, 2, 0);
                }
            m_mountPoints.erase(it);
        }
    }
    return 0;
}

int Plugin::getFiles(HANDLE Plugin, PluginPanelItem *PanelItem, int itemsNumber, int Move, const wchar_t **destPath, int OpMode)
{
    return 0;
}

int Plugin::putFiles(HANDLE Plugin, PluginPanelItem *PanelItem, int itemsNumber, int Move, const wchar_t *SrcPath, int OpMode)
{
    return 0;
}

int Plugin::processEditorEvent(int Event, void *Param)
{
    return 0;
}

int Plugin::processEditorInput(const INPUT_RECORD *Rec)
{
    return 0;
}

void Plugin::clearPanelItems()
{
    for (PluginPanelItem& item : m_items)
    {
        free((void*)item.FindData.lpwszFileName);
    }
    m_items.clear();
}

void Plugin::updatePanelItems()
{
    clearPanelItems();
    for (const auto& mountPt : m_mountPoints)
    {
        PluginPanelItem item { };
        item.FindData.lpwszFileName = wcsdup(mountPt.second.getResPath().c_str());
        item.FindData.dwFileAttributes = FILE_ATTRIBUTE_DIRECTORY | FILE_ATTRIBUTE_ARCHIVE;
        item.CustomColumnNumber = 0;
        m_items.push_back(item);
    }
}
<|endoftext|>


<commit_before>#include <OgreSceneNode.h>
#include <OgreSceneManager.h>

#include <rviz/visualization_manager.h>
#include <rviz/frame_manager.h>
#include <rviz/properties/color_property.h>
#include <rviz/properties/float_property.h>
#include <rviz/properties/int_property.h>
#include <rviz/properties/parse_color.h>
#include <rviz/validate_floats.h>

#include <boost/foreach.hpp>

#include "wrench_visual.h"

#include "wrench_display.h"

namespace rviz
{

    WrenchStampedDisplay::WrenchStampedDisplay()
    {
	force_color_property_ =
	    new rviz::ColorProperty( "Force Color", QColor( 204, 51, 51 ),
                                     "Color to draw the force arrows.",
                                     this, SLOT( updateColorAndAlpha() ));

	torque_color_property_ =
	    new rviz::ColorProperty( "Torque Color", QColor( 204, 204, 51),
                                     "Color to draw the torque arrows.",
                                     this, SLOT( updateColorAndAlpha() ));

	alpha_property_ =
            new rviz::FloatProperty( "Alpha", 1.0,
                                     "0 is fully transparent, 1.0 is fully opaque.",
                                     this, SLOT( updateColorAndAlpha() ));

	force_scale_property_ =
            new rviz::FloatProperty( "Force Arrow Scale", 2.0,
                                     "force arrow scale",
                                     this, SLOT( updateColorAndAlpha() ));

        torque_scale_property_ =
            new rviz::FloatProperty( "Torque Arrow Scale", 2.0,
                                     "torque arrow scale",
                                     this, SLOT( updateColorAndAlpha() ));

	width_property_ =
            new rviz::FloatProperty( "Arrow Width", 0.5,
                                     "arrow width",
                                     this, SLOT( updateColorAndAlpha() ));

	history_length_property_ =
	    new rviz::IntProperty( "History Length", 1,
                                   "Number of prior measurements to display.",
                                   this, SLOT( updateHistoryLength() ));

        history_length_property_->setMin( 1 );
        history_length_property_->setMax( 100000 );
    }

    void WrenchStampedDisplay::onInitialize()
    {
        MFDClass::onInitialize();
	updateHistoryLength( );
    }

    WrenchStampedDisplay::~WrenchStampedDisplay()
    {
    }

    // Override rviz::Display's reset() function to add a call to clear().
    void WrenchStampedDisplay::reset()
    {
        MFDClass::reset();
	visuals_.clear();
    }

    void WrenchStampedDisplay::updateColorAndAlpha()
    {
        float alpha = alpha_property_->getFloat();
        float force_scale = force_scale_property_->getFloat();
        float torque_scale = torque_scale_property_->getFloat();
        float width = width_property_->getFloat();
        Ogre::ColourValue force_color = force_color_property_->getOgreColor();
        Ogre::ColourValue torque_color = torque_color_property_->getOgreColor();

        for( size_t i = 0; i < visuals_.size(); i++ )
	{
            visuals_[i]->setForceColor( force_color.r, force_color.g, force_color.b, alpha );
            visuals_[i]->setTorqueColor( torque_color.r, torque_color.g, torque_color.b, alpha );
            visuals_[i]->setForceScale( force_scale );
            visuals_[i]->setTorqueScale( torque_scale );
            visuals_[i]->setWidth( width );
	}
    }

    // Set the number of past visuals to show.
    void WrenchStampedDisplay::updateHistoryLength()
    {
        visuals_.rset_capacity(history_length_property_->getInt());
    }

    bool validateFloats( const geometry_msgs::WrenchStamped& msg )
    {
        return rviz::validateFloats(msg.wrench.force) && rviz::validateFloats(msg.wrench.torque) ;
    }

    // This is our callback to handle an incoming message.
    void WrenchStampedDisplay::processMessage( const geometry_msgs::WrenchStamped::ConstPtr& msg )
    {
        if( !validateFloats( *msg ))
            {
                setStatus( rviz::StatusProperty::Error, "Topic", "Message contained invalid floating point values (nans or infs)" );
                return;
            }

	// Here we call the rviz::FrameManager to get the transform from the
	// fixed frame to the frame in the header of this Imu message.  If
	// it fails, we can't do anything else so we return.
	Ogre::Quaternion orientation;
	Ogre::Vector3 position;
	if( !context_->getFrameManager()->getTransform( msg->header.frame_id,
                                                        msg->header.stamp,
                                                        position, orientation ))
	  {
	    ROS_DEBUG( "Error transforming from frame '%s' to frame '%s'",
		       msg->header.frame_id.c_str(), qPrintable( fixed_frame_ ));
	    return;
	  }

        if ( position.isNaN() )
          {
            ROS_ERROR_THROTTLE(1.0, "Wrench position contains NaNs. Will skip rendering as long as it will have valid position");
            return;
          }

        // We are keeping a circular buffer of visual pointers.  This gets
        // the next one, or creates and stores it if the buffer is not full
        boost::shared_ptr<WrenchStampedVisual> visual;
        if( visuals_.full() )
            {
                visual = visuals_.front();
            }
        else
            {
                visual.reset(new WrenchStampedVisual( context_->getSceneManager(), scene_node_ ));
            }

	// Now set or update the contents of the chosen visual.
	visual->setMessage( msg );
	visual->setFramePosition( position );
	visual->setFrameOrientation( orientation );
        float alpha = alpha_property_->getFloat();
        float force_scale = force_scale_property_->getFloat();
        float torque_scale = torque_scale_property_->getFloat();
        float width = width_property_->getFloat();
        Ogre::ColourValue force_color = force_color_property_->getOgreColor();
        Ogre::ColourValue torque_color = torque_color_property_->getOgreColor();
	visual->setForceColor( force_color.r, force_color.g, force_color.b, alpha );
	visual->setTorqueColor( torque_color.r, torque_color.g, torque_color.b, alpha );
        visual->setForceScale( force_scale );
        visual->setTorqueScale( torque_scale );
        visual->setWidth( width );

        // And send it to the end of the circular buffer
        visuals_.push_back(visual);
    }

} // end namespace rviz

// Tell pluginlib about this class.  It is important to do this in
// global scope, outside our package's namespace.
#include <pluginlib/class_list_macros.h>
PLUGINLIB_EXPORT_CLASS( rviz::WrenchStampedDisplay, rviz::Display )

<commit_msg>[src/rviz/default_plugin/wrench_display.cpp] update comment by comments<commit_after>#include <OgreSceneNode.h>
#include <OgreSceneManager.h>

#include <rviz/visualization_manager.h>
#include <rviz/frame_manager.h>
#include <rviz/properties/color_property.h>
#include <rviz/properties/float_property.h>
#include <rviz/properties/int_property.h>
#include <rviz/properties/parse_color.h>
#include <rviz/validate_floats.h>

#include <boost/foreach.hpp>

#include "wrench_visual.h"

#include "wrench_display.h"

namespace rviz
{

    WrenchStampedDisplay::WrenchStampedDisplay()
    {
	force_color_property_ =
	    new rviz::ColorProperty( "Force Color", QColor( 204, 51, 51 ),
                                     "Color to draw the force arrows.",
                                     this, SLOT( updateColorAndAlpha() ));

	torque_color_property_ =
	    new rviz::ColorProperty( "Torque Color", QColor( 204, 204, 51),
                                     "Color to draw the torque arrows.",
                                     this, SLOT( updateColorAndAlpha() ));

	alpha_property_ =
            new rviz::FloatProperty( "Alpha", 1.0,
                                     "0 is fully transparent, 1.0 is fully opaque.",
                                     this, SLOT( updateColorAndAlpha() ));

	force_scale_property_ =
            new rviz::FloatProperty( "Force Arrow Scale", 2.0,
                                     "force arrow scale",
                                     this, SLOT( updateColorAndAlpha() ));

        torque_scale_property_ =
            new rviz::FloatProperty( "Torque Arrow Scale", 2.0,
                                     "torque arrow scale",
                                     this, SLOT( updateColorAndAlpha() ));

	width_property_ =
            new rviz::FloatProperty( "Arrow Width", 0.5,
                                     "arrow width",
                                     this, SLOT( updateColorAndAlpha() ));

	history_length_property_ =
	    new rviz::IntProperty( "History Length", 1,
                                   "Number of prior measurements to display.",
                                   this, SLOT( updateHistoryLength() ));

        history_length_property_->setMin( 1 );
        history_length_property_->setMax( 100000 );
    }

    void WrenchStampedDisplay::onInitialize()
    {
        MFDClass::onInitialize();
	updateHistoryLength( );
    }

    WrenchStampedDisplay::~WrenchStampedDisplay()
    {
    }

    // Override rviz::Display's reset() function to add a call to clear().
    void WrenchStampedDisplay::reset()
    {
        MFDClass::reset();
	visuals_.clear();
    }

    void WrenchStampedDisplay::updateColorAndAlpha()
    {
        float alpha = alpha_property_->getFloat();
        float force_scale = force_scale_property_->getFloat();
        float torque_scale = torque_scale_property_->getFloat();
        float width = width_property_->getFloat();
        Ogre::ColourValue force_color = force_color_property_->getOgreColor();
        Ogre::ColourValue torque_color = torque_color_property_->getOgreColor();

        for( size_t i = 0; i < visuals_.size(); i++ )
	{
            visuals_[i]->setForceColor( force_color.r, force_color.g, force_color.b, alpha );
            visuals_[i]->setTorqueColor( torque_color.r, torque_color.g, torque_color.b, alpha );
            visuals_[i]->setForceScale( force_scale );
            visuals_[i]->setTorqueScale( torque_scale );
            visuals_[i]->setWidth( width );
	}
    }

    // Set the number of past visuals to show.
    void WrenchStampedDisplay::updateHistoryLength()
    {
        visuals_.rset_capacity(history_length_property_->getInt());
    }

    bool validateFloats( const geometry_msgs::WrenchStamped& msg )
    {
        return rviz::validateFloats(msg.wrench.force) && rviz::validateFloats(msg.wrench.torque) ;
    }

    // This is our callback to handle an incoming message.
    void WrenchStampedDisplay::processMessage( const geometry_msgs::WrenchStamped::ConstPtr& msg )
    {
        if( !validateFloats( *msg ))
            {
                setStatus( rviz::StatusProperty::Error, "Topic", "Message contained invalid floating point values (nans or infs)" );
                return;
            }

	// Here we call the rviz::FrameManager to get the transform from the
	// fixed frame to the frame in the header of this Imu message.  If
	// it fails, we can't do anything else so we return.
	Ogre::Quaternion orientation;
	Ogre::Vector3 position;
	if( !context_->getFrameManager()->getTransform( msg->header.frame_id,
                                                        msg->header.stamp,
                                                        position, orientation ))
	  {
	    ROS_DEBUG( "Error transforming from frame '%s' to frame '%s'",
		       msg->header.frame_id.c_str(), qPrintable( fixed_frame_ ));
	    return;
	  }

        if ( position.isNaN() )
          {
            ROS_ERROR_THROTTLE(1.0, "Wrench position contains NaNs. Skipping render as long as the position is invalid");
            return;
          }

        // We are keeping a circular buffer of visual pointers.  This gets
        // the next one, or creates and stores it if the buffer is not full
        boost::shared_ptr<WrenchStampedVisual> visual;
        if( visuals_.full() )
            {
                visual = visuals_.front();
            }
        else
            {
                visual.reset(new WrenchStampedVisual( context_->getSceneManager(), scene_node_ ));
            }

	// Now set or update the contents of the chosen visual.
	visual->setMessage( msg );
	visual->setFramePosition( position );
	visual->setFrameOrientation( orientation );
        float alpha = alpha_property_->getFloat();
        float force_scale = force_scale_property_->getFloat();
        float torque_scale = torque_scale_property_->getFloat();
        float width = width_property_->getFloat();
        Ogre::ColourValue force_color = force_color_property_->getOgreColor();
        Ogre::ColourValue torque_color = torque_color_property_->getOgreColor();
	visual->setForceColor( force_color.r, force_color.g, force_color.b, alpha );
	visual->setTorqueColor( torque_color.r, torque_color.g, torque_color.b, alpha );
        visual->setForceScale( force_scale );
        visual->setTorqueScale( torque_scale );
        visual->setWidth( width );

        // And send it to the end of the circular buffer
        visuals_.push_back(visual);
    }

} // end namespace rviz

// Tell pluginlib about this class.  It is important to do this in
// global scope, outside our package's namespace.
#include <pluginlib/class_list_macros.h>
PLUGINLIB_EXPORT_CLASS( rviz::WrenchStampedDisplay, rviz::Display )

<|endoftext|>


<commit_before>/*

Copyright (c) 2003, Arvid Norberg
All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:

    * Redistributions of source code must retain the above copyright
      notice, this list of conditions and the following disclaimer.
    * Redistributions in binary form must reproduce the above copyright
      notice, this list of conditions and the following disclaimer in
      the documentation and/or other materials provided with the distribution.
    * Neither the name of the author nor the names of its
      contributors may be used to endorse or promote products derived
      from this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.

*/

#include <cctype>

#ifdef _MSC_VER
#pragma warning(push, 1)
#endif

#include <boost/optional.hpp>

#ifdef _MSC_VER
#pragma warning(pop)
#endif

#include "libtorrent/identify_client.hpp"
#include "libtorrent/fingerprint.hpp"

#if defined(_MSC_VER) && _MSC_VER < 1300
namespace std
{
	using ::isprint;
	using ::isdigit;
}
#endif

namespace
{

	using namespace libtorrent;

	int decode_digit(char c)
	{
		if (std::isdigit(c)) return c - '0';
		return std::toupper(c) - 'A' + 10;
	}

	// takes a peer id and returns a valid boost::optional
	// object if the peer id matched the azureus style encoding
	// the returned fingerprint contains information about the
	// client's id
	boost::optional<fingerprint> parse_az_style(const peer_id& id)
	{
		fingerprint ret("..", 0, 0, 0, 0);
		peer_id::const_iterator i = id.begin();

		if (*i != '-') return boost::optional<fingerprint>();
		++i;

		for (int j = 0; j < 2; ++j)
		{
			if (!std::isprint(*i)) return boost::optional<fingerprint>();
			ret.id[j] = *i;
			++i;
		}

		if (!std::isalnum(*i)) return boost::optional<fingerprint>();
		ret.major_version = decode_digit(*i);
		++i;

		if (!std::isalnum(*i)) return boost::optional<fingerprint>();
		ret.minor_version = decode_digit(*i);
		++i;

		if (!std::isalnum(*i)) return boost::optional<fingerprint>();
		ret.revision_version = decode_digit(*i);
		++i;

		if (!std::isalnum(*i)) return boost::optional<fingerprint>();
		ret.tag_version = decode_digit(*i);
		++i;

		if (*i != '-') return boost::optional<fingerprint>();

		return boost::optional<fingerprint>(ret);
	}

	// checks if a peer id can possibly contain a shadow-style
	// identification
	boost::optional<fingerprint> parse_shadow_style(const peer_id& id)
	{
		fingerprint ret("..", 0, 0, 0, 0);
		peer_id::const_iterator i = id.begin();

		if (!std::isalnum(*i)) return boost::optional<fingerprint>();
		ret.id[0] = *i;
		ret.id[1] = 0;
		++i;

		if (std::equal(id.begin()+4, id.begin()+8, "----"))
		{
			if (!std::isalnum(*i)) return boost::optional<fingerprint>();
			ret.major_version = decode_digit(*i);
			++i;

			if (!std::isalnum(*i)) return boost::optional<fingerprint>();
			ret.minor_version = decode_digit(*i);
			++i;

			if (!std::isalnum(*i)) return boost::optional<fingerprint>();
			ret.revision_version = decode_digit(*i);
		}
		else if (id[8] == 0)
		{
			if (*i > 127) return boost::optional<fingerprint>();
			ret.major_version = *i;
			++i;

			if (*i > 127) return boost::optional<fingerprint>();
			ret.minor_version = *i;
			++i;

			if (*i > 127) return boost::optional<fingerprint>();
			ret.revision_version = *i;
		}
		else
			return boost::optional<fingerprint>();

		ret.tag_version = 0;
		return boost::optional<fingerprint>(ret);
	}

	// checks if a peer id can possibly contain a mainline-style
	// identification
	boost::optional<fingerprint> parse_mainline_style(const peer_id& id)
	{
		fingerprint ret("..", 0, 0, 0, 0);
		peer_id::const_iterator i = id.begin();

		if (!std::isprint(*i)) return boost::optional<fingerprint>();
		ret.id[0] = *i;
		ret.id[1] = 0;
		++i;

		if (!std::isalnum(*i)) return boost::optional<fingerprint>();
		ret.major_version = decode_digit(*i);
		++i;

		if (*i != '-') return boost::optional<fingerprint>();
		++i;

		if (!std::isalnum(*i)) return boost::optional<fingerprint>();
		ret.minor_version = decode_digit(*i);
		++i;

		if (*i != '-') return boost::optional<fingerprint>();
		++i;

		if (!std::isalnum(*i)) return boost::optional<fingerprint>();
		ret.revision_version = decode_digit(*i);
		++i;

		if (!std::equal(i, i+1, "--")) return boost::optional<fingerprint>();

		ret.tag_version = 0;
		return boost::optional<fingerprint>(ret);
	}

} // namespace unnamed

namespace libtorrent
{

	std::string identify_client(const peer_id& p)
	{
		peer_id::const_iterator PID = p.begin();
		boost::optional<fingerprint> f;

		if (p.is_all_zeros()) return "Unknown";

		// look for azureus style id
		f = parse_az_style(p);
		if (f)
		{
			std::stringstream identity;

			// azureus
			if (std::equal(f->id, f->id+2, "AZ"))
				identity << "Azureus ";

			// BittorrentX
			else if (std::equal(f->id, f->id+2, "BX"))
				identity << "BittorrentX ";

			// libtorrent
			else if (std::equal(f->id, f->id+2, "LT"))
				identity << "libtorrent ";

			// Moonlight Torrent
			else if (std::equal(f->id, f->id+2, "MT"))
				identity << "Moonlight Torrent ";

			// Torrent Storm
			else if (std::equal(f->id, f->id+2, "TS"))
				identity << "TorrentStorm ";

			// SwarmScope
			else if (std::equal(f->id, f->id+2, "SS"))
				identity << "SwarmScope ";

			// XanTorrent
			else if (std::equal(f->id, f->id+2, "XT"))
				identity << "XanTorrent ";

			// unknown client
			else
				identity << std::string(f->id, f->id+2) << " ";

			identity << (int)f->major_version
				<< "." << (int)f->minor_version
				<< "." << (int)f->revision_version
				<< "." << (int)f->tag_version;

			return identity.str();
		}

		// look for shadow style id
		f = parse_shadow_style(p);
		if (f)
		{
			std::stringstream identity;

			// Shadow
			if (std::equal(f->id, f->id+1, "S"))
				identity << "Shadow ";

			// ABC
			else if (std::equal(f->id, f->id+1, "A"))
				identity << "ABC ";

			// UPnP
			else if (std::equal(f->id, f->id+1, "U"))
				identity << "UPnP ";

			// BitTornado
			else if (std::equal(f->id, f->id+1, "T"))
				identity << "BitTornado ";

			// unknown client
			else
				identity << std::string(f->id, f->id+1) << " ";

			identity << (int)f->major_version
				<< "." << (int)f->minor_version
				<< "." << (int)f->revision_version;

			return identity.str();
		}

		f = parse_mainline_style(p);
		if (f)
		{
			std::stringstream identity;

			// Mainline
			if (std::equal(f->id, f->id+1, "M"))
				identity << "Mainline ";

			// unknown client
			else
				identity << std::string(f->id, f->id+1) << " ";

			identity << (int)f->major_version
				<< "." << (int)f->minor_version
				<< "." << (int)f->revision_version;

			return identity.str();
		}

		// ----------------------
		// non standard encodings
		// ----------------------

		if (std::equal(PID, PID + 12, "-G3g3rmz    "))
		{
			return "G3 Torrent";
		}

		if (std::equal(PID, PID + 4, "exbc"))
		{
			std::stringstream s;
			s << "BitComet " << (int)PID[4] << "." << (int)PID[5]/10 << (int)PID[5]%10;
			return s.str();
		}

		if (std::equal(PID + 5, PID + 5 + 8, "Azureus"))
		{
			return "Azureus 2.0.3.2";
		}

		if (std::equal(PID, PID + 11, "DansClient"))
		{
			return "XanTorrent";
		}

		if (std::equal(PID, PID + 7, "Plus---"))
		{
			return "Bittorrent Plus";
		}

		if (std::equal(PID, PID + 16, "Deadman Walking-"))
		{
			return "Deadman";
		}

		if (std::equal(PID, PID + 7, "btuga"))
		{
			return "BTugaXP";
		}

		if (std::equal(PID, PID + 7, "btfans"))
		{
			return "SimpleBT";
		}

		if (std::equal(PID, PID + 7, "turbobt")
			&& std::isalnum(PID[8])
			&& std::isalnum(PID[10])
			&& std::isalnum(PID[12]))
		{
			std::stringstream s;
			s << "TurboBT " << PID[8] << "." << PID[10] << "." << PID[12];
			return s.str();
		}

		if (std::equal(PID, PID + 13, "\0\0\0\0\0\0\0\0\0\0\0\0\x97"))
		{
			return "Experimental 3.2.1b2";
		}

		if (std::equal(PID, PID + 13, "\0\0\0\0\0\0\0\0\0\0\0\0\0"))
		{
			return "Experimental 3.1";
		}

		if (std::equal(PID, PID + 12, "\0\0\0\0\0\0\0\0\0\0\0\0"))
		{
			return "Generic";
		}

		std::string unknown("Unknown [");
		for (peer_id::const_iterator i = p.begin(); i != p.end(); ++i)
		{
			unknown += std::isprint(*i)?*i:'.';
		}
		unknown += "]";
		return unknown;
	}

}
<commit_msg>updated client identification<commit_after>/*

Copyright (c) 2003, Arvid Norberg
All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:

    * Redistributions of source code must retain the above copyright
      notice, this list of conditions and the following disclaimer.
    * Redistributions in binary form must reproduce the above copyright
      notice, this list of conditions and the following disclaimer in
      the documentation and/or other materials provided with the distribution.
    * Neither the name of the author nor the names of its
      contributors may be used to endorse or promote products derived
      from this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.

*/

#include <cctype>

#ifdef _MSC_VER
#pragma warning(push, 1)
#endif

#include <boost/optional.hpp>

#ifdef _MSC_VER
#pragma warning(pop)
#endif

#include "libtorrent/identify_client.hpp"
#include "libtorrent/fingerprint.hpp"

#if defined(_MSC_VER) && _MSC_VER < 1300
namespace std
{
	using ::isprint;
	using ::isdigit;
}
#endif

namespace
{

	using namespace libtorrent;

	int decode_digit(char c)
	{
		if (std::isdigit(c)) return c - '0';
		return std::toupper(c) - 'A' + 10;
	}

	// takes a peer id and returns a valid boost::optional
	// object if the peer id matched the azureus style encoding
	// the returned fingerprint contains information about the
	// client's id
	boost::optional<fingerprint> parse_az_style(const peer_id& id)
	{
		fingerprint ret("..", 0, 0, 0, 0);
		peer_id::const_iterator i = id.begin();

		if (*i != '-') return boost::optional<fingerprint>();
		++i;

		for (int j = 0; j < 2; ++j)
		{
			if (!std::isprint(*i)) return boost::optional<fingerprint>();
			ret.id[j] = *i;
			++i;
		}

		if (!std::isalnum(*i)) return boost::optional<fingerprint>();
		ret.major_version = decode_digit(*i);
		++i;

		if (!std::isalnum(*i)) return boost::optional<fingerprint>();
		ret.minor_version = decode_digit(*i);
		++i;

		if (!std::isalnum(*i)) return boost::optional<fingerprint>();
		ret.revision_version = decode_digit(*i);
		++i;

		if (!std::isalnum(*i)) return boost::optional<fingerprint>();
		ret.tag_version = decode_digit(*i);
		++i;

		if (*i != '-') return boost::optional<fingerprint>();

		return boost::optional<fingerprint>(ret);
	}

	// checks if a peer id can possibly contain a shadow-style
	// identification
	boost::optional<fingerprint> parse_shadow_style(const peer_id& id)
	{
		fingerprint ret("..", 0, 0, 0, 0);
		peer_id::const_iterator i = id.begin();

		if (!std::isalnum(*i)) return boost::optional<fingerprint>();
		ret.id[0] = *i;
		ret.id[1] = 0;
		++i;

		if (std::equal(id.begin()+4, id.begin()+8, "----"))
		{
			if (!std::isalnum(*i)) return boost::optional<fingerprint>();
			ret.major_version = decode_digit(*i);
			++i;

			if (!std::isalnum(*i)) return boost::optional<fingerprint>();
			ret.minor_version = decode_digit(*i);
			++i;

			if (!std::isalnum(*i)) return boost::optional<fingerprint>();
			ret.revision_version = decode_digit(*i);
		}
		else if (id[8] == 0)
		{
			if (*i > 127) return boost::optional<fingerprint>();
			ret.major_version = *i;
			++i;

			if (*i > 127) return boost::optional<fingerprint>();
			ret.minor_version = *i;
			++i;

			if (*i > 127) return boost::optional<fingerprint>();
			ret.revision_version = *i;
		}
		else
			return boost::optional<fingerprint>();

		ret.tag_version = 0;
		return boost::optional<fingerprint>(ret);
	}

	// checks if a peer id can possibly contain a mainline-style
	// identification
	boost::optional<fingerprint> parse_mainline_style(const peer_id& id)
	{
		fingerprint ret("..", 0, 0, 0, 0);
		peer_id::const_iterator i = id.begin();

		if (!std::isprint(*i)) return boost::optional<fingerprint>();
		ret.id[0] = *i;
		ret.id[1] = 0;
		++i;

		if (!std::isalnum(*i)) return boost::optional<fingerprint>();
		ret.major_version = decode_digit(*i);
		++i;

		if (*i != '-') return boost::optional<fingerprint>();
		++i;

		if (!std::isalnum(*i)) return boost::optional<fingerprint>();
		ret.minor_version = decode_digit(*i);
		++i;

		if (*i != '-') return boost::optional<fingerprint>();
		++i;

		if (!std::isalnum(*i)) return boost::optional<fingerprint>();
		ret.revision_version = decode_digit(*i);
		++i;

		if (!std::equal(i, i+1, "--")) return boost::optional<fingerprint>();

		ret.tag_version = 0;
		return boost::optional<fingerprint>(ret);
	}

} // namespace unnamed

namespace libtorrent
{

	std::string identify_client(const peer_id& p)
	{
		peer_id::const_iterator PID = p.begin();
		boost::optional<fingerprint> f;

		if (p.is_all_zeros()) return "Unknown";

		// look for azureus style id
		f = parse_az_style(p);
		if (f)
		{
			std::stringstream identity;

			// azureus
			if (std::equal(f->id, f->id+2, "AZ"))
				identity << "Azureus ";

			// BittorrentX
			else if (std::equal(f->id, f->id+2, "BX"))
				identity << "BittorrentX ";

			// libtorrent
			else if (std::equal(f->id, f->id+2, "LT"))
				identity << "libtorrent ";

			// Moonlight Torrent
			else if (std::equal(f->id, f->id+2, "MT"))
				identity << "Moonlight Torrent ";

			// Torrent Storm
			else if (std::equal(f->id, f->id+2, "TS"))
				identity << "TorrentStorm ";

			// SwarmScope
			else if (std::equal(f->id, f->id+2, "SS"))
				identity << "SwarmScope ";

			// XanTorrent
			else if (std::equal(f->id, f->id+2, "XT"))
				identity << "XanTorrent ";

			// TorrentDotNet
			else if (std::equal(f->id, f->id+2, "TN"))
				identity << "TorrentDotNET ";

			// unknown client
			else
				identity << std::string(f->id, f->id+2) << " ";

			identity << (int)f->major_version
				<< "." << (int)f->minor_version
				<< "." << (int)f->revision_version
				<< "." << (int)f->tag_version;

			return identity.str();
		}

		// look for shadow style id
		f = parse_shadow_style(p);
		if (f)
		{
			std::stringstream identity;

			// Shadow
			if (std::equal(f->id, f->id+1, "S"))
				identity << "Shadow ";

			// ABC
			else if (std::equal(f->id, f->id+1, "A"))
				identity << "ABC ";

			// UPnP
			else if (std::equal(f->id, f->id+1, "U"))
				identity << "UPnP ";

			// BitTornado
			else if (std::equal(f->id, f->id+1, "T"))
				identity << "BitTornado ";

			// unknown client
			else
				identity << std::string(f->id, f->id+1) << " ";

			identity << (int)f->major_version
				<< "." << (int)f->minor_version
				<< "." << (int)f->revision_version;

			return identity.str();
		}

		f = parse_mainline_style(p);
		if (f)
		{
			std::stringstream identity;

			// Mainline
			if (std::equal(f->id, f->id+1, "M"))
				identity << "Mainline ";

			// unknown client
			else
				identity << std::string(f->id, f->id+1) << " ";

			identity << (int)f->major_version
				<< "." << (int)f->minor_version
				<< "." << (int)f->revision_version;

			return identity.str();
		}

		// ----------------------
		// non standard encodings
		// ----------------------

		if (std::equal(PID, PID + 12, "-G3g3rmz    "))
		{
			return "G3 Torrent";
		}

		if (std::equal(PID, PID + 4, "exbc"))
		{
			std::stringstream s;
			s << "BitComet " << (int)PID[4] << "." << (int)PID[5]/10 << (int)PID[5]%10;
			return s.str();
		}

		if (std::equal(PID + 5, PID + 5 + 8, "Azureus"))
		{
			return "Azureus 2.0.3.2";
		}

		if (std::equal(PID, PID + 11, "DansClient"))
		{
			return "XanTorrent";
		}

		if (std::equal(PID, PID + 7, "Plus---"))
		{
			return "Bittorrent Plus";
		}

		if (std::equal(PID, PID + 16, "Deadman Walking-"))
		{
			return "Deadman";
		}

		if (std::equal(PID, PID + 7, "btuga"))
		{
			return "BTugaXP";
		}

		if (std::equal(PID, PID + 7, "btfans"))
		{
			return "SimpleBT";
		}

		if (std::equal(PID, PID + 7, "turbobt")
			&& std::isalnum(PID[8])
			&& std::isalnum(PID[10])
			&& std::isalnum(PID[12]))
		{
			std::stringstream s;
			s << "TurboBT " << PID[8] << "." << PID[10] << "." << PID[12];
			return s.str();
		}

		if (std::equal(PID, PID + 13, "\0\0\0\0\0\0\0\0\0\0\0\0\x97"))
		{
			return "Experimental 3.2.1b2";
		}

		if (std::equal(PID, PID + 13, "\0\0\0\0\0\0\0\0\0\0\0\0\0"))
		{
			return "Experimental 3.1";
		}

		if (std::equal(PID, PID + 12, "\0\0\0\0\0\0\0\0\0\0\0\0"))
		{
			return "Generic";
		}

		std::string unknown("Unknown [");
		for (peer_id::const_iterator i = p.begin(); i != p.end(); ++i)
		{
			unknown += std::isprint(*i)?*i:'.';
		}
		unknown += "]";
		return unknown;
	}

}
<|endoftext|>


<commit_before>#ifndef CPPMATH_POINT2_HPP
#define CPPMATH_POINT2_HPP

#include "Vector.hpp"
#include "../compat.hpp"

namespace math
{
    template <typename T>
    class Point2
    {
        public:
            constexpr Point2() : x(0), y(0) {};
            constexpr Point2(const T& x_, const T& y_) : x(x_), y(y_) {};

            Vec2<T> toVector() const
            {
                return Vec2<T>(x, y);
            }

            const Vec2<T>& asVector() const
            {
                return *reinterpret_cast<const Vec2<T>*>(this);
            }

            Vec2<T>& asVector()
            {
                return *reinterpret_cast<Vec2<T>*>(this);
            }

            void set(const T& a, const T& b)
            {
                x = a;
                y = b;
            }

            void set(const T& val)
            {
                x = y = val;
            }

            template <typename T2>
            constexpr operator Point2<T2>() const
            {
                return Point2<T2>(static_cast<T2>(x), static_cast<T2>(y));
            }

            template <typename T2>
            Point2<T>& operator-=(const Vec2<T2>& vec)
            {
                x -= vec.x;
                y -= vec.y;
                return *this;
            }

            template <typename T2>
            Point2<T> operator-(const Vec2<T2>& vec) const
            {
                return Point2<T>(x - vec.x, y - vec.y);
            }

            template <typename T2>
            Point2<T>& operator+=(const Vec2<T2>& vec)
            {
                x += vec.x;
                y += vec.y;
                return *this;
            }

            template <typename T2>
            Point2<T> operator+(const Vec2<T2>& vec) const
            {
                return Point2<T>(x + vec.x, y + vec.y);
            }

            template <typename T2>
            Vec2<T> operator-(const Point2<T2>& p2) const
            {
                return Vec2<T>(x - p2.x, y - p2.y);
            }

            constexpr const T& operator[](size_t i) const
            {
                return data[i];
            }

            T& operator[](size_t i)
            {
                return data[i];
            }

        public:
            union {
                struct {
                    T x, y;
                };
                T data[2];
            };
    };

    typedef Point2<float> Point2f;
    typedef Point2<double> Point2d;
    typedef Point2<int> Point2i;

    template <typename T, typename T2>
    constexpr Point2<T> snap(const Point2<T>& p, const Point2<T2> gridsize)
    {
        return Point2<T>(snap(p.x, gridsize.x), snap(p.y, gridsize.y));
    }

    template <typename T, typename T2>
    constexpr Point2<T> smartSnap(const Point2<T>& p, const Point2<T2> gridsize)
    {
        return Point2<T>(smartSnap(p.x, gridsize.x), smartSnap(p.y, gridsize.y));
    }
}

#endif
<commit_msg>Add comparison operators to Point2<commit_after>#ifndef CPPMATH_POINT2_HPP
#define CPPMATH_POINT2_HPP

#include "Vector.hpp"
#include "../compat.hpp"

namespace math
{
    template <typename T>
    class Point2
    {
        public:
            constexpr Point2() : x(0), y(0) {};
            constexpr Point2(const T& x_, const T& y_) : x(x_), y(y_) {};

            Vec2<T> toVector() const
            {
                return Vec2<T>(x, y);
            }

            const Vec2<T>& asVector() const
            {
                return *reinterpret_cast<const Vec2<T>*>(this);
            }

            Vec2<T>& asVector()
            {
                return *reinterpret_cast<Vec2<T>*>(this);
            }

            void set(const T& a, const T& b)
            {
                x = a;
                y = b;
            }

            void set(const T& val)
            {
                x = y = val;
            }

            constexpr bool operator!=(const Point2<T>& p) const
            {
                return !operator==(p);
            }

            constexpr bool operator==(const Point2<T>& p) const
            {
                return x == p.x && y == p.y;
            }

            template <typename T2>
            constexpr operator Point2<T2>() const
            {
                return Point2<T2>(static_cast<T2>(x), static_cast<T2>(y));
            }

            template <typename T2>
            Point2<T>& operator-=(const Vec2<T2>& vec)
            {
                x -= vec.x;
                y -= vec.y;
                return *this;
            }

            template <typename T2>
            Point2<T> operator-(const Vec2<T2>& vec) const
            {
                return Point2<T>(x - vec.x, y - vec.y);
            }

            template <typename T2>
            Point2<T>& operator+=(const Vec2<T2>& vec)
            {
                x += vec.x;
                y += vec.y;
                return *this;
            }

            template <typename T2>
            Point2<T> operator+(const Vec2<T2>& vec) const
            {
                return Point2<T>(x + vec.x, y + vec.y);
            }

            template <typename T2>
            Vec2<T> operator-(const Point2<T2>& p2) const
            {
                return Vec2<T>(x - p2.x, y - p2.y);
            }

            constexpr const T& operator[](size_t i) const
            {
                return data[i];
            }

            T& operator[](size_t i)
            {
                return data[i];
            }

        public:
            union {
                struct {
                    T x, y;
                };
                T data[2];
            };
    };

    typedef Point2<float> Point2f;
    typedef Point2<double> Point2d;
    typedef Point2<int> Point2i;

    template <typename T, typename T2>
    constexpr Point2<T> snap(const Point2<T>& p, const Point2<T2> gridsize)
    {
        return Point2<T>(snap(p.x, gridsize.x), snap(p.y, gridsize.y));
    }

    template <typename T, typename T2>
    constexpr Point2<T> smartSnap(const Point2<T>& p, const Point2<T2> gridsize)
    {
        return Point2<T>(smartSnap(p.x, gridsize.x), smartSnap(p.y, gridsize.y));
    }
}

#endif
<|endoftext|>


<commit_before>/*

Copyright (c) 2003, Arvid Norberg
All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:

    * Redistributions of source code must retain the above copyright
      notice, this list of conditions and the following disclaimer.
    * Redistributions in binary form must reproduce the above copyright
      notice, this list of conditions and the following disclaimer in
      the documentation and/or other materials provided with the distribution.
    * Neither the name of the author nor the names of its
      contributors may be used to endorse or promote products derived
      from this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.

*/

#include "libtorrent/pch.hpp"

#include <cctype>
#include <algorithm>
#include <stdio.h>

#ifdef _MSC_VER
#pragma warning(push, 1)
#endif

#include <boost/optional.hpp>

#ifdef _MSC_VER
#pragma warning(pop)
#endif

#include "libtorrent/identify_client.hpp"
#include "libtorrent/fingerprint.hpp"
#include "libtorrent/escape_string.hpp"

namespace
{

	using namespace libtorrent;

	int decode_digit(char c)
	{
		if (is_digit(c)) return c - '0';
		return unsigned(c) - 'A' + 10;
	}

	// takes a peer id and returns a valid boost::optional
	// object if the peer id matched the azureus style encoding
	// the returned fingerprint contains information about the
	// client's id
	boost::optional<fingerprint> parse_az_style(const peer_id& id)
	{
		fingerprint ret("..", 0, 0, 0, 0);

		if (id[0] != '-' || !is_print(id[1]) || (id[2] < '0')
			|| (id[3] < '0') || (id[4] < '0')
			|| (id[5] < '0') || (id[6] < '0')
			|| id[7] != '-')
			return boost::optional<fingerprint>();

		ret.name[0] = id[1];
		ret.name[1] = id[2];
		ret.major_version = decode_digit(id[3]);
		ret.minor_version = decode_digit(id[4]);
		ret.revision_version = decode_digit(id[5]);
		ret.tag_version = decode_digit(id[6]);

		return boost::optional<fingerprint>(ret);
	}

	// checks if a peer id can possibly contain a shadow-style
	// identification
	boost::optional<fingerprint> parse_shadow_style(const peer_id& id)
	{
		fingerprint ret("..", 0, 0, 0, 0);

		if (!is_alpha(id[0]) && !is_digit(id[0]))
			return boost::optional<fingerprint>();

		if (std::equal(id.begin()+4, id.begin()+6, "--"))
		{
			if ((id[1] < '0') || (id[2] < '0')
				|| (id[3] < '0'))
				return boost::optional<fingerprint>();
			ret.major_version = decode_digit(id[1]);
			ret.minor_version = decode_digit(id[2]);
			ret.revision_version = decode_digit(id[3]);
		}
		else
		{
			if (id[8] != 0 || id[1] > 127 || id[2] > 127 || id[3] > 127)
				return boost::optional<fingerprint>();
			ret.major_version = id[1];
			ret.minor_version = id[2];
			ret.revision_version = id[3];
		}

		ret.name[0] = id[0];
		ret.name[1] = 0;

		ret.tag_version = 0;
		return boost::optional<fingerprint>(ret);
	}

	// checks if a peer id can possibly contain a mainline-style
	// identification
	boost::optional<fingerprint> parse_mainline_style(const peer_id& id)
	{
		char ids[21];
		std::copy(id.begin(), id.end(), ids);
		ids[20] = 0;
		fingerprint ret("..", 0, 0, 0, 0);
		ret.name[1] = 0;
		ret.tag_version = 0;
		if (sscanf(ids, "%c%d-%d-%d--", &ret.name[0], &ret.major_version, &ret.minor_version
			, &ret.revision_version) != 4
			|| !is_print(ret.name[0]))
			return boost::optional<fingerprint>();

		return boost::optional<fingerprint>(ret);
	}

	struct map_entry
	{
		char const* id;
		char const* name;
	};

	// only support BitTorrentSpecification
	// must be ordered alphabetically
	map_entry name_map[] =
	{
		{"A",  "ABC"}
		, {"AG",  "Ares"}
		, {"AR", "Arctic Torrent"}
		, {"AV", "Avicora"}
		, {"AX", "BitPump"}
		, {"AZ", "Azureus"}
		, {"A~",  "Ares"}
		, {"BB", "BitBuddy"}
		, {"BC", "BitComet"}
		, {"BF", "Bitflu"}
		, {"BG", "BTG"}
		, {"BR", "BitRocket"}
		, {"BS", "BTSlave"}
		, {"BX", "BittorrentX"}
		, {"CD", "Enhanced CTorrent"}
		, {"CT", "CTorrent"}
		, {"DE", "Deluge"}
		, {"EB", "EBit"}
		, {"ES", "electric sheep"}
		, {"HL", "Halite"}
		, {"HN", "Hydranode"}
		, {"KT", "KTorrent"}
		, {"LC", "LeechCraft"}
		, {"LK", "Linkage"}
		, {"LP", "lphant"}
		, {"LT", "libtorrent"}
		, {"M",  "Mainline"}
		, {"ML", "MLDonkey"}
		, {"MO", "Mono Torrent"}
		, {"MP", "MooPolice"}
		, {"MR", "Miro"}
		, {"MT", "Moonlight Torrent"}
		, {"O",  "Osprey Permaseed"}
		, {"PD",  "Pando"}
		, {"Q", "BTQueue"}
		, {"QT", "Qt 4"}
		, {"R",  "Tribler"}
		, {"S",  "Shadow"}
		, {"SB", "Swiftbit"}
		, {"SN", "ShareNet"}
		, {"SS", "SwarmScope"}
		, {"ST", "SymTorrent"}
		, {"SZ", "Shareaza"}
		, {"S~",  "Shareaza (beta)"}
		, {"T",  "BitTornado"}
		, {"TN", "Torrent.NET"}
		, {"TR", "Transmission"}
		, {"TS", "TorrentStorm"}
		, {"TT", "TuoTu"}
		, {"U",  "UPnP"}
		, {"UL", "uLeecher"}
		, {"UT", "uTorrent"}
		, {"XL", "Xunlei"}
		, {"XT", "XanTorrent"}
		, {"XX", "Xtorrent"}
		, {"ZT", "ZipTorrent"}
		, {"lt", "rTorrent"}
		, {"pX", "pHoeniX"}
		, {"qB", "qBittorrent"}
		, {"st", "SharkTorrent"}
	};

	struct generic_map_entry
	{
		int offset;
		char const* id;
		char const* name;
	};
	// non-standard names
	generic_map_entry generic_mappings[] =
	{
		{0, "Deadman Walking-", "Deadman"}
		, {5, "Azureus", "Azureus 2.0.3.2"}
		, {0, "DansClient", "XanTorrent"}
		, {4, "btfans", "SimpleBT"}
		, {0, "PRC.P---", "Bittorrent Plus! II"}
		, {0, "P87.P---", "Bittorrent Plus!"}
		, {0, "S587Plus", "Bittorrent Plus!"}
		, {0, "martini", "Martini Man"}
		, {0, "Plus---", "Bittorrent Plus"}
		, {0, "turbobt", "TurboBT"}
		, {0, "a00---0", "Swarmy"}
		, {0, "a02---0", "Swarmy"}
		, {0, "T00---0", "Teeweety"}
		, {0, "BTDWV-", "Deadman Walking"}
		, {2, "BS", "BitSpirit"}
		, {0, "Pando-", "Pando"}
		, {0, "LIME", "LimeWire"}
		, {0, "btuga", "BTugaXP"}
		, {0, "oernu", "BTugaXP"}
		, {0, "Mbrst", "Burst!"}
		, {0, "PEERAPP", "PeerApp"}
		, {0, "Plus", "Plus!"}
		, {0, "-Qt-", "Qt"}
		, {0, "exbc", "BitComet"}
		, {0, "DNA", "BitTorrent DNA"}
		, {0, "-G3", "G3 Torrent"}
		, {0, "-FG", "FlashGet"}
		, {0, "-ML", "MLdonkey"}
		, {0, "XBT", "XBT"}
		, {0, "OP", "Opera"}
		, {2, "RS", "Rufus"}
		, {0, "AZ2500BT", "BitTyrant"}
	};

	bool compare_id(map_entry const& lhs, map_entry const& rhs)
	{
		return lhs.id[0] < rhs.id[0]
			|| ((lhs.id[0] == rhs.id[0]) && (lhs.id[1] < rhs.id[1]));
	}

	std::string lookup(fingerprint const& f)
	{
		char identity[200];

		const int size = sizeof(name_map)/sizeof(name_map[0]);
		map_entry tmp = {f.name, ""};
		map_entry* i =
			std::lower_bound(name_map, name_map + size
				, tmp, &compare_id);

#ifndef NDEBUG
		for (int i = 1; i < size; ++i)
		{
			TORRENT_ASSERT(compare_id(name_map[i-1]
				, name_map[i]));
		}
#endif

		char temp[3];
		char const* name = 0;
		if (i < name_map + size && std::equal(f.name, f.name + 2, i->id))
		{
			name = i->name;
		}
		else
		{
			// if we don't have this client in the list
			// just use the one or two letter code
			memcpy(temp, f.name, 2);
			temp[2] = 0;
			name = temp;
		}

		int num_chars = snprintf(identity, sizeof(identity), "%s %u.%u.%u", name
			, f.major_version, f.minor_version, f.revision_version);

		if (f.tag_version != 0)
		{
			snprintf(identity + num_chars, sizeof(identity) - num_chars
				, ".%u", f.tag_version);
		}

		return identity;
	}

	bool find_string(unsigned char const* id, char const* search)
	{
		return std::equal(search, search + std::strlen(search), id);
	}
}

namespace libtorrent
{

	boost::optional<fingerprint> client_fingerprint(peer_id const& p)
	{
		// look for azureus style id
		boost::optional<fingerprint> f;
		f = parse_az_style(p);
		if (f) return f;

		// look for shadow style id
		f = parse_shadow_style(p);
		if (f) return f;

		// look for mainline style id
		f = parse_mainline_style(p);
		if (f) return f;
		return f;
	}

	std::string identify_client(peer_id const& p)
	{
		peer_id::const_iterator PID = p.begin();
		boost::optional<fingerprint> f;

		if (p.is_all_zeros()) return "Unknown";

		// ----------------------
		// non standard encodings
		// ----------------------

		int num_generic_mappings = sizeof(generic_mappings) / sizeof(generic_mappings[0]);

		for (int i = 0; i < num_generic_mappings; ++i)
		{
			generic_map_entry const& e = generic_mappings[i];
			if (find_string(PID + e.offset, e.id)) return e.name;
		}

		if (find_string(PID, "-BOW") && PID[7] == '-')
			return "Bits on Wheels " + std::string((char const*)PID + 4, (char const*)PID + 7);

		if (find_string(PID, "eX"))
		{
			std::string user((char const*)PID + 2, (char const*)PID + 14);
			return std::string("eXeem ('") + user.c_str() + "')";
		}

		if (std::equal(PID, PID + 13, "\0\0\0\0\0\0\0\0\0\0\0\0\x97"))
			return "Experimental 3.2.1b2";

		if (std::equal(PID, PID + 13, "\0\0\0\0\0\0\0\0\0\0\0\0\0"))
			return "Experimental 3.1";

		// look for azureus style id
		f = parse_az_style(p);
		if (f) return lookup(*f);

		// look for shadow style id
		f = parse_shadow_style(p);
		if (f) return lookup(*f);

		// look for mainline style id
		f = parse_mainline_style(p);
		if (f) return lookup(*f);

		if (std::equal(PID, PID + 12, "\0\0\0\0\0\0\0\0\0\0\0\0"))
			return "Generic";

		std::string unknown("Unknown [");
		for (peer_id::const_iterator i = p.begin(); i != p.end(); ++i)
		{
			unknown += is_print(char(*i))?*i:'.';
		}
		unknown += "]";
		return unknown;
	}

}
<commit_msg>added some clients to identify_client<commit_after>/*

Copyright (c) 2003, Arvid Norberg
All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:

    * Redistributions of source code must retain the above copyright
      notice, this list of conditions and the following disclaimer.
    * Redistributions in binary form must reproduce the above copyright
      notice, this list of conditions and the following disclaimer in
      the documentation and/or other materials provided with the distribution.
    * Neither the name of the author nor the names of its
      contributors may be used to endorse or promote products derived
      from this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.

*/

#include "libtorrent/pch.hpp"

#include <cctype>
#include <algorithm>
#include <stdio.h>

#ifdef _MSC_VER
#pragma warning(push, 1)
#endif

#include <boost/optional.hpp>

#ifdef _MSC_VER
#pragma warning(pop)
#endif

#include "libtorrent/identify_client.hpp"
#include "libtorrent/fingerprint.hpp"
#include "libtorrent/escape_string.hpp"

namespace
{

	using namespace libtorrent;

	int decode_digit(char c)
	{
		if (is_digit(c)) return c - '0';
		return unsigned(c) - 'A' + 10;
	}

	// takes a peer id and returns a valid boost::optional
	// object if the peer id matched the azureus style encoding
	// the returned fingerprint contains information about the
	// client's id
	boost::optional<fingerprint> parse_az_style(const peer_id& id)
	{
		fingerprint ret("..", 0, 0, 0, 0);

		if (id[0] != '-' || !is_print(id[1]) || (id[2] < '0')
			|| (id[3] < '0') || (id[4] < '0')
			|| (id[5] < '0') || (id[6] < '0')
			|| id[7] != '-')
			return boost::optional<fingerprint>();

		ret.name[0] = id[1];
		ret.name[1] = id[2];
		ret.major_version = decode_digit(id[3]);
		ret.minor_version = decode_digit(id[4]);
		ret.revision_version = decode_digit(id[5]);
		ret.tag_version = decode_digit(id[6]);

		return boost::optional<fingerprint>(ret);
	}

	// checks if a peer id can possibly contain a shadow-style
	// identification
	boost::optional<fingerprint> parse_shadow_style(const peer_id& id)
	{
		fingerprint ret("..", 0, 0, 0, 0);

		if (!is_alpha(id[0]) && !is_digit(id[0]))
			return boost::optional<fingerprint>();

		if (std::equal(id.begin()+4, id.begin()+6, "--"))
		{
			if ((id[1] < '0') || (id[2] < '0')
				|| (id[3] < '0'))
				return boost::optional<fingerprint>();
			ret.major_version = decode_digit(id[1]);
			ret.minor_version = decode_digit(id[2]);
			ret.revision_version = decode_digit(id[3]);
		}
		else
		{
			if (id[8] != 0 || id[1] > 127 || id[2] > 127 || id[3] > 127)
				return boost::optional<fingerprint>();
			ret.major_version = id[1];
			ret.minor_version = id[2];
			ret.revision_version = id[3];
		}

		ret.name[0] = id[0];
		ret.name[1] = 0;

		ret.tag_version = 0;
		return boost::optional<fingerprint>(ret);
	}

	// checks if a peer id can possibly contain a mainline-style
	// identification
	boost::optional<fingerprint> parse_mainline_style(const peer_id& id)
	{
		char ids[21];
		std::copy(id.begin(), id.end(), ids);
		ids[20] = 0;
		fingerprint ret("..", 0, 0, 0, 0);
		ret.name[1] = 0;
		ret.tag_version = 0;
		if (sscanf(ids, "%c%d-%d-%d--", &ret.name[0], &ret.major_version, &ret.minor_version
			, &ret.revision_version) != 4
			|| !is_print(ret.name[0]))
			return boost::optional<fingerprint>();

		return boost::optional<fingerprint>(ret);
	}

	struct map_entry
	{
		char const* id;
		char const* name;
	};

	// only support BitTorrentSpecification
	// must be ordered alphabetically
	map_entry name_map[] =
	{
		{"A",  "ABC"}
		, {"AG",  "Ares"}
		, {"AR", "Arctic Torrent"}
		, {"AV", "Avicora"}
		, {"AX", "BitPump"}
		, {"AZ", "Azureus"}
		, {"A~",  "Ares"}
		, {"BB", "BitBuddy"}
		, {"BC", "BitComet"}
		, {"BF", "Bitflu"}
		, {"BG", "BTG"}
		, {"BR", "BitRocket"}
		, {"BS", "BTSlave"}
		, {"BX", "BittorrentX"}
		, {"CD", "Enhanced CTorrent"}
		, {"CT", "CTorrent"}
		, {"DE", "Deluge"}
		, {"EB", "EBit"}
		, {"ES", "electric sheep"}
		, {"HL", "Halite"}
		, {"HN", "Hydranode"}
		, {"KT", "KTorrent"}
		, {"LC", "LeechCraft"}
		, {"LK", "Linkage"}
		, {"LP", "lphant"}
		, {"LT", "libtorrent"}
		, {"M",  "Mainline"}
		, {"ML", "MLDonkey"}
		, {"MO", "Mono Torrent"}
		, {"MP", "MooPolice"}
		, {"MR", "Miro"}
		, {"MT", "Moonlight Torrent"}
		, {"O",  "Osprey Permaseed"}
		, {"PD",  "Pando"}
		, {"Q", "BTQueue"}
		, {"QD", "QQDownload"}
		, {"QT", "Qt 4"}
		, {"R",  "Tribler"}
		, {"S",  "Shadow"}
		, {"SB", "Swiftbit"}
		, {"SD", "Xunlei"}
		, {"SN", "ShareNet"}
		, {"SS", "SwarmScope"}
		, {"ST", "SymTorrent"}
		, {"SZ", "Shareaza"}
		, {"S~",  "Shareaza (beta)"}
		, {"T",  "BitTornado"}
		, {"TN", "Torrent.NET"}
		, {"TR", "Transmission"}
		, {"TS", "TorrentStorm"}
		, {"TT", "TuoTu"}
		, {"U",  "UPnP"}
		, {"UL", "uLeecher"}
		, {"UT", "uTorrent"}
		, {"VG", "Vagaa"}
		, {"XL", "Xunlei"}
		, {"XT", "XanTorrent"}
		, {"XX", "Xtorrent"}
		, {"ZT", "ZipTorrent"}
		, {"lt", "rTorrent"}
		, {"pX", "pHoeniX"}
		, {"qB", "qBittorrent"}
		, {"st", "SharkTorrent"}
	};

	struct generic_map_entry
	{
		int offset;
		char const* id;
		char const* name;
	};
	// non-standard names
	generic_map_entry generic_mappings[] =
	{
		{0, "Deadman Walking-", "Deadman"}
		, {5, "Azureus", "Azureus 2.0.3.2"}
		, {0, "DansClient", "XanTorrent"}
		, {4, "btfans", "SimpleBT"}
		, {0, "PRC.P---", "Bittorrent Plus! II"}
		, {0, "P87.P---", "Bittorrent Plus!"}
		, {0, "S587Plus", "Bittorrent Plus!"}
		, {0, "martini", "Martini Man"}
		, {0, "Plus---", "Bittorrent Plus"}
		, {0, "turbobt", "TurboBT"}
		, {0, "a00---0", "Swarmy"}
		, {0, "a02---0", "Swarmy"}
		, {0, "T00---0", "Teeweety"}
		, {0, "BTDWV-", "Deadman Walking"}
		, {2, "BS", "BitSpirit"}
		, {0, "Pando-", "Pando"}
		, {0, "LIME", "LimeWire"}
		, {0, "btuga", "BTugaXP"}
		, {0, "oernu", "BTugaXP"}
		, {0, "Mbrst", "Burst!"}
		, {0, "PEERAPP", "PeerApp"}
		, {0, "Plus", "Plus!"}
		, {0, "-Qt-", "Qt"}
		, {0, "exbc", "BitComet"}
		, {0, "DNA", "BitTorrent DNA"}
		, {0, "-G3", "G3 Torrent"}
		, {0, "-FG", "FlashGet"}
		, {0, "-ML", "MLdonkey"}
		, {0, "XBT", "XBT"}
		, {0, "OP", "Opera"}
		, {2, "RS", "Rufus"}
		, {0, "AZ2500BT", "BitTyrant"}
	};

	bool compare_id(map_entry const& lhs, map_entry const& rhs)
	{
		return lhs.id[0] < rhs.id[0]
			|| ((lhs.id[0] == rhs.id[0]) && (lhs.id[1] < rhs.id[1]));
	}

	std::string lookup(fingerprint const& f)
	{
		char identity[200];

		const int size = sizeof(name_map)/sizeof(name_map[0]);
		map_entry tmp = {f.name, ""};
		map_entry* i =
			std::lower_bound(name_map, name_map + size
				, tmp, &compare_id);

#ifndef NDEBUG
		for (int i = 1; i < size; ++i)
		{
			TORRENT_ASSERT(compare_id(name_map[i-1]
				, name_map[i]));
		}
#endif

		char temp[3];
		char const* name = 0;
		if (i < name_map + size && std::equal(f.name, f.name + 2, i->id))
		{
			name = i->name;
		}
		else
		{
			// if we don't have this client in the list
			// just use the one or two letter code
			memcpy(temp, f.name, 2);
			temp[2] = 0;
			name = temp;
		}

		int num_chars = snprintf(identity, sizeof(identity), "%s %u.%u.%u", name
			, f.major_version, f.minor_version, f.revision_version);

		if (f.tag_version != 0)
		{
			snprintf(identity + num_chars, sizeof(identity) - num_chars
				, ".%u", f.tag_version);
		}

		return identity;
	}

	bool find_string(unsigned char const* id, char const* search)
	{
		return std::equal(search, search + std::strlen(search), id);
	}
}

namespace libtorrent
{

	boost::optional<fingerprint> client_fingerprint(peer_id const& p)
	{
		// look for azureus style id
		boost::optional<fingerprint> f;
		f = parse_az_style(p);
		if (f) return f;

		// look for shadow style id
		f = parse_shadow_style(p);
		if (f) return f;

		// look for mainline style id
		f = parse_mainline_style(p);
		if (f) return f;
		return f;
	}

	std::string identify_client(peer_id const& p)
	{
		peer_id::const_iterator PID = p.begin();
		boost::optional<fingerprint> f;

		if (p.is_all_zeros()) return "Unknown";

		// ----------------------
		// non standard encodings
		// ----------------------

		int num_generic_mappings = sizeof(generic_mappings) / sizeof(generic_mappings[0]);

		for (int i = 0; i < num_generic_mappings; ++i)
		{
			generic_map_entry const& e = generic_mappings[i];
			if (find_string(PID + e.offset, e.id)) return e.name;
		}

		if (find_string(PID, "-BOW") && PID[7] == '-')
			return "Bits on Wheels " + std::string((char const*)PID + 4, (char const*)PID + 7);

		if (find_string(PID, "eX"))
		{
			std::string user((char const*)PID + 2, (char const*)PID + 14);
			return std::string("eXeem ('") + user.c_str() + "')";
		}

		if (std::equal(PID, PID + 13, "\0\0\0\0\0\0\0\0\0\0\0\0\x97"))
			return "Experimental 3.2.1b2";

		if (std::equal(PID, PID + 13, "\0\0\0\0\0\0\0\0\0\0\0\0\0"))
			return "Experimental 3.1";

		// look for azureus style id
		f = parse_az_style(p);
		if (f) return lookup(*f);

		// look for shadow style id
		f = parse_shadow_style(p);
		if (f) return lookup(*f);

		// look for mainline style id
		f = parse_mainline_style(p);
		if (f) return lookup(*f);

		if (std::equal(PID, PID + 12, "\0\0\0\0\0\0\0\0\0\0\0\0"))
			return "Generic";

		std::string unknown("Unknown [");
		for (peer_id::const_iterator i = p.begin(); i != p.end(); ++i)
		{
			unknown += is_print(char(*i))?*i:'.';
		}
		unknown += "]";
		return unknown;
	}

}
<|endoftext|>


<commit_before>/*=========================================================================

  Program:   Visualization Toolkit
  Module:    vtkMapper.cxx
  Language:  C++
  Date:      $Date$
  Version:   $Revision$

Copyright (c) 1993-1996 Ken Martin, Will Schroeder, Bill Lorensen.

This software is copyrighted by Ken Martin, Will Schroeder and Bill Lorensen.
The following terms apply to all files associated with the software unless
explicitly disclaimed in individual files. This copyright specifically does
not apply to the related textbook "The Visualization Toolkit" ISBN
013199837-4 published by Prentice Hall which is covered by its own copyright.

The authors hereby grant permission to use, copy, and distribute this
software and its documentation for any purpose, provided that existing
copyright notices are retained in all copies and that this notice is included
verbatim in any distributions. Additionally, the authors grant permission to
modify this software and its documentation for any purpose, provided that
such modifications are not distributed without the explicit consent of the
authors and that existing copyright notices are retained in all copies. Some
of the algorithms implemented by this software are patented, observe all
applicable patent law.

IN NO EVENT SHALL THE AUTHORS OR DISTRIBUTORS BE LIABLE TO ANY PARTY FOR
DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
OF THE USE OF THIS SOFTWARE, ITS DOCUMENTATION, OR ANY DERIVATIVES THEREOF,
EVEN IF THE AUTHORS HAVE BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

THE AUTHORS AND DISTRIBUTORS SPECIFICALLY DISCLAIM ANY WARRANTIES, INCLUDING,
BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
PARTICULAR PURPOSE, AND NON-INFRINGEMENT.  THIS SOFTWARE IS PROVIDED ON AN
"AS IS" BASIS, AND THE AUTHORS AND DISTRIBUTORS HAVE NO OBLIGATION TO PROVIDE
MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.

=========================================================================*/
#include "vtkMapper.h"

// Description:
// Construct with initial range (0,1).
vtkMapper::vtkMapper()
{
  this->Input = NULL;
  this->Colors = NULL;

  this->StartRender = NULL;
  this->StartRenderArgDelete = NULL;
  this->StartRenderArg = NULL;
  this->EndRender = NULL;
  this->EndRenderArgDelete = NULL;
  this->EndRenderArg = NULL;

  this->LookupTable = NULL;

  this->ScalarsVisible = 1;
  this->ScalarRange[0] = 0.0; this->ScalarRange[1] = 1.0;

  this->SelfCreatedLookupTable = 0;
}

vtkMapper::~vtkMapper()
{
  if ( this->SelfCreatedLookupTable && this->LookupTable != NULL)
    this->LookupTable->Delete();
  if ( this->Colors != NULL ) this->Colors->Delete();
}

// Description:
// Overload standard modified time function. If lookup table is modified,
// then this object is modified as well.
unsigned long vtkMapper::GetMTime()
{
  unsigned long mTime=this->MTime.GetMTime();
  unsigned long lutMTime;

  if ( this->LookupTable != NULL )
    {
    lutMTime = this->LookupTable->GetMTime();
    mTime = ( lutMTime > mTime ? lutMTime : mTime );
    }

  return mTime;
}

void vtkMapper::operator=(const vtkMapper& m)
{
  this->SetLookupTable(m.LookupTable);

  this->SetScalarsVisible(m.ScalarsVisible);
  this->SetScalarRange(m.ScalarRange[0], m.ScalarRange[1]);

  this->SetStartRender(m.StartRender,m.StartRenderArg);
  this->SetEndRender(m.EndRender,m.EndRenderArg);
}

vtkColorScalars *vtkMapper::GetColors()
{
  vtkPointData *pd;
  vtkScalars *scalars;
  int i, numPts;
  vtkColorScalars *colors;

  // make sure we have a lookup table
  if ( this->LookupTable == NULL ) this->CreateDefaultLookupTable();
  this->LookupTable->Build();

  //
  // create colors
  //
  numPts = this->Input->GetNumberOfPoints();
  if ( this->ScalarsVisible && (pd=this->Input->GetPointData()) &&
       (scalars=pd->GetScalars()) )
    {
    if ( strcmp(scalars->GetScalarType(),"ColorScalar") )
      {
      if ( this->Colors == NULL )
	{
	this->Colors = new vtkAPixmap(numPts);
	}
      else
	{
	int numColors=this->Colors->GetNumberOfColors();
	if ( numColors < numPts ) this->Colors->Allocate(numPts);
	}

      this->LookupTable->SetTableRange(this->ScalarRange);
      for (i=0; i < numPts; i++)
	{
	this->Colors->SetColor(i,this->LookupTable->
			       MapValue(scalars->GetScalar(i)));
	}
      colors = this->Colors;
      }
    else //color scalar
      {
      colors = (vtkColorScalars *)scalars;
      }
    }
  else
    {
    if ( this->Colors ) this->Colors->Delete();
    this->Colors = colors = NULL;
    }

  return colors;
}

// Description:
// Specify a function to be called before rendering process begins.
// Function will be called with argument provided.
void vtkMapper::SetStartRender(void (*f)(void *), void *arg)
{
  if ( f != this->StartRender || arg != this->StartRenderArg )
    {
    // delete the current arg if there is one and a delete meth
    if ((this->StartRenderArg)&&(this->StartRenderArgDelete))
      {
      (*this->StartRenderArgDelete)(this->StartRenderArg);
      }
    this->StartRender = f;
    this->StartRenderArg = arg;
    this->Modified();
    }
}

// Description:
// Specify a method to delete the user specified argument to the
// StartRenderMethod. This is an optional capability.
void vtkMapper::SetStartRenderArgDelete(void (*f)(void *))
{
  if ( f != this->StartRenderArgDelete)
    {
    this->StartRenderArgDelete = f;
    this->Modified();
    }
}

// Description:
// Specify a method to delete the user specified argument to the
// EndRenderMethod. This is an optional capability.
void vtkMapper::SetEndRenderArgDelete(void (*f)(void *))
{
  if ( f != this->EndRenderArgDelete)
    {
    this->EndRenderArgDelete = f;
    this->Modified();
    }
}

// Description:
// Specify a function to be called when rendering process completes.
// Function will be called with argument provided.
void vtkMapper::SetEndRender(void (*f)(void *), void *arg)
{
  if ( f != this->EndRender || arg != EndRenderArg )
    {
    // delete the current arg if there is one and a delete meth
    if ((this->EndRenderArg)&&(this->EndRenderArgDelete))
      {
      (*this->EndRenderArgDelete)(this->EndRenderArg);
      }
    this->EndRender = f;
    this->EndRenderArg = arg;
    this->Modified();
    }
}

// Description:
// Specify a lookup table for the mapper to use.
void vtkMapper::SetLookupTable(vtkLookupTable *lut)
{
  if ( this->LookupTable != lut )
    {
    if ( this->SelfCreatedLookupTable ) this->LookupTable->Delete();
    this->SelfCreatedLookupTable = 0;
    this->LookupTable = lut;
    this->Modified();
    }
}

vtkLookupTable *vtkMapper::GetLookupTable()
{
  if ( this->LookupTable == NULL ) this->CreateDefaultLookupTable();
  return this->LookupTable;
}

void vtkMapper::CreateDefaultLookupTable()
{
  if ( this->SelfCreatedLookupTable ) this->LookupTable->Delete();
  this->LookupTable = new vtkLookupTable;
  this->SelfCreatedLookupTable = 1;
}

float *vtkMapper::GetCenter()
{
  static float center[3];
  float *bounds;

  bounds = this->GetBounds();
  for (int i=0; i<3; i++) center[i] = (bounds[2*i+1] + bounds[2*i]) / 2.0;
  return center;
}

// Description:
// Update the network connected to this mapper.
void vtkMapper::Update()
{
  if ( this->Input )
    {
    this->Input->Update();
    }
}

void vtkMapper::PrintSelf(ostream& os, vtkIndent indent)
{
  vtkObject::PrintSelf(os,indent);

  if ( this->Input )
    {
    os << indent << "Input: (" << this->Input << ")\n";
    }
  else
    {
    os << indent << "Input: (none)\n";
    }

  os << indent << "Build Time: " <<this->BuildTime.GetMTime() << "\n";
  if ( this->StartRender )
    {
    os << indent << "Start Render method defined.\n";
    }
  else
    {
    os << indent << "No Start Render method.\n";
    }

  if ( this->EndRender )
    {
    os << indent << "End Render method defined.\n";
    }
  else
    {
    os << indent << "No End Render method.\n";
    }

  if ( this->LookupTable )
    {
    os << indent << "Lookup Table:\n";
    this->LookupTable->PrintSelf(os,indent.GetNextIndent());
    }
  else
    {
    os << indent << "Lookup Table: (none)\n";
    }
  os << indent << "Scalars Visible: "
    << (this->ScalarsVisible ? "On\n" : "Off\n");

  float *range = this->GetScalarRange();
  os << indent << "Scalar Range: (" << range[0] << ", " << range[1] << ")\n";
}
<commit_msg>bug fix in GetColors<commit_after>/*=========================================================================

  Program:   Visualization Toolkit
  Module:    vtkMapper.cxx
  Language:  C++
  Date:      $Date$
  Version:   $Revision$

Copyright (c) 1993-1996 Ken Martin, Will Schroeder, Bill Lorensen.

This software is copyrighted by Ken Martin, Will Schroeder and Bill Lorensen.
The following terms apply to all files associated with the software unless
explicitly disclaimed in individual files. This copyright specifically does
not apply to the related textbook "The Visualization Toolkit" ISBN
013199837-4 published by Prentice Hall which is covered by its own copyright.

The authors hereby grant permission to use, copy, and distribute this
software and its documentation for any purpose, provided that existing
copyright notices are retained in all copies and that this notice is included
verbatim in any distributions. Additionally, the authors grant permission to
modify this software and its documentation for any purpose, provided that
such modifications are not distributed without the explicit consent of the
authors and that existing copyright notices are retained in all copies. Some
of the algorithms implemented by this software are patented, observe all
applicable patent law.

IN NO EVENT SHALL THE AUTHORS OR DISTRIBUTORS BE LIABLE TO ANY PARTY FOR
DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
OF THE USE OF THIS SOFTWARE, ITS DOCUMENTATION, OR ANY DERIVATIVES THEREOF,
EVEN IF THE AUTHORS HAVE BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

THE AUTHORS AND DISTRIBUTORS SPECIFICALLY DISCLAIM ANY WARRANTIES, INCLUDING,
BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
PARTICULAR PURPOSE, AND NON-INFRINGEMENT.  THIS SOFTWARE IS PROVIDED ON AN
"AS IS" BASIS, AND THE AUTHORS AND DISTRIBUTORS HAVE NO OBLIGATION TO PROVIDE
MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.

=========================================================================*/
#include "vtkMapper.h"

// Description:
// Construct with initial range (0,1).
vtkMapper::vtkMapper()
{
  this->Input = NULL;
  this->Colors = NULL;

  this->StartRender = NULL;
  this->StartRenderArgDelete = NULL;
  this->StartRenderArg = NULL;
  this->EndRender = NULL;
  this->EndRenderArgDelete = NULL;
  this->EndRenderArg = NULL;

  this->LookupTable = NULL;

  this->ScalarsVisible = 1;
  this->ScalarRange[0] = 0.0; this->ScalarRange[1] = 1.0;

  this->SelfCreatedLookupTable = 0;
}

vtkMapper::~vtkMapper()
{
  if ( this->SelfCreatedLookupTable && this->LookupTable != NULL)
    this->LookupTable->Delete();
  if ( this->Colors != NULL ) this->Colors->Delete();
}

// Description:
// Overload standard modified time function. If lookup table is modified,
// then this object is modified as well.
unsigned long vtkMapper::GetMTime()
{
  unsigned long mTime=this->MTime.GetMTime();
  unsigned long lutMTime;

  if ( this->LookupTable != NULL )
    {
    lutMTime = this->LookupTable->GetMTime();
    mTime = ( lutMTime > mTime ? lutMTime : mTime );
    }

  return mTime;
}

void vtkMapper::operator=(const vtkMapper& m)
{
  this->SetLookupTable(m.LookupTable);

  this->SetScalarsVisible(m.ScalarsVisible);
  this->SetScalarRange(m.ScalarRange[0], m.ScalarRange[1]);

  this->SetStartRender(m.StartRender,m.StartRenderArg);
  this->SetEndRender(m.EndRender,m.EndRenderArg);
}

vtkColorScalars *vtkMapper::GetColors()
{
  vtkPointData *pd;
  vtkScalars *scalars;
  int i, numPts;
  vtkColorScalars *colors;

  // make sure we have a lookup table
  if ( this->LookupTable == NULL ) this->CreateDefaultLookupTable();
  this->LookupTable->Build();

  //
  // create colors
  //
  numPts = this->Input->GetNumberOfPoints();
  if ( this->ScalarsVisible && (pd=this->Input->GetPointData()) &&
       (scalars=pd->GetScalars()) )
    {
    if ( strcmp(scalars->GetScalarType(),"ColorScalar") )
      {
      if ( this->Colors == NULL )
	{
	this->Colors = new vtkAPixmap(numPts);
	}
      else
	{
	int numColors=this->Colors->GetNumberOfColors();
	if ( numColors < numPts ) this->Colors->Allocate(numPts);
	}

      this->LookupTable->SetTableRange(this->ScalarRange);
      for (i=0; i < numPts; i++)
	{
	this->Colors->SetColor(i,this->LookupTable->
			       MapValue(scalars->GetScalar(i)));
	}
      // make sure that MaxID is set correctly
      this->Colors->InsertColor(numPts-1,this->LookupTable->
			        MapValue(scalars->GetScalar(numPts-1)));

      colors = this->Colors;
      }
    else //color scalar
      {
      colors = (vtkColorScalars *)scalars;
      }
    }
  else
    {
    if ( this->Colors ) this->Colors->Delete();
    this->Colors = colors = NULL;
    }

  return colors;
}

// Description:
// Specify a function to be called before rendering process begins.
// Function will be called with argument provided.
void vtkMapper::SetStartRender(void (*f)(void *), void *arg)
{
  if ( f != this->StartRender || arg != this->StartRenderArg )
    {
    // delete the current arg if there is one and a delete meth
    if ((this->StartRenderArg)&&(this->StartRenderArgDelete))
      {
      (*this->StartRenderArgDelete)(this->StartRenderArg);
      }
    this->StartRender = f;
    this->StartRenderArg = arg;
    this->Modified();
    }
}

// Description:
// Specify a method to delete the user specified argument to the
// StartRenderMethod. This is an optional capability.
void vtkMapper::SetStartRenderArgDelete(void (*f)(void *))
{
  if ( f != this->StartRenderArgDelete)
    {
    this->StartRenderArgDelete = f;
    this->Modified();
    }
}

// Description:
// Specify a method to delete the user specified argument to the
// EndRenderMethod. This is an optional capability.
void vtkMapper::SetEndRenderArgDelete(void (*f)(void *))
{
  if ( f != this->EndRenderArgDelete)
    {
    this->EndRenderArgDelete = f;
    this->Modified();
    }
}

// Description:
// Specify a function to be called when rendering process completes.
// Function will be called with argument provided.
void vtkMapper::SetEndRender(void (*f)(void *), void *arg)
{
  if ( f != this->EndRender || arg != EndRenderArg )
    {
    // delete the current arg if there is one and a delete meth
    if ((this->EndRenderArg)&&(this->EndRenderArgDelete))
      {
      (*this->EndRenderArgDelete)(this->EndRenderArg);
      }
    this->EndRender = f;
    this->EndRenderArg = arg;
    this->Modified();
    }
}

// Description:
// Specify a lookup table for the mapper to use.
void vtkMapper::SetLookupTable(vtkLookupTable *lut)
{
  if ( this->LookupTable != lut )
    {
    if ( this->SelfCreatedLookupTable ) this->LookupTable->Delete();
    this->SelfCreatedLookupTable = 0;
    this->LookupTable = lut;
    this->Modified();
    }
}

vtkLookupTable *vtkMapper::GetLookupTable()
{
  if ( this->LookupTable == NULL ) this->CreateDefaultLookupTable();
  return this->LookupTable;
}

void vtkMapper::CreateDefaultLookupTable()
{
  if ( this->SelfCreatedLookupTable ) this->LookupTable->Delete();
  this->LookupTable = new vtkLookupTable;
  this->SelfCreatedLookupTable = 1;
}

float *vtkMapper::GetCenter()
{
  static float center[3];
  float *bounds;

  bounds = this->GetBounds();
  for (int i=0; i<3; i++) center[i] = (bounds[2*i+1] + bounds[2*i]) / 2.0;
  return center;
}

// Description:
// Update the network connected to this mapper.
void vtkMapper::Update()
{
  if ( this->Input )
    {
    this->Input->Update();
    }
}

void vtkMapper::PrintSelf(ostream& os, vtkIndent indent)
{
  vtkObject::PrintSelf(os,indent);

  if ( this->Input )
    {
    os << indent << "Input: (" << this->Input << ")\n";
    }
  else
    {
    os << indent << "Input: (none)\n";
    }

  os << indent << "Build Time: " <<this->BuildTime.GetMTime() << "\n";
  if ( this->StartRender )
    {
    os << indent << "Start Render method defined.\n";
    }
  else
    {
    os << indent << "No Start Render method.\n";
    }

  if ( this->EndRender )
    {
    os << indent << "End Render method defined.\n";
    }
  else
    {
    os << indent << "No End Render method.\n";
    }

  if ( this->LookupTable )
    {
    os << indent << "Lookup Table:\n";
    this->LookupTable->PrintSelf(os,indent.GetNextIndent());
    }
  else
    {
    os << indent << "Lookup Table: (none)\n";
    }
  os << indent << "Scalars Visible: "
    << (this->ScalarsVisible ? "On\n" : "Off\n");

  float *range = this->GetScalarRange();
  os << indent << "Scalar Range: (" << range[0] << ", " << range[1] << ")\n";
}
<|endoftext|>