<commit_before>
#include <iterator>

#include "Representations/Infrastructure/JointData.h"
#include "Tools/Math/Common.h"
#include "PlatformInterface/Platform.h"
#include "Tools/Debug/NaoTHAssert.h"
#include "Messages/Framework-Representations.pb.h"
#include <google/protobuf/io/zero_copy_stream_impl.h>

using namespace naoth;
using namespace std;

double JointData::min[JointData::numOfJoint];
double JointData::max[JointData::numOfJoint];

JointData::JointData()
{
  for (int i = 0; i < numOfJoint; i++)
  {
    position[i] = 0;
    dp[i] = 0;
    ddp[i] = 0;
    stiffness[i] = 0.0;
  }
}

void JointData::loadJointLimitsFromConfig()
{
  const Configuration& cfg = Platform::getInstance().theConfiguration;
  for (int i = 0; i < JointData::numOfJoint; i++)
  {
    string jointName = JointData::getJointName((JointData::JointID)i);
    if (cfg.hasKey("joints", jointName + "Max"))
    {
      double maxDeg = cfg.getDouble("joints", jointName + "Max");
      max[i] = Math::fromDegrees(maxDeg);
    } else
    {
      THROW("JointData: can not get " + jointName + " max angle");
    }

    if (cfg.hasKey("joints", jointName + "Min"))
    {
      double minDeg = cfg.getDouble("joints", jointName + "Min");
      min[i] = Math::fromDegrees(minDeg);
    } else
    {
      THROW("JointData: can not get " + jointName + " min angle");
    }
  }//enf for
}//end init

string JointData::getJointName(JointID joint)
{
  switch (joint)
  {
    case HeadPitch: return string("HeadPitch");
    case HeadYaw: return string("HeadYaw");
    case RShoulderRoll: return string("RShoulderRoll");
    case LShoulderRoll: return string("LShoulderRoll");
    case RShoulderPitch: return string("RShoulderPitch");
    case LShoulderPitch: return string("LShoulderPitch");
    case RElbowRoll: return string("RElbowRoll");
    case LElbowRoll: return string("LElbowRoll");
    case RElbowYaw: return string("RElbowYaw");
    case LElbowYaw: return string("LElbowYaw");
    case LHipYawPitch: return string("LHipYawPitch");
    case RHipYawPitch: return string("RHipYawPitch");
    case RHipPitch: return string("RHipPitch");
    case LHipPitch: return string("LHipPitch");
    case RHipRoll: return string("RHipRoll");
    case LHipRoll: return string("LHipRoll");
    case RKneePitch: return string("RKneePitch");
    case LKneePitch: return string("LKneePitch");
    case RAnklePitch: return string("RAnklePitch");
    case LAnklePitch: return string("LAnklePitch");
    case RAnkleRoll: return string("RAnkleRoll");
    case LAnkleRoll: return string("LAnkleRoll");
    default: return string("Unknown Joint");
  }//end switch
}//end getJointName

double JointData::mirrorData(JointID joint) const
{
  switch (joint)
  {
      // Head (don't mirror)
    case HeadYaw: return -position[HeadYaw];
    case HeadPitch: return position[HeadPitch];

      // Arms
    case RShoulderPitch: return position[LShoulderPitch];
    case RShoulderRoll: return -position[LShoulderRoll];
    case RElbowYaw: return -position[LElbowYaw];
    case RElbowRoll: return -position[LElbowRoll];

    case LShoulderPitch: return position[RShoulderPitch];
    case LShoulderRoll: return -position[RShoulderRoll];
    case LElbowYaw: return -position[RElbowYaw];
    case LElbowRoll: return -position[RElbowRoll];

      // Legs
    case RHipYawPitch: return position[LHipYawPitch];
    case RHipPitch: return position[LHipPitch];
    case RHipRoll: return -position[LHipRoll];
    case RKneePitch: return position[LKneePitch];
    case RAnklePitch: return position[LAnklePitch];
    case RAnkleRoll: return -position[LAnkleRoll];

    case LHipYawPitch: return position[RHipYawPitch];
    case LHipPitch: return position[RHipPitch];
    case LHipRoll: return -position[RHipRoll];
    case LKneePitch: return position[RKneePitch];
    case LAnklePitch: return position[RAnklePitch];
    case LAnkleRoll: return -position[RAnkleRoll];
    default: return position[joint];
  }
}//end mirrorData

JointData::JointID JointData::jointIDFromName(std::string name)
{
  for (int i = 0; i < numOfJoint; i++) {
    if (name == getJointName((JointID) i)) return (JointID) i;
  }//end for

  return numOfJoint;
}//end getJointName

void JointData::mirrorFrom(const JointData& jointData)
{
  for (int i = 0; i < numOfJoint; i++)
    position[i] = jointData.mirrorData((JointID) i);
}//end mirror

void JointData::mirror()
{
  JointData tmp = *this;
  mirrorFrom(tmp);
}

void JointData::clamp(JointID id)
{
  position[id] = Math::clamp(position[id], min[id], max[id]);
}

void JointData::clamp()
{
  for( int i=0; i<numOfJoint; i++)
  {
    clamp((JointID)i);
  }
}

bool JointData::isInRange(JointData::JointID id, double ang) const
{
    return ang <= max[id] && ang >= min[id];
}

bool JointData::isInRange(JointData::JointID id) const
{
    return isInRange(id, position[id]);
}

void JointData::updateSpeed(const JointData& lastData, double dt)
{
  const double* lastPose = lastData.position;
  double idt = 1 / dt;
  for ( int i=0; i<JointData::numOfJoint; i++)
  {
    dp[i] = (position[i] - lastPose[i]) * idt;
  }
}

void JointData::updateAcceleration(const JointData& lastData, double dt)
{
  const double* lastSpeed = lastData.dp;
  double idt = 1 / dt;
  for (int i = 0; i < JointData::numOfJoint; i++)
  {
    ddp[i] = (dp[i] - lastSpeed[i]) * idt;
  }
}

bool JointData::isLegStiffnessOn() const
{
  for ( int i=JointData::RHipYawPitch; i<JointData::numOfJoint; i++)
  {
    if ( stiffness[i] < 0 ) return false;
  }
  return true;
}

int JointData::checkStiffness() const
{
  for(int i=0; i<JointData::numOfJoint; i++)
  {
    double v = stiffness[i];
    if ( v > 1 || v < -1 )
    {
      return i;
      //THROW("Get ILLEGAL Stiffness: "<<getJointName(JointData::JointID(i))<<" = "<<v);
    }
  }
  return -1;
}

SensorJointData::SensorJointData()
  : timestamp(0)
{
  for (int i = 0; i < numOfJoint; i++)
  {
    electricCurrent[i] = 0.0;
    temperature[i] = 0.0;
  }//end for
}

void SensorJointData::print(ostream& stream) const
{
  stream << "Timestamp: " << timestamp << endl;
  stream << "Joint [pos(deg), stiffness, temperature,current]" << endl;
  stream << "------------------------" << endl;
  for (int i = 0; i < numOfJoint; i++)
  {
    stream.precision(4);
    stream << getJointName((JointData::JointID) i) << "\t[" << fixed << Math::toDegrees(position[i]) << ", " << stiffness[i] << ", ";
    stream.precision(0);
    stream << temperature[i] << ", ";
    stream.precision(3);
    stream << electricCurrent[i] << "]" <<  endl;
  }//end for
}//end print

SensorJointData::~SensorJointData()
{
}

MotorJointData::MotorJointData()
{
}

MotorJointData::~MotorJointData()
{
}

void MotorJointData::print(ostream& stream) const
{
  stream << "Joint [pos, stiffness]" << endl;
  stream << "------------------------" << endl;
  for (int i = 0; i < numOfJoint; i++) {
    stream << getJointName((JointData::JointID) i) << "[" << position[i] << ", " << stiffness[i] << "]" << endl;
  }//end for
}//end print

void Serializer<SensorJointData>::serialize(const SensorJointData& representation, std::ostream& stream)
{
  naothmessages::SensorJointData message;

  for(int i=0; i < JointData::numOfJoint; i++)
  {
    message.add_electriccurrent(representation.electricCurrent[i]);
    message.add_temperature(representation.temperature[i]);

    message.mutable_jointdata()->add_position(representation.position[i]);
    message.mutable_jointdata()->add_stiffness(representation.stiffness[i]);
    message.mutable_jointdata()->add_dp(representation.dp[i]);
    message.mutable_jointdata()->add_ddp(representation.ddp[i]);
  }

  google::protobuf::io::OstreamOutputStream buf(&stream);
  message.SerializeToZeroCopyStream(&buf);
}

void Serializer<SensorJointData>::deserialize(std::istream& stream, SensorJointData& representation)
{
  naothmessages::SensorJointData message;
  google::protobuf::io::IstreamInputStream buf(&stream);
  message.ParseFromZeroCopyStream(&buf);

  // assure the integrity of the message
  ASSERT(message.electriccurrent().size() == JointData::numOfJoint);
  ASSERT(message.temperature().size() == JointData::numOfJoint);

  ASSERT(message.jointdata().position().size() == JointData::numOfJoint);
  ASSERT(message.jointdata().stiffness().size() == JointData::numOfJoint);
  ASSERT(message.jointdata().dp().size() == JointData::numOfJoint);
  ASSERT(message.jointdata().ddp().size() == JointData::numOfJoint);

  for (int i = 0; i < JointData::numOfJoint; i++)
  {
    representation.electricCurrent[i] = message.electriccurrent(i);
    representation.temperature[i] = message.temperature(i);
    // joint data
    representation.position[i] = message.jointdata().position(i);
    representation.stiffness[i] = message.jointdata().stiffness(i);
    representation.dp[i] = message.jointdata().dp(i);
    representation.ddp[i] = message.jointdata().ddp(i);
  }
}

void Serializer<MotorJointData>::serialize(const MotorJointData& representation, std::ostream& stream)
{
  naothmessages::JointData message;

  for(int i=0; i < JointData::numOfJoint; i++)
  {
    message.add_position(representation.position[i]);
    message.add_stiffness(representation.stiffness[i]);
    message.add_dp(representation.dp[i]);
    message.add_ddp(representation.ddp[i]);
  }

  google::protobuf::io::OstreamOutputStream buf(&stream);
  message.SerializeToZeroCopyStream(&buf);
}

void Serializer<MotorJointData>::deserialize(std::istream& stream, MotorJointData& representation)
{
  naothmessages::JointData message;
  google::protobuf::io::IstreamInputStream buf(&stream);
  message.ParseFromZeroCopyStream(&buf);

  // assure the integrity of the message
  ASSERT(message.position().size() == JointData::numOfJoint);
  ASSERT(message.stiffness().size() == JointData::numOfJoint);
  ASSERT(message.dp().size() == JointData::numOfJoint);
  ASSERT(message.ddp().size() == JointData::numOfJoint);

  for(int i=0; i < JointData::numOfJoint; i++)
  {
    representation.position[i] = message.position(i);
    representation.stiffness[i] = message.stiffness(i);
    representation.dp[i] = message.dp(i);
    representation.ddp[i] = message.ddp(i);
  }
}

<commit_msg>little cleanup<commit_after>
#include <iterator>

#include "Representations/Infrastructure/JointData.h"
#include "Tools/Math/Common.h"
#include "PlatformInterface/Platform.h"
#include "Tools/Debug/NaoTHAssert.h"
#include "Messages/Framework-Representations.pb.h"
#include <google/protobuf/io/zero_copy_stream_impl.h>

using namespace naoth;
using namespace std;

double JointData::min[JointData::numOfJoint];
double JointData::max[JointData::numOfJoint];

JointData::JointData()
{
  // init the arrays
  for (int i = 0; i < numOfJoint; i++)
  {
    position[i] = 0.0;
    dp[i] = 0.0;
    ddp[i] = 0.0;
    stiffness[i] = 0.0;
  }
}

void JointData::loadJointLimitsFromConfig()
{
  const Configuration& cfg = Platform::getInstance().theConfiguration;
  for (int i = 0; i < JointData::numOfJoint; i++)
  {
    string jointName = JointData::getJointName((JointData::JointID)i);

    if (cfg.hasKey("joints", jointName + "Max")) {
      max[i] = Math::fromDegrees(cfg.getDouble("joints", jointName + "Max"));
    } else {
      THROW("JointData: can not get " + jointName + " max angle");
    }

    if (cfg.hasKey("joints", jointName + "Min")) {
      min[i] = Math::fromDegrees(cfg.getDouble("joints", jointName + "Min"));
    } else {
      THROW("JointData: can not get " + jointName + " min angle");
    }
  }//enf for
}//end init

