<commit_before>//
//  libavg - Media Playback Engine.
//  Copyright (C) 2003-2008 Ulrich von Zadow
//
//  This library is free software; you can redistribute it and/or
//  modify it under the terms of the GNU Lesser General Public
//  License as published by the Free Software Foundation; either
//  version 2 of the License, or (at your option) any later version.
//
//  This library is distributed in the hope that it will be useful,
//  but WITHOUT ANY WARRANTY; without even the implied warranty of
//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
//  Lesser General Public License for more details.
//
//  You should have received a copy of the GNU Lesser General Public
//  License along with this library; if not, write to the Free Software
//  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
//
//  Current versions can be found at www.libavg.de
//

#include "Canvas.h"

#include "Player.h"
#include "AVGNode.h"
#include "SDLDisplayEngine.h"
#include "Shape.h"
#include "OffscreenCanvas.h"

#include "../base/Exception.h"
#include "../base/Logger.h"
#include "../base/ScopeTimer.h"

#include <iostream>

using namespace std;
using namespace boost;

namespace avg {

Canvas::Canvas(Player * pPlayer)
    : m_pPlayer(pPlayer),
      m_pDisplayEngine(0),
      m_PlaybackEndSignal(&IPlaybackEndListener::onPlaybackEnd),
      m_FrameEndSignal(&IFrameEndListener::onFrameEnd),
      m_PreRenderSignal(&IPreRenderListener::onPreRender)
{
}

Canvas::~Canvas()
{
}

void Canvas::setRoot(NodePtr pRootNode)
{
    assert(!m_pRootNode);
    m_pRootNode = dynamic_pointer_cast<CanvasNode>(pRootNode);
    m_pRootNode->setParent(DivNodeWeakPtr(), VisibleNode::NS_CONNECTED,
            shared_from_this());
    registerNode(m_pRootNode);
}

void Canvas::initPlayback(SDLDisplayEngine* pDisplayEngine, AudioEngine* pAudioEngine,
        int multiSampleSamples)
{
    m_pDisplayEngine = pDisplayEngine;
    m_pRootNode->setRenderingEngines(m_pDisplayEngine, pAudioEngine);
    m_MultiSampleSamples = multiSampleSamples;
}

void Canvas::stopPlayback()
{
    if (m_pDisplayEngine) {
        m_PlaybackEndSignal.emit();
        m_pRootNode->disconnect(true);
        m_pRootNode = CanvasNodePtr();
        m_IDMap.clear();
        m_pDisplayEngine = 0;
    }
}

VisibleNodePtr Canvas::getElementByID(const std::string& id)
{
    if (m_IDMap.find(id) != m_IDMap.end()) {
        return m_IDMap.find(id)->second;
    } else {
        AVG_TRACE(Logger::WARNING, "getElementByID(\"" << id << "\") failed.");
        return VisibleNodePtr();
    }
}

void Canvas::registerNode(VisibleNodePtr pNode)
{
    addNodeID(pNode);
    DivNodePtr pDivNode = boost::dynamic_pointer_cast<DivNode>(pNode);
    if (pDivNode) {
        for (unsigned i=0; i<pDivNode->getNumChildren(); i++) {
            registerNode(pDivNode->getVChild(i));
        }
    }
}

void Canvas::addNodeID(VisibleNodePtr pNode)
{
    const string& id = pNode->getID();
    if (id != "") {
        if (m_IDMap.find(id) != m_IDMap.end() &&
            m_IDMap.find(id)->second != pNode)
        {
            throw (Exception (AVG_ERR_XML_DUPLICATE_ID,
                string("Error: duplicate id ")+id));
        }
        m_IDMap.insert(NodeIDMap::value_type(id, pNode));
    }
}

void Canvas::removeNodeID(const string& id)
{
    if (id != "") {
        map<string, VisibleNodePtr>::iterator it;
        it = m_IDMap.find(id);
        if (it != m_IDMap.end()) {
            m_IDMap.erase(it);
        } else {
            cerr << "removeNodeID(\"" << id << "\") failed." << endl;
            AVG_ASSERT(false);
        }
    }
}

CanvasNodePtr Canvas::getRootNode() const
{
    return m_pRootNode;
}

static ProfilingZoneID PreRenderSignalProfilingZone("PreRender signal");
static ProfilingZoneID RenderProfilingZone("Render");
static ProfilingZoneID FrameEndProfilingZone("OnFrameEnd");

void Canvas::doFrame(bool bPythonAvailable)
{
    {
        ScopeTimer Timer(PreRenderSignalProfilingZone);
        m_PreRenderSignal.emit();
    }
    if (!m_pPlayer->isStopping()) {
        ScopeTimer Timer(RenderProfilingZone);
        if (bPythonAvailable) {
            Py_BEGIN_ALLOW_THREADS;
            try {
                render();
            } catch(...) {
                Py_BLOCK_THREADS;
                throw;
            }
            Py_END_ALLOW_THREADS;
        } else {
            render();
        }
    }
    {
        ScopeTimer Timer(FrameEndProfilingZone);
        m_FrameEndSignal.emit();
    }
}

IntPoint Canvas::getSize() const
{
    return IntPoint(m_pRootNode->getSize());
}

void Canvas::registerPlaybackEndListener(IPlaybackEndListener* pListener)
{
    m_PlaybackEndSignal.connect(pListener);
}

void Canvas::unregisterPlaybackEndListener(IPlaybackEndListener* pListener)
{
    m_PlaybackEndSignal.disconnect(pListener);
}

void Canvas::registerFrameEndListener(IFrameEndListener* pListener)
{
    m_FrameEndSignal.connect(pListener);
}

void Canvas::unregisterFrameEndListener(IFrameEndListener* pListener)
{
    m_FrameEndSignal.disconnect(pListener);
}

void Canvas::registerPreRenderListener(IPreRenderListener* pListener)
{
    m_PreRenderSignal.connect(pListener);
}

void Canvas::unregisterPreRenderListener(IPreRenderListener* pListener)
{
    m_PreRenderSignal.disconnect(pListener);
}

bool Canvas::operator ==(const Canvas& other) const
{
    return this == &other;
}

bool Canvas::operator !=(const Canvas& other) const
{
    return this != &other;
}

long Canvas::getHash() const
{
    return long(this);
}

Player* Canvas::getPlayer() const
{
    return m_pPlayer;
}

SDLDisplayEngine* Canvas::getDisplayEngine() const
{
    return m_pDisplayEngine;
}

vector<VisibleNodeWeakPtr> Canvas::getElementsByPos(const DPoint& pos) const
{
    vector<VisibleNodeWeakPtr> elements;
    m_pRootNode->getElementsByPos(pos, elements);
    return elements;
}

static ProfilingZoneID PreRenderProfilingZone("PreRender");

void Canvas::render(IntPoint windowSize, bool bUpsideDown,
        ProfilingZoneID& renderProfilingZone)
{
    {
        ScopeTimer Timer(PreRenderProfilingZone);
        m_pRootNode->preRender();
    }
    if (m_MultiSampleSamples > 1) {
        glEnable(GL_MULTISAMPLE);
        OGLErrorCheck(AVG_ERR_VIDEO_GENERAL,
                "SDLDisplayEngine::render: glEnable(GL_MULTISAMPLE)");
    } else {
        glDisable(GL_MULTISAMPLE);
        OGLErrorCheck(AVG_ERR_VIDEO_GENERAL,
                "SDLDisplayEngine::render: glDisable(GL_MULTISAMPLE)");
    }
    clearGLBuffers(GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    glViewport(0, 0, windowSize.x, windowSize.y);
    OGLErrorCheck(AVG_ERR_VIDEO_GENERAL, "SDLDisplayEngine::render: glViewport()");
    glMatrixMode(GL_PROJECTION);
    OGLErrorCheck(AVG_ERR_VIDEO_GENERAL, "SDLDisplayEngine::render: glMatrixMode()");
    glLoadIdentity();
    OGLErrorCheck(AVG_ERR_VIDEO_GENERAL, "SDLDisplayEngine::render: glLoadIdentity()");
    IntPoint size = IntPoint(m_pRootNode->getSize());
    if (bUpsideDown) {
        gluOrtho2D(0, size.x, 0, size.y);
    } else {
        gluOrtho2D(0, size.x, size.y, 0);
    }
    OGLErrorCheck(AVG_ERR_VIDEO_GENERAL, "SDLDisplayEngine::render: gluOrtho2D()");
    glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
    OGLErrorCheck(AVG_ERR_VIDEO_GENERAL, "SDLDisplayEngine::render: glTexEnvf()");

    const DRect rc(0,0, size.x, size.y);
    glMatrixMode(GL_MODELVIEW);
    {
        ScopeTimer Timer(renderProfilingZone);
        m_pRootNode->maybeRender(rc);

        renderOutlines();
    }
}

void Canvas::renderOutlines()
{
    Shape * pShape = new Shape(MaterialInfo(GL_REPEAT, GL_CLAMP_TO_EDGE, false));
    pShape->moveToGPU(m_pDisplayEngine);
    VertexArrayPtr pVA = pShape->getVertexArray();
    m_pDisplayEngine->setBlendMode(DisplayEngine::BLEND_BLEND, false);
    m_pRootNode->renderOutlines(pVA, Pixel32(0,0,0,0));
    if (pVA->getCurVert() != 0) {
        pVA->update();
        pShape->draw();
    }
    delete pShape;
}

}
<commit_msg>Outline rendering cleanup.<commit_after>//
//  libavg - Media Playback Engine.
//  Copyright (C) 2003-2008 Ulrich von Zadow
//
//  This library is free software; you can redistribute it and/or
//  modify it under the terms of the GNU Lesser General Public
//  License as published by the Free Software Foundation; either
//  version 2 of the License, or (at your option) any later version.
//
//  This library is distributed in the hope that it will be useful,
//  but WITHOUT ANY WARRANTY; without even the implied warranty of
//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
//  Lesser General Public License for more details.
//
//  You should have received a copy of the GNU Lesser General Public
//  License along with this library; if not, write to the Free Software
//  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
//
//  Current versions can be found at www.libavg.de
//

#include "Canvas.h"

#include "Player.h"
#include "AVGNode.h"
#include "SDLDisplayEngine.h"
#include "Shape.h"
#include "OffscreenCanvas.h"

#include "../base/Exception.h"
#include "../base/Logger.h"
#include "../base/ScopeTimer.h"

#include <iostream>

using namespace std;
using namespace boost;

namespace avg {

Canvas::Canvas(Player * pPlayer)
    : m_pPlayer(pPlayer),
      m_pDisplayEngine(0),
      m_PlaybackEndSignal(&IPlaybackEndListener::onPlaybackEnd),
      m_FrameEndSignal(&IFrameEndListener::onFrameEnd),
      m_PreRenderSignal(&IPreRenderListener::onPreRender)
{
}

Canvas::~Canvas()
{
}

void Canvas::setRoot(NodePtr pRootNode)
{
    assert(!m_pRootNode);
    m_pRootNode = dynamic_pointer_cast<CanvasNode>(pRootNode);
    m_pRootNode->setParent(DivNodeWeakPtr(), VisibleNode::NS_CONNECTED,
            shared_from_this());
    registerNode(m_pRootNode);
}

void Canvas::initPlayback(SDLDisplayEngine* pDisplayEngine, AudioEngine* pAudioEngine,
        int multiSampleSamples)
{
    m_pDisplayEngine = pDisplayEngine;
    m_pRootNode->setRenderingEngines(m_pDisplayEngine, pAudioEngine);
    m_MultiSampleSamples = multiSampleSamples;
}

void Canvas::stopPlayback()
{
    if (m_pDisplayEngine) {
        m_PlaybackEndSignal.emit();
        m_pRootNode->disconnect(true);
        m_pRootNode = CanvasNodePtr();
        m_IDMap.clear();
        m_pDisplayEngine = 0;
    }
}

VisibleNodePtr Canvas::getElementByID(const std::string& id)
{
    if (m_IDMap.find(id) != m_IDMap.end()) {
        return m_IDMap.find(id)->second;
    } else {
        AVG_TRACE(Logger::WARNING, "getElementByID(\"" << id << "\") failed.");
        return VisibleNodePtr();
    }
}

void Canvas::registerNode(VisibleNodePtr pNode)
{
    addNodeID(pNode);
    DivNodePtr pDivNode = boost::dynamic_pointer_cast<DivNode>(pNode);
    if (pDivNode) {
        for (unsigned i=0; i<pDivNode->getNumChildren(); i++) {
            registerNode(pDivNode->getVChild(i));
        }
    }
}

void Canvas::addNodeID(VisibleNodePtr pNode)
{
    const string& id = pNode->getID();
    if (id != "") {
        if (m_IDMap.find(id) != m_IDMap.end() &&
            m_IDMap.find(id)->second != pNode)
        {
            throw (Exception (AVG_ERR_XML_DUPLICATE_ID,
                string("Error: duplicate id ")+id));
        }
        m_IDMap.insert(NodeIDMap::value_type(id, pNode));
    }
}

void Canvas::removeNodeID(const string& id)
{
    if (id != "") {
        map<string, VisibleNodePtr>::iterator it;
        it = m_IDMap.find(id);
        if (it != m_IDMap.end()) {
            m_IDMap.erase(it);
        } else {
            cerr << "removeNodeID(\"" << id << "\") failed." << endl;
            AVG_ASSERT(false);
        }
    }
}

CanvasNodePtr Canvas::getRootNode() const
{
    return m_pRootNode;
}

static ProfilingZoneID PreRenderSignalProfilingZone("PreRender signal");
static ProfilingZoneID RenderProfilingZone("Render");
static ProfilingZoneID FrameEndProfilingZone("OnFrameEnd");

void Canvas::doFrame(bool bPythonAvailable)
{
    {
        ScopeTimer Timer(PreRenderSignalProfilingZone);
        m_PreRenderSignal.emit();
    }
    if (!m_pPlayer->isStopping()) {
        ScopeTimer Timer(RenderProfilingZone);
        if (bPythonAvailable) {
            Py_BEGIN_ALLOW_THREADS;
            try {
                render();
            } catch(...) {
                Py_BLOCK_THREADS;
                throw;
            }
            Py_END_ALLOW_THREADS;
        } else {
            render();
        }
    }
    {
        ScopeTimer Timer(FrameEndProfilingZone);
        m_FrameEndSignal.emit();
    }
}

IntPoint Canvas::getSize() const
{
    return IntPoint(m_pRootNode->getSize());
}

void Canvas::registerPlaybackEndListener(IPlaybackEndListener* pListener)
{
    m_PlaybackEndSignal.connect(pListener);
}

void Canvas::unregisterPlaybackEndListener(IPlaybackEndListener* pListener)
{
    m_PlaybackEndSignal.disconnect(pListener);
}

void Canvas::registerFrameEndListener(IFrameEndListener* pListener)
{
    m_FrameEndSignal.connect(pListener);
}

void Canvas::unregisterFrameEndListener(IFrameEndListener* pListener)
{
    m_FrameEndSignal.disconnect(pListener);
}

void Canvas::registerPreRenderListener(IPreRenderListener* pListener)
{
    m_PreRenderSignal.connect(pListener);
}

void Canvas::unregisterPreRenderListener(IPreRenderListener* pListener)
{
    m_PreRenderSignal.disconnect(pListener);
}

bool Canvas::operator ==(const Canvas& other) const
{
    return this == &other;
}

bool Canvas::operator !=(const Canvas& other) const
{
    return this != &other;
}

long Canvas::getHash() const
{
    return long(this);
}

Player* Canvas::getPlayer() const
{
    return m_pPlayer;
}

SDLDisplayEngine* Canvas::getDisplayEngine() const
{
    return m_pDisplayEngine;
}

vector<VisibleNodeWeakPtr> Canvas::getElementsByPos(const DPoint& pos) const
{
    vector<VisibleNodeWeakPtr> elements;
    m_pRootNode->getElementsByPos(pos, elements);
    return elements;
}

static ProfilingZoneID PreRenderProfilingZone("PreRender");

void Canvas::render(IntPoint windowSize, bool bUpsideDown,
        ProfilingZoneID& renderProfilingZone)
{
    {
        ScopeTimer Timer(PreRenderProfilingZone);
        m_pRootNode->preRender();
    }
    if (m_MultiSampleSamples > 1) {
        glEnable(GL_MULTISAMPLE);
        OGLErrorCheck(AVG_ERR_VIDEO_GENERAL,
                "SDLDisplayEngine::render: glEnable(GL_MULTISAMPLE)");
    } else {
        glDisable(GL_MULTISAMPLE);
        OGLErrorCheck(AVG_ERR_VIDEO_GENERAL,
                "SDLDisplayEngine::render: glDisable(GL_MULTISAMPLE)");
    }
    clearGLBuffers(GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    glViewport(0, 0, windowSize.x, windowSize.y);
    OGLErrorCheck(AVG_ERR_VIDEO_GENERAL, "SDLDisplayEngine::render: glViewport()");
    glMatrixMode(GL_PROJECTION);
    OGLErrorCheck(AVG_ERR_VIDEO_GENERAL, "SDLDisplayEngine::render: glMatrixMode()");
    glLoadIdentity();
    OGLErrorCheck(AVG_ERR_VIDEO_GENERAL, "SDLDisplayEngine::render: glLoadIdentity()");
    IntPoint size = IntPoint(m_pRootNode->getSize());
    if (bUpsideDown) {
        gluOrtho2D(0, size.x, 0, size.y);
    } else {
        gluOrtho2D(0, size.x, size.y, 0);
    }
    OGLErrorCheck(AVG_ERR_VIDEO_GENERAL, "SDLDisplayEngine::render: gluOrtho2D()");
    glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
    OGLErrorCheck(AVG_ERR_VIDEO_GENERAL, "SDLDisplayEngine::render: glTexEnvf()");

    const DRect rc(0,0, size.x, size.y);
    glMatrixMode(GL_MODELVIEW);
    {
        ScopeTimer Timer(renderProfilingZone);
        m_pRootNode->maybeRender(rc);

        renderOutlines();
    }
}

void Canvas::renderOutlines()
{
    VertexArrayPtr pVA(new VertexArray);
    m_pDisplayEngine->setBlendMode(DisplayEngine::BLEND_BLEND, false);
    m_pRootNode->renderOutlines(pVA, Pixel32(0,0,0,0));
    if (pVA->getCurVert() != 0) {
        pVA->update();
        m_pDisplayEngine->enableTexture(false);
        m_pDisplayEngine->enableGLColorArray(true);
        pVA->draw();
    }
}

}
<|endoftext|>


<commit_before>#include "binary_sort_tree.h"
#include <stdio.h>
#include <string>

#define ARR_LEN 16

static int compare(void *elem1, void *elem2)
{
    int *vp1 = (int *)elem1;
    int *vp2 = (int *)elem2;

    return *vp1 - *vp2;
}

static void print(const std::string &str, int ret)
{
    if (ret == E_FAILURE)
    {
        printf("%s failed!\n", str.data());
    }
    else if (ret == E_SUCCESS)
    {
        printf("%s success!\n", str.data());
    }
}

static void test()
{
    int arr[ARR_LEN] = {0};
    for (int i = 0; i < ARR_LEN; i++)
    {
        arr[i] = i + 1;
    }

    BinarySortTree ptree;
    ptree.init(arr, ARR_LEN, sizeof(int), compare);

    printf("------------key is 10---------\n");
    int key = 10;
    int ret = ptree.find_node(&key, compare);
    print("find_node:10", ret);

    printf("------------key is 20--------\n");
    key = 20;
    ret = ptree.delete_node(&key, compare);
    print("delete_node:20", ret);

    printf("------------key is 25---------\n");
    key = 25;
    ret = ptree.find_node(&key, compare);
    print("find_node:25", ret);

    printf("------------key is 30---------\n");
    key = 30;
    ret = ptree.insert_node(&key, sizeof(int), compare);
    print("insert_node:30", ret);
    ret = ptree.find_node(&key, compare);
    print("find_node:30", ret);
    ret = ptree.delete_node(&key, compare);
    print("delete_node:30", ret);
    ret = ptree.find_node(&key, compare);
    print("find_node:30", ret);

}

int main(int argc, char const *argv[])
{
    test();
    return 0;
}<commit_msg>Update main.cc<commit_after>#include "binary_sort_tree.h"
#include <stdio.h>
#include <string>

#define ARR_LEN 16

static int compare(void *elem1, void *elem2)
{
    int *vp1 = (int *)elem1;
    int *vp2 = (int *)elem2;

    return *vp1 - *vp2;
}

static void print(const std::string &str, int ret)
{
    if (ret == E_FAILURE)
    {
        printf("%s failed!\n", str.data());
    }
    else if (ret == E_SUCCESS)
    {
        printf("%s success!\n", str.data());
    }
}

static void test()
{
    int arr[ARR_LEN] = {0};
    for (int i = 0; i < ARR_LEN; i++)
    {
        arr[i] = i + 1;
    }

    BinarySortTree ptree;
    ptree.init(arr, ARR_LEN, sizeof(int), compare);

    printf("------------key is 10---------\n");
    int key = 10;
    int ret = ptree.find_node(&key, compare);
    print("find_node:10", ret);

    printf("------------key is 20--------\n");
    key = 20;
    ret = ptree.delete_node(&key, compare);
    print("delete_node:20", ret);

    printf("------------key is 25---------\n");
    key = 25;
    ret = ptree.find_node(&key, compare);
    print("find_node:25", ret);

    printf("------------key is 30---------\n");
    key = 30;
    ret = ptree.insert_node(&key, sizeof(int), compare);
    print("insert_node:30", ret);
    ret = ptree.find_node(&key, compare);
    print("find_node:30", ret);
    ret = ptree.delete_node(&key, compare);
    print("delete_node:30", ret);
    ret = ptree.find_node(&key, compare);
    print("find_node:30", ret);
}

int main(int argc, char const *argv[])
{
    test();
    return 0;
}
<|endoftext|>


<commit_before>// Copyright (c) 2011 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "ppapi/proxy/ppb_flash_net_connector_proxy.h"

#include <algorithm>

#include "ppapi/c/pp_errors.h"
#include "ppapi/c/private/ppb_flash_net_connector.h"
#include "ppapi/proxy/plugin_dispatcher.h"
#include "ppapi/proxy/plugin_resource.h"
#include "ppapi/proxy/ppapi_messages.h"
#include "ppapi/proxy/serialized_var.h"

namespace pp {
namespace proxy {

std::string NetAddressToString(const PP_Flash_NetAddress& addr) {
  return std::string(addr.data, std::min(static_cast<size_t>(addr.size),
                                         sizeof(addr.data)));
}

void StringToNetAddress(const std::string& str, PP_Flash_NetAddress* addr) {
  addr->size = std::min(str.size(), sizeof(addr->data));
  memcpy(addr->data, str.data(), addr->size);
}

class FlashNetConnector : public PluginResource {
 public:
  FlashNetConnector(const HostResource& resource)
      : PluginResource(resource),
        callback_(PP_BlockUntilComplete()),
        local_addr_out_(NULL),
        remote_addr_out_(NULL) {
  }
  ~FlashNetConnector() {
    if (callback_.func)
      PP_RunCompletionCallback(&callback_, PP_ERROR_ABORTED);
  }

