<commit_before>#include <vector>
#include "vp9/common/vp9_onyxc_int.h"
#include "vp9/vp9_iface_common.h"
#include "vp9/encoder/vp9_encoder.h"
#include "vp9/encoder/vp9_firstpass.h"
#include "vp9/simple_encode.h"
#include "vp9/vp9_cx_iface.h"

// TODO(angiebird): Merge this function with vpx_img_plane_width()
static int img_plane_width(const vpx_image_t *img, int plane) {
  if (plane > 0 && img->x_chroma_shift > 0)
    return (img->d_w + 1) >> img->x_chroma_shift;
  else
    return img->d_w;
}

// TODO(angiebird): Merge this function with vpx_img_plane_height()
static int img_plane_height(const vpx_image_t *img, int plane) {
  if (plane > 0 && img->y_chroma_shift > 0)
    return (img->d_h + 1) >> img->y_chroma_shift;
  else
    return img->d_h;
}

// TODO(angiebird): Merge this function with vpx_img_read()
static int img_read(vpx_image_t *img, FILE *file) {
  int plane;

  for (plane = 0; plane < 3; ++plane) {
    unsigned char *buf = img->planes[plane];
    const int stride = img->stride[plane];
    const int w = img_plane_width(img, plane) *
                  ((img->fmt & VPX_IMG_FMT_HIGHBITDEPTH) ? 2 : 1);
    const int h = img_plane_height(img, plane);
    int y;

    for (y = 0; y < h; ++y) {
      if (fread(buf, 1, w, file) != (size_t)w) return 0;
      buf += stride;
    }
  }

  return 1;
}

class SimpleEncode::impl {
 public:
  VP9_COMP *cpi;
  vpx_img_fmt_t img_fmt;
  vpx_image_t tmp_img;
  std::vector<FIRSTPASS_STATS> first_pass_stats;
};

static VP9_COMP *init_encoder(const VP9EncoderConfig *oxcf,
                              vpx_img_fmt_t img_fmt) {
  VP9_COMP *cpi;
  BufferPool *buffer_pool = (BufferPool *)vpx_calloc(1, sizeof(*buffer_pool));
  vp9_initialize_enc();
  cpi = vp9_create_compressor(oxcf, buffer_pool);
  vp9_update_compressor_with_img_fmt(cpi, img_fmt);
  return cpi;
}

static void free_encoder(VP9_COMP *cpi) {
  vpx_free(cpi->common.buffer_pool);
  vp9_remove_compressor(cpi);
}

static INLINE vpx_rational_t make_vpx_rational(int num, int den) {
  vpx_rational_t v;
  v.num = num;
  v.den = den;
  return v;
}

static INLINE FrameType
get_frame_type_from_update_type(FRAME_UPDATE_TYPE update_type) {
  // TODO(angiebird): Figure out if we need frame type other than key frame,
  // alternate reference and inter frame
  switch (update_type) {
    case KF_UPDATE: return kKeyFrame; break;
    case ARF_UPDATE: return kAlternateReference; break;
    default: return kInterFrame; break;
  }
}

static void update_encode_frame_result(
    EncodeFrameResult *encode_frame_result,
    const ENCODE_FRAME_RESULT *encode_frame_info) {
  encode_frame_result->coding_data_bit_size =
      encode_frame_result->coding_data_byte_size * 8;
  encode_frame_result->show_idx = encode_frame_info->show_idx;
  encode_frame_result->frame_type =
      get_frame_type_from_update_type(encode_frame_info->update_type);
  encode_frame_result->psnr = encode_frame_info->psnr;
  encode_frame_result->sse = encode_frame_info->sse;
  encode_frame_result->quantize_index = encode_frame_info->quantize_index;
}

SimpleEncode::SimpleEncode(int frame_width, int frame_height,
                           int frame_rate_num, int frame_rate_den,
                           int target_bitrate, int num_frames,
                           const char *infile_path)
    : pimpl{ std::unique_ptr<impl>(new impl()) } {
  this->frame_width = frame_width;
  this->frame_height = frame_height;
  this->frame_rate_num = frame_rate_num;
  this->frame_rate_den = frame_rate_den;
  this->target_bitrate = target_bitrate;
  this->num_frames = num_frames;
  // TODO(angirbid): Should we keep a file pointer here or keep the file_path?
  this->file = fopen(infile_path, "r");
  pimpl->cpi = NULL;
  pimpl->img_fmt = VPX_IMG_FMT_I420;
}

void SimpleEncode::ComputeFirstPassStats() {
  vpx_rational_t frame_rate = make_vpx_rational(frame_rate_num, frame_rate_den);
  const VP9EncoderConfig oxcf = vp9_get_encoder_config(
      frame_width, frame_height, frame_rate, target_bitrate, VPX_RC_FIRST_PASS);
  VP9_COMP *cpi = init_encoder(&oxcf, pimpl->img_fmt);
  struct lookahead_ctx *lookahead = cpi->lookahead;
  int i;
  int use_highbitdepth = 0;
#if CONFIG_VP9_HIGHBITDEPTH
  use_highbitdepth = cpi->common.use_highbitdepth;
#endif
  vpx_image_t img;
  vpx_img_alloc(&img, pimpl->img_fmt, frame_width, frame_height, 1);
  rewind(file);
  pimpl->first_pass_stats.clear();
  for (i = 0; i < num_frames; ++i) {
    assert(!vp9_lookahead_full(lookahead));
    if (img_read(&img, file)) {
      int next_show_idx = vp9_lookahead_next_show_idx(lookahead);
      int64_t ts_start =
          timebase_units_to_ticks(&oxcf.g_timebase_in_ts, next_show_idx);
      int64_t ts_end =
          timebase_units_to_ticks(&oxcf.g_timebase_in_ts, next_show_idx + 1);
      YV12_BUFFER_CONFIG sd;
      image2yuvconfig(&img, &sd);
      vp9_lookahead_push(lookahead, &sd, ts_start, ts_end, use_highbitdepth, 0);
      {
        int64_t time_stamp;
        int64_t time_end;
        int flush = 1;  // Make vp9_get_compressed_data process a frame
        size_t size;
        unsigned int frame_flags = 0;
        ENCODE_FRAME_RESULT encode_frame_info;
        // TODO(angiebird): Call vp9_first_pass directly
        vp9_get_compressed_data(cpi, &frame_flags, &size, NULL, &time_stamp,
                                &time_end, flush, &encode_frame_info);
        // vp9_get_compressed_data only generates first pass stats not
        // compresses data
        assert(size == 0);
      }
      pimpl->first_pass_stats.push_back(vp9_get_frame_stats(&cpi->twopass));
    }
  }
  vp9_end_first_pass(cpi);
  // TODO(angiebird): Store the total_stats apart form first_pass_stats
  pimpl->first_pass_stats.push_back(vp9_get_total_stats(&cpi->twopass));
  free_encoder(cpi);
  rewind(file);
  vpx_img_free(&img);
}

std::vector<std::vector<double>> SimpleEncode::ObserveFirstPassStats() {
  std::vector<std::vector<double>> output_stats;
  // TODO(angiebird): This function make several assumptions of
  // FIRSTPASS_STATS. 1) All elements in FIRSTPASS_STATS are double except the
  // last one. 2) The last entry of first_pass_stats is the total_stats.
  // Change the code structure, so that we don't have to make these assumptions

  // Note the last entry of first_pass_stats is the total_stats, we don't need
  // it.
  for (size_t i = 0; i < pimpl->first_pass_stats.size() - 1; ++i) {
    double *buf_start = reinterpret_cast<double *>(&pimpl->first_pass_stats[i]);
    // We use - 1 here because the last member in FIRSTPASS_STATS is not double
    double *buf_end =
        buf_start + sizeof(pimpl->first_pass_stats[i]) / sizeof(*buf_end) - 1;
    std::vector<double> this_stats(buf_start, buf_end);
    output_stats.push_back(this_stats);
  }
  return output_stats;
}

void SimpleEncode::StartEncode() {
  assert(pimpl->first_pass_stats.size() > 0);
  vpx_rational_t frame_rate = make_vpx_rational(frame_rate_num, frame_rate_den);
  VP9EncoderConfig oxcf = vp9_get_encoder_config(
      frame_width, frame_height, frame_rate, target_bitrate, VPX_RC_LAST_PASS);
  vpx_fixed_buf_t stats;
  stats.buf = pimpl->first_pass_stats.data();
  stats.sz =
      sizeof(pimpl->first_pass_stats[0]) * pimpl->first_pass_stats.size();

  vp9_set_first_pass_stats(&oxcf, &stats);
  assert(pimpl->cpi == NULL);
  pimpl->cpi = init_encoder(&oxcf, pimpl->img_fmt);
  vpx_img_alloc(&pimpl->tmp_img, pimpl->img_fmt, frame_width, frame_height, 1);
  rewind(file);
}

void SimpleEncode::EndEncode() {
  free_encoder(pimpl->cpi);
  pimpl->cpi = nullptr;
  vpx_img_free(&pimpl->tmp_img);
  rewind(file);
}

void SimpleEncode::EncodeFrame(EncodeFrameResult *encode_frame_result) {
  VP9_COMP *cpi = pimpl->cpi;
  struct lookahead_ctx *lookahead = cpi->lookahead;
  int use_highbitdepth = 0;
#if CONFIG_VP9_HIGHBITDEPTH
  use_highbitdepth = cpi->common.use_highbitdepth;
#endif
  // The lookahead's size is set to oxcf->lag_in_frames.
  // We want to fill lookahead to it's max capacity if possible so that the
  // encoder can construct alt ref frame in time.
  // In the other words, we hope vp9_get_compressed_data to encode a frame
  // every time in the function
  while (!vp9_lookahead_full(lookahead)) {
    // TODO(angiebird): Check whether we can move this file read logics to
    // lookahead
    if (img_read(&pimpl->tmp_img, file)) {
      int next_show_idx = vp9_lookahead_next_show_idx(lookahead);
      int64_t ts_start =
          timebase_units_to_ticks(&cpi->oxcf.g_timebase_in_ts, next_show_idx);
      int64_t ts_end = timebase_units_to_ticks(&cpi->oxcf.g_timebase_in_ts,
                                               next_show_idx + 1);
      YV12_BUFFER_CONFIG sd;
      image2yuvconfig(&pimpl->tmp_img, &sd);
      vp9_lookahead_push(lookahead, &sd, ts_start, ts_end, use_highbitdepth, 0);
    } else {
      break;
    }
  }
  assert(encode_frame_result->coding_data.get() == nullptr);
  const size_t max_coding_data_byte_size = frame_width * frame_height * 3;
  encode_frame_result->coding_data = std::move(
      std::unique_ptr<uint8_t[]>(new uint8_t[max_coding_data_byte_size]));
  int64_t time_stamp;
  int64_t time_end;
  int flush = 1;  // Make vp9_get_compressed_data encode a frame
  unsigned int frame_flags = 0;
  ENCODE_FRAME_RESULT encode_frame_info;
  vp9_get_compressed_data(cpi, &frame_flags,
                          &encode_frame_result->coding_data_byte_size,
                          encode_frame_result->coding_data.get(), &time_stamp,
                          &time_end, flush, &encode_frame_info);
  // vp9_get_compressed_data is expected to encode a frame every time, so the
  // data size should be greater than zero.
  assert(encode_frame_result->coding_data_byte_size > 0);
  assert(encode_frame_result->coding_data_byte_size <
         max_coding_data_byte_size);

  update_encode_frame_result(encode_frame_result, &encode_frame_info);
}

void SimpleEncode::EncodeFrameWithQuantizeIndex(
    EncodeFrameResult *encode_frame_result, int quantize_index) {
  encode_command_set_external_quantize_index(&pimpl->cpi->encode_command,
                                             quantize_index);
  EncodeFrame(encode_frame_result);
  encode_command_reset_external_quantize_index(&pimpl->cpi->encode_command);
}

int SimpleEncode::GetCodingFrameNum() {
  assert(pimpl->first_pass_stats.size() - 1 > 0);
  // These are the default settings for now.
  const int multi_layer_arf = 0;
  const int allow_alt_ref = 1;
  vpx_rational_t frame_rate = make_vpx_rational(frame_rate_num, frame_rate_den);
  const VP9EncoderConfig oxcf = vp9_get_encoder_config(
      frame_width, frame_height, frame_rate, target_bitrate, VPX_RC_LAST_PASS);
  FRAME_INFO frame_info = vp9_get_frame_info(&oxcf);
  FIRST_PASS_INFO first_pass_info;
  fps_init_first_pass_info(&first_pass_info, pimpl->first_pass_stats.data(),
                           num_frames);
  return vp9_get_coding_frame_num(&oxcf, &frame_info, &first_pass_info,
                                  multi_layer_arf, allow_alt_ref);
}

