<commit_before>#include "Geometry.h"

#include <cstdio>
#include <fstream>
#include <stdexcept>

#include "spruce.hh"

using std::string;
using std::istringstream;
using std::ifstream;

using Eigen::Vector3i;
using Eigen::Vector3d;
using Eigen::RowVectorXd;
using Eigen::Matrix3Xd;
using Eigen::Matrix3Xi;

namespace DrakeShapes {
const int Geometry::NUM_BBOX_POINTS = 8;
const int Sphere::NUM_POINTS = 1;
const int Capsule::NUM_POINTS = 2;

std::string ShapeToString(Shape ss) {
  switch (ss) {
    case UNKNOWN:
      return "UNKNOWN";
    case BOX:
      return "BOX";
    case SPHERE:
      return "SPHERE";
    case CYLINDER:
      return "CYLINDER";
    case MESH:
      return "MESH";
    case MESH_POINTS:
      return "MESH_POINTS";
    case CAPSULE:
      return "CAPSULE";
  }
  return "UNDEFINED";
}

Geometry::Geometry() : shape(UNKNOWN) {}

Geometry::Geometry(const Geometry &other) { shape = other.getShape(); }

Geometry::Geometry(Shape shape) : shape(shape) {}

Shape Geometry::getShape() const { return shape; }

Geometry *Geometry::clone() const { return new Geometry(*this); }

void Geometry::getPoints(Matrix3Xd &points) const { points = Matrix3Xd(); }

void Geometry::getBoundingBoxPoints(Matrix3Xd &points) const {
  points = Matrix3Xd();
}

void Geometry::getBoundingBoxPoints(double x_half_width, double y_half_width,
                                    double z_half_width,
                                    Eigen::Matrix3Xd &points) const {
  // Return axis-aligned bounding-box vertices
  points.resize(3, NUM_BBOX_POINTS);

  RowVectorXd cx(NUM_BBOX_POINTS), cy(NUM_BBOX_POINTS), cz(NUM_BBOX_POINTS);
  cx << -1, 1, 1, -1, -1, 1, 1, -1;
  cy << 1, 1, 1, 1, -1, -1, -1, -1;
  cz << 1, 1, -1, -1, -1, -1, 1, 1;
  cx = cx * x_half_width;
  cy = cy * y_half_width;
  cz = cz * z_half_width;

  points << cx, cy, cz;
}

std::ostream &operator<<(std::ostream &out, const Geometry &gg) {
  out << ShapeToString(gg.getShape()) << ", " << gg.NUM_BBOX_POINTS;
  return out;
}

Sphere::Sphere(double radius) : Geometry(SPHERE), radius(radius) {}

Sphere *Sphere::clone() const { return new Sphere(*this); }

void Sphere::getPoints(Matrix3Xd &points) const {
  points = Matrix3Xd::Zero(3, NUM_POINTS);
}

void Sphere::getBoundingBoxPoints(Matrix3Xd &points) const {
  Geometry::getBoundingBoxPoints(radius, radius, radius, points);
}

void Sphere::getTerrainContactPoints(Matrix3Xd &points) const {
  if (radius < 1e-6)
    getPoints(points);
  else
    points = Matrix3Xd();
}

std::ostream &operator<<(std::ostream &out, const Sphere &ss) {
  out << static_cast<const Geometry &>(ss) << ", " << ss.radius << ", "
      << ss.NUM_POINTS;
  return out;
}

Box::Box(const Eigen::Vector3d &size) : Geometry(BOX), size(size) {}

Box *Box::clone() const { return new Box(*this); }

void Box::getPoints(Matrix3Xd &points) const {
  Geometry::getBoundingBoxPoints(size(0) / 2.0, size(1) / 2.0, size(2) / 2.0,
                                 points);
}

void Box::getBoundingBoxPoints(Matrix3Xd &points) const { getPoints(points); }

void Box::getTerrainContactPoints(Matrix3Xd &points) const {
  getPoints(points);
}

std::ostream &operator<<(std::ostream &out, const Box &bb) {
  out << static_cast<const Geometry &>(bb) << ", " << bb.size.transpose();
  return out;
}

Cylinder::Cylinder(double radius, double length)
    : Geometry(CYLINDER), radius(radius), length(length) {}

Cylinder *Cylinder::clone() const { return new Cylinder(*this); }

void Cylinder::getPoints(Matrix3Xd &points) const {
  static bool warnOnce = true;
  if (warnOnce) {
    std::cerr << "Warning: DrakeShapes::Cylinder::getPoints(): "
        "This method returns the vertices of the cylinder''s bounding-box."
         << std::endl;
    warnOnce = false;
  }

  getBoundingBoxPoints(points);
}

void Cylinder::getBoundingBoxPoints(Matrix3Xd &points) const {
  Geometry::getBoundingBoxPoints(radius, radius, length / 2.0, points);
}

std::ostream &operator<<(std::ostream &out, const Cylinder &cc) {
  out << static_cast<const Geometry &>(cc) << ", " << cc.radius << ", "
      << cc.length;
  return out;
}

Capsule::Capsule(double radius, double length)
    : Geometry(CAPSULE), radius(radius), length(length) {}

Capsule *Capsule::clone() const { return new Capsule(*this); }

void Capsule::getPoints(Matrix3Xd &points) const {
  // Return segment end-points
  points.resize(Eigen::NoChange, NUM_POINTS);
  RowVectorXd cx = RowVectorXd::Zero(NUM_POINTS);
  RowVectorXd cy = RowVectorXd::Zero(NUM_POINTS);
  RowVectorXd cz = RowVectorXd::Zero(NUM_POINTS);
  cz << length / 2.0, -length / 2.0;

  points << cx, cy, cz;
}

void Capsule::getBoundingBoxPoints(Matrix3Xd &points) const {
  Geometry::getBoundingBoxPoints(radius, radius, (length / 2.0 + radius),
                                 points);
}

std::ostream &operator<<(std::ostream &out, const Capsule &cc) {
  out << static_cast<const Geometry &>(cc) << ", " << cc.radius << ", "
      << cc.length;
  return out;
}

Mesh::Mesh(const string &filename)
    : Geometry(MESH), scale(1.0, 1.0, 1.0), filename(filename) {}

Mesh::Mesh(const string &filename, const string &resolved_filename)
    : Geometry(MESH),
      scale(1.0, 1.0, 1.0),
      filename(filename),
      resolved_filename(resolved_filename) {}

bool Mesh::extractMeshVertices(Matrix3Xd& vertex_coordinates) const {
  if (resolved_filename.empty()) return false;

  string obj_file_name = FindFileWithObjExtension();
  ifstream file(obj_file_name);
  if (!file) {
    throw std::runtime_error(
        "Error opening file \"" + obj_file_name + "\".");
  }

  string line;
  // Count the number of vertices and resize vertex_coordinates.
  int num_vertices = 0;
  while (getline(file, line)) {
    istringstream iss(line);
    string type;
    if (iss >> type && type == "v") {
      ++num_vertices;
    }
  }
  vertex_coordinates.resize(3, num_vertices);

  file.clear();
  file.seekg(0, file.beg);

  double d;
  int j = 0;
  while (getline(file, line)) {
    istringstream iss(line);
    string type;
    if (iss >> type && type == "v") {
      int i = 0;
      while (iss >> d) {
        vertex_coordinates(i++, j) = d;
      }
      ++j;
    }
  }
  return true;
}

string Mesh::FindFileWithObjExtension() const {
  spruce::path spath(resolved_filename);
  string ext = spath.extension();
  std::transform(ext.begin(), ext.end(), ext.begin(), ::tolower);

  if (ext.compare(".obj") == 0) {
    // Checks if the file with the obj extension exists.
    if (!spath.exists()) {
      throw std::runtime_error(
          "Unable to open file \"" + spath.getStr() + "\".");
    }
  } else {
    // Tries changing the extension to obj.
    spath.setExtension(".obj");
    if (!spath.exists()) {
      throw std::runtime_error(
          "Unable to resolve an obj file from the filename \""
              + spath.getStr() + "\" provided.");
    }
  }

  return spath.getStr();
}

void Mesh::LoadObjFile(PointsVector* vertices,
                       TrianglesVector* triangles) const {
  string obj_file_name = FindFileWithObjExtension();
  ifstream file(obj_file_name);
  if (!file) {
    throw std::runtime_error(
        "Error opening file \"" + obj_file_name + "\".");
  }

  std::string line;
  int line_number = 0;
  while (!file.eof()) {
    ++line_number;
    std::getline(file, line);
    std::stringstream ss(line);
    std::string key;
    ss >> key;

    if (key == "v") {
      // Reads a 3D vertex.
      double x, y, z;
      ss >> x; ss >> y; ss >> z;
      if (ss.fail()) {
        throw std::runtime_error(
            "In file \"" + obj_file_name + "\" "
            "(L." + std::to_string(line_number) + "). "
            "Vertex in the wrong format.");
      }
      vertices->push_back(Vector3d(x, y, z));
    } else if (key == "f") {
      // Reads the connectivity for a single triangle.
      std::vector<int> indices;
      int index;
      while (ss >> index) {
        // Ignores line until the next whitespace.
        // This effectively ignores texture coordinates and normals.
        // The first entry always corresponds to an index in the face.
        ss.ignore(line.size(), ' ');
        if (ss.fail()) {
          throw std::runtime_error(
              "In file \"" + obj_file_name + "\" "
              "(L." + std::to_string(line_number) + "). "
              "Triangle face in the wrong format.");
        }
        indices.push_back(index);
      }
      if (indices.size() != 3) {
        throw std::runtime_error(
            "In file \"" + obj_file_name + "\" "
            "(L." + std::to_string(line_number) + "). "
            "Only triangular faces supported. However "
            + std::to_string(indices.size()) + " indices are provided.");
      }
      triangles->push_back(Vector3i(indices[0]-1, indices[1]-1, indices[2]-1));
    }
  }
}

Mesh *Mesh::clone() const { return new Mesh(*this); }

void Mesh::getPoints(Eigen::Matrix3Xd &point_matrix) const {
  extractMeshVertices(point_matrix);
}

void Mesh::getBoundingBoxPoints(Matrix3Xd &bbox_points) const {
  Matrix3Xd mesh_vertices;
  extractMeshVertices(mesh_vertices);

  Vector3d min_pos = mesh_vertices.rowwise().minCoeff();
  Vector3d max_pos = mesh_vertices.rowwise().maxCoeff();

  bbox_points.resize(Eigen::NoChange, NUM_BBOX_POINTS);
  bbox_points << min_pos(0), min_pos(0), min_pos(0), min_pos(0), max_pos(0),
      max_pos(0), max_pos(0), max_pos(0), min_pos(1), min_pos(1), max_pos(1),
      max_pos(1), min_pos(1), min_pos(1), max_pos(1), max_pos(1), min_pos(2),
      max_pos(2), min_pos(2), max_pos(2), min_pos(2), max_pos(2), min_pos(2),
      max_pos(2);
}

std::ostream &operator<<(std::ostream &out, const Mesh &mm) {
  out << static_cast<const Geometry &>(mm) << ", " << mm.scale << ", "
      << mm.filename << ", " << mm.resolved_filename << ", " << mm.root_dir;
  return out;
}

MeshPoints::MeshPoints(const Eigen::Matrix3Xd &points)
    : Geometry(MESH_POINTS), points(points) {}

MeshPoints *MeshPoints::clone() const { return new MeshPoints(*this); }

void MeshPoints::getPoints(Eigen::Matrix3Xd &point_matrix) const {
  point_matrix = points;
}

void MeshPoints::getBoundingBoxPoints(Matrix3Xd &bbox_points) const {
  Vector3d min_pos = points.rowwise().minCoeff();
  Vector3d max_pos = points.rowwise().maxCoeff();

  bbox_points.resize(Eigen::NoChange, NUM_BBOX_POINTS);
  bbox_points << min_pos(0), min_pos(0), min_pos(0), min_pos(0), max_pos(0),
      max_pos(0), max_pos(0), max_pos(0), min_pos(1), min_pos(1), max_pos(1),
      max_pos(1), min_pos(1), min_pos(1), max_pos(1), max_pos(1), min_pos(2),
      max_pos(2), min_pos(2), max_pos(2), min_pos(2), max_pos(2), min_pos(2),
      max_pos(2);
}

std::ostream &operator<<(std::ostream &out, const MeshPoints &mp) {
  out << static_cast<const Geometry &>(mp) << ",\n" << mp.points;
  return out;
}

}  // namespace DrakeShapes
<commit_msg>std::ostream --> ostream<commit_after>#include "Geometry.h"

