<commit_before>/**
 * @file DartLoader.cpp
 */

#include "DartLoader.h"
#include <map>
#include "../urdf_parser/urdf_parser.h"
#include <iostream>
#include <fstream>
#include "dynamics/BodyNodeDynamics.h"
#include "dynamics/SkeletonDynamics.h"
#include "robotics/World.h"
#include "robotics/Robot.h"
#include "robotics/Object.h"

/**
 * @function DartLoader
 * @brief Constructor
 */
DartLoader::DartLoader() {
}

/**
 * @function ~DartLoader
 * @brief Destructor
 */
DartLoader::~DartLoader() {

}

/**
 * @function parseSkeleton
 */
dynamics::SkeletonDynamics* DartLoader::parseSkeleton( std::string _urdfFile ) {

  std::string xml_string;
  xml_string = readXmlToString( _urdfFile );

  boost::shared_ptr<urdf::ModelInterface> skeletonModel = urdf::parseURDF( xml_string );

  return modelInterfaceToSkeleton( skeletonModel );

}

/**
 * @function parseRobot
 */
robotics::Robot* DartLoader::parseRobot( std::string _urdfFile ) {

  std::string xml_string;
  xml_string = readXmlToString( _urdfFile );
  boost::shared_ptr<urdf::ModelInterface> robotModel = urdf::parseURDF( xml_string );
  return modelInterfaceToRobot( robotModel );
}

/**
 * @function parseObject
 */
robotics::Object* DartLoader::parseObject( std::string _urdfFile ) {

  std::string xml_string;
  xml_string = readXmlToString( _urdfFile );
  boost::shared_ptr<urdf::ModelInterface> objectModel = urdf::parseURDF( xml_string );
  return modelInterfaceToObject( objectModel );

}

/**
 * @function parseWorld
 */
robotics::World* DartLoader::parseWorld( std::string _urdfFile ) {

  mWorldPath = _urdfFile;

  // Change path to a Unix-style path if given a Windows one
  // Windows can handle Unix-style paths (apparently)
  std::replace( mWorldPath.begin(), mWorldPath.end(), '\\' , '/' );
  mPath = mWorldPath.substr( 0, mWorldPath.rfind("/") + 1 );

  // std::cout<< " mPath :" << mPath << std::endl;

  robotics::World* world = new robotics::World();
	robotics::Robot* robot;
  robotics::Object* object;

  std::string xml_string;
  xml_string = readXmlToString( _urdfFile );

  boost::shared_ptr<urdf::World> worldInterface =  urdf::parseWorldURDF(xml_string, mPath );

  double roll, pitch, yaw;
  for( unsigned int i = 0; i < worldInterface->objectModels.size(); ++i ) {

    object = modelInterfaceToObject(  worldInterface->objectModels[i].model );
    // Initialize position and RPY
    worldInterface->objectModels[i].origin.rotation.getRPY( roll, pitch, yaw );
    object->setRotationRPY( roll, pitch, yaw );

    object->setPositionX( worldInterface->objectModels[i].origin.position.x );
    object->setPositionY( worldInterface->objectModels[i].origin.position.y );
    object->setPositionZ( worldInterface->objectModels[i].origin.position.z );
    object->update();
    world->addObject( object );
  }

  for( unsigned int i = 0; i < worldInterface->robotModels.size(); ++i )  {

    robot = modelInterfaceToRobot(  worldInterface->robotModels[i].model );
    // Initialize position and RPY
    worldInterface->robotModels[i].origin.rotation.getRPY( roll, pitch, yaw );
    robot->setRotationRPY( roll, pitch, yaw );

    robot->setPositionX( worldInterface->robotModels[i].origin.position.x );
    robot->setPositionY( worldInterface->robotModels[i].origin.position.y );
    robot->setPositionZ( worldInterface->robotModels[i].origin.position.z );
    robot->update();
    world->addRobot( robot );
  }

  world->rebuildCollision();
  return world;
}

/**
 * @function modelInterfaceToSkeleton
 * @brief Read the ModelInterface and spits out a SkeletonDynamics object
 */
dynamics::SkeletonDynamics* DartLoader::modelInterfaceToSkeleton( boost::shared_ptr<urdf::ModelInterface> _model ) {

  dynamics::SkeletonDynamics* mSkeleton;
  dynamics::BodyNodeDynamics *node, *rootNode;
  kinematics::Joint *joint, *rootJoint;

  /** Create new skeleton object */
  mSkeleton = new dynamics::SkeletonDynamics();

  /** Set skeleton name */
  mSkeleton->setName( _model->getName() );

  /** Load links and convert them to DART BodyNodes */
  mNodes.resize(0);

  for( std::map<std::string, boost::shared_ptr<urdf::Link> >::const_iterator lk = _model->links_.begin();
       lk != _model->links_.end();
       lk++ ) {
    node = createDartNode( (*lk).second, mSkeleton );
    // We return NULL for "world" link, hence this if condition
    if( node != NULL ) { mNodes.push_back( node ); }
  }

  if(debug) printf ("** Created %u body nodes \n", mNodes.size() );

  /** Initialize Joint store vector */
  mJoints.resize(0);

  /** root joint */
  std::string rootName = _model->getRoot()->name;
  rootNode = getNode( rootName );

  if(debug) printf ("[DartLoader] Root Node: %s \n", rootNode->getName() );

  /** If root node is NULL, nothing to create */
  if( rootNode == NULL ) {
    // Good, we have to set the node attached to world as root
    if( rootName == "world" ) {
      int numRoots = _model->getRoot()->child_links.size();
      if( numRoots != 1 ) {
	std::cout<< "[ERROR] Not unique link attached to world" <<std::endl;
      } else {
	rootName = (_model->getRoot()->child_links)[0]->name;
	rootNode = getNode( rootName );
	if( rootNode == NULL ) { return NULL; }
	std::cout<<"[info] World specified in URDF. Root node considered:"<< rootName <<std::endl;

	// Since the original rootName was world, add the joint that had it as its parent (only one)
	for( std::map<std::string, boost::shared_ptr<urdf::Joint> >::const_iterator jt = _model->joints_.begin();
	     jt != _model->joints_.end(); jt++ ) {
	  if( ( (*jt).second )->parent_link_name == "world" ) {
	    joint = createDartJoint( (*jt).second, mSkeleton );
	    mJoints.push_back( joint );
	  }
	} // end of else
      } // end of rootName == "world"
    }
    // Bad. Either the URDF is bad or the structure is not tree-like
    else {
      std::cout << "[ERROR] No root node found!" << std::endl;
      return NULL;
    }
  }
  else {
    /** Create a joint for floating */
    rootJoint =  createDartRootJoint( rootNode, mSkeleton );
    mJoints.push_back( rootJoint );
  }

  //-- Save DART structure

  // Push parents first
  std::list<dynamics::BodyNodeDynamics*> nodeStack;
  dynamics::BodyNodeDynamics* u;
  nodeStack.push_back( rootNode );

  int numIter = 0;
  while( !nodeStack.empty() && numIter < mNodes.size() ) {
    // Get front element on stack and update it
    u = nodeStack.front();
    // Add it to the Skeleton
    mSkeleton->addNode(u);

    for( std::map<std::string, boost::shared_ptr<urdf::Joint> >::const_iterator jt = _model->joints_.begin();
	 jt != _model->joints_.end();
	 jt++ ) {
      if( ( (*jt).second )->parent_link_name == u->getName() ) {
	joint = createDartJoint( (*jt).second, mSkeleton );
	mJoints.push_back( joint );
      }
    }

    // Pop it out
    nodeStack.pop_front();

    // Add its kids
    for( int idx = 0; idx < u->getNumChildJoints(); ++idx ) {
      nodeStack.push_back( (dynamics::BodyNodeDynamics*)( u->getChildNode(idx) ) );
    }
    numIter++;
  } // end while

  if(debug) printf ("[debug] Created %u joints \n", mJoints.size() );
  if(debug) printf ("[debug] Pushed %d nodes in order \n", numIter );

  // Init robot (skeleton)
  mSkeleton->initSkel();

  return mSkeleton;
}

/**
 * @function modelInterfaceToRobot
 */
robotics::Robot* DartLoader::modelInterfaceToRobot( boost::shared_ptr<urdf::ModelInterface> _model ) {

  robotics::Robot* mRobot;
  dynamics::BodyNodeDynamics *node, *rootNode;
  kinematics::Joint *joint, *rootJoint;

  /** Create new robot object */
  mRobot = new robotics::Robot();

  /** Set robot name */
  mRobot->setName( _model->getName() );

  /** Load links and convert them to DART BodyNodes */
  mNodes.resize(0);

  for( std::map<std::string, boost::shared_ptr<urdf::Link> >::const_iterator lk = _model->links_.begin();
       lk != _model->links_.end();
       lk++ ) {
    node = createDartNode( (*lk).second, mRobot );
    // We return NULL for "world" link, hence this if condition
    if( node != NULL ) { mNodes.push_back( node ); }
  }

  if(debug) printf ("** Created %u body nodes \n", mNodes.size() );

  /** Initialize Joint store vector */
  mJoints.resize(0);

  /** root joint */
  std::string rootName = _model->getRoot()->name;
  rootNode = getNode( rootName );

  if(debug) printf ("[DartLoader] Root Node: %s \n", rootNode->getName() );

  /** If root node is NULL, nothing to create */
  if( rootNode == NULL ) {
    // Good, we have to set the node attached to world as root
    if( rootName == "world" ) {
      int numRoots = _model->getRoot()->child_links.size();
      if( numRoots != 1 ) {
	std::cout<< "[ERROR] Not unique link attached to world" <<std::endl;
      } else {
	rootName = (_model->getRoot()->child_links)[0]->name;
	rootNode = getNode( rootName );
	if( rootNode == NULL ) { return NULL; }
	std::cout<<"[info] World specified in URDF. Root node considered:"<< rootName <<std::endl;

	// Since the original rootName was world, add the joint that had it as its parent (only one)
	for( std::map<std::string, boost::shared_ptr<urdf::Joint> >::const_iterator jt = _model->joints_.begin();
	     jt != _model->joints_.end(); jt++ ) {
	  if( ( (*jt).second )->parent_link_name == "world" ) {
	    joint = createDartJoint( (*jt).second, mRobot );
	    mJoints.push_back( joint );
	  }
	} // end of else
      } // end of rootName == "world"
    }
    // Bad. Either the URDF is bad or the structure is not tree-like
    else {
      std::cout << "[ERROR] No root node found!" << std::endl;
      return NULL;
    }
  }
  else {
    /** Create a joint for floating */
    rootJoint =  createDartRootJoint( rootNode, mRobot );
    mJoints.push_back( rootJoint );
  }

  //-- Save DART structure

  // Push parents first
  std::list<dynamics::BodyNodeDynamics*> nodeStack;
  dynamics::BodyNodeDynamics* u;
  nodeStack.push_back( rootNode );

  int numIter = 0;
  while( !nodeStack.empty() && numIter < mNodes.size() ) {
    // Get front element on stack and update it
    u = nodeStack.front();
    // Add it to the Robot
    mRobot->addNode(u);

    for( std::map<std::string, boost::shared_ptr<urdf::Joint> >::const_iterator jt = _model->joints_.begin();
	 jt != _model->joints_.end();
	 jt++ ) {
      if( ( (*jt).second )->parent_link_name == u->getName() ) {
	joint = createDartJoint( (*jt).second, mRobot );
	mJoints.push_back( joint );
      }
    }

    // Pop it out
    nodeStack.pop_front();

    // Add its kids
    for( int idx = 0; idx < u->getNumChildJoints(); ++idx ) {
      nodeStack.push_back( (dynamics::BodyNodeDynamics*)( u->getChildNode(idx) ) );
    }
    numIter++;
  } // end while

  if(debug) printf ("[debug] Created %u joints \n", mJoints.size() );
  if(debug) printf ("[debug] Pushed %d nodes in order \n", numIter );

  // Init robot (skeleton)
  mRobot->initSkel();
  mRobot->update();
  return mRobot;
}

/**
 * @function modelInterfaceToObject
 */
