<commit_before>/*
 * Copyright (c) 2008, Willow Garage, Inc.
 * 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 Willow Garage, Inc. nor the names of its
 *       contributors may be used to endorse or promote products derived from
 *       this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 */

#include "robot.h"
#include "robot_link.h"
#include "common.h"
#include "properties/property.h"
#include "properties/property_manager.h"
#include "visualization_manager.h"

#include "ogre_tools/object.h"
#include "ogre_tools/shape.h"
#include "ogre_tools/axes.h"

#include <tf/transform_listener.h>
#include <planning_models/kinematic.h>

#include <OGRE/OgreSceneNode.h>
#include <OGRE/OgreSceneManager.h>
#include <OGRE/OgreRibbonTrail.h>
#include <OGRE/OgreEntity.h>
#include <OGRE/OgreMaterialManager.h>
#include <OGRE/OgreMaterial.h>

#include <ros/console.h>

namespace rviz
{

Robot::Robot( VisualizationManager* manager, const std::string& name )
: ogre_tools::Object( manager->getSceneManager() )
, visual_visible_( true )
, collision_visible_( false )
, vis_manager_(manager)
, property_manager_(NULL)
, user_data_( NULL )
, name_( name )
{
  root_visual_node_ = scene_manager_->getRootSceneNode()->createChildSceneNode();
  root_collision_node_ = scene_manager_->getRootSceneNode()->createChildSceneNode();
  root_other_node_ = scene_manager_->getRootSceneNode()->createChildSceneNode();

  setVisualVisible( visual_visible_ );
  setCollisionVisible( collision_visible_ );
  setAlpha(1.0f);
}

Robot::~Robot()
{
  clear();

  scene_manager_->destroySceneNode( root_visual_node_->getName() );
  scene_manager_->destroySceneNode( root_collision_node_->getName() );
  scene_manager_->destroySceneNode( root_other_node_->getName() );
}

void Robot::setVisible( bool visible )
{
  if ( visible )
  {
    root_visual_node_->setVisible( visual_visible_ );
    root_collision_node_->setVisible( collision_visible_ );
  }
  else
  {
    root_visual_node_->setVisible( false );
    root_collision_node_->setVisible( false );
  }
}

void Robot::setVisualVisible( bool visible )
{
  visual_visible_ = visible;
  root_visual_node_->setVisible( visible );
}

void Robot::setCollisionVisible( bool visible )
{
  collision_visible_ = visible;
  root_collision_node_->setVisible( visible );
}

bool Robot::isVisualVisible()
{
  return visual_visible_;
}

bool Robot::isCollisionVisible()
{
  return collision_visible_;
}

void Robot::setAlpha(float a)
{
  alpha_ = a;

  M_NameToLink::iterator it = links_.begin();
  M_NameToLink::iterator end = links_.end();
  for ( ; it != end; ++it )
  {
    RobotLink* info = it->second;

    info->setAlpha(alpha_);
  }
}

void Robot::setUserData( const Ogre::Any& user_data )
{
  user_data_ = user_data;
}

void Robot::clear()
{
  M_NameToLink::iterator link_it = links_.begin();
  M_NameToLink::iterator link_end = links_.end();
  for ( ; link_it != link_end; ++link_it )
  {
    RobotLink* info = link_it->second;
    delete info;
  }

  if ( property_manager_ )
  {
    property_manager_->deleteByUserData( this );
  }

  links_category_.reset();
  links_.clear();
  root_visual_node_->removeAndDestroyAllChildren();
  root_collision_node_->removeAndDestroyAllChildren();
}

void Robot::setPropertyManager( PropertyManager* property_manager, const CategoryPropertyWPtr& parent )
{
  ROS_ASSERT( property_manager );
  ROS_ASSERT( parent.lock() );

  property_manager_ = property_manager;
  parent_property_ = parent;

  if ( !links_.empty() )
  {
    M_NameToLink::iterator link_it = links_.begin();
    M_NameToLink::iterator link_end = links_.end();
    for ( ; link_it != link_end; ++link_it )
    {
      RobotLink* info = link_it->second;

      info->createProperties();
    }
  }
}

void Robot::load( mechanism::Robot &descr, bool visual, bool collision )
{
  clear();

  if ( property_manager_ )
  {
    ROS_ASSERT(!links_category_.lock());
    links_category_ = property_manager_->createCategory( "Links", name_, parent_property_, this );
  }

  for (size_t i = 0; i < descr.links_.size(); ++i)
  {
    mechanism::Link &link = *descr.links_[i];

    RobotLink* link_info = new RobotLink(this, vis_manager_);
    link_info->load(descr, link, visual, collision);

    bool inserted = links_.insert( std::make_pair( link_info->getName(), link_info ) ).second;
    ROS_ASSERT( inserted );

    joint_to_link_[ link_info->getJointName() ] = link_info->getName();

    link_info->setAlpha(alpha_);
  }

  CategoryPropertyPtr cat_prop = links_category_.lock();
  cat_prop->collapse();

  setVisualVisible(isVisualVisible());
  setCollisionVisible(isCollisionVisible());
}

RobotLink* Robot::getLink( const std::string& name )
{
  M_NameToLink::iterator it = links_.find( name );
  if ( it == links_.end() )
  {
    ROS_WARN( "Link [%s] does not exist", name.c_str() );
    return NULL;
  }

  return it->second;
}

void Robot::update( tf::TransformListener* tf, const std::string& target_frame )
{
  typedef std::vector<std::string> V_string;
  V_string frames;
  tf->getFrameStrings( frames );

  M_NameToLink::iterator link_it = links_.begin();
  M_NameToLink::iterator link_end = links_.end();
  for ( ; link_it != link_end; ++link_it )
  {
    const std::string& name = link_it->first;
    RobotLink* info = link_it->second;

    if ( std::find( frames.begin(), frames.end(), name ) == frames.end() )
    {
      ROS_ERROR( "Frame '%s' does not exist in the TF frame list", name.c_str() );

      info->setToErrorMaterial();
      continue;
    }

    info->setToNormalMaterial();

    tf::Stamped<tf::Pose> pose( btTransform( btQuaternion( 0, 0, 0 ), btVector3( 0, 0, 0 ) ), ros::Time(), name );

    if (tf->canTransform(target_frame, name, ros::Time()))
    {
      try
      {
        tf->transformPose( target_frame, pose, pose );
      }
      catch(tf::TransformException& e)
      {
        ROS_ERROR( "Error transforming from frame '%s' to frame '%s'\n", name.c_str(), target_frame.c_str() );
      }
    }

    //printf( "Link %s:\npose: %6f %6f %6f,\t%6f %6f %6f\n", name.c_str(), pose.data_.getOrigin().x(), pose.data_.getOrigin().y(), pose.data_.getOrigin().z(), pose.data_.getOrigin().y()aw, pose.pitch, pose.roll );

    Ogre::Vector3 position( pose.getOrigin().x(), pose.getOrigin().y(), pose.getOrigin().z() );
    robotToOgre( position );

    btScalar yaw, pitch, roll;
    pose.getBasis().getEulerZYX( yaw, pitch, roll );

    Ogre::Matrix3 orientation( ogreMatrixFromRobotEulers( yaw, pitch, roll ) );

    // Collision/visual transforms are the same in this case
    info->setTransforms( position, orientation, position, orientation, true );
  }
}

void Robot::update( planning_models::KinematicModel* kinematic_model, const std::string& target_frame )
{
  M_NameToLink::iterator link_it = links_.begin();
  M_NameToLink::iterator link_end = links_.end();
  for ( ; link_it != link_end; ++link_it )
  {
    const std::string& name = link_it->first;
    RobotLink* info = link_it->second;

    planning_models::KinematicModel::Link* link = kinematic_model->getLink( name );

    if ( !link )
    {
      continue;
    }

    btVector3 robot_visual_position = link->globalTransFwd.getOrigin();
    btQuaternion robot_visual_orientation = link->globalTransFwd.getRotation();
    Ogre::Vector3 visual_position( robot_visual_position.getX(), robot_visual_position.getY(), robot_visual_position.getZ() );
    Ogre::Quaternion visual_orientation( robot_visual_orientation.getW(), robot_visual_orientation.getX(), robot_visual_orientation.getY(), robot_visual_orientation.getZ() );
    robotToOgre( visual_position );
    robotToOgre( visual_orientation );

    btVector3 robot_collision_position = link->globalTrans.getOrigin();
    btQuaternion robot_collision_orientation = link->globalTrans.getRotation();
    Ogre::Vector3 collision_position( robot_collision_position.getX(), robot_collision_position.getY(), robot_collision_position.getZ() );
    Ogre::Quaternion collision_orientation( robot_collision_orientation.getW(), robot_collision_orientation.getX(), robot_collision_orientation.getY(), robot_collision_orientation.getZ() );
    robotToOgre( collision_position );
    robotToOgre( collision_orientation );

    info->setTransforms( visual_position, visual_orientation, collision_position, collision_orientation, false );
  }
}

void Robot::update( const robot_msgs::MechanismState& state )
{
  std::vector<robot_msgs::JointState>::const_iterator it = state.joint_states.begin();
  std::vector<robot_msgs::JointState>::const_iterator end = state.joint_states.end();
  for ( ; it != end; ++it )
  {
    const robot_msgs::JointState& joint_state = *it;
    M_string::iterator str_it = joint_to_link_.find( joint_state.name );
    if ( str_it != joint_to_link_.end() )
    {
      RobotLink* info = getLink( str_it->second );

      info->setJointState(joint_state);
    }
  }
}

void Robot::setPosition( const Ogre::Vector3& position )
{
  root_visual_node_->setPosition( position );
  root_collision_node_->setPosition( position );
}

void Robot::setOrientation( const Ogre::Quaternion& orientation )
{
  root_visual_node_->setOrientation( orientation );
  root_collision_node_->setOrientation( orientation );
}

void Robot::setScale( const Ogre::Vector3& scale )
{
  root_visual_node_->setScale( scale );
  root_collision_node_->setScale( scale );
}

const Ogre::Vector3& Robot::getPosition()
{
  return root_visual_node_->getPosition();
}

const Ogre::Quaternion& Robot::getOrientation()
{
  return root_visual_node_->getOrientation();
}

void Robot::setColor( float r, float g, float b, float a )
{
  /// @todo Make this work on the meshes as well?

  M_NameToLink::iterator link_it = links_.begin();
  M_NameToLink::iterator link_end = links_.end();
  for ( ; link_it != link_end; ++link_it )
  {
    RobotLink* info = link_it->second;
    info->setColor(r, g, b, a);
  }
}

} // namespace rviz
<commit_msg>Until we have a good way for multi-robot support in mechanism control, adding a hack for displaying the robot model that assumes the global namespace<commit_after>/*
 * Copyright (c) 2008, Willow Garage, Inc.
 * 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 Willow Garage, Inc. nor the names of its
 *       contributors may be used to endorse or promote products derived from
 *       this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 */

#include "robot.h"
#include "robot_link.h"
#include "common.h"
#include "properties/property.h"
#include "properties/property_manager.h"
#include "visualization_manager.h"

#include "ogre_tools/object.h"
#include "ogre_tools/shape.h"
#include "ogre_tools/axes.h"

#include <tf/transform_listener.h>
#include <planning_models/kinematic.h>

#include <OGRE/OgreSceneNode.h>
#include <OGRE/OgreSceneManager.h>
#include <OGRE/OgreRibbonTrail.h>
#include <OGRE/OgreEntity.h>
#include <OGRE/OgreMaterialManager.h>
#include <OGRE/OgreMaterial.h>

#include <ros/console.h>