#include <cstdio>
#include <fstream>
#include <stdexcept>

#include "spruce.hh"

using std::string;
using std::ostream;
using std::istringstream;
using std::ifstream;

using Eigen::Vector3i;
using Eigen::Vector3d;
using Eigen::RowVectorXd;
using Eigen::Matrix3Xd;
using Eigen::Matrix3Xi;

namespace DrakeShapes {
const int Geometry::NUM_BBOX_POINTS = 8;
const int Sphere::NUM_POINTS = 1;
const int Capsule::NUM_POINTS = 2;

string ShapeToString(Shape ss) {
  switch (ss) {
    case UNKNOWN:
      return "UNKNOWN";
    case BOX:
      return "BOX";
    case SPHERE:
      return "SPHERE";
    case CYLINDER:
      return "CYLINDER";
    case MESH:
      return "MESH";
    case MESH_POINTS:
      return "MESH_POINTS";
    case CAPSULE:
      return "CAPSULE";
  }
  return "UNDEFINED";
}

Geometry::Geometry() : shape(UNKNOWN) {}

Geometry::Geometry(const Geometry &other) { shape = other.getShape(); }

Geometry::Geometry(Shape shape) : shape(shape) {}

Shape Geometry::getShape() const { return shape; }

Geometry *Geometry::clone() const { return new Geometry(*this); }

void Geometry::getPoints(Matrix3Xd &points) const { points = Matrix3Xd(); }

void Geometry::getBoundingBoxPoints(Matrix3Xd &points) const {
  points = Matrix3Xd();
}

void Geometry::getBoundingBoxPoints(double x_half_width, double y_half_width,
                                    double z_half_width,
                                    Eigen::Matrix3Xd &points) const {
  // Return axis-aligned bounding-box vertices
  points.resize(3, NUM_BBOX_POINTS);

  RowVectorXd cx(NUM_BBOX_POINTS), cy(NUM_BBOX_POINTS), cz(NUM_BBOX_POINTS);
  cx << -1, 1, 1, -1, -1, 1, 1, -1;
  cy << 1, 1, 1, 1, -1, -1, -1, -1;
  cz << 1, 1, -1, -1, -1, -1, 1, 1;
  cx = cx * x_half_width;
  cy = cy * y_half_width;
  cz = cz * z_half_width;

  points << cx, cy, cz;
}

ostream &operator<<(ostream &out, const Geometry &gg) {
  out << ShapeToString(gg.getShape()) << ", " << gg.NUM_BBOX_POINTS;
  return out;
}

Sphere::Sphere(double radius) : Geometry(SPHERE), radius(radius) {}

Sphere *Sphere::clone() const { return new Sphere(*this); }

void Sphere::getPoints(Matrix3Xd &points) const {
  points = Matrix3Xd::Zero(3, NUM_POINTS);
}

void Sphere::getBoundingBoxPoints(Matrix3Xd &points) const {
  Geometry::getBoundingBoxPoints(radius, radius, radius, points);
}

void Sphere::getTerrainContactPoints(Matrix3Xd &points) const {
  if (radius < 1e-6)
    getPoints(points);
  else
    points = Matrix3Xd();
}

ostream &operator<<(ostream &out, const Sphere &ss) {
  out << static_cast<const Geometry &>(ss) << ", " << ss.radius << ", "
      << ss.NUM_POINTS;
  return out;
}

Box::Box(const Eigen::Vector3d &size) : Geometry(BOX), size(size) {}

Box *Box::clone() const { return new Box(*this); }

void Box::getPoints(Matrix3Xd &points) const {
  Geometry::getBoundingBoxPoints(size(0) / 2.0, size(1) / 2.0, size(2) / 2.0,
                                 points);
}

void Box::getBoundingBoxPoints(Matrix3Xd &points) const { getPoints(points); }

void Box::getTerrainContactPoints(Matrix3Xd &points) const {
  getPoints(points);
}

ostream &operator<<(ostream &out, const Box &bb) {
  out << static_cast<const Geometry &>(bb) << ", " << bb.size.transpose();
  return out;
}

Cylinder::Cylinder(double radius, double length)
    : Geometry(CYLINDER), radius(radius), length(length) {}

Cylinder *Cylinder::clone() const { return new Cylinder(*this); }

void Cylinder::getPoints(Matrix3Xd &points) const {
  static bool warnOnce = true;
  if (warnOnce) {
    std::cerr << "Warning: DrakeShapes::Cylinder::getPoints(): "
        "This method returns the vertices of the cylinder''s bounding-box."
         << std::endl;
    warnOnce = false;
  }

  getBoundingBoxPoints(points);
}

void Cylinder::getBoundingBoxPoints(Matrix3Xd &points) const {
  Geometry::getBoundingBoxPoints(radius, radius, length / 2.0, points);
}

ostream &operator<<(ostream &out, const Cylinder &cc) {
  out << static_cast<const Geometry &>(cc) << ", " << cc.radius << ", "
      << cc.length;
  return out;
}

Capsule::Capsule(double radius, double length)
    : Geometry(CAPSULE), radius(radius), length(length) {}

Capsule *Capsule::clone() const { return new Capsule(*this); }

void Capsule::getPoints(Matrix3Xd &points) const {
  // Return segment end-points
  points.resize(Eigen::NoChange, NUM_POINTS);
  RowVectorXd cx = RowVectorXd::Zero(NUM_POINTS);
  RowVectorXd cy = RowVectorXd::Zero(NUM_POINTS);
  RowVectorXd cz = RowVectorXd::Zero(NUM_POINTS);
  cz << length / 2.0, -length / 2.0;

  points << cx, cy, cz;
}

void Capsule::getBoundingBoxPoints(Matrix3Xd &points) const {
  Geometry::getBoundingBoxPoints(radius, radius, (length / 2.0 + radius),
                                 points);
}

ostream &operator<<(ostream &out, const Capsule &cc) {
  out << static_cast<const Geometry &>(cc) << ", " << cc.radius << ", "
      << cc.length;
  return out;
}

Mesh::Mesh(const string &filename)
    : Geometry(MESH), scale(1.0, 1.0, 1.0), filename(filename) {}

Mesh::Mesh(const string &filename, const string &resolved_filename)
    : Geometry(MESH),
      scale(1.0, 1.0, 1.0),
      filename(filename),
      resolved_filename(resolved_filename) {}

bool Mesh::extractMeshVertices(Matrix3Xd& vertex_coordinates) const {
  if (resolved_filename.empty()) return false;

  string obj_file_name = FindFileWithObjExtension();
  ifstream file(obj_file_name);
  if (!file) {
    throw std::runtime_error(
        "Error opening file \"" + obj_file_name + "\".");
  }

  string line;
  // Count the number of vertices and resize vertex_coordinates.
  int num_vertices = 0;
  while (getline(file, line)) {
    istringstream iss(line);
    string type;
    if (iss >> type && type == "v") {
      ++num_vertices;
    }
  }
  vertex_coordinates.resize(3, num_vertices);

  file.clear();
  file.seekg(0, file.beg);

  double d;
  int j = 0;
  while (getline(file, line)) {
    istringstream iss(line);
    string type;
    if (iss >> type && type == "v") {
      int i = 0;
      while (iss >> d) {
        vertex_coordinates(i++, j) = d;
      }
      ++j;
    }
  }
  return true;
}

string Mesh::FindFileWithObjExtension() const {
  spruce::path spath(resolved_filename);
  string ext = spath.extension();
  std::transform(ext.begin(), ext.end(), ext.begin(), ::tolower);

  if (ext.compare(".obj") == 0) {
    // Checks if the file with the obj extension exists.
    if (!spath.exists()) {
      throw std::runtime_error(
          "Unable to open file \"" + spath.getStr() + "\".");
    }
  } else {
    // Tries changing the extension to obj.
    spath.setExtension(".obj");
    if (!spath.exists()) {
      throw std::runtime_error(
          "Unable to resolve an obj file from the filename \""
              + spath.getStr() + "\" provided.");
    }
  }

  return spath.getStr();
}

void Mesh::LoadObjFile(PointsVector* vertices,
                       TrianglesVector* triangles) const {
  string obj_file_name = FindFileWithObjExtension();
  ifstream file(obj_file_name);
  if (!file) {
    throw std::runtime_error(
        "Error opening file \"" + obj_file_name + "\".");
  }

  std::string line;
  int line_number = 0;
  while (!file.eof()) {
    ++line_number;
    std::getline(file, line);
    std::stringstream ss(line);
    std::string key;
    ss >> key;

    if (key == "v") {
      // Reads a 3D vertex.
      double x, y, z;
      ss >> x; ss >> y; ss >> z;
      if (ss.fail()) {
        throw std::runtime_error(
            "In file \"" + obj_file_name + "\" "
            "(L." + std::to_string(line_number) + "). "
            "Vertex in the wrong format.");
      }
      vertices->push_back(Vector3d(x, y, z));
    } else if (key == "f") {
      // Reads the connectivity for a single triangle.
      std::vector<int> indices;
      int index;
      while (ss >> index) {
        // Ignores line until the next whitespace.
        // This effectively ignores texture coordinates and normals.
        // The first entry always corresponds to an index in the face.
        ss.ignore(line.size(), ' ');
        if (ss.fail()) {
          throw std::runtime_error(
              "In file \"" + obj_file_name + "\" "
              "(L." + std::to_string(line_number) + "). "
              "Triangle face in the wrong format.");
        }
        indices.push_back(index);
      }
      if (indices.size() != 3) {
        throw std::runtime_error(
            "In file \"" + obj_file_name + "\" "
            "(L." + std::to_string(line_number) + "). "
            "Only triangular faces supported. However "
            + std::to_string(indices.size()) + " indices are provided.");
      }
      triangles->push_back(Vector3i(indices[0]-1, indices[1]-1, indices[2]-1));
    }
  }
}

Mesh *Mesh::clone() const { return new Mesh(*this); }

void Mesh::getPoints(Eigen::Matrix3Xd &point_matrix) const {
  extractMeshVertices(point_matrix);
}

void Mesh::getBoundingBoxPoints(Matrix3Xd &bbox_points) const {
  Matrix3Xd mesh_vertices;
  extractMeshVertices(mesh_vertices);

  Vector3d min_pos = mesh_vertices.rowwise().minCoeff();
  Vector3d max_pos = mesh_vertices.rowwise().maxCoeff();

  bbox_points.resize(Eigen::NoChange, NUM_BBOX_POINTS);
  bbox_points << min_pos(0), min_pos(0), min_pos(0), min_pos(0), max_pos(0),
      max_pos(0), max_pos(0), max_pos(0), min_pos(1), min_pos(1), max_pos(1),
      max_pos(1), min_pos(1), min_pos(1), max_pos(1), max_pos(1), min_pos(2),
      max_pos(2), min_pos(2), max_pos(2), min_pos(2), max_pos(2), min_pos(2),
      max_pos(2);
}

ostream &operator<<(ostream &out, const Mesh &mm) {
  out << static_cast<const Geometry &>(mm) << ", " << mm.scale << ", "
      << mm.filename << ", " << mm.resolved_filename << ", " << mm.root_dir;
  return out;
}

MeshPoints::MeshPoints(const Eigen::Matrix3Xd &points)
    : Geometry(MESH_POINTS), points(points) {}

MeshPoints *MeshPoints::clone() const { return new MeshPoints(*this); }

void MeshPoints::getPoints(Eigen::Matrix3Xd &point_matrix) const {
  point_matrix = points;
}

void MeshPoints::getBoundingBoxPoints(Matrix3Xd &bbox_points) const {
  Vector3d min_pos = points.rowwise().minCoeff();
  Vector3d max_pos = points.rowwise().maxCoeff();

  bbox_points.resize(Eigen::NoChange, NUM_BBOX_POINTS);
  bbox_points << min_pos(0), min_pos(0), min_pos(0), min_pos(0), max_pos(0),
      max_pos(0), max_pos(0), max_pos(0), min_pos(1), min_pos(1), max_pos(1),
      max_pos(1), min_pos(1), min_pos(1), max_pos(1), max_pos(1), min_pos(2),
      max_pos(2), min_pos(2), max_pos(2), min_pos(2), max_pos(2), min_pos(2),
      max_pos(2);
}

ostream &operator<<(ostream &out, const MeshPoints &mp) {
  out << static_cast<const Geometry &>(mp) << ",\n" << mp.points;
  return out;
}

}  // namespace DrakeShapes
<|endoftext|>