robotics::Object* DartLoader::modelInterfaceToObject( boost::shared_ptr<urdf::ModelInterface> _model ) {

  robotics::Object* mObject;
  dynamics::BodyNodeDynamics *node, *rootNode;
  kinematics::Joint *joint, *rootJoint;

  mObject = new robotics::Object();

  // name
  mObject->setName( _model->getName() );

  // BodyNode
  mNodes.resize(0);
  for( std::map<std::string, boost::shared_ptr<urdf::Link> >::const_iterator lk = _model->links_.begin();
       lk != _model->links_.end();
       lk++ ) {
    node = createDartNode( (*lk).second, mObject );
    mNodes.push_back( node );
  }
    if(debug) printf ("[debug] Created %u body nodes \n", mNodes.size() );

  // Joint
  mJoints.resize(0);

  for( std::map<std::string, boost::shared_ptr<urdf::Joint> >::const_iterator jt = _model->joints_.begin();
       jt != _model->joints_.end();
       jt++ ) {
    joint = createDartJoint( (*jt).second, mObject );
    mJoints.push_back( joint );

  }

  //-- root joint
  rootNode = getNode( _model->getRoot()->name ); // no rootnode
  rootJoint = createDartRootJoint( rootNode, mObject );
  mJoints.push_back( rootJoint );

  if(debug) printf ("[debug] Created %u joints \n", mJoints.size() );

  //-- Save DART structure

  // 1. Root node was added already so add...

  // 2. The rest of nodes
  for( unsigned int i = 0; i < mNodes.size(); ++i ) {
    // Add nodes to the object
      mObject->addNode( mNodes[i] );
  }

  // Init object (skeleton)
  mObject->initSkel();
  mObject->update();

  return mObject;
}

/**
 * @function getNode
 */
dynamics::BodyNodeDynamics* DartLoader::getNode( std::string _nodeName ) {

  for( unsigned int i = 0; i < mNodes.size(); ++i ) {
    std::string node( mNodes[i]->getName() );
    if( node ==  _nodeName ) {
      return mNodes[i];
    }
  }
  if(debug) printf ("[getNode] ERROR: Returning  NULL for  %s \n", _nodeName.c_str() );
  return NULL;
}

/**
 * @function readXml
 */
std::string  DartLoader::readXmlToString( std::string _xmlFile ) {

  std::string xml_string;

  std::fstream xml_file( _xmlFile.c_str(), std::fstream::in );

  // Read xml
  while( xml_file.good() ) {
    std::string line;
    std::getline( xml_file, line );
    xml_string += (line + "\n");
  }
  xml_file.close();

  return xml_string;
}
<commit_msg>Added alert message when you load a URDF that does not contain a world element<commit_after>/**
 * @file DartLoader.cpp
 */

#include "DartLoader.h"
#include <map>
#include "../urdf_parser/urdf_parser.h"
#include <iostream>
#include <fstream>
#include "dynamics/BodyNodeDynamics.h"
#include "dynamics/SkeletonDynamics.h"
#include "robotics/World.h"
#include "robotics/Robot.h"
#include "robotics/Object.h"

/**
 * @function DartLoader
 * @brief Constructor
 */
DartLoader::DartLoader() {
}

/**
 * @function ~DartLoader
 * @brief Destructor
 */
DartLoader::~DartLoader() {

}

/**
 * @function parseSkeleton
 */
dynamics::SkeletonDynamics* DartLoader::parseSkeleton( std::string _urdfFile ) {

  std::string xml_string;
  xml_string = readXmlToString( _urdfFile );

  boost::shared_ptr<urdf::ModelInterface> skeletonModel = urdf::parseURDF( xml_string );

  return modelInterfaceToSkeleton( skeletonModel );

}

/**
 * @function parseRobot
 */
robotics::Robot* DartLoader::parseRobot( std::string _urdfFile ) {

  std::string xml_string;
  xml_string = readXmlToString( _urdfFile );
  boost::shared_ptr<urdf::ModelInterface> robotModel = urdf::parseURDF( xml_string );
  return modelInterfaceToRobot( robotModel );
}

/**
 * @function parseObject
 */
robotics::Object* DartLoader::parseObject( std::string _urdfFile ) {

  std::string xml_string;
  xml_string = readXmlToString( _urdfFile );
  boost::shared_ptr<urdf::ModelInterface> objectModel = urdf::parseURDF( xml_string );
  return modelInterfaceToObject( objectModel );

}

/**
 * @function parseWorld
 */
robotics::World* DartLoader::parseWorld( std::string _urdfFile ) {

  mWorldPath = _urdfFile;

  // Change path to a Unix-style path if given a Windows one
  // Windows can handle Unix-style paths (apparently)
  std::replace( mWorldPath.begin(), mWorldPath.end(), '\\' , '/' );
  mPath = mWorldPath.substr( 0, mWorldPath.rfind("/") + 1 );

  // std::cout<< " mPath :" << mPath << std::endl;

  robotics::World* world = new robotics::World();
	robotics::Robot* robot;
  robotics::Object* object;

  std::string xml_string;
  xml_string = readXmlToString( _urdfFile );

  boost::shared_ptr<urdf::World> worldInterface =  urdf::parseWorldURDF(xml_string, mPath );

  if( !worldInterface->name.empty() ) {

    double roll, pitch, yaw;
    for( unsigned int i = 0; i < worldInterface->objectModels.size(); ++i ) {

      object = modelInterfaceToObject(  worldInterface->objectModels[i].model );
      // Initialize position and RPY
      worldInterface->objectModels[i].origin.rotation.getRPY( roll, pitch, yaw );
      object->setRotationRPY( roll, pitch, yaw );

      object->setPositionX( worldInterface->objectModels[i].origin.position.x );
      object->setPositionY( worldInterface->objectModels[i].origin.position.y );
      object->setPositionZ( worldInterface->objectModels[i].origin.position.z );
      object->update();
      world->addObject( object );
    }

    for( unsigned int i = 0; i < worldInterface->robotModels.size(); ++i )  {

      robot = modelInterfaceToRobot(  worldInterface->robotModels[i].model );
      // Initialize position and RPY
      worldInterface->robotModels[i].origin.rotation.getRPY( roll, pitch, yaw );
      robot->setRotationRPY( roll, pitch, yaw );

      robot->setPositionX( worldInterface->robotModels[i].origin.position.x );
      robot->setPositionY( worldInterface->robotModels[i].origin.position.y );
      robot->setPositionZ( worldInterface->robotModels[i].origin.position.z );
      robot->update();
      world->addRobot( robot );
    }

    world->rebuildCollision();
  }

  else {
    std::cout<< "[!] Either you loaded a world without name or the urdf does not contain a world element. Exiting and no loading!"<<std::endl;
  }

    return world;
}

/**
 * @function modelInterfaceToSkeleton
 * @brief Read the ModelInterface and spits out a SkeletonDynamics object
 */
dynamics::SkeletonDynamics* DartLoader::modelInterfaceToSkeleton( boost::shared_ptr<urdf::ModelInterface> _model ) {

  dynamics::SkeletonDynamics* mSkeleton;
  dynamics::BodyNodeDynamics *node, *rootNode;
  kinematics::Joint *joint, *rootJoint;

  /** Create new skeleton object */
  mSkeleton = new dynamics::SkeletonDynamics();

  /** Set skeleton name */
  mSkeleton->setName( _model->getName() );

  /** Load links and convert them to DART BodyNodes */
  mNodes.resize(0);

  for( std::map<std::string, boost::shared_ptr<urdf::Link> >::const_iterator lk = _model->links_.begin();
       lk != _model->links_.end();
       lk++ ) {
    node = createDartNode( (*lk).second, mSkeleton );
    // We return NULL for "world" link, hence this if condition
    if( node != NULL ) { mNodes.push_back( node ); }
  }

  if(debug) printf ("** Created %u body nodes \n", mNodes.size() );

  /** Initialize Joint store vector */
  mJoints.resize(0);

  /** root joint */
  std::string rootName = _model->getRoot()->name;
  rootNode = getNode( rootName );

  if(debug) printf ("[DartLoader] Root Node: %s \n", rootNode->getName() );

  /** If root node is NULL, nothing to create */
  if( rootNode == NULL ) {
    // Good, we have to set the node attached to world as root
    if( rootName == "world" ) {
      int numRoots = _model->getRoot()->child_links.size();
      if( numRoots != 1 ) {
	std::cout<< "[ERROR] Not unique link attached to world" <<std::endl;
      } else {
	rootName = (_model->getRoot()->child_links)[0]->name;
	rootNode = getNode( rootName );
	if( rootNode == NULL ) { return NULL; }
	std::cout<<"[info] World specified in URDF. Root node considered:"<< rootName <<std::endl;

	// Since the original rootName was world, add the joint that had it as its parent (only one)
	for( std::map<std::string, boost::shared_ptr<urdf::Joint> >::const_iterator jt = _model->joints_.begin();
	     jt != _model->joints_.end(); jt++ ) {
	  if( ( (*jt).second )->parent_link_name == "world" ) {
	    joint = createDartJoint( (*jt).second, mSkeleton );
	    mJoints.push_back( joint );
	  }
	} // end of else
      } // end of rootName == "world"
    }
    // Bad. Either the URDF is bad or the structure is not tree-like
    else {
      std::cout << "[ERROR] No root node found!" << std::endl;
      return NULL;
    }
  }
  else {
    /** Create a joint for floating */
    rootJoint =  createDartRootJoint( rootNode, mSkeleton );
    mJoints.push_back( rootJoint );
  }

  //-- Save DART structure

  // Push parents first
  std::list<dynamics::BodyNodeDynamics*> nodeStack;
  dynamics::BodyNodeDynamics* u;
  nodeStack.push_back( rootNode );

  int numIter = 0;
  while( !nodeStack.empty() && numIter < mNodes.size() ) {
    // Get front element on stack and update it
    u = nodeStack.front();
    // Add it to the Skeleton
    mSkeleton->addNode(u);

    for( std::map<std::string, boost::shared_ptr<urdf::Joint> >::const_iterator jt = _model->joints_.begin();
	 jt != _model->joints_.end();
	 jt++ ) {
      if( ( (*jt).second )->parent_link_name == u->getName() ) {
	joint = createDartJoint( (*jt).second, mSkeleton );
	mJoints.push_back( joint );
      }
    }

    // Pop it out
    nodeStack.pop_front();

    // Add its kids
    for( int idx = 0; idx < u->getNumChildJoints(); ++idx ) {
      nodeStack.push_back( (dynamics::BodyNodeDynamics*)( u->getChildNode(idx) ) );
    }
    numIter++;
  } // end while

  if(debug) printf ("[debug] Created %u joints \n", mJoints.size() );
  if(debug) printf ("[debug] Pushed %d nodes in order \n", numIter );

  // Init robot (skeleton)
  mSkeleton->initSkel();

  return mSkeleton;
}

/**
 * @function modelInterfaceToRobot
 */
robotics::Robot* DartLoader::modelInterfaceToRobot( boost::shared_ptr<urdf::ModelInterface> _model ) {

  robotics::Robot* mRobot;
  dynamics::BodyNodeDynamics *node, *rootNode;
  kinematics::Joint *joint, *rootJoint;

  /** Create new robot object */
  mRobot = new robotics::Robot();

  /** Set robot name */
  mRobot->setName( _model->getName() );

  /** Load links and convert them to DART BodyNodes */
  mNodes.resize(0);

  for( std::map<std::string, boost::shared_ptr<urdf::Link> >::const_iterator lk = _model->links_.begin();
       lk != _model->links_.end();
       lk++ ) {
    node = createDartNode( (*lk).second, mRobot );
    // We return NULL for "world" link, hence this if condition
    if( node != NULL ) { mNodes.push_back( node ); }
  }

  if(debug) printf ("** Created %u body nodes \n", mNodes.size() );

  /** Initialize Joint store vector */
  mJoints.resize(0);

  /** root joint */
  std::string rootName = _model->getRoot()->name;
  rootNode = getNode( rootName );

  if(debug) printf ("[DartLoader] Root Node: %s \n", rootNode->getName() );

  /** If root node is NULL, nothing to create */
  if( rootNode == NULL ) {
    // Good, we have to set the node attached to world as root
    if( rootName == "world" ) {
      int numRoots = _model->getRoot()->child_links.size();
      if( numRoots != 1 ) {
	std::cout<< "[ERROR] Not unique link attached to world" <<std::endl;
      } else {
	rootName = (_model->getRoot()->child_links)[0]->name;
	rootNode = getNode( rootName );
	if( rootNode == NULL ) { return NULL; }
	std::cout<<"[info] World specified in URDF. Root node considered:"<< rootName <<std::endl;

	// Since the original rootName was world, add the joint that had it as its parent (only one)
	for( std::map<std::string, boost::shared_ptr<urdf::Joint> >::const_iterator jt = _model->joints_.begin();
	     jt != _model->joints_.end(); jt++ ) {
	  if( ( (*jt).second )->parent_link_name == "world" ) {
	    joint = createDartJoint( (*jt).second, mRobot );
	    mJoints.push_back( joint );
	  }
	} // end of else
      } // end of rootName == "world"
    }
    // Bad. Either the URDF is bad or the structure is not tree-like
    else {
      std::cout << "[ERROR] No root node found!" << std::endl;
      return NULL;
    }
  }
  else {
    /** Create a joint for floating */
    rootJoint =  createDartRootJoint( rootNode, mRobot );
    mJoints.push_back( rootJoint );
  }

  //-- Save DART structure

  // Push parents first
  std::list<dynamics::BodyNodeDynamics*> nodeStack;
  dynamics::BodyNodeDynamics* u;
  nodeStack.push_back( rootNode );

  int numIter = 0;
  while( !nodeStack.empty() && numIter < mNodes.size() ) {
    // Get front element on stack and update it
    u = nodeStack.front();
    // Add it to the Robot
    mRobot->addNode(u);

    for( std::map<std::string, boost::shared_ptr<urdf::Joint> >::const_iterator jt = _model->joints_.begin();
	 jt != _model->joints_.end();
	 jt++ ) {
      if( ( (*jt).second )->parent_link_name == u->getName() ) {
	joint = createDartJoint( (*jt).second, mRobot );
	mJoints.push_back( joint );
      }
    }

    // Pop it out
    nodeStack.pop_front();

    // Add its kids
    for( int idx = 0; idx < u->getNumChildJoints(); ++idx ) {
      nodeStack.push_back( (dynamics::BodyNodeDynamics*)( u->getChildNode(idx) ) );
    }
    numIter++;
  } // end while

  if(debug) printf ("[debug] Created %u joints \n", mJoints.size() );
  if(debug) printf ("[debug] Pushed %d nodes in order \n", numIter );

  // Init robot (skeleton)
  mRobot->initSkel();
  mRobot->update();
  return mRobot;
}

