<commit_before>#include "Affordance.h"
#include <otdf_lcm_utils/otdf_lcm_utils.h>
#include "ConstraintApp.h"
#include <kdl/treefksolverpos_recursive.hpp>

Affordance::Affordance(const std::string& filename) : m_log(std::cout)
{
  // load the OTDF file
  std::string xml_string;
  if ( !otdf::get_xml_string_from_file(filename, xml_string) ) {
    m_log << "unable to get_xml_string_from_file " << filename << std::endl;
    return;
  }

  //convert OTDF to URDF
  boost::shared_ptr<otdf::ModelInterface> otdf_instance(otdf::parseOTDF(xml_string));
  otdf_instance->update();

  std::string urdf_xml_string(otdf::convertObjectInstanceToCompliantURDFstring(otdf_instance));

  // Parse KDL tree
  if ( !kdl_parser::treeFromString(urdf_xml_string, m_tree) ) {
    m_log << "ERROR: Failed to extract kdl tree from " << filename
	  << " otdf object instance "<< std::endl;
    return;
  }

  UpdateJointNames();

  //print some debug info on the new affordance
  m_log << "Joint names and numbers: " << std::endl;
  PrintJointNames();

  m_log << "created KDL object with " << m_tree.getNrOfJoints() << " joints and "
	<< m_tree.getNrOfSegments() << " segments" << std::endl;
  PrintKdlTree(m_tree, m_tree.getRootSegment()->second, 0);
}

Affordance::Affordance(std::ostream& log, const drc::affordance_t& msg) : m_log(log)
{
  /*
  std::string urdf_xml_string;
  if ( !otdf::AffordanceLcmMsgToUrdfString(msg, urdf_xml_string) ) {
    m_log << "ERROR: failed to process new affordance" << std::endl;
    return;
  }
  */

  const std::string filename(msg.otdf_type);

  // load the OTDF file
  std::string xml_string;
  if ( !otdf::get_xml_string_from_file(filename, xml_string) ) {
    m_log << "unable to get_xml_string_from_file " << filename << std::endl;
    return;
  }

  //convert OTDF to URDF
  boost::shared_ptr<otdf::ModelInterface> otdf_instance(otdf::parseOTDF(xml_string));

  for(int i=0;i<msg.nparams;i++){
    otdf_instance->setParam(msg.param_names[i],msg.params[i]);
    m_log << msg.param_names[i] << "<=" << msg.params[i] << std::endl;
  }
  for(int i=0;i<msg.nstates;i++){
    double pos, vel;
    pos = msg.states[i];
    vel =0;
    otdf_instance->setJointState(msg.state_names[i],pos,vel);
    m_log << msg.state_names[i] << "<=" << pos << std::endl;
  }
  otdf_instance->update();

  std::string urdf_xml_string(otdf::convertObjectInstanceToCompliantURDFstring(otdf_instance));

  // Parse KDL tree
  if ( !kdl_parser::treeFromString(urdf_xml_string, m_tree) ) {
    m_log << "ERROR: Failed to extract kdl tree from " << msg.otdf_type << ", uid=" << msg.uid
	  << " otdf object instance "<< std::endl;
    return;
  }

  UpdateJointNames();

  //print some debug info on the new affordance
  m_log << "xml string: " << std::endl
	<< urdf_xml_string << std::endl;

  m_log << "Joint names and numbers: " << std::endl;
  PrintJointNames();

  m_log << "created KDL object with " << m_tree.getNrOfJoints() << " joints and "
	<< m_tree.getNrOfSegments() << " segments" << std::endl;
  PrintKdlTree(m_tree, m_tree.getRootSegment()->second, 0);
}

void Affordance::PrintKdlTree(const KDL::Tree& tree,
			      const KDL::TreeElement& segment,
			      unsigned int depth)
{
  for ( unsigned int i = 0; i < depth; i++ ) {
    m_log << " ";
  }
  m_log << segment.segment.getName()
	<< ", joint " << segment.segment.getJoint().getName()
	<< " of type " << segment.segment.getJoint().getTypeName()
	<< ", joint #" << segment.q_nr
	<< std::endl;
  for ( unsigned int i = 0; i < segment.children.size(); i++ ) {
    PrintKdlTree(tree, segment.children[i]->second, depth+1);
  }
}

void Affordance::PrintJointNames()
{
  for ( JointMultiIndex::nth_index<0>::type::iterator iter = m_joints.begin();
	iter != m_joints.end(); ++iter ) {
    m_log << iter->name << " #" << iter->num << std::endl;
  }
}

void Affordance::UpdateJointNames(const KDL::TreeElement* element /*=NULL*/)
{
  if ( !element ) {
    m_joints.clear();
    UpdateJointNames(&m_tree.getRootSegment()->second);

    //perform sanity checks; loop through the joints and verify that the q_nr's are sequential and start at zero
    int q_nr = 0;
    for ( JointMultiIndex::nth_index<0>::type::iterator iter = m_joints.begin();
	iter != m_joints.end(); ++iter ) {
      if ( q_nr != iter->num ) {
	m_log << "ERROR: while parsing tree, expected joint #" << q_nr << ", found joint #" << iter->num << std::endl;
	m_joints.clear();
	m_tree = KDL::Tree();
	return;
      }
      q_nr++;
    }
    return;
  }

  if ( element->segment.getJoint().getType() != KDL::Joint::None ) {
    m_joints.insert(Joint(element->segment.getJoint().getName(), element->q_nr));
  }

  for ( unsigned int i = 0; i < element->children.size(); i++ ) {
    UpdateJointNames(&element->children[i]->second);
  }

}

/*
void Affordance::GetState(std::vector<double>& state) const
{
  state = ConstraintApp::FrameToVector(m_basepose);

  for ( JointMultiIndex::nth_index<0>::type::const_iterator iter = m_joints.begin();
	iter != m_joints.end(); ++iter ) {
    state.push_back(iter->value);
  }
}
*/

bool Affordance::GetStateFromMsg(const drc::affordance_t& msg, StateVector& state)
{
  //extract the x,y,z,r,p,w from the msg params
  ConstraintApp::OptionalKDLFrame msgFrame(ConstraintApp::GetFrameFromParams(&msg));
  if ( !msgFrame ) {
    m_log << "ERROR: Affordance::UpdateStateFromMsg unable to recover frame from message" << std::endl;
    return false;
  }
  state = ConstraintApp::FrameToVector(*msgFrame);

  //convert the msg.state to a map
  typedef std::map<std::string, double> ValueMap;
  ValueMap values;
  for ( int i=0; i<msg.nstates; i++ ) {
    values.insert(std::pair<std::string, double>(msg.state_names[i], msg.states[i]));
  }

  //iterate through the joints according to their q_nr number
  for ( JointMultiIndex::nth_index<0>::type::iterator iter = m_joints.begin();
	iter != m_joints.end(); ++iter ) {
    ValueMap::iterator match = values.find(iter->name);
    if ( match == values.end() ) {
      m_log << "ERROR: unable to find joint " << iter->name << " in the message state" << std::endl;
      return false;
    }
    state.push_back(match->second);
  }

  //perform sanity checks
  if ( state.size() != 6 + m_joints.size() ) {
    m_log << "ERROR: state has improper size" << std::endl;
    return false;
  }

  return true;
}

void Affordance::PrintState(const StateVector& state)
{
  for ( int i = 0; i < state.size(); i++ ) {
    m_log << state[i] << ", ";
  }
  m_log << std::endl;
}

bool Affordance::DecodeState(const StateVector& state, KDL::Frame& root_expressedIn_world, KDL::JntArray& joints)
{
  const int basePoseSize = 6;
  if ( state.size() < basePoseSize ) {
    m_log << "ERROR: Affordance::DecodeState must be of at least size 6 (not " << state.size() << ")" << std::endl;
    m_log << "   state=";
    for ( int i = 0; i < state.size(); i++ ) m_log << state[i] << ", ";
    m_log << std::endl;
    return false;
  }

  root_expressedIn_world = GetFrameFromVector(state);

  int numJoints = state.size() - basePoseSize;
  if ( numJoints < 0 ) return false;
  joints.resize(numJoints);
  for ( int i = 0; i < numJoints; i++ ) {
    joints(i) = state[i+basePoseSize];
  }

  return true;
}

bool Affordance::GetSegmentExpressedInWorld(const std::string& segmentName, const StateVector& state,
					    KDL::Frame& segment_expressedIn_world)
{
  KDL::Frame root_expressedIn_world;
  KDL::JntArray joints;
  if ( !DecodeState(state, root_expressedIn_world, joints) ) {
    return false;
  }

  KDL::Frame segment_expressedIn_root;
  KDL::TreeFkSolverPos_recursive fk(m_tree);
  int fkret = fk.JntToCart(joints, segment_expressedIn_root, segmentName);
  //if ( fkret < 0 ) {
    m_log << "ERROR: Affordance::GetSegmentExpressedInWorld: fk returned " << fkret << std::endl
	  << "   segmentName=" << segmentName << std::endl
	  << "   joints=" << joints.data << std::endl;
    m_log << "   state=";
    for ( int i = 0; i < state.size(); i++ ) m_log << state[i] << ", ";
    m_log << std::endl;
    //  return false;
    //}

  segment_expressedIn_world = root_expressedIn_world * segment_expressedIn_root;

  return true;
}

KDL::Frame Affordance::GetFrameFromVector(const StateVector& state)
{
  KDL::Frame ret;
  ret.p[0] = state[0];
  ret.p[1] = state[1];
  ret.p[2] = state[2];
  ret.M = KDL::Rotation::RPY(state[3], state[4], state[5]);
  return ret;
}
<commit_msg> <commit_after>#include "Affordance.h"
#include <otdf_lcm_utils/otdf_lcm_utils.h>
#include "ConstraintApp.h"
#include <kdl/treefksolverpos_recursive.hpp>

Affordance::Affordance(const std::string& filename) : m_log(std::cout)
{
  // load the OTDF file
  std::string xml_string;
  if ( !otdf::get_xml_string_from_file(filename, xml_string) ) {
    m_log << "unable to get_xml_string_from_file " << filename << std::endl;
    return;
  }

  //convert OTDF to URDF
  boost::shared_ptr<otdf::ModelInterface> otdf_instance(otdf::parseOTDF(xml_string));
  otdf_instance->update();

  std::string urdf_xml_string(otdf::convertObjectInstanceToCompliantURDFstring(otdf_instance));

  // Parse KDL tree
  if ( !kdl_parser::treeFromString(urdf_xml_string, m_tree) ) {
    m_log << "ERROR: Failed to extract kdl tree from " << filename
	  << " otdf object instance "<< std::endl;
    return;
  }

  UpdateJointNames();

  //print some debug info on the new affordance
  m_log << "Joint names and numbers: " << std::endl;
  PrintJointNames();

  m_log << "created KDL object with " << m_tree.getNrOfJoints() << " joints and "
	<< m_tree.getNrOfSegments() << " segments" << std::endl;
  PrintKdlTree(m_tree, m_tree.getRootSegment()->second, 0);
}

Affordance::Affordance(std::ostream& log, const drc::affordance_t& msg) : m_log(log)
{
  /*
  std::string urdf_xml_string;
  if ( !otdf::AffordanceLcmMsgToUrdfString(msg, urdf_xml_string) ) {
    m_log << "ERROR: failed to process new affordance" << std::endl;
    return;
  }
  */

  const std::string filename(msg.otdf_type);

  // load the OTDF file
  std::string xml_string;
  if ( !otdf::get_xml_string_from_file(filename, xml_string) ) {
    m_log << "unable to get_xml_string_from_file " << filename << std::endl;
    return;
  }

  //convert OTDF to URDF
  boost::shared_ptr<otdf::ModelInterface> otdf_instance(otdf::parseOTDF(xml_string));

  for(int i=0;i<msg.nparams;i++){
    otdf_instance->setParam(msg.param_names[i],msg.params[i]);
    m_log << msg.param_names[i] << "<=" << msg.params[i] << std::endl;
  }
  for(int i=0;i<msg.nstates;i++){
    double pos, vel;
    pos = msg.states[i];
    vel =0;
    otdf_instance->setJointState(msg.state_names[i],pos,vel);
    m_log << msg.state_names[i] << "<=" << pos << std::endl;
  }
  otdf_instance->update();

  std::string urdf_xml_string(otdf::convertObjectInstanceToCompliantURDFstring(otdf_instance));

  // Parse KDL tree
  if ( !kdl_parser::treeFromString(urdf_xml_string, m_tree) ) {
    m_log << "ERROR: Failed to extract kdl tree from " << msg.otdf_type << ", uid=" << msg.uid
	  << " otdf object instance "<< std::endl;
    return;
  }

  UpdateJointNames();

  //print some debug info on the new affordance
  m_log << "xml string: " << std::endl
	<< urdf_xml_string << std::endl;

  m_log << "Joint names and numbers: " << std::endl;
  PrintJointNames();

  m_log << "created KDL object with " << m_tree.getNrOfJoints() << " joints and "
	<< m_tree.getNrOfSegments() << " segments" << std::endl;
  PrintKdlTree(m_tree, m_tree.getRootSegment()->second, 0);
}

