<commit_before>#include <ros/ros.h>
#include <nav_msgs/Odometry.h>
#include <tf/transform_broadcaster.h>
#include <math.h>
#include <boost/array.hpp>
#include <Eigen/LU>
#include "snowmower_localization/ekf.h"

// System update
void Ekf::systemUpdate(double dt){
  // Update the state estimate using x_p (the vector) and u
  double x = state_(0);
  double y = state_(1);
  double theta = state_(2);
  double v = state_(3);
  double omega = state_(4);

  // Update the State

  ////////////////////////////////////////////////////////////
  // First determine the correction factor. This is described in Wang 1988. The limit of cf as omega approaches 0 is 1. The following if statement protects against dividing by zero.
  double cf;
  if (omega == 0){
    cf = 1;
  }
  else{
    cf = sin(omega*dt/2)/(omega*dt/2);
  }

  // deltaX and deltaY are used a lot later. So, it makes sense to calculate them once now.
  double deltaX = cf*v*dt*cos(theta+omega*dt/2);
  double deltaY = cf*v*dt*sin(theta+omega*dt/2);
  double deltaTheta = omega*dt;

  x = x + deltaX;
  y = y + deltaY;
  theta = theta + deltaTheta;
  v = v;
  omega = omega;

  state_ << x, y, theta, v, omega;

  // Calculate F (using the updated state variables)
  double F13 =  -2*v*sin(omega*dt/2)*sin(omega*dt/2+theta)/omega;
  double F14 =   2 * sin(omega*dt/2)*cos(omega*dt/2+theta)/omega;
  double F23 =   2*v*sin(omega*dt/2)*cos(omega*dt/2+theta)/omega;
  double F24 =   2 * sin(omega*dt/2)*sin(omega*dt/2+theta)/omega;
  double F15 =  v*dt*cos(omega*dt/2)*cos(omega*dt/2+theta)/omega -
                 2*v*sin(omega*dt/2)*cos(omega*dt/2+theta)/pow(omega,2) -
	        v*dt*sin(omega*dt/2)*sin(omega*dt/2+theta)/omega;
  double F25 =  v*dt*sin(omega*dt/2)*cos(omega*dt/2+theta)/omega -
                 2*v*sin(omega*dt/2)*sin(omega*dt/2+theta)/pow(omega,2) -
	        v*dt*cos(omega*dt/2)*sin(omega*dt/2+theta)/omega;
  // And construct the final matrix
  MatrixXd F(5,5);
  F << 1,   0, F13, F14, F15,
       0,   1, F23, F24, F25,
       0,   0,   1,   0,  dt,
       0,   0,   0,   1,   0,
       0,   0,   0,   0,   1;

  cov_ = F*cov_*F.transpose() + Q_;
}

/***********************
 Equations for DecaWave
 1. h(x)
 2. measurement update
 3. callback function
***********************/

// 1. h(x)
Vector4d  Ekf::hDecaWave(Vector5d state) {
  double d1 = sqrt(pow(dw1x_-state(0),2)+pow(dw1y_-state(1),2));
  double d2 = sqrt(pow(dw2x_-state(0),2)+pow(dw2y_-state(1),2));
  double d3 = sqrt(pow(dw3x_-state(0),2)+pow(dw3y_-state(1),2));
  double d4 = sqrt(pow(dw4x_-state(0),2)+pow(dw4y_-state(1),2));
  Vector4d h;
  h << d1, d2, d3, d4;
  return h;
}

// 2. measurement update
void Ekf::measurementUpdateDecaWave(Vector4d z){
  double x = state_(0);
  double y = state_(1);

  // Calculate H
  double H11 = -pow(pow(dw1x_-x,2)+pow(dw1y_-y,2),-0.5)*(dw1x_-x);
  double H12 = -pow(pow(dw1x_-x,2)+pow(dw1y_-y,2),-0.5)*(dw1y_-y);
  double H21 = -pow(pow(dw2x_-x,2)+pow(dw2y_-y,2),-0.5)*(dw2x_-x);
  double H22 = -pow(pow(dw2x_-x,2)+pow(dw2y_-y,2),-0.5)*(dw2y_-y);
  double H31 = -pow(pow(dw3x_-x,2)+pow(dw3y_-y,2),-0.5)*(dw3x_-x);
  double H32 = -pow(pow(dw3x_-x,2)+pow(dw3y_-y,2),-0.5)*(dw3y_-y);
  double H41 = -pow(pow(dw4x_-x,2)+pow(dw4y_-y,2),-0.5)*(dw4x_-x);
  double H42 = -pow(pow(dw4x_-x,2)+pow(dw4y_-y,2),-0.5)*(dw4y_-y);

  MatrixXd H(4,5);
  H << H11, H12, 0, 0, 0,
       H21, H22, 0, 0, 0,
       H31, H32, 0, 0, 0,
       H41, H42, 0, 0, 0;

  // Find Kalman Gain
  MatrixXd K(5,4);
  K = cov_*H.transpose()*(H*cov_*H.transpose()+RDecaWave_).inverse();

  // Find new state
  state_ = state_ + K*(z - hDecaWave(state_));

  // Find new covariance
  cov_ = cov_ - K*H*cov_;
}

// 3. callback function
void Ekf::dwSubCB(const snowmower_msgs::DecaWaveMsg& msg){

}

/***********************
 Equations for Encoders
 1. h(x)
 2. measurement update
 3. callback function
***********************/

// 1. h(x)
Vector2d Ekf::hEnc(Vector5d state){
  Vector2d h;
  double h1 = state(3)+b_/2*state(4); // v+(b/2)*omega
  double h2 = state(3)-b_/2*state(4); // v-(b/2)*omega
  h << h1, h2;
  return h;
}

// 2. measurement update
void Ekf::measurementUpdateEncoders(Vector2d z){ // z is encL and encR
  // Calculate H
  double H15 = b_/2;
  double H25 = -b_/2;

  MatrixXd H(2,5);
  H << 0, 0, 0, 1, H15,
       0, 0, 0, 1, H25;

  // Find Kalman Gain
  MatrixXd K(5,2);
  K = cov_*H.transpose()*(H*cov_*H.transpose()+RDecaWave_).inverse();

  // Find new state
  state_ = state_ + K*(z - hEnc(state_));

  // Find new covariance
  cov_ = cov_ - K*H*cov_;
}

// 3. callback function
void Ekf::encSubCB(const snowmower_msgs::EncMsg& msg){

}

/***********************
 Equations for IMU
 1. h(x)
 2. measurement update
 3. callback function
***********************/

// 1. h(x)
double Ekf::hIMU(Vector5d state){
  return state(4); // return omega
}

void Ekf::measurementUpdateIMU(double z){ // z is omega_z

  MatrixXd H(1,5);
  H << 0, 0, 0, 0, 1;
  // Find Kalman Gain
  MatrixXd K(5,1);
  // Must create a 1x1 matrix container for the double RIMU_
  MatrixXd R(1,1);
  R << RIMU_;
  K = cov_*H.transpose()*(H*cov_*H.transpose()+R).inverse();

  // Find new state
  state_ = state_ + K*(z - hIMU(state_));

  // Find new covariance
  cov_ = cov_ - K*H*cov_;
}

void Ekf::imuSubCB(const sensor_msgs::Imu& msg){

}

  // Determine time since the last time dt() was called.
double Ekf::dt(){
  ros::Duration dt;
  ros::Time currentTime = ros::Time::now();
  dt = currentTime - lastTime_;
  lastTime_ = currentTime;
  return dt.toSec();
}

  // Publish the state as an odom message on the topic odom_ekf. Alos well broadcast a transform.
void Ekf::publishState(){
  // Create an Odometry message to publish
  nav_msgs::Odometry state_msg;

  // Populate timestamp, position frame, and velocity frame
  state_msg.header.stamp = ros::Time::now();
  state_msg.header.frame_id = "map";
  state_msg.child_frame_id = "base_link";

  // Populate the position and orientation
  state_msg.pose.pose.position.x = state_(0); // x
  state_msg.pose.pose.position.y = state_(1); // y
  state_msg.pose.pose.orientation = tf::createQuaternionMsgFromYaw(state_(2)); // theta

  boost::array<double,36> temp;
  // Populate the covariance matrix
  state_msg.pose.covariance = temp;

  // Populate the linear and angular velocities
  state_msg.twist.twist.linear.x = state_(3); // v
  state_msg.twist.twist.angular.z = state_(4); // omega

  // Populate the covariance matrix
  state_msg.twist.covariance = temp;

  // Publish the message!
  statePub_.publish(state_msg);

  // Now for the transform

}

void Ekf::init(){
  // System Model Covariance Matrix
  Q_ << 0.01, 0,    0,    0,    0,
        0,    0.01, 0,    0,    0,
        0,    0,    0.01, 0,    0,
        0,    0,    0,    0.01, 0,
        0,    0,    0,    0,    0.01;

  // Decawave Beacon Locations (in meters)
  dw1x_ = 0;
  dw1y_ = 0;
  dw2x_ = 5;
  dw2y_ = 0;
  dw3x_ = 5;
  dw3y_ = 15;
  dw4x_ = 0;
  dw4y_ = 15;
  // Decawave Covariance Matrix
  RDecaWave_ << 0.1, 0.0, 0.0, 0.0,
                0.0, 0.1, 0.0, 0.0,
                0.0, 0.0, 0.1, 0.0,
                0.0, 0.0, 0.0, 0.1;

  // IMU Covariance "Matrix"
  RIMU_ = .01;

  // Wheel Track Width (in meteres)
  b_ = .7;
  // Encoder ticks per revolutions (left and right)
  tpmRight_ = 50000;
  tpmLeft_  = 50000;

  // Initialize lastTime_
  // State should also be initialized
  lastTime_ = ros::Time::now();
}

/* Constructor */
Ekf::Ekf(): private_nh_("~") {

  // Create a publisher object to publish the determined state of the robot. Odometry messages contain both Pose and Twist with covariance. In this simulator, we will not worry about the covariance.
  statePub_ = public_nh_.advertise<nav_msgs::Odometry>("odom_ekf",1);

  // Create a subscriber object to subscribe to the topic
  dwSub_ = public_nh_.subscribe("dw_beacons",1,&Ekf::dwSubCB,this);
  imuSub_ = public_nh_.subscribe("imu/data",1,&Ekf::imuSubCB,this);
  encSub_ = public_nh_.subscribe("enc",1,&Ekf::encSubCB,this);

  init();
};

/* Destructor */
Ekf::~Ekf() {

};

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

  //Initialize ROS
  ros::init(argc, argv, "ekf");

  // Create an EKF object
  Ekf ekf;

  ros::spin();

  return 0;
}
<commit_msg>Made time an argument of Ekf::dt() so that measurement time can be passed.<commit_after>#include <ros/ros.h>
#include <nav_msgs/Odometry.h>
#include <tf/transform_broadcaster.h>
#include <math.h>
#include <boost/array.hpp>
#include <Eigen/LU>
#include "snowmower_localization/ekf.h"