/**
 * @function modelInterfaceToObject
 */
robotics::Object* DartLoader::modelInterfaceToObject( boost::shared_ptr<urdf::ModelInterface> _model ) {

  robotics::Object* mObject;
  dynamics::BodyNodeDynamics *node, *rootNode;
  kinematics::Joint *joint, *rootJoint;

  mObject = new robotics::Object();

  // name
  mObject->setName( _model->getName() );

  // BodyNode
  mNodes.resize(0);
  for( std::map<std::string, boost::shared_ptr<urdf::Link> >::const_iterator lk = _model->links_.begin();
       lk != _model->links_.end();
       lk++ ) {
    node = createDartNode( (*lk).second, mObject );
    mNodes.push_back( node );
  }
    if(debug) printf ("[debug] Created %u body nodes \n", mNodes.size() );

  // Joint
  mJoints.resize(0);

  for( std::map<std::string, boost::shared_ptr<urdf::Joint> >::const_iterator jt = _model->joints_.begin();
       jt != _model->joints_.end();
       jt++ ) {
    joint = createDartJoint( (*jt).second, mObject );
    mJoints.push_back( joint );

  }

  //-- root joint
  rootNode = getNode( _model->getRoot()->name ); // no rootnode
  rootJoint = createDartRootJoint( rootNode, mObject );
  mJoints.push_back( rootJoint );

  if(debug) printf ("[debug] Created %u joints \n", mJoints.size() );

  //-- Save DART structure

  // 1. Root node was added already so add...

  // 2. The rest of nodes
  for( unsigned int i = 0; i < mNodes.size(); ++i ) {
    // Add nodes to the object
      mObject->addNode( mNodes[i] );
  }

  // Init object (skeleton)
  mObject->initSkel();
  mObject->update();

  return mObject;
}

/**
 * @function getNode
 */
dynamics::BodyNodeDynamics* DartLoader::getNode( std::string _nodeName ) {

  for( unsigned int i = 0; i < mNodes.size(); ++i ) {
    std::string node( mNodes[i]->getName() );
    if( node ==  _nodeName ) {
      return mNodes[i];
    }
  }
  if(debug) printf ("[getNode] ERROR: Returning  NULL for  %s \n", _nodeName.c_str() );
  return NULL;
}

/**
 * @function readXml
 */
std::string  DartLoader::readXmlToString( std::string _xmlFile ) {

  std::string xml_string;

  std::fstream xml_file( _xmlFile.c_str(), std::fstream::in );

  // Read xml
  while( xml_file.good() ) {
    std::string line;
    std::getline( xml_file, line );
    xml_string += (line + "\n");
  }
  xml_file.close();

  return xml_string;
}
<|endoftext|>


<commit_before>// This file is part of the AliceVision project.
// This Source Code Form is subject to the terms of the Mozilla Public License,
// v. 2.0. If a copy of the MPL was not distributed with this file,
// You can obtain one at https://mozilla.org/MPL/2.0/.

#include "aliceVision/sfm/sfm.hpp"
#include "aliceVision/sfm/utils/uid.hpp"
#include <aliceVision/config.hpp>

#include "dependencies/stlplus3/filesystemSimplified/file_system.hpp"

#include <boost/program_options.hpp>
#include <boost/system/error_code.hpp>
#include <boost/filesystem.hpp>

#include <string>
#include <vector>

using namespace aliceVision;
using namespace aliceVision::sfm;
namespace po = boost::program_options;

// Convert from a SfMData format to another
int main(int argc, char **argv)
{
  // command-line parameters

  std::string verboseLevel = system::EVerboseLevel_enumToString(system::Logger::getDefaultVerboseLevel());
  std::string sfmDataFilename;
  std::string outputSfMDataFilename;
  std::string matchesFolder;

  // user optional parameters

  bool flagViews = true;
  bool flagIntrinsics = true;
  bool flagExtrinsics = true;
  bool flagStructure = true;
  bool flagObservations = true;
  bool recomputeUID = true;

  po::options_description allParams("AliceVision convertSfMFormat");

  po::options_description requiredParams("Required parameters");
  requiredParams.add_options()
    ("input,i", po::value<std::string>(&sfmDataFilename)->required(),
      "SfMData file.")
    ("output,o", po::value<std::string>(&outputSfMDataFilename)->required(),
      "Path to the output Alembic file.")
    ("matchesFolder,m", po::value<std::string>(&matchesFolder)->required(),
      "Path to a folder in which computed matches are stored.");

  po::options_description optionalParams("Optional parameters");
  optionalParams.add_options()
    ("views", po::value<bool>(&flagViews)->default_value(flagViews),
      "Export views.")
    ("intrinsics", po::value<bool>(&flagIntrinsics)->default_value(flagIntrinsics),
      "Export intrinsics.")
    ("extrinsics", po::value<bool>(&flagExtrinsics)->default_value(flagExtrinsics),
      "Export extrinsics.")
    ("structure", po::value<bool>(&flagStructure)->default_value(flagStructure),
      "Export structure.")
    ("observations", po::value<bool>(&flagObservations)->default_value(flagObservations),
      "Export observations.")
    ("regenerateUID", po::value<bool>(&recomputeUID)->default_value(recomputeUID),
      "Regenerate UID.");

  po::options_description logParams("Log parameters");
  logParams.add_options()
    ("verboseLevel,v", po::value<std::string>(&verboseLevel)->default_value(verboseLevel),
      "verbosity level (fatal,  error, warning, info, debug, trace).");

  allParams.add(requiredParams).add(optionalParams).add(logParams);

  po::variables_map vm;
  try
  {
    po::store(po::parse_command_line(argc, argv, allParams), vm);

    if(vm.count("help") || (argc == 1))
    {
      ALICEVISION_COUT(allParams);
      return EXIT_SUCCESS;
    }
    po::notify(vm);
  }
  catch(boost::program_options::required_option& e)
  {
    ALICEVISION_CERR("ERROR: " << e.what());
    ALICEVISION_COUT("Usage:\n\n" << allParams);
    return EXIT_FAILURE;
  }
  catch(boost::program_options::error& e)
  {
    ALICEVISION_CERR("ERROR: " << e.what());
    ALICEVISION_COUT("Usage:\n\n" << allParams);
    return EXIT_FAILURE;
  }

  // set verbose level
  system::Logger::get()->setLogLevel(verboseLevel);

  if (sfmDataFilename.empty() || outputSfMDataFilename.empty())
  {
    std::cerr << "Invalid input or output filename." << std::endl;
    return EXIT_FAILURE;
  }

  // OptionSwitch is cloned in cmd.add(),
  // so we must use cmd.used() instead of testing OptionSwitch.used
  int flags =
    (flagViews ? VIEWS      : 0)
  | (flagIntrinsics ? INTRINSICS : 0)
  | (flagExtrinsics ? EXTRINSICS : 0)
  | (flagObservations ? OBSERVATIONS : 0)
  | (flagStructure ? STRUCTURE  : 0);

  flags = (flags) ? flags : ALL;

  // Load input SfMData scene
  SfMData sfm_data;
  if (!Load(sfm_data, sfmDataFilename, ESfMData(ALL)))
  {
    std::cerr << std::endl
      << "The input SfMData file \"" << sfmDataFilename << "\" cannot be read." << std::endl;
    return EXIT_FAILURE;
  }

  if(recomputeUID)
  {
    std::cout << "Recomputing the UID of the views..." << std::endl;
    std::map<std::size_t, std::size_t> oldIdToNew;
    regenerateUID(sfm_data, oldIdToNew);

    if(!matchesFolder.empty())
    {
      std::cout << "Generating alias for .feat and .desc with the UIDs" << std::endl;
      for(const auto& iter : oldIdToNew)
      {
        const auto oldID = iter.first;
        const auto newID = iter.second;

        // nothing to do if the ids are the same
        if(oldID == newID)
          continue;

        const auto oldFeatfilename = stlplus::create_filespec(matchesFolder, std::to_string(oldID), ".feat");
        const auto newFeatfilename = stlplus::create_filespec(matchesFolder, std::to_string(newID), ".feat");
        const auto oldDescfilename = stlplus::create_filespec(matchesFolder, std::to_string(oldID), ".desc");
        const auto newDescfilename = stlplus::create_filespec(matchesFolder, std::to_string(newID), ".desc");

        if(!(stlplus::is_file(oldFeatfilename) && stlplus::is_file(oldDescfilename)))
        {
          std::cerr << "Cannot find the features file for view ID " << oldID
                      << std::endl;
          return EXIT_FAILURE;
        }
        boost::system::error_code ec;
        boost::filesystem::create_symlink(oldFeatfilename, newFeatfilename, ec);
        if(ec)
        {
          std::cerr << "Error while creating " << newFeatfilename << ": " << ec.message() << std::endl;
          return EXIT_FAILURE;
        }
        boost::filesystem::create_symlink(oldDescfilename, newDescfilename, ec);
        if(ec)
        {
          std::cerr << "Error while creating " << newDescfilename << ": " << ec.message() << std::endl;
          return EXIT_FAILURE;
        }
      }
    }
  }

  // Export the SfMData scene in the expected format
  if (!Save(sfm_data, outputSfMDataFilename, ESfMData(flags)))
  {
    std::cerr << std::endl
      << "An error occured while trying to save \"" << outputSfMDataFilename << "\"." << std::endl;
    return EXIT_FAILURE;
  }
  return EXIT_SUCCESS;
}
<commit_msg>[software] convertSfMFormat `recomputeUID` is now false by default<commit_after>// This file is part of the AliceVision project.
// This Source Code Form is subject to the terms of the Mozilla Public License,
// v. 2.0. If a copy of the MPL was not distributed with this file,
// You can obtain one at https://mozilla.org/MPL/2.0/.

#include "aliceVision/sfm/sfm.hpp"
#include "aliceVision/sfm/utils/uid.hpp"
#include <aliceVision/config.hpp>

#include "dependencies/stlplus3/filesystemSimplified/file_system.hpp"

#include <boost/program_options.hpp>
#include <boost/system/error_code.hpp>
#include <boost/filesystem.hpp>

#include <string>
#include <vector>

using namespace aliceVision;
using namespace aliceVision::sfm;
namespace po = boost::program_options;