namespace rviz
{

Robot::Robot( VisualizationManager* manager, const std::string& name )
: ogre_tools::Object( manager->getSceneManager() )
, visual_visible_( true )
, collision_visible_( false )
, vis_manager_(manager)
, property_manager_(NULL)
, user_data_( NULL )
, name_( name )
{
  root_visual_node_ = scene_manager_->getRootSceneNode()->createChildSceneNode();
  root_collision_node_ = scene_manager_->getRootSceneNode()->createChildSceneNode();
  root_other_node_ = scene_manager_->getRootSceneNode()->createChildSceneNode();

  setVisualVisible( visual_visible_ );
  setCollisionVisible( collision_visible_ );
  setAlpha(1.0f);
}

Robot::~Robot()
{
  clear();

  scene_manager_->destroySceneNode( root_visual_node_->getName() );
  scene_manager_->destroySceneNode( root_collision_node_->getName() );
  scene_manager_->destroySceneNode( root_other_node_->getName() );
}

void Robot::setVisible( bool visible )
{
  if ( visible )
  {
    root_visual_node_->setVisible( visual_visible_ );
    root_collision_node_->setVisible( collision_visible_ );
  }
  else
  {
    root_visual_node_->setVisible( false );
    root_collision_node_->setVisible( false );
  }
}

void Robot::setVisualVisible( bool visible )
{
  visual_visible_ = visible;
  root_visual_node_->setVisible( visible );
}

void Robot::setCollisionVisible( bool visible )
{
  collision_visible_ = visible;
  root_collision_node_->setVisible( visible );
}

bool Robot::isVisualVisible()
{
  return visual_visible_;
}

bool Robot::isCollisionVisible()
{
  return collision_visible_;
}

void Robot::setAlpha(float a)
{
  alpha_ = a;

  M_NameToLink::iterator it = links_.begin();
  M_NameToLink::iterator end = links_.end();
  for ( ; it != end; ++it )
  {
    RobotLink* info = it->second;

    info->setAlpha(alpha_);
  }
}

void Robot::setUserData( const Ogre::Any& user_data )
{
  user_data_ = user_data;
}

void Robot::clear()
{
  M_NameToLink::iterator link_it = links_.begin();
  M_NameToLink::iterator link_end = links_.end();
  for ( ; link_it != link_end; ++link_it )
  {
    RobotLink* info = link_it->second;
    delete info;
  }

  if ( property_manager_ )
  {
    property_manager_->deleteByUserData( this );
  }

  links_category_.reset();
  links_.clear();
  root_visual_node_->removeAndDestroyAllChildren();
  root_collision_node_->removeAndDestroyAllChildren();
}

void Robot::setPropertyManager( PropertyManager* property_manager, const CategoryPropertyWPtr& parent )
{
  ROS_ASSERT( property_manager );
  ROS_ASSERT( parent.lock() );

  property_manager_ = property_manager;
  parent_property_ = parent;

  if ( !links_.empty() )
  {
    M_NameToLink::iterator link_it = links_.begin();
    M_NameToLink::iterator link_end = links_.end();
    for ( ; link_it != link_end; ++link_it )
    {
      RobotLink* info = link_it->second;

      info->createProperties();
    }
  }
}

void Robot::load( mechanism::Robot &descr, bool visual, bool collision )
{
  clear();

  if ( property_manager_ )
  {
    ROS_ASSERT(!links_category_.lock());
    links_category_ = property_manager_->createCategory( "Links", name_, parent_property_, this );
  }

  for (size_t i = 0; i < descr.links_.size(); ++i)
  {
    mechanism::Link &link = *descr.links_[i];

    RobotLink* link_info = new RobotLink(this, vis_manager_);
    link_info->load(descr, link, visual, collision);

    bool inserted = links_.insert( std::make_pair( link_info->getName(), link_info ) ).second;
    ROS_ASSERT( inserted );

    joint_to_link_[ link_info->getJointName() ] = link_info->getName();

    link_info->setAlpha(alpha_);
  }

  CategoryPropertyPtr cat_prop = links_category_.lock();
  cat_prop->collapse();

  setVisualVisible(isVisualVisible());
  setCollisionVisible(isCollisionVisible());
}

RobotLink* Robot::getLink( const std::string& name )
{
  M_NameToLink::iterator it = links_.find( name );
  if ( it == links_.end() )
  {
    ROS_WARN( "Link [%s] does not exist", name.c_str() );
    return NULL;
  }

  return it->second;
}

void Robot::update( tf::TransformListener* tf, const std::string& target_frame )
{
  typedef std::vector<std::string> V_string;
  V_string frames;
  tf->getFrameStrings( frames );

  M_NameToLink::iterator link_it = links_.begin();
  M_NameToLink::iterator link_end = links_.end();
  for ( ; link_it != link_end; ++link_it )
  {
    ///@todo TODO: REMOVE THIS HACK
    const std::string& name = "/" + link_it->first;
    ///end HACK

    RobotLink* info = link_it->second;

    if ( std::find( frames.begin(), frames.end(), name ) == frames.end() )
    {
      ROS_ERROR( "Frame '%s' does not exist in the TF frame list", name.c_str() );

      info->setToErrorMaterial();
      continue;
    }

    info->setToNormalMaterial();

    tf::Stamped<tf::Pose> pose( btTransform( btQuaternion( 0, 0, 0 ), btVector3( 0, 0, 0 ) ), ros::Time(), name );

    if (tf->canTransform(target_frame, name, ros::Time()))
    {
      try
      {
        tf->transformPose( target_frame, pose, pose );
      }
      catch(tf::TransformException& e)
      {
        ROS_ERROR( "Error transforming from frame '%s' to frame '%s'\n", name.c_str(), target_frame.c_str() );
      }
    }

    //printf( "Link %s:\npose: %6f %6f %6f,\t%6f %6f %6f\n", name.c_str(), pose.data_.getOrigin().x(), pose.data_.getOrigin().y(), pose.data_.getOrigin().z(), pose.data_.getOrigin().y()aw, pose.pitch, pose.roll );

    Ogre::Vector3 position( pose.getOrigin().x(), pose.getOrigin().y(), pose.getOrigin().z() );
    robotToOgre( position );

    btScalar yaw, pitch, roll;
    pose.getBasis().getEulerZYX( yaw, pitch, roll );

    Ogre::Matrix3 orientation( ogreMatrixFromRobotEulers( yaw, pitch, roll ) );

    // Collision/visual transforms are the same in this case
    info->setTransforms( position, orientation, position, orientation, true );
  }
}

void Robot::update( planning_models::KinematicModel* kinematic_model, const std::string& target_frame )
{
  M_NameToLink::iterator link_it = links_.begin();
  M_NameToLink::iterator link_end = links_.end();
  for ( ; link_it != link_end; ++link_it )
  {
    const std::string& name = link_it->first;
    RobotLink* info = link_it->second;

    planning_models::KinematicModel::Link* link = kinematic_model->getLink( name );

    if ( !link )
    {
      continue;
    }

    btVector3 robot_visual_position = link->globalTransFwd.getOrigin();
    btQuaternion robot_visual_orientation = link->globalTransFwd.getRotation();
    Ogre::Vector3 visual_position( robot_visual_position.getX(), robot_visual_position.getY(), robot_visual_position.getZ() );
    Ogre::Quaternion visual_orientation( robot_visual_orientation.getW(), robot_visual_orientation.getX(), robot_visual_orientation.getY(), robot_visual_orientation.getZ() );
    robotToOgre( visual_position );
    robotToOgre( visual_orientation );

    btVector3 robot_collision_position = link->globalTrans.getOrigin();
    btQuaternion robot_collision_orientation = link->globalTrans.getRotation();
    Ogre::Vector3 collision_position( robot_collision_position.getX(), robot_collision_position.getY(), robot_collision_position.getZ() );
    Ogre::Quaternion collision_orientation( robot_collision_orientation.getW(), robot_collision_orientation.getX(), robot_collision_orientation.getY(), robot_collision_orientation.getZ() );
    robotToOgre( collision_position );
    robotToOgre( collision_orientation );

    info->setTransforms( visual_position, visual_orientation, collision_position, collision_orientation, false );
  }
}

void Robot::update( const robot_msgs::MechanismState& state )
{
  std::vector<robot_msgs::JointState>::const_iterator it = state.joint_states.begin();
  std::vector<robot_msgs::JointState>::const_iterator end = state.joint_states.end();
  for ( ; it != end; ++it )
  {
    const robot_msgs::JointState& joint_state = *it;
    M_string::iterator str_it = joint_to_link_.find( joint_state.name );
    if ( str_it != joint_to_link_.end() )
    {
      RobotLink* info = getLink( str_it->second );

      info->setJointState(joint_state);
    }
  }
}

void Robot::setPosition( const Ogre::Vector3& position )
{
  root_visual_node_->setPosition( position );
  root_collision_node_->setPosition( position );
}

void Robot::setOrientation( const Ogre::Quaternion& orientation )
{
  root_visual_node_->setOrientation( orientation );
  root_collision_node_->setOrientation( orientation );
}

void Robot::setScale( const Ogre::Vector3& scale )
{
  root_visual_node_->setScale( scale );
  root_collision_node_->setScale( scale );
}

const Ogre::Vector3& Robot::getPosition()
{
  return root_visual_node_->getPosition();
}

const Ogre::Quaternion& Robot::getOrientation()
{
  return root_visual_node_->getOrientation();
}

void Robot::setColor( float r, float g, float b, float a )
{
  /// @todo Make this work on the meshes as well?

  M_NameToLink::iterator link_it = links_.begin();
  M_NameToLink::iterator link_end = links_.end();
  for ( ; link_it != link_end; ++link_it )
  {
    RobotLink* info = link_it->second;
    info->setColor(r, g, b, a);
  }
}

} // namespace rviz
<|endoftext|>


<commit_before>#include "term.h"
#include "../parser/SceneParser.h"

#include "core/math/basics.h"
#include "core/model/Scene.h"
#include "core/common/Buffer.h"
#include "core/realtime/Engine.h"

#include <cstdlib>
#include <string>
#include <unistd.h>
#include <chrono>

using namespace proxo;

int main(int argc, char** argv)
{
	// Load scene from file
	SceneParser parser;
	Scene scene;
	std::string sceneFileName = argc >= 2 ? argv[1] : "media/parc.scene";
	if(!parser.readScene(sceneFileName, scene)) {
		printf("readScene failed!\n");
		return 2;
	}
	scene.printSize();

	positive screen_width;
	positive screen_height;
  BufferToXTerm::getViewSize(screen_width, screen_height);
  screen_height -= 4;
  printf("Image size: %dx%d\n", screen_width, screen_height);
  scene.camera.setRenderTarget(screen_width, screen_height, 0);
  scene.camera.updateProjection();

	Buffer buf(screen_width, screen_height);

	Engine realTimeEngine(&buf, &scene);
	realTimeEngine.createMatchingPool();

	BufferToXTerm btx(buf);

	// program main loop
	bool done = false;
	while(!done) {
    realTimeEngine.render();
    auto txt = btx.convert2();
    fwrite(txt.get(), strlen(txt.get()), 1, stdout);
    fflush(stdout);
    //usleep(300*1000);
//    break;
	} // end main loop

	return 0;
}
<commit_msg>Print render time to stderr in term sample<commit_after>#include "term.h"
#include "../parser/SceneParser.h"

#include "core/math/basics.h"
#include "core/model/Scene.h"
#include "core/common/Buffer.h"
#include "core/realtime/Engine.h"

#include <cstdlib>
#include <string>
#include <unistd.h>
#include <chrono>

using namespace proxo;

int main(int argc, char** argv)
{
	// Load scene from file
	SceneParser parser;
	Scene scene;
	std::string sceneFileName = argc >= 2 ? argv[1] : "media/parc.scene";
	if(!parser.readScene(sceneFileName, scene)) {
		printf("readScene failed!\n");
		return 2;
	}
	scene.printSize();

	positive screen_width;
	positive screen_height;
  BufferToXTerm::getViewSize(screen_width, screen_height);
  screen_height -= 4;
  printf("Image size: %dx%d\n", screen_width, screen_height);
  scene.camera.setRenderTarget(screen_width, screen_height, 0);
  scene.camera.updateProjection();

	Buffer buf(screen_width, screen_height);

	Engine realTimeEngine(&buf, &scene);
	realTimeEngine.createMatchingPool();

	BufferToXTerm btx(buf);

	// program main loop
	bool done = false;
	while(!done) {
    auto t1 = std::chrono::system_clock::now();
    realTimeEngine.render();
    auto t2 = std::chrono::system_clock::now();
    std::chrono::duration<double> diff = t2 - t1;
    fprintf(stderr, "render: %f sec\n", diff.count());
    auto txt = btx.convert2();
    fwrite(txt.get(), strlen(txt.get()), 1, stdout);
    fflush(stdout);
    //usleep(300*1000);
//    break;
	} // end main loop

	return 0;
}
<|endoftext|>


<commit_before>/**
 * @file
 *
 * @brief
 *
 * @copyright BSD License (see LICENSE.md or https://www.libelektra.org)
 */

#include "dump.hpp"

using namespace ckdb;

#include <fstream>
#include <iostream>
#include <sstream>
#include <string>
#include <vector>

#include <kdberrors.h>
#include <kdblogger.h>