// System update
void Ekf::systemUpdate(double dt){
  // Update the state estimate using x_p (the vector) and u
  double x = state_(0);
  double y = state_(1);
  double theta = state_(2);
  double v = state_(3);
  double omega = state_(4);

  // Update the State

  ////////////////////////////////////////////////////////////
  // First determine the correction factor. This is described in Wang 1988. The limit of cf as omega approaches 0 is 1. The following if statement protects against dividing by zero.
  double cf;
  if (omega == 0){
    cf = 1;
  }
  else{
    cf = sin(omega*dt/2)/(omega*dt/2);
  }

  // deltaX and deltaY are used a lot later. So, it makes sense to calculate them once now.
  double deltaX = cf*v*dt*cos(theta+omega*dt/2);
  double deltaY = cf*v*dt*sin(theta+omega*dt/2);
  double deltaTheta = omega*dt;

  x = x + deltaX;
  y = y + deltaY;
  theta = theta + deltaTheta;
  v = v;
  omega = omega;

  state_ << x, y, theta, v, omega;

  // Calculate F (using the updated state variables)
  double F13 =  -2*v*sin(omega*dt/2)*sin(omega*dt/2+theta)/omega;
  double F14 =   2 * sin(omega*dt/2)*cos(omega*dt/2+theta)/omega;
  double F23 =   2*v*sin(omega*dt/2)*cos(omega*dt/2+theta)/omega;
  double F24 =   2 * sin(omega*dt/2)*sin(omega*dt/2+theta)/omega;
  double F15 =  v*dt*cos(omega*dt/2)*cos(omega*dt/2+theta)/omega -
                 2*v*sin(omega*dt/2)*cos(omega*dt/2+theta)/pow(omega,2) -
	        v*dt*sin(omega*dt/2)*sin(omega*dt/2+theta)/omega;
  double F25 =  v*dt*sin(omega*dt/2)*cos(omega*dt/2+theta)/omega -
                 2*v*sin(omega*dt/2)*sin(omega*dt/2+theta)/pow(omega,2) -
	        v*dt*cos(omega*dt/2)*sin(omega*dt/2+theta)/omega;
  // And construct the final matrix
  MatrixXd F(5,5);
  F << 1,   0, F13, F14, F15,
       0,   1, F23, F24, F25,
       0,   0,   1,   0,  dt,
       0,   0,   0,   1,   0,
       0,   0,   0,   0,   1;

  cov_ = F*cov_*F.transpose() + Q_;
}

/***********************
 Equations for DecaWave
 1. h(x)
 2. measurement update
 3. callback function
***********************/

// 1. h(x)
Vector4d  Ekf::hDecaWave(Vector5d state) {
  double d1 = sqrt(pow(dw1x_-state(0),2)+pow(dw1y_-state(1),2));
  double d2 = sqrt(pow(dw2x_-state(0),2)+pow(dw2y_-state(1),2));
  double d3 = sqrt(pow(dw3x_-state(0),2)+pow(dw3y_-state(1),2));
  double d4 = sqrt(pow(dw4x_-state(0),2)+pow(dw4y_-state(1),2));
  Vector4d h;
  h << d1, d2, d3, d4;
  return h;
}

// 2. measurement update
void Ekf::measurementUpdateDecaWave(Vector4d z){
  double x = state_(0);
  double y = state_(1);

  // Calculate H
  double H11 = -pow(pow(dw1x_-x,2)+pow(dw1y_-y,2),-0.5)*(dw1x_-x);
  double H12 = -pow(pow(dw1x_-x,2)+pow(dw1y_-y,2),-0.5)*(dw1y_-y);
  double H21 = -pow(pow(dw2x_-x,2)+pow(dw2y_-y,2),-0.5)*(dw2x_-x);
  double H22 = -pow(pow(dw2x_-x,2)+pow(dw2y_-y,2),-0.5)*(dw2y_-y);
  double H31 = -pow(pow(dw3x_-x,2)+pow(dw3y_-y,2),-0.5)*(dw3x_-x);
  double H32 = -pow(pow(dw3x_-x,2)+pow(dw3y_-y,2),-0.5)*(dw3y_-y);
  double H41 = -pow(pow(dw4x_-x,2)+pow(dw4y_-y,2),-0.5)*(dw4x_-x);
  double H42 = -pow(pow(dw4x_-x,2)+pow(dw4y_-y,2),-0.5)*(dw4y_-y);

  MatrixXd H(4,5);
  H << H11, H12, 0, 0, 0,
       H21, H22, 0, 0, 0,
       H31, H32, 0, 0, 0,
       H41, H42, 0, 0, 0;

  // Find Kalman Gain
  MatrixXd K(5,4);
  K = cov_*H.transpose()*(H*cov_*H.transpose()+RDecaWave_).inverse();

  // Find new state
  state_ = state_ + K*(z - hDecaWave(state_));

  // Find new covariance
  cov_ = cov_ - K*H*cov_;
}

// 3. callback function
void Ekf::dwSubCB(const snowmower_msgs::DecaWaveMsg& msg){

}

/***********************
 Equations for Encoders
 1. h(x)
 2. measurement update
 3. callback function
***********************/

// 1. h(x)
Vector2d Ekf::hEnc(Vector5d state){
  Vector2d h;
  double h1 = state(3)+b_/2*state(4); // v+(b/2)*omega
  double h2 = state(3)-b_/2*state(4); // v-(b/2)*omega
  h << h1, h2;
  return h;
}

// 2. measurement update
void Ekf::measurementUpdateEncoders(Vector2d z){ // z is encL and encR
  // Calculate H
  double H15 = b_/2;
  double H25 = -b_/2;

  MatrixXd H(2,5);
  H << 0, 0, 0, 1, H15,
       0, 0, 0, 1, H25;

  // Find Kalman Gain
  MatrixXd K(5,2);
  K = cov_*H.transpose()*(H*cov_*H.transpose()+RDecaWave_).inverse();

  // Find new state
  state_ = state_ + K*(z - hEnc(state_));

  // Find new covariance
  cov_ = cov_ - K*H*cov_;
}

// 3. callback function
void Ekf::encSubCB(const snowmower_msgs::EncMsg& msg){

}

/***********************
 Equations for IMU
 1. h(x)
 2. measurement update
 3. callback function
***********************/

// 1. h(x)
double Ekf::hIMU(Vector5d state){
  return state(4); // return omega
}

void Ekf::measurementUpdateIMU(double z){ // z is omega_z

  MatrixXd H(1,5);
  H << 0, 0, 0, 0, 1;
  // Find Kalman Gain
  MatrixXd K(5,1);
  // Must create a 1x1 matrix container for the double RIMU_
  MatrixXd R(1,1);
  R << RIMU_;
  K = cov_*H.transpose()*(H*cov_*H.transpose()+R).inverse();

  // Find new state
  state_ = state_ + K*(z - hIMU(state_));

  // Find new covariance
  cov_ = cov_ - K*H*cov_;
}

void Ekf::imuSubCB(const sensor_msgs::Imu& msg){

}

  // Determine time since the last time dt() was called.
double Ekf::dt(ros::Time currentTime){
  ros::Duration dt;
  dt = currentTime - lastTime_;
  lastTime_ = currentTime;
  return dt.toSec();
}

  // Publish the state as an odom message on the topic odom_ekf. Alos well broadcast a transform.
void Ekf::publishState(){
  // Create an Odometry message to publish
  nav_msgs::Odometry state_msg;

  // Populate timestamp, position frame, and velocity frame
  state_msg.header.stamp = ros::Time::now();
  state_msg.header.frame_id = "map";
  state_msg.child_frame_id = "base_link";

  // Populate the position and orientation
  state_msg.pose.pose.position.x = state_(0); // x
  state_msg.pose.pose.position.y = state_(1); // y
  state_msg.pose.pose.orientation = tf::createQuaternionMsgFromYaw(state_(2)); // theta

  boost::array<double,36> temp;
  // Populate the covariance matrix
  state_msg.pose.covariance = temp;

  // Populate the linear and angular velocities
  state_msg.twist.twist.linear.x = state_(3); // v
  state_msg.twist.twist.angular.z = state_(4); // omega

  // Populate the covariance matrix
  state_msg.twist.covariance = temp;

  // Publish the message!
  statePub_.publish(state_msg);

  // Now for the transform

}

void Ekf::init(){
  // System Model Covariance Matrix
  Q_ << 0.01, 0,    0,    0,    0,
        0,    0.01, 0,    0,    0,
        0,    0,    0.01, 0,    0,
        0,    0,    0,    0.01, 0,
        0,    0,    0,    0,    0.01;

  // Decawave Beacon Locations (in meters)
  dw1x_ = 0;
  dw1y_ = 0;
  dw2x_ = 5;
  dw2y_ = 0;
  dw3x_ = 5;
  dw3y_ = 15;
  dw4x_ = 0;
  dw4y_ = 15;
  // Decawave Covariance Matrix
  RDecaWave_ << 0.1, 0.0, 0.0, 0.0,
                0.0, 0.1, 0.0, 0.0,
                0.0, 0.0, 0.1, 0.0,
                0.0, 0.0, 0.0, 0.1;

  // IMU Covariance "Matrix"
  RIMU_ = .01;

  // Wheel Track Width (in meteres)
  b_ = .7;
  // Encoder ticks per revolutions (left and right)
  tpmRight_ = 50000;
  tpmLeft_  = 50000;

  // Initialize lastTime_
  // State should also be initialized
  lastTime_ = ros::Time::now();
}

/* Constructor */
Ekf::Ekf(): private_nh_("~") {

  // Create a publisher object to publish the determined state of the robot. Odometry messages contain both Pose and Twist with covariance. In this simulator, we will not worry about the covariance.
  statePub_ = public_nh_.advertise<nav_msgs::Odometry>("odom_ekf",1);

  // Create a subscriber object to subscribe to the topic
  dwSub_ = public_nh_.subscribe("dw_beacons",1,&Ekf::dwSubCB,this);
  imuSub_ = public_nh_.subscribe("imu/data",1,&Ekf::imuSubCB,this);
  encSub_ = public_nh_.subscribe("enc",1,&Ekf::encSubCB,this);

  init();
};