  // Resource overrides.
  virtual FlashNetConnector* AsFlashNetConnector() {
    return this;
  }

  bool HasCallback() const {
    return callback_.func != NULL;
  }

  void SetCallback(const PP_CompletionCallback& callback,
                   PP_FileHandle* socket_out,
                   PP_Flash_NetAddress* local_addr_out,
                   PP_Flash_NetAddress* remote_addr_out) {
    callback_ = callback;
    socket_out_ = socket_out;
    local_addr_out_ = local_addr_out;
    remote_addr_out_ = remote_addr_out;
  }

  void ConnectComplete(int32_t result,
                       base::PlatformFile file,
                       const std::string& local_addr_as_string,
                       const std::string& remote_addr_as_string) {
    if (!callback_.func) {
      base::ClosePlatformFile(file);
      return;
    }

    *socket_out_ = static_cast<PP_FileHandle>(file);
    StringToNetAddress(local_addr_as_string, local_addr_out_);
    StringToNetAddress(remote_addr_as_string, remote_addr_out_);

    PP_CompletionCallback temp_callback = callback_;
    callback_ = PP_BlockUntilComplete();
    PP_RunCompletionCallback(&temp_callback, result);
  }

 private:
  PP_CompletionCallback callback_;
  PP_FileHandle* socket_out_;
  PP_Flash_NetAddress* local_addr_out_;
  PP_Flash_NetAddress* remote_addr_out_;
};

// Contains the data that the host interface will write to so we can send it
// to the plugin. This is created when a request is initiated, and deleted in
// the callback handler.
struct PPB_Flash_NetConnector_Proxy::ConnectCallbackInfo {
  ConnectCallbackInfo(const HostResource& r) : resource(r), handle(0) {
    local_addr.size = 0;
    remote_addr.size = 0;
  }

