<commit_before>// Copyright (c) 2017 Franka Emika GmbH
// Use of this source code is governed by the Apache-2.0 license, see LICENSE
#include <franka/robot.h>

#include <utility>

#include "control_loop.h"
#include "network.h"
#include "robot_impl.h"

namespace franka {

Robot::Robot(const std::string& franka_address, RealtimeConfig realtime_config, size_t log_size)
    : impl_{new Robot::Impl(
          std::make_unique<Network>(franka_address, research_interface::robot::kCommandPort),
          log_size,
          realtime_config)} {}

// Has to be declared here, as the Impl type is incomplete in the header.
Robot::~Robot() noexcept = default;

Robot::Robot(Robot&& other) noexcept {
  std::lock_guard<std::mutex> _(other.control_mutex_);
  impl_ = std::move(other.impl_);
}

Robot& Robot::operator=(Robot&& other) noexcept {
  if (&other != this) {
    std::unique_lock<std::mutex> this_lock(control_mutex_, std::defer_lock);
    std::unique_lock<std::mutex> other_lock(other.control_mutex_, std::defer_lock);
    std::lock(this_lock, other_lock);
    impl_ = std::move(other.impl_);
  }
  return *this;
}

Robot::ServerVersion Robot::serverVersion() const noexcept {
  return impl_->serverVersion();
}

void Robot::control(std::function<Torques(const RobotState&, franka::Duration)> control_callback,
                    bool limit_rate,
                    double cutoff_frequency) {
  std::unique_lock<std::mutex> l(control_mutex_, std::try_to_lock);
  if (!l.owns_lock()) {
    throw InvalidOperationException(
        "libfranka robot: Cannot perform this operation while another control or read operation "
        "is running.");
  }

  ControlLoop<JointVelocities> loop(*impl_, std::move(control_callback),
                                    [](const RobotState&, Duration) -> JointVelocities {
                                      return {{0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0}};
                                    },
                                    limit_rate, cutoff_frequency);
  loop();
}

void Robot::control(
    std::function<Torques(const RobotState&, franka::Duration)> control_callback,
    std::function<JointPositions(const RobotState&, franka::Duration)> motion_generator_callback,
    bool limit_rate,
    double cutoff_frequency) {
  std::unique_lock<std::mutex> l(control_mutex_, std::try_to_lock);
  if (!l.owns_lock()) {
    throw InvalidOperationException(
        "libfranka robot: Cannot perform this operation while another control or read operation "
        "is running.");
  }

  ControlLoop<JointPositions> loop(*impl_, std::move(control_callback),
                                   std::move(motion_generator_callback), limit_rate,
                                   cutoff_frequency);
  loop();
}

void Robot::control(
    std::function<Torques(const RobotState&, franka::Duration)> control_callback,
    std::function<JointVelocities(const RobotState&, franka::Duration)> motion_generator_callback,
    bool limit_rate,
    double cutoff_frequency) {
  std::unique_lock<std::mutex> l(control_mutex_, std::try_to_lock);
  if (!l.owns_lock()) {
    throw InvalidOperationException(
        "libfranka robot: Cannot perform this operation while another control or read operation "
        "is running.");
  }

  ControlLoop<JointVelocities> loop(*impl_, std::move(control_callback),
                                    std::move(motion_generator_callback), limit_rate,
                                    cutoff_frequency);
  loop();
}

void Robot::control(
    std::function<Torques(const RobotState&, franka::Duration)> control_callback,
    std::function<CartesianPose(const RobotState&, franka::Duration)> motion_generator_callback,
    bool limit_rate,
    double cutoff_frequency) {
  std::unique_lock<std::mutex> l(control_mutex_, std::try_to_lock);
  if (!l.owns_lock()) {
    throw InvalidOperationException(
        "libfranka robot: Cannot perform this operation while another control or read operation "
        "is running.");
  }

  ControlLoop<CartesianPose> loop(*impl_, std::move(control_callback),
                                  std::move(motion_generator_callback), limit_rate,
                                  cutoff_frequency);
  loop();
}

void Robot::control(std::function<Torques(const RobotState&, franka::Duration)> control_callback,
                    std::function<CartesianVelocities(const RobotState&, franka::Duration)>
                        motion_generator_callback,
                    bool limit_rate,
                    double cutoff_frequency) {
  std::unique_lock<std::mutex> l(control_mutex_, std::try_to_lock);
  if (!l.owns_lock()) {
    throw InvalidOperationException(
        "libfranka robot: Cannot perform this operation while another control or read operation "
        "is running.");
  }

  ControlLoop<CartesianVelocities> loop(*impl_, std::move(control_callback),
                                        std::move(motion_generator_callback), limit_rate,
                                        cutoff_frequency);
  loop();
}

void Robot::control(
    std::function<JointPositions(const RobotState&, franka::Duration)> motion_generator_callback,
    ControllerMode controller_mode,
    bool limit_rate,
    double cutoff_frequency) {
  std::unique_lock<std::mutex> l(control_mutex_, std::try_to_lock);
  if (!l.owns_lock()) {
    throw InvalidOperationException(
        "libfranka robot: Cannot perform this operation while another control or read operation "
        "is running.");
  }

  ControlLoop<JointPositions> loop(*impl_, controller_mode, std::move(motion_generator_callback),
                                   limit_rate, cutoff_frequency);
  loop();
}

void Robot::control(
    std::function<JointVelocities(const RobotState&, franka::Duration)> motion_generator_callback,
    ControllerMode controller_mode,
    bool limit_rate,
    double cutoff_frequency) {
  std::unique_lock<std::mutex> l(control_mutex_, std::try_to_lock);
  if (!l.owns_lock()) {
    throw InvalidOperationException(
        "libfranka robot: Cannot perform this operation while another control or read operation "
        "is running.");
  }

  ControlLoop<JointVelocities> loop(*impl_, controller_mode, std::move(motion_generator_callback),
                                    limit_rate, cutoff_frequency);
  loop();
}

void Robot::control(
    std::function<CartesianPose(const RobotState&, franka::Duration)> motion_generator_callback,
    ControllerMode controller_mode,
    bool limit_rate,
    double cutoff_frequency) {
  std::unique_lock<std::mutex> l(control_mutex_, std::try_to_lock);
  if (!l.owns_lock()) {
    throw InvalidOperationException(
        "libfranka robot: Cannot perform this operation while another control or read operation "
        "is running.");
  }

  ControlLoop<CartesianPose> loop(*impl_, controller_mode, std::move(motion_generator_callback),
                                  limit_rate, cutoff_frequency);
  loop();
}

void Robot::control(std::function<CartesianVelocities(const RobotState&, franka::Duration)>
                        motion_generator_callback,
                    ControllerMode controller_mode,
                    bool limit_rate,
                    double cutoff_frequency) {
  std::unique_lock<std::mutex> l(control_mutex_, std::try_to_lock);
  if (!l.owns_lock()) {
    throw InvalidOperationException(
        "libfranka robot: Cannot perform this operation while another control or read operation "
        "is running.");
  }

  ControlLoop<CartesianVelocities> loop(
      *impl_, controller_mode, std::move(motion_generator_callback), limit_rate, cutoff_frequency);
  loop();
}

// NOLINTNEXTLINE(performance-unnecessary-value-param)
void Robot::read(std::function<bool(const RobotState&)> read_callback) {
  std::unique_lock<std::mutex> l(control_mutex_, std::try_to_lock);
  if (!l.owns_lock()) {
    throw InvalidOperationException(
        "libfranka robot: Cannot perform this operation while another control or read operation "
        "is running.");
  }

  while (true) {
    RobotState robot_state = impl_->update(nullptr, nullptr);
    if (!read_callback(robot_state)) {
      break;
    }
  }
}

RobotState Robot::readOnce() {
  std::unique_lock<std::mutex> l(control_mutex_, std::try_to_lock);
  if (!l.owns_lock()) {
    throw InvalidOperationException(
        "libfranka robot: Cannot perform this operation while another control or read operation "
        "is running.");
  }

  return impl_->readOnce();
}

VirtualWallCuboid Robot::getVirtualWall(int32_t id) {
  VirtualWallCuboid virtual_wall;
  impl_->executeCommand<research_interface::robot::GetCartesianLimit>(id, &virtual_wall);
  return virtual_wall;
}

void Robot::setCollisionBehavior(const std::array<double, 7>& lower_torque_thresholds_acceleration,
                                 const std::array<double, 7>& upper_torque_thresholds_acceleration,
                                 const std::array<double, 7>& lower_torque_thresholds_nominal,
                                 const std::array<double, 7>& upper_torque_thresholds_nominal,
                                 const std::array<double, 6>& lower_force_thresholds_acceleration,
                                 const std::array<double, 6>& upper_force_thresholds_acceleration,
                                 const std::array<double, 6>& lower_force_thresholds_nominal,
                                 const std::array<double, 6>& upper_force_thresholds_nominal) {
  impl_->executeCommand<research_interface::robot::SetCollisionBehavior>(
      lower_torque_thresholds_acceleration, upper_torque_thresholds_acceleration,
      lower_torque_thresholds_nominal, upper_torque_thresholds_nominal,
      lower_force_thresholds_acceleration, upper_force_thresholds_acceleration,
      lower_force_thresholds_nominal, upper_force_thresholds_nominal);
}

void Robot::setCollisionBehavior(const std::array<double, 7>& lower_torque_thresholds,
                                 const std::array<double, 7>& upper_torque_thresholds,
                                 const std::array<double, 6>& lower_force_thresholds,
                                 const std::array<double, 6>& upper_force_thresholds) {
  impl_->executeCommand<research_interface::robot::SetCollisionBehavior>(
      lower_torque_thresholds, upper_torque_thresholds, lower_torque_thresholds,
      upper_torque_thresholds, lower_force_thresholds, upper_force_thresholds,
      lower_force_thresholds, upper_force_thresholds);
}

void Robot::setJointImpedance(
    const std::array<double, 7>& K_theta) {  // NOLINT(readability-named-parameter)
  impl_->executeCommand<research_interface::robot::SetJointImpedance>(K_theta);
}

void Robot::setCartesianImpedance(
    const std::array<double, 6>& K_x) {  // NOLINT(readability-named-parameter)
  impl_->executeCommand<research_interface::robot::SetCartesianImpedance>(K_x);
}

void Robot::setGuidingMode(const std::array<bool, 6>& guiding_mode, bool elbow) {
  impl_->executeCommand<research_interface::robot::SetGuidingMode>(guiding_mode, elbow);
}

void Robot::setK(const std::array<double, 16>& EE_T_K) {  // NOLINT(readability-named-parameter)
  impl_->executeCommand<research_interface::robot::SetEEToK>(EE_T_K);
}

void Robot::setEE(const std::array<double, 16>& F_T_EE) {  // NOLINT(readability-named-parameter)
  impl_->executeCommand<research_interface::robot::SetNEToEE>(F_T_EE);
}

void Robot::setLoad(double load_mass,
                    const std::array<double, 3>& F_x_Cload,  // NOLINT(readability-named-parameter)
                    const std::array<double, 9>& load_inertia) {
  impl_->executeCommand<research_interface::robot::SetLoad>(load_mass, F_x_Cload, load_inertia);
}

void Robot::setFilters(double joint_position_filter_frequency,
                       double joint_velocity_filter_frequency,
                       double cartesian_position_filter_frequency,
                       double cartesian_velocity_filter_frequency,
                       double controller_filter_frequency) {
  impl_->executeCommand<research_interface::robot::SetFilters>(
      joint_position_filter_frequency, joint_velocity_filter_frequency,
      cartesian_position_filter_frequency, cartesian_velocity_filter_frequency,
      controller_filter_frequency);
}

void Robot::automaticErrorRecovery() {
  impl_->executeCommand<research_interface::robot::AutomaticErrorRecovery>();
}

void Robot::stop() {
  impl_->executeCommand<research_interface::robot::StopMove>();
}

Model Robot::loadModel() {
  return impl_->loadModel();
}

}  // namespace franka
<commit_msg>Fix parameter names<commit_after>// Copyright (c) 2017 Franka Emika GmbH
// Use of this source code is governed by the Apache-2.0 license, see LICENSE
#include <franka/robot.h>