void Affordance::PrintKdlTree(const KDL::Tree& tree,
			      const KDL::TreeElement& segment,
			      unsigned int depth)
{
  for ( unsigned int i = 0; i < depth; i++ ) {
    m_log << " ";
  }
  m_log << segment.segment.getName()
	<< ", joint " << segment.segment.getJoint().getName()
	<< " of type " << segment.segment.getJoint().getTypeName()
	<< ", joint #" << segment.q_nr
	<< std::endl;
  for ( unsigned int i = 0; i < segment.children.size(); i++ ) {
    PrintKdlTree(tree, segment.children[i]->second, depth+1);
  }
}

void Affordance::PrintJointNames()
{
  for ( JointMultiIndex::nth_index<0>::type::iterator iter = m_joints.begin();
	iter != m_joints.end(); ++iter ) {
    m_log << iter->name << " #" << iter->num << std::endl;
  }
}

void Affordance::UpdateJointNames(const KDL::TreeElement* element /*=NULL*/)
{
  if ( !element ) {
    m_joints.clear();
    UpdateJointNames(&m_tree.getRootSegment()->second);

    //perform sanity checks; loop through the joints and verify that the q_nr's are sequential and start at zero
    int q_nr = 0;
    for ( JointMultiIndex::nth_index<0>::type::iterator iter = m_joints.begin();
	iter != m_joints.end(); ++iter ) {
      if ( q_nr != iter->num ) {
	m_log << "ERROR: while parsing tree, expected joint #" << q_nr << ", found joint #" << iter->num << std::endl;
	m_joints.clear();
	m_tree = KDL::Tree();
	return;
      }
      q_nr++;
    }
    return;
  }

  if ( element->segment.getJoint().getType() != KDL::Joint::None ) {
    m_joints.insert(Joint(element->segment.getJoint().getName(), element->q_nr));
  }

  for ( unsigned int i = 0; i < element->children.size(); i++ ) {
    UpdateJointNames(&element->children[i]->second);
  }

}

/*
void Affordance::GetState(std::vector<double>& state) const
{
  state = ConstraintApp::FrameToVector(m_basepose);

  for ( JointMultiIndex::nth_index<0>::type::const_iterator iter = m_joints.begin();
	iter != m_joints.end(); ++iter ) {
    state.push_back(iter->value);
  }
}
*/

bool Affordance::GetStateFromMsg(const drc::affordance_t& msg, StateVector& state)
{
  //extract the x,y,z,r,p,w from the msg params
  ConstraintApp::OptionalKDLFrame msgFrame(ConstraintApp::GetFrameFromParams(&msg));
  if ( !msgFrame ) {
    m_log << "ERROR: Affordance::UpdateStateFromMsg unable to recover frame from message" << std::endl;
    return false;
  }
  state = ConstraintApp::FrameToVector(*msgFrame);

  //convert the msg.state to a map
  typedef std::map<std::string, double> ValueMap;
  ValueMap values;
  for ( int i=0; i<msg.nstates; i++ ) {
    values.insert(std::pair<std::string, double>(msg.state_names[i], msg.states[i]));
  }

  //iterate through the joints according to their q_nr number
  for ( JointMultiIndex::nth_index<0>::type::iterator iter = m_joints.begin();
	iter != m_joints.end(); ++iter ) {
    ValueMap::iterator match = values.find(iter->name);
    if ( match == values.end() ) {
      m_log << "ERROR: unable to find joint " << iter->name << " in the message state" << std::endl;
      return false;
    }
    state.push_back(match->second);
  }

  //perform sanity checks
  if ( state.size() != 6 + m_joints.size() ) {
    m_log << "ERROR: state has improper size" << std::endl;
    return false;
  }

  return true;
}

void Affordance::PrintState(const StateVector& state)
{
  for ( int i = 0; i < state.size(); i++ ) {
    m_log << state[i] << ", ";
  }
  m_log << std::endl;
}

bool Affordance::DecodeState(const StateVector& state, KDL::Frame& root_expressedIn_world, KDL::JntArray& joints)
{
  const int basePoseSize = 6;
  if ( state.size() < basePoseSize ) {
    m_log << "ERROR: Affordance::DecodeState must be of at least size 6 (not " << state.size() << ")" << std::endl;
    m_log << "   state=";
    for ( int i = 0; i < state.size(); i++ ) m_log << state[i] << ", ";
    m_log << std::endl;
    return false;
  }

  root_expressedIn_world = GetFrameFromVector(state);

  int numJoints = state.size() - basePoseSize;
  if ( numJoints < 0 ) return false;
  joints.resize(numJoints);
  for ( int i = 0; i < numJoints; i++ ) {
    joints(i) = state[i+basePoseSize];
  }

  return true;
}

bool Affordance::GetSegmentExpressedInWorld(const std::string& segmentName, const StateVector& state,
					    KDL::Frame& segment_expressedIn_world)
{
  KDL::Frame root_expressedIn_world;
  KDL::JntArray joints;
  if ( !DecodeState(state, root_expressedIn_world, joints) ) {
    return false;
  }

  KDL::Frame segment_expressedIn_root;
  KDL::TreeFkSolverPos_recursive fk(m_tree);
  int fkret = fk.JntToCart(joints, segment_expressedIn_root, segmentName);
  if ( fkret < 0 ) {
    m_log << "ERROR: Affordance::GetSegmentExpressedInWorld: fk returned " << fkret << std::endl
	  << "   segmentName=" << segmentName << std::endl
	  << "   joints=" << joints.data << std::endl;
    m_log << "   state=";
    for ( int i = 0; i < state.size(); i++ ) m_log << state[i] << ", ";
    m_log << std::endl;
    return false;
  }

  segment_expressedIn_world = root_expressedIn_world * segment_expressedIn_root;

  return true;
}

KDL::Frame Affordance::GetFrameFromVector(const StateVector& state)
{
  KDL::Frame ret;
  ret.p[0] = state[0];
  ret.p[1] = state[1];
  ret.p[2] = state[2];
  ret.M = KDL::Rotation::RPY(state[3], state[4], state[5]);
  return ret;
}
<|endoftext|>


<commit_before>/*
 *  yosys -- Yosys Open SYnthesis Suite
 *
 *  Copyright (C) 2012  Clifford Wolf <clifford@clifford.at>
 *
 *  Permission to use, copy, modify, and/or distribute this software for any
 *  purpose with or without fee is hereby granted, provided that the above
 *  copyright notice and this permission notice appear in all copies.
 *
 *  THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 *  WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 *  MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
 *  ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 *  WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 *  ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 *  OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 *
 */

#include "kernel/yosys.h"
#include "kernel/sigtools.h"

USING_YOSYS_NAMESPACE
PRIVATE_NAMESPACE_BEGIN

int lut2mux(Cell *cell)
{
	SigSpec sig_a = cell->getPort("\\A");
	SigSpec sig_y = cell->getPort("\\Y");
	Const lut = cell->getParam("\\LUT");
	int count = 1;

	if (GetSize(sig_a) == 1)
	{
		cell->module->addMuxGate(NEW_ID, lut[0], lut[1], sig_a, sig_y);
	}
	else
	{
		SigSpec sig_a_hi = sig_a[GetSize(sig_a)-1];
		SigSpec sig_a_lo = sig_a.extract(0, GetSize(sig_a)-1);
		SigSpec sig_y1 = cell->module->addWire(NEW_ID);
		SigSpec sig_y2 = cell->module->addWire(NEW_ID);

		Const lut1 = lut.extract(0, GetSize(lut)/2);
		Const lut2 = lut.extract(GetSize(lut)/2, GetSize(lut)/2);

		count += lut2mux(cell->module->addLut(NEW_ID, sig_a_lo, sig_y1, lut1));
		count += lut2mux(cell->module->addLut(NEW_ID, sig_a_lo, sig_y2, lut2));

		cell->module->addMuxGate(NEW_ID, sig_y1, sig_y2, sig_a_hi, sig_y);
	}

	cell->module->remove(cell);
	return count;
}

struct Lut2muxPass : public Pass {
	Lut2muxPass() : Pass("lut2mux", "convert $lut to $_MUX_") { }
	virtual void help()
	{
		//   |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
		log("\n");
		log("    lut2mux [options] [selection]\n");
		log("\n");
		log("This pass converts $lut cells to $_MUX_ gates.\n");
		log("\n");
	}
	virtual void execute(std::vector<std::string> args, RTLIL::Design *design)
	{
		log_header("Executing LUT2MUX pass (mapping to constant drivers).\n");

		size_t argidx;
		for (argidx = 1; argidx < args.size(); argidx++)
		{
			// if (args[argidx] == "-v") {
			// 	continue;
			// }
			break;
		}
		extra_args(args, argidx, design);

		for (auto module : design->selected_modules())
		for (auto cell : module->selected_cells()) {
			if (cell->type == "$lut") {
				IdString cell_name = cell->name;
				int count = lut2mux(cell);
				log("Converted %s.%s to %d MUX cells.\n", log_id(module), log_id(cell_name), count);
			}
		}
	}
} Lut2muxPass;

PRIVATE_NAMESPACE_END
<commit_msg>Fixed copy&paste error in log message in lut2mux<commit_after>/*
 *  yosys -- Yosys Open SYnthesis Suite
 *
 *  Copyright (C) 2012  Clifford Wolf <clifford@clifford.at>
 *
 *  Permission to use, copy, modify, and/or distribute this software for any
 *  purpose with or without fee is hereby granted, provided that the above
 *  copyright notice and this permission notice appear in all copies.
 *
 *  THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 *  WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 *  MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
 *  ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 *  WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 *  ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 *  OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 *
 */

#include "kernel/yosys.h"
#include "kernel/sigtools.h"

USING_YOSYS_NAMESPACE
PRIVATE_NAMESPACE_BEGIN

int lut2mux(Cell *cell)
{
	SigSpec sig_a = cell->getPort("\\A");
	SigSpec sig_y = cell->getPort("\\Y");
	Const lut = cell->getParam("\\LUT");
	int count = 1;

	if (GetSize(sig_a) == 1)
	{
		cell->module->addMuxGate(NEW_ID, lut[0], lut[1], sig_a, sig_y);
	}
	else
	{
		SigSpec sig_a_hi = sig_a[GetSize(sig_a)-1];
		SigSpec sig_a_lo = sig_a.extract(0, GetSize(sig_a)-1);
		SigSpec sig_y1 = cell->module->addWire(NEW_ID);
		SigSpec sig_y2 = cell->module->addWire(NEW_ID);

		Const lut1 = lut.extract(0, GetSize(lut)/2);
		Const lut2 = lut.extract(GetSize(lut)/2, GetSize(lut)/2);

		count += lut2mux(cell->module->addLut(NEW_ID, sig_a_lo, sig_y1, lut1));
		count += lut2mux(cell->module->addLut(NEW_ID, sig_a_lo, sig_y2, lut2));

		cell->module->addMuxGate(NEW_ID, sig_y1, sig_y2, sig_a_hi, sig_y);
	}

	cell->module->remove(cell);
	return count;
}

struct Lut2muxPass : public Pass {
	Lut2muxPass() : Pass("lut2mux", "convert $lut to $_MUX_") { }
	virtual void help()
	{
		//   |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
		log("\n");
		log("    lut2mux [options] [selection]\n");
		log("\n");
		log("This pass converts $lut cells to $_MUX_ gates.\n");
		log("\n");
	}
	virtual void execute(std::vector<std::string> args, RTLIL::Design *design)
	{
		log_header("Executing LUT2MUX pass (convert $lut to $_MUX_).\n");

		size_t argidx;
		for (argidx = 1; argidx < args.size(); argidx++)
		{
			// if (args[argidx] == "-v") {
			// 	continue;
			// }
			break;
		}
		extra_args(args, argidx, design);

		for (auto module : design->selected_modules())
		for (auto cell : module->selected_cells()) {
			if (cell->type == "$lut") {
				IdString cell_name = cell->name;
				int count = lut2mux(cell);
				log("Converted %s.%s to %d MUX cells.\n", log_id(module), log_id(cell_name), count);
			}
		}
	}
} Lut2muxPass;