/* Destructor */
Ekf::~Ekf() {

};

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

  //Initialize ROS
  ros::init(argc, argv, "ekf");

  // Create an EKF object
  Ekf ekf;

  ros::spin();

  return 0;
}
<|endoftext|>


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

  Library: CppMicroServices

  Copyright (c) German Cancer Research Center,
    Division of Medical and Biological Informatics

  Licensed under the Apache License, Version 2.0 (the "License");
  you may not use this file except in compliance with the License.
  You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

  Unless required by applicable law or agreed to in writing, software
  distributed under the License is distributed on an "AS IS" BASIS,
  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  See the License for the specific language governing permissions and
  limitations under the License.

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

#include "usModuleResource.h"

#include "usAtomicInt_p.h"
#include "usModuleResourceTree_p.h"

#include <string>

US_BEGIN_NAMESPACE

class ModuleResourcePrivate
{

public:

  ModuleResourcePrivate()
    : resourceTree(NULL)
    , node(-1)
    , size(0)
    , data(NULL)
    , isFile(false)
    , ref(1)
  {}

  std::string fileName;
  std::string path;
  std::string filePath;

  ModuleResourceTree* resourceTree;

  int node;
  int32_t size;
  const unsigned char* data;

  mutable std::vector<std::string> children;

  bool isFile;

  /**
   * Reference count for implicitly shared private implementation.
   */
  AtomicInt ref;
};

ModuleResource::ModuleResource()
  : d(new ModuleResourcePrivate)
{
}

ModuleResource::ModuleResource(const ModuleResource &resource)
  : d(resource.d)
{
  d->ref.Ref();
}

ModuleResource::ModuleResource(const std::string& _file, ModuleResourceTree* resourceTree)
  : d(new ModuleResourcePrivate)
{
  d->resourceTree = resourceTree;

  std::string file = _file;
  if (file.empty()) file = "/";
  if (file[0] != '/') file = std::string("/") + file;

  std::size_t index = file.find_last_of('/');
  if (index < file.size()-1)
  {
    d->fileName = file.substr(index+1);
  }
  std::string rawPath = file.substr(0,index+1);

  // remove duplicate /
  std::string::value_type lastChar = 0;
  for (std::size_t i = 0; i < rawPath.size(); ++i)
  {
    if (rawPath[i] == '/' && lastChar == '/')
    {
      continue;
    }
    lastChar = rawPath[i];
    d->path.push_back(lastChar);
  }

  d->filePath = d->path + d->fileName;

  d->node = d->resourceTree->FindNode(GetFilePath());
  if (d->node != -1)
  {
    d->isFile = !resourceTree->IsDir(d->node);
    if (d->isFile)
    {
      d->data = d->resourceTree->GetData(d->node, &d->size);
    }
  }
}

ModuleResource::~ModuleResource()
{
  if (!d->ref.Deref())
    delete d;
}

ModuleResource& ModuleResource::operator =(const ModuleResource& resource)
{
  ModuleResourcePrivate* curr_d = d;
  d = resource.d;
  d->ref.Ref();

  if (!curr_d->ref.Deref())
    delete curr_d;

  return *this;
}

bool ModuleResource::operator <(const ModuleResource& resource) const
{
  return this->GetFilePath() < resource.GetFilePath();
}

bool ModuleResource::operator ==(const ModuleResource& resource) const
{
  return this->GetFilePath() == resource.GetFilePath();
}

bool ModuleResource::operator !=(const ModuleResource &resource) const
{
  return !(*this == resource);
}

bool ModuleResource::IsValid() const
{
  return d->resourceTree->IsValid() && d->node > -1;
}

us::ModuleResource::operator bool() const
{
  return IsValid();
}

std::string ModuleResource::GetFileName() const
{
  return d->fileName;
}

std::string ModuleResource::GetPath() const
{
  return d->path;
}

std::string ModuleResource::GetFilePath() const
{
  return d->filePath;
}

std::string ModuleResource::GetBaseName() const
{
  return d->fileName.substr(0, d->fileName.find_first_of('.'));
}

std::string ModuleResource::GetCompleteBaseName() const
{
  return d->fileName.substr(0, d->fileName.find_last_of('.'));
}

std::string ModuleResource::GetSuffix() const
{
  std::size_t index = d->fileName.find_last_of('.');
  return index < d->fileName.size()-1 ? d->fileName.substr(index+1) : std::string("");
}

bool ModuleResource::IsDir() const
{
  return !d->isFile;
}

bool ModuleResource::IsFile() const
{
  return d->isFile;
}

std::vector<std::string> ModuleResource::GetChildren() const
{
  if (d->isFile || !IsValid()) return d->children;

  if (!d->children.empty()) return d->children;

  d->resourceTree->GetChildren(d->node, d->children);
  return d->children;
}

int ModuleResource::GetSize() const
{
  return d->size;
}

const unsigned char* ModuleResource::GetData() const
{
  if (!IsValid()) return NULL;
  return d->data;
}

std::size_t ModuleResource::Hash() const
{
  using namespace US_HASH_FUNCTION_NAMESPACE;
  return US_HASH_FUNCTION(std::string, this->GetFilePath());
}

US_END_NAMESPACE

US_USE_NAMESPACE

std::ostream& operator<<(std::ostream& os, const ModuleResource& resource)
{
  return os << resource.GetFilePath();
}
<commit_msg>Removed superfluous namespace prefix.<commit_after>/*=============================================================================

  Library: CppMicroServices

  Copyright (c) German Cancer Research Center,
    Division of Medical and Biological Informatics

  Licensed under the Apache License, Version 2.0 (the "License");
  you may not use this file except in compliance with the License.
  You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

  Unless required by applicable law or agreed to in writing, software
  distributed under the License is distributed on an "AS IS" BASIS,
  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  See the License for the specific language governing permissions and
  limitations under the License.

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

#include "usModuleResource.h"

#include "usAtomicInt_p.h"
#include "usModuleResourceTree_p.h"

#include <string>

US_BEGIN_NAMESPACE

class ModuleResourcePrivate
{

public:

  ModuleResourcePrivate()
    : resourceTree(NULL)
    , node(-1)
    , size(0)
    , data(NULL)
    , isFile(false)
    , ref(1)
  {}

  std::string fileName;
  std::string path;
  std::string filePath;

  ModuleResourceTree* resourceTree;

  int node;
  int32_t size;
  const unsigned char* data;

  mutable std::vector<std::string> children;

  bool isFile;

  /**
   * Reference count for implicitly shared private implementation.
   */
  AtomicInt ref;
};

ModuleResource::ModuleResource()
  : d(new ModuleResourcePrivate)
{
}

ModuleResource::ModuleResource(const ModuleResource &resource)
  : d(resource.d)
{
  d->ref.Ref();
}

ModuleResource::ModuleResource(const std::string& _file, ModuleResourceTree* resourceTree)
  : d(new ModuleResourcePrivate)
{
  d->resourceTree = resourceTree;

  std::string file = _file;
  if (file.empty()) file = "/";
  if (file[0] != '/') file = std::string("/") + file;

  std::size_t index = file.find_last_of('/');
  if (index < file.size()-1)
  {
    d->fileName = file.substr(index+1);
  }
  std::string rawPath = file.substr(0,index+1);

  // remove duplicate /
  std::string::value_type lastChar = 0;
  for (std::size_t i = 0; i < rawPath.size(); ++i)
  {
    if (rawPath[i] == '/' && lastChar == '/')
    {
      continue;
    }
    lastChar = rawPath[i];
    d->path.push_back(lastChar);
  }

  d->filePath = d->path + d->fileName;

  d->node = d->resourceTree->FindNode(GetFilePath());
  if (d->node != -1)
  {
    d->isFile = !resourceTree->IsDir(d->node);
    if (d->isFile)
    {
      d->data = d->resourceTree->GetData(d->node, &d->size);
    }
  }
}

ModuleResource::~ModuleResource()
{
  if (!d->ref.Deref())
    delete d;
}

ModuleResource& ModuleResource::operator =(const ModuleResource& resource)
{
  ModuleResourcePrivate* curr_d = d;
  d = resource.d;
  d->ref.Ref();

  if (!curr_d->ref.Deref())
    delete curr_d;

  return *this;
}

bool ModuleResource::operator <(const ModuleResource& resource) const
{
  return this->GetFilePath() < resource.GetFilePath();
}

bool ModuleResource::operator ==(const ModuleResource& resource) const
{
  return this->GetFilePath() == resource.GetFilePath();
}

bool ModuleResource::operator !=(const ModuleResource &resource) const
{
  return !(*this == resource);
}

bool ModuleResource::IsValid() const
{
  return d->resourceTree->IsValid() && d->node > -1;
}

ModuleResource::operator bool() const
{
  return IsValid();
}

std::string ModuleResource::GetFileName() const
{
  return d->fileName;
}

std::string ModuleResource::GetPath() const
{
  return d->path;
}

std::string ModuleResource::GetFilePath() const
{
  return d->filePath;
}

std::string ModuleResource::GetBaseName() const
{
  return d->fileName.substr(0, d->fileName.find_first_of('.'));
}

std::string ModuleResource::GetCompleteBaseName() const
{
  return d->fileName.substr(0, d->fileName.find_last_of('.'));
}

std::string ModuleResource::GetSuffix() const
{
  std::size_t index = d->fileName.find_last_of('.');
  return index < d->fileName.size()-1 ? d->fileName.substr(index+1) : std::string("");
}

bool ModuleResource::IsDir() const
{
  return !d->isFile;
}

bool ModuleResource::IsFile() const
{
  return d->isFile;
}

std::vector<std::string> ModuleResource::GetChildren() const
{
  if (d->isFile || !IsValid()) return d->children;

  if (!d->children.empty()) return d->children;

  d->resourceTree->GetChildren(d->node, d->children);
  return d->children;
}

int ModuleResource::GetSize() const
{
  return d->size;
}

const unsigned char* ModuleResource::GetData() const
{
  if (!IsValid()) return NULL;
  return d->data;
}

std::size_t ModuleResource::Hash() const
{
  using namespace US_HASH_FUNCTION_NAMESPACE;
  return US_HASH_FUNCTION(std::string, this->GetFilePath());
}

US_END_NAMESPACE

US_USE_NAMESPACE

std::ostream& operator<<(std::ostream& os, const ModuleResource& resource)
{
  return os << resource.GetFilePath();
}
<|endoftext|>


<commit_before>#include "LocalSearchPathFinder.hpp"
#include "GreedyPathFinder.hpp"
#include <queue>
#include <iostream>
#include <limits>
#include "Types.hpp"

using namespace FireflyAssembler;
using namespace std;