#include <utility>

#include "control_loop.h"
#include "network.h"
#include "robot_impl.h"

namespace franka {

Robot::Robot(const std::string& franka_address, RealtimeConfig realtime_config, size_t log_size)
    : impl_{new Robot::Impl(
          std::make_unique<Network>(franka_address, research_interface::robot::kCommandPort),
          log_size,
          realtime_config)} {}

// Has to be declared here, as the Impl type is incomplete in the header.
Robot::~Robot() noexcept = default;

Robot::Robot(Robot&& other) noexcept {
  std::lock_guard<std::mutex> _(other.control_mutex_);
  impl_ = std::move(other.impl_);
}

Robot& Robot::operator=(Robot&& other) noexcept {
  if (&other != this) {
    std::unique_lock<std::mutex> this_lock(control_mutex_, std::defer_lock);
    std::unique_lock<std::mutex> other_lock(other.control_mutex_, std::defer_lock);
    std::lock(this_lock, other_lock);
    impl_ = std::move(other.impl_);
  }
  return *this;
}

Robot::ServerVersion Robot::serverVersion() const noexcept {
  return impl_->serverVersion();
}

void Robot::control(std::function<Torques(const RobotState&, franka::Duration)> control_callback,
                    bool limit_rate,
                    double cutoff_frequency) {
  std::unique_lock<std::mutex> l(control_mutex_, std::try_to_lock);
  if (!l.owns_lock()) {
    throw InvalidOperationException(
        "libfranka robot: Cannot perform this operation while another control or read operation "
        "is running.");
  }

  ControlLoop<JointVelocities> loop(*impl_, std::move(control_callback),
                                    [](const RobotState&, Duration) -> JointVelocities {
                                      return {{0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0}};
                                    },
                                    limit_rate, cutoff_frequency);
  loop();
}

void Robot::control(
    std::function<Torques(const RobotState&, franka::Duration)> control_callback,
    std::function<JointPositions(const RobotState&, franka::Duration)> motion_generator_callback,
    bool limit_rate,
    double cutoff_frequency) {
  std::unique_lock<std::mutex> l(control_mutex_, std::try_to_lock);
  if (!l.owns_lock()) {
    throw InvalidOperationException(
        "libfranka robot: Cannot perform this operation while another control or read operation "
        "is running.");
  }

  ControlLoop<JointPositions> loop(*impl_, std::move(control_callback),
                                   std::move(motion_generator_callback), limit_rate,
                                   cutoff_frequency);
  loop();
}

void Robot::control(
    std::function<Torques(const RobotState&, franka::Duration)> control_callback,
    std::function<JointVelocities(const RobotState&, franka::Duration)> motion_generator_callback,
    bool limit_rate,
    double cutoff_frequency) {
  std::unique_lock<std::mutex> l(control_mutex_, std::try_to_lock);
  if (!l.owns_lock()) {
    throw InvalidOperationException(
        "libfranka robot: Cannot perform this operation while another control or read operation "
        "is running.");
  }

  ControlLoop<JointVelocities> loop(*impl_, std::move(control_callback),
                                    std::move(motion_generator_callback), limit_rate,
                                    cutoff_frequency);
  loop();
}

void Robot::control(
    std::function<Torques(const RobotState&, franka::Duration)> control_callback,
    std::function<CartesianPose(const RobotState&, franka::Duration)> motion_generator_callback,
    bool limit_rate,
    double cutoff_frequency) {
  std::unique_lock<std::mutex> l(control_mutex_, std::try_to_lock);
  if (!l.owns_lock()) {
    throw InvalidOperationException(
        "libfranka robot: Cannot perform this operation while another control or read operation "
        "is running.");
  }

  ControlLoop<CartesianPose> loop(*impl_, std::move(control_callback),
                                  std::move(motion_generator_callback), limit_rate,
                                  cutoff_frequency);
  loop();
}

void Robot::control(std::function<Torques(const RobotState&, franka::Duration)> control_callback,
                    std::function<CartesianVelocities(const RobotState&, franka::Duration)>
                        motion_generator_callback,
                    bool limit_rate,
                    double cutoff_frequency) {
  std::unique_lock<std::mutex> l(control_mutex_, std::try_to_lock);
  if (!l.owns_lock()) {
    throw InvalidOperationException(
        "libfranka robot: Cannot perform this operation while another control or read operation "
        "is running.");
  }

  ControlLoop<CartesianVelocities> loop(*impl_, std::move(control_callback),
                                        std::move(motion_generator_callback), limit_rate,
                                        cutoff_frequency);
  loop();
}

void Robot::control(
    std::function<JointPositions(const RobotState&, franka::Duration)> motion_generator_callback,
    ControllerMode controller_mode,
    bool limit_rate,
    double cutoff_frequency) {
  std::unique_lock<std::mutex> l(control_mutex_, std::try_to_lock);
  if (!l.owns_lock()) {
    throw InvalidOperationException(
        "libfranka robot: Cannot perform this operation while another control or read operation "
        "is running.");
  }

  ControlLoop<JointPositions> loop(*impl_, controller_mode, std::move(motion_generator_callback),
                                   limit_rate, cutoff_frequency);
  loop();
}

void Robot::control(
    std::function<JointVelocities(const RobotState&, franka::Duration)> motion_generator_callback,
    ControllerMode controller_mode,
    bool limit_rate,
    double cutoff_frequency) {
  std::unique_lock<std::mutex> l(control_mutex_, std::try_to_lock);
  if (!l.owns_lock()) {
    throw InvalidOperationException(
        "libfranka robot: Cannot perform this operation while another control or read operation "
        "is running.");
  }

  ControlLoop<JointVelocities> loop(*impl_, controller_mode, std::move(motion_generator_callback),
                                    limit_rate, cutoff_frequency);
  loop();
}

void Robot::control(
    std::function<CartesianPose(const RobotState&, franka::Duration)> motion_generator_callback,
    ControllerMode controller_mode,
    bool limit_rate,
    double cutoff_frequency) {
  std::unique_lock<std::mutex> l(control_mutex_, std::try_to_lock);
  if (!l.owns_lock()) {
    throw InvalidOperationException(
        "libfranka robot: Cannot perform this operation while another control or read operation "
        "is running.");
  }

  ControlLoop<CartesianPose> loop(*impl_, controller_mode, std::move(motion_generator_callback),
                                  limit_rate, cutoff_frequency);
  loop();
}

void Robot::control(std::function<CartesianVelocities(const RobotState&, franka::Duration)>
                        motion_generator_callback,
                    ControllerMode controller_mode,
                    bool limit_rate,
                    double cutoff_frequency) {
  std::unique_lock<std::mutex> l(control_mutex_, std::try_to_lock);
  if (!l.owns_lock()) {
    throw InvalidOperationException(
        "libfranka robot: Cannot perform this operation while another control or read operation "
        "is running.");
  }

  ControlLoop<CartesianVelocities> loop(
      *impl_, controller_mode, std::move(motion_generator_callback), limit_rate, cutoff_frequency);
  loop();
}

// NOLINTNEXTLINE(performance-unnecessary-value-param)
void Robot::read(std::function<bool(const RobotState&)> read_callback) {
  std::unique_lock<std::mutex> l(control_mutex_, std::try_to_lock);
  if (!l.owns_lock()) {
    throw InvalidOperationException(
        "libfranka robot: Cannot perform this operation while another control or read operation "
        "is running.");
  }

  while (true) {
    RobotState robot_state = impl_->update(nullptr, nullptr);
    if (!read_callback(robot_state)) {
      break;
    }
  }
}

RobotState Robot::readOnce() {
  std::unique_lock<std::mutex> l(control_mutex_, std::try_to_lock);
  if (!l.owns_lock()) {
    throw InvalidOperationException(
        "libfranka robot: Cannot perform this operation while another control or read operation "
        "is running.");
  }

  return impl_->readOnce();
}

VirtualWallCuboid Robot::getVirtualWall(int32_t id) {
  VirtualWallCuboid virtual_wall;
  impl_->executeCommand<research_interface::robot::GetCartesianLimit>(id, &virtual_wall);
  return virtual_wall;
}

void Robot::setCollisionBehavior(const std::array<double, 7>& lower_torque_thresholds_acceleration,
                                 const std::array<double, 7>& upper_torque_thresholds_acceleration,
                                 const std::array<double, 7>& lower_torque_thresholds_nominal,
                                 const std::array<double, 7>& upper_torque_thresholds_nominal,
                                 const std::array<double, 6>& lower_force_thresholds_acceleration,
                                 const std::array<double, 6>& upper_force_thresholds_acceleration,
                                 const std::array<double, 6>& lower_force_thresholds_nominal,
                                 const std::array<double, 6>& upper_force_thresholds_nominal) {
  impl_->executeCommand<research_interface::robot::SetCollisionBehavior>(
      lower_torque_thresholds_acceleration, upper_torque_thresholds_acceleration,
      lower_torque_thresholds_nominal, upper_torque_thresholds_nominal,
      lower_force_thresholds_acceleration, upper_force_thresholds_acceleration,
      lower_force_thresholds_nominal, upper_force_thresholds_nominal);
}

void Robot::setCollisionBehavior(const std::array<double, 7>& lower_torque_thresholds,
                                 const std::array<double, 7>& upper_torque_thresholds,
                                 const std::array<double, 6>& lower_force_thresholds,
                                 const std::array<double, 6>& upper_force_thresholds) {
  impl_->executeCommand<research_interface::robot::SetCollisionBehavior>(
      lower_torque_thresholds, upper_torque_thresholds, lower_torque_thresholds,
      upper_torque_thresholds, lower_force_thresholds, upper_force_thresholds,
      lower_force_thresholds, upper_force_thresholds);
}

void Robot::setJointImpedance(
    const std::array<double, 7>& K_theta) {  // NOLINT(readability-named-parameter)
  impl_->executeCommand<research_interface::robot::SetJointImpedance>(K_theta);
}

void Robot::setCartesianImpedance(
    const std::array<double, 6>& K_x) {  // NOLINT(readability-named-parameter)
  impl_->executeCommand<research_interface::robot::SetCartesianImpedance>(K_x);
}

void Robot::setGuidingMode(const std::array<bool, 6>& guiding_mode, bool elbow) {
  impl_->executeCommand<research_interface::robot::SetGuidingMode>(guiding_mode, elbow);
}

void Robot::setK(const std::array<double, 16>& EE_T_K) {  // NOLINT(readability-named-parameter)
  impl_->executeCommand<research_interface::robot::SetEEToK>(EE_T_K);
}

void Robot::setEE(const std::array<double, 16>& NE_T_EE) {  // NOLINT(readability-named-parameter)
  impl_->executeCommand<research_interface::robot::SetNEToEE>(NE_T_EE);
}

void Robot::setLoad(double load_mass,
                    const std::array<double, 3>& F_x_Cload,  // NOLINT(readability-named-parameter)
                    const std::array<double, 9>& load_inertia) {
  impl_->executeCommand<research_interface::robot::SetLoad>(load_mass, F_x_Cload, load_inertia);
}

void Robot::setFilters(double joint_position_filter_frequency,
                       double joint_velocity_filter_frequency,
                       double cartesian_position_filter_frequency,
                       double cartesian_velocity_filter_frequency,
                       double controller_filter_frequency) {
  impl_->executeCommand<research_interface::robot::SetFilters>(
      joint_position_filter_frequency, joint_velocity_filter_frequency,
      cartesian_position_filter_frequency, cartesian_velocity_filter_frequency,
      controller_filter_frequency);
}

void Robot::automaticErrorRecovery() {
  impl_->executeCommand<research_interface::robot::AutomaticErrorRecovery>();
}

void Robot::stop() {
  impl_->executeCommand<research_interface::robot::StopMove>();
}

Model Robot::loadModel() {
  return impl_->loadModel();
}

}  // namespace franka
<|endoftext|>


