<commit_before>// Copyright (c) 2015-2016, The University of Texas at Austin
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
//     * Redistributions of source code must retain the above copyright
//       notice, this list of conditions and the following disclaimer.
//
//     * Redistributions in binary form must reproduce the above copyright
//       notice, this list of conditions and the following disclaimer in the
//       documentation and/or other materials provided with the distribution.
//
//     * Neither the name of the copyright holder nor the names of its
//       contributors may be used to endorse or promote products derived from
//       this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER 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.

/** @file move_robot.cpp
 *
 *  @brief ROS server that acts as an interface for ROS MoveIt! and publishes end-effector pose.
 *
 *  @author karl.kruusamae(at)utexas.edu
 */

#include "temoto/move_robot.h"

/** This method is executed when temoto/move_robot_service service is called.
 *  It updates target_pose_stamped based on the client's request and sets the new_move_req flag to let main() know that moving of the robot has been requested.
 *  @param req temoto::Goal service request.
 *  @param res temoto::Goal service response.
 *  @return always true.
 */
bool MoveRobotInterface::serviceUpdate(temoto::Goal::Request  &req,
				       temoto::Goal::Response &res)
{
//  ROS_INFO("New service update requested.");
  if (req.action_type == temoto::GoalRequest::CARTESIAN_COMPUTE)
  {
    // Set current state as the start state for planner. For some reason the actual built-in function doesn't do that.
    movegroup_.setStartState( *(movegroup_.getCurrentState()) );

    // waypoints are interpreted in the "leap_motion" ref.frame
    movegroup_.setPoseReferenceFrame(req.cartesian_frame);

    // Computed Cartesian trajectory.
    moveit_msgs::RobotTrajectory trajectory;
    res.cartesian_fraction = movegroup_.computeCartesianPath(req.cartesian_wayposes,
                                             0.01,  // eef_step
                                             0.0,   // jump_threshold
                                             trajectory);
    ROS_INFO("[MoveRobotInterface::serviceUpdate] Cartesian path %.2f%% acheived", res.cartesian_fraction * 100.0);

    latest_plan_.trajectory_ = trajectory;
    new_plan_available_ = true;
  }
  else
  {
    // sets the action associated to target pose
    req_action_type_ = req.action_type;

    // sets target requested pose
    target_pose_stamped_ = req.goal;

    // check for named target
    use_named_target_ = false;					// by default do not use named_target.
    named_target_ = req.named_target;				// get named_target from the service request.
    ROS_INFO("[MoveRobotInterface::serviceUpdate] named_target_='%s'", named_target_.c_str());
    if (!named_target_.empty()) use_named_target_ = true;	// if a named target was specified, set use_named_target_ to true.
    if (use_named_target_) ROS_INFO("[MoveRobotInterface::serviceUpdate] use_named_target is set TRUE");

    // Set new_move_requested_ TRUE for main() to see it
    new_move_requested_ = true;
    ROS_INFO("[MoveRobotInterface::serviceUpdate] new_move_requested_ is set TRUE");
  }
  return true;
} // end serviceUpdate

/** Plans and/or executes the motion of the robot.
 *  @param robot MoveGroup object of the robot.
 */
void MoveRobotInterface::requestMove()
{

  // Set current state as the start state for planner. For some reason the actual built-in function doesn't do that.
  movegroup_.setStartState( *(movegroup_.getCurrentState()) );

  // Get and print current position of the end effector
  geometry_msgs::PoseStamped current_pose = movegroup_.getCurrentPose();
  ROS_INFO("[move_robot/requestMove] === CURRENT POSE ( as given by MoveGroup::getCurrentPose() ) ===");
  ROS_INFO("[move_robot/requestMove] Current pose frame: %s", current_pose.header.frame_id.c_str());
  ROS_INFO("[move_robot/requestMove] Current pose (posit x, y, z): (%f, %f, %f)", current_pose.pose.position.x, current_pose.pose.position.y, current_pose.pose.position.z);
  ROS_INFO("[move_robot/requestMove] Current pose (orien x, y, z, w): (%f, %f, %f, %f)", current_pose.pose.orientation.x, current_pose.pose.orientation.y, current_pose.pose.orientation.z, current_pose.pose.orientation.w);

  // Use either named or pose target (named target takes the priority over regular pose target).
  if (use_named_target_)						// if use_named_target is true
  {
    bool set_target_ok = movegroup_.setNamedTarget(named_target_);	// set target pose as a named target
    if (!set_target_ok)							// check if setting named target was successful
    {
      ROS_INFO("[move_robot/requestMove] Failed to set named target. Please retry.");
      return;								// return if setNamedTarget failed
    }
    else
      ROS_INFO("[move_robot/requestMove] Using NAMED TARGET for planning and/or moving.");
  } // end if (use_named_target_)
  else
  {
//     movegroup_.setEndEffectorLink( "temoto_end_effector" );
    ROS_INFO("[move_robot/requestMove] Found end effector link: %s", movegroup_.getEndEffectorLink().c_str());
    // use the stamped target pose to set the target pose for robot
    bool set_target_ok = movegroup_.setPoseTarget(target_pose_stamped_ /*, "temoto_end_effector"*/);
    if (!set_target_ok)							// check if set target pose failed
    {
      ROS_INFO("[move_robot/requestMove] Failed to set pose target. Please retry.");
      return;								// return if setPoseTarget failed
    }
    else
      ROS_INFO("[move_robot/requestMove] Using POSE TARGET for planning and/or moving.");
  }

  // TODO
//   // Set goal tolerance based on the actual shift from current positio to target position
//   std::vector <geometry_msgs::Point> current_and_target;		// Vector that contains current and target points
//   current_and_target.push_back(current_pose.pose.position);		// Add current position
//   current_and_target.push_back(target_pose.position);			// Add target position
//   double shift = calculateDistance(current_and_target);			// Calculate the linear distance between the two positions
//   // CALCULATE DISTNACE BETWEEN CURRENT AND TARGET
//   // CALCULATE TOLERANCE AS A PERCENTAGE OF DISTANCE && CONSIDER SOME MIN/MAX LIMITS
//   // SET TOLERANCE FOR PLANNING

  // Just checking what is the target pose
  geometry_msgs::PoseStamped current_target = movegroup_.getPoseTarget();
  ROS_INFO("[move_robot/requestMove] Target pose frame: %s", current_target.header.frame_id.c_str());
  ROS_INFO("[move_robot/requestMove] Target pose (posit x, y, z): (%f, %f, %f)", current_target.pose.position.x, current_target.pose.position.y, current_target.pose.position.z);
  ROS_INFO("[move_robot/requestMove] Target pose (orien x, y, z, w): (%f, %f, %f, %f)", current_target.pose.orientation.x, current_target.pose.orientation.y, current_target.pose.orientation.z, current_target.pose.orientation.w);

  // Based on action type: PLAN (0x01), EXECUTE PLAN (0x02), or PLAN&EXECUTE (0x03)
  if ( req_action_type_ == temoto::GoalRequest::PLAN )
  {
    ROS_INFO("[move_robot/requestMove] Starting to plan ...");
    ROS_INFO("[move_robot/requestMove] Planning frame: %s", movegroup_.getPlanningFrame().c_str());
    movegroup_.plan( latest_plan_ );				// Calculate plan and store it in latest_plan_.
    new_plan_available_ = true;					// Set new_plan_available_ to TRUE.
    ROS_INFO("[move_robot/requestMove] DONE planning.");
  }
  else if ( req_action_type_ == temoto::GoalRequest::EXECUTE )
  {
    ROS_INFO("[move_robot/requestMove] Starting to execute last plan ...");
    if ( new_plan_available_ ) movegroup_.execute( latest_plan_ );	// If there is a new plan, execute latest_plan_.
    else ROS_INFO("[move_robot/requestMove] No plan to execute.");	// Else do nothing but printout "no plan"
    new_plan_available_ = false;					// Either case, set new_plan_available_ to FALSE.
    ROS_INFO("[move_robot/requestMove] DONE executing the plan");
  }
  else if ( req_action_type_ == temoto::GoalRequest::GO )
  {
    ROS_INFO("[move_robot/requestMove] Starting to move (i.e. plan & execute) ...");
//     robot.move();						// Plan and execute.
    // Since move() has a bug of start state not being current state, I am going to plan and execute sequentally.
    moveit::planning_interface::MoveGroup::Plan move_plan;
    printf("[move_robot/requestMove] Planning ...");
    movegroup_.plan( move_plan );
    printf("[DONE] \n[move_robot/requestMove] and Executing ...\n");
    movegroup_.execute( move_plan );
    ROS_INFO("[move_robot/requestMove] DONE moving.");
    new_plan_available_ = false;					// As any previous plan has become invalid, set new_plan_available_ to FALSE.
  }

  return;
} // end requestMove

/** Main method. */
int main(int argc, char **argv)
{
  // ROS init
  ros::init(argc, argv, "move_robot");
  // ROS Nodehandle for public namespace
  ros::NodeHandle n;
  // ROS NodeHandle for accessing private parameters
  ros::NodeHandle pn("~");

  // Using an async spinner
  ros::AsyncSpinner spinner(1);
  spinner.start();

  // get user-specified name for the movegroup as a private parameter
  std::string move_group_name;
  pn.getParam("movegroup", move_group_name);
  if ( move_group_name.empty() )
  {
    ROS_ERROR("[move_robot/main] No movegroup name was specified. Aborting.");
    return -1;
  }
  ROS_INFO("[move_robot/main] Retrieved '%s' from parameter server as a movegroup name.", move_group_name.c_str());

  // Create MoveRobotInterface for user-specified movegroup
  MoveRobotInterface moveIF(move_group_name);
  // Using RRTConnectkConfigDefault planner for motion planning
  moveIF.movegroup_.setPlannerId("RRTConnectkConfigDefault");

  // FYI
  ROS_INFO("[move_robot/main] Planning frame: %s", moveIF.movegroup_.getPlanningFrame().c_str());
  ROS_INFO("[move_robot/main] End effector link: %s", moveIF.movegroup_.getEndEffectorLink().c_str());
  ROS_INFO("[move_robot/main] End effector: %s", moveIF.movegroup_.getEndEffector().c_str());
  ROS_INFO("[move_robot/main] Goal position tolerance is: %.6f", moveIF.movegroup_.getGoalPositionTolerance());
  ROS_INFO("[move_robot/main] Goal orientation tolerance is: %.6f", moveIF.movegroup_.getGoalOrientationTolerance());
  ROS_INFO("[move_robot/main] Goal joint tolerance is: %.6f", moveIF.movegroup_.getGoalJointTolerance());

  // Set up service for move_robot_service; if there's a service request, executes serviceUpdate() function
  ros::ServiceServer service = n.advertiseService("temoto/move_robot_service", &MoveRobotInterface::serviceUpdate, &moveIF);
  ROS_INFO("[move_robot/main] Service 'temoto/move_robot_service' up and going. Ready to send move commands to %s.", move_group_name.c_str());

  // Set up publisher for the end effector location
  ros::Publisher pub_end_effector = n.advertise<geometry_msgs::PoseStamped>( "temoto/end_effector_pose", 1 );

  // ROS client for /temoto/adjust_rviz_camera
  ros::ServiceClient client_visual = n.serviceClient<std_srvs::Empty>("temoto/adjust_rviz_camera");
  std_srvs::Empty empty_srv;			// Empty service.

  while ( ros::ok() )
  {
    // check if there has been a service request for a new move
    if ( moveIF.new_move_requested_ && moveIF.req_action_type_ < 0x04 )
    {
      moveIF.requestMove();			// plan and execute move using move_group
      moveIF.new_move_requested_ = false;	// set request flag to false
      moveIF.new_end_effector_pose_ = true;	// assumes that request move resulted in new pose for end effector and sets the corresponding flag
    }

    // get and publish current end effector pose;
    pub_end_effector.publish( moveIF.movegroup_.getCurrentPose() );

    // If pose of the end effector has changed. Update camera position if the end effector has moved since the last time camera was positioned.
    if ( moveIF.new_end_effector_pose_ )
    {
      client_visual.call(empty_srv);
      moveIF.new_end_effector_pose_ = false;	// set new_end_effector_pose to zero
    } // end if

  } // end while

  return 0;
} // end main
<commit_msg>tried using spinOnce() but for some reason it did not work<commit_after>// Copyright (c) 2015-2016, The University of Texas at Austin
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
//     * Redistributions of source code must retain the above copyright
//       notice, this list of conditions and the following disclaimer.
//
//     * Redistributions in binary form must reproduce the above copyright
//       notice, this list of conditions and the following disclaimer in the
//       documentation and/or other materials provided with the distribution.
//
//     * Neither the name of the copyright holder nor the names of its
//       contributors may be used to endorse or promote products derived from
//       this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER 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.