PathPointer LocalSearchPathFinder::findPath(IGraphConstPointer graph,
        FitnessFunctionPointer ff)
{
    if (graph->sequenceCount() == 1)
    {
        vector<int> path(1);
        path.push_back(0);
        PathPointer returned(new Path(graph, path));
        return returned;
    }
    else
    {
        PathFinderPointer greedy(new GreedyPathFinder());
        PathPointer initial = greedy->findPath(graph,ff);
        vector<int> triedPath(graph->sequenceCount());
        for (int i = 0; i < graph->sequenceCount(); i++)
        {
            triedPath.push_back((*initial)[i]);
        }

        double currentScore = ff->rate(Path(graph, triedPath));
        double bestScore = -numeric_limits<double>::infinity();
        while (currentScore > bestScore)
        {
            bestScore = currentScore;
            bool found = false;
            for (int i = 0; i < graph->sequenceCount(); i++)
            {
                for (int j = i + 1; j < graph->sequenceCount(); j++)
                {
                    int tmp = triedPath[i];
                    triedPath[i] = triedPath[j];
                    triedPath[j] = tmp;
                    double score = ff->rate(Path(graph,triedPath));
                    if (score > currentScore)
                    {
                        found = true;
                        currentScore = score;
                        break;
                    }
                    triedPath[j] = triedPath[i];
                    triedPath[i] = tmp;
                }
                if (found)
                {
                    break;
                }
            }
        }
        return PathPointer(new Path(graph, triedPath));
    }
}

<commit_msg>Fix bug with LocalSearch.<commit_after>#include "LocalSearchPathFinder.hpp"
#include "GreedyPathFinder.hpp"
#include <queue>
#include <iostream>
#include <limits>
#include "Types.hpp"

using namespace FireflyAssembler;
using namespace std;

PathPointer LocalSearchPathFinder::findPath(IGraphConstPointer graph,
        FitnessFunctionPointer ff)
{
    if (graph->sequenceCount() == 1)
    {
        vector<int> path(1);
        path.push_back(0);
        PathPointer returned(new Path(graph, path));
        return returned;
    }
    else
    {
        PathFinderPointer greedy(new GreedyPathFinder());
        PathPointer initial = greedy->findPath(graph,ff);
        vector<int> triedPath;
        for (int i = 0; i < graph->sequenceCount(); i++)
        {
            triedPath.push_back((*initial)[i]);
        }
        cout << "Graph size: " << graph->sequenceCount() << endl;
        cout << "path size: " << triedPath.size() << endl;

        double currentScore = ff->rate(Path(graph, triedPath));
        double bestScore = -numeric_limits<double>::infinity();
        while (currentScore > bestScore)
        {
            bestScore = currentScore;
            bool found = false;
            for (int i = 0; i < graph->sequenceCount(); i++)
            {
                for (int j = i + 1; j < graph->sequenceCount(); j++)
                {
                    int tmp = triedPath[i];
                    triedPath[i] = triedPath[j];
                    triedPath[j] = tmp;
                    double score = ff->rate(Path(graph,triedPath));
                    if (score > currentScore)
                    {
                        found = true;
                        currentScore = score;
                        break;
                    }
                    triedPath[j] = triedPath[i];
                    triedPath[i] = tmp;
                }
                if (found)
                {
                    break;
                }
            }
        }
        return PathPointer(new Path(graph, triedPath));
    }
}

<|endoftext|>


<commit_before>#ifndef GAMELIB_DATASET_HPP
#define GAMELIB_DATASET_HPP

#include <string>
#include <unordered_map>

/*
 * A collection to store a set of data (duh).
 * There's currently no custom implementation because a custom implementation
 * would mostly be a wrapper around std::unordered_map.
 * Instead of directly using std::unordered_map wherever a data set is required,
 * this DataSet alias should be used instead to make it easier to switch to
 * a custom implementation later (if there will ever be one).
 *
 * A DataSet must be std map-like, that means it must...:
 *  - be iterable (std compatible) and therefore...
 *  - have begin() and end() functions that return an (const) iterator to a
 *    std::pair containing the key and value.
 *  - have a size() function
 *  - have a find() function that takes a key as parameter and returns
 *    an (const) iterator to the key-value pair and end() if it doesn't exist.
 */

namespace gamelib
{
    typedef std::string DataSetKey;

    template <class T>
    using DataSet = std::unordered_map<DataSetKey, T>;

    // template <class T>
    // class DataSet : private std::unordered_map<DataSetKey, T>
    // {
    //     typedef std::unordered_map<DataSetKey, T> Map;
    //
    //     public:
    //         using Map::find;
    //         using Map::size;
    //         using Map::operator[];
    //         using Map::begin;
    //         using Map::end;
    // };
}

#endif
<commit_msg>Implement (a) DataSet base class(es)<commit_after>#ifndef GAMELIB_DATASET_HPP
#define GAMELIB_DATASET_HPP

#include <string>
#include <unordered_map>
#include "utils/JsonObject.hpp"
#include "utils/log.hpp"

/*
 * A collection to store a set of data (duh).
 *
 * This is the implementation for a basic dataset and should work in most
 * cases. It's mostly a wrapper around std::unordered_map (using private
 * inheritance) and optionally extends it with functions to load from json
 * (by inheriting from JsonObject).
 * See further down for more information to the different DataSet types.
 *
 * Classes that require a dataset, for example StaticDataSetTilemap, should
 * take a template argument as dataset type rather than using DataSet
 * directly. This is because there might be different kinds of datasets,
 * e.g. SpriteSet, and forcing a specific type would lead to unneccessary
 * inheritance trouble/overhead or code repetition when a derived class
 * needs a specific type of dataset.
 *
 * For example, StaticRenderTilemap requires a SpriteSet. Using DataSet
 * directly in the underlying StaticDataSetTilemap instead of specifying
 * the type as template argument, would make it (more) difficult to use it
 * as a base for StaticRenderTilemap, because it would require rewriting
 * all dataset related functions to only allow SpriteSets.
 *
 * To avoid different interpretations of a dataset, these are the
 * requirements for a dataset class:
 *
 * A DataSet must be std map-like, that means it must...:
 *  - be iterable (std compatible) and therefore...
 *  - have begin() and end() functions that return an (const) iterator to a
 *    std::pair containing the key and value.
 *  - have a size() function
 *  - have a find() function that takes a key as parameter and returns
 *    an (const) iterator to the key-value pair and end() if it doesn't exist.
 *  - have a [] operator, taking a key and returning a reference to the
 *    object stored at the given key. If it doesn't exist, it is created.
 */

namespace gamelib
{
    typedef std::string DataSetKey;

    template <class T>
    using DataSetCallback = bool(*)(const Json::Value&, T&);

    /*
     * The base class for datasets.
     * It's basically a wrapper around std::unordered_map.
     */
    template <class T>
    class DataSet : protected std::unordered_map<DataSetKey, T>
    {
        typedef std::unordered_map<DataSetKey, T> Map;

        public:
            using Map::find;
            using Map::size;
            using Map::operator[];
            using Map::begin;
            using Map::end;

            using typename Map::iterator;
            using typename Map::const_iterator;
            using typename Map::difference_type;
            using typename Map::size_type;
            using typename Map::value_type;
            using typename Map::key_type;
            using typename Map::pointer;
            using typename Map::reference;

        public:
            virtual ~DataSet() {}
            virtual void destroy()
            {
                this->clear();
                LOG_DEBUG_WARN("DataSet destroyed");
            }
    };

    /*
     * A DataSet with json functionality.
     * It takes a type T and a function F as template arguments. T is the
     * data type to store and F is a function that takes a Json::Value aswell
     * as a T reference as parameters and returns a bool.
     * When loadFromJson is called, it will iterate trough all key-value pairs
     * inside the "objects" node and invoke F with the current value. Its job
     * is to fill the given T& with the corresponding values from the json
     * node and return whether it was successful or not.
     * In case F returns false, the value is not added and a warning message
     * is printed.
     *
     * Json structure:
     * Note that only values inside "objects" are read!
     * <value> will be passed to the callback function and can therefore be
     * any json type (array, dict, string, int, ...).
     * {
     *     "objects": {
     *         <objectname>: <value>,
     *         ...
     *     }
     * }
     */

    template <class T>
    class JsonDataSet : public DataSet<T>, public Json::JsonObject
    {
        public:
            JsonDataSet(DataSetCallback<T> callback) : _callback(callback) {}
            virtual ~JsonDataSet() {}

            virtual bool loadFromJson(const Json::Value& node)
            {
                this->clear();

                if (!node.isMember("objects"))
                {
                    LOG_ERROR("No objects specified");
                    return false;
                }

                auto& objs = node["objects"];
                for (auto i = objs.begin(); i != objs.end(); ++i)
                {
                    T o;
                    if (_callback(*i, o))
                        this->operator[](i.key().asString()) = o;
                    else
                        LOG_WARN("Failed to load '", i.key().asString(), "'");
                }

                LOG_DEBUG("DataSet loaded with ", this->size(), " objects");

                return true;
            }

        private:
            DataSetCallback<T> _callback;
    };

    /*
     * In some cases it might be useful to put different datasets in one file
     * to avoid having to write the exact same config multiple times.
     * To seperate the different datasets, "namespaces" can be used.
     *
     * The following function (namespaceReader) or alias (NamespaceDataSet)
     * can be used to read from a file using the namespace pattern.
     *
     * Json structure:
     * {
     *     "objects": {
     *         <objectname>: {
     *             <namespace>: <value>,
     *             ...
     *         },
     *         ...
     *     }
     * }
     *
     * Note that it's not possible to use string literals as template
     * arguments. Therefore you need to pass single chars (which is ugly but
     * it works), e.g.:
     * JsonDataSet<SomeType>(namespaceReader<SomeType, somefunc,
     *                    'n', 'a', 'm', 'e', 's', 'p', 'a', 'c', 'e'>)
     */

    template <class T, DataSetCallback<T> F, char... chrs>
    bool namespaceReader(const Json::Value& node, T& obj)
    {
        static const char str[] = { chrs..., 0 };
        if (node.isMember(str))
            return F(node[str], obj);
        return false;
    }

    // template <class T, DataSetCallback<T> F, const char* str>
    // bool namespaceReader(const Json::Value& node, T& obj)
    // {
    //     if (node.isMember(str))
    //         return F(node[str], obj);
    //     return false;
    // }
}

#endif
<|endoftext|>


<commit_before>//
//  inpal_algorithm.hpp
//  Inverse Palindrome Library
//
//  Created by Bryan Triana on 7/22/16.
//  Copyright © 2016 Inverse Palindrome. All rights reserved.
//

#ifndef inpal_algorithm_hpp
#define inpal_algorithm_hpp

#include <cstdlib>
#include <string>
#include <vector>

namespace inpal
{
   namespace algorithm
    {
        std::size_t gcd(std::size_t a, std::size_t b);
        std::size_t modulo(std::size_t a, std::size_t b, std::size_t c);
        std::size_t mulmod(std::size_t a, std::size_t b, std::size_t c);
        std::size_t pollard_rho(std::size_t num);
        std::vector<std::size_t> trial_division(std::size_t num);
        bool pal_test(std::size_t num);

    }
}