  HostResource resource;

  PP_FileHandle handle;
  PP_Flash_NetAddress local_addr;
  PP_Flash_NetAddress remote_addr;
};

namespace {

PP_Resource Create(PP_Instance instance_id) {
  PluginDispatcher* dispatcher = PluginDispatcher::GetForInstance(instance_id);
  if (!dispatcher)
    return 0;

  HostResource result;
  dispatcher->Send(new PpapiHostMsg_PPBFlashNetConnector_Create(
      INTERFACE_ID_PPB_FLASH_NETCONNECTOR, instance_id, &result));
  if (result.is_null())
    return 0;

  linked_ptr<FlashNetConnector> object(new FlashNetConnector(result));
  return PluginResourceTracker::GetInstance()->AddResource(object);
}

PP_Bool IsFlashNetConnector(PP_Resource resource_id) {
  FlashNetConnector* object =
      PluginResource::GetAs<FlashNetConnector>(resource_id);
  return BoolToPPBool(!!object);
}

// Backend for both ConnectTcp and ConnectTcpAddress. To keep things generic,
// the message is passed in (on error, it's deleted).
int32_t ConnectWithMessage(FlashNetConnector* object,
                           IPC::Message* msg,
                           PP_FileHandle* socket_out,
                           struct PP_Flash_NetAddress* local_addr_out,
                           struct PP_Flash_NetAddress* remote_addr_out,
                           struct PP_CompletionCallback callback) {
  scoped_ptr<IPC::Message> msg_deletor(msg);
  if (object->HasCallback())
    return PP_ERROR_INPROGRESS;  // Can only have one pending request.

  // Send the request, it will call us back via ConnectACK.
  PluginDispatcher* dispatcher = PluginDispatcher::GetForInstance(
      object->instance());
  if (!dispatcher)
    return PP_ERROR_BADARGUMENT;
  dispatcher->Send(msg_deletor.release());

  object->SetCallback(callback, socket_out, local_addr_out, remote_addr_out);
  return PP_OK_COMPLETIONPENDING;
}

int32_t ConnectTcp(PP_Resource connector_id,
                   const char* host,
                   uint16_t port,
                   PP_FileHandle* socket_out,
                   struct PP_Flash_NetAddress* local_addr_out,
                   struct PP_Flash_NetAddress* remote_addr_out,
                   struct PP_CompletionCallback callback) {
  FlashNetConnector* object =
      PluginResource::GetAs<FlashNetConnector>(connector_id);
  if (!object)
    return PP_ERROR_BADARGUMENT;
  return ConnectWithMessage(
      object,
      new PpapiHostMsg_PPBFlashNetConnector_ConnectTcp(
          INTERFACE_ID_PPB_FLASH_NETCONNECTOR,
          object->host_resource(), host, port),
      socket_out, local_addr_out, remote_addr_out, callback);
}

int32_t ConnectTcpAddress(PP_Resource connector_id,
                          const struct PP_Flash_NetAddress* addr,
                          PP_FileHandle* socket_out,
                          struct PP_Flash_NetAddress* local_addr_out,
                          struct PP_Flash_NetAddress* remote_addr_out,
                          struct PP_CompletionCallback callback) {
  FlashNetConnector* object =
      PluginResource::GetAs<FlashNetConnector>(connector_id);
  if (!object)
    return PP_ERROR_BADARGUMENT;
  return ConnectWithMessage(
      object,
      new PpapiHostMsg_PPBFlashNetConnector_ConnectTcpAddress(
          INTERFACE_ID_PPB_FLASH_NETCONNECTOR,
          object->host_resource(), NetAddressToString(*addr)),
      socket_out, local_addr_out, remote_addr_out, callback);
}

const PPB_Flash_NetConnector flash_netconnector_interface = {
  &Create,
  &IsFlashNetConnector,
  &ConnectTcp,
  &ConnectTcpAddress
};

InterfaceProxy* CreateFlashNetConnectorProxy(Dispatcher* dispatcher,
                                             const void* target_interface) {
  return new PPB_Flash_NetConnector_Proxy(dispatcher, target_interface);
}

}  // namespace

PPB_Flash_NetConnector_Proxy::PPB_Flash_NetConnector_Proxy(
    Dispatcher* dispatcher, const void* target_interface)
    : InterfaceProxy(dispatcher, target_interface),
      callback_factory_(ALLOW_THIS_IN_INITIALIZER_LIST(this)) {
}

PPB_Flash_NetConnector_Proxy::~PPB_Flash_NetConnector_Proxy() {
}

// static
const InterfaceProxy::Info* PPB_Flash_NetConnector_Proxy::GetInfo() {
  static const Info info = {
    &flash_netconnector_interface,
    PPB_FLASH_NETCONNECTOR_INTERFACE,
    INTERFACE_ID_PPB_FLASH_NETCONNECTOR,
    false,
    &CreateFlashNetConnectorProxy
  };
  return &info;
}

bool PPB_Flash_NetConnector_Proxy::OnMessageReceived(const IPC::Message& msg) {
  bool handled = true;
  IPC_BEGIN_MESSAGE_MAP(PPB_Flash_NetConnector_Proxy, msg)
    IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBFlashNetConnector_Create,
                        OnMsgCreate)
    IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBFlashNetConnector_ConnectTcp,
                        OnMsgConnectTcp)
    IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBFlashNetConnector_ConnectTcpAddress,
                        OnMsgConnectTcpAddress)
    IPC_MESSAGE_HANDLER(PpapiMsg_PPBFlashNetConnector_ConnectACK,
                        OnMsgConnectACK)
    IPC_MESSAGE_UNHANDLED(handled = false)
  IPC_END_MESSAGE_MAP()
  return handled;
}

void PPB_Flash_NetConnector_Proxy::OnMsgCreate(PP_Instance instance_id,
                                               HostResource* result) {
  result->SetHostResource(
      instance_id,
      ppb_flash_net_connector_target()->Create(instance_id));
}

void PPB_Flash_NetConnector_Proxy::OnMsgConnectTcp(
    const HostResource& resource,
    const std::string& host,
    uint16_t port) {
  ConnectCallbackInfo* info = new ConnectCallbackInfo(resource);
  CompletionCallback callback = callback_factory_.NewCallback(
      &PPB_Flash_NetConnector_Proxy::OnCompleteCallbackInHost, info);

  int32_t result = ppb_flash_net_connector_target()->ConnectTcp(
      resource.host_resource(), host.c_str(), port,
      &info->handle, &info->local_addr, &info->remote_addr,
      callback.pp_completion_callback());
  if (result != PP_OK_COMPLETIONPENDING)
    OnCompleteCallbackInHost(result, info);
}

void PPB_Flash_NetConnector_Proxy::OnMsgConnectTcpAddress(
    const HostResource& resource,
    const std::string& net_address_as_string) {
  ConnectCallbackInfo* info = new ConnectCallbackInfo(resource);
  CompletionCallback callback = callback_factory_.NewCallback(
      &PPB_Flash_NetConnector_Proxy::OnCompleteCallbackInHost, info);

  PP_Flash_NetAddress net_address;
  StringToNetAddress(net_address_as_string, &net_address);

  int32_t result = ppb_flash_net_connector_target()->ConnectTcpAddress(
      resource.host_resource(), &net_address,
      &info->handle, &info->local_addr, &info->remote_addr,
      callback.pp_completion_callback());
  if (result != PP_OK_COMPLETIONPENDING)
    OnCompleteCallbackInHost(result, info);
}

void PPB_Flash_NetConnector_Proxy::OnMsgConnectACK(
    const HostResource& host_resource,
    int32_t result,
    IPC::PlatformFileForTransit handle,
    const std::string& load_addr_as_string,
    const std::string& remote_addr_as_string) {
  base::PlatformFile platform_file =
      IPC::PlatformFileForTransitToPlatformFile(handle);

  PP_Resource plugin_resource =
      PluginResourceTracker::GetInstance()->PluginResourceForHostResource(
          host_resource);
  if (!plugin_resource) {
    base::ClosePlatformFile(platform_file);
    return;
  }
  FlashNetConnector* object =
      PluginResource::GetAs<FlashNetConnector>(plugin_resource);
  if (!object) {
    base::ClosePlatformFile(platform_file);
    return;
  }

  object->ConnectComplete(result, platform_file,
                          load_addr_as_string, remote_addr_as_string);
}

void PPB_Flash_NetConnector_Proxy::OnCompleteCallbackInHost(
    int32_t result,
    ConnectCallbackInfo* info) {
  // Callback must always delete the info.
  scoped_ptr<ConnectCallbackInfo> info_deletor(info);

  if (result == PP_OK) {
    dispatcher()->Send(new PpapiMsg_PPBFlashNetConnector_ConnectACK(
        INTERFACE_ID_PPB_FLASH_NETCONNECTOR,
        info->resource, result,
        dispatcher()->ShareHandleWithRemote(
            static_cast<base::PlatformFile>(info->handle), true),
        NetAddressToString(info->local_addr),
        NetAddressToString(info->remote_addr)));
  } else {
    dispatcher()->Send(new PpapiMsg_PPBFlashNetConnector_ConnectACK(
        INTERFACE_ID_PPB_FLASH_NETCONNECTOR,
        info->resource, result,
        IPC::InvalidPlatformFileForTransit(), std::string(), std::string()));
  }
}

}  // namespace proxy
}  // namespace pp
<commit_msg>Don't re-enter when destroying FlashNetConnector<commit_after>// Copyright (c) 2011 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "ppapi/proxy/ppb_flash_net_connector_proxy.h"

#include <algorithm>

#include "ppapi/c/pp_errors.h"
#include "ppapi/c/private/ppb_flash_net_connector.h"
#include "ppapi/proxy/plugin_dispatcher.h"
#include "ppapi/proxy/plugin_resource.h"
#include "ppapi/proxy/ppapi_messages.h"
#include "ppapi/proxy/serialized_var.h"

namespace pp {
namespace proxy {

std::string NetAddressToString(const PP_Flash_NetAddress& addr) {
  return std::string(addr.data, std::min(static_cast<size_t>(addr.size),
                                         sizeof(addr.data)));
}

void StringToNetAddress(const std::string& str, PP_Flash_NetAddress* addr) {
  addr->size = std::min(str.size(), sizeof(addr->data));
  memcpy(addr->data, str.data(), addr->size);
}

class AbortCallbackTask : public Task {
 public:
  AbortCallbackTask(PP_CompletionCallback callback)
      : callback_(callback) {}

  virtual void Run() {
    PP_RunCompletionCallback(&callback_, PP_ERROR_ABORTED);
  }

 private:
  PP_CompletionCallback callback_;
};

class FlashNetConnector : public PluginResource {
 public:
  FlashNetConnector(const HostResource& resource)
      : PluginResource(resource),
        callback_(PP_BlockUntilComplete()),
        local_addr_out_(NULL),
        remote_addr_out_(NULL) {
  }
  ~FlashNetConnector() {
    if (callback_.func) {
      MessageLoop::current()->PostTask(FROM_HERE,
                                       new AbortCallbackTask(callback_));
    }
  }

  // Resource overrides.
  virtual FlashNetConnector* AsFlashNetConnector() {
    return this;
  }

  bool HasCallback() const {
    return callback_.func != NULL;
  }