namespace dump
{

int serialise (std::ostream & os, ckdb::Key *, ckdb::KeySet * ks)
{
	ckdb::Key * cur;

	os << "kdbOpen 1" << std::endl;

	os << "ksNew " << ckdb::ksGetSize (ks) << std::endl;

	ckdb::KeySet * metacopies = ckdb::ksNew (0, KS_END);

	ksRewind (ks);
	while ((cur = ksNext (ks)) != nullptr)
	{
		size_t namesize = ckdb::keyGetNameSize (cur);
		size_t valuesize = ckdb::keyGetValueSize (cur);
		os << "keyNew " << namesize << " " << valuesize << std::endl;
		os.write (ckdb::keyName (cur), namesize);
		os.write (static_cast<const char *> (ckdb::keyValue (cur)), valuesize);
		os << std::endl;

		const ckdb::Key * meta;
		ckdb::keyRewindMeta (cur);
		while ((meta = ckdb::keyNextMeta (cur)) != nullptr)
		{
			std::stringstream ss;
			ss << "user/" << meta; // use the address of pointer as name

			ckdb::Key * search = ckdb::keyNew (ss.str ().c_str (), KEY_END);
			ckdb::Key * ret = ksLookup (metacopies, search, 0);

			if (!ret)
			{
				/* This metakey was not serialised up to now */
				size_t metanamesize = ckdb::keyGetNameSize (meta);
				size_t metavaluesize = ckdb::keyGetValueSize (meta);

				os << "keyMeta " << metanamesize << " " << metavaluesize << std::endl;
				os.write (ckdb::keyName (meta), metanamesize);
				os.write (static_cast<const char *> (ckdb::keyValue (meta)), metavaluesize);
				os << std::endl;

				std::stringstream ssv;
				ssv << namesize << " " << metanamesize << std::endl;
				ssv.write (ckdb::keyName (cur), namesize);
				ssv.write (ckdb::keyName (meta), metanamesize);
				ckdb::keySetRaw (search, ssv.str ().c_str (), ssv.str ().size ());

				ksAppendKey (metacopies, search);
			}
			else
			{
				/* Meta key already serialised, write out a reference to it */
				keyDel (search);

				os << "keyCopyMeta ";
				os.write (static_cast<const char *> (ckdb::keyValue (ret)), ckdb::keyGetValueSize (ret));
				os << std::endl;
			}
		}
		os << "keyEnd" << std::endl;
	}
	os << "ksEnd" << std::endl;

	ksDel (metacopies);

	return 1;
}

int unserialise (std::istream & is, ckdb::Key * errorKey, ckdb::KeySet * ks)
{
	ckdb::Key * cur = nullptr;

	std::vector<char> namebuffer (4048);
	std::vector<char> valuebuffer (4048);
	std::string line;
	std::string command;
	size_t nrKeys;
	size_t namesize;
	size_t valuesize;

	while (std::getline (is, line))
	{
		std::stringstream ss (line);
		ss >> command;

		if (command == "kdbOpen")
		{
			std::string version;
			ss >> version;
			if (version != "1")
			{
				ELEKTRA_SET_ERROR (50, errorKey, version.c_str ());
				return -1;
			}
		}
		else if (command == "ksNew")
		{
			ss >> nrKeys;

			ksClear (ks);
		}
		else if (command == "keyNew")
		{
			cur = ckdb::keyNew (nullptr);

			ss >> namesize;
			ss >> valuesize;

			if (namesize > namebuffer.size ()) namebuffer.resize (namesize + 1);
			is.read (&namebuffer[0], namesize);
			namebuffer[namesize] = 0;
			ckdb::keySetName (cur, &namebuffer[0]);

			if (valuesize > valuebuffer.size ()) valuebuffer.resize (valuesize + 1);
			is.read (&valuebuffer[0], valuesize);
			valuebuffer[valuesize] = 0;

			ckdb::keySetRaw (cur, &valuebuffer[0], valuesize);
			std::getline (is, line);
		}
		else if (command == "keyMeta")
		{
			ss >> namesize;
			ss >> valuesize;

			if (namesize > namebuffer.size ()) namebuffer.resize (namesize + 1);
			is.read (&namebuffer[0], namesize);
			namebuffer[namesize] = 0;

			if (valuesize > valuebuffer.size ()) valuebuffer.resize (valuesize + 1);
			is.read (&valuebuffer[0], valuesize);
			valuebuffer[valuesize] = 0;

			keySetMeta (cur, &namebuffer[0], &valuebuffer[0]);
			std::getline (is, line);
		}
		else if (command == "keyCopyMeta")
		{
			ss >> namesize;
			ss >> valuesize;

			if (namesize > namebuffer.size ()) namebuffer.resize (namesize + 1);
			is.read (&namebuffer[0], namesize);
			namebuffer[namesize] = 0;

			if (valuesize > valuebuffer.size ()) valuebuffer.resize (valuesize + 1);
			is.read (&valuebuffer[0], valuesize);
			valuebuffer[valuesize] = 0;

			ckdb::Key * search = ckdb::ksLookupByName (ks, &namebuffer[0], 0);
			ckdb::keyCopyMeta (cur, search, &valuebuffer[0]);
			std::getline (is, line);
		}
		else if (command == "keyEnd")
		{
			ckdb::ksAppendKey (ks, cur);
			cur = nullptr;
		}
		else if (command == "ksEnd")
		{
			break;
		}
		else
		{
			ELEKTRA_SET_ERROR (49, errorKey, command.c_str ());
			return -1;
		}
	}
	return 1;
}

} // namespace dump

extern "C" {

int elektraDumpGet (ckdb::Plugin *, ckdb::KeySet * returned, ckdb::Key * parentKey)
{
	Key * root = ckdb::keyNew ("system/elektra/modules/dump", KEY_END);
	if (keyRel (root, parentKey) >= 0)
	{
		keyDel (root);
		KeySet * n = ksNew (50, keyNew ("system/elektra/modules/dump", KEY_VALUE, "dump plugin waits for your orders", KEY_END),
				    keyNew ("system/elektra/modules/dump/exports", KEY_END),
				    keyNew ("system/elektra/modules/dump/exports/get", KEY_FUNC, elektraDumpGet, KEY_END),
				    keyNew ("system/elektra/modules/dump/exports/set", KEY_FUNC, elektraDumpSet, KEY_END),
				    keyNew ("system/elektra/modules/dump/exports/serialise", KEY_FUNC, dump::serialise, KEY_END),
				    keyNew ("system/elektra/modules/dump/exports/unserialise", KEY_FUNC, dump::unserialise, KEY_END),
#include "readme_dump.c"
				    keyNew ("system/elektra/modules/dump/infos/version", KEY_VALUE, PLUGINVERSION, KEY_END), KS_END);
		ksAppend (returned, n);
		ksDel (n);
		return 1;
	}
	keyDel (root);
	int errnosave = errno;

	// ELEKTRA_LOG (ELEKTRA_LOG_MODULE_DUMP, "opening file %s", keyString (parentKey));
	std::ifstream ofs (keyString (parentKey), std::ios::binary);
	if (!ofs.is_open ())
	{
		ELEKTRA_SET_ERROR_GET (parentKey);
		errno = errnosave;
		return -1;
	}

	return dump::unserialise (ofs, parentKey, returned);
}

int elektraDumpSet (ckdb::Plugin *, ckdb::KeySet * returned, ckdb::Key * parentKey)
{
	int errnosave = errno;
	// ELEKTRA_LOG (ELEKTRA_LOG_MODULE_DUMP, "opening file %s", keyString (parentKey));
	std::ofstream ofs (keyString (parentKey), std::ios::binary);
	if (!ofs.is_open ())
	{
		ELEKTRA_SET_ERROR_SET (parentKey);
		errno = errnosave;
		return -1;
	}

	return dump::serialise (ofs, parentKey, returned);
}

ckdb::Plugin * ELEKTRA_PLUGIN_EXPORT (dump)
{
	// clang-format off
	return elektraPluginExport("dump",
		ELEKTRA_PLUGIN_GET,		&elektraDumpGet,
		ELEKTRA_PLUGIN_SET,		&elektraDumpSet,
		ELEKTRA_PLUGIN_END);
}

} // extern C

<commit_msg>fcrypt: make dump use non-text version<commit_after>/**
 * @file
 *
 * @brief
 *
 * @copyright BSD License (see LICENSE.md or https://www.libelektra.org)
 */

#include "dump.hpp"

using namespace ckdb;

#include <fstream>
#include <iostream>
#include <sstream>
#include <string>
#include <vector>

#include <kdberrors.h>
#include <kdblogger.h>

namespace dump
{

int serialise (std::ostream & os, ckdb::Key *, ckdb::KeySet * ks)
{
	ckdb::Key * cur;

	os << "kdbOpen 1" << std::endl;

	os << "ksNew " << ckdb::ksGetSize (ks) << std::endl;

	ckdb::KeySet * metacopies = ckdb::ksNew (0, KS_END);

	ksRewind (ks);
	while ((cur = ksNext (ks)) != nullptr)
	{
		size_t namesize = ckdb::keyGetNameSize (cur);
		size_t valuesize = ckdb::keyGetValueSize (cur);
		os << "keyNew " << namesize << " " << valuesize << std::endl;
		os.write (ckdb::keyName (cur), namesize);
		os.write (static_cast<const char *> (ckdb::keyValue (cur)), valuesize);
		os << std::endl;

		const ckdb::Key * meta;
		ckdb::keyRewindMeta (cur);
		while ((meta = ckdb::keyNextMeta (cur)) != nullptr)
		{
			std::stringstream ss;
			ss << "user/" << meta; // use the address of pointer as name

			ckdb::Key * search = ckdb::keyNew (ss.str ().c_str (), KEY_END);
			ckdb::Key * ret = ksLookup (metacopies, search, 0);

			if (!ret)
			{
				/* This metakey was not serialised up to now */
				size_t metanamesize = ckdb::keyGetNameSize (meta);
				size_t metavaluesize = ckdb::keyGetValueSize (meta);

				os << "keyMeta " << metanamesize << " " << metavaluesize << std::endl;
				os.write (ckdb::keyName (meta), metanamesize);
				os.write (static_cast<const char *> (ckdb::keyValue (meta)), metavaluesize);
				os << std::endl;

				std::stringstream ssv;
				ssv << namesize << " " << metanamesize << std::endl;
				ssv.write (ckdb::keyName (cur), namesize);
				ssv.write (ckdb::keyName (meta), metanamesize);
				ckdb::keySetRaw (search, ssv.str ().c_str (), ssv.str ().size ());

				ksAppendKey (metacopies, search);
			}
			else
			{
				/* Meta key already serialised, write out a reference to it */
				keyDel (search);

				os << "keyCopyMeta ";
				os.write (static_cast<const char *> (ckdb::keyValue (ret)), ckdb::keyGetValueSize (ret));
				os << std::endl;
			}
		}
		os << "keyEnd" << std::endl;
	}
	os << "ksEnd" << std::endl;

	ksDel (metacopies);

	return 1;
}

int unserialise (std::istream & is, ckdb::Key * errorKey, ckdb::KeySet * ks)
{
	ckdb::Key * cur = nullptr;

	std::vector<char> namebuffer (4048);
	std::vector<char> valuebuffer (4048);
	std::string line;
	std::string command;
	size_t nrKeys;
	size_t namesize;
	size_t valuesize;

	while (std::getline (is, line))
	{
		std::stringstream ss (line);
		ss >> command;

		if (command == "kdbOpen")
		{
			std::string version;
			ss >> version;
			if (version != "1")
			{
				ELEKTRA_SET_ERROR (50, errorKey, version.c_str ());
				return -1;
			}
		}
		else if (command == "ksNew")
		{
			ss >> nrKeys;

			ksClear (ks);
		}
		else if (command == "keyNew")
		{
			cur = ckdb::keyNew (nullptr);

			ss >> namesize;
			ss >> valuesize;

			if (namesize > namebuffer.size ()) namebuffer.resize (namesize + 1);
			is.read (&namebuffer[0], namesize);
			namebuffer[namesize] = 0;
			ckdb::keySetName (cur, &namebuffer[0]);

			if (valuesize > valuebuffer.size ()) valuebuffer.resize (valuesize + 1);
			is.read (&valuebuffer[0], valuesize);
			valuebuffer[valuesize] = 0;

			ckdb::keySetRaw (cur, &valuebuffer[0], valuesize);
			std::getline (is, line);
		}
		else if (command == "keyMeta")
		{
			ss >> namesize;
			ss >> valuesize;

			if (namesize > namebuffer.size ()) namebuffer.resize (namesize + 1);
			is.read (&namebuffer[0], namesize);
			namebuffer[namesize] = 0;

			if (valuesize > valuebuffer.size ()) valuebuffer.resize (valuesize + 1);
			is.read (&valuebuffer[0], valuesize);
			valuebuffer[valuesize] = 0;

			keySetMeta (cur, &namebuffer[0], &valuebuffer[0]);
			std::getline (is, line);
		}
		else if (command == "keyCopyMeta")
		{
			ss >> namesize;
			ss >> valuesize;

			if (namesize > namebuffer.size ()) namebuffer.resize (namesize + 1);
			is.read (&namebuffer[0], namesize);
			namebuffer[namesize] = 0;

			if (valuesize > valuebuffer.size ()) valuebuffer.resize (valuesize + 1);
			is.read (&valuebuffer[0], valuesize);
			valuebuffer[valuesize] = 0;

			ckdb::Key * search = ckdb::ksLookupByName (ks, &namebuffer[0], 0);
			ckdb::keyCopyMeta (cur, search, &valuebuffer[0]);
			std::getline (is, line);
		}
		else if (command == "keyEnd")
		{
			ckdb::ksAppendKey (ks, cur);
			cur = nullptr;
		}
		else if (command == "ksEnd")
		{
			break;
		}
		else
		{
			ELEKTRA_SET_ERROR (49, errorKey, command.c_str ());
			return -1;
		}
	}
	return 1;
}

} // namespace dump