<commit_before>//============================================================================
// vSMC/example/pf/include/pf_mpi_do.hpp
//----------------------------------------------------------------------------
//                         vSMC: Scalable Monte Carlo
//----------------------------------------------------------------------------
// Copyright (c) 2013,2014, Yan Zhou
// 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.
//
// 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 HOLDER 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.
//============================================================================

#ifndef VSMC_EXAMPLE_PF_MPI_DO_HPP
#define VSMC_EXAMPLE_PF_MPI_DO_HPP

template <vsmc::MatrixOrder Order>
inline void cv_do (vsmc::ResampleScheme res, char **argv,
        const std::string &name)
{
    vsmc::Seed::instance().set(101);
    std::size_t N = (ParticleNum / 3) *
        static_cast<std::size_t>(boost::mpi::communicator().rank() + 1);
    vsmc::Sampler<cv_state<Order> > sampler(N, res, 0.5);
    sampler
        .init(cv_init<Order>())
        .move(vsmc::MoveAdapter<
                cv_state<Order>, BASE_MOVE, cv_move<Order> >(), true)
        .monitor("pos", 2, vsmc::MonitorEvalAdapter<
                cv_state<Order>, BASE_MONITOR>(cv_est<Order>));
    sampler.monitor("pos").name(0) = "pos.x";
    sampler.monitor("pos").name(1) = "pos.y";
    std::stringstream ss;
    ss << name << ".r" << sampler.particle().value().world().rank();
    std::string rname(ss.str());

#if VSMC_HAS_HDF5
    sampler.initialize(argv[1]);
    vsmc::hdf5store(sampler.particle().value(),
            argv[2] + rname + ".trace.h5", "Trace.0");
    for (std::size_t i = 0; i != DataNum - 1; ++i) {
        std::stringstream tss;
        tss << "Trace." << (i + 1);
        sampler.iterate();
        vsmc::hdf5store(sampler.particle().value(),
                argv[2] + rname + ".trace.h5", tss.str(), true);
    }
#else
    sampler.initialize(argv[1]);
    sampler.iterate(DataNum - 1);
#endif

    std::string est_file_name(argv[2] + rname + ".tsv");
    std::ofstream est_file;
    est_file.open(est_file_name.c_str());
    est_file << sampler << std::endl;
    est_file.close();
    est_file_name = argv[2] + rname + ".trace.tsv";
    est_file.open(est_file_name.c_str());
    est_file << sampler.particle().value() << std::endl;
    est_file.close();

    const std::vector<std::size_t> &send_num =
        sampler.particle().value().copy_send_num();
    std::string send_file_name(argv[2] + rname + ".send");
    std::ofstream send_file;
    send_file.open(send_file_name.c_str());
    for (std::size_t i = 0; i != send_num.size(); ++i)
        send_file << send_num[i] << '\n';
    send_file.close();

#if VSMC_HAS_HDF5
    vsmc::hdf5store(sampler, argv[2] + rname + ".h5", "Sampler");
#endif
}

#endif // VSMC_EXAMPLE_PF_MPI_DO_HPP
<commit_msg>remove use of send num<commit_after>//============================================================================
// vSMC/example/pf/include/pf_mpi_do.hpp
//----------------------------------------------------------------------------
//                         vSMC: Scalable Monte Carlo
//----------------------------------------------------------------------------
// Copyright (c) 2013,2014, Yan Zhou
// 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.
//
// 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 HOLDER 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.
//============================================================================

#ifndef VSMC_EXAMPLE_PF_MPI_DO_HPP
#define VSMC_EXAMPLE_PF_MPI_DO_HPP

template <vsmc::MatrixOrder Order>
inline void cv_do (vsmc::ResampleScheme res, char **argv,
        const std::string &name)
{
    vsmc::Seed::instance().set(101);
    std::size_t N = (ParticleNum / 3) *
        static_cast<std::size_t>(boost::mpi::communicator().rank() + 1);
    vsmc::Sampler<cv_state<Order> > sampler(N, res, 0.5);
    sampler
        .init(cv_init<Order>())
        .move(vsmc::MoveAdapter<
                cv_state<Order>, BASE_MOVE, cv_move<Order> >(), true)
        .monitor("pos", 2, vsmc::MonitorEvalAdapter<
                cv_state<Order>, BASE_MONITOR>(cv_est<Order>));
    sampler.monitor("pos").name(0) = "pos.x";
    sampler.monitor("pos").name(1) = "pos.y";
    std::stringstream ss;
    ss << name << ".r" << sampler.particle().value().world().rank();
    std::string rname(ss.str());

#if VSMC_HAS_HDF5
    sampler.initialize(argv[1]);
    vsmc::hdf5store(sampler.particle().value(),
            argv[2] + rname + ".trace.h5", "Trace.0");
    for (std::size_t i = 0; i != DataNum - 1; ++i) {
        std::stringstream tss;
        tss << "Trace." << (i + 1);
        sampler.iterate();
        vsmc::hdf5store(sampler.particle().value(),
                argv[2] + rname + ".trace.h5", tss.str(), true);
    }
#else
    sampler.initialize(argv[1]);
    sampler.iterate(DataNum - 1);
#endif

    std::string est_file_name(argv[2] + rname + ".tsv");
    std::ofstream est_file;
    est_file.open(est_file_name.c_str());
    est_file << sampler << std::endl;
    est_file.close();
    est_file_name = argv[2] + rname + ".trace.tsv";
    est_file.open(est_file_name.c_str());
    est_file << sampler.particle().value() << std::endl;
    est_file.close();

#if VSMC_HAS_HDF5
    vsmc::hdf5store(sampler, argv[2] + rname + ".h5", "Sampler");
#endif
}

#endif // VSMC_EXAMPLE_PF_MPI_DO_HPP
<|endoftext|>


<commit_before>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: ed_ioleobject.cxx,v $
 *
 *  $Revision: 1.19 $
 *
 *  last change: $Author: obo $ $Date: 2007-01-25 11:36:17 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    This library is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *    Lesser General Public License for more details.
 *
 *    You should have received a copy of the GNU Lesser General Public
 *    License along with this library; if not, write to the Free Software
 *    Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/

#include "embeddoc.hxx"

#ifndef _OSL_DIAGNOSE_H_
#include <ols/diagnose.h>
#endif
#ifndef _COM_SUN_STAR_FRAME_XController_HPP_
#include <com/sun/star/frame/XController.hpp>
#endif
#ifndef _COM_SUN_STAR_BEANS_PROPERTYVALUE_HPP_
#include <com/sun/star/beans/PropertyValue.hpp>
#endif

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

extern ::rtl::OUString  getFilterNameFromGUID_Impl( GUID* );

//-------------------------------------------------------------------------------
// IOleObject

STDMETHODIMP EmbedDocument_Impl::SetClientSite( IOleClientSite* pSite )
{
    m_pClientSite = pSite;
    return S_OK;
}

STDMETHODIMP EmbedDocument_Impl::GetClientSite( IOleClientSite** pSite )
{
    *pSite = m_pClientSite;
    return S_OK;
}

STDMETHODIMP EmbedDocument_Impl::SetHostNames( LPCOLESTR szContainerApp, LPCOLESTR szContainerObj )
{
    // the code should be ignored for links
    if ( !m_aFileName.getLength() )
    {
        m_pDocHolder->setTitle(
            rtl::OUString(
                (sal_Unicode*)szContainerObj));
        m_pDocHolder->setContainerName(
            rtl::OUString(
                (sal_Unicode*)szContainerApp));
    }

    return S_OK;
}

STDMETHODIMP EmbedDocument_Impl::Close( DWORD dwSaveOption )
{
    if ( dwSaveOption == 2 && m_aFileName.getLength() )
    {
        // ask the user about saving
        if ( m_pDocHolder->ExecuteSuspendCloseFrame() )
        {
            m_pDocHolder->CloseDocument();
            return S_OK;
        }
        else
            return OLE_E_PROMPTSAVECANCELLED;
    }

    HRESULT hr = S_OK;

    if ( dwSaveOption != 1 )
        hr = SaveObject(); // ADVF_DATAONSTOP);

    m_pDocHolder->FreeOffice();
    m_pDocHolder->CloseDocument();
    m_pDocHolder->CloseFrame();

    OLENotifyClosing();

    return hr;
}

HRESULT EmbedDocument_Impl::OLENotifyClosing()
{
    HRESULT hr = S_OK;

    if ( m_pClientSite )
        m_pClientSite->OnShowWindow( FALSE );

    AdviseSinkHashMap aAHM(m_aAdviseHashMap);

    for ( AdviseSinkHashMapIterator iAdvise = aAHM.begin();
          iAdvise != aAHM.end(); iAdvise++ )
    {
        if ( iAdvise->second )
            iAdvise->second->OnClose();
    }

    return hr;

}