  void SetCallback(const PP_CompletionCallback& callback,
                   PP_FileHandle* socket_out,
                   PP_Flash_NetAddress* local_addr_out,
                   PP_Flash_NetAddress* remote_addr_out) {
    callback_ = callback;
    socket_out_ = socket_out;
    local_addr_out_ = local_addr_out;
    remote_addr_out_ = remote_addr_out;
  }

  void ConnectComplete(int32_t result,
                       base::PlatformFile file,
                       const std::string& local_addr_as_string,
                       const std::string& remote_addr_as_string) {
    if (!callback_.func) {
      base::ClosePlatformFile(file);
      return;
    }

    *socket_out_ = static_cast<PP_FileHandle>(file);
    StringToNetAddress(local_addr_as_string, local_addr_out_);
    StringToNetAddress(remote_addr_as_string, remote_addr_out_);

    PP_CompletionCallback temp_callback = callback_;
    callback_ = PP_BlockUntilComplete();
    PP_RunCompletionCallback(&temp_callback, result);
  }

 private:
  PP_CompletionCallback callback_;
  PP_FileHandle* socket_out_;
  PP_Flash_NetAddress* local_addr_out_;
  PP_Flash_NetAddress* remote_addr_out_;
};

// Contains the data that the host interface will write to so we can send it
// to the plugin. This is created when a request is initiated, and deleted in
// the callback handler.
struct PPB_Flash_NetConnector_Proxy::ConnectCallbackInfo {
  ConnectCallbackInfo(const HostResource& r) : resource(r), handle(0) {
    local_addr.size = 0;
    remote_addr.size = 0;
  }

  HostResource resource;

  PP_FileHandle handle;
  PP_Flash_NetAddress local_addr;
  PP_Flash_NetAddress remote_addr;
};

namespace {

PP_Resource Create(PP_Instance instance_id) {
  PluginDispatcher* dispatcher = PluginDispatcher::GetForInstance(instance_id);
  if (!dispatcher)
    return 0;

  HostResource result;
  dispatcher->Send(new PpapiHostMsg_PPBFlashNetConnector_Create(
      INTERFACE_ID_PPB_FLASH_NETCONNECTOR, instance_id, &result));
  if (result.is_null())
    return 0;

  linked_ptr<FlashNetConnector> object(new FlashNetConnector(result));
  return PluginResourceTracker::GetInstance()->AddResource(object);
}

PP_Bool IsFlashNetConnector(PP_Resource resource_id) {
  FlashNetConnector* object =
      PluginResource::GetAs<FlashNetConnector>(resource_id);
  return BoolToPPBool(!!object);
}

// Backend for both ConnectTcp and ConnectTcpAddress. To keep things generic,
// the message is passed in (on error, it's deleted).
int32_t ConnectWithMessage(FlashNetConnector* object,
                           IPC::Message* msg,
                           PP_FileHandle* socket_out,
                           struct PP_Flash_NetAddress* local_addr_out,
                           struct PP_Flash_NetAddress* remote_addr_out,
                           struct PP_CompletionCallback callback) {
  scoped_ptr<IPC::Message> msg_deletor(msg);
  if (object->HasCallback())
    return PP_ERROR_INPROGRESS;  // Can only have one pending request.

  // Send the request, it will call us back via ConnectACK.
  PluginDispatcher* dispatcher = PluginDispatcher::GetForInstance(
      object->instance());
  if (!dispatcher)
    return PP_ERROR_BADARGUMENT;
  dispatcher->Send(msg_deletor.release());

  object->SetCallback(callback, socket_out, local_addr_out, remote_addr_out);
  return PP_OK_COMPLETIONPENDING;
}

int32_t ConnectTcp(PP_Resource connector_id,
                   const char* host,
                   uint16_t port,
                   PP_FileHandle* socket_out,
                   struct PP_Flash_NetAddress* local_addr_out,
                   struct PP_Flash_NetAddress* remote_addr_out,
                   struct PP_CompletionCallback callback) {
  FlashNetConnector* object =
      PluginResource::GetAs<FlashNetConnector>(connector_id);
  if (!object)
    return PP_ERROR_BADARGUMENT;
  return ConnectWithMessage(
      object,
      new PpapiHostMsg_PPBFlashNetConnector_ConnectTcp(
          INTERFACE_ID_PPB_FLASH_NETCONNECTOR,
          object->host_resource(), host, port),
      socket_out, local_addr_out, remote_addr_out, callback);
}

int32_t ConnectTcpAddress(PP_Resource connector_id,
                          const struct PP_Flash_NetAddress* addr,
                          PP_FileHandle* socket_out,
                          struct PP_Flash_NetAddress* local_addr_out,
                          struct PP_Flash_NetAddress* remote_addr_out,
                          struct PP_CompletionCallback callback) {
  FlashNetConnector* object =
      PluginResource::GetAs<FlashNetConnector>(connector_id);
  if (!object)
    return PP_ERROR_BADARGUMENT;
  return ConnectWithMessage(
      object,
      new PpapiHostMsg_PPBFlashNetConnector_ConnectTcpAddress(
          INTERFACE_ID_PPB_FLASH_NETCONNECTOR,
          object->host_resource(), NetAddressToString(*addr)),
      socket_out, local_addr_out, remote_addr_out, callback);
}

const PPB_Flash_NetConnector flash_netconnector_interface = {
  &Create,
  &IsFlashNetConnector,
  &ConnectTcp,
  &ConnectTcpAddress
};

InterfaceProxy* CreateFlashNetConnectorProxy(Dispatcher* dispatcher,
                                             const void* target_interface) {
  return new PPB_Flash_NetConnector_Proxy(dispatcher, target_interface);
}

}  // namespace

PPB_Flash_NetConnector_Proxy::PPB_Flash_NetConnector_Proxy(
    Dispatcher* dispatcher, const void* target_interface)
    : InterfaceProxy(dispatcher, target_interface),
      callback_factory_(ALLOW_THIS_IN_INITIALIZER_LIST(this)) {
}

PPB_Flash_NetConnector_Proxy::~PPB_Flash_NetConnector_Proxy() {
}

// static
const InterfaceProxy::Info* PPB_Flash_NetConnector_Proxy::GetInfo() {
  static const Info info = {
    &flash_netconnector_interface,
    PPB_FLASH_NETCONNECTOR_INTERFACE,
    INTERFACE_ID_PPB_FLASH_NETCONNECTOR,
    false,
    &CreateFlashNetConnectorProxy
  };
  return &info;
}

bool PPB_Flash_NetConnector_Proxy::OnMessageReceived(const IPC::Message& msg) {
  bool handled = true;
  IPC_BEGIN_MESSAGE_MAP(PPB_Flash_NetConnector_Proxy, msg)
    IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBFlashNetConnector_Create,
                        OnMsgCreate)
    IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBFlashNetConnector_ConnectTcp,
                        OnMsgConnectTcp)
    IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBFlashNetConnector_ConnectTcpAddress,
                        OnMsgConnectTcpAddress)
    IPC_MESSAGE_HANDLER(PpapiMsg_PPBFlashNetConnector_ConnectACK,
                        OnMsgConnectACK)
    IPC_MESSAGE_UNHANDLED(handled = false)
  IPC_END_MESSAGE_MAP()
  return handled;
}

void PPB_Flash_NetConnector_Proxy::OnMsgCreate(PP_Instance instance_id,
                                               HostResource* result) {
  result->SetHostResource(
      instance_id,
      ppb_flash_net_connector_target()->Create(instance_id));
}

void PPB_Flash_NetConnector_Proxy::OnMsgConnectTcp(
    const HostResource& resource,
    const std::string& host,
    uint16_t port) {
  ConnectCallbackInfo* info = new ConnectCallbackInfo(resource);
  CompletionCallback callback = callback_factory_.NewCallback(
      &PPB_Flash_NetConnector_Proxy::OnCompleteCallbackInHost, info);

  int32_t result = ppb_flash_net_connector_target()->ConnectTcp(
      resource.host_resource(), host.c_str(), port,
      &info->handle, &info->local_addr, &info->remote_addr,
      callback.pp_completion_callback());
  if (result != PP_OK_COMPLETIONPENDING)
    OnCompleteCallbackInHost(result, info);
}

void PPB_Flash_NetConnector_Proxy::OnMsgConnectTcpAddress(
    const HostResource& resource,
    const std::string& net_address_as_string) {
  ConnectCallbackInfo* info = new ConnectCallbackInfo(resource);
  CompletionCallback callback = callback_factory_.NewCallback(
      &PPB_Flash_NetConnector_Proxy::OnCompleteCallbackInHost, info);

  PP_Flash_NetAddress net_address;
  StringToNetAddress(net_address_as_string, &net_address);

  int32_t result = ppb_flash_net_connector_target()->ConnectTcpAddress(
      resource.host_resource(), &net_address,
      &info->handle, &info->local_addr, &info->remote_addr,
      callback.pp_completion_callback());
  if (result != PP_OK_COMPLETIONPENDING)
    OnCompleteCallbackInHost(result, info);
}

void PPB_Flash_NetConnector_Proxy::OnMsgConnectACK(
    const HostResource& host_resource,
    int32_t result,
    IPC::PlatformFileForTransit handle,
    const std::string& load_addr_as_string,
    const std::string& remote_addr_as_string) {
  base::PlatformFile platform_file =
      IPC::PlatformFileForTransitToPlatformFile(handle);

  PP_Resource plugin_resource =
      PluginResourceTracker::GetInstance()->PluginResourceForHostResource(
          host_resource);
  if (!plugin_resource) {
    base::ClosePlatformFile(platform_file);
    return;
  }
  FlashNetConnector* object =
      PluginResource::GetAs<FlashNetConnector>(plugin_resource);
  if (!object) {
    base::ClosePlatformFile(platform_file);
    return;
  }

  object->ConnectComplete(result, platform_file,
                          load_addr_as_string, remote_addr_as_string);
}

void PPB_Flash_NetConnector_Proxy::OnCompleteCallbackInHost(
    int32_t result,
    ConnectCallbackInfo* info) {
  // Callback must always delete the info.
  scoped_ptr<ConnectCallbackInfo> info_deletor(info);

  if (result == PP_OK) {
    dispatcher()->Send(new PpapiMsg_PPBFlashNetConnector_ConnectACK(
        INTERFACE_ID_PPB_FLASH_NETCONNECTOR,
        info->resource, result,
        dispatcher()->ShareHandleWithRemote(
            static_cast<base::PlatformFile>(info->handle), true),
        NetAddressToString(info->local_addr),
        NetAddressToString(info->remote_addr)));
  } else {
    dispatcher()->Send(new PpapiMsg_PPBFlashNetConnector_ConnectACK(
        INTERFACE_ID_PPB_FLASH_NETCONNECTOR,
        info->resource, result,
        IPC::InvalidPlatformFileForTransit(), std::string(), std::string()));
  }
}

}  // namespace proxy
}  // namespace pp
<|endoftext|>


<commit_before>/****************************************************************************
**
** Copyright (C) 2013 Jolla Ltd.
** Contact: lorn.potter@jollamobile.com
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file.  Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
****************************************************************************/

#include "qofonomanager.h"
#include "qofonomodem.h"
#include "dbus/ofonomanager.h"
#include <QVariant>
#include <QTimer>
#include "dbustypes.h"

QDBusArgument &operator<<(QDBusArgument &argument, const ObjectPathProperties &modem)
{
    argument.beginStructure();
    argument << modem.path << modem.properties;
    argument.endStructure();
    return argument;
}

const QDBusArgument &operator>>(const QDBusArgument &argument, ObjectPathProperties &modem)
{
    argument.beginStructure();
    argument >> modem.path >> modem.properties;
    argument.endStructure();
    return argument;
}

class QOfonoManagerPrivate
{
public:
    QOfonoManagerPrivate();
    OfonoManager *ofonoManager;
    QStringList modems;
    bool available;
    QDBusServiceWatcher *ofonoWatcher;
};

QOfonoManagerPrivate::QOfonoManagerPrivate() :
 ofonoManager(0)
, modems(QStringList())
, available(0)
, ofonoWatcher(0)
{
    qDBusRegisterMetaType<ObjectPathProperties>();
    qDBusRegisterMetaType<ObjectPathPropertiesList>();
    qRegisterMetaType<ObjectPathProperties>("ObjectPathProperties");
    qRegisterMetaType<ObjectPathPropertiesList>("ObjectPathPropertiesList");
}