#endif /* inpal_algorithm_hpp */

<commit_msg>Update inpal_algorithm.hpp<commit_after>//
//  inpal_algorithm.hpp
//  Inverse Palindrome Library
//
//  Created by Bryan Triana on 7/22/16.
//  Copyright © 2016 Inverse Palindrome. All rights reserved.
//

#ifndef inpal_algorithm_hpp
#define inpal_algorithm_hpp

#include <cstdlib>
#include <string>
#include <vector>

namespace inpal
{
   namespace algorithm
    {
        std::size_t gcd(std::size_t a, std::size_t b);
        std::size_t modulo(std::size_t a, std::size_t b, std::size_t c);
        std::size_t mulmod(std::size_t a, std::size_t b, std::size_t c);
        std::size_t pollard_rho(std::size_t num);
        std::vector<std::size_t> trial_division(std::size_t num);
        bool pal_test(std::size_t num);
    }
}

#endif /* inpal_algorithm_hpp */

<|endoftext|>


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

    Copyright (c) 2003 Cornelius Schumacher <schumacher@kde.org>

    This library is free software; you can redistribute it and/or
    modify it under the terms of the GNU Library General Public
    License as published by the Free Software Foundation; either
    version 2 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
    Library General Public License for more details.

    You should have received a copy of the GNU Library General Public License
    along with this library; see the file COPYING.LIB.  If not, write to
    the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
    Boston, MA 02111-1307, USA.
*/

#include "localkonnectorconfig.h"

#include "localkonnector.h"

#include <libkcal/resourcelocal.h>

#include <kconfig.h>
#include <klocale.h>
#include <kabc/resourcefile.h>
#include <kmessagebox.h>
#include <kinputdialog.h>
#include <klineedit.h>

#include <qlabel.h>
#include <qlayout.h>
#include <qpushbutton.h>

using namespace KSync;

LocalKonnectorConfig::LocalKonnectorConfig( QWidget *parent )
  : KRES::ConfigWidget( parent, 0 )
{
  QBoxLayout *topLayout = new QVBoxLayout( this );

  topLayout->addWidget( new QLabel( i18n("Calendar file:"), this ) );

  mCalendarFile = new KURLRequester( this );
  mCalendarFile->setMode( KFile::File | KFile::LocalOnly );
  topLayout->addWidget( mCalendarFile );

  QPushButton *button =
      new QPushButton( i18n("Select From Existing Resources..."), this );
  connect( button, SIGNAL( clicked() ), SLOT( selectCalendarResource() ) );
  topLayout->addWidget( button );

  topLayout->addSpacing( 4 );

  topLayout->addWidget( new QLabel( i18n("Address book file:"), this ) );

  mAddressBookFile = new KURLRequester( this );
  mAddressBookFile->setMode( KFile::File | KFile::LocalOnly );
  topLayout->addWidget( mAddressBookFile );

  button = new QPushButton( i18n("Select From Existing Resources..."), this );
  connect( button, SIGNAL( clicked() ), SLOT( selectAddressBookResource() ) );
  topLayout->addWidget( button );
}

LocalKonnectorConfig::~LocalKonnectorConfig()
{
}

void LocalKonnectorConfig::loadSettings( KRES::Resource *r )
{
  LocalKonnector *konnector = dynamic_cast<LocalKonnector *>( r );
  if ( konnector ) {
    mCalendarFile->setURL( konnector->calendarFile() );
    mAddressBookFile->setURL( konnector->addressBookFile() );
  }
}

void LocalKonnectorConfig::saveSettings( KRES::Resource *r )
{
  LocalKonnector *konnector = dynamic_cast<LocalKonnector *>( r );
  if ( konnector ) {
    konnector->setCalendarFile( mCalendarFile->url() );
    konnector->setAddressBookFile( mAddressBookFile->url() );
  }
}

void LocalKonnectorConfig::selectAddressBookResource()
{
  QStringList files;

  KRES::Manager<KABC::Resource> manager( "contact" );
  manager.readConfig();

  KRES::Manager<KABC::Resource>::Iterator it;
  for( it = manager.begin(); it != manager.end(); ++it ) {
    if ( (*it)->inherits( "KABC::ResourceFile" ) ) {
      KABC::ResourceFile *r = static_cast<KABC::ResourceFile *>( *it );
      files.append( r->fileName() );
    }
  }

  if ( files.isEmpty() ) {
    KMessageBox::sorry( this, i18n("No file resources found.") );
  } else {
    QString file = KInputDialog::getItem( i18n("Select File"),
        i18n("Please select an addressbook file:"), files, 0, false, 0, this );
    if ( !file.isEmpty() ) {
      mAddressBookFile->lineEdit()->setText( file );
    }
  }
}

void LocalKonnectorConfig::selectCalendarResource()
{
  QStringList files;

  KCal::CalendarResourceManager manager( "calendar" );
  manager.readConfig();

  KCal::CalendarResourceManager::Iterator it;
  for( it = manager.begin(); it != manager.end(); ++it ) {
    if ( (*it)->inherits( "KCal::ResourceLocal" ) ) {
      KCal::ResourceLocal *r = static_cast<KCal::ResourceLocal *>( *it );
      files.append( r->fileName() );
    }
  }

  if ( files.isEmpty() ) {
    KMessageBox::sorry( this, i18n("No file resources found.") );
  } else {
    QString file = KInputDialog::getItem( i18n("Select File"),
        i18n("Please select a calendar file:"), files, 0, false, 0, this );
    if ( !file.isEmpty() ) {
      mCalendarFile->lineEdit()->setText( file );
    }
  }
}

#include "localkonnectorconfig.moc"
<commit_msg>Replace 'Resources' by 'Calendars' and 'Address Books'<commit_after>/*
    This file is part of KitchenSync.

    Copyright (c) 2003 Cornelius Schumacher <schumacher@kde.org>

    This library is free software; you can redistribute it and/or
    modify it under the terms of the GNU Library General Public
    License as published by the Free Software Foundation; either
    version 2 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
    Library General Public License for more details.

    You should have received a copy of the GNU Library General Public License
    along with this library; see the file COPYING.LIB.  If not, write to
    the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
    Boston, MA 02111-1307, USA.
*/

#include "localkonnectorconfig.h"

#include "localkonnector.h"

#include <libkcal/resourcelocal.h>

#include <kconfig.h>
#include <klocale.h>
#include <kabc/resourcefile.h>
#include <kmessagebox.h>
#include <kinputdialog.h>
#include <klineedit.h>

#include <qlabel.h>
#include <qlayout.h>
#include <qpushbutton.h>

using namespace KSync;

LocalKonnectorConfig::LocalKonnectorConfig( QWidget *parent )
  : KRES::ConfigWidget( parent, 0 )
{
  QBoxLayout *topLayout = new QVBoxLayout( this );

  topLayout->addWidget( new QLabel( i18n("Calendar file:"), this ) );

  mCalendarFile = new KURLRequester( this );
  mCalendarFile->setMode( KFile::File | KFile::LocalOnly );
  topLayout->addWidget( mCalendarFile );

  QPushButton *button =
      new QPushButton( i18n("Select From Existing Calendars..."), this );
  connect( button, SIGNAL( clicked() ), SLOT( selectCalendarResource() ) );
  topLayout->addWidget( button );

  topLayout->addSpacing( 4 );

  topLayout->addWidget( new QLabel( i18n("Address book file:"), this ) );

  mAddressBookFile = new KURLRequester( this );
  mAddressBookFile->setMode( KFile::File | KFile::LocalOnly );
  topLayout->addWidget( mAddressBookFile );

  button = new QPushButton( i18n("Select From Existing Address Books..."), this );
  connect( button, SIGNAL( clicked() ), SLOT( selectAddressBookResource() ) );
  topLayout->addWidget( button );
}

LocalKonnectorConfig::~LocalKonnectorConfig()
{
}

void LocalKonnectorConfig::loadSettings( KRES::Resource *r )
{
  LocalKonnector *konnector = dynamic_cast<LocalKonnector *>( r );
  if ( konnector ) {
    mCalendarFile->setURL( konnector->calendarFile() );
    mAddressBookFile->setURL( konnector->addressBookFile() );
  }
}

void LocalKonnectorConfig::saveSettings( KRES::Resource *r )
{
  LocalKonnector *konnector = dynamic_cast<LocalKonnector *>( r );
  if ( konnector ) {
    konnector->setCalendarFile( mCalendarFile->url() );
    konnector->setAddressBookFile( mAddressBookFile->url() );
  }
}

void LocalKonnectorConfig::selectAddressBookResource()
{
  QStringList files;

  KRES::Manager<KABC::Resource> manager( "contact" );
  manager.readConfig();

  KRES::Manager<KABC::Resource>::Iterator it;
  for( it = manager.begin(); it != manager.end(); ++it ) {
    if ( (*it)->inherits( "KABC::ResourceFile" ) ) {
      KABC::ResourceFile *r = static_cast<KABC::ResourceFile *>( *it );
      files.append( r->fileName() );
    }
  }

  if ( files.isEmpty() ) {
    KMessageBox::sorry( this, i18n("No file resources found.") );
  } else {
    QString file = KInputDialog::getItem( i18n("Select File"),
        i18n("Please select an addressbook file:"), files, 0, false, 0, this );
    if ( !file.isEmpty() ) {
      mAddressBookFile->lineEdit()->setText( file );
    }
  }
}

void LocalKonnectorConfig::selectCalendarResource()
{
  QStringList files;

  KCal::CalendarResourceManager manager( "calendar" );
  manager.readConfig();

  KCal::CalendarResourceManager::Iterator it;
  for( it = manager.begin(); it != manager.end(); ++it ) {
    if ( (*it)->inherits( "KCal::ResourceLocal" ) ) {
      KCal::ResourceLocal *r = static_cast<KCal::ResourceLocal *>( *it );
      files.append( r->fileName() );
    }
  }

  if ( files.isEmpty() ) {
    KMessageBox::sorry( this, i18n("No file resources found.") );
  } else {
    QString file = KInputDialog::getItem( i18n("Select File"),
        i18n("Please select a calendar file:"), files, 0, false, 0, this );
    if ( !file.isEmpty() ) {
      mCalendarFile->lineEdit()->setText( file );
    }
  }
}

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


<commit_before>#include "Stdafx.h"
#include <msclr/marshal.h>
#include <ogrsf_frmts.h>
#include "Driver.h"
#include "DataSource.h"
#include "LayerCollection.h"

using namespace System;
using namespace OSGeo::Ogr;