/** @file move_robot.cpp
 *
 *  @brief ROS server that acts as an interface for ROS MoveIt! and publishes end-effector pose.
 *
 *  @author karl.kruusamae(at)utexas.edu
 */

#include "temoto/move_robot.h"

/** This method is executed when temoto/move_robot_service service is called.
 *  It updates target_pose_stamped based on the client's request and sets the new_move_req flag to let main() know that moving of the robot has been requested.
 *  @param req temoto::Goal service request.
 *  @param res temoto::Goal service response.
 *  @return always true.
 */
bool MoveRobotInterface::serviceUpdate(temoto::Goal::Request  &req,
				       temoto::Goal::Response &res)
{
//  ROS_INFO("New service update requested.");
  if (req.action_type == temoto::GoalRequest::CARTESIAN_COMPUTE)
  {
    // Set current state as the start state for planner. For some reason the actual built-in function doesn't do that.
    movegroup_.setStartState( *(movegroup_.getCurrentState()) );

    // waypoints are interpreted in the "leap_motion" ref.frame
    movegroup_.setPoseReferenceFrame(req.cartesian_frame);

    // Computed Cartesian trajectory.
    moveit_msgs::RobotTrajectory trajectory;
    res.cartesian_fraction = movegroup_.computeCartesianPath(req.cartesian_wayposes,
                                             0.01,  // eef_step
                                             0.0,   // jump_threshold
                                             trajectory);
    ROS_INFO("[MoveRobotInterface::serviceUpdate] Cartesian path %.2f%% acheived", res.cartesian_fraction * 100.0);

    latest_plan_.trajectory_ = trajectory;
    new_plan_available_ = true;
  }
  else
  {
    // sets the action associated to target pose
    req_action_type_ = req.action_type;

    // sets target requested pose
    target_pose_stamped_ = req.goal;

    // check for named target
    use_named_target_ = false;					// by default do not use named_target.
    named_target_ = req.named_target;				// get named_target from the service request.
    ROS_INFO("[MoveRobotInterface::serviceUpdate] named_target_='%s'", named_target_.c_str());
    if (!named_target_.empty()) use_named_target_ = true;	// if a named target was specified, set use_named_target_ to true.
    if (use_named_target_) ROS_INFO("[MoveRobotInterface::serviceUpdate] use_named_target is set TRUE");

    // Set new_move_requested_ TRUE for main() to see it
    new_move_requested_ = true;
    ROS_INFO("[MoveRobotInterface::serviceUpdate] new_move_requested_ is set TRUE");
  }
  return true;
} // end serviceUpdate

/** Plans and/or executes the motion of the robot.
 *  @param robot MoveGroup object of the robot.
 */
void MoveRobotInterface::requestMove()
{

  // Set current state as the start state for planner. For some reason the actual built-in function doesn't do that.
  movegroup_.setStartState( *(movegroup_.getCurrentState()) );

  // Get and print current position of the end effector
  geometry_msgs::PoseStamped current_pose = movegroup_.getCurrentPose();
  ROS_INFO("[move_robot/requestMove] === CURRENT POSE ( as given by MoveGroup::getCurrentPose() ) ===");
  ROS_INFO("[move_robot/requestMove] Current pose frame: %s", current_pose.header.frame_id.c_str());
  ROS_INFO("[move_robot/requestMove] Current pose (posit x, y, z): (%f, %f, %f)", current_pose.pose.position.x, current_pose.pose.position.y, current_pose.pose.position.z);
  ROS_INFO("[move_robot/requestMove] Current pose (orien x, y, z, w): (%f, %f, %f, %f)", current_pose.pose.orientation.x, current_pose.pose.orientation.y, current_pose.pose.orientation.z, current_pose.pose.orientation.w);

  // Use either named or pose target (named target takes the priority over regular pose target).
  if (use_named_target_)						// if use_named_target is true
  {
    bool set_target_ok = movegroup_.setNamedTarget(named_target_);	// set target pose as a named target
    if (!set_target_ok)							// check if setting named target was successful
    {
      ROS_INFO("[move_robot/requestMove] Failed to set named target. Please retry.");
      return;								// return if setNamedTarget failed
    }
    else
      ROS_INFO("[move_robot/requestMove] Using NAMED TARGET for planning and/or moving.");
  } // end if (use_named_target_)
  else
  {
//     movegroup_.setEndEffectorLink( "temoto_end_effector" );
    ROS_INFO("[move_robot/requestMove] Found end effector link: %s", movegroup_.getEndEffectorLink().c_str());
    // use the stamped target pose to set the target pose for robot
    bool set_target_ok = movegroup_.setPoseTarget(target_pose_stamped_ /*, "temoto_end_effector"*/);
    if (!set_target_ok)							// check if set target pose failed
    {
      ROS_INFO("[move_robot/requestMove] Failed to set pose target. Please retry.");
      return;								// return if setPoseTarget failed
    }
    else
      ROS_INFO("[move_robot/requestMove] Using POSE TARGET for planning and/or moving.");
  }

  // TODO
//   // Set goal tolerance based on the actual shift from current positio to target position
//   std::vector <geometry_msgs::Point> current_and_target;		// Vector that contains current and target points
//   current_and_target.push_back(current_pose.pose.position);		// Add current position
//   current_and_target.push_back(target_pose.position);			// Add target position
//   double shift = calculateDistance(current_and_target);			// Calculate the linear distance between the two positions
//   // CALCULATE DISTNACE BETWEEN CURRENT AND TARGET
//   // CALCULATE TOLERANCE AS A PERCENTAGE OF DISTANCE && CONSIDER SOME MIN/MAX LIMITS
//   // SET TOLERANCE FOR PLANNING

  // Just checking what is the target pose
  geometry_msgs::PoseStamped current_target = movegroup_.getPoseTarget();
  ROS_INFO("[move_robot/requestMove] Target pose frame: %s", current_target.header.frame_id.c_str());
  ROS_INFO("[move_robot/requestMove] Target pose (posit x, y, z): (%f, %f, %f)", current_target.pose.position.x, current_target.pose.position.y, current_target.pose.position.z);
  ROS_INFO("[move_robot/requestMove] Target pose (orien x, y, z, w): (%f, %f, %f, %f)", current_target.pose.orientation.x, current_target.pose.orientation.y, current_target.pose.orientation.z, current_target.pose.orientation.w);

  // Based on action type: PLAN (0x01), EXECUTE PLAN (0x02), or PLAN&EXECUTE (0x03)
  if ( req_action_type_ == temoto::GoalRequest::PLAN )
  {
    ROS_INFO("[move_robot/requestMove] Starting to plan ...");
    ROS_INFO("[move_robot/requestMove] Planning frame: %s", movegroup_.getPlanningFrame().c_str());
    movegroup_.plan( latest_plan_ );				// Calculate plan and store it in latest_plan_.
    new_plan_available_ = true;					// Set new_plan_available_ to TRUE.
    ROS_INFO("[move_robot/requestMove] DONE planning.");
  }
  else if ( req_action_type_ == temoto::GoalRequest::EXECUTE )
  {
    ROS_INFO("[move_robot/requestMove] Starting to execute last plan ...");
    if ( new_plan_available_ ) movegroup_.execute( latest_plan_ );	// If there is a new plan, execute latest_plan_.
    else ROS_INFO("[move_robot/requestMove] No plan to execute.");	// Else do nothing but printout "no plan"
    new_plan_available_ = false;					// Either case, set new_plan_available_ to FALSE.
    ROS_INFO("[move_robot/requestMove] DONE executing the plan");
  }
  else if ( req_action_type_ == temoto::GoalRequest::GO )
  {
    ROS_INFO("[move_robot/requestMove] Starting to move (i.e. plan & execute) ...");
//     robot.move();						// Plan and execute.
    // Since move() has a bug of start state not being current state, I am going to plan and execute sequentally.
    moveit::planning_interface::MoveGroup::Plan move_plan;
    printf("[move_robot/requestMove] Planning ...");
    movegroup_.plan( move_plan );
    printf("[DONE] \n[move_robot/requestMove] and Executing ...\n");
    movegroup_.execute( move_plan );
    ROS_INFO("[move_robot/requestMove] DONE moving.");
    new_plan_available_ = false;					// As any previous plan has become invalid, set new_plan_available_ to FALSE.
  }

  return;
} // end requestMove