SimpleEncode::~SimpleEncode() {}
<commit_msg>Close the file that SimpleEncode opens in its ctor in its dtor.<commit_after>#include <vector>
#include "vp9/common/vp9_onyxc_int.h"
#include "vp9/vp9_iface_common.h"
#include "vp9/encoder/vp9_encoder.h"
#include "vp9/encoder/vp9_firstpass.h"
#include "vp9/simple_encode.h"
#include "vp9/vp9_cx_iface.h"

// TODO(angiebird): Merge this function with vpx_img_plane_width()
static int img_plane_width(const vpx_image_t *img, int plane) {
  if (plane > 0 && img->x_chroma_shift > 0)
    return (img->d_w + 1) >> img->x_chroma_shift;
  else
    return img->d_w;
}

// TODO(angiebird): Merge this function with vpx_img_plane_height()
static int img_plane_height(const vpx_image_t *img, int plane) {
  if (plane > 0 && img->y_chroma_shift > 0)
    return (img->d_h + 1) >> img->y_chroma_shift;
  else
    return img->d_h;
}

// TODO(angiebird): Merge this function with vpx_img_read()
static int img_read(vpx_image_t *img, FILE *file) {
  int plane;

  for (plane = 0; plane < 3; ++plane) {
    unsigned char *buf = img->planes[plane];
    const int stride = img->stride[plane];
    const int w = img_plane_width(img, plane) *
                  ((img->fmt & VPX_IMG_FMT_HIGHBITDEPTH) ? 2 : 1);
    const int h = img_plane_height(img, plane);
    int y;

    for (y = 0; y < h; ++y) {
      if (fread(buf, 1, w, file) != (size_t)w) return 0;
      buf += stride;
    }
  }

  return 1;
}

class SimpleEncode::impl {
 public:
  VP9_COMP *cpi;
  vpx_img_fmt_t img_fmt;
  vpx_image_t tmp_img;
  std::vector<FIRSTPASS_STATS> first_pass_stats;
};

static VP9_COMP *init_encoder(const VP9EncoderConfig *oxcf,
                              vpx_img_fmt_t img_fmt) {
  VP9_COMP *cpi;
  BufferPool *buffer_pool = (BufferPool *)vpx_calloc(1, sizeof(*buffer_pool));
  vp9_initialize_enc();
  cpi = vp9_create_compressor(oxcf, buffer_pool);
  vp9_update_compressor_with_img_fmt(cpi, img_fmt);
  return cpi;
}

static void free_encoder(VP9_COMP *cpi) {
  vpx_free(cpi->common.buffer_pool);
  vp9_remove_compressor(cpi);
}

static INLINE vpx_rational_t make_vpx_rational(int num, int den) {
  vpx_rational_t v;
  v.num = num;
  v.den = den;
  return v;
}

static INLINE FrameType
get_frame_type_from_update_type(FRAME_UPDATE_TYPE update_type) {
  // TODO(angiebird): Figure out if we need frame type other than key frame,
  // alternate reference and inter frame
  switch (update_type) {
    case KF_UPDATE: return kKeyFrame; break;
    case ARF_UPDATE: return kAlternateReference; break;
    default: return kInterFrame; break;
  }
}

static void update_encode_frame_result(
    EncodeFrameResult *encode_frame_result,
    const ENCODE_FRAME_RESULT *encode_frame_info) {
  encode_frame_result->coding_data_bit_size =
      encode_frame_result->coding_data_byte_size * 8;
  encode_frame_result->show_idx = encode_frame_info->show_idx;
  encode_frame_result->frame_type =
      get_frame_type_from_update_type(encode_frame_info->update_type);
  encode_frame_result->psnr = encode_frame_info->psnr;
  encode_frame_result->sse = encode_frame_info->sse;
  encode_frame_result->quantize_index = encode_frame_info->quantize_index;
}

SimpleEncode::SimpleEncode(int frame_width, int frame_height,
                           int frame_rate_num, int frame_rate_den,
                           int target_bitrate, int num_frames,
                           const char *infile_path)
    : pimpl{ std::unique_ptr<impl>(new impl()) } {
  this->frame_width = frame_width;
  this->frame_height = frame_height;
  this->frame_rate_num = frame_rate_num;
  this->frame_rate_den = frame_rate_den;
  this->target_bitrate = target_bitrate;
  this->num_frames = num_frames;
  // TODO(angirbid): Should we keep a file pointer here or keep the file_path?
  this->file = fopen(infile_path, "r");
  pimpl->cpi = NULL;
  pimpl->img_fmt = VPX_IMG_FMT_I420;
}

void SimpleEncode::ComputeFirstPassStats() {
  vpx_rational_t frame_rate = make_vpx_rational(frame_rate_num, frame_rate_den);
  const VP9EncoderConfig oxcf = vp9_get_encoder_config(
      frame_width, frame_height, frame_rate, target_bitrate, VPX_RC_FIRST_PASS);
  VP9_COMP *cpi = init_encoder(&oxcf, pimpl->img_fmt);
  struct lookahead_ctx *lookahead = cpi->lookahead;
  int i;
  int use_highbitdepth = 0;
#if CONFIG_VP9_HIGHBITDEPTH
  use_highbitdepth = cpi->common.use_highbitdepth;
#endif
  vpx_image_t img;
  vpx_img_alloc(&img, pimpl->img_fmt, frame_width, frame_height, 1);
  rewind(file);
  pimpl->first_pass_stats.clear();
  for (i = 0; i < num_frames; ++i) {
    assert(!vp9_lookahead_full(lookahead));
    if (img_read(&img, file)) {
      int next_show_idx = vp9_lookahead_next_show_idx(lookahead);
      int64_t ts_start =
          timebase_units_to_ticks(&oxcf.g_timebase_in_ts, next_show_idx);
      int64_t ts_end =
          timebase_units_to_ticks(&oxcf.g_timebase_in_ts, next_show_idx + 1);
      YV12_BUFFER_CONFIG sd;
      image2yuvconfig(&img, &sd);
      vp9_lookahead_push(lookahead, &sd, ts_start, ts_end, use_highbitdepth, 0);
      {
        int64_t time_stamp;
        int64_t time_end;
        int flush = 1;  // Make vp9_get_compressed_data process a frame
        size_t size;
        unsigned int frame_flags = 0;
        ENCODE_FRAME_RESULT encode_frame_info;
        // TODO(angiebird): Call vp9_first_pass directly
        vp9_get_compressed_data(cpi, &frame_flags, &size, NULL, &time_stamp,
                                &time_end, flush, &encode_frame_info);
        // vp9_get_compressed_data only generates first pass stats not
        // compresses data
        assert(size == 0);
      }
      pimpl->first_pass_stats.push_back(vp9_get_frame_stats(&cpi->twopass));
    }
  }
  vp9_end_first_pass(cpi);
  // TODO(angiebird): Store the total_stats apart form first_pass_stats
  pimpl->first_pass_stats.push_back(vp9_get_total_stats(&cpi->twopass));
  free_encoder(cpi);
  rewind(file);
  vpx_img_free(&img);
}

std::vector<std::vector<double>> SimpleEncode::ObserveFirstPassStats() {
  std::vector<std::vector<double>> output_stats;
  // TODO(angiebird): This function make several assumptions of
  // FIRSTPASS_STATS. 1) All elements in FIRSTPASS_STATS are double except the
  // last one. 2) The last entry of first_pass_stats is the total_stats.
  // Change the code structure, so that we don't have to make these assumptions

  // Note the last entry of first_pass_stats is the total_stats, we don't need
  // it.
  for (size_t i = 0; i < pimpl->first_pass_stats.size() - 1; ++i) {
    double *buf_start = reinterpret_cast<double *>(&pimpl->first_pass_stats[i]);
    // We use - 1 here because the last member in FIRSTPASS_STATS is not double
    double *buf_end =
        buf_start + sizeof(pimpl->first_pass_stats[i]) / sizeof(*buf_end) - 1;
    std::vector<double> this_stats(buf_start, buf_end);
    output_stats.push_back(this_stats);
  }
  return output_stats;
}

void SimpleEncode::StartEncode() {
  assert(pimpl->first_pass_stats.size() > 0);
  vpx_rational_t frame_rate = make_vpx_rational(frame_rate_num, frame_rate_den);
  VP9EncoderConfig oxcf = vp9_get_encoder_config(
      frame_width, frame_height, frame_rate, target_bitrate, VPX_RC_LAST_PASS);
  vpx_fixed_buf_t stats;
  stats.buf = pimpl->first_pass_stats.data();
  stats.sz =
      sizeof(pimpl->first_pass_stats[0]) * pimpl->first_pass_stats.size();

  vp9_set_first_pass_stats(&oxcf, &stats);
  assert(pimpl->cpi == NULL);
  pimpl->cpi = init_encoder(&oxcf, pimpl->img_fmt);
  vpx_img_alloc(&pimpl->tmp_img, pimpl->img_fmt, frame_width, frame_height, 1);
  rewind(file);
}

void SimpleEncode::EndEncode() {
  free_encoder(pimpl->cpi);
  pimpl->cpi = nullptr;
  vpx_img_free(&pimpl->tmp_img);
  rewind(file);
}

void SimpleEncode::EncodeFrame(EncodeFrameResult *encode_frame_result) {
  VP9_COMP *cpi = pimpl->cpi;
  struct lookahead_ctx *lookahead = cpi->lookahead;
  int use_highbitdepth = 0;
#if CONFIG_VP9_HIGHBITDEPTH
  use_highbitdepth = cpi->common.use_highbitdepth;
#endif
  // The lookahead's size is set to oxcf->lag_in_frames.
  // We want to fill lookahead to it's max capacity if possible so that the
  // encoder can construct alt ref frame in time.
  // In the other words, we hope vp9_get_compressed_data to encode a frame
  // every time in the function
  while (!vp9_lookahead_full(lookahead)) {
    // TODO(angiebird): Check whether we can move this file read logics to
    // lookahead
    if (img_read(&pimpl->tmp_img, file)) {
      int next_show_idx = vp9_lookahead_next_show_idx(lookahead);
      int64_t ts_start =
          timebase_units_to_ticks(&cpi->oxcf.g_timebase_in_ts, next_show_idx);
      int64_t ts_end = timebase_units_to_ticks(&cpi->oxcf.g_timebase_in_ts,
                                               next_show_idx + 1);
      YV12_BUFFER_CONFIG sd;
      image2yuvconfig(&pimpl->tmp_img, &sd);
      vp9_lookahead_push(lookahead, &sd, ts_start, ts_end, use_highbitdepth, 0);
    } else {
      break;
    }
  }
  assert(encode_frame_result->coding_data.get() == nullptr);
  const size_t max_coding_data_byte_size = frame_width * frame_height * 3;
  encode_frame_result->coding_data = std::move(
      std::unique_ptr<uint8_t[]>(new uint8_t[max_coding_data_byte_size]));
  int64_t time_stamp;
  int64_t time_end;
  int flush = 1;  // Make vp9_get_compressed_data encode a frame
  unsigned int frame_flags = 0;
  ENCODE_FRAME_RESULT encode_frame_info;
  vp9_get_compressed_data(cpi, &frame_flags,
                          &encode_frame_result->coding_data_byte_size,
                          encode_frame_result->coding_data.get(), &time_stamp,
                          &time_end, flush, &encode_frame_info);
  // vp9_get_compressed_data is expected to encode a frame every time, so the
  // data size should be greater than zero.
  assert(encode_frame_result->coding_data_byte_size > 0);
  assert(encode_frame_result->coding_data_byte_size <
         max_coding_data_byte_size);

  update_encode_frame_result(encode_frame_result, &encode_frame_info);
}

void SimpleEncode::EncodeFrameWithQuantizeIndex(
    EncodeFrameResult *encode_frame_result, int quantize_index) {
  encode_command_set_external_quantize_index(&pimpl->cpi->encode_command,
                                             quantize_index);
  EncodeFrame(encode_frame_result);
  encode_command_reset_external_quantize_index(&pimpl->cpi->encode_command);
}