STDMETHODIMP EmbedDocument_Impl::SetMoniker( DWORD /*dwWhichMoniker*/, IMoniker * /*pmk*/ )
{
    return E_NOTIMPL;
}

STDMETHODIMP EmbedDocument_Impl::GetMoniker( DWORD /*dwAssign*/, DWORD /*dwWhichMoniker*/, IMoniker ** /*ppmk*/ )
{
    return E_NOTIMPL;
}

STDMETHODIMP EmbedDocument_Impl::InitFromData( IDataObject * /*pDataObject*/, BOOL /*fCreation*/, DWORD /*dwReserved*/ )
{
    return E_NOTIMPL;
}

STDMETHODIMP EmbedDocument_Impl::GetClipboardData( DWORD /*dwReserved*/, IDataObject ** /*ppDataObject*/ )
{
    return E_NOTIMPL;
}

/**
 *  Well, this is a not so very inefficient way to deliver
 *
 */

STDMETHODIMP EmbedDocument_Impl::DoVerb(
    LONG iVerb,
    LPMSG,
    IOleClientSite *pActiveSite,
    LONG,
    HWND,
    LPCRECT )
{
    // no locking is used since the OLE must use the same thread always
    if ( m_bIsInVerbHandling )
        return OLEOBJ_S_CANNOT_DOVERB_NOW;

    BooleanGuard_Impl aGuard( m_bIsInVerbHandling );

    if ( iVerb == OLEIVERB_PRIMARY )
    {
        if ( m_aFileName.getLength() )
        {
            // that should be a link
            iVerb = OLEIVERB_OPEN;
        }
        else
            iVerb = OLEIVERB_SHOW;
    }

    try
    {
        switch(iVerb) {
            case OLEIVERB_DISCARDUNDOSTATE:
                // free any undostate?
                break;
            case OLEIVERB_INPLACEACTIVATE:
                OSL_ENSURE(m_pDocHolder,"no document for inplace activation");

                return m_pDocHolder->InPlaceActivate(pActiveSite,FALSE);
                break;
            case OLEIVERB_UIACTIVATE:
                OSL_ENSURE(m_pDocHolder,"no document for     inplace activation");

                return m_pDocHolder->InPlaceActivate(pActiveSite,TRUE);
                break;
            case OLEIVERB_PRIMARY:
            case OLEIVERB_SHOW:
                OSL_ENSURE(m_pDocHolder,"no document for inplace activation");

                if(m_pDocHolder->isActive())
                    return NOERROR; //Already active

                if(SUCCEEDED(
                    m_pDocHolder->InPlaceActivate(
                        pActiveSite,TRUE)))
                    return NOERROR;

                // intended fall trough
            case OLEIVERB_OPEN:
                OSL_ENSURE(m_pDocHolder,"no document to open");

                // the commented code could be usefull in case
                // outer window would be resized depending from inner one
                // RECTL aEmbArea;
                // m_pDocHolder->GetVisArea( &aEmbArea );
                // m_pDocHolder->show();
                // m_pDocHolder->SetVisArea( &aEmbArea );

                if(m_pDocHolder->isActive())
                {
                    m_pDocHolder->InPlaceDeactivate();
                    m_pDocHolder->DisableInplaceActivation(true);
                }

                SIZEL aEmbSize;
                m_pDocHolder->GetExtent( &aEmbSize );
                m_pDocHolder->show();
                m_pDocHolder->resizeWin( aEmbSize );

                if ( m_pClientSite )
                    m_pClientSite->OnShowWindow( TRUE );

                notify();
                break;
            case OLEIVERB_HIDE:
                OSL_ENSURE(m_pDocHolder,"no document to hide");

                if(m_pDocHolder->isActive())
                    m_pDocHolder->InPlaceDeactivate();
                else {
                    m_pDocHolder->hide();

                    if( m_pClientSite )
                        m_pClientSite->OnShowWindow(FALSE);
                }
                break;
            default:
                break;
        }
    }
    catch( uno::Exception& )
    {
        return OLEOBJ_S_CANNOT_DOVERB_NOW;
    }

    return NOERROR;
}

STDMETHODIMP EmbedDocument_Impl::EnumVerbs( IEnumOLEVERB ** /*ppEnumOleVerb*/ )
{
    return OLE_S_USEREG;
}

STDMETHODIMP EmbedDocument_Impl::Update()
{
    return S_OK;
}

STDMETHODIMP EmbedDocument_Impl::IsUpToDate()
{
    return S_OK;
}

STDMETHODIMP EmbedDocument_Impl::GetUserClassID( CLSID *pClsid )
{
    return GetClassID( pClsid );
}

STDMETHODIMP EmbedDocument_Impl::GetUserType( DWORD /*dwFormOfTypeUe*/, LPOLESTR * /*pszUserType*/ )
{
    return OLE_S_USEREG;
}

STDMETHODIMP EmbedDocument_Impl::SetExtent( DWORD /*dwDrawAspect*/, SIZEL *psizel )
{
    if ( !psizel )
        return E_FAIL;

    m_pDocHolder->SetExtent( psizel );

    return S_OK;
}

STDMETHODIMP EmbedDocument_Impl::GetExtent( DWORD /*dwDrawAspect*/, SIZEL * psizel )
{
    if ( !psizel )
        return E_INVALIDARG;

    if ( FAILED( m_pDocHolder->GetExtent( psizel ) ) )
    {
        // return default values
        psizel->cx = 500;
        psizel->cy = 500;
    }

    return S_OK;
}

STDMETHODIMP EmbedDocument_Impl::Advise( IAdviseSink *pAdvSink, DWORD *pdwConnection )
{
    if ( m_nAdviseNum == 0xFFFFFFFF )
        return E_OUTOFMEMORY;

    pAdvSink->AddRef();
    m_aAdviseHashMap.insert( ::std::pair< DWORD, IAdviseSink* >( m_nAdviseNum, pAdvSink ) );
    *pdwConnection = m_nAdviseNum++;

    return S_OK;
}

STDMETHODIMP EmbedDocument_Impl::Unadvise( DWORD dwConnection )
{
    AdviseSinkHashMapIterator iAdvise = m_aAdviseHashMap.find( dwConnection );
    if ( iAdvise != m_aAdviseHashMap.end() )
    {
        iAdvise->second->Release();
        m_aAdviseHashMap.erase( iAdvise );
    }
    else
        return OLE_E_NOCONNECTION;

    return S_OK;
}

STDMETHODIMP EmbedDocument_Impl::EnumAdvise( IEnumSTATDATA ** /*ppenumAdvise*/ )
{
    return E_NOTIMPL;
}

STDMETHODIMP EmbedDocument_Impl::GetMiscStatus( DWORD /*dwAspect*/, DWORD * /*pdwStatus*/ )
{
    return OLE_S_USEREG;
}

STDMETHODIMP EmbedDocument_Impl::SetColorScheme( LOGPALETTE * /*pLogpal*/ )
{
    return E_NOTIMPL;
}

//-------------------------------------------------------------------------------
// IDispatch

STDMETHODIMP EmbedDocument_Impl::GetTypeInfoCount( unsigned int FAR*  pctinfo )
{
    if ( m_pDocHolder->GetIDispatch() )
        return m_pDocHolder->GetIDispatch()->GetTypeInfoCount( pctinfo );

    return E_NOTIMPL;
}

STDMETHODIMP EmbedDocument_Impl::GetTypeInfo( unsigned int iTInfo, LCID lcid, ITypeInfo FAR* FAR* ppTInfo )
{
    if ( m_pDocHolder->GetIDispatch() )
        return m_pDocHolder->GetIDispatch()->GetTypeInfo( iTInfo, lcid, ppTInfo );

    return DISP_E_BADINDEX; // the only error that can be returned
}

STDMETHODIMP EmbedDocument_Impl::GetIDsOfNames( REFIID riid,
                                                OLECHAR FAR* FAR* rgszNames,
                                                unsigned int cNames,
                                                LCID lcid,
                                                DISPID FAR* rgDispId )
{
    if ( m_pDocHolder->GetIDispatch() )
        return m_pDocHolder->GetIDispatch()->GetIDsOfNames( riid, rgszNames, cNames, lcid, rgDispId );

    for ( unsigned int ind = 0; ind < cNames; ind++ )
        rgDispId[ind] = DISPID_UNKNOWN;

    return DISP_E_UNKNOWNNAME;
}

STDMETHODIMP EmbedDocument_Impl::Invoke( DISPID dispIdMember,
                                         REFIID riid,
                                         LCID lcid,
                                         WORD wFlags,
                                         DISPPARAMS FAR* pDispParams,
                                         VARIANT FAR* pVarResult,
                                         EXCEPINFO FAR* pExcepInfo,
                                         unsigned int FAR* puArgErr )
{
    if ( m_pDocHolder->GetIDispatch() )
        return m_pDocHolder->GetIDispatch()->Invoke( dispIdMember,
                                                     riid,
                                                     lcid,
                                                     wFlags,
                                                     pDispParams,
                                                     pVarResult,
                                                     pExcepInfo,
                                                     puArgErr );

    return DISP_E_MEMBERNOTFOUND;
}

// C++ - methods

HRESULT EmbedDocument_Impl::SaveObject()
{
    HRESULT hr = S_OK;

    if(m_pClientSite) {
        hr = m_pClientSite->SaveObject();

        for ( AdviseSinkHashMapIterator iAdvise =
                  m_aAdviseHashMap.begin();
              iAdvise != m_aAdviseHashMap.end();
              iAdvise++ )
            if ( iAdvise->second )
                iAdvise->second->OnSave( );
    }
    else if ( m_aFileName.getLength() && IsDirty() == S_OK )
    {
        ::rtl::OUString aPreservFileName = m_aFileName;

        // in case of links the containers does not provide client site sometimes
        hr = Save( (LPCOLESTR)NULL, FALSE ); // triggers saving to the link location
        SaveCompleted( (LPCOLESTR)aPreservFileName.getStr() );
    }

    notify( false );

    return hr;
}

HRESULT EmbedDocument_Impl::ShowObject()
{
    HRESULT hr = S_OK;

    if(m_pClientSite)
        hr = m_pClientSite->ShowObject();

    return hr;
}

void EmbedDocument_Impl::notify( bool bDataChanged )
{
    for ( AdviseSinkHashMapIterator iAdvise =
              m_aAdviseHashMap.begin();
          iAdvise != m_aAdviseHashMap.end();
          iAdvise++ )
        if ( iAdvise->second )
            iAdvise->second->OnViewChange( DVASPECT_CONTENT, -1 );

    if ( m_pDAdviseHolder && bDataChanged )
        m_pDAdviseHolder->SendOnDataChange( (IDataObject*)this, 0, 0 );
}