// Convert from a SfMData format to another
int main(int argc, char **argv)
{
  // command-line parameters

  std::string verboseLevel = system::EVerboseLevel_enumToString(system::Logger::getDefaultVerboseLevel());
  std::string sfmDataFilename;
  std::string outputSfMDataFilename;
  std::string matchesFolder;

  // user optional parameters

  bool flagViews = true;
  bool flagIntrinsics = true;
  bool flagExtrinsics = true;
  bool flagStructure = true;
  bool flagObservations = true;
  bool recomputeUID = false;

  po::options_description allParams("AliceVision convertSfMFormat");

  po::options_description requiredParams("Required parameters");
  requiredParams.add_options()
    ("input,i", po::value<std::string>(&sfmDataFilename)->required(),
      "SfMData file.")
    ("output,o", po::value<std::string>(&outputSfMDataFilename)->required(),
      "Path to the output Alembic file.")
    ("matchesFolder,m", po::value<std::string>(&matchesFolder)->required(),
      "Path to a folder in which computed matches are stored.");

  po::options_description optionalParams("Optional parameters");
  optionalParams.add_options()
    ("views", po::value<bool>(&flagViews)->default_value(flagViews),
      "Export views.")
    ("intrinsics", po::value<bool>(&flagIntrinsics)->default_value(flagIntrinsics),
      "Export intrinsics.")
    ("extrinsics", po::value<bool>(&flagExtrinsics)->default_value(flagExtrinsics),
      "Export extrinsics.")
    ("structure", po::value<bool>(&flagStructure)->default_value(flagStructure),
      "Export structure.")
    ("observations", po::value<bool>(&flagObservations)->default_value(flagObservations),
      "Export observations.")
    ("regenerateUID", po::value<bool>(&recomputeUID)->default_value(recomputeUID),
      "Regenerate UID.");

  po::options_description logParams("Log parameters");
  logParams.add_options()
    ("verboseLevel,v", po::value<std::string>(&verboseLevel)->default_value(verboseLevel),
      "verbosity level (fatal,  error, warning, info, debug, trace).");

  allParams.add(requiredParams).add(optionalParams).add(logParams);

  po::variables_map vm;
  try
  {
    po::store(po::parse_command_line(argc, argv, allParams), vm);

    if(vm.count("help") || (argc == 1))
    {
      ALICEVISION_COUT(allParams);
      return EXIT_SUCCESS;
    }
    po::notify(vm);
  }
  catch(boost::program_options::required_option& e)
  {
    ALICEVISION_CERR("ERROR: " << e.what());
    ALICEVISION_COUT("Usage:\n\n" << allParams);
    return EXIT_FAILURE;
  }
  catch(boost::program_options::error& e)
  {
    ALICEVISION_CERR("ERROR: " << e.what());
    ALICEVISION_COUT("Usage:\n\n" << allParams);
    return EXIT_FAILURE;
  }

  // set verbose level
  system::Logger::get()->setLogLevel(verboseLevel);

  if (sfmDataFilename.empty() || outputSfMDataFilename.empty())
  {
    std::cerr << "Invalid input or output filename." << std::endl;
    return EXIT_FAILURE;
  }

  // OptionSwitch is cloned in cmd.add(),
  // so we must use cmd.used() instead of testing OptionSwitch.used
  int flags =
    (flagViews ? VIEWS      : 0)
  | (flagIntrinsics ? INTRINSICS : 0)
  | (flagExtrinsics ? EXTRINSICS : 0)
  | (flagObservations ? OBSERVATIONS : 0)
  | (flagStructure ? STRUCTURE  : 0);

  flags = (flags) ? flags : ALL;

  // Load input SfMData scene
  SfMData sfm_data;
  if (!Load(sfm_data, sfmDataFilename, ESfMData(ALL)))
  {
    std::cerr << std::endl
      << "The input SfMData file \"" << sfmDataFilename << "\" cannot be read." << std::endl;
    return EXIT_FAILURE;
  }

  if(recomputeUID)
  {
    std::cout << "Recomputing the UID of the views..." << std::endl;
    std::map<std::size_t, std::size_t> oldIdToNew;
    regenerateUID(sfm_data, oldIdToNew);

    if(!matchesFolder.empty())
    {
      std::cout << "Generating alias for .feat and .desc with the UIDs" << std::endl;
      for(const auto& iter : oldIdToNew)
      {
        const auto oldID = iter.first;
        const auto newID = iter.second;

        // nothing to do if the ids are the same
        if(oldID == newID)
          continue;

        const auto oldFeatfilename = stlplus::create_filespec(matchesFolder, std::to_string(oldID), ".feat");
        const auto newFeatfilename = stlplus::create_filespec(matchesFolder, std::to_string(newID), ".feat");
        const auto oldDescfilename = stlplus::create_filespec(matchesFolder, std::to_string(oldID), ".desc");
        const auto newDescfilename = stlplus::create_filespec(matchesFolder, std::to_string(newID), ".desc");

        if(!(stlplus::is_file(oldFeatfilename) && stlplus::is_file(oldDescfilename)))
        {
          std::cerr << "Cannot find the features file for view ID " << oldID
                      << std::endl;
          return EXIT_FAILURE;
        }
        boost::system::error_code ec;
        boost::filesystem::create_symlink(oldFeatfilename, newFeatfilename, ec);
        if(ec)
        {
          std::cerr << "Error while creating " << newFeatfilename << ": " << ec.message() << std::endl;
          return EXIT_FAILURE;
        }
        boost::filesystem::create_symlink(oldDescfilename, newDescfilename, ec);
        if(ec)
        {
          std::cerr << "Error while creating " << newDescfilename << ": " << ec.message() << std::endl;
          return EXIT_FAILURE;
        }
      }
    }
  }

  // Export the SfMData scene in the expected format
  if (!Save(sfm_data, outputSfMDataFilename, ESfMData(flags)))
  {
    std::cerr << std::endl
      << "An error occured while trying to save \"" << outputSfMDataFilename << "\"." << std::endl;
    return EXIT_FAILURE;
  }
  return EXIT_SUCCESS;
}
<|endoftext|>


<commit_before>// Copyright (c) 2013 Joshua Beitler, Mirus contributors

// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:

// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.

// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.

#include <stddef.h>
#include <stdint.h>
#include <util/string.hpp>

namespace mirus {
    class mem_bit {
    public:
        bool used;
    };

    class heap {
    public:
        mem_bit[255] bits;
    };
}<commit_msg>Mixed up array creation<commit_after>// Copyright (c) 2013 Joshua Beitler, Mirus contributors

// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:

// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.

// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.

#include <stddef.h>
#include <stdint.h>
#include <util/string.hpp>

namespace mirus {
    class mem_bit {
    public:
        bool used;
    };

    class heap {
    public:
        mem_bit bits[255];
    };
}<|endoftext|>


<commit_before>#include "MasyuField.h"

namespace Penciloid
{
MasyuField::MasyuField()
{
	height = 0;
	width = 0;

	hints = nullptr;
}

MasyuField::~MasyuField()
{
	if (hints) delete[] hints;
}

void MasyuField::Init(int height_t, int width_t)
{
	height = height_t;
	width = width_t;

	if (hints) delete[] hints;
	hints = new int[height * width];

	for (int i = 0; i < height * width; ++i) hints[i] = HINT_NONE;

	auxiliary.Init(this);
	grid.SetAuxiliarySolver(&auxiliary);
	grid.Init(height - 1, width - 1);
}

int MasyuField::SetHint(int y, int x, int hint)
{
	int id = VertexId(y, x);

	if (hints[id] != HINT_NONE) {
		if (hints[id] != hint) {
			return grid.UpdateStatus(SolverStatus::INCONSISTENT);
		}
		return grid.UpdateStatus(0);
	}

	hints[id] = hint;
	CheckTheorem(y * 2, x * 2);
	CheckVertex(y * 2, x * 2);

	return grid.GetStatus();
}

void MasyuField::CheckTheorem(int y, int x)
{
	// TODO: implement appropriately
}

void MasyuField::CheckVertex(int y, int x)
{
	int hint = hints[VertexId(y/ 2, x / 2)];

	if (hint == HINT_WHITE) {
		// TODO: implement rule for hint of white circle

	} else if (hint == HINT_BLACK) {
		int line_direction_candidate = 15;

		for (int i = 0; i < 4; ++i) {
			int dy1 = GridConstant::GRID_DY[i], dx1 = GridConstant::GRID_DX[i];
			int dy2 = GridConstant::GRID_DY[(i + 1) & 3], dx2 = GridConstant::GRID_DX[(i + 1) & 3];

			if (grid.GetSegmentStyleSafe(y + dy1, x + dx1) == LOOP_BLANK) continue;
			if (grid.GetSegmentStyleSafe(y + dy1 * 3, x + dx1 * 3) == LOOP_BLANK) continue;
			if (grid.GetSegmentStyleSafe(y + dy2, x + dx2) == LOOP_BLANK) continue;
			if (grid.GetSegmentStyleSafe(y + dy2 * 3, x + dx2 * 3) == LOOP_BLANK) continue;
			if (grid.GetSegmentStyleSafe(y + dy1 * 2 + dy2, x + dx1 * 2 + dx2) == LOOP_LINE) continue;
			if (grid.GetSegmentStyleSafe(y + dy1 * 2 - dy2, x + dx1 * 2 - dx2) == LOOP_LINE) continue;
			if (grid.GetSegmentStyleSafe(y + dy2 * 2 + dy1, x + dx2 * 2 + dx1) == LOOP_LINE) continue;
			if (grid.GetSegmentStyleSafe(y + dy2 * 2 - dy1, x + dx2 * 2 - dx1) == LOOP_LINE) continue;

			line_direction_candidate &= ((1 << i) | (1 << ((i + 1) & 3)));
		}

		for (int i = 0; i < 4; ++i) if (line_direction_candidate & (1 << i)) {
			int dy = GridConstant::GRID_DY[i], dx = GridConstant::GRID_DX[i];
			grid.DetermineLine(y + dy, x + dx);
			grid.DetermineLine(y + dy * 3, x + dx * 3);
		}
	}
}

void MasyuField::Debug()
{
	for (int i = 0; i <= (height - 1) * 2; ++i) {
		for (int j = 0; j <= (width - 1) * 2; ++j) {
			if (i % 2 == 0 && j % 2 == 0) {
				int hint = hints[VertexId(i / 2, j / 2)];

				if (hint == HINT_NONE) fprintf(stderr, "+");
				else if (hint == HINT_WHITE) fprintf(stderr, "O");
				else if (hint == HINT_BLACK) fprintf(stderr, "#");
			} else if (i % 2 == 0 && j % 2 == 1) {
				int style = GetSegmentStyle(i, j);
				if (style == LOOP_UNDECIDED) fprintf(stderr, "   ");
				if (style == LOOP_LINE) fprintf(stderr, "---");
				if (style == LOOP_BLANK) fprintf(stderr, " X ");
			} else if (i % 2 == 1 && j % 2 == 0) {
				int style = GetSegmentStyle(i, j);
				if (style == LOOP_UNDECIDED) fprintf(stderr, " ");
				if (style == LOOP_LINE) fprintf(stderr, "|");
				if (style == LOOP_BLANK) fprintf(stderr, "X");
			} else if (i % 2 == 1 && j % 2 == 1) {
				fprintf(stderr, "   ");
			}
		}
		fprintf(stderr, "\n");
	}
}

}<commit_msg>Improve CheckVertex in MasyuField so as to support hint of white circle<commit_after>#include "MasyuField.h"