QOfonoManager::QOfonoManager(QObject *parent) :
    QObject(parent)
  , d_ptr(new QOfonoManagerPrivate)
{

    d_ptr->ofonoWatcher = new QDBusServiceWatcher("org.ofono",QDBusConnection::systemBus(),
            QDBusServiceWatcher::WatchForRegistration |
            QDBusServiceWatcher::WatchForUnregistration, this);

    connect(d_ptr->ofonoWatcher, SIGNAL(serviceRegistered(QString)),
            this, SLOT(connectToOfono(QString)));
    connect(d_ptr->ofonoWatcher, SIGNAL(serviceUnregistered(QString)),
            this, SLOT(ofonoUnregistered(QString)));

    d_ptr->available = QDBusConnection::systemBus().interface()->isServiceRegistered("org.ofono");
    if(d_ptr->available) {
        connectToOfono(QString());
    }
}

QOfonoManager::~QOfonoManager()
{
    delete d_ptr;
}

QStringList QOfonoManager::modems()
{
    return d_ptr->modems;
}

void QOfonoManager::onModemAdd(const QDBusObjectPath& path, const QVariantMap& var)
{
    QString pathStr = path.path();
    if (!d_ptr->modems.contains(pathStr)) {
        d_ptr->modems.append(pathStr);
        Q_EMIT modemAdded(pathStr);
        Q_EMIT modemsChanged(d_ptr->modems);
    }
}

void QOfonoManager::onModemRemove(const QDBusObjectPath& path)
{
    QString pathStr = path.path();
    /* we need to send out modem removed signal, since we decided to turn modem off directly */
    Q_EMIT modemRemoved(pathStr);
    if (d_ptr->modems.contains(pathStr)) {
        d_ptr->modems.removeOne(pathStr);
        Q_EMIT modemsChanged(d_ptr->modems);
    }
}

bool QOfonoManager::available() const
{
    return d_ptr->available;
}

void QOfonoManager::connectToOfono(const QString &)
{
    d_ptr->ofonoManager = new OfonoManager("org.ofono","/",QDBusConnection::systemBus(),this);
    if (d_ptr->ofonoManager->isValid()) {
        QDBusPendingReply<ObjectPathPropertiesList> reply = d_ptr->ofonoManager->GetModems();
        reply.waitForFinished();
        // fugly I know... but we need sorted modems
        // with hardware listed first
        QOfonoModem oModem;
        foreach(ObjectPathProperties modem, reply.value()) {
            QString modemPath = modem.path.path();
            oModem.setModemPath(modemPath);
            if (oModem.type() == "hardware"
                    && !modemPath.contains("phonesim")) {
                // running phonesim from desktop
                // presents phonesim as hardware
                d_ptr->modems.prepend(modemPath);
            } else {
                d_ptr->modems.append(modemPath);
            }

            Q_EMIT modemAdded(modemPath);
        }
        Q_EMIT modemsChanged(d_ptr->modems);
    }
    Q_EMIT availableChanged(true);
    connect(d_ptr->ofonoManager, SIGNAL(ModemAdded(QDBusObjectPath,QVariantMap)), this, SLOT(onModemAdd(QDBusObjectPath,QVariantMap)));
    connect(d_ptr->ofonoManager, SIGNAL(ModemRemoved(QDBusObjectPath)), this, SLOT(onModemRemove(QDBusObjectPath)));
}

void QOfonoManager::ofonoUnregistered(const QString &)
{
    d_ptr->available = false;
    delete d_ptr->ofonoManager;
    Q_FOREACH(const QString &modem, d_ptr->modems) {
        Q_EMIT modemRemoved(modem);
    }
    d_ptr->modems.clear();
    Q_EMIT modemsChanged(d_ptr->modems);
    Q_EMIT availableChanged(false);
}

bool QOfonoManager::isValid() const
{
    return d_ptr->ofonoManager->isValid();
}
<commit_msg>[libqofono] Update 'available' property when org.ofono service becomes available<commit_after>/****************************************************************************
**
** Copyright (C) 2013 Jolla Ltd.
** Contact: lorn.potter@jollamobile.com
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file.  Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
****************************************************************************/

#include "qofonomanager.h"
#include "qofonomodem.h"
#include "dbus/ofonomanager.h"
#include <QVariant>
#include <QTimer>
#include "dbustypes.h"

QDBusArgument &operator<<(QDBusArgument &argument, const ObjectPathProperties &modem)
{
    argument.beginStructure();
    argument << modem.path << modem.properties;
    argument.endStructure();
    return argument;
}

const QDBusArgument &operator>>(const QDBusArgument &argument, ObjectPathProperties &modem)
{
    argument.beginStructure();
    argument >> modem.path >> modem.properties;
    argument.endStructure();
    return argument;
}

class QOfonoManagerPrivate
{
public:
    QOfonoManagerPrivate();
    OfonoManager *ofonoManager;
    QStringList modems;
    bool available;
    QDBusServiceWatcher *ofonoWatcher;
};

QOfonoManagerPrivate::QOfonoManagerPrivate() :
 ofonoManager(0)
, modems(QStringList())
, available(0)
, ofonoWatcher(0)
{
    qDBusRegisterMetaType<ObjectPathProperties>();
    qDBusRegisterMetaType<ObjectPathPropertiesList>();
    qRegisterMetaType<ObjectPathProperties>("ObjectPathProperties");
    qRegisterMetaType<ObjectPathPropertiesList>("ObjectPathPropertiesList");
}

QOfonoManager::QOfonoManager(QObject *parent) :
    QObject(parent)
  , d_ptr(new QOfonoManagerPrivate)
{

    d_ptr->ofonoWatcher = new QDBusServiceWatcher("org.ofono",QDBusConnection::systemBus(),
            QDBusServiceWatcher::WatchForRegistration |
            QDBusServiceWatcher::WatchForUnregistration, this);

    connect(d_ptr->ofonoWatcher, SIGNAL(serviceRegistered(QString)),
            this, SLOT(connectToOfono(QString)));
    connect(d_ptr->ofonoWatcher, SIGNAL(serviceUnregistered(QString)),
            this, SLOT(ofonoUnregistered(QString)));

    d_ptr->available = QDBusConnection::systemBus().interface()->isServiceRegistered("org.ofono");
    if(d_ptr->available) {
        connectToOfono(QString());
    }
}

QOfonoManager::~QOfonoManager()
{
    delete d_ptr;
}

QStringList QOfonoManager::modems()
{
    return d_ptr->modems;
}

void QOfonoManager::onModemAdd(const QDBusObjectPath& path, const QVariantMap& var)
{
    QString pathStr = path.path();
    if (!d_ptr->modems.contains(pathStr)) {
        d_ptr->modems.append(pathStr);
        Q_EMIT modemAdded(pathStr);
        Q_EMIT modemsChanged(d_ptr->modems);
    }
}

void QOfonoManager::onModemRemove(const QDBusObjectPath& path)
{
    QString pathStr = path.path();
    /* we need to send out modem removed signal, since we decided to turn modem off directly */
    Q_EMIT modemRemoved(pathStr);
    if (d_ptr->modems.contains(pathStr)) {
        d_ptr->modems.removeOne(pathStr);
        Q_EMIT modemsChanged(d_ptr->modems);
    }
}

bool QOfonoManager::available() const
{
    return d_ptr->available;
}

void QOfonoManager::connectToOfono(const QString &)
{
    d_ptr->ofonoManager = new OfonoManager("org.ofono","/",QDBusConnection::systemBus(),this);
    if (d_ptr->ofonoManager->isValid()) {
        QDBusPendingReply<ObjectPathPropertiesList> reply = d_ptr->ofonoManager->GetModems();
        reply.waitForFinished();
        // fugly I know... but we need sorted modems
        // with hardware listed first
        QOfonoModem oModem;
        foreach(ObjectPathProperties modem, reply.value()) {
            QString modemPath = modem.path.path();
            oModem.setModemPath(modemPath);
            if (oModem.type() == "hardware"
                    && !modemPath.contains("phonesim")) {
                // running phonesim from desktop
                // presents phonesim as hardware
                d_ptr->modems.prepend(modemPath);
            } else {
                d_ptr->modems.append(modemPath);
            }

            Q_EMIT modemAdded(modemPath);
        }
        Q_EMIT modemsChanged(d_ptr->modems);
    }
    d_ptr->available = true;
    Q_EMIT availableChanged(true);
    connect(d_ptr->ofonoManager, SIGNAL(ModemAdded(QDBusObjectPath,QVariantMap)), this, SLOT(onModemAdd(QDBusObjectPath,QVariantMap)));
    connect(d_ptr->ofonoManager, SIGNAL(ModemRemoved(QDBusObjectPath)), this, SLOT(onModemRemove(QDBusObjectPath)));
}

void QOfonoManager::ofonoUnregistered(const QString &)
{
    d_ptr->available = false;
    delete d_ptr->ofonoManager;
    Q_FOREACH(const QString &modem, d_ptr->modems) {
        Q_EMIT modemRemoved(modem);
    }
    d_ptr->modems.clear();
    Q_EMIT modemsChanged(d_ptr->modems);
    Q_EMIT availableChanged(false);
}

bool QOfonoManager::isValid() const
{
    return d_ptr->ofonoManager->isValid();
}
<|endoftext|>


<commit_before>#pragma once
#include <envire_core/graph/TransformGraph.hpp>
#include <envire_core/events/GraphEventDispatcher.hpp>
#include <envire_core/events/EdgeModifiedEvent.hpp>
#include <envire_core/items/Transform.hpp>
#include <envire_core/graph/TreeView.hpp>
#include <vizkit3d/TransformerGraph.hpp>
#include <vizkit3d/NodeLink.hpp>
#include <utility>
#include <memory>

/**Visualizes the structure of the given TransformGraph.
 * Automatically updates the structure if the graph changes.
 */
template <class FRAME_PROP>
class TransformGraphStructureVisualizer : public envire::core::GraphEventDispatcher
{
  using vertex_descriptor = envire::core::GraphTraits::vertex_descriptor;
  using Transform = envire::core::Transform;
  using edge_descriptor = envire::core::GraphTraits::edge_descriptor;
  using TransformerGraph = vizkit3d::TransformerGraph;
  using EdgeModifiedEvent = envire::core::EdgeModifiedEvent;
  using PosAtt = osg::PositionAttitudeTransform;
public:
  using GraphPtr = std::shared_ptr<envire::core::TransformGraph<FRAME_PROP>>;
  using FrameId = envire::core::FrameId;
  using TreeView = envire::core::TreeView;

  /**Creates an instance of the visualizer that is not connected to any graph.
   * init() needs to be called in order to use the graph*/
  TransformGraphStructureVisualizer();

  /**Creates an instance that is connected to @p graph and displays the structure
   * starting from @p rootNode*/
  TransformGraphStructureVisualizer(GraphPtr graph, const FrameId& rootNode);

  /**Connects the visualizer to the specified graph.
   * @note this method may only be called once*/
  void init(GraphPtr graph, const FrameId& rootNode);

  /**Only valid after init has been called */
  osg::ref_ptr<osg::Group> getRootNode();

  /**Changes the root node of the visualization */
  void changeRoot(const FrameId& newRoot);

  /**Event handler for the EDGE_MODIFIED event of the TransformGraph */
  virtual void edgeModified(const EdgeModifiedEvent& e);

private:

  /**Adds the treeView starting to the transformerGraph */
  void addTreeview(const TreeView& view, const FrameId& rootNode);

  void setTransformation(const FrameId& source, const FrameId& target,
                         const Transform& tf);

  /**converts a transform to something that osg does unterstand */
  std::pair<osg::Quat, osg::Vec3d> convertTransform(const Transform& tf) const;

  GraphPtr graph;
  TreeView treeView; /**< The view of the graph that is currently visualized*/
  bool initialized = false; /** < */
  osg::ref_ptr<osg::Group> transformerGraph;
  FrameId rootNode;

};

template <class F>
TransformGraphStructureVisualizer<F>::TransformGraphStructureVisualizer()
{}