// Fix strange warnings about some
// ATL::CAxHostWindow::QueryInterface|AddRef|Releae functions.
// warning C4505: 'xxx' : unreferenced local function has been removed
#if defined(_MSC_VER)
#pragma warning(disable: 4505)
#endif
<commit_msg>INTEGRATION: CWS changefileheader (1.19.28); FILE MERGED 2008/04/01 21:31:42 thb 1.19.28.4: #i85898# Corrected misspelled header name; removed misspelled include guard 2008/04/01 15:13:58 thb 1.19.28.3: #i85898# Stripping all external header guards 2008/04/01 12:29:01 thb 1.19.28.2: #i85898# Stripping all external header guards 2008/03/31 13:33:41 rt 1.19.28.1: #i87441# Change license header to LPGL v3.<commit_after>/*************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2008 by Sun Microsystems, Inc.
 *
 * OpenOffice.org - a multi-platform office productivity suite
 *
 * $RCSfile: ed_ioleobject.cxx,v $
 * $Revision: 1.20 $
 *
 * This file is part of OpenOffice.org.
 *
 * OpenOffice.org is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License version 3
 * only, as published by the Free Software Foundation.
 *
 * OpenOffice.org is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License version 3 for more details
 * (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU Lesser General Public License
 * version 3 along with OpenOffice.org.  If not, see
 * <http://www.openoffice.org/license.html>
 * for a copy of the LGPLv3 License.
 *
 ************************************************************************/

#include "embeddoc.hxx"
#include <osl/diagnose.h>
#include <com/sun/star/frame/XController.hpp>
#include <com/sun/star/beans/PropertyValue.hpp>

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

extern ::rtl::OUString  getFilterNameFromGUID_Impl( GUID* );

//-------------------------------------------------------------------------------
// IOleObject

STDMETHODIMP EmbedDocument_Impl::SetClientSite( IOleClientSite* pSite )
{
    m_pClientSite = pSite;
    return S_OK;
}

STDMETHODIMP EmbedDocument_Impl::GetClientSite( IOleClientSite** pSite )
{
    *pSite = m_pClientSite;
    return S_OK;
}

STDMETHODIMP EmbedDocument_Impl::SetHostNames( LPCOLESTR szContainerApp, LPCOLESTR szContainerObj )
{
    // the code should be ignored for links
    if ( !m_aFileName.getLength() )
    {
        m_pDocHolder->setTitle(
            rtl::OUString(
                (sal_Unicode*)szContainerObj));
        m_pDocHolder->setContainerName(
            rtl::OUString(
                (sal_Unicode*)szContainerApp));
    }

    return S_OK;
}

STDMETHODIMP EmbedDocument_Impl::Close( DWORD dwSaveOption )
{
    if ( dwSaveOption == 2 && m_aFileName.getLength() )
    {
        // ask the user about saving
        if ( m_pDocHolder->ExecuteSuspendCloseFrame() )
        {
            m_pDocHolder->CloseDocument();
            return S_OK;
        }
        else
            return OLE_E_PROMPTSAVECANCELLED;
    }

    HRESULT hr = S_OK;

    if ( dwSaveOption != 1 )
        hr = SaveObject(); // ADVF_DATAONSTOP);

    m_pDocHolder->FreeOffice();
    m_pDocHolder->CloseDocument();
    m_pDocHolder->CloseFrame();

    OLENotifyClosing();

    return hr;
}

HRESULT EmbedDocument_Impl::OLENotifyClosing()
{
    HRESULT hr = S_OK;

    if ( m_pClientSite )
        m_pClientSite->OnShowWindow( FALSE );

    AdviseSinkHashMap aAHM(m_aAdviseHashMap);

    for ( AdviseSinkHashMapIterator iAdvise = aAHM.begin();
          iAdvise != aAHM.end(); iAdvise++ )
    {
        if ( iAdvise->second )
            iAdvise->second->OnClose();
    }

    return hr;

}

STDMETHODIMP EmbedDocument_Impl::SetMoniker( DWORD /*dwWhichMoniker*/, IMoniker * /*pmk*/ )
{
    return E_NOTIMPL;
}

STDMETHODIMP EmbedDocument_Impl::GetMoniker( DWORD /*dwAssign*/, DWORD /*dwWhichMoniker*/, IMoniker ** /*ppmk*/ )
{
    return E_NOTIMPL;
}

STDMETHODIMP EmbedDocument_Impl::InitFromData( IDataObject * /*pDataObject*/, BOOL /*fCreation*/, DWORD /*dwReserved*/ )
{
    return E_NOTIMPL;
}

STDMETHODIMP EmbedDocument_Impl::GetClipboardData( DWORD /*dwReserved*/, IDataObject ** /*ppDataObject*/ )
{
    return E_NOTIMPL;
}

/**
 *  Well, this is a not so very inefficient way to deliver
 *
 */

STDMETHODIMP EmbedDocument_Impl::DoVerb(
    LONG iVerb,
    LPMSG,
    IOleClientSite *pActiveSite,
    LONG,
    HWND,
    LPCRECT )
{
    // no locking is used since the OLE must use the same thread always
    if ( m_bIsInVerbHandling )
        return OLEOBJ_S_CANNOT_DOVERB_NOW;

    BooleanGuard_Impl aGuard( m_bIsInVerbHandling );

    if ( iVerb == OLEIVERB_PRIMARY )
    {
        if ( m_aFileName.getLength() )
        {
            // that should be a link
            iVerb = OLEIVERB_OPEN;
        }
        else
            iVerb = OLEIVERB_SHOW;
    }

    try
    {
        switch(iVerb) {
            case OLEIVERB_DISCARDUNDOSTATE:
                // free any undostate?
                break;
            case OLEIVERB_INPLACEACTIVATE:
                OSL_ENSURE(m_pDocHolder,"no document for inplace activation");

                return m_pDocHolder->InPlaceActivate(pActiveSite,FALSE);
                break;
            case OLEIVERB_UIACTIVATE:
                OSL_ENSURE(m_pDocHolder,"no document for     inplace activation");

                return m_pDocHolder->InPlaceActivate(pActiveSite,TRUE);
                break;
            case OLEIVERB_PRIMARY:
            case OLEIVERB_SHOW:
                OSL_ENSURE(m_pDocHolder,"no document for inplace activation");

                if(m_pDocHolder->isActive())
                    return NOERROR; //Already active

                if(SUCCEEDED(
                    m_pDocHolder->InPlaceActivate(
                        pActiveSite,TRUE)))
                    return NOERROR;

                // intended fall trough
            case OLEIVERB_OPEN:
                OSL_ENSURE(m_pDocHolder,"no document to open");

                // the commented code could be usefull in case
                // outer window would be resized depending from inner one
                // RECTL aEmbArea;
                // m_pDocHolder->GetVisArea( &aEmbArea );
                // m_pDocHolder->show();
                // m_pDocHolder->SetVisArea( &aEmbArea );

                if(m_pDocHolder->isActive())
                {
                    m_pDocHolder->InPlaceDeactivate();
                    m_pDocHolder->DisableInplaceActivation(true);
                }

                SIZEL aEmbSize;
                m_pDocHolder->GetExtent( &aEmbSize );
                m_pDocHolder->show();
                m_pDocHolder->resizeWin( aEmbSize );

                if ( m_pClientSite )
                    m_pClientSite->OnShowWindow( TRUE );

                notify();
                break;
            case OLEIVERB_HIDE:
                OSL_ENSURE(m_pDocHolder,"no document to hide");

                if(m_pDocHolder->isActive())
                    m_pDocHolder->InPlaceDeactivate();
                else {
                    m_pDocHolder->hide();

                    if( m_pClientSite )
                        m_pClientSite->OnShowWindow(FALSE);
                }
                break;
            default:
                break;
        }
    }
    catch( uno::Exception& )
    {
        return OLEOBJ_S_CANNOT_DOVERB_NOW;
    }

    return NOERROR;
}

STDMETHODIMP EmbedDocument_Impl::EnumVerbs( IEnumOLEVERB ** /*ppEnumOleVerb*/ )
{
    return OLE_S_USEREG;
}

STDMETHODIMP EmbedDocument_Impl::Update()
{
    return S_OK;
}

STDMETHODIMP EmbedDocument_Impl::IsUpToDate()
{
    return S_OK;
}

STDMETHODIMP EmbedDocument_Impl::GetUserClassID( CLSID *pClsid )
{
    return GetClassID( pClsid );
}

STDMETHODIMP EmbedDocument_Impl::GetUserType( DWORD /*dwFormOfTypeUe*/, LPOLESTR * /*pszUserType*/ )
{
    return OLE_S_USEREG;
}

STDMETHODIMP EmbedDocument_Impl::SetExtent( DWORD /*dwDrawAspect*/, SIZEL *psizel )
{
    if ( !psizel )
        return E_FAIL;

    m_pDocHolder->SetExtent( psizel );

    return S_OK;
}

STDMETHODIMP EmbedDocument_Impl::GetExtent( DWORD /*dwDrawAspect*/, SIZEL * psizel )
{
    if ( !psizel )
        return E_INVALIDARG;

    if ( FAILED( m_pDocHolder->GetExtent( psizel ) ) )
    {
        // return default values
        psizel->cx = 500;
        psizel->cy = 500;
    }

    return S_OK;
}

STDMETHODIMP EmbedDocument_Impl::Advise( IAdviseSink *pAdvSink, DWORD *pdwConnection )
{
    if ( m_nAdviseNum == 0xFFFFFFFF )
        return E_OUTOFMEMORY;

    pAdvSink->AddRef();
    m_aAdviseHashMap.insert( ::std::pair< DWORD, IAdviseSink* >( m_nAdviseNum, pAdvSink ) );
    *pdwConnection = m_nAdviseNum++;

    return S_OK;
}

STDMETHODIMP EmbedDocument_Impl::Unadvise( DWORD dwConnection )
{
    AdviseSinkHashMapIterator iAdvise = m_aAdviseHashMap.find( dwConnection );
    if ( iAdvise != m_aAdviseHashMap.end() )
    {
        iAdvise->second->Release();
        m_aAdviseHashMap.erase( iAdvise );
    }
    else
        return OLE_E_NOCONNECTION;

    return S_OK;
}

STDMETHODIMP EmbedDocument_Impl::EnumAdvise( IEnumSTATDATA ** /*ppenumAdvise*/ )
{
    return E_NOTIMPL;
}

STDMETHODIMP EmbedDocument_Impl::GetMiscStatus( DWORD /*dwAspect*/, DWORD * /*pdwStatus*/ )
{
    return OLE_S_USEREG;
}

STDMETHODIMP EmbedDocument_Impl::SetColorScheme( LOGPALETTE * /*pLogpal*/ )
{
    return E_NOTIMPL;
}

//-------------------------------------------------------------------------------
// IDispatch

STDMETHODIMP EmbedDocument_Impl::GetTypeInfoCount( unsigned int FAR*  pctinfo )
{
    if ( m_pDocHolder->GetIDispatch() )
        return m_pDocHolder->GetIDispatch()->GetTypeInfoCount( pctinfo );

    return E_NOTIMPL;
}

STDMETHODIMP EmbedDocument_Impl::GetTypeInfo( unsigned int iTInfo, LCID lcid, ITypeInfo FAR* FAR* ppTInfo )
{
    if ( m_pDocHolder->GetIDispatch() )
        return m_pDocHolder->GetIDispatch()->GetTypeInfo( iTInfo, lcid, ppTInfo );

    return DISP_E_BADINDEX; // the only error that can be returned
}

STDMETHODIMP EmbedDocument_Impl::GetIDsOfNames( REFIID riid,
                                                OLECHAR FAR* FAR* rgszNames,
                                                unsigned int cNames,
                                                LCID lcid,
                                                DISPID FAR* rgDispId )
{
    if ( m_pDocHolder->GetIDispatch() )
        return m_pDocHolder->GetIDispatch()->GetIDsOfNames( riid, rgszNames, cNames, lcid, rgDispId );

    for ( unsigned int ind = 0; ind < cNames; ind++ )
        rgDispId[ind] = DISPID_UNKNOWN;

    return DISP_E_UNKNOWNNAME;
}

STDMETHODIMP EmbedDocument_Impl::Invoke( DISPID dispIdMember,
                                         REFIID riid,
                                         LCID lcid,
                                         WORD wFlags,
                                         DISPPARAMS FAR* pDispParams,
                                         VARIANT FAR* pVarResult,
                                         EXCEPINFO FAR* pExcepInfo,
                                         unsigned int FAR* puArgErr )
{
    if ( m_pDocHolder->GetIDispatch() )
        return m_pDocHolder->GetIDispatch()->Invoke( dispIdMember,
                                                     riid,
                                                     lcid,
                                                     wFlags,
                                                     pDispParams,
                                                     pVarResult,
                                                     pExcepInfo,
                                                     puArgErr );

    return DISP_E_MEMBERNOTFOUND;
}

// C++ - methods

HRESULT EmbedDocument_Impl::SaveObject()
{
    HRESULT hr = S_OK;

    if(m_pClientSite) {
        hr = m_pClientSite->SaveObject();

        for ( AdviseSinkHashMapIterator iAdvise =
                  m_aAdviseHashMap.begin();
              iAdvise != m_aAdviseHashMap.end();
              iAdvise++ )
            if ( iAdvise->second )
                iAdvise->second->OnSave( );
    }
    else if ( m_aFileName.getLength() && IsDirty() == S_OK )
    {
        ::rtl::OUString aPreservFileName = m_aFileName;

        // in case of links the containers does not provide client site sometimes
        hr = Save( (LPCOLESTR)NULL, FALSE ); // triggers saving to the link location
        SaveCompleted( (LPCOLESTR)aPreservFileName.getStr() );
    }

    notify( false );

    return hr;
}

HRESULT EmbedDocument_Impl::ShowObject()
{
    HRESULT hr = S_OK;

    if(m_pClientSite)
        hr = m_pClientSite->ShowObject();

    return hr;
}

void EmbedDocument_Impl::notify( bool bDataChanged )
{
    for ( AdviseSinkHashMapIterator iAdvise =
              m_aAdviseHashMap.begin();
          iAdvise != m_aAdviseHashMap.end();
          iAdvise++ )
        if ( iAdvise->second )
            iAdvise->second->OnViewChange( DVASPECT_CONTENT, -1 );

    if ( m_pDAdviseHolder && bDataChanged )
        m_pDAdviseHolder->SendOnDataChange( (IDataObject*)this, 0, 0 );
}

// Fix strange warnings about some
// ATL::CAxHostWindow::QueryInterface|AddRef|Releae functions.
// warning C4505: 'xxx' : unreferenced local function has been removed
#if defined(_MSC_VER)
#pragma warning(disable: 4505)
#endif
<|endoftext|>


<commit_before>#include <algorithm>
#include <iostream>
#include <string>
#include <unordered_map>
#include <utility>
#include <vector>
#include <climits>

using namespace std;

vector<int> dx = {0, 1, 0, -1};
vector<int> dy = {1, 0, -1, 0};

template <typename T>
void show(T a) {
  for (auto i : a) {
    cout << i << " ";
  }
  cout << endl;
}
template <typename T>
void showmatrix(T a) {
  for (auto j : a) {
    for (auto i : j) {
      cout << i;
    }
    cout << endl;
  }
  cout << endl;
}
void check(int i = 0) { cout << "checkpoint:[" << i << "]" << endl; }

int main(int argc, char *argv[]) {
  ios::sync_with_stdio(false);
  cin.tie(NULL);
}
<commit_msg>update template<commit_after>#include <algorithm>
#include <iostream>
#include <string>
#include <unordered_map>
#include <unordered_set>
#include <utility>
#include <vector>
#include <climits>
#include <stack>

using namespace std;
using ll=long long;

vector<int> dx = {0, 1, 0, -1};
vector<int> dy = {1, 0, -1, 0};

template <typename T>
void show(T a) {
  for (auto i : a) {
    cout << i << " ";
  }
  cout << endl;
}
template <typename T>
void showmatrix(T a) {
  for (auto j : a) {
    for (auto i : j) {
      cout << i;
    }
    cout << endl;
  }
  cout << endl;
}
void check(int i = 0) { cout << "checkpoint:[" << i << "]" << endl; }

int main(int argc, char *argv[]) {
  ios::sync_with_stdio(false);
  cin.tie(NULL);
}
<|endoftext|>


<commit_before>/**
 * Copyright (c) Facebook, Inc. and its affiliates.
 *
 * This source code is licensed under the MIT license found in the
 * LICENSE file in the root directory of this source tree.
 */

#include "RootShadowNode.h"

#include <react/components/view/conversions.h>
#include <react/debug/SystraceSection.h>

namespace facebook {
namespace react {

const char RootComponentName[] = "RootView";

void RootShadowNode::layout() {
  SystraceSection s("RootShadowNode::layout");
  ensureUnsealed();
  layout(getProps()->layoutContext);

  // This is the rare place where shadow node must layout (set `layoutMetrics`)
  // itself because there is no a parent node which usually should do it.
  if (getHasNewLayout()) {
    setLayoutMetrics(layoutMetricsFromYogaNode(yogaNode_));
    setHasNewLayout(false);
  }
}

UnsharedRootShadowNode RootShadowNode::clone(
    const LayoutConstraints &layoutConstraints,
    const LayoutContext &layoutContext) const {
  auto props = std::make_shared<const RootProps>(
      *getProps(), layoutConstraints, layoutContext);
  auto newRootShadowNode = std::make_shared<RootShadowNode>(
      *this,
      ShadowNodeFragment{
          /* .tag = */ ShadowNodeFragment::tagPlaceholder(),
          /* .rootTag = */ ShadowNodeFragment::surfaceIdPlaceholder(),
          /* .props = */ props,
      });
  return newRootShadowNode;
}

UnsharedRootShadowNode RootShadowNode::clone(
    const SharedShadowNode &oldShadowNode,
    const SharedShadowNode &newShadowNode) const {
  std::vector<std::reference_wrapper<const ShadowNode>> ancestors;

  if (!oldShadowNode->constructAncestorPath(*this, ancestors)) {
    return UnsharedRootShadowNode{nullptr};
  }

  auto oldChild = oldShadowNode;
  auto newChild = newShadowNode;

  for (const auto &ancestor : ancestors) {
    auto oldParent = ancestor.get().shared_from_this();

    auto children = oldParent->getChildren();
    std::replace(children.begin(), children.end(), oldChild, newChild);

    auto sharedChildren = std::make_shared<SharedShadowNodeList>(children);
    auto newParent = oldParent->clone({
        /* .tag = */ ShadowNodeFragment::tagPlaceholder(),
        /* .rootTag = */ ShadowNodeFragment::surfaceIdPlaceholder(),
        /* .props = */ ShadowNodeFragment::propsPlaceholder(),
        /* .eventEmitter = */ ShadowNodeFragment::eventEmitterPlaceholder(),
        /* .children = */ sharedChildren,
    });

    newParent->replaceChild(oldChild, newChild);

    oldChild = oldParent;
    newChild = newParent;
  }

  return std::const_pointer_cast<RootShadowNode>(
      std::static_pointer_cast<const RootShadowNode>(newChild));
}

} // namespace react
} // namespace facebook
<commit_msg>Fabric: Removed unnecessary call in `RootShadowNode::clone`<commit_after>/**
 * Copyright (c) Facebook, Inc. and its affiliates.
 *
 * This source code is licensed under the MIT license found in the
 * LICENSE file in the root directory of this source tree.
 */

#include "RootShadowNode.h"

#include <react/components/view/conversions.h>
#include <react/debug/SystraceSection.h>

namespace facebook {
namespace react {

const char RootComponentName[] = "RootView";

void RootShadowNode::layout() {
  SystraceSection s("RootShadowNode::layout");
  ensureUnsealed();
  layout(getProps()->layoutContext);

  // This is the rare place where shadow node must layout (set `layoutMetrics`)
  // itself because there is no a parent node which usually should do it.
  if (getHasNewLayout()) {
    setLayoutMetrics(layoutMetricsFromYogaNode(yogaNode_));
    setHasNewLayout(false);
  }
}

UnsharedRootShadowNode RootShadowNode::clone(
    const LayoutConstraints &layoutConstraints,
    const LayoutContext &layoutContext) const {
  auto props = std::make_shared<const RootProps>(
      *getProps(), layoutConstraints, layoutContext);
  auto newRootShadowNode = std::make_shared<RootShadowNode>(
      *this,
      ShadowNodeFragment{
          /* .tag = */ ShadowNodeFragment::tagPlaceholder(),
          /* .rootTag = */ ShadowNodeFragment::surfaceIdPlaceholder(),
          /* .props = */ props,
      });
  return newRootShadowNode;
}

UnsharedRootShadowNode RootShadowNode::clone(
    const SharedShadowNode &oldShadowNode,
    const SharedShadowNode &newShadowNode) const {
  std::vector<std::reference_wrapper<const ShadowNode>> ancestors;

  if (!oldShadowNode->constructAncestorPath(*this, ancestors)) {
    return UnsharedRootShadowNode{nullptr};
  }

  auto oldChild = oldShadowNode;
  auto newChild = newShadowNode;

  for (const auto &ancestor : ancestors) {
    auto oldParent = ancestor.get().shared_from_this();

    auto children = oldParent->getChildren();
    std::replace(children.begin(), children.end(), oldChild, newChild);

    auto sharedChildren = std::make_shared<SharedShadowNodeList>(children);
    auto newParent = oldParent->clone({
        /* .tag = */ ShadowNodeFragment::tagPlaceholder(),
        /* .rootTag = */ ShadowNodeFragment::surfaceIdPlaceholder(),
        /* .props = */ ShadowNodeFragment::propsPlaceholder(),
        /* .eventEmitter = */ ShadowNodeFragment::eventEmitterPlaceholder(),
        /* .children = */ sharedChildren,
    });

    oldChild = oldParent;
    newChild = newParent;
  }

  return std::const_pointer_cast<RootShadowNode>(
      std::static_pointer_cast<const RootShadowNode>(newChild));
}

} // namespace react
} // namespace facebook
<|endoftext|>


<commit_before>/** @file

  A brief file description

  @section license License

  Licensed to the Apache Software Foundation (ASF) under one
  or more contributor license agreements.  See the NOTICE file
  distributed with this work for additional information
  regarding copyright ownership.  The ASF licenses this file
  to you under the Apache License, Version 2.0 (the
  "License"); you may not use this file except in compliance
  with the License.  You may obtain a copy of the License at

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

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

/****************************************************************************

   OneWayTunnel.cc

   A OneWayTunnel is a module that connects two virtual connections, a
   source vc and a target vc, and copies the data between source and target.

   This class used to be called HttpTunnelVC, but it doesn't seem to have
   anything to do with HTTP, so it has been renamed to OneWayTunnel.
 ****************************************************************************/

#include "P_EventSystem.h"
#include "I_OneWayTunnel.h"

// #define TEST

//////////////////////////////////////////////////////////////////////////////
//
//      OneWayTunnel::OneWayTunnel()
//
//////////////////////////////////////////////////////////////////////////////

ClassAllocator<OneWayTunnel> OneWayTunnelAllocator("OneWayTunnelAllocator");

inline void
transfer_data(MIOBufferAccessor &in_buf, MIOBufferAccessor &out_buf)
{
  ink_release_assert(!"Not Implemented.");

  int64_t n = in_buf.reader()->read_avail();
  int64_t o = out_buf.writer()->write_avail();

  if (n > o)
    n = o;
  if (!n)
    return;
  memcpy(in_buf.reader()->start(), out_buf.writer()->end(), n);
  in_buf.reader()->consume(n);
  out_buf.writer()->fill(n);
}

OneWayTunnel::OneWayTunnel()
  : Continuation(0), vioSource(0), vioTarget(0), cont(0), manipulate_fn(0), n_connections(0), lerrno(0), single_buffer(0),
    close_source(0), close_target(0), tunnel_till_done(0), tunnel_peer(0), free_vcs(true)
{
}

OneWayTunnel *
OneWayTunnel::OneWayTunnel_alloc()
{
  return OneWayTunnelAllocator.alloc();
}

void
OneWayTunnel::OneWayTunnel_free(OneWayTunnel *pOWT)
{
  pOWT->mutex = NULL;
  OneWayTunnelAllocator.free(pOWT);
}

void
OneWayTunnel::SetupTwoWayTunnel(OneWayTunnel *east, OneWayTunnel *west)
{
  // make sure the both use the same mutex
  ink_assert(east->mutex == west->mutex);

  east->tunnel_peer = west;
  west->tunnel_peer = east;
}

OneWayTunnel::~OneWayTunnel()
{
}

OneWayTunnel::OneWayTunnel(Continuation *aCont, Transform_fn aManipulate_fn, bool aclose_source, bool aclose_target)
  : Continuation(aCont ? (ProxyMutex *)aCont->mutex : new_ProxyMutex()), cont(aCont), manipulate_fn(aManipulate_fn),
    n_connections(2), lerrno(0), single_buffer(true), close_source(aclose_source), close_target(aclose_target),
    tunnel_till_done(false), free_vcs(false)
{
  ink_assert(!"This form of OneWayTunnel() constructor not supported");
}

void
OneWayTunnel::init(VConnection *vcSource, VConnection *vcTarget, Continuation *aCont, int size_estimate, ProxyMutex *aMutex,
                   int64_t nbytes, bool asingle_buffer, bool aclose_source, bool aclose_target, Transform_fn aManipulate_fn,
                   int water_mark)
{
  mutex = aCont ? (ProxyMutex *)aCont->mutex : (aMutex ? aMutex : new_ProxyMutex());
  cont = aMutex ? NULL : aCont;
  single_buffer = asingle_buffer;
  manipulate_fn = aManipulate_fn;
  n_connections = 2;
  close_source = aclose_source;
  close_target = aclose_target;
  lerrno = 0;
  tunnel_till_done = (nbytes == TUNNEL_TILL_DONE);

  SET_HANDLER(&OneWayTunnel::startEvent);

  int64_t size_index = 0;

  if (size_estimate)
    size_index = buffer_size_to_index(size_estimate);
  else
    size_index = default_large_iobuffer_size;

  Debug("one_way_tunnel", "buffer size index [%" PRId64 "] [%d]\n", size_index, size_estimate);

  // enqueue read request on vcSource.
  MIOBuffer *buf1 = new_MIOBuffer(size_index);
  MIOBuffer *buf2 = NULL;
  if (single_buffer)
    buf2 = buf1;
  else
    buf2 = new_MIOBuffer(size_index);

  buf1->water_mark = water_mark;

  SCOPED_MUTEX_LOCK(lock, mutex, this_ethread());
  vioSource = vcSource->do_io_read(this, nbytes, buf1);
  vioTarget = vcTarget->do_io_write(this, nbytes, buf2->alloc_reader(), 0);
  ink_assert(vioSource && vioTarget);

  return;
}

void
OneWayTunnel::init(VConnection *vcSource, VConnection *vcTarget, Continuation *aCont, VIO *SourceVio, IOBufferReader *reader,
                   bool aclose_source, bool aclose_target)
{
  (void)vcSource;
  mutex = aCont ? (ProxyMutex *)aCont->mutex : new_ProxyMutex();
  cont = aCont;
  single_buffer = true;
  manipulate_fn = 0;
  n_connections = 2;
  close_source = aclose_source;
  close_target = aclose_target;
  tunnel_till_done = true;

  // Prior to constructing the OneWayTunnel, we initiated a do_io(VIO::READ)
  // on the source VC.  We wish to use the same MIO buffer in the tunnel.

  // do_io() read already posted on vcSource.
  SET_HANDLER(&OneWayTunnel::startEvent);

  SourceVio->set_continuation(this);
  SCOPED_MUTEX_LOCK(lock, mutex, this_ethread());
  vioSource = SourceVio;

  vioTarget = vcTarget->do_io_write(this, TUNNEL_TILL_DONE, reader, 0);
  ink_assert(vioSource && vioTarget);
}

void
OneWayTunnel::init(Continuation *aCont, VIO *SourceVio, VIO *TargetVio, bool aclose_source, bool aclose_target)
{
  mutex = aCont ? (ProxyMutex *)aCont->mutex : new_ProxyMutex();
  cont = aCont;
  single_buffer = true;
  manipulate_fn = 0;
  n_connections = 2;
  close_source = aclose_source;
  close_target = aclose_target;
  tunnel_till_done = true;

  // do_io_read() read already posted on vcSource.
  // do_io_write() already posted on vcTarget
  SET_HANDLER(&OneWayTunnel::startEvent);

  ink_assert(SourceVio && TargetVio);

  SourceVio->set_continuation(this);
  TargetVio->set_continuation(this);
  vioSource = SourceVio;
  vioTarget = TargetVio;
}

void
OneWayTunnel::transform(MIOBufferAccessor &in_buf, MIOBufferAccessor &out_buf)
{
  if (manipulate_fn)
    manipulate_fn(in_buf, out_buf);
  else if (in_buf.writer() != out_buf.writer())
    transfer_data(in_buf, out_buf);
}

//////////////////////////////////////////////////////////////////////////////
//
//      int OneWayTunnel::startEvent()
//
//////////////////////////////////////////////////////////////////////////////

//
// tunnel was invoked with an event
//
int
OneWayTunnel::startEvent(int event, void *data)
{
  VIO *vio = (VIO *)data;
  int ret = VC_EVENT_DONE;
  int result = 0;

#ifdef TEST
  const char *event_origin = (vio == vioSource ? "source" : "target"), *event_name = get_vc_event_name(event);
  printf("OneWayTunnel --- %s received from %s VC\n", event_name, event_origin);
#endif

  if (!vioTarget)
    goto Lerror;

  // handle the event
  //
  switch (event) {
  case ONE_WAY_TUNNEL_EVENT_PEER_CLOSE:
    /* This event is sent out by our peer */
    ink_assert(tunnel_peer);
    tunnel_peer = NULL;
    free_vcs = false;
    goto Ldone;

  case VC_EVENT_READ_READY:
    transform(vioSource->buffer, vioTarget->buffer);
    vioTarget->reenable();
    ret = VC_EVENT_CONT;
    break;

  case VC_EVENT_WRITE_READY:
    if (vioSource)
      vioSource->reenable();
    ret = VC_EVENT_CONT;
    break;

  case VC_EVENT_EOS:
    if (!tunnel_till_done && vio->ntodo())
      goto Lerror;
    if (vio == vioSource) {
      transform(vioSource->buffer, vioTarget->buffer);
      goto Lread_complete;
    } else
      goto Ldone;

  Lread_complete:
  case VC_EVENT_READ_COMPLETE:
    // set write nbytes to the current buffer size
    //
    vioTarget->nbytes = vioTarget->ndone + vioTarget->buffer.reader()->read_avail();
    if (vioTarget->nbytes == vioTarget->ndone)
      goto Ldone;
    vioTarget->reenable();
    if (!tunnel_peer)
      close_source_vio(0);
    break;

  Lerror:
  case VC_EVENT_ERROR:
    lerrno = ((VIO *)data)->vc_server->lerrno;
  case VC_EVENT_INACTIVITY_TIMEOUT:
  case VC_EVENT_ACTIVE_TIMEOUT:
    result = -1;
  Ldone:
  case VC_EVENT_WRITE_COMPLETE:
    if (tunnel_peer) {
      // inform the peer:
      tunnel_peer->startEvent(ONE_WAY_TUNNEL_EVENT_PEER_CLOSE, data);
    }
    close_source_vio(result);
    close_target_vio(result);
    connection_closed(result);
    break;

  default:
    ink_assert(!"bad case");
    ret = VC_EVENT_CONT;
    break;
  }
#ifdef TEST
  printf("    (OneWayTunnel returning value: %s)\n", (ret == VC_EVENT_DONE ? "VC_EVENT_DONE" : "VC_EVENT_CONT"));
#endif
  return ret;
}

// If result is Non-zero, the vc should be aborted.
void
OneWayTunnel::close_source_vio(int result)
{
  if (vioSource) {
    if (last_connection() || !single_buffer) {
      free_MIOBuffer(vioSource->buffer.writer());
      vioSource->buffer.clear();
    }
    if (close_source && free_vcs) {
      vioSource->vc_server->do_io_close(result ? lerrno : -1);
    }
    vioSource = NULL;
    n_connections--;
  }
}

void
OneWayTunnel::close_target_vio(int result, VIO *vio)
{
  (void)vio;
  if (vioTarget) {
    if (last_connection() || !single_buffer) {
      free_MIOBuffer(vioTarget->buffer.writer());
      vioTarget->buffer.clear();
    }
    if (close_target && free_vcs) {
      vioTarget->vc_server->do_io_close(result ? lerrno : -1);
    }
    vioTarget = NULL;
    n_connections--;
  }
}

//////////////////////////////////////////////////////////////////////////////
//
//      void OneWayTunnel::connection_closed
//
//////////////////////////////////////////////////////////////////////////////
void
OneWayTunnel::connection_closed(int result)
{
  if (cont) {
#ifdef TEST
    cout << "OneWayTunnel::connection_closed() ... calling cont" << endl;
#endif
    cont->handleEvent(result ? VC_EVENT_ERROR : VC_EVENT_EOS, cont);
  } else {
    OneWayTunnel_free(this);
  }
}

void
OneWayTunnel::reenable_all()
{
  if (vioSource)
    vioSource->reenable();
  if (vioTarget)
    vioTarget->reenable();
}

bool
OneWayTunnel::last_connection()
{
  return n_connections == 1;
}
<commit_msg>TS-4201: call cont->handleEvent with OneWayTunnel object This closes #476.<commit_after>/** @file

  A brief file description

  @section license License

  Licensed to the Apache Software Foundation (ASF) under one
  or more contributor license agreements.  See the NOTICE file
  distributed with this work for additional information
  regarding copyright ownership.  The ASF licenses this file
  to you under the Apache License, Version 2.0 (the
  "License"); you may not use this file except in compliance
  with the License.  You may obtain a copy of the License at

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

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

/****************************************************************************

   OneWayTunnel.cc

   A OneWayTunnel is a module that connects two virtual connections, a
   source vc and a target vc, and copies the data between source and target.

   This class used to be called HttpTunnelVC, but it doesn't seem to have
   anything to do with HTTP, so it has been renamed to OneWayTunnel.
 ****************************************************************************/

#include "P_EventSystem.h"
#include "I_OneWayTunnel.h"

// #define TEST

//////////////////////////////////////////////////////////////////////////////
//
//      OneWayTunnel::OneWayTunnel()
//
//////////////////////////////////////////////////////////////////////////////

ClassAllocator<OneWayTunnel> OneWayTunnelAllocator("OneWayTunnelAllocator");

inline void
transfer_data(MIOBufferAccessor &in_buf, MIOBufferAccessor &out_buf)
{
  ink_release_assert(!"Not Implemented.");

  int64_t n = in_buf.reader()->read_avail();
  int64_t o = out_buf.writer()->write_avail();

  if (n > o)
    n = o;
  if (!n)
    return;
  memcpy(in_buf.reader()->start(), out_buf.writer()->end(), n);
  in_buf.reader()->consume(n);
  out_buf.writer()->fill(n);
}

OneWayTunnel::OneWayTunnel()
  : Continuation(0), vioSource(0), vioTarget(0), cont(0), manipulate_fn(0), n_connections(0), lerrno(0), single_buffer(0),
    close_source(0), close_target(0), tunnel_till_done(0), tunnel_peer(0), free_vcs(true)
{
}

OneWayTunnel *
OneWayTunnel::OneWayTunnel_alloc()
{
  return OneWayTunnelAllocator.alloc();
}

void
OneWayTunnel::OneWayTunnel_free(OneWayTunnel *pOWT)
{
  pOWT->mutex = NULL;
  OneWayTunnelAllocator.free(pOWT);
}

void
OneWayTunnel::SetupTwoWayTunnel(OneWayTunnel *east, OneWayTunnel *west)
{
  // make sure the both use the same mutex
  ink_assert(east->mutex == west->mutex);

  east->tunnel_peer = west;
  west->tunnel_peer = east;
}

OneWayTunnel::~OneWayTunnel()
{
}

OneWayTunnel::OneWayTunnel(Continuation *aCont, Transform_fn aManipulate_fn, bool aclose_source, bool aclose_target)
  : Continuation(aCont ? (ProxyMutex *)aCont->mutex : new_ProxyMutex()), cont(aCont), manipulate_fn(aManipulate_fn),
    n_connections(2), lerrno(0), single_buffer(true), close_source(aclose_source), close_target(aclose_target),
    tunnel_till_done(false), free_vcs(false)
{
  ink_assert(!"This form of OneWayTunnel() constructor not supported");
}

void
OneWayTunnel::init(VConnection *vcSource, VConnection *vcTarget, Continuation *aCont, int size_estimate, ProxyMutex *aMutex,
                   int64_t nbytes, bool asingle_buffer, bool aclose_source, bool aclose_target, Transform_fn aManipulate_fn,
                   int water_mark)
{
  mutex = aCont ? (ProxyMutex *)aCont->mutex : (aMutex ? aMutex : new_ProxyMutex());
  cont = aMutex ? NULL : aCont;
  single_buffer = asingle_buffer;
  manipulate_fn = aManipulate_fn;
  n_connections = 2;
  close_source = aclose_source;
  close_target = aclose_target;
  lerrno = 0;
  tunnel_till_done = (nbytes == TUNNEL_TILL_DONE);

  SET_HANDLER(&OneWayTunnel::startEvent);

  int64_t size_index = 0;

  if (size_estimate)
    size_index = buffer_size_to_index(size_estimate);
  else
    size_index = default_large_iobuffer_size;

  Debug("one_way_tunnel", "buffer size index [%" PRId64 "] [%d]\n", size_index, size_estimate);

  // enqueue read request on vcSource.
  MIOBuffer *buf1 = new_MIOBuffer(size_index);
  MIOBuffer *buf2 = NULL;
  if (single_buffer)
    buf2 = buf1;
  else
    buf2 = new_MIOBuffer(size_index);

  buf1->water_mark = water_mark;

  SCOPED_MUTEX_LOCK(lock, mutex, this_ethread());
  vioSource = vcSource->do_io_read(this, nbytes, buf1);
  vioTarget = vcTarget->do_io_write(this, nbytes, buf2->alloc_reader(), 0);
  ink_assert(vioSource && vioTarget);

  return;
}

void
OneWayTunnel::init(VConnection *vcSource, VConnection *vcTarget, Continuation *aCont, VIO *SourceVio, IOBufferReader *reader,
                   bool aclose_source, bool aclose_target)
{
  (void)vcSource;
  mutex = aCont ? (ProxyMutex *)aCont->mutex : new_ProxyMutex();
  cont = aCont;
  single_buffer = true;
  manipulate_fn = 0;
  n_connections = 2;
  close_source = aclose_source;
  close_target = aclose_target;
  tunnel_till_done = true;

  // Prior to constructing the OneWayTunnel, we initiated a do_io(VIO::READ)
  // on the source VC.  We wish to use the same MIO buffer in the tunnel.

  // do_io() read already posted on vcSource.
  SET_HANDLER(&OneWayTunnel::startEvent);

  SourceVio->set_continuation(this);
  SCOPED_MUTEX_LOCK(lock, mutex, this_ethread());
  vioSource = SourceVio;

  vioTarget = vcTarget->do_io_write(this, TUNNEL_TILL_DONE, reader, 0);
  ink_assert(vioSource && vioTarget);
}

void
OneWayTunnel::init(Continuation *aCont, VIO *SourceVio, VIO *TargetVio, bool aclose_source, bool aclose_target)
{
  mutex = aCont ? (ProxyMutex *)aCont->mutex : new_ProxyMutex();
  cont = aCont;
  single_buffer = true;
  manipulate_fn = 0;
  n_connections = 2;
  close_source = aclose_source;
  close_target = aclose_target;
  tunnel_till_done = true;

  // do_io_read() read already posted on vcSource.
  // do_io_write() already posted on vcTarget
  SET_HANDLER(&OneWayTunnel::startEvent);

  ink_assert(SourceVio && TargetVio);

  SourceVio->set_continuation(this);
  TargetVio->set_continuation(this);
  vioSource = SourceVio;
  vioTarget = TargetVio;
}

void
OneWayTunnel::transform(MIOBufferAccessor &in_buf, MIOBufferAccessor &out_buf)
{
  if (manipulate_fn)
    manipulate_fn(in_buf, out_buf);
  else if (in_buf.writer() != out_buf.writer())
    transfer_data(in_buf, out_buf);
}

//////////////////////////////////////////////////////////////////////////////
//
//      int OneWayTunnel::startEvent()
//
//////////////////////////////////////////////////////////////////////////////

//
// tunnel was invoked with an event
//
int
OneWayTunnel::startEvent(int event, void *data)
{
  VIO *vio = (VIO *)data;
  int ret = VC_EVENT_DONE;
  int result = 0;

#ifdef TEST
  const char *event_origin = (vio == vioSource ? "source" : "target"), *event_name = get_vc_event_name(event);
  printf("OneWayTunnel --- %s received from %s VC\n", event_name, event_origin);
#endif

  if (!vioTarget)
    goto Lerror;

  // handle the event
  //
  switch (event) {
  case ONE_WAY_TUNNEL_EVENT_PEER_CLOSE:
    /* This event is sent out by our peer */
    ink_assert(tunnel_peer);
    tunnel_peer = NULL;
    free_vcs = false;
    goto Ldone;

  case VC_EVENT_READ_READY:
    transform(vioSource->buffer, vioTarget->buffer);
    vioTarget->reenable();
    ret = VC_EVENT_CONT;
    break;

  case VC_EVENT_WRITE_READY:
    if (vioSource)
      vioSource->reenable();
    ret = VC_EVENT_CONT;
    break;

  case VC_EVENT_EOS:
    if (!tunnel_till_done && vio->ntodo())
      goto Lerror;
    if (vio == vioSource) {
      transform(vioSource->buffer, vioTarget->buffer);
      goto Lread_complete;
    } else
      goto Ldone;

  Lread_complete:
  case VC_EVENT_READ_COMPLETE:
    // set write nbytes to the current buffer size
    //
    vioTarget->nbytes = vioTarget->ndone + vioTarget->buffer.reader()->read_avail();
    if (vioTarget->nbytes == vioTarget->ndone)
      goto Ldone;
    vioTarget->reenable();
    if (!tunnel_peer)
      close_source_vio(0);
    break;

  Lerror:
  case VC_EVENT_ERROR:
    lerrno = ((VIO *)data)->vc_server->lerrno;
  case VC_EVENT_INACTIVITY_TIMEOUT:
  case VC_EVENT_ACTIVE_TIMEOUT:
    result = -1;
  Ldone:
  case VC_EVENT_WRITE_COMPLETE:
    if (tunnel_peer) {
      // inform the peer:
      tunnel_peer->startEvent(ONE_WAY_TUNNEL_EVENT_PEER_CLOSE, data);
    }
    close_source_vio(result);
    close_target_vio(result);
    connection_closed(result);
    break;

  default:
    ink_assert(!"bad case");
    ret = VC_EVENT_CONT;
    break;
  }
#ifdef TEST
  printf("    (OneWayTunnel returning value: %s)\n", (ret == VC_EVENT_DONE ? "VC_EVENT_DONE" : "VC_EVENT_CONT"));
#endif
  return ret;
}

// If result is Non-zero, the vc should be aborted.
void
OneWayTunnel::close_source_vio(int result)
{
  if (vioSource) {
    if (last_connection() || !single_buffer) {
      free_MIOBuffer(vioSource->buffer.writer());
      vioSource->buffer.clear();
    }
    if (close_source && free_vcs) {
      vioSource->vc_server->do_io_close(result ? lerrno : -1);
    }
    vioSource = NULL;
    n_connections--;
  }
}

void
OneWayTunnel::close_target_vio(int result, VIO *vio)
{
  (void)vio;
  if (vioTarget) {
    if (last_connection() || !single_buffer) {
      free_MIOBuffer(vioTarget->buffer.writer());
      vioTarget->buffer.clear();
    }
    if (close_target && free_vcs) {
      vioTarget->vc_server->do_io_close(result ? lerrno : -1);
    }
    vioTarget = NULL;
    n_connections--;
  }
}

//////////////////////////////////////////////////////////////////////////////
//
//      void OneWayTunnel::connection_closed
//
//////////////////////////////////////////////////////////////////////////////
void
OneWayTunnel::connection_closed(int result)
{
  if (cont) {
#ifdef TEST
    cout << "OneWayTunnel::connection_closed() ... calling cont" << endl;
#endif
    cont->handleEvent(result ? VC_EVENT_ERROR : VC_EVENT_EOS, this);
  } else {
    OneWayTunnel_free(this);
  }
}

void
OneWayTunnel::reenable_all()
{
  if (vioSource)
    vioSource->reenable();
  if (vioTarget)
    vioTarget->reenable();
}

bool
OneWayTunnel::last_connection()
{
  return n_connections == 1;
}
<|endoftext|>