namespace Penciloid
{
MasyuField::MasyuField()
{
	height = 0;
	width = 0;

	hints = nullptr;
}

MasyuField::~MasyuField()
{
	if (hints) delete[] hints;
}

void MasyuField::Init(int height_t, int width_t)
{
	height = height_t;
	width = width_t;

	if (hints) delete[] hints;
	hints = new int[height * width];

	for (int i = 0; i < height * width; ++i) hints[i] = HINT_NONE;

	auxiliary.Init(this);
	grid.SetAuxiliarySolver(&auxiliary);
	grid.Init(height - 1, width - 1);
}

int MasyuField::SetHint(int y, int x, int hint)
{
	int id = VertexId(y, x);

	if (hints[id] != HINT_NONE) {
		if (hints[id] != hint) {
			return grid.UpdateStatus(SolverStatus::INCONSISTENT);
		}
		return grid.UpdateStatus(0);
	}

	hints[id] = hint;
	CheckTheorem(y * 2, x * 2);
	CheckVertex(y * 2, x * 2);

	return grid.GetStatus();
}

void MasyuField::CheckTheorem(int y, int x)
{
	// TODO: implement appropriately
}

void MasyuField::CheckVertex(int y, int x)
{
	int hint = hints[VertexId(y/ 2, x / 2)];

	if (hint == HINT_WHITE) {
		// TODO: faster checker
		int neighborhood_segment_style[16];

		for (int i = 0; i < 16; ++i) {
			neighborhood_segment_style[i] = grid.GetSegmentStyleSafe(
				y + GridConstant::GRID_DY[i / 4] * 2 + GridConstant::GRID_DY[i % 4],
				x + GridConstant::GRID_DX[i / 4] * 2 + GridConstant::GRID_DX[i % 4]
				);
		}

		int segment_line_candidate = (1 << 16) - 1;
		int segment_blank_candidate = (1 << 16) - 1;

		do {
			if (neighborhood_segment_style[2] == LOOP_BLANK) break;
			if (neighborhood_segment_style[8] == LOOP_BLANK) break;
			if (neighborhood_segment_style[7] == LOOP_LINE) break;
			if (neighborhood_segment_style[13] == LOOP_LINE) break;

			int end1[] = { 0, 1, 3 };
			int end2[] = { 10, 9, 11 };

			for (int i = 0; i < 3; ++i) {
				for (int j = 0; j < 3; ++j) {
					if (i == 0 && j == 0) continue;

					if (neighborhood_segment_style[end1[i]] == LOOP_BLANK) continue;
					if (neighborhood_segment_style[end2[j]] == LOOP_BLANK) continue;
					if (neighborhood_segment_style[end1[(i + 1) % 3]] == LOOP_LINE) continue;
					if (neighborhood_segment_style[end2[(j + 1) % 3]] == LOOP_LINE) continue;
					if (neighborhood_segment_style[end1[(i + 2) % 3]] == LOOP_LINE) continue;
					if (neighborhood_segment_style[end2[(j + 2) % 3]] == LOOP_LINE) continue;

					int line_location = (1 << 2) | (1 << 8) | (1 << end1[i]) | (1 << end2[j]);
					int blank_location = ((15 << 0) | (15 << 8)) ^ line_location;

					segment_line_candidate &= line_location;
					segment_blank_candidate &= blank_location;
				}
			}
		} while (false);

		do {
			if (neighborhood_segment_style[7] == LOOP_BLANK) break;
			if (neighborhood_segment_style[13] == LOOP_BLANK) break;
			if (neighborhood_segment_style[2] == LOOP_LINE) break;
			if (neighborhood_segment_style[8] == LOOP_LINE) break;

			int end1[] = { 5, 4, 6 };
			int end2[] = { 15, 12, 14 };

			for (int i = 0; i < 3; ++i) {
				for (int j = 0; j < 3; ++j) {
					if (i == 0 && j == 0) continue;

					if (neighborhood_segment_style[end1[i]] == LOOP_BLANK) continue;
					if (neighborhood_segment_style[end2[j]] == LOOP_BLANK) continue;
					if (neighborhood_segment_style[end1[(i + 1) % 3]] == LOOP_LINE) continue;
					if (neighborhood_segment_style[end2[(j + 1) % 3]] == LOOP_LINE) continue;
					if (neighborhood_segment_style[end1[(i + 2) % 3]] == LOOP_LINE) continue;
					if (neighborhood_segment_style[end2[(j + 2) % 3]] == LOOP_LINE) continue;

					int line_location = (1 << 7) | (1 << 13) | (1 << end1[i]) | (1 << end2[j]);
					int blank_location = ((15 << 4) | (15 << 12)) ^ line_location;

					segment_line_candidate &= line_location;
					segment_blank_candidate &= blank_location;
				}
			}
		} while (false);

		for (int i = 0; i < 16; ++i) {
			if (segment_line_candidate & (1 << i)) {
				grid.DetermineLine(
					y + GridConstant::GRID_DY[i / 4] * 2 + GridConstant::GRID_DY[i % 4],
					x + GridConstant::GRID_DX[i / 4] * 2 + GridConstant::GRID_DX[i % 4]
					);
			}

			if (segment_blank_candidate & (1 << i)) {
				grid.DetermineBlank(
					y + GridConstant::GRID_DY[i / 4] * 2 + GridConstant::GRID_DY[i % 4],
					x + GridConstant::GRID_DX[i / 4] * 2 + GridConstant::GRID_DX[i % 4]
					);
			}
		}

	} else if (hint == HINT_BLACK) {
		int line_direction_candidate = 15;

		for (int i = 0; i < 4; ++i) {
			int dy1 = GridConstant::GRID_DY[i], dx1 = GridConstant::GRID_DX[i];
			int dy2 = GridConstant::GRID_DY[(i + 1) & 3], dx2 = GridConstant::GRID_DX[(i + 1) & 3];

			if (grid.GetSegmentStyleSafe(y + dy1, x + dx1) == LOOP_BLANK) continue;
			if (grid.GetSegmentStyleSafe(y + dy1 * 3, x + dx1 * 3) == LOOP_BLANK) continue;
			if (grid.GetSegmentStyleSafe(y + dy2, x + dx2) == LOOP_BLANK) continue;
			if (grid.GetSegmentStyleSafe(y + dy2 * 3, x + dx2 * 3) == LOOP_BLANK) continue;
			if (grid.GetSegmentStyleSafe(y + dy1 * 2 + dy2, x + dx1 * 2 + dx2) == LOOP_LINE) continue;
			if (grid.GetSegmentStyleSafe(y + dy1 * 2 - dy2, x + dx1 * 2 - dx2) == LOOP_LINE) continue;
			if (grid.GetSegmentStyleSafe(y + dy2 * 2 + dy1, x + dx2 * 2 + dx1) == LOOP_LINE) continue;
			if (grid.GetSegmentStyleSafe(y + dy2 * 2 - dy1, x + dx2 * 2 - dx1) == LOOP_LINE) continue;

			line_direction_candidate &= ((1 << i) | (1 << ((i + 1) & 3)));
		}

		for (int i = 0; i < 4; ++i) if (line_direction_candidate & (1 << i)) {
			int dy = GridConstant::GRID_DY[i], dx = GridConstant::GRID_DX[i];
			grid.DetermineLine(y + dy, x + dx);
			grid.DetermineLine(y + dy * 3, x + dx * 3);
		}
	}
}

void MasyuField::Debug()
{
	for (int i = 0; i <= (height - 1) * 2; ++i) {
		for (int j = 0; j <= (width - 1) * 2; ++j) {
			if (i % 2 == 0 && j % 2 == 0) {
				int hint = hints[VertexId(i / 2, j / 2)];

				if (hint == HINT_NONE) fprintf(stderr, "+");
				else if (hint == HINT_WHITE) fprintf(stderr, "O");
				else if (hint == HINT_BLACK) fprintf(stderr, "#");
			} else if (i % 2 == 0 && j % 2 == 1) {
				int style = GetSegmentStyle(i, j);
				if (style == LOOP_UNDECIDED) fprintf(stderr, "   ");
				if (style == LOOP_LINE) fprintf(stderr, "---");
				if (style == LOOP_BLANK) fprintf(stderr, " X ");
			} else if (i % 2 == 1 && j % 2 == 0) {
				int style = GetSegmentStyle(i, j);
				if (style == LOOP_UNDECIDED) fprintf(stderr, " ");
				if (style == LOOP_LINE) fprintf(stderr, "|");
				if (style == LOOP_BLANK) fprintf(stderr, "X");
			} else if (i % 2 == 1 && j % 2 == 1) {
				fprintf(stderr, "   ");
			}
		}
		fprintf(stderr, "\n");
	}
}

}<|endoftext|>


<commit_before>#include "input_reader.h"
#include <string.h>
#include <algorithm>
#include <string>
#include "logging.h"

using baidu::common::INFO;
using baidu::common::WARNING;

namespace baidu {
namespace shuttle {

class LineBuffer {
public:
    LineBuffer() : head_(0) {}
    void Reset() {
        data_.erase();
        head_ = 0;
    }
    void Append(char* new_data, size_t len) {
        data_.append(new_data, len);
    }
    void FillRemain(std::string* line) {
        line->assign(data_, head_, data_.size() - head_);
    }
    bool ReadLine(std::string* line) {
        if (head_ == data_.size()) {
            return false;
        }
        for (size_t i = head_; i < data_.size(); i++) {
            if (data_[i] == '\n') {
                line->assign(data_, head_, i - head_);
                head_ = i + 1;
                return true;
            }
        }
        if (head_ > 0) {
            data_.erase(0, head_);
            head_ = 0;
        }
        return false;
    }
    size_t Size() {
        return data_.size() - head_;
    }
private:
    std::string data_;
    size_t head_;
};

class TextReader : public InputReader {
public:
    class IteratorImpl : public InputReader::Iterator {
    public:
        IteratorImpl(TextReader* reader) : has_more_(false),
                                           status_(kOk),
                                           reader_(reader) {}
        virtual ~IteratorImpl() {}
        bool Done() { return !has_more_;}
        void Next();
        const std::string& Record() { return line_;}
        Status Error() {return status_;};
        void SetHasMore(bool has_more) {has_more_ =  has_more;}
        void SetError(Status err) {status_ = err;}
    private:
        bool has_more_;
        Status status_;
        std::string line_;
        TextReader* reader_;
    };

    TextReader(FileSystem* fs) : fs_(fs),
                                 offset_(0), len_(0),
                                 read_bytes_(0),
                                 reach_eof_(false) {}
    virtual ~TextReader() {delete fs_;}
    Status Open(const std::string& path, FileSystem::Param param);
    Iterator* Read(int64_t offset, int64_t len);
    Status Close();
private:
    Status ReadNextLine(std::string* line);
private:
    FileSystem* fs_;
    LineBuffer buf_;
    int64_t offset_;
    int64_t len_;
    int64_t read_bytes_;
    bool reach_eof_;
};

class SeqFileReader : public InputReader {
public:
    class IteratorImpl : public InputReader::Iterator {
    public:
        IteratorImpl(SeqFileReader* reader) : has_more_(false),
                                              status_(kOk),
                                              reader_(reader) {}
        virtual ~IteratorImpl() {}
        bool Done() { return !has_more_;}
        void Next();
        const std::string& Record() {return record_;};
        Status Error() {return status_;};
        void SetHasMore(bool has_more) {has_more_ =  has_more;}
        void SetError(Status err) {status_ = err;}
    private:
        bool has_more_;
        Status status_;
        std::string record_;
        SeqFileReader* reader_;
    };