/** Main method. */
int main(int argc, char **argv)
{
  // ROS init
  ros::init(argc, argv, "move_robot");
  // ROS Nodehandle for public namespace
  ros::NodeHandle n;
  // ROS NodeHandle for accessing private parameters
  ros::NodeHandle pn("~");

//   ros::Rate node_rate(1000);

  // Using an async spinner
  ros::AsyncSpinner spinner(1);
  spinner.start();

  // get user-specified name for the movegroup as a private parameter
  std::string move_group_name;
  pn.getParam("movegroup", move_group_name);
  if ( move_group_name.empty() )
  {
    ROS_ERROR("[move_robot/main] No movegroup name was specified. Aborting.");
    return -1;
  }
  ROS_INFO("[move_robot/main] Retrieved '%s' from parameter server as a movegroup name.", move_group_name.c_str());

  // Create MoveRobotInterface for user-specified movegroup
  MoveRobotInterface moveIF(move_group_name);
  // Using RRTConnectkConfigDefault planner for motion planning
  moveIF.movegroup_.setPlannerId("RRTConnectkConfigDefault");

  // FYI
  ROS_INFO("[move_robot/main] Planning frame: %s", moveIF.movegroup_.getPlanningFrame().c_str());
  ROS_INFO("[move_robot/main] End effector link: %s", moveIF.movegroup_.getEndEffectorLink().c_str());
  ROS_INFO("[move_robot/main] End effector: %s", moveIF.movegroup_.getEndEffector().c_str());
  ROS_INFO("[move_robot/main] Goal position tolerance is: %.6f", moveIF.movegroup_.getGoalPositionTolerance());
  ROS_INFO("[move_robot/main] Goal orientation tolerance is: %.6f", moveIF.movegroup_.getGoalOrientationTolerance());
  ROS_INFO("[move_robot/main] Goal joint tolerance is: %.6f", moveIF.movegroup_.getGoalJointTolerance());

  // Set up service for move_robot_service; if there's a service request, executes serviceUpdate() function
  ros::ServiceServer service = n.advertiseService("temoto/move_robot_service", &MoveRobotInterface::serviceUpdate, &moveIF);
  ROS_INFO("[move_robot/main] Service 'temoto/move_robot_service' up and going. Ready to send move commands to %s.", move_group_name.c_str());

  // Set up publisher for the end effector location
  ros::Publisher pub_end_effector = n.advertise<geometry_msgs::PoseStamped>( "temoto/end_effector_pose", 1 );

  // ROS client for /temoto/adjust_rviz_camera
  ros::ServiceClient client_visual = n.serviceClient<std_srvs::Empty>("temoto/adjust_rviz_camera");
  std_srvs::Empty empty_srv;			// Empty service.

  while ( ros::ok() )
  {
    // check if there has been a service request for a new move
    if ( moveIF.new_move_requested_ && moveIF.req_action_type_ < 0x04 )
    {
      moveIF.requestMove();			// plan and execute move using move_group
      moveIF.new_move_requested_ = false;	// set request flag to false
      moveIF.new_end_effector_pose_ = true;	// assumes that request move resulted in new pose for end effector and sets the corresponding flag
    }

    // get and publish current end effector pose;
    pub_end_effector.publish( moveIF.movegroup_.getCurrentPose() );

    // If pose of the end effector has changed. Update camera position if the end effector has moved since the last time camera was positioned.
    if ( moveIF.new_end_effector_pose_ )
    {
      client_visual.call(empty_srv);
      moveIF.new_end_effector_pose_ = false;	// set new_end_effector_pose to zero
    } // end if

//     ros::spinOnce();
//     node_rate.sleep();

  } // end while

  return 0;
} // end main
<|endoftext|>


<commit_before>/**
 * Template C++ file.
 * Function with references to pointers: func(int *&ptr);
 */
/********************* Header Files ***********************/
/* C++ Headers */
#include <iostream> /* Input/output objects. */
//#include <fstream> /* File operations. */
//#include <sstream> /* String stream. */
#include <string> /* C++ String class. */
//#include <new> /* Defines bad_malloc exception, new functions. */
//#include <typeinfo> /* Casting header. */
//#include <exception> /* Top level exception header. */
//#include <stdexcept> /* Derived exception classes. */

/* STL Headers */
//#include <vector>
//#include <list>
//#include <deque>
//#include <stack>
//#include <queue>
//#include <priority_queue>
//#include <bitset>
//#include <set> // multiset for multiple keys allowed.
//#include <map> // multimap for multiple keys allowed.
//#include <utility> // Has pair for map.
//#include <algorithm>
//#include <numeric>
//#include <functional> // Functional objects.
//#include <iterator> // Contains back_inserter function and like.

/* C Headers */
//#include <cstdlib>
//#include <cstddef>
//#include <cctype>
//#include <cstring>
//#include <cstdio>
//#include <climits>
//#include <cassert>

/* Project Headers */

/******************* Constants/Macros *********************/

/**************** Namespace Declarations ******************/
using std::cin;
using std::cout;
using std::endl;
using std::string;

/******************* Type Definitions *********************/
/* For enums: Try to namesapce the common elements.
 * typedef enum {
 *	VAL_,
 * } name_e;
 */

/* For structs:
 * typedef struct name_s {
 *	int index;
 * } name_t;
 */

/****************** Class Definitions *********************/

/****************** Static Functions **********************/

/****************** Global Functions **********************/
/**
 * Main loop of the function.
 */
int main(void) {

	return 0;
}

/* Notes:
 * Force call to use another version of virtual function: baseP->Item_base::net_price(42);
 *
 */
<commit_msg>Forgot a line.<commit_after>/**
 * Template C++ file.
 * Function with references to pointers: func(int *&ptr);
 */
/********************* Header Files ***********************/
/* C++ Headers */
#include <iostream> /* Input/output objects. */
//#include <fstream> /* File operations. */
//#include <sstream> /* String stream. */
#include <string> /* C++ String class. */
//#include <new> /* Defines bad_malloc exception, new functions. */
//#include <typeinfo> /* Casting header. */
//#include <exception> /* Top level exception header. */
//#include <stdexcept> /* Derived exception classes. */

/* STL Headers */
//#include <vector>
//#include <list>
//#include <deque>
//#include <stack>
//#include <queue>
//#include <priority_queue>
//#include <bitset>
//#include <set> // multiset for multiple keys allowed.
//#include <map> // multimap for multiple keys allowed.
//#include <utility> // Has pair for map.
//#include <algorithm>
//#include <numeric>
//#include <functional> // Functional objects.
//#include <iterator> // Contains back_inserter function and like.

/* C Headers */
//#include <cstdlib>
//#include <cstddef>
//#include <cctype>
//#include <cstring>
//#include <cstdio>
//#include <climits>
//#include <cassert>

/* Project Headers */

/******************* Constants/Macros *********************/

/**************** Namespace Declarations ******************/
using std::cin;
using std::cout;
using std::endl;
using std::string;

/******************* Type Definitions *********************/
/* For enums: Try to namesapce the common elements.
 * typedef enum {
 *	VAL_,
 * } name_e;
 */

/* For structs:
 * typedef struct name_s {
 *	int index;
 * } name_t;
 */

/****************** Class Definitions *********************/

/****************** Global Functions **********************/
/**
 * Main loop of the function.
 */
int main(void) {

	return 0;
}

/* Notes:
 * Force call to use another version of virtual function: baseP->Item_base::net_price(42);
 *
 */
<|endoftext|>


<commit_before>/*************************************************************************
 *
 *  $RCSfile: vclxbitmap.cxx,v $
 *
 *  $Revision: 1.1.1.1 $
 *
 *  last change: $Author: hr $ $Date: 2000-09-18 17:02:08 $
 *
 *  The Contents of this file are made available subject to the terms of
 *  either of the following licenses
 *
 *         - GNU Lesser General Public License Version 2.1
 *         - Sun Industry Standards Source License Version 1.1
 *
 *  Sun Microsystems Inc., October, 2000
 *
 *  GNU Lesser General Public License Version 2.1
 *  =============================================
 *  Copyright 2000 by Sun Microsystems, Inc.
 *  901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public
 *  License version 2.1, as published by the Free Software Foundation.
 *
 *  This library is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *  Lesser General Public License for more details.
 *
 *  You should have received a copy of the GNU Lesser General Public
 *  License along with this library; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *  MA  02111-1307  USA
 *
 *
 *  Sun Industry Standards Source License Version 1.1
 *  =================================================
 *  The contents of this file are subject to the Sun Industry Standards
 *  Source License Version 1.1 (the "License"); You may not use this file
 *  except in compliance with the License. You may obtain a copy of the
 *  License at http://www.openoffice.org/license.html.
 *
 *  Software provided under this License is provided on an "AS IS" basis,
 *  WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
 *  WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
 *  MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
 *  See the License for the specific provisions governing your rights and
 *  obligations concerning the Software.
 *
 *  The Initial Developer of the Original Code is: Sun Microsystems, Inc.
 *
 *  Copyright: 2000 by Sun Microsystems, Inc.
 *
 *  All Rights Reserved.
 *
 *  Contributor(s): _______________________________________
 *
 *
 ************************************************************************/

#include <toolkit/awt/vclxbitmap.hxx>
#include <toolkit/helper/macros.hxx>
#include <cppuhelper/typeprovider.hxx>
#include <tools/stream.hxx>
#include <rtl/memory.h>
#include <rtl/uuid.h>

//  ----------------------------------------------------
//  class VCLXBitmap
//  ----------------------------------------------------

// ::com::sun::star::uno::XInterface
::com::sun::star::uno::Any VCLXBitmap::queryInterface( const ::com::sun::star::uno::Type & rType ) throw(::com::sun::star::uno::RuntimeException)
{
    ::com::sun::star::uno::Any aRet = ::cppu::queryInterface( rType,
                                        SAL_STATIC_CAST( ::com::sun::star::awt::XBitmap*, this ),
                                        SAL_STATIC_CAST( ::com::sun::star::awt::XDisplayBitmap*, this ),
                                        SAL_STATIC_CAST( ::com::sun::star::lang::XUnoTunnel*, this ),
                                        SAL_STATIC_CAST( ::com::sun::star::lang::XTypeProvider*, this ) );
    return (aRet.hasValue() ? aRet : OWeakObject::queryInterface( rType ));
}

// ::com::sun::star::lang::XUnoTunnel
IMPL_XUNOTUNNEL( VCLXBitmap )

// ::com::sun::star::lang::XTypeProvider
IMPL_XTYPEPROVIDER_START( VCLXBitmap )
    getCppuType( ( ::com::sun::star::uno::Reference< ::com::sun::star::awt::XBitmap>* ) NULL ),
    getCppuType( ( ::com::sun::star::uno::Reference< ::com::sun::star::awt::XDisplayBitmap>* ) NULL )
IMPL_XTYPEPROVIDER_END

// ::com::sun::star::awt::XBitmap
::com::sun::star::awt::Size VCLXBitmap::getSize() throw(::com::sun::star::uno::RuntimeException)
{
    ::osl::Guard< ::osl::Mutex > aGuard( GetMutex() );

    ::com::sun::star::awt::Size aSize( maBitmap.GetSizePixel().Width(), maBitmap.GetSizePixel().Height() );
    return aSize;
}

::com::sun::star::uno::Sequence< sal_Int8 > VCLXBitmap::getDIB() throw(::com::sun::star::uno::RuntimeException)
{
    ::osl::Guard< ::osl::Mutex > aGuard( GetMutex() );

    SvMemoryStream aMem;
    aMem << maBitmap.GetBitmap();
    return ::com::sun::star::uno::Sequence<sal_Int8>( (sal_Int8*) aMem.GetData(), aMem.Tell() );
}