DataSource::DataSource(OGRDataSource* dataSource)
{
	this->_dataSource = dataSource;

	this->_capabilities = DataSourceCapabilities::None;
	if (this->_dataSource->TestCapability(ODsCCreateLayer))
	{
		this->_capabilities = this->_capabilities | DataSourceCapabilities::CreateLayer;
	}

	if (this->_dataSource->TestCapability(ODsCDeleteLayer))
	{
		this->_capabilities = this->_capabilities | DataSourceCapabilities::DeleteLayer;
	}

	this->_driver = gcnew OSGeo::Ogr::Driver(this->_dataSource->GetDriver());
}

DataSource::DataSource(OGRDataSource* dataSource, OGRSFDriver* driver)
{
	this->_dataSource = dataSource;
	this->_driver = gcnew OSGeo::Ogr::Driver(driver);
}

DataSource^ DataSource::Open(String^ filename)
{
	OGRRegisterAll();
	msclr::interop::marshal_context cxt;
	OGRDataSource *poDS;
	char const* input = cxt.marshal_as<char const*>(filename);
	poDS = OGRSFDriverRegistrar::Open(input, FALSE);
	return gcnew OSGeo::Ogr::DataSource(poDS);
}

DataSource^ DataSource::Copy(String^ name)
{
	OGRRegisterAll();
	msclr::interop::marshal_context cxt;
	return gcnew OSGeo::Ogr::DataSource(this->_driver->Handle->CopyDataSource(this->Handle, cxt.marshal_as<char const*>(name), NULL), this->_driver->Handle);
}

OSGeo::Ogr::Driver^ DataSource::Driver::get()
{
	return this->_driver;
}

DataSourceCapabilities DataSource::Capabilities::get()
{
	return this->_capabilities;
}

OGRDataSource* DataSource::Handle::get()
{
	return this->_dataSource;
}

String^ DataSource::Name::get()
{
	const char* name = this->_dataSource->GetName();
	msclr::interop::marshal_context cxt;
	return cxt.marshal_as<String^>(name);
}

LayerCollection^ DataSource::Layers::get()
{
	return gcnew LayerCollection(this->_dataSource);
}

// Finalise this instance.
DataSource::!DataSource()
{
	if (this->_dataSource != NULL)
	{
		OGRDataSource::DestroyDataSource(this->_dataSource);
		this->_dataSource = NULL;
	}
}

// Dispose this instance.
DataSource::~DataSource()
{
	this->!DataSource();
}<commit_msg>Throw an exception when the Data Source is NULL<commit_after>#include "Stdafx.h"
#include <msclr/marshal.h>
#include <ogrsf_frmts.h>
#include "Driver.h"
#include "DataSource.h"
#include "LayerCollection.h"
#include "GdalException.h"

using namespace System;
using namespace OSGeo::Ogr;

DataSource::DataSource(OGRDataSource* dataSource)
{
	this->_dataSource = dataSource;

	this->_capabilities = DataSourceCapabilities::None;
	if (this->_dataSource->TestCapability(ODsCCreateLayer))
	{
		this->_capabilities = this->_capabilities | DataSourceCapabilities::CreateLayer;
	}

	if (this->_dataSource->TestCapability(ODsCDeleteLayer))
	{
		this->_capabilities = this->_capabilities | DataSourceCapabilities::DeleteLayer;
	}

	this->_driver = gcnew OSGeo::Ogr::Driver(this->_dataSource->GetDriver());
}

DataSource::DataSource(OGRDataSource* dataSource, OGRSFDriver* driver)
{
	this->_dataSource = dataSource;
	this->_driver = gcnew OSGeo::Ogr::Driver(driver);
}

DataSource^ DataSource::Open(String^ filename)
{
	OGRRegisterAll();
	msclr::interop::marshal_context cxt;
	OGRDataSource *poDS;
	char const* input = cxt.marshal_as<char const*>(filename);
	poDS = OGRSFDriverRegistrar::Open(input, FALSE);
	if (poDS == NULL)
	{
		throw GdalException::Create();
	}

	return gcnew OSGeo::Ogr::DataSource(poDS);
}

DataSource^ DataSource::Copy(String^ name)
{
	OGRRegisterAll();
	msclr::interop::marshal_context cxt;
	return gcnew OSGeo::Ogr::DataSource(this->_driver->Handle->CopyDataSource(this->Handle, cxt.marshal_as<char const*>(name), NULL), this->_driver->Handle);
}

OSGeo::Ogr::Driver^ DataSource::Driver::get()
{
	return this->_driver;
}

DataSourceCapabilities DataSource::Capabilities::get()
{
	return this->_capabilities;
}

OGRDataSource* DataSource::Handle::get()
{
	return this->_dataSource;
}

String^ DataSource::Name::get()
{
	const char* name = this->_dataSource->GetName();
	msclr::interop::marshal_context cxt;
	return cxt.marshal_as<String^>(name);
}

LayerCollection^ DataSource::Layers::get()
{
	return gcnew LayerCollection(this->_dataSource);
}

// Finalise this instance.
DataSource::!DataSource()
{
	if (this->_dataSource != NULL)
	{
		OGRDataSource::DestroyDataSource(this->_dataSource);
		this->_dataSource = NULL;
	}
}

// Dispose this instance.
DataSource::~DataSource()
{
	this->!DataSource();
}<|endoftext|>


<commit_before>/*
 * Copyright (C) 2008-2010 The QXmpp developers
 *
 * Author:
 *  Manjeet Dahiya
 *
 * Source:
 *  http://code.google.com/p/qxmpp
 *
 * This file is a part of QXmpp 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 "QXmppDiscoveryManager.h"

#include <QDomElement>
#include <QCoreApplication>

#include "QXmppClient.h"
#include "QXmppConstants.h"
#include "QXmppDiscoveryIq.h"
#include "QXmppStream.h"

bool QXmppDiscoveryManager::handleStanza(QXmppStream *stream, const QDomElement &element)
{
    if (element.tagName() == "iq" && QXmppDiscoveryIq::isDiscoveryIq(element))
    {
        QXmppDiscoveryIq infoIq;
        infoIq.parse(element);

        if(infoIq.type() == QXmppIq::Get &&
           infoIq.queryType() == QXmppDiscoveryIq::InfoQuery &&
           (infoIq.queryNode().isEmpty() || infoIq.queryNode().startsWith(QString(capabilities_node))))
        {
            // respond to query
            QXmppDiscoveryIq qxmppFeatures = capabilities();
            qxmppFeatures.setId(infoIq.id());
            qxmppFeatures.setTo(infoIq.from());
            qxmppFeatures.setQueryNode(infoIq.queryNode());
            stream->sendPacket(qxmppFeatures);
        }

        emit informationReceived(infoIq);
        return true;
    }
    return false;
}

void QXmppDiscoveryManager::requestInformation(const QString& jid)
{
}

QStringList QXmppDiscoveryManager::discoveryFeatures() const
{
    return QStringList() << ns_disco_info;
}

QXmppDiscoveryIq QXmppDiscoveryManager::capabilities()
{
    QXmppDiscoveryIq iq;
    iq.setType(QXmppIq::Result);
    iq.setQueryType(QXmppDiscoveryIq::InfoQuery);

    // features
    QStringList features;
    features
        << ns_rpc               // XEP-0009: Jabber-RPC
//        << ns_disco_info        // XEP-0030: Service Discovery
        << ns_ibb               // XEP-0047: In-Band Bytestreams
        << ns_vcard             // XEP-0054: vcard-temp
        << ns_bytestreams       // XEP-0065: SOCKS5 Bytestreams
        << ns_chat_states       // XEP-0085: Chat State Notifications
        << ns_stream_initiation // XEP-0095: Stream Initiation
        << ns_stream_initiation_file_transfer // XEP-0096: SI File Transfer
        << ns_capabilities      // XEP-0115 : Entity Capabilities
        << ns_jingle            // XEP-0166 : Jingle
        << ns_jingle_rtp        // XEP-0167 : Jingle RTP Sessions
        << ns_jingle_rtp_audio
        << ns_jingle_ice_udp    // XEP-0176 : Jingle ICE-UDP Transport Method
        << ns_ping;             // XEP-0199: XMPP Ping

    foreach(QXmppClientExtension* extension, client()->extensions())
    {
        if(extension)
            features << extension->discoveryFeatures();
    }

    iq.setFeatures(features);

    // identities
    QList<QXmppDiscoveryIq::Identity> identities;
    QXmppDiscoveryIq::Identity identity;

    identity.setCategory("automation");
    identity.setType("rpc");
    identities.append(identity);

    identity.setCategory("client");
    identity.setType("pc");
    identity.setName(QString("%1 %2").arg(qApp->applicationName(), qApp->applicationVersion()));
    identities.append(identity);

    iq.setIdentities(identities);
    return iq;
}
<commit_msg>implement requestInformation()<commit_after>/*
 * Copyright (C) 2008-2010 The QXmpp developers
 *
 * Author:
 *  Manjeet Dahiya
 *
 * Source:
 *  http://code.google.com/p/qxmpp
 *
 * This file is a part of QXmpp 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 "QXmppDiscoveryManager.h"

#include <QDomElement>
#include <QCoreApplication>

#include "QXmppClient.h"
#include "QXmppConstants.h"
#include "QXmppDiscoveryIq.h"
#include "QXmppStream.h"

bool QXmppDiscoveryManager::handleStanza(QXmppStream *stream, const QDomElement &element)
{
    if (element.tagName() == "iq" && QXmppDiscoveryIq::isDiscoveryIq(element))
    {
        QXmppDiscoveryIq infoIq;
        infoIq.parse(element);

        if(infoIq.type() == QXmppIq::Get &&
           infoIq.queryType() == QXmppDiscoveryIq::InfoQuery &&
           (infoIq.queryNode().isEmpty() || infoIq.queryNode().startsWith(QString(capabilities_node))))
        {
            // respond to query
            QXmppDiscoveryIq qxmppFeatures = capabilities();
            qxmppFeatures.setId(infoIq.id());
            qxmppFeatures.setTo(infoIq.from());
            qxmppFeatures.setQueryNode(infoIq.queryNode());
            stream->sendPacket(qxmppFeatures);
        }

        emit informationReceived(infoIq);
        return true;
    }
    return false;
}

void QXmppDiscoveryManager::requestInformation(const QString& jid)
{
    QXmppDiscoveryIq request;
    request.setType(QXmppIq::Get);
    request.setQueryType(QXmppDiscoveryIq::ItemsQuery);
    request.setTo(jid);
    request.setFrom(client()->configuration().jid());
    client()->sendPacket(request)
}

QStringList QXmppDiscoveryManager::discoveryFeatures() const
{
    return QStringList() << ns_disco_info;
}

QXmppDiscoveryIq QXmppDiscoveryManager::capabilities()
{
    QXmppDiscoveryIq iq;
    iq.setType(QXmppIq::Result);
    iq.setQueryType(QXmppDiscoveryIq::InfoQuery);

    // features
    QStringList features;
    features
        << ns_rpc               // XEP-0009: Jabber-RPC
//        << ns_disco_info        // XEP-0030: Service Discovery
        << ns_ibb               // XEP-0047: In-Band Bytestreams
        << ns_vcard             // XEP-0054: vcard-temp
        << ns_bytestreams       // XEP-0065: SOCKS5 Bytestreams
        << ns_chat_states       // XEP-0085: Chat State Notifications
        << ns_stream_initiation // XEP-0095: Stream Initiation
        << ns_stream_initiation_file_transfer // XEP-0096: SI File Transfer
        << ns_capabilities      // XEP-0115 : Entity Capabilities
        << ns_jingle            // XEP-0166 : Jingle
        << ns_jingle_rtp        // XEP-0167 : Jingle RTP Sessions
        << ns_jingle_rtp_audio
        << ns_jingle_ice_udp    // XEP-0176 : Jingle ICE-UDP Transport Method
        << ns_ping;             // XEP-0199: XMPP Ping

    foreach(QXmppClientExtension* extension, client()->extensions())
    {
        if(extension)
            features << extension->discoveryFeatures();
    }

    iq.setFeatures(features);

    // identities
    QList<QXmppDiscoveryIq::Identity> identities;
    QXmppDiscoveryIq::Identity identity;

    identity.setCategory("automation");
    identity.setType("rpc");
    identities.append(identity);

    identity.setCategory("client");
    identity.setType("pc");
    identity.setName(QString("%1 %2").arg(qApp->applicationName(), qApp->applicationVersion()));
    identities.append(identity);

    iq.setIdentities(identities);
    return iq;
}
<|endoftext|>


<commit_before>#include "btree/iteration.hpp"
#include "btree/btree_data_provider.hpp"

leaf_iterator_t::leaf_iterator_t(const leaf_node_t *leaf, int index, buf_lock_t *lock, const boost::shared_ptr<transactor_t>& transactor) :
    leaf(leaf), index(index), lock(lock), transactor(transactor) {

    rassert(leaf != NULL);
    rassert(lock != NULL);
}

boost::optional<key_with_data_provider_t> leaf_iterator_t::next() {
    rassert(index >= 0);
    if (index >= leaf->npairs) {
        done();
        return boost::none;
    }

    return boost::make_optional(pair_to_key_with_data_provider(leaf::get_pair_by_index(leaf, index++)));
}

void leaf_iterator_t::prefetch() {
    /* this space intentionally left blank */
}