int SimpleEncode::GetCodingFrameNum() {
  assert(pimpl->first_pass_stats.size() - 1 > 0);
  // These are the default settings for now.
  const int multi_layer_arf = 0;
  const int allow_alt_ref = 1;
  vpx_rational_t frame_rate = make_vpx_rational(frame_rate_num, frame_rate_den);
  const VP9EncoderConfig oxcf = vp9_get_encoder_config(
      frame_width, frame_height, frame_rate, target_bitrate, VPX_RC_LAST_PASS);
  FRAME_INFO frame_info = vp9_get_frame_info(&oxcf);
  FIRST_PASS_INFO first_pass_info;
  fps_init_first_pass_info(&first_pass_info, pimpl->first_pass_stats.data(),
                           num_frames);
  return vp9_get_coding_frame_num(&oxcf, &frame_info, &first_pass_info,
                                  multi_layer_arf, allow_alt_ref);
}

SimpleEncode::~SimpleEncode() {
  if (this->file != NULL) {
    fclose(this->file);
  }
}
<|endoftext|>


<commit_before>#pragma once

namespace beluga
{
    enum http_methods
    {
	GET,
	POST,
	HEAD,
	PATCH,
	PUT,
	DELETE,
	CONNECT,
	OPTIONS,
	TRACE,
    };
}
<commit_msg>added missing http prefix<commit_after>#pragma once

namespace beluga
{
    enum http_methods
    {
	HTTP_GET,
	HTTP_POST,
	HTTP_HEAD,
	HTTP_PATCH,
	HTTP_PUT,
	HTTP_DELETE,
	HTTP_CONNECT,
	HTTP_OPTIONS,
	HTTP_TRACE,
    };
}
<|endoftext|>


<commit_before>#include <stdio.h>
#include <stdint.h>
#include <assert.h>
#include <stdlib.h>
#include <map>
#include <vector>
#include <string>
#include <iostream>

using std::string;
using std::map;
using std::vector;

typedef uint32_t Id;

struct Packet {
    Id id, parent;
    uint8_t event, type, bits, width, value_idx, num_int_args;
    char name[17];
    uint8_t payload[4096-32]; // Not all of this will be used, but this is the max possible size.

    size_t value_bytes() const {
        size_t bytes_per_elem = 1;
        while (bytes_per_elem*8 < bits) bytes_per_elem <<= 1;
        return bytes_per_elem * width;
    }

    size_t int_args_bytes() const {
        return sizeof(int) * num_int_args;
    }

    size_t payload_bytes() const {
        return value_bytes() + int_args_bytes();
    }

    // Grab a packet from stdin. Returns false when stdin closes.
    bool read_from_stdin() {
        if (!read_stdin(this, 32)) {
            return false;
        }
        assert(read_stdin(payload, payload_bytes()) &&
               "Unexpected EOF mid-packet");
        return true;
    }

private:
    bool read_stdin(void *d, ssize_t size) {
        uint8_t *dst = (uint8_t *)d;
        if (!size) return true;
        while (1) {
            ssize_t s = read(0, dst, size);
            if (s == 0) {
                // EOF
                return false;
            } else if (s < 0) {
                perror("Failed during read");
                exit(-1);
                return 0;
            } else if (s == size) {
                return true;
            }
            size -= s;
            dst += s;
        }
    }
};

class Point {
    vector<int> p;
public:
    Point(int num_int_args, const int *int_args) {
        p.insert(p.end(), int_args, int_args + num_int_args);
    }

    Point(const vector<int> &v) : p(v) {
    }

    Point() {}

    int operator[](int x) const {
        return p[x];
    }

    int &operator[](int x) {
        return p[x];
    }

    int dimensions() const {
        return (int)p.size();
    }

    bool operator<(const Point &other) const {
        for (size_t i = 0; i < p.size(); i++) {
            if (p[i] < other[i]) return true;
            if (p[i] > other[i]) return false;
        }
        return false;
    }
};

struct Box {
    Point top_left;
    Point bottom_right;

    Box() {}

    Box(const Point &tl, const Point &br) : top_left(tl), bottom_right(br) {}

    Box(int num_int_args, int *int_args) {
        vector<int> tl, br;
        for (int i = 0; i < num_int_args/2; i++) {
            tl.push_back(int_args[i*2]);
            br.push_back(int_args[i*2] + int_args[i*2+1] - 1);
        }
        top_left = Point(tl);
        bottom_right = Point(br);
    }

    int dimensions() const {
        return top_left.dimensions();
    }

    void include(const Point &p) {
        if (dimensions() == 0) {
            top_left = p;
            bottom_right = p;
        } else {
            assert(p.dimensions() == top_left.dimensions());
            assert(p.dimensions() == bottom_right.dimensions());
            for (int i = 0; i < dimensions(); i++) {
                top_left[i] = std::min(top_left[i], p[i]);
                bottom_right[i] = std::max(bottom_right[i], p[i]);
            }
        }
    }

    void include(const Box &b) {
        include(b.top_left);
        include(b.bottom_right);
    }

    bool contains(const Point &p) const {
        assert(p.dimensions() == top_left.dimensions());
        assert(p.dimensions() == bottom_right.dimensions());
        for (int i = 0; i < p.dimensions(); i++) {
            if (top_left[i] > p[i]) return false;
            if (bottom_right[i] < p[i]) return false;
        }
        return true;
    }

    bool contains(const Box &b) const {
        return contains(b.top_left) && contains(b.bottom_right);
    }

};

class Count {
    size_t val;

public:
    Count() : val(0) {}

    void operator++(int) {
        val++;
    }

    void operator+=(int x) {
        val += x;
    }

    void operator+=(const Count &x) {
        val += x.val;
    }

    size_t value() const {
        return val;
    }

};

struct Production {
    enum {Producing, Updating, Consuming} state;

    Box region;

    void load(Count clock, const Packet &p) {
        assert(state == Updating || state == Consuming);
    }

    void store(Count clock, const Packet &p) {
        assert(state == Producing || state == Updating);
    }
};

struct Realization {
    map<Id, Production *> productions;

    Box region;

    struct PointState {
        size_t last_load, last_store;
        PointState() : last_load(0), last_store(0) {}
    };
    map<Point, PointState> state_map;

    void load(Count clock, const Packet &p) {
        Production *prod = productions[p.parent];
        assert(prod && "Load without a parent");
        prod->load(clock, p);
    }

    void store(Count clock, const Packet &p) {
        Production *prod = productions[p.parent];
        assert(prod && "Store without a parent");
        prod->store(clock, p);
    }

    void produce(Count clock, const Packet &p) {
        Production *prod = new Production;
        productions[p.id] = prod;
        prod->state = Production::Producing;
    }

    void update(Count clock, const Packet &p) {
        Production *prod = productions[p.parent];
        assert(prod && "Update without a parent");
        prod->state = Production::Updating;
    }

    void consume(Count clock, const Packet &p) {
        Production *prod = productions[p.parent];
        assert(prod && "Consume without a parent");
        prod->state = Production::Consuming;
    }

    void end_consume(Count clock, const Packet &p) {
        Production *prod = productions[p.parent];
        assert(prod && "Consume without a parent");
        // Retrieve stats
        delete prod;
        productions.erase(p.parent);
    }

};

struct FuncStats {
    map<Id, Realization *> realizations;

    Count loads, stores;

    FuncStats() {}

    void load(Count clock, const Packet &p) {
        Realization *r = realizations[p.parent];
        assert(r && "Load without a parent");
        r->load(clock, p);
        loads++;
    }

    void store(Count clock, const Packet &p) {
        Realization *r = realizations[p.parent];
        assert(r && "Store without a parent");
        r->store(clock, p);
        stores++;
    }

    void produce(Count clock, const Packet &p) {
        Realization *r = realizations[p.parent];
        assert(r && "Produce without a parent");
        realizations[p.id] = r;
        r->produce(clock, p);
    }

    void update(Count clock, const Packet &p) {
        Realization *r = realizations[p.parent];
        assert(r && "Update without a parent");
        r->update(clock, p);
    }

    void consume(Count clock, const Packet &p) {
        Realization *r = realizations[p.parent];
        assert(r && "Consume without a parent");
        r->consume(clock, p);
    }

    void end_consume(Count clock, const Packet &p) {
        Realization *r = realizations[p.parent];
        assert(r && "Update without a parent");
        r->end_consume(clock, p);
        realizations.erase(p.parent);
    }

    void begin_realize(Count clock, const Packet &p) {
        Realization *r = new Realization;
        realizations[p.id] = r;
    }

    void end_realize(Count clock, const Packet &p) {
        Realization *r = realizations[p.parent];
        // Aggregate stats
        delete r;
        realizations.erase(p.parent);
    }

    void report() const {
        std::cout << " stores:" << stores.value() << '\n';
        std::cout << " loads:" << loads.value() << '\n';
    }
};

int main(int argc, char **argv) {
    assert(sizeof(Packet) == 4096);

    map<string, FuncStats> funcs;

    Count clock;

    while (1) {
        Packet p;
        if (!p.read_from_stdin()) {
            break;
        }

        //printf("Packet header: %u %u %d %d %d %d %d %d %s\n", p.id, p.parent, p.event, p.type, p.bits, p.width, p.value_idx, p.num_int_args, p.name);

        FuncStats &f = funcs[p.name];

        switch (p.event) {
        case 0:
            f.load(clock, p);
            clock += p.value_bytes();
            break;
        case 1:
            f.store(clock, p);
            clock += p.value_bytes();
            break;
        case 2: // begin realization
            f.begin_realize(clock, p);
            break;
        case 3: // end realization
            f.end_realize(clock, p);
            break;
        case 4: // produce
            f.produce(clock, p);
            break;
        case 5: // update
            f.update(clock, p);
            break;
        case 6: // consume
            f.consume(clock, p);
            break;
        case 7: // end consume
            f.end_consume(clock, p);
            break;
        default:
            exit(-1);
        }
    }

    for (map<string, FuncStats>::iterator iter = funcs.begin();
         iter != funcs.end(); ++iter) {
        std::cout << "Function " << iter->first << ":\n";
        iter->second.report();
    }

    return 0;
}
<commit_msg>Added unistd to HalideTrace<commit_after>#include <stdio.h>
#include <stdint.h>
#include <assert.h>
#include <stdlib.h>
#include <map>
#include <vector>
#include <string>
#include <iostream>
#include <unistd.h>

using std::string;
using std::map;
using std::vector;

typedef uint32_t Id;

struct Packet {
    Id id, parent;
    uint8_t event, type, bits, width, value_idx, num_int_args;
    char name[17];
    uint8_t payload[4096-32]; // Not all of this will be used, but this is the max possible size.

    size_t value_bytes() const {
        size_t bytes_per_elem = 1;
        while (bytes_per_elem*8 < bits) bytes_per_elem <<= 1;
        return bytes_per_elem * width;
    }

    size_t int_args_bytes() const {
        return sizeof(int) * num_int_args;
    }

    size_t payload_bytes() const {
        return value_bytes() + int_args_bytes();
    }

    // Grab a packet from stdin. Returns false when stdin closes.
    bool read_from_stdin() {
        if (!read_stdin(this, 32)) {
            return false;
        }
        assert(read_stdin(payload, payload_bytes()) &&
               "Unexpected EOF mid-packet");
        return true;
    }

private:
    bool read_stdin(void *d, ssize_t size) {
        uint8_t *dst = (uint8_t *)d;
        if (!size) return true;
        while (1) {
            ssize_t s = read(0, dst, size);
            if (s == 0) {
                // EOF
                return false;
            } else if (s < 0) {
                perror("Failed during read");
                exit(-1);
                return 0;
            } else if (s == size) {
                return true;
            }
            size -= s;
            dst += s;
        }
    }
};

class Point {
    vector<int> p;
public:
    Point(int num_int_args, const int *int_args) {
        p.insert(p.end(), int_args, int_args + num_int_args);
    }

    Point(const vector<int> &v) : p(v) {
    }

    Point() {}

    int operator[](int x) const {
        return p[x];
    }

    int &operator[](int x) {
        return p[x];
    }

    int dimensions() const {
        return (int)p.size();
    }

    bool operator<(const Point &other) const {
        for (size_t i = 0; i < p.size(); i++) {
            if (p[i] < other[i]) return true;
            if (p[i] > other[i]) return false;
        }
        return false;
    }
};

struct Box {
    Point top_left;
    Point bottom_right;

    Box() {}

    Box(const Point &tl, const Point &br) : top_left(tl), bottom_right(br) {}

    Box(int num_int_args, int *int_args) {
        vector<int> tl, br;
        for (int i = 0; i < num_int_args/2; i++) {
            tl.push_back(int_args[i*2]);
            br.push_back(int_args[i*2] + int_args[i*2+1] - 1);
        }
        top_left = Point(tl);
        bottom_right = Point(br);
    }