::com::sun::star::uno::Sequence< sal_Int8 > VCLXBitmap::getMaskDIB() throw(::com::sun::star::uno::RuntimeException)
{
    ::osl::Guard< ::osl::Mutex > aGuard( GetMutex() );

    SvMemoryStream aMem;
    aMem << maBitmap.GetMask();
    return ::com::sun::star::uno::Sequence<sal_Int8>( (sal_Int8*) aMem.GetData(), aMem.Tell() );
}

<commit_msg>INTEGRATION: CWS ooo19126 (1.1.1.1.442); FILE MERGED 2005/09/05 16:58:06 rt 1.1.1.1.442.1: #i54170# Change license header: remove SISSL<commit_after>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: vclxbitmap.cxx,v $
 *
 *  $Revision: 1.2 $
 *
 *  last change: $Author: rt $ $Date: 2005-09-09 13:11:45 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    This library is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *    Lesser General Public License for more details.
 *
 *    You should have received a copy of the GNU Lesser General Public
 *    License along with this library; if not, write to the Free Software
 *    Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/

#include <toolkit/awt/vclxbitmap.hxx>
#include <toolkit/helper/macros.hxx>
#include <cppuhelper/typeprovider.hxx>
#include <tools/stream.hxx>
#include <rtl/memory.h>
#include <rtl/uuid.h>

//  ----------------------------------------------------
//  class VCLXBitmap
//  ----------------------------------------------------

// ::com::sun::star::uno::XInterface
::com::sun::star::uno::Any VCLXBitmap::queryInterface( const ::com::sun::star::uno::Type & rType ) throw(::com::sun::star::uno::RuntimeException)
{
    ::com::sun::star::uno::Any aRet = ::cppu::queryInterface( rType,
                                        SAL_STATIC_CAST( ::com::sun::star::awt::XBitmap*, this ),
                                        SAL_STATIC_CAST( ::com::sun::star::awt::XDisplayBitmap*, this ),
                                        SAL_STATIC_CAST( ::com::sun::star::lang::XUnoTunnel*, this ),
                                        SAL_STATIC_CAST( ::com::sun::star::lang::XTypeProvider*, this ) );
    return (aRet.hasValue() ? aRet : OWeakObject::queryInterface( rType ));
}

// ::com::sun::star::lang::XUnoTunnel
IMPL_XUNOTUNNEL( VCLXBitmap )

// ::com::sun::star::lang::XTypeProvider
IMPL_XTYPEPROVIDER_START( VCLXBitmap )
    getCppuType( ( ::com::sun::star::uno::Reference< ::com::sun::star::awt::XBitmap>* ) NULL ),
    getCppuType( ( ::com::sun::star::uno::Reference< ::com::sun::star::awt::XDisplayBitmap>* ) NULL )
IMPL_XTYPEPROVIDER_END

// ::com::sun::star::awt::XBitmap
::com::sun::star::awt::Size VCLXBitmap::getSize() throw(::com::sun::star::uno::RuntimeException)
{
    ::osl::Guard< ::osl::Mutex > aGuard( GetMutex() );

    ::com::sun::star::awt::Size aSize( maBitmap.GetSizePixel().Width(), maBitmap.GetSizePixel().Height() );
    return aSize;
}

::com::sun::star::uno::Sequence< sal_Int8 > VCLXBitmap::getDIB() throw(::com::sun::star::uno::RuntimeException)
{
    ::osl::Guard< ::osl::Mutex > aGuard( GetMutex() );

    SvMemoryStream aMem;
    aMem << maBitmap.GetBitmap();
    return ::com::sun::star::uno::Sequence<sal_Int8>( (sal_Int8*) aMem.GetData(), aMem.Tell() );
}

::com::sun::star::uno::Sequence< sal_Int8 > VCLXBitmap::getMaskDIB() throw(::com::sun::star::uno::RuntimeException)
{
    ::osl::Guard< ::osl::Mutex > aGuard( GetMutex() );

    SvMemoryStream aMem;
    aMem << maBitmap.GetMask();
    return ::com::sun::star::uno::Sequence<sal_Int8>( (sal_Int8*) aMem.GetData(), aMem.Tell() );
}

<|endoftext|>


<commit_before><commit_msg>Remove unused VCLXWindowImpl parts<commit_after><|endoftext|>


<commit_before>/*
 * Copyright 2015 Google Inc.
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 *
 */

#include "VisualBench.h"

#include "GrContext.h"
#include "ProcStats.h"
#include "SkApplication.h"
#include "SkCanvas.h"
#include "SkCommandLineFlags.h"
#include "SkGraphics.h"
#include "SkGr.h"
#include "SkOSFile.h"
#include "SkStream.h"
#include "Stats.h"
#include "VisualLightweightBenchModule.h"
#include "VisualInteractiveModule.h"
#include "gl/GrGLInterface.h"

DEFINE_bool2(fullscreen, f, true, "Run fullscreen.");
DEFINE_bool2(interactive, n, false, "Run in interactive mode.");
DEFINE_bool2(dif, d, false, "Use device-independent fonts.");

VisualBench::VisualBench(void* hwnd, int argc, char** argv)
    : INHERITED(hwnd) {
    SkCommandLineFlags::Parse(argc, argv);

    SkDebugf("Command line arguments:");
    for (int i = 0; i < argc; ++i) {
        SkDebugf("%s\n", argv[i]);
    }

    // these have to happen after commandline parsing
    if (FLAGS_dif) {
        const SkSurfaceProps& props(INHERITED::getSurfaceProps());
        uint32_t flags = SkSurfaceProps::kUseDeviceIndependentFonts_Flag | props.flags();
        INHERITED::setSurfaceProps(SkSurfaceProps(flags, props.pixelGeometry()));
    }
    fModule.reset(new VisualLightweightBenchModule(this));
    if (FLAGS_interactive) {
        fModule.reset(new VisualInteractiveModule(this));
    }

    this->setTitle();
    this->setupBackend();
}

VisualBench::~VisualBench() {
    this->tearDownContext();
}

void VisualBench::setTitle() {
    SkString title("VisualBench");
    INHERITED::setTitle(title.c_str());
}

SkSurface* VisualBench::createSurface() {
    if (!fSurface) {
        SkSurfaceProps props(INHERITED::getSurfaceProps());
        fSurface.reset(SkSurface::NewRenderTargetDirect(fRenderTarget, &props));
    }

    // The caller will wrap the SkSurface in an SkAutoTUnref
    return SkRef(fSurface.get());
}

bool VisualBench::setupBackend() {
    this->setColorType(kRGBA_8888_SkColorType);
    this->setVisibleP(true);
    this->setClipToBounds(false);

    if (FLAGS_fullscreen) {
        if (!this->makeFullscreen()) {
            SkDebugf("Could not go fullscreen!");
        }
    }

    this->resetContext();
    return true;
}

void VisualBench::resetContext() {
    this->tearDownContext();
    this->setupContext();
}

void VisualBench::setupContext() {
    if (!this->attach(kNativeGL_BackEndType, FLAGS_msaa, &fAttachmentInfo)) {
        SkDebugf("Not possible to create backend.\n");
        INHERITED::detach();
        SkFAIL("Could not create backend\n");
    }

    this->setVsync(false);

    fSurface.reset(nullptr);

    fInterface.reset(GrGLCreateNativeInterface());

    // TODO use the GLContext creation factories and also set this all up in configs
    if (0 == FLAGS_nvpr) {
        fInterface.reset(GrGLInterfaceRemoveNVPR(fInterface));
    }
    SkASSERT(fInterface);

    // setup contexts
    fContext.reset(GrContext::Create(kOpenGL_GrBackend, (GrBackendContext)fInterface.get()));
    SkASSERT(fContext);

    // setup rendertargets
    this->setupRenderTarget();
}

void VisualBench::tearDownContext() {
    if (fContext) {
        // We abandon the context in case SkWindow has kept a ref to the surface
        fContext->abandonContext();
        fContext.reset();
        fSurface.reset();
        fInterface.reset();
        this->detach();
    }
}

void VisualBench::setupRenderTarget() {
    if (fContext) {
        fRenderTarget.reset(this->renderTarget(fAttachmentInfo, fInterface, fContext));
    }
}

void VisualBench::draw(SkCanvas* canvas) {
    fModule->draw(canvas);

    // Invalidate the window to force a redraw. Poor man's animation mechanism.
    this->inval(nullptr);
}

void VisualBench::clear(SkCanvas* canvas, SkColor color, int frames) {
    canvas->clear(color);
    for (int i = 0; i < frames - 1; ++i) {
        canvas->flush();
        this->present();
        canvas->clear(color);
    }
}

void VisualBench::onSizeChange() {
    this->setupRenderTarget();
}

bool VisualBench::onHandleChar(SkUnichar unichar) {
    static const auto kEscKey = 27;
    if (kEscKey == unichar) {
        this->closeWindow();
        return true;
    }

    return fModule->onHandleChar(unichar);
}

// Externally declared entry points
void application_init() {
    SkGraphics::Init();
    SkEvent::Init();
}

void application_term() {
    SkEvent::Term();
}

SkOSWindow* create_sk_window(void* hwnd, int argc, char** argv) {
    return new VisualBench(hwnd, argc, argv);
}

<commit_msg>Move command line print above parse in VisualBench<commit_after>/*
 * Copyright 2015 Google Inc.
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 *
 */

#include "VisualBench.h"

#include "GrContext.h"
#include "ProcStats.h"
#include "SkApplication.h"
#include "SkCanvas.h"
#include "SkCommandLineFlags.h"
#include "SkGraphics.h"
#include "SkGr.h"
#include "SkOSFile.h"
#include "SkStream.h"
#include "Stats.h"
#include "VisualLightweightBenchModule.h"
#include "VisualInteractiveModule.h"
#include "gl/GrGLInterface.h"

DEFINE_bool2(fullscreen, f, true, "Run fullscreen.");
DEFINE_bool2(interactive, n, false, "Run in interactive mode.");
DEFINE_bool2(dif, d, false, "Use device-independent fonts.");

VisualBench::VisualBench(void* hwnd, int argc, char** argv)
    : INHERITED(hwnd) {
    SkDebugf("Command line arguments:");
    for (int i = 0; i < argc; ++i) {
        SkDebugf("%s\n", argv[i]);
    }

    SkCommandLineFlags::Parse(argc, argv);

    // these have to happen after commandline parsing
    if (FLAGS_dif) {
        const SkSurfaceProps& props(INHERITED::getSurfaceProps());
        uint32_t flags = SkSurfaceProps::kUseDeviceIndependentFonts_Flag | props.flags();
        INHERITED::setSurfaceProps(SkSurfaceProps(flags, props.pixelGeometry()));
    }
    fModule.reset(new VisualLightweightBenchModule(this));
    if (FLAGS_interactive) {
        fModule.reset(new VisualInteractiveModule(this));
    }

    this->setTitle();
    this->setupBackend();
}

VisualBench::~VisualBench() {
    this->tearDownContext();
}