    SeqFileReader(InfSeqFile* sf) : sf_(sf), offset_(0), len_(0),
                                    read_bytes_(0),
                                    reach_eof_(false),
                                    end_offfset_(0) {}
    virtual ~SeqFileReader() {delete sf_;}
    Status Open(const std::string& path, FileSystem::Param param);
    Iterator* Read(int64_t offset, int64_t len);
    Status Close();
private:
    Status ReadNextKV(std::string* key, std::string* value);
private:
    InfSeqFile* sf_;
    int64_t offset_;
    int64_t len_;
    int64_t read_bytes_;
    bool reach_eof_;
    std::string end_key_;
    std::string end_value_;
    int64_t end_offfset_;
};

void TextReader::IteratorImpl::Next() {
    Status status = reader_->ReadNextLine(&line_);
    if (status != kOk) {
        has_more_ = false;
    } else {
        has_more_ = true;
    }
    status_ = status;
}

Status TextReader::Open(const std::string& path, FileSystem::Param param) {
    if (!fs_->Open(path, param, kReadFile)) {
        return kOpenFileFail;
    }
    return kOk;
}

InputReader::Iterator* TextReader::Read(int64_t offset, int64_t len) {
    offset_ = offset;
    len_ = len;
    read_bytes_ = 0;
    buf_.Reset();
    reach_eof_ = false;
    IteratorImpl* it = new IteratorImpl(this);
    char byte_prev;
    if (offset > 0) {
        //need to skip the first in-complete line;
        if (!fs_->Seek(offset - 1)) {
            LOG(WARNING, "seek to %ld fail", offset - 1);
            it->SetHasMore(false);
            it->SetError(kReadFileFail);
            return it;
        }
        if (!fs_->Read((void*)&byte_prev, 1)) {
            LOG(WARNING, "read prev byte fail");
            it->SetHasMore(false);
            it->SetError(kReadFileFail);
            return it;
        }
    }
    if (!fs_->Seek(offset)) {
        LOG(WARNING, "seek to %ld fail", offset);
        it->SetHasMore(false);
        it->SetError(kReadFileFail);
        return it;
    }
    it->Next();
    if (it->Error() == kOk && offset > 0) {
        if (byte_prev != '\n') {
            it->Next(); //jump the first line
        }
    }
    return it;
}

Status TextReader::Close() {
    if(!fs_->Close()) {
        return kCloseFileFail;
    }
    return kOk;
}

Status TextReader::ReadNextLine(std::string* line) {
    assert(line);
    //printf("read_bytes: %ld\n", read_bytes_);
    if (read_bytes_ >= len_ || reach_eof_) {
        return kNoMore;
    }
    if (buf_.ReadLine(line)) {
        //read a line success
    } else {
        int one_size = std::min(40960L, len_);
        char* one_buf = (char*)malloc(one_size);;
        int n_ret = 0;
        while ( (n_ret = fs_->Read((void*)one_buf, one_size)) > 0) {
            buf_.Append(one_buf, n_ret);
            if (memchr(one_buf, '\n', n_ret) != NULL) {
                break;
            }
        }
        free(one_buf);
        if (n_ret < 0) {
            return kReadFileFail;
        } else if (n_ret == 0) {
            if (buf_.Size() > 0) { //sometimes, the last line has no EOL
                buf_.FillRemain(line);
                read_bytes_ += line->size();
                reach_eof_ = true;
                return kOk;
            } else {
                return kNoMore;
            }
        } else {
           assert(buf_.ReadLine(line));
        }
    }
    read_bytes_ += (line->size() + 1);
    return kOk;
}

Status SeqFileReader::Open(const std::string& path, FileSystem::Param param) {
    if (!sf_->Open(path, param, kReadFile)) {
        return kOpenFileFail;
    } else {
        return kOk;
    }
}

InputReader::Iterator* SeqFileReader::Read(int64_t offset, int64_t len) {
    offset_ = offset;
    len_ = len;
    IteratorImpl* it = new IteratorImpl(this);
    if (offset_ + len_ >= sf_->GetSize()) {
        end_offfset_ = 0;
    } else if (sf_->Seek(offset_ + len_)) {
        end_offfset_ = sf_->Tell();
        bool eof;
        if (!sf_->ReadNextRecord(&end_key_, &end_value_, &eof)) {
            it->SetHasMore(false);
            it->SetError(kReadFileFail);
            return it;
        }
    } else {
        it->SetHasMore(false);
        it->SetError(kReadFileFail);
        return it;
    }
    if (!sf_->Seek(offset)) {
        it->SetHasMore(false);
        it->SetError(kReadFileFail);
        return it;
    }
    it->Next();
    return it;
}

Status SeqFileReader::Close() {
    if (!sf_->Close()) {
        return kCloseFileFail;
    }
    return kOk;
}

Status SeqFileReader::ReadNextKV(std::string* key, std::string* value) {
    bool eof = false;
    if (sf_->ReadNextRecord(key, value, &eof) ) {
        if (eof) {
            return kNoMore;
        }
        int64_t cur_pos = sf_->Tell();
        //fprintf(stderr, "cur_pos:%ld, offset:%ld\n", cur_pos, offset_);
        if (cur_pos < 0) {
            return kReadFileFail;
        }
        if (cur_pos == end_offfset_) {
            if (*key == end_key_ && *value == end_value_) {
                return kNoMore;
            }
        }
        return kOk;
    } else {
        return kReadFileFail;
    }
}

void SeqFileReader::IteratorImpl::Next() {
    std::string key;
    std::string value;
    Status status;
    status = reader_->ReadNextKV(&key, &value);
    if (status == kOk) {
        int32_t key_len = (int32_t)key.size();
        int32_t value_len = (int32_t)value.size();
        record_.erase();
        record_.append((const char*)(&key_len), sizeof(key_len));
        record_.append(key);
        record_.append((const char*)(&value_len), sizeof(value_len));
        record_.append(value);
        has_more_ = true;
        status_ = kOk;
    } else if (status == kNoMore) {
        has_more_ = false;
        status_ = kNoMore;
    } else {
        has_more_ = false;
        status_ = status;
    }
}

InputReader* InputReader::CreateHdfsTextReader() {
    return new TextReader(FileSystem::CreateInfHdfs());
}

InputReader* InputReader::CreateLocalTextReader() {
    return new TextReader(FileSystem::CreateLocalFs());
}

InputReader* InputReader::CreateSeqFileReader() {
    return new SeqFileReader(new InfSeqFile());
}

} //namepsace shuttle
} //namespace baidu
<commit_msg>bug fix: seqfile split<commit_after>#include "input_reader.h"
#include <string.h>
#include <limits>
#include <algorithm>
#include <string>
#include "logging.h"

using baidu::common::INFO;
using baidu::common::WARNING;

namespace baidu {
namespace shuttle {

class LineBuffer {
public:
    LineBuffer() : head_(0) {}
    void Reset() {
        data_.erase();
        head_ = 0;
    }
    void Append(char* new_data, size_t len) {
        data_.append(new_data, len);
    }
    void FillRemain(std::string* line) {
        line->assign(data_, head_, data_.size() - head_);
    }
    bool ReadLine(std::string* line) {
        if (head_ == data_.size()) {
            return false;
        }
        for (size_t i = head_; i < data_.size(); i++) {
            if (data_[i] == '\n') {
                line->assign(data_, head_, i - head_);
                head_ = i + 1;
                return true;
            }
        }
        if (head_ > 0) {
            data_.erase(0, head_);
            head_ = 0;
        }
        return false;
    }
    size_t Size() {
        return data_.size() - head_;
    }
private:
    std::string data_;
    size_t head_;
};

class TextReader : public InputReader {
public:
    class IteratorImpl : public InputReader::Iterator {
    public:
        IteratorImpl(TextReader* reader) : has_more_(false),
                                           status_(kOk),
                                           reader_(reader) {}
        virtual ~IteratorImpl() {}
        bool Done() { return !has_more_;}
        void Next();
        const std::string& Record() { return line_;}
        Status Error() {return status_;};
        void SetHasMore(bool has_more) {has_more_ =  has_more;}
        void SetError(Status err) {status_ = err;}
    private:
        bool has_more_;
        Status status_;
        std::string line_;
        TextReader* reader_;
    };

    TextReader(FileSystem* fs) : fs_(fs),
                                 offset_(0), len_(0),
                                 read_bytes_(0),
                                 reach_eof_(false) {}
    virtual ~TextReader() {delete fs_;}
    Status Open(const std::string& path, FileSystem::Param param);
    Iterator* Read(int64_t offset, int64_t len);
    Status Close();
private:
    Status ReadNextLine(std::string* line);
private:
    FileSystem* fs_;
    LineBuffer buf_;
    int64_t offset_;
    int64_t len_;
    int64_t read_bytes_;
    bool reach_eof_;
};

class SeqFileReader : public InputReader {
public:
    class IteratorImpl : public InputReader::Iterator {
    public:
        IteratorImpl(SeqFileReader* reader) : has_more_(false),
                                              status_(kOk),
                                              reader_(reader) {}
        virtual ~IteratorImpl() {}
        bool Done() { return !has_more_;}
        void Next();
        const std::string& Record() {return record_;};
        Status Error() {return status_;};
        void SetHasMore(bool has_more) {has_more_ =  has_more;}
        void SetError(Status err) {status_ = err;}
    private:
        bool has_more_;
        Status status_;
        std::string record_;
        SeqFileReader* reader_;
    };

    SeqFileReader(InfSeqFile* sf) : sf_(sf), offset_(0), len_(0),
                                    read_bytes_(0),
                                    reach_eof_(false),
                                    end_offfset_(0) {}
    virtual ~SeqFileReader() {delete sf_;}
    Status Open(const std::string& path, FileSystem::Param param);
    Iterator* Read(int64_t offset, int64_t len);
    Status Close();
private:
    Status ReadNextKV(std::string* key, std::string* value);
private:
    InfSeqFile* sf_;
    int64_t offset_;
    int64_t len_;
    int64_t read_bytes_;
    bool reach_eof_;
    std::string end_key_;
    std::string end_value_;
    int64_t end_offfset_;
};

void TextReader::IteratorImpl::Next() {
    Status status = reader_->ReadNextLine(&line_);
    if (status != kOk) {
        has_more_ = false;
    } else {
        has_more_ = true;
    }
    status_ = status;
}

Status TextReader::Open(const std::string& path, FileSystem::Param param) {
    if (!fs_->Open(path, param, kReadFile)) {
        return kOpenFileFail;
    }
    return kOk;
}

InputReader::Iterator* TextReader::Read(int64_t offset, int64_t len) {
    offset_ = offset;
    len_ = len;
    read_bytes_ = 0;
    buf_.Reset();
    reach_eof_ = false;
    IteratorImpl* it = new IteratorImpl(this);
    char byte_prev;
    if (offset > 0) {
        //need to skip the first in-complete line;
        if (!fs_->Seek(offset - 1)) {
            LOG(WARNING, "seek to %ld fail", offset - 1);
            it->SetHasMore(false);
            it->SetError(kReadFileFail);
            return it;
        }
        if (!fs_->Read((void*)&byte_prev, 1)) {
            LOG(WARNING, "read prev byte fail");
            it->SetHasMore(false);
            it->SetError(kReadFileFail);
            return it;
        }
    }
    if (!fs_->Seek(offset)) {
        LOG(WARNING, "seek to %ld fail", offset);
        it->SetHasMore(false);
        it->SetError(kReadFileFail);
        return it;
    }
    it->Next();
    if (it->Error() == kOk && offset > 0) {
        if (byte_prev != '\n') {
            it->Next(); //jump the first line
        }
    }
    return it;
}

Status TextReader::Close() {
    if(!fs_->Close()) {
        return kCloseFileFail;
    }
    return kOk;
}

Status TextReader::ReadNextLine(std::string* line) {
    assert(line);
    //printf("read_bytes: %ld\n", read_bytes_);
    if (read_bytes_ >= len_ || reach_eof_) {
        return kNoMore;
    }
    if (buf_.ReadLine(line)) {
        //read a line success
    } else {
        int one_size = std::min(40960L, len_);
        char* one_buf = (char*)malloc(one_size);;
        int n_ret = 0;
        while ( (n_ret = fs_->Read((void*)one_buf, one_size)) > 0) {
            buf_.Append(one_buf, n_ret);
            if (memchr(one_buf, '\n', n_ret) != NULL) {
                break;
            }
        }
        free(one_buf);
        if (n_ret < 0) {
            return kReadFileFail;
        } else if (n_ret == 0) {
            if (buf_.Size() > 0) { //sometimes, the last line has no EOL
                buf_.FillRemain(line);
                read_bytes_ += line->size();
                reach_eof_ = true;
                return kOk;
            } else {
                return kNoMore;
            }
        } else {
           assert(buf_.ReadLine(line));
        }
    }
    read_bytes_ += (line->size() + 1);
    return kOk;
}

Status SeqFileReader::Open(const std::string& path, FileSystem::Param param) {
    if (!sf_->Open(path, param, kReadFile)) {
        return kOpenFileFail;
    } else {
        return kOk;
    }
}

InputReader::Iterator* SeqFileReader::Read(int64_t offset, int64_t len) {
    offset_ = offset;
    len_ = len;
    IteratorImpl* it = new IteratorImpl(this);
    if (offset_ + len_ >= sf_->GetSize()) {
        end_offfset_ = std::numeric_limits<int64_t>::max();
    } else if (sf_->Seek(offset_ + len_)) {
        end_offfset_ = sf_->Tell();
        bool eof;
        if (!sf_->ReadNextRecord(&end_key_, &end_value_, &eof)) {
            it->SetHasMore(false);
            it->SetError(kReadFileFail);
            return it;
        }
    } else {
        it->SetHasMore(false);
        it->SetError(kReadFileFail);
        return it;
    }
    if (!sf_->Seek(offset)) {
        it->SetHasMore(false);
        it->SetError(kReadFileFail);
        return it;
    }
    it->Next();
    return it;
}

Status SeqFileReader::Close() {
    if (!sf_->Close()) {
        return kCloseFileFail;
    }
    return kOk;
}

Status SeqFileReader::ReadNextKV(std::string* key, std::string* value) {
    bool eof = false;
    if (sf_->ReadNextRecord(key, value, &eof) ) {
        if (eof) {
            return kNoMore;
        }
        int64_t cur_pos = sf_->Tell();
        //fprintf(stderr, "cur_pos:%ld, offset:%ld\n", cur_pos, offset_);
        if (cur_pos < 0) {
            return kReadFileFail;
        }
        if (cur_pos == end_offfset_) {
            if (*key == end_key_ && *value == end_value_) {
                return kNoMore;
            }
        }
        if (cur_pos > end_offfset_) {
            return kNoMore;
        }
        return kOk;
    } else {
        return kReadFileFail;
    }
}

void SeqFileReader::IteratorImpl::Next() {
    std::string key;
    std::string value;
    Status status;
    status = reader_->ReadNextKV(&key, &value);
    if (status == kOk) {
        int32_t key_len = (int32_t)key.size();
        int32_t value_len = (int32_t)value.size();
        record_.erase();
        record_.append((const char*)(&key_len), sizeof(key_len));
        record_.append(key);
        record_.append((const char*)(&value_len), sizeof(value_len));
        record_.append(value);
        has_more_ = true;
        status_ = kOk;
    } else if (status == kNoMore) {
        has_more_ = false;
        status_ = kNoMore;
    } else {
        has_more_ = false;
        status_ = status;
    }
}

InputReader* InputReader::CreateHdfsTextReader() {
    return new TextReader(FileSystem::CreateInfHdfs());
}

InputReader* InputReader::CreateLocalTextReader() {
    return new TextReader(FileSystem::CreateLocalFs());
}

InputReader* InputReader::CreateSeqFileReader() {
    return new SeqFileReader(new InfSeqFile());
}

} //namepsace shuttle
} //namespace baidu
<|endoftext|>