PRIVATE_NAMESPACE_END
<|endoftext|>


<commit_before>/// \file RNTupleDescriptorFmt.cxx
/// \ingroup NTuple ROOT7
/// \author Jakob Blomer <jblomer@cern.ch>
/// \date 2019-08-25
/// \warning This is part of the ROOT 7 prototype! It will change without notice. It might trigger earthquakes. Feedback
/// is welcome!

/*************************************************************************
 * Copyright (C) 1995-2019, Rene Brun and Fons Rademakers.               *
 * All rights reserved.                                                  *
 *                                                                       *
 * For the licensing terms see $ROOTSYS/LICENSE.                         *
 * For the list of contributors see $ROOTSYS/README/CREDITS.             *
 *************************************************************************/

#include <ROOT/RColumnElement.hxx>
#include <ROOT/RColumnModel.hxx>
#include <ROOT/RNTupleDescriptor.hxx>
#include <ROOT/RNTupleUtil.hxx>

#include <algorithm>
#include <iomanip>
#include <ostream>
#include <unordered_map>
#include <vector>

namespace {

struct ClusterInfo {
   std::uint64_t fFirstEntry = 0;
   std::uint32_t fNPages = 0;
   std::uint32_t fNEntries = 0;
   std::uint32_t fBytesOnStorage = 0;
   std::uint32_t fBytesInMemory = 0;

   bool operator ==(const ClusterInfo &other) const {
      return fFirstEntry == other.fFirstEntry;
   }

   bool operator <(const ClusterInfo &other) const {
      return fFirstEntry < other.fFirstEntry;
   }
};

struct ColumnInfo {
   ROOT::Experimental::DescriptorId_t fColumnId = 0;
   ROOT::Experimental::DescriptorId_t fFieldId = 0;
   std::uint64_t fLocalOrder = 0;
   std::uint64_t fNElements = 0;
   std::uint64_t fNPages = 0;
   std::uint64_t fBytesOnStorage = 0;
   std::uint32_t fElementSize = 0;
   ROOT::Experimental::EColumnType fType;
   std::string fFieldName;
   std::string fFieldDescription;

   bool operator <(const ColumnInfo &other) const {
      if (fFieldName == other.fFieldName)
         return fLocalOrder < other.fLocalOrder;
      return fFieldName < other.fFieldName;
   }
};

static std::string GetFieldName(ROOT::Experimental::DescriptorId_t fieldId,
   const ROOT::Experimental::RNTupleDescriptor &ntupleDesc)
{
   const auto &fieldDesc = ntupleDesc.GetFieldDescriptor(fieldId);
   if (fieldDesc.GetParentId() == ROOT::Experimental::kInvalidDescriptorId)
      return fieldDesc.GetFieldName();
   return GetFieldName(fieldDesc.GetParentId(), ntupleDesc) + "." + fieldDesc.GetFieldName();
}

static std::string GetFieldDescription(ROOT::Experimental::DescriptorId_t fFieldId,
   const ROOT::Experimental::RNTupleDescriptor &ntupleDesc)
{
   const auto &fieldDesc = ntupleDesc.GetFieldDescriptor(fFieldId);
   return fieldDesc.GetFieldDescription();
}

} // anonymous namespace

void ROOT::Experimental::RNTupleDescriptor::PrintInfo(std::ostream &output) const
{
   std::vector<ColumnInfo> columns;
   std::vector<ClusterInfo> clusters;
   std::unordered_map<DescriptorId_t, unsigned int> cluster2Idx;
   for (const auto &cluster : fClusterDescriptors) {
      ClusterInfo info;
      info.fFirstEntry = cluster.second.GetFirstEntryIndex();
      info.fNEntries = cluster.second.GetNEntries();
      cluster2Idx[cluster.first] = clusters.size();
      clusters.emplace_back(info);
   }

   std::uint64_t bytesOnStorage = 0;
   std::uint64_t bytesInMemory = 0;
   std::uint64_t nPages = 0;
   int compression = -1;
   for (const auto &column : fColumnDescriptors) {
      // We generate the default memory representation for the given column type in order
      // to report the size _in memory_ of column elements
      auto elementSize = Detail::RColumnElementBase::Generate(column.second.GetModel().GetType())->GetSize();

      ColumnInfo info;
      info.fColumnId = column.second.GetId();
      info.fFieldId = column.second.GetFieldId();
      info.fLocalOrder = column.second.GetIndex();
      info.fElementSize = elementSize;
      info.fType = column.second.GetModel().GetType();

      for (const auto &cluster : fClusterDescriptors) {
         auto columnRange = cluster.second.GetColumnRange(column.first);
         info.fNElements += columnRange.fNElements;
         if (compression == -1) {
            compression = columnRange.fCompressionSettings;
         }
         const auto &pageRange = cluster.second.GetPageRange(column.first);
         auto idx = cluster2Idx[cluster.first];
         for (const auto &page : pageRange.fPageInfos) {
            bytesOnStorage += page.fLocator.fBytesOnStorage;
            bytesInMemory += page.fNElements * elementSize;
            clusters[idx].fBytesOnStorage += page.fLocator.fBytesOnStorage;
            clusters[idx].fBytesInMemory += page.fNElements * elementSize;
            ++clusters[idx].fNPages;
            info.fBytesOnStorage += page.fLocator.fBytesOnStorage;
            ++info.fNPages;
            ++nPages;
         }
      }
      columns.emplace_back(info);
   }
   auto headerSize = GetHeaderSize();
   auto footerSize = GetFooterSize();
   output << "============================================================" << std::endl;
   output << "NTUPLE:      " << GetName() << std::endl;
   output << "Compression: " << compression << std::endl;
   output << "------------------------------------------------------------" << std::endl;
   output << "  # Entries:        " << GetNEntries() << std::endl;
   output << "  # Fields:         " << GetNFields() << std::endl;
   output << "  # Columns:        " << GetNColumns() << std::endl;
   output << "  # Pages:          " << nPages << std::endl;
   output << "  # Clusters:       " << GetNClusters() << std::endl;
   output << "  Size on storage:  " << bytesOnStorage << " B" << std::endl;
   output << "  Compression rate: " << std::fixed << std::setprecision(2)
                                    << float(bytesInMemory) / float(bytesOnStorage) << std::endl;
   output << "  Header size:      " << headerSize << " B" << std::endl;
   output << "  Footer size:      " << footerSize << " B" << std::endl;
   output << "  Meta-data / data: " << std::fixed << std::setprecision(3)
                                    << float(headerSize + footerSize) / float(bytesOnStorage) << std::endl;
   output << "------------------------------------------------------------" << std::endl;
   output << "CLUSTER DETAILS" << std::endl;
   output << "------------------------------------------------------------" << std::endl;

   std::sort(clusters.begin(), clusters.end());
   for (unsigned int i = 0; i < clusters.size(); ++i) {
      output << "  # " << std::setw(5) << i
             << "   Entry range:     [" << clusters[i].fFirstEntry << ".."
             << clusters[i].fFirstEntry + clusters[i].fNEntries - 1 << "]  --  " << clusters[i].fNEntries << std::endl;
      output << "         "
             << "   # Pages:         " << clusters[i].fNPages << std::endl;
      output << "         "
             << "   Size on storage: " << clusters[i].fBytesOnStorage << " B" << std::endl;
      output << "         "
             << "   Compression:     " << std::fixed << std::setprecision(2)
             << float(clusters[i].fBytesInMemory) / float(float(clusters[i].fBytesOnStorage)) << std::endl;
   }

   output << "------------------------------------------------------------" << std::endl;
   output << "COLUMN DETAILS" << std::endl;
   output << "------------------------------------------------------------" << std::endl;
   for (auto &col : columns) {
      col.fFieldName = GetFieldName(col.fFieldId, *this).substr(1);
      col.fFieldDescription = GetFieldDescription(col.fFieldId, *this);
   }
   std::sort(columns.begin(), columns.end());
   for (const auto &col : columns) {
      auto avgPageSize = (col.fNPages == 0) ? 0 : (col.fBytesOnStorage / col.fNPages);
      auto avgElementsPerPage = (col.fNPages == 0) ? 0 : (col.fNElements / col.fNPages);
      std::string nameAndType = std::string("  ") + col.fFieldName + " [#" + std::to_string(col.fLocalOrder) + "]"
         + "  --  " + Detail::RColumnElementBase::GetTypeName(col.fType);
      std::string id = std::string("{id:") + std::to_string(col.fColumnId) + "}";
      output << nameAndType << std::setw(60 - nameAndType.length()) << id << std::endl;
      if(col.fFieldDescription != "")
         output << "    Description          " << col.fFieldDescription << std::endl;
      output << "    # Elements:          " << col.fNElements << std::endl;
      output << "    # Pages:             " << col.fNPages << std::endl;
      output << "    Avg elements / page: " << avgElementsPerPage << std::endl;
      output << "    Avg page size:       " << avgPageSize << " B" << std::endl;
      output << "    Size on storage:     " << col.fBytesOnStorage << " B" << std::endl;
      output << "    Compression:         " << std::fixed << std::setprecision(2)
             << float(col.fElementSize * col.fNElements) / float(col.fBytesOnStorage) << std::endl;
      output << "............................................................" << std::endl;
   }
}
<commit_msg>semicolon for description field<commit_after>/// \file RNTupleDescriptorFmt.cxx
/// \ingroup NTuple ROOT7
/// \author Jakob Blomer <jblomer@cern.ch>
/// \date 2019-08-25
/// \warning This is part of the ROOT 7 prototype! It will change without notice. It might trigger earthquakes. Feedback
/// is welcome!

/*************************************************************************
 * Copyright (C) 1995-2019, Rene Brun and Fons Rademakers.               *
 * All rights reserved.                                                  *
 *                                                                       *
 * For the licensing terms see $ROOTSYS/LICENSE.                         *
 * For the list of contributors see $ROOTSYS/README/CREDITS.             *
 *************************************************************************/

#include <ROOT/RColumnElement.hxx>
#include <ROOT/RColumnModel.hxx>
#include <ROOT/RNTupleDescriptor.hxx>
#include <ROOT/RNTupleUtil.hxx>

#include <algorithm>
#include <iomanip>
#include <ostream>
#include <unordered_map>
#include <vector>

namespace {

struct ClusterInfo {
   std::uint64_t fFirstEntry = 0;
   std::uint32_t fNPages = 0;
   std::uint32_t fNEntries = 0;
   std::uint32_t fBytesOnStorage = 0;
   std::uint32_t fBytesInMemory = 0;

   bool operator ==(const ClusterInfo &other) const {
      return fFirstEntry == other.fFirstEntry;
   }

   bool operator <(const ClusterInfo &other) const {
      return fFirstEntry < other.fFirstEntry;
   }
};

struct ColumnInfo {
   ROOT::Experimental::DescriptorId_t fColumnId = 0;
   ROOT::Experimental::DescriptorId_t fFieldId = 0;
   std::uint64_t fLocalOrder = 0;
   std::uint64_t fNElements = 0;
   std::uint64_t fNPages = 0;
   std::uint64_t fBytesOnStorage = 0;
   std::uint32_t fElementSize = 0;
   ROOT::Experimental::EColumnType fType;
   std::string fFieldName;
   std::string fFieldDescription;

   bool operator <(const ColumnInfo &other) const {
      if (fFieldName == other.fFieldName)
         return fLocalOrder < other.fLocalOrder;
      return fFieldName < other.fFieldName;
   }
};

static std::string GetFieldName(ROOT::Experimental::DescriptorId_t fieldId,
   const ROOT::Experimental::RNTupleDescriptor &ntupleDesc)
{
   const auto &fieldDesc = ntupleDesc.GetFieldDescriptor(fieldId);
   if (fieldDesc.GetParentId() == ROOT::Experimental::kInvalidDescriptorId)
      return fieldDesc.GetFieldName();
   return GetFieldName(fieldDesc.GetParentId(), ntupleDesc) + "." + fieldDesc.GetFieldName();
}

static std::string GetFieldDescription(ROOT::Experimental::DescriptorId_t fFieldId,
   const ROOT::Experimental::RNTupleDescriptor &ntupleDesc)
{
   const auto &fieldDesc = ntupleDesc.GetFieldDescriptor(fFieldId);
   return fieldDesc.GetFieldDescription();
}

} // anonymous namespace