<commit_before>#ifndef CONTAINERS_REFC_PTR_HPP_
#define CONTAINERS_REFC_PTR_HPP_

#include "utils.hpp"

// Users of this class must implement two overloads:
//
//     void refc_ptr_add_ref(T *obj)
//
// Increments the reference count in obj, may not throw exceptions.
//
//     void refc_ptr_release(T *)
//
// Decrements the reference count in obj, and releases it if the
// reference count has hit zero.  May not throw exceptions.

template <class T>
class refc_ptr {
public:
    refc_ptr() : px_(NULL) { }

    // Takes a pointer allocated on the heap (with a ref count of
    // zero) and claims ownership over it (making its ref count 1).
    explicit refc_ptr(T *unowned) : px_(NULL) {
        reset(unowned);
    }

    ~refc_ptr() {
        reset();
    }

    void copy_from(const refc_ptr& other) {
        reset(other.px_);
    }

    void reset(T *other = NULL) {
        if (other) {
            refc_ptr_add_ref(other);
        }
        if (px_) {
            refc_ptr_release(px_);
        }
        px_ = other;
    }

    T& operator*() const {
        rassert(px_);
        return *px_;
    }

    T *operator->() const {
        rassert(px_);
        return px_;
    }

    T *get() const {
        return px_;
    }

    void swap(refc_ptr& other) {
        T *tmp = other.px_;
        other.px_ = px_;
        px_ = tmp;
    }

    typedef void (refc_ptr::*bool_type)() const;
    void dummy_member_function() const { }

    operator bool_type() const {
        return px_ ? &refc_ptr::dummy_member_function : 0;
    }

private:
    DISABLE_COPYING(refc_ptr);
    // TODO(sam): Temporarily to easy transition.
    // void operator=(const refc_ptr& other);
    T *px_;
};

template <class T>
void swap(refc_ptr<T>& a, refc_ptr<T>& b) {
    a.swap(b);
}

#endif  // CONTAINERS_REFC_PTR_HPP_
<commit_msg>Removed old commented code, added new comments, from refc_ptr.<commit_after>#ifndef CONTAINERS_REFC_PTR_HPP_
#define CONTAINERS_REFC_PTR_HPP_

#include "utils.hpp"

// An intrusive_ptr-like pointer with no implicit copy constructor or
// assignment operator.
//
// Users of this class must implement two overloads:
//
//     void refc_ptr_add_ref(T *obj)
//
//         Increments the reference count in obj.  May not throw
//         exceptions.
//
//     void refc_ptr_release(T *)
//
//         Decrements the reference count in obj, and releases it if
//         the reference count has hit zero.  May not throw
//         exceptions.
template <class T>
class refc_ptr {
public:
    refc_ptr() : px_(NULL) { }

    // Takes a pointer allocated on the heap (with a ref count of
    // zero) and claims ownership over it (making its ref count 1).
    explicit refc_ptr(T *unowned) : px_(NULL) {
        reset(unowned);
    }

    ~refc_ptr() {
        reset();
    }

    void copy_from(const refc_ptr& other) {
        reset(other.px_);
    }

    void reset(T *other = NULL) {
        if (other) {
            refc_ptr_add_ref(other);
        }
        if (px_) {
            refc_ptr_release(px_);
        }
        px_ = other;
    }

    T& operator*() const {
        rassert(px_);
        return *px_;
    }

    T *operator->() const {
        rassert(px_);
        return px_;
    }

    T *get() const {
        return px_;
    }

    void swap(refc_ptr& other) {
        T *tmp = other.px_;
        other.px_ = px_;
        px_ = tmp;
    }

    // A dummy bool type that can't get implicitly converted to int.
    typedef void (refc_ptr::*bool_type)() const;
    void dummy_member_function() const { }

    operator bool_type() const {
        return px_ ? &refc_ptr::dummy_member_function : 0;
    }

private:
    DISABLE_COPYING(refc_ptr);
    T *px_;
};

template <class T>
void swap(refc_ptr<T>& a, refc_ptr<T>& b) {
    a.swap(b);
}

#endif  // CONTAINERS_REFC_PTR_HPP_
<|endoftext|>


<commit_before>/*
 * The MIT License (MIT)
 * Copyright (c) 2015 Peter Vanusanik <admin@en-circle.com>
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal in
 * the Software without restriction, including without limitation the rights to use, copy,
 * modify, merge, publish, distribute, sublicense, and/or sell copies of the Software,
 * and to permit persons to whom the Software is furnished to do so, subject to the
 * following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all copies
 * or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS
 * OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 *
 * framebuffer.cc
 *  Created on: Jan 6, 2016
 *      Author: Peter Vanusanik
 *  Contents:
 */

#include "../../grx/grx.h"
#include "../../grx/image.h"

ruint_t dev_fb_get_height(registers_t* r) {
	if (daemon_registered(SERVICE_FRAMEBUFFER) && !is_daemon_process(get_current_pid(), SERVICE_FRAMEBUFFER))
		return DS_ERROR_NOT_ALLOWED;
	// TODO: add authorization

	return grx_get_height();
}

ruint_t dev_fb_get_width(registers_t* r) {
	if (daemon_registered(SERVICE_FRAMEBUFFER) && !is_daemon_process(get_current_pid(), SERVICE_FRAMEBUFFER))
		return DS_ERROR_NOT_ALLOWED;
	// TODO: add authorization

	return grx_get_width();
}