    int dimensions() const {
        return top_left.dimensions();
    }

    void include(const Point &p) {
        if (dimensions() == 0) {
            top_left = p;
            bottom_right = p;
        } else {
            assert(p.dimensions() == top_left.dimensions());
            assert(p.dimensions() == bottom_right.dimensions());
            for (int i = 0; i < dimensions(); i++) {
                top_left[i] = std::min(top_left[i], p[i]);
                bottom_right[i] = std::max(bottom_right[i], p[i]);
            }
        }
    }

    void include(const Box &b) {
        include(b.top_left);
        include(b.bottom_right);
    }

    bool contains(const Point &p) const {
        assert(p.dimensions() == top_left.dimensions());
        assert(p.dimensions() == bottom_right.dimensions());
        for (int i = 0; i < p.dimensions(); i++) {
            if (top_left[i] > p[i]) return false;
            if (bottom_right[i] < p[i]) return false;
        }
        return true;
    }

    bool contains(const Box &b) const {
        return contains(b.top_left) && contains(b.bottom_right);
    }

};

class Count {
    size_t val;

public:
    Count() : val(0) {}

    void operator++(int) {
        val++;
    }

    void operator+=(int x) {
        val += x;
    }

    void operator+=(const Count &x) {
        val += x.val;
    }

    size_t value() const {
        return val;
    }

};

struct Production {
    enum {Producing, Updating, Consuming} state;

    Box region;

    void load(Count clock, const Packet &p) {
        assert(state == Updating || state == Consuming);
    }

    void store(Count clock, const Packet &p) {
        assert(state == Producing || state == Updating);
    }
};

struct Realization {
    map<Id, Production *> productions;

    Box region;

    struct PointState {
        size_t last_load, last_store;
        PointState() : last_load(0), last_store(0) {}
    };
    map<Point, PointState> state_map;

    void load(Count clock, const Packet &p) {
        Production *prod = productions[p.parent];
        assert(prod && "Load without a parent");
        prod->load(clock, p);
    }

    void store(Count clock, const Packet &p) {
        Production *prod = productions[p.parent];
        assert(prod && "Store without a parent");
        prod->store(clock, p);
    }

    void produce(Count clock, const Packet &p) {
        Production *prod = new Production;
        productions[p.id] = prod;
        prod->state = Production::Producing;
    }

    void update(Count clock, const Packet &p) {
        Production *prod = productions[p.parent];
        assert(prod && "Update without a parent");
        prod->state = Production::Updating;
    }

    void consume(Count clock, const Packet &p) {
        Production *prod = productions[p.parent];
        assert(prod && "Consume without a parent");
        prod->state = Production::Consuming;
    }

    void end_consume(Count clock, const Packet &p) {
        Production *prod = productions[p.parent];
        assert(prod && "Consume without a parent");
        // Retrieve stats
        delete prod;
        productions.erase(p.parent);
    }

};

struct FuncStats {
    map<Id, Realization *> realizations;

    Count loads, stores;

    FuncStats() {}

    void load(Count clock, const Packet &p) {
        Realization *r = realizations[p.parent];
        assert(r && "Load without a parent");
        r->load(clock, p);
        loads++;
    }

    void store(Count clock, const Packet &p) {
        Realization *r = realizations[p.parent];
        assert(r && "Store without a parent");
        r->store(clock, p);
        stores++;
    }

    void produce(Count clock, const Packet &p) {
        Realization *r = realizations[p.parent];
        assert(r && "Produce without a parent");
        realizations[p.id] = r;
        r->produce(clock, p);
    }

    void update(Count clock, const Packet &p) {
        Realization *r = realizations[p.parent];
        assert(r && "Update without a parent");
        r->update(clock, p);
    }

    void consume(Count clock, const Packet &p) {
        Realization *r = realizations[p.parent];
        assert(r && "Consume without a parent");
        r->consume(clock, p);
    }

    void end_consume(Count clock, const Packet &p) {
        Realization *r = realizations[p.parent];
        assert(r && "Update without a parent");
        r->end_consume(clock, p);
        realizations.erase(p.parent);
    }

    void begin_realize(Count clock, const Packet &p) {
        Realization *r = new Realization;
        realizations[p.id] = r;
    }

    void end_realize(Count clock, const Packet &p) {
        Realization *r = realizations[p.parent];
        // Aggregate stats
        delete r;
        realizations.erase(p.parent);
    }

    void report() const {
        std::cout << " stores:" << stores.value() << '\n';
        std::cout << " loads:" << loads.value() << '\n';
    }
};

int main(int argc, char **argv) {
    assert(sizeof(Packet) == 4096);

    map<string, FuncStats> funcs;

    Count clock;

    while (1) {
        Packet p;
        if (!p.read_from_stdin()) {
            break;
        }

        //printf("Packet header: %u %u %d %d %d %d %d %d %s\n", p.id, p.parent, p.event, p.type, p.bits, p.width, p.value_idx, p.num_int_args, p.name);

        FuncStats &f = funcs[p.name];

        switch (p.event) {
        case 0:
            f.load(clock, p);
            clock += p.value_bytes();
            break;
        case 1:
            f.store(clock, p);
            clock += p.value_bytes();
            break;
        case 2: // begin realization
            f.begin_realize(clock, p);
            break;
        case 3: // end realization
            f.end_realize(clock, p);
            break;
        case 4: // produce
            f.produce(clock, p);
            break;
        case 5: // update
            f.update(clock, p);
            break;
        case 6: // consume
            f.consume(clock, p);
            break;
        case 7: // end consume
            f.end_consume(clock, p);
            break;
        default:
            exit(-1);
        }
    }

    for (map<string, FuncStats>::iterator iter = funcs.begin();
         iter != funcs.end(); ++iter) {
        std::cout << "Function " << iter->first << ":\n";
        iter->second.report();
    }

    return 0;
}
<|endoftext|>


<commit_before>/*************************************************************************
 *
 *  $RCSfile: xfactory.hxx,v $
 *
 *  $Revision: 1.5 $
 *
 *  last change: $Author: hr $ $Date: 2004-05-10 17:51:58 $
 *
 *  The Contents of this file are made available subject to the terms of
 *  either of the following licenses
 *
 *         - GNU Lesser General Public License Version 2.1
 *         - Sun Industry Standards Source License Version 1.1
 *
 *  Sun Microsystems Inc., October, 2000
 *
 *  GNU Lesser General Public License Version 2.1
 *  =============================================
 *  Copyright 2000 by Sun Microsystems, Inc.
 *  901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public
 *  License version 2.1, as published by the Free Software Foundation.
 *
 *  This library is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *  Lesser General Public License for more details.
 *
 *  You should have received a copy of the GNU Lesser General Public
 *  License along with this library; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *  MA  02111-1307  USA
 *
 *
 *  Sun Industry Standards Source License Version 1.1
 *  =================================================
 *  The contents of this file are subject to the Sun Industry Standards
 *  Source License Version 1.1 (the "License"); You may not use this file
 *  except in compliance with the License. You may obtain a copy of the
 *  License at http://www.openoffice.org/license.html.
 *
 *  Software provided under this License is provided on an "AS IS" basis,
 *  WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
 *  WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
 *  MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
 *  See the License for the specific provisions governing your rights and
 *  obligations concerning the Software.
 *
 *  The Initial Developer of the Original Code is: Sun Microsystems, Inc.
 *
 *  Copyright: 2000 by Sun Microsystems, Inc.
 *
 *  All Rights Reserved.
 *
 *  Contributor(s): _______________________________________
 *
 *
 ************************************************************************/

#ifndef __XFACTORY_HXX_
#define __XFACTORY_HXX_

#ifndef _COM_SUN_STAR_EMBED_XEMBEDOBJECTCREATOR_HPP_
#include <com/sun/star/embed/XEmbedObjectCreator.hpp>
#endif
#ifndef _COM_SUN_STAR_EMBED_XEMBEDOBJECTFACTORY_HPP_
#include <com/sun/star/embed/XEmbedObjectFactory.hpp>
#endif
#ifndef _COM_SUN_STAR_EMBED_XLINKCREATOR_HPP_
#include <com/sun/star/embed/XLinkCreator.hpp>
#endif
#ifndef _COM_SUN_STAR_EMBED_XLINKFACTORY_HPP_
#include <com/sun/star/embed/XLinkFactory.hpp>
#endif

#ifndef _COM_SUN_STAR_LANG_XSERVICEINFO_HPP_
#include <com/sun/star/lang/XServiceInfo.hpp>
#endif

#ifndef _CPPUHELPER_IMPLBASE5_HXX_
#include <cppuhelper/implbase5.hxx>
#endif

class OOoEmbeddedObjectFactory : public ::cppu::WeakImplHelper5<
                                                ::com::sun::star::embed::XEmbedObjectCreator,
                                                ::com::sun::star::embed::XEmbedObjectFactory,
                                                ::com::sun::star::embed::XLinkCreator,
                                                ::com::sun::star::embed::XLinkFactory,
                                                ::com::sun::star::lang::XServiceInfo >
{
    ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory > m_xFactory;

public:
    OOoEmbeddedObjectFactory(
        const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory >& xFactory )
    : m_xFactory( xFactory )
    {
        OSL_ENSURE( xFactory.is(), "No service manager is provided!\n" );
    }

    static ::com::sun::star::uno::Sequence< ::rtl::OUString > SAL_CALL impl_staticGetSupportedServiceNames();

    static ::rtl::OUString SAL_CALL impl_staticGetImplementationName();

    static ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface > SAL_CALL
        impl_staticCreateSelfInstance(
            const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory >& xServiceManager );

    // XEmbedObjectCreator
    virtual ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface > SAL_CALL createInstanceInitNew( const ::com::sun::star::uno::Sequence< sal_Int8 >& aClassID, const ::rtl::OUString& aClassName, const ::com::sun::star::uno::Reference< ::com::sun::star::embed::XStorage >& xStorage, const ::rtl::OUString& sEntName, const ::com::sun::star::uno::Sequence< ::com::sun::star::beans::PropertyValue >& lObjArgs ) throw (::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::io::IOException, ::com::sun::star::uno::Exception, ::com::sun::star::uno::RuntimeException);
    virtual ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface > SAL_CALL createInstanceInitFromEntry( const ::com::sun::star::uno::Reference< ::com::sun::star::embed::XStorage >& xStorage, const ::rtl::OUString& sEntName, const ::com::sun::star::uno::Sequence< ::com::sun::star::beans::PropertyValue >& aMediaDescr, const ::com::sun::star::uno::Sequence< ::com::sun::star::beans::PropertyValue >& lObjArgs ) throw (::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::container::NoSuchElementException, ::com::sun::star::io::IOException, ::com::sun::star::uno::Exception, ::com::sun::star::uno::RuntimeException);
    virtual ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface > SAL_CALL createInstanceInitFromMediaDescriptor( const ::com::sun::star::uno::Reference< ::com::sun::star::embed::XStorage >& xStorage, const ::rtl::OUString& sEntName, const ::com::sun::star::uno::Sequence< ::com::sun::star::beans::PropertyValue >& aMediaDescr, const ::com::sun::star::uno::Sequence< ::com::sun::star::beans::PropertyValue >& lObjArgs ) throw (::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::io::IOException, ::com::sun::star::uno::Exception, ::com::sun::star::uno::RuntimeException);

    // XEmbedObjectFactory
    virtual ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface > SAL_CALL createInstanceUserInit( const ::com::sun::star::uno::Sequence< sal_Int8 >& aClassID, const ::rtl::OUString& aClassName, const ::com::sun::star::uno::Reference< ::com::sun::star::embed::XStorage >& xStorage, const ::rtl::OUString& sEntName, sal_Int32 nEntryConnectionMode, const ::com::sun::star::uno::Sequence< ::com::sun::star::beans::PropertyValue >& lArguments, const ::com::sun::star::uno::Sequence< ::com::sun::star::beans::PropertyValue >& lObjArgs ) throw (::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::io::IOException, ::com::sun::star::uno::Exception, ::com::sun::star::uno::RuntimeException);

    // XLinkCreator
    virtual ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface > SAL_CALL createInstanceLink( const ::com::sun::star::uno::Reference< ::com::sun::star::embed::XStorage >& xStorage, const ::rtl::OUString& sEntName, const ::com::sun::star::uno::Sequence< ::com::sun::star::beans::PropertyValue >& aMediaDescr, const ::com::sun::star::uno::Sequence< ::com::sun::star::beans::PropertyValue >& lObjArgs ) throw (::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::io::IOException, ::com::sun::star::uno::Exception, ::com::sun::star::uno::RuntimeException);

    // XLinkFactory
    virtual ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface > SAL_CALL createInstanceLinkUserInit( const ::com::sun::star::uno::Sequence< sal_Int8 >& aClassID, const ::rtl::OUString& aClassName, const ::com::sun::star::uno::Reference< ::com::sun::star::embed::XStorage >& xStorage, const ::rtl::OUString& sEntName, const ::com::sun::star::uno::Sequence< ::com::sun::star::beans::PropertyValue >& lArguments, const ::com::sun::star::uno::Sequence< ::com::sun::star::beans::PropertyValue >& lObjArgs ) throw (::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::io::IOException, ::com::sun::star::uno::Exception, ::com::sun::star::uno::RuntimeException);

    // XServiceInfo
    virtual ::rtl::OUString SAL_CALL getImplementationName() throw (::com::sun::star::uno::RuntimeException);
    virtual sal_Bool SAL_CALL supportsService( const ::rtl::OUString& ServiceName ) throw (::com::sun::star::uno::RuntimeException);
    virtual ::com::sun::star::uno::Sequence< ::rtl::OUString > SAL_CALL getSupportedServiceNames() throw (::com::sun::star::uno::RuntimeException);

};