void ROOT::Experimental::RNTupleDescriptor::PrintInfo(std::ostream &output) const
{
   std::vector<ColumnInfo> columns;
   std::vector<ClusterInfo> clusters;
   std::unordered_map<DescriptorId_t, unsigned int> cluster2Idx;
   for (const auto &cluster : fClusterDescriptors) {
      ClusterInfo info;
      info.fFirstEntry = cluster.second.GetFirstEntryIndex();
      info.fNEntries = cluster.second.GetNEntries();
      cluster2Idx[cluster.first] = clusters.size();
      clusters.emplace_back(info);
   }

   std::uint64_t bytesOnStorage = 0;
   std::uint64_t bytesInMemory = 0;
   std::uint64_t nPages = 0;
   int compression = -1;
   for (const auto &column : fColumnDescriptors) {
      // We generate the default memory representation for the given column type in order
      // to report the size _in memory_ of column elements
      auto elementSize = Detail::RColumnElementBase::Generate(column.second.GetModel().GetType())->GetSize();

      ColumnInfo info;
      info.fColumnId = column.second.GetId();
      info.fFieldId = column.second.GetFieldId();
      info.fLocalOrder = column.second.GetIndex();
      info.fElementSize = elementSize;
      info.fType = column.second.GetModel().GetType();

      for (const auto &cluster : fClusterDescriptors) {
         auto columnRange = cluster.second.GetColumnRange(column.first);
         info.fNElements += columnRange.fNElements;
         if (compression == -1) {
            compression = columnRange.fCompressionSettings;
         }
         const auto &pageRange = cluster.second.GetPageRange(column.first);
         auto idx = cluster2Idx[cluster.first];
         for (const auto &page : pageRange.fPageInfos) {
            bytesOnStorage += page.fLocator.fBytesOnStorage;
            bytesInMemory += page.fNElements * elementSize;
            clusters[idx].fBytesOnStorage += page.fLocator.fBytesOnStorage;
            clusters[idx].fBytesInMemory += page.fNElements * elementSize;
            ++clusters[idx].fNPages;
            info.fBytesOnStorage += page.fLocator.fBytesOnStorage;
            ++info.fNPages;
            ++nPages;
         }
      }
      columns.emplace_back(info);
   }
   auto headerSize = GetHeaderSize();
   auto footerSize = GetFooterSize();
   output << "============================================================" << std::endl;
   output << "NTUPLE:      " << GetName() << std::endl;
   output << "Compression: " << compression << std::endl;
   output << "------------------------------------------------------------" << std::endl;
   output << "  # Entries:        " << GetNEntries() << std::endl;
   output << "  # Fields:         " << GetNFields() << std::endl;
   output << "  # Columns:        " << GetNColumns() << std::endl;
   output << "  # Pages:          " << nPages << std::endl;
   output << "  # Clusters:       " << GetNClusters() << std::endl;
   output << "  Size on storage:  " << bytesOnStorage << " B" << std::endl;
   output << "  Compression rate: " << std::fixed << std::setprecision(2)
                                    << float(bytesInMemory) / float(bytesOnStorage) << std::endl;
   output << "  Header size:      " << headerSize << " B" << std::endl;
   output << "  Footer size:      " << footerSize << " B" << std::endl;
   output << "  Meta-data / data: " << std::fixed << std::setprecision(3)
                                    << float(headerSize + footerSize) / float(bytesOnStorage) << std::endl;
   output << "------------------------------------------------------------" << std::endl;
   output << "CLUSTER DETAILS" << std::endl;
   output << "------------------------------------------------------------" << std::endl;

   std::sort(clusters.begin(), clusters.end());
   for (unsigned int i = 0; i < clusters.size(); ++i) {
      output << "  # " << std::setw(5) << i
             << "   Entry range:     [" << clusters[i].fFirstEntry << ".."
             << clusters[i].fFirstEntry + clusters[i].fNEntries - 1 << "]  --  " << clusters[i].fNEntries << std::endl;
      output << "         "
             << "   # Pages:         " << clusters[i].fNPages << std::endl;
      output << "         "
             << "   Size on storage: " << clusters[i].fBytesOnStorage << " B" << std::endl;
      output << "         "
             << "   Compression:     " << std::fixed << std::setprecision(2)
             << float(clusters[i].fBytesInMemory) / float(float(clusters[i].fBytesOnStorage)) << std::endl;
   }

   output << "------------------------------------------------------------" << std::endl;
   output << "COLUMN DETAILS" << std::endl;
   output << "------------------------------------------------------------" << std::endl;
   for (auto &col : columns) {
      col.fFieldName = GetFieldName(col.fFieldId, *this).substr(1);
      col.fFieldDescription = GetFieldDescription(col.fFieldId, *this);
   }
   std::sort(columns.begin(), columns.end());
   for (const auto &col : columns) {
      auto avgPageSize = (col.fNPages == 0) ? 0 : (col.fBytesOnStorage / col.fNPages);
      auto avgElementsPerPage = (col.fNPages == 0) ? 0 : (col.fNElements / col.fNPages);
      std::string nameAndType = std::string("  ") + col.fFieldName + " [#" + std::to_string(col.fLocalOrder) + "]"
         + "  --  " + Detail::RColumnElementBase::GetTypeName(col.fType);
      std::string id = std::string("{id:") + std::to_string(col.fColumnId) + "}";
      output << nameAndType << std::setw(60 - nameAndType.length()) << id << std::endl;
      if(col.fFieldDescription != "")
         output << "    Description:         " << col.fFieldDescription << std::endl;
      output << "    # Elements:          " << col.fNElements << std::endl;
      output << "    # Pages:             " << col.fNPages << std::endl;
      output << "    Avg elements / page: " << avgElementsPerPage << std::endl;
      output << "    Avg page size:       " << avgPageSize << " B" << std::endl;
      output << "    Size on storage:     " << col.fBytesOnStorage << " B" << std::endl;
      output << "    Compression:         " << std::fixed << std::setprecision(2)
             << float(col.fElementSize * col.fNElements) / float(col.fBytesOnStorage) << std::endl;
      output << "............................................................" << std::endl;
   }
}
<|endoftext|>


<commit_before>#include "pending_irob.h"
#include "pending_receiver_irob.h"
#include "debug.h"
#include "timeops.h"
#include "cmm_socket.private.h"
#include "pthread_util.h"
#include <algorithm>
#include <vector>
using std::min; using std::vector;

PendingReceiverIROB::PendingReceiverIROB(struct begin_irob_data begin_irob,
					 u_long send_labels)
    : PendingIROB(begin_irob.id, begin_irob.numdeps, begin_irob.deps,
                  send_labels), offset(0), num_bytes(0)
{
    partial_chunk.data = NULL;
    partial_chunk.datalen = 0;
}

PendingReceiverIROB::PendingReceiverIROB(struct default_irob_data default_irob,
					 u_long send_labels)
    : PendingIROB(default_irob.id, default_irob.datalen, default_irob.data,
                  send_labels), offset(0),
      num_bytes(default_irob.datalen)
{
    partial_chunk.data = NULL;
    partial_chunk.datalen = 0;
}

PendingReceiverIROB::~PendingReceiverIROB()
{
    // XXX: make sure there are no races here
    delete [] partial_chunk.data;
}

bool
PendingReceiverIROB::add_chunk(struct irob_chunk_data& chunk)
{
    bool result = PendingIROB::add_chunk(chunk);
    if (result) {
        num_bytes += chunk.datalen;
	dbgprintf("Added chunk %d (%d bytes) to IROB %d\n",
		  chunk.seqno, chunk.datalen, id);
    } else {
	dbgprintf("Adding chunk %d (%d bytes) on IROB %d failed!\n",
		  chunk.seqno, chunk.datalen, id);
    }
    return result;
}

bool
PendingReceiverIROB::is_ready(void)
{
    return deps.empty();
}

ssize_t
PendingReceiverIROB::read_data(void *buf, size_t len)
{
    ssize_t bytes_copied = 0;

    dbgprintf("Attempting to copy %lu bytes from irob %d, which has %d bytes,\n"
	      "                   %d untouched chunks, and %s partial chunk\n",
	      len, id, num_bytes, chunks.size(), (partial_chunk.data?"a":"no"));
    if (partial_chunk.data) {
	dbgprintf("Copying first from partial chunk; offset=%d, datalen=%d\n",
		  offset, partial_chunk.datalen);
        ssize_t bytes = min(len, partial_chunk.datalen - offset);
        assert(bytes > 0);
        memcpy(buf, partial_chunk.data + offset, bytes);
        if (len >= (partial_chunk.datalen - offset)) {
            delete [] partial_chunk.data;
            partial_chunk.data = NULL;
            partial_chunk.datalen = 0;
            offset = 0;
        } else {
            offset += bytes;
        }
        len -= bytes;
        bytes_copied += bytes;
    }

    /* if len == 0 here, we'll skip the loop */
    while (len > 0 && !chunks.empty()) {
        struct irob_chunk_data chunk = chunks.front();
        chunks.pop_front();

	dbgprintf("Copying from chunk: datalen=%d, data=%p\n",
		  chunk.datalen, chunk.data);

        ssize_t bytes = min(len, chunk.datalen);
        memcpy((char*)buf + bytes_copied, chunk.data, bytes);
        bytes_copied += bytes;
        if (chunk.datalen > len) {
            offset = bytes;
            partial_chunk = chunk;
        } else {
            delete [] chunk.data;
        }
        len -= bytes;
	dbgprintf("Read %d bytes; %d bytes remaining in request\n",
		  bytes, len);
    }
    num_bytes -= bytes_copied;
    dbgprintf("Copied %d bytes from IROB %d\n", bytes_copied, id);
    return bytes_copied;
}

ssize_t
PendingReceiverIROB::numbytes()
{
    return num_bytes;
}

PendingReceiverIROBLattice::PendingReceiverIROBLattice(CMMSocketImpl *sk_)
    : sk(sk_), partially_read_irob(NULL)
{
}

PendingReceiverIROBLattice::~PendingReceiverIROBLattice()
{
    // XXX: make sure there are no races here
    delete partially_read_irob;
}

bool
PendingReceiverIROBLattice::data_is_ready()
{
    PthreadScopedLock lock(&sk->scheduling_state_lock);
    return (!ready_irobs.empty());
}

/* REQ: call with scheduling_state_lock held
 *
 * There's a race on partially_read_irob between get_ready_irob and
 * partially_read below, but they are only called sequentially. */
PendingReceiverIROB *
PendingReceiverIROBLattice::get_ready_irob()
{
    irob_id_t ready_irob_id = -1;
    PendingIROB *pi = NULL;
    PendingReceiverIROB *pirob = NULL;
    if (partially_read_irob) {
        if (!partially_read_irob->is_complete()) {
            /* TODO: block until more bytes are available */
	    assert(0);
        }
        pirob = partially_read_irob;
        partially_read_irob = NULL;
        dbgprintf("get_ready_irob: returning partially-read IROB %d\n",
                  pirob->id);
    } else {
        /* TODO: nonblocking */
	struct timeval begin, end, diff;
	TIME(begin);
        while (pi == NULL) {
#ifndef CMM_UNIT_TESTING
            while (ready_irobs.empty()) {
                assert(sk);
                if (sk->is_shutting_down()) {
                    dbgprintf("get_ready_irob: returning NULL\n");
                    return NULL;
                }
                pthread_cond_wait(&sk->scheduling_state_cv, &sk->scheduling_state_lock);
            }
#endif

            if (!pop_item(ready_irobs, ready_irob_id)) {
                assert(0);
            }
            pi = find(ready_irob_id);
            if (!pi) {
                dbgprintf("Looks like IROB %d was already received; "
                          "ignoring\n", ready_irob_id);
            }
	}
	TIME(end);
	TIMEDIFF(begin, end, diff);
	dbgprintf("recv: spent %lu.%06lu seconds waiting for a ready IROB\n",
		  diff.tv_sec, diff.tv_usec);

        assert(pi);
        pirob = dynamic_cast<PendingReceiverIROB*>(pi);
        assert(pirob);

        dbgprintf("get_ready_irob: returning IROB %d\n",
                  pirob->id);
    }
    return pirob;
}

// must call with scheduling_state_lock held
void
PendingReceiverIROBLattice::release(irob_id_t id)
{
    if (ready_irobs.empty()) {
#ifndef CMM_UNIT_TESTING
        char c = 42; // value will be ignored
        (void)write(sk->select_pipe[1], &c, 1);
        dbgprintf("waking selectors for msocket %d\n",
                  sk->sock);
#endif
    }
    ready_irobs.insert(id);
#ifndef CMM_UNIT_TESTING
    pthread_cond_broadcast(&sk->scheduling_state_cv);
#endif
}

/* This is where all the scheduling logic happens.
 * This function decides how to pass IROB data to the application.
 */