string JointData::getJointName(JointID joint)
{
  switch (joint)
  {
    case HeadPitch: return string("HeadPitch");
    case HeadYaw: return string("HeadYaw");
    case RShoulderRoll: return string("RShoulderRoll");
    case LShoulderRoll: return string("LShoulderRoll");
    case RShoulderPitch: return string("RShoulderPitch");
    case LShoulderPitch: return string("LShoulderPitch");
    case RElbowRoll: return string("RElbowRoll");
    case LElbowRoll: return string("LElbowRoll");
    case RElbowYaw: return string("RElbowYaw");
    case LElbowYaw: return string("LElbowYaw");
    case LHipYawPitch: return string("LHipYawPitch");
    case RHipYawPitch: return string("RHipYawPitch");
    case RHipPitch: return string("RHipPitch");
    case LHipPitch: return string("LHipPitch");
    case RHipRoll: return string("RHipRoll");
    case LHipRoll: return string("LHipRoll");
    case RKneePitch: return string("RKneePitch");
    case LKneePitch: return string("LKneePitch");
    case RAnklePitch: return string("RAnklePitch");
    case LAnklePitch: return string("LAnklePitch");
    case RAnkleRoll: return string("RAnkleRoll");
    case LAnkleRoll: return string("LAnkleRoll");
    default: return string("Unknown Joint");
  }//end switch
}//end getJointName

double JointData::mirrorData(JointID joint) const
{
  switch (joint)
  {
      // Head (don't mirror)
    case HeadYaw: return -position[HeadYaw];
    case HeadPitch: return position[HeadPitch];

      // Arms
    case RShoulderPitch: return position[LShoulderPitch];
    case RShoulderRoll: return -position[LShoulderRoll];
    case RElbowYaw: return -position[LElbowYaw];
    case RElbowRoll: return -position[LElbowRoll];

    case LShoulderPitch: return position[RShoulderPitch];
    case LShoulderRoll: return -position[RShoulderRoll];
    case LElbowYaw: return -position[RElbowYaw];
    case LElbowRoll: return -position[RElbowRoll];

      // Legs
    case RHipYawPitch: return position[LHipYawPitch];
    case RHipPitch: return position[LHipPitch];
    case RHipRoll: return -position[LHipRoll];
    case RKneePitch: return position[LKneePitch];
    case RAnklePitch: return position[LAnklePitch];
    case RAnkleRoll: return -position[LAnkleRoll];

    case LHipYawPitch: return position[RHipYawPitch];
    case LHipPitch: return position[RHipPitch];
    case LHipRoll: return -position[RHipRoll];
    case LKneePitch: return position[RKneePitch];
    case LAnklePitch: return position[RAnklePitch];
    case LAnkleRoll: return -position[RAnkleRoll];
    default: return position[joint];
  }
}//end mirrorData

JointData::JointID JointData::jointIDFromName(std::string name)
{
  for (int i = 0; i < numOfJoint; i++) {
    if (name == getJointName((JointID) i)) return (JointID) i;
  }

  return numOfJoint;
}//end getJointName

void JointData::mirrorFrom(const JointData& jointData)
{
  for (int i = 0; i < numOfJoint; i++) {
    position[i] = jointData.mirrorData((JointID) i);
  }
}//end mirror

void JointData::mirror()
{
  JointData tmp = *this;
  mirrorFrom(tmp);
}

void JointData::clamp(JointID id)
{
  position[id] = Math::clamp(position[id], min[id], max[id]);
}

void JointData::clamp()
{
  for( int i=0; i<numOfJoint; i++) {
    clamp((JointID)i);
  }
}

bool JointData::isInRange(JointData::JointID id, double ang) const
{
    return ang <= max[id] && ang >= min[id];
}

bool JointData::isInRange(JointData::JointID id) const
{
    return isInRange(id, position[id]);
}

void JointData::updateSpeed(const JointData& lastData, double dt)
{
  const double* lastPose = lastData.position;
  double idt = 1 / dt;
  for ( int i=0; i<JointData::numOfJoint; i++)
  {
    dp[i] = (position[i] - lastPose[i]) * idt;
  }
}

void JointData::updateAcceleration(const JointData& lastData, double dt)
{
  const double* lastSpeed = lastData.dp;
  double idt = 1 / dt;
  for (int i = 0; i < JointData::numOfJoint; i++)
  {
    ddp[i] = (dp[i] - lastSpeed[i]) * idt;
  }
}

bool JointData::isLegStiffnessOn() const
{
  for ( int i=JointData::RHipYawPitch; i<JointData::numOfJoint; i++)
  {
    if ( stiffness[i] < 0 ) return false;
  }
  return true;
}

int JointData::checkStiffness() const
{
  for(int i=0; i<JointData::numOfJoint; i++)
  {
    double v = stiffness[i];
    if ( v > 1 || v < -1 )
    {
      return i;
      //THROW("Get ILLEGAL Stiffness: "<<getJointName(JointData::JointID(i))<<" = "<<v);
    }
  }
  return -1;
}

SensorJointData::SensorJointData()
  : timestamp(0)
{
  for (int i = 0; i < numOfJoint; i++)
  {
    electricCurrent[i] = 0.0;
    temperature[i] = 0.0;
  }
}

void SensorJointData::print(ostream& stream) const
{
  stream << "Timestamp: " << timestamp << endl;
  stream << "Joint [pos(deg), stiffness, temperature,current]" << endl;
  stream << "------------------------" << endl;
  for (int i = 0; i < numOfJoint; i++)
  {
    stream.precision(4);
    stream << getJointName((JointData::JointID) i) << "\t[" << fixed << Math::toDegrees(position[i]) << ", " << stiffness[i] << ", ";
    stream.precision(0);
    stream << temperature[i] << ", ";
    stream.precision(3);
    stream << electricCurrent[i] << "]" <<  endl;
  }
}//end print

SensorJointData::~SensorJointData()
{
}

MotorJointData::MotorJointData()
{
}

MotorJointData::~MotorJointData()
{
}

void MotorJointData::print(ostream& stream) const
{
  stream << "Joint [pos, stiffness]" << endl;
  stream << "------------------------" << endl;
  for (int i = 0; i < numOfJoint; i++) {
    stream << getJointName((JointData::JointID) i) << "[" << position[i] << ", " << stiffness[i] << "]" << endl;
  }
}//end print

void Serializer<SensorJointData>::serialize(const SensorJointData& representation, std::ostream& stream)
{
  naothmessages::SensorJointData message;

  for(int i=0; i < JointData::numOfJoint; i++)
  {
    message.add_electriccurrent(representation.electricCurrent[i]);
    message.add_temperature(representation.temperature[i]);

    message.mutable_jointdata()->add_position(representation.position[i]);
    message.mutable_jointdata()->add_stiffness(representation.stiffness[i]);
    message.mutable_jointdata()->add_dp(representation.dp[i]);
    message.mutable_jointdata()->add_ddp(representation.ddp[i]);
  }

  google::protobuf::io::OstreamOutputStream buf(&stream);
  message.SerializeToZeroCopyStream(&buf);
}

void Serializer<SensorJointData>::deserialize(std::istream& stream, SensorJointData& representation)
{
  naothmessages::SensorJointData message;
  google::protobuf::io::IstreamInputStream buf(&stream);
  message.ParseFromZeroCopyStream(&buf);

  // assure the integrity of the message
  ASSERT(message.electriccurrent().size() == JointData::numOfJoint);
  ASSERT(message.temperature().size() == JointData::numOfJoint);

  ASSERT(message.jointdata().position().size() == JointData::numOfJoint);
  ASSERT(message.jointdata().stiffness().size() == JointData::numOfJoint);
  ASSERT(message.jointdata().dp().size() == JointData::numOfJoint);
  ASSERT(message.jointdata().ddp().size() == JointData::numOfJoint);

  for (int i = 0; i < JointData::numOfJoint; i++)
  {
    representation.electricCurrent[i] = message.electriccurrent(i);
    representation.temperature[i] = message.temperature(i);
    // joint data
    representation.position[i] = message.jointdata().position(i);
    representation.stiffness[i] = message.jointdata().stiffness(i);
    representation.dp[i] = message.jointdata().dp(i);
    representation.ddp[i] = message.jointdata().ddp(i);
  }
}

void Serializer<MotorJointData>::serialize(const MotorJointData& representation, std::ostream& stream)
{
  naothmessages::JointData message;

  for(int i=0; i < JointData::numOfJoint; i++)
  {
    message.add_position(representation.position[i]);
    message.add_stiffness(representation.stiffness[i]);
    message.add_dp(representation.dp[i]);
    message.add_ddp(representation.ddp[i]);
  }

  google::protobuf::io::OstreamOutputStream buf(&stream);
  message.SerializeToZeroCopyStream(&buf);
}

void Serializer<MotorJointData>::deserialize(std::istream& stream, MotorJointData& representation)
{
  naothmessages::JointData message;
  google::protobuf::io::IstreamInputStream buf(&stream);
  message.ParseFromZeroCopyStream(&buf);

  // assure the integrity of the message
  ASSERT(message.position().size() == JointData::numOfJoint);
  ASSERT(message.stiffness().size() == JointData::numOfJoint);
  ASSERT(message.dp().size() == JointData::numOfJoint);
  ASSERT(message.ddp().size() == JointData::numOfJoint);

  for(int i=0; i < JointData::numOfJoint; i++)
  {
    representation.position[i] = message.position(i);
    representation.stiffness[i] = message.stiffness(i);
    representation.dp[i] = message.dp(i);
    representation.ddp[i] = message.ddp(i);
  }
}

<|endoftext|>


<commit_before>// StoryMaster Simulator
// Bryan DeGrendel (c) 2014
//
// See LICENSE for licensing information.
//
// simulator.cpp - Main file for the sample StoryMaster simulator.

#include <cstdlib>
#include <cstdio>

#include <iostream>

#include <storymaster.h>

using namespace std;

int main(int argc, const char *argv[])
{
  cout << "Operating over [examples/dialog.scene.lua] with runtime " SM_VERSION_STRING << endl;

  sm_core *core = (sm_core *)(malloc(sizeof(sm_core)));
  sm_session *session = (sm_session *)(malloc(sizeof(sm_session)));
  sm_scene *scene = (sm_scene *)(malloc(sizeof(sm_scene)));

  // TODO: Check return valuez and all that
  sm_core_init(core);
  sm_session_init(session, core, "common");
  sm_scene_init(scene, session, "dialog");

  sm_scene_load_from_file(scene, "examples/dialog.scene.lua");
  sm_scene_execute(scene);

  sm_scene_deinit(scene);
  sm_session_deinit(session);
  sm_core_deinit(core);

  free(scene);
  free(core);

  return 0;
}

<commit_msg>Updated the simulator to the latest API.<commit_after>// StoryMaster Simulator
// Bryan DeGrendel (c) 2014
//
// See LICENSE for licensing information.
//
// simulator.cpp - Main file for the sample StoryMaster simulator.

#include <cstdlib>
#include <cstdio>

#include <iostream>

#include <storymaster.h>

using namespace std;

int main(int argc, const char *argv[])
{
  cout << "Operating over [examples/dialog.scene.lua] with runtime " SM_VERSION_STRING << endl;

  sm_core *core = (sm_core *)(malloc(sizeof(sm_core)));
  sm_session *session = (sm_session *)(malloc(sizeof(sm_session)));
  sm_scene *scene = (sm_scene *)(malloc(sizeof(sm_scene)));

  // TODO: Check return valuez and all that
  sm_core_init(core);
  sm_session_init(session, core, "common");
  sm_scene_init_from_file(scene, session, "dialog", "example/dialog.lua");

  sm_scene_execute(scene);

  sm_scene_deinit(scene);
  sm_session_deinit(session);
  sm_core_deinit(core);

  free(scene);
  free(core);

  return 0;
}

<|endoftext|>


<commit_before>//
// (c) Copyright 2017 DESY,ESS
//
// This file is part of h5cpp.
//
// This library is free software; you can redistribute it and/or modify it
// under the terms of the GNU Lesser General Public License as published
// by the Free Software Foundation; either version 2.1 of the License, or
// (at your option) any later version.
//
// This library is distributed in the hope that it will be useful, but
// WITHOUT ANY WARRANTY; without even the implied warranty ofMERCHANTABILITY
// 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., 51 Franklin Street, Fifth Floor
// Boston, MA  02110-1301 USA
// ===========================================================================
//
// Author: Eugen Wintersberger <eugen.wintersberger@desy.de>
// Created on: Aug 16, 2017
//

#include <stdexcept>

#include <h5cpp/property/file_creation.hpp>

