<commit_before>/*
 * AsyncServer.hpp
 *
 * Copyright (C) 2009-12 by RStudio, Inc.
 *
 * This program is licensed to you under the terms of version 3 of the
 * GNU Affero General Public License. This program is distributed WITHOUT
 * ANY EXPRESS OR IMPLIED WARRANTY, INCLUDING THOSE OF NON-INFRINGEMENT,
 * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Please refer to the
 * AGPL (http://www.gnu.org/licenses/agpl-3.0.txt) for more details.
 *
 */

#ifndef CORE_HTTP_ASYNC_SERVER_HPP
#define CORE_HTTP_ASYNC_SERVER_HPP

#include <vector>

#include <boost/shared_ptr.hpp>
#include <boost/function.hpp>
#include <boost/algorithm/string.hpp>

#include <boost/asio/io_service.hpp>
#include <boost/asio/placeholders.hpp>
#include <boost/asio/deadline_timer.hpp>

#include <core/BoostThread.hpp>
#include <core/Error.hpp>
#include <core/BoostErrors.hpp>
#include <core/Log.hpp>
#include <core/ScheduledCommand.hpp>
#include <core/system/System.hpp>

#include <core/http/Request.hpp>
#include <core/http/Response.hpp>
#include <core/http/AsyncConnectionImpl.hpp>
#include <core/http/AsyncUriHandler.hpp>
#include <core/http/Util.hpp>
#include <core/http/UriHandler.hpp>
#include <core/http/SocketUtils.hpp>
#include <core/http/SocketAcceptorService.hpp>

namespace core {
namespace http {

template <typename ProtocolType>
class AsyncServer : boost::noncopyable
{
public:
   AsyncServer(const std::string& serverName,
               const std::string& baseUri = std::string())
      : abortOnResourceError_(false),
        serverName_(serverName),
        baseUri_(baseUri),
        acceptorService_(),
        scheduledCommandTimer_(acceptorService_.ioService())
   {
   }

   virtual ~AsyncServer()
   {
   }

   void setAbortOnResourceError(bool abortOnResourceError)
   {
      abortOnResourceError_ = abortOnResourceError;
   }

   void addHandler(const std::string& prefix,
                   const AsyncUriHandlerFunction& handler)
   {
      uriHandlers_.add(AsyncUriHandler(baseUri_ + prefix, handler));
   }

   void addBlockingHandler(const std::string& prefix,
                           const UriHandlerFunction& handler)
   {
      addHandler(prefix,
                 boost::bind(handleAsyncConnectionSynchronously, handler, _1));
   }

   void setDefaultHandler(const AsyncUriHandlerFunction& handler)
   {
      defaultHandler_ = handler;
   }

   void setBlockingDefaultHandler(const UriHandlerFunction& handler)
   {
      setDefaultHandler(boost::bind(handleAsyncConnectionSynchronously,
                                    handler,
                                    _1));
   }

   void addScheduledCommand(boost::shared_ptr<ScheduledCommand> pCmd)
   {
      scheduledCommands_.push_back(pCmd);
   }

   Error run(std::size_t threadPoolSize = 1)
   {
      try
      {
         // get ready for next connection
         acceptNextConnection();

         // initialize scheduled command timer
         waitForScheduledCommandTimer();

         // block all signals for the creation of the thread pool
         // (prevents signals from occurring on any of the handler threads)
         core::system::SignalBlocker signalBlocker;
         Error error = signalBlocker.blockAll();
         if (error)
            return error ;

         // create the threads
         for (std::size_t i=0; i < threadPoolSize; ++i)
         {
            // run the thread
            boost::shared_ptr<boost::thread> pThread(new boost::thread(
                              &AsyncServer<ProtocolType>::runServiceThread,
                              this));

            // add to list of threads
            threads_.push_back(pThread);
         }
      }
      catch(const boost::thread_resource_error& e)
      {
         return Error(boost::thread_error::ec_from_exception(e),
                      ERROR_LOCATION);
      }

      return Success();
   }

   void stop()
   {
      // close acceptor so we free up the main port immediately
      boost::system::error_code closeEc;
      acceptorService_.closeAcceptor(closeEc);
      if (closeEc)
         LOG_ERROR(Error(closeEc, ERROR_LOCATION));

      // stop the server
      acceptorService_.ioService().stop();
   }

   void waitUntilStopped()
   {
      // wait until all of the threads in the pool exit
      for (std::size_t i=0; i < threads_.size(); ++i)
         threads_[i]->join();
   }

private:

   void runServiceThread()
   {
      try
      {
         boost::system::error_code ec;
         acceptorService_.ioService().run(ec);
         if (ec)
            LOG_ERROR(Error(ec, ERROR_LOCATION));
      }
      CATCH_UNEXPECTED_EXCEPTION
   }

   void acceptNextConnection()
   {
      // create a new connection
      ptrNextConnection_.reset(new AsyncConnectionImpl<ProtocolType>(

         // controlling io_service
         acceptorService_.ioService(),

         // connection handler
         boost::bind(&AsyncServer<ProtocolType>::handleConnection,
                     this, _1, _2),

         // response filter
         boost::bind(&AsyncServer<ProtocolType>::connectionResponseFilter,
                     this, _1)
      ));

      // wait for next connection
      acceptorService_.asyncAccept(
         ptrNextConnection_->socket(),
         boost::bind(&AsyncServer<ProtocolType>::handleAccept,
                     this,
                     boost::asio::placeholders::error)
      );
   }

   void handleAccept(const boost::system::error_code& ec)
   {
      try
      {
         if (!ec)
         {
            // start connection
            ptrNextConnection_->startReading();
         }
         else
         {
            // for errors, log and continue (but don't log operation aborted
            // or bad file descriptor since it happens in the ordinary course
            // of shutting down the server)
            if (ec != boost::asio::error::operation_aborted &&
                ec != boost::system::errc::bad_file_descriptor)
            {
               // log the error
               LOG_ERROR(Error(ec, ERROR_LOCATION)) ;

               // check for resource exhaustion
               checkForResourceExhaustion(ec, ERROR_LOCATION);
            }
         }
      }
      catch(const boost::system::system_error& e)
      {
         // always log
         LOG_ERROR_MESSAGE(std::string("Unexpected exception: ") + e.what());

         // check for resource exhaustion
         checkForResourceExhaustion(e.code(), ERROR_LOCATION);
      }
      CATCH_UNEXPECTED_EXCEPTION

      // ALWAYS accept next connection
      try
      {
         acceptNextConnection() ;
      }
      CATCH_UNEXPECTED_EXCEPTION
   }

   void handleConnection(
         boost::shared_ptr<AsyncConnectionImpl<ProtocolType> > pConnection,
         http::Request* pRequest)
   {
      try
      {
         // call filter
         onRequest(&(pConnection->socket()), pRequest);

         // convert to cannonical HttpConnection
         boost::shared_ptr<AsyncConnection> pAsyncConnection =
             boost::shared_static_cast<AsyncConnection>(pConnection);

         // call the appropriate handler to generate a response
         std::string uri = pRequest->uri();
         AsyncUriHandlerFunction handler = uriHandlers_.handlerFor(uri);
         if (handler)
         {
            // call the handler
            handler(pAsyncConnection) ;
         }
         else if (defaultHandler_)
         {
            // call the default handler
            defaultHandler_(pAsyncConnection);
         }
         else
         {
            // log error
            LOG_ERROR_MESSAGE("Handler not found for uri: " + pRequest->uri());

            // return 404 not found
            pConnection->response().setStatusCode(http::status::NotFound) ;
         }
      }
      catch(const boost::system::system_error& e)
      {
         // always log
         LOG_ERROR_MESSAGE(std::string("Unexpected exception: ") + e.what());

         // check for resource exhaustion
         checkForResourceExhaustion(e.code(), ERROR_LOCATION);
      }
      CATCH_UNEXPECTED_EXCEPTION
   }

   void connectionResponseFilter(http::Response* pResponse)
   {
      // set server header (evade ref-counting to defend against
      // non-threadsafe std::string implementations)
      pResponse->setHeader("Server", std::string(serverName_.c_str()));
   }

   void waitForScheduledCommandTimer()
   {
      // set expiration time for 3 seconds from now
      boost::system::error_code ec;
      scheduledCommandTimer_.expires_from_now(boost::posix_time::seconds(3),
                                              ec);

      // attempt to schedule timer (should always succeed but
      // include error check to be paranoid/robust)
      if (!ec)
      {
         scheduledCommandTimer_.async_wait(boost::bind(
               &AsyncServer<ProtocolType>::handleScheduledCommandTimer,
               this,
               boost::asio::placeholders::error));
      }
      else
      {
         // unexpected error setting timer. log it
         LOG_ERROR(Error(ec, ERROR_LOCATION));
      }
   }

   void handleScheduledCommandTimer(const boost::system::error_code& ec)
   {
      try
      {
         if (!ec)
         {
            // execute all commands
            std::for_each(scheduledCommands_.begin(),
                          scheduledCommands_.end(),
                          boost::bind(&ScheduledCommand::execute, _1));

            // remove any commands which are finished
            scheduledCommands_.erase(
                 std::remove_if(scheduledCommands_.begin(),
                                scheduledCommands_.end(),
                                boost::bind(&ScheduledCommand::finished, _1)),
                 scheduledCommands_.end());

           // wait for the timer again
           waitForScheduledCommandTimer();

         }
         else
         {
            LOG_ERROR(Error(ec, ERROR_LOCATION));
         }
      }
      CATCH_UNEXPECTED_EXCEPTION
   }

protected:
   SocketAcceptorService<ProtocolType>& acceptorService()
   {
      return acceptorService_;
   }

private:

   virtual void onRequest(typename ProtocolType::socket* pSocket,
                          http::Request* pRequest)
   {

   }