/* TODO: nonblocking mode */
ssize_t
PendingReceiverIROBLattice::recv(void *bufp, size_t len, int flags,
                                 u_long *recv_labels)
{
    vector<PendingReceiverIROB *> pirobs;
    char *buf = (char*)bufp;

    struct timeval begin, end, diff;
    TIME(begin);

#ifndef CMM_UNIT_TESTING
    PthreadScopedLock lock(&sk->scheduling_state_lock);
    // will be released while waiting for bytes to arrive
#endif

    ssize_t bytes_passed = 0;
    while ((size_t)bytes_passed < len) {
	struct timeval one_begin, one_end, one_diff;
	TIME(one_begin);
        PendingReceiverIROB *pirob = get_ready_irob();
	TIME(one_end);
	TIMEDIFF(one_begin, one_end, one_diff);
	dbgprintf("Getting one ready IROB took %lu.%06lu seconds\n",
		  one_diff.tv_sec, one_diff.tv_usec);
	if (!pirob) {
            // XXX: for now assume we're shutting down; we need a sentinel
            // to differentiate this from non-blocking read with no ready data

#ifdef CMM_UNIT_TESTING
            return bytes_passed;
#else
            assert(sk);
	    if (sk->is_shutting_down()) {
                return bytes_passed;
            } else {
	        assert(0); /* XXX: nonblocking case may return NULL */
            }
#endif
	}

        /* after the IROB is returned here, no other thread will
         * unsafely modify it.
         * XXX: this will not be true if we allow get_next_irob
         * to return ready, incomplete IROBs.
         * We could fix that by simply having a sentinel chunk
         * on the queue of chunks. */

        assert(pirob->is_ready());
        assert(pirob->is_complete()); /* XXX: see get_next_irob */

        if (bytes_passed == 0) {
            if (recv_labels) {
                *recv_labels = pirob->send_labels;
            }
        }

        bytes_passed += pirob->read_data(buf + bytes_passed,
                                         len - bytes_passed);
        if (pirob->is_complete() && pirob->numbytes() == 0) {
            erase(pirob->id);
            release_dependents(pirob, ReadyIROB());
            delete pirob;
        } else {
            assert(partially_read_irob == NULL);
            partially_read_irob = pirob;
        }
    }
    TIME(end);
    TIMEDIFF(begin, end, diff);
    dbgprintf("recv: gathering and copying bytes took %lu.%06lu seconds\n",
	      diff.tv_sec, diff.tv_usec);

    dbgprintf("Passing %d bytes to application\n", bytes_passed);
    return bytes_passed;
}
<commit_msg>small bug in PendingReceiverIROBLattice::data_is_ready; forgot to check partially_read_irob.  Don't know if it will make a difference in this case, though.<commit_after>#include "pending_irob.h"
#include "pending_receiver_irob.h"
#include "debug.h"
#include "timeops.h"
#include "cmm_socket.private.h"
#include "pthread_util.h"
#include <algorithm>
#include <vector>
using std::min; using std::vector;

PendingReceiverIROB::PendingReceiverIROB(struct begin_irob_data begin_irob,
					 u_long send_labels)
    : PendingIROB(begin_irob.id, begin_irob.numdeps, begin_irob.deps,
                  send_labels), offset(0), num_bytes(0)
{
    partial_chunk.data = NULL;
    partial_chunk.datalen = 0;
}

PendingReceiverIROB::PendingReceiverIROB(struct default_irob_data default_irob,
					 u_long send_labels)
    : PendingIROB(default_irob.id, default_irob.datalen, default_irob.data,
                  send_labels), offset(0),
      num_bytes(default_irob.datalen)
{
    partial_chunk.data = NULL;
    partial_chunk.datalen = 0;
}

PendingReceiverIROB::~PendingReceiverIROB()
{
    // XXX: make sure there are no races here
    delete [] partial_chunk.data;
}

bool
PendingReceiverIROB::add_chunk(struct irob_chunk_data& chunk)
{
    bool result = PendingIROB::add_chunk(chunk);
    if (result) {
        num_bytes += chunk.datalen;
	dbgprintf("Added chunk %d (%d bytes) to IROB %d\n",
		  chunk.seqno, chunk.datalen, id);
    } else {
	dbgprintf("Adding chunk %d (%d bytes) on IROB %d failed!\n",
		  chunk.seqno, chunk.datalen, id);
    }
    return result;
}

bool
PendingReceiverIROB::is_ready(void)
{
    return deps.empty();
}

ssize_t
PendingReceiverIROB::read_data(void *buf, size_t len)
{
    ssize_t bytes_copied = 0;

    dbgprintf("Attempting to copy %lu bytes from irob %d, which has %d bytes,\n"
	      "                   %d untouched chunks, and %s partial chunk\n",
	      len, id, num_bytes, chunks.size(), (partial_chunk.data?"a":"no"));
    if (partial_chunk.data) {
	dbgprintf("Copying first from partial chunk; offset=%d, datalen=%d\n",
		  offset, partial_chunk.datalen);
        ssize_t bytes = min(len, partial_chunk.datalen - offset);
        assert(bytes > 0);
        memcpy(buf, partial_chunk.data + offset, bytes);
        if (len >= (partial_chunk.datalen - offset)) {
            delete [] partial_chunk.data;
            partial_chunk.data = NULL;
            partial_chunk.datalen = 0;
            offset = 0;
        } else {
            offset += bytes;
        }
        len -= bytes;
        bytes_copied += bytes;
    }

    /* if len == 0 here, we'll skip the loop */
    while (len > 0 && !chunks.empty()) {
        struct irob_chunk_data chunk = chunks.front();
        chunks.pop_front();

	dbgprintf("Copying from chunk: datalen=%d, data=%p\n",
		  chunk.datalen, chunk.data);

        ssize_t bytes = min(len, chunk.datalen);
        memcpy((char*)buf + bytes_copied, chunk.data, bytes);
        bytes_copied += bytes;
        if (chunk.datalen > len) {
            offset = bytes;
            partial_chunk = chunk;
        } else {
            delete [] chunk.data;
        }
        len -= bytes;
	dbgprintf("Read %d bytes; %d bytes remaining in request\n",
		  bytes, len);
    }
    num_bytes -= bytes_copied;
    dbgprintf("Copied %d bytes from IROB %d\n", bytes_copied, id);
    return bytes_copied;
}

ssize_t
PendingReceiverIROB::numbytes()
{
    return num_bytes;
}

PendingReceiverIROBLattice::PendingReceiverIROBLattice(CMMSocketImpl *sk_)
    : sk(sk_), partially_read_irob(NULL)
{
}

PendingReceiverIROBLattice::~PendingReceiverIROBLattice()
{
    // XXX: make sure there are no races here
    delete partially_read_irob;
}

bool
PendingReceiverIROBLattice::data_is_ready()
{
    PthreadScopedLock lock(&sk->scheduling_state_lock);
    return (partially_read_irob || !ready_irobs.empty());
}

/* REQ: call with scheduling_state_lock held
 *
 * There's a race on partially_read_irob between get_ready_irob and
 * partially_read below, but they are only called sequentially. */
PendingReceiverIROB *
PendingReceiverIROBLattice::get_ready_irob()
{
    irob_id_t ready_irob_id = -1;
    PendingIROB *pi = NULL;
    PendingReceiverIROB *pirob = NULL;
    if (partially_read_irob) {
        if (!partially_read_irob->is_complete()) {
            /* TODO: block until more bytes are available */
	    assert(0);
        }
        pirob = partially_read_irob;
        partially_read_irob = NULL;
        dbgprintf("get_ready_irob: returning partially-read IROB %d\n",
                  pirob->id);
    } else {
        /* TODO: nonblocking */
	struct timeval begin, end, diff;
	TIME(begin);
        while (pi == NULL) {
#ifndef CMM_UNIT_TESTING
            while (ready_irobs.empty()) {
                assert(sk);
                if (sk->is_shutting_down()) {
                    dbgprintf("get_ready_irob: returning NULL\n");
                    return NULL;
                }
                pthread_cond_wait(&sk->scheduling_state_cv, &sk->scheduling_state_lock);
            }
#endif

            if (!pop_item(ready_irobs, ready_irob_id)) {
                assert(0);
            }
            pi = find(ready_irob_id);
            if (!pi) {
                dbgprintf("Looks like IROB %d was already received; "
                          "ignoring\n", ready_irob_id);
            }
	}
	TIME(end);
	TIMEDIFF(begin, end, diff);
	dbgprintf("recv: spent %lu.%06lu seconds waiting for a ready IROB\n",
		  diff.tv_sec, diff.tv_usec);

        assert(pi);
        pirob = dynamic_cast<PendingReceiverIROB*>(pi);
        assert(pirob);

        dbgprintf("get_ready_irob: returning IROB %d\n",
                  pirob->id);
    }
    return pirob;
}

// must call with scheduling_state_lock held
void
PendingReceiverIROBLattice::release(irob_id_t id)
{
    if (ready_irobs.empty()) {
#ifndef CMM_UNIT_TESTING
        char c = 42; // value will be ignored
        (void)write(sk->select_pipe[1], &c, 1);
        dbgprintf("waking selectors for msocket %d\n",
                  sk->sock);
#endif
    }
    ready_irobs.insert(id);
#ifndef CMM_UNIT_TESTING
    pthread_cond_broadcast(&sk->scheduling_state_cv);
#endif
}

/* This is where all the scheduling logic happens.
 * This function decides how to pass IROB data to the application.
 */
/* TODO: nonblocking mode */
ssize_t
PendingReceiverIROBLattice::recv(void *bufp, size_t len, int flags,
                                 u_long *recv_labels)
{
    vector<PendingReceiverIROB *> pirobs;
    char *buf = (char*)bufp;

    struct timeval begin, end, diff;
    TIME(begin);

#ifndef CMM_UNIT_TESTING
    PthreadScopedLock lock(&sk->scheduling_state_lock);
    // will be released while waiting for bytes to arrive
#endif

    ssize_t bytes_passed = 0;
    while ((size_t)bytes_passed < len) {
	struct timeval one_begin, one_end, one_diff;
	TIME(one_begin);
        PendingReceiverIROB *pirob = get_ready_irob();
	TIME(one_end);
	TIMEDIFF(one_begin, one_end, one_diff);
	dbgprintf("Getting one ready IROB took %lu.%06lu seconds\n",
		  one_diff.tv_sec, one_diff.tv_usec);
	if (!pirob) {
            // XXX: for now assume we're shutting down; we need a sentinel
            // to differentiate this from non-blocking read with no ready data

#ifdef CMM_UNIT_TESTING
            return bytes_passed;
#else
            assert(sk);
	    if (sk->is_shutting_down()) {
                return bytes_passed;
            } else {
	        assert(0); /* XXX: nonblocking case may return NULL */
            }
#endif
	}

        /* after the IROB is returned here, no other thread will
         * unsafely modify it.
         * XXX: this will not be true if we allow get_next_irob
         * to return ready, incomplete IROBs.
         * We could fix that by simply having a sentinel chunk
         * on the queue of chunks. */

        assert(pirob->is_ready());
        assert(pirob->is_complete()); /* XXX: see get_next_irob */

        if (bytes_passed == 0) {
            if (recv_labels) {
                *recv_labels = pirob->send_labels;
            }
        }

        bytes_passed += pirob->read_data(buf + bytes_passed,
                                         len - bytes_passed);
        if (pirob->is_complete() && pirob->numbytes() == 0) {
            erase(pirob->id);
            release_dependents(pirob, ReadyIROB());
            delete pirob;
        } else {
            assert(partially_read_irob == NULL);
            partially_read_irob = pirob;
        }
    }
    TIME(end);
    TIMEDIFF(begin, end, diff);
    dbgprintf("recv: gathering and copying bytes took %lu.%06lu seconds\n",
	      diff.tv_sec, diff.tv_usec);

    dbgprintf("Passing %d bytes to application\n", bytes_passed);
    return bytes_passed;
}
<|endoftext|>


<commit_before><commit_msg>Eliminate superfluous member of guarded_container<commit_after><|endoftext|>


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

#ifndef _LOCKENTRYSEQUENCE_HXX_
#include "LockEntrySequence.hxx"
#endif

using namespace webdav_ucp;
using namespace com::sun::star;

//////////////////////////////////////////////////////////////////////////

#define DAV_ELM_LOCK_FIRST (NE_ELM_UNUSED)