extern "C" {

int elektraDumpGet (ckdb::Plugin *, ckdb::KeySet * returned, ckdb::Key * parentKey)
{
	Key * root = ckdb::keyNew ("system/elektra/modules/dump", KEY_END);
	if (keyRel (root, parentKey) >= 0)
	{
		keyDel (root);
		KeySet * n = ksNew (50, keyNew ("system/elektra/modules/dump", KEY_VALUE, "dump plugin waits for your orders", KEY_END),
				    keyNew ("system/elektra/modules/dump/exports", KEY_END),
				    keyNew ("system/elektra/modules/dump/exports/get", KEY_FUNC, elektraDumpGet, KEY_END),
				    keyNew ("system/elektra/modules/dump/exports/set", KEY_FUNC, elektraDumpSet, KEY_END),
				    keyNew ("system/elektra/modules/dump/exports/serialise", KEY_FUNC, dump::serialise, KEY_END),
				    keyNew ("system/elektra/modules/dump/exports/unserialise", KEY_FUNC, dump::unserialise, KEY_END),
				    keyNew ("system/elektra/modules/dump/config/needs/fcrypt/textmode", KEY_VALUE, "0", KEY_END),
#include "readme_dump.c"
				    keyNew ("system/elektra/modules/dump/infos/version", KEY_VALUE, PLUGINVERSION, KEY_END), KS_END);
		ksAppend (returned, n);
		ksDel (n);
		return 1;
	}
	keyDel (root);
	int errnosave = errno;

	// ELEKTRA_LOG (ELEKTRA_LOG_MODULE_DUMP, "opening file %s", keyString (parentKey));
	std::ifstream ofs (keyString (parentKey), std::ios::binary);
	if (!ofs.is_open ())
	{
		ELEKTRA_SET_ERROR_GET (parentKey);
		errno = errnosave;
		return -1;
	}

	return dump::unserialise (ofs, parentKey, returned);
}

int elektraDumpSet (ckdb::Plugin *, ckdb::KeySet * returned, ckdb::Key * parentKey)
{
	int errnosave = errno;
	// ELEKTRA_LOG (ELEKTRA_LOG_MODULE_DUMP, "opening file %s", keyString (parentKey));
	std::ofstream ofs (keyString (parentKey), std::ios::binary);
	if (!ofs.is_open ())
	{
		ELEKTRA_SET_ERROR_SET (parentKey);
		errno = errnosave;
		return -1;
	}

	return dump::serialise (ofs, parentKey, returned);
}

ckdb::Plugin * ELEKTRA_PLUGIN_EXPORT (dump)
{
	// clang-format off
	return elektraPluginExport("dump",
		ELEKTRA_PLUGIN_GET,		&elektraDumpGet,
		ELEKTRA_PLUGIN_SET,		&elektraDumpSet,
		ELEKTRA_PLUGIN_END);
}

} // extern C

<|endoftext|>


<commit_before>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: undofactory.cxx,v $
 *
 *  $Revision: 1.3 $
 *
 *  last change: $Author: obo $ $Date: 2006-09-16 18:18:03 $
 *
 *  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
 *
 ************************************************************************/

// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_sd.hxx"

#ifndef _TOOLS_DEBUG_HXX
#include <tools/debug.hxx>
#endif

#include "undo/undofactory.hxx"
#include "undo/undoobjects.hxx"

using namespace sd;

SdrUndoAction* UndoFactory::CreateUndoRemoveObject( SdrObject& rObject, bool bOrdNumDirect )
{
    return new UndoRemoveObject( rObject, bOrdNumDirect );
}

SdrUndoAction* UndoFactory::CreateUndoDeleteObject( SdrObject& rObject, bool bOrdNumDirect )
{
    return new UndoDeleteObject( rObject, bOrdNumDirect );
}

SdrUndoAction* UndoFactory::CreateUndoObjectSetText( SdrObject& rNewObj )
{
    return new UndoObjectSetText( rNewObj );
}

SdrUndoAction* UndoFactory::CreateUndoReplaceObject( SdrObject& rOldObject, SdrObject& rNewObject, bool bOrdNumDirect )
{
    return new UndoReplaceObject( rOldObject, rNewObject, bOrdNumDirect );
}

SdrUndoAction* UndoFactory::CreateUndoGeoObject( SdrObject& rObject )
{
    return new UndoGeoObject( rObject );
}

SdrUndoAction* UndoFactory::CreateUndoAttrObject( SdrObject& rObject, bool bStyleSheet1, bool bSaveText )
{
    return new UndoAttrObject( rObject, bStyleSheet1, bSaveText );
}
<commit_msg>INTEGRATION: CWS impresstables2 (1.3.114); FILE MERGED 2007/10/11 15:38:28 cl 1.3.114.1: #i68103# added undo for tables<commit_after>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: undofactory.cxx,v $
 *
 *  $Revision: 1.4 $
 *
 *  last change: $Author: rt $ $Date: 2008-03-12 11:30:03 $
 *
 *  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
 *
 ************************************************************************/

// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_sd.hxx"

#ifndef _TOOLS_DEBUG_HXX
#include <tools/debug.hxx>
#endif

#include "undo/undofactory.hxx"
#include "undo/undoobjects.hxx"

using namespace sd;

SdrUndoAction* UndoFactory::CreateUndoRemoveObject( SdrObject& rObject, bool bOrdNumDirect )
{
    return new UndoRemoveObject( rObject, bOrdNumDirect );
}

SdrUndoAction* UndoFactory::CreateUndoDeleteObject( SdrObject& rObject, bool bOrdNumDirect )
{
    return new UndoDeleteObject( rObject, bOrdNumDirect );
}

SdrUndoAction* UndoFactory::CreateUndoObjectSetText( SdrObject& rNewObj, sal_Int32 nText )
{
    return new UndoObjectSetText( rNewObj, nText );
}

SdrUndoAction* UndoFactory::CreateUndoReplaceObject( SdrObject& rOldObject, SdrObject& rNewObject, bool bOrdNumDirect )
{
    return new UndoReplaceObject( rOldObject, rNewObject, bOrdNumDirect );
}

SdrUndoAction* UndoFactory::CreateUndoGeoObject( SdrObject& rObject )
{
    return new UndoGeoObject( rObject );
}

SdrUndoAction* UndoFactory::CreateUndoAttrObject( SdrObject& rObject, bool bStyleSheet1, bool bSaveText )
{
    return new UndoAttrObject( rObject, bStyleSheet1, bSaveText );
}
<|endoftext|>


<commit_before>/*
 * Copyright (C) 2009, Gostai S.A.S.
 *
 * This software is provided "as is" without warranty of any kind,
 * either expressed or implied, including but not limited to the
 * implied warranties of fitness for a particular purpose.
 *
 * See the LICENSE file for more information.
 */

#include <sys/stat.h>

#include <cassert>
#include <cstring>
#include <cstdlib>
#include <cstdio>
#include <iostream>

#include <libport/config.h>
#include <libport/foreach.hh>

#include <urbi/urbi-root.hh>
#include <libport/config.h>

#if defined WIN32
# define APPLE_LINUX_WINDOWS(Apple, Linux, Windows) Windows
#elif defined __APPLE__
# define APPLE_LINUX_WINDOWS(Apple, Linux, Windows) Apple
#else
# define APPLE_LINUX_WINDOWS(Apple, Linux, Windows) Linux
#endif

/*--------.
| Helpers |
`--------*/

static std::string
xgetenv(const std::string& var)
{
  const char* res = getenv(var.c_str());
  return res ? res : "";
}

// static void
// xsetenv(const std::string& var, const std::string& val, int force)
// {
// #ifdef WIN32
//   if (force || xgetenv(var).empty())
//     _putenv(strdup((var + "=" + val).c_str()));
// #else
//   setenv(var.c_str(), val.c_str(), force);
// #endif
// }

/*------------.
| Reporting.  |
`------------*/

static bool
debug()
{
  static bool res = xgetenv("GD_LEVEL") == "DUMP";
  return res;
}

# define URBI_ROOT_ECHO(S)                      \
  std::cerr << S << std::endl                   \

# define URBI_ROOT_DEBUG(Self, S)                       \
  do {                                                  \
    if (debug())                                        \
      URBI_ROOT_ECHO(Self << ": " << S);                \
  } while (0)                                           \

# define URBI_ROOT_FATAL(Self, N, S)            \
  do {                                          \
    URBI_ROOT_ECHO(Self << ": " << S);          \
    exit(N);                                    \
  } while (0)

/*-----------------.
| File constants.  |
`-----------------*/

static const std::string libext =
                           APPLE_LINUX_WINDOWS(".dylib", ".so", ".dll");
static const std::string separator =
                           APPLE_LINUX_WINDOWS("/", "/", "\\");
static const std::string libdir =
                           APPLE_LINUX_WINDOWS("lib", "lib", "bin");
static const std::string libuobjects_dir =
                           std::string("/gostai/core/") + LIBPORT_URBI_HOST;

/*-------------------------------------.
| Crapy dynamic portability routines.  |
`-------------------------------------*/

#ifdef WIN32
#define RTLD_LAZY 0
#define RTLD_NOW 0
#define RTLD_GLOBAL 0

static RTLD_HANDLE
dlopen(const char* name, int)
{
  RTLD_HANDLE res = LoadLibrary(name);
  if (res)
  {
    char buf[BUFSIZ];
    GetModuleFileName(res, buf, sizeof buf - 1);
    buf[sizeof buf - 1] = 0;
  }
  return res;
}

static void*
dlsym(RTLD_HANDLE module, const char* name)
{
  return GetProcAddress(module, name);
}

static const char*
dlerror(DWORD err = GetLastError())
{
  static char buf[1024];

  FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
                0, err, 0,
                (LPTSTR)buf, sizeof buf,
                0);

  return buf;
}

#else
# include <dlfcn.h>
#endif

typedef std::vector<std::string> strings_type;
static strings_type
split(std::string lib)
{
  strings_type res;
  size_t pos;
  while ((pos = lib.find(':')) != lib.npos)
  {
    std::string s = lib.substr(0, pos);
    lib = lib.substr(pos + 1, lib.npos);
#ifdef WIN32
    // In case we split "c:\foo" into "c" and "\foo", glue them
    // together again.
    if (s[0] == '\\'
        && !res.empty()
        && res.back().length() == 1)
      res.back() += ':' + s;
    else
#endif
      res.push_back(s);
  }
  if (!lib.empty())
    res.push_back(lib);
  return res;
}

static RTLD_HANDLE
xdlopen(const std::string& path, int flags, const std::string& self)
{
  URBI_ROOT_DEBUG(self, "loading library: " << path);
  RTLD_HANDLE res = dlopen(path.c_str(), flags);
  if (!res)
    URBI_ROOT_FATAL(self, 1,
                    "cannot open library: " << path << ": " << dlerror());
  return res;
}

static
std::string
resolve_symlinks(const std::string& logname, const std::string& s)
{
#if defined WIN32
  return s;
#else
  char path[BUFSIZ];
  strncpy(path, s.c_str(), BUFSIZ);
  path[BUFSIZ - 1] = 0;
  while (readlink(path, path, BUFSIZ) != -1)
    URBI_ROOT_DEBUG(logname, "unrolling symbolic link: " << path);
  return path;
#endif
}

/*-----------.
| UrbiRoot.  |
`-----------*/