   void maybeAbortServer(const std::string& message,
                         const core::ErrorLocation& location)
   {
      if (abortOnResourceError_)
      {
         core::log::logErrorMessage("(ABORTING SERVER): " + message, location);
         ::abort();
      }
      else
      {
         core::log::logWarningMessage(
                  "Resource exhaustion error occurred (continuing to run)",
                  location);
      }
   }

   void checkForResourceExhaustion(const boost::system::error_code& ec,
                                   const core::ErrorLocation& location)
   {
      if ( ec.category() == boost::system::get_system_category() &&
          (ec.value() == boost::system::errc::too_many_files_open ||
           ec.value() == boost::system::errc::not_enough_memory) )
      {
         // our process has run out of memory or file handles. in this
         // case the only way future requests can be serviced is if we
         // abort and allow upstart to respawn us
         maybeAbortServer("Resource exhaustion", location);
      }
   }

   static void handleAsyncConnectionSynchronously(
                        const UriHandlerFunction& uriHandlerFunction,
                        boost::shared_ptr<AsyncConnection> pConnection)
   {
      uriHandlerFunction(pConnection->request(), &(pConnection->response()));
      pConnection->writeResponse();
   }

private:
   bool abortOnResourceError_;
   std::string serverName_;
   std::string baseUri_;
   boost::shared_ptr<AsyncConnectionImpl<ProtocolType> > ptrNextConnection_;
   AsyncUriHandlers uriHandlers_ ;
   AsyncUriHandlerFunction defaultHandler_;
   std::vector<boost::shared_ptr<boost::thread> > threads_;
   SocketAcceptorService<ProtocolType> acceptorService_;
   boost::asio::deadline_timer scheduledCommandTimer_;
   std::vector<boost::shared_ptr<ScheduledCommand> > scheduledCommands_;
};

} // namespace http
} // namespace core

#endif // CORE_HTTP_ASYNC_SERVER_HPP