namespace hdf5 {
namespace property{

FileCreationList::FileCreationList():
    GroupCreationList(kFileCreate)
{
}

FileCreationList::~FileCreationList()
{}

hsize_t FileCreationList::user_block() const
{
  hsize_t buffer;
  if(0 > H5Pget_userblock(static_cast<hid_t>(*this), &buffer))
  {
    throw std::runtime_error("Cannot retrieve user block size from file creation property list!");
  }
  return buffer;
}

void FileCreationList::user_block(hsize_t size) const
{
  if(0 > H5Pset_userblock(static_cast<hid_t>(*this), size))
  {
    throw std::runtime_error("Cannot set user block size for file creation property list!");
  }
}

void FileCreationList::object_offset_size(size_t size) const
{
  if(0 > H5Pset_sizes(static_cast<hid_t>(*this), size, 0))
  {
    throw std::runtime_error("Failure setting object offset size to file creation property list!");
  }
}

size_t FileCreationList::object_offset_size() const
{
  size_t offset_size = 0,
         length_size = 0;

  if(0 > H5Pget_sizes(static_cast<hid_t>(*this), &offset_size, &length_size))
  {
    throw std::runtime_error("Failure retrieving object offset size from file creation property list!");
  }

  return offset_size;
}

void FileCreationList::object_length_size(size_t size) const
{
  if(0 > H5Pset_sizes(static_cast<hid_t>(*this), 0, size))
  {
    throw std::runtime_error("Failure setting object length size in file creation property list!");
  }
}

size_t FileCreationList::object_length_size() const
{
  size_t offset_size = 0,
         length_size = 0;

  if(0 > H5Pget_sizes(static_cast<hid_t>(*this), &offset_size, &length_size))
  {
    throw std::runtime_error("Failure retrieving object length size from file creation property list!");
  }

  return length_size;
}

  void FileCreationList::btree_rank(unsigned ik)
  {
    if(0 > H5Pset_sym_k(static_cast<hid_t>(*this), ik, 0))
    {
      throw std::runtime_error("Failure setting rank parameter for symbol table nodes!");
    }
  }

  unsigned FileCreationList::btree_rank() const
  {
    unsigned ret;
    if(0 > H5Pget_sym_k(static_cast<hid_t>(*this), &ret, NULL))
    {
      throw std::runtime_error("Failure retrieving rank parameter for symbol table nodes!");
    }
    return ret;
  }

  void FileCreationList::btree_symbols(unsigned lk)
  {
    if(0 > H5Pset_sym_k(static_cast<hid_t>(*this), 0, lk))
    {
      throw std::runtime_error("Failure setting symbol size parameter for symbol table nodes!");
    }
  }

  unsigned FileCreationList::btree_symbols() const
  {
    unsigned ret;
    if(0 > H5Pget_sym_k(static_cast<hid_t>(*this), NULL, &ret))
    {
      throw std::runtime_error("Failure retrieving symbol size parameter for symbol table nodes!");
    }
    return ret;
  }

} // namespace property
} // namespace hdf5
<commit_msg>some simplification of sizes functions, variable nomenclature changes; updates #98'<commit_after>//
// (c) Copyright 2017 DESY,ESS
//
// This file is part of h5cpp.
//
// This library is free software; you can redistribute it and/or modify it
// under the terms of the GNU Lesser General Public License as published
// by the Free Software Foundation; either version 2.1 of the License, or
// (at your option) any later version.
//
// This library is distributed in the hope that it will be useful, but
// WITHOUT ANY WARRANTY; without even the implied warranty ofMERCHANTABILITY
// 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., 51 Franklin Street, Fifth Floor
// Boston, MA  02110-1301 USA
// ===========================================================================
//
// Author: Eugen Wintersberger <eugen.wintersberger@desy.de>
// Created on: Aug 16, 2017
//

#include <stdexcept>

#include <h5cpp/property/file_creation.hpp>

namespace hdf5 {
namespace property{

FileCreationList::FileCreationList():
    GroupCreationList(kFileCreate)
{
}

FileCreationList::~FileCreationList()
{}

hsize_t FileCreationList::user_block() const
{
  hsize_t buffer;
  if(0 > H5Pget_userblock(static_cast<hid_t>(*this), &buffer))
  {
    throw std::runtime_error("Cannot retrieve user block size from file creation property list!");
  }
  return buffer;
}

void FileCreationList::user_block(hsize_t size) const
{
  if(0 > H5Pset_userblock(static_cast<hid_t>(*this), size))
  {
    throw std::runtime_error("Cannot set user block size for file creation property list!");
  }
}

void FileCreationList::object_offset_size(size_t size) const
{
  if(0 > H5Pset_sizes(static_cast<hid_t>(*this), size, 0))
  {
    throw std::runtime_error("Failure setting object offset size to file creation property list!");
  }
}

size_t FileCreationList::object_offset_size() const
{
  size_t offset_size {0};
  if(0 > H5Pget_sizes(static_cast<hid_t>(*this), &offset_size, NULL))
  {
    throw std::runtime_error("Failure retrieving object offset size from file creation property list!");
  }

  return offset_size;
}

void FileCreationList::object_length_size(size_t size) const
{
  if(0 > H5Pset_sizes(static_cast<hid_t>(*this), 0, size))
  {
    throw std::runtime_error("Failure setting object length size in file creation property list!");
  }
}

size_t FileCreationList::object_length_size() const
{
  size_t length_size {0};
  if(0 > H5Pget_sizes(static_cast<hid_t>(*this), NULL, &length_size))
  {
    throw std::runtime_error("Failure retrieving object length size from file creation property list!");
  }
  return length_size;
}

  void FileCreationList::btree_rank(unsigned ik)
  {
    if(0 > H5Pset_sym_k(static_cast<hid_t>(*this), ik, 0))
    {
      throw std::runtime_error("Failure setting rank parameter for symbol table nodes!");
    }
  }

  unsigned FileCreationList::btree_rank() const
  {
    unsigned ik {0};
    if(0 > H5Pget_sym_k(static_cast<hid_t>(*this), &ik, NULL))
    {
      throw std::runtime_error("Failure retrieving rank parameter for symbol table nodes!");
    }
    return ik;
  }

  void FileCreationList::btree_symbols(unsigned lk)
  {
    if(0 > H5Pset_sym_k(static_cast<hid_t>(*this), 0, lk))
    {
      throw std::runtime_error("Failure setting symbol size parameter for symbol table nodes!");
    }
  }

  unsigned FileCreationList::btree_symbols() const
  {
    unsigned lk {0};
    if(0 > H5Pget_sym_k(static_cast<hid_t>(*this), NULL, &lk))
    {
      throw std::runtime_error("Failure retrieving symbol size parameter for symbol table nodes!");
    }
    return lk;
  }

} // namespace property
} // namespace hdf5
<|endoftext|>


<commit_before>/*************************************************************************
 *
 *  $RCSfile: so_main.cxx,v $
 *
 *  $Revision: 1.2 $
 *
 *  last change: $Author: rt $ $Date: 2004-08-20 10:08:44 $
 *
 *  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 WARRUNTY OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING,
 *  WITHOUT LIMITATION, WARRUNTIES 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): _______________________________________
 *
 *
 ************************************************************************/
#ifdef UNIX
#include <sys/stat.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#endif //end of UNIX

#ifdef WNT
#pragma once
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <winsock2.h>
#include <stdlib.h>
#include <malloc.h>
#include <memory.h>
#include <tchar.h>
#endif //end of WNT

#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>

#include "ns_debug.hxx"
#include "so_msg.hxx"
#include "so_instance.hxx"
#include "so_env.hxx"

#include "nsp_func.hxx"

#define MAX_NODE_NUM 1024
SoPluginInstance* lpInstance[MAX_NODE_NUM];

long int NSP_ReadFromPipe(NSP_PIPE_FD fp, void* buf, unsigned long int len)
{
    unsigned long int len_unix = 0, len_wnt = 0;

    len_unix = NSP_Read_Pipe(fp, buf, len, &len_wnt);
#ifdef UNIX
    return  len_unix;
#endif //end of UNIX
#ifdef WNT
    return  len_wnt;
#endif //end of WNT

}

int find_free_node()
{
    for(int i=0; i<MAX_NODE_NUM; i++)
    {
        if(NULL == lpInstance[i])
            return i;
    }
    return -1;
}

int find_cur_node(sal_Int32 cur_id)
{
    for(int i=0; i<MAX_NODE_NUM; i++)
    {
        if(lpInstance[i] == NULL)
            continue;
        if(cur_id == lpInstance[i]->GetParent())
            return i;
    }
    return -1;
}

sal_Bool dump_plugin_message(PLUGIN_MSG* pMsg)
{
    if (!pMsg)
        return sal_False;
    debug_fprintf(NSP_LOG_APPEND, "NSPlugin Message: msg_id:%d; instance_id:%d;wnd_id:%d;wnd_x:%d;wnd_y:%d;wnd_w:%d;wnd_h:%d; url:%s\n",
        pMsg->msg_id, pMsg->instance_id, pMsg->wnd_id,
        pMsg->wnd_x, pMsg->wnd_y, pMsg->wnd_w, pMsg->wnd_h, pMsg->url);
    return sal_True;
}

int prepareEnviron()
{
    // if child process inherit the chdir() property from parent process, if yes, no getNewLibraryPath() needed
    const char* pNewLibraryPath = getNewLibraryPath();
    putenv( (char*) pNewLibraryPath );
    SoPluginInstance::SetSODir((char *)findProgramDir());

    return 0;
}

int Set_Window(PLUGIN_MSG* pMsg)
{
    dump_plugin_message(pMsg);
    int cur_no;
    if( -1 == (cur_no = find_cur_node(pMsg->instance_id)))
        return -1;
    if(lpInstance[cur_no]->SetWindow(pMsg->wnd_id,
        pMsg->wnd_x, pMsg->wnd_y, pMsg->wnd_w, pMsg->wnd_h))
        return 0;
    else
        return -1;
}

int Set_URL(PLUGIN_MSG* pMsg)
{
    dump_plugin_message(pMsg);
    int cur_no;
    if( -1 == (cur_no = find_cur_node(pMsg->instance_id)))
        return -1;
    if(lpInstance[cur_no]->SetURL(pMsg->url))
        return 0;
    else
        return -1;
}

int New_Instance(PLUGIN_MSG* pMsg)
{
    dump_plugin_message(pMsg);
    int free_no;
    if( -1 == (free_no = find_free_node()))
        return -1;
    lpInstance[free_no] = new SoPluginInstance(pMsg->instance_id);
    return 0;
}

int Destroy(PLUGIN_MSG* pMsg)
{
    dump_plugin_message(pMsg);
    int cur_no;
    if( -1 == (cur_no = find_cur_node(pMsg->instance_id)))
        return -1;
    if(lpInstance[cur_no] != NULL)
    {
        lpInstance[cur_no]->Destroy();
        debug_fprintf(NSP_LOG_APPEND, "print by Nsplugin, begin delete.\n");
        delete(lpInstance[cur_no]);
        lpInstance[cur_no] = NULL;
    }
    return 0;
}

int Print(PLUGIN_MSG* pMsg)
{
    dump_plugin_message(pMsg);
    int cur_no;
    if( -1 == (cur_no = find_cur_node(pMsg->instance_id)))
        return -1;
    if(lpInstance[cur_no] != NULL)
    {
        lpInstance[cur_no]->Print();
    }
    return 0;
}

int Shutdown()
{
    for(int cur_no=0; cur_no<MAX_NODE_NUM; cur_no++)
    {
        if(lpInstance[cur_no] == NULL)
            continue;
        lpInstance[cur_no]->Destroy();
        debug_fprintf(NSP_LOG_APPEND, "print by Nsplugin, begin delete.\n");
        delete(lpInstance[cur_no]);
        lpInstance[cur_no] = NULL;
    }
    return -1;
}

int dispatchMsg(PLUGIN_MSG* pMsg)
{
    switch(pMsg->msg_id)
    {
        case SO_SET_WINDOW:
            return Set_Window(pMsg);
        case SO_NEW_INSTANCE:
            return New_Instance(pMsg);
        case SO_SET_URL:
            return Set_URL(pMsg);
        case SO_DESTROY:
            return Destroy(pMsg);
        case SO_SHUTDOWN:
            Shutdown();
            return -1;
         case SO_PRINT:
            Print(pMsg);
            return 0;
        default:
            return -1;
            break;
    }
}