#endif

<commit_msg>INTEGRATION: CWS mav09 (1.5.2); FILE MERGED 2004/06/18 14:18:12 mba 1.5.2.2: #i27773#: special objects implementation 2004/06/10 16:19:49 mav 1.5.2.1: #i27773# use configuration for conversion purposes<commit_after>/*************************************************************************
 *
 *  $RCSfile: xfactory.hxx,v $
 *
 *  $Revision: 1.6 $
 *
 *  last change: $Author: kz $ $Date: 2004-10-04 19:50:44 $
 *
 *  The Contents of this file are made available subject to the terms of
 *  either of the following licenses
 *
 *         - GNU Lesser General Public License Version 2.1
 *         - Sun Industry Standards Source License Version 1.1
 *
 *  Sun Microsystems Inc., October, 2000
 *
 *  GNU Lesser General Public License Version 2.1
 *  =============================================
 *  Copyright 2000 by Sun Microsystems, Inc.
 *  901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public
 *  License version 2.1, as published by the Free Software Foundation.
 *
 *  This library is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *  Lesser General Public License for more details.
 *
 *  You should have received a copy of the GNU Lesser General Public
 *  License along with this library; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *  MA  02111-1307  USA
 *
 *
 *  Sun Industry Standards Source License Version 1.1
 *  =================================================
 *  The contents of this file are subject to the Sun Industry Standards
 *  Source License Version 1.1 (the "License"); You may not use this file
 *  except in compliance with the License. You may obtain a copy of the
 *  License at http://www.openoffice.org/license.html.
 *
 *  Software provided under this License is provided on an "AS IS" basis,
 *  WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
 *  WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
 *  MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
 *  See the License for the specific provisions governing your rights and
 *  obligations concerning the Software.
 *
 *  The Initial Developer of the Original Code is: Sun Microsystems, Inc.
 *
 *  Copyright: 2000 by Sun Microsystems, Inc.
 *
 *  All Rights Reserved.
 *
 *  Contributor(s): _______________________________________
 *
 *
 ************************************************************************/

#ifndef __XFACTORY_HXX_
#define __XFACTORY_HXX_

#ifndef _COM_SUN_STAR_EMBED_XEMBEDOBJECTCREATOR_HPP_
#include <com/sun/star/embed/XEmbedObjectCreator.hpp>
#endif
#ifndef _COM_SUN_STAR_EMBED_XEMBEDOBJECTFACTORY_HPP_
#include <com/sun/star/embed/XEmbedObjectFactory.hpp>
#endif
#ifndef _COM_SUN_STAR_EMBED_XLINKCREATOR_HPP_
#include <com/sun/star/embed/XLinkCreator.hpp>
#endif
#ifndef _COM_SUN_STAR_EMBED_XLINKFACTORY_HPP_
#include <com/sun/star/embed/XLinkFactory.hpp>
#endif

#ifndef _COM_SUN_STAR_LANG_XSERVICEINFO_HPP_
#include <com/sun/star/lang/XServiceInfo.hpp>
#endif

#ifndef _CPPUHELPER_IMPLBASE2_HXX_
#include <cppuhelper/implbase2.hxx>
#endif
#ifndef _CPPUHELPER_IMPLBASE5_HXX_
#include <cppuhelper/implbase5.hxx>
#endif

#include <confighelper.hxx>

class OOoEmbeddedObjectFactory : public ::cppu::WeakImplHelper5<
                                                ::com::sun::star::embed::XEmbedObjectCreator,
                                                ::com::sun::star::embed::XEmbedObjectFactory,
                                                ::com::sun::star::embed::XLinkCreator,
                                                ::com::sun::star::embed::XLinkFactory,
                                                ::com::sun::star::lang::XServiceInfo >
{
    ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory > m_xFactory;

    ConfigurationHelper m_aConfigHelper;

public:
    OOoEmbeddedObjectFactory(
        const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory >& xFactory )
    : m_xFactory( xFactory )
    , m_aConfigHelper( xFactory )
    {
        OSL_ENSURE( xFactory.is(), "No service manager is provided!\n" );
    }

    static ::com::sun::star::uno::Sequence< ::rtl::OUString > SAL_CALL impl_staticGetSupportedServiceNames();

    static ::rtl::OUString SAL_CALL impl_staticGetImplementationName();

    static ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface > SAL_CALL
        impl_staticCreateSelfInstance(
            const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory >& xServiceManager );

    // XEmbedObjectCreator
    virtual ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface > SAL_CALL createInstanceInitNew( const ::com::sun::star::uno::Sequence< sal_Int8 >& aClassID, const ::rtl::OUString& aClassName, const ::com::sun::star::uno::Reference< ::com::sun::star::embed::XStorage >& xStorage, const ::rtl::OUString& sEntName, const ::com::sun::star::uno::Sequence< ::com::sun::star::beans::PropertyValue >& lObjArgs ) throw (::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::io::IOException, ::com::sun::star::uno::Exception, ::com::sun::star::uno::RuntimeException);
    virtual ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface > SAL_CALL createInstanceInitFromEntry( const ::com::sun::star::uno::Reference< ::com::sun::star::embed::XStorage >& xStorage, const ::rtl::OUString& sEntName, const ::com::sun::star::uno::Sequence< ::com::sun::star::beans::PropertyValue >& aMediaDescr, const ::com::sun::star::uno::Sequence< ::com::sun::star::beans::PropertyValue >& lObjArgs ) throw (::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::container::NoSuchElementException, ::com::sun::star::io::IOException, ::com::sun::star::uno::Exception, ::com::sun::star::uno::RuntimeException);
    virtual ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface > SAL_CALL createInstanceInitFromMediaDescriptor( const ::com::sun::star::uno::Reference< ::com::sun::star::embed::XStorage >& xStorage, const ::rtl::OUString& sEntName, const ::com::sun::star::uno::Sequence< ::com::sun::star::beans::PropertyValue >& aMediaDescr, const ::com::sun::star::uno::Sequence< ::com::sun::star::beans::PropertyValue >& lObjArgs ) throw (::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::io::IOException, ::com::sun::star::uno::Exception, ::com::sun::star::uno::RuntimeException);

    // XEmbedObjectFactory
    virtual ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface > SAL_CALL createInstanceUserInit( const ::com::sun::star::uno::Sequence< sal_Int8 >& aClassID, const ::rtl::OUString& aClassName, const ::com::sun::star::uno::Reference< ::com::sun::star::embed::XStorage >& xStorage, const ::rtl::OUString& sEntName, sal_Int32 nEntryConnectionMode, const ::com::sun::star::uno::Sequence< ::com::sun::star::beans::PropertyValue >& lArguments, const ::com::sun::star::uno::Sequence< ::com::sun::star::beans::PropertyValue >& lObjArgs ) throw (::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::io::IOException, ::com::sun::star::uno::Exception, ::com::sun::star::uno::RuntimeException);

    // XLinkCreator
    virtual ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface > SAL_CALL createInstanceLink( const ::com::sun::star::uno::Reference< ::com::sun::star::embed::XStorage >& xStorage, const ::rtl::OUString& sEntName, const ::com::sun::star::uno::Sequence< ::com::sun::star::beans::PropertyValue >& aMediaDescr, const ::com::sun::star::uno::Sequence< ::com::sun::star::beans::PropertyValue >& lObjArgs ) throw (::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::io::IOException, ::com::sun::star::uno::Exception, ::com::sun::star::uno::RuntimeException);

    // XLinkFactory
    virtual ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface > SAL_CALL createInstanceLinkUserInit( const ::com::sun::star::uno::Sequence< sal_Int8 >& aClassID, const ::rtl::OUString& aClassName, const ::com::sun::star::uno::Reference< ::com::sun::star::embed::XStorage >& xStorage, const ::rtl::OUString& sEntName, const ::com::sun::star::uno::Sequence< ::com::sun::star::beans::PropertyValue >& lArguments, const ::com::sun::star::uno::Sequence< ::com::sun::star::beans::PropertyValue >& lObjArgs ) throw (::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::io::IOException, ::com::sun::star::uno::Exception, ::com::sun::star::uno::RuntimeException);

    // XServiceInfo
    virtual ::rtl::OUString SAL_CALL getImplementationName() throw (::com::sun::star::uno::RuntimeException);
    virtual sal_Bool SAL_CALL supportsService( const ::rtl::OUString& ServiceName ) throw (::com::sun::star::uno::RuntimeException);
    virtual ::com::sun::star::uno::Sequence< ::rtl::OUString > SAL_CALL getSupportedServiceNames() throw (::com::sun::star::uno::RuntimeException);

};

class OOoSpecialEmbeddedObjectFactory : public ::cppu::WeakImplHelper2<
                                                ::com::sun::star::embed::XEmbedObjectFactory,
                                                ::com::sun::star::lang::XServiceInfo >
{
    ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory > m_xFactory;

    ConfigurationHelper m_aConfigHelper;

public:
    OOoSpecialEmbeddedObjectFactory(
        const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory >& xFactory )
    : m_xFactory( xFactory )
    , m_aConfigHelper( xFactory )
    {
        OSL_ENSURE( xFactory.is(), "No service manager is provided!\n" );
    }

    static ::com::sun::star::uno::Sequence< ::rtl::OUString > SAL_CALL impl_staticGetSupportedServiceNames();

    static ::rtl::OUString SAL_CALL impl_staticGetImplementationName();

    static ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface > SAL_CALL
        impl_staticCreateSelfInstance(
            const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory >& xServiceManager );

    // XEmbedObjectFactory
    virtual ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface > SAL_CALL createInstanceUserInit( const ::com::sun::star::uno::Sequence< sal_Int8 >& aClassID, const ::rtl::OUString& aClassName, const ::com::sun::star::uno::Reference< ::com::sun::star::embed::XStorage >& xStorage, const ::rtl::OUString& sEntName, sal_Int32 nEntryConnectionMode, const ::com::sun::star::uno::Sequence< ::com::sun::star::beans::PropertyValue >& lArguments, const ::com::sun::star::uno::Sequence< ::com::sun::star::beans::PropertyValue >& lObjArgs ) throw (::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::io::IOException, ::com::sun::star::uno::Exception, ::com::sun::star::uno::RuntimeException);

    // XServiceInfo
    virtual ::rtl::OUString SAL_CALL getImplementationName() throw (::com::sun::star::uno::RuntimeException);
    virtual sal_Bool SAL_CALL supportsService( const ::rtl::OUString& ServiceName ) throw (::com::sun::star::uno::RuntimeException);
    virtual ::com::sun::star::uno::Sequence< ::rtl::OUString > SAL_CALL getSupportedServiceNames() throw (::com::sun::star::uno::RuntimeException);
};

#endif

<|endoftext|>


<commit_before>/*****************************************************************************
 *
 * This file is part of Mapnik (c++ mapping toolkit)
 *
 * Copyright (C) 2011 Artem Pavlenko
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 *
 *****************************************************************************/

#ifndef MAPNIK_IMAGE_COMPOSITING_HPP
#define MAPNIK_IMAGE_COMPOSITING_HPP