UrbiRoot::UrbiRoot(const std::string& program, bool static_build)
  : program_(program)
  , root_()
  , handle_libjpeg_(0)
  , handle_libport_(0)
  , handle_libsched_(0)
  , handle_liburbi_(0)
  , handle_libuobject_(0)
{
  // Find our directory.
  std::string uroot = xgetenv("URBI_ROOT");
  if (!uroot.empty())
  {
    URBI_ROOT_DEBUG(program_,
                    "URBI_ROOT is set, forcing root directory: " << root_);
    root_ = uroot;
  }
  else
  {
    URBI_ROOT_DEBUG(program_, "guessing Urbi root: invoked as: " << program_);
    // Handle the chained symlinks case.
    std::string argv0 = resolve_symlinks(program_, program);

#ifdef WIN32
    size_t pos = argv0.find_last_of("/\\");
#else
    size_t pos = argv0.rfind('/');
#endif
    if (pos == std::string::npos)
    {
      URBI_ROOT_DEBUG(program_,
                      "invoked from the path, looking for ourselves in PATH");
      strings_type path = split(xgetenv("PATH"));
      foreach (const std::string& dir, path)
      {
        struct stat stats;
        std::string file = dir + separator + argv0;
        if (stat(file.c_str(), &stats) == 0)
        {
          URBI_ROOT_DEBUG(program_, "found: " << file);
          root_ = dir + separator + "..";
          URBI_ROOT_DEBUG(program_, "root directory is: " << root_);
          break;
        }
        URBI_ROOT_DEBUG(program_, "not found: " << file);
      }
    }
    else
    {
      root_ = argv0.substr(0, pos) + separator + "..";
      URBI_ROOT_DEBUG(program_,
                      "invoked with a path, setting root to parent directory: "
                      << root_);
    }
  }

  if (root_.empty())
    URBI_ROOT_FATAL(program_, 3, "Unable to find Urbi SDK installation location. Please set URBI_ROOT.");

  // const std::string urbi_path = root_ + separator + "share" + separator + "gostai";
  // xsetenv("URBI_PATH", xgetenv("URBI_PATH") + ":" + urbi_path, true);
  // URBI_ROOT_DEBUG("append to URBI_PATH: " << urbi_path);
  if (!static_build)
  {
    handle_libjpeg_        = library_load("jpeg",        "JPEG");
    handle_libport_        = library_load("port",        "PORT");
    handle_libsched_       = library_load("sched",       "SCHED");
    handle_libser_         = library_load("serialize",   "SER");
    handle_liburbi_        = library_load("urbi",        "URBI");
  }
}

RTLD_HANDLE
UrbiRoot::library_load(const std::string& base, const std::string& env)
{
  std::string path;
  const std::string varname = "URBI_ROOT_LIB" + env;
  std::string alt = xgetenv(varname);

  if (alt.empty())
    path = root_ + separator + libdir + separator + "lib" + base + libext;
  else
    path = alt + libext;
  return xdlopen(path, RTLD_NOW | RTLD_GLOBAL, program_);
}

std::string
UrbiRoot::root() const
{
  return root_;
}

std::string
UrbiRoot::core_path() const
{
  return root_ + libuobjects_dir;
}

std::string
UrbiRoot::uobjects_path() const
{
  return core_path() + separator + "uobjects";
}

std::string
UrbiRoot::share_path() const
{
  return root_ + separator + "share/gostai";
}

void
UrbiRoot::load_plugin()
{
  URBI_ROOT_DEBUG(program_, "loading plugin UObject implementation");
  handle_libuobject_ = xdlopen(root_ + libuobjects_dir + separator
                               + "engine/libuobject" + libext,
                               RTLD_NOW | RTLD_GLOBAL, program_);
}

/// Location of Urbi remote libuobject
void
UrbiRoot::load_remote()
{
  URBI_ROOT_DEBUG(program_, "loading remote UObject implementation");
  handle_libuobject_ = xdlopen(root_ + libuobjects_dir + separator
                               + "remote/libuobject" + libext,
                               RTLD_NOW | RTLD_GLOBAL, program_);
}

void
UrbiRoot::load_custom(const std::string& path_)
{
  std::string path = path_ + separator + "libuobject" + libext;
  URBI_ROOT_DEBUG(program_, "loading custom UObject implementation: " << path);
  handle_libuobject_ = xdlopen(path, RTLD_NOW | RTLD_GLOBAL, program_);
}

typedef int(*urbi_launch_type)(int, const char*[], UrbiRoot&);
int
UrbiRoot::urbi_launch(int argc, const char** argv)
{
  URBI_ROOT_DEBUG(program_, "loading symbol urbi_launch from liburbi-launch");
  // Reinterpret-cast fails with gcc3 arm
  urbi_launch_type f = (urbi_launch_type)(dlsym(handle_liburbi_, "urbi_launch"));

  if (!f)
    URBI_ROOT_FATAL(program_, 2, "cannot locate urbi_launch symbol: " << dlerror());

  return f(argc, argv, *this);
}

int
UrbiRoot::urbi_launch(int argc, char** argv)
{
  return urbi_launch(argc, const_cast<const char**>(argv));
}

typedef int(*urbi_main_type)(const std::vector<std::string>& args,
                             UrbiRoot& root,
                             bool block, bool errors);
int
UrbiRoot::urbi_main(const std::vector<std::string>& args,
                    bool block, bool errors)
{
  URBI_ROOT_DEBUG(program_, "loading symbol urbi_main_args from libuobject");
  // Reinterpret-cast fails with gcc3 arm
  urbi_main_type f =
    (urbi_main_type)(dlsym(handle_libuobject_, "urbi_main_args"));

  if (!f)
    URBI_ROOT_FATAL(program_, 2,
                    "cannot locate urbi_launch symbol: " << dlerror());

  return f(args, *this, block, errors);
}
<commit_msg>urbi-root: attempt to fix on OS X.<commit_after>/*
 * Copyright (C) 2009, Gostai S.A.S.
 *
 * This software is provided "as is" without warranty of any kind,
 * either expressed or implied, including but not limited to the
 * implied warranties of fitness for a particular purpose.
 *
 * See the LICENSE file for more information.
 */

#include <sys/stat.h>

#include <cassert>
#include <cstring>
#include <cstdlib>
#include <cstdio>
#include <iostream>

#include <libport/config.h>
#include <libport/foreach.hh>

#include <urbi/urbi-root.hh>
#include <libport/config.h>

#if defined WIN32
# define APPLE_LINUX_WINDOWS(Apple, Linux, Windows) Windows
#elif defined __APPLE__
# define APPLE_LINUX_WINDOWS(Apple, Linux, Windows) Apple
#else
# define APPLE_LINUX_WINDOWS(Apple, Linux, Windows) Linux
#endif

/*--------.
| Helpers |
`--------*/

static std::string
xgetenv(const std::string& var)
{
  const char* res = getenv(var.c_str());
  return res ? res : "";
}

// static void
// xsetenv(const std::string& var, const std::string& val, int force)
// {
// #ifdef WIN32
//   if (force || xgetenv(var).empty())
//     _putenv(strdup((var + "=" + val).c_str()));
// #else
//   setenv(var.c_str(), val.c_str(), force);
// #endif
// }

/*------------.
| Reporting.  |
`------------*/

static bool
debug()
{
  static bool res = xgetenv("GD_LEVEL") == "DUMP";
  return res;
}

# define URBI_ROOT_ECHO(S)                      \
  std::cerr << S << std::endl                   \

# define URBI_ROOT_DEBUG(Self, S)                       \
  do {                                                  \
    if (debug())                                        \
      URBI_ROOT_ECHO(Self << ": " << S);                \
  } while (0)                                           \

# define URBI_ROOT_FATAL(Self, N, S)            \
  do {                                          \
    URBI_ROOT_ECHO(Self << ": " << S);          \
    exit(N);                                    \
  } while (0)

/*-----------------.
| File constants.  |
`-----------------*/

static const std::string libext =
                           APPLE_LINUX_WINDOWS(".dylib", ".so", ".dll");
static const std::string separator =
                           APPLE_LINUX_WINDOWS("/", "/", "\\");
static const std::string libdir =
                           APPLE_LINUX_WINDOWS("lib", "lib", "bin");
static const std::string libuobjects_dir =
                           std::string("/gostai/core/") + LIBPORT_URBI_HOST;

/*-------------------------------------.
| Crapy dynamic portability routines.  |
`-------------------------------------*/

#ifdef WIN32
#define RTLD_LAZY 0
#define RTLD_NOW 0
#define RTLD_GLOBAL 0

static RTLD_HANDLE
dlopen(const char* name, int)
{
  RTLD_HANDLE res = LoadLibrary(name);
  if (res)
  {
    char buf[BUFSIZ];
    GetModuleFileName(res, buf, sizeof buf - 1);
    buf[sizeof buf - 1] = 0;
  }
  return res;
}

static void*
dlsym(RTLD_HANDLE module, const char* name)
{
  return GetProcAddress(module, name);
}

static const char*
dlerror(DWORD err = GetLastError())
{
  static char buf[1024];

  FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
                0, err, 0,
                (LPTSTR)buf, sizeof buf,
                0);

  return buf;
}

#else
# include <dlfcn.h>
#endif

typedef std::vector<std::string> strings_type;
static strings_type
split(std::string lib)
{
  strings_type res;
  size_t pos;
  while ((pos = lib.find(':')) != lib.npos)
  {
    std::string s = lib.substr(0, pos);
    lib = lib.substr(pos + 1, lib.npos);
#ifdef WIN32
    // In case we split "c:\foo" into "c" and "\foo", glue them
    // together again.
    if (s[0] == '\\'
        && !res.empty()
        && res.back().length() == 1)
      res.back() += ':' + s;
    else
#endif
      res.push_back(s);
  }
  if (!lib.empty())
    res.push_back(lib);
  return res;
}

static RTLD_HANDLE
xdlopen(const std::string& path, int flags, const std::string& self)
{
  URBI_ROOT_DEBUG(self, "loading library: " << path);
  RTLD_HANDLE res = dlopen(path.c_str(), flags);
  if (!res)
    URBI_ROOT_FATAL(self, 1,
                    "cannot open library: " << path << ": " << dlerror());
  return res;
}

static
std::string
resolve_symlinks(const std::string& logname, const std::string& s)
{
#if defined WIN32
  return s;
#else
  char path[BUFSIZ];
  strncpy(path, s.c_str(), BUFSIZ);
  path[BUFSIZ - 1] = 0;
  while (readlink(path, path, BUFSIZ) != -1)
    URBI_ROOT_DEBUG(logname, "unrolling symbolic link: " << path);
  return path;
#endif
}

/*-----------.
| UrbiRoot.  |
`-----------*/

UrbiRoot::UrbiRoot(const std::string& program, bool static_build)
  : program_(program)
  , root_()
  , handle_libjpeg_(0)
  , handle_libport_(0)
  , handle_libsched_(0)
  , handle_liburbi_(0)
  , handle_libuobject_(0)
{
  // Find our directory.
  std::string uroot = xgetenv("URBI_ROOT");
  if (!uroot.empty())
  {
    URBI_ROOT_DEBUG(program_,
                    "URBI_ROOT is set, forcing root directory: " << root_);
    root_ = uroot;
  }
  else
  {
    URBI_ROOT_DEBUG(program_, "guessing Urbi root: invoked as: " << program_);
    // Handle the chained symlinks case.
    std::string argv0 = resolve_symlinks(program_, program);

#ifdef WIN32
    size_t pos = argv0.find_last_of("/\\");
#else
    size_t pos = argv0.rfind('/');
#endif
    if (pos == std::string::npos)
    {
      URBI_ROOT_DEBUG(program_,
                      "invoked from the path, looking for ourselves in PATH");
      strings_type path = split(xgetenv("PATH"));
      foreach (const std::string& dir, path)
      {
        struct stat stats;
        std::string file = dir + separator + argv0;
        if (stat(file.c_str(), &stats) == 0)
        {
          URBI_ROOT_DEBUG(program_, "found: " << file);
          root_ = dir + separator + "..";
          URBI_ROOT_DEBUG(program_, "root directory is: " << root_);
          break;
        }
        URBI_ROOT_DEBUG(program_, "not found: " << file);
      }
    }
    else
    {
      root_ = argv0.substr(0, pos) + separator + "..";
      URBI_ROOT_DEBUG(program_,
                      "invoked with a path, setting root to parent directory: "
                      << root_);
    }
  }

  if (root_.empty())
    URBI_ROOT_FATAL(program_, 3, "Unable to find Urbi SDK installation location. Please set URBI_ROOT.");

  // const std::string urbi_path = root_ + separator + "share" + separator + "gostai";
  // xsetenv("URBI_PATH", xgetenv("URBI_PATH") + ":" + urbi_path, true);
  // URBI_ROOT_DEBUG("append to URBI_PATH: " << urbi_path);
  if (!static_build)
  {
#if defined __APPLE__
    xdlopen("/usr/lib/libSystem.B.dylib", RTLD_NOW | RTLD_GLOBAL, program_);
#endif
    handle_libjpeg_        = library_load("jpeg",        "JPEG");
    handle_libport_        = library_load("port",        "PORT");
    handle_libsched_       = library_load("sched",       "SCHED");
    handle_libser_         = library_load("serialize",   "SER");
    handle_liburbi_        = library_load("urbi",        "URBI");
  }
}

RTLD_HANDLE
UrbiRoot::library_load(const std::string& base, const std::string& env)
{
  std::string path;
  const std::string varname = "URBI_ROOT_LIB" + env;
  std::string alt = xgetenv(varname);

  if (alt.empty())
    path = root_ + separator + libdir + separator + "lib" + base + libext;
  else
    path = alt + libext;
  return xdlopen(path, RTLD_NOW | RTLD_GLOBAL, program_);
}

std::string
UrbiRoot::root() const
{
  return root_;
}

std::string
UrbiRoot::core_path() const
{
  return root_ + libuobjects_dir;
}