sal_Bool start_office(NSP_PIPE_FD read_fd)
{
    int my_sock;
    struct sockaddr_in dst_addr;
#ifdef WNT
    {
        WSADATA wsaData;
        WORD wVersionRequested;

        wVersionRequested = MAKEWORD(2,0);
        if(WSAStartup(wVersionRequested, &wsaData))
        {
           NSP_Close_Pipe(read_fd);
           debug_fprintf(NSP_LOG_APPEND, "Can not init socket in Windows.\n");
           return sal_False;
        }
    }
#endif //end of WNT
    memset(&dst_addr, 0, sizeof(dst_addr));
    dst_addr.sin_family = AF_INET;
    dst_addr.sin_port   = htons(SO_SERVER_PORT);
    dst_addr.sin_addr.s_addr = inet_addr("127.0.0.1");

    int count = 0;
    int ret = 0;

    my_sock=socket(PF_INET, SOCK_STREAM, 0);

    // if Star Office has been stared, we need not to start it again
    ret = connect(my_sock, (struct sockaddr *)&dst_addr, sizeof(dst_addr));
    if(ret == 0)
    {
        NSP_CloseSocket(my_sock);
        debug_fprintf(NSP_LOG_APPEND, "Staroffice already start\n");
        return sal_True;
    }
    {
        debug_fprintf(NSP_LOG_APPEND, "try to star Staroffice\n");
        char para[128] = {0};
        sprintf(para, "-accept=socket,host=0,port=%d;urp", SO_SERVER_PORT);
#ifdef UNIX
        int nChildPID = fork();
        if( ! nChildPID )  // child process
       {
            NSP_CloseSocket(my_sock);
            NSP_Close_Pipe(read_fd);
            execl("/bin/sh", "/bin/sh", "soffice", "-nologo", "-nodefault", para, NULL);
            _exit(255);
        }
#endif //end of UNIX
#ifdef WNT
            STARTUPINFO NSP_StarInfo;
            memset((void*) &NSP_StarInfo, 0, sizeof(STARTUPINFO));
            NSP_StarInfo.cb = sizeof(STARTUPINFO);
            PROCESS_INFORMATION NSP_ProcessInfo;
            memset((void*)&NSP_ProcessInfo, 0, sizeof(PROCESS_INFORMATION));
            sprintf(para, " -nologo -nodefault -accept=socket,host=0,port=%d;urp", SO_SERVER_PORT);
            SECURITY_ATTRIBUTES  NSP_access = { sizeof(SECURITY_ATTRIBUTES), NULL, FALSE};
            CreateProcess(findSofficeExecutable(), para, NULL, NULL, FALSE,
                        0 , NULL, NULL, &NSP_StarInfo, &NSP_ProcessInfo);
#endif //end of WNT
    }

    // try to connect to background SO, thus judge if it is ready
    while(0 > connect(my_sock, (struct sockaddr *)&dst_addr, sizeof(dst_addr)))
    {
        NSP_Sleep(1);
        if (count++ >= 120)
        {
            NSP_CloseSocket(my_sock);
            debug_fprintf(NSP_LOG_APPEND, "print by nsplugin, con star remote StarOffice\n");
            return sal_False;
        }
        debug_fprintf(NSP_LOG_APPEND, "print by nsplugin,  Current count: %d\n", count);
    }
    NSP_CloseSocket(my_sock);
    NSP_Sleep(5);

    prepareEnviron();

    return sal_True;
}

static  NSP_PIPE_FD la_read_fd = 0;

int main(int argc, char** argv)
{
   // Sleep(20*1000);
    debug_fprintf(NSP_LOG_APPEND, "start of main\n");
    memset(lpInstance, 0, sizeof(lpInstance));
    char readbuf[NPP_BUFFER_SIZE];

    NSP_PIPE_FD fd_pipe[2];
    int iPipe[2];
#ifdef UNIX
     if(argc < 3)
    {
        debug_fprintf(NSP_LOG_APPEND, "print by nsplugin, command error; too little argument to start plugin exec\n");
        return sal_False;
    }
    iPipe[0] = atoi(argv[1]);
    iPipe[1] = atoi(argv[2]);
#endif  //end of UNIX
#ifdef WNT
    //sscanf( GetCommandLine(), "%d %d", &iPipe[0],  &iPipe[1] );
    iPipe[0] = atoi(argv[0]);
    iPipe[1] = atoi(argv[1]);
#endif  //end of WNT

    // fd_pipe[0]: read, fd_pipe[0]: write
    fd_pipe[0] = (NSP_PIPE_FD) iPipe[0] ;
    fd_pipe[1] = (NSP_PIPE_FD) iPipe[1] ;
    NSP_Close_Pipe(fd_pipe[1]);

    la_read_fd = fd_pipe[0];
    if(la_read_fd < 0)
    {
        debug_fprintf(NSP_LOG_APPEND, "print by nsplugin, command error: bad read file id:%s \n", la_read_fd);
        return 0;
    }

    if(!start_office(la_read_fd))
    {
        NSP_Close_Pipe(la_read_fd);
        return -1;
    }

    PLUGIN_MSG nMsg;
    int len;
    while(1)
    {
        memset(&nMsg, 0, sizeof(PLUGIN_MSG));
        len = NSP_ReadFromPipe(la_read_fd, (char*)&nMsg, sizeof(PLUGIN_MSG));
        if(len != sizeof(PLUGIN_MSG))
            break;
        debug_fprintf(NSP_LOG_APPEND, "Read message from pipe type %d \n", nMsg.msg_id);
        if(-1 == dispatchMsg(&nMsg))
        {
            debug_fprintf(NSP_LOG_APPEND, "plugin will shutdown\n");
            break;
        }
    }
    NSP_Close_Pipe(la_read_fd);
    _exit(0);
}

extern "C"{
    sal_Bool restart_office(void){
        return start_office(la_read_fd);
    }
}
<commit_msg>INTEGRATION: CWS nsplugin3 (1.2.32); FILE MERGED 2004/11/12 02:01:02 jmeng 1.2.32.1: change paramater of CreateProcess in Windows to pass correct __argv to SO<commit_after>/*************************************************************************
 *
 *  $RCSfile: so_main.cxx,v $
 *
 *  $Revision: 1.3 $
 *
 *  last change: $Author: kz $ $Date: 2004-11-26 16:02:22 $
 *
 *  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 WARRUNTY OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING,
 *  WITHOUT LIMITATION, WARRUNTIES 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): _______________________________________
 *
 *
 ************************************************************************/
#ifdef UNIX
#include <sys/stat.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#endif //end of UNIX

#ifdef WNT
#pragma once
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <winsock2.h>
#include <stdlib.h>
#include <malloc.h>
#include <memory.h>
#include <tchar.h>
#endif //end of WNT

#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>

#include "ns_debug.hxx"
#include "so_msg.hxx"
#include "so_instance.hxx"
#include "so_env.hxx"

#include "nsp_func.hxx"

#define MAX_NODE_NUM 1024
SoPluginInstance* lpInstance[MAX_NODE_NUM];

long int NSP_ReadFromPipe(NSP_PIPE_FD fp, void* buf, unsigned long int len)
{
    unsigned long int len_unix = 0, len_wnt = 0;

    len_unix = NSP_Read_Pipe(fp, buf, len, &len_wnt);
#ifdef UNIX
    return  len_unix;
#endif //end of UNIX
#ifdef WNT
    return  len_wnt;
#endif //end of WNT

}

int find_free_node()
{
    for(int i=0; i<MAX_NODE_NUM; i++)
    {
        if(NULL == lpInstance[i])
            return i;
    }
    return -1;
}

int find_cur_node(sal_Int32 cur_id)
{
    for(int i=0; i<MAX_NODE_NUM; i++)
    {
        if(lpInstance[i] == NULL)
            continue;
        if(cur_id == lpInstance[i]->GetParent())
            return i;
    }
    return -1;
}

sal_Bool dump_plugin_message(PLUGIN_MSG* pMsg)
{
    if (!pMsg)
        return sal_False;
    debug_fprintf(NSP_LOG_APPEND, "NSPlugin Message: msg_id:%d; instance_id:%d;wnd_id:%d;wnd_x:%d;wnd_y:%d;wnd_w:%d;wnd_h:%d; url:%s\n",
        pMsg->msg_id, pMsg->instance_id, pMsg->wnd_id,
        pMsg->wnd_x, pMsg->wnd_y, pMsg->wnd_w, pMsg->wnd_h, pMsg->url);
    return sal_True;
}

int prepareEnviron()
{
    // if child process inherit the chdir() property from parent process, if yes, no getNewLibraryPath() needed
    const char* pNewLibraryPath = getNewLibraryPath();
    putenv( (char*) pNewLibraryPath );
    SoPluginInstance::SetSODir((char *)findProgramDir());

    return 0;
}

int Set_Window(PLUGIN_MSG* pMsg)
{
    dump_plugin_message(pMsg);
    int cur_no;
    if( -1 == (cur_no = find_cur_node(pMsg->instance_id)))
        return -1;
    if(lpInstance[cur_no]->SetWindow(pMsg->wnd_id,
        pMsg->wnd_x, pMsg->wnd_y, pMsg->wnd_w, pMsg->wnd_h))
        return 0;
    else
        return -1;
}

int Set_URL(PLUGIN_MSG* pMsg)
{
    dump_plugin_message(pMsg);
    int cur_no;
    if( -1 == (cur_no = find_cur_node(pMsg->instance_id)))
        return -1;
    if(lpInstance[cur_no]->SetURL(pMsg->url))
        return 0;
    else
        return -1;
}

int New_Instance(PLUGIN_MSG* pMsg)
{
    dump_plugin_message(pMsg);
    int free_no;
    if( -1 == (free_no = find_free_node()))
        return -1;
    lpInstance[free_no] = new SoPluginInstance(pMsg->instance_id);
    return 0;
}

int Destroy(PLUGIN_MSG* pMsg)
{
    dump_plugin_message(pMsg);
    int cur_no;
    if( -1 == (cur_no = find_cur_node(pMsg->instance_id)))
        return -1;
    if(lpInstance[cur_no] != NULL)
    {
        lpInstance[cur_no]->Destroy();
        debug_fprintf(NSP_LOG_APPEND, "print by Nsplugin, begin delete.\n");
        delete(lpInstance[cur_no]);
        lpInstance[cur_no] = NULL;
    }
    return 0;
}

int Print(PLUGIN_MSG* pMsg)
{
    dump_plugin_message(pMsg);
    int cur_no;
    if( -1 == (cur_no = find_cur_node(pMsg->instance_id)))
        return -1;
    if(lpInstance[cur_no] != NULL)
    {
        lpInstance[cur_no]->Print();
    }
    return 0;
}

int Shutdown()
{
    for(int cur_no=0; cur_no<MAX_NODE_NUM; cur_no++)
    {
        if(lpInstance[cur_no] == NULL)
            continue;
        lpInstance[cur_no]->Destroy();
        debug_fprintf(NSP_LOG_APPEND, "print by Nsplugin, begin delete.\n");
        delete(lpInstance[cur_no]);
        lpInstance[cur_no] = NULL;
    }
    return -1;
}

int dispatchMsg(PLUGIN_MSG* pMsg)
{
    switch(pMsg->msg_id)
    {
        case SO_SET_WINDOW:
            return Set_Window(pMsg);
        case SO_NEW_INSTANCE:
            return New_Instance(pMsg);
        case SO_SET_URL:
            return Set_URL(pMsg);
        case SO_DESTROY:
            return Destroy(pMsg);
        case SO_SHUTDOWN:
            Shutdown();
            return -1;
         case SO_PRINT:
            Print(pMsg);
            return 0;
        default:
            return -1;
            break;
    }
}