void VisualBench::setTitle() {
    SkString title("VisualBench");
    INHERITED::setTitle(title.c_str());
}

SkSurface* VisualBench::createSurface() {
    if (!fSurface) {
        SkSurfaceProps props(INHERITED::getSurfaceProps());
        fSurface.reset(SkSurface::NewRenderTargetDirect(fRenderTarget, &props));
    }

    // The caller will wrap the SkSurface in an SkAutoTUnref
    return SkRef(fSurface.get());
}

bool VisualBench::setupBackend() {
    this->setColorType(kRGBA_8888_SkColorType);
    this->setVisibleP(true);
    this->setClipToBounds(false);

    if (FLAGS_fullscreen) {
        if (!this->makeFullscreen()) {
            SkDebugf("Could not go fullscreen!");
        }
    }

    this->resetContext();
    return true;
}

void VisualBench::resetContext() {
    this->tearDownContext();
    this->setupContext();
}

void VisualBench::setupContext() {
    if (!this->attach(kNativeGL_BackEndType, FLAGS_msaa, &fAttachmentInfo)) {
        SkDebugf("Not possible to create backend.\n");
        INHERITED::detach();
        SkFAIL("Could not create backend\n");
    }

    this->setVsync(false);

    fSurface.reset(nullptr);

    fInterface.reset(GrGLCreateNativeInterface());

    // TODO use the GLContext creation factories and also set this all up in configs
    if (0 == FLAGS_nvpr) {
        fInterface.reset(GrGLInterfaceRemoveNVPR(fInterface));
    }
    SkASSERT(fInterface);

    // setup contexts
    fContext.reset(GrContext::Create(kOpenGL_GrBackend, (GrBackendContext)fInterface.get()));
    SkASSERT(fContext);

    // setup rendertargets
    this->setupRenderTarget();
}

void VisualBench::tearDownContext() {
    if (fContext) {
        // We abandon the context in case SkWindow has kept a ref to the surface
        fContext->abandonContext();
        fContext.reset();
        fSurface.reset();
        fInterface.reset();
        this->detach();
    }
}

void VisualBench::setupRenderTarget() {
    if (fContext) {
        fRenderTarget.reset(this->renderTarget(fAttachmentInfo, fInterface, fContext));
    }
}

void VisualBench::draw(SkCanvas* canvas) {
    fModule->draw(canvas);

    // Invalidate the window to force a redraw. Poor man's animation mechanism.
    this->inval(nullptr);
}

void VisualBench::clear(SkCanvas* canvas, SkColor color, int frames) {
    canvas->clear(color);
    for (int i = 0; i < frames - 1; ++i) {
        canvas->flush();
        this->present();
        canvas->clear(color);
    }
}

void VisualBench::onSizeChange() {
    this->setupRenderTarget();
}

bool VisualBench::onHandleChar(SkUnichar unichar) {
    static const auto kEscKey = 27;
    if (kEscKey == unichar) {
        this->closeWindow();
        return true;
    }

    return fModule->onHandleChar(unichar);
}

// Externally declared entry points
void application_init() {
    SkGraphics::Init();
    SkEvent::Init();
}

void application_term() {
    SkEvent::Term();
}

SkOSWindow* create_sk_window(void* hwnd, int argc, char** argv) {
    return new VisualBench(hwnd, argc, argv);
}

<|endoftext|>