std::string
UrbiRoot::uobjects_path() const
{
  return core_path() + separator + "uobjects";
}

std::string
UrbiRoot::share_path() const
{
  return root_ + separator + "share/gostai";
}

void
UrbiRoot::load_plugin()
{
  URBI_ROOT_DEBUG(program_, "loading plugin UObject implementation");
  handle_libuobject_ = xdlopen(root_ + libuobjects_dir + separator
                               + "engine/libuobject" + libext,
                               RTLD_NOW | RTLD_GLOBAL, program_);
}

/// Location of Urbi remote libuobject
void
UrbiRoot::load_remote()
{
  URBI_ROOT_DEBUG(program_, "loading remote UObject implementation");
  handle_libuobject_ = xdlopen(root_ + libuobjects_dir + separator
                               + "remote/libuobject" + libext,
                               RTLD_NOW | RTLD_GLOBAL, program_);
}

void
UrbiRoot::load_custom(const std::string& path_)
{
  std::string path = path_ + separator + "libuobject" + libext;
  URBI_ROOT_DEBUG(program_, "loading custom UObject implementation: " << path);
  handle_libuobject_ = xdlopen(path, RTLD_NOW | RTLD_GLOBAL, program_);
}

typedef int(*urbi_launch_type)(int, const char*[], UrbiRoot&);
int
UrbiRoot::urbi_launch(int argc, const char** argv)
{
  URBI_ROOT_DEBUG(program_, "loading symbol urbi_launch from liburbi-launch");
  // Reinterpret-cast fails with gcc3 arm
  urbi_launch_type f = (urbi_launch_type)(dlsym(handle_liburbi_, "urbi_launch"));

  if (!f)
    URBI_ROOT_FATAL(program_, 2, "cannot locate urbi_launch symbol: " << dlerror());

  return f(argc, argv, *this);
}

int
UrbiRoot::urbi_launch(int argc, char** argv)
{
  return urbi_launch(argc, const_cast<const char**>(argv));
}

typedef int(*urbi_main_type)(const std::vector<std::string>& args,
                             UrbiRoot& root,
                             bool block, bool errors);
int
UrbiRoot::urbi_main(const std::vector<std::string>& args,
                    bool block, bool errors)
{
  URBI_ROOT_DEBUG(program_, "loading symbol urbi_main_args from libuobject");
  // Reinterpret-cast fails with gcc3 arm
  urbi_main_type f =
    (urbi_main_type)(dlsym(handle_libuobject_, "urbi_main_args"));

  if (!f)
    URBI_ROOT_FATAL(program_, 2,
                    "cannot locate urbi_launch symbol: " << dlerror());

  return f(args, *this, block, errors);
}
<|endoftext|>


<commit_before>/*
 * Copyright (C) 2009, 2010, Gostai S.A.S.
 *
 * This software is provided "as is" without warranty of any kind,
 * either expressed or implied, including but not limited to the
 * implied warranties of fitness for a particular purpose.
 *
 * See the LICENSE file for more information.
 */

#include <libport/sys/stat.h>

#include <libport/cassert>
#include <libport/cstring>
#include <libport/cstdlib>
#include <libport/cstdio>
#include <iostream>

#include <libport/config.h>
#include <libport/foreach.hh>
#include <libport/sysexits.hh>

#include <urbi/urbi-root.hh>
#include <libport/config.h>

#if defined WIN32
# define APPLE_LINUX_WINDOWS(Apple, Linux, Windows) Windows
#elif defined __APPLE__
# define APPLE_LINUX_WINDOWS(Apple, Linux, Windows) Apple
#else
# define APPLE_LINUX_WINDOWS(Apple, Linux, Windows) Linux
#endif

/*----------.
| Helpers.  |
`----------*/

static std::string
mygetenv(const std::string& var, const std::string& val = "")
{
  const char* res = getenv(var.c_str());
  return res ? std::string(res) : val;
}

// static void
// xsetenv(const std::string& var, const std::string& val, int force)
// {
// #ifdef WIN32
//   if (force || mygetenv(var).empty())
//     _putenv(strdup((var + "=" + val).c_str()));
// #else
//   setenv(var.c_str(), val.c_str(), force);
// #endif
// }

/*------------.
| Reporting.  |
`------------*/

static bool
debug()
{
  static bool res = mygetenv("GD_LEVEL") == "DUMP";
  return res;
}

# define URBI_ROOT_ECHO(S)                      \
  std::cerr << S << std::endl                   \

# define URBI_ROOT_DEBUG(Self, S)                       \
  do {                                                  \
    if (debug())                                        \
      URBI_ROOT_ECHO(Self << ": " << S);                \
  } while (0)                                           \

# define URBI_ROOT_FATAL(Self, N, S)            \
  do {                                          \
    URBI_ROOT_ECHO(Self << ": " << S);          \
    exit(N);                                    \
  } while (0)

/*-----------------.
| File constants.  |
`-----------------*/

static const std::string libext =
                           APPLE_LINUX_WINDOWS(".dylib", ".so", ".dll");
static const std::string separator =
                           APPLE_LINUX_WINDOWS("/", "/", "\\");
static const std::string libdir =
                           APPLE_LINUX_WINDOWS("lib", "lib", "bin");

/// Join path components.
static
std::string
operator/(const std::string& lhs, const std::string& rhs)
{
  return (lhs.empty() ? rhs
          : rhs.empty() ? lhs
          : lhs + separator + rhs);
}

/*-------------------------------------.
| Crapy dynamic portability routines.  |
`-------------------------------------*/

#ifdef WIN32
#define RTLD_LAZY 0
#define RTLD_NOW 0
#define RTLD_GLOBAL 0

static RTLD_HANDLE
dlopen(const char* name, int)
{
  RTLD_HANDLE res = LoadLibrary(name);
  if (res)
  {
    char buf[BUFSIZ];
    GetModuleFileName(res, buf, sizeof buf - 1);
    buf[sizeof buf - 1] = 0;
  }
  return res;
}

static void*
dlsym(RTLD_HANDLE module, const char* name)
{
  return GetProcAddress(module, name);
}

static const char*
dlerror(DWORD err = GetLastError())
{
  static char buf[1024];

  FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
                0, err, 0,
                (LPTSTR)buf, sizeof buf,
                0);

  return buf;
}

#else
# include <dlfcn.h>
#endif

typedef std::vector<std::string> strings_type;
static strings_type
split(std::string lib)
{
  strings_type res;
  size_t pos;
  while ((pos = lib.find(':')) != lib.npos)
  {
    std::string s = lib.substr(0, pos);
    lib = lib.substr(pos + 1, lib.npos);
#ifdef WIN32
    // In case we split "c:\foo" into "c" and "\foo", glue them
    // together again.
    if (s[0] == '\\'
        && !res.empty()
        && res.back().length() == 1)
      res.back() += ':' + s;
    else
#endif
      res.push_back(s);
  }
  if (!lib.empty())
    res.push_back(lib);
  return res;
}

/// \a path does not include the extension.
static
RTLD_HANDLE
xdlopen(const std::string& program,
        const std::string& msg,
        std::string path,
        sysexit status = EX_FAIL,
        int flags = RTLD_LAZY | RTLD_GLOBAL)
{
  path += libext;
  URBI_ROOT_DEBUG(program, "loading library: " << path << " (" << msg << ")");
  if (RTLD_HANDLE res = dlopen(path.c_str(), flags))
    return res;
  else
    URBI_ROOT_FATAL(program, status,
                    "cannot open library: " << path << ": " << dlerror());
}

template <typename Res>
static
Res
xdlsym(const std::string& program,
       const char* modname, RTLD_HANDLE module,
       const char* name)
{
  URBI_ROOT_DEBUG(program, "loading symbol " << name << " from " << modname);
  // Reinterpret-cast fails with gcc3 arm.
  if (Res res = (Res)(dlsym(module, name)))
    return res;
  else
    URBI_ROOT_FATAL(program, 2,
                    "cannot locate " << name << " symbol: " << dlerror());
}

static
std::string
resolve_symlinks(const std::string& logname, const std::string& s)
{
#if defined WIN32
  return s;
#else
  char path[BUFSIZ];
  strncpy(path, s.c_str(), BUFSIZ);
  path[BUFSIZ - 1] = 0;
  while (readlink(path, path, BUFSIZ) != -1)
    URBI_ROOT_DEBUG(logname, "unrolling symbolic link: " << path);
  return path;
#endif
}

/*-----------.
| UrbiRoot.  |
`-----------*/

UrbiRoot::UrbiRoot(const std::string& program, bool static_build)
  : program_(program)
  , root_()
  , handle_libjpeg_(0)
  , handle_libport_(0)
  , handle_libsched_(0)
  , handle_liburbi_(0)
  , handle_libuobject_(0)
{
  // Find our directory.
  std::string uroot = mygetenv("URBI_ROOT");
  if (!uroot.empty())
  {
    URBI_ROOT_DEBUG(program_,
                    "URBI_ROOT is set, forcing root directory: " << root_);
    root_ = uroot;
  }
  else
  {
    URBI_ROOT_DEBUG(program_, "guessing Urbi root: invoked as: " << program_);
    // Handle the chained symlinks case.
    std::string argv0 = resolve_symlinks(program_, program);

#ifdef WIN32
    size_t pos = argv0.find_last_of("/\\");
#else
    size_t pos = argv0.rfind('/');
#endif
    if (pos == std::string::npos)
    {
      URBI_ROOT_DEBUG(program_,
                      "invoked from the path, looking for ourselves in PATH");
      strings_type path = split(mygetenv("PATH"));
      foreach (const std::string& dir, path)
      {
        struct stat stats;
        std::string file = dir / argv0;
        if (stat(file.c_str(), &stats) == 0)
        {
          URBI_ROOT_DEBUG(program_, "found: " << file);
          root_ = dir / "..";
          URBI_ROOT_DEBUG(program_, "root directory is: " << root_);
          break;
        }
        URBI_ROOT_DEBUG(program_, "not found: " << file);
      }
    }
    else
    {
      root_ = argv0.substr(0, pos) / "..";
      URBI_ROOT_DEBUG(program_,
                      "invoked with a path, setting root to parent directory: "
                      << root_);
    }
  }

  if (root_.empty())
    URBI_ROOT_FATAL(program_, 3,
                    "Unable to find Urbi SDK installation location. "
                    "Please set URBI_ROOT.");

  if (!static_build)
  {
    handle_libjpeg_      = library_load("jpeg");
    handle_libport_      = library_load("port");
    handle_libsched_     = library_load("sched");
    handle_libserialize_ = library_load("serialize");
    handle_liburbi_      = library_load("urbi");
  }
}

RTLD_HANDLE
UrbiRoot::library_load(const std::string& base)
{
  std::string envvar = "URBI_ROOT_LIB" + base;
  foreach (char& s, envvar)
    s = toupper(s);

  return
    xdlopen(program_,
            base,
            mygetenv(envvar,
                     root() / libdir / "lib" + base + LIBPORT_LIBSFX));
}

const std::string&
UrbiRoot::root() const
{
  return root_;
}

std::string
UrbiRoot::core_path() const
{
  return root() / "gostai";
}

std::string
UrbiRoot::uobjects_path() const
{
  return core_path() / "uobjects";
}

std::string
UrbiRoot::share_path() const
{
  return root() / "gostai" / "share";
}

void
UrbiRoot::load_plugin()
{
  handle_libuobject_ =
    xdlopen(program_,
            "plugin UObject implementation",
            mygetenv("URBI_ROOT_LIBPLUGIN",
                     core_path() / "engine" / "libuobject" LIBPORT_LIBSFX),
            // This exit status is understood by the test suite.  It
            // helps it skipping SDK Remote tests that cannot run
            // without Urbi SDK.
            EX_OSFILE);
}

/// Location of Urbi remote libuobject
void
UrbiRoot::load_remote()
{
  handle_libuobject_ =
    xdlopen(program_,
            "remote UObject implementation",
            mygetenv("URBI_ROOT_LIBREMOTE",
                     core_path() / "remote" / "libuobject" LIBPORT_LIBSFX),
            EX_OSFILE);
}

void
UrbiRoot::load_custom(const std::string& path_)
{
  handle_libuobject_ =
    xdlopen(program_,
            "custom UObject implementation",
            path_ / "libuobject",
            EX_OSFILE);
}

typedef int(*urbi_launch_type)(int, const char*[], UrbiRoot&);
int
UrbiRoot::urbi_launch(int argc, const char** argv)
{
  urbi_launch_type f =
    xdlsym<urbi_launch_type>(program_,
                             "liburbi-launch", handle_liburbi_,
                             "urbi_launch");
  return f(argc, argv, *this);
}

int
UrbiRoot::urbi_launch(int argc, char** argv)
{
  return urbi_launch(argc, const_cast<const char**>(argv));
}