<commit_before>/* mbed Microcontroller Library
 * Copyright (c) 2017 ARM Limited
 * SPDX-License-Identifier: Apache-2.0
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "blockdevice/HeapBlockDevice.h"
#include "platform/mbed_atomic.h"
#include <stdlib.h>
#include <string.h>

namespace mbed {

HeapBlockDevice::HeapBlockDevice(bd_size_t size, bd_size_t block)
    : _read_size(block), _program_size(block), _erase_size(block)
    , _count(size / block), _blocks(0), _init_ref_count(0), _is_initialized(false)
{
    MBED_ASSERT(_count * _erase_size == size);
}

HeapBlockDevice::HeapBlockDevice(bd_size_t size, bd_size_t read, bd_size_t program, bd_size_t erase)
    : _read_size(read), _program_size(program), _erase_size(erase)
    , _count(size / erase), _blocks(0), _init_ref_count(0), _is_initialized(false)
{
    MBED_ASSERT(_count * _erase_size == size);
}

HeapBlockDevice::~HeapBlockDevice()
{
    if (_blocks) {
        for (size_t i = 0; i < _count; i++) {
            free(_blocks[i]);
        }

        delete[] _blocks;
        _blocks = 0;
    }
}

int HeapBlockDevice::init()
{
    uint32_t val = core_util_atomic_incr_u32(&_init_ref_count, 1);

    if (val != 1) {
        return BD_ERROR_OK;
    }

    if (!_blocks) {
        _blocks = new uint8_t *[_count];
        for (size_t i = 0; i < _count; i++) {
            _blocks[i] = 0;
        }
    }

    _is_initialized = true;
    return BD_ERROR_OK;
}

int HeapBlockDevice::deinit()
{
    if (!_is_initialized) {
        return BD_ERROR_OK;
    }

    uint32_t val = core_util_atomic_decr_u32(&_init_ref_count, 1);

    if (val) {
        return BD_ERROR_OK;
    }

    MBED_ASSERT(_blocks != NULL);
    // Memory is lazily cleaned up in destructor to allow
    // data to live across de/reinitialization
    _is_initialized = false;
    return BD_ERROR_OK;
}

bd_size_t HeapBlockDevice::get_read_size() const
{
    return _read_size;
}

bd_size_t HeapBlockDevice::get_program_size() const
{
    return _program_size;
}

bd_size_t HeapBlockDevice::get_erase_size() const
{
    return _erase_size;
}

bd_size_t HeapBlockDevice::get_erase_size(bd_addr_t addr) const
{
    return _erase_size;
}

bd_size_t HeapBlockDevice::size() const
{
    return _count * _erase_size;
}

int HeapBlockDevice::read(void *b, bd_addr_t addr, bd_size_t size)
{
    if (!_is_initialized) {
        return BD_ERROR_DEVICE_ERROR;
    }
    if (!is_valid_read(addr, size)) {
        return BD_ERROR_DEVICE_ERROR;
    }

    uint8_t *buffer = static_cast<uint8_t *>(b);

    while (size > 0) {
        bd_addr_t hi = addr / _erase_size;
        bd_addr_t lo = addr % _erase_size;

        if (_blocks[hi]) {
            memcpy(buffer, &_blocks[hi][lo], _read_size);
        } else {
            memset(buffer, 0, _read_size);
        }

        buffer += _read_size;
        addr += _read_size;
        size -= _read_size;
    }

    return 0;
}

int HeapBlockDevice::program(const void *b, bd_addr_t addr, bd_size_t size)
{
    if (!_is_initialized) {
        return BD_ERROR_DEVICE_ERROR;
    }
    if (!is_valid_program(addr, size)) {
        return BD_ERROR_DEVICE_ERROR;
    }

    const uint8_t *buffer = static_cast<const uint8_t *>(b);

    while (size > 0) {
        bd_addr_t hi = addr / _erase_size;
        bd_addr_t lo = addr % _erase_size;

        if (!_blocks[hi]) {
            _blocks[hi] = (uint8_t *)malloc(_erase_size);
            if (!_blocks[hi]) {
                return BD_ERROR_DEVICE_ERROR;
            }
        }

        memcpy(&_blocks[hi][lo], buffer, _program_size);

        buffer += _program_size;
        addr += _program_size;
        size -= _program_size;
    }

    return 0;
}

int HeapBlockDevice::erase(bd_addr_t addr, bd_size_t size)
{
    if (!_is_initialized) {
        return BD_ERROR_DEVICE_ERROR;
    }
    if (!is_valid_erase(addr, size)) {
        return BD_ERROR_DEVICE_ERROR;
    }
    return 0;
}

const char *HeapBlockDevice::get_type() const
{
    return "HEAP";
}

} // namespace mbed
<commit_msg>HeapBlockDevice: allocate with std::nothrow<commit_after>/* mbed Microcontroller Library
 * Copyright (c) 2017 ARM Limited
 * SPDX-License-Identifier: Apache-2.0
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "blockdevice/HeapBlockDevice.h"
#include "platform/mbed_atomic.h"
#include <stdlib.h>
#include <string.h>

namespace mbed {

HeapBlockDevice::HeapBlockDevice(bd_size_t size, bd_size_t block)
    : _read_size(block), _program_size(block), _erase_size(block)
    , _count(size / block), _blocks(0), _init_ref_count(0), _is_initialized(false)
{
    MBED_ASSERT(_count * _erase_size == size);
}

HeapBlockDevice::HeapBlockDevice(bd_size_t size, bd_size_t read, bd_size_t program, bd_size_t erase)
    : _read_size(read), _program_size(program), _erase_size(erase)
    , _count(size / erase), _blocks(0), _init_ref_count(0), _is_initialized(false)
{
    MBED_ASSERT(_count * _erase_size == size);
}

HeapBlockDevice::~HeapBlockDevice()
{
    if (_blocks) {
        for (size_t i = 0; i < _count; i++) {
            delete[] _blocks[i];
        }

        delete[] _blocks;
        _blocks = 0;
    }
}

int HeapBlockDevice::init()
{
    uint32_t val = core_util_atomic_incr_u32(&_init_ref_count, 1);

    if (val != 1) {
        return BD_ERROR_OK;
    }

    if (!_blocks) {
        _blocks = new (std::nothrow) uint8_t *[_count];
        if (!_blocks) {
            return BD_ERROR_DEVICE_ERROR;
        }

        for (size_t i = 0; i < _count; i++) {
            _blocks[i] = 0;
        }
    }

    _is_initialized = true;
    return BD_ERROR_OK;
}

int HeapBlockDevice::deinit()
{
    if (!_is_initialized) {
        return BD_ERROR_OK;
    }

    uint32_t val = core_util_atomic_decr_u32(&_init_ref_count, 1);

    if (val) {
        return BD_ERROR_OK;
    }

    MBED_ASSERT(_blocks != NULL);
    // Memory is lazily cleaned up in destructor to allow
    // data to live across de/reinitialization
    _is_initialized = false;
    return BD_ERROR_OK;
}

bd_size_t HeapBlockDevice::get_read_size() const
{
    return _read_size;
}

bd_size_t HeapBlockDevice::get_program_size() const
{
    return _program_size;
}

bd_size_t HeapBlockDevice::get_erase_size() const
{
    return _erase_size;
}

bd_size_t HeapBlockDevice::get_erase_size(bd_addr_t addr) const
{
    return _erase_size;
}

bd_size_t HeapBlockDevice::size() const
{
    return _count * _erase_size;
}

int HeapBlockDevice::read(void *b, bd_addr_t addr, bd_size_t size)
{
    if (!_is_initialized) {
        return BD_ERROR_DEVICE_ERROR;
    }
    if (!is_valid_read(addr, size)) {
        return BD_ERROR_DEVICE_ERROR;
    }

    uint8_t *buffer = static_cast<uint8_t *>(b);

    while (size > 0) {
        bd_addr_t hi = addr / _erase_size;
        bd_addr_t lo = addr % _erase_size;

        if (_blocks[hi]) {
            memcpy(buffer, &_blocks[hi][lo], _read_size);
        } else {
            memset(buffer, 0, _read_size);
        }

        buffer += _read_size;
        addr += _read_size;
        size -= _read_size;
    }

    return 0;
}

int HeapBlockDevice::program(const void *b, bd_addr_t addr, bd_size_t size)
{
    if (!_is_initialized) {
        return BD_ERROR_DEVICE_ERROR;
    }
    if (!is_valid_program(addr, size)) {
        return BD_ERROR_DEVICE_ERROR;
    }

    const uint8_t *buffer = static_cast<const uint8_t *>(b);

    while (size > 0) {
        bd_addr_t hi = addr / _erase_size;
        bd_addr_t lo = addr % _erase_size;

        if (!_blocks[hi]) {
            _blocks[hi] = new (std::nothrow) uint8_t[_erase_size];
            if (!_blocks[hi]) {
                return BD_ERROR_DEVICE_ERROR;
            }
        }

        memcpy(&_blocks[hi][lo], buffer, _program_size);

        buffer += _program_size;
        addr += _program_size;
        size -= _program_size;
    }

    return 0;
}

int HeapBlockDevice::erase(bd_addr_t addr, bd_size_t size)
{
    if (!_is_initialized) {
        return BD_ERROR_DEVICE_ERROR;
    }
    if (!is_valid_erase(addr, size)) {
        return BD_ERROR_DEVICE_ERROR;
    }
    return 0;
}

const char *HeapBlockDevice::get_type() const
{
    return "HEAP";
}

} // namespace mbed
<|endoftext|>


<commit_before>/*
    This file is part of Magnum.

    Copyright © 2010, 2011, 2012, 2013, 2014, 2015, 2016
              Vladimír Vondruš <mosra@centrum.cz>

    Permission is hereby granted, free of charge, to any person obtaining a
    copy of this software and associated documentation files (the "Software"),
    to deal in the Software without restriction, including without limitation
    the rights to use, copy, modify, merge, publish, distribute, sublicense,
    and/or sell copies of the Software, and to permit persons to whom the
    Software is furnished to do so, subject to the following conditions:

    The above copyright notice and this permission notice shall be included
    in all copies or substantial portions of the Software.

    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
    THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
    FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
    DEALINGS IN THE SOFTWARE.
*/

#include <iomanip>
#include <sstream>
#include <Corrade/PluginManager/Manager.h>
#include <Magnum/Platform/Sdl2Application.h>
#include <Magnum/Math/Complex.h>
#include <Magnum/DefaultFramebuffer.h>
#include <Magnum/Mesh.h>
#include <Magnum/Renderer.h>
#include <Magnum/Shaders/DistanceFieldVector.h>
#include <Magnum/Text/AbstractFont.h>
#include <Magnum/Text/DistanceFieldGlyphCache.h>
#include <Magnum/Text/Renderer.h>

#include "configure.h"

namespace Magnum { namespace Examples {

class TextExample: public Platform::Application {
    public:
        explicit TextExample(const Arguments& arguments);

    private:
        void viewportEvent(const Vector2i& size) override;
        void drawEvent() override;
        void mousePressEvent(MouseEvent& event) override;

        void updateText();

        PluginManager::Manager<Text::AbstractFont> _manager;
        std::unique_ptr<Text::AbstractFont> _font;

        Text::DistanceFieldGlyphCache _cache;
        Mesh _text;
        Buffer _vertices, _indices;
        std::unique_ptr<Text::Renderer2D> _text2;
        Shaders::DistanceFieldVector2D _shader;