// agg
#include "agg_rendering_buffer.h"
#include "agg_rasterizer_scanline_aa.h"
#include "agg_scanline_u.h"
#include "agg_renderer_scanline.h"
#include "agg_pixfmt_rgba.h"

namespace mapnik
{

// Compositing modes
// http://www.w3.org/TR/2009/WD-SVGCompositing-20090430/

enum composite_mode_e
{
    clear = 1,
    src,
    dst,
    src_over,
    dst_over,
    src_in,
    dst_in,
    src_out,
    dst_out,
    src_atop,
    dst_atop,
    _xor,
    plus,
    minus,
    multiply,
    screen,
    overlay,
    darken,
    lighten,
    color_dodge,
    color_burn,
    hard_light,
    soft_light,
    difference,
    exclusion,
    contrast,
    invert,
    invert_rgb
};

template <typename T1, typename T2>
void composite(T1 & im, T2 & im2, composite_mode_e mode)
{
    typedef agg::rgba8 color;
    typedef agg::order_bgra order;
    typedef agg::pixel32_type pixel_type;
    typedef agg::comp_op_adaptor_rgba<color, order> blender_type;
    typedef agg::pixfmt_custom_blend_rgba<blender_type, agg::rendering_buffer> pixfmt_type;
    typedef agg::renderer_base<pixfmt_type> renderer_type;
    typedef agg::comp_op_adaptor_rgba<color, order> blender_type;
    typedef agg::renderer_base<pixfmt_type> renderer_type;

    agg::rendering_buffer source(im.getBytes(),im.width(),im.height(),im.width() * 4);
    agg::rendering_buffer mask(im2.getBytes(),im2.width(),im2.height(),im2.width() * 4);

    agg::pixfmt_custom_blend_rgba<blender_type, agg::rendering_buffer> pixf(source);
    agg::pixfmt_custom_blend_rgba<blender_type, agg::rendering_buffer> pixf_mask(mask);

    switch(mode)
    {
    case clear :
        pixf.comp_op(agg::comp_op_clear);
        break;
    case src:
        pixf.comp_op(agg::comp_op_src);
        break;
    case dst:
        pixf.comp_op(agg::comp_op_dst);
        break;
    case src_over:
        pixf.comp_op(agg::comp_op_src_over);
        break;
    case dst_over:
        pixf.comp_op(agg::comp_op_dst_over);
        break;
    case src_in:
        pixf.comp_op(agg::comp_op_src_in);
        break;
    case dst_in:
        pixf.comp_op(agg::comp_op_dst_in);
        break;
    case src_out:
        pixf.comp_op(agg::comp_op_src_out);
        break;
    case dst_out:
        pixf.comp_op(agg::comp_op_dst_out);
        break;
    case src_atop:
        pixf.comp_op(agg::comp_op_src_atop);
        break;
    case dst_atop:
        pixf.comp_op(agg::comp_op_dst_atop);
        break;
    case _xor:
        pixf.comp_op(agg::comp_op_xor);
        break;
    case plus:
        pixf.comp_op(agg::comp_op_plus);
        break;
    case minus:
        pixf.comp_op(agg::comp_op_minus);
        break;
    case multiply:
        pixf.comp_op(agg::comp_op_multiply);
        break;
    case screen:
        pixf.comp_op(agg::comp_op_screen);
        break;
    case overlay:
        pixf.comp_op(agg::comp_op_overlay);
        break;
    case darken:
        pixf.comp_op(agg::comp_op_darken);
        break;
    case lighten:
        pixf.comp_op(agg::comp_op_lighten);
        break;
    case color_dodge:
        pixf.comp_op(agg::comp_op_color_dodge);
        break;
    case color_burn:
        pixf.comp_op(agg::comp_op_color_burn);
        break;
    case hard_light:
        pixf.comp_op(agg::comp_op_hard_light);
        break;
    case soft_light:
        pixf.comp_op(agg::comp_op_soft_light);
        break;
    case difference:
        pixf.comp_op(agg::comp_op_difference);
        break;
    case exclusion:
        pixf.comp_op(agg::comp_op_exclusion);
        break;
    case contrast:
        pixf.comp_op(agg::comp_op_contrast);
        break;
    case invert:
        pixf.comp_op(agg::comp_op_invert);
        break;
    case invert_rgb:
        pixf.comp_op(agg::comp_op_invert_rgb);
        break;
    }
    renderer_type ren(pixf);
    agg::renderer_base<pixfmt_type> rb(pixf);
    rb.blend_from(pixf_mask,0,0,0,255);

}

}

#endif // MAPNIK_IMAGE_COMPOSITING_HPP
<commit_msg>+ always premultiply destination buffer for correct ops   (ensure no color component exceeds alpha channel)<commit_after>/*****************************************************************************
 *
 * This file is part of Mapnik (c++ mapping toolkit)
 *
 * Copyright (C) 2011 Artem Pavlenko
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 *
 *****************************************************************************/

#ifndef MAPNIK_IMAGE_COMPOSITING_HPP
#define MAPNIK_IMAGE_COMPOSITING_HPP

// agg
#include "agg_rendering_buffer.h"
#include "agg_rasterizer_scanline_aa.h"
#include "agg_scanline_u.h"
#include "agg_renderer_scanline.h"
#include "agg_pixfmt_rgba.h"

namespace mapnik
{

// Compositing modes
// http://www.w3.org/TR/2009/WD-SVGCompositing-20090430/

enum composite_mode_e
{
    clear = 1,
    src,
    dst,
    src_over,
    dst_over,
    src_in,
    dst_in,
    src_out,
    dst_out,
    src_atop,
    dst_atop,
    _xor,
    plus,
    minus,
    multiply,
    screen,
    overlay,
    darken,
    lighten,
    color_dodge,
    color_burn,
    hard_light,
    soft_light,
    difference,
    exclusion,
    contrast,
    invert,
    invert_rgb
};

template <typename T1, typename T2>
void composite(T1 & im, T2 & im2, composite_mode_e mode)
{
    typedef agg::rgba8 color;
    typedef agg::order_bgra order;
    typedef agg::pixel32_type pixel_type;
    typedef agg::comp_op_adaptor_rgba<color, order> blender_type;
    typedef agg::pixfmt_custom_blend_rgba<blender_type, agg::rendering_buffer> pixfmt_type;
    typedef agg::renderer_base<pixfmt_type> renderer_type;
    typedef agg::comp_op_adaptor_rgba<color, order> blender_type;
    typedef agg::renderer_base<pixfmt_type> renderer_type;

    agg::rendering_buffer source(im.getBytes(),im.width(),im.height(),im.width() * 4);
    agg::rendering_buffer mask(im2.getBytes(),im2.width(),im2.height(),im2.width() * 4);

    agg::pixfmt_custom_blend_rgba<blender_type, agg::rendering_buffer> pixf(source);
    pixf.premultiply();
    agg::pixfmt_custom_blend_rgba<blender_type, agg::rendering_buffer> pixf_mask(mask);

    switch(mode)
    {
    case clear :
        pixf.comp_op(agg::comp_op_clear);
        break;
    case src:
        pixf.comp_op(agg::comp_op_src);
        break;
    case dst:
        pixf.comp_op(agg::comp_op_dst);
        break;
    case src_over:
        pixf.comp_op(agg::comp_op_src_over);
        break;
    case dst_over:
        pixf.comp_op(agg::comp_op_dst_over);
        break;
    case src_in:
        pixf.comp_op(agg::comp_op_src_in);
        break;
    case dst_in:
        pixf.comp_op(agg::comp_op_dst_in);
        break;
    case src_out:
        pixf.comp_op(agg::comp_op_src_out);
        break;
    case dst_out:
        pixf.comp_op(agg::comp_op_dst_out);
        break;
    case src_atop:
        pixf.comp_op(agg::comp_op_src_atop);
        break;
    case dst_atop:
        pixf.comp_op(agg::comp_op_dst_atop);
        break;
    case _xor:
        pixf.comp_op(agg::comp_op_xor);
        break;
    case plus:
        pixf.comp_op(agg::comp_op_plus);
        break;
    case minus:
        pixf.comp_op(agg::comp_op_minus);
        break;
    case multiply:
        pixf.comp_op(agg::comp_op_multiply);
        break;
    case screen:
        pixf.comp_op(agg::comp_op_screen);
        break;
    case overlay:
        pixf.comp_op(agg::comp_op_overlay);
        break;
    case darken:
        pixf.comp_op(agg::comp_op_darken);
        break;
    case lighten:
        pixf.comp_op(agg::comp_op_lighten);
        break;
    case color_dodge:
        pixf.comp_op(agg::comp_op_color_dodge);
        break;
    case color_burn:
        pixf.comp_op(agg::comp_op_color_burn);
        break;
    case hard_light:
        pixf.comp_op(agg::comp_op_hard_light);
        break;
    case soft_light:
        pixf.comp_op(agg::comp_op_soft_light);
        break;
    case difference:
        pixf.comp_op(agg::comp_op_difference);
        break;
    case exclusion:
        pixf.comp_op(agg::comp_op_exclusion);
        break;
    case contrast:
        pixf.comp_op(agg::comp_op_contrast);
        break;
    case invert:
        pixf.comp_op(agg::comp_op_invert);
        break;
    case invert_rgb:
        pixf.comp_op(agg::comp_op_invert_rgb);
        break;
    }
    renderer_type ren(pixf);
    agg::renderer_base<pixfmt_type> rb(pixf);
    rb.blend_from(pixf_mask,0,0,0,255);

}

}

#endif // MAPNIK_IMAGE_COMPOSITING_HPP
<|endoftext|>


<commit_before>// Copyright (C) 2010-2013 Joshua Boyce.
// See the file COPYING for copying permission.

#pragma once

#include <array>
#include <string>
#include <vector>
#include <utility>
#include <utility>
#include <iterator>
#include <algorithm>

#include <hadesmem/detail/warning_disable_prefix.hpp>
#include <boost/filesystem.hpp>
#include <hadesmem/detail/warning_disable_suffix.hpp>

#include <windows.h>

#include <hadesmem/call.hpp>
#include <hadesmem/alloc.hpp>
#include <hadesmem/error.hpp>
#include <hadesmem/write.hpp>
#include <hadesmem/config.hpp>
#include <hadesmem/module.hpp>
#include <hadesmem/process.hpp>
#include <hadesmem/detail/assert.hpp>
#include <hadesmem/detail/self_path.hpp>
#include <hadesmem/detail/smart_handle.hpp>