<commit_msg>don't log an error when the server scheduler timer receives operation cancelled<commit_after>/*
 * AsyncServer.hpp
 *
 * Copyright (C) 2009-12 by RStudio, Inc.
 *
 * This program is licensed to you under the terms of version 3 of the
 * GNU Affero General Public License. This program is distributed WITHOUT
 * ANY EXPRESS OR IMPLIED WARRANTY, INCLUDING THOSE OF NON-INFRINGEMENT,
 * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Please refer to the
 * AGPL (http://www.gnu.org/licenses/agpl-3.0.txt) for more details.
 *
 */

#ifndef CORE_HTTP_ASYNC_SERVER_HPP
#define CORE_HTTP_ASYNC_SERVER_HPP

#include <vector>

#include <boost/shared_ptr.hpp>
#include <boost/function.hpp>
#include <boost/algorithm/string.hpp>

#include <boost/asio/io_service.hpp>
#include <boost/asio/placeholders.hpp>
#include <boost/asio/deadline_timer.hpp>

#include <core/BoostThread.hpp>
#include <core/Error.hpp>
#include <core/BoostErrors.hpp>
#include <core/Log.hpp>
#include <core/ScheduledCommand.hpp>
#include <core/system/System.hpp>

#include <core/http/Request.hpp>
#include <core/http/Response.hpp>
#include <core/http/AsyncConnectionImpl.hpp>
#include <core/http/AsyncUriHandler.hpp>
#include <core/http/Util.hpp>
#include <core/http/UriHandler.hpp>
#include <core/http/SocketUtils.hpp>
#include <core/http/SocketAcceptorService.hpp>

namespace core {
namespace http {

template <typename ProtocolType>
class AsyncServer : boost::noncopyable
{
public:
   AsyncServer(const std::string& serverName,
               const std::string& baseUri = std::string())
      : abortOnResourceError_(false),
        serverName_(serverName),
        baseUri_(baseUri),
        acceptorService_(),
        scheduledCommandTimer_(acceptorService_.ioService())
   {
   }

   virtual ~AsyncServer()
   {
   }

   void setAbortOnResourceError(bool abortOnResourceError)
   {
      abortOnResourceError_ = abortOnResourceError;
   }

   void addHandler(const std::string& prefix,
                   const AsyncUriHandlerFunction& handler)
   {
      uriHandlers_.add(AsyncUriHandler(baseUri_ + prefix, handler));
   }

   void addBlockingHandler(const std::string& prefix,
                           const UriHandlerFunction& handler)
   {
      addHandler(prefix,
                 boost::bind(handleAsyncConnectionSynchronously, handler, _1));
   }

   void setDefaultHandler(const AsyncUriHandlerFunction& handler)
   {
      defaultHandler_ = handler;
   }

   void setBlockingDefaultHandler(const UriHandlerFunction& handler)
   {
      setDefaultHandler(boost::bind(handleAsyncConnectionSynchronously,
                                    handler,
                                    _1));
   }

   void addScheduledCommand(boost::shared_ptr<ScheduledCommand> pCmd)
   {
      scheduledCommands_.push_back(pCmd);
   }

   Error run(std::size_t threadPoolSize = 1)
   {
      try
      {
         // get ready for next connection
         acceptNextConnection();

         // initialize scheduled command timer
         waitForScheduledCommandTimer();

         // block all signals for the creation of the thread pool
         // (prevents signals from occurring on any of the handler threads)
         core::system::SignalBlocker signalBlocker;
         Error error = signalBlocker.blockAll();
         if (error)
            return error ;

         // create the threads
         for (std::size_t i=0; i < threadPoolSize; ++i)
         {
            // run the thread
            boost::shared_ptr<boost::thread> pThread(new boost::thread(
                              &AsyncServer<ProtocolType>::runServiceThread,
                              this));

            // add to list of threads
            threads_.push_back(pThread);
         }
      }
      catch(const boost::thread_resource_error& e)
      {
         return Error(boost::thread_error::ec_from_exception(e),
                      ERROR_LOCATION);
      }

      return Success();
   }

   void stop()
   {
      // close acceptor so we free up the main port immediately
      boost::system::error_code closeEc;
      acceptorService_.closeAcceptor(closeEc);
      if (closeEc)
         LOG_ERROR(Error(closeEc, ERROR_LOCATION));

      // stop the server
      acceptorService_.ioService().stop();
   }

   void waitUntilStopped()
   {
      // wait until all of the threads in the pool exit
      for (std::size_t i=0; i < threads_.size(); ++i)
         threads_[i]->join();
   }

private:

   void runServiceThread()
   {
      try
      {
         boost::system::error_code ec;
         acceptorService_.ioService().run(ec);
         if (ec)
            LOG_ERROR(Error(ec, ERROR_LOCATION));
      }
      CATCH_UNEXPECTED_EXCEPTION
   }

   void acceptNextConnection()
   {
      // create a new connection
      ptrNextConnection_.reset(new AsyncConnectionImpl<ProtocolType>(

         // controlling io_service
         acceptorService_.ioService(),

         // connection handler
         boost::bind(&AsyncServer<ProtocolType>::handleConnection,
                     this, _1, _2),

         // response filter
         boost::bind(&AsyncServer<ProtocolType>::connectionResponseFilter,
                     this, _1)
      ));

      // wait for next connection
      acceptorService_.asyncAccept(
         ptrNextConnection_->socket(),
         boost::bind(&AsyncServer<ProtocolType>::handleAccept,
                     this,
                     boost::asio::placeholders::error)
      );
   }

   void handleAccept(const boost::system::error_code& ec)
   {
      try
      {
         if (!ec)
         {
            // start connection
            ptrNextConnection_->startReading();
         }
         else
         {
            // for errors, log and continue (but don't log operation aborted
            // or bad file descriptor since it happens in the ordinary course
            // of shutting down the server)
            if (ec != boost::asio::error::operation_aborted &&
                ec != boost::system::errc::bad_file_descriptor)
            {
               // log the error
               LOG_ERROR(Error(ec, ERROR_LOCATION)) ;

               // check for resource exhaustion
               checkForResourceExhaustion(ec, ERROR_LOCATION);
            }
         }
      }
      catch(const boost::system::system_error& e)
      {
         // always log
         LOG_ERROR_MESSAGE(std::string("Unexpected exception: ") + e.what());

         // check for resource exhaustion
         checkForResourceExhaustion(e.code(), ERROR_LOCATION);
      }
      CATCH_UNEXPECTED_EXCEPTION

      // ALWAYS accept next connection
      try
      {
         acceptNextConnection() ;
      }
      CATCH_UNEXPECTED_EXCEPTION
   }

   void handleConnection(
         boost::shared_ptr<AsyncConnectionImpl<ProtocolType> > pConnection,
         http::Request* pRequest)
   {
      try
      {
         // call filter
         onRequest(&(pConnection->socket()), pRequest);

         // convert to cannonical HttpConnection
         boost::shared_ptr<AsyncConnection> pAsyncConnection =
             boost::shared_static_cast<AsyncConnection>(pConnection);

         // call the appropriate handler to generate a response
         std::string uri = pRequest->uri();
         AsyncUriHandlerFunction handler = uriHandlers_.handlerFor(uri);
         if (handler)
         {
            // call the handler
            handler(pAsyncConnection) ;
         }
         else if (defaultHandler_)
         {
            // call the default handler
            defaultHandler_(pAsyncConnection);
         }
         else
         {
            // log error
            LOG_ERROR_MESSAGE("Handler not found for uri: " + pRequest->uri());

            // return 404 not found
            pConnection->response().setStatusCode(http::status::NotFound) ;
         }
      }
      catch(const boost::system::system_error& e)
      {
         // always log
         LOG_ERROR_MESSAGE(std::string("Unexpected exception: ") + e.what());

         // check for resource exhaustion
         checkForResourceExhaustion(e.code(), ERROR_LOCATION);
      }
      CATCH_UNEXPECTED_EXCEPTION
   }

   void connectionResponseFilter(http::Response* pResponse)
   {
      // set server header (evade ref-counting to defend against
      // non-threadsafe std::string implementations)
      pResponse->setHeader("Server", std::string(serverName_.c_str()));
   }

   void waitForScheduledCommandTimer()
   {
      // set expiration time for 3 seconds from now
      boost::system::error_code ec;
      scheduledCommandTimer_.expires_from_now(boost::posix_time::seconds(3),
                                              ec);

      // attempt to schedule timer (should always succeed but
      // include error check to be paranoid/robust)
      if (!ec)
      {
         scheduledCommandTimer_.async_wait(boost::bind(
               &AsyncServer<ProtocolType>::handleScheduledCommandTimer,
               this,
               boost::asio::placeholders::error));
      }
      else
      {
         // unexpected error setting timer. log it
         LOG_ERROR(Error(ec, ERROR_LOCATION));
      }
   }

   void handleScheduledCommandTimer(const boost::system::error_code& ec)
   {
      try
      {
         if (!ec)
         {
            // execute all commands
            std::for_each(scheduledCommands_.begin(),
                          scheduledCommands_.end(),
                          boost::bind(&ScheduledCommand::execute, _1));

            // remove any commands which are finished
            scheduledCommands_.erase(
                 std::remove_if(scheduledCommands_.begin(),
                                scheduledCommands_.end(),
                                boost::bind(&ScheduledCommand::finished, _1)),
                 scheduledCommands_.end());

           // wait for the timer again
           waitForScheduledCommandTimer();

         }
         else
         {
            if (ec != boost::system::errc::operation_canceled)
               LOG_ERROR(Error(ec, ERROR_LOCATION));
         }
      }
      CATCH_UNEXPECTED_EXCEPTION
   }

protected:
   SocketAcceptorService<ProtocolType>& acceptorService()
   {
      return acceptorService_;
   }

private:

   virtual void onRequest(typename ProtocolType::socket* pSocket,
                          http::Request* pRequest)
   {

   }

   void maybeAbortServer(const std::string& message,
                         const core::ErrorLocation& location)
   {
      if (abortOnResourceError_)
      {
         core::log::logErrorMessage("(ABORTING SERVER): " + message, location);
         ::abort();
      }
      else
      {
         core::log::logWarningMessage(
                  "Resource exhaustion error occurred (continuing to run)",
                  location);
      }
   }

   void checkForResourceExhaustion(const boost::system::error_code& ec,
                                   const core::ErrorLocation& location)
   {
      if ( ec.category() == boost::system::get_system_category() &&
          (ec.value() == boost::system::errc::too_many_files_open ||
           ec.value() == boost::system::errc::not_enough_memory) )
      {
         // our process has run out of memory or file handles. in this
         // case the only way future requests can be serviced is if we
         // abort and allow upstart to respawn us
         maybeAbortServer("Resource exhaustion", location);
      }
   }

   static void handleAsyncConnectionSynchronously(
                        const UriHandlerFunction& uriHandlerFunction,
                        boost::shared_ptr<AsyncConnection> pConnection)
   {
      uriHandlerFunction(pConnection->request(), &(pConnection->response()));
      pConnection->writeResponse();
   }

private:
   bool abortOnResourceError_;
   std::string serverName_;
   std::string baseUri_;
   boost::shared_ptr<AsyncConnectionImpl<ProtocolType> > ptrNextConnection_;
   AsyncUriHandlers uriHandlers_ ;
   AsyncUriHandlerFunction defaultHandler_;
   std::vector<boost::shared_ptr<boost::thread> > threads_;
   SocketAcceptorService<ProtocolType> acceptorService_;
   boost::asio::deadline_timer scheduledCommandTimer_;
   std::vector<boost::shared_ptr<ScheduledCommand> > scheduledCommands_;
};

} // namespace http
} // namespace core

#endif // CORE_HTTP_ASYNC_SERVER_HPP

<|endoftext|>


<commit_before>#include <ros/ros.h>
#include <tf2_ros/transform_broadcaster.h>
#include <geometry_msgs/TransformStamped.h>
#include <geometry_msgs/Point.h>

void pointCallback(const geometry_msgs::Point::ConstPtr& msg) {
  static tf2_ros::TransformBroadcaster br;
  geometry_msgs::TransformStamped transformStamped;

  transformStamped.header.stamp = ros::Time::now();
  transformStamped.header.frame_id = "kinect";
  transformStamped.child_frame_id = "tomato";
  transformStamped.transform.translation.x = msg->x;
  transformStamped.transform.translation.y = msg->y;
  transformStamped.transform.translation.z = msg->z;
  transformStamped.transform.rotation.x = 0;
  transformStamped.transform.rotation.y = 0;
  transformStamped.transform.rotation.z = 0;
  transformStamped.transform.rotation.w = 1;

  br.sendTransform(transformStamped);
}

int main(int argc, char** argv){
  ros::init(argc, argv, "tomato_broadcaster");
  ros::NodeHandle node;

  ros::Subscriber sub = node.subscribe("/tomato_point", 1, &pointCallback);

  ros::spin();
  return 0;
}
<commit_msg>Add offset from rosparam on kinect_broadcaster<commit_after>#include <ros/ros.h>
#include <tf2_ros/transform_broadcaster.h>
#include <geometry_msgs/TransformStamped.h>
#include <geometry_msgs/Point.h>

int offsetX, offsetY, offsetZ;

void pointCallback(const geometry_msgs::Point::ConstPtr& msg) {
  static tf2_ros::TransformBroadcaster br;
  geometry_msgs::TransformStamped transformStamped;

  transformStamped.header.stamp = ros::Time::now();
  transformStamped.header.frame_id = "kinect";
  transformStamped.child_frame_id = "tomato";
  transformStamped.transform.translation.x = msg->x + offsetX;
  transformStamped.transform.translation.y = msg->y + offsetY;
  transformStamped.transform.translation.z = msg->z + offsetZ;
  transformStamped.transform.rotation.x = 0;
  transformStamped.transform.rotation.y = 0;
  transformStamped.transform.rotation.z = 0;
  transformStamped.transform.rotation.w = 1;

  br.sendTransform(transformStamped);
}

int main(int argc, char** argv){
  ros::init(argc, argv, "tomato_broadcaster");
  ros::NodeHandle node;
  ros::NodeHandle private_node;

  private_node.getParam("kinect_offset_x", offsetX);
  private_node.getPrram("kinect_offset_y", offsetY);
  private_node.getPrram("kinect_offset_z", offsetZ);

  ros::Subscriber sub = node.subscribe("/tomato_point", 1, &pointCallback);

  ros::spin();
  return 0;
}
<|endoftext|>


<commit_before>/****************************************************************************
**
** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (ivan.frade@nokia.com)
**
** This file is part of the QtSparql module (not yet part of the Qt Toolkit).
**
** $QT_BEGIN_LICENSE:LGPL$
** Commercial Usage
** Licensees holding valid Qt Commercial licenses may use this file in
** accordance with the Qt Commercial License Agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Nokia.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file.  Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights.  These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3.0 as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL included in the
** packaging of this file.  Please review the following information to
** ensure the GNU General Public License version 3.0 requirements will be
** met: http://www.gnu.org/copyleft/gpl.html.
**
** If you have questions regarding the use of this file, please contact
** Nokia at ivan.frade@nokia.com.
** $QT_END_LICENSE$
**
****************************************************************************/

#include "qsparql_tracker_direct_p.h"

#include <qsparqlerror.h>
#include <qsparqlbinding.h>
#include <qsparqlquery.h>
#include <qsparqlresultrow.h>
#include <qsparqlconnection.h>

#include <qcoreapplication.h>
#include <qvariant.h>
#include <qstringlist.h>
#include <qvector.h>

#include <qdebug.h>

// The gdbusintrospection.h header has a variable called 'signals', which
// gets substituted with the Qt 'signals' macro. So work round the
// problem by undefining it here.
#undef signals
#include <tracker-sparql.h>

QT_BEGIN_NAMESPACE

// The default for how often the result will emit the dataReady signal.  Can be
// customized via QSparqlConnectionOptions.
#define DEFAULT_DATA_READY_INTERVAL 100

class QTrackerDirectDriverPrivate {
public:
    QTrackerDirectDriverPrivate();
    ~QTrackerDirectDriverPrivate();

    TrackerSparqlConnection *connection;
    int dataReadyInterval;
};

class QTrackerDirectResultPrivate : public QObject {
    Q_OBJECT
public:
    QTrackerDirectResultPrivate(QTrackerDirectResult* result, QTrackerDirectDriverPrivate *dpp);

    ~QTrackerDirectResultPrivate();
    void terminate();
    void setLastError(const QSparqlError& e);
    void setBoolValue(bool v);
    void dataReady(int totalCount);

    TrackerSparqlCursor * cursor;
    QVector<QString> columnNames;
    QVector<QSparqlResultRow> results;
    bool isFinished;
    bool resultAlive; // whether the corresponding Result object is still alive
    QEventLoop *loop;
    int lastDataReady;

    QTrackerDirectResult* q;
    QTrackerDirectDriverPrivate *driverPrivate;
};

static void
async_cursor_next_callback( GObject *source_object,
                            GAsyncResult *result,
                            gpointer user_data)
{
    Q_UNUSED(source_object);
    QTrackerDirectResultPrivate *data = static_cast<QTrackerDirectResultPrivate*>(user_data);

    if (!data->resultAlive) {
        // The user has deleted the Result object before this callback was
        // called. Just delete the ResultPrivate here and do nothing.
        delete data;
        return;
    }
    GError *error = 0;
    gboolean active = tracker_sparql_cursor_next_finish(data->cursor, result, &error);

    if (error != 0) {
        QSparqlError e(QString::fromLatin1(error ? error->message : "unknown error"));
        e.setType(QSparqlError::BackendError);
        data->setLastError(e);
        g_error_free(error);
        data->terminate();
        return;
    }

    if (!active) {
        if (data->q->isBool()) {
            data->setBoolValue( data->results.count() == 1
                                && data->results[0].count() == 1
                                && data->results[0].binding(0).value().toBool());
        }

        data->terminate();
        return;
    }

    QSparqlResultRow resultRow;
    gint n_columns = tracker_sparql_cursor_get_n_columns(data->cursor);

    if (data->columnNames.empty()) {
        for (int i = 0; i < n_columns; i++) {
            data->columnNames.append(QString::fromUtf8(tracker_sparql_cursor_get_variable_name(data->cursor, i)));
        }
    }

    for (int i = 0; i < n_columns; i++) {
        QString value = QString::fromUtf8(tracker_sparql_cursor_get_string(data->cursor, i, 0));
        QSparqlBinding binding;
        binding.setName(data->columnNames[i]);
        TrackerSparqlValueType type = tracker_sparql_cursor_get_value_type(data->cursor, i);

        switch (type) {
        case TRACKER_SPARQL_VALUE_TYPE_UNBOUND:
            break;
        case TRACKER_SPARQL_VALUE_TYPE_URI:
            binding.setValue(QUrl(value));
            break;
        case TRACKER_SPARQL_VALUE_TYPE_STRING:
            binding.setValue(value, QUrl::fromEncoded("http://www.w3.org/2001/XMLSchema#string"));
            break;
        case TRACKER_SPARQL_VALUE_TYPE_INTEGER:
            binding.setValue(value, QUrl::fromEncoded("http://www.w3.org/2001/XMLSchema#integer"));
            break;
        case TRACKER_SPARQL_VALUE_TYPE_DOUBLE:
            binding.setValue(value, QUrl::fromEncoded("http://www.w3.org/2001/XMLSchema#double"));
            break;
        case TRACKER_SPARQL_VALUE_TYPE_DATETIME:
            binding.setValue(value, QUrl::fromEncoded("http://www.w3.org/2001/XMLSchema#dateTime"));
            break;
        case TRACKER_SPARQL_VALUE_TYPE_BLANK_NODE:
            binding.setBlankNodeLabel(value);
            break;
        case TRACKER_SPARQL_VALUE_TYPE_BOOLEAN:
            binding.setValue(value == QLatin1String("1") ? QString::fromLatin1("true") : QString::fromLatin1("false"),
                             QUrl::fromEncoded("http://www.w3.org/2001/XMLSchema#boolean"));
            break;
        default:
            break;
        }

        resultRow.append(binding);
    }

    data->results.append(resultRow);
    data->dataReady(data->results.count());
    tracker_sparql_cursor_next_async(data->cursor, 0, async_cursor_next_callback, data);
}

static void
async_query_callback(   GObject *source_object,
                        GAsyncResult *result,
                        gpointer user_data)
{
    Q_UNUSED(source_object);
    QTrackerDirectResultPrivate *data = static_cast<QTrackerDirectResultPrivate*>(user_data);
    if (!data->resultAlive) {
        // The user has deleted the Result object before this callback was
        // called. Just delete the ResultPrivate here and do nothing.
        delete data;
        return;
    }
    GError *error = 0;
    data->cursor = tracker_sparql_connection_query_finish(data->driverPrivate->connection, result, &error);

    if (error != 0 || data->cursor == 0) {
        QSparqlError e(QString::fromLatin1(error ? error->message : "unknown error"));
        e.setType(QSparqlError::StatementError);
        data->setLastError(e);
        g_error_free(error);
        data->terminate();
        return;
    }

    tracker_sparql_cursor_next_async(data->cursor, 0, async_cursor_next_callback, data);
}

static void
async_update_callback( GObject *source_object,
                       GAsyncResult *result,
                       gpointer user_data)
{
    Q_UNUSED(source_object);
    QTrackerDirectResultPrivate *data = static_cast<QTrackerDirectResultPrivate*>(user_data);
    if (!data->resultAlive) {
        // The user has deleted the Result object before this callback was
        // called. Just delete the ResultPrivate here and do nothing.
        delete data;
        return;
    }
    GError *error = 0;
    tracker_sparql_connection_update_finish(data->driverPrivate->connection, result, &error);

    if (error != 0) {
        QSparqlError e(QString::fromLatin1(error ? error->message : "unknown error"));
        e.setType(QSparqlError::StatementError);
        data->setLastError(e);
        g_error_free(error);
        data->terminate();
        return;
    }

    data->terminate();
}

QTrackerDirectResultPrivate::QTrackerDirectResultPrivate(
    QTrackerDirectResult* result,
    QTrackerDirectDriverPrivate *dpp)
: cursor(0), isFinished(false), resultAlive(true), loop(0), lastDataReady(0),
  q(result), driverPrivate(dpp)
{
}

QTrackerDirectResultPrivate::~QTrackerDirectResultPrivate()
{
    if (cursor != 0)
        g_object_unref(cursor);
}

void QTrackerDirectResultPrivate::terminate()
{
    isFinished = true;
    dataReady(results.count());
    q->emit finished();

    if (loop != 0)
        loop->exit();
}

void QTrackerDirectResultPrivate::setLastError(const QSparqlError& e)
{
    q->setLastError(e);
}

void QTrackerDirectResultPrivate::setBoolValue(bool v)
{
    q->setBoolValue(v);
}

void QTrackerDirectResultPrivate::dataReady(int totalCount)
{
    bool doEmit = false;
    if (isFinished && totalCount > lastDataReady) {
        // emit the last dataChanged signal even if there is 1 additional item
        doEmit = true;
    }
    else if (totalCount >= lastDataReady + driverPrivate->dataReadyInterval) {
        doEmit = true;
    }
    if (doEmit) {
        emit q->dataReady(totalCount);
        lastDataReady = totalCount;
    }
}

QTrackerDirectResult::QTrackerDirectResult(QTrackerDirectDriverPrivate* p)
{
    d = new QTrackerDirectResultPrivate(this, p);
}

QTrackerDirectResult::~QTrackerDirectResult()
{
    if (!d->isFinished) {
        // We're deleting the Result before the async data retrieval has
        // finished. There is a pending async callback that will be called at
        // some point, and that will have our ResultPrivate as user_data. Don't
        // delete the ResultPrivate here, but just mark that we're no longer
        // alive. The callback will then delete the ResultPrivate.
        d->resultAlive = false;
    }
    else {
        delete d;
    }
}

QTrackerDirectResult* QTrackerDirectDriver::exec(const QString& query,
                          QSparqlQuery::StatementType type)
{
    QTrackerDirectResult* res = new QTrackerDirectResult(d);
    res->setStatementType(type);
    res->setQuery(query);

    switch (type) {
    case QSparqlQuery::AskStatement:
    case QSparqlQuery::SelectStatement:
    {
        tracker_sparql_connection_query_async(  d->connection,
                                                query.toLatin1().constData(),
                                                0,
                                                async_query_callback,
                                                res->d);
        break;
    }
    case QSparqlQuery::InsertStatement:
    case QSparqlQuery::DeleteStatement:
        tracker_sparql_connection_update_async( d->connection,
                                                query.toLatin1().constData(),
                                                0,
                                                0,
                                                async_update_callback,
                                                res->d);
    {
        break;
    }
    default:
        qWarning() << "Tracker backend: unsupported statement type";
        res->setLastError(QSparqlError(
                              QLatin1String("Unsupported statement type"),
                              QSparqlError::BackendError));
        break;
    }
    return res;
}

void QTrackerDirectResult::cleanup()
{
    setPos(QSparql::BeforeFirstRow);
}

QSparqlBinding QTrackerDirectResult::binding(int field) const
{
    if (!isValid()) {
        return QSparqlBinding();
    }

    if (field >= d->results[pos()].count() || field < 0) {
        qWarning() << "QTrackerDirectResult::data[" << pos() << "]: column" << field << "out of range";
        return QSparqlBinding();
    }

    return d->results[pos()].binding(field);
}

QVariant QTrackerDirectResult::value(int field) const
{
    if (!isValid()) {
        return QVariant();
    }

    if (field >= d->results[pos()].count() || field < 0) {
        qWarning() << "QTrackerDirectResult::data[" << pos() << "]: column" << field << "out of range";
        return QVariant();
    }

    return d->results[pos()].value(field);
}

void QTrackerDirectResult::waitForFinished()
{
    if (d->isFinished)
        return;

    QEventLoop loop;
    d->loop = &loop;
    loop.exec();
    d->loop = 0;
}

bool QTrackerDirectResult::isFinished() const
{
    return d->isFinished;
}

int QTrackerDirectResult::size() const
{
    return d->results.count();
}

QSparqlResultRow QTrackerDirectResult::current() const
{
    if (!isValid()) {
        return QSparqlResultRow();
    }

    if (pos() < 0 || pos() >= d->results.count())
        return QSparqlResultRow();

    return d->results[pos()];
}

QTrackerDirectDriverPrivate::QTrackerDirectDriverPrivate()
    : dataReadyInterval(DEFAULT_DATA_READY_INTERVAL)
{
}

QTrackerDirectDriverPrivate::~QTrackerDirectDriverPrivate()
{
}

QTrackerDirectDriver::QTrackerDirectDriver(QObject* parent)
    : QSparqlDriver(parent)
{
    d = new QTrackerDirectDriverPrivate();
    /* Initialize GLib type system */
    g_type_init();

}

QTrackerDirectDriver::~QTrackerDirectDriver()
{
    delete d;
}

bool QTrackerDirectDriver::hasFeature(QSparqlConnection::Feature f) const
{
    switch (f) {
    case QSparqlConnection::QuerySize:
        return true;
    case QSparqlConnection::AskQueries:
        return true;
    case QSparqlConnection::ConstructQueries:
        return false;
    case QSparqlConnection::UpdateQueries:
        return true;
    case QSparqlConnection::DefaultGraph:
        return true;
    }
    return false;
}

QAtomicInt connectionCounter = 0;

bool QTrackerDirectDriver::open(const QSparqlConnectionOptions& options)
{
    QVariant dataReadyInterval = options.option(QLatin1String("dataReadyInterval"));
    if (!dataReadyInterval.isNull() && dataReadyInterval.type() == QVariant::Int)
        d->dataReadyInterval = dataReadyInterval.toInt();

    if (isOpen())
        close();

    GError *error = 0;
    d->connection = tracker_sparql_connection_get(0, &error);
    // maybe-TODO: Add the GCancellable
    if (!d->connection) {
        qWarning("Couldn't obtain a direct connection to the Tracker store: %s",
                    error ? error->message : "unknown error");
        g_error_free(error);
        return false;
    }

    setOpen(true);
    setOpenError(false);

    return true;
}

void QTrackerDirectDriver::close()
{
    g_object_unref(d->connection);

    if (isOpen()) {
        setOpen(false);
        setOpenError(false);
    }
}

QT_END_NAMESPACE

#include "qsparql_tracker_direct.moc"
<commit_msg>Direct driver: g_object_unref the cursor earlier.<commit_after>/****************************************************************************
**
** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (ivan.frade@nokia.com)
**
** This file is part of the QtSparql module (not yet part of the Qt Toolkit).
**
** $QT_BEGIN_LICENSE:LGPL$
** Commercial Usage
** Licensees holding valid Qt Commercial licenses may use this file in
** accordance with the Qt Commercial License Agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Nokia.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file.  Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights.  These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3.0 as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL included in the
** packaging of this file.  Please review the following information to
** ensure the GNU General Public License version 3.0 requirements will be
** met: http://www.gnu.org/copyleft/gpl.html.
**
** If you have questions regarding the use of this file, please contact
** Nokia at ivan.frade@nokia.com.
** $QT_END_LICENSE$
**
****************************************************************************/

#include "qsparql_tracker_direct_p.h"

#include <qsparqlerror.h>
#include <qsparqlbinding.h>
#include <qsparqlquery.h>
#include <qsparqlresultrow.h>
#include <qsparqlconnection.h>

#include <qcoreapplication.h>
#include <qvariant.h>
#include <qstringlist.h>
#include <qvector.h>

#include <qdebug.h>

// The gdbusintrospection.h header has a variable called 'signals', which
// gets substituted with the Qt 'signals' macro. So work round the
// problem by undefining it here.
#undef signals
#include <tracker-sparql.h>

QT_BEGIN_NAMESPACE

// The default for how often the result will emit the dataReady signal.  Can be
// customized via QSparqlConnectionOptions.
#define DEFAULT_DATA_READY_INTERVAL 100

class QTrackerDirectDriverPrivate {
public:
    QTrackerDirectDriverPrivate();
    ~QTrackerDirectDriverPrivate();

    TrackerSparqlConnection *connection;
    int dataReadyInterval;
};

class QTrackerDirectResultPrivate : public QObject {
    Q_OBJECT
public:
    QTrackerDirectResultPrivate(QTrackerDirectResult* result, QTrackerDirectDriverPrivate *dpp);

    ~QTrackerDirectResultPrivate();
    void terminate();
    void setLastError(const QSparqlError& e);
    void setBoolValue(bool v);
    void dataReady(int totalCount);

    TrackerSparqlCursor * cursor;
    QVector<QString> columnNames;
    QVector<QSparqlResultRow> results;
    bool isFinished;
    bool resultAlive; // whether the corresponding Result object is still alive
    QEventLoop *loop;
    int lastDataReady;

    QTrackerDirectResult* q;
    QTrackerDirectDriverPrivate *driverPrivate;
};

static void
async_cursor_next_callback( GObject *source_object,
                            GAsyncResult *result,
                            gpointer user_data)
{
    Q_UNUSED(source_object);
    QTrackerDirectResultPrivate *data = static_cast<QTrackerDirectResultPrivate*>(user_data);

    if (!data->resultAlive) {
        // The user has deleted the Result object before this callback was
        // called. Just delete the ResultPrivate here and do nothing.
        delete data;
        return;
    }
    GError *error = 0;
    gboolean active = tracker_sparql_cursor_next_finish(data->cursor, result, &error);

    if (error != 0) {
        QSparqlError e(QString::fromLatin1(error ? error->message : "unknown error"));
        e.setType(QSparqlError::BackendError);
        data->setLastError(e);
        g_error_free(error);
        data->terminate();
        return;
    }

    if (!active) {
        if (data->q->isBool()) {
            data->setBoolValue( data->results.count() == 1
                                && data->results[0].count() == 1
                                && data->results[0].binding(0).value().toBool());
        }

        data->terminate();
        return;
    }

    QSparqlResultRow resultRow;
    gint n_columns = tracker_sparql_cursor_get_n_columns(data->cursor);

    if (data->columnNames.empty()) {
        for (int i = 0; i < n_columns; i++) {
            data->columnNames.append(QString::fromUtf8(tracker_sparql_cursor_get_variable_name(data->cursor, i)));
        }
    }

    for (int i = 0; i < n_columns; i++) {
        QString value = QString::fromUtf8(tracker_sparql_cursor_get_string(data->cursor, i, 0));
        QSparqlBinding binding;
        binding.setName(data->columnNames[i]);
        TrackerSparqlValueType type = tracker_sparql_cursor_get_value_type(data->cursor, i);

        switch (type) {
        case TRACKER_SPARQL_VALUE_TYPE_UNBOUND:
            break;
        case TRACKER_SPARQL_VALUE_TYPE_URI:
            binding.setValue(QUrl(value));
            break;
        case TRACKER_SPARQL_VALUE_TYPE_STRING:
            binding.setValue(value, QUrl::fromEncoded("http://www.w3.org/2001/XMLSchema#string"));
            break;
        case TRACKER_SPARQL_VALUE_TYPE_INTEGER:
            binding.setValue(value, QUrl::fromEncoded("http://www.w3.org/2001/XMLSchema#integer"));
            break;
        case TRACKER_SPARQL_VALUE_TYPE_DOUBLE:
            binding.setValue(value, QUrl::fromEncoded("http://www.w3.org/2001/XMLSchema#double"));
            break;
        case TRACKER_SPARQL_VALUE_TYPE_DATETIME:
            binding.setValue(value, QUrl::fromEncoded("http://www.w3.org/2001/XMLSchema#dateTime"));
            break;
        case TRACKER_SPARQL_VALUE_TYPE_BLANK_NODE:
            binding.setBlankNodeLabel(value);
            break;
        case TRACKER_SPARQL_VALUE_TYPE_BOOLEAN:
            binding.setValue(value == QLatin1String("1") ? QString::fromLatin1("true") : QString::fromLatin1("false"),
                             QUrl::fromEncoded("http://www.w3.org/2001/XMLSchema#boolean"));
            break;
        default:
            break;
        }

        resultRow.append(binding);
    }

    data->results.append(resultRow);
    data->dataReady(data->results.count());
    tracker_sparql_cursor_next_async(data->cursor, 0, async_cursor_next_callback, data);
}

static void
async_query_callback(   GObject *source_object,
                        GAsyncResult *result,
                        gpointer user_data)
{
    Q_UNUSED(source_object);
    QTrackerDirectResultPrivate *data = static_cast<QTrackerDirectResultPrivate*>(user_data);
    if (!data->resultAlive) {
        // The user has deleted the Result object before this callback was
        // called. Just delete the ResultPrivate here and do nothing.
        delete data;
        return;
    }
    GError *error = 0;
    data->cursor = tracker_sparql_connection_query_finish(data->driverPrivate->connection, result, &error);

    if (error != 0 || data->cursor == 0) {
        QSparqlError e(QString::fromLatin1(error ? error->message : "unknown error"));
        e.setType(QSparqlError::StatementError);
        data->setLastError(e);
        g_error_free(error);
        data->terminate();
        return;
    }

    tracker_sparql_cursor_next_async(data->cursor, 0, async_cursor_next_callback, data);
}

static void
async_update_callback( GObject *source_object,
                       GAsyncResult *result,
                       gpointer user_data)
{
    Q_UNUSED(source_object);
    QTrackerDirectResultPrivate *data = static_cast<QTrackerDirectResultPrivate*>(user_data);
    if (!data->resultAlive) {
        // The user has deleted the Result object before this callback was
        // called. Just delete the ResultPrivate here and do nothing.
        delete data;
        return;
    }
    GError *error = 0;
    tracker_sparql_connection_update_finish(data->driverPrivate->connection, result, &error);

    if (error != 0) {
        QSparqlError e(QString::fromLatin1(error ? error->message : "unknown error"));
        e.setType(QSparqlError::StatementError);
        data->setLastError(e);
        g_error_free(error);
        data->terminate();
        return;
    }

    data->terminate();
}

QTrackerDirectResultPrivate::QTrackerDirectResultPrivate(
    QTrackerDirectResult* result,
    QTrackerDirectDriverPrivate *dpp)
: cursor(0), isFinished(false), resultAlive(true), loop(0), lastDataReady(0),
  q(result), driverPrivate(dpp)
{
}

QTrackerDirectResultPrivate::~QTrackerDirectResultPrivate()
{
    if (cursor != 0)
        g_object_unref(cursor);
}

void QTrackerDirectResultPrivate::terminate()
{
    isFinished = true;
    dataReady(results.count());
    q->emit finished();
    if (cursor != 0) {
        g_object_unref(cursor);
        cursor = 0;
    }
    if (loop != 0)
        loop->exit();
}

void QTrackerDirectResultPrivate::setLastError(const QSparqlError& e)
{
    q->setLastError(e);
}

void QTrackerDirectResultPrivate::setBoolValue(bool v)
{
    q->setBoolValue(v);
}

void QTrackerDirectResultPrivate::dataReady(int totalCount)
{
    bool doEmit = false;
    if (isFinished && totalCount > lastDataReady) {
        // emit the last dataChanged signal even if there is 1 additional item
        doEmit = true;
    }
    else if (totalCount >= lastDataReady + driverPrivate->dataReadyInterval) {
        doEmit = true;
    }
    if (doEmit) {
        emit q->dataReady(totalCount);
        lastDataReady = totalCount;
    }
}

QTrackerDirectResult::QTrackerDirectResult(QTrackerDirectDriverPrivate* p)
{
    d = new QTrackerDirectResultPrivate(this, p);
}

QTrackerDirectResult::~QTrackerDirectResult()
{
    if (!d->isFinished) {
        // We're deleting the Result before the async data retrieval has
        // finished. There is a pending async callback that will be called at
        // some point, and that will have our ResultPrivate as user_data. Don't
        // delete the ResultPrivate here, but just mark that we're no longer
        // alive. The callback will then delete the ResultPrivate.
        d->resultAlive = false;
    }
    else {
        delete d;
    }
}

QTrackerDirectResult* QTrackerDirectDriver::exec(const QString& query,
                          QSparqlQuery::StatementType type)
{
    QTrackerDirectResult* res = new QTrackerDirectResult(d);
    res->setStatementType(type);
    res->setQuery(query);

    switch (type) {
    case QSparqlQuery::AskStatement:
    case QSparqlQuery::SelectStatement:
    {
        tracker_sparql_connection_query_async(  d->connection,
                                                query.toLatin1().constData(),
                                                0,
                                                async_query_callback,
                                                res->d);
        break;
    }
    case QSparqlQuery::InsertStatement:
    case QSparqlQuery::DeleteStatement:
        tracker_sparql_connection_update_async( d->connection,
                                                query.toLatin1().constData(),
                                                0,
                                                0,
                                                async_update_callback,
                                                res->d);
    {
        break;
    }
    default:
        qWarning() << "Tracker backend: unsupported statement type";
        res->setLastError(QSparqlError(
                              QLatin1String("Unsupported statement type"),
                              QSparqlError::BackendError));
        break;
    }
    return res;
}

void QTrackerDirectResult::cleanup()
{
    setPos(QSparql::BeforeFirstRow);
}

QSparqlBinding QTrackerDirectResult::binding(int field) const
{
    if (!isValid()) {
        return QSparqlBinding();
    }

    if (field >= d->results[pos()].count() || field < 0) {
        qWarning() << "QTrackerDirectResult::data[" << pos() << "]: column" << field << "out of range";
        return QSparqlBinding();
    }

    return d->results[pos()].binding(field);
}

QVariant QTrackerDirectResult::value(int field) const
{
    if (!isValid()) {
        return QVariant();
    }

    if (field >= d->results[pos()].count() || field < 0) {
        qWarning() << "QTrackerDirectResult::data[" << pos() << "]: column" << field << "out of range";
        return QVariant();
    }

    return d->results[pos()].value(field);
}

void QTrackerDirectResult::waitForFinished()
{
    if (d->isFinished)
        return;

    QEventLoop loop;
    d->loop = &loop;
    loop.exec();
    d->loop = 0;
}

bool QTrackerDirectResult::isFinished() const
{
    return d->isFinished;
}

int QTrackerDirectResult::size() const
{
    return d->results.count();
}

QSparqlResultRow QTrackerDirectResult::current() const
{
    if (!isValid()) {
        return QSparqlResultRow();
    }

    if (pos() < 0 || pos() >= d->results.count())
        return QSparqlResultRow();

    return d->results[pos()];
}

QTrackerDirectDriverPrivate::QTrackerDirectDriverPrivate()
    : dataReadyInterval(DEFAULT_DATA_READY_INTERVAL)
{
}

QTrackerDirectDriverPrivate::~QTrackerDirectDriverPrivate()
{
}

QTrackerDirectDriver::QTrackerDirectDriver(QObject* parent)
    : QSparqlDriver(parent)
{
    d = new QTrackerDirectDriverPrivate();
    /* Initialize GLib type system */
    g_type_init();

}

QTrackerDirectDriver::~QTrackerDirectDriver()
{
    delete d;
}

bool QTrackerDirectDriver::hasFeature(QSparqlConnection::Feature f) const
{
    switch (f) {
    case QSparqlConnection::QuerySize:
        return true;
    case QSparqlConnection::AskQueries:
        return true;
    case QSparqlConnection::ConstructQueries:
        return false;
    case QSparqlConnection::UpdateQueries:
        return true;
    case QSparqlConnection::DefaultGraph:
        return true;
    }
    return false;
}

QAtomicInt connectionCounter = 0;

bool QTrackerDirectDriver::open(const QSparqlConnectionOptions& options)
{
    QVariant dataReadyInterval = options.option(QLatin1String("dataReadyInterval"));
    if (!dataReadyInterval.isNull() && dataReadyInterval.type() == QVariant::Int)
        d->dataReadyInterval = dataReadyInterval.toInt();

    if (isOpen())
        close();

    GError *error = 0;
    d->connection = tracker_sparql_connection_get(0, &error);
    // maybe-TODO: Add the GCancellable
    if (!d->connection) {
        qWarning("Couldn't obtain a direct connection to the Tracker store: %s",
                    error ? error->message : "unknown error");
        g_error_free(error);
        return false;
    }

    setOpen(true);
    setOpenError(false);

    return true;
}

void QTrackerDirectDriver::close()
{
    g_object_unref(d->connection);

    if (isOpen()) {
        setOpen(false);
        setOpenError(false);
    }
}

QT_END_NAMESPACE

#include "qsparql_tracker_direct.moc"
<|endoftext|>


<commit_before><commit_msg>add Dynamic Array class functions definitions<commit_after>#include <iostream>
#include <algorithm>

#include "DynamicArray.h"

DynamicArray::DynamicArray() {

}

DynamicArray::~DynamicArray() {

}

DynamicArray::DynamicArray(DynamicArray const & other) {

}

DynamicArray& DynamicArray::operator=(DynamicArray const & other) {

}

DynamicArray::~DynamicArray() {

}

void DynamicArray::free() {

}

void DynamicArray::reallocate(size_t newSize) {

}

void DynamicArray::add(int element) {

}

size_t DynamicArray::getAllocatedSize() const {

}

size_t DynamicArray::getLength() const {

}

int DynamicArray::getAt(size_t index) const {

}

void DynamicArray::setAt(size_t index, int value) {

}

void DynamicArray::print() const {

}

DynamicArray DynamicArray::operator+(DynamicArray const& rhs) const {

}

///
///  proxy ,        index.
///
///
/// proxy ,           .
///
/// :
/// 1.        index
///     .
///  ,  proxy   .
/// 2. proxy      ,
///  .  ,
///   , proxy        .
///
DynamicArrayElementProxy DynamicArray::operator[](size_t index) {

}

///
///  proxy ,        index.
///
///
///  proxy ,  * *
///    .
///
const DynamicArrayElementProxy DynamicArray::operator[](size_t index) const {

}

/// ============================================================================

DynamicArrayElementProxy::DynamicArrayElementProxy(DynamicArray * pDynamicArray, size_t elementIndex) :
pParent(pDynamicArray),
parentElementIndex(elementIndex) {
}

DynamicArrayElementProxy::operator int() const {

}

DynamicArrayElementProxy & DynamicArrayElementProxy::operator=(int value) {

}<|endoftext|>


<commit_before>/**************************************************************************
 *
 * Copyright 2009-2011 VMware, Inc.
 * All Rights Reserved.
 *
 * Permission is hereby granted, free of charge, to any person obtaining a
 * copy of this software and associated documentation files (the
 * "Software"), to deal in the Software without restriction, including
 * without limitation the rights to use, copy, modify, merge, publish,
 * distribute, sub license, and/or sell copies of the Software, and to
 * permit persons to whom the Software is furnished to do so, subject to
 * the following conditions:
 *
 * The above copyright notice and this permission notice (including the
 * next paragraph) shall be included in all copies or substantial portions
 * of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
 * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR
 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 *
 **************************************************************************/

#include <llvm-c/Core.h>
#include <llvm/Target/TargetMachine.h>
#include <llvm/Target/TargetInstrInfo.h>
#include <llvm/Support/raw_ostream.h>
#include <llvm/Support/MemoryObject.h>

#if HAVE_LLVM >= 0x0300
#include <llvm/Support/TargetRegistry.h>
#include <llvm/Support/TargetSelect.h>
#else /* HAVE_LLVM < 0x0300 */
#include <llvm/Target/TargetRegistry.h>
#include <llvm/Target/TargetSelect.h>
#endif /* HAVE_LLVM < 0x0300 */

#if HAVE_LLVM >= 0x0209
#include <llvm/Support/Host.h>
#else /* HAVE_LLVM < 0x0209 */
#include <llvm/System/Host.h>
#endif /* HAVE_LLVM < 0x0209 */

#if HAVE_LLVM >= 0x0207
#include <llvm/MC/MCDisassembler.h>
#include <llvm/MC/MCAsmInfo.h>
#include <llvm/MC/MCInst.h>
#include <llvm/MC/MCInstPrinter.h>
#endif /* HAVE_LLVM >= 0x0207 */

#include "util/u_math.h"
#include "util/u_debug.h"

#include "lp_bld_debug.h"

/**
 * Check alignment.
 *
 * It is important that this check is not implemented as a macro or inlined
 * function, as the compiler assumptions in respect to alignment of global
 * and stack variables would often make the check a no op, defeating the
 * whole purpose of the exercise.
 */
extern "C" boolean
lp_check_alignment(const void *ptr, unsigned alignment)
{
   assert(util_is_power_of_two(alignment));
   return ((uintptr_t)ptr & (alignment - 1)) == 0;
}

class raw_debug_ostream :
   public llvm::raw_ostream
{
   uint64_t pos;

   void write_impl(const char *Ptr, size_t Size);
   uint64_t current_pos() { return pos; }
   uint64_t current_pos() const { return pos; }

#if HAVE_LLVM >= 0x207
   uint64_t preferred_buffer_size() { return 512; }
#else
   size_t preferred_buffer_size() { return 512; }
#endif
};

void
raw_debug_ostream::write_impl(const char *Ptr, size_t Size)
{
   if (Size > 0) {
      char *lastPtr = (char *)&Ptr[Size];
      char last = *lastPtr;
      *lastPtr = 0;
      _debug_printf("%*s", Size, Ptr);
      *lastPtr = last;
      pos += Size;
   }
}

/**
 * Same as LLVMDumpValue, but through our debugging channels.
 */
extern "C" void
lp_debug_dump_value(LLVMValueRef value)
{
#if (defined(PIPE_OS_WINDOWS) && !defined(PIPE_CC_MSVC)) || defined(PIPE_OS_EMBDDED)
   raw_debug_ostream os;
   llvm::unwrap(value)->print(os);
   os.flush();
#else
   LLVMDumpValue(value);
#endif
}

#if HAVE_LLVM >= 0x0207
/*
 * MemoryObject wrapper around a buffer of memory, to be used by MC
 * disassembler.
 */
class BufferMemoryObject:
   public llvm::MemoryObject
{
private:
   const uint8_t *Bytes;
   uint64_t Length;
public:
   BufferMemoryObject(const uint8_t *bytes, uint64_t length) :
      Bytes(bytes), Length(length)
   {
   }

   uint64_t getBase() const
   {
      return 0;
   }

   uint64_t getExtent() const
   {
      return Length;
   }

   int readByte(uint64_t addr, uint8_t *byte) const
   {
      if (addr > getExtent())
         return -1;
      *byte = Bytes[addr];
      return 0;
   }
};
#endif /* HAVE_LLVM >= 0x0207 */

/*
 * Disassemble a function, using the LLVM MC disassembler.
 *
 * See also:
 * - http://blog.llvm.org/2010/01/x86-disassembler.html
 * - http://blog.llvm.org/2010/04/intro-to-llvm-mc-project.html
 */
extern "C" void
lp_disassemble(const void* func)
{
#if HAVE_LLVM >= 0x0207
   using namespace llvm;

   const uint8_t *bytes = (const uint8_t *)func;

   /*
    * Limit disassembly to this extent
    */
   const uint64_t extent = 0x10000;

   uint64_t max_pc = 0;

   /*
    * Initialize all used objects.
    */

   std::string Triple = sys::getHostTriple();

   std::string Error;
   const Target *T = TargetRegistry::lookupTarget(Triple, Error);

#if HAVE_LLVM >= 0x0208
   InitializeNativeTargetAsmPrinter();
#else
   InitializeAllAsmPrinters();
#endif

   InitializeAllDisassemblers();

#if HAVE_LLVM >= 0x0300
   OwningPtr<const MCAsmInfo> AsmInfo(T->createMCAsmInfo(Triple));
#else
   OwningPtr<const MCAsmInfo> AsmInfo(T->createAsmInfo(Triple));
#endif

   if (!AsmInfo) {
      debug_printf("error: no assembly info for target %s\n", Triple.c_str());
      return;
   }

#if HAVE_LLVM >= 0x0300
   const MCSubtargetInfo *STI = T->createMCSubtargetInfo(Triple, sys::getHostCPUName(), "");
   OwningPtr<const MCDisassembler> DisAsm(T->createMCDisassembler(*STI));
#else
   OwningPtr<const MCDisassembler> DisAsm(T->createMCDisassembler());
#endif
   if (!DisAsm) {
      debug_printf("error: no disassembler for target %s\n", Triple.c_str());
      return;
   }

   raw_debug_ostream Out;

#if HAVE_LLVM >= 0x0300
   unsigned int AsmPrinterVariant = AsmInfo->getAssemblerDialect();
#else
   int AsmPrinterVariant = AsmInfo->getAssemblerDialect();
#endif

#if HAVE_LLVM >= 0x0300
   OwningPtr<MCInstPrinter> Printer(
         T->createMCInstPrinter(AsmPrinterVariant, *AsmInfo, *STI));
#elif HAVE_LLVM >= 0x0208
   OwningPtr<MCInstPrinter> Printer(
         T->createMCInstPrinter(AsmPrinterVariant, *AsmInfo));
#else
   OwningPtr<MCInstPrinter> Printer(
         T->createMCInstPrinter(AsmPrinterVariant, *AsmInfo, Out));
#endif
   if (!Printer) {
      debug_printf("error: no instruction printer for target %s\n", Triple.c_str());
      return;
   }

#if HAVE_LLVM >= 0x0300
   TargetMachine *TM = T->createTargetMachine(Triple, sys::getHostCPUName(), "");
#else
   TargetMachine *TM = T->createTargetMachine(Triple, "");
#endif

   const TargetInstrInfo *TII = TM->getInstrInfo();

   /*
    * Wrap the data in a MemoryObject
    */
   BufferMemoryObject memoryObject((const uint8_t *)bytes, extent);

   uint64_t pc;
   pc = 0;
   while (true) {
      MCInst Inst;
      uint64_t Size;

      /*
       * Print address.  We use addresses relative to the start of the function,
       * so that between runs.
       */

      debug_printf("%6lu:\t", (unsigned long)pc);

      if (!DisAsm->getInstruction(Inst, Size, memoryObject,
                                 pc,
#if HAVE_LLVM >= 0x0300
				  nulls(), nulls())) {
#else
				  nulls())) {
#endif
         debug_printf("invalid\n");
         pc += 1;
      }

      /*
       * Output the bytes in hexidecimal format.
       */

      if (0) {
         unsigned i;
         for (i = 0; i < Size; ++i) {
            debug_printf("%02x ", ((const uint8_t*)bytes)[pc + i]);
         }
         for (; i < 16; ++i) {
            debug_printf("   ");
         }
      }

      /*
       * Print the instruction.
       */

#if HAVE_LLVM >= 0x0300
      Printer->printInst(&Inst, Out, "");
#elif HAVE_LLVM >= 0x208
      Printer->printInst(&Inst, Out);
#else
      Printer->printInst(&Inst);
#endif
      Out.flush();

      /*
       * Advance.
       */

      pc += Size;

#if HAVE_LLVM >= 0x0300
      const MCInstrDesc &TID = TII->get(Inst.getOpcode());
#else
      const TargetInstrDesc &TID = TII->get(Inst.getOpcode());
#endif

      /*
       * Keep track of forward jumps to a nearby address.
       */

      if (TID.isBranch()) {
         for (unsigned i = 0; i < Inst.getNumOperands(); ++i) {
            const MCOperand &operand = Inst.getOperand(i);
            if (operand.isImm()) {
               uint64_t jump;

               /*
                * FIXME: Handle both relative and absolute addresses correctly.
                * EDInstInfo actually has this info, but operandTypes and
                * operandFlags enums are not exposed in the public interface.
                */

               if (1) {
                  /*
                   * PC relative addr.
                   */

                  jump = pc + operand.getImm();
               } else {
                  /*
                   * Absolute addr.
                   */

                  jump = (uint64_t)operand.getImm();
               }

               /*
                * Output the address relative to the function start, given
                * that MC will print the addresses relative the current pc.
                */
               debug_printf("\t\t; %lu", (unsigned long)jump);

               /*
                * Ignore far jumps given it could be actually a tail return to
                * a random address.
                */

               if (jump > max_pc &&
                   jump < extent) {
                  max_pc = jump;
               }
            }
         }
      }

      debug_printf("\n");

      /*
       * Stop disassembling on return statements, if there is no record of a
       * jump to a successive address.
       */

      if (TID.isReturn()) {
         if (pc > max_pc) {
            break;
         }
      }
   }

   /*
    * Print GDB command, useful to verify output.
    */

   if (0) {
      debug_printf("disassemble %p %p\n", bytes, bytes + pc);
   }

   debug_printf("\n");
#else /* HAVE_LLVM < 0x0207 */
   (void)func;
#endif /* HAVE_LLVM < 0x0207 */
}