template <class F>
TransformGraphStructureVisualizer<F>::TransformGraphStructureVisualizer(GraphPtr graph,
                                                                        const FrameId& rootNode)
{
  init(graph, rootNode);
}

template <class F>
void TransformGraphStructureVisualizer<F>::init(GraphPtr graph, const FrameId& root)
{
  assert(!initialized);
  this->graph = graph;
  transformerGraph = TransformerGraph::create("transform_graph_world")->asGroup();
  rootNode = root;
  graph->getTree(root, true, &treeView);
  addTreeview(treeView, rootNode);
  subscribe(&*graph);
  initialized = true;
}

template <class F>
void TransformGraphStructureVisualizer<F>::addTreeview(const TreeView& view,
                                                       const FrameId& rootNode
)
{
  TransformerGraph::addFrame(*transformerGraph, rootNode);
  TransformerGraph::makeRoot(*transformerGraph, rootNode);

  const vertex_descriptor rootVertex = graph->getVertex(rootNode);

  //walk the tree and create a scene graph out of it
  treeView.visitDfs(rootVertex, [&] (const vertex_descriptor vd, const vertex_descriptor parent)
  {
    //skip the root node, the corresponding osg node has been created manually beforehand
    if(vd == rootVertex) return;

    const FrameId& id = graph->getFrameId(vd);
    const FrameId& parentId = graph->getFrameId(parent);

    TransformerGraph::addFrame(*transformerGraph, id);
    const Transform tf = graph->getTransform(parent, vd);
    setTransformation(parentId, id, tf);
  });

  //when the minimal tree has been added, the cross-edges can be added.
  //we need to add them manually because the TransformerGraph breaks when
  //adding loops
  for(const edge_descriptor edge : treeView.crossEdges)
  {
    const FrameId& source = graph->getFrameId(graph->source(edge));
    const FrameId& target = graph->getFrameId(graph->target(edge));

    PosAtt* srcNode = dynamic_cast<PosAtt*>(TransformerGraph::getFrame(*transformerGraph, source));
    PosAtt* tarNode = dynamic_cast<PosAtt*>(TransformerGraph::getFrame(*transformerGraph, target));
    assert(srcNode);
    assert(tarNode);

    //The NodeLink will update its position automatically to reflect changes in src and target
    osg::Node *link = vizkit::NodeLink::create(srcNode, tarNode, osg::Vec4(255,255,0,255));
    link->setName("crossEdge");
    osg::Group* group = TransformerGraph::getFrameGroup(*transformerGraph, source);
    group->addChild(link);
  }
}

template <class F>
void TransformGraphStructureVisualizer<F>::setTransformation(const FrameId& source,
                                                             const FrameId& target,
                                                             const Transform& tf)
{
  //normalizing is important, otherwise osg will break when switching the root.
  osg::Quat orientation;
  osg::Vec3d translation;
  std::tie(orientation, translation) = convertTransform(tf);

  std::cout << source << " -> " << target << translation.x() << " " << translation.y() << " "
            << translation.z() << std::endl;

  TransformerGraph::setTransformation(*transformerGraph, source, target, orientation, translation);
}

template <class F>
void TransformGraphStructureVisualizer<F>::changeRoot(const FrameId& newRoot)
{
  //check if the new root is part of the current TreeView
  //if it is, the TransformerGraph already knows about it and we can just
  //change the root. Otherwise the whole tree needs to be re-generated.
  //This only happens when the graph consists of multiple disconnected graphs
  const vertex_descriptor newRootDesc = graph->getVertex(newRoot);
  if(treeView.tree.find(newRootDesc) != treeView.tree.end())
  {
    TransformerGraph::makeRoot(*transformerGraph, newRoot);
  }
  else
  {
    treeView.unsubscribe();
    treeView.clear();
    vizkit3d::TransformerGraph::removeFrame(*transformerGraph, rootNode);//clear the visualization
    graph->getTree(newRoot, true, &treeView);
    addTreeview(treeView, newRoot);
    rootNode = newRoot;
  }
}

template <class F>
osg::ref_ptr<osg::Group> TransformGraphStructureVisualizer<F>::getRootNode()
{
  assert(initialized);

  return transformerGraph;
}

template <class F>
void TransformGraphStructureVisualizer<F>::edgeModified(const EdgeModifiedEvent& e)
{
  assert(initialized);
  Transform tf = graph->getTransform(e.origin, e.target);
  osg::Quat orientation;
  osg::Vec3d translation;
  std::tie(orientation, translation) = convertTransform(tf);
  TransformerGraph::setTransformation(*transformerGraph, e.origin, e.target, orientation, translation);
}

template <class F>
std::pair<osg::Quat, osg::Vec3d> TransformGraphStructureVisualizer<F>::convertTransform(const Transform& tf) const
{
  const base::Quaterniond& rot = tf.transform.orientation.normalized();
  const base::Position& pos = tf.transform.translation;
  const osg::Quat orientation(rot.x(), rot.y(), rot.z(), rot.w());
  const osg::Vec3d translation(pos.x(), pos.y(), pos.z());
  return std::make_pair(orientation, translation);
}

<commit_msg>visualizer: works as intendet... i guess<commit_after>#pragma once
#include <envire_core/graph/TransformGraph.hpp>
#include <envire_core/items/Transform.hpp>
#include <envire_core/graph/TreeView.hpp>
#include <envire_core/events/GraphEventDispatcher.hpp>
#include <vizkit3d/TransformerGraph.hpp>
#include <vizkit3d/NodeLink.hpp>
#include <utility>
#include <memory>

/**Visualizes the structure of the given TransformGraph.
 * Automatically updates the structure if the graph changes.
 */
template <class FRAME_PROP>
class TransformGraphStructureVisualizer : envire::core::GraphEventDispatcher
{
  using vertex_descriptor = envire::core::GraphTraits::vertex_descriptor;
  using edge_descriptor = envire::core::GraphTraits::edge_descriptor;
  using Transform = envire::core::Transform;
  using TransformerGraph = vizkit3d::TransformerGraph;
  using EdgeModifiedEvent = envire::core::EdgeModifiedEvent;

public:
  using GraphPtr = std::shared_ptr<envire::core::TransformGraph<FRAME_PROP>>;
  using FrameId = envire::core::FrameId;
  using TreeView = envire::core::TreeView;

  /**Creates an instance of the visualizer that is not connected to any graph.
   * init() needs to be called in order to use the graph*/
  TransformGraphStructureVisualizer();

  /**Creates an instance that is connected to @p graph and displays the structure
   * starting from @p rootNode*/
  TransformGraphStructureVisualizer(GraphPtr graph, const FrameId& rootNode);

  /**Connects the visualizer to the specified graph.
   * @note this method may only be called once*/
  void init(GraphPtr graph, const FrameId& rootNode);

  /**Only valid after init has been called */
  osg::ref_ptr<osg::Group> getRootNode();

  /**Changes the root node of the visualization */
  void changeRoot(const FrameId& newRoot);

  /**Is called whenever a new edge is added to the treeView */
  void edgeAdded(vertex_descriptor origin,
                 vertex_descriptor target);

  /**Is called whenever a new cross-edge is added to the treeView */
  void crossEdgeAdded(edge_descriptor edge);

  /**Is called whenever an edge is modified inside the graph */
  void edgeModified(const EdgeModifiedEvent& e);

private:

  void setTransformation(const FrameId& source, const FrameId& target,
                         const Transform& tf);

  /**converts a transform to something that osg does unterstand */
  std::pair<osg::Quat, osg::Vec3d> convertTransform(const Transform& tf) const;

  GraphPtr graph;
  TreeView treeView; /**< The view of the graph that is currently visualized*/
  bool initialized = false; /** < */
  osg::ref_ptr<osg::Group> transformerGraph;
  FrameId rootNode;

};

template <class F>
TransformGraphStructureVisualizer<F>::TransformGraphStructureVisualizer()
{}

template <class F>
TransformGraphStructureVisualizer<F>::TransformGraphStructureVisualizer(GraphPtr graph,
                                                                        const FrameId& rootNode)
{
  init(graph, rootNode);
}

template <class F>
void TransformGraphStructureVisualizer<F>::init(GraphPtr graph, const FrameId& root)
{
  assert(!initialized);
  this->graph = graph;
  transformerGraph = TransformerGraph::create("transform_graph_world")->asGroup();
  rootNode = root;

      //Lambda to call edgeAdded event handler
  auto edgeAddedLambda = std::bind(&TransformGraphStructureVisualizer<F>::edgeAdded,
                                   this, std::placeholders::_1, std::placeholders::_2);
  treeView.edgeAdded.connect(edgeAddedLambda);

  auto crosEdgeAddedLambda = std::bind(&TransformGraphStructureVisualizer<F>::crossEdgeAdded,
                                       this, std::placeholders::_1);
  treeView.crossEdgeAdded.connect(crosEdgeAddedLambda);

  graph->getTree(root, true, &treeView); //this will cause lots of edgeAdded events which will add the edges
  TransformerGraph::makeRoot(*transformerGraph, root);
  //addTreeview(treeView, rootNode);
  subscribe(&*graph);
  initialized = true;
}

template <class F>
void TransformGraphStructureVisualizer<F>::setTransformation(const FrameId& source,
                                                             const FrameId& target,
                                                             const Transform& tf)
{
  //normalizing is important, otherwise osg will break when switching the root.
  osg::Quat orientation;
  osg::Vec3d translation;
  std::tie(orientation, translation) = convertTransform(tf);

  TransformerGraph::setTransformation(*transformerGraph, source, target, orientation, translation);
}

template <class F>
void TransformGraphStructureVisualizer<F>::changeRoot(const FrameId& newRoot)
{
  //check if the new root is part of the current TreeView
  //if it is, the TransformerGraph already knows about it and we can just
  //change the root. Otherwise the whole tree needs to be re-generated.
  //This only happens when the graph consists of multiple disconnected graphs
  const vertex_descriptor newRootDesc = graph->getVertex(newRoot);
  if(treeView.vertexExists(newRootDesc))
  {
    TransformerGraph::makeRoot(*transformerGraph, newRoot);
  }
  else
  {
    treeView.unsubscribe();
    treeView.clear();
    vizkit3d::TransformerGraph::removeFrame(*transformerGraph, rootNode);//clear the visualization
    //resubscribe the now empty treeview, this will cause a whole new bunch of edgeAdded events
    graph->getTree(newRoot, true, &treeView);
    rootNode = newRoot;
    TransformerGraph::makeRoot(*transformerGraph, newRoot);
  }
}

template <class F>
osg::ref_ptr<osg::Group> TransformGraphStructureVisualizer<F>::getRootNode()
{
  assert(initialized);

  return transformerGraph;
}

template <class F>
void TransformGraphStructureVisualizer<F>::edgeModified(const EdgeModifiedEvent& e)
{
  assert(initialized);
  Transform tf = graph->getTransform(e.origin, e.target);
  const vertex_descriptor originDesc = graph->getVertex(e.origin);
  const vertex_descriptor targetDesc = graph->getVertex(e.target);

  osg::Quat orientation;
  osg::Vec3d translation;
  std::tie(orientation, translation) = convertTransform(tf);
  TransformerGraph::setTransformation(*transformerGraph, e.origin, e.target, orientation, translation);
}

template <class F>
void TransformGraphStructureVisualizer<F>::edgeAdded(vertex_descriptor origin,
                                                     vertex_descriptor target)
{
  const Transform tf = graph->getTransform(origin, target);
  const FrameId& originName = graph->getFrameId(origin);
  const FrameId& targetName = graph->getFrameId(target);
  osg::Quat orientation;
  osg::Vec3d translation;
  std::tie(orientation, translation) = convertTransform(tf);

  if(TransformerGraph::getFrame(*transformerGraph, originName) == nullptr)
    TransformerGraph::addFrame(*transformerGraph, originName);

  if(TransformerGraph::getFrame(*transformerGraph, targetName) == nullptr)
    TransformerGraph::addFrame(*transformerGraph, targetName);

  TransformerGraph::setTransformation(*transformerGraph, originName, targetName, orientation, translation);
}