sal_Bool start_office(NSP_PIPE_FD read_fd)
{
    int my_sock;
    struct sockaddr_in dst_addr;
    char sCommand[NPP_PATH_MAX];
    sCommand[0] = 0;
#ifdef WNT
    {
        WSADATA wsaData;
        WORD wVersionRequested;

        wVersionRequested = MAKEWORD(2,0);
        if(WSAStartup(wVersionRequested, &wsaData))
        {
           NSP_Close_Pipe(read_fd);
           debug_fprintf(NSP_LOG_APPEND, "Can not init socket in Windows.\n");
           return sal_False;
        }
    }
#endif //end of WNT
    memset(&dst_addr, 0, sizeof(dst_addr));
    dst_addr.sin_family = AF_INET;
    dst_addr.sin_port   = htons(SO_SERVER_PORT);
    dst_addr.sin_addr.s_addr = inet_addr("127.0.0.1");

    int count = 0;
    int ret = 0;

    my_sock=socket(PF_INET, SOCK_STREAM, 0);

    // if Star Office has been stared, we need not to start it again
    ret = connect(my_sock, (struct sockaddr *)&dst_addr, sizeof(dst_addr));
    if(ret == 0)
    {
        NSP_CloseSocket(my_sock);
        debug_fprintf(NSP_LOG_APPEND, "Staroffice already start\n");
        return sal_True;
    }
    {
        debug_fprintf(NSP_LOG_APPEND, "try to star Staroffice\n");
        char para[128] = {0};
        sprintf(para, "-accept=socket,host=0,port=%d;urp", SO_SERVER_PORT);
#ifdef UNIX
        int nChildPID = fork();
        if( ! nChildPID )  // child process
       {
            NSP_CloseSocket(my_sock);
            NSP_Close_Pipe(read_fd);
            sprintf(sCommand, "/bin/sh soffice -nologo -nodefault %s", para);
            debug_fprintf(NSP_LOG_APPEND,"StarOffice will be started by command: %s\n",sCommand);
            execl("/bin/sh", "/bin/sh", "soffice", "-nologo", "-nodefault", para, NULL);
            _exit(255);
        }
#endif //end of UNIX
#ifdef WNT
            STARTUPINFO NSP_StarInfo;
            memset((void*) &NSP_StarInfo, 0, sizeof(STARTUPINFO));
            NSP_StarInfo.cb = sizeof(STARTUPINFO);
            PROCESS_INFORMATION NSP_ProcessInfo;
            memset((void*)&NSP_ProcessInfo, 0, sizeof(PROCESS_INFORMATION));
            sprintf(para, " -nologo -nodefault -accept=socket,host=0,port=%d;urp", SO_SERVER_PORT);
            //sprintf(para, " -accept=socket,host=0,port=%d;urp\n", SO_SERVER_PORT);
            SECURITY_ATTRIBUTES  NSP_access = { sizeof(SECURITY_ATTRIBUTES), NULL, FALSE};
            sprintf(sCommand, "\"%s\" %s", findSofficeExecutable(), para);
            debug_fprintf(NSP_LOG_APPEND,"StarOffice will be started by command: %s",sCommand);
            BOOL ret = false;
            ret = CreateProcess(findSofficeExecutable(), sCommand, NULL, NULL, FALSE,
                        0 , NULL, NULL, &NSP_StarInfo, &NSP_ProcessInfo);
            if(ret==false){
                debug_fprintf(NSP_LOG_APPEND,"run staroffice error: %u \n",
                    GetLastError());
            }
            else   debug_fprintf(NSP_LOG_APPEND,"run staroffice success\n");
#endif //end of WNT
    }

    NSP_Sleep(5);
    // try to connect to background SO, thus judge if it is ready
    while(0 > connect(my_sock, (struct sockaddr *)&dst_addr, sizeof(dst_addr)))
    {
        NSP_Sleep(1);
        if (count++ >= 120)
        {
            NSP_CloseSocket(my_sock);
            debug_fprintf(NSP_LOG_APPEND, "print by nsplugin, con star remote StarOffice\n");
            return sal_False;
        }
        debug_fprintf(NSP_LOG_APPEND, "print by nsplugin,  Current count: %d\n", count);
    }
    NSP_CloseSocket(my_sock);
    NSP_Sleep(5);

    prepareEnviron();

    return sal_True;
}

static  NSP_PIPE_FD la_read_fd = 0;

int main(int argc, char** argv)
{
   // Sleep(20*1000);
    debug_fprintf(NSP_LOG_APPEND, "start of main\n");
    memset(lpInstance, 0, sizeof(lpInstance));
    char readbuf[NPP_BUFFER_SIZE];

    NSP_PIPE_FD fd_pipe[2];
    int iPipe[2];
#ifdef UNIX
     if(argc < 3)
    {
        debug_fprintf(NSP_LOG_APPEND, "print by nsplugin, command error; too little argument to start plugin exec\n");
        return sal_False;
    }
    iPipe[0] = atoi(argv[1]);
    iPipe[1] = atoi(argv[2]);
#endif  //end of UNIX
#ifdef WNT
    //sscanf( GetCommandLine(), "%d %d", &iPipe[0],  &iPipe[1] );
    iPipe[0] = atoi(argv[0]);
    iPipe[1] = atoi(argv[1]);
#endif  //end of WNT

    // fd_pipe[0]: read, fd_pipe[0]: write
    fd_pipe[0] = (NSP_PIPE_FD) iPipe[0] ;
    fd_pipe[1] = (NSP_PIPE_FD) iPipe[1] ;
    NSP_Close_Pipe(fd_pipe[1]);

    la_read_fd = fd_pipe[0];
    if(la_read_fd < 0)
    {
        debug_fprintf(NSP_LOG_APPEND, "print by nsplugin, command error: bad read file id:%s \n", la_read_fd);
        return 0;
    }

    if(!start_office(la_read_fd))
    {
        NSP_Close_Pipe(la_read_fd);
        return -1;
    }

    PLUGIN_MSG nMsg;
    int len;
    while(1)
    {
        memset(&nMsg, 0, sizeof(PLUGIN_MSG));
        len = NSP_ReadFromPipe(la_read_fd, (char*)&nMsg, sizeof(PLUGIN_MSG));
        if(len != sizeof(PLUGIN_MSG))
            break;
        debug_fprintf(NSP_LOG_APPEND, "Read message from pipe type %d \n", nMsg.msg_id);
        if(-1 == dispatchMsg(&nMsg))
        {
            debug_fprintf(NSP_LOG_APPEND, "plugin will shutdown\n");
            break;
        }
    }
    NSP_Close_Pipe(la_read_fd);
    _exit(0);
}

extern "C"{
    sal_Bool restart_office(void){
        return start_office(la_read_fd);
    }
}
<|endoftext|>


<commit_before>/*
    addcontactwizard.cpp - Kopete's Add Contact Wizard

    Copyright (c) 2002 by Nick Betcher           <nbetcher@kde.org>
    Copyright (c) 2002 by Duncan Mac-Vicar Prett <duncan@kde.org>

    Kopete    (c) 2002 by the Kopete developers  <kopete-devel@kde.org>

    *************************************************************************
    *                                                                       *
    * This program is free software; you can redistribute it and/or modify  *
    * it under the terms of the GNU General Public License as published by  *
    * the Free Software Foundation; either version 2 of the License, or     *
    * (at your option) any later version.                                   *
    *                                                                       *
    *************************************************************************
*/

#include <qlayout.h>

#include <kglobal.h>
#include <klocale.h>
#include <kiconloader.h>
#include <klineeditdlg.h>
#include <kpushbutton.h>
#include <kstandarddirs.h>
#include <kdebug.h>
#include <klistview.h>

#include "addcontactpage.h"
#include "addcontactwizard.h"
#include "kopetegroup.h"
#include "kopetecontactlist.h"
#include "kopeteprotocol.h"
#include "kopetemetacontact.h"
#include "kopeteaccountmanager.h"
#include "kopeteaccount.h"
#include "kopeteprotocol.h"

AddContactWizard::AddContactWizard( QWidget *parent, const char *name )
: AddContactWizard_Base( parent, name )
{
	QStringList groups = KopeteContactList::contactList()->groups().toStringList();

	QStringList::ConstIterator it = groups.begin();
	for( ; it != groups.end(); ++it )
	{
		QString groupname = *it;

		if ( !groupname.isNull() )
			new QCheckListItem( groupList, groupname, QCheckListItem::CheckBox);
	}

	protocolListView->clear();
	m_accountItems.clear();

	QCheckListItem* accountLVI=0L;
	QPtrList<KopeteAccount>  accounts = KopeteAccountManager::manager()->accounts();
	for(KopeteAccount *i=accounts.first() ; i; i=accounts.next() )
	{
		accountLVI= new QCheckListItem( protocolListView, i->accountId(), QCheckListItem::CheckBox);
		accountLVI->setText(1,i->protocol()->displayName() + QString::fromLatin1(" ") );
		accountLVI->setPixmap( 1, SmallIcon( i->protocol()->pluginIcon() ) );
		m_accountItems.insert(accountLVI,i);
	}

	if ( accounts.count() == 1 )
	{
		accountLVI->setOn( true );
		setAppropriate( selectService, false );
	}

	setNextEnabled(selectService, (accounts.count() == 1));
	setFinishEnabled(finis, true);

	connect( addGroupButton, SIGNAL(clicked()) , SLOT(slotAddGroupClicked()) );
	connect( protocolListView, SIGNAL(clicked(QListViewItem *)), this, SLOT(slotProtocolListClicked(QListViewItem *)));
}

AddContactWizard::~AddContactWizard()
{
}

void AddContactWizard::slotProtocolListClicked( QListViewItem *)
{
	// Just makes sure a protocol is selected before allowing the user to continue
	bool oneIsChecked = false;

	for (QListViewItemIterator it(protocolListView); it.current(); ++it)
	{
		QCheckListItem *check = dynamic_cast<QCheckListItem *>(it.current());
		if (check && check->isOn())
		{
			oneIsChecked = true;
			break;
		}
	}

	setNextEnabled(selectService, oneIsChecked);
}

void AddContactWizard::slotGroupListClicked( QListViewItem *)
{
	//top-level contacts are allowed
/*
	bool oneIsChecked = false;
	for (QListViewItem *listItem = groupList->firstChild(); listItem != 0; listItem = listItem->itemBelow())
	{
		QCheckListItem *check = dynamic_cast<QCheckListItem *>(listItem);
		if (!check)
		{
			kdDebug(14000) << "WARNING : AddContactWizard::slotGroupListClicked : one listItem is not a CheckListItem" << endl;
		}
		else 	if (check->isOn())
		{
			oneIsChecked = true;
			break;
		}
	}
	setNextEnabled(page2,oneIsChecked);
  */
}

void AddContactWizard::slotAddGroupClicked()
{
	bool ok;
	QString groupName = KLineEditDlg::getText(
		i18n( "New Group - Kopete" ),
		i18n( "Please enter the name for the new group:" ),
		QString::null, &ok );

	if ( !groupName.isNull() && ok)
		new QCheckListItem( groupList, groupName, QCheckListItem::CheckBox);
}

void AddContactWizard::slotRemoveGroupClicked()
{
}

void AddContactWizard::accept()
{
	KopeteMetaContact *m = new KopeteMetaContact();
	bool topLevel = true;
	for (QListViewItemIterator it(groupList); it.current(); ++it)
	{
		QCheckListItem *check = dynamic_cast<QCheckListItem *>(it.current());
		if (check && check->isOn())
		{
			m->addToGroup(KopeteContactList::contactList()->getGroup(check->text()));
			topLevel = false;
		}
	}
	m->setTopLevel(topLevel);

	QMap <KopeteAccount*,AddContactPage*>::Iterator it;
	for ( it = protocolPages.begin(); it != protocolPages.end(); ++it )
	{
		it.data()->apply(it.key(),m);
	}
	KopeteContactList::contactList()->addMetaContact(m);
	delete(this);
}

void AddContactWizard::next()
{
	if (currentPage() == selectService ||
		(currentPage() == intro && !appropriate( selectService )))
	{
		QMap <KopeteAccount*,AddContactPage*>::Iterator it;
		for ( it = protocolPages.begin(); it != protocolPages.end(); ++it )
		{
			delete it.data();
		}
		protocolPages.clear();

		// We don't keep track of this pointer because it gets deleted when the wizard does (which is what we want)
		for (QListViewItemIterator it(protocolListView); it.current(); ++it)
		{
			QCheckListItem *item = dynamic_cast<QCheckListItem *>(it.current());
			if (item && item->isOn())
			{
				// this shouldn't happen either, but I hate crashes
				if (!m_accountItems[item]) continue;

				AddContactPage *addPage = m_accountItems[item]->protocol()->createAddContactWidget(this, m_accountItems[item] );
				if (!addPage) continue;

				QString title = i18n( "The account name is prepended here",
									  "%1 contact information" )
									 .arg( item->text(0) );
				addPage->show();
				insertPage( addPage, title, indexOf( selectGroup) );
				protocolPages.insert( m_accountItems[item] , addPage );
			}
		}
		QWizard::next();
		return;
	}
	if (currentPage() != intro &&
		currentPage() != selectService &&
		currentPage() != selectGroup &&
		currentPage() != finis)
	{
		AddContactPage *ePage = dynamic_cast<AddContactPage *>(currentPage());
		if (!ePage || !ePage->validateData())
			return;
	}
	QWizard::next();
}

#include "addcontactwizard.moc"

// vim: set noet ts=4 sts=4 sw=4:

<commit_msg>Remove the metacontact created by the add contact wizzard if the contact creation fail<commit_after>/*
    addcontactwizard.cpp - Kopete's Add Contact Wizard

    Copyright (c) 2002 by Nick Betcher           <nbetcher@kde.org>
    Copyright (c) 2002 by Duncan Mac-Vicar Prett <duncan@kde.org>

    Kopete    (c) 2002 by the Kopete developers  <kopete-devel@kde.org>

    *************************************************************************
    *                                                                       *
    * This program is free software; you can redistribute it and/or modify  *
    * it under the terms of the GNU General Public License as published by  *
    * the Free Software Foundation; either version 2 of the License, or     *
    * (at your option) any later version.                                   *
    *                                                                       *
    *************************************************************************
*/

#include <qlayout.h>

#include <kglobal.h>
#include <klocale.h>
#include <kiconloader.h>
#include <klineeditdlg.h>
#include <kpushbutton.h>
#include <kstandarddirs.h>
#include <kdebug.h>
#include <klistview.h>

#include "addcontactpage.h"
#include "addcontactwizard.h"
#include "kopetegroup.h"
#include "kopetecontactlist.h"
#include "kopeteprotocol.h"
#include "kopetemetacontact.h"
#include "kopeteaccountmanager.h"
#include "kopeteaccount.h"
#include "kopeteprotocol.h"

AddContactWizard::AddContactWizard( QWidget *parent, const char *name )
: AddContactWizard_Base( parent, name )
{
	QStringList groups = KopeteContactList::contactList()->groups().toStringList();

	QStringList::ConstIterator it = groups.begin();
	for( ; it != groups.end(); ++it )
	{
		QString groupname = *it;

		if ( !groupname.isNull() )
			new QCheckListItem( groupList, groupname, QCheckListItem::CheckBox);
	}

	protocolListView->clear();
	m_accountItems.clear();

	QCheckListItem* accountLVI=0L;
	QPtrList<KopeteAccount>  accounts = KopeteAccountManager::manager()->accounts();
	for(KopeteAccount *i=accounts.first() ; i; i=accounts.next() )
	{
		accountLVI= new QCheckListItem( protocolListView, i->accountId(), QCheckListItem::CheckBox);
		accountLVI->setText(1,i->protocol()->displayName() + QString::fromLatin1(" ") );
		accountLVI->setPixmap( 1, SmallIcon( i->protocol()->pluginIcon() ) );
		m_accountItems.insert(accountLVI,i);
	}

	if ( accounts.count() == 1 )
	{
		accountLVI->setOn( true );
		setAppropriate( selectService, false );
	}

	setNextEnabled(selectService, (accounts.count() == 1));
	setFinishEnabled(finis, true);

	connect( addGroupButton, SIGNAL(clicked()) , SLOT(slotAddGroupClicked()) );
	connect( protocolListView, SIGNAL(clicked(QListViewItem *)), this, SLOT(slotProtocolListClicked(QListViewItem *)));
}

AddContactWizard::~AddContactWizard()
{
}

void AddContactWizard::slotProtocolListClicked( QListViewItem *)
{
	// Just makes sure a protocol is selected before allowing the user to continue
	bool oneIsChecked = false;

	for (QListViewItemIterator it(protocolListView); it.current(); ++it)
	{
		QCheckListItem *check = dynamic_cast<QCheckListItem *>(it.current());
		if (check && check->isOn())
		{
			oneIsChecked = true;
			break;
		}
	}

	setNextEnabled(selectService, oneIsChecked);
}

void AddContactWizard::slotGroupListClicked( QListViewItem *)
{
	//top-level contacts are allowed
/*
	bool oneIsChecked = false;
	for (QListViewItem *listItem = groupList->firstChild(); listItem != 0; listItem = listItem->itemBelow())
	{
		QCheckListItem *check = dynamic_cast<QCheckListItem *>(listItem);
		if (!check)
		{
			kdDebug(14000) << "WARNING : AddContactWizard::slotGroupListClicked : one listItem is not a CheckListItem" << endl;
		}
		else 	if (check->isOn())
		{
			oneIsChecked = true;
			break;
		}
	}
	setNextEnabled(page2,oneIsChecked);
  */
}

void AddContactWizard::slotAddGroupClicked()
{
	bool ok;
	QString groupName = KLineEditDlg::getText(
		i18n( "New Group - Kopete" ),
		i18n( "Please enter the name for the new group:" ),
		QString::null, &ok );

	if ( !groupName.isNull() && ok)
		new QCheckListItem( groupList, groupName, QCheckListItem::CheckBox);
}

void AddContactWizard::slotRemoveGroupClicked()
{
}

void AddContactWizard::accept()
{
	KopeteMetaContact *m = new KopeteMetaContact();
	bool topLevel = true;
	for (QListViewItemIterator it(groupList); it.current(); ++it)
	{
		QCheckListItem *check = dynamic_cast<QCheckListItem *>(it.current());
		if (check && check->isOn())
		{
			m->addToGroup(KopeteContactList::contactList()->getGroup(check->text()));
			topLevel = false;
		}
	}
	m->setTopLevel(topLevel);

	bool ok=false;

	QMap <KopeteAccount*,AddContactPage*>::Iterator it;
	for ( it = protocolPages.begin(); it != protocolPages.end(); ++it )
	{
		ok |= it.data()->apply(it.key(),m);
	}
	if(ok)
		KopeteContactList::contactList()->addMetaContact(m);
	else
		delete m;
	delete this;
}

void AddContactWizard::next()
{
	if (currentPage() == selectService ||
		(currentPage() == intro && !appropriate( selectService )))
	{
		QMap <KopeteAccount*,AddContactPage*>::Iterator it;
		for ( it = protocolPages.begin(); it != protocolPages.end(); ++it )
		{
			delete it.data();
		}
		protocolPages.clear();

		// We don't keep track of this pointer because it gets deleted when the wizard does (which is what we want)
		for (QListViewItemIterator it(protocolListView); it.current(); ++it)
		{
			QCheckListItem *item = dynamic_cast<QCheckListItem *>(it.current());
			if (item && item->isOn())
			{
				// this shouldn't happen either, but I hate crashes
				if (!m_accountItems[item]) continue;

				AddContactPage *addPage = m_accountItems[item]->protocol()->createAddContactWidget(this, m_accountItems[item] );
				if (!addPage) continue;

				QString title = i18n( "The account name is prepended here",
									  "%1 contact information" )
									 .arg( item->text(0) );
				addPage->show();
				insertPage( addPage, title, indexOf( selectGroup) );
				protocolPages.insert( m_accountItems[item] , addPage );
			}
		}
		QWizard::next();
		return;
	}
	if (currentPage() != intro &&
		currentPage() != selectService &&
		currentPage() != selectGroup &&
		currentPage() != finis)
	{
		AddContactPage *ePage = dynamic_cast<AddContactPage *>(currentPage());
		if (!ePage || !ePage->validateData())
			return;
	}
	QWizard::next();
}

#include "addcontactwizard.moc"

// vim: set noet ts=4 sts=4 sw=4:

<|endoftext|>


<commit_before>#ifndef __MODEL_CLIENT_HPP__
#define __MODEL_CLIENT_HPP__

#include <map>
#include <boost/shared_ptr.hpp>

#include "urdf/model.h"
#include <lcm/lcm.h>
#include "lcmtypes/model_pub_robot_urdf_t.h"
#include <fstream>

class ModelClient
{
  public:
    ModelClient (lcm_t* lcm_, int keep_updated);
    ModelClient(lcm_t* lcm_, std::string model_channel_, int keep_updated_);

    // Get the model client directly from the specified file:
    // robot name isn't important
    ModelClient(std::string urdf_filename);

    ~ModelClient() {}

    void doModelClient();

    static void robot_urdf_handler_aux(const lcm_recv_buf_t* rbuf, const char* channel,
                                            const model_pub_robot_urdf_t* msg, void* user_data){
      ((ModelClient *) user_data)->robot_urdf_handler(channel, msg);
    }
    void robot_urdf_handler(const char* channel, const model_pub_robot_urdf_t *msg);

    // Returns false if urdf isn't an XML string:
    bool readURDFFromFile(std::string);

    void parseURDFString();
    // determine which hands are connected to the robot and store that info
    // this information is higher level than just the string as it assumes an lcmtype
    void setHandConfiguration();

    std::string getURDFString(){ return urdf_xml_string_; }
    std::string getRobotName(){ return robot_name_; }
    std::vector<std::string> getJointNames(){ return joint_names_; };
    int8_t getLeftHand(){ return left_hand_; };
    int8_t getRightHand(){ return right_hand_; };

  private:
    lcm_t* lcm_;
    lcm::Subscription *_urdf_subscription; //valid as long as _urdf_parsed == false
    bool urdf_parsed_;
    std::string model_channel_;
    std::string robot_name_;
    std::string urdf_xml_string_;
    std::vector<std::string> joint_names_;
    std::map<std::string, boost::shared_ptr<urdf::Link> > links_map_;
    int keep_updated_;

    int8_t left_hand_, right_hand_;

    bool file_read_success_;
};

#endif
<commit_msg>add cpp include<commit_after>#ifndef __MODEL_CLIENT_HPP__
#define __MODEL_CLIENT_HPP__

#include <map>
#include <boost/shared_ptr.hpp>

#include "urdf/model.h"
#include <lcm/lcm.h>
#include <lcm/lcm-cpp.hpp>
#include "lcmtypes/model_pub_robot_urdf_t.h"
#include <fstream>

class ModelClient
{
  public:
    ModelClient (lcm_t* lcm_, int keep_updated);
    ModelClient(lcm_t* lcm_, std::string model_channel_, int keep_updated_);

    // Get the model client directly from the specified file:
    // robot name isn't important
    ModelClient(std::string urdf_filename);

    ~ModelClient() {}

    void doModelClient();

    static void robot_urdf_handler_aux(const lcm_recv_buf_t* rbuf, const char* channel,
                                            const model_pub_robot_urdf_t* msg, void* user_data){
      ((ModelClient *) user_data)->robot_urdf_handler(channel, msg);
    }
    void robot_urdf_handler(const char* channel, const model_pub_robot_urdf_t *msg);

    // Returns false if urdf isn't an XML string:
    bool readURDFFromFile(std::string);

    void parseURDFString();
    // determine which hands are connected to the robot and store that info
    // this information is higher level than just the string as it assumes an lcmtype
    void setHandConfiguration();

    std::string getURDFString(){ return urdf_xml_string_; }
    std::string getRobotName(){ return robot_name_; }
    std::vector<std::string> getJointNames(){ return joint_names_; };
    int8_t getLeftHand(){ return left_hand_; };
    int8_t getRightHand(){ return right_hand_; };

  private:
    lcm_t* lcm_;
    lcm::Subscription *_urdf_subscription; //valid as long as _urdf_parsed == false
    bool urdf_parsed_;
    std::string model_channel_;
    std::string robot_name_;
    std::string urdf_xml_string_;
    std::vector<std::string> joint_names_;
    std::map<std::string, boost::shared_ptr<urdf::Link> > links_map_;
    int keep_updated_;

    int8_t left_hand_, right_hand_;

    bool file_read_success_;
};

#endif
<|endoftext|>


<commit_before>/*
 * Copyright (C) 2012-2013 Matt Broadstone
 * Contact: http://bitbucket.org/devonit/qjsonrpc
 *
 * This file is part of the QJsonRpc Library.
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * 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.
 */
#include <QEventLoop>
#include <QTimer>
#include <QDebug>

#if QT_VERSION >= 0x050000
#include <QJsonDocument>
#else
#include "json/qjsondocument.h"
#endif

#include "qjsonrpcsocket_p.h"
#include "qjsonrpcservicereply_p.h"
#include "qjsonrpchttpclient.h"

class QJsonRpcHttpReplyPrivate : public QJsonRpcServiceReplyPrivate
{
public:
    QJsonRpcMessage request;
    QNetworkReply *reply;
};

class QJsonRpcHttpReply : public QJsonRpcServiceReply
{
    Q_OBJECT
public:
    QJsonRpcHttpReply(const QJsonRpcMessage &request,
                      QNetworkReply *reply, QObject *parent = 0)
        : QJsonRpcServiceReply(*new QJsonRpcHttpReplyPrivate, parent)
    {
        Q_D(QJsonRpcHttpReply);
        d->request = request;
        d->reply = reply;
        connect(d->reply, SIGNAL(finished()), this, SLOT(networkReplyFinished()));
        connect(d->reply, SIGNAL(error(QNetworkReply::NetworkError)),
                    this, SLOT(networkReplyError(QNetworkReply::NetworkError)));
    }