<commit_msg>gallivm: change sys::getHostTriple to sys::getDefaultTargetTriple for LLVM >= 0x0301<commit_after>/**************************************************************************
 *
 * Copyright 2009-2011 VMware, Inc.
 * All Rights Reserved.
 *
 * Permission is hereby granted, free of charge, to any person obtaining a
 * copy of this software and associated documentation files (the
 * "Software"), to deal in the Software without restriction, including
 * without limitation the rights to use, copy, modify, merge, publish,
 * distribute, sub license, and/or sell copies of the Software, and to
 * permit persons to whom the Software is furnished to do so, subject to
 * the following conditions:
 *
 * The above copyright notice and this permission notice (including the
 * next paragraph) shall be included in all copies or substantial portions
 * of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
 * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR
 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 *
 **************************************************************************/

#include <llvm-c/Core.h>
#include <llvm/Target/TargetMachine.h>
#include <llvm/Target/TargetInstrInfo.h>
#include <llvm/Support/raw_ostream.h>
#include <llvm/Support/MemoryObject.h>

#if HAVE_LLVM >= 0x0300
#include <llvm/Support/TargetRegistry.h>
#include <llvm/Support/TargetSelect.h>
#else /* HAVE_LLVM < 0x0300 */
#include <llvm/Target/TargetRegistry.h>
#include <llvm/Target/TargetSelect.h>
#endif /* HAVE_LLVM < 0x0300 */