template <class F>
void TransformGraphStructureVisualizer<F>::crossEdgeAdded(edge_descriptor edge)
{
  const FrameId& source = graph->getFrameId(graph->source(edge));
  const FrameId& target = graph->getFrameId(graph->target(edge));

  osg::Node* srcNode = TransformerGraph::getFrame(*transformerGraph, source);
  osg::Node* tarNode = TransformerGraph::getFrame(*transformerGraph, target);
  //the frames should always exist, otherwise this edge wouldn't be a cross-edge
  assert(srcNode);
  assert(tarNode);

  //The NodeLink will update its position automatically to reflect changes in src and target
  osg::Node *link = vizkit::NodeLink::create(srcNode, tarNode, osg::Vec4(255,255,0,255));
  link->setName("crossEdge");
  osg::Group* group = TransformerGraph::getFrameGroup(*transformerGraph, source);
  group->addChild(link);
}

template <class F>
std::pair<osg::Quat, osg::Vec3d> TransformGraphStructureVisualizer<F>::convertTransform(const Transform& tf) const
{
  const base::Quaterniond& rot = tf.transform.orientation.normalized();
  const base::Position& pos = tf.transform.translation;
  const osg::Quat orientation(rot.x(), rot.y(), rot.z(), rot.w());
  const osg::Vec3d translation(pos.x(), pos.y(), pos.z());
  return std::make_pair(orientation, translation);
}

<|endoftext|>


<commit_before>#ifndef LEGACY_CPU_CHECK_HPP_38B388C1_AF11_4F09_9643_074418E35699
#define LEGACY_CPU_CHECK_HPP_38B388C1_AF11_4F09_9643_074418E35699
#pragma once

/*
legacy_cpu_check.hpp

  SSE2  x86
*/
/*
Copyright  1996 Eugene Roshal
Copyright  2000 Far Group
All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
1. Redistributions of source code must retain the above copyright
   notice, this list of conditions and the following disclaimer.
2. 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.
3. The name of the authors may not be used to endorse or promote products
   derived from this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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.
*/

bool IsLegacyCPU();

#endif // LASTERROR_HPP_1C20B3B0_E43C_4DCC_9729_DFD883E99DD3
<commit_msg>-copypaste - comment fixrd<commit_after>#ifndef LEGACY_CPU_CHECK_HPP_38B388C1_AF11_4F09_9643_074418E35699
#define LEGACY_CPU_CHECK_HPP_38B388C1_AF11_4F09_9643_074418E35699
#pragma once

/*
legacy_cpu_check.hpp

  SSE2  x86
*/
/*
Copyright  1996 Eugene Roshal
Copyright  2000 Far Group
All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
1. Redistributions of source code must retain the above copyright
   notice, this list of conditions and the following disclaimer.
2. 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.
3. The name of the authors may not be used to endorse or promote products
   derived from this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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.
*/

bool IsLegacyCPU();

#endif // LEGACY_CPU_CHECK_HPP_38B388C1_AF11_4F09_9643_074418E35699
<|endoftext|>


<commit_before>/* Licensed GNU LGPL v3 or later: http://www.gnu.org/licenses/lgpl.html */
#include <rcore/testutils.hh>
#include <ui/uithread.hh>
#include <stdio.h>
#include <stdlib.h>     // lrand48

namespace {
using namespace Rapicorn;

static void
test_rect (void)
{
  Rect r1;
  TASSERT (r1.empty());
  r1.assign (Point (7.1, 7.2), Point (8.4, 8.5));       // stores width=1.3, height=1.3 in double precision
  TASSERT (!r1.empty());
  Rect r2 (7.1, 7.2, 1.3, 1.3);
  TASSERT (r2 == Rect (7.1, 7.2, 1.3, 1.3));
  TASSERT (false == (r2 != Rect (7.1, 7.2, 1.3, 1.3)));
  Rect r3 (7.1, 7.2, 1.0, 1.0);
  TASSERT (r3.equals (r2, 0.1) == false);
  TASSERT (r3.equals (r2, 0.5) == true);
  TASSERT (r2.equals (r1, 0.00000000000001));           // using epsilon due to precision artefacts
}
REGISTER_UITHREAD_TEST ("Region/rectangles", test_rect);

static void
test_region_basics (void)
{
  Region r, z;
  TASSERT (r.empty());
  TASSERT (z.empty());
  TASSERT (r.equal (r));
  TASSERT (r.equal (z));
  r.add (Rect (Point (-1, -1), Point (1, 1)));
  TASSERT (!r.empty());
  TASSERT (z.empty());
  TASSERT (!r.equal (z));
  r.swap (z);
  TASSERT (r.empty());
  TASSERT (!z.empty());
  TASSERT (!r.equal (z));
  z.clear();
  TASSERT (r.empty());
  TASSERT (z.empty());
  TASSERT (r.equal (z));
}
REGISTER_UITHREAD_TEST ("Region/region basics", test_region_basics);

static void
test_region_rect1 (void)
{
  Region r;
  r.clear();
  TASSERT (r.empty());
  TASSERT (r.contains (Point (0, 0)) == false);
  r.add (Rect (Point (3, 3), Point (5, 5)));
  TASSERT (!r.empty());
  TASSERT (r.contains (2, 2) == false);
  TASSERT (r.contains (3, 3));
  TASSERT (r.contains (4, 4));
  TASSERT (r.contains (5, 5) == false);
  TASSERT (r.contains (6, 6) == false);
  TASSERT (r.contains (Rect (Point (3, 3), Point (5, 5))) == r.INSIDE);
  TASSERT (r.contains (Rect (Point (4, 4), Point (6, 6))) == r.PARTIAL);
  TASSERT (r.contains (Rect (Point (5, 5), Point (6, 6))) == r.OUTSIDE);
  vector<Rect> rects;
  r.list_rects (rects);
  TASSERT (rects.size() == 1);
  TASSERT (rects[0].lower_left() == Point (3, 3));
  TASSERT (rects[0].upper_right() == Point (5, 5));
  Region z (r);
  TASSERT (r.equal (z));
  r.exor (r);
  TASSERT (r.empty());
  TASSERT (!r.equal (z));
  z.clear();
  TASSERT (r.equal (z));
  TASSERT (r.extents() == Rect (Point (0, 0), Point (0, 0)));
  const Region e;
  TASSERT (e.contains (Point (0, 0)) == false);
  TASSERT (e.contains (Rect (Point (0, 0), Point (0, 0))) == true);
  TASSERT (e.contains (Rect (Point (0, 0), Point (1, 1))) == false);
  TASSERT (e.contains (Region()) == true);
}
REGISTER_UITHREAD_TEST ("Region/region rec1t", test_region_rect1);

static void
test_region2 (void)
{
  Region a (Rect (Point (-1, -1), Point (1, 1)));
  Region b (Rect (Point (-1, -1), Point (0, 0)));
  TASSERT (a.equal (b) == false);
  TASSERT ((a != b) == true);
  TASSERT ((a == b) == false);
  TASSERT (a.cmp (b) != 0);
  if (a.cmp (b) < 0)
    TASSERT (a < b);
  else
    TASSERT (b < a);
  a.clear();
  b.clear();
  TASSERT (a.empty());
  TASSERT (b.empty());
  TASSERT (a.equal (b) == true);
  TASSERT ((a != b) == false);
  TASSERT ((a == b) == true);
  TASSERT (a.cmp (b) == 0);
  TASSERT ((a < b) == false);
  TASSERT ((b < a) == false);
}
REGISTER_UITHREAD_TEST ("Region/region2", test_region2);

static void
test_region2_ops (void)
{
  Region a (Rect (Point (-1, -1), Point (1, 1))), sa = a;
  Region b (Rect (Point (-1, -1), Point (0, 0))), sb = b;
  Region c (Rect (Point (-1, -1), Point (0, 0))), sc = c;
  b.intersect (a);
  TASSERT (b == c);
  TASSERT (a != c);
  TASSERT (b == sb);
  TASSERT (a == sa);
  a.intersect (b);
  TASSERT (a != sa);
  TASSERT (a == c);
  a = sa;
  TASSERT (a == sa);
  TASSERT (a.contains (c.extents()) == true);
  a.subtract (b);
  TASSERT (a != sa);
  TASSERT (a.contains (c.extents()) == false);
  a.add (b);
  TASSERT (a.contains (c.extents()) == true);
  TASSERT (a == sa);
  a.add (b);
  TASSERT (a == sa);
  a.intersect (a);
  TASSERT (a == sa);
  a.exor (a);
  TASSERT (a.empty());
  a.exor (b);
  TASSERT (a == b);
  b.exor (a);
  TASSERT (b.empty() && b != sb);
  b.exor (a);
  TASSERT (b == sb);
}
REGISTER_UITHREAD_TEST ("Region/region2 ops", test_region2_ops);

static Region
create_rand_region (void)
{
  Region r;
  int u = 1 + (abs (lrand48()) % 157);
  if (u >= 50 && u <= 99)
    return Region (Point (70, 123455), Point (12345, 1987)); // need equal regions with some probability
  for (int i = 0; i < u; i++)
    r.add (Rect (Point (lrand48() * 0.005 + (((int64) lrand48()) << 16), lrand48() * 0.005 + (((int64) lrand48()) << 16)),
                 Point (lrand48() * 0.005 + (((int64) lrand48()) << 16), lrand48() * 0.005 + (((int64) lrand48()) << 16))));
  return r;
}

static void
test_region_fract (void)
{
  Region r;
  TASSERT (r.empty());
  const double epsilon = r.epsilon();   /* allow errors within +-epsilon */
  TASSERT (epsilon <= 0.5);             /* assert at least pxiel resolution */
  r.clear();
  TASSERT (r.empty());
  TASSERT (r.contains (Point (0, 0)) == false);
  r.add (Rect (Point (0.1, 0.2), Point (3.4, 4.5)));
  TASSERT (!r.empty());
  TASSERT (r.contains (2, 2));
  TASSERT (r.contains (0, 0) == false);
  TASSERT (r.contains (1, 1));
  TASSERT (r.contains (3, 3));
  TASSERT (r.contains (3.3, 3));
  TASSERT (r.contains (3.5, 3) == false);
  TASSERT (r.contains (3.3, 4.4));
  TASSERT (r.contains (3.3, 4.6) == false);
  TASSERT (r.contains (6, 6) == false);
  TASSERT (r.contains (Rect (1, 1, 2, 2)) == r.INSIDE);
  TASSERT (r.contains (Rect (0, 0, 3, 3)) == r.PARTIAL);
  TASSERT (r.contains (Rect (3.5, 0, 70, 70)) == r.OUTSIDE);
  Region r2 = r;
  TASSERT (r2.extents().equals (Rect (0.1, 0.2, 3.3, 4.3), epsilon));
  r2.add (Rect (0, 0, 0.1, 4.5));
  r2.add (Rect (0, 0, 3.4, 0.2));
  Region r3 (Rect (0, 0, 3.4, 4.5));
  TASSERT (r2 == r3);
  std::vector<Rect> rects;
  r3.list_rects (rects);
  TASSERT (rects.size() == 1);
  TASSERT (rects[0].equals (Rect (0, 0, 3.4, 4.5), epsilon));
  if (0)
    printf ("\nREGION:\n%s\nEMPTY:\n%s\n", create_rand_region().string().c_str(), Region().string().c_str());
}
REGISTER_UITHREAD_TEST ("Region/fractional regions", test_region_fract);

static void
test_region_cmp ()
{
  int cases = 0;
  for (uint i = 0; i < 65 || cases != 7; i++)
    {
      Region r1 = create_rand_region();
      TCHECK (r1.contains (r1) == r1.INSIDE);
      TCHECK (r1.contains (Region (r1)) == r1.INSIDE);
      Region r2 = create_rand_region();
      TCHECK (r2.contains (r2) == r2.INSIDE);
      TCHECK (r2.contains (Region (r2)) == r2.INSIDE);
      int c1 = r1.cmp (r2);
      int c2 = r2.cmp (r1);
      TCHECK (c1 == -c2);
      if (c1)
        {
          TCHECK (r1 != r2);
          TCHECK (r2 != r1);
        }
      else
        {
          TCHECK (r1 == r2);
          TCHECK (r2 == r1);
        }
      if (c1 < 0)
        {
          TCHECK (r1 < r2);
          TCHECK (r1.equal (r2) == false);
          TCHECK ((r2 < r1) == false);
          TCHECK (r2.equal (r1) == false);
          cases |= 1;
        }
      else if (c1 == 0)
        {
          TCHECK ((r1 < r2) == false);
          TCHECK (r1.equal (r2) == true);
          TCHECK ((r2 < r1) == false);
          TCHECK (r2.equal (r1) == true);
          cases |= 2;
        }
      else if (c1 > 0)
        {
          TCHECK (r2 < r1);
          TCHECK (r2.equal (r1) == false);
          TCHECK ((r1 < r2) == false);
          TCHECK (r1.equal (r2) == false);
          cases |= 4;
        }
      Region c;
      TCHECK (r1.contains (c)); // empty containment
      TCHECK (r2.contains (c)); // empty containment
      c.add (r1);
      c.add (r2);
      TCHECK (c.contains (r1));
      TCHECK (c.contains (r2));
      c.subtract (r1);
      c.subtract (r2);
      if (!r1.empty())
        TCHECK (c.contains (r1) == false);
      if (!r2.empty())
        TCHECK (c.contains (r2) == false);
      TASSERT (c.empty());
    }
}
REGISTER_UITHREAD_TEST ("Region/random-cmp", test_region_cmp);

} // Anon
<commit_msg>UI: use TCMP() for region tests where possible<commit_after>/* Licensed GNU LGPL v3 or later: http://www.gnu.org/licenses/lgpl.html */
#include <rcore/testutils.hh>
#include <ui/uithread.hh>
#include <stdio.h>
#include <stdlib.h>     // lrand48