typedef int(*urbi_main_type)(const std::vector<std::string>& args,
                             UrbiRoot& root,
                             bool block, bool errors);
int
UrbiRoot::urbi_main(const std::vector<std::string>& args,
                    bool block, bool errors)
{
  urbi_main_type f =
    xdlsym<urbi_main_type>(program_,
                           "libuobject", handle_libuobject_,
                           "urbi_main_args");
  URBI_ROOT_DEBUG(program_, "command line: ");
  foreach (const std::string& arg, args)
    URBI_ROOT_DEBUG(program_, "  " << arg);

  return f(args, *this, block, errors);
}
<commit_msg>build: fix location of libraries.<commit_after>/*
 * Copyright (C) 2009, 2010, Gostai S.A.S.
 *
 * This software is provided "as is" without warranty of any kind,
 * either expressed or implied, including but not limited to the
 * implied warranties of fitness for a particular purpose.
 *
 * See the LICENSE file for more information.
 */

#include <libport/sys/stat.h>

#include <libport/cassert>
#include <libport/cstring>
#include <libport/cstdlib>
#include <libport/cstdio>
#include <iostream>

#include <libport/config.h>
#include <libport/foreach.hh>
#include <libport/sysexits.hh>

#include <urbi/urbi-root.hh>
#include <libport/config.h>

#if defined WIN32
# define APPLE_LINUX_WINDOWS(Apple, Linux, Windows) Windows
#elif defined __APPLE__
# define APPLE_LINUX_WINDOWS(Apple, Linux, Windows) Apple
#else
# define APPLE_LINUX_WINDOWS(Apple, Linux, Windows) Linux
#endif

/*----------.
| Helpers.  |
`----------*/

static std::string
mygetenv(const std::string& var, const std::string& val = "")
{
  const char* res = getenv(var.c_str());
  return res ? std::string(res) : val;
}

// static void
// xsetenv(const std::string& var, const std::string& val, int force)
// {
// #ifdef WIN32
//   if (force || mygetenv(var).empty())
//     _putenv(strdup((var + "=" + val).c_str()));
// #else
//   setenv(var.c_str(), val.c_str(), force);
// #endif
// }

/*------------.
| Reporting.  |
`------------*/

static bool
debug()
{
  static bool res = mygetenv("GD_LEVEL") == "DUMP";
  return res;
}

# define URBI_ROOT_ECHO(S)                      \
  std::cerr << S << std::endl                   \

# define URBI_ROOT_DEBUG(Self, S)                       \
  do {                                                  \
    if (debug())                                        \
      URBI_ROOT_ECHO(Self << ": " << S);                \
  } while (0)                                           \

# define URBI_ROOT_FATAL(Self, N, S)            \
  do {                                          \
    URBI_ROOT_ECHO(Self << ": " << S);          \
    exit(N);                                    \
  } while (0)

/*-----------------.
| File constants.  |
`-----------------*/

static const std::string libext =
                           APPLE_LINUX_WINDOWS(".dylib", ".so", ".dll");
static const std::string separator =
                           APPLE_LINUX_WINDOWS("/", "/", "\\");
static const std::string libdir =
                           APPLE_LINUX_WINDOWS("lib", "lib", "bin");

/// Join path components.
static
std::string
operator/(const std::string& lhs, const std::string& rhs)
{
  return (lhs.empty() ? rhs
          : rhs.empty() ? lhs
          : lhs + separator + rhs);
}

/*-------------------------------------.
| Crapy dynamic portability routines.  |
`-------------------------------------*/

#ifdef WIN32
#define RTLD_LAZY 0
#define RTLD_NOW 0
#define RTLD_GLOBAL 0

static RTLD_HANDLE
dlopen(const char* name, int)
{
  RTLD_HANDLE res = LoadLibrary(name);
  if (res)
  {
    char buf[BUFSIZ];
    GetModuleFileName(res, buf, sizeof buf - 1);
    buf[sizeof buf - 1] = 0;
  }
  return res;
}

static void*
dlsym(RTLD_HANDLE module, const char* name)
{
  return GetProcAddress(module, name);
}

static const char*
dlerror(DWORD err = GetLastError())
{
  static char buf[1024];

  FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
                0, err, 0,
                (LPTSTR)buf, sizeof buf,
                0);

  return buf;
}

#else
# include <dlfcn.h>
#endif

typedef std::vector<std::string> strings_type;
static strings_type
split(std::string lib)
{
  strings_type res;
  size_t pos;
  while ((pos = lib.find(':')) != lib.npos)
  {
    std::string s = lib.substr(0, pos);
    lib = lib.substr(pos + 1, lib.npos);
#ifdef WIN32
    // In case we split "c:\foo" into "c" and "\foo", glue them
    // together again.
    if (s[0] == '\\'
        && !res.empty()
        && res.back().length() == 1)
      res.back() += ':' + s;
    else
#endif
      res.push_back(s);
  }
  if (!lib.empty())
    res.push_back(lib);
  return res;
}

/// \a path does not include the extension.
static
RTLD_HANDLE
xdlopen(const std::string& program,
        const std::string& msg,
        std::string path,
        sysexit status = EX_FAIL,
        int flags = RTLD_LAZY | RTLD_GLOBAL)
{
  path += libext;
  URBI_ROOT_DEBUG(program, "loading library: " << path << " (" << msg << ")");
  if (RTLD_HANDLE res = dlopen(path.c_str(), flags))
    return res;
  else
    URBI_ROOT_FATAL(program, status,
                    "cannot open library: " << path << ": " << dlerror());
}

template <typename Res>
static
Res
xdlsym(const std::string& program,
       const char* modname, RTLD_HANDLE module,
       const char* name)
{
  URBI_ROOT_DEBUG(program, "loading symbol " << name << " from " << modname);
  // Reinterpret-cast fails with gcc3 arm.
  if (Res res = (Res)(dlsym(module, name)))
    return res;
  else
    URBI_ROOT_FATAL(program, 2,
                    "cannot locate " << name << " symbol: " << dlerror());
}

static
std::string
resolve_symlinks(const std::string& logname, const std::string& s)
{
#if defined WIN32
  return s;
#else
  char path[BUFSIZ];
  strncpy(path, s.c_str(), BUFSIZ);
  path[BUFSIZ - 1] = 0;
  while (readlink(path, path, BUFSIZ) != -1)
    URBI_ROOT_DEBUG(logname, "unrolling symbolic link: " << path);
  return path;
#endif
}

/*-----------.
| UrbiRoot.  |
`-----------*/

UrbiRoot::UrbiRoot(const std::string& program, bool static_build)
  : program_(program)
  , root_()
  , handle_libjpeg_(0)
  , handle_libport_(0)
  , handle_libsched_(0)
  , handle_liburbi_(0)
  , handle_libuobject_(0)
{
  // Find our directory.
  std::string uroot = mygetenv("URBI_ROOT");
  if (!uroot.empty())
  {
    URBI_ROOT_DEBUG(program_,
                    "URBI_ROOT is set, forcing root directory: " << root_);
    root_ = uroot;
  }
  else
  {
    URBI_ROOT_DEBUG(program_, "guessing Urbi root: invoked as: " << program_);
    // Handle the chained symlinks case.
    std::string argv0 = resolve_symlinks(program_, program);

#ifdef WIN32
    size_t pos = argv0.find_last_of("/\\");
#else
    size_t pos = argv0.rfind('/');
#endif
    if (pos == std::string::npos)
    {
      URBI_ROOT_DEBUG(program_,
                      "invoked from the path, looking for ourselves in PATH");
      strings_type path = split(mygetenv("PATH"));
      foreach (const std::string& dir, path)
      {
        struct stat stats;
        std::string file = dir / argv0;
        if (stat(file.c_str(), &stats) == 0)
        {
          URBI_ROOT_DEBUG(program_, "found: " << file);
          root_ = dir / "..";
          URBI_ROOT_DEBUG(program_, "root directory is: " << root_);
          break;
        }
        URBI_ROOT_DEBUG(program_, "not found: " << file);
      }
    }
    else
    {
      root_ = argv0.substr(0, pos) / "..";
      URBI_ROOT_DEBUG(program_,
                      "invoked with a path, setting root to parent directory: "
                      << root_);
    }
  }

  if (root_.empty())
    URBI_ROOT_FATAL(program_, 3,
                    "Unable to find Urbi SDK installation location. "
                    "Please set URBI_ROOT.");

  if (!static_build)
  {
    handle_libjpeg_      = library_load("jpeg");
    handle_libport_      = library_load("port");
    handle_libsched_     = library_load("sched");
    handle_libserialize_ = library_load("serialize");
    handle_liburbi_      = library_load("urbi");
  }
}

RTLD_HANDLE
UrbiRoot::library_load(const std::string& base)
{
  std::string envvar = "URBI_ROOT_LIB" + base;
  foreach (char& s, envvar)
    s = toupper(s);

  return
    xdlopen(program_,
            base,
            mygetenv(envvar,
                     root() / libdir / "lib" + base + LIBPORT_LIBSFX));
}

const std::string&
UrbiRoot::root() const
{
  return root_;
}

std::string
UrbiRoot::core_path() const
{
  return root() / "lib" / "gostai";
}

std::string
UrbiRoot::uobjects_path() const
{
  return core_path() / "uobjects";
}

std::string
UrbiRoot::share_path() const
{
  return root() / "gostai" / "share";
}

void
UrbiRoot::load_plugin()
{
  handle_libuobject_ =
    xdlopen(program_,
            "plugin UObject implementation",
            mygetenv("URBI_ROOT_LIBPLUGIN",
                     core_path() / "engine" / "libuobject" LIBPORT_LIBSFX),
            // This exit status is understood by the test suite.  It
            // helps it skipping SDK Remote tests that cannot run
            // without Urbi SDK.
            EX_OSFILE);
}

/// Location of Urbi remote libuobject
void
UrbiRoot::load_remote()
{
  handle_libuobject_ =
    xdlopen(program_,
            "remote UObject implementation",
            mygetenv("URBI_ROOT_LIBREMOTE",
                     core_path() / "remote" / "libuobject" LIBPORT_LIBSFX),
            EX_OSFILE);
}

void
UrbiRoot::load_custom(const std::string& path_)
{
  handle_libuobject_ =
    xdlopen(program_,
            "custom UObject implementation",
            path_ / "libuobject",
            EX_OSFILE);
}

typedef int(*urbi_launch_type)(int, const char*[], UrbiRoot&);
int
UrbiRoot::urbi_launch(int argc, const char** argv)
{
  urbi_launch_type f =
    xdlsym<urbi_launch_type>(program_,
                             "liburbi-launch", handle_liburbi_,
                             "urbi_launch");
  return f(argc, argv, *this);
}

int
UrbiRoot::urbi_launch(int argc, char** argv)
{
  return urbi_launch(argc, const_cast<const char**>(argv));
}

typedef int(*urbi_main_type)(const std::vector<std::string>& args,
                             UrbiRoot& root,
                             bool block, bool errors);
int
UrbiRoot::urbi_main(const std::vector<std::string>& args,
                    bool block, bool errors)
{
  urbi_main_type f =
    xdlsym<urbi_main_type>(program_,
                           "libuobject", handle_libuobject_,
                           "urbi_main_args");
  URBI_ROOT_DEBUG(program_, "command line: ");
  foreach (const std::string& arg, args)
    URBI_ROOT_DEBUG(program_, "  " << arg);

  return f(args, *this, block, errors);
}
<|endoftext|>


<commit_before>/*
 *  illarionserver - server for the game Illarion
 *  Copyright 2011 Illarion e.V.
 *
 *  This file is part of illarionserver.
 *
 *  illarionserver is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU Affero General Public License as published by
 *  the Free Software Foundation, either version 3 of the License, or
 *  (at your option) any later version.
 *
 *  illarionserver 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 Affero General Public License for more details.
 *
 *  You should have received a copy of the GNU Affero General Public License
 *  along with illarionserver.  If not, see <http://www.gnu.org/licenses/>.
 */

#ifndef LUA_SCRIPT_HPP
#define LUA_SCRIPT_HPP

extern "C" {
#include <lua.h>
}

#include "Item.hpp"
#include "Logger.hpp"
#include "character_ptr.hpp"
#include "globals.hpp"

#include <chrono>
#include <luabind/luabind.hpp>
#include <luabind/object.hpp>
#include <map>
#include <stdexcept>

class Character;
class World;
class Dialog;

class ScriptException : public std::runtime_error {
public:
    explicit ScriptException(const std::string &s) : std::runtime_error(s) {}
};

enum SouTarTypes {
    LUA_NONE = 0,      /**< not a correct type (only for initialisation) */
    LUA_FIELD = 1,     /**< target was a field */
    LUA_ITEM = 2,      /**< target was a item */
    LUA_CHARACTER = 3, /**< target was character*/
    LUA_DIALOG = 4
};