#define DAV_ELM_lockentry (DAV_ELM_LOCK_FIRST + 1)
#define DAV_ELM_lockscope (DAV_ELM_LOCK_FIRST + 2)
#define DAV_ELM_locktype  (DAV_ELM_LOCK_FIRST + 3)
#define DAV_ELM_exclusive (DAV_ELM_LOCK_FIRST + 4)
#define DAV_ELM_shared    (DAV_ELM_LOCK_FIRST + 5)
#define DAV_ELM_write     (DAV_ELM_LOCK_FIRST + 6)

// static
const struct ne_xml_elm LockEntrySequence::elements[] =
{
    { "", "lockentry",  DAV_ELM_lockentry, 0 },
    { "", "lockscope",  DAV_ELM_lockscope, 0 },
    { "", "locktype",   DAV_ELM_locktype,  0 },
    { "", "exclusive",  DAV_ELM_exclusive, 0 }, // leaf
    { "", "shared",     DAV_ELM_shared,    0 }, // leaf
    { "", "write",      DAV_ELM_write,     0 }, // leaf
    { 0 }
};

struct LockEntrySequenceParseContext
{
    ucb::LockEntry * pEntry;

    LockEntrySequenceParseContext() : pEntry( 0 ) {}
    ~LockEntrySequenceParseContext() { delete pEntry; }
};

//////////////////////////////////////////////////////////////////////////
extern "C" int LinkEntrySequence_validate_callback( void * userdata,
                                                    ne_xml_elmid parent,
                                                    ne_xml_elmid child )
{
    // @@@
    return NE_XML_VALID;
}

//////////////////////////////////////////////////////////////////////////
extern "C" int LinkEntrySequence_endelement_callback( void * userdata,
                                                      const struct ne_xml_elm * s,
                                                      const char * cdata )
{
    LockEntrySequenceParseContext * pCtx
                = static_cast< LockEntrySequenceParseContext * >( userdata );
    if ( !pCtx->pEntry )
        pCtx->pEntry = new ucb::LockEntry;

    switch ( s->id )
    {
        case DAV_ELM_exclusive:
            pCtx->pEntry->Scope = ucb::LockScope_EXCLUSIVE;
            break;

        case DAV_ELM_shared:
            pCtx->pEntry->Scope = ucb::LockScope_SHARED;
            break;

        case DAV_ELM_write:
            pCtx->pEntry->Type = ucb::LockType_WRITE;
            break;

        default:
            break;
    }
    return 0;
}