namespace {
using namespace Rapicorn;

static void
test_rect (void)
{
  Rect r1;
  TASSERT (r1.empty());
  r1.assign (Point (7.1, 7.2), Point (8.4, 8.5));       // stores width=1.3, height=1.3 in double precision
  TASSERT (!r1.empty());
  Rect r2 (7.1, 7.2, 1.3, 1.3);
  TCMP (r2, ==, Rect (7.1, 7.2, 1.3, 1.3));
  TASSERT (false == (r2 != Rect (7.1, 7.2, 1.3, 1.3)));
  Rect r3 (7.1, 7.2, 1.0, 1.0);
  TCMP (r3.equals (r2, 0.1), ==, false);
  TCMP (r3.equals (r2, 0.5), ==, true);
  TASSERT (r2.equals (r1, 0.00000000000001));           // using epsilon due to precision artefacts
}
REGISTER_UITHREAD_TEST ("Region/rectangles", test_rect);

static void
test_region_basics (void)
{
  Region r, z;
  TASSERT (r.empty());
  TASSERT (z.empty());
  TASSERT (r.equal (r));
  TASSERT (r.equal (z));
  r.add (Rect (Point (-1, -1), Point (1, 1)));
  TASSERT (!r.empty());
  TASSERT (z.empty());
  TASSERT (!r.equal (z));
  r.swap (z);
  TASSERT (r.empty());
  TASSERT (!z.empty());
  TASSERT (!r.equal (z));
  z.clear();
  TASSERT (r.empty());
  TASSERT (z.empty());
  TASSERT (r.equal (z));
}
REGISTER_UITHREAD_TEST ("Region/region basics", test_region_basics);

static void
test_region_rect1 (void)
{
  Region r;
  r.clear();
  TASSERT (r.empty());
  TCMP (r.contains (Point (0, 0)), ==, false);
  r.add (Rect (Point (3, 3), Point (5, 5)));
  TASSERT (!r.empty());
  TCMP (r.contains (2, 2), ==, false);
  TASSERT (r.contains (3, 3));
  TASSERT (r.contains (4, 4));
  TCMP (r.contains (5, 5), ==, false);
  TCMP (r.contains (6, 6), ==, false);
  TCMP (r.contains (Rect (Point (3, 3), Point (5, 5))), ==, r.INSIDE);
  TCMP (r.contains (Rect (Point (4, 4), Point (6, 6))), ==, r.PARTIAL);
  TCMP (r.contains (Rect (Point (5, 5), Point (6, 6))), ==, r.OUTSIDE);
  vector<Rect> rects;
  r.list_rects (rects);
  TCMP (rects.size(), ==, 1);
  TCMP (rects[0].lower_left(), ==, Point (3, 3));
  TCMP (rects[0].upper_right(), ==, Point (5, 5));
  Region z (r);
  TASSERT (r.equal (z));
  r.exor (r);
  TASSERT (r.empty());
  TASSERT (!r.equal (z));
  z.clear();
  TASSERT (r.equal (z));
  TCMP (r.extents(), ==, Rect (Point (0, 0), Point (0, 0)));
  const Region e;
  TCMP (e.contains (Point (0, 0)), ==, false);
  TCMP (e.contains (Rect (Point (0, 0), Point (0, 0))), ==, true);
  TCMP (e.contains (Rect (Point (0, 0), Point (1, 1))), ==, false);
  TCMP (e.contains (Region()), ==, true);
}
REGISTER_UITHREAD_TEST ("Region/region rec1t", test_region_rect1);

static void
test_region2 (void)
{
  Region a (Rect (Point (-1, -1), Point (1, 1)));
  Region b (Rect (Point (-1, -1), Point (0, 0)));
  TCMP (a.equal (b), ==, false);
  TASSERT ((a != b) == true);
  TASSERT ((a == b) == false);
  TCMP (a.cmp (b), !=, 0);
  if (a.cmp (b) < 0)
    TCMP (a, <, b);
  else
    TCMP (b, <, a);
  a.clear();
  b.clear();
  TASSERT (a.empty());
  TASSERT (b.empty());
  TCMP (a.equal (b), ==, true);
  TASSERT ((a != b) == false);
  TASSERT ((a == b) == true);
  TCMP (a.cmp (b), ==, 0);
  TCMP ((a < b), ==, false);
  TCMP ((b < a), ==, false);
}
REGISTER_UITHREAD_TEST ("Region/region2", test_region2);

static void
test_region2_ops (void)
{
  Region a (Rect (Point (-1, -1), Point (1, 1))), sa = a;
  Region b (Rect (Point (-1, -1), Point (0, 0))), sb = b;
  Region c (Rect (Point (-1, -1), Point (0, 0))), sc = c;
  b.intersect (a);
  TCMP (b, ==, c);
  TCMP (a, !=, c);
  TCMP (b, ==, sb);
  TCMP (a, ==, sa);
  a.intersect (b);
  TCMP (a, !=, sa);
  TCMP (a, ==, c);
  a = sa;
  TCMP (a, ==, sa);
  TCMP (a.contains (c.extents()), ==, true);
  a.subtract (b);
  TCMP (a, !=, sa);
  TCMP (a.contains (c.extents()), ==, false);
  a.add (b);
  TCMP (a.contains (c.extents()), ==, true);
  TCMP (a, ==, sa);
  a.add (b);
  TCMP (a, ==, sa);
  a.intersect (a);
  TCMP (a, ==, sa);
  a.exor (a);
  TASSERT (a.empty());
  a.exor (b);
  TCMP (a, ==, b);
  b.exor (a);
  TASSERT (b.empty());
  TCMP (b, !=, sb);
  b.exor (a);
  TCMP (b, ==, sb);
}
REGISTER_UITHREAD_TEST ("Region/region2 ops", test_region2_ops);

static Region
create_rand_region (void)
{
  Region r;
  int u = 1 + (abs (lrand48()) % 157);
  if (u >= 50 && u <= 99)
    return Region (Point (70, 123455), Point (12345, 1987)); // need equal regions with some probability
  for (int i = 0; i < u; i++)
    r.add (Rect (Point (lrand48() * 0.005 + (((int64) lrand48()) << 16), lrand48() * 0.005 + (((int64) lrand48()) << 16)),
                 Point (lrand48() * 0.005 + (((int64) lrand48()) << 16), lrand48() * 0.005 + (((int64) lrand48()) << 16))));
  return r;
}

static void
test_region_fract (void)
{
  Region r;
  TASSERT (r.empty());
  const double epsilon = r.epsilon();   /* allow errors within +-epsilon */
  TCMP (epsilon, <=, 0.5);             /* assert at least pxiel resolution */
  r.clear();
  TASSERT (r.empty());
  TCMP (r.contains (Point (0, 0)), ==, false);
  r.add (Rect (Point (0.1, 0.2), Point (3.4, 4.5)));
  TASSERT (!r.empty());
  TASSERT (r.contains (2, 2));
  TCMP (r.contains (0, 0), ==, false);
  TASSERT (r.contains (1, 1));
  TASSERT (r.contains (3, 3));
  TASSERT (r.contains (3.3, 3));
  TCMP (r.contains (3.5, 3), ==, false);
  TASSERT (r.contains (3.3, 4.4));
  TCMP (r.contains (3.3, 4.6), ==, false);
  TCMP (r.contains (6, 6), ==, false);
  TCMP (r.contains (Rect (1, 1, 2, 2)), ==, r.INSIDE);
  TCMP (r.contains (Rect (0, 0, 3, 3)), ==, r.PARTIAL);
  TCMP (r.contains (Rect (3.5, 0, 70, 70)), ==, r.OUTSIDE);
  Region r2 = r;
  TASSERT (r2.extents().equals (Rect (0.1, 0.2, 3.3, 4.3), epsilon));
  r2.add (Rect (0, 0, 0.1, 4.5));
  r2.add (Rect (0, 0, 3.4, 0.2));
  Region r3 (Rect (0, 0, 3.4, 4.5));
  TCMP (r2, ==, r3);
  std::vector<Rect> rects;
  r3.list_rects (rects);
  TCMP (rects.size(), ==, 1);
  TASSERT (rects[0].equals (Rect (0, 0, 3.4, 4.5), epsilon));
  if (0)
    printf ("\nREGION:\n%s\nEMPTY:\n%s\n", create_rand_region().string().c_str(), Region().string().c_str());
}
REGISTER_UITHREAD_TEST ("Region/fractional regions", test_region_fract);

static void
test_region_cmp ()
{
  int cases = 0;
  for (uint i = 0; i < 65 || cases != 7; i++)
    {
      Region r1 = create_rand_region();
      TCMP (r1.contains (r1), ==, r1.INSIDE);
      TCMP (r1.contains (Region (r1)), ==, r1.INSIDE);
      Region r2 = create_rand_region();
      TCMP (r2.contains (r2), ==, r2.INSIDE);
      TCMP (r2.contains (Region (r2)), ==, r2.INSIDE);
      int c1 = r1.cmp (r2);
      int c2 = r2.cmp (r1);
      TCMP (c1, ==, -c2);
      if (c1)
        {
          TCMP (r1, !=, r2);
          TCMP (r2, !=, r1);
        }
      else
        {
          TCMP (r1, ==, r2);
          TCMP (r2, ==, r1);
        }
      if (c1 < 0)
        {
          TCMP (r1, <, r2);
          TCMP (r1.equal (r2), ==, false);
          TCMP ((r2 < r1), ==, false);
          TCMP (r2.equal (r1), ==, false);
          cases |= 1;
        }
      else if (c1 == 0)
        {
          TCMP ((r1 < r2), ==, false);
          TCMP (r1.equal (r2), ==, true);
          TCMP ((r2 < r1), ==, false);
          TCMP (r2.equal (r1), ==, true);
          cases |= 2;
        }
      else if (c1 > 0)
        {
          TCMP (r2, <, r1);
          TCMP (r2.equal (r1), ==, false);
          TCMP ((r1 < r2), ==, false);
          TCMP (r1.equal (r2), ==, false);
          cases |= 4;
        }
      Region c;
      TASSERT (r1.contains (c)); // empty containment
      TASSERT (r2.contains (c)); // empty containment
      c.add (r1);
      c.add (r2);
      TASSERT (c.contains (r1));
      TASSERT (c.contains (r2));
      c.subtract (r1);
      c.subtract (r2);
      if (!r1.empty())
        TCMP (c.contains (r1), ==, false);
      if (!r2.empty())
        TCMP (c.contains (r2), ==, false);
      TASSERT (c.empty());
    }
}
REGISTER_UITHREAD_TEST ("Region/random-cmp", test_region_cmp);

} // Anon
<|endoftext|>