ruint_t dev_fb_update(registers_t* r) {
	if (daemon_registered(SERVICE_FRAMEBUFFER) && !is_daemon_process(get_current_pid(), SERVICE_FRAMEBUFFER))
		return DS_ERROR_NOT_ALLOWED;
	// TODO: add authorization

	flush_buffer();
	return DS_ERROR_SUCCESS;
}

ruint_t dev_fb_write(registers_t* r, ruint_t bytes, ruint_t x, ruint_t y, ruint_t w, ruint_t h) {
	if (daemon_registered(SERVICE_FRAMEBUFFER) && !is_daemon_process(get_current_pid(), SERVICE_FRAMEBUFFER))
		return DS_ERROR_NOT_ALLOWED;
	// TODO: add authorization

	image_t image;
	image.image_data = (uint8_t*)bytes;
	image.image_type = IMAGE_RGB;
	image.w = (uint32_t)w;
	image.h = (uint32_t)h;

	blit(&image, (uint32_t)x, (uint32_t)y);

	return DS_ERROR_SUCCESS;
}

ruint_t dev_fb_clear(registers_t* r, ruint_t red, ruint_t green, ruint_t blue) {
	if (daemon_registered(SERVICE_FRAMEBUFFER) && !is_daemon_process(get_current_pid(), SERVICE_FRAMEBUFFER))
		return DS_ERROR_NOT_ALLOWED;
	// TODO: add authorization

	clear_screen(red, green, blue);

	return DS_ERROR_SUCCESS;
}

ruint_t dev_fb_putpixel(registers_t* r, ruint_t* color, ruint_t x, ruint_t y) {
	if (daemon_registered(SERVICE_FRAMEBUFFER) && !is_daemon_process(get_current_pid(), SERVICE_FRAMEBUFFER))
		return DS_ERROR_NOT_ALLOWED;
	// TODO: add authorization

	image_t image;
	image.image_data = (uint8_t*)color;
	image.image_type = IMAGE_RGB;
	image.w = 1;
	image.h = 1;

	blit(&image, (uint32_t)x, (uint32_t)y);

	return DS_ERROR_SUCCESS;
}
<commit_msg>minor fixes<commit_after>/*
 * The MIT License (MIT)
 * Copyright (c) 2015 Peter Vanusanik <admin@en-circle.com>
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal in
 * the Software without restriction, including without limitation the rights to use, copy,
 * modify, merge, publish, distribute, sublicense, and/or sell copies of the Software,
 * and to permit persons to whom the Software is furnished to do so, subject to the
 * following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all copies
 * or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS
 * OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 *
 * framebuffer.cc
 *  Created on: Jan 6, 2016
 *      Author: Peter Vanusanik
 *  Contents:
 */

#include "../../grx/grx.h"
#include "../../grx/image.h"

ruint_t dev_fb_get_height(registers_t* r) {
	if (daemon_registered(SERVICE_FRAMEBUFFER) && !is_daemon_process(get_current_pid(), SERVICE_FRAMEBUFFER))
		return DS_ERROR_NOT_ALLOWED;
	// TODO: add authorization

	return grx_get_height();
}

ruint_t dev_fb_get_width(registers_t* r) {
	if (daemon_registered(SERVICE_FRAMEBUFFER) && !is_daemon_process(get_current_pid(), SERVICE_FRAMEBUFFER))
		return DS_ERROR_NOT_ALLOWED;
	// TODO: add authorization

	return grx_get_width();
}

ruint_t dev_fb_update(registers_t* r) {
	if (daemon_registered(SERVICE_FRAMEBUFFER) && !is_daemon_process(get_current_pid(), SERVICE_FRAMEBUFFER))
		return DS_ERROR_NOT_ALLOWED;
	// TODO: add authorization

	flush_buffer();
	return DS_ERROR_SUCCESS;
}

ruint_t dev_fb_write(registers_t* r, ruint_t bytes, ruint_t x, ruint_t y, ruint_t w, ruint_t h) {
	if (daemon_registered(SERVICE_FRAMEBUFFER) && !is_daemon_process(get_current_pid(), SERVICE_FRAMEBUFFER))
		return DS_ERROR_NOT_ALLOWED;
	// TODO: add authorization

	image_t image;
	image.image_data = (uint8_t*)bytes;
	image.image_type = IMAGE_RGB;
	image.w = (uint32_t)w;
	image.h = (uint32_t)h;

	blit(&image, (uint32_t)x, (uint32_t)y);

	return DS_ERROR_SUCCESS;
}

ruint_t dev_fb_clear(registers_t* r, ruint_t red, ruint_t green, ruint_t blue) {
	if (daemon_registered(SERVICE_FRAMEBUFFER) && !is_daemon_process(get_current_pid(), SERVICE_FRAMEBUFFER))
		return DS_ERROR_NOT_ALLOWED;
	// TODO: add authorization

	clear_screen(red, green, blue);

	return DS_ERROR_SUCCESS;
}

ruint_t dev_fb_putpixel(registers_t* r, ruint_t color, ruint_t x, ruint_t y) {
	if (daemon_registered(SERVICE_FRAMEBUFFER) && !is_daemon_process(get_current_pid(), SERVICE_FRAMEBUFFER))
		return DS_ERROR_NOT_ALLOWED;
	// TODO: add authorization

	image_t image;
	image.image_data = (uint8_t*)color;
	image.image_type = IMAGE_RGB;
	image.w = 1;
	image.h = 1;

	blit(&image, (uint32_t)x, (uint32_t)y);

	return DS_ERROR_SUCCESS;
}
<|endoftext|>


<commit_before>// Begin CVS Header
//   $Source: /Volumes/Home/Users/shoops/cvs/copasi_dev/copasi/UI/CQEventDM.cpp,v $
//   $Revision: 1.1 $
//   $Name:  $
//   $Author: aekamal $
//   $Date: 2009/07/06 12:12:14 $
// End CVS Header

// Copyright (C) 2008 by Pedro Mendes, Virginia Tech Intellectual
// Properties, Inc., EML Research, gGmbH, University of Heidelberg,
// and The University of Manchester.
// All rights reserved.

#include <QString>

#include "CopasiDataModel/CCopasiDataModel.h"
#include "report/CCopasiRootContainer.h"
#include "report/CKeyFactory.h"

#include "CQMessageBox.h"
#include "CQEventDM.h"
#include "qtUtilities.h"

CQEventDM::CQEventDM(QObject *parent)
    : CQBaseDataModel(parent)

{
}

int CQEventDM::rowCount(const QModelIndex& C_UNUSED(parent)) const
{
  return (*CCopasiRootContainer::getDatamodelList())[0]->getModel()->getEvents().size() + 1;
}
int CQEventDM::columnCount(const QModelIndex& C_UNUSED(parent)) const
{
  return TOTAL_COLS_EVENTS;
}

Qt::ItemFlags CQEventDM::flags(const QModelIndex &index) const
{
  if (!index.isValid())
    return Qt::ItemIsEnabled;

  if (index.column() == COL_NAME_EVENTS || index.column() == COL_ORDER_EVENTS)
    return QAbstractItemModel::flags(index) | Qt::ItemIsEditable;
  else
    return QAbstractItemModel::flags(index);
}

QVariant CQEventDM::data(const QModelIndex &index, int role) const
{
  if (!index.isValid())
    return QVariant();

  if (index.row() >= rowCount())
    return QVariant();

  if (role == Qt::DisplayRole || role == Qt::EditRole)
    {
      if (isDefaultRow(index))
        {
          switch (index.column())
            {
              case COL_ROW_NUMBER:
                return QVariant(index.row() + 1);
              case COL_NAME_EVENTS:
                return QVariant(QString("No Name"));
              case COL_ORDER_EVENTS:
              {
                if (role == Qt::DisplayRole)
                  return QVariant();
                else if (role == Qt::EditRole)
                  return QVariant(rowCount());
              }
              default:
                return QVariant(QString(""));
            }
        }
      else
        {
          CEvent *pEvent = (*CCopasiRootContainer::getDatamodelList())[0]->getModel()->getEvents()[index.row()];
          QString assignmentTarget = "";
          QString assignmentExpression = "";

          if (index.column() == COL_ASSIGNTARGET_EVENTS || index.column() == COL_ASSIGNEXPRESSION_EVENTS)
            {
              CCopasiVectorN< CEventAssignment >::const_iterator it = pEvent->getAssignments().begin();
              CCopasiVectorN< CEventAssignment >::const_iterator begin = pEvent->getAssignments().begin();
              CCopasiVectorN< CEventAssignment >::const_iterator end = pEvent->getAssignments().end();

              for (; it != end; ++it)
                {
                  const CModelEntity * pEntity =
                    dynamic_cast< CModelEntity * >(CCopasiRootContainer::getKeyFactory()->get((*it)->getTargetKey()));

                  if (pEntity != NULL)
                    {
                      if (it != begin)
                        {
                          assignmentTarget += "\n";
                          assignmentExpression += "\n";
                        }

                      assignmentTarget += FROM_UTF8(pEntity->getObjectDisplayName());
                      assignmentExpression += FROM_UTF8((*it)->getExpression());
                    }
                }
            }

          switch (index.column())
            {
              case COL_ROW_NUMBER:
                return QVariant(index.row() + 1);

              case COL_NAME_EVENTS:
                return QVariant(FROM_UTF8(pEvent->getObjectName()));

              case COL_ORDER_EVENTS:
                return QVariant(pEvent->getOrder());

              case COL_TRIGGER_EVENTS:
                return QVariant(FROM_UTF8(pEvent->getTriggerExpression()));

              case COL_DELAYED_EVENTS:
              {
                if (pEvent->getDelayExpression() == "")
                  return QVariant(QString("No"));
                else
                  return QVariant(QString("Yes"));
              }

              case COL_DELAY_EXPRESSION_EVENTS:
                return QVariant(FROM_UTF8(pEvent->getDelayExpression()));

              case COL_ASSIGNTARGET_EVENTS:
                return QVariant(assignmentTarget);

              case COL_ASSIGNEXPRESSION_EVENTS:
                return QVariant(assignmentExpression);
            }
        }
    }

  return QVariant();
}