enum LtaStates {
    LTS_NOLTACTION = 0,       /**< no longtime action in this script */
    LTS_ACTIONABORTED = 1,    /**< long time action was aborted */
    LTS_ACTIONSUCCESSFULL = 2 /**< long time action was performed sucessfulle*/
};

struct SouTar {
    Character *character = nullptr;
    ScriptItem item;
    SouTarTypes Type = LUA_NONE;
    position pos{};
    unsigned int dialog = 0;
};

class LuaScript {
public:
    LuaScript();
    explicit LuaScript(std::string filename);
    LuaScript(const std::string &code, const std::string &scriptname);
    LuaScript(const LuaScript &) = delete;
    auto operator=(const LuaScript &) -> LuaScript & = delete;
    LuaScript(LuaScript &&) = default;
    auto operator=(LuaScript &&) -> LuaScript & = default;
    virtual ~LuaScript();

    [[nodiscard]] auto getFileName() const -> std::string { return _filename; }

    static auto getLuaState() -> lua_State * { return _luaState; }

    static void shutdownLua();
    [[nodiscard]] auto existsEntrypoint(const std::string &entrypoint) const -> bool;
    void addQuestScript(const std::string &entrypoint, const std::shared_ptr<LuaScript> &script);

    template <typename T> static void executeDialogCallback(T &dialog) {
        luabind::object callback = dialog.getCallback();

        if (luabind::type(callback) != LUA_TFUNCTION) {
            return;
        }

        try {
            callback(dialog);
        } catch (luabind::error &e) {
            lua_State *L = e.state();
            Logger::error(LogFacility::Script) << "Exception in " << dialog.getClassName() << " callback"
                                               << ": " << std::string(lua_tostring(L, -1)) << Log::end;
            lua_pop(L, 1);
        }
    }

    template <typename U, typename T> static auto executeDialogCallback(T &dialog) -> U {
        luabind::object callback = dialog.getCallback();

        if (luabind::type(callback) != LUA_TFUNCTION) {
            return U();
        }

        try {
            return luabind::object_cast<U>(callback(dialog));
        } catch (luabind::cast_failed &e) {
            const std::string &expectedType = e.info().name();
            Logger::error(LogFacility::Script) << "Invalid return type in " << dialog.getClassName() << " callback: "
                                               << " Expected type " << expectedType << Log::end;
        } catch (luabind::error &e) {
            lua_State *L = e.state();
            Logger::error(LogFacility::Script) << "Exception in " << dialog.getClassName() << " callback"
                                               << ": " << lua_tostring(L, -1) << Log::end;
            lua_pop(L, 1);
        }

        return U();
    }

    [[noreturn]] static void triggerScriptError(const std::string &msg);
    static void writeDeprecatedMsg(const std::string &deprecatedEntity);
    static void writeDebugMsg(const std::string &msg);

protected:
    static lua_State *_luaState;
    static bool initialized;

    template <typename... Args> void callEntrypoint(const std::string &entrypoint, const Args &...args) {
        setCurrentWorldScript();

        if (!callQuestEntrypoint(entrypoint, args...)) {
            safeCall(entrypoint, args...);
        }
    }
    template <typename T, typename... Args>
    auto callEntrypoint(const std::string &entrypoint, const Args &...args) -> T {
        setCurrentWorldScript();
        callQuestEntrypoint(entrypoint, args...);
        return safeCall<T, Args...>(entrypoint, args...);
    }

private:
    static void initialize();
    void loadIntoLuaState();
    void handleLuaLoadError(int errorCode);
    void handleLuaCallError(int errorCode);
    static void init_base_functions();
    static auto add_backtrace(lua_State *L) -> int;
    static void writeErrorMsg();
    void writeCastErrorMsg(const std::string &entryPoint, const luabind::cast_failed &e) const;
    void checkRunTime(const std::string &entryPoint, const std::chrono::nanoseconds duration) const;
    void setCurrentWorldScript();
    auto buildEntrypoint(const std::string &entrypoint) -> luabind::object;
    [[nodiscard]] auto existsQuestEntrypoint(const std::string &entrypoint) const -> bool;

    template <typename... Args> auto callQuestEntrypoint(const std::string &entrypoint, const Args &...args) -> bool {
        auto entrypointRange = questScripts.equal_range(entrypoint);
        bool foundQuest = false;

        for (auto it = entrypointRange.first; it != entrypointRange.second; ++it) {
            foundQuest = foundQuest || it->second->safeCall<bool>(entrypoint, args...);
        }

        return foundQuest;
    }

    template <typename... Args> void safeCall(const std::string &entrypoint, const Args &...args) {
        try {
            using clock = std::chrono::steady_clock;

            auto luaEntrypoint = buildEntrypoint(entrypoint);

            const auto startTime = clock::now();
            luaEntrypoint(args...);
            const auto duration = clock::now() - startTime;

            checkRunTime(entrypoint, duration);
        } catch (const luabind::error &e) {
            writeErrorMsg();
        }
    }
    template <typename T, typename... Args> auto safeCall(const std::string &entrypoint, const Args &...args) -> T {
        try {
            using clock = std::chrono::steady_clock;

            auto luaEntrypoint = buildEntrypoint(entrypoint);

            const auto startTime = clock::now();
            auto result = luaEntrypoint(args...);
            const auto duration = clock::now() - startTime;

            checkRunTime(entrypoint, duration);

            return luabind::object_cast<T>(result);
        } catch (luabind::cast_failed &e) {
            writeCastErrorMsg(entrypoint, e);
        } catch (luabind::error &e) {
            writeErrorMsg();
        }

        return T();
    }

    std::string _filename{};
    std::string luafile{};
    using QuestScripts = std::multimap<const std::string, std::shared_ptr<LuaScript>>;
    QuestScripts questScripts;
};

#endif
<commit_msg>clang format<commit_after>/*
 *  illarionserver - server for the game Illarion
 *  Copyright 2011 Illarion e.V.
 *
 *  This file is part of illarionserver.
 *
 *  illarionserver is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU Affero General Public License as published by
 *  the Free Software Foundation, either version 3 of the License, or
 *  (at your option) any later version.
 *
 *  illarionserver 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 Affero General Public License for more details.
 *
 *  You should have received a copy of the GNU Affero General Public License
 *  along with illarionserver.  If not, see <http://www.gnu.org/licenses/>.
 */

#ifndef LUA_SCRIPT_HPP
#define LUA_SCRIPT_HPP

extern "C" {
#include <lua.h>
}

#include "Item.hpp"
#include "Logger.hpp"
#include "character_ptr.hpp"
#include "globals.hpp"

#include <chrono>
#include <luabind/luabind.hpp>
#include <luabind/object.hpp>
#include <map>
#include <stdexcept>

class Character;
class World;
class Dialog;

class ScriptException : public std::runtime_error {
public:
    explicit ScriptException(const std::string &s) : std::runtime_error(s) {}
};

enum SouTarTypes {
    LUA_NONE = 0,      /**< not a correct type (only for initialisation) */
    LUA_FIELD = 1,     /**< target was a field */
    LUA_ITEM = 2,      /**< target was a item */
    LUA_CHARACTER = 3, /**< target was character*/
    LUA_DIALOG = 4
};

enum LtaStates {
    LTS_NOLTACTION = 0,       /**< no longtime action in this script */
    LTS_ACTIONABORTED = 1,    /**< long time action was aborted */
    LTS_ACTIONSUCCESSFULL = 2 /**< long time action was performed sucessfulle*/
};

struct SouTar {
    Character *character = nullptr;
    ScriptItem item;
    SouTarTypes Type = LUA_NONE;
    position pos{};
    unsigned int dialog = 0;
};

class LuaScript {
public:
    LuaScript();
    explicit LuaScript(std::string filename);
    LuaScript(const std::string &code, const std::string &scriptname);
    LuaScript(const LuaScript &) = delete;
    auto operator=(const LuaScript &) -> LuaScript & = delete;
    LuaScript(LuaScript &&) = default;
    auto operator=(LuaScript &&) -> LuaScript & = default;
    virtual ~LuaScript();

    [[nodiscard]] auto getFileName() const -> std::string { return _filename; }

    static auto getLuaState() -> lua_State * { return _luaState; }

    static void shutdownLua();
    [[nodiscard]] auto existsEntrypoint(const std::string &entrypoint) const -> bool;
    void addQuestScript(const std::string &entrypoint, const std::shared_ptr<LuaScript> &script);

    template <typename T> static void executeDialogCallback(T &dialog) {
        luabind::object callback = dialog.getCallback();

        if (luabind::type(callback) != LUA_TFUNCTION) {
            return;
        }

        try {
            callback(dialog);
        } catch (luabind::error &e) {
            lua_State *L = e.state();
            Logger::error(LogFacility::Script) << "Exception in " << dialog.getClassName() << " callback"
                                               << ": " << std::string(lua_tostring(L, -1)) << Log::end;
            lua_pop(L, 1);
        }
    }

    template <typename U, typename T> static auto executeDialogCallback(T &dialog) -> U {
        luabind::object callback = dialog.getCallback();

        if (luabind::type(callback) != LUA_TFUNCTION) {
            return U();
        }

        try {
            return luabind::object_cast<U>(callback(dialog));
        } catch (luabind::cast_failed &e) {
            const std::string &expectedType = e.info().name();
            Logger::error(LogFacility::Script) << "Invalid return type in " << dialog.getClassName() << " callback: "
                                               << " Expected type " << expectedType << Log::end;
        } catch (luabind::error &e) {
            lua_State *L = e.state();
            Logger::error(LogFacility::Script) << "Exception in " << dialog.getClassName() << " callback"
                                               << ": " << lua_tostring(L, -1) << Log::end;
            lua_pop(L, 1);
        }

        return U();
    }

    [[noreturn]] static void triggerScriptError(const std::string &msg);
    static void writeDeprecatedMsg(const std::string &deprecatedEntity);
    static void writeDebugMsg(const std::string &msg);

protected:
    static lua_State *_luaState;
    static bool initialized;

    template <typename... Args> void callEntrypoint(const std::string &entrypoint, const Args &...args) {
        setCurrentWorldScript();

        if (!callQuestEntrypoint(entrypoint, args...)) {
            safeCall(entrypoint, args...);
        }
    }
    template <typename T, typename... Args>
    auto callEntrypoint(const std::string &entrypoint, const Args &...args) -> T {
        setCurrentWorldScript();
        callQuestEntrypoint(entrypoint, args...);
        return safeCall<T, Args...>(entrypoint, args...);
    }

private:
    static void initialize();
    void loadIntoLuaState();
    void handleLuaLoadError(int errorCode);
    void handleLuaCallError(int errorCode);
    static void init_base_functions();
    static auto add_backtrace(lua_State *L) -> int;
    static void writeErrorMsg();
    void writeCastErrorMsg(const std::string &entryPoint, const luabind::cast_failed &e) const;
    void checkRunTime(const std::string &entryPoint, const std::chrono::nanoseconds duration) const;
    void setCurrentWorldScript();
    auto buildEntrypoint(const std::string &entrypoint) -> luabind::object;
    [[nodiscard]] auto existsQuestEntrypoint(const std::string &entrypoint) const -> bool;

    template <typename... Args> auto callQuestEntrypoint(const std::string &entrypoint, const Args &...args) -> bool {
        auto entrypointRange = questScripts.equal_range(entrypoint);
        bool foundQuest = false;

        for (auto it = entrypointRange.first; it != entrypointRange.second; ++it) {
            foundQuest = foundQuest || it->second->safeCall<bool>(entrypoint, args...);
        }

        return foundQuest;
    }

    template <typename... Args> void safeCall(const std::string &entrypoint, const Args &...args) {
        try {
            using clock = std::chrono::steady_clock;

            auto luaEntrypoint = buildEntrypoint(entrypoint);

            const auto startTime = clock::now();
            luaEntrypoint(args...);
            const auto duration = clock::now() - startTime;

            checkRunTime(entrypoint, duration);
        } catch (const luabind::error &e) {
            writeErrorMsg();
        }
    }
    template <typename T, typename... Args> auto safeCall(const std::string &entrypoint, const Args &...args) -> T {
        try {
            using clock = std::chrono::steady_clock;

            auto luaEntrypoint = buildEntrypoint(entrypoint);

            const auto startTime = clock::now();
            auto result = luaEntrypoint(args...);
            const auto duration = clock::now() - startTime;

            checkRunTime(entrypoint, duration);

            return luabind::object_cast<T>(result);
        } catch (luabind::cast_failed &e) {
            writeCastErrorMsg(entrypoint, e);
        } catch (luabind::error &e) {
            writeErrorMsg();
        }

        return T();
    }

    std::string _filename{};
    std::string luafile{};
    using QuestScripts = std::multimap<const std::string, std::shared_ptr<LuaScript>>;
    QuestScripts questScripts;
};

#endif
<|endoftext|>