#if HAVE_LLVM >= 0x0209
#include <llvm/Support/Host.h>
#else /* HAVE_LLVM < 0x0209 */
#include <llvm/System/Host.h>
#endif /* HAVE_LLVM < 0x0209 */

#if HAVE_LLVM >= 0x0207
#include <llvm/MC/MCDisassembler.h>
#include <llvm/MC/MCAsmInfo.h>
#include <llvm/MC/MCInst.h>
#include <llvm/MC/MCInstPrinter.h>
#endif /* HAVE_LLVM >= 0x0207 */

#include "util/u_math.h"
#include "util/u_debug.h"

#include "lp_bld_debug.h"

/**
 * Check alignment.
 *
 * It is important that this check is not implemented as a macro or inlined
 * function, as the compiler assumptions in respect to alignment of global
 * and stack variables would often make the check a no op, defeating the
 * whole purpose of the exercise.
 */
extern "C" boolean
lp_check_alignment(const void *ptr, unsigned alignment)
{
   assert(util_is_power_of_two(alignment));
   return ((uintptr_t)ptr & (alignment - 1)) == 0;
}

class raw_debug_ostream :
   public llvm::raw_ostream
{
   uint64_t pos;

   void write_impl(const char *Ptr, size_t Size);
   uint64_t current_pos() { return pos; }
   uint64_t current_pos() const { return pos; }

#if HAVE_LLVM >= 0x207
   uint64_t preferred_buffer_size() { return 512; }
#else
   size_t preferred_buffer_size() { return 512; }
#endif
};