QVariant CQEventDM::headerData(int section, Qt::Orientation orientation,
                               int role) const
{
  if (role != Qt::DisplayRole)
    return QVariant();

  if (orientation == Qt::Horizontal)
    {
      switch (section)
        {
          case COL_ROW_NUMBER:
            return QVariant(QString("#"));
          case COL_NAME_EVENTS:
            return QVariant(QString("Name"));
          case COL_ORDER_EVENTS:
            return QVariant(QString("Order"));
          case COL_TRIGGER_EVENTS:
            return QVariant(QString("Trigger Expression"));
          case COL_DELAYED_EVENTS:
            return QVariant("Delayed");
          case COL_DELAY_EXPRESSION_EVENTS:
            return QVariant("Delay Expression");
          case COL_ASSIGNTARGET_EVENTS:
            return QVariant("Assignment Target");
          case COL_ASSIGNEXPRESSION_EVENTS:
            return QVariant("Assignment Expression");
          default:
            return QVariant();
        }
    }
  else  //Vertical header
    return QString("%1").arg(section + 1);
}

bool CQEventDM::setData(const QModelIndex &index, const QVariant &value,
                        int role)
{
  if (index.isValid() && role == Qt::EditRole)
    {
      bool defaultRow = isDefaultRow(index);

      if (defaultRow)
        {
          if (index.data() != value)
            insertRow();
          else
            return false;
        }

      assert(CCopasiRootContainer::getDatamodelList()->size() > 0);
      CEvent *pEvent = (*CCopasiRootContainer::getDatamodelList())[0]->getModel()->getEvents()[index.row()];

      if (index.column() == COL_NAME_EVENTS)
        pEvent->setObjectName(TO_UTF8(value.toString()));
      else if (index.column() == COL_ORDER_EVENTS)
        pEvent->setOrder(value.toUInt());

      if (defaultRow && this->index(index.row(), COL_NAME_EVENTS).data().toString() == "No Name")
        pEvent->setObjectName(TO_UTF8(createNewName("Event", COL_NAME_EVENTS)));

      emit dataChanged(index, index);
    }

  return true;
}

bool CQEventDM::insertRows(int position, int rows, const QModelIndex&)
{
  beginInsertRows(QModelIndex(), position, position + rows - 1);

  for (int row = 0; row < rows; ++row)
    {
      (*CCopasiRootContainer::getDatamodelList())[0]->getModel()->createEvent("");
    }

  endInsertRows();
  return true;
}

bool CQEventDM::removeRows(int position, int rows, const QModelIndex&)
{
  if (rows <= 0)
    return true;

  beginRemoveRows(QModelIndex(), position, position + rows - 1);

  for (int row = 0; row < rows; ++row)
    {
      (*CCopasiRootContainer::getDatamodelList())[0]->getModel()->removeEvent(position);
    }

  endRemoveRows();
  return true;
}

bool CQEventDM::removeRows(QModelIndexList rows, const QModelIndex&)
{
  if (rows.isEmpty())
    return false;

  CModel * pModel = (*CCopasiRootContainer::getDatamodelList())[0]->getModel();

  if (pModel == NULL)
    return false;

//Build the list of pointers to items to be deleted
//before actually deleting any item.
  QList <CEvent *> pEvents;
  QModelIndexList::const_iterator i;

  for (i = rows.begin(); i != rows.end(); ++i)
    {
      if (!isDefaultRow(*i) && pModel->getEvents()[(*i).row()])
        pEvents.append(pModel->getEvents()[(*i).row()]);
    }

  QList <CEvent *>::const_iterator j;

  for (j = pEvents.begin(); j != pEvents.end(); ++j)
    {
      CEvent * pEvent = *j;

      unsigned C_INT32 delRow =
        pModel->getEvents().CCopasiVector< CEvent >::getIndex(pEvent);

      if (delRow != C_INVALID_INDEX)
        {
          std::set< const CCopasiObject * > deletedObjects;
          QMessageBox::StandardButton choice =
            CQMessageBox::confirmDelete(NULL, pModel, "event",
                                        FROM_UTF8(pEvent->getObjectName()),
                                        deletedObjects);

          if (choice == QMessageBox::Ok)
            removeRow(delRow);
        }
    }

  return true;
}
<commit_msg>fix to make it compile on mac and linux. Had to disable some code!<commit_after>// Begin CVS Header
//   $Source: /Volumes/Home/Users/shoops/cvs/copasi_dev/copasi/UI/CQEventDM.cpp,v $
//   $Revision: 1.2 $
//   $Name:  $
//   $Author: ssahle $
//   $Date: 2009/07/06 14:42:53 $
// End CVS Header

// Copyright (C) 2008 by Pedro Mendes, Virginia Tech Intellectual
// Properties, Inc., EML Research, gGmbH, University of Heidelberg,
// and The University of Manchester.
// All rights reserved.

#include <QString>

#include "CopasiDataModel/CCopasiDataModel.h"
#include "report/CCopasiRootContainer.h"
#include "report/CKeyFactory.h"

#include "CQMessageBox.h"
#include "CQEventDM.h"
#include "qtUtilities.h"

CQEventDM::CQEventDM(QObject *parent)
    : CQBaseDataModel(parent)

{
}

int CQEventDM::rowCount(const QModelIndex& C_UNUSED(parent)) const
{
  return (*CCopasiRootContainer::getDatamodelList())[0]->getModel()->getEvents().size() + 1;
}
int CQEventDM::columnCount(const QModelIndex& C_UNUSED(parent)) const
{
  return TOTAL_COLS_EVENTS;
}

Qt::ItemFlags CQEventDM::flags(const QModelIndex &index) const
{
  if (!index.isValid())
    return Qt::ItemIsEnabled;

  if (index.column() == COL_NAME_EVENTS || index.column() == COL_ORDER_EVENTS)
    return QAbstractItemModel::flags(index) | Qt::ItemIsEditable;
  else
    return QAbstractItemModel::flags(index);
}

QVariant CQEventDM::data(const QModelIndex &index, int role) const
{
  if (!index.isValid())
    return QVariant();

  if (index.row() >= rowCount())
    return QVariant();

  if (role == Qt::DisplayRole || role == Qt::EditRole)
    {
      if (isDefaultRow(index))
        {
          switch (index.column())
            {
              case COL_ROW_NUMBER:
                return QVariant(index.row() + 1);
              case COL_NAME_EVENTS:
                return QVariant(QString("No Name"));
              case COL_ORDER_EVENTS:
              {
                if (role == Qt::DisplayRole)
                  return QVariant();
                else if (role == Qt::EditRole)
                  return QVariant(rowCount());
              }
              default:
                return QVariant(QString(""));
            }
        }
      else
        {
          CEvent *pEvent = (*CCopasiRootContainer::getDatamodelList())[0]->getModel()->getEvents()[index.row()];
          QString assignmentTarget = "";
          QString assignmentExpression = "";

          if (index.column() == COL_ASSIGNTARGET_EVENTS || index.column() == COL_ASSIGNEXPRESSION_EVENTS)
            {
              CCopasiVectorN< CEventAssignment >::const_iterator it = pEvent->getAssignments().begin();
              CCopasiVectorN< CEventAssignment >::const_iterator begin = pEvent->getAssignments().begin();
              CCopasiVectorN< CEventAssignment >::const_iterator end = pEvent->getAssignments().end();

              for (; it != end; ++it)
                {
                  const CModelEntity * pEntity =
                    dynamic_cast< CModelEntity * >(CCopasiRootContainer::getKeyFactory()->get((*it)->getTargetKey()));

                  if (pEntity != NULL)
                    {
                      if (it != begin)
                        {
                          assignmentTarget += "\n";
                          assignmentExpression += "\n";
                        }

                      assignmentTarget += FROM_UTF8(pEntity->getObjectDisplayName());
                      assignmentExpression += FROM_UTF8((*it)->getExpression());
                    }
                }
            }

          switch (index.column())
            {
              case COL_ROW_NUMBER:
                return QVariant(index.row() + 1);

              case COL_NAME_EVENTS:
                return QVariant(FROM_UTF8(pEvent->getObjectName()));

              case COL_ORDER_EVENTS:
                return QVariant((unsigned int)pEvent->getOrder());

              case COL_TRIGGER_EVENTS:
                return QVariant(FROM_UTF8(pEvent->getTriggerExpression()));

              case COL_DELAYED_EVENTS:
              {
                if (pEvent->getDelayExpression() == "")
                  return QVariant(QString("No"));
                else
                  return QVariant(QString("Yes"));
              }

              case COL_DELAY_EXPRESSION_EVENTS:
                return QVariant(FROM_UTF8(pEvent->getDelayExpression()));

              case COL_ASSIGNTARGET_EVENTS:
                return QVariant(assignmentTarget);

              case COL_ASSIGNEXPRESSION_EVENTS:
                return QVariant(assignmentExpression);
            }
        }
    }

  return QVariant();
}