leaf_iterator_t::~leaf_iterator_t() {
    done();
}

void leaf_iterator_t::done() {
    if (lock) {
        transactor->transaction()->ensure_thread();
        delete lock;
        lock = NULL;
    }
}

key_with_data_provider_t leaf_iterator_t::pair_to_key_with_data_provider(const btree_leaf_pair* pair) {
    value_data_provider_t *data_provider = value_data_provider_t::create(pair->value(), transactor);
    return key_with_data_provider_t(key_to_str(&pair->key), pair->value()->mcflags(),
        boost::shared_ptr<data_provider_t>(data_provider));
}

slice_leaves_iterator_t::slice_leaves_iterator_t(const boost::shared_ptr<transactor_t>& transactor, btree_slice_t *slice,
    store_key_t *start, store_key_t *end, bool left_open, bool right_open) :
        transactor(transactor), slice(slice),
        start(start), end(end), left_open(left_open), right_open(right_open),
        traversal_state(), started(false), nevermore(false) {
}

boost::optional<leaf_iterator_t*> slice_leaves_iterator_t::next() {
    if (nevermore)
        return boost::none;

    boost::optional<leaf_iterator_t*> leaf = !started ? get_first_leaf() : get_next_leaf();
    if (!leaf)
        done();
    return leaf;
}

void slice_leaves_iterator_t::prefetch() {
    // Not implemented yet
}

slice_leaves_iterator_t::~slice_leaves_iterator_t() {
    done();
}

void slice_leaves_iterator_t::done() {
    while (!traversal_state.empty()) {
        delete traversal_state.back().lock;
        traversal_state.pop_back();
    }
    nevermore = true;
}

boost::optional<leaf_iterator_t*> slice_leaves_iterator_t::get_first_leaf() {
    on_thread_t mover(slice->home_thread); // Move to the slice's thread.

    started = true;
    buf_lock_t *buf_lock = new buf_lock_t(*transactor, block_id_t(SUPERBLOCK_ID), rwi_read);
    block_id_t root_id = ptr_cast<btree_superblock_t>(buf_lock->buf()->get_data_read())->root_block;
    rassert(root_id != SUPERBLOCK_ID);

    if (root_id == NULL_BLOCK_ID) {
        delete buf_lock;
        return boost::none;
    }

    {
        buf_lock_t tmp(*transactor, root_id, rwi_read);
        buf_lock->swap(tmp);
    }

    // read root node
    const node_t *node = ptr_cast<node_t>(buf_lock->buf()->get_data_read());
    rassert(node != NULL);

    while (node::is_internal(node)) {
        const internal_node_t *i_node = ptr_cast<internal_node_t>(node);

        // push the i_node onto the traversal_state stack
        int index = internal_node::impl::get_offset_index(i_node, start);
        rassert(index >= 0);
        if (index >= i_node->npairs) {
            // this subtree has all the keys smaller than 'start', move to the leaf in the next subtree
            delete buf_lock;
            return get_next_leaf();
        }
        traversal_state.push_back(internal_node_state(i_node, index, buf_lock));

        block_id_t child_id = get_child_id(i_node, index);

        buf_lock = new buf_lock_t(*transactor, child_id, rwi_read);
        node = ptr_cast<node_t>(buf_lock->buf()->get_data_read());
    }

    rassert(node != NULL);
    rassert(node::is_leaf(node));
    rassert(buf_lock != NULL);

    const leaf_node_t *l_node = ptr_cast<leaf_node_t>(node);
    int index = leaf::impl::get_offset_index(l_node, start);

    if (index < l_node->npairs) {
        return boost::make_optional(new leaf_iterator_t(l_node, index, buf_lock, transactor));
    } else {
        // there's nothing more in this leaf, we might as well move to the next leaf
        delete buf_lock;
        return get_next_leaf();
    }
}

boost::optional<leaf_iterator_t*> slice_leaves_iterator_t::get_next_leaf() {
    while (traversal_state.size() > 0) {
        internal_node_state state = traversal_state.back();
        traversal_state.pop_back();

        rassert(state.index >= 0 && state.index < state.node->npairs);
        ++state.index;
        if (state.index < state.node->npairs) {
            traversal_state.push_back(state);

            // get next child and find its leftmost leaf
            block_id_t child_id = get_child_id(state.node, state.index);
            return get_leftmost_leaf(child_id);
        } else {
            delete state.lock;  // this also releases the memory used by state.node
        }
    }
    return boost::none;
}

boost::optional<leaf_iterator_t*> slice_leaves_iterator_t::get_leftmost_leaf(block_id_t node_id) {
    on_thread_t mover(slice->home_thread); // Move to the slice's thread.

    buf_lock_t *buf_lock = new buf_lock_t(*transactor, node_id, rwi_read);
    const node_t *node = ptr_cast<node_t>(buf_lock->buf()->get_data_read());

    while (node::is_internal(node)) {
        const internal_node_t *i_node = ptr_cast<internal_node_t>(node);
        rassert(i_node->npairs > 0);

        // push the i_node onto the traversal_state stack
        const int leftmost_child_index = 0;
        traversal_state.push_back(internal_node_state(i_node, leftmost_child_index, buf_lock));

        block_id_t child_id = get_child_id(i_node, leftmost_child_index);

        buf_lock = new buf_lock_t(*transactor, child_id, rwi_read);
        node = ptr_cast<node_t>(buf_lock->buf()->get_data_read());
    }
    rassert(node != NULL);
    rassert(node::is_leaf(node));
    rassert(buf_lock != NULL);

    const leaf_node_t *l_node = ptr_cast<leaf_node_t>(node);
    return boost::make_optional(new leaf_iterator_t(l_node, 0, buf_lock, transactor));
}

block_id_t slice_leaves_iterator_t::get_child_id(const internal_node_t *i_node, int index) const {
    block_id_t child_id = internal_node::get_pair_by_index(i_node, index)->lnode;
    rassert(child_id != NULL_BLOCK_ID);
    rassert(child_id != SUPERBLOCK_ID);

    return child_id;
}

slice_keys_iterator_t::slice_keys_iterator_t(const boost::shared_ptr<transactor_t>& transactor, btree_slice_t *slice, store_key_t *start, store_key_t *end, bool left_open, bool right_open) :
    transactor(transactor), slice(slice), start(start), start_str(key_to_str(start)), end(end), end_str(key_to_str(end)), left_open(left_open), right_open(right_open),
    no_more_data(false), active_leaf(NULL), leaves_iterator(NULL) { }

slice_keys_iterator_t::~slice_keys_iterator_t() {
    done();
}

boost::optional<key_with_data_provider_t> slice_keys_iterator_t::next() {
    if (no_more_data)
        return boost::none;

    boost::optional<key_with_data_provider_t> result = active_leaf == NULL ? get_first_value() : get_next_value();
    if (!result) {
        done();
    }
    return result;
}

void slice_keys_iterator_t::prefetch() {
}

boost::optional<key_with_data_provider_t> slice_keys_iterator_t::get_first_value() {
    leaves_iterator = new slice_leaves_iterator_t(transactor, slice, start, end, left_open, right_open);

    // get the first leaf with our start key (or something greater)
    boost::optional<leaf_iterator_t*> first = leaves_iterator->next();
    if (!first)
        return boost::none;

    active_leaf = first.get();
    rassert(active_leaf != NULL);

    // get a value from the leaf
    boost::optional<key_with_data_provider_t> first_pair = active_leaf->next();
    if (!first_pair)
        return first_pair;  // returns empty result

    key_with_data_provider_t pair = first_pair.get();

    // skip the start key if left_open
    int compare_result = pair.key.compare(start_str);
    rassert(compare_result >= 0);
    if (left_open && compare_result == 0) {
        return get_next_value();
    } else {
        return validate_return_value(pair);
    }
}

boost::optional<key_with_data_provider_t> slice_keys_iterator_t::get_next_value() {
    rassert(leaves_iterator != NULL);
    rassert(active_leaf != NULL);

    // get a value from the leaf
    boost::optional<key_with_data_provider_t> current_pair = active_leaf->next();
    if (!current_pair) {
        delete active_leaf;
        active_leaf = NULL;

        boost::optional<leaf_iterator_t*> leaf = leaves_iterator->next();
        if (!leaf)
            return boost::none;

        active_leaf = leaf.get();
        current_pair = active_leaf->next();
        if (!current_pair)
            return boost::none;
    }

    return validate_return_value(current_pair.get());
}