<commit_before>// Copyright (c) 2016 Google Inc.
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and/or associated documentation files (the
// "Materials"), to deal in the Materials without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Materials, and to
// permit persons to whom the Materials are furnished to do so, subject to
// the following conditions:
//
// The above copyright notice and this permission notice shall be included
// in all copies or substantial portions of the Materials.
//
// MODIFICATIONS TO THIS FILE MAY MEAN IT NO LONGER ACCURATELY REFLECTS
// KHRONOS STANDARDS. THE UNMODIFIED, NORMATIVE VERSIONS OF KHRONOS
// SPECIFICATIONS AND HEADER INFORMATION ARE LOCATED AT
//    https://www.khronos.org/registry/
//
// THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
// MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.

#include "bin_to_dot.h"

#include <cassert>
#include <iostream>
#include <vector>

#include "assembly_grammar.h"

namespace {

const char* kMergeStyle = "style=dashed";
const char* kContinueStyle = "style=dotted";

// A DotConverter can be used to dump the GraphViz "dot" graph for
// a SPIR-V module.
class DotConverter {
 public:
  DotConverter(std::iostream* out) : out_(*out) {}

  // Emits the graph preamble.
  void Begin() const {
    out_ << "digraph {\n";
    // Emit a simple legend
    out_ << "legend_merge_src [shape=plaintext, label=\"\"];\n"
         << "legend_merge_dest [shape=plaintext, label=\"\"];\n"
         << "legend_merge_src -> legend_merge_dest [label=\" merge\","
         << kMergeStyle << "];\n"
         << "legend_continue_src [shape=plaintext, label=\"\"];\n"
         << "legend_continue_dest [shape=plaintext, label=\"\"];\n"
         << "legend_continue_src -> legend_continue_dest [label=\" continue\","
         << kContinueStyle << "];\n";
  }
  // Emits the graph postamble.
  void End() const { out_ << "}\n"; }

  // Emits the Dot commands for the given instruction.
  spv_result_t HandleInstruction(const spv_parsed_instruction_t& inst);

 private:
  // Ends processing for the current block, emitting its dot code.
  void FlushBlock(const std::vector<uint32_t>& successors);

  // The ID of the current functio, or 0 if outside of a function.
  uint32_t current_function_id_ = 0;

  // The ID of the current basic block, or 0 if outside of a block.
  uint32_t current_block_id_ = 0;

  // Have we completed processing for the entry block to this fuction?
  bool seen_function_entry_block_ = false;

  // The Id of the merge block for this block if it exists, or 0 otherwise.
  uint32_t merge_ = 0;
  // The Id of the continue target block for this block if it exists, or 0
  // otherwise.
  uint32_t continue_target_ = 0;

  // The output stream.
  std::ostream& out_;
};

spv_result_t DotConverter::HandleInstruction(
    const spv_parsed_instruction_t& inst) {
  switch(inst.opcode) {
    case SpvOpFunction:
      current_function_id_ = inst.result_id;
      seen_function_entry_block_ = false;
      break;
    case SpvOpFunctionEnd:
      current_function_id_ = 0;
      break;

    case SpvOpLabel:
      current_block_id_ = inst.result_id;
      break;

    case SpvOpBranch:
      FlushBlock({inst.words[1]});
      break;
    case SpvOpBranchConditional:
      FlushBlock({inst.words[2], inst.words[3]});
      break;
    case SpvOpSwitch: {
      std::vector<uint32_t> successors{inst.words[2]};
      for (size_t i = 3; i < inst.num_operands; i += 2) {
        successors.push_back(inst.words[inst.operands[i].offset]);
      }
      FlushBlock(successors);
    } break;

    case SpvOpKill:
    case SpvOpReturn:
    case SpvOpUnreachable:
    case SpvOpReturnValue:
      FlushBlock({});
      break;

    case SpvOpLoopMerge:
      merge_ = inst.words[1];
      continue_target_ = inst.words[2];
      break;
    case SpvOpSelectionMerge:
      merge_ = inst.words[1];
      break;
    default:
      break;
  }
  return SPV_SUCCESS;
}

void DotConverter::FlushBlock(const std::vector<uint32_t>& successors) {
  out_ << current_block_id_;
  if (!seen_function_entry_block_) {
    out_ << " [label=\"" << current_block_id_ << "\nFn " << current_function_id_
         << " entry\", shape=box]";
  }
  out_ << ";\n";

  for (auto successor : successors) {
    out_ << current_block_id_ << " -> " << successor << ";\n";
  }

  if (merge_) {
    out_ << current_block_id_ << " -> " << merge_ << " [" << kMergeStyle
         << "];\n";
  }
  if (continue_target_) {
    out_ << current_block_id_ << " -> " << continue_target_ << " ["
         << kContinueStyle << "];\n";
  }

  // Reset the book-keeping for a block.
  seen_function_entry_block_ = true;
  merge_ = 0;
  continue_target_ = 0;
}

spv_result_t HandleInstruction(
    void* user_data, const spv_parsed_instruction_t* parsed_instruction) {
  assert(user_data);
  auto converter = static_cast<DotConverter*>(user_data);
  return converter->HandleInstruction(*parsed_instruction);
}

}  // anonymous namespace

spv_result_t BinaryToDot(const spv_const_context context, const uint32_t* words,
                         size_t num_words, std::iostream* out,
                         spv_diagnostic* diagnostic) {
  // Invalid arguments return error codes, but don't necessarily generate
  // diagnostics.  These are programmer errors, not user errors.
  if (!diagnostic) return SPV_ERROR_INVALID_DIAGNOSTIC;
  const libspirv::AssemblyGrammar grammar(context);
  if (!grammar.isValid()) return SPV_ERROR_INVALID_TABLE;

  DotConverter converter(out);
  converter.Begin();
  if (auto error = spvBinaryParse(context, &converter, words, num_words,
                                  nullptr, HandleInstruction, diagnostic)) {
    return error;
  }
  converter.End();

  return SPV_SUCCESS;
}
<commit_msg>Use friendly names for Ids<commit_after>// Copyright (c) 2016 Google Inc.
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and/or associated documentation files (the
// "Materials"), to deal in the Materials without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Materials, and to
// permit persons to whom the Materials are furnished to do so, subject to
// the following conditions:
//
// The above copyright notice and this permission notice shall be included
// in all copies or substantial portions of the Materials.
//
// MODIFICATIONS TO THIS FILE MAY MEAN IT NO LONGER ACCURATELY REFLECTS
// KHRONOS STANDARDS. THE UNMODIFIED, NORMATIVE VERSIONS OF KHRONOS
// SPECIFICATIONS AND HEADER INFORMATION ARE LOCATED AT
//    https://www.khronos.org/registry/
//
// THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
// MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.

#include "bin_to_dot.h"

#include <cassert>
#include <iostream>
#include <vector>

#include "assembly_grammar.h"
#include "name_mapper.h"

namespace {

const char* kMergeStyle = "style=dashed";
const char* kContinueStyle = "style=dotted";

// A DotConverter can be used to dump the GraphViz "dot" graph for
// a SPIR-V module.
class DotConverter {
 public:
  DotConverter(libspirv::NameMapper name_mapper, std::iostream* out)
      : name_mapper_(name_mapper), out_(*out) {}

  // Emits the graph preamble.
  void Begin() const {
    out_ << "digraph {\n";
    // Emit a simple legend
    out_ << "legend_merge_src [shape=plaintext, label=\"\"];\n"
         << "legend_merge_dest [shape=plaintext, label=\"\"];\n"
         << "legend_merge_src -> legend_merge_dest [label=\" merge\","
         << kMergeStyle << "];\n"
         << "legend_continue_src [shape=plaintext, label=\"\"];\n"
         << "legend_continue_dest [shape=plaintext, label=\"\"];\n"
         << "legend_continue_src -> legend_continue_dest [label=\" continue\","
         << kContinueStyle << "];\n";
  }
  // Emits the graph postamble.
  void End() const { out_ << "}\n"; }

  // Emits the Dot commands for the given instruction.
  spv_result_t HandleInstruction(const spv_parsed_instruction_t& inst);

 private:
  // Ends processing for the current block, emitting its dot code.
  void FlushBlock(const std::vector<uint32_t>& successors);

  // The ID of the current functio, or 0 if outside of a function.
  uint32_t current_function_id_ = 0;

  // The ID of the current basic block, or 0 if outside of a block.
  uint32_t current_block_id_ = 0;

  // Have we completed processing for the entry block to this fuction?
  bool seen_function_entry_block_ = false;

  // The Id of the merge block for this block if it exists, or 0 otherwise.
  uint32_t merge_ = 0;
  // The Id of the continue target block for this block if it exists, or 0
  // otherwise.
  uint32_t continue_target_ = 0;

  // An object for mapping Ids to names.
  libspirv::NameMapper name_mapper_;

  // The output stream.
  std::ostream& out_;
};

spv_result_t DotConverter::HandleInstruction(
    const spv_parsed_instruction_t& inst) {
  switch(inst.opcode) {
    case SpvOpFunction:
      current_function_id_ = inst.result_id;
      seen_function_entry_block_ = false;
      break;
    case SpvOpFunctionEnd:
      current_function_id_ = 0;
      break;

    case SpvOpLabel:
      current_block_id_ = inst.result_id;
      break;

    case SpvOpBranch:
      FlushBlock({inst.words[1]});
      break;
    case SpvOpBranchConditional:
      FlushBlock({inst.words[2], inst.words[3]});
      break;
    case SpvOpSwitch: {
      std::vector<uint32_t> successors{inst.words[2]};
      for (size_t i = 3; i < inst.num_operands; i += 2) {
        successors.push_back(inst.words[inst.operands[i].offset]);
      }
      FlushBlock(successors);
    } break;

    case SpvOpKill:
    case SpvOpReturn:
    case SpvOpUnreachable:
    case SpvOpReturnValue:
      FlushBlock({});
      break;

    case SpvOpLoopMerge:
      merge_ = inst.words[1];
      continue_target_ = inst.words[2];
      break;
    case SpvOpSelectionMerge:
      merge_ = inst.words[1];
      break;
    default:
      break;
  }
  return SPV_SUCCESS;
}

void DotConverter::FlushBlock(const std::vector<uint32_t>& successors) {
  out_ << current_block_id_;
  if (!seen_function_entry_block_) {
    out_ << " [label=\"" << name_mapper_(current_block_id_) << "\nFn "
         << name_mapper_(current_function_id_) << " entry\", shape=box];\n";
  } else {
    out_ << " [label=\"" << name_mapper_(current_block_id_) << "\"];\n";
  }

  for (auto successor : successors) {
    out_ << current_block_id_ << " -> " << successor << ";\n";
  }

  if (merge_) {
    out_ << current_block_id_ << " -> " << merge_ << " [" << kMergeStyle
         << "];\n";
  }
  if (continue_target_) {
    out_ << current_block_id_ << " -> " << continue_target_ << " ["
         << kContinueStyle << "];\n";
  }

  // Reset the book-keeping for a block.
  seen_function_entry_block_ = true;
  merge_ = 0;
  continue_target_ = 0;
}

spv_result_t HandleInstruction(
    void* user_data, const spv_parsed_instruction_t* parsed_instruction) {
  assert(user_data);
  auto converter = static_cast<DotConverter*>(user_data);
  return converter->HandleInstruction(*parsed_instruction);
}

}  // anonymous namespace

spv_result_t BinaryToDot(const spv_const_context context, const uint32_t* words,
                         size_t num_words, std::iostream* out,
                         spv_diagnostic* diagnostic) {
  // Invalid arguments return error codes, but don't necessarily generate
  // diagnostics.  These are programmer errors, not user errors.
  if (!diagnostic) return SPV_ERROR_INVALID_DIAGNOSTIC;
  const libspirv::AssemblyGrammar grammar(context);
  if (!grammar.isValid()) return SPV_ERROR_INVALID_TABLE;

  libspirv::FriendlyNameMapper friendly_mapper(context, words, num_words);
  DotConverter converter(friendly_mapper.GetNameMapper(), out);
  converter.Begin();
  if (auto error = spvBinaryParse(context, &converter, words, num_words,
                                  nullptr, HandleInstruction, diagnostic)) {
    return error;
  }
  converter.End();

  return SPV_SUCCESS;
}
<|endoftext|>


<commit_before>#include "Hout.h"
#include "Common.h"
#include <algorithm>
#include <iostream>

#define SNK_VERSION L"v2.1"

//Original WildcardCmp:
// Written by Jack Handy <jakkhandy@hotmail.com>
// http://www.codeproject.com/Articles/1088/Wildcard-string-compare-globbing
//Changes made:
// Uses wchar_t instead of char
// Match is case-insensitive
// Matches '\' (Windows path delimiter) in string only with '\' in wildcard ignoring '?' and '*'
bool WildcardCmp(const wchar_t* wild, const wchar_t* string)
{
	const wchar_t *cp=NULL, *mp=NULL;

	while (*string&&*wild!=L'*') {
		if (towlower(*wild)!=towlower(*string)&&(*wild!=L'?'||*string==L'\\'))
			return false;
		wild++;
		string++;
	}

	while (*string) {
		if (*wild==L'*') {
			mp=++wild;
			cp=string;
		} else if (towlower(*wild)==towlower(*string)||(*wild==L'?'&&*string!=L'\\')) {
			wild++;
			string++;
		} else if (*cp==L'\\') {
			return false;
		} else {
			wild=mp;
			string=cp+++1;
		}
	}

	while (*wild==L'*')
		wild++;

	return !*wild;
}

bool MultiWildcardCmp(const wchar_t* wild, const wchar_t* string, const wchar_t* del)
{
	wchar_t buffer[wcslen(wild)+1];
	wcscpy(buffer, wild);

	for (wchar_t* token=wcstok(buffer, del); token; token=wcstok(NULL, del))
		if (WildcardCmp(token, string)) return true;

	return false;
}

void MakeRulesFromArgv(int argc, wchar_t** argv, std::stack<std::wstring> &rules, int skip_argc)
{
	wchar_t *head, *token;
	while (argc-->skip_argc) switch (*argv[argc]) {
		case L'/':
			if ((token=wcschr(argv[argc], L'=')))
				*token++=L'\0';

			rules.push((head=wcstok(argv[argc], L":")));

			if (token)
				rules.push(std::wstring(L"=")+token);

			while ((token=wcstok(NULL, L":")))
				rules.push(head+std::wstring(L":")+token);

			continue;
		case L'+':
		case L'-':
			head=argv[argc];

			while (*++argv[argc]!=L'\0')
				rules.push({*head, *argv[argc]});

			continue;
		case L'#':
		case L'\0':
			continue;
		default:
			std::wcerr<<L"Warning: unknown input: "<<argv[argc]<<std::endl;
	}

#if DEBUG>=3
	std::stack<std::wstring> _rules=rules;
	std::wcerr<<L"" __FILE__ ":MakeRulesFromArgv:"<<__LINE__<<L": Rules (unfolding stack)..."<<std::endl;
	while (!_rules.empty()) {
		std::wcerr<<L"\t\t"<<_rules.top()<<std::endl;
		_rules.pop();
	}
#endif
}

bool PidListCmp(const wchar_t* pid_list, std::vector<ULONG_PTR> *uptr_array, const ULONG_PTR *pid)
{
	std::vector<ULONG_PTR> local_uptr_array;

	if (!uptr_array)
		uptr_array=&local_uptr_array;

	if (pid_list) {
		wchar_t buffer[wcslen(pid_list)+1];
		wcscpy(buffer, pid_list);

		ULONG_PTR dw_pri, dw_sec, *pdw_cur=&dw_pri;
		wchar_t* rtok;
		bool cnv_err=false;

		for (wchar_t* token=wcstok(buffer, L",;"); token; token=wcstok(NULL, L",;")) {
			for(;;) {
				if (!*token||*token==L'-'||*token==L'+'||*token==L' ') {
					cnv_err=true;
					break;
				}
				*pdw_cur=wcstoul(token, &rtok, 0);
				if ((*pdw_cur==0&&rtok==token)||(*pdw_cur==ULONG_MAX&&errno==ERANGE)||(*rtok&&(*rtok!=L'-'||pdw_cur!=&dw_pri))) {
					cnv_err=true;
					break;
				}
				if (*rtok) {
					token=rtok+1;
					pdw_cur=&dw_sec;
				} else {
					if (pdw_cur==&dw_sec) {
						for (DWORD dw_i=dw_pri; uptr_array->push_back(dw_i), dw_i!=dw_sec; dw_pri<=dw_sec?dw_i++:dw_i--);
						pdw_cur=&dw_pri;
					} else
						uptr_array->push_back(dw_pri);
					break;
				}
			}
			if (cnv_err) {
				std::wcerr<<L"Warning: PID list \""<<pid_list<<L"\" is malformed, error in token \""<<token<<L"\"!"<<std::endl;
				uptr_array->clear();
				return false;
			}
		}

		//All this hassle with sorting, erasing and following binary_search is to speed up performance with big PID arrays
		//Because intended use for this function is mass PID killing or killing single PIDs from vaguely known range
		std::sort(uptr_array->begin(), uptr_array->end());
		uptr_array->erase(std::unique(uptr_array->begin(), uptr_array->end()), uptr_array->end());
	}

	if (pid)
		return std::binary_search(uptr_array->begin(), uptr_array->end(), *pid);
	else
		return true;
}

HANDLE OpenProcessWrapper(DWORD dwProcessId, DWORD &dwDesiredAccess, DWORD dwMandatory)
{
	//If OpenProcess with provided dwDesiredAccess succeeded - return resulting hProcess
	if (HANDLE hProcess=OpenProcess(dwDesiredAccess, FALSE, dwProcessId))
		return hProcess;

	//If PROCESS_ALL_ACCESS is required - fail
	if (dwDesiredAccess==PROCESS_ALL_ACCESS) {
		dwDesiredAccess=0;
		return NULL;
	//If dwDesiredAccess contains PROCESS_QUERY_INFORMATION - change it to PROCESS_QUERY_LIMITED_INFORMATION and try again
	} else if (dwDesiredAccess&PROCESS_QUERY_INFORMATION&~dwMandatory) {
		dwDesiredAccess&=~PROCESS_QUERY_INFORMATION;
		dwDesiredAccess|=PROCESS_QUERY_LIMITED_INFORMATION;
	//If dwDesiredAccess contains PROCESS_VM_READ - remove it and try again
	//Additionally change PROCESS_QUERY_LIMITED_INFORMATION to PROCESS_QUERY_INFORMATION if present
	} else if (dwDesiredAccess&PROCESS_VM_READ&~dwMandatory) {
		if (dwDesiredAccess&PROCESS_QUERY_LIMITED_INFORMATION&~dwMandatory) {
			dwDesiredAccess&=~PROCESS_QUERY_LIMITED_INFORMATION;
			dwDesiredAccess|=PROCESS_QUERY_INFORMATION;
		}
		dwDesiredAccess&=~PROCESS_VM_READ;
	//If no PROCESS_QUERY_INFORMATION or PROCESS_VM_READ flags was set - fail
	} else {
		dwDesiredAccess=0;
		return NULL;
	}

	return OpenProcessWrapper(dwProcessId, dwDesiredAccess, dwMandatory);
}

bool CheckIfFileExists(const wchar_t* fpath)
{
	if (!fpath||fpath[0]==L'\0'||(				//We don't need NULL or empty paths
		(fpath[0]!=L'\\'||fpath[1]!=L'\\')&&	//We interested in UNC and...
		(fpath[1]!=L':'||fpath[2]!=L'\\')		//...absolute paths
		))
		return false;
	//Ballad about full vs relative paths
	//CheckIfFileExists needs full path: i.e. path which can't be misinterpreted - it should stay the same regardless of CWD, CD or PATH variable
	//It needs it because it is hevaily used in scenarios where real path should be reconstructed from some nonsense
	//And some of this nonsense may look like relative path and be falsely reported as something that might be real
	//In the end, there is no relative-path based algorithms in SnK - only name and full-path based
	//Here MS have an official paper about which paths are considred relative/full on Windows: https://msdn.microsoft.com/library/windows/desktop/aa365247.aspx#paths
	//They also have PathIsRelative funcion in shlwapi.dll (4.71+)
	//In ReactOS/Wine PathIsRelative is reversed to the following algorithm (original Win NT algorithm is actually the same):
	//If it starts from slash ('\') or second character is colon (':') then return false, otherwise return true
	//And this (Microsoft's own!) algorithm contradicts to the official paper mentioned earlier: paths like "C:tmp.txt" (it's a valid path!) will be erroneously treated like full
	//More idiocy: paths like "\blah\blah.txt" are treated as full in official paper because, well, they are actually not relative to the CURRENT DIRECTORY
	//But they are still relative (to current drive) though not in MS terms - MS defines "relative" strictly as "relative to current directory"
	//So here is refined algorithm for CheckIfFileExists to check if file path is absolute in strict NT kernel terms: RtlPathTypeUncAbsolute or RtlPathTypeDriveAbsolute (see RtlDetermineDosPathNameType_U):
	//It starts from double slash ("\\") or it's second-to-third chracters are colon with slash (":\") - it's assumed that supplied path has nothing to do with device paths

	DWORD dwAttrib=GetFileAttributes(fpath);	//Works with UNC paths (ok), relative paths (fixed by code above), affected by Wow64FsRedirection (need some external code to turn this off), can fail because of security restrictions (whatever)
	if (dwAttrib!=INVALID_FILE_ATTRIBUTES&&!(dwAttrib&FILE_ATTRIBUTE_DIRECTORY))	//Don't need directories
		return true;
	else
		return false;
}

void PrintUsage()
{
#ifndef HIDDEN
	Hout::Separator(L"Usage: SnK [settings_block|swith[:parametres][=argument]] ...");
	Hout::EmptyLine();
	Hout::Separator(L"This is a usage quick reference. Please check README.TXT for more information.");
	Hout::EmptyLine();
	Hout::Separator(L"Switches:");
	Hout::Separator(L"/hlp", 2);
	Hout::Paragraph(L"Print this help and exit.",
					4);
	Hout::Separator(L"/ver", 2);
	Hout::Paragraph(L"Print version information and exit.",
					4);
	Hout::Separator(L"/bpp", 2);
	Hout::Paragraph(L"Make standart Windows 'informational beep' and continue execution.",
					4);
	Hout::Separator(L"/sec", 2);
	Hout::Paragraph(L"Secured execution. Will exit program if there is another instance already running that has executed this switch.",
					4);
	Hout::Separator(L"/blk(:clear|[:full]=WCARDS)", 2);
	Hout::Paragraph(L"Add processes which name matches one of wildcars (case-insensitive, with globbing) to blacklist or clear blacklist.",
					4);
	Hout::Separator(L"/cpu", 2);
	Hout::Paragraph(L"Kill process with highest cpu load.",
					4);
	Hout::Separator(L"/pth[:full]=WCARDS", 2);
	Hout::Paragraph(L"Kill process with highest cpu load which name matches one of wildcars (case-insensitive, with globbing).",
					4);
	Hout::Separator(L"/mod[:full]=WCARDS", 2);
	Hout::Paragraph(L"Kill process with highest cpu load that has module which name matches one of wildcars (case-insensitive, with globbing).",
					4);
	Hout::Separator(L"/pid=PIDS", 2);
	Hout::Paragraph(L"Kill process with highest cpu load which PID belongs to PID array.",
					4);
	Hout::Separator(L"/d3d[:simple]", 2);
	Hout::Paragraph(L"Kill process with highest cpu load that uses DirectX (Direct3D).",
					4);
	Hout::Separator(L"/ogl[:simple]", 2);
	Hout::Paragraph(L"Kill process with highest cpu load that uses OpenGL.",
					4);
	Hout::Separator(L"/gld[:simple]", 2);
	Hout::Paragraph(L"Kill process with highest cpu load that uses Glide (3Dfx).",
					4);
	Hout::Separator(L"/inr[:manual|:vista]", 2);
	Hout::Paragraph(L"Kill process with highest cpu load that doesn't respond (Is Not Responding).",
					4);
	Hout::Separator(L"/fsc[:anywnd][:primary]", 2);
	Hout::Paragraph(L"Kill process with highest cpu load that is running in fullscreen.",
					4);
	Hout::Separator(L"/fgd", 2);
	Hout::Paragraph(L"Kill process which window is in foreground.",
					4);
	Hout::EmptyLine();
	Hout::Separator(L"Settings:");
	Hout::Separator(L"+t|-t", 2);
	Hout::Paragraph(L"Will turn test mode on/off.",
					4);
	Hout::Separator(L"+v|-v", 2);
	Hout::Paragraph(L"Will turn verbose mode on/off.",
					4);
	Hout::Separator(L"+a|-a", 2);
	Hout::Paragraph(L" Will turn 'query all processes' mode on/off.",
					4);
	Hout::Separator(L"+l|-l", 2);
	Hout::Paragraph(L" Will turn 'loop' mode on/off.",
					4);
	Hout::Separator(L"+i|-i", 2);
	Hout::Paragraph(L" Will turn 'ignore' mode on/off.",
					4);
#else
	Hout::Separator(L"Usage: SnKh [settings_block|swith[:parametres][=argument]] ...");
	Hout::EmptyLine();
	Hout::Separator(L"Please check README.TXT for more information.");
#endif
}

void PrintVersion()
{
#ifndef HIDDEN
#ifdef _WIN64
	Hout::Separator(L"Search and Kill (x64) " SNK_VERSION);
#else
	Hout::Separator(L"Search and Kill " SNK_VERSION);
#endif
	Hout::EmptyLine();
	Hout::Separator(L"Run with /hlp switch for usage information");
#else
#ifdef _WIN64
	Hout::Separator(L"Search and Kill (x64 windowless) " SNK_VERSION);
#else
	Hout::Separator(L"Search and Kill (windowless) " SNK_VERSION);
#endif
	Hout::EmptyLine();
	Hout::Separator(L"Please check README.TXT for more information");
#endif
	Hout::EmptyLine();
	Hout::Separator(L"Copyright (c) 2012-2016 Lcferrum");
	Hout::Separator(L"Licensed under BSD license - see LICENSE.TXT file for details");
}
<commit_msg>That looks better<commit_after>#include "Hout.h"
#include "Common.h"
#include <algorithm>
#include <iostream>

#define SNK_VERSION L"v2.1"

//Original WildcardCmp:
// Written by Jack Handy <jakkhandy@hotmail.com>
// http://www.codeproject.com/Articles/1088/Wildcard-string-compare-globbing
//Changes made:
// Uses wchar_t instead of char
// Match is case-insensitive
// Matches '\' (Windows path delimiter) in string only with '\' in wildcard ignoring '?' and '*'
bool WildcardCmp(const wchar_t* wild, const wchar_t* string)
{
	const wchar_t *cp=NULL, *mp=NULL;

	while (*string&&*wild!=L'*') {
		if (towlower(*wild)!=towlower(*string)&&(*wild!=L'?'||*string==L'\\'))
			return false;
		wild++;
		string++;
	}

	while (*string) {
		if (*wild==L'*') {
			mp=++wild;
			cp=string;
		} else if (towlower(*wild)==towlower(*string)||(*wild==L'?'&&*string!=L'\\')) {
			wild++;
			string++;
		} else if (*cp==L'\\') {
			return false;
		} else {
			wild=mp;
			string=++cp;
		}
	}

	while (*wild==L'*')
		wild++;

	return !*wild;
}

bool MultiWildcardCmp(const wchar_t* wild, const wchar_t* string, const wchar_t* del)
{
	wchar_t buffer[wcslen(wild)+1];
	wcscpy(buffer, wild);

	for (wchar_t* token=wcstok(buffer, del); token; token=wcstok(NULL, del))
		if (WildcardCmp(token, string)) return true;

	return false;
}

void MakeRulesFromArgv(int argc, wchar_t** argv, std::stack<std::wstring> &rules, int skip_argc)
{
	wchar_t *head, *token;
	while (argc-->skip_argc) switch (*argv[argc]) {
		case L'/':
			if ((token=wcschr(argv[argc], L'=')))
				*token++=L'\0';

			rules.push((head=wcstok(argv[argc], L":")));

			if (token)
				rules.push(std::wstring(L"=")+token);

			while ((token=wcstok(NULL, L":")))
				rules.push(head+std::wstring(L":")+token);

			continue;
		case L'+':
		case L'-':
			head=argv[argc];

			while (*++argv[argc]!=L'\0')
				rules.push({*head, *argv[argc]});

			continue;
		case L'#':
		case L'\0':
			continue;
		default:
			std::wcerr<<L"Warning: unknown input: "<<argv[argc]<<std::endl;
	}

#if DEBUG>=3
	std::stack<std::wstring> _rules=rules;
	std::wcerr<<L"" __FILE__ ":MakeRulesFromArgv:"<<__LINE__<<L": Rules (unfolding stack)..."<<std::endl;
	while (!_rules.empty()) {
		std::wcerr<<L"\t\t"<<_rules.top()<<std::endl;
		_rules.pop();
	}
#endif
}

bool PidListCmp(const wchar_t* pid_list, std::vector<ULONG_PTR> *uptr_array, const ULONG_PTR *pid)
{
	std::vector<ULONG_PTR> local_uptr_array;

	if (!uptr_array)
		uptr_array=&local_uptr_array;

	if (pid_list) {
		wchar_t buffer[wcslen(pid_list)+1];
		wcscpy(buffer, pid_list);

		ULONG_PTR dw_pri, dw_sec, *pdw_cur=&dw_pri;
		wchar_t* rtok;
		bool cnv_err=false;

		for (wchar_t* token=wcstok(buffer, L",;"); token; token=wcstok(NULL, L",;")) {
			for(;;) {
				if (!*token||*token==L'-'||*token==L'+'||*token==L' ') {
					cnv_err=true;
					break;
				}
				*pdw_cur=wcstoul(token, &rtok, 0);
				if ((*pdw_cur==0&&rtok==token)||(*pdw_cur==ULONG_MAX&&errno==ERANGE)||(*rtok&&(*rtok!=L'-'||pdw_cur!=&dw_pri))) {
					cnv_err=true;
					break;
				}
				if (*rtok) {
					token=rtok+1;
					pdw_cur=&dw_sec;
				} else {
					if (pdw_cur==&dw_sec) {
						for (DWORD dw_i=dw_pri; uptr_array->push_back(dw_i), dw_i!=dw_sec; dw_pri<=dw_sec?dw_i++:dw_i--);
						pdw_cur=&dw_pri;
					} else
						uptr_array->push_back(dw_pri);
					break;
				}
			}
			if (cnv_err) {
				std::wcerr<<L"Warning: PID list \""<<pid_list<<L"\" is malformed, error in token \""<<token<<L"\"!"<<std::endl;
				uptr_array->clear();
				return false;
			}
		}

		//All this hassle with sorting, erasing and following binary_search is to speed up performance with big PID arrays
		//Because intended use for this function is mass PID killing or killing single PIDs from vaguely known range
		std::sort(uptr_array->begin(), uptr_array->end());
		uptr_array->erase(std::unique(uptr_array->begin(), uptr_array->end()), uptr_array->end());
	}

	if (pid)
		return std::binary_search(uptr_array->begin(), uptr_array->end(), *pid);
	else
		return true;
}

HANDLE OpenProcessWrapper(DWORD dwProcessId, DWORD &dwDesiredAccess, DWORD dwMandatory)
{
	//If OpenProcess with provided dwDesiredAccess succeeded - return resulting hProcess
	if (HANDLE hProcess=OpenProcess(dwDesiredAccess, FALSE, dwProcessId))
		return hProcess;

	//If PROCESS_ALL_ACCESS is required - fail
	if (dwDesiredAccess==PROCESS_ALL_ACCESS) {
		dwDesiredAccess=0;
		return NULL;
	//If dwDesiredAccess contains PROCESS_QUERY_INFORMATION - change it to PROCESS_QUERY_LIMITED_INFORMATION and try again
	} else if (dwDesiredAccess&PROCESS_QUERY_INFORMATION&~dwMandatory) {
		dwDesiredAccess&=~PROCESS_QUERY_INFORMATION;
		dwDesiredAccess|=PROCESS_QUERY_LIMITED_INFORMATION;
	//If dwDesiredAccess contains PROCESS_VM_READ - remove it and try again
	//Additionally change PROCESS_QUERY_LIMITED_INFORMATION to PROCESS_QUERY_INFORMATION if present
	} else if (dwDesiredAccess&PROCESS_VM_READ&~dwMandatory) {
		if (dwDesiredAccess&PROCESS_QUERY_LIMITED_INFORMATION&~dwMandatory) {
			dwDesiredAccess&=~PROCESS_QUERY_LIMITED_INFORMATION;
			dwDesiredAccess|=PROCESS_QUERY_INFORMATION;
		}
		dwDesiredAccess&=~PROCESS_VM_READ;
	//If no PROCESS_QUERY_INFORMATION or PROCESS_VM_READ flags was set - fail
	} else {
		dwDesiredAccess=0;
		return NULL;
	}

	return OpenProcessWrapper(dwProcessId, dwDesiredAccess, dwMandatory);
}

bool CheckIfFileExists(const wchar_t* fpath)
{
	if (!fpath||fpath[0]==L'\0'||(				//We don't need NULL or empty paths
		(fpath[0]!=L'\\'||fpath[1]!=L'\\')&&	//We interested in UNC and...
		(fpath[1]!=L':'||fpath[2]!=L'\\')		//...absolute paths
		))
		return false;
	//Ballad about full vs relative paths
	//CheckIfFileExists needs full path: i.e. path which can't be misinterpreted - it should stay the same regardless of CWD, CD or PATH variable
	//It needs it because it is hevaily used in scenarios where real path should be reconstructed from some nonsense
	//And some of this nonsense may look like relative path and be falsely reported as something that might be real
	//In the end, there is no relative-path based algorithms in SnK - only name and full-path based
	//Here MS have an official paper about which paths are considred relative/full on Windows: https://msdn.microsoft.com/library/windows/desktop/aa365247.aspx#paths
	//They also have PathIsRelative funcion in shlwapi.dll (4.71+)
	//In ReactOS/Wine PathIsRelative is reversed to the following algorithm (original Win NT algorithm is actually the same):
	//If it starts from slash ('\') or second character is colon (':') then return false, otherwise return true
	//And this (Microsoft's own!) algorithm contradicts to the official paper mentioned earlier: paths like "C:tmp.txt" (it's a valid path!) will be erroneously treated like full
	//More idiocy: paths like "\blah\blah.txt" are treated as full in official paper because, well, they are actually not relative to the CURRENT DIRECTORY
	//But they are still relative (to current drive) though not in MS terms - MS defines "relative" strictly as "relative to current directory"
	//So here is refined algorithm for CheckIfFileExists to check if file path is absolute in strict NT kernel terms: RtlPathTypeUncAbsolute or RtlPathTypeDriveAbsolute (see RtlDetermineDosPathNameType_U):
	//It starts from double slash ("\\") or it's second-to-third chracters are colon with slash (":\") - it's assumed that supplied path has nothing to do with device paths

	DWORD dwAttrib=GetFileAttributes(fpath);	//Works with UNC paths (ok), relative paths (fixed by code above), affected by Wow64FsRedirection (need some external code to turn this off), can fail because of security restrictions (whatever)
	if (dwAttrib!=INVALID_FILE_ATTRIBUTES&&!(dwAttrib&FILE_ATTRIBUTE_DIRECTORY))	//Don't need directories
		return true;
	else
		return false;
}

void PrintUsage()
{
#ifndef HIDDEN
	Hout::Separator(L"Usage: SnK [settings_block|swith[:parametres][=argument]] ...");
	Hout::EmptyLine();
	Hout::Separator(L"This is a usage quick reference. Please check README.TXT for more information.");
	Hout::EmptyLine();
	Hout::Separator(L"Switches:");
	Hout::Separator(L"/hlp", 2);
	Hout::Paragraph(L"Print this help and exit.",
					4);
	Hout::Separator(L"/ver", 2);
	Hout::Paragraph(L"Print version information and exit.",
					4);
	Hout::Separator(L"/bpp", 2);
	Hout::Paragraph(L"Make standart Windows 'informational beep' and continue execution.",
					4);
	Hout::Separator(L"/sec", 2);
	Hout::Paragraph(L"Secured execution. Will exit program if there is another instance already running that has executed this switch.",
					4);
	Hout::Separator(L"/blk(:clear|[:full]=WCARDS)", 2);
	Hout::Paragraph(L"Add processes which name matches one of wildcars (case-insensitive, with globbing) to blacklist or clear blacklist.",
					4);
	Hout::Separator(L"/cpu", 2);
	Hout::Paragraph(L"Kill process with highest cpu load.",
					4);
	Hout::Separator(L"/pth[:full]=WCARDS", 2);
	Hout::Paragraph(L"Kill process with highest cpu load which name matches one of wildcars (case-insensitive, with globbing).",
					4);
	Hout::Separator(L"/mod[:full]=WCARDS", 2);
	Hout::Paragraph(L"Kill process with highest cpu load that has module which name matches one of wildcars (case-insensitive, with globbing).",
					4);
	Hout::Separator(L"/pid=PIDS", 2);
	Hout::Paragraph(L"Kill process with highest cpu load which PID belongs to PID array.",
					4);
	Hout::Separator(L"/d3d[:simple]", 2);
	Hout::Paragraph(L"Kill process with highest cpu load that uses DirectX (Direct3D).",
					4);
	Hout::Separator(L"/ogl[:simple]", 2);
	Hout::Paragraph(L"Kill process with highest cpu load that uses OpenGL.",
					4);
	Hout::Separator(L"/gld[:simple]", 2);
	Hout::Paragraph(L"Kill process with highest cpu load that uses Glide (3Dfx).",
					4);
	Hout::Separator(L"/inr[:manual|:vista]", 2);
	Hout::Paragraph(L"Kill process with highest cpu load that doesn't respond (Is Not Responding).",
					4);
	Hout::Separator(L"/fsc[:anywnd][:primary]", 2);
	Hout::Paragraph(L"Kill process with highest cpu load that is running in fullscreen.",
					4);
	Hout::Separator(L"/fgd", 2);
	Hout::Paragraph(L"Kill process which window is in foreground.",
					4);
	Hout::EmptyLine();
	Hout::Separator(L"Settings:");
	Hout::Separator(L"+t|-t", 2);
	Hout::Paragraph(L"Will turn test mode on/off.",
					4);
	Hout::Separator(L"+v|-v", 2);
	Hout::Paragraph(L"Will turn verbose mode on/off.",
					4);
	Hout::Separator(L"+a|-a", 2);
	Hout::Paragraph(L" Will turn 'query all processes' mode on/off.",
					4);
	Hout::Separator(L"+l|-l", 2);
	Hout::Paragraph(L" Will turn 'loop' mode on/off.",
					4);
	Hout::Separator(L"+i|-i", 2);
	Hout::Paragraph(L" Will turn 'ignore' mode on/off.",
					4);
#else
	Hout::Separator(L"Usage: SnKh [settings_block|swith[:parametres][=argument]] ...");
	Hout::EmptyLine();
	Hout::Separator(L"Please check README.TXT for more information.");
#endif
}

void PrintVersion()
{
#ifndef HIDDEN
#ifdef _WIN64
	Hout::Separator(L"Search and Kill (x64) " SNK_VERSION);
#else
	Hout::Separator(L"Search and Kill " SNK_VERSION);
#endif
	Hout::EmptyLine();
	Hout::Separator(L"Run with /hlp switch for usage information");
#else
#ifdef _WIN64
	Hout::Separator(L"Search and Kill (x64 windowless) " SNK_VERSION);
#else
	Hout::Separator(L"Search and Kill (windowless) " SNK_VERSION);
#endif
	Hout::EmptyLine();
	Hout::Separator(L"Please check README.TXT for more information");
#endif
	Hout::EmptyLine();
	Hout::Separator(L"Copyright (c) 2012-2016 Lcferrum");
	Hout::Separator(L"Licensed under BSD license - see LICENSE.TXT file for details");
}
<|endoftext|>