QVariant CQEventDM::headerData(int section, Qt::Orientation orientation,
                               int role) const
{
  if (role != Qt::DisplayRole)
    return QVariant();

  if (orientation == Qt::Horizontal)
    {
      switch (section)
        {
          case COL_ROW_NUMBER:
            return QVariant(QString("#"));
          case COL_NAME_EVENTS:
            return QVariant(QString("Name"));
          case COL_ORDER_EVENTS:
            return QVariant(QString("Order"));
          case COL_TRIGGER_EVENTS:
            return QVariant(QString("Trigger Expression"));
          case COL_DELAYED_EVENTS:
            return QVariant("Delayed");
          case COL_DELAY_EXPRESSION_EVENTS:
            return QVariant("Delay Expression");
          case COL_ASSIGNTARGET_EVENTS:
            return QVariant("Assignment Target");
          case COL_ASSIGNEXPRESSION_EVENTS:
            return QVariant("Assignment Expression");
          default:
            return QVariant();
        }
    }
  else  //Vertical header
    return QString("%1").arg(section + 1);
}

bool CQEventDM::setData(const QModelIndex &index, const QVariant &value,
                        int role)
{
  if (index.isValid() && role == Qt::EditRole)
    {
      bool defaultRow = isDefaultRow(index);

      if (defaultRow)
        {
          if (index.data() != value)
            insertRow();
          else
            return false;
        }

      assert(CCopasiRootContainer::getDatamodelList()->size() > 0);
      CEvent *pEvent = (*CCopasiRootContainer::getDatamodelList())[0]->getModel()->getEvents()[index.row()];

      if (index.column() == COL_NAME_EVENTS)
        pEvent->setObjectName(TO_UTF8(value.toString()));
      else if (index.column() == COL_ORDER_EVENTS)
        pEvent->setOrder(value.toUInt());

      if (defaultRow && this->index(index.row(), COL_NAME_EVENTS).data().toString() == "No Name")
        pEvent->setObjectName(TO_UTF8(createNewName("Event", COL_NAME_EVENTS)));

      emit dataChanged(index, index);
    }

  return true;
}

bool CQEventDM::insertRows(int position, int rows, const QModelIndex&)
{
  beginInsertRows(QModelIndex(), position, position + rows - 1);

  for (int row = 0; row < rows; ++row)
    {
      (*CCopasiRootContainer::getDatamodelList())[0]->getModel()->createEvent("");
    }

  endInsertRows();
  return true;
}

bool CQEventDM::removeRows(int position, int rows, const QModelIndex&)
{
  if (rows <= 0)
    return true;

  beginRemoveRows(QModelIndex(), position, position + rows - 1);

  for (int row = 0; row < rows; ++row)
    {
//      (*CCopasiRootContainer::getDatamodelList())[0]->getModel()->removeEvent(position);
    }

  endRemoveRows();
  return true;
}

bool CQEventDM::removeRows(QModelIndexList rows, const QModelIndex&)
{
  if (rows.isEmpty())
    return false;

  CModel * pModel = (*CCopasiRootContainer::getDatamodelList())[0]->getModel();

  if (pModel == NULL)
    return false;

//Build the list of pointers to items to be deleted
//before actually deleting any item.
  QList <CEvent *> pEvents;
  QModelIndexList::const_iterator i;

  for (i = rows.begin(); i != rows.end(); ++i)
    {
      if (!isDefaultRow(*i) && pModel->getEvents()[(*i).row()])
        pEvents.append(pModel->getEvents()[(*i).row()]);
    }

  QList <CEvent *>::const_iterator j;

  for (j = pEvents.begin(); j != pEvents.end(); ++j)
    {
      CEvent * pEvent = *j;

      unsigned C_INT32 delRow =
        pModel->getEvents().CCopasiVector< CEvent >::getIndex(pEvent);

      if (delRow != C_INVALID_INDEX)
        {
          std::set< const CCopasiObject * > deletedObjects;
          QMessageBox::StandardButton choice =
            CQMessageBox::confirmDelete(NULL, pModel, "event",
                                        FROM_UTF8(pEvent->getObjectName()),
                                        deletedObjects);

          if (choice == QMessageBox::Ok)
            removeRow(delRow);
        }
    }

  return true;
}
<|endoftext|>


<commit_before>/* Copyright (c) 2017-2019 Hans-Kristian Arntzen
 *
 * Permission is hereby granted, free of charge, to any person obtaining
 * a copy of this software and associated documentation files (the
 * "Software"), to deal in the Software without restriction, including
 * without limitation the rights to use, copy, modify, merge, publish,
 * distribute, sublicense, and/or sell copies of the Software, and to
 * permit persons to whom the Software is furnished to do so, subject to
 * the following conditions:
 *
 * The above copyright notice and this permission notice shall be
 * included in all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
 * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
 * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 */

#include "application.hpp"
#include "command_buffer.hpp"
#include "device.hpp"
#include "os_filesystem.hpp"
#include "math.hpp"
#include <string.h>

using namespace Granite;
using namespace Vulkan;

struct MultiviewApplication : Application, EventHandler
{
	MultiviewApplication()
	{
		EVENT_MANAGER_REGISTER_LATCH(MultiviewApplication,
		                             on_device_created,
		                             on_device_destroyed,
		                             DeviceCreatedEvent);
	}

	void on_device_created(const DeviceCreatedEvent &e)
	{
		auto rt = ImageCreateInfo::render_target(256, 64, VK_FORMAT_R8G8B8A8_UNORM);
		rt.initial_layout = VK_IMAGE_LAYOUT_UNDEFINED;
		rt.layers = 4;
		rt.usage |= VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT;
		multiview_rt = e.get_device().create_image(rt);
	}

	void on_device_destroyed(const DeviceCreatedEvent &)
	{
		multiview_rt.reset();
	}

	void render_frame(double, double) override
	{
		auto &device = get_wsi().get_device();
		auto cmd = device.request_command_buffer();

		RenderPassInfo rp;
		rp.num_color_attachments = 1;
		rp.color_attachments[0] = &multiview_rt->get_view();
		rp.clear_attachments = 1;
		rp.store_attachments = 1;
		rp.base_layer = 1;
		rp.num_layers = 3;
		for (unsigned i = 0; i < 4; i++)
			rp.clear_color[0].float32[i] = 1.0f;

		cmd->image_barrier(*multiview_rt, VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
		                   VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, 0,
		                   VK_PIPELINE_STAGE_TRANSFER_BIT, VK_ACCESS_TRANSFER_WRITE_BIT);

		cmd->clear_image(*multiview_rt, {});

		cmd->image_barrier(*multiview_rt, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
		                   VK_PIPELINE_STAGE_TRANSFER_BIT, VK_ACCESS_TRANSFER_WRITE_BIT,
		                   VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT);

		cmd->begin_render_pass(rp);
		cmd->set_opaque_state();
		cmd->set_primitive_topology(VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP);
		cmd->set_program("assets://shaders/multiview_quad.vert", "assets://shaders/multiview_quad.frag");
		auto *coord = static_cast<int8_t *>(cmd->allocate_vertex_data(0, 8, 2));
		coord[0] = -1;
		coord[1] = -1;
		coord[2] = -1;
		coord[3] = +1;
		coord[4] = +1;
		coord[5] = -1;
		coord[6] = +1;
		coord[7] = +1;
		cmd->set_vertex_attrib(0, 0, VK_FORMAT_R8G8_SNORM, 0);
		auto *base_positions = cmd->allocate_typed_constant_data<vec4>(0, 0, 4);
		base_positions[0] = vec4(-0.8f, -0.8f, 0.0f, 1.0f);
		base_positions[1] = vec4(-0.8f, +0.8f, 0.0f, 1.0f);
		base_positions[2] = vec4(+0.8f, -0.8f, 0.0f, 1.0f);
		base_positions[3] = vec4(+0.8f, +0.8f, 0.0f, 1.0f);
		cmd->draw(4, 4);
		cmd->end_render_pass();

		cmd->image_barrier(*multiview_rt, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL,
		                   VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
		                   VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, VK_ACCESS_SHADER_READ_BIT);

		rp = device.get_swapchain_render_pass(SwapchainRenderPass::ColorOnly);
		cmd->begin_render_pass(rp);
		cmd->set_texture(0, 0, multiview_rt->get_view(), StockSampler::NearestClamp);
		CommandBufferUtil::draw_fullscreen_quad(*cmd, "builtin://shaders/quad.vert", "assets://shaders/multiview_debug.frag");
		cmd->end_render_pass();

		device.submit(cmd);
	}

	ImageHandle multiview_rt;
};

namespace Granite
{
Application *application_create(int, char **)
{
	application_dummy();

#ifdef ASSET_DIRECTORY
	const char *asset_dir = getenv("ASSET_DIRECTORY");
	if (!asset_dir)
		asset_dir = ASSET_DIRECTORY;

	Global::filesystem()->register_protocol("assets", std::unique_ptr<FilesystemBackend>(new OSFilesystem(asset_dir)));
#endif

	try
	{
		auto *app = new MultiviewApplication();
		return app;
	}
	catch (const std::exception &e)
	{
		LOGE("application_create() threw exception: %s\n", e.what());
		return nullptr;
	}
}
}
<commit_msg>Test indirect multiview.<commit_after>/* Copyright (c) 2017-2019 Hans-Kristian Arntzen
 *
 * Permission is hereby granted, free of charge, to any person obtaining
 * a copy of this software and associated documentation files (the
 * "Software"), to deal in the Software without restriction, including
 * without limitation the rights to use, copy, modify, merge, publish,
 * distribute, sublicense, and/or sell copies of the Software, and to
 * permit persons to whom the Software is furnished to do so, subject to
 * the following conditions:
 *
 * The above copyright notice and this permission notice shall be
 * included in all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
 * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
 * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 */

#include "application.hpp"
#include "command_buffer.hpp"
#include "device.hpp"
#include "os_filesystem.hpp"
#include "math.hpp"
#include <string.h>

using namespace Granite;
using namespace Vulkan;