//////////////////////////////////////////////////////////////////////////
// static
bool LockEntrySequence::createFromXML( const rtl::OString & rInData,
                                       uno::Sequence<
                                               ucb::LockEntry > & rOutData )
{
    const sal_Int32 TOKEN_LENGTH = 12; // </lockentry>
    bool success = true;

    // rInData may contain multiple <lockentry>...</lockentry> tags.
    sal_Int32 nCount = 0;
    sal_Int32 nStart = 0;
    sal_Int32 nEnd   = rInData.indexOf( "</lockentry>" );
    while ( nEnd > -1 )
    {
        ne_xml_parser * parser = ne_xml_create();
        if ( !parser )
        {
            success = false;
            break;
        }

        LockEntrySequenceParseContext aCtx;
        ne_xml_push_handler( parser,
                                  elements,
                                  LinkEntrySequence_validate_callback,
                                  0, // startelement_callback
                                  LinkEntrySequence_endelement_callback,
                                  &aCtx );

        ne_xml_parse( parser,
                       rInData.getStr() + nStart,
                       nEnd - nStart + TOKEN_LENGTH );

        success = !!ne_xml_valid( parser );

        ne_xml_destroy( parser );

        if ( !success )
            break;

        if ( aCtx.pEntry )
        {
            nCount++;
            if ( nCount > rOutData.getLength() )
                rOutData.realloc( rOutData.getLength() + 2 );

            rOutData[ nCount - 1 ] = *aCtx.pEntry;
        }

        nStart = nEnd + TOKEN_LENGTH + 1;
        nEnd   = rInData.indexOf( "</lockentry>", nStart );
    }

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

#include <string.h>

#ifndef NE_XML_H
#include <neon/ne_xml.h>
#endif

#ifndef _LOCKENTRYSEQUENCE_HXX_
#include "LockEntrySequence.hxx"
#endif

using namespace webdav_ucp;
using namespace com::sun::star;

//////////////////////////////////////////////////////////////////////////

struct LockEntrySequenceParseContext
{
    ucb::LockEntry * pEntry;
    bool hasScope;
    bool hasType;

    LockEntrySequenceParseContext()
    : pEntry( 0 ), hasScope( false ), hasType( false ) {}
    ~LockEntrySequenceParseContext() { delete pEntry; }
};

#define STATE_TOP (1)

#define STATE_LOCKENTRY (STATE_TOP)
#define STATE_LOCKSCOPE (STATE_TOP + 1)
#define STATE_EXCLUSIVE (STATE_TOP + 2)
#define STATE_SHARED    (STATE_TOP + 3)
#define STATE_LOCKTYPE  (STATE_TOP + 4)
#define STATE_WRITE     (STATE_TOP + 5)

//////////////////////////////////////////////////////////////////////////
extern "C" int LockEntrySequence_startelement_callback(
    void *userdata,
    int parent,
    const char *nspace,
    const char *name,
    const char **atts )
{
    if ( ( name != 0 ) &&
         ( ( nspace == 0 ) || ( strcmp( nspace, "" ) == 0 ) ) )
    {
        switch ( parent )
        {
            case NE_XML_STATEROOT:
                if ( strcmp( name, "lockentry" ) == 0 )
                    return STATE_LOCKENTRY;
                break;

            case STATE_LOCKENTRY:
                if ( strcmp( name, "lockscope" ) == 0 )
                    return STATE_LOCKSCOPE;
                else if ( strcmp( name, "locktype" ) == 0 )
                    return STATE_LOCKTYPE;
                break;

            case STATE_LOCKSCOPE:
                if ( strcmp( name, "exclusive" ) == 0 )
                    return STATE_EXCLUSIVE;
                else if ( strcmp( name, "shared" ) == 0 )
                    return STATE_SHARED;
                break;

            case STATE_LOCKTYPE:
                if ( strcmp( name, "write" ) == 0 )
                    return STATE_WRITE;
                break;
        }
    }
    return NE_XML_DECLINE;
}

//////////////////////////////////////////////////////////////////////////
extern "C" int LockEntrySequence_chardata_callback(
    void *userdata,
    int state,
    const char *buf,
    size_t len )
{
    return 0; // zero to continue, non-zero to abort parsing
}

//////////////////////////////////////////////////////////////////////////
extern "C" int LockEntrySequence_endelement_callback(
    void *userdata,
    int state,
    const char *nspace,
    const char *name )
{
    LockEntrySequenceParseContext * pCtx
                = static_cast< LockEntrySequenceParseContext * >( userdata );
    if ( !pCtx->pEntry )
        pCtx->pEntry = new ucb::LockEntry;

    switch ( state )
    {
        case STATE_EXCLUSIVE:
            pCtx->pEntry->Scope = ucb::LockScope_EXCLUSIVE;
            pCtx->hasScope = true;
            break;

        case STATE_SHARED:
            pCtx->pEntry->Scope = ucb::LockScope_SHARED;
            pCtx->hasScope = true;
            break;

        case STATE_WRITE:
            pCtx->pEntry->Type = ucb::LockType_WRITE;
            pCtx->hasType = true;
            break;

        case STATE_LOCKSCOPE:
            if ( !pCtx->hasScope )
                return 1; // abort
            break;

        case STATE_LOCKTYPE:
            if ( !pCtx->hasType )
                return 1; // abort
            break;

        case STATE_LOCKENTRY:
            if ( !pCtx->hasType || !pCtx->hasType )
                return 1; // abort
            break;

        default:
            break;
    }
    return 0; // zero to continue, non-zero to abort parsing
}

//////////////////////////////////////////////////////////////////////////
// static
bool LockEntrySequence::createFromXML( const rtl::OString & rInData,
                                       uno::Sequence<
                                               ucb::LockEntry > & rOutData )
{
    const sal_Int32 TOKEN_LENGTH = 12; // </lockentry>
    bool success = true;

    // rInData may contain multiple <lockentry>...</lockentry> tags.
    sal_Int32 nCount = 0;
    sal_Int32 nStart = 0;
    sal_Int32 nEnd   = rInData.indexOf( "</lockentry>" );
    while ( nEnd > -1 )
    {
        ne_xml_parser * parser = ne_xml_create();
        if ( !parser )
        {
            success = false;
            break;
        }

        LockEntrySequenceParseContext aCtx;
        ne_xml_push_handler( parser,
                             LockEntrySequence_startelement_callback,
                             LockEntrySequence_chardata_callback,
                             LockEntrySequence_endelement_callback,
                             &aCtx );

        ne_xml_parse( parser,
                       rInData.getStr() + nStart,
                       nEnd - nStart + TOKEN_LENGTH );

        success = !!ne_xml_valid( parser );

        ne_xml_destroy( parser );

        if ( !success )
            break;

        if ( aCtx.pEntry )
        {
            nCount++;
            if ( nCount > rOutData.getLength() )
                rOutData.realloc( rOutData.getLength() + 2 );

            rOutData[ nCount - 1 ] = *aCtx.pEntry;
        }

        nStart = nEnd + TOKEN_LENGTH + 1;
        nEnd   = rInData.indexOf( "</lockentry>", nStart );
    }

    rOutData.realloc( nCount );
    return success;
}
<|endoftext|>


<commit_before>/*===================================================================

The Medical Imaging Interaction Toolkit (MITK)

Copyright (c) German Cancer Research Center,
Division of Medical and Biological Informatics.
All rights reserved.

This software is distributed WITHOUT ANY WARRANTY; without
even the implied warranty of MERCHANTABILITY or FITNESS FOR
A PARTICULAR PURPOSE.

See LICENSE.txt or http://www.mitk.org for details.

===================================================================*/

#include "mitkGeometry3D.h"
#include "mitkTestingMacros.h"

mitk::Geometry3D::Pointer m_Geometry3D;
mitk::Geometry3D::Pointer m_AnotherGeometry3D;

/**
 * @brief Setup Always call this method before each Test-case to ensure correct and new intialization of the two used members for a new test case.
 */
static void Setup()
{
  m_Geometry3D = mitk::Geometry3D::New();
  m_Geometry3D->Initialize();
  m_AnotherGeometry3D = m_Geometry3D->Clone();
}

static void AreEqual_CloneAndOriginal_ReturnsTrue()
{
  Setup();
  MITK_TEST_CONDITION_REQUIRED( mitk::Geometry3D::AreEqual( m_Geometry3D, m_AnotherGeometry3D), "A clone should be equal to its original.");
}

static void AreEqual_DifferentOrigin_ReturnsFalse()
{
  Setup();

  mitk::Point3D origin;
  origin[0] = 0.0;
  origin[1] = 0.0;
  origin[2] = mitk::eps * 1.01;
  m_AnotherGeometry3D->SetOrigin(origin);

  MITK_TEST_CONDITION_REQUIRED( !mitk::Geometry3D::AreEqual( m_Geometry3D, m_AnotherGeometry3D), "Origin was modified. Result should be false.");
}

static void AreEqual_DifferentIndexToWorldTransform_ReturnsFalse()
{
  Setup();

  //Create another index to world transform and make it different somehow
  mitk::AffineTransform3D::Pointer differentIndexToWorldTransform = mitk::AffineTransform3D::New();

  mitk::AffineTransform3D::MatrixType differentMatrix;
  differentMatrix.SetIdentity();
  differentMatrix(1,1) = 2;

  differentIndexToWorldTransform->SetMatrix( differentMatrix );
  m_AnotherGeometry3D->SetIndexToWorldTransform(differentIndexToWorldTransform);

  MITK_TEST_CONDITION_REQUIRED( !mitk::Geometry3D::AreEqual( m_Geometry3D, m_AnotherGeometry3D), "IndexToWorldTransform was modified. Result should be false.");
}

static void AreEqual_DifferentSpacing_ReturnsFalse()
{
  Setup();

  mitk::Vector3D differentSpacing;
  differentSpacing[0] = 1.0;
  differentSpacing[1] = 1.0*mitk::eps;
  differentSpacing[2] = 1.0;

  m_AnotherGeometry3D->SetSpacing(differentSpacing);

  MITK_TEST_CONDITION_REQUIRED( !mitk::Geometry3D::AreEqual( m_Geometry3D, m_AnotherGeometry3D), "Spacing was modified. Result should be false.");
}

static void AreEqual_InputIsNull_ReturnsFalse()
{
  Setup();

  m_Geometry3D = NULL;
  m_AnotherGeometry3D = NULL;

  MITK_TEST_CONDITION_REQUIRED( !mitk::Geometry3D::AreEqual( m_Geometry3D, m_AnotherGeometry3D), "Input is NULL. Result should be false.");
}

static void AreEqual_DifferentImageGeometry_ReturnsFalse()
{
  Setup();

  m_AnotherGeometry3D->SetImageGeometry(true);

  MITK_TEST_CONDITION_REQUIRED( !mitk::Geometry3D::AreEqual( m_Geometry3D, m_AnotherGeometry3D), "One Geometry is image, the other is not. Result should be false.");
}

static void AreEqual_DifferentBoundingBox_ReturnsFalse()
{
    Setup();

    //create different bounds to make the comparison false
    float bounds[ ] = {0.0, 0.0, 0.0*mitk::eps, 0.0, 0.0, 0.0};
    m_AnotherGeometry3D->SetBounds(bounds);

    MITK_TEST_CONDITION_REQUIRED( !mitk::Geometry3D::AreEqual( m_Geometry3D, m_AnotherGeometry3D), "Bounds are different. Result should be false.");
    //The second test-case invokes explicitly the concrete comparison method,
    //because this is currently skipped in mitk::Geometry3D::AreEqual as the
    //comparison of extent and axis fails if the bounds are changed.
    MITK_TEST_CONDITION_REQUIRED( !mitk::Geometry3D::AreBoundingBoxesEqual( m_Geometry3D, m_AnotherGeometry3D), "Bounds are different. Result should be false.");
}

/**
 * @brief mitkGeometry3DAreEqualTest A test class for AreEqual methods in mitk::Geometry3D.
 */
int mitkGeometry3DAreEqualTest(int /*argc*/, char* /*argv*/[])
{
  MITK_TEST_BEGIN(mitkGeometry3DAreEqualTest);

  AreEqual_CloneAndOriginal_ReturnsTrue();
  AreEqual_InputIsNull_ReturnsFalse();
  AreEqual_DifferentSpacing_ReturnsFalse();
  AreEqual_DifferentImageGeometry_ReturnsFalse();
  AreEqual_DifferentOrigin_ReturnsFalse();
  AreEqual_DifferentIndexToWorldTransform_ReturnsFalse();
  AreEqual_DifferentBoundingBox_ReturnsFalse();

  MITK_TEST_END();

  return EXIT_SUCCESS;
}
<commit_msg>Removed old "AreEqualTest". New version is "EqualTest".<commit_after><|endoftext|>


<commit_before>/*=========================================================================

Program:   Medical Imaging & Interaction Toolkit
Module:    $RCSfile$
Language:  C++
Date:      $Date$
Version:   $Revision$

Copyright (c) German Cancer Research Center, Division of Medical and
Biological Informatics. All rights reserved.
See MITKCopyright.txt or http://www.mitk.org/copyright.html for details.

This software is distributed WITHOUT ANY WARRANTY; without even
the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
PURPOSE.  See the above copyright notices for more information.

=========================================================================*/

#include "mitkGeometry2DDataVtkMapper3D.h"
#include "mitkPlaneGeometry.h"
#include "mitkDataTree.h"
#include "mitkImageMapper2D.h"
#include "mitkSurface.h"
#include "mitkGeometry2DDataToSurfaceFilter.h"
#include "mitkColorProperty.h"
#include "mitkProperties.h"
#include "mitkLookupTableProperty.h"
#include "mitkLevelWindowProperty.h"
#include "mitkSmartPointerProperty.h"
#include "mitkWeakPointerProperty.h"

#include <vtkActor.h>
#include <vtkProperty.h>
#include <vtkTexture.h>
#include <vtkPlaneSource.h>
#include <vtkPolyDataMapper.h>
#include <vtkLookupTable.h>
#include <vtkActor.h>
#include <vtkImageData.h>
#include <vtkLinearTransform.h>
#include <vtkAssembly.h>
#include <vtkFeatureEdges.h>
#include <vtkTubeFilter.h>

#include "pic2vtk.h"

//##ModelId=3E691E09038E
mitk::Geometry2DDataVtkMapper3D::Geometry2DDataVtkMapper3D() : m_DataTreeIterator(NULL), m_LastTextureUpdateTime(0)
{
  m_VtkPolyDataMapper = vtkPolyDataMapper::New();
  m_VtkPolyDataMapper->ImmediateModeRenderingOn();

  m_ImageActor = vtkActor::New();
  m_ImageActor->SetMapper(m_VtkPolyDataMapper);
  m_ImageActor->GetProperty()->SetAmbient(0.5);

  m_VtkLookupTable = vtkLookupTable::New();
  m_VtkLookupTable->SetTableRange (-1024, 4096);
  m_VtkLookupTable->SetSaturationRange (0, 0);
  m_VtkLookupTable->SetHueRange (0, 0);
  m_VtkLookupTable->SetValueRange (0, 1);
  m_VtkLookupTable->Build ();

  m_VtkLookupTableDefault = m_VtkLookupTable;

  m_VtkTexture = vtkTexture::New();
  m_VtkTexture->InterpolateOn();
  m_VtkTexture->SetLookupTable(m_VtkLookupTable);
  m_VtkTexture->MapColorScalarsThroughLookupTableOn();

  m_EdgeTuber = vtkTubeFilter::New();
  m_EdgeMapper = vtkPolyDataMapper::New();
  m_Edges = vtkFeatureEdges::New();
  m_EdgeActor = vtkActor::New();

  m_EdgeTuber->SetInput( m_Edges->GetOutput() );
  m_EdgeTuber->SetNumberOfSides( 12 );
  m_EdgeTuber->CappingOn();

  m_EdgeMapper->SetInput( m_EdgeTuber->GetOutput() );
  m_EdgeMapper->ScalarVisibilityOff();

  m_EdgeActor->SetMapper( m_EdgeMapper );

  m_Prop3DAssembly = vtkAssembly::New();
  m_Prop3DAssembly->AddPart( m_ImageActor );
  m_Prop3DAssembly->AddPart( m_EdgeActor );

  m_Prop3D = m_Prop3DAssembly;
  m_Prop3D->Register(NULL);
}

//##ModelId=3E691E090394
mitk::Geometry2DDataVtkMapper3D::~Geometry2DDataVtkMapper3D()
{
  m_VtkPolyDataMapper->Delete();
  m_Prop3DAssembly->Delete();
  m_ImageActor->Delete();
  m_VtkLookupTable->Delete();
  m_VtkTexture->Delete();
  m_EdgeTuber->Delete();
  m_EdgeMapper->Delete();
  m_Edges->Delete();
  m_EdgeActor->Delete();
}

//##ModelId=3E691E090380
const mitk::Geometry2DData *mitk::Geometry2DDataVtkMapper3D::GetInput()
{
  return static_cast<const mitk::Geometry2DData * > ( GetData() );
}

//##ModelId=3E6E874F0007
void mitk::Geometry2DDataVtkMapper3D::SetDataIteratorForTexture(const mitk::DataTreeIteratorBase* iterator)
{
  if(m_DataTreeIterator != iterator)
  {
    m_DataTreeIterator = iterator;
    Modified();
  }
}

//##ModelId=3EF19F850151
void mitk::Geometry2DDataVtkMapper3D::GenerateData(mitk::BaseRenderer* renderer)
{
  if ( !this->IsVisible(renderer) )
  {
    m_Prop3DAssembly->VisibilityOff();
    return;
  }

  m_Prop3DAssembly->VisibilityOn();

  mitk::Geometry2DData::Pointer input  = const_cast<mitk::Geometry2DData*>(this->GetInput());

  if(input.IsNotNull() && (input->GetGeometry2D() != NULL))
  {
    mitk::Geometry2DDataToSurfaceFilter::Pointer surfaceCreator;
    mitk::SmartPointerProperty::Pointer surfacecreatorprop;
    surfacecreatorprop=dynamic_cast<mitk::SmartPointerProperty*>(GetDataTreeNode()->GetProperty("surfacegeometry", renderer).GetPointer());
    if( (surfacecreatorprop.IsNull()) ||
      (surfacecreatorprop->GetSmartPointer().IsNull()) ||
      ((surfaceCreator=dynamic_cast<mitk::Geometry2DDataToSurfaceFilter*>(surfacecreatorprop->GetSmartPointer().GetPointer())).IsNull())
      )
    {
      surfaceCreator = mitk::Geometry2DDataToSurfaceFilter::New();
      surfaceCreator->PlaceByGeometryOn();
      surfacecreatorprop=new mitk::SmartPointerProperty(surfaceCreator);
      GetDataTreeNode()->SetProperty("surfacegeometry", surfacecreatorprop);
    }

    surfaceCreator->SetInput(input);

    int res;
    if(GetDataTreeNode()->GetIntProperty("xresolution", res, renderer))
      surfaceCreator->SetXResolution(res);
    if(GetDataTreeNode()->GetIntProperty("yresolution", res, renderer))
      surfaceCreator->SetYResolution(res);

    surfaceCreator->Update(); //@FIXME ohne das crash
    m_VtkPolyDataMapper->SetInput(surfaceCreator->GetOutput()->GetVtkPolyData());

    bool texture=false;
    if(m_DataTreeIterator.IsNotNull())
    {
      mitk::DataTreeIteratorClone it=m_DataTreeIterator.GetPointer();
      while(!it->IsAtEnd())
      {
        mitk::DataTreeNode* node=it->Get();
        mitk::Mapper::Pointer mapper = node->GetMapper(1);
        mitk::ImageMapper2D* imagemapper = dynamic_cast<ImageMapper2D*>(mapper.GetPointer());

        if((node->IsVisible(renderer)) && (imagemapper))
        {
          mitk::WeakPointerProperty::Pointer rendererProp
                                               = dynamic_cast<mitk::WeakPointerProperty*>(GetDataTreeNode()->GetPropertyList()->GetProperty("renderer").GetPointer());
          if(rendererProp.IsNotNull())
          {
            mitk::BaseRenderer::Pointer renderer = dynamic_cast<mitk::BaseRenderer*>(rendererProp->GetWeakPointer().GetPointer());
            if(renderer.IsNotNull())
            {

              // check for LookupTable
              mitk::LookupTableProperty::Pointer LookupTableProb;
              LookupTableProb = dynamic_cast<mitk::LookupTableProperty*>(node->GetPropertyList()->GetProperty("LookupTable").GetPointer());
              if (LookupTableProb.IsNotNull() )
              {
                m_VtkLookupTable = LookupTableProb->GetLookupTable().GetVtkLookupTable();
                m_VtkTexture->SetLookupTable(m_VtkLookupTable);
                // m_VtkTexture->Modified();
              } else {
                m_VtkLookupTable = m_VtkLookupTableDefault;
              }

              // check for level window prop and use it for display if it exists
              mitk::LevelWindow levelWindow;
              if(node->GetLevelWindow(levelWindow, renderer))
                m_VtkLookupTable->SetTableRange(levelWindow.GetMin(),levelWindow.GetMax());

              //we have to do this before GenerateAllData() is called there may be
              //no RendererInfo for renderer yet, thus GenerateAllData won't update
              //the (non-existing) RendererInfo for renderer. By calling GetRendererInfo
              //a RendererInfo will be created for renderer (if it does not exist yet).
              const ImageMapper2D::RendererInfo* ri=imagemapper->GetRendererInfo(renderer);
              imagemapper->GenerateAllData();
              texture = true;
              if((ri!=NULL) && (ri->m_Pic!=NULL) &&(m_LastTextureUpdateTime<ri->m_LastUpdateTime))
              {
                ipPicDescriptor *p=ri->m_Pic;
                if((p->dim==2) && (p->n[0]>2) && (p->n[1]>2))
                {
                  vtkImageData* vtkimage=Pic2vtk::convert(p);
                  m_VtkTexture->SetInput(vtkimage);
                  vtkimage->Delete(); vtkimage=NULL;
                  m_ImageActor->SetTexture(m_VtkTexture);
                  m_LastTextureUpdateTime=ri->m_LastUpdateTime;
                  bool textureInterpolation=true;
                  m_VtkTexture->SetInterpolate(textureInterpolation ? 1 : 0);
                }
                else
                  texture = false;
              }
              break;
            }
          }
        }
        ++it;
      }
    }
    if(texture==false)
    {
      m_ImageActor->SetTexture(NULL);
    }

    // Configurate the tube-shaped frame: size according to the surface
    // bounds, color as specified in the plane's properties
    vtkPolyData* surfacePolyData = surfaceCreator->GetOutput()->GetVtkPolyData();
    m_Edges->SetInput( surfacePolyData );

    // Determine maximum extent
    vtkFloatingPointType* surfaceBounds = surfacePolyData->GetBounds();
    vtkFloatingPointType extent = surfaceBounds[1] - surfaceBounds[0];
    vtkFloatingPointType extentY = surfaceBounds[3] - surfaceBounds[2];
    vtkFloatingPointType extentZ = surfaceBounds[5] - surfaceBounds[4];

    if ( extent < extentY ) extent = extentY;
    if ( extent < extentZ ) extent = extentZ;

    // Adjust the radius according to extent
    m_EdgeTuber->SetRadius( extent / 250.0 );

    // Get the plane's color and set the tube properties accordingly
    mitk::ColorProperty::Pointer colorProperty;
    colorProperty = dynamic_cast<mitk::ColorProperty*>(
      this->GetDataTreeNode()->GetProperty("color").GetPointer( )
    );

    const mitk::Color& color = colorProperty->GetColor();
    m_EdgeActor->GetProperty()->SetColor(
      color.GetRed(), color.GetGreen(), color.GetBlue()
    );

    // Apply properties read from the PropertyList
    this->ApplyProperties(m_ImageActor, renderer);

    m_Prop3D->SetUserTransform(GetDataTreeNode()->GetVtkTransform());
  }
}
<commit_msg>FIX: Missing #include<commit_after>/*=========================================================================

Program:   Medical Imaging & Interaction Toolkit
Module:    $RCSfile$
Language:  C++
Date:      $Date$
Version:   $Revision$

Copyright (c) German Cancer Research Center, Division of Medical and
Biological Informatics. All rights reserved.
See MITKCopyright.txt or http://www.mitk.org/copyright.html for details.

This software is distributed WITHOUT ANY WARRANTY; without even
the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
PURPOSE.  See the above copyright notices for more information.

=========================================================================*/

#include "mitkGeometry2DDataVtkMapper3D.h"
#include "mitkPlaneGeometry.h"
#include "mitkDataTree.h"
#include "mitkImageMapper2D.h"
#include "mitkSurface.h"
#include "mitkGeometry2DDataToSurfaceFilter.h"
#include "mitkColorProperty.h"
#include "mitkProperties.h"
#include "mitkLookupTableProperty.h"
#include "mitkLevelWindowProperty.h"
#include "mitkSmartPointerProperty.h"
#include "mitkWeakPointerProperty.h"

#include <vtkActor.h>
#include <vtkProperty.h>
#include <vtkTexture.h>
#include <vtkPlaneSource.h>
#include <vtkPolyDataMapper.h>
#include <vtkPolyData.h>
#include <vtkLookupTable.h>
#include <vtkActor.h>
#include <vtkImageData.h>
#include <vtkLinearTransform.h>
#include <vtkAssembly.h>
#include <vtkFeatureEdges.h>
#include <vtkTubeFilter.h>

#include "pic2vtk.h"

//##ModelId=3E691E09038E
mitk::Geometry2DDataVtkMapper3D::Geometry2DDataVtkMapper3D() : m_DataTreeIterator(NULL), m_LastTextureUpdateTime(0)
{
  m_VtkPolyDataMapper = vtkPolyDataMapper::New();
  m_VtkPolyDataMapper->ImmediateModeRenderingOn();

  m_ImageActor = vtkActor::New();
  m_ImageActor->SetMapper(m_VtkPolyDataMapper);
  m_ImageActor->GetProperty()->SetAmbient(0.5);

  m_VtkLookupTable = vtkLookupTable::New();
  m_VtkLookupTable->SetTableRange (-1024, 4096);
  m_VtkLookupTable->SetSaturationRange (0, 0);
  m_VtkLookupTable->SetHueRange (0, 0);
  m_VtkLookupTable->SetValueRange (0, 1);
  m_VtkLookupTable->Build ();

  m_VtkLookupTableDefault = m_VtkLookupTable;

  m_VtkTexture = vtkTexture::New();
  m_VtkTexture->InterpolateOn();
  m_VtkTexture->SetLookupTable(m_VtkLookupTable);
  m_VtkTexture->MapColorScalarsThroughLookupTableOn();

  m_EdgeTuber = vtkTubeFilter::New();
  m_EdgeMapper = vtkPolyDataMapper::New();
  m_Edges = vtkFeatureEdges::New();
  m_EdgeActor = vtkActor::New();

  m_EdgeTuber->SetInput( m_Edges->GetOutput() );
  m_EdgeTuber->SetNumberOfSides( 12 );
  m_EdgeTuber->CappingOn();

  m_EdgeMapper->SetInput( m_EdgeTuber->GetOutput() );
  m_EdgeMapper->ScalarVisibilityOff();

  m_EdgeActor->SetMapper( m_EdgeMapper );

  m_Prop3DAssembly = vtkAssembly::New();
  m_Prop3DAssembly->AddPart( m_ImageActor );
  m_Prop3DAssembly->AddPart( m_EdgeActor );

  m_Prop3D = m_Prop3DAssembly;
  m_Prop3D->Register(NULL);
}

//##ModelId=3E691E090394
mitk::Geometry2DDataVtkMapper3D::~Geometry2DDataVtkMapper3D()
{
  m_VtkPolyDataMapper->Delete();
  m_Prop3DAssembly->Delete();
  m_ImageActor->Delete();
  m_VtkLookupTable->Delete();
  m_VtkTexture->Delete();
  m_EdgeTuber->Delete();
  m_EdgeMapper->Delete();
  m_Edges->Delete();
  m_EdgeActor->Delete();
}

//##ModelId=3E691E090380
const mitk::Geometry2DData *mitk::Geometry2DDataVtkMapper3D::GetInput()
{
  return static_cast<const mitk::Geometry2DData * > ( GetData() );
}

//##ModelId=3E6E874F0007
void mitk::Geometry2DDataVtkMapper3D::SetDataIteratorForTexture(const mitk::DataTreeIteratorBase* iterator)
{
  if(m_DataTreeIterator != iterator)
  {
    m_DataTreeIterator = iterator;
    Modified();
  }
}

//##ModelId=3EF19F850151
void mitk::Geometry2DDataVtkMapper3D::GenerateData(mitk::BaseRenderer* renderer)
{
  if ( !this->IsVisible(renderer) )
  {
    m_Prop3DAssembly->VisibilityOff();
    return;
  }

  m_Prop3DAssembly->VisibilityOn();

  mitk::Geometry2DData::Pointer input  = const_cast<mitk::Geometry2DData*>(this->GetInput());

  if(input.IsNotNull() && (input->GetGeometry2D() != NULL))
  {
    mitk::Geometry2DDataToSurfaceFilter::Pointer surfaceCreator;
    mitk::SmartPointerProperty::Pointer surfacecreatorprop;
    surfacecreatorprop=dynamic_cast<mitk::SmartPointerProperty*>(GetDataTreeNode()->GetProperty("surfacegeometry", renderer).GetPointer());
    if( (surfacecreatorprop.IsNull()) ||
      (surfacecreatorprop->GetSmartPointer().IsNull()) ||
      ((surfaceCreator=dynamic_cast<mitk::Geometry2DDataToSurfaceFilter*>(surfacecreatorprop->GetSmartPointer().GetPointer())).IsNull())
      )
    {
      surfaceCreator = mitk::Geometry2DDataToSurfaceFilter::New();
      surfaceCreator->PlaceByGeometryOn();
      surfacecreatorprop=new mitk::SmartPointerProperty(surfaceCreator);
      GetDataTreeNode()->SetProperty("surfacegeometry", surfacecreatorprop);
    }

    surfaceCreator->SetInput(input);

    int res;
    if(GetDataTreeNode()->GetIntProperty("xresolution", res, renderer))
      surfaceCreator->SetXResolution(res);
    if(GetDataTreeNode()->GetIntProperty("yresolution", res, renderer))
      surfaceCreator->SetYResolution(res);

    surfaceCreator->Update(); //@FIXME ohne das crash
    m_VtkPolyDataMapper->SetInput(surfaceCreator->GetOutput()->GetVtkPolyData());

    bool texture=false;
    if(m_DataTreeIterator.IsNotNull())
    {
      mitk::DataTreeIteratorClone it=m_DataTreeIterator.GetPointer();
      while(!it->IsAtEnd())
      {
        mitk::DataTreeNode* node=it->Get();
        mitk::Mapper::Pointer mapper = node->GetMapper(1);
        mitk::ImageMapper2D* imagemapper = dynamic_cast<ImageMapper2D*>(mapper.GetPointer());

        if((node->IsVisible(renderer)) && (imagemapper))
        {
          mitk::WeakPointerProperty::Pointer rendererProp
                                               = dynamic_cast<mitk::WeakPointerProperty*>(GetDataTreeNode()->GetPropertyList()->GetProperty("renderer").GetPointer());
          if(rendererProp.IsNotNull())
          {
            mitk::BaseRenderer::Pointer renderer = dynamic_cast<mitk::BaseRenderer*>(rendererProp->GetWeakPointer().GetPointer());
            if(renderer.IsNotNull())
            {

              // check for LookupTable
              mitk::LookupTableProperty::Pointer LookupTableProb;
              LookupTableProb = dynamic_cast<mitk::LookupTableProperty*>(node->GetPropertyList()->GetProperty("LookupTable").GetPointer());
              if (LookupTableProb.IsNotNull() )
              {
                m_VtkLookupTable = LookupTableProb->GetLookupTable().GetVtkLookupTable();
                m_VtkTexture->SetLookupTable(m_VtkLookupTable);
                // m_VtkTexture->Modified();
              } else {
                m_VtkLookupTable = m_VtkLookupTableDefault;
              }

              // check for level window prop and use it for display if it exists
              mitk::LevelWindow levelWindow;
              if(node->GetLevelWindow(levelWindow, renderer))
                m_VtkLookupTable->SetTableRange(levelWindow.GetMin(),levelWindow.GetMax());

              //we have to do this before GenerateAllData() is called there may be
              //no RendererInfo for renderer yet, thus GenerateAllData won't update
              //the (non-existing) RendererInfo for renderer. By calling GetRendererInfo
              //a RendererInfo will be created for renderer (if it does not exist yet).
              const ImageMapper2D::RendererInfo* ri=imagemapper->GetRendererInfo(renderer);
              imagemapper->GenerateAllData();
              texture = true;
              if((ri!=NULL) && (ri->m_Pic!=NULL) &&(m_LastTextureUpdateTime<ri->m_LastUpdateTime))
              {
                ipPicDescriptor *p=ri->m_Pic;
                if((p->dim==2) && (p->n[0]>2) && (p->n[1]>2))
                {
                  vtkImageData* vtkimage=Pic2vtk::convert(p);
                  m_VtkTexture->SetInput(vtkimage);
                  vtkimage->Delete(); vtkimage=NULL;
                  m_ImageActor->SetTexture(m_VtkTexture);
                  m_LastTextureUpdateTime=ri->m_LastUpdateTime;
                  bool textureInterpolation=true;
                  m_VtkTexture->SetInterpolate(textureInterpolation ? 1 : 0);
                }
                else
                  texture = false;
              }
              break;
            }
          }
        }
        ++it;
      }
    }
    if(texture==false)
    {
      m_ImageActor->SetTexture(NULL);
    }

    // Configurate the tube-shaped frame: size according to the surface
    // bounds, color as specified in the plane's properties
    vtkPolyData* surfacePolyData = surfaceCreator->GetOutput()->GetVtkPolyData();
    m_Edges->SetInput( surfacePolyData );

    // Determine maximum extent
    vtkFloatingPointType* surfaceBounds = surfacePolyData->GetBounds();
    vtkFloatingPointType extent = surfaceBounds[1] - surfaceBounds[0];
    vtkFloatingPointType extentY = surfaceBounds[3] - surfaceBounds[2];
    vtkFloatingPointType extentZ = surfaceBounds[5] - surfaceBounds[4];

    if ( extent < extentY ) extent = extentY;
    if ( extent < extentZ ) extent = extentZ;

    // Adjust the radius according to extent
    m_EdgeTuber->SetRadius( extent / 250.0 );

    // Get the plane's color and set the tube properties accordingly
    mitk::ColorProperty::Pointer colorProperty;
    colorProperty = dynamic_cast<mitk::ColorProperty*>(
      this->GetDataTreeNode()->GetProperty("color").GetPointer( )
    );

    const mitk::Color& color = colorProperty->GetColor();
    m_EdgeActor->GetProperty()->SetColor(
      color.GetRed(), color.GetGreen(), color.GetBlue()
    );

    // Apply properties read from the PropertyList
    this->ApplyProperties(m_ImageActor, renderer);

    m_Prop3D->SetUserTransform(GetDataTreeNode()->GetVtkTransform());
  }
}
<|endoftext|>