void
raw_debug_ostream::write_impl(const char *Ptr, size_t Size)
{
   if (Size > 0) {
      char *lastPtr = (char *)&Ptr[Size];
      char last = *lastPtr;
      *lastPtr = 0;
      _debug_printf("%*s", Size, Ptr);
      *lastPtr = last;
      pos += Size;
   }
}

/**
 * Same as LLVMDumpValue, but through our debugging channels.
 */
extern "C" void
lp_debug_dump_value(LLVMValueRef value)
{
#if (defined(PIPE_OS_WINDOWS) && !defined(PIPE_CC_MSVC)) || defined(PIPE_OS_EMBDDED)
   raw_debug_ostream os;
   llvm::unwrap(value)->print(os);
   os.flush();
#else
   LLVMDumpValue(value);
#endif
}

#if HAVE_LLVM >= 0x0207
/*
 * MemoryObject wrapper around a buffer of memory, to be used by MC
 * disassembler.
 */
class BufferMemoryObject:
   public llvm::MemoryObject
{
private:
   const uint8_t *Bytes;
   uint64_t Length;
public:
   BufferMemoryObject(const uint8_t *bytes, uint64_t length) :
      Bytes(bytes), Length(length)
   {
   }

   uint64_t getBase() const
   {
      return 0;
   }

   uint64_t getExtent() const
   {
      return Length;
   }

   int readByte(uint64_t addr, uint8_t *byte) const
   {
      if (addr > getExtent())
         return -1;
      *byte = Bytes[addr];
      return 0;
   }
};
#endif /* HAVE_LLVM >= 0x0207 */