struct MultiviewApplication : Application, EventHandler
{
	MultiviewApplication()
	{
		EVENT_MANAGER_REGISTER_LATCH(MultiviewApplication,
		                             on_device_created,
		                             on_device_destroyed,
		                             DeviceCreatedEvent);
	}

	void on_device_created(const DeviceCreatedEvent &e)
	{
		auto rt = ImageCreateInfo::render_target(256, 64, VK_FORMAT_R8G8B8A8_UNORM);
		rt.initial_layout = VK_IMAGE_LAYOUT_UNDEFINED;
		rt.layers = 4;
		rt.usage |= VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT;
		multiview_rt = e.get_device().create_image(rt);

		VkDrawIndirectCommand initial = {};
		initial.vertexCount = 4;
		initial.instanceCount = 4;
		BufferCreateInfo info = {};
		info.size = sizeof(VkDrawIndirectCommand);
		info.usage = VK_BUFFER_USAGE_INDIRECT_BUFFER_BIT;
		info.domain = BufferDomain::Device;
		indirect = e.get_device().create_buffer(info, &initial);
	}

	void on_device_destroyed(const DeviceCreatedEvent &)
	{
		multiview_rt.reset();
	}

	void render_frame(double, double) override
	{
		auto &device = get_wsi().get_device();
		auto cmd = device.request_command_buffer();

		RenderPassInfo rp;
		rp.num_color_attachments = 1;
		rp.color_attachments[0] = &multiview_rt->get_view();
		rp.clear_attachments = 1;
		rp.store_attachments = 1;
		rp.base_layer = 1;
		rp.num_layers = 3;
		for (unsigned i = 0; i < 4; i++)
			rp.clear_color[0].float32[i] = 1.0f;

		cmd->image_barrier(*multiview_rt, VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
		                   VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, 0,
		                   VK_PIPELINE_STAGE_TRANSFER_BIT, VK_ACCESS_TRANSFER_WRITE_BIT);

		cmd->clear_image(*multiview_rt, {});

		cmd->image_barrier(*multiview_rt, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
		                   VK_PIPELINE_STAGE_TRANSFER_BIT, VK_ACCESS_TRANSFER_WRITE_BIT,
		                   VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT);

		cmd->begin_render_pass(rp);
		cmd->set_opaque_state();
		cmd->set_primitive_topology(VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP);
		cmd->set_program("assets://shaders/multiview_quad.vert", "assets://shaders/multiview_quad.frag");
		auto *coord = static_cast<int8_t *>(cmd->allocate_vertex_data(0, 8, 2));
		coord[0] = -1;
		coord[1] = -1;
		coord[2] = -1;
		coord[3] = +1;
		coord[4] = +1;
		coord[5] = -1;
		coord[6] = +1;
		coord[7] = +1;
		cmd->set_vertex_attrib(0, 0, VK_FORMAT_R8G8_SNORM, 0);
		auto *base_positions = cmd->allocate_typed_constant_data<vec4>(0, 0, 4);
		base_positions[0] = vec4(-0.8f, -0.8f, 0.0f, 1.0f);
		base_positions[1] = vec4(-0.8f, +0.8f, 0.0f, 1.0f);
		base_positions[2] = vec4(+0.8f, -0.8f, 0.0f, 1.0f);
		base_positions[3] = vec4(+0.8f, +0.8f, 0.0f, 1.0f);
		//cmd->draw(4, 4);
		cmd->draw_indirect(*indirect, 0, 1, sizeof(VkDrawIndirectCommand));
		cmd->end_render_pass();

		cmd->image_barrier(*multiview_rt, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL,
		                   VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
		                   VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, VK_ACCESS_SHADER_READ_BIT);

		rp = device.get_swapchain_render_pass(SwapchainRenderPass::ColorOnly);
		cmd->begin_render_pass(rp);
		cmd->set_texture(0, 0, multiview_rt->get_view(), StockSampler::NearestClamp);
		CommandBufferUtil::draw_fullscreen_quad(*cmd, "builtin://shaders/quad.vert", "assets://shaders/multiview_debug.frag");
		cmd->end_render_pass();

		device.submit(cmd);
	}

	ImageHandle multiview_rt;
	BufferHandle indirect;
};

namespace Granite
{
Application *application_create(int, char **)
{
	application_dummy();

#ifdef ASSET_DIRECTORY
	const char *asset_dir = getenv("ASSET_DIRECTORY");
	if (!asset_dir)
		asset_dir = ASSET_DIRECTORY;

	Global::filesystem()->register_protocol("assets", std::unique_ptr<FilesystemBackend>(new OSFilesystem(asset_dir)));
#endif

	try
	{
		auto *app = new MultiviewApplication();
		return app;
	}
	catch (const std::exception &e)
	{
		LOGE("application_create() threw exception: %s\n", e.what());
		return nullptr;
	}
}
}
<|endoftext|>


<commit_before>/*
 * author: Max Kellermann <mk@cm4all.com>
 */

#ifndef CERT_DATABASE_HXX
#define CERT_DATABASE_HXX

#include "pg/Connection.hxx"
#include "ssl/Unique.hxx"

#include <string>

typedef struct aes_key_st AES_KEY;
struct CertDatabaseConfig;

class CertDatabase {
    const CertDatabaseConfig &config;

    PgConnection conn;

    const std::string schema;

public:
    explicit CertDatabase(const CertDatabaseConfig &_config);

    ConnStatusType GetStatus() const {
        return conn.GetStatus();
    }

    gcc_pure
    const char *GetErrorMessage() const {
        return conn.GetErrorMessage();
    }

    bool CheckConnected();
    void EnsureConnected();

    gcc_pure
    int GetSocket() const {
        return conn.GetSocket();
    }

    void ConsumeInput() {
        conn.ConsumeInput();
    }

    PgNotify GetNextNotify() {
        return conn.GetNextNotify();
    }

    PgResult ListenModified();
    PgResult NotifyModified();

    gcc_pure
    std::string GetCurrentTimestamp() {
        const auto result = conn.Execute("SELECT CURRENT_TIMESTAMP");
        return result.GetOnlyStringChecked();
    }

    gcc_pure
    std::string GetLastModified() {
        const auto result = conn.Execute("SELECT MAX(modified) FROM server_certificate");
        return result.GetOnlyStringChecked();
    }

    bool BeginSerializable() {
        return conn.BeginSerializable();
    }

    bool Commit() {
        return conn.Commit();
    }

    void InsertServerCertificate(const char *common_name,
                                 const char *not_before,
                                 const char *not_after,
                                 X509 &cert, ConstBuffer<void> key,
                                 const char *key_wrap_name);

    /**
     * @return true when new certificate has been inserted, false when an
     * existing certificate has been updated
     */
    bool LoadServerCertificate(X509 &cert, EVP_PKEY &key,
                               const char *key_wrap_name,
                               AES_KEY *wrap_key);

    /**
     * Delete *.acme.invalid for alt_names of the given certificate.
     */
    unsigned DeleteAcmeInvalidAlt(X509 &cert);

    UniqueX509 GetServerCertificate(const char *name);

    /**
     * Throws std:;runtime_error on error.
     *
     * @return a pair of certificate and key, or {nullptr, nullptr} if
     * no matching certificate was found
     */
    std::pair<UniqueX509, UniqueEVP_PKEY> GetServerCertificateKey(const char *name);
    std::pair<UniqueX509, UniqueEVP_PKEY> GetServerCertificateKey(unsigned id);

private:
    PgResult InsertServerCertificate(const char *common_name,
                                     const char *not_before,
                                     const char *not_after,
                                     PgBinaryValue cert, PgBinaryValue key,
                                     const char *key_wrap_name) {
        return conn.ExecuteBinary("INSERT INTO server_certificate("
                                  "common_name, "
                                  "not_before, not_after, "
                                  "certificate_der, key_der, key_wrap_name) "
                                  "VALUES($1, $2, $3, $4, $5, $6)"
                                  " RETURNING id",
                                  common_name,
                                  not_before, not_after,
                                  cert, key, key_wrap_name);
    }

    PgResult UpdateServerCertificate(const char *common_name,
                                     const char *not_before,
                                     const char *not_after,
                                     PgBinaryValue cert, PgBinaryValue key,
                                     const char *key_wrap_name) {
        return conn.ExecuteBinary("UPDATE server_certificate SET "
                                  "not_before=$2, not_after=$3, "
                                  "certificate_der=$4, key_der=$5, "
                                  "key_wrap_name=$6, "
                                  "modified=CURRENT_TIMESTAMP, deleted=FALSE "
                                  "WHERE common_name=$1"
                                  " RETURNING id",
                                  common_name, not_before, not_after,
                                  cert, key, key_wrap_name);
    }

    PgResult DeleteAltNames(const char *server_certificate_id) {
        return conn.ExecuteParams("DELETE FROM server_certificate_alt_name"
                                  " WHERE server_certificate_id=$1",
                                  server_certificate_id);
    }

    PgResult InsertAltName(const char *server_certificate_id,
                           const char *name) {
        return conn.ExecuteParams("INSERT INTO server_certificate_alt_name"
                                  "(server_certificate_id, name)"
                                  " VALUES($1, $2)",
                                  server_certificate_id, name);
    }

public:
    PgResult DeleteServerCertificateByName(const char *common_name) {
        return conn.ExecuteParams(true,
                                  "UPDATE server_certificate SET "
                                  "modified=CURRENT_TIMESTAMP, deleted=TRUE "
                                  "WHERE common_name=$1 AND NOT deleted",
                                  common_name);
    }

private:
    template<typename T>
    PgResult DeleteAcmeInvalidByNames(const T &names) {
        return conn.ExecuteParams(true,
                                  "UPDATE server_certificate SET "
                                  "modified=CURRENT_TIMESTAMP, deleted=TRUE "
                                  "WHERE NOT deleted AND common_name = ANY($1)"
                                  " AND EXISTS("
                                  "SELECT id FROM server_certificate_alt_name"
                                  " WHERE server_certificate_id=server_certificate.id"
                                  " AND name LIKE '%.acme.invalid')",
                                  names);
    }