namespace hadesmem
{

namespace detail
{

inline void ArgvQuote(std::wstring* command_line, std::wstring const& argument,
  bool force)
{
  // Unless we're told otherwise, don't quote unless we actually
  // need to do so (and hopefully avoid problems if programs won't
  // parse quotes properly).
  if (!force && !argument.empty() && argument.find_first_of(L" \t\n\v\"")
    == argument.npos)
  {
    command_line->append(argument);
  }
  else
  {
    command_line->push_back(L'"');

    for (auto it = std::begin(argument); ;++it)
    {
      std::size_t num_backslashes = 0;

      while (it != std::end(argument) && *it == L'\\')
      {
        ++it;
        ++num_backslashes;
      }

      if (it == std::end(argument))
      {
        // Escape all backslashes, but let the terminating
        // double quotation mark we add below be interpreted
        // as a metacharacter.
        command_line->append(num_backslashes * 2, L'\\');
        break;
      }
      else if (*it == L'"')
      {
        // Escape all backslashes and the following
        // double quotation mark.
        command_line->append(num_backslashes * 2 + 1, L'\\');
        command_line->push_back(*it);
      }
      else
      {
        // Backslashes aren't special here.
        command_line->append(num_backslashes, L'\\');
        command_line->push_back(*it);
      }
    }

    command_line->push_back(L'"');
  }
}

inline void ForceLdrInitializeThunk(DWORD proc_id)
{
  Process const process(proc_id);

  // This is used to generate a 'nullsub' function, which is called in
  // the context of the remote process in order to 'force' a call to
  // ntdll.dll!LdrInitializeThunk. This is necessary because module
  // enumeration will fail if LdrInitializeThunk has not been called,
  // and Injector::InjectDll (and the APIs it uses) depends on the
  // module enumeration APIs.
#if defined(HADESMEM_ARCH_X64)
  std::array<BYTE, 1> return_instr = { { 0xC3 } };
#elif defined(HADESMEM_ARCH_X86)
  std::array<BYTE, 3> return_instr = { { 0xC2, 0x04, 0x00 } };
#else
#error "[HadesMem] Unsupported architecture."
#endif

  Allocator const stub_remote(process, sizeof(return_instr));

  Write(process, stub_remote.GetBase(), return_instr);

  auto const stub_remote_pfn =
    reinterpret_cast<LPTHREAD_START_ROUTINE>(
    reinterpret_cast<DWORD_PTR>(stub_remote.GetBase()));

  detail::SmartHandle const remote_thread(::CreateRemoteThread(
    process.GetHandle(), nullptr, 0, stub_remote_pfn, nullptr, 0, nullptr));
  if (!remote_thread.GetHandle())
  {
    DWORD const last_error = ::GetLastError();
    HADESMEM_THROW_EXCEPTION(Error() <<
      ErrorString("Could not create remote thread.") <<
      ErrorCodeWinLast(last_error));
  }

  // TODO: Add a sensible and configurable timeout.
  if (::WaitForSingleObject(remote_thread.GetHandle(), INFINITE) !=
    WAIT_OBJECT_0)
  {
    DWORD const last_error = ::GetLastError();
    HADESMEM_THROW_EXCEPTION(Error() <<
      ErrorString("Could not wait for remote thread.") <<
      ErrorCodeWinLast(last_error));
  }
}

}

template <typename T>
class CallResult;

struct InjectFlags
{
  enum
  {
    kNone = 0,
    kPathResolution = 1 << 0,
    kAddToSearchOrder = 1 << 1,
    kKeepSuspended = 1 << 2,
    kInvalidFlagMaxValue = 1 << 3
  };
};

inline HMODULE InjectDll(Process const& process, std::wstring const& path,
  int flags)
{
  HADESMEM_ASSERT((flags & ~(InjectFlags::kInvalidFlagMaxValue - 1)) == 0);

   boost::filesystem::path path_real(path);

  bool const path_resolution = !!(flags & InjectFlags::kPathResolution);

  if (path_resolution && path_real.is_relative())
  {
    path_real = boost::filesystem::absolute(path_real,
      detail::GetSelfDirPath());
  }
  path_real.make_preferred();

  bool const add_path = !!(flags & InjectFlags::kAddToSearchOrder);
  if (add_path && path_real.is_relative())
  {
    HADESMEM_THROW_EXCEPTION(Error() <<
      ErrorString("Cannot modify search order unless an absolute path "
      "or path resolution is used."));
  }

  // Note: Only performing this check when path resolution is enabled,
  // because otherwise we would need to perform the check in the context
  // of the remote process, which is not possible to do without
  // introducing race conditions and other potential problems. So we just
  // let LoadLibraryW do the check for us.
  if (path_resolution && !boost::filesystem::exists(path_real))
  {
    HADESMEM_THROW_EXCEPTION(Error() <<
      ErrorString("Could not find module file."));
  }

  detail::ForceLdrInitializeThunk(process.GetId());

  std::wstring const path_string(path_real.native());
  std::size_t const path_buf_size = (path_string.size() + 1) *
    sizeof(wchar_t);

  Allocator const lib_file_remote(process, path_buf_size);
  WriteString(process, lib_file_remote.GetBase(), path_string);

  Module const kernel32_mod(process, L"kernel32.dll");
  auto const load_library = FindProcedure(kernel32_mod, "LoadLibraryExW");

  typedef HMODULE (LoadLibraryExFuncT)(LPCWSTR lpFileName, HANDLE hFile,
    DWORD dwFlags);
  auto const load_library_ret =
    Call<LoadLibraryExFuncT>(process, reinterpret_cast<FnPtr>(load_library),
    CallConv::kWinApi, static_cast<LPCWSTR>(lib_file_remote.GetBase()),
    nullptr, add_path ? LOAD_WITH_ALTERED_SEARCH_PATH : 0UL);
  if (!load_library_ret.GetReturnValue())
  {
    HADESMEM_THROW_EXCEPTION(Error() <<
      ErrorString("Call to LoadLibraryW in remote process failed.") <<
      ErrorCodeWinLast(load_library_ret.GetLastError()));
  }

  return load_library_ret.GetReturnValue();
}

inline void FreeDll(Process const& process, HMODULE module)
{
  Module const kernel32_mod(process, L"kernel32.dll");
  auto const free_library = FindProcedure(kernel32_mod, "FreeLibrary");

  typedef BOOL (FreeLibraryFuncT)(HMODULE hModule);
  auto const free_library_ret =
    Call<FreeLibraryFuncT>(process, reinterpret_cast<FnPtr>(free_library),
    CallConv::kWinApi, module);
  if (!free_library_ret.GetReturnValue())
  {
    HADESMEM_THROW_EXCEPTION(Error() <<
      ErrorString("Call to FreeLibrary in remote process failed.") <<
      ErrorCodeWinLast(free_library_ret.GetLastError()));
  }
}

// TODO: Configurable timeout.
inline CallResult<DWORD_PTR> CallExport(Process const& process, HMODULE module,
  std::string const& export_name)
{
  Module const module_remote(process, module);
  auto const export_ptr = FindProcedure(module_remote, export_name);

  return Call<DWORD_PTR()>(process, reinterpret_cast<FnPtr>(export_ptr),
    CallConv::kDefault);
}

class CreateAndInjectData
{
public:
  explicit CreateAndInjectData(Process const& process, HMODULE module,
    DWORD_PTR export_ret, DWORD export_last_error)
    : process_(process),
    module_(module),
    export_ret_(export_ret),
    export_last_error_(export_last_error)
  { }

  CreateAndInjectData(CreateAndInjectData const& other)
    : process_(other.process_),
    module_(other.module_),
    export_ret_(other.export_ret_),
    export_last_error_(other.export_last_error_)
  { }

  CreateAndInjectData& operator=(CreateAndInjectData const& other)
  {
    process_ = other.process_;
    module_ = other.module_;
    export_ret_ = other.export_ret_;
    export_last_error_ = other.export_last_error_;

    return *this;
  }

  CreateAndInjectData(CreateAndInjectData&& other) HADESMEM_NOEXCEPT
    : process_(std::move(other.process_)),
    module_(other.module_),
    export_ret_(other.export_ret_),
    export_last_error_(other.export_last_error_)
  { }

  CreateAndInjectData& operator=(CreateAndInjectData&& other)
    HADESMEM_NOEXCEPT
  {
    process_ = std::move(other.process_);
    module_ = other.module_;
    export_ret_ = other.export_ret_;
    export_last_error_ = other.export_last_error_;

    return *this;
  }

  ~CreateAndInjectData() HADESMEM_NOEXCEPT
  { }

  Process GetProcess() const
  {
    return process_;
  }

  HMODULE GetModule() const HADESMEM_NOEXCEPT
  {
    return module_;
  }

  DWORD_PTR GetExportRet() const HADESMEM_NOEXCEPT
  {
    return export_ret_;
  }

  DWORD GetExportLastError() const HADESMEM_NOEXCEPT
  {
    return export_last_error_;
  }

private:
  Process process_;
  HMODULE module_;
  DWORD_PTR export_ret_;
  DWORD export_last_error_;
};

inline CreateAndInjectData CreateAndInject(
  std::wstring const& path,
  std::wstring const& work_dir,
  std::vector<std::wstring> const& args,
  std::wstring const& module,
  std::string const& export_name,
  int flags)
{
  boost::filesystem::path const path_real(path);

  std::wstring command_line;
  detail::ArgvQuote(&command_line, path_real.native(), false);
  std::for_each(std::begin(args), std::end(args),
    [&] (std::wstring const& arg)
  {
    command_line += L' ';
    detail::ArgvQuote(&command_line, arg, false);
  });
  std::vector<wchar_t> proc_args(std::begin(command_line),
    std::end(command_line));
  proc_args.push_back(L'\0');

  boost::filesystem::path work_dir_real;
  if (!work_dir.empty())
  {
    work_dir_real = work_dir;
  }
  else if (path_real.has_parent_path())
  {
    work_dir_real = path_real.parent_path();
  }
  else
  {
    work_dir_real = L"./";
  }

  STARTUPINFO start_info;
  ::ZeroMemory(&start_info, sizeof(start_info));
  start_info.cb = sizeof(start_info);
  PROCESS_INFORMATION proc_info;
  ::ZeroMemory(&proc_info, sizeof(proc_info));
  if (!::CreateProcess(path_real.c_str(), proc_args.data(), nullptr, nullptr,
    FALSE, CREATE_SUSPENDED | CREATE_UNICODE_ENVIRONMENT, nullptr,
    work_dir_real.c_str(), &start_info, &proc_info))
  {
    DWORD const last_error = ::GetLastError();
    HADESMEM_THROW_EXCEPTION(Error() <<
      ErrorString("CreateProcess failed.") <<
      ErrorCodeWinLast(last_error));
  }

  detail::SmartHandle const proc_handle(proc_info.hProcess);
  detail::SmartHandle const thread_handle(proc_info.hThread);

  try
  {
    Process const process(proc_info.dwProcessId);

    HMODULE const remote_module = InjectDll(process, module, flags);

    CallResult<DWORD_PTR> export_ret(0, 0);
    if (!export_name.empty())
    {
      // TODO: Configurable timeout.
      export_ret = CallExport(process, remote_module, export_name);
    }

    if (flags & InjectFlags::kKeepSuspended)
    {
      if (::ResumeThread(thread_handle.GetHandle()) == static_cast<DWORD>(-1))
      {
        DWORD const last_error = ::GetLastError();
        HADESMEM_THROW_EXCEPTION(Error() <<
          ErrorString("Could not resume process.") <<
          ErrorCodeWinLast(last_error) <<
          ErrorCodeWinRet(export_ret.GetReturnValue()) <<
          ErrorCodeWinOther(export_ret.GetLastError()));
      }
    }

    return CreateAndInjectData(process, remote_module,
      export_ret.GetReturnValue(), export_ret.GetLastError());
  }
  catch (std::exception const& /*e*/)
  {
    // Terminate process if injection failed, otherwise the 'zombie' process
    // would be leaked.
    ::TerminateProcess(proc_handle.GetHandle(), 0);

    throw;
  }
}

}
<commit_msg>* Fix whitespace.<commit_after>// Copyright (C) 2010-2013 Joshua Boyce.
// See the file COPYING for copying permission.

#pragma once

#include <array>
#include <string>
#include <vector>
#include <utility>
#include <utility>
#include <iterator>
#include <algorithm>

#include <hadesmem/detail/warning_disable_prefix.hpp>
#include <boost/filesystem.hpp>
#include <hadesmem/detail/warning_disable_suffix.hpp>

#include <windows.h>

#include <hadesmem/call.hpp>
#include <hadesmem/alloc.hpp>
#include <hadesmem/error.hpp>
#include <hadesmem/write.hpp>
#include <hadesmem/config.hpp>
#include <hadesmem/module.hpp>
#include <hadesmem/process.hpp>
#include <hadesmem/detail/assert.hpp>
#include <hadesmem/detail/self_path.hpp>
#include <hadesmem/detail/smart_handle.hpp>