boost::optional<key_with_data_provider_t> slice_keys_iterator_t::validate_return_value(key_with_data_provider_t &pair) const {
    int compare_result = pair.key.compare(end_str);
    if (compare_result < 0 || (!right_open && compare_result == 0)) {
        return boost::make_optional(pair);
    } else {
        return boost::none;
    }
}

void slice_keys_iterator_t::done() {
    if (active_leaf) {
        delete active_leaf;
        active_leaf = NULL;
    }
    if (leaves_iterator) {
        delete leaves_iterator;
        leaves_iterator = NULL;
    }
    no_more_data = true;
}

<commit_msg>Don't return expired values in rget<commit_after>#include "btree/iteration.hpp"
#include "btree/btree_data_provider.hpp"

leaf_iterator_t::leaf_iterator_t(const leaf_node_t *leaf, int index, buf_lock_t *lock, const boost::shared_ptr<transactor_t>& transactor) :
    leaf(leaf), index(index), lock(lock), transactor(transactor) {

    rassert(leaf != NULL);
    rassert(lock != NULL);
}

boost::optional<key_with_data_provider_t> leaf_iterator_t::next() {
    rassert(index >= 0);
    const btree_leaf_pair *pair;
    do {
        if (index >= leaf->npairs) {
            done();
            return boost::none;
        }
        pair = leaf::get_pair_by_index(leaf, index++);
    } while (pair->value()->expired());

    return boost::make_optional(pair_to_key_with_data_provider(pair));
}

void leaf_iterator_t::prefetch() {
    /* this space intentionally left blank */
}

leaf_iterator_t::~leaf_iterator_t() {
    done();
}

void leaf_iterator_t::done() {
    if (lock) {
        transactor->transaction()->ensure_thread();
        delete lock;
        lock = NULL;
    }
}

key_with_data_provider_t leaf_iterator_t::pair_to_key_with_data_provider(const btree_leaf_pair* pair) {
    value_data_provider_t *data_provider = value_data_provider_t::create(pair->value(), transactor);
    return key_with_data_provider_t(key_to_str(&pair->key), pair->value()->mcflags(),
        boost::shared_ptr<data_provider_t>(data_provider));
}

slice_leaves_iterator_t::slice_leaves_iterator_t(const boost::shared_ptr<transactor_t>& transactor, btree_slice_t *slice,
    store_key_t *start, store_key_t *end, bool left_open, bool right_open) :
        transactor(transactor), slice(slice),
        start(start), end(end), left_open(left_open), right_open(right_open),
        traversal_state(), started(false), nevermore(false) {
}

boost::optional<leaf_iterator_t*> slice_leaves_iterator_t::next() {
    if (nevermore)
        return boost::none;

    boost::optional<leaf_iterator_t*> leaf = !started ? get_first_leaf() : get_next_leaf();
    if (!leaf)
        done();
    return leaf;
}

void slice_leaves_iterator_t::prefetch() {
    // Not implemented yet
}

slice_leaves_iterator_t::~slice_leaves_iterator_t() {
    done();
}

void slice_leaves_iterator_t::done() {
    while (!traversal_state.empty()) {
        delete traversal_state.back().lock;
        traversal_state.pop_back();
    }
    nevermore = true;
}

boost::optional<leaf_iterator_t*> slice_leaves_iterator_t::get_first_leaf() {
    on_thread_t mover(slice->home_thread); // Move to the slice's thread.

    started = true;
    buf_lock_t *buf_lock = new buf_lock_t(*transactor, block_id_t(SUPERBLOCK_ID), rwi_read);
    block_id_t root_id = ptr_cast<btree_superblock_t>(buf_lock->buf()->get_data_read())->root_block;
    rassert(root_id != SUPERBLOCK_ID);

    if (root_id == NULL_BLOCK_ID) {
        delete buf_lock;
        return boost::none;
    }

    {
        buf_lock_t tmp(*transactor, root_id, rwi_read);
        buf_lock->swap(tmp);
    }

    // read root node
    const node_t *node = ptr_cast<node_t>(buf_lock->buf()->get_data_read());
    rassert(node != NULL);

    while (node::is_internal(node)) {
        const internal_node_t *i_node = ptr_cast<internal_node_t>(node);

        // push the i_node onto the traversal_state stack
        int index = internal_node::impl::get_offset_index(i_node, start);
        rassert(index >= 0);
        if (index >= i_node->npairs) {
            // this subtree has all the keys smaller than 'start', move to the leaf in the next subtree
            delete buf_lock;
            return get_next_leaf();
        }
        traversal_state.push_back(internal_node_state(i_node, index, buf_lock));

        block_id_t child_id = get_child_id(i_node, index);

        buf_lock = new buf_lock_t(*transactor, child_id, rwi_read);
        node = ptr_cast<node_t>(buf_lock->buf()->get_data_read());
    }

    rassert(node != NULL);
    rassert(node::is_leaf(node));
    rassert(buf_lock != NULL);

    const leaf_node_t *l_node = ptr_cast<leaf_node_t>(node);
    int index = leaf::impl::get_offset_index(l_node, start);

    if (index < l_node->npairs) {
        return boost::make_optional(new leaf_iterator_t(l_node, index, buf_lock, transactor));
    } else {
        // there's nothing more in this leaf, we might as well move to the next leaf
        delete buf_lock;
        return get_next_leaf();
    }
}

boost::optional<leaf_iterator_t*> slice_leaves_iterator_t::get_next_leaf() {
    while (traversal_state.size() > 0) {
        internal_node_state state = traversal_state.back();
        traversal_state.pop_back();

        rassert(state.index >= 0 && state.index < state.node->npairs);
        ++state.index;
        if (state.index < state.node->npairs) {
            traversal_state.push_back(state);

            // get next child and find its leftmost leaf
            block_id_t child_id = get_child_id(state.node, state.index);
            return get_leftmost_leaf(child_id);
        } else {
            delete state.lock;  // this also releases the memory used by state.node
        }
    }
    return boost::none;
}

boost::optional<leaf_iterator_t*> slice_leaves_iterator_t::get_leftmost_leaf(block_id_t node_id) {
    on_thread_t mover(slice->home_thread); // Move to the slice's thread.

    buf_lock_t *buf_lock = new buf_lock_t(*transactor, node_id, rwi_read);
    const node_t *node = ptr_cast<node_t>(buf_lock->buf()->get_data_read());

    while (node::is_internal(node)) {
        const internal_node_t *i_node = ptr_cast<internal_node_t>(node);
        rassert(i_node->npairs > 0);

        // push the i_node onto the traversal_state stack
        const int leftmost_child_index = 0;
        traversal_state.push_back(internal_node_state(i_node, leftmost_child_index, buf_lock));

        block_id_t child_id = get_child_id(i_node, leftmost_child_index);

        buf_lock = new buf_lock_t(*transactor, child_id, rwi_read);
        node = ptr_cast<node_t>(buf_lock->buf()->get_data_read());
    }
    rassert(node != NULL);
    rassert(node::is_leaf(node));
    rassert(buf_lock != NULL);

    const leaf_node_t *l_node = ptr_cast<leaf_node_t>(node);
    return boost::make_optional(new leaf_iterator_t(l_node, 0, buf_lock, transactor));
}

block_id_t slice_leaves_iterator_t::get_child_id(const internal_node_t *i_node, int index) const {
    block_id_t child_id = internal_node::get_pair_by_index(i_node, index)->lnode;
    rassert(child_id != NULL_BLOCK_ID);
    rassert(child_id != SUPERBLOCK_ID);

    return child_id;
}

slice_keys_iterator_t::slice_keys_iterator_t(const boost::shared_ptr<transactor_t>& transactor, btree_slice_t *slice, store_key_t *start, store_key_t *end, bool left_open, bool right_open) :
    transactor(transactor), slice(slice), start(start), start_str(key_to_str(start)), end(end), end_str(key_to_str(end)), left_open(left_open), right_open(right_open),
    no_more_data(false), active_leaf(NULL), leaves_iterator(NULL) { }

slice_keys_iterator_t::~slice_keys_iterator_t() {
    done();
}

boost::optional<key_with_data_provider_t> slice_keys_iterator_t::next() {
    if (no_more_data)
        return boost::none;

    boost::optional<key_with_data_provider_t> result = active_leaf == NULL ? get_first_value() : get_next_value();
    if (!result) {
        done();
    }
    return result;
}

void slice_keys_iterator_t::prefetch() {
}

boost::optional<key_with_data_provider_t> slice_keys_iterator_t::get_first_value() {
    leaves_iterator = new slice_leaves_iterator_t(transactor, slice, start, end, left_open, right_open);

    // get the first leaf with our start key (or something greater)
    boost::optional<leaf_iterator_t*> first = leaves_iterator->next();
    if (!first)
        return boost::none;

    active_leaf = first.get();
    rassert(active_leaf != NULL);

    // get a value from the leaf
    boost::optional<key_with_data_provider_t> first_pair = active_leaf->next();
    if (!first_pair)
        return first_pair;  // returns empty result

    key_with_data_provider_t pair = first_pair.get();

    // skip the start key if left_open
    int compare_result = pair.key.compare(start_str);
    rassert(compare_result >= 0);
    if (left_open && compare_result == 0) {
        return get_next_value();
    } else {
        return validate_return_value(pair);
    }
}

boost::optional<key_with_data_provider_t> slice_keys_iterator_t::get_next_value() {
    rassert(leaves_iterator != NULL);
    rassert(active_leaf != NULL);

    // get a value from the leaf
    boost::optional<key_with_data_provider_t> current_pair = active_leaf->next();
    if (!current_pair) {
        delete active_leaf;
        active_leaf = NULL;

        boost::optional<leaf_iterator_t*> leaf = leaves_iterator->next();
        if (!leaf)
            return boost::none;

        active_leaf = leaf.get();
        current_pair = active_leaf->next();
        if (!current_pair)
            return boost::none;
    }

    return validate_return_value(current_pair.get());
}

boost::optional<key_with_data_provider_t> slice_keys_iterator_t::validate_return_value(key_with_data_provider_t &pair) const {
    int compare_result = pair.key.compare(end_str);
    if (compare_result < 0 || (!right_open && compare_result == 0)) {
        return boost::make_optional(pair);
    } else {
        return boost::none;
    }
}

void slice_keys_iterator_t::done() {
    if (active_leaf) {
        delete active_leaf;
        active_leaf = NULL;
    }
    if (leaves_iterator) {
        delete leaves_iterator;
        leaves_iterator = NULL;
    }
    no_more_data = true;
}

<|endoftext|>