/*
 * Disassemble a function, using the LLVM MC disassembler.
 *
 * See also:
 * - http://blog.llvm.org/2010/01/x86-disassembler.html
 * - http://blog.llvm.org/2010/04/intro-to-llvm-mc-project.html
 */
extern "C" void
lp_disassemble(const void* func)
{
#if HAVE_LLVM >= 0x0207
   using namespace llvm;

   const uint8_t *bytes = (const uint8_t *)func;

   /*
    * Limit disassembly to this extent
    */
   const uint64_t extent = 0x10000;

   uint64_t max_pc = 0;

   /*
    * Initialize all used objects.
    */

#if HAVE_LLVM >= 0x0301
   std::string Triple = sys::getDefaultTargetTriple();
#else
   std::string Triple = sys::getHostTriple();
#endif

   std::string Error;
   const Target *T = TargetRegistry::lookupTarget(Triple, Error);

#if HAVE_LLVM >= 0x0208
   InitializeNativeTargetAsmPrinter();
#else
   InitializeAllAsmPrinters();
#endif

   InitializeAllDisassemblers();

#if HAVE_LLVM >= 0x0300
   OwningPtr<const MCAsmInfo> AsmInfo(T->createMCAsmInfo(Triple));
#else
   OwningPtr<const MCAsmInfo> AsmInfo(T->createAsmInfo(Triple));
#endif

   if (!AsmInfo) {
      debug_printf("error: no assembly info for target %s\n", Triple.c_str());
      return;
   }

#if HAVE_LLVM >= 0x0300
   const MCSubtargetInfo *STI = T->createMCSubtargetInfo(Triple, sys::getHostCPUName(), "");
   OwningPtr<const MCDisassembler> DisAsm(T->createMCDisassembler(*STI));
#else
   OwningPtr<const MCDisassembler> DisAsm(T->createMCDisassembler());
#endif
   if (!DisAsm) {
      debug_printf("error: no disassembler for target %s\n", Triple.c_str());
      return;
   }

   raw_debug_ostream Out;

#if HAVE_LLVM >= 0x0300
   unsigned int AsmPrinterVariant = AsmInfo->getAssemblerDialect();
#else
   int AsmPrinterVariant = AsmInfo->getAssemblerDialect();
#endif

#if HAVE_LLVM >= 0x0300
   OwningPtr<MCInstPrinter> Printer(
         T->createMCInstPrinter(AsmPrinterVariant, *AsmInfo, *STI));
#elif HAVE_LLVM >= 0x0208
   OwningPtr<MCInstPrinter> Printer(
         T->createMCInstPrinter(AsmPrinterVariant, *AsmInfo));
#else
   OwningPtr<MCInstPrinter> Printer(
         T->createMCInstPrinter(AsmPrinterVariant, *AsmInfo, Out));
#endif
   if (!Printer) {
      debug_printf("error: no instruction printer for target %s\n", Triple.c_str());
      return;
   }

#if HAVE_LLVM >= 0x0300
   TargetMachine *TM = T->createTargetMachine(Triple, sys::getHostCPUName(), "");
#else
   TargetMachine *TM = T->createTargetMachine(Triple, "");
#endif

   const TargetInstrInfo *TII = TM->getInstrInfo();

   /*
    * Wrap the data in a MemoryObject
    */
   BufferMemoryObject memoryObject((const uint8_t *)bytes, extent);

   uint64_t pc;
   pc = 0;
   while (true) {
      MCInst Inst;
      uint64_t Size;

      /*
       * Print address.  We use addresses relative to the start of the function,
       * so that between runs.
       */

      debug_printf("%6lu:\t", (unsigned long)pc);

      if (!DisAsm->getInstruction(Inst, Size, memoryObject,
                                 pc,
#if HAVE_LLVM >= 0x0300
				  nulls(), nulls())) {
#else
				  nulls())) {
#endif
         debug_printf("invalid\n");
         pc += 1;
      }

      /*
       * Output the bytes in hexidecimal format.
       */

      if (0) {
         unsigned i;
         for (i = 0; i < Size; ++i) {
            debug_printf("%02x ", ((const uint8_t*)bytes)[pc + i]);
         }
         for (; i < 16; ++i) {
            debug_printf("   ");
         }
      }

      /*
       * Print the instruction.
       */

#if HAVE_LLVM >= 0x0300
      Printer->printInst(&Inst, Out, "");
#elif HAVE_LLVM >= 0x208
      Printer->printInst(&Inst, Out);
#else
      Printer->printInst(&Inst);
#endif
      Out.flush();

      /*
       * Advance.
       */

      pc += Size;

#if HAVE_LLVM >= 0x0300
      const MCInstrDesc &TID = TII->get(Inst.getOpcode());
#else
      const TargetInstrDesc &TID = TII->get(Inst.getOpcode());
#endif

      /*
       * Keep track of forward jumps to a nearby address.
       */

      if (TID.isBranch()) {
         for (unsigned i = 0; i < Inst.getNumOperands(); ++i) {
            const MCOperand &operand = Inst.getOperand(i);
            if (operand.isImm()) {
               uint64_t jump;

               /*
                * FIXME: Handle both relative and absolute addresses correctly.
                * EDInstInfo actually has this info, but operandTypes and
                * operandFlags enums are not exposed in the public interface.
                */

               if (1) {
                  /*
                   * PC relative addr.
                   */

                  jump = pc + operand.getImm();
               } else {
                  /*
                   * Absolute addr.
                   */

                  jump = (uint64_t)operand.getImm();
               }

               /*
                * Output the address relative to the function start, given
                * that MC will print the addresses relative the current pc.
                */
               debug_printf("\t\t; %lu", (unsigned long)jump);

               /*
                * Ignore far jumps given it could be actually a tail return to
                * a random address.
                */

               if (jump > max_pc &&
                   jump < extent) {
                  max_pc = jump;
               }
            }
         }
      }

      debug_printf("\n");

      /*
       * Stop disassembling on return statements, if there is no record of a
       * jump to a successive address.
       */

      if (TID.isReturn()) {
         if (pc > max_pc) {
            break;
         }
      }
   }

   /*
    * Print GDB command, useful to verify output.
    */

   if (0) {
      debug_printf("disassemble %p %p\n", bytes, bytes + pc);
   }

   debug_printf("\n");
#else /* HAVE_LLVM < 0x0207 */
   (void)func;
#endif /* HAVE_LLVM < 0x0207 */
}

<|endoftext|>