    virtual ~QJsonRpcHttpReply() {}

private Q_SLOTS:
    void networkReplyFinished()
    {
        Q_D(QJsonRpcHttpReply);
        QNetworkReply *reply = qobject_cast<QNetworkReply*>(sender());
        if (!reply) {
            qJsonRpcDebug() << Q_FUNC_INFO << "invalid reply";
            return;
        }

        if (reply->error() != QNetworkReply::NoError) {
            // this should be handled by the networkReplyError slot
        } else {
            QByteArray data = reply->readAll();
            QJsonDocument doc = QJsonDocument::fromJson(data);
            if (doc.isEmpty() || doc.isNull() || !doc.isObject()) {
                d->response =
                    d->request.createErrorResponse(QJsonRpc::ParseError,
                                                   "unable to process incoming JSON data",
                                                   QString::fromUtf8(data));
            } else {
                qJsonRpcDebug() << "received: " << doc.toJson();
                QJsonRpcMessage response = QJsonRpcMessage::fromObject(doc.object());
                if (d->request.type() == QJsonRpcMessage::Request &&
                    d->request.id() != response.id()) {
                    d->response =
                        d->request.createErrorResponse(QJsonRpc::InternalError,
                                                       "invalid response id",
                                                       QString::fromUtf8(data));
                } else {
                    d->response = response;
                }
            }
        }

        Q_EMIT finished();
    }

    void networkReplyError(QNetworkReply::NetworkError code)
    {
        Q_D(QJsonRpcHttpReply);
        QNetworkReply *reply = qobject_cast<QNetworkReply*>(sender());
        if (!reply) {
            qJsonRpcDebug() << Q_FUNC_INFO << "invalid reply";
            return;
        }

        if (code == QNetworkReply::NoError)
            return;

        d->response = d->request.createErrorResponse(QJsonRpc::InternalError,
                                       "error with http request",
                                       reply->errorString());
        Q_EMIT finished();
    }

private:
    Q_DISABLE_COPY(QJsonRpcHttpReply)
    Q_DECLARE_PRIVATE(QJsonRpcHttpReply)

};

class QJsonRpcHttpClientPrivate : public QJsonRpcAbstractSocketPrivate
{
public:
    void initializeNetworkAccessManager(QJsonRpcHttpClient *client) {
        QObject::connect(networkAccessManager, SIGNAL(authenticationRequired(QNetworkReply*,QAuthenticator*)),
                client, SLOT(handleAuthenticationRequired(QNetworkReply*,QAuthenticator*)));
        QObject::connect(networkAccessManager, SIGNAL(sslErrors(QNetworkReply*,QList<QSslError>)),
                client, SLOT(handleSslErrors(QNetworkReply*,QList<QSslError>)));
    }

    QNetworkReply *writeMessage(const QJsonRpcMessage &message) {
        QNetworkRequest request(endPoint);
        request.setHeader(QNetworkRequest::ContentTypeHeader, "application/json");
        request.setRawHeader("Accept", "application/json-rpc");
        if (!sslConfiguration.isNull())
            request.setSslConfiguration(sslConfiguration);

        QByteArray data = message.toJson();
        qJsonRpcDebug() << "sending: " << data;
        return networkAccessManager->post(request, data);
    }

    QUrl endPoint;
    QNetworkAccessManager *networkAccessManager;
    QSslConfiguration sslConfiguration;
};

QJsonRpcHttpClient::QJsonRpcHttpClient(QObject *parent)
    : QJsonRpcAbstractSocket(*new QJsonRpcHttpClientPrivate, parent)
{
    Q_D(QJsonRpcHttpClient);
    d->networkAccessManager = new QNetworkAccessManager(this);
    d->initializeNetworkAccessManager(this);
}

QJsonRpcHttpClient::QJsonRpcHttpClient(QNetworkAccessManager *manager, QObject *parent)
    : QJsonRpcAbstractSocket(*new QJsonRpcHttpClientPrivate, parent)
{
    Q_D(QJsonRpcHttpClient);
    d->networkAccessManager = manager;
    d->initializeNetworkAccessManager(this);
}

QJsonRpcHttpClient::QJsonRpcHttpClient(const QString &endPoint, QObject *parent)
    : QJsonRpcAbstractSocket(*new QJsonRpcHttpClientPrivate, parent)
{
    Q_D(QJsonRpcHttpClient);
    d->endPoint = QUrl::fromUserInput(endPoint);
    d->networkAccessManager = new QNetworkAccessManager(this);
    d->initializeNetworkAccessManager(this);
}

QJsonRpcHttpClient::~QJsonRpcHttpClient()
{
}

bool QJsonRpcHttpClient::isValid() const
{
    Q_D(const QJsonRpcHttpClient);
    return d->networkAccessManager && !d->endPoint.isEmpty() && d->endPoint.isValid();
}

QUrl QJsonRpcHttpClient::endPoint() const
{
    Q_D(const QJsonRpcHttpClient);
    return d->endPoint;
}

void QJsonRpcHttpClient::setEndPoint(const QUrl &endPoint)
{
    Q_D(QJsonRpcHttpClient);
    d->endPoint = endPoint;
}

void QJsonRpcHttpClient::setEndPoint(const QString &endPoint)
{
    Q_D(QJsonRpcHttpClient);
    d->endPoint = QUrl::fromUserInput(endPoint);
}

QSslConfiguration QJsonRpcHttpClient::sslConfiguration() const
{
    Q_D(const QJsonRpcHttpClient);
    return d->sslConfiguration;
}

void QJsonRpcHttpClient::setSslConfiguration(const QSslConfiguration &sslConfiguration)
{
    Q_D(QJsonRpcHttpClient);
    d->sslConfiguration = sslConfiguration;
}

QNetworkAccessManager *QJsonRpcHttpClient::networkAccessManager()
{
    Q_D(QJsonRpcHttpClient);
    return d->networkAccessManager;
}

void QJsonRpcHttpClient::notify(const QJsonRpcMessage &message)
{
    Q_D(QJsonRpcHttpClient);
    if (d->endPoint.isEmpty()) {
        qJsonRpcDebug() << Q_FUNC_INFO << "invalid endpoint specified";
        return;
    }

    QNetworkReply *reply = d->writeMessage(message);
    connect(reply, SIGNAL(finished()), reply, SLOT(deleteLater()));

    // NOTE: we might want to connect this to a local slot to track errors
    //       for debugging later?
    connect(reply, SIGNAL(error(QNetworkReply::NetworkError)), reply, SLOT(deleteLater()));
}

QJsonRpcServiceReply *QJsonRpcHttpClient::sendMessage(const QJsonRpcMessage &message)
{
    Q_D(QJsonRpcHttpClient);
    if (d->endPoint.isEmpty()) {
        qJsonRpcDebug() << Q_FUNC_INFO << "invalid endpoint specified";
        return 0;
    }

    QNetworkReply *reply = d->writeMessage(message);
    return new QJsonRpcHttpReply(message, reply);
}

QJsonRpcMessage QJsonRpcHttpClient::sendMessageBlocking(const QJsonRpcMessage &message, int msecs)
{
    QJsonRpcServiceReply *reply = sendMessage(message);
    QScopedPointer<QJsonRpcServiceReply> replyPtr(reply);

    QEventLoop responseLoop;
    connect(reply, SIGNAL(finished()), &responseLoop, SLOT(quit()));
    QTimer::singleShot(msecs, &responseLoop, SLOT(quit()));
    responseLoop.exec();

    if (!reply->response().isValid())
        return message.createErrorResponse(QJsonRpc::TimeoutError, "request timed out");
    return reply->response();
}

void QJsonRpcHttpClient::handleAuthenticationRequired(QNetworkReply *reply, QAuthenticator *authenticator)
{
    Q_UNUSED(reply)
    Q_UNUSED(authenticator)
}

void QJsonRpcHttpClient::handleSslErrors(QNetworkReply *reply, const QList<QSslError> &errors)
{
    Q_UNUSED(errors)
    reply->ignoreSslErrors();
}

#include "qjsonrpchttpclient.moc"
<commit_msg>remove duplicate request member in QJsonRpcHttpReply<commit_after>/*
 * Copyright (C) 2012-2013 Matt Broadstone
 * Contact: http://bitbucket.org/devonit/qjsonrpc
 *
 * This file is part of the QJsonRpc Library.
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * 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.
 */
#include <QEventLoop>
#include <QTimer>
#include <QDebug>

#if QT_VERSION >= 0x050000
#include <QJsonDocument>
#else
#include "json/qjsondocument.h"
#endif

#include "qjsonrpcsocket_p.h"
#include "qjsonrpcservicereply_p.h"
#include "qjsonrpchttpclient.h"

class QJsonRpcHttpReplyPrivate : public QJsonRpcServiceReplyPrivate
{
public:
    QNetworkReply *reply;
};

class QJsonRpcHttpReply : public QJsonRpcServiceReply
{
    Q_OBJECT
public:
    QJsonRpcHttpReply(const QJsonRpcMessage &request,
                      QNetworkReply *reply, QObject *parent = 0)
        : QJsonRpcServiceReply(*new QJsonRpcHttpReplyPrivate, parent)
    {
        Q_D(QJsonRpcHttpReply);
        d->request = request;
        d->reply = reply;
        connect(d->reply, SIGNAL(finished()), this, SLOT(networkReplyFinished()));
        connect(d->reply, SIGNAL(error(QNetworkReply::NetworkError)),
                    this, SLOT(networkReplyError(QNetworkReply::NetworkError)));
    }

    virtual ~QJsonRpcHttpReply() {}

private Q_SLOTS:
    void networkReplyFinished()
    {
        Q_D(QJsonRpcHttpReply);
        QNetworkReply *reply = qobject_cast<QNetworkReply*>(sender());
        if (!reply) {
            qJsonRpcDebug() << Q_FUNC_INFO << "invalid reply";
            return;
        }

        if (reply->error() != QNetworkReply::NoError) {
            // this should be handled by the networkReplyError slot
        } else {
            QByteArray data = reply->readAll();
            QJsonDocument doc = QJsonDocument::fromJson(data);
            if (doc.isEmpty() || doc.isNull() || !doc.isObject()) {
                d->response =
                    d->request.createErrorResponse(QJsonRpc::ParseError,
                                                   "unable to process incoming JSON data",
                                                   QString::fromUtf8(data));
            } else {
                qJsonRpcDebug() << "received: " << doc.toJson();
                QJsonRpcMessage response = QJsonRpcMessage::fromObject(doc.object());
                if (d->request.type() == QJsonRpcMessage::Request &&
                    d->request.id() != response.id()) {
                    d->response =
                        d->request.createErrorResponse(QJsonRpc::InternalError,
                                                       "invalid response id",
                                                       QString::fromUtf8(data));
                } else {
                    d->response = response;
                }
            }
        }

        Q_EMIT finished();
    }

    void networkReplyError(QNetworkReply::NetworkError code)
    {
        Q_D(QJsonRpcHttpReply);
        QNetworkReply *reply = qobject_cast<QNetworkReply*>(sender());
        if (!reply) {
            qJsonRpcDebug() << Q_FUNC_INFO << "invalid reply";
            return;
        }

        if (code == QNetworkReply::NoError)
            return;

        d->response = d->request.createErrorResponse(QJsonRpc::InternalError,
                                       "error with http request",
                                       reply->errorString());
        Q_EMIT finished();
    }

private:
    Q_DISABLE_COPY(QJsonRpcHttpReply)
    Q_DECLARE_PRIVATE(QJsonRpcHttpReply)

};

class QJsonRpcHttpClientPrivate : public QJsonRpcAbstractSocketPrivate
{
public:
    void initializeNetworkAccessManager(QJsonRpcHttpClient *client) {
        QObject::connect(networkAccessManager, SIGNAL(authenticationRequired(QNetworkReply*,QAuthenticator*)),
                client, SLOT(handleAuthenticationRequired(QNetworkReply*,QAuthenticator*)));
        QObject::connect(networkAccessManager, SIGNAL(sslErrors(QNetworkReply*,QList<QSslError>)),
                client, SLOT(handleSslErrors(QNetworkReply*,QList<QSslError>)));
    }

    QNetworkReply *writeMessage(const QJsonRpcMessage &message) {
        QNetworkRequest request(endPoint);
        request.setHeader(QNetworkRequest::ContentTypeHeader, "application/json");
        request.setRawHeader("Accept", "application/json-rpc");
        if (!sslConfiguration.isNull())
            request.setSslConfiguration(sslConfiguration);

        QByteArray data = message.toJson();
        qJsonRpcDebug() << "sending: " << data;
        return networkAccessManager->post(request, data);
    }

    QUrl endPoint;
    QNetworkAccessManager *networkAccessManager;
    QSslConfiguration sslConfiguration;
};

QJsonRpcHttpClient::QJsonRpcHttpClient(QObject *parent)
    : QJsonRpcAbstractSocket(*new QJsonRpcHttpClientPrivate, parent)
{
    Q_D(QJsonRpcHttpClient);
    d->networkAccessManager = new QNetworkAccessManager(this);
    d->initializeNetworkAccessManager(this);
}