        Matrix3 _transformation;
        Matrix3 _projection;
};

TextExample::TextExample(const Arguments& arguments): Platform::Application(arguments, Configuration().setTitle("Magnum Text Example")), _manager(MAGNUM_PLUGINS_FONT_DIR), _cache(Vector2i(2048), Vector2i(512), 22), _text{NoCreate} {
    /* Load FreeTypeFont plugin */
    _font = _manager.loadAndInstantiate("FreeTypeFont");
    if(!_font) std::exit(1);

    /* Open the font and fill glyph cache */
    Utility::Resource rs("fonts");
    if(!_font->openSingleData(rs.getRaw("DejaVuSans.ttf"), 110.0f)) {
        Error() << "Cannot open font file";
        std::exit(1);
    }

    _font->fillGlyphCache(_cache, "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789:-+,.!°ěäЗдравстуймиγειασουτνκόμ ");
    std::tie(_text, std::ignore) = Text::Renderer2D::render(*_font, _cache, 0.1295f,
        "Hello, world!\n"
        "Ahoj, světe!\n"
        "Здравствуй, мир!\n"
        "γεια σου, τον κόσμο!\n"
        "Hej Världen!",
        _vertices, _indices, BufferUsage::StaticDraw, Text::Alignment::MiddleCenter);

    _text2.reset(new Text::Renderer2D(*_font, _cache, 0.035f, Text::Alignment::TopRight));
    _text2->reserve(40, BufferUsage::DynamicDraw, BufferUsage::StaticDraw);

    Renderer::enable(Renderer::Feature::Blending);
    Renderer::setBlendFunction(Renderer::BlendFunction::One, Renderer::BlendFunction::OneMinusSourceAlpha);
    Renderer::setBlendEquation(Renderer::BlendEquation::Add, Renderer::BlendEquation::Add);

    _transformation = Matrix3::rotation(Deg(-10.0f));
    _projection = Matrix3::scaling(Vector2::yScale(Vector2(defaultFramebuffer.viewport().size()).aspectRatio()));
    updateText();
}

void TextExample::viewportEvent(const Vector2i& size) {
    defaultFramebuffer.setViewport({{}, size});

    _projection = Matrix3::scaling(Vector2::yScale(Vector2(size).aspectRatio()));
}

void TextExample::drawEvent() {
    defaultFramebuffer.clear(FramebufferClear::Color);

    _shader.setVectorTexture(_cache.texture());

    _shader.setTransformationProjectionMatrix(_projection * _transformation)
        .setColor(Color3::fromHSV(216.0_degf, 0.85f, 1.0f))
        .setOutlineColor(Color3{0.95f})
        .setOutlineRange(0.45f, 0.35f)
        .setSmoothness(0.025f/ _transformation.uniformScaling());
    _text.draw(_shader);

    _shader.setTransformationProjectionMatrix(_projection*
        Matrix3::translation(1.0f/ _projection.rotationScaling().diagonal()))
        .setColor(Color4(1.0f, 0.0f))
        .setOutlineRange(0.5f, 1.0f)
        .setSmoothness(0.075f);
    _text2->mesh().draw(_shader);

    swapBuffers();
}

void TextExample::mousePressEvent(MouseEvent& event) {
    if(event.button() == MouseEvent::Button::WheelUp)
        _transformation = Matrix3::rotation(Deg(1.0f))*Matrix3::scaling(Vector2(1.1f))* _transformation;
    else if(event.button() == MouseEvent::Button::WheelDown)
        _transformation = Matrix3::rotation(Deg(-1.0f))*Matrix3::scaling(Vector2(1.0f/1.1f))* _transformation;
    else return;

    updateText();

    event.setAccepted();
    redraw();
}

void TextExample::updateText() {
    std::ostringstream out;
    out << std::setprecision(2)
        << "Rotation: "
        << Float(Deg(Complex::fromMatrix(_transformation.rotation()).angle()))
        << "°\nScale: "
        << _transformation.uniformScaling();
    _text2->render(out.str());
}

}}

MAGNUM_APPLICATION_MAIN(Magnum::Examples::TextExample)
<commit_msg>text: fix the blend function so alpha transparency works correctly.<commit_after>/*
    This file is part of Magnum.

    Copyright © 2010, 2011, 2012, 2013, 2014, 2015, 2016
              Vladimír Vondruš <mosra@centrum.cz>

    Permission is hereby granted, free of charge, to any person obtaining a
    copy of this software and associated documentation files (the "Software"),
    to deal in the Software without restriction, including without limitation
    the rights to use, copy, modify, merge, publish, distribute, sublicense,
    and/or sell copies of the Software, and to permit persons to whom the
    Software is furnished to do so, subject to the following conditions:

    The above copyright notice and this permission notice shall be included
    in all copies or substantial portions of the Software.

    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
    THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
    FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
    DEALINGS IN THE SOFTWARE.
*/

#include <iomanip>
#include <sstream>
#include <Corrade/PluginManager/Manager.h>
#include <Magnum/Platform/Sdl2Application.h>
#include <Magnum/Math/Complex.h>
#include <Magnum/DefaultFramebuffer.h>
#include <Magnum/Mesh.h>
#include <Magnum/Renderer.h>
#include <Magnum/Shaders/DistanceFieldVector.h>
#include <Magnum/Text/AbstractFont.h>
#include <Magnum/Text/DistanceFieldGlyphCache.h>
#include <Magnum/Text/Renderer.h>

#include "configure.h"

namespace Magnum { namespace Examples {

class TextExample: public Platform::Application {
    public:
        explicit TextExample(const Arguments& arguments);

    private:
        void viewportEvent(const Vector2i& size) override;
        void drawEvent() override;
        void mousePressEvent(MouseEvent& event) override;

        void updateText();

        PluginManager::Manager<Text::AbstractFont> _manager;
        std::unique_ptr<Text::AbstractFont> _font;

        Text::DistanceFieldGlyphCache _cache;
        Mesh _text;
        Buffer _vertices, _indices;
        std::unique_ptr<Text::Renderer2D> _text2;
        Shaders::DistanceFieldVector2D _shader;

        Matrix3 _transformation;
        Matrix3 _projection;
};

TextExample::TextExample(const Arguments& arguments): Platform::Application(arguments, Configuration().setTitle("Magnum Text Example")), _manager(MAGNUM_PLUGINS_FONT_DIR), _cache(Vector2i(2048), Vector2i(512), 22), _text{NoCreate} {
    /* Load FreeTypeFont plugin */
    _font = _manager.loadAndInstantiate("FreeTypeFont");
    if(!_font) std::exit(1);

    /* Open the font and fill glyph cache */
    Utility::Resource rs("fonts");
    if(!_font->openSingleData(rs.getRaw("DejaVuSans.ttf"), 110.0f)) {
        Error() << "Cannot open font file";
        std::exit(1);
    }

    _font->fillGlyphCache(_cache, "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789:-+,.!°ěäЗдравстуймиγειασουτνκόμ ");
    std::tie(_text, std::ignore) = Text::Renderer2D::render(*_font, _cache, 0.1295f,
        "Hello, world!\n"
        "Ahoj, světe!\n"
        "Здравствуй, мир!\n"
        "γεια σου, τον κόσμο!\n"
        "Hej Världen!",
        _vertices, _indices, BufferUsage::StaticDraw, Text::Alignment::MiddleCenter);

    _text2.reset(new Text::Renderer2D(*_font, _cache, 0.035f, Text::Alignment::TopRight));
    _text2->reserve(40, BufferUsage::DynamicDraw, BufferUsage::StaticDraw);

    Renderer::enable(Renderer::Feature::Blending);
    Renderer::setBlendFunction(Renderer::BlendFunction::SourceAlpha, Renderer::BlendFunction::OneMinusSourceAlpha);
    Renderer::setBlendEquation(Renderer::BlendEquation::Add, Renderer::BlendEquation::Add);

    _transformation = Matrix3::rotation(Deg(-10.0f));
    _projection = Matrix3::scaling(Vector2::yScale(Vector2(defaultFramebuffer.viewport().size()).aspectRatio()));
    updateText();
}

void TextExample::viewportEvent(const Vector2i& size) {
    defaultFramebuffer.setViewport({{}, size});

    _projection = Matrix3::scaling(Vector2::yScale(Vector2(size).aspectRatio()));
}

void TextExample::drawEvent() {
    defaultFramebuffer.clear(FramebufferClear::Color);

    _shader.setVectorTexture(_cache.texture());

    _shader.setTransformationProjectionMatrix(_projection * _transformation)
        .setColor(Color3::fromHSV(216.0_degf, 0.85f, 1.0f))
        .setOutlineColor(Color3{0.95f})
        .setOutlineRange(0.45f, 0.35f)
        .setSmoothness(0.025f/ _transformation.uniformScaling());
    _text.draw(_shader);

    _shader.setTransformationProjectionMatrix(_projection*
        Matrix3::translation(1.0f/ _projection.rotationScaling().diagonal()))
        .setColor(Color4(1.0f, 0.0f))
        .setOutlineRange(0.5f, 1.0f)
        .setSmoothness(0.075f);
    _text2->mesh().draw(_shader);

    swapBuffers();
}

void TextExample::mousePressEvent(MouseEvent& event) {
    if(event.button() == MouseEvent::Button::WheelUp)
        _transformation = Matrix3::rotation(Deg(1.0f))*Matrix3::scaling(Vector2(1.1f))* _transformation;
    else if(event.button() == MouseEvent::Button::WheelDown)
        _transformation = Matrix3::rotation(Deg(-1.0f))*Matrix3::scaling(Vector2(1.0f/1.1f))* _transformation;
    else return;

    updateText();

    event.setAccepted();
    redraw();
}

void TextExample::updateText() {
    std::ostringstream out;
    out << std::setprecision(2)
        << "Rotation: "
        << Float(Deg(Complex::fromMatrix(_transformation.rotation()).angle()))
        << "°\nScale: "
        << _transformation.uniformScaling();
    _text2->render(out.str());
}

}}

MAGNUM_APPLICATION_MAIN(Magnum::Examples::TextExample)
<|endoftext|>


<commit_before>// Tightdb daemon (tightdbd) responsible for async commits

#include <tightdb/group_shared.hpp>
#include <unistd.h>

using namespace tightdb;

void exit_handler()
{
    fprintf(stderr, "Daemon exiting (exit_handler called)");
}

int main(int argc, char* argv[])
{

    // rudimentary check that a database name is provided as parameter.
    if (argc != 2) {
        fprintf(stderr, "ERROR: No database name provided\n");
        exit(3);
    }

    // Spawn daemon proces. Parent will exit causing the daemon to be
    // adopted by the init process. Ensures that the daemon won't become
    // a zombie, but be collected by the init process when it exits.
    // This is the second fork of the double-fork-idiom.
    int pid = fork();
    if (pid == 0) { // in daemon process:

        atexit(exit_handler);
        fprintf(stderr, "Daemon starting\n");
        try {
            SharedGroup::unattached_tag tag;
            SharedGroup async_committer(tag);
            char* file = argv[1];
            async_committer.open(file, true, SharedGroup::durability_Async, true);
        } catch (...) {
            fprintf(stderr, "Daemon threw an exception");
        }

    } else if (pid > 0) { // in parent, fork was ok, so return succes

        exit(0);

    } else { // in parent, fork failed, so return error code

        exit(2);
    }
    // never come here
}

<commit_msg>minor minor fix<commit_after>// Tightdb daemon (tightdbd) responsible for async commits

#include <tightdb/group_shared.hpp>
#include <unistd.h>

using namespace tightdb;

void exit_handler()
{
    fprintf(stderr, "Daemon exiting (exit_handler called)\n");
}

int main(int argc, char* argv[])
{

    // rudimentary check that a database name is provided as parameter.
    if (argc != 2) {
        fprintf(stderr, "ERROR: No database name provided\n");
        exit(3);
    }

    // Spawn daemon proces. Parent will exit causing the daemon to be
    // adopted by the init process. Ensures that the daemon won't become
    // a zombie, but be collected by the init process when it exits.
    // This is the second fork of the double-fork-idiom.
    int pid = fork();
    if (pid == 0) { // in daemon process:

        atexit(exit_handler);
        fprintf(stderr, "Daemon starting\n");
        try {
            SharedGroup::unattached_tag tag;
            SharedGroup async_committer(tag);
            char* file = argv[1];
            async_committer.open(file, true, SharedGroup::durability_Async, true);
        } catch (...) {
            fprintf(stderr, "Daemon threw an exception");
        }

    } else if (pid > 0) { // in parent, fork was ok, so return succes

        exit(0);

    } else { // in parent, fork failed, so return error code

        exit(2);
    }
    // never come here
}

<|endoftext|>