namespace hadesmem
{

namespace detail
{

inline void ArgvQuote(std::wstring* command_line, std::wstring const& argument,
  bool force)
{
  // Unless we're told otherwise, don't quote unless we actually
  // need to do so (and hopefully avoid problems if programs won't
  // parse quotes properly).
  if (!force && !argument.empty() && argument.find_first_of(L" \t\n\v\"")
    == argument.npos)
  {
    command_line->append(argument);
  }
  else
  {
    command_line->push_back(L'"');

    for (auto it = std::begin(argument); ;++it)
    {
      std::size_t num_backslashes = 0;

      while (it != std::end(argument) && *it == L'\\')
      {
        ++it;
        ++num_backslashes;
      }

      if (it == std::end(argument))
      {
        // Escape all backslashes, but let the terminating
        // double quotation mark we add below be interpreted
        // as a metacharacter.
        command_line->append(num_backslashes * 2, L'\\');
        break;
      }
      else if (*it == L'"')
      {
        // Escape all backslashes and the following
        // double quotation mark.
        command_line->append(num_backslashes * 2 + 1, L'\\');
        command_line->push_back(*it);
      }
      else
      {
        // Backslashes aren't special here.
        command_line->append(num_backslashes, L'\\');
        command_line->push_back(*it);
      }
    }

    command_line->push_back(L'"');
  }
}

inline void ForceLdrInitializeThunk(DWORD proc_id)
{
  Process const process(proc_id);

  // This is used to generate a 'nullsub' function, which is called in
  // the context of the remote process in order to 'force' a call to
  // ntdll.dll!LdrInitializeThunk. This is necessary because module
  // enumeration will fail if LdrInitializeThunk has not been called,
  // and Injector::InjectDll (and the APIs it uses) depends on the
  // module enumeration APIs.
#if defined(HADESMEM_ARCH_X64)
  std::array<BYTE, 1> return_instr = { { 0xC3 } };
#elif defined(HADESMEM_ARCH_X86)
  std::array<BYTE, 3> return_instr = { { 0xC2, 0x04, 0x00 } };
#else
#error "[HadesMem] Unsupported architecture."
#endif

  Allocator const stub_remote(process, sizeof(return_instr));

  Write(process, stub_remote.GetBase(), return_instr);

  auto const stub_remote_pfn =
    reinterpret_cast<LPTHREAD_START_ROUTINE>(
    reinterpret_cast<DWORD_PTR>(stub_remote.GetBase()));

  detail::SmartHandle const remote_thread(::CreateRemoteThread(
    process.GetHandle(), nullptr, 0, stub_remote_pfn, nullptr, 0, nullptr));
  if (!remote_thread.GetHandle())
  {
    DWORD const last_error = ::GetLastError();
    HADESMEM_THROW_EXCEPTION(Error() <<
      ErrorString("Could not create remote thread.") <<
      ErrorCodeWinLast(last_error));
  }

  // TODO: Add a sensible and configurable timeout.
  if (::WaitForSingleObject(remote_thread.GetHandle(), INFINITE) !=
    WAIT_OBJECT_0)
  {
    DWORD const last_error = ::GetLastError();
    HADESMEM_THROW_EXCEPTION(Error() <<
      ErrorString("Could not wait for remote thread.") <<
      ErrorCodeWinLast(last_error));
  }
}

}

template <typename T>
class CallResult;

struct InjectFlags
{
  enum
  {
    kNone = 0,
    kPathResolution = 1 << 0,
    kAddToSearchOrder = 1 << 1,
    kKeepSuspended = 1 << 2,
    kInvalidFlagMaxValue = 1 << 3
  };
};

inline HMODULE InjectDll(Process const& process, std::wstring const& path,
  int flags)
{
  HADESMEM_ASSERT((flags & ~(InjectFlags::kInvalidFlagMaxValue - 1)) == 0);

  boost::filesystem::path path_real(path);

  bool const path_resolution = !!(flags & InjectFlags::kPathResolution);

  if (path_resolution && path_real.is_relative())
  {
    path_real = boost::filesystem::absolute(path_real,
      detail::GetSelfDirPath());
  }
  path_real.make_preferred();

  bool const add_path = !!(flags & InjectFlags::kAddToSearchOrder);
  if (add_path && path_real.is_relative())
  {
    HADESMEM_THROW_EXCEPTION(Error() <<
      ErrorString("Cannot modify search order unless an absolute path "
      "or path resolution is used."));
  }

  // Note: Only performing this check when path resolution is enabled,
  // because otherwise we would need to perform the check in the context
  // of the remote process, which is not possible to do without
  // introducing race conditions and other potential problems. So we just
  // let LoadLibraryW do the check for us.
  if (path_resolution && !boost::filesystem::exists(path_real))
  {
    HADESMEM_THROW_EXCEPTION(Error() <<
      ErrorString("Could not find module file."));
  }

  detail::ForceLdrInitializeThunk(process.GetId());

  std::wstring const path_string(path_real.native());
  std::size_t const path_buf_size = (path_string.size() + 1) *
    sizeof(wchar_t);

  Allocator const lib_file_remote(process, path_buf_size);
  WriteString(process, lib_file_remote.GetBase(), path_string);

  Module const kernel32_mod(process, L"kernel32.dll");
  auto const load_library = FindProcedure(kernel32_mod, "LoadLibraryExW");

  typedef HMODULE (LoadLibraryExFuncT)(LPCWSTR lpFileName, HANDLE hFile,
    DWORD dwFlags);
  auto const load_library_ret =
    Call<LoadLibraryExFuncT>(process, reinterpret_cast<FnPtr>(load_library),
    CallConv::kWinApi, static_cast<LPCWSTR>(lib_file_remote.GetBase()),
    nullptr, add_path ? LOAD_WITH_ALTERED_SEARCH_PATH : 0UL);
  if (!load_library_ret.GetReturnValue())
  {
    HADESMEM_THROW_EXCEPTION(Error() <<
      ErrorString("Call to LoadLibraryW in remote process failed.") <<
      ErrorCodeWinLast(load_library_ret.GetLastError()));
  }

  return load_library_ret.GetReturnValue();
}

inline void FreeDll(Process const& process, HMODULE module)
{
  Module const kernel32_mod(process, L"kernel32.dll");
  auto const free_library = FindProcedure(kernel32_mod, "FreeLibrary");

  typedef BOOL (FreeLibraryFuncT)(HMODULE hModule);
  auto const free_library_ret =
    Call<FreeLibraryFuncT>(process, reinterpret_cast<FnPtr>(free_library),
    CallConv::kWinApi, module);
  if (!free_library_ret.GetReturnValue())
  {
    HADESMEM_THROW_EXCEPTION(Error() <<
      ErrorString("Call to FreeLibrary in remote process failed.") <<
      ErrorCodeWinLast(free_library_ret.GetLastError()));
  }
}

// TODO: Configurable timeout.
inline CallResult<DWORD_PTR> CallExport(Process const& process, HMODULE module,
  std::string const& export_name)
{
  Module const module_remote(process, module);
  auto const export_ptr = FindProcedure(module_remote, export_name);

  return Call<DWORD_PTR()>(process, reinterpret_cast<FnPtr>(export_ptr),
    CallConv::kDefault);
}

class CreateAndInjectData
{
public:
  explicit CreateAndInjectData(Process const& process, HMODULE module,
    DWORD_PTR export_ret, DWORD export_last_error)
    : process_(process),
    module_(module),
    export_ret_(export_ret),
    export_last_error_(export_last_error)
  { }

  CreateAndInjectData(CreateAndInjectData const& other)
    : process_(other.process_),
    module_(other.module_),
    export_ret_(other.export_ret_),
    export_last_error_(other.export_last_error_)
  { }

  CreateAndInjectData& operator=(CreateAndInjectData const& other)
  {
    process_ = other.process_;
    module_ = other.module_;
    export_ret_ = other.export_ret_;
    export_last_error_ = other.export_last_error_;

    return *this;
  }

  CreateAndInjectData(CreateAndInjectData&& other) HADESMEM_NOEXCEPT
    : process_(std::move(other.process_)),
    module_(other.module_),
    export_ret_(other.export_ret_),
    export_last_error_(other.export_last_error_)
  { }

  CreateAndInjectData& operator=(CreateAndInjectData&& other)
    HADESMEM_NOEXCEPT
  {
    process_ = std::move(other.process_);
    module_ = other.module_;
    export_ret_ = other.export_ret_;
    export_last_error_ = other.export_last_error_;

    return *this;
  }

  ~CreateAndInjectData() HADESMEM_NOEXCEPT
  { }

  Process GetProcess() const
  {
    return process_;
  }

  HMODULE GetModule() const HADESMEM_NOEXCEPT
  {
    return module_;
  }

  DWORD_PTR GetExportRet() const HADESMEM_NOEXCEPT
  {
    return export_ret_;
  }

  DWORD GetExportLastError() const HADESMEM_NOEXCEPT
  {
    return export_last_error_;
  }

private:
  Process process_;
  HMODULE module_;
  DWORD_PTR export_ret_;
  DWORD export_last_error_;
};

inline CreateAndInjectData CreateAndInject(
  std::wstring const& path,
  std::wstring const& work_dir,
  std::vector<std::wstring> const& args,
  std::wstring const& module,
  std::string const& export_name,
  int flags)
{
  boost::filesystem::path const path_real(path);

  std::wstring command_line;
  detail::ArgvQuote(&command_line, path_real.native(), false);
  std::for_each(std::begin(args), std::end(args),
    [&] (std::wstring const& arg)
  {
    command_line += L' ';
    detail::ArgvQuote(&command_line, arg, false);
  });
  std::vector<wchar_t> proc_args(std::begin(command_line),
    std::end(command_line));
  proc_args.push_back(L'\0');

  boost::filesystem::path work_dir_real;
  if (!work_dir.empty())
  {
    work_dir_real = work_dir;
  }
  else if (path_real.has_parent_path())
  {
    work_dir_real = path_real.parent_path();
  }
  else
  {
    work_dir_real = L"./";
  }

  STARTUPINFO start_info;
  ::ZeroMemory(&start_info, sizeof(start_info));
  start_info.cb = sizeof(start_info);
  PROCESS_INFORMATION proc_info;
  ::ZeroMemory(&proc_info, sizeof(proc_info));
  if (!::CreateProcess(path_real.c_str(), proc_args.data(), nullptr, nullptr,
    FALSE, CREATE_SUSPENDED | CREATE_UNICODE_ENVIRONMENT, nullptr,
    work_dir_real.c_str(), &start_info, &proc_info))
  {
    DWORD const last_error = ::GetLastError();
    HADESMEM_THROW_EXCEPTION(Error() <<
      ErrorString("CreateProcess failed.") <<
      ErrorCodeWinLast(last_error));
  }

  detail::SmartHandle const proc_handle(proc_info.hProcess);
  detail::SmartHandle const thread_handle(proc_info.hThread);

  try
  {
    Process const process(proc_info.dwProcessId);

    HMODULE const remote_module = InjectDll(process, module, flags);

    CallResult<DWORD_PTR> export_ret(0, 0);
    if (!export_name.empty())
    {
      // TODO: Configurable timeout.
      export_ret = CallExport(process, remote_module, export_name);
    }

    if (flags & InjectFlags::kKeepSuspended)
    {
      if (::ResumeThread(thread_handle.GetHandle()) == static_cast<DWORD>(-1))
      {
        DWORD const last_error = ::GetLastError();
        HADESMEM_THROW_EXCEPTION(Error() <<
          ErrorString("Could not resume process.") <<
          ErrorCodeWinLast(last_error) <<
          ErrorCodeWinRet(export_ret.GetReturnValue()) <<
          ErrorCodeWinOther(export_ret.GetLastError()));
      }
    }

    return CreateAndInjectData(process, remote_module,
      export_ret.GetReturnValue(), export_ret.GetLastError());
  }
  catch (std::exception const& /*e*/)
  {
    // Terminate process if injection failed, otherwise the 'zombie' process
    // would be leaked.
    ::TerminateProcess(proc_handle.GetHandle(), 0);

    throw;
  }
}

}
<|endoftext|>


<commit_before>#pragma once
#include <thectci/component_registry.hpp>

namespace the
{

namespace ctci
{

class ServiceRegistry
{
  public:
    template < typename T >
    static void register_service( T& service_implementation )
    {
      instance().m_services.register_component< T >( service_implementation );
    }

    template < typename T >
    static T& service()
    {
      return instance().m_services.component< T >();
    }

  private:
    static ServiceRegistry& instance();

    typedef ComponentRegistry Services;
    Services m_services;
};

template < typename ServiceInterface, typename ServiceImplementation >
class AutoServiceRegister
{
  public:
    template < typename... Args >
    AutoServiceRegister( Args&&... args )
      : m_service_instance( std::forward<Args>( args )... )
    {
      ServiceRegistry::register_service< ServiceInterface >( m_service_instance );
    }

  private:
    ServiceImplementation m_service_instance;
};

}

}

<commit_msg>service registry construction modification<commit_after>#pragma once
#include <thectci/component_registry.hpp>

namespace the
{

namespace ctci
{

class ServiceRegistry
{
  public:
    template < typename T >
    static void register_service( T& service_implementation )
    {
      instance().m_services.register_component< T >( service_implementation );
    }

    template < typename T >
    static T& service()
    {
      return instance().m_services.component< T >();
    }

    ServiceRegistry( const ServiceRegistry& ) = delete;
    ServiceRegistry& operator=( const ServiceRegistry& ) = delete;
  private:
    ServiceRegistry() = default;

    static ServiceRegistry& instance();

    typedef ComponentRegistry Services;
    Services m_services;
};

template < typename ServiceInterface, typename ServiceImplementation >
class AutoServiceRegister
{
  public:
    template < typename... Args >
    AutoServiceRegister( Args&&... args )
      : m_service_instance( std::forward<Args>( args )... )
    {
      ServiceRegistry::register_service< ServiceInterface >( m_service_instance );
    }

  private:
    ServiceImplementation m_service_instance;
};

}

}

<|endoftext|>