QJsonRpcHttpClient::QJsonRpcHttpClient(QNetworkAccessManager *manager, QObject *parent)
    : QJsonRpcAbstractSocket(*new QJsonRpcHttpClientPrivate, parent)
{
    Q_D(QJsonRpcHttpClient);
    d->networkAccessManager = manager;
    d->initializeNetworkAccessManager(this);
}

QJsonRpcHttpClient::QJsonRpcHttpClient(const QString &endPoint, QObject *parent)
    : QJsonRpcAbstractSocket(*new QJsonRpcHttpClientPrivate, parent)
{
    Q_D(QJsonRpcHttpClient);
    d->endPoint = QUrl::fromUserInput(endPoint);
    d->networkAccessManager = new QNetworkAccessManager(this);
    d->initializeNetworkAccessManager(this);
}

QJsonRpcHttpClient::~QJsonRpcHttpClient()
{
}

bool QJsonRpcHttpClient::isValid() const
{
    Q_D(const QJsonRpcHttpClient);
    return d->networkAccessManager && !d->endPoint.isEmpty() && d->endPoint.isValid();
}

QUrl QJsonRpcHttpClient::endPoint() const
{
    Q_D(const QJsonRpcHttpClient);
    return d->endPoint;
}

void QJsonRpcHttpClient::setEndPoint(const QUrl &endPoint)
{
    Q_D(QJsonRpcHttpClient);
    d->endPoint = endPoint;
}

void QJsonRpcHttpClient::setEndPoint(const QString &endPoint)
{
    Q_D(QJsonRpcHttpClient);
    d->endPoint = QUrl::fromUserInput(endPoint);
}

QSslConfiguration QJsonRpcHttpClient::sslConfiguration() const
{
    Q_D(const QJsonRpcHttpClient);
    return d->sslConfiguration;
}

void QJsonRpcHttpClient::setSslConfiguration(const QSslConfiguration &sslConfiguration)
{
    Q_D(QJsonRpcHttpClient);
    d->sslConfiguration = sslConfiguration;
}

QNetworkAccessManager *QJsonRpcHttpClient::networkAccessManager()
{
    Q_D(QJsonRpcHttpClient);
    return d->networkAccessManager;
}

void QJsonRpcHttpClient::notify(const QJsonRpcMessage &message)
{
    Q_D(QJsonRpcHttpClient);
    if (d->endPoint.isEmpty()) {
        qJsonRpcDebug() << Q_FUNC_INFO << "invalid endpoint specified";
        return;
    }

    QNetworkReply *reply = d->writeMessage(message);
    connect(reply, SIGNAL(finished()), reply, SLOT(deleteLater()));

    // NOTE: we might want to connect this to a local slot to track errors
    //       for debugging later?
    connect(reply, SIGNAL(error(QNetworkReply::NetworkError)), reply, SLOT(deleteLater()));
}

QJsonRpcServiceReply *QJsonRpcHttpClient::sendMessage(const QJsonRpcMessage &message)
{
    Q_D(QJsonRpcHttpClient);
    if (d->endPoint.isEmpty()) {
        qJsonRpcDebug() << Q_FUNC_INFO << "invalid endpoint specified";
        return 0;
    }

    QNetworkReply *reply = d->writeMessage(message);
    return new QJsonRpcHttpReply(message, reply);
}

QJsonRpcMessage QJsonRpcHttpClient::sendMessageBlocking(const QJsonRpcMessage &message, int msecs)
{
    QJsonRpcServiceReply *reply = sendMessage(message);
    QScopedPointer<QJsonRpcServiceReply> replyPtr(reply);

    QEventLoop responseLoop;
    connect(reply, SIGNAL(finished()), &responseLoop, SLOT(quit()));
    QTimer::singleShot(msecs, &responseLoop, SLOT(quit()));
    responseLoop.exec();

    if (!reply->response().isValid())
        return message.createErrorResponse(QJsonRpc::TimeoutError, "request timed out");
    return reply->response();
}

void QJsonRpcHttpClient::handleAuthenticationRequired(QNetworkReply *reply, QAuthenticator *authenticator)
{
    Q_UNUSED(reply)
    Q_UNUSED(authenticator)
}

void QJsonRpcHttpClient::handleSslErrors(QNetworkReply *reply, const QList<QSslError> &errors)
{
    Q_UNUSED(errors)
    reply->ignoreSslErrors();
}

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


<commit_before>#include <ecl/thread/semaphore.hpp>

#include <array>
#include <thread>
#include <atomic>
#include <algorithm>
#include <functional>

#include <CppUTest/TestHarness.h>
#include <CppUTest/CommandLineTestRunner.h>

// Error code helper
// TODO: move it to 'utils' headers and protect with check of
// current test state (enabled or disabled)
static SimpleString StringFrom(ecl::err err)
{
    return SimpleString{ecl::err_to_str(err)};
}

// Helpers
template< class Container, class Func >
static void test_for_each(Container &cont, Func fn)
{
    std::for_each(cont.begin(), cont.end(), fn);
}

static void test_delay(unsigned msecs = 1000)
{
    std::this_thread::sleep_for(std::chrono::milliseconds(msecs));
}

constexpr auto threads_count = 10;

TEST_GROUP(semaphore)
{
    void setup()
    {
    }

    void teardown()
    {
    }
};

TEST(semaphore, signal_wait_no_hang)
{
    // Should complete without a hang
    ecl::semaphore sem;
    sem.signal();
    sem.wait();
}

TEST(semaphore, try_wait)
{
    // Should complete without a hang
    ecl::semaphore sem;

    sem.signal();

    auto rc = sem.try_wait();
    CHECK_EQUAL(ecl::err::ok, rc);

    rc = sem.try_wait();
    CHECK_EQUAL(ecl::err::again, rc);

    rc = sem.try_wait();
    CHECK_EQUAL(ecl::err::again, rc);

    // Signal same semaphore again
    // to make sure counter is in valid state
    sem.signal();

    rc = sem.try_wait();
    CHECK_EQUAL(ecl::err::ok, rc);

    rc = sem.try_wait();
    CHECK_EQUAL(ecl::err::again, rc);
}

TEST(semaphore, one_semaphore_few_threads)
{
    // Preparation

    // Counts how many threads completed
    int counter = 0;
    // Counts how many signals sent
    int signalled = 0;

    // Semaphore itself
    ecl::semaphore semaphore;

    auto single_thread = [&counter, &semaphore]() {
        semaphore.wait();
        counter++;
    };

    std::array< std::thread, threads_count > threads;

    // Test itself

    // Start threads
    test_for_each(threads, [&single_thread](auto &thread) {
        thread = std::thread(single_thread);
    });

    // Let them wait on semaphore
    test_delay(20);
    // Threads are started and should wait for orders
    CHECK_EQUAL(0, counter);
    // Unblock threads one by one
    test_for_each(threads, [&](auto &thread) {
        (void) thread; // We don't need this
        semaphore.signal();
        signalled++;
        test_delay(50); // Let some thread finish its work
        CHECK_EQUAL(signalled, counter); // Check that only one thread is finished
    });

    // Wait for threads to finish
    test_for_each(threads, [](auto &thread) { thread.join(); });
}

TEST(semaphore, multiple_threads)
{
    // Preparation

    // Object associated with a thread
    struct test_object
    {
        ecl::semaphore      semaphore;
        std::thread         thread;
        volatile bool       flag;
    };

    std::array< test_object, threads_count > objs;

    auto single_thread = [](auto *obj) {
        obj->semaphore.wait();
        obj->flag = true; // Rise a flag only if semaphore signaled
    };

    // Test itself

    // Start threads
    test_for_each(objs, [&single_thread](auto &obj) {
        obj.flag = false;
        obj.thread = std::thread(single_thread, &obj);
    });

    // Let them wait on semaphore
    test_delay(100);
    // Threads are started and should wait for orders
    test_for_each(objs, [](auto &obj) { CHECK(!obj.flag); } );
    // Unblock threads
    test_for_each(objs, [](auto &obj) { obj.semaphore.signal(); });
    // Let threads do the work
    test_delay(100);
    // Check that work is done
    test_for_each(objs, [](auto &obj) { CHECK(obj.flag); });
    // Wait for threads to finish
    test_for_each(objs, [](auto &obj) { obj.thread.join(); });
}

int main(int argc, char *argv[])
{
    return CommandLineTestRunner::RunAllTests(argc, argv);
}
<commit_msg>Fix semaphore test by introducing increased delays<commit_after>#include <ecl/thread/semaphore.hpp>

#include <array>
#include <thread>
#include <atomic>
#include <algorithm>
#include <functional>

#include <CppUTest/TestHarness.h>
#include <CppUTest/CommandLineTestRunner.h>

// TODO: remove ugly sleep-programming

// Error code helper
// TODO: move it to 'utils' headers and protect with check of
// current test state (enabled or disabled)
static SimpleString StringFrom(ecl::err err)
{
    return SimpleString{ecl::err_to_str(err)};
}

// Helpers
template< class Container, class Func >
static void test_for_each(Container &cont, Func fn)
{
    std::for_each(cont.begin(), cont.end(), fn);
}

static void test_delay(unsigned msecs = 1000)
{
    std::this_thread::sleep_for(std::chrono::milliseconds(msecs));
}

constexpr auto threads_count = 10;

TEST_GROUP(semaphore)
{
    void setup()
    {
    }

    void teardown()
    {
    }
};

TEST(semaphore, signal_wait_no_hang)
{
    // Should complete without a hang
    ecl::semaphore sem;
    sem.signal();
    sem.wait();
}

TEST(semaphore, try_wait)
{
    // Should complete without a hang
    ecl::semaphore sem;

    sem.signal();

    auto rc = sem.try_wait();
    CHECK_EQUAL(ecl::err::ok, rc);

    rc = sem.try_wait();
    CHECK_EQUAL(ecl::err::again, rc);

    rc = sem.try_wait();
    CHECK_EQUAL(ecl::err::again, rc);

    // Signal same semaphore again
    // to make sure counter is in valid state
    sem.signal();

    rc = sem.try_wait();
    CHECK_EQUAL(ecl::err::ok, rc);

    rc = sem.try_wait();
    CHECK_EQUAL(ecl::err::again, rc);
}

TEST(semaphore, one_semaphore_few_threads)
{
    // Preparation

    // Counts how many threads completed
    int counter = 0;
    // Counts how many signals sent
    int signalled = 0;

    // Semaphore itself
    ecl::semaphore semaphore;

    auto single_thread = [&counter, &semaphore]() {
        semaphore.wait();
        counter++;
    };

    std::array< std::thread, threads_count > threads;

    // Test itself

    // Start threads
    test_for_each(threads, [&single_thread](auto &thread) {
        thread = std::thread(single_thread);
    });

    // Let them wait on semaphore
    test_delay(20);
    // Threads are started and should wait for orders
    CHECK_EQUAL(0, counter);
    // Unblock threads one by one
    test_for_each(threads, [&](auto &thread) {
        (void) thread; // We don't need this
        semaphore.signal();
        signalled++;
        test_delay(100); // Let some thread finish its work
        CHECK_EQUAL(signalled, counter); // Check that only one thread is finished
    });

    // Wait for threads to finish
    test_for_each(threads, [](auto &thread) { thread.join(); });
}

TEST(semaphore, multiple_threads)
{
    // Preparation

    // Object associated with a thread
    struct test_object
    {
        ecl::semaphore      semaphore;
        std::thread         thread;
        volatile bool       flag;
    };

    std::array< test_object, threads_count > objs;

    auto single_thread = [](auto *obj) {
        obj->semaphore.wait();
        obj->flag = true; // Rise a flag only if semaphore signaled
    };

    // Test itself

    // Start threads
    test_for_each(objs, [&single_thread](auto &obj) {
        obj.flag = false;
        obj.thread = std::thread(single_thread, &obj);
    });

    // Let them wait on semaphore
    test_delay(100);
    // Threads are started and should wait for orders
    test_for_each(objs, [](auto &obj) { CHECK(!obj.flag); } );
    // Unblock threads
    test_for_each(objs, [](auto &obj) { obj.semaphore.signal(); });
    // Let threads do the work
    test_delay(100);
    // Check that work is done
    test_for_each(objs, [](auto &obj) { CHECK(obj.flag); });
    // Wait for threads to finish
    test_for_each(objs, [](auto &obj) { obj.thread.join(); });
}

int main(int argc, char *argv[])
{
    return CommandLineTestRunner::RunAllTests(argc, argv);
}
<|endoftext|>