    PgResult FindServerCertificateByName(const char *common_name) {
        return conn.ExecuteParams(true,
                                  "SELECT certificate_der "
                                  "FROM server_certificate "
                                  "WHERE NOT deleted AND "
                                  "(common_name=$1 OR EXISTS("
                                  "SELECT id FROM server_certificate_alt_name"
                                  " WHERE server_certificate_id=server_certificate.id"
                                  " AND name=$1))"
                                  "ORDER BY"
                                  /* prefer certificates which expire later */
                                  " not_after DESC,"
                                  /* prefer exact match in common_name: */
                                  " common_name=$1 DESC "
                                  "LIMIT 1",
                                  common_name);
    }

    PgResult FindServerCertificateKeyByName(const char *common_name) {
        return conn.ExecuteParams(true,
                                  "SELECT certificate_der, key_der, key_wrap_name "
                                  "FROM server_certificate "
                                  "WHERE NOT deleted AND "
                                  "(common_name=$1 OR EXISTS("
                                  "SELECT id FROM server_certificate_alt_name"
                                  " WHERE server_certificate_id=server_certificate.id"
                                  " AND name=$1))"
                                  "ORDER BY"
                                  /* prefer certificates which expire later */
                                  " not_after DESC,"
                                  /* prefer exact match in common_name: */
                                  " common_name=$1 DESC "
                                  "LIMIT 1",
                                  common_name);
    }

    PgResult FindServerCertificateKeyById(unsigned id) {
        return conn.ExecuteParams(true,
                                  "SELECT certificate_der, key_der, key_wrap_name "
                                  "FROM server_certificate "
                                  "WHERE id=$1",
                                  id);
    }

public:
    PgResult GetModifiedServerCertificatesMeta(const char *since) {
        return conn.ExecuteParams("SELECT deleted, modified, common_name "
                                  "FROM server_certificate "
                                  "WHERE modified>$1",
                                  since);
    }

    PgResult TailModifiedServerCertificatesMeta() {
        return conn.Execute("SELECT deleted, modified, common_name "
                            "FROM server_certificate "
                            "ORDER BY modified LIMIT 20");
    }
};

#endif
<commit_msg>certdb/CertDatabase: remove unused column "schema"<commit_after>/*
 * author: Max Kellermann <mk@cm4all.com>
 */

#ifndef CERT_DATABASE_HXX
#define CERT_DATABASE_HXX

#include "pg/Connection.hxx"
#include "ssl/Unique.hxx"

#include <string>

typedef struct aes_key_st AES_KEY;
struct CertDatabaseConfig;

class CertDatabase {
    const CertDatabaseConfig &config;

    PgConnection conn;

public:
    explicit CertDatabase(const CertDatabaseConfig &_config);

    ConnStatusType GetStatus() const {
        return conn.GetStatus();
    }

    gcc_pure
    const char *GetErrorMessage() const {
        return conn.GetErrorMessage();
    }

    bool CheckConnected();
    void EnsureConnected();

    gcc_pure
    int GetSocket() const {
        return conn.GetSocket();
    }

    void ConsumeInput() {
        conn.ConsumeInput();
    }

    PgNotify GetNextNotify() {
        return conn.GetNextNotify();
    }

    PgResult ListenModified();
    PgResult NotifyModified();

    gcc_pure
    std::string GetCurrentTimestamp() {
        const auto result = conn.Execute("SELECT CURRENT_TIMESTAMP");
        return result.GetOnlyStringChecked();
    }

    gcc_pure
    std::string GetLastModified() {
        const auto result = conn.Execute("SELECT MAX(modified) FROM server_certificate");
        return result.GetOnlyStringChecked();
    }

    bool BeginSerializable() {
        return conn.BeginSerializable();
    }

    bool Commit() {
        return conn.Commit();
    }

    void InsertServerCertificate(const char *common_name,
                                 const char *not_before,
                                 const char *not_after,
                                 X509 &cert, ConstBuffer<void> key,
                                 const char *key_wrap_name);

    /**
     * @return true when new certificate has been inserted, false when an
     * existing certificate has been updated
     */
    bool LoadServerCertificate(X509 &cert, EVP_PKEY &key,
                               const char *key_wrap_name,
                               AES_KEY *wrap_key);

    /**
     * Delete *.acme.invalid for alt_names of the given certificate.
     */
    unsigned DeleteAcmeInvalidAlt(X509 &cert);

    UniqueX509 GetServerCertificate(const char *name);

    /**
     * Throws std:;runtime_error on error.
     *
     * @return a pair of certificate and key, or {nullptr, nullptr} if
     * no matching certificate was found
     */
    std::pair<UniqueX509, UniqueEVP_PKEY> GetServerCertificateKey(const char *name);
    std::pair<UniqueX509, UniqueEVP_PKEY> GetServerCertificateKey(unsigned id);

private:
    PgResult InsertServerCertificate(const char *common_name,
                                     const char *not_before,
                                     const char *not_after,
                                     PgBinaryValue cert, PgBinaryValue key,
                                     const char *key_wrap_name) {
        return conn.ExecuteBinary("INSERT INTO server_certificate("
                                  "common_name, "
                                  "not_before, not_after, "
                                  "certificate_der, key_der, key_wrap_name) "
                                  "VALUES($1, $2, $3, $4, $5, $6)"
                                  " RETURNING id",
                                  common_name,
                                  not_before, not_after,
                                  cert, key, key_wrap_name);
    }

    PgResult UpdateServerCertificate(const char *common_name,
                                     const char *not_before,
                                     const char *not_after,
                                     PgBinaryValue cert, PgBinaryValue key,
                                     const char *key_wrap_name) {
        return conn.ExecuteBinary("UPDATE server_certificate SET "
                                  "not_before=$2, not_after=$3, "
                                  "certificate_der=$4, key_der=$5, "
                                  "key_wrap_name=$6, "
                                  "modified=CURRENT_TIMESTAMP, deleted=FALSE "
                                  "WHERE common_name=$1"
                                  " RETURNING id",
                                  common_name, not_before, not_after,
                                  cert, key, key_wrap_name);
    }

    PgResult DeleteAltNames(const char *server_certificate_id) {
        return conn.ExecuteParams("DELETE FROM server_certificate_alt_name"
                                  " WHERE server_certificate_id=$1",
                                  server_certificate_id);
    }

    PgResult InsertAltName(const char *server_certificate_id,
                           const char *name) {
        return conn.ExecuteParams("INSERT INTO server_certificate_alt_name"
                                  "(server_certificate_id, name)"
                                  " VALUES($1, $2)",
                                  server_certificate_id, name);
    }

public:
    PgResult DeleteServerCertificateByName(const char *common_name) {
        return conn.ExecuteParams(true,
                                  "UPDATE server_certificate SET "
                                  "modified=CURRENT_TIMESTAMP, deleted=TRUE "
                                  "WHERE common_name=$1 AND NOT deleted",
                                  common_name);
    }

private:
    template<typename T>
    PgResult DeleteAcmeInvalidByNames(const T &names) {
        return conn.ExecuteParams(true,
                                  "UPDATE server_certificate SET "
                                  "modified=CURRENT_TIMESTAMP, deleted=TRUE "
                                  "WHERE NOT deleted AND common_name = ANY($1)"
                                  " AND EXISTS("
                                  "SELECT id FROM server_certificate_alt_name"
                                  " WHERE server_certificate_id=server_certificate.id"
                                  " AND name LIKE '%.acme.invalid')",
                                  names);
    }

    PgResult FindServerCertificateByName(const char *common_name) {
        return conn.ExecuteParams(true,
                                  "SELECT certificate_der "
                                  "FROM server_certificate "
                                  "WHERE NOT deleted AND "
                                  "(common_name=$1 OR EXISTS("
                                  "SELECT id FROM server_certificate_alt_name"
                                  " WHERE server_certificate_id=server_certificate.id"
                                  " AND name=$1))"
                                  "ORDER BY"
                                  /* prefer certificates which expire later */
                                  " not_after DESC,"
                                  /* prefer exact match in common_name: */
                                  " common_name=$1 DESC "
                                  "LIMIT 1",
                                  common_name);
    }

    PgResult FindServerCertificateKeyByName(const char *common_name) {
        return conn.ExecuteParams(true,
                                  "SELECT certificate_der, key_der, key_wrap_name "
                                  "FROM server_certificate "
                                  "WHERE NOT deleted AND "
                                  "(common_name=$1 OR EXISTS("
                                  "SELECT id FROM server_certificate_alt_name"
                                  " WHERE server_certificate_id=server_certificate.id"
                                  " AND name=$1))"
                                  "ORDER BY"
                                  /* prefer certificates which expire later */
                                  " not_after DESC,"
                                  /* prefer exact match in common_name: */
                                  " common_name=$1 DESC "
                                  "LIMIT 1",
                                  common_name);
    }

    PgResult FindServerCertificateKeyById(unsigned id) {
        return conn.ExecuteParams(true,
                                  "SELECT certificate_der, key_der, key_wrap_name "
                                  "FROM server_certificate "
                                  "WHERE id=$1",
                                  id);
    }

public:
    PgResult GetModifiedServerCertificatesMeta(const char *since) {
        return conn.ExecuteParams("SELECT deleted, modified, common_name "
                                  "FROM server_certificate "
                                  "WHERE modified>$1",
                                  since);
    }

    PgResult TailModifiedServerCertificatesMeta() {
        return conn.Execute("SELECT deleted, modified, common_name "
                            "FROM server_certificate "
                            "ORDER BY modified LIMIT 20");
    }
};

#endif
<|endoftext|>