<commit_before>#include "draw.hpp"
#include <algorithm>

SDL_Renderer * _render = NULL;

void draw_init( SDL_Renderer * render ) {
    _render = render;
}

int set_coloru( Uint32 color ) {
    Uint8 r, ro, g, go, b, bo, ao;

    r = ( color >> 16 );
    g = ( ( color >> 8 ) & 0xff );
    b = ( color & 0xff );
    SDL_GetRenderDrawColor( _render, &ro, &go, &bo, &ao );
    return SDL_SetRenderDrawColor( _render, r, g, b, 0xff );
}

int set_color3u( Uint8 red, Uint8 green, Uint8 blue ) {
    Uint8 ro, go, bo, ao;

    SDL_GetRenderDrawColor( _render, &ro, &go, &bo, &ao );
    return SDL_SetRenderDrawColor( _render, red, green, blue, 0xff );
}

int set_color4u( Uint8 red, Uint8 green, Uint8 blue, Uint8 alpha ) {
    Uint8 ro, go, bo, ao;

    SDL_GetRenderDrawColor( _render, &ro, &go, &bo, &ao );
    return SDL_SetRenderDrawColor( _render, red, green, blue, alpha );
}

int draw_aaline( int x1, int y1, int x2, int y2 ) {
    Uint32 intshift, erracc, erradj, erracctmp, wgt;
    int dx, dy, tmp, xdir, y0p1, x0pxdir, result;
    Sint32 xx0, yy0, xx1, yy1;
    Uint8 r, g, b, a;

    result = SDL_GetRenderDrawColor( _render, &r, &g, &b, &a );
    xx0 = x1; yy0 = y1;
    xx1 = x2; yy1 = y2;
    if ( yy0 > yy1 ) {
        tmp = yy0; yy0 = yy1;
        yy1 = tmp; tmp = xx0;
        xx0 = xx1; xx1 = tmp;
    }
    dx = xx1 - xx0;
    dy = yy1 - yy0;
    if ( dx == 0 || dy == 0 ) {
        return SDL_RenderDrawLine( _render, x1, y1, x2, y2 );
    }
    xdir = 1;
    if ( dx < 0 ) {
        xdir = -1;
        dx = -dx;
    }
    erracc = 0;
    intshift = 24;
    result |= set_color3u( r, g, b );
    result |= SDL_RenderDrawPoint( _render, x1, y1 );
    if ( dy > dx ) {
        erradj = ( ( dx << 16 ) / dy ) << 16;
        x0pxdir = xx0 + xdir;
        while ( --dy ) {
            erracctmp = erracc;
            erracc += erradj;
            if ( erracc <= erracctmp ) {
                xx0 = x0pxdir;
                x0pxdir += xdir;
            }
            yy0++;
            wgt = ( erracc >> intshift ) & 255;
            result |= set_color4u( r, g, b, 255 - wgt );
            result |= SDL_RenderDrawPoint( _render, xx0, yy0 );
            result |= set_color4u( r, g, b, wgt );
            result |= SDL_RenderDrawPoint( _render, x0pxdir, yy0 );
        }
    } else {
        erradj = ( ( dy << 16 ) / dx ) << 16;
        y0p1 = yy0 + 1;
        while ( --dx ) {
            erracctmp = erracc;
            erracc += erradj;
            if ( erracc <= erracctmp ) {
                yy0 = y0p1;
                y0p1++;
            }
            xx0 += xdir;
            wgt = ( erracc >> intshift ) & 255;
            result |= set_color4u( r, g, b, 255 - wgt );
            result |= SDL_RenderDrawPoint( _render, xx0, yy0 );
            result |= set_color4u( r, g, b, wgt );
            result |= SDL_RenderDrawPoint( _render, xx0, y0p1 );
        }
    }
    return result;
}

void draw_path(vec3s n, SDL_Point center, std::vector<vec3s> vs) {
    // отрисовываем путь
    // пока без проверки невидимых линий
    SDL_Point prev;
    bool pe = false;
    for ( auto v: vs ) {
        if ( visible ( n, v ) )
        {
            SDL_Point cur = surf_to_screen( n, v, center);
            if ( pe )
                draw_aaline( prev.x, prev.y, cur.x, cur.y );
            prev = cur;
            pe = true;
        }
        else
            pe = false;
    }
}

void draw_sphere( vec3s n, SDL_Point center, float R, field & f ) {
    // набор точек от 0 до 2pi
    int size = 65;
    std::vector<vec3s> v(size);
    for (int i = 0; i < size; ++i) {
        v[i].r = R;
        v[i].theta = 2 * M_PI * i / (size - 1);
    }
    // меридианы
    for ( unsigned int i = 0; i < f.width; ++i ) {
        float p = i * 2 * M_PI / f.width;
        for (int i = 0; i < size; ++i) {v[i].phi = p;};
        draw_path( n, center, v);
    }

    for (int i = 0; i < size; ++i) {v[i].phi = 2 * M_PI * i / (size - 1);}
    // широты
    for ( unsigned int i = 1; i < f.height; ++i ) {
        float p = i * M_PI / f.height;
        for (int i = 0; i < size; ++i) {v[i].theta = p;};
        draw_path( n, center, v);
    }

    // оси координат (для проверки корректности отрисовки)
    set_color3u(255, 0, 0);
    draw_path( n, center, {{0,0,0}, {1.2f*R, M_PI/2, 0}});
    set_color3u(0, 255, 0);
    draw_path( n, center, {{0,0,0}, {1.2f*R, M_PI/2, M_PI / 2}});
    set_color3u(0, 0, 255);
    draw_path( n, center, {{0,0,0}, {1.2f*R, 0, 0}});
}

int draw_filled_polygon( const SDL_Point* vs, const int n ) {
    int min_y, max_y, result, counts;
    int ind1, ind2, x1, x2, y1, y2;
    int * polygons = new int [n];
    int xa, xb;

    if ( vs == nullptr || n < 3 ) {
        return -1;
    }
    min_y = std::min( vs[0].y, vs[n].y );
    max_y = std::max( vs[0].y, vs[n].y );
    result = 0;
    for ( int y = min_y; y < max_y; y++ ) {
        counts = 0;
        for ( int i = 0; i < n; i++ ) {
            if ( !i ) {
                ind1 = n - 1;
                ind2 = 0;
            } else {
                ind1 = i - 1;
                ind2 = i;
            }
            y1 = vs[ind1].y;
            y2 = vs[ind2].y;
            if ( y1 < y2 ) {
                x1 = vs[ind1].x;
                x2 = vs[ind2].x;
            } else if ( y1 > y2 ) {
                y2 = vs[ind1].y;
                y1 = vs[ind2].y;
                x2 = vs[ind1].x;
                x1 = vs[ind2].x;
            } else {
                continue;
            }
            if ( ( ( y >= y1 ) && ( y < y2 ) ) || ( ( y == max_y ) && ( y > y1 ) && ( y <= y2 ) ) ) {
                polygons[counts++] = ( ( 65536 * ( y - y1 ) ) / ( y2 - y1 ) ) * ( x2 - x1 ) + ( 65536 * x1 );
            }
        }
        std::sort( polygons, polygons + counts );
        result = 0;
        for ( int i = 0; i < counts; i += 2 ) {
            xa = polygons[i+0] + 1;
            xb = polygons[i+1] - 1;
            xa = ( xa >> 16 ) + ( ( xa & 32768 ) >> 15 );
            xb = ( xb >> 16 ) + ( ( xb & 32768 ) >> 15 );
            result |= SDL_RenderDrawLine( _render, xa, y, xb, y );
        }
    }
    delete[] polygons;
    return result;
}
<commit_msg>[upd] find {max, min}<commit_after>#include "draw.hpp"
#include <algorithm>

SDL_Renderer * _render = NULL;

void draw_init( SDL_Renderer * render ) {
    _render = render;
}

int set_coloru( Uint32 color ) {
    Uint8 r, ro, g, go, b, bo, ao;

    r = ( color >> 16 );
    g = ( ( color >> 8 ) & 0xff );
    b = ( color & 0xff );
    SDL_GetRenderDrawColor( _render, &ro, &go, &bo, &ao );
    return SDL_SetRenderDrawColor( _render, r, g, b, 0xff );
}

int set_color3u( Uint8 red, Uint8 green, Uint8 blue ) {
    Uint8 ro, go, bo, ao;

    SDL_GetRenderDrawColor( _render, &ro, &go, &bo, &ao );
    return SDL_SetRenderDrawColor( _render, red, green, blue, 0xff );
}

int set_color4u( Uint8 red, Uint8 green, Uint8 blue, Uint8 alpha ) {
    Uint8 ro, go, bo, ao;

    SDL_GetRenderDrawColor( _render, &ro, &go, &bo, &ao );
    return SDL_SetRenderDrawColor( _render, red, green, blue, alpha );
}

int draw_aaline( int x1, int y1, int x2, int y2 ) {
    Uint32 intshift, erracc, erradj, erracctmp, wgt;
    int dx, dy, tmp, xdir, y0p1, x0pxdir, result;
    Sint32 xx0, yy0, xx1, yy1;
    Uint8 r, g, b, a;

    result = SDL_GetRenderDrawColor( _render, &r, &g, &b, &a );
    xx0 = x1; yy0 = y1;
    xx1 = x2; yy1 = y2;
    if ( yy0 > yy1 ) {
        tmp = yy0; yy0 = yy1;
        yy1 = tmp; tmp = xx0;
        xx0 = xx1; xx1 = tmp;
    }
    dx = xx1 - xx0;
    dy = yy1 - yy0;
    if ( dx == 0 || dy == 0 ) {
        return SDL_RenderDrawLine( _render, x1, y1, x2, y2 );
    }
    xdir = 1;
    if ( dx < 0 ) {
        xdir = -1;
        dx = -dx;
    }
    erracc = 0;
    intshift = 24;
    result |= set_color3u( r, g, b );
    result |= SDL_RenderDrawPoint( _render, x1, y1 );
    if ( dy > dx ) {
        erradj = ( ( dx << 16 ) / dy ) << 16;
        x0pxdir = xx0 + xdir;
        while ( --dy ) {
            erracctmp = erracc;
            erracc += erradj;
            if ( erracc <= erracctmp ) {
                xx0 = x0pxdir;
                x0pxdir += xdir;
            }
            yy0++;
            wgt = ( erracc >> intshift ) & 255;
            result |= set_color4u( r, g, b, 255 - wgt );
            result |= SDL_RenderDrawPoint( _render, xx0, yy0 );
            result |= set_color4u( r, g, b, wgt );
            result |= SDL_RenderDrawPoint( _render, x0pxdir, yy0 );
        }
    } else {
        erradj = ( ( dy << 16 ) / dx ) << 16;
        y0p1 = yy0 + 1;
        while ( --dx ) {
            erracctmp = erracc;
            erracc += erradj;
            if ( erracc <= erracctmp ) {
                yy0 = y0p1;
                y0p1++;
            }
            xx0 += xdir;
            wgt = ( erracc >> intshift ) & 255;
            result |= set_color4u( r, g, b, 255 - wgt );
            result |= SDL_RenderDrawPoint( _render, xx0, yy0 );
            result |= set_color4u( r, g, b, wgt );
            result |= SDL_RenderDrawPoint( _render, xx0, y0p1 );
        }
    }
    return result;
}

void draw_path(vec3s n, SDL_Point center, std::vector<vec3s> vs) {
    // отрисовываем путь
    // пока без проверки невидимых линий
    SDL_Point prev;
    bool pe = false;
    for ( auto v: vs ) {
        if ( visible ( n, v ) )
        {
            SDL_Point cur = surf_to_screen( n, v, center);
            if ( pe )
                draw_aaline( prev.x, prev.y, cur.x, cur.y );
            prev = cur;
            pe = true;
        }
        else
            pe = false;
    }
}

void draw_sphere( vec3s n, SDL_Point center, float R, field & f ) {
    // набор точек от 0 до 2pi
    int size = 65;
    std::vector<vec3s> v(size);
    for (int i = 0; i < size; ++i) {
        v[i].r = R;
        v[i].theta = 2 * M_PI * i / (size - 1);
    }
    // меридианы
    for ( unsigned int i = 0; i < f.width; ++i ) {
        float p = i * 2 * M_PI / f.width;
        for (int i = 0; i < size; ++i) {v[i].phi = p;};
        draw_path( n, center, v);
    }

    for (int i = 0; i < size; ++i) {v[i].phi = 2 * M_PI * i / (size - 1);}
    // широты
    for ( unsigned int i = 1; i < f.height; ++i ) {
        float p = i * M_PI / f.height;
        for (int i = 0; i < size; ++i) {v[i].theta = p;};
        draw_path( n, center, v);
    }

    // оси координат (для проверки корректности отрисовки)
    set_color3u(255, 0, 0);
    draw_path( n, center, {{0,0,0}, {1.2f*R, M_PI/2, 0}});
    set_color3u(0, 255, 0);
    draw_path( n, center, {{0,0,0}, {1.2f*R, M_PI/2, M_PI / 2}});
    set_color3u(0, 0, 255);
    draw_path( n, center, {{0,0,0}, {1.2f*R, 0, 0}});
}

bool SDL_point_compare_y( const SDL_Point & a, const SDL_Point & b ) {
    return a.y < b.y;
}

int draw_filled_polygon( const SDL_Point* vs, const int n ) {
    int min_y, max_y, result, counts;
    int ind1, ind2, x1, x2, y1, y2;
    int * polygons = new int [n];
    int xa, xb;

    if ( vs == nullptr || n < 3 ) {
        return -1;
    }
    // нужно тестирование
    min_y = std::min_element( vs, vs + n, SDL_point_compare_y )->y;
    max_y = std::max_element( vs, vs + n, SDL_point_compare_y )->y;
    result = 0;
    for ( int y = min_y; y < max_y; y++ ) {
        counts = 0;
        for ( int i = 0; i < n; i++ ) {
            if ( !i ) {
                ind1 = n - 1;
                ind2 = 0;
            } else {
                ind1 = i - 1;
                ind2 = i;
            }
            y1 = vs[ind1].y;
            y2 = vs[ind2].y;
            if ( y1 < y2 ) {
                x1 = vs[ind1].x;
                x2 = vs[ind2].x;
            } else if ( y1 > y2 ) {
                y2 = vs[ind1].y;
                y1 = vs[ind2].y;
                x2 = vs[ind1].x;
                x1 = vs[ind2].x;
            } else {
                continue;
            }
            if ( ( ( y >= y1 ) && ( y < y2 ) ) || ( ( y == max_y ) && ( y > y1 ) && ( y <= y2 ) ) ) {
                polygons[counts++] = ( ( 65536 * ( y - y1 ) ) / ( y2 - y1 ) ) * ( x2 - x1 ) + ( 65536 * x1 );
            }
        }
        std::sort( polygons, polygons + counts );
        result = 0;
        for ( int i = 0; i < counts; i += 2 ) {
            xa = polygons[i+0] + 1;
            xb = polygons[i+1] - 1;
            xa = ( xa >> 16 ) + ( ( xa & 32768 ) >> 15 );
            xb = ( xb >> 16 ) + ( ( xb & 32768 ) >> 15 );
            result |= SDL_RenderDrawLine( _render, xa, y, xb, y );
        }
    }
    delete[] polygons;
    return result;
}
<|endoftext|>


<commit_before>#include <laser_odometry_core/laser_odometry_core.h>

#include <laser_odometry_core/laser_odometry_utils.h>

#include <boost/assign/list_of.hpp>

#define assert_not_null(x) \
  assert(scan_ptr != nullptr && #x ' is nullptr at ' __LINE__);

namespace laser_odometry
{

bool LaserOdometryBase::configure()
{
  reset();

  private_nh_.param("laser_frame",      laser_frame_,      std::string("base_laser_link"));
  private_nh_.param("base_frame",       base_frame_,       std::string("base_link"));
  private_nh_.param("odom_frame",       fixed_frame_,      std::string("odom"));
  private_nh_.param("laser_odom_frame", laser_odom_frame_, std::string("odom"));

  // Default covariance diag :
  std::vector<double> default_covariance;
  private_nh_.param("covariance_diag", default_covariance, default_covariance);

  if (default_covariance.size() != 6)
  {
    ROS_WARN_STREAM("Retrieved " << default_covariance.size()
                    << " covariance coeff. Should be 6. Setting default.");

    default_covariance.resize(6);
    std::fill_n(default_covariance.begin(), 6, 1e-5);
  }

  twist_covariance_ = boost::assign::list_of
               (static_cast<double>(default_covariance[0]))  (0)  (0)  (0)  (0) (0)
               (0)  (static_cast<double>(default_covariance[1]))  (0)  (0)  (0) (0)
               (0)  (0)  (static_cast<double>(default_covariance[2]))  (0)  (0) (0)
               (0)  (0)  (0)  (static_cast<double>(default_covariance[3]))  (0) (0)
               (0)  (0)  (0)  (0)  (static_cast<double>(default_covariance[4])) (0)
               (0)  (0)  (0)  (0)  (0)  (static_cast<double>(default_covariance[5]));

  // Configure derived class
  configured_ = configureImpl();

  return configured_;
}

LaserOdometryBase::ProcessReport
LaserOdometryBase::process(const sensor_msgs::LaserScanConstPtr& scan_msg,
                           geometry_msgs::Pose2DPtr pose_msg,
                           geometry_msgs::Pose2DPtr /*relative_pose_msg*/)
{
  assert_not_null(scan_msg);
  assert_not_null(pose_msg);

  has_new_kf_   = false;
  current_time_ = scan_msg->header.stamp;

  // first message
  if (!initialized_)
  {
    initialized_ = initialize(scan_msg);

    fixed_origin_to_base_ = fixed_origin_ * fixed_to_base_;

    //pose_covariance_ = twist_covariance_;

    fillMsg(pose_msg);

    ROS_INFO_STREAM_COND(initialized_, "LaserOdometry Initialized!");

    return ProcessReport{true, true};
  }

  preProcessing();

  tf::Transform guess_relative_tf_ = predict(relative_tf_);

  // account for the change since the last kf, in the fixed frame
  guess_relative_tf_ = guess_relative_tf_ * (fixed_to_base_ * fixed_to_base_kf_.inverse());

  // the predicted change of the laser's position, in the laser frame
  tf::Transform pred_rel_tf_in_ltf = laser_to_base_ * fixed_to_base_.inverse() *
                                      guess_relative_tf_ * fixed_to_base_ * base_to_laser_ ;

  // The actual computation
  const bool processed = process_impl(scan_msg, pred_rel_tf_in_ltf);

  if (processed)
  {
    // the correction of the base's position, in the base frame
    relative_tf_ = base_to_laser_ * correction_ * laser_to_base_;

    // update the pose in the fixed frame
    fixed_to_base_ = fixed_to_base_kf_ * relative_tf_;

    // update the pose in the fixed 'origin' frame
    fixed_origin_to_base_ = fixed_origin_ * fixed_to_base_;
  }
  else
  {
    relative_tf_.setIdentity();
    ROS_WARN("Error in laser matching");
  }

  // Retrieve pose2D
  fillMsg(pose_msg);

  has_new_kf_ = isKeyFrame(relative_tf_);
  if (has_new_kf_)
  {
    // generate a keyframe

    fixed_to_base_kf_ = fixed_to_base_;

    reference_scan_ = scan_msg;

    isKeyFrame();
  }
  else
    isNotKeyFrame();

  postProcessing();

  return ProcessReport{processed, has_new_kf_};
}

LaserOdometryBase::ProcessReport
LaserOdometryBase::process(const sensor_msgs::LaserScanConstPtr& scan_ptr,
                           nav_msgs::OdometryPtr odom_ptr,
                           nav_msgs::OdometryPtr /*relative_odom_ptr*/)
{
  assert_not_null(scan_ptr);
  assert_not_null(odom_ptr);

  geometry_msgs::Pose2DPtr pose_2d_ptr = boost::make_shared<geometry_msgs::Pose2D>();

  const auto process_report = process(scan_ptr, pose_2d_ptr);

  fillMsg(odom_ptr);

  return process_report;
}

LaserOdometryBase::ProcessReport
LaserOdometryBase::process(const sensor_msgs::PointCloud2ConstPtr& cloud_msg,
                           geometry_msgs::Pose2DPtr pose_msg,
                           geometry_msgs::Pose2DPtr /*relative_pose_ptr*/)
{
  assert_not_null(cloud_msg);
  assert_not_null(pose_msg);

  has_new_kf_   = false;
  current_time_ = cloud_msg->header.stamp;

  // first message
  if (!initialized_)
  {
    initialized_ = initialize(cloud_msg);

    fixed_origin_to_base_ = fixed_origin_ * fixed_to_base_;

    //pose_covariance_ = twist_covariance_;

    fillMsg(pose_msg);

    ROS_INFO_STREAM_COND(initialized_, "LaserOdometry Initialized!");

    return ProcessReport{true, true};
  }

  preProcessing();

  tf::Transform guess_relative_tf_ = predict(relative_tf_);

  // account for the change since the last kf, in the fixed frame
  guess_relative_tf_ = guess_relative_tf_ * (fixed_to_base_ * fixed_to_base_kf_.inverse());

  // the predicted change of the laser's position, in the laser frame
  tf::Transform pred_rel_tf_in_ltf = laser_to_base_ * fixed_to_base_.inverse() *
                                      guess_relative_tf_ * fixed_to_base_ * base_to_laser_ ;

  // The actual computation
  const bool processed = process_impl(cloud_msg, pred_rel_tf_in_ltf);

  if (processed)
  {
    // the correction of the base's position, in the base frame
    relative_tf_ = base_to_laser_ * correction_ * laser_to_base_;

    // update the pose in the fixed frame
    fixed_to_base_ = fixed_to_base_kf_ * relative_tf_;

    // update the pose in the fixed 'origin' frame
    fixed_origin_to_base_ = fixed_origin_ * fixed_to_base_;
  }
  else
  {
    relative_tf_.setIdentity();
    ROS_WARN("Error in laser matching");
  }

  // Retrieve pose2D
  fillMsg(pose_msg);

  has_new_kf_ = isKeyFrame(correction_);

  if (has_new_kf_)
  {
    // generate a keyframe
    fixed_to_base_kf_ = fixed_to_base_;

    reference_cloud_ = cloud_msg;

    isKeyFrame();
  }
  else
    isNotKeyFrame();

  postProcessing();

  return ProcessReport{processed, has_new_kf_};
}

LaserOdometryBase::ProcessReport
LaserOdometryBase::process(const sensor_msgs::PointCloud2ConstPtr& cloud_msg,
                           nav_msgs::OdometryPtr odom_ptr,
                           nav_msgs::OdometryPtr /*relative_odom_ptr*/)
{
  assert_not_null(cloud_msg);
  assert_not_null(odom_ptr);

  geometry_msgs::Pose2DPtr pose_2d_ptr = boost::make_shared<geometry_msgs::Pose2D>();

  const auto process_report = process(cloud_msg, pose_2d_ptr);

  fillMsg(odom_ptr);

  return process_report;
}

bool LaserOdometryBase::process_impl(const sensor_msgs::LaserScanConstPtr& /*laser_msg*/,
                                     const tf::Transform& /*prediction*/)
{
  throw std::runtime_error("process_impl(sensor_msgs::LaserScanConstPtr) not implemented.");
}

bool LaserOdometryBase::process_impl(const sensor_msgs::PointCloud2ConstPtr& /*cloud_msg*/,
                                     const tf::Transform& /*prediction*/)
{
  throw std::runtime_error("process_impl(sensor_msgs::PointCloud2ConstPtr) not implemented.");
}

const tf::Transform& LaserOdometryBase::getEstimatedPose() const noexcept
{
  return fixed_origin_to_base_;
}

void LaserOdometryBase::reset()
{
  correction_        = tf::Transform::getIdentity();

  base_to_laser_     = tf::Transform::getIdentity();
  laser_to_base_     = tf::Transform::getIdentity();
  relative_tf_       = tf::Transform::getIdentity();
  fixed_origin_      = tf::Transform::getIdentity();
  fixed_to_base_     = tf::Transform::getIdentity();
  guess_relative_tf_ = tf::Transform::getIdentity();
  fixed_to_base_kf_  = tf::Transform::getIdentity();

  reference_scan_  = nullptr;
  reference_cloud_ = nullptr;
}

bool LaserOdometryBase::configured() const noexcept
{
  return configured_;
}

bool LaserOdometryBase::configureImpl()
{
  return true;
}

bool LaserOdometryBase::initialize(const sensor_msgs::LaserScanConstPtr&   /*scan_msg*/)
{
  return true;
}

bool LaserOdometryBase::initialize(const sensor_msgs::PointCloud2ConstPtr& /*cloud_msg*/)
{
  return true;
}

tf::Transform LaserOdometryBase::predict(const tf::Transform& /*tf*/)
{
  return tf::Transform::getIdentity();
}

void LaserOdometryBase::preProcessing()
{

}

void LaserOdometryBase::postProcessing()
{

}

bool LaserOdometryBase::isKeyFrame(const tf::Transform& /*correction*/)
{
  return true;
}

void LaserOdometryBase::isKeyFrame()
{

}

void LaserOdometryBase::isNotKeyFrame()
{

}

OdomType LaserOdometryBase::odomType() const noexcept
{
  ROS_WARN("odomType() function called but not overloaded!");
  return OdomType::Unknown;
}

bool LaserOdometryBase::hasNewKeyFrame() const noexcept
{
  return has_new_kf_;
}

void LaserOdometryBase::getKeyFrame(sensor_msgs::LaserScanConstPtr& kframe) const noexcept
{
  kframe = reference_scan_;
}

void LaserOdometryBase::getKeyFrame(sensor_msgs::PointCloud2ConstPtr& kframe) const noexcept
{
  kframe = reference_cloud_;
}

////////////////////////
///                  ///
/// Guetter / Setter ///
///                  ///
////////////////////////

tf::Transform& LaserOdometryBase::getOrigin()
{
  return fixed_origin_;
}

const tf::Transform& LaserOdometryBase::getOrigin() const
{
  return fixed_origin_;
}

void LaserOdometryBase::setOrigin(const tf::Transform& origin)
{
  fixed_origin_ = origin;
}

tf::Transform& LaserOdometryBase::getInitialGuess()
{
  return guess_relative_tf_;
}

const tf::Transform& LaserOdometryBase::getInitialGuess() const
{
  return guess_relative_tf_;
}

void LaserOdometryBase::setInitialGuess(const tf::Transform& guess)
{
  guess_relative_tf_ = guess;
}

tf::Transform& LaserOdometryBase::getLaserPose()
{
  return base_to_laser_;
}

const tf::Transform& LaserOdometryBase::getLaserPose() const
{
  return base_to_laser_;
}

void LaserOdometryBase::setLaserPose(const tf::Transform& base_to_laser)
{
  base_to_laser_ = base_to_laser;
  laser_to_base_ = base_to_laser.inverse();
}

const std::string& LaserOdometryBase::getFrameBase()  const noexcept
{
  return base_frame_;
}

const std::string& LaserOdometryBase::getFrameLaser() const noexcept
{
  return laser_frame_;
}

const std::string& LaserOdometryBase::getFrameFixed() const noexcept
{
  return fixed_frame_;
}

const std::string& LaserOdometryBase::getFrameOdom()  const noexcept
{
  return laser_odom_frame_;
}

void LaserOdometryBase::setFrameBase(const std::string& frame)
{
  base_frame_ = frame;
}

void LaserOdometryBase::setFrameLaser(const std::string& frame)
{
  laser_frame_ = frame;
}

void LaserOdometryBase::setFrameFixed(const std::string& frame)
{
  fixed_frame_ = frame;
}

void LaserOdometryBase::setFrameOdom(const std::string& frame)
{
  laser_odom_frame_ = frame;
}

const ros::Time& LaserOdometryBase::getCurrentTime() const noexcept
{
  return current_time_;
}

} /* namespace laser_odometry */
<commit_msg>fix macro<commit_after>#include <laser_odometry_core/laser_odometry_core.h>

#include <laser_odometry_core/laser_odometry_utils.h>

#include <boost/assign/list_of.hpp>

#define assert_not_null(x) \
  assert(x != nullptr && #x ' is nullptr at ' __LINE__);

namespace laser_odometry
{

bool LaserOdometryBase::configure()
{
  reset();

  private_nh_.param("laser_frame",      laser_frame_,      std::string("base_laser_link"));
  private_nh_.param("base_frame",       base_frame_,       std::string("base_link"));
  private_nh_.param("odom_frame",       fixed_frame_,      std::string("odom"));
  private_nh_.param("laser_odom_frame", laser_odom_frame_, std::string("odom"));

  // Default covariance diag :
  std::vector<double> default_covariance;
  private_nh_.param("covariance_diag", default_covariance, default_covariance);

  if (default_covariance.size() != 6)
  {
    ROS_WARN_STREAM("Retrieved " << default_covariance.size()
                    << " covariance coeff. Should be 6. Setting default.");

    default_covariance.resize(6);
    std::fill_n(default_covariance.begin(), 6, 1e-5);
  }

  twist_covariance_ = boost::assign::list_of
               (static_cast<double>(default_covariance[0]))  (0)  (0)  (0)  (0) (0)
               (0)  (static_cast<double>(default_covariance[1]))  (0)  (0)  (0) (0)
               (0)  (0)  (static_cast<double>(default_covariance[2]))  (0)  (0) (0)
               (0)  (0)  (0)  (static_cast<double>(default_covariance[3]))  (0) (0)
               (0)  (0)  (0)  (0)  (static_cast<double>(default_covariance[4])) (0)
               (0)  (0)  (0)  (0)  (0)  (static_cast<double>(default_covariance[5]));

  // Configure derived class
  configured_ = configureImpl();

  return configured_;
}

LaserOdometryBase::ProcessReport
LaserOdometryBase::process(const sensor_msgs::LaserScanConstPtr& scan_msg,
                           geometry_msgs::Pose2DPtr pose_msg,
                           geometry_msgs::Pose2DPtr /*relative_pose_msg*/)
{
  assert_not_null(scan_msg);
  assert_not_null(pose_msg);

  has_new_kf_   = false;
  current_time_ = scan_msg->header.stamp;

  // first message
  if (!initialized_)
  {
    initialized_ = initialize(scan_msg);

    fixed_origin_to_base_ = fixed_origin_ * fixed_to_base_;

    //pose_covariance_ = twist_covariance_;

    fillMsg(pose_msg);

    ROS_INFO_STREAM_COND(initialized_, "LaserOdometry Initialized!");

    return ProcessReport{true, true};
  }

  preProcessing();

  tf::Transform guess_relative_tf_ = predict(relative_tf_);

  // account for the change since the last kf, in the fixed frame
  guess_relative_tf_ = guess_relative_tf_ * (fixed_to_base_ * fixed_to_base_kf_.inverse());

  // the predicted change of the laser's position, in the laser frame
  tf::Transform pred_rel_tf_in_ltf = laser_to_base_ * fixed_to_base_.inverse() *
                                      guess_relative_tf_ * fixed_to_base_ * base_to_laser_ ;

  // The actual computation
  const bool processed = process_impl(scan_msg, pred_rel_tf_in_ltf);

  if (processed)
  {
    // the correction of the base's position, in the base frame
    relative_tf_ = base_to_laser_ * correction_ * laser_to_base_;

    // update the pose in the fixed frame
    fixed_to_base_ = fixed_to_base_kf_ * relative_tf_;

    // update the pose in the fixed 'origin' frame
    fixed_origin_to_base_ = fixed_origin_ * fixed_to_base_;
  }
  else
  {
    relative_tf_.setIdentity();
    ROS_WARN("Error in laser matching");
  }

  // Retrieve pose2D
  fillMsg(pose_msg);

  has_new_kf_ = isKeyFrame(relative_tf_);
  if (has_new_kf_)
  {
    // generate a keyframe

    fixed_to_base_kf_ = fixed_to_base_;

    reference_scan_ = scan_msg;

    isKeyFrame();
  }
  else
    isNotKeyFrame();

  postProcessing();

  return ProcessReport{processed, has_new_kf_};
}

LaserOdometryBase::ProcessReport
LaserOdometryBase::process(const sensor_msgs::LaserScanConstPtr& scan_ptr,
                           nav_msgs::OdometryPtr odom_ptr,
                           nav_msgs::OdometryPtr /*relative_odom_ptr*/)
{
  assert_not_null(scan_ptr);
  assert_not_null(odom_ptr);

  geometry_msgs::Pose2DPtr pose_2d_ptr = boost::make_shared<geometry_msgs::Pose2D>();

  const auto process_report = process(scan_ptr, pose_2d_ptr);

  fillMsg(odom_ptr);

  return process_report;
}

LaserOdometryBase::ProcessReport
LaserOdometryBase::process(const sensor_msgs::PointCloud2ConstPtr& cloud_msg,
                           geometry_msgs::Pose2DPtr pose_msg,
                           geometry_msgs::Pose2DPtr /*relative_pose_ptr*/)
{
  assert_not_null(cloud_msg);
  assert_not_null(pose_msg);

  has_new_kf_   = false;
  current_time_ = cloud_msg->header.stamp;

  // first message
  if (!initialized_)
  {
    initialized_ = initialize(cloud_msg);

    fixed_origin_to_base_ = fixed_origin_ * fixed_to_base_;

    //pose_covariance_ = twist_covariance_;

    fillMsg(pose_msg);

    ROS_INFO_STREAM_COND(initialized_, "LaserOdometry Initialized!");

    return ProcessReport{true, true};
  }

  preProcessing();

  tf::Transform guess_relative_tf_ = predict(relative_tf_);

  // account for the change since the last kf, in the fixed frame
  guess_relative_tf_ = guess_relative_tf_ * (fixed_to_base_ * fixed_to_base_kf_.inverse());

  // the predicted change of the laser's position, in the laser frame
  tf::Transform pred_rel_tf_in_ltf = laser_to_base_ * fixed_to_base_.inverse() *
                                      guess_relative_tf_ * fixed_to_base_ * base_to_laser_ ;

  // The actual computation
  const bool processed = process_impl(cloud_msg, pred_rel_tf_in_ltf);

  if (processed)
  {
    // the correction of the base's position, in the base frame
    relative_tf_ = base_to_laser_ * correction_ * laser_to_base_;

    // update the pose in the fixed frame
    fixed_to_base_ = fixed_to_base_kf_ * relative_tf_;

    // update the pose in the fixed 'origin' frame
    fixed_origin_to_base_ = fixed_origin_ * fixed_to_base_;
  }
  else
  {
    relative_tf_.setIdentity();
    ROS_WARN("Error in laser matching");
  }

  // Retrieve pose2D
  fillMsg(pose_msg);

  has_new_kf_ = isKeyFrame(correction_);

  if (has_new_kf_)
  {
    // generate a keyframe
    fixed_to_base_kf_ = fixed_to_base_;

    reference_cloud_ = cloud_msg;

    isKeyFrame();
  }
  else
    isNotKeyFrame();

  postProcessing();

  return ProcessReport{processed, has_new_kf_};
}

LaserOdometryBase::ProcessReport
LaserOdometryBase::process(const sensor_msgs::PointCloud2ConstPtr& cloud_msg,
                           nav_msgs::OdometryPtr odom_ptr,
                           nav_msgs::OdometryPtr /*relative_odom_ptr*/)
{
  assert_not_null(cloud_msg);
  assert_not_null(odom_ptr);

  geometry_msgs::Pose2DPtr pose_2d_ptr = boost::make_shared<geometry_msgs::Pose2D>();

  const auto process_report = process(cloud_msg, pose_2d_ptr);

  fillMsg(odom_ptr);

  return process_report;
}

bool LaserOdometryBase::process_impl(const sensor_msgs::LaserScanConstPtr& /*laser_msg*/,
                                     const tf::Transform& /*prediction*/)
{
  throw std::runtime_error("process_impl(sensor_msgs::LaserScanConstPtr) not implemented.");
}

bool LaserOdometryBase::process_impl(const sensor_msgs::PointCloud2ConstPtr& /*cloud_msg*/,
                                     const tf::Transform& /*prediction*/)
{
  throw std::runtime_error("process_impl(sensor_msgs::PointCloud2ConstPtr) not implemented.");
}

const tf::Transform& LaserOdometryBase::getEstimatedPose() const noexcept
{
  return fixed_origin_to_base_;
}

void LaserOdometryBase::reset()
{
  correction_        = tf::Transform::getIdentity();

  base_to_laser_     = tf::Transform::getIdentity();
  laser_to_base_     = tf::Transform::getIdentity();
  relative_tf_       = tf::Transform::getIdentity();
  fixed_origin_      = tf::Transform::getIdentity();
  fixed_to_base_     = tf::Transform::getIdentity();
  guess_relative_tf_ = tf::Transform::getIdentity();
  fixed_to_base_kf_  = tf::Transform::getIdentity();

  reference_scan_  = nullptr;
  reference_cloud_ = nullptr;
}

bool LaserOdometryBase::configured() const noexcept
{
  return configured_;
}

bool LaserOdometryBase::configureImpl()
{
  return true;
}

bool LaserOdometryBase::initialize(const sensor_msgs::LaserScanConstPtr&   /*scan_msg*/)
{
  return true;
}

bool LaserOdometryBase::initialize(const sensor_msgs::PointCloud2ConstPtr& /*cloud_msg*/)
{
  return true;
}

tf::Transform LaserOdometryBase::predict(const tf::Transform& /*tf*/)
{
  return tf::Transform::getIdentity();
}

void LaserOdometryBase::preProcessing()
{

}

void LaserOdometryBase::postProcessing()
{

}

bool LaserOdometryBase::isKeyFrame(const tf::Transform& /*correction*/)
{
  return true;
}

void LaserOdometryBase::isKeyFrame()
{

}

void LaserOdometryBase::isNotKeyFrame()
{

}

OdomType LaserOdometryBase::odomType() const noexcept
{
  ROS_WARN("odomType() function called but not overloaded!");
  return OdomType::Unknown;
}

bool LaserOdometryBase::hasNewKeyFrame() const noexcept
{
  return has_new_kf_;
}

void LaserOdometryBase::getKeyFrame(sensor_msgs::LaserScanConstPtr& kframe) const noexcept
{
  kframe = reference_scan_;
}

void LaserOdometryBase::getKeyFrame(sensor_msgs::PointCloud2ConstPtr& kframe) const noexcept
{
  kframe = reference_cloud_;
}

////////////////////////
///                  ///
/// Guetter / Setter ///
///                  ///
////////////////////////

tf::Transform& LaserOdometryBase::getOrigin()
{
  return fixed_origin_;
}

const tf::Transform& LaserOdometryBase::getOrigin() const
{
  return fixed_origin_;
}

void LaserOdometryBase::setOrigin(const tf::Transform& origin)
{
  fixed_origin_ = origin;
}

tf::Transform& LaserOdometryBase::getInitialGuess()
{
  return guess_relative_tf_;
}

const tf::Transform& LaserOdometryBase::getInitialGuess() const
{
  return guess_relative_tf_;
}

void LaserOdometryBase::setInitialGuess(const tf::Transform& guess)
{
  guess_relative_tf_ = guess;
}

tf::Transform& LaserOdometryBase::getLaserPose()
{
  return base_to_laser_;
}

const tf::Transform& LaserOdometryBase::getLaserPose() const
{
  return base_to_laser_;
}

void LaserOdometryBase::setLaserPose(const tf::Transform& base_to_laser)
{
  base_to_laser_ = base_to_laser;
  laser_to_base_ = base_to_laser.inverse();
}

const std::string& LaserOdometryBase::getFrameBase()  const noexcept
{
  return base_frame_;
}

const std::string& LaserOdometryBase::getFrameLaser() const noexcept
{
  return laser_frame_;
}

const std::string& LaserOdometryBase::getFrameFixed() const noexcept
{
  return fixed_frame_;
}

const std::string& LaserOdometryBase::getFrameOdom()  const noexcept
{
  return laser_odom_frame_;
}

void LaserOdometryBase::setFrameBase(const std::string& frame)
{
  base_frame_ = frame;
}

void LaserOdometryBase::setFrameLaser(const std::string& frame)
{
  laser_frame_ = frame;
}

void LaserOdometryBase::setFrameFixed(const std::string& frame)
{
  fixed_frame_ = frame;
}

void LaserOdometryBase::setFrameOdom(const std::string& frame)
{
  laser_odom_frame_ = frame;
}

const ros::Time& LaserOdometryBase::getCurrentTime() const noexcept
{
  return current_time_;
}

} /* namespace laser_odometry */
<|endoftext|>


<commit_before>/*

Copyright (c) 2003, Arvid Norberg
All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:

    * Redistributions of source code must retain the above copyright
      notice, this list of conditions and the following disclaimer.
    * Redistributions in binary form must reproduce the above copyright
      notice, this list of conditions and the following disclaimer in
      the documentation and/or other materials provided with the distribution.
    * Neither the name of the author nor the names of its
      contributors may be used to endorse or promote products derived
      from this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.

*/

#include "libtorrent/pch.hpp"

#ifdef _WIN32
// windows part
#include "libtorrent/utf8.hpp"

#include <io.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <sys/types.h>

#ifndef _MODE_T_
typedef int mode_t;
#endif

#ifdef UNICODE
#include "libtorrent/storage.hpp"
#endif

#else
// unix part
#define _FILE_OFFSET_BITS 64
#include <unistd.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <errno.h>

#include <boost/static_assert.hpp>
// make sure the _FILE_OFFSET_BITS define worked
// on this platform
BOOST_STATIC_ASSERT(sizeof(lseek(0, 0, 0)) >= 8);

#endif

#include <boost/filesystem/operations.hpp>
#include "libtorrent/file.hpp"
#include <sstream>

#ifndef O_BINARY
#define O_BINARY 0
#endif

#ifndef O_RANDOM
#define O_RANDOM 0
#endif

#ifdef UNICODE
#include "libtorrent/storage.hpp"
#endif

namespace fs = boost::filesystem;

namespace
{
	enum { mode_in = 1, mode_out = 2 };

	mode_t map_open_mode(int m)
	{
		if (m == (mode_in | mode_out)) return O_RDWR | O_CREAT | O_BINARY | O_RANDOM;
		if (m == mode_out) return O_WRONLY | O_CREAT | O_BINARY | O_RANDOM;
		if (m == mode_in) return O_RDONLY | O_BINARY | O_RANDOM;
		assert(false);
		return 0;
	}

#ifdef WIN32
	std::string utf8_native(std::string const& s)
	{
		try
		{
			std::wstring ws;
			libtorrent::utf8_wchar(s, ws);
			std::size_t size = wcstombs(0, ws.c_str(), 0);
			if (size == std::size_t(-1)) return s;
			std::string ret;
			ret.resize(size);
			size = wcstombs(&ret[0], ws.c_str(), size + 1);
			if (size == wchar_t(-1)) return s;
			ret.resize(size);
			return ret;
		}
		catch(std::exception)
		{
			return s;
		}
	}
#else
	std::string utf8_native(std::string const& s)
	{
		return s;
	}
#endif

}

namespace libtorrent
{

	const file::open_mode file::in(mode_in);
	const file::open_mode file::out(mode_out);

	const file::seek_mode file::begin(1);
	const file::seek_mode file::end(2);

	struct file::impl
	{
		impl()
			: m_fd(-1)
			, m_open_mode(0)
		{}

		impl(fs::path const& path, int mode)
			: m_fd(-1)
			, m_open_mode(0)
		{
			open(path, mode);
		}

		~impl()
		{
			close();
		}

		void open(fs::path const& path, int mode)
		{
			assert(path.is_complete());
			close();
#if defined(_WIN32) && defined(UNICODE)
			std::wstring wpath(safe_convert(path.native_file_string()));
			m_fd = ::_wopen(
				wpath.c_str()
				, map_open_mode(mode)
				, S_IREAD | S_IWRITE);
#else
#ifdef _WIN32
			m_fd = ::_open(
#else
			m_fd = ::open(
#endif
				utf8_native(path.native_file_string()).c_str()
				, map_open_mode(mode)
#ifdef _WIN32
				, S_IREAD | S_IWRITE);
#else
				, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
#endif
#endif
			if (m_fd == -1)
			{
				std::stringstream msg;
				msg << "open failed: '" << path.native_file_string() << "'. "
					<< strerror(errno);
				throw file_error(msg.str());
			}
			m_open_mode = mode;
		}

		void close()
		{
			if (m_fd == -1) return;

#ifdef _WIN32
			::_close(m_fd);
#else
			::close(m_fd);
#endif
			m_fd = -1;
			m_open_mode = 0;
		}

		size_type read(char* buf, size_type num_bytes)
		{
			assert(num_bytes > 0);
			assert(m_open_mode & mode_in);
			assert(m_fd != -1);

#ifdef _WIN32
			size_type ret = ::_read(m_fd, buf, num_bytes);
#else
			size_type ret = ::read(m_fd, buf, num_bytes);
#endif
			if (ret == -1 || ret == 0)
			{
				std::stringstream msg;
				msg << "read failed: " << strerror(errno);
				throw file_error(msg.str());
			}
			return ret;
		}

		size_type write(const char* buf, size_type num_bytes)
		{
			assert(m_open_mode & mode_out);
			assert(m_fd != -1);

			// TODO: Test this a bit more, what happens with random failures in
			// the files?
//			if ((rand() % 100) > 80)
//				throw file_error("debug");

#ifdef _WIN32
			size_type ret = ::_write(m_fd, buf, num_bytes);
#else
			size_type ret = ::write(m_fd, buf, num_bytes);
#endif
			if (ret == -1)
			{
				std::stringstream msg;
				msg << "write failed: " << strerror(errno);
				throw file_error(msg.str());
			}
			return ret;
		}

		size_type seek(size_type offset, int m)
		{
			assert(m_open_mode);
			assert(m_fd != -1);

			int seekdir = (m == 1)?SEEK_SET:SEEK_END;
#ifdef _WIN32
			size_type ret = _lseeki64(m_fd, offset, seekdir);
#else
			size_type ret = lseek(m_fd, offset, seekdir);
#endif

			// For some strange reason this fails
			// on win32. Use windows specific file
			// wrapper instead.
			if (ret == -1)
			{
				std::stringstream msg;
				msg << "seek failed: '" << strerror(errno)
					<< "' fd: " << m_fd
					<< " offset: " << offset
					<< " seekdir: " << seekdir;
				throw file_error(msg.str());
			}
			return ret;
		}

		size_type tell()
		{
			assert(m_open_mode);
			assert(m_fd != -1);

#ifdef _WIN32
			return _telli64(m_fd);
#else
			return lseek(m_fd, 0, SEEK_CUR);
#endif
		}

		int m_fd;
		int m_open_mode;
	};

	// pimpl forwardings

	file::file() : m_impl(new impl()) {}

	file::file(boost::filesystem::path const& p, file::open_mode m)
		: m_impl(new impl(p, m.m_mask))
	{}

	file::~file() {}

	void file::open(boost::filesystem::path const& p, file::open_mode m)
	{
		m_impl->open(p, m.m_mask);
	}

	void file::close()
	{
		m_impl->close();
	}

	size_type file::write(const char* buf, size_type num_bytes)
	{
		return m_impl->write(buf, num_bytes);
	}

	size_type file::read(char* buf, size_type num_bytes)
	{
		return m_impl->read(buf, num_bytes);
	}

	size_type file::seek(size_type pos, file::seek_mode m)
	{
		return m_impl->seek(pos, m.m_val);
	}

	size_type file::tell()
	{
		return m_impl->tell();
	}

}
<commit_msg>reverted last check-in<commit_after>/*

Copyright (c) 2003, Arvid Norberg
All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:

    * Redistributions of source code must retain the above copyright
      notice, this list of conditions and the following disclaimer.
    * Redistributions in binary form must reproduce the above copyright
      notice, this list of conditions and the following disclaimer in
      the documentation and/or other materials provided with the distribution.
    * Neither the name of the author nor the names of its
      contributors may be used to endorse or promote products derived
      from this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.

*/

#include "libtorrent/pch.hpp"

#ifdef _WIN32
// windows part
#include "libtorrent/utf8.hpp"

#include <io.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <sys/types.h>

#ifndef _MODE_T_
typedef int mode_t;
#endif

#ifdef UNICODE
#include "libtorrent/storage.hpp"
#endif

#else
// unix part
#define _FILE_OFFSET_BITS 64
#include <unistd.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <errno.h>

#include <boost/static_assert.hpp>
// make sure the _FILE_OFFSET_BITS define worked
// on this platform
BOOST_STATIC_ASSERT(sizeof(lseek(0, 0, 0)) >= 8);

#endif

#include <boost/filesystem/operations.hpp>
#include "libtorrent/file.hpp"
#include <sstream>

#ifndef O_BINARY
#define O_BINARY 0
#endif

#ifndef O_RANDOM
#define O_RANDOM 0
#endif

#ifdef UNICODE
#include "libtorrent/storage.hpp"
#endif

namespace fs = boost::filesystem;

namespace
{
	enum { mode_in = 1, mode_out = 2 };

	mode_t map_open_mode(int m)
	{
		if (m == (mode_in | mode_out)) return O_RDWR | O_CREAT | O_BINARY | O_RANDOM;
		if (m == mode_out) return O_WRONLY | O_CREAT | O_BINARY | O_RANDOM;
		if (m == mode_in) return O_RDONLY | O_BINARY | O_RANDOM;
		assert(false);
		return 0;
	}

#ifdef WIN32
	std::string utf8_native(std::string const& s)
	{
		try
		{
			std::wstring ws;
			libtorrent::utf8_wchar(s, ws);
			std::size_t size = wcstombs(0, ws.c_str(), 0);
			if (size == std::size_t(-1)) return s;
			std::string ret;
			ret.resize(size);
			size = wcstombs(&ret[0], ws.c_str(), size + 1);
			if (size == wchar_t(-1)) return s;
			ret.resize(size);
			return ret;
		}
		catch(std::exception)
		{
			return s;
		}
	}
#else
	std::string utf8_native(std::string const& s)
	{
		return s;
	}
#endif

}

namespace libtorrent
{

	const file::open_mode file::in(mode_in);
	const file::open_mode file::out(mode_out);

	const file::seek_mode file::begin(1);
	const file::seek_mode file::end(2);

	struct file::impl
	{
		impl()
			: m_fd(-1)
			, m_open_mode(0)
		{}

		impl(fs::path const& path, int mode)
			: m_fd(-1)
			, m_open_mode(0)
		{
			open(path, mode);
		}

		~impl()
		{
			close();
		}

		void open(fs::path const& path, int mode)
		{
			assert(path.is_complete());
			close();
#if defined(_WIN32) && defined(UNICODE)
			std::wstring wpath(safe_convert(path.native_file_string()));
			m_fd = ::_wopen(
				wpath.c_str()
				, map_open_mode(mode)
				, S_IREAD | S_IWRITE);
#else
#ifdef _WIN32
			m_fd = ::_open(
#else
			m_fd = ::open(
#endif
				utf8_native(path.native_file_string()).c_str()
				, map_open_mode(mode)
#ifdef _WIN32
				, S_IREAD | S_IWRITE);
#else
				, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
#endif
#endif
			if (m_fd == -1)
			{
				std::stringstream msg;
				msg << "open failed: '" << path.native_file_string() << "'. "
					<< strerror(errno);
				throw file_error(msg.str());
			}
			m_open_mode = mode;
		}

		void close()
		{
			if (m_fd == -1) return;

#ifdef _WIN32
			::_close(m_fd);
#else
			::close(m_fd);
#endif
			m_fd = -1;
			m_open_mode = 0;
		}

		size_type read(char* buf, size_type num_bytes)
		{
			assert(m_open_mode & mode_in);
			assert(m_fd != -1);

#ifdef _WIN32
			size_type ret = ::_read(m_fd, buf, num_bytes);
#else
			size_type ret = ::read(m_fd, buf, num_bytes);
#endif
			if (ret == -1)
			{
				std::stringstream msg;
				msg << "read failed: " << strerror(errno);
				throw file_error(msg.str());
			}
			return ret;
		}

		size_type write(const char* buf, size_type num_bytes)
		{
			assert(m_open_mode & mode_out);
			assert(m_fd != -1);

			// TODO: Test this a bit more, what happens with random failures in
			// the files?
//			if ((rand() % 100) > 80)
//				throw file_error("debug");

#ifdef _WIN32
			size_type ret = ::_write(m_fd, buf, num_bytes);
#else
			size_type ret = ::write(m_fd, buf, num_bytes);
#endif
			if (ret == -1)
			{
				std::stringstream msg;
				msg << "write failed: " << strerror(errno);
				throw file_error(msg.str());
			}
			return ret;
		}

		size_type seek(size_type offset, int m)
		{
			assert(m_open_mode);
			assert(m_fd != -1);

			int seekdir = (m == 1)?SEEK_SET:SEEK_END;
#ifdef _WIN32
			size_type ret = _lseeki64(m_fd, offset, seekdir);
#else
			size_type ret = lseek(m_fd, offset, seekdir);
#endif

			// For some strange reason this fails
			// on win32. Use windows specific file
			// wrapper instead.
			if (ret == -1)
			{
				std::stringstream msg;
				msg << "seek failed: '" << strerror(errno)
					<< "' fd: " << m_fd
					<< " offset: " << offset
					<< " seekdir: " << seekdir;
				throw file_error(msg.str());
			}
			return ret;
		}

		size_type tell()
		{
			assert(m_open_mode);
			assert(m_fd != -1);

#ifdef _WIN32
			return _telli64(m_fd);
#else
			return lseek(m_fd, 0, SEEK_CUR);
#endif
		}

		int m_fd;
		int m_open_mode;
	};

	// pimpl forwardings

	file::file() : m_impl(new impl()) {}

	file::file(boost::filesystem::path const& p, file::open_mode m)
		: m_impl(new impl(p, m.m_mask))
	{}

	file::~file() {}

	void file::open(boost::filesystem::path const& p, file::open_mode m)
	{
		m_impl->open(p, m.m_mask);
	}

	void file::close()
	{
		m_impl->close();
	}

	size_type file::write(const char* buf, size_type num_bytes)
	{
		return m_impl->write(buf, num_bytes);
	}

	size_type file::read(char* buf, size_type num_bytes)
	{
		return m_impl->read(buf, num_bytes);
	}

	size_type file::seek(size_type pos, file::seek_mode m)
	{
		return m_impl->seek(pos, m.m_val);
	}

	size_type file::tell()
	{
		return m_impl->tell();
	}

}
<|endoftext|>


<commit_before>/*

Copyright (c) 2003, Arvid Norberg
All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:

    * Redistributions of source code must retain the above copyright
      notice, this list of conditions and the following disclaimer.
    * Redistributions in binary form must reproduce the above copyright
      notice, this list of conditions and the following disclaimer in
      the documentation and/or other materials provided with the distribution.
    * Neither the name of the author nor the names of its
      contributors may be used to endorse or promote products derived
      from this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.

*/

#include "libtorrent/pch.hpp"

#ifdef _WIN32
// windows part
#include "libtorrent/utf8.hpp"

#include <io.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <sys/types.h>

#ifndef _MODE_T_
typedef int mode_t;
#endif

#ifdef UNICODE
#include "libtorrent/storage.hpp"
#endif

#else
// unix part
#define _FILE_OFFSET_BITS 64
#include <unistd.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <errno.h>

#include <boost/static_assert.hpp>
// make sure the _FILE_OFFSET_BITS define worked
// on this platform
BOOST_STATIC_ASSERT(sizeof(lseek(0, 0, 0)) >= 8);

#endif

#include <boost/filesystem/operations.hpp>
#include "libtorrent/file.hpp"
#include <sstream>

#ifndef O_BINARY
#define O_BINARY 0
#endif

#ifndef O_RANDOM
#define O_RANDOM 0
#endif

#ifdef UNICODE
#include "libtorrent/storage.hpp"
#endif

#include "libtorrent/assert.hpp"

namespace
{
	enum { mode_in = 1, mode_out = 2 };

	mode_t map_open_mode(int m)
	{
		if (m == (mode_in | mode_out)) return O_RDWR | O_CREAT | O_BINARY | O_RANDOM;
		if (m == mode_out) return O_WRONLY | O_CREAT | O_BINARY | O_RANDOM;
		if (m == mode_in) return O_RDONLY | O_BINARY | O_RANDOM;
		TORRENT_ASSERT(false);
		return 0;
	}

#ifdef WIN32
	std::string utf8_native(std::string const& s)
	{
		try
		{
			std::wstring ws;
			libtorrent::utf8_wchar(s, ws);
			std::size_t size = wcstombs(0, ws.c_str(), 0);
			if (size == std::size_t(-1)) return s;
			std::string ret;
			ret.resize(size);
			size = wcstombs(&ret[0], ws.c_str(), size + 1);
			if (size == wchar_t(-1)) return s;
			ret.resize(size);
			return ret;
		}
		catch(std::exception)
		{
			return s;
		}
	}
#else
	std::string utf8_native(std::string const& s)
	{
		return s;
	}
#endif

}

namespace libtorrent
{

	namespace fs = boost::filesystem;

	const file::open_mode file::in(mode_in);
	const file::open_mode file::out(mode_out);

	const file::seek_mode file::begin(1);
	const file::seek_mode file::end(2);

	struct file::impl
	{
		impl()
			: m_fd(-1)
			, m_open_mode(0)
		{}

		impl(fs::path const& path, int mode)
			: m_fd(-1)
			, m_open_mode(0)
		{
			open(path, mode);
		}

		~impl()
		{
			close();
		}

		void open(fs::path const& path, int mode)
		{
			TORRENT_ASSERT(path.is_complete());
			close();
#if defined(_WIN32) && defined(UNICODE)
			std::wstring wpath(safe_convert(path.native_file_string()));
			m_fd = ::_wopen(
				wpath.c_str()
				, map_open_mode(mode)
				, S_IREAD | S_IWRITE);
#else
#ifdef _WIN32
			m_fd = ::_open(
#else
			m_fd = ::open(
#endif
				utf8_native(path.native_file_string()).c_str()
				, map_open_mode(mode)
#ifdef _WIN32
				, S_IREAD | S_IWRITE);
#else
				, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
#endif
#endif
			if (m_fd == -1)
			{
				std::stringstream msg;
				msg << "open failed: '" << path.native_file_string() << "'. "
					<< strerror(errno);
				throw file_error(msg.str());
			}
			m_open_mode = mode;
		}

		void close()
		{
			if (m_fd == -1) return;

#ifdef _WIN32
			::_close(m_fd);
#else
			::close(m_fd);
#endif
			m_fd = -1;
			m_open_mode = 0;
		}

		size_type read(char* buf, size_type num_bytes)
		{
			TORRENT_ASSERT(m_open_mode & mode_in);
			TORRENT_ASSERT(m_fd != -1);

#ifdef _WIN32
			size_type ret = ::_read(m_fd, buf, num_bytes);
#else
			size_type ret = ::read(m_fd, buf, num_bytes);
#endif
			if (ret == -1)
			{
				std::stringstream msg;
				msg << "read failed: " << strerror(errno);
				throw file_error(msg.str());
			}
			return ret;
		}

		size_type write(const char* buf, size_type num_bytes)
		{
			TORRENT_ASSERT(m_open_mode & mode_out);
			TORRENT_ASSERT(m_fd != -1);

			// TODO: Test this a bit more, what happens with random failures in
			// the files?
//			if ((rand() % 100) > 80)
//				throw file_error("debug");

#ifdef _WIN32
			size_type ret = ::_write(m_fd, buf, num_bytes);
#else
			size_type ret = ::write(m_fd, buf, num_bytes);
#endif
			if (ret == -1)
			{
				std::stringstream msg;
				msg << "write failed: " << strerror(errno);
				throw file_error(msg.str());
			}
			return ret;
		}

		void set_size(size_type s)
		{
#ifdef _WIN32
#error file.cpp is for posix systems only. use file_win.cpp on windows
#else
			if (ftruncate(m_fd, s) < 0)
			{
				std::stringstream msg;
				msg << "ftruncate failed: '" << strerror(errno);
				throw file_error(msg.str());
			}
#endif
		}

		size_type seek(size_type offset, int m = 1)
		{
			TORRENT_ASSERT(m_open_mode);
			TORRENT_ASSERT(m_fd != -1);

			int seekdir = (m == 1)?SEEK_SET:SEEK_END;
#ifdef _WIN32
			size_type ret = _lseeki64(m_fd, offset, seekdir);
#else
			size_type ret = lseek(m_fd, offset, seekdir);
#endif

			// For some strange reason this fails
			// on win32. Use windows specific file
			// wrapper instead.
			if (ret == -1)
			{
				std::stringstream msg;
				msg << "seek failed: '" << strerror(errno)
					<< "' fd: " << m_fd
					<< " offset: " << offset
					<< " seekdir: " << seekdir;
				throw file_error(msg.str());
			}
			return ret;
		}

		size_type tell()
		{
			TORRENT_ASSERT(m_open_mode);
			TORRENT_ASSERT(m_fd != -1);

#ifdef _WIN32
			return _telli64(m_fd);
#else
			return lseek(m_fd, 0, SEEK_CUR);
#endif
		}

		int m_fd;
		int m_open_mode;
	};

	// pimpl forwardings

	file::file() : m_impl(new impl()) {}

	file::file(fs::path const& p, file::open_mode m)
		: m_impl(new impl(p, m.m_mask))
	{}

	file::~file() {}

	void file::open(fs::path const& p, file::open_mode m)
	{
		m_impl->open(p, m.m_mask);
	}

	void file::close()
	{
		m_impl->close();
	}

	size_type file::write(const char* buf, size_type num_bytes)
	{
		return m_impl->write(buf, num_bytes);
	}

	size_type file::read(char* buf, size_type num_bytes)
	{
		return m_impl->read(buf, num_bytes);
	}

	void file::set_size(size_type s)
	{
		m_impl->set_size(s);
	}

	size_type file::seek(size_type pos, file::seek_mode m)
	{
		return m_impl->seek(pos, m.m_val);
	}

	size_type file::tell()
	{
		return m_impl->tell();
	}

}
<commit_msg>include fixes in file.cpp<commit_after>/*

Copyright (c) 2003, Arvid Norberg
All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:

    * Redistributions of source code must retain the above copyright
      notice, this list of conditions and the following disclaimer.
    * Redistributions in binary form must reproduce the above copyright
      notice, this list of conditions and the following disclaimer in
      the documentation and/or other materials provided with the distribution.
    * Neither the name of the author nor the names of its
      contributors may be used to endorse or promote products derived
      from this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.

*/

#include "libtorrent/pch.hpp"

#ifdef _WIN32
// windows part
#include "libtorrent/utf8.hpp"

#include <io.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <sys/types.h>

#ifndef _MODE_T_
typedef int mode_t;
#endif

#ifdef UNICODE
#include "libtorrent/storage.hpp"
#endif

#else
// unix part
#define _FILE_OFFSET_BITS 64
#include <unistd.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <errno.h>

#include <boost/static_assert.hpp>
// make sure the _FILE_OFFSET_BITS define worked
// on this platform
BOOST_STATIC_ASSERT(sizeof(lseek(0, 0, 0)) >= 8);

#endif

#include <boost/filesystem/operations.hpp>
#include "libtorrent/file.hpp"
#include <sstream>
#include <cstring>

#ifndef O_BINARY
#define O_BINARY 0
#endif

#ifndef O_RANDOM
#define O_RANDOM 0
#endif

#ifdef UNICODE
#include "libtorrent/storage.hpp"
#endif

#include "libtorrent/assert.hpp"

namespace
{
	enum { mode_in = 1, mode_out = 2 };

	mode_t map_open_mode(int m)
	{
		if (m == (mode_in | mode_out)) return O_RDWR | O_CREAT | O_BINARY | O_RANDOM;
		if (m == mode_out) return O_WRONLY | O_CREAT | O_BINARY | O_RANDOM;
		if (m == mode_in) return O_RDONLY | O_BINARY | O_RANDOM;
		TORRENT_ASSERT(false);
		return 0;
	}

#ifdef WIN32
	std::string utf8_native(std::string const& s)
	{
		try
		{
			std::wstring ws;
			libtorrent::utf8_wchar(s, ws);
			std::size_t size = wcstombs(0, ws.c_str(), 0);
			if (size == std::size_t(-1)) return s;
			std::string ret;
			ret.resize(size);
			size = wcstombs(&ret[0], ws.c_str(), size + 1);
			if (size == wchar_t(-1)) return s;
			ret.resize(size);
			return ret;
		}
		catch(std::exception)
		{
			return s;
		}
	}
#else
	std::string utf8_native(std::string const& s)
	{
		return s;
	}
#endif

}

namespace libtorrent
{

	namespace fs = boost::filesystem;

	const file::open_mode file::in(mode_in);
	const file::open_mode file::out(mode_out);

	const file::seek_mode file::begin(1);
	const file::seek_mode file::end(2);

	struct file::impl
	{
		impl()
			: m_fd(-1)
			, m_open_mode(0)
		{}

		impl(fs::path const& path, int mode)
			: m_fd(-1)
			, m_open_mode(0)
		{
			open(path, mode);
		}

		~impl()
		{
			close();
		}

		void open(fs::path const& path, int mode)
		{
			TORRENT_ASSERT(path.is_complete());
			close();
#if defined(_WIN32) && defined(UNICODE)
			std::wstring wpath(safe_convert(path.native_file_string()));
			m_fd = ::_wopen(
				wpath.c_str()
				, map_open_mode(mode)
				, S_IREAD | S_IWRITE);
#else
#ifdef _WIN32
			m_fd = ::_open(
#else
			m_fd = ::open(
#endif
				utf8_native(path.native_file_string()).c_str()
				, map_open_mode(mode)
#ifdef _WIN32
				, S_IREAD | S_IWRITE);
#else
				, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
#endif
#endif
			if (m_fd == -1)
			{
				std::stringstream msg;
				msg << "open failed: '" << path.native_file_string() << "'. "
					<< std::strerror(errno);
				throw file_error(msg.str());
			}
			m_open_mode = mode;
		}

		void close()
		{
			if (m_fd == -1) return;

#ifdef _WIN32
			::_close(m_fd);
#else
			::close(m_fd);
#endif
			m_fd = -1;
			m_open_mode = 0;
		}

		size_type read(char* buf, size_type num_bytes)
		{
			TORRENT_ASSERT(m_open_mode & mode_in);
			TORRENT_ASSERT(m_fd != -1);

#ifdef _WIN32
			size_type ret = ::_read(m_fd, buf, num_bytes);
#else
			size_type ret = ::read(m_fd, buf, num_bytes);
#endif
			if (ret == -1)
			{
				std::stringstream msg;
				msg << "read failed: " << std::strerror(errno);
				throw file_error(msg.str());
			}
			return ret;
		}

		size_type write(const char* buf, size_type num_bytes)
		{
			TORRENT_ASSERT(m_open_mode & mode_out);
			TORRENT_ASSERT(m_fd != -1);

			// TODO: Test this a bit more, what happens with random failures in
			// the files?
//			if ((rand() % 100) > 80)
//				throw file_error("debug");

#ifdef _WIN32
			size_type ret = ::_write(m_fd, buf, num_bytes);
#else
			size_type ret = ::write(m_fd, buf, num_bytes);
#endif
			if (ret == -1)
			{
				std::stringstream msg;
				msg << "write failed: " << std::strerror(errno);
				throw file_error(msg.str());
			}
			return ret;
		}

		void set_size(size_type s)
		{
#ifdef _WIN32
#error file.cpp is for posix systems only. use file_win.cpp on windows
#else
			if (ftruncate(m_fd, s) < 0)
			{
				std::stringstream msg;
				msg << "ftruncate failed: '" << std::strerror(errno);
				throw file_error(msg.str());
			}
#endif
		}

		size_type seek(size_type offset, int m = 1)
		{
			TORRENT_ASSERT(m_open_mode);
			TORRENT_ASSERT(m_fd != -1);

			int seekdir = (m == 1)?SEEK_SET:SEEK_END;
#ifdef _WIN32
			size_type ret = _lseeki64(m_fd, offset, seekdir);
#else
			size_type ret = lseek(m_fd, offset, seekdir);
#endif

			// For some strange reason this fails
			// on win32. Use windows specific file
			// wrapper instead.
			if (ret == -1)
			{
				std::stringstream msg;
				msg << "seek failed: '" << std::strerror(errno)
					<< "' fd: " << m_fd
					<< " offset: " << offset
					<< " seekdir: " << seekdir;
				throw file_error(msg.str());
			}
			return ret;
		}

		size_type tell()
		{
			TORRENT_ASSERT(m_open_mode);
			TORRENT_ASSERT(m_fd != -1);

#ifdef _WIN32
			return _telli64(m_fd);
#else
			return lseek(m_fd, 0, SEEK_CUR);
#endif
		}

		int m_fd;
		int m_open_mode;
	};

	// pimpl forwardings

	file::file() : m_impl(new impl()) {}

	file::file(fs::path const& p, file::open_mode m)
		: m_impl(new impl(p, m.m_mask))
	{}

	file::~file() {}

	void file::open(fs::path const& p, file::open_mode m)
	{
		m_impl->open(p, m.m_mask);
	}

	void file::close()
	{
		m_impl->close();
	}

	size_type file::write(const char* buf, size_type num_bytes)
	{
		return m_impl->write(buf, num_bytes);
	}

	size_type file::read(char* buf, size_type num_bytes)
	{
		return m_impl->read(buf, num_bytes);
	}

	void file::set_size(size_type s)
	{
		m_impl->set_size(s);
	}

	size_type file::seek(size_type pos, file::seek_mode m)
	{
		return m_impl->seek(pos, m.m_val);
	}

	size_type file::tell()
	{
		return m_impl->tell();
	}

}
<|endoftext|>


<commit_before>// $Id$
//
//  Copyright (C) 2003-2010 Greg Landrum and Rational Discovery LLC
//
//   @@ All Rights Reserved @@
//  This file is part of the RDKit.
//  The contents are covered by the terms of the BSD license
//  which is included in the file license.txt, found at the root
//  of the RDKit source tree.
//

#define NO_IMPORT_ARRAY
#include <boost/python.hpp>
#include <string>

#include <GraphMol/RDKitBase.h>
#include <GraphMol/QueryAtom.h>
#include <RDGeneral/types.h>
#include <Geometry/point.h>
#include <GraphMol/SmilesParse/SmilesWrite.h>
#include <GraphMol/SmilesParse/SmartsWrite.h>

#include "seqs.hpp"
#include <algorithm>

namespace python = boost::python;
namespace RDKit{
  namespace {
    std::string qhelper(Atom::QUERYATOM_QUERY *q,int depth){
      std::string res="";
      if(q){
	for (unsigned int i=0;i<depth;++i) res+="  ";
	res += q->getDescription()+"\n";
	for(Atom::QUERYATOM_QUERY::CHILD_VECT_CI ci=q->beginChildren();
	    ci!=q->endChildren();++ci){
	  res +=  qhelper((*ci).get(),depth+1);
	}
      }
      return res;
    }
  } // end of local namespace
  std::string describeQuery(const Atom*atom){
    std::string res="";
    if(atom->hasQuery()){
      res=qhelper(atom->getQuery(),0);
    }
    return res;
  }

  void AtomSetProp(const Atom *atom, const char *key,std::string val) {
    //std::cerr<<"asp: "<<atom<<" " << key<<" - " << val << std::endl;
    atom->setProp(key, val);
  }

  int AtomHasProp(const Atom *atom, const char *key) {
    //std::cerr<<"ahp: "<<atom<<" " << key<< std::endl;
    int res = atom->hasProp(key);
    return res;
  }

  std::string AtomGetProp(const Atom *atom, const char *key) {
    if (!atom->hasProp(key)) {
      PyErr_SetString(PyExc_KeyError,key);
      throw python::error_already_set();
    }
    std::string res;
    atom->getProp(key, res);
    return res;
  }
  python::tuple AtomGetNeighbors(Atom *atom){
    python::list res;
    const ROMol *parent = &atom->getOwningMol();
    ROMol::ADJ_ITER begin,end;
    boost::tie(begin,end) = parent->getAtomNeighbors(atom);
    while(begin!=end){
      res.append(python::ptr(parent->getAtomWithIdx(*begin)));
      begin++;
    }
    return python::tuple(res);
  }

  python::tuple AtomGetBonds(Atom *atom){
    python::list res;
    const ROMol *parent = &atom->getOwningMol();
    ROMol::OEDGE_ITER begin,end;
    boost::tie(begin,end) = parent->getAtomBonds(atom);
    while(begin!=end){
      Bond *tmpB = (*parent)[*begin].get();
      res.append(python::ptr(tmpB));
      begin++;
    }
    return python::tuple(res);
  }

  bool AtomIsInRing(const Atom *atom){
    if(!atom->getOwningMol().getRingInfo()->isInitialized()){
      MolOps::findSSSR(atom->getOwningMol());
    }
    return atom->getOwningMol().getRingInfo()->numAtomRings(atom->getIdx())!=0;
  }
  bool AtomIsInRingSize(const Atom *atom,int size){
    if(!atom->getOwningMol().getRingInfo()->isInitialized()){
      MolOps::findSSSR(atom->getOwningMol());
    }
    return atom->getOwningMol().getRingInfo()->isAtomInRingOfSize(atom->getIdx(),size);
  }

  std::string AtomGetSmarts(const Atom *atom){
    std::string res;
    if(atom->hasQuery()){
      res=SmartsWrite::GetAtomSmarts(static_cast<const QueryAtom *>(atom));
    } else {
      res = SmilesWrite::GetAtomSmiles(atom);
    }
    return res;
  }

  // FIX: is there any reason at all to not just prevent the construction of Atoms?
  std::string atomClassDoc="The class to store Atoms.\n\
Note that, though it is possible to create one, having an Atom on its own\n\
(i.e not associated with a molecule) is not particularly useful.\n";
struct atom_wrapper {
  static void wrap(){
    python::class_<Atom>("Atom",atomClassDoc.c_str(),python::init<std::string>())

      .def(python::init<unsigned int>("Constructor, takes either an int (atomic number) or a string (atomic symbol).\n"))

      .def("GetAtomicNum",&Atom::getAtomicNum,
	   "Returns the atomic number.")

      .def("SetAtomicNum",&Atom::setAtomicNum,
	   "Sets the atomic number, takes an integer value as an argument")

      .def("GetSymbol",&Atom::getSymbol,
	   "Returns the atomic number (a string)\n")

      .def("GetIdx",&Atom::getIdx,
	   "Returns the atom's index (ordering in the molecule)\n")

      .def("GetDegree",&Atom::getDegree,
	   "Returns the degree of the atom in the molecule.\n\n"
	   "  The degree of an atom is defined to be its number of\n"
	   "  directly-bonded neighbors.\n"
	   "  The degree is independent of bond orders, but is dependent\n"
	   "    on whether or not Hs are explicit in the graph.\n"
           )
      .def("GetTotalDegree",&Atom::getTotalDegree,
	   "Returns the degree of the atom in the molecule including Hs.\n\n"
	   "  The degree of an atom is defined to be its number of\n"
	   "  directly-bonded neighbors.\n"
	   "  The degree is independent of bond orders.\n")

      .def("GetTotalNumHs",&Atom::getTotalNumHs,
           (python::arg("self"),python::arg("includeNeighbors")=false),
           "Returns the total number of Hs (explicit and implicit) on the atom.\n\n"
           "  ARGUMENTS:\n\n"
           "    - includeNeighbors: (optional) toggles inclusion of neighboring H atoms in the sum.\n"
           "      Defaults to 0.\n")

      .def("GetNumImplicitHs",&Atom::getNumImplicitHs,
	   "Returns the total number of implicit Hs on the atom.\n")

      .def("GetExplicitValence",&Atom::getExplicitValence,
           "Returns the number of explicit Hs on the atom.\n")

      .def("GetImplicitValence",&Atom::getImplicitValence,
           "Returns the number of implicit Hs on the atom.\n")

      .def("GetFormalCharge",&Atom::getFormalCharge)
      .def("SetFormalCharge",&Atom::setFormalCharge)

      .def("SetNoImplicit",&Atom::setNoImplicit,
	   "Sets a marker on the atom that *disallows* implicit Hs.\n"
	   "  This holds even if the atom would otherwise have implicit Hs added.\n")
      .def("GetNoImplicit",&Atom::getNoImplicit,
	   "Returns whether or not the atom is *allowed* to have implicit Hs.\n")

      .def("SetNumExplicitHs",&Atom::setNumExplicitHs)
      .def("GetNumExplicitHs",&Atom::getNumExplicitHs)
      .def("SetIsAromatic",&Atom::setIsAromatic)
      .def("GetIsAromatic",&Atom::getIsAromatic)
      .def("SetMass",&Atom::setMass)
      .def("GetMass",&Atom::getMass)
      .def("SetNumRadicalElectrons",&Atom::setNumRadicalElectrons)
      .def("GetNumRadicalElectrons",&Atom::getNumRadicalElectrons)

      // NOTE: these may be used at some point in the future, but they
      //  aren't now, so there's no point in confusing things.
      //.def("SetDativeFlag",&Atom::setDativeFlag)
      //.def("GetDativeFlag",&Atom::getDativeFlag)
      //.def("ClearDativeFlag",&Atom::clearDativeFlag)

      .def("SetChiralTag",&Atom::setChiralTag)
      .def("InvertChirality",&Atom::invertChirality)
      .def("GetChiralTag",&Atom::getChiralTag)

      .def("SetHybridization",&Atom::setHybridization,
	   "Sets the hybridization of the atom.\n"
	   "  The argument should be a HybridizationType\n")
      .def("GetHybridization",&Atom::getHybridization,
	   "Returns the atom's hybridization.\n")

      .def("GetOwningMol",&Atom::getOwningMol,
	   "Returns the Mol that owns this atom.\n",
	   python::return_value_policy<python::reference_existing_object>())

      .def("GetNeighbors",AtomGetNeighbors,
	   "Returns a read-only sequence of the atom's neighbors\n")

      .def("GetBonds",AtomGetBonds,
	   "Returns a read-only sequence of the atom's bonds\n")

      .def("Match",(bool (Atom::*)(const Atom *) const)&Atom::Match,
	   "Returns whether or not this atom matches another Atom.\n\n"
	   "  Each Atom (or query Atom) has a query function which is\n"
	   "  used for this type of matching.\n\n"
	   "  ARGUMENTS:\n"
	   "    - other: the other Atom to which to compare\n")

      .def("IsInRingSize",AtomIsInRingSize,
	   "Returns whether or not the atom is in a ring of a particular size.\n\n"
	   "  ARGUMENTS:\n"
	   "    - size: the ring size to look for\n")

      .def("IsInRing",AtomIsInRing,
	   "Returns whether or not the atom is in a ring\n\n")

      .def("HasQuery",&Atom::hasQuery,
     "Returns whether or not the atom has an associated query\n\n")

      .def("DescribeQuery",describeQuery,
	   "returns a text description of the query. Primarily intended for debugging purposes.\n\n")

      .def("GetSmarts",AtomGetSmarts,
              "returns the SMARTS (or SMILES) string for an Atom\n\n")

      // properties
      .def("SetProp",AtomSetProp,
	   (python::arg("self"), python::arg("key"),
	    python::arg("val")),
	   "Sets an atomic property\n\n"
	   "  ARGUMENTS:\n"
	   "    - key: the name of the property to be set (a string).\n"
	   "    - value: the property value (a string).\n\n"
           )

      .def("GetProp", AtomGetProp,
           "Returns the value of the property.\n\n"
	   "  ARGUMENTS:\n"
	   "    - key: the name of the property to return (a string).\n\n"
	   "  RETURNS: a string\n\n"
	   "  NOTE:\n"
	   "    - If the property has not been set, a KeyError exception will be raised.\n")

      .def("HasProp", AtomHasProp,
           "Queries a Atom to see if a particular property has been assigned.\n\n"
	   "  ARGUMENTS:\n"
	   "    - key: the name of the property to check for (a string).\n")

      .def("GetPropNames",&Atom::getPropList,
	   (python::arg("self")),
           "Returns a list of the properties set on the Atom.\n\n"
           )

      ;

    python::enum_<Atom::HybridizationType>("HybridizationType")
      .value("UNSPECIFIED",Atom::UNSPECIFIED)
      .value("SP",Atom::SP)
      .value("SP2",Atom::SP2)
      .value("SP3",Atom::SP3)
      .value("SP3D",Atom::SP3D)
      .value("SP3D2",Atom::SP3D2)
      .value("OTHER",Atom::OTHER)
      ;
    python::enum_<Atom::ChiralType>("ChiralType")
      .value("CHI_UNSPECIFIED",Atom::CHI_UNSPECIFIED)
      .value("CHI_TETRAHEDRAL_CW",Atom::CHI_TETRAHEDRAL_CW)
      .value("CHI_TETRAHEDRAL_CCW",Atom::CHI_TETRAHEDRAL_CCW)
      .value("CHI_OTHER",Atom::CHI_OTHER)
      ;

  };
};
}// end of namespace
void wrap_atom() {
  RDKit::atom_wrapper::wrap();
}
<commit_msg>fix sf.net issue 3495619<commit_after>// $Id$
//
//  Copyright (C) 2003-2010 Greg Landrum and Rational Discovery LLC
//
//   @@ All Rights Reserved @@
//  This file is part of the RDKit.
//  The contents are covered by the terms of the BSD license
//  which is included in the file license.txt, found at the root
//  of the RDKit source tree.
//

#define NO_IMPORT_ARRAY
#include <boost/python.hpp>
#include <string>

#include <GraphMol/RDKitBase.h>
#include <GraphMol/QueryAtom.h>
#include <RDGeneral/types.h>
#include <Geometry/point.h>
#include <GraphMol/SmilesParse/SmilesWrite.h>
#include <GraphMol/SmilesParse/SmartsWrite.h>

#include "seqs.hpp"
#include <algorithm>

namespace python = boost::python;
namespace RDKit{
  namespace {
    std::string qhelper(Atom::QUERYATOM_QUERY *q,int depth){
      std::string res="";
      if(q){
	for (unsigned int i=0;i<depth;++i) res+="  ";
	res += q->getDescription()+"\n";
	for(Atom::QUERYATOM_QUERY::CHILD_VECT_CI ci=q->beginChildren();
	    ci!=q->endChildren();++ci){
	  res +=  qhelper((*ci).get(),depth+1);
	}
      }
      return res;
    }
  } // end of local namespace
  std::string describeQuery(const Atom*atom){
    std::string res="";
    if(atom->hasQuery()){
      res=qhelper(atom->getQuery(),0);
    }
    return res;
  }

  void AtomSetProp(const Atom *atom, const char *key,std::string val) {
    //std::cerr<<"asp: "<<atom<<" " << key<<" - " << val << std::endl;
    atom->setProp(key, val);
  }

  int AtomHasProp(const Atom *atom, const char *key) {
    //std::cerr<<"ahp: "<<atom<<" " << key<< std::endl;
    int res = atom->hasProp(key);
    return res;
  }

  std::string AtomGetProp(const Atom *atom, const char *key) {
    if (!atom->hasProp(key)) {
      PyErr_SetString(PyExc_KeyError,key);
      throw python::error_already_set();
    }
    std::string res;
    atom->getProp(key, res);
    return res;
  }
  python::tuple AtomGetNeighbors(Atom *atom){
    python::list res;
    const ROMol *parent = &atom->getOwningMol();
    ROMol::ADJ_ITER begin,end;
    boost::tie(begin,end) = parent->getAtomNeighbors(atom);
    while(begin!=end){
      res.append(python::ptr(parent->getAtomWithIdx(*begin)));
      begin++;
    }
    return python::tuple(res);
  }

  python::tuple AtomGetBonds(Atom *atom){
    python::list res;
    const ROMol *parent = &atom->getOwningMol();
    ROMol::OEDGE_ITER begin,end;
    boost::tie(begin,end) = parent->getAtomBonds(atom);
    while(begin!=end){
      Bond *tmpB = (*parent)[*begin].get();
      res.append(python::ptr(tmpB));
      begin++;
    }
    return python::tuple(res);
  }

  bool AtomIsInRing(const Atom *atom){
    if(!atom->getOwningMol().getRingInfo()->isInitialized()){
      MolOps::findSSSR(atom->getOwningMol());
    }
    return atom->getOwningMol().getRingInfo()->numAtomRings(atom->getIdx())!=0;
  }
  bool AtomIsInRingSize(const Atom *atom,int size){
    if(!atom->getOwningMol().getRingInfo()->isInitialized()){
      MolOps::findSSSR(atom->getOwningMol());
    }
    return atom->getOwningMol().getRingInfo()->isAtomInRingOfSize(atom->getIdx(),size);
  }

  std::string AtomGetSmarts(const Atom *atom){
    std::string res;
    if(atom->hasQuery()){
      res=SmartsWrite::GetAtomSmarts(static_cast<const QueryAtom *>(atom));
    } else {
      res = SmilesWrite::GetAtomSmiles(atom);
    }
    return res;
  }

  // FIX: is there any reason at all to not just prevent the construction of Atoms?
  std::string atomClassDoc="The class to store Atoms.\n\
Note that, though it is possible to create one, having an Atom on its own\n\
(i.e not associated with a molecule) is not particularly useful.\n";
struct atom_wrapper {
  static void wrap(){
    python::class_<Atom>("Atom",atomClassDoc.c_str(),python::init<std::string>())

      .def(python::init<unsigned int>("Constructor, takes either an int (atomic number) or a string (atomic symbol).\n"))

      .def("GetAtomicNum",&Atom::getAtomicNum,
	   "Returns the atomic number.")

      .def("SetAtomicNum",&Atom::setAtomicNum,
	   "Sets the atomic number, takes an integer value as an argument")

      .def("GetSymbol",&Atom::getSymbol,
	   "Returns the atomic symbol (a string)\n")

      .def("GetIdx",&Atom::getIdx,
	   "Returns the atom's index (ordering in the molecule)\n")

      .def("GetDegree",&Atom::getDegree,
	   "Returns the degree of the atom in the molecule.\n\n"
	   "  The degree of an atom is defined to be its number of\n"
	   "  directly-bonded neighbors.\n"
	   "  The degree is independent of bond orders, but is dependent\n"
	   "    on whether or not Hs are explicit in the graph.\n"
           )
      .def("GetTotalDegree",&Atom::getTotalDegree,
	   "Returns the degree of the atom in the molecule including Hs.\n\n"
	   "  The degree of an atom is defined to be its number of\n"
	   "  directly-bonded neighbors.\n"
	   "  The degree is independent of bond orders.\n")

      .def("GetTotalNumHs",&Atom::getTotalNumHs,
           (python::arg("self"),python::arg("includeNeighbors")=false),
           "Returns the total number of Hs (explicit and implicit) on the atom.\n\n"
           "  ARGUMENTS:\n\n"
           "    - includeNeighbors: (optional) toggles inclusion of neighboring H atoms in the sum.\n"
           "      Defaults to 0.\n")

      .def("GetNumImplicitHs",&Atom::getNumImplicitHs,
	   "Returns the total number of implicit Hs on the atom.\n")

      .def("GetExplicitValence",&Atom::getExplicitValence,
           "Returns the number of explicit Hs on the atom.\n")

      .def("GetImplicitValence",&Atom::getImplicitValence,
           "Returns the number of implicit Hs on the atom.\n")

      .def("GetFormalCharge",&Atom::getFormalCharge)
      .def("SetFormalCharge",&Atom::setFormalCharge)

      .def("SetNoImplicit",&Atom::setNoImplicit,
	   "Sets a marker on the atom that *disallows* implicit Hs.\n"
	   "  This holds even if the atom would otherwise have implicit Hs added.\n")
      .def("GetNoImplicit",&Atom::getNoImplicit,
	   "Returns whether or not the atom is *allowed* to have implicit Hs.\n")

      .def("SetNumExplicitHs",&Atom::setNumExplicitHs)
      .def("GetNumExplicitHs",&Atom::getNumExplicitHs)
      .def("SetIsAromatic",&Atom::setIsAromatic)
      .def("GetIsAromatic",&Atom::getIsAromatic)
      .def("SetMass",&Atom::setMass)
      .def("GetMass",&Atom::getMass)
      .def("SetNumRadicalElectrons",&Atom::setNumRadicalElectrons)
      .def("GetNumRadicalElectrons",&Atom::getNumRadicalElectrons)

      // NOTE: these may be used at some point in the future, but they
      //  aren't now, so there's no point in confusing things.
      //.def("SetDativeFlag",&Atom::setDativeFlag)
      //.def("GetDativeFlag",&Atom::getDativeFlag)
      //.def("ClearDativeFlag",&Atom::clearDativeFlag)

      .def("SetChiralTag",&Atom::setChiralTag)
      .def("InvertChirality",&Atom::invertChirality)
      .def("GetChiralTag",&Atom::getChiralTag)

      .def("SetHybridization",&Atom::setHybridization,
	   "Sets the hybridization of the atom.\n"
	   "  The argument should be a HybridizationType\n")
      .def("GetHybridization",&Atom::getHybridization,
	   "Returns the atom's hybridization.\n")

      .def("GetOwningMol",&Atom::getOwningMol,
	   "Returns the Mol that owns this atom.\n",
	   python::return_value_policy<python::reference_existing_object>())

      .def("GetNeighbors",AtomGetNeighbors,
	   "Returns a read-only sequence of the atom's neighbors\n")

      .def("GetBonds",AtomGetBonds,
	   "Returns a read-only sequence of the atom's bonds\n")

      .def("Match",(bool (Atom::*)(const Atom *) const)&Atom::Match,
	   "Returns whether or not this atom matches another Atom.\n\n"
	   "  Each Atom (or query Atom) has a query function which is\n"
	   "  used for this type of matching.\n\n"
	   "  ARGUMENTS:\n"
	   "    - other: the other Atom to which to compare\n")

      .def("IsInRingSize",AtomIsInRingSize,
	   "Returns whether or not the atom is in a ring of a particular size.\n\n"
	   "  ARGUMENTS:\n"
	   "    - size: the ring size to look for\n")

      .def("IsInRing",AtomIsInRing,
	   "Returns whether or not the atom is in a ring\n\n")

      .def("HasQuery",&Atom::hasQuery,
     "Returns whether or not the atom has an associated query\n\n")

      .def("DescribeQuery",describeQuery,
	   "returns a text description of the query. Primarily intended for debugging purposes.\n\n")

      .def("GetSmarts",AtomGetSmarts,
              "returns the SMARTS (or SMILES) string for an Atom\n\n")

      // properties
      .def("SetProp",AtomSetProp,
	   (python::arg("self"), python::arg("key"),
	    python::arg("val")),
	   "Sets an atomic property\n\n"
	   "  ARGUMENTS:\n"
	   "    - key: the name of the property to be set (a string).\n"
	   "    - value: the property value (a string).\n\n"
           )

      .def("GetProp", AtomGetProp,
           "Returns the value of the property.\n\n"
	   "  ARGUMENTS:\n"
	   "    - key: the name of the property to return (a string).\n\n"
	   "  RETURNS: a string\n\n"
	   "  NOTE:\n"
	   "    - If the property has not been set, a KeyError exception will be raised.\n")

      .def("HasProp", AtomHasProp,
           "Queries a Atom to see if a particular property has been assigned.\n\n"
	   "  ARGUMENTS:\n"
	   "    - key: the name of the property to check for (a string).\n")

      .def("GetPropNames",&Atom::getPropList,
	   (python::arg("self")),
           "Returns a list of the properties set on the Atom.\n\n"
           )

      ;

    python::enum_<Atom::HybridizationType>("HybridizationType")
      .value("UNSPECIFIED",Atom::UNSPECIFIED)
      .value("SP",Atom::SP)
      .value("SP2",Atom::SP2)
      .value("SP3",Atom::SP3)
      .value("SP3D",Atom::SP3D)
      .value("SP3D2",Atom::SP3D2)
      .value("OTHER",Atom::OTHER)
      ;
    python::enum_<Atom::ChiralType>("ChiralType")
      .value("CHI_UNSPECIFIED",Atom::CHI_UNSPECIFIED)
      .value("CHI_TETRAHEDRAL_CW",Atom::CHI_TETRAHEDRAL_CW)
      .value("CHI_TETRAHEDRAL_CCW",Atom::CHI_TETRAHEDRAL_CCW)
      .value("CHI_OTHER",Atom::CHI_OTHER)
      ;

  };
};
}// end of namespace
void wrap_atom() {
  RDKit::atom_wrapper::wrap();
}
<|endoftext|>


<commit_before>#include "ed.h"
#include "mainframe.h"

ApplicationFrame::ApplicationFrame ()
     : mouse (kbdq)
{
  default_tab_columns = 8;
  auto_save_count = 0;
  ime_composition = 0;
  ime_open_mode = kbd_queue::IME_MODE_OFF;
  sleep_timer_exhausted = 0;
  last_vkeycode = -1;
  kbd_repeat_count = 0;
  wait_cursor_depth = 0;
  f_in_drop = 0;
  drop_window = 0;
  drag_window = 0;
  drag_buffer = 0;
  f_protect_quit = 0;
  hwnd_clipboard = 0;
  last_cmd_tick = GetTickCount ();
  f_auto_save_pending = 0;
  default_caret_blink_time = 0;
  last_blink_caret = 0;
  lquit_char = make_char ('G' - '@');
  quit_vkey = 'G';
  quit_mod = MOD_CONTROL;
  minibuffer_prompt_column = -1;
  mframe = new main_frame();

  memset((void*)&active_frame, 0, sizeof(active_frame));
  a_next = 0;
}

ApplicationFrame::~ApplicationFrame ()
{
	mframe->cleanup();
	delete mframe;
}

ApplicationFrame *root = NULL;

static void inline ensure_root()
{
	if(root == NULL)
	{
		root = new ApplicationFrame();
	}
}

ApplicationFrame& active_app_frame()
{
	ensure_root();
	return *root;
}

main_frame& active_main_frame()
{
	ensure_root();
	return *root->mframe;
}

ApplicationFrame *first_app_frame() { ensure_root(); return root; }

ApplicationFrame* retrieve_app_frame(HWND hwnd)
{
  return (ApplicationFrame *)GetWindowLong (hwnd, 0);
}

#include <vector>
static std::vector<ApplicationFrame*> g_floating_frames;

void app_frame_gc_mark(void (*f)(lisp))
{
  for(ApplicationFrame *app1 = root; app1; app1 = app1->a_next)
  {
	  Window *wp;
	  for (wp = app1->active_frame.windows; wp; wp = wp->w_next)
		(*f) (wp->lwp);
	  for (wp = app1->active_frame.reserved; wp; wp = wp->w_next)
		(*f) (wp->lwp);
	  for (wp = app1->active_frame.deleted; wp; wp = wp->w_next)
		(*f) (wp->lwp);

	  app1->mframe->gc_mark(f);

	  (*f)(app1->lfp);
      app1->user_timer.gc_mark (f);
  }
}

// this needs all appframe, so implement in this file.
void
Window::modify_all_mode_line ()
{
  for(ApplicationFrame *app1 = root; app1; app1 = app1->a_next)
  {
	  for (Window *wp = app1->active_frame.windows; wp; wp = wp->w_next)
		wp->w_disp_flags |= WDF_MODELINE;
  }
}

void insert_app_frame(HWND hwnd, ApplicationFrame *app1)
{
  SetWindowLong (hwnd, 0, LONG (app1));
}

bool is_last_app_frame()
{
	if(root == NULL || root->a_next == NULL)
		return true;
	return false;
}

void notify_focus(ApplicationFrame *app1)
{
	if (root == app1) // do nothing.
		return;

	ApplicationFrame *cur = root;
	ApplicationFrame *prev = cur;
	while(cur != app1)
	{
		prev = cur;
		cur = cur->a_next;
	}
	assert(prev->a_next == app1);

	prev->a_next = app1->a_next;
	app1->a_next = root;
	root = app1;
	kbd_queue::change_application_window = true;
	for(Window* wp = root->active_frame.windows; wp; wp = wp->w_next)
		wp->update_window();
}

static void unchain_app_frame(ApplicationFrame* app1)
{
	if(root == app1){
		root = app1->a_next;
		app1->a_next = 0;
		return;
	}
	ApplicationFrame *app = root;
	while(app->a_next != app1)
	{
		app = app->a_next;
	}
	app->a_next = app1->a_next;
	app1->a_next = 0;
}

void delete_app_frame(ApplicationFrame *app1)
{
	unchain_app_frame(app1);
	// delete app1;
	g_floating_frames.push_back(app1);
	kbd_queue::change_application_window = true;
// 	notify_focus(root);
}

extern void remove_menus(ApplicationFrame* app);

void delete_floating_app_frame()
{
	for(std::vector<ApplicationFrame*>::iterator it = g_floating_frames.begin(); it != g_floating_frames.end(); it++)
	{
		ApplicationFrame *app1 = *it;
		remove_menus(app1);
		delete app1;
	}
	g_floating_frames.clear();
}

extern int init_app(HINSTANCE hinst, ApplicationFrame* app1);

ApplicationFrame * coerce_to_frame (lisp object)
{
  if (!object || object == Qnil)
    return &active_app_frame ();
  check_appframe (object);
  if (!xappframe_fp (object))
    FEprogram_error (Edeleted_window);
  return xappframe_fp (object);
}

// --- below here is lisp functions.
lisp
Fmake_frame (lisp opt)
{
	HINSTANCE hinst = root->hinst;

	ApplicationFrame* new_app = new ApplicationFrame();
	new_app->a_next = root;
	root = new_app;

	init_app(hinst, new_app);

	return new_app->lfp;
}
lisp
Fselected_frame ()
{
  assert (xappframe_fp (active_app_frame ().lfp));
  assert (xappframe_fp (active_app_frame ().lfp) == &active_app_frame ());
  return active_app_frame ().lfp;
}

// ignore minibufp now.
lisp
Fnext_frame (lisp frame, lisp minibufp)
{
  ApplicationFrame *app = coerce_to_frame(frame);
  ApplicationFrame *next = app->a_next;
  if (!next)
    next = first_app_frame();
  return next->lfp;
}

lisp
Fframe_list ()
{
  ApplicationFrame *app1 = first_app_frame();
  lisp result = xcons (app1->lfp, Qnil);
  lisp p = result;
  for(app1 = app1->a_next; app1; app1 = app1->a_next)
  {
      xcdr (p) = xcons (app1->lfp, Qnil);
      p = xcdr (p);
  }

  return result;
}

lisp
Fother_frame ()
{
  ApplicationFrame *app1 = first_app_frame();
  if(app1->a_next)
  {
	  PostMessage(app1->a_next->toplev, WM_SETFOCUS, 0, 0);
	  return Qt;
  }
  return Qnil;
}
<commit_msg>other trial of other-frame. not working either. commit for record purpose.<commit_after>#include "ed.h"
#include "mainframe.h"

ApplicationFrame::ApplicationFrame ()
     : mouse (kbdq)
{
  default_tab_columns = 8;
  auto_save_count = 0;
  ime_composition = 0;
  ime_open_mode = kbd_queue::IME_MODE_OFF;
  sleep_timer_exhausted = 0;
  last_vkeycode = -1;
  kbd_repeat_count = 0;
  wait_cursor_depth = 0;
  f_in_drop = 0;
  drop_window = 0;
  drag_window = 0;
  drag_buffer = 0;
  f_protect_quit = 0;
  hwnd_clipboard = 0;
  last_cmd_tick = GetTickCount ();
  f_auto_save_pending = 0;
  default_caret_blink_time = 0;
  last_blink_caret = 0;
  lquit_char = make_char ('G' - '@');
  quit_vkey = 'G';
  quit_mod = MOD_CONTROL;
  minibuffer_prompt_column = -1;
  mframe = new main_frame();

  memset((void*)&active_frame, 0, sizeof(active_frame));
  a_next = 0;
}

ApplicationFrame::~ApplicationFrame ()
{
	mframe->cleanup();
	delete mframe;
}

ApplicationFrame *root = NULL;

static void inline ensure_root()
{
	if(root == NULL)
	{
		root = new ApplicationFrame();
	}
}

ApplicationFrame& active_app_frame()
{
	ensure_root();
	return *root;
}

main_frame& active_main_frame()
{
	ensure_root();
	return *root->mframe;
}

ApplicationFrame *first_app_frame() { ensure_root(); return root; }

ApplicationFrame* retrieve_app_frame(HWND hwnd)
{
  return (ApplicationFrame *)GetWindowLong (hwnd, 0);
}

#include <vector>
static std::vector<ApplicationFrame*> g_floating_frames;

void app_frame_gc_mark(void (*f)(lisp))
{
  for(ApplicationFrame *app1 = root; app1; app1 = app1->a_next)
  {
	  Window *wp;
	  for (wp = app1->active_frame.windows; wp; wp = wp->w_next)
		(*f) (wp->lwp);
	  for (wp = app1->active_frame.reserved; wp; wp = wp->w_next)
		(*f) (wp->lwp);
	  for (wp = app1->active_frame.deleted; wp; wp = wp->w_next)
		(*f) (wp->lwp);

	  app1->mframe->gc_mark(f);

	  (*f)(app1->lfp);
      app1->user_timer.gc_mark (f);
  }
}

// this needs all appframe, so implement in this file.
void
Window::modify_all_mode_line ()
{
  for(ApplicationFrame *app1 = root; app1; app1 = app1->a_next)
  {
	  for (Window *wp = app1->active_frame.windows; wp; wp = wp->w_next)
		wp->w_disp_flags |= WDF_MODELINE;
  }
}

void insert_app_frame(HWND hwnd, ApplicationFrame *app1)
{
  SetWindowLong (hwnd, 0, LONG (app1));
}

bool is_last_app_frame()
{
	if(root == NULL || root->a_next == NULL)
		return true;
	return false;
}

void notify_focus(ApplicationFrame *app1)
{
	if (root == app1) // do nothing.
		return;

	ApplicationFrame *cur = root;
	ApplicationFrame *prev = cur;
	while(cur != app1)
	{
		prev = cur;
		cur = cur->a_next;
	}
	assert(prev->a_next == app1);

	prev->a_next = app1->a_next;
	app1->a_next = root;
	root = app1;
	kbd_queue::change_application_window = true;
	for(Window* wp = root->active_frame.windows; wp; wp = wp->w_next)
		wp->update_window();
}

static void unchain_app_frame(ApplicationFrame* app1)
{
	if(root == app1){
		root = app1->a_next;
		app1->a_next = 0;
		return;
	}
	ApplicationFrame *app = root;
	while(app->a_next != app1)
	{
		app = app->a_next;
	}
	app->a_next = app1->a_next;
	app1->a_next = 0;
}

void delete_app_frame(ApplicationFrame *app1)
{
	unchain_app_frame(app1);
	// delete app1;
	g_floating_frames.push_back(app1);
	kbd_queue::change_application_window = true;
// 	notify_focus(root);
}

extern void remove_menus(ApplicationFrame* app);

void delete_floating_app_frame()
{
	for(std::vector<ApplicationFrame*>::iterator it = g_floating_frames.begin(); it != g_floating_frames.end(); it++)
	{
		ApplicationFrame *app1 = *it;
		remove_menus(app1);
		delete app1;
	}
	g_floating_frames.clear();
}

extern int init_app(HINSTANCE hinst, ApplicationFrame* app1);

ApplicationFrame * coerce_to_frame (lisp object)
{
  if (!object || object == Qnil)
    return &active_app_frame ();
  check_appframe (object);
  if (!xappframe_fp (object))
    FEprogram_error (Edeleted_window);
  return xappframe_fp (object);
}

// --- below here is lisp functions.
lisp
Fmake_frame (lisp opt)
{
	HINSTANCE hinst = root->hinst;

	ApplicationFrame* new_app = new ApplicationFrame();
	new_app->a_next = root;
	root = new_app;

	init_app(hinst, new_app);

	return new_app->lfp;
}
lisp
Fselected_frame ()
{
  assert (xappframe_fp (active_app_frame ().lfp));
  assert (xappframe_fp (active_app_frame ().lfp) == &active_app_frame ());
  return active_app_frame ().lfp;
}

// ignore minibufp now.
lisp
Fnext_frame (lisp frame, lisp minibufp)
{
  ApplicationFrame *app = coerce_to_frame(frame);
  ApplicationFrame *next = app->a_next;
  if (!next)
    next = first_app_frame();
  return next->lfp;
}

lisp
Fframe_list ()
{
  ApplicationFrame *app1 = first_app_frame();
  lisp result = xcons (app1->lfp, Qnil);
  lisp p = result;
  for(app1 = app1->a_next; app1; app1 = app1->a_next)
  {
      xcdr (p) = xcons (app1->lfp, Qnil);
      p = xcdr (p);
  }

  return result;
}

lisp
Fother_frame ()
{
  ApplicationFrame *app1 = first_app_frame();
  if(app1->a_next)
  {
	  SetFocus(app1->a_next->toplev);
	  return Qt;
  }
  return Qnil;
}
<|endoftext|>