<commit_before>#include "openmc/source.h"

#if defined (__unix__) || (defined (__APPLE__) && defined (__MACH__))
#define HAS_DYNAMIC_LINKING
#endif

#include <algorithm> // for move

#ifdef HAS_DYNAMIC_LINKING
#include <dlfcn.h> // for dlopen, dlsym, dlclose, dlerror
#endif

#include <fmt/core.h>
#include "xtensor/xadapt.hpp"

#include "openmc/bank.h"
#include "openmc/cell.h"
#include "openmc/error.h"
#include "openmc/file_utils.h"
#include "openmc/hdf5_interface.h"
#include "openmc/material.h"
#include "openmc/message_passing.h"
#include "openmc/mgxs_interface.h"
#include "openmc/nuclide.h"
#include "openmc/capi.h"
#include "openmc/random_lcg.h"
#include "openmc/search.h"
#include "openmc/settings.h"
#include "openmc/simulation.h"
#include "openmc/state_point.h"
#include "openmc/xml_interface.h"

namespace openmc {

//==============================================================================
// Global variables
//==============================================================================

namespace model {

typedef Particle::Bank (*sample_t)(uint64_t  &seed);
sample_t sample_source;
void* source_library;

std::vector<SourceDistribution> external_sources;

}

//==============================================================================
// SourceDistribution implementation
//==============================================================================

SourceDistribution::SourceDistribution(UPtrSpace space, UPtrAngle angle, UPtrDist energy)
  : space_{std::move(space)}, angle_{std::move(angle)}, energy_{std::move(energy)} { }

SourceDistribution::SourceDistribution(pugi::xml_node node)
{
  // Check for particle type
  if (check_for_node(node, "particle")) {
    auto temp_str = get_node_value(node, "particle", true, true);
    if (temp_str == "neutron") {
      particle_ = Particle::Type::neutron;
    } else if (temp_str == "photon") {
      particle_ = Particle::Type::photon;
      settings::photon_transport = true;
    } else {
      fatal_error(std::string("Unknown source particle type: ") + temp_str);
    }
  }

  // Check for source strength
  if (check_for_node(node, "strength")) {
    strength_ = std::stod(get_node_value(node, "strength"));
  }

  // Check for external source file
  if (check_for_node(node, "file")) {
    // Copy path of source file
    settings::path_source = get_node_value(node, "file", false, true);

    // Check if source file exists
    if (!file_exists(settings::path_source)) {
      fatal_error(fmt::format("Source file '{}' does not exist.",
        settings::path_source));
    }
  } else if (check_for_node(node, "library")) {
    settings::path_source_library = get_node_value(node, "library", false, true);
    if (!file_exists(settings::path_source_library)) {
      fatal_error(fmt::format("Source library '{}' does not exist.",
        settings::path_source_library));
    }
  } else {

    // Spatial distribution for external source
    if (check_for_node(node, "space")) {
      // Get pointer to spatial distribution
      pugi::xml_node node_space = node.child("space");

      // Check for type of spatial distribution and read
      std::string type;
      if (check_for_node(node_space, "type"))
        type = get_node_value(node_space, "type", true, true);
      if (type == "cartesian") {
        space_ = UPtrSpace{new CartesianIndependent(node_space)};
      } else if (type == "cylindrical") {
        space_ = UPtrSpace{new CylindricalIndependent(node_space)};
      } else if (type == "spherical") {
        space_ = UPtrSpace{new SphericalIndependent(node_space)};
      } else if (type == "box") {
        space_ = UPtrSpace{new SpatialBox(node_space)};
      } else if (type == "fission") {
        space_ = UPtrSpace{new SpatialBox(node_space, true)};
      } else if (type == "point") {
        space_ = UPtrSpace{new SpatialPoint(node_space)};
      } else {
        fatal_error(fmt::format(
          "Invalid spatial distribution for external source: {}", type));
      }

    } else {
      // If no spatial distribution specified, make it a point source
      space_ = UPtrSpace{new SpatialPoint()};
    }

    // Determine external source angular distribution
    if (check_for_node(node, "angle")) {
      // Get pointer to angular distribution
      pugi::xml_node node_angle = node.child("angle");

      // Check for type of angular distribution
      std::string type;
      if (check_for_node(node_angle, "type"))
        type = get_node_value(node_angle, "type", true, true);
      if (type == "isotropic") {
        angle_ = UPtrAngle{new Isotropic()};
      } else if (type == "monodirectional") {
        angle_ = UPtrAngle{new Monodirectional(node_angle)};
      } else if (type == "mu-phi") {
        angle_ = UPtrAngle{new PolarAzimuthal(node_angle)};
      } else {
        fatal_error(fmt::format(
          "Invalid angular distribution for external source: {}", type));
      }

    } else {
      angle_ = UPtrAngle{new Isotropic()};
    }

    // Determine external source energy distribution
    if (check_for_node(node, "energy")) {
      pugi::xml_node node_dist = node.child("energy");
      energy_ = distribution_from_xml(node_dist);
    } else {
      // Default to a Watt spectrum with parameters 0.988 MeV and 2.249 MeV^-1
      energy_ = UPtrDist{new Watt(0.988e6, 2.249e-6)};
    }
  }
}

Particle::Bank SourceDistribution::sample(uint64_t* seed) const
{
  Particle::Bank site;

  // Set weight to one by default
  site.wgt = 1.0;

  // Repeat sampling source location until a good site has been found
  bool found = false;
  int n_reject = 0;
  static int n_accept = 0;
  while (!found) {
    // Set particle type
    site.particle = particle_;

    // Sample spatial distribution
    site.r = space_->sample(seed);
    double xyz[] {site.r.x, site.r.y, site.r.z};

    // Now search to see if location exists in geometry
    int32_t cell_index, instance;
    int err = openmc_find_cell(xyz, &cell_index, &instance);
    found = (err != OPENMC_E_GEOMETRY);

    // Check if spatial site is in fissionable material
    if (found) {
      auto space_box = dynamic_cast<SpatialBox*>(space_.get());
      if (space_box) {
        if (space_box->only_fissionable()) {
          // Determine material
          const auto& c = model::cells[cell_index];
          auto mat_index = c->material_.size() == 1
            ? c->material_[0] : c->material_[instance];

          if (mat_index == MATERIAL_VOID) {
            found = false;
          } else {
            if (!model::materials[mat_index]->fissionable_) found = false;
          }
        }
      }
    }

    // Check for rejection
    if (!found) {
      ++n_reject;
      if (n_reject >= EXTSRC_REJECT_THRESHOLD &&
          static_cast<double>(n_accept)/n_reject <= EXTSRC_REJECT_FRACTION) {
        fatal_error("More than 95% of external source sites sampled were "
                    "rejected. Please check your external source definition.");
      }
    }
  }

  // Increment number of accepted samples
  ++n_accept;

  // Sample angle
  site.u = angle_->sample(seed);

  // Check for monoenergetic source above maximum particle energy
  auto p = static_cast<int>(particle_);
  auto energy_ptr = dynamic_cast<Discrete*>(energy_.get());
  if (energy_ptr) {
    auto energies = xt::adapt(energy_ptr->x());
    if (xt::any(energies > data::energy_max[p])) {
      fatal_error("Source energy above range of energies of at least "
                  "one cross section table");
    } else if (xt::any(energies < data::energy_min[p])) {
      fatal_error("Source energy below range of energies of at least "
                  "one cross section table");
    }
  }

  while (true) {
    // Sample energy spectrum
    site.E = energy_->sample(seed);

    // Resample if energy falls outside minimum or maximum particle energy
    if (site.E < data::energy_max[p] && site.E > data::energy_min[p]) break;
  }

  // Set delayed group
  site.delayed_group = 0;

  return site;
}

//==============================================================================
// Non-member functions
//==============================================================================

void initialize_source()
{
  write_message("Initializing source particles...", 5);

  if (!settings::path_source.empty()) {
    // Read the source from a binary file instead of sampling from some
    // assumed source distribution

    write_message(fmt::format("Reading source file from {}...",
      settings::path_source), 6);

    // Open the binary file
    hid_t file_id = file_open(settings::path_source, 'r', true);

    // Read the file type
    std::string filetype;
    read_attribute(file_id, "filetype", filetype);

    // Check to make sure this is a source file
    if (filetype != "source" && filetype != "statepoint") {
      fatal_error("Specified starting source file not a source file type.");
    }

    // Read in the source bank
    read_source_bank(file_id);

    // Close file
    file_close(file_id);
  } else if (!settings::path_source_library.empty()) {

    write_message(fmt::format("Sampling from library source {}...",
      settings::path_source), 6);

    fill_source_bank_custom_source();

  } else {
    // Generation source sites from specified distribution in user input
    for (int64_t i = 0; i < simulation::work_per_rank; ++i) {
      // initialize random number seed
      int64_t id = simulation::total_gen*settings::n_particles +
        simulation::work_index[mpi::rank] + i + 1;
      uint64_t seed = init_seed(id, STREAM_SOURCE);

      // sample external source distribution
      simulation::source_bank[i] = sample_external_source(&seed);
    }
  }

  // Write out initial source
  if (settings::write_initial_source) {
    write_message("Writing out initial source...", 5);
    std::string filename = settings::path_output + "initial_source.h5";
    hid_t file_id = file_open(filename, 'w', true);
    write_source_bank(file_id);
    file_close(file_id);
  }
}

Particle::Bank sample_external_source(uint64_t* seed)
{
  // Determine total source strength
  double total_strength = 0.0;
  for (auto& s : model::external_sources)
    total_strength += s.strength();

  // Sample from among multiple source distributions
  int i = 0;
  if (model::external_sources.size() > 1) {
    double xi = prn(seed)*total_strength;
    double c = 0.0;
    for (; i < model::external_sources.size(); ++i) {
      c += model::external_sources[i].strength();
      if (xi < c) break;
    }
  }

  // Sample source site from i-th source distribution
  Particle::Bank site {model::external_sources[i].sample(seed)};

  // If running in MG, convert site.E to group
  if (!settings::run_CE) {
    site.E = lower_bound_index(data::mg.rev_energy_bins_.begin(),
      data::mg.rev_energy_bins_.end(), site.E);
    site.E = data::mg.num_energy_groups_ - site.E - 1.;
  }

  return site;
}

void free_memory_source()
{
  model::external_sources.clear();
}

//Load custom source library
void load_custom_source_library()
{
#ifdef HAS_DYNAMIC_LINKING

  // Open the library
  model::source_library = dlopen(settings::path_source_library.c_str(), RTLD_LAZY);
  if (!model::source_library) {
    fatal_error("Couldn't open source library " + settings::path_source_library);
  }

  // reset errors
  dlerror();

  // get the function from the library
  //using sample_t = Particle::Bank (*)(uint64_t* seed);
  model::sample_source = reinterpret_cast<model::sample_t>(dlsym(model::source_library, "sample_source"));

  // check for any dlsym errors
  auto dlsym_error = dlerror();
  if (dlsym_error) {
    dlclose(model::source_library);
    fatal_error(fmt::format("Couldn't open the sample_source symbol: {}", dlsym_error));
  }

#else
  fatal_error("Custom source libraries have not yet been implemented for "
    "non-POSIX systems");
#endif

}

//Release custom source library
void close_custom_source_library()
{
  dlclose(model::source_library);
}

//Sample source particle from custom library
Particle::Bank sample_custom_source_library(uint64_t* seed)
{
  Particle::Bank site = model::sample_source(*seed);
  return site;
}

// fill the source bank from the external source
void fill_source_bank_custom_source()
{
  // Load the custom library
  load_custom_source_library();

  // Generation source sites from specified distribution in the
  // library source
  for (int64_t i = 0; i < simulation::work_per_rank; ++i) {
    // initialize random number seed
    int64_t id = (simulation::total_gen + overall_generation()) *
      settings::n_particles + simulation::work_index[mpi::rank] + i + 1;
     uint64_t seed = init_seed(id, STREAM_SOURCE);

    // sample custom library source
    simulation::source_bank[i] = sample_custom_source_library(&seed);
  }

  // release the library
  close_custom_source_library();
}

} // namespace openmc
<commit_msg>Remove unnecessary variable in src/source.cpp<commit_after>#include "openmc/source.h"

#if defined (__unix__) || (defined (__APPLE__) && defined (__MACH__))
#define HAS_DYNAMIC_LINKING
#endif

#include <algorithm> // for move

#ifdef HAS_DYNAMIC_LINKING
#include <dlfcn.h> // for dlopen, dlsym, dlclose, dlerror
#endif

#include <fmt/core.h>
#include "xtensor/xadapt.hpp"

#include "openmc/bank.h"
#include "openmc/cell.h"
#include "openmc/error.h"
#include "openmc/file_utils.h"
#include "openmc/hdf5_interface.h"
#include "openmc/material.h"
#include "openmc/message_passing.h"
#include "openmc/mgxs_interface.h"
#include "openmc/nuclide.h"
#include "openmc/capi.h"
#include "openmc/random_lcg.h"
#include "openmc/search.h"
#include "openmc/settings.h"
#include "openmc/simulation.h"
#include "openmc/state_point.h"
#include "openmc/xml_interface.h"

namespace openmc {

//==============================================================================
// Global variables
//==============================================================================

namespace model {

typedef Particle::Bank (*sample_t)(uint64_t  &seed);
sample_t sample_source;
void* source_library;

std::vector<SourceDistribution> external_sources;

}

//==============================================================================
// SourceDistribution implementation
//==============================================================================

SourceDistribution::SourceDistribution(UPtrSpace space, UPtrAngle angle, UPtrDist energy)
  : space_{std::move(space)}, angle_{std::move(angle)}, energy_{std::move(energy)} { }

SourceDistribution::SourceDistribution(pugi::xml_node node)
{
  // Check for particle type
  if (check_for_node(node, "particle")) {
    auto temp_str = get_node_value(node, "particle", true, true);
    if (temp_str == "neutron") {
      particle_ = Particle::Type::neutron;
    } else if (temp_str == "photon") {
      particle_ = Particle::Type::photon;
      settings::photon_transport = true;
    } else {
      fatal_error(std::string("Unknown source particle type: ") + temp_str);
    }
  }

  // Check for source strength
  if (check_for_node(node, "strength")) {
    strength_ = std::stod(get_node_value(node, "strength"));
  }

  // Check for external source file
  if (check_for_node(node, "file")) {
    // Copy path of source file
    settings::path_source = get_node_value(node, "file", false, true);

    // Check if source file exists
    if (!file_exists(settings::path_source)) {
      fatal_error(fmt::format("Source file '{}' does not exist.",
        settings::path_source));
    }
  } else if (check_for_node(node, "library")) {
    settings::path_source_library = get_node_value(node, "library", false, true);
    if (!file_exists(settings::path_source_library)) {
      fatal_error(fmt::format("Source library '{}' does not exist.",
        settings::path_source_library));
    }
  } else {

    // Spatial distribution for external source
    if (check_for_node(node, "space")) {
      // Get pointer to spatial distribution
      pugi::xml_node node_space = node.child("space");

      // Check for type of spatial distribution and read
      std::string type;
      if (check_for_node(node_space, "type"))
        type = get_node_value(node_space, "type", true, true);
      if (type == "cartesian") {
        space_ = UPtrSpace{new CartesianIndependent(node_space)};
      } else if (type == "cylindrical") {
        space_ = UPtrSpace{new CylindricalIndependent(node_space)};
      } else if (type == "spherical") {
        space_ = UPtrSpace{new SphericalIndependent(node_space)};
      } else if (type == "box") {
        space_ = UPtrSpace{new SpatialBox(node_space)};
      } else if (type == "fission") {
        space_ = UPtrSpace{new SpatialBox(node_space, true)};
      } else if (type == "point") {
        space_ = UPtrSpace{new SpatialPoint(node_space)};
      } else {
        fatal_error(fmt::format(
          "Invalid spatial distribution for external source: {}", type));
      }

    } else {
      // If no spatial distribution specified, make it a point source
      space_ = UPtrSpace{new SpatialPoint()};
    }

    // Determine external source angular distribution
    if (check_for_node(node, "angle")) {
      // Get pointer to angular distribution
      pugi::xml_node node_angle = node.child("angle");

      // Check for type of angular distribution
      std::string type;
      if (check_for_node(node_angle, "type"))
        type = get_node_value(node_angle, "type", true, true);
      if (type == "isotropic") {
        angle_ = UPtrAngle{new Isotropic()};
      } else if (type == "monodirectional") {
        angle_ = UPtrAngle{new Monodirectional(node_angle)};
      } else if (type == "mu-phi") {
        angle_ = UPtrAngle{new PolarAzimuthal(node_angle)};
      } else {
        fatal_error(fmt::format(
          "Invalid angular distribution for external source: {}", type));
      }

    } else {
      angle_ = UPtrAngle{new Isotropic()};
    }

    // Determine external source energy distribution
    if (check_for_node(node, "energy")) {
      pugi::xml_node node_dist = node.child("energy");
      energy_ = distribution_from_xml(node_dist);
    } else {
      // Default to a Watt spectrum with parameters 0.988 MeV and 2.249 MeV^-1
      energy_ = UPtrDist{new Watt(0.988e6, 2.249e-6)};
    }
  }
}

Particle::Bank SourceDistribution::sample(uint64_t* seed) const
{
  Particle::Bank site;

  // Set weight to one by default
  site.wgt = 1.0;

  // Repeat sampling source location until a good site has been found
  bool found = false;
  int n_reject = 0;
  static int n_accept = 0;
  while (!found) {
    // Set particle type
    site.particle = particle_;

    // Sample spatial distribution
    site.r = space_->sample(seed);
    double xyz[] {site.r.x, site.r.y, site.r.z};

    // Now search to see if location exists in geometry
    int32_t cell_index, instance;
    int err = openmc_find_cell(xyz, &cell_index, &instance);
    found = (err != OPENMC_E_GEOMETRY);

    // Check if spatial site is in fissionable material
    if (found) {
      auto space_box = dynamic_cast<SpatialBox*>(space_.get());
      if (space_box) {
        if (space_box->only_fissionable()) {
          // Determine material
          const auto& c = model::cells[cell_index];
          auto mat_index = c->material_.size() == 1
            ? c->material_[0] : c->material_[instance];

          if (mat_index == MATERIAL_VOID) {
            found = false;
          } else {
            if (!model::materials[mat_index]->fissionable_) found = false;
          }
        }
      }
    }

    // Check for rejection
    if (!found) {
      ++n_reject;
      if (n_reject >= EXTSRC_REJECT_THRESHOLD &&
          static_cast<double>(n_accept)/n_reject <= EXTSRC_REJECT_FRACTION) {
        fatal_error("More than 95% of external source sites sampled were "
                    "rejected. Please check your external source definition.");
      }
    }
  }

  // Increment number of accepted samples
  ++n_accept;

  // Sample angle
  site.u = angle_->sample(seed);

  // Check for monoenergetic source above maximum particle energy
  auto p = static_cast<int>(particle_);
  auto energy_ptr = dynamic_cast<Discrete*>(energy_.get());
  if (energy_ptr) {
    auto energies = xt::adapt(energy_ptr->x());
    if (xt::any(energies > data::energy_max[p])) {
      fatal_error("Source energy above range of energies of at least "
                  "one cross section table");
    } else if (xt::any(energies < data::energy_min[p])) {
      fatal_error("Source energy below range of energies of at least "
                  "one cross section table");
    }
  }

  while (true) {
    // Sample energy spectrum
    site.E = energy_->sample(seed);

    // Resample if energy falls outside minimum or maximum particle energy
    if (site.E < data::energy_max[p] && site.E > data::energy_min[p]) break;
  }

  // Set delayed group
  site.delayed_group = 0;

  return site;
}

//==============================================================================
// Non-member functions
//==============================================================================

void initialize_source()
{
  write_message("Initializing source particles...", 5);

  if (!settings::path_source.empty()) {
    // Read the source from a binary file instead of sampling from some
    // assumed source distribution

    write_message(fmt::format("Reading source file from {}...",
      settings::path_source), 6);

    // Open the binary file
    hid_t file_id = file_open(settings::path_source, 'r', true);

    // Read the file type
    std::string filetype;
    read_attribute(file_id, "filetype", filetype);

    // Check to make sure this is a source file
    if (filetype != "source" && filetype != "statepoint") {
      fatal_error("Specified starting source file not a source file type.");
    }

    // Read in the source bank
    read_source_bank(file_id);

    // Close file
    file_close(file_id);
  } else if (!settings::path_source_library.empty()) {

    write_message(fmt::format("Sampling from library source {}...",
      settings::path_source), 6);

    fill_source_bank_custom_source();

  } else {
    // Generation source sites from specified distribution in user input
    for (int64_t i = 0; i < simulation::work_per_rank; ++i) {
      // initialize random number seed
      int64_t id = simulation::total_gen*settings::n_particles +
        simulation::work_index[mpi::rank] + i + 1;
      uint64_t seed = init_seed(id, STREAM_SOURCE);

      // sample external source distribution
      simulation::source_bank[i] = sample_external_source(&seed);
    }
  }

  // Write out initial source
  if (settings::write_initial_source) {
    write_message("Writing out initial source...", 5);
    std::string filename = settings::path_output + "initial_source.h5";
    hid_t file_id = file_open(filename, 'w', true);
    write_source_bank(file_id);
    file_close(file_id);
  }
}

Particle::Bank sample_external_source(uint64_t* seed)
{
  // Determine total source strength
  double total_strength = 0.0;
  for (auto& s : model::external_sources)
    total_strength += s.strength();

  // Sample from among multiple source distributions
  int i = 0;
  if (model::external_sources.size() > 1) {
    double xi = prn(seed)*total_strength;
    double c = 0.0;
    for (; i < model::external_sources.size(); ++i) {
      c += model::external_sources[i].strength();
      if (xi < c) break;
    }
  }

  // Sample source site from i-th source distribution
  Particle::Bank site {model::external_sources[i].sample(seed)};

  // If running in MG, convert site.E to group
  if (!settings::run_CE) {
    site.E = lower_bound_index(data::mg.rev_energy_bins_.begin(),
      data::mg.rev_energy_bins_.end(), site.E);
    site.E = data::mg.num_energy_groups_ - site.E - 1.;
  }

  return site;
}

void free_memory_source()
{
  model::external_sources.clear();
}

//Load custom source library
void load_custom_source_library()
{
#ifdef HAS_DYNAMIC_LINKING

  // Open the library
  model::source_library = dlopen(settings::path_source_library.c_str(), RTLD_LAZY);
  if (!model::source_library) {
    fatal_error("Couldn't open source library " + settings::path_source_library);
  }

  // reset errors
  dlerror();

  // get the function from the library
  //using sample_t = Particle::Bank (*)(uint64_t* seed);
  model::sample_source = reinterpret_cast<model::sample_t>(dlsym(model::source_library, "sample_source"));

  // check for any dlsym errors
  auto dlsym_error = dlerror();
  if (dlsym_error) {
    dlclose(model::source_library);
    fatal_error(fmt::format("Couldn't open the sample_source symbol: {}", dlsym_error));
  }

#else
  fatal_error("Custom source libraries have not yet been implemented for "
    "non-POSIX systems");
#endif

}

//Release custom source library
void close_custom_source_library()
{
  dlclose(model::source_library);
}

//Sample source particle from custom library
Particle::Bank sample_custom_source_library(uint64_t* seed)
{
  return model::sample_source(*seed);
}

// fill the source bank from the external source
void fill_source_bank_custom_source()
{
  // Load the custom library
  load_custom_source_library();

  // Generation source sites from specified distribution in the
  // library source
  for (int64_t i = 0; i < simulation::work_per_rank; ++i) {
    // initialize random number seed
    int64_t id = (simulation::total_gen + overall_generation()) *
      settings::n_particles + simulation::work_index[mpi::rank] + i + 1;
     uint64_t seed = init_seed(id, STREAM_SOURCE);

    // sample custom library source
    simulation::source_bank[i] = sample_custom_source_library(&seed);
  }

  // release the library
  close_custom_source_library();
}

} // namespace openmc
<|endoftext|>


<commit_before>#include "envoy/api/v2/rds.pb.validate.h"

#include "common/router/config_impl.h"

#include "test/common/router/route_fuzz.pb.h"
#include "test/fuzz/fuzz_runner.h"
#include "test/fuzz/utility.h"
#include "test/mocks/server/mocks.h"

namespace Envoy {
namespace Router {
namespace {

// A templated method to replace invalid characters in a protocol buffer that contains
// (request/response)_headers_to_(add/remove).
template <class T> T replaceInvalidHeaders(const T& config) {
  T clean_config = config;
  clean_config.mutable_request_headers_to_add()->CopyFrom(
      Fuzz::replaceInvalidHeaders(config.request_headers_to_add()));
  clean_config.mutable_response_headers_to_add()->CopyFrom(
      Fuzz::replaceInvalidHeaders(config.response_headers_to_add()));
  auto request_headers_to_remove = clean_config.mutable_request_headers_to_remove();
  std::for_each(request_headers_to_remove->begin(), request_headers_to_remove->end(),
                [](std::string& n) { n = Fuzz::replaceInvalidCharacters(n); });
  auto response_headers_to_remove = clean_config.mutable_response_headers_to_remove();
  std::for_each(response_headers_to_remove->begin(), response_headers_to_remove->end(),
                [](std::string& n) { n = Fuzz::replaceInvalidCharacters(n); });
  return clean_config;
}

// Removes invalid headers from the RouteConfiguration as well as in each of the virtual hosts.
envoy::api::v2::RouteConfiguration
cleanRouteConfig(envoy::api::v2::RouteConfiguration route_config) {
  // A route config contains a list of HTTP headers that should be added and/or removed to each
  // request and/or response the connection manager routes. This removes invalid characters the
  // headers.
  envoy::api::v2::RouteConfiguration clean_config =
      replaceInvalidHeaders<envoy::api::v2::RouteConfiguration>(route_config);
  // Replace invalid characters from
  auto internal_only_headers = clean_config.mutable_internal_only_headers();
  std::for_each(internal_only_headers->begin(), internal_only_headers->end(),
                [](std::string& n) { n = Fuzz::replaceInvalidCharacters(n); });
  auto virtual_hosts = clean_config.mutable_virtual_hosts();
  std::for_each(
      virtual_hosts->begin(), virtual_hosts->end(),
      [](envoy::api::v2::route::VirtualHost& virtual_host) {
        // Each virtual host in the routing configuration contains a list of headers to add and/or
        // remove from each request and response that get routed through it. This replaces invalid
        // header characters in these fields.
        virtual_host = replaceInvalidHeaders<envoy::api::v2::route::VirtualHost>(virtual_host);
        // Envoy can determine the cluster to route to by reading the HTTP header named by the
        // cluster_header from the request header. Because these cluster_headers are destined to be
        // added to a Header Map, we iterate through each route in and remove invalid characters
        // from their cluster headers.
        std::for_each(virtual_host.mutable_routes()->begin(), virtual_host.mutable_routes()->end(),
                      [](envoy::api::v2::route::Route& route) {
                        if (route.has_route()) {
                          route.mutable_route()->set_cluster_header(
                              Fuzz::replaceInvalidCharacters(route.route().cluster_header()));
                          if (route.route().cluster_header().empty()) {
                            route.mutable_route()->set_cluster_header("not-empty");
                          }
                        }
                      });
      });

  return clean_config;
}

// TODO(htuch): figure out how to generate via a genrule from config_impl_test the full corpus.
DEFINE_PROTO_FUZZER(const test::common::router::RouteTestCase& input) {
  try {
    NiceMock<Envoy::StreamInfo::MockStreamInfo> stream_info;
    NiceMock<Server::Configuration::MockFactoryContext> factory_context;
    TestUtility::validate(input.config());
    ConfigImpl config(cleanRouteConfig(input.config()), factory_context, true);
    Http::TestHeaderMapImpl headers = Fuzz::fromHeaders(input.headers());
    // It's a precondition of routing that {:authority, :path, x-forwarded-proto} headers exists,
    // HCM enforces this.
    if (headers.Host() == nullptr) {
      headers.insertHost().value(std::string("example.com"));
    }
    if (headers.Path() == nullptr) {
      headers.insertPath().value(std::string("/"));
    }
    if (headers.ForwardedProto() == nullptr) {
      headers.insertForwardedProto().value(std::string("http"));
    }
    auto route = config.route(headers, input.random_value());
    if (route != nullptr && route->routeEntry() != nullptr) {
      route->routeEntry()->finalizeRequestHeaders(headers, stream_info, true);
    }
    ENVOY_LOG_MISC(trace, "Success");
  } catch (const EnvoyException& e) {
    ENVOY_LOG_MISC(debug, "EnvoyException: {}", e.what());
  }
}

} // namespace
} // namespace Router
} // namespace Envoy
<commit_msg>fuzz: improve fuzz performance for accesslog and route (#8397)<commit_after>#include "envoy/api/v2/rds.pb.validate.h"

#include "common/router/config_impl.h"

#include "test/common/router/route_fuzz.pb.h"
#include "test/fuzz/fuzz_runner.h"
#include "test/fuzz/utility.h"
#include "test/mocks/server/mocks.h"

namespace Envoy {
namespace Router {
namespace {

// A templated method to replace invalid characters in a protocol buffer that contains
// (request/response)_headers_to_(add/remove).
template <class T> T replaceInvalidHeaders(const T& config) {
  T clean_config = config;
  clean_config.mutable_request_headers_to_add()->CopyFrom(
      Fuzz::replaceInvalidHeaders(config.request_headers_to_add()));
  clean_config.mutable_response_headers_to_add()->CopyFrom(
      Fuzz::replaceInvalidHeaders(config.response_headers_to_add()));
  auto request_headers_to_remove = clean_config.mutable_request_headers_to_remove();
  std::for_each(request_headers_to_remove->begin(), request_headers_to_remove->end(),
                [](std::string& n) { n = Fuzz::replaceInvalidCharacters(n); });
  auto response_headers_to_remove = clean_config.mutable_response_headers_to_remove();
  std::for_each(response_headers_to_remove->begin(), response_headers_to_remove->end(),
                [](std::string& n) { n = Fuzz::replaceInvalidCharacters(n); });
  return clean_config;
}

// Removes invalid headers from the RouteConfiguration as well as in each of the virtual hosts.
envoy::api::v2::RouteConfiguration
cleanRouteConfig(envoy::api::v2::RouteConfiguration route_config) {
  // A route config contains a list of HTTP headers that should be added and/or removed to each
  // request and/or response the connection manager routes. This removes invalid characters the
  // headers.
  envoy::api::v2::RouteConfiguration clean_config =
      replaceInvalidHeaders<envoy::api::v2::RouteConfiguration>(route_config);
  auto internal_only_headers = clean_config.mutable_internal_only_headers();
  std::for_each(internal_only_headers->begin(), internal_only_headers->end(),
                [](std::string& n) { n = Fuzz::replaceInvalidCharacters(n); });
  auto virtual_hosts = clean_config.mutable_virtual_hosts();
  std::for_each(
      virtual_hosts->begin(), virtual_hosts->end(),
      [](envoy::api::v2::route::VirtualHost& virtual_host) {
        // Each virtual host in the routing configuration contains a list of headers to add and/or
        // remove from each request and response that get routed through it. This replaces invalid
        // header characters in these fields.
        virtual_host = replaceInvalidHeaders<envoy::api::v2::route::VirtualHost>(virtual_host);
        // Envoy can determine the cluster to route to by reading the HTTP header named by the
        // cluster_header from the request header. Because these cluster_headers are destined to be
        // added to a Header Map, we iterate through each route in and remove invalid characters
        // from their cluster headers.
        std::for_each(virtual_host.mutable_routes()->begin(), virtual_host.mutable_routes()->end(),
                      [](envoy::api::v2::route::Route& route) {
                        if (route.has_route()) {
                          route.mutable_route()->set_cluster_header(
                              Fuzz::replaceInvalidCharacters(route.route().cluster_header()));
                          if (route.route().cluster_header().empty()) {
                            route.mutable_route()->set_cluster_header("not-empty");
                          }
                        }
                      });
      });

  return clean_config;
}

// TODO(htuch): figure out how to generate via a genrule from config_impl_test the full corpus.
DEFINE_PROTO_FUZZER(const test::common::router::RouteTestCase& input) {
  static NiceMock<Envoy::StreamInfo::MockStreamInfo> stream_info;
  static NiceMock<Server::Configuration::MockFactoryContext> factory_context;
  try {
    TestUtility::validate(input.config());
    ConfigImpl config(cleanRouteConfig(input.config()), factory_context, true);
    Http::TestHeaderMapImpl headers = Fuzz::fromHeaders(input.headers());
    // It's a precondition of routing that {:authority, :path, x-forwarded-proto} headers exists,
    // HCM enforces this.
    if (headers.Host() == nullptr) {
      headers.insertHost().value(std::string("example.com"));
    }
    if (headers.Path() == nullptr) {
      headers.insertPath().value(std::string("/"));
    }
    if (headers.ForwardedProto() == nullptr) {
      headers.insertForwardedProto().value(std::string("http"));
    }
    auto route = config.route(headers, input.random_value());
    if (route != nullptr && route->routeEntry() != nullptr) {
      route->routeEntry()->finalizeRequestHeaders(headers, stream_info, true);
    }
    ENVOY_LOG_MISC(trace, "Success");
  } catch (const EnvoyException& e) {
    ENVOY_LOG_MISC(debug, "EnvoyException: {}", e.what());
  }
}

} // namespace
} // namespace Router
} // namespace Envoy
<|endoftext|>


<commit_before>#include <chrono>
#include <vector>
#include "caffe2/core/operator.h"
#include "caffe2/core/stats.h"
#include "caffe2/core/tensor.h"

namespace caffe2 {
namespace {

class StatRegistryCreateOp : public Operator<CPUContext> {
 public:
  StatRegistryCreateOp(const OperatorDef& operator_def, Workspace* ws)
      : Operator(operator_def, ws) {}

  bool RunOnDevice() override {
    *OperatorBase::Output<std::unique_ptr<StatRegistry>>(0) =
        std::unique_ptr<StatRegistry>(new StatRegistry);
    return true;
  }
};

class StatRegistryExportOp : public Operator<CPUContext> {
 public:
  StatRegistryExportOp(const OperatorDef& operator_def, Workspace* ws)
      : Operator(operator_def, ws),
        reset_(GetSingleArgument<bool>("reset", true)) {}

  bool RunOnDevice() override {
    auto registry = InputSize() > 0
        ? OperatorBase::Input<std::unique_ptr<StatRegistry>>(0).get()
        : &StatRegistry::get();
    auto* keys = Output(0);
    auto* values = Output(1);
    auto* timestamps = Output(2);
    auto data = registry->publish(reset_);
    keys->Resize(data.size());
    values->Resize(data.size());
    timestamps->Resize(data.size());
    auto* pkeys = keys->mutable_data<std::string>();
    auto* pvals = values->mutable_data<int64_t>();
    auto* ptimestamps = timestamps->mutable_data<int64_t>();
    int i = 0;
    for (const auto& stat : data) {
      pkeys[i] = std::move(stat.key);
      pvals[i] = stat.value;
      ptimestamps[i] =
          std::chrono::nanoseconds(stat.ts.time_since_epoch()).count();
      ++i;
    }
    return true;
  }

 private:
  bool reset_;
};

class StatRegistryUpdateOp : public Operator<CPUContext> {
 public:
  StatRegistryUpdateOp(const OperatorDef& operator_def, Workspace* ws)
      : Operator(operator_def, ws) {}

  bool RunOnDevice() override {
    const auto& keys = Input(0);
    const auto& values = Input(1);
    auto registry = InputSize() == 3
        ? OperatorBase::Input<std::unique_ptr<StatRegistry>>(2).get()
        : &StatRegistry::get();
    CAFFE_ENFORCE_EQ(keys.size(), values.size());
    ExportedStatList data(keys.size());
    auto* pkeys = keys.data<std::string>();
    auto* pvals = values.data<int64_t>();
    int i = 0;
    for (auto& stat : data) {
      stat.key = pkeys[i];
      stat.value = pvals[i];
      ++i;
    }
    registry->update(data);
    return true;
  }
};

class TimerInstance {
 public:
  explicit TimerInstance(const std::string& name)
      : running_(false), stat_(name) {}

  void begin() {
    CAFFE_ENFORCE(!running_, "Called TimerBegin on an already running timer.");
    running_ = true;
    start_ = std::chrono::high_resolution_clock::now();
  }

  void end() {
    CAFFE_ENFORCE(running_, "Called TimerEnd on a stopped timer.");
    using namespace std::chrono;
    auto duration = high_resolution_clock::now() - start_;
    auto nanos = duration_cast<nanoseconds>(duration).count();
    CAFFE_EVENT(stat_, time_ns, nanos);
    running_ = false;
  }

 private:
  bool running_;
  std::chrono::high_resolution_clock::time_point start_;

  struct TimerStat {
    CAFFE_STAT_CTOR(TimerStat);
    CAFFE_AVG_EXPORTED_STAT(time_ns);
  } stat_;
};

struct TimerBeginOp : public Operator<CPUContext> {
  TimerBeginOp(const OperatorDef& operator_def, Workspace* ws)
      : Operator(operator_def, ws), timer_([this]() {
          auto givenName = GetSingleArgument<std::string>("counter_name", "");
          return givenName.empty() ? def().output().Get(0) : givenName;
        }()) {}

  bool RunOnDevice() override {
    *OperatorBase::Output<TimerInstance*>(0) = &timer_;
    timer_.begin();
    return true;
  }

 private:
  TimerInstance timer_;
};

struct TimerEndOp : public Operator<CPUContext> {
  TimerEndOp(const OperatorDef& operator_def, Workspace* ws)
      : Operator(operator_def, ws) {}

  bool RunOnDevice() override {
    OperatorBase::Input<TimerInstance*>(0)->end();
    return true;
  }
};

REGISTER_CPU_OPERATOR(StatRegistryCreate, StatRegistryCreateOp);
REGISTER_CPU_OPERATOR(StatRegistryUpdate, StatRegistryUpdateOp);
REGISTER_CPU_OPERATOR(StatRegistryExport, StatRegistryExportOp);

REGISTER_CPU_OPERATOR(TimerBegin, TimerBeginOp);
REGISTER_CPU_OPERATOR(TimerEnd, TimerEndOp);

OPERATOR_SCHEMA(StatRegistryCreate)
    .NumInputs(0)
    .NumOutputs(1)
    .SetDoc(R"DOC(
Create a StatRegistry object that will contain a map of performance counters
keyed by name. A StatRegistry is used to gather and retrieve performance
counts throuhgout the caffe2 codebase.
)DOC")
    .Output(0, "handle", "A Blob pointing to the newly created StatRegistry.");

OPERATOR_SCHEMA(StatRegistryUpdate)
    .NumInputs(2, 3)
    .NumOutputs(0)
    .SetDoc(R"DOC(
Update the given StatRegistry, or the global StatRegistry,
with the values of counters for the given keys.
)DOC")
    .Input(0, "keys", "1D string tensor with the key names to update.")
    .Input(1, "values", "1D int64 tensor with the values to update.")
    .Input(
        2,
        "handle",
        "If provided, update the given StatRegistry. "
        "Otherwise, update the global singleton.");

OPERATOR_SCHEMA(StatRegistryExport)
    .NumInputs(0, 1)
    .NumOutputs(3)
    .Input(
        0,
        "handle",
        "If provided, export values from given StatRegistry."
        "Otherwise, export values from the global singleton StatRegistry.")
    .Output(0, "keys", "1D string tensor with exported key names")
    .Output(1, "values", "1D int64 tensor with exported values")
    .Output(2, "timestamps", "The unix timestamp at counter retrieval.")
    .Arg(
        "reset",
        "(default true) Whether to atomically reset the counters afterwards.");
}

OPERATOR_SCHEMA(TimerBegin)
    .NumInputs(0)
    .NumOutputs(1)
    .SetDoc(R"DOC(
Start a wallclock timer, returning a pointer to it.
The timer is stopped by calling TimerEnd)DOC")
    .Arg("counter_name", "Name of the timer. If not provided, use output name.")
    .Output(0, "timer", "Pointer to timer, to be passed to TimerEnd.");

OPERATOR_SCHEMA(TimerEnd)
    .NumInputs(1)
    .NumOutputs(0)
    .SetDoc("Stop a timer started with TimerBegin, publishing a CAFFE_EVENT")
    .Input(0, "timer", "Pointer to timer, obtained from TimerBegin.");

CAFFE_KNOWN_TYPE(TimerInstance*);
CAFFE_KNOWN_TYPE(std::unique_ptr<caffe2::StatRegistry>);
} // namespace caffe2
<commit_msg>add automatic timing of parameter update phase<commit_after>#include <chrono>
#include <vector>
#include "caffe2/core/operator.h"
#include "caffe2/core/stats.h"
#include "caffe2/core/tensor.h"

namespace caffe2 {
namespace {

class StatRegistryCreateOp : public Operator<CPUContext> {
 public:
  StatRegistryCreateOp(const OperatorDef& operator_def, Workspace* ws)
      : Operator(operator_def, ws) {}

  bool RunOnDevice() override {
    *OperatorBase::Output<std::unique_ptr<StatRegistry>>(0) =
        std::unique_ptr<StatRegistry>(new StatRegistry);
    return true;
  }
};

class StatRegistryExportOp : public Operator<CPUContext> {
 public:
  StatRegistryExportOp(const OperatorDef& operator_def, Workspace* ws)
      : Operator(operator_def, ws),
        reset_(GetSingleArgument<bool>("reset", true)) {}

  bool RunOnDevice() override {
    auto registry = InputSize() > 0
        ? OperatorBase::Input<std::unique_ptr<StatRegistry>>(0).get()
        : &StatRegistry::get();
    auto* keys = Output(0);
    auto* values = Output(1);
    auto* timestamps = Output(2);
    auto data = registry->publish(reset_);
    keys->Resize(data.size());
    values->Resize(data.size());
    timestamps->Resize(data.size());
    auto* pkeys = keys->mutable_data<std::string>();
    auto* pvals = values->mutable_data<int64_t>();
    auto* ptimestamps = timestamps->mutable_data<int64_t>();
    int i = 0;
    for (const auto& stat : data) {
      pkeys[i] = std::move(stat.key);
      pvals[i] = stat.value;
      ptimestamps[i] =
          std::chrono::nanoseconds(stat.ts.time_since_epoch()).count();
      ++i;
    }
    return true;
  }

 private:
  bool reset_;
};

class StatRegistryUpdateOp : public Operator<CPUContext> {
 public:
  StatRegistryUpdateOp(const OperatorDef& operator_def, Workspace* ws)
      : Operator(operator_def, ws) {}

  bool RunOnDevice() override {
    const auto& keys = Input(0);
    const auto& values = Input(1);
    auto registry = InputSize() == 3
        ? OperatorBase::Input<std::unique_ptr<StatRegistry>>(2).get()
        : &StatRegistry::get();
    CAFFE_ENFORCE_EQ(keys.size(), values.size());
    ExportedStatList data(keys.size());
    auto* pkeys = keys.data<std::string>();
    auto* pvals = values.data<int64_t>();
    int i = 0;
    for (auto& stat : data) {
      stat.key = pkeys[i];
      stat.value = pvals[i];
      ++i;
    }
    registry->update(data);
    return true;
  }
};

class TimerInstance {
 public:
  explicit TimerInstance(const std::string& name)
      : running_(false), stat_(name) {}

  void begin() {
    CAFFE_ENFORCE(!running_, "Called TimerBegin on an already running timer.");
    running_ = true;
    start_ = std::chrono::high_resolution_clock::now();
  }

  void end() {
    CAFFE_ENFORCE(running_, "Called TimerEnd on a stopped timer.");
    using namespace std::chrono;
    auto duration = high_resolution_clock::now() - start_;
    auto nanos = duration_cast<nanoseconds>(duration).count();
    CAFFE_EVENT(stat_, time_ns, nanos);
    running_ = false;
  }

  int64_t get_ns() {
    CAFFE_ENFORCE(running_, "Called TimerGet on a stopped timer.");
    using namespace std::chrono;
    auto duration = high_resolution_clock::now() - start_;
    auto nanos = duration_cast<nanoseconds>(duration).count();
    return nanos;
  }

 private:
  bool running_;
  std::chrono::high_resolution_clock::time_point start_;

  struct TimerStat {
    CAFFE_STAT_CTOR(TimerStat);
    CAFFE_AVG_EXPORTED_STAT(time_ns);
  } stat_;
};

struct TimerBeginOp : public Operator<CPUContext> {
  TimerBeginOp(const OperatorDef& operator_def, Workspace* ws)
      : Operator(operator_def, ws), timer_([this]() {
          auto givenName = GetSingleArgument<std::string>("counter_name", "");
          return givenName.empty() ? def().output().Get(0) : givenName;
        }()) {}

  bool RunOnDevice() override {
    *OperatorBase::Output<TimerInstance*>(0) = &timer_;
    timer_.begin();
    return true;
  }

 private:
  TimerInstance timer_;
};

struct TimerEndOp : public Operator<CPUContext> {
  TimerEndOp(const OperatorDef& operator_def, Workspace* ws)
      : Operator(operator_def, ws) {}

  bool RunOnDevice() override {
    OperatorBase::Input<TimerInstance*>(0)->end();
    return true;
  }
};

struct TimerGetAndEndOp : public Operator<CPUContext> {
  TimerGetAndEndOp(const OperatorDef& operator_def, Workspace* ws)
      : Operator(operator_def, ws) {}

  bool RunOnDevice() override {
    int64_t nanos = OperatorBase::Input<TimerInstance*>(0)->get_ns();
    OperatorBase::Input<TimerInstance*>(0)->end();
    auto* res = OperatorBase::Output<TensorCPU>(0);
    res->Resize(1);
    res->template mutable_data<int64_t>()[0] = nanos;
    return true;
  }
};

REGISTER_CPU_OPERATOR(StatRegistryCreate, StatRegistryCreateOp);
REGISTER_CPU_OPERATOR(StatRegistryUpdate, StatRegistryUpdateOp);
REGISTER_CPU_OPERATOR(StatRegistryExport, StatRegistryExportOp);

REGISTER_CPU_OPERATOR(TimerBegin, TimerBeginOp);
REGISTER_CPU_OPERATOR(TimerEnd, TimerEndOp);
REGISTER_CPU_OPERATOR(TimerGetAndEnd, TimerGetAndEndOp);

OPERATOR_SCHEMA(StatRegistryCreate)
    .NumInputs(0)
    .NumOutputs(1)
    .SetDoc(R"DOC(
Create a StatRegistry object that will contain a map of performance counters
keyed by name. A StatRegistry is used to gather and retrieve performance
counts throuhgout the caffe2 codebase.
)DOC")
    .Output(0, "handle", "A Blob pointing to the newly created StatRegistry.");

OPERATOR_SCHEMA(StatRegistryUpdate)
    .NumInputs(2, 3)
    .NumOutputs(0)
    .SetDoc(R"DOC(
Update the given StatRegistry, or the global StatRegistry,
with the values of counters for the given keys.
)DOC")
    .Input(0, "keys", "1D string tensor with the key names to update.")
    .Input(1, "values", "1D int64 tensor with the values to update.")
    .Input(
        2,
        "handle",
        "If provided, update the given StatRegistry. "
        "Otherwise, update the global singleton.");

OPERATOR_SCHEMA(StatRegistryExport)
    .NumInputs(0, 1)
    .NumOutputs(3)
    .Input(
        0,
        "handle",
        "If provided, export values from given StatRegistry."
        "Otherwise, export values from the global singleton StatRegistry.")
    .Output(0, "keys", "1D string tensor with exported key names")
    .Output(1, "values", "1D int64 tensor with exported values")
    .Output(2, "timestamps", "The unix timestamp at counter retrieval.")
    .Arg(
        "reset",
        "(default true) Whether to atomically reset the counters afterwards.");
}

OPERATOR_SCHEMA(TimerBegin)
    .NumInputs(0)
    .NumOutputs(1)
    .SetDoc(R"DOC(
Start a wallclock timer, returning a pointer to it.
The timer is stopped by calling TimerEnd)DOC")
    .Arg("counter_name", "Name of the timer. If not provided, use output name.")
    .Output(0, "timer", "Pointer to timer, to be passed to TimerEnd.");

OPERATOR_SCHEMA(TimerEnd)
    .NumInputs(1)
    .NumOutputs(0)
    .SetDoc("Stop a timer started with TimerBegin, publishing a CAFFE_EVENT")
    .Input(0, "timer", "Pointer to timer, obtained from TimerBegin.");

OPERATOR_SCHEMA(TimerGetAndEnd)
    .NumInputs(1)
    .NumOutputs(1)
    .SetDoc(R"DOC(Queries the current time of a timer in nanos, stops the timer
            publishing a CAFFE_EVENT)DOC")
    .Input(0, "timer", "Pointer to timer, obtained from TimerBegin.")
    .Output(0, "nanos", "nanoseconds in int64");

CAFFE_KNOWN_TYPE(TimerInstance*);
CAFFE_KNOWN_TYPE(std::unique_ptr<caffe2::StatRegistry>);
} // namespace caffe2
<|endoftext|>


<commit_before>// Copyright 2017 Netherlands Institute for Radio Astronomy (ASTRON)
// Copyright 2017 Netherlands eScience Center
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#pragma once

struct Options
{
    // Debug mode
    bool debug = false;
    // Print messages to standard output
    bool print = false;
    // Use subband dedispersion
    bool subbandDedispersion = false;
    // Avoid merging batches of dispersed data into contiguous memory
    bool splitBatchesDedispersion = false;
    // Compact the triggered events in time and DM dimensions
    bool compactResults = false;
    // Threshold for triggering
    float threshold = 0.0f;
    // SNR mode
    SNRMode snrMode;
    // Step size for median of medians (MOMAD mode)
    unsigned int medianStepSize = 5;
};

struct DeviceOptions
{
    // OpenCL synchronized operations
    bool synchronized = false;
    // OpenCL platform ID
    unsigned int platformID = 0;
    // OpenCL device ID
    unsigned int deviceID = 0;
    // OpenCL device name
    std::string deviceName{};
    // Padding of OpenCL devices
    AstroData::paddingConf padding{};
};

struct DataOptions
{
    // Use LOFAR file as input
    bool dataLOFAR = false;
    // Use SIGPROC file as input
    bool dataSIGPROC = false;
    // Use PSRDADA buffer as input
    bool dataPSRDADA = false;
    // SIGPROC streaming mode
    bool streamingMode = false;
    // Size (in bytes) of the SIGPROC file header
    unsigned int headerSizeSIGPROC = 0;
    // Name of the input file
    std::string dataFile{};
    // Basename for the output files
    std::string outputFile{};
    // Name of the file containing the zapped channels
    std::string channelsFile{};
    // Name of the file containing the integration steps
    std::string integrationFile{};
#ifdef HAVE_HDF5
    // Limit the number of batches processed from a LOFAR file
    bool limit = false;
    // Name of the LOFAR header file
    std::string headerFile{};
#endif // HAVE_HDF5
#ifdef HAVE_PSRDADA
    // PSRDADA buffer key
    key_t dadaKey = 0;
#endif // HAVE_PSRDADA
};

struct GeneratorOptions
{
    // Use random numbers in generated data
    bool random = false;
    // Width of random generated pulse
    unsigned int width = 0;
    // DM of random generated pulse
    float DM = 0.0f;
};

struct HostMemory
{
    // Input data when reading a whole input file
    std::vector<std::vector<std::vector<inputDataType> *> *> input;
    // Input data when in streaming mode
    std::vector<std::vector<inputDataType> *> inputStream;
    // Zapped channels
    std::vector<unsigned int> zappedChannels;
    // Integration steps
    std::set<unsigned int> integrationSteps;
    // Map to create synthesized beams
    std::vector<unsigned int> beamMapping;
    // Dispersed data
    std::vector<inputDataType> dispersedData;
    // Subbanded data
    std::vector<outputDataType> subbandedData;
    // Dedispersed data
    std::vector<outputDataType> dedispersedData;
    // Integrated data
    std::vector<outputDataType> integratedData;
    // SNR data (SNR mode)
    std::vector<float> snrData;
    // Index of the sample with highest SNR value (SNR mode)
    std::vector<unsigned int> snrSamples;
    // Value of max sample (MOMAD mode)
    std::vector<outputDataType> maxValues;
    // Index of max sample (MOMAD MODE)
    std::vector<unsigned int> maxIndices;
    // Medians of medians (MOMAD mode)
    std::vector<outputDataType> mediansOfMedians;
    // Medians of medians absolute deviation (MOMAD mode)
    std::vector<outputDataType> medianOfMediansAbsoluteDeviation;
    // Shifts single step dedispersion
    std::vector<float> *shiftsSingleStep = nullptr;
    // Shifts step one subbanding dedispersion
    std::vector<float> *shiftsStepOne = nullptr;
    // Shifts step two subbanding dedispersion
    std::vector<float> *shiftsStepTwo = nullptr;
#ifdef HAVE_PSRDADA
    // PSRDADA ring buffer
    dada_hdu_t *ringBuffer = nullptr;
#endif // HAVE_PSRDADA
};

struct DeviceMemory
{
    // Shifts single step dedispersion
    cl::Buffer shiftsSingleStep;
    // Shifts step one subbanding dedispersion
    cl::Buffer shiftsStepOne;
    // Shifts step two subbanding dedispersion
    cl::Buffer shiftsStepTwo;
    // Zapped channels
    cl::Buffer zappedChannels;
    // Map to create synthesized beams
    cl::Buffer beamMapping;
    // Dispersed dada
    cl::Buffer dispersedData;
    // Subbanded data
    cl::Buffer subbandedData;
    // Dedispersed data
    cl::Buffer dedispersedData;
    // Integrated data
    cl::Buffer integratedData;
    // SNR data (SNR mode)
    cl::Buffer snrData;
    // Index of the sample with highest SNR value (SNR mode)
    cl::Buffer snrSamples;
    // Value of max sample (MOMAD mode)
    cl::Buffer maxValues;
    // Index of max sample (MOMAD mode)
    cl::Buffer maxIndices;
    // Median of medians first step (MOMAD mode)
    cl::Buffer medianOfMediansStepOne;
    // Median of medians second step (MOMAD mode)
    cl::Buffer medianOfMediansStepTwo;
};

struct KernelConfigurations
{
    // Configuration of single step dedispersion kernel
    Dedispersion::tunedDedispersionConf dedispersionSingleStepParameters;
    // Configuration of subband dedispersion kernel, step one
    Dedispersion::tunedDedispersionConf dedispersionStepOneParameters;
    // Configuration of subband dedispersion kernel, step two
    Dedispersion::tunedDedispersionConf dedispersionStepTwoParameters;
    // Configuration of integration kernel
    Integration::tunedIntegrationConf integrationParameters;
    // Configuration of SNR kernel (SNR mode)
    SNR::tunedSNRConf snrParameters;
    // Configuration of max kernel (MOMAD mode)
    SNR::tunedSNRConf maxParameters;
    // Configuration of median of medians first step (MOMAD mode)
    SNR::tunedSNRConf medianOfMediansStepOneParameters;
    // Configuration of median of medians second step (MOMAD mode)
    SNR::tunedSNRConf medianOfMediansStepTwoParameters;
    // Configuration of median of medians absolute deviation (MOMAD mode)
    SNR::tunedSNRConf medianOfMediansAbsoluteDeviationParameters;
};

struct Kernels
{
    // Single step dedispersion kernel
    cl::Kernel *dedispersionSingleStep = nullptr;
    // Step one subbanding dedispersion kernel
    cl::Kernel *dedispersionStepOne = nullptr;
    // Step two subbanding dedispersion kernel
    cl::Kernel *dedispersionStepTwo = nullptr;
    // Integration kernels, one for each integration step
    std::vector<cl::Kernel *> integration;
    // SNR kernels, one for the original data and one for each integration step (SNR mode)
    std::vector<cl::Kernel *> snr;
    // Max kernels, one for the original data and one for each integration step (MOMAD mode)
    std::vector<cl::Kernel *> max;
    // Median of medians first step, one for the original data and one for each integration step (MOMAD mode)
    std::vector<cl::Kernel *> medianOfMediansStepOne;
    // Median of medians second step, one for the original data and one for each integration step (MOMAD mode)
    std::vector<cl::Kernel *> medianOfMediansStepTwo;
    // Median of medians absolute deviation, one for the original data and one for each integration step (MOMAD mode)
    std::vector<cl::Kernel *> medianOfMediansAbsoluteDeviation;
};

struct KernelRunTimeConfigurations
{
    // Global NDrange for single step dedispersion
    cl::NDRange dedispersionSingleStepGlobal;
    // Local NDRange for single step dedispersion
    cl::NDRange dedispersionSingleStepLocal;
    // Global NDRange for subbanding dedispersion step one
    cl::NDRange dedispersionStepOneGlobal;
    // Local NDRange for subbanding dedispersion step one
    cl::NDRange dedispersionStepOneLocal;
    // Global NDRange for subbanding dedispersion step two
    cl::NDRange dedispersionStepTwoGlobal;
    // Local NDRange for subbanding dedispersion step two
    cl::NDRange dedispersionStepTwoLocal;
    // Global NDRange for integration
    std::vector<cl::NDRange> integrationGlobal;
    // Local NDRange for integration
    std::vector<cl::NDRange> integrationLocal;
    // Global NDRange for SNR (SNR mode)
    std::vector<cl::NDRange> snrGlobal;
    // Local NDRange for SNR (SNR mode)
    std::vector<cl::NDRange> snrLocal;
    // Global NDRange for max (MOMAD mode)
    std::vector<cl::NDRange> maxGlobal;
    // Local NDRange for max (MOMAD mode)
    std::vector<cl::NDRange> maxLocal;
    // Global NDRange for median of medians first step (MOMAD mode)
    std::vector<cl::NDRange> medianOfMediansStepOneGlobal;
    // Local NDRange for median of medians first step (MOMAD mode)
    std::vector<cl::NDRange> medianOfMediansStepOneLocal;
    // Global NDRange for median of medians second step (MOMAD mode)
    std::vector<cl::NDRange> medianOfMediansStepTwoGlobal;
    // Local NDRange for median of medians second step (MOMAD mode)
    std::vector<cl::NDRange> medianOfMediansStepTwoLocal;
    // Global NDRange for median of medians absolute deviation (MOMAD mode)
    std::vector<cl::NDRange> medianOfMediansAbsoluteDeviationGlobal;
    // Local NDRange for median of medians absolute deviation (MOMAD mode)
    std::vector<cl::NDRange> medianOfMediansAbsoluteDeviationLocal;
};

struct Timers
{
    isa::utils::Timer inputLoad;
    isa::utils::Timer search;
    isa::utils::Timer inputHandling;
    isa::utils::Timer inputCopy;
    isa::utils::Timer dedispersionSingleStep;
    isa::utils::Timer dedispersionStepOne;
    isa::utils::Timer dedispersionStepTwo;
    isa::utils::Timer integration;
    isa::utils::Timer snr;
    isa::utils::Timer outputCopy;
    isa::utils::Timer trigger;
};

struct TriggeredEvent
{
    unsigned int beam = 0;
    unsigned int sample = 0;
    unsigned int integration = 0;
    float DM = 0.0f;
    float SNR = 0.0f;
};

struct CompactedEvent : TriggeredEvent
{
    unsigned int compactedIntegration = 1;
    unsigned int compactedDMs = 1;
};

using TriggeredEvents = std::vector<std::map<unsigned int, std::vector<TriggeredEvent>>>;
using CompactedEvents = std::vector<std::vector<CompactedEvent>>;

struct OpenCLRunTime
{
    cl::Context *context = nullptr;
    std::vector<cl::Platform> *platforms = nullptr;
    std::vector<cl::Device> *devices = nullptr;
    std::vector<std::vector<cl::CommandQueue>> *queues = nullptr;
};

enum SNRMode
{
    Standard,
    Momad
};
<commit_msg>Added timers for MOMAD kernels.<commit_after>// Copyright 2017 Netherlands Institute for Radio Astronomy (ASTRON)
// Copyright 2017 Netherlands eScience Center
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#pragma once

struct Options
{
    // Debug mode
    bool debug = false;
    // Print messages to standard output
    bool print = false;
    // Use subband dedispersion
    bool subbandDedispersion = false;
    // Avoid merging batches of dispersed data into contiguous memory
    bool splitBatchesDedispersion = false;
    // Compact the triggered events in time and DM dimensions
    bool compactResults = false;
    // Threshold for triggering
    float threshold = 0.0f;
    // SNR mode
    SNRMode snrMode;
    // Step size for median of medians (MOMAD mode)
    unsigned int medianStepSize = 5;
};

struct DeviceOptions
{
    // OpenCL synchronized operations
    bool synchronized = false;
    // OpenCL platform ID
    unsigned int platformID = 0;
    // OpenCL device ID
    unsigned int deviceID = 0;
    // OpenCL device name
    std::string deviceName{};
    // Padding of OpenCL devices
    AstroData::paddingConf padding{};
};

struct DataOptions
{
    // Use LOFAR file as input
    bool dataLOFAR = false;
    // Use SIGPROC file as input
    bool dataSIGPROC = false;
    // Use PSRDADA buffer as input
    bool dataPSRDADA = false;
    // SIGPROC streaming mode
    bool streamingMode = false;
    // Size (in bytes) of the SIGPROC file header
    unsigned int headerSizeSIGPROC = 0;
    // Name of the input file
    std::string dataFile{};
    // Basename for the output files
    std::string outputFile{};
    // Name of the file containing the zapped channels
    std::string channelsFile{};
    // Name of the file containing the integration steps
    std::string integrationFile{};
#ifdef HAVE_HDF5
    // Limit the number of batches processed from a LOFAR file
    bool limit = false;
    // Name of the LOFAR header file
    std::string headerFile{};
#endif // HAVE_HDF5
#ifdef HAVE_PSRDADA
    // PSRDADA buffer key
    key_t dadaKey = 0;
#endif // HAVE_PSRDADA
};

struct GeneratorOptions
{
    // Use random numbers in generated data
    bool random = false;
    // Width of random generated pulse
    unsigned int width = 0;
    // DM of random generated pulse
    float DM = 0.0f;
};

struct HostMemory
{
    // Input data when reading a whole input file
    std::vector<std::vector<std::vector<inputDataType> *> *> input;
    // Input data when in streaming mode
    std::vector<std::vector<inputDataType> *> inputStream;
    // Zapped channels
    std::vector<unsigned int> zappedChannels;
    // Integration steps
    std::set<unsigned int> integrationSteps;
    // Map to create synthesized beams
    std::vector<unsigned int> beamMapping;
    // Dispersed data
    std::vector<inputDataType> dispersedData;
    // Subbanded data
    std::vector<outputDataType> subbandedData;
    // Dedispersed data
    std::vector<outputDataType> dedispersedData;
    // Integrated data
    std::vector<outputDataType> integratedData;
    // SNR data (SNR mode)
    std::vector<float> snrData;
    // Index of the sample with highest SNR value (SNR mode)
    std::vector<unsigned int> snrSamples;
    // Value of max sample (MOMAD mode)
    std::vector<outputDataType> maxValues;
    // Index of max sample (MOMAD MODE)
    std::vector<unsigned int> maxIndices;
    // Medians of medians (MOMAD mode)
    std::vector<outputDataType> mediansOfMedians;
    // Medians of medians absolute deviation (MOMAD mode)
    std::vector<outputDataType> medianOfMediansAbsoluteDeviation;
    // Shifts single step dedispersion
    std::vector<float> *shiftsSingleStep = nullptr;
    // Shifts step one subbanding dedispersion
    std::vector<float> *shiftsStepOne = nullptr;
    // Shifts step two subbanding dedispersion
    std::vector<float> *shiftsStepTwo = nullptr;
#ifdef HAVE_PSRDADA
    // PSRDADA ring buffer
    dada_hdu_t *ringBuffer = nullptr;
#endif // HAVE_PSRDADA
};

struct DeviceMemory
{
    // Shifts single step dedispersion
    cl::Buffer shiftsSingleStep;
    // Shifts step one subbanding dedispersion
    cl::Buffer shiftsStepOne;
    // Shifts step two subbanding dedispersion
    cl::Buffer shiftsStepTwo;
    // Zapped channels
    cl::Buffer zappedChannels;
    // Map to create synthesized beams
    cl::Buffer beamMapping;
    // Dispersed dada
    cl::Buffer dispersedData;
    // Subbanded data
    cl::Buffer subbandedData;
    // Dedispersed data
    cl::Buffer dedispersedData;
    // Integrated data
    cl::Buffer integratedData;
    // SNR data (SNR mode)
    cl::Buffer snrData;
    // Index of the sample with highest SNR value (SNR mode)
    cl::Buffer snrSamples;
    // Value of max sample (MOMAD mode)
    cl::Buffer maxValues;
    // Index of max sample (MOMAD mode)
    cl::Buffer maxIndices;
    // Median of medians first step (MOMAD mode)
    cl::Buffer medianOfMediansStepOne;
    // Median of medians second step (MOMAD mode)
    cl::Buffer medianOfMediansStepTwo;
};

struct KernelConfigurations
{
    // Configuration of single step dedispersion kernel
    Dedispersion::tunedDedispersionConf dedispersionSingleStepParameters;
    // Configuration of subband dedispersion kernel, step one
    Dedispersion::tunedDedispersionConf dedispersionStepOneParameters;
    // Configuration of subband dedispersion kernel, step two
    Dedispersion::tunedDedispersionConf dedispersionStepTwoParameters;
    // Configuration of integration kernel
    Integration::tunedIntegrationConf integrationParameters;
    // Configuration of SNR kernel (SNR mode)
    SNR::tunedSNRConf snrParameters;
    // Configuration of max kernel (MOMAD mode)
    SNR::tunedSNRConf maxParameters;
    // Configuration of median of medians first step (MOMAD mode)
    SNR::tunedSNRConf medianOfMediansStepOneParameters;
    // Configuration of median of medians second step (MOMAD mode)
    SNR::tunedSNRConf medianOfMediansStepTwoParameters;
    // Configuration of median of medians absolute deviation (MOMAD mode)
    SNR::tunedSNRConf medianOfMediansAbsoluteDeviationParameters;
};

struct Kernels
{
    // Single step dedispersion kernel
    cl::Kernel *dedispersionSingleStep = nullptr;
    // Step one subbanding dedispersion kernel
    cl::Kernel *dedispersionStepOne = nullptr;
    // Step two subbanding dedispersion kernel
    cl::Kernel *dedispersionStepTwo = nullptr;
    // Integration kernels, one for each integration step
    std::vector<cl::Kernel *> integration;
    // SNR kernels, one for the original data and one for each integration step (SNR mode)
    std::vector<cl::Kernel *> snr;
    // Max kernels, one for the original data and one for each integration step (MOMAD mode)
    std::vector<cl::Kernel *> max;
    // Median of medians first step, one for the original data and one for each integration step (MOMAD mode)
    std::vector<cl::Kernel *> medianOfMediansStepOne;
    // Median of medians second step, one for the original data and one for each integration step (MOMAD mode)
    std::vector<cl::Kernel *> medianOfMediansStepTwo;
    // Median of medians absolute deviation, one for the original data and one for each integration step (MOMAD mode)
    std::vector<cl::Kernel *> medianOfMediansAbsoluteDeviation;
};

struct KernelRunTimeConfigurations
{
    // Global NDrange for single step dedispersion
    cl::NDRange dedispersionSingleStepGlobal;
    // Local NDRange for single step dedispersion
    cl::NDRange dedispersionSingleStepLocal;
    // Global NDRange for subbanding dedispersion step one
    cl::NDRange dedispersionStepOneGlobal;
    // Local NDRange for subbanding dedispersion step one
    cl::NDRange dedispersionStepOneLocal;
    // Global NDRange for subbanding dedispersion step two
    cl::NDRange dedispersionStepTwoGlobal;
    // Local NDRange for subbanding dedispersion step two
    cl::NDRange dedispersionStepTwoLocal;
    // Global NDRange for integration
    std::vector<cl::NDRange> integrationGlobal;
    // Local NDRange for integration
    std::vector<cl::NDRange> integrationLocal;
    // Global NDRange for SNR (SNR mode)
    std::vector<cl::NDRange> snrGlobal;
    // Local NDRange for SNR (SNR mode)
    std::vector<cl::NDRange> snrLocal;
    // Global NDRange for max (MOMAD mode)
    std::vector<cl::NDRange> maxGlobal;
    // Local NDRange for max (MOMAD mode)
    std::vector<cl::NDRange> maxLocal;
    // Global NDRange for median of medians first step (MOMAD mode)
    std::vector<cl::NDRange> medianOfMediansStepOneGlobal;
    // Local NDRange for median of medians first step (MOMAD mode)
    std::vector<cl::NDRange> medianOfMediansStepOneLocal;
    // Global NDRange for median of medians second step (MOMAD mode)
    std::vector<cl::NDRange> medianOfMediansStepTwoGlobal;
    // Local NDRange for median of medians second step (MOMAD mode)
    std::vector<cl::NDRange> medianOfMediansStepTwoLocal;
    // Global NDRange for median of medians absolute deviation (MOMAD mode)
    std::vector<cl::NDRange> medianOfMediansAbsoluteDeviationGlobal;
    // Local NDRange for median of medians absolute deviation (MOMAD mode)
    std::vector<cl::NDRange> medianOfMediansAbsoluteDeviationLocal;
};

struct Timers
{
    isa::utils::Timer inputLoad;
    isa::utils::Timer search;
    isa::utils::Timer inputHandling;
    isa::utils::Timer inputCopy;
    isa::utils::Timer dedispersionSingleStep;
    isa::utils::Timer dedispersionStepOne;
    isa::utils::Timer dedispersionStepTwo;
    isa::utils::Timer integration;
    isa::utils::Timer snr;
    isa::utils::Timer max;
    isa::utils::Timer medianOfMediansStepOne;
    isa::utils::Timer medianOfMediansStepTwo;
    isa::utils::Timer medianOfMediansAbsoluteDeviationStepOne;
    isa::utils::Timer medianOfMediansAbsoluteDeviationStepTwo;
    isa::utils::Timer outputCopy;
    isa::utils::Timer trigger;
};

struct TriggeredEvent
{
    unsigned int beam = 0;
    unsigned int sample = 0;
    unsigned int integration = 0;
    float DM = 0.0f;
    float SNR = 0.0f;
};

struct CompactedEvent : TriggeredEvent
{
    unsigned int compactedIntegration = 1;
    unsigned int compactedDMs = 1;
};

using TriggeredEvents = std::vector<std::map<unsigned int, std::vector<TriggeredEvent>>>;
using CompactedEvents = std::vector<std::vector<CompactedEvent>>;

struct OpenCLRunTime
{
    cl::Context *context = nullptr;
    std::vector<cl::Platform> *platforms = nullptr;
    std::vector<cl::Device> *devices = nullptr;
    std::vector<std::vector<cl::CommandQueue>> *queues = nullptr;
};

enum SNRMode
{
    Standard,
    Momad
};
<|endoftext|>


<commit_before>// Copyright (c) 2011 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "crypto/hmac.h"

#include <nss.h>
#include <pk11pub.h>

#include "base/logging.h"
#include "base/memory/scoped_ptr.h"
#include "crypto/nss_util.h"
#include "crypto/scoped_nss_types.h"

namespace crypto {

struct HMACPlatformData {
  CK_MECHANISM_TYPE mechanism_;
  ScopedPK11Slot slot_;
  ScopedPK11SymKey sym_key_;
};

HMAC::HMAC(HashAlgorithm hash_alg)
    : hash_alg_(hash_alg), plat_(new HMACPlatformData()) {
  // Only SHA-1 and SHA-256 hash algorithms are supported.
  switch (hash_alg_) {
    case SHA1:
      plat_->mechanism_ = CKM_SHA_1_HMAC;
      break;
    case SHA256:
      plat_->mechanism_ = CKM_SHA256_HMAC;
      break;
    default:
      NOTREACHED() << "Unsupported hash algorithm";
      break;
  }
}

HMAC::~HMAC() {
}

bool HMAC::Init(const unsigned char *key, int key_length) {
  EnsureNSSInit();

  if (plat_->slot_.get()) {
    // Init must not be called more than twice on the same HMAC object.
    NOTREACHED();
    return false;
  }

  plat_->slot_.reset(PK11_GetBestSlot(plat_->mechanism_, NULL));
  if (!plat_->slot_.get()) {
    NOTREACHED();
    return false;
  }

  SECItem key_item;
  key_item.type = siBuffer;
  key_item.data = const_cast<unsigned char*>(key);  // NSS API isn't const.
  key_item.len = key_length;

  plat_->sym_key_.reset(PK11_ImportSymKey(plat_->slot_.get(),
                                          plat_->mechanism_,
                                          PK11_OriginUnwrap,
                                          CKA_SIGN,
                                          &key_item,
                                          NULL));
  if (!plat_->sym_key_.get()) {
    NOTREACHED();
    return false;
  }

  return true;
}

bool HMAC::Sign(const base::StringPiece& data,
                unsigned char* digest,
                int digest_length) const {
  if (!plat_->sym_key_.get()) {
    // Init has not been called before Sign.
    NOTREACHED();
    return false;
  }

  SECItem param = { siBuffer, NULL, 0 };
  ScopedPK11Context context(PK11_CreateContextBySymKey(plat_->mechanism_,
                                                       CKA_SIGN,
                                                       plat_->sym_key_.get(),
                                                       &param));
  if (!context.get()) {
    NOTREACHED();
    return false;
  }

  if (PK11_DigestBegin(context.get()) != SECSuccess) {
    NOTREACHED();
    return false;
  }

  if (PK11_DigestOp(context.get(),
                    reinterpret_cast<const unsigned char*>(data.data()),
                    data.length()) != SECSuccess) {
    NOTREACHED();
    return false;
  }

  unsigned int len = 0;
  if (PK11_DigestFinal(context.get(),
                       digest, &len, digest_length) != SECSuccess) {
    NOTREACHED();
    return false;
  }

  return true;
}

}  // namespace crypto
<commit_msg>Fixed slot selection in HMAC class to ensure that we are using softtoken instead of TPM slots.<commit_after>// Copyright (c) 2011 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "crypto/hmac.h"

#include <nss.h>
#include <pk11pub.h>

#include "base/logging.h"
#include "base/memory/scoped_ptr.h"
#include "crypto/nss_util.h"
#include "crypto/scoped_nss_types.h"

namespace crypto {

struct HMACPlatformData {
  CK_MECHANISM_TYPE mechanism_;
  ScopedPK11Slot slot_;
  ScopedPK11SymKey sym_key_;
};

HMAC::HMAC(HashAlgorithm hash_alg)
    : hash_alg_(hash_alg), plat_(new HMACPlatformData()) {
  // Only SHA-1 and SHA-256 hash algorithms are supported.
  switch (hash_alg_) {
    case SHA1:
      plat_->mechanism_ = CKM_SHA_1_HMAC;
      break;
    case SHA256:
      plat_->mechanism_ = CKM_SHA256_HMAC;
      break;
    default:
      NOTREACHED() << "Unsupported hash algorithm";
      break;
  }
}

HMAC::~HMAC() {
}

bool HMAC::Init(const unsigned char *key, int key_length) {
  EnsureNSSInit();

  if (plat_->slot_.get()) {
    // Init must not be called more than twice on the same HMAC object.
    NOTREACHED();
    return false;
  }

  plat_->slot_.reset(PK11_GetInternalSlot());
  if (!plat_->slot_.get()) {
    NOTREACHED();
    return false;
  }

  SECItem key_item;
  key_item.type = siBuffer;
  key_item.data = const_cast<unsigned char*>(key);  // NSS API isn't const.
  key_item.len = key_length;

  plat_->sym_key_.reset(PK11_ImportSymKey(plat_->slot_.get(),
                                          plat_->mechanism_,
                                          PK11_OriginUnwrap,
                                          CKA_SIGN,
                                          &key_item,
                                          NULL));
  if (!plat_->sym_key_.get()) {
    NOTREACHED();
    return false;
  }

  return true;
}

bool HMAC::Sign(const base::StringPiece& data,
                unsigned char* digest,
                int digest_length) const {
  if (!plat_->sym_key_.get()) {
    // Init has not been called before Sign.
    NOTREACHED();
    return false;
  }

  SECItem param = { siBuffer, NULL, 0 };
  ScopedPK11Context context(PK11_CreateContextBySymKey(plat_->mechanism_,
                                                       CKA_SIGN,
                                                       plat_->sym_key_.get(),
                                                       &param));
  if (!context.get()) {
    NOTREACHED();
    return false;
  }

  if (PK11_DigestBegin(context.get()) != SECSuccess) {
    NOTREACHED();
    return false;
  }

  if (PK11_DigestOp(context.get(),
                    reinterpret_cast<const unsigned char*>(data.data()),
                    data.length()) != SECSuccess) {
    LOG(WARNING) << "PK11_DigestOp failed, error " << PORT_GetError()
                 << ", slot name " << PK11_GetSlotName(plat_->slot_.get())
                 << ", token name " << PK11_GetTokenName(plat_->slot_.get());
    NOTREACHED();
    return false;
  }

  unsigned int len = 0;
  if (PK11_DigestFinal(context.get(),
                       digest, &len, digest_length) != SECSuccess) {
    NOTREACHED();
    return false;
  }

  return true;
}

}  // namespace crypto
<|endoftext|>


<commit_before>/* Siconos-Kernel, Copyright INRIA 2005-2012.
* Siconos is a program dedicated to modeling, simulation and control
* of non smooth dynamical systems.
* Siconos is a free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
* Siconos 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Siconos; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
*
* Contact: Vincent ACARY, siconos-team@lists.gforge.inria.fr
*/

/*! \file Question.hpp
  \brief ask something to a class with a visitor */

/** example :
 *
 * struct ForMass : public Question<SP::SiconosMatrix>
 * {
 *    void visit(const LagrangianDS& ds)
 *    {
 *       Question::answer = ds.mass();
 *    }
 *
 * }
 * SP::DynamicalSystem ds
 * [...]
 *
 * SP::SiconosMatrix mass = ask<ForMass>(*ds);
 */

/* use boost array for the initialization of non const reference */
//#include <boost/type_traits.hpp>

#ifndef Question_hpp
#define Question_hpp

#include "SiconosVisitor.hpp"

#if (__cplusplus >= 201103L) && !defined(USE_BOOST_FOR_CXX11)
#include <type_traits>
#include <array>
#else
#include <boost/type_traits/remove_reference.hpp>
#include <boost/array.hpp>
#endif

/** a generic return value visitor */
template <class AnswerType>
struct Question : public SiconosVisitor
{
  typedef AnswerType type;
  type answer;

  Question() : answer(std11::array<typename std11::remove_reference<AnswerType>::type, 1>()[0])
  {};
  Question(AnswerType ref) : answer(ref) {};

};

/** get some value from a visitable object with the help of a
    GeneralQuestion
    \param v a visitable object
 */
template <class GeneralQuestion, class Visitable>
typename GeneralQuestion::type ask(const Visitable& v)
{
  GeneralQuestion t;

  v.accept(t);

  return t.answer;

}

/** get some value from a visitable object with the help of a
    parameterized GeneralQuestion
    \param v a visitable object
    \param arg the GeneralQuestion argument
 */
template <class GeneralQuestion, class Visitable, class Argument>
typename GeneralQuestion::type ask(const Visitable& v, const Argument& arg)
{
  GeneralQuestion t(arg);

  v.accept(t);

  return t.answer;

}

/** apply a SiconosVisitor to a visitable object
 * \param v a visitable object
 */
template <class Visitor, class Visitable>
void apply(const Visitable& v)
{
  static Visitor t;

  v.accept(t);

}

/** apply a parameterized SiconosVisitor to a visitable object
 * \param v a visitable object
 * \param arg the SiconosVisitor argument
 */
template <class VisitorWithArgument, class Visitable, class Argument>
void apply(const Visitable& v, const Argument& arg)
{
  VisitorWithArgument t(arg);

  v.accept(t);

}

/** apply a parameterized SiconosVisitor to a visitable object
 * \param v a visitable object
 * \param arg1 the first SiconosVisitor argument
 * \param arg2 the second SiconosVisitor argument
 */
template <class VisitorWith2Arguments, class Visitable, class Argument1, class Argument2>
void apply(const Visitable& v, const Argument1& arg1, const Argument2& arg2)
{
  VisitorWith2Arguments t(arg1, arg2);

  v.accept(t);

}

#define ANSWER(T,CODE)                          \
  void visit(const T& ds)                       \
  {                                             \
    answer = ds . CODE;                         \
  }

#define ANSWER_V(T,CODE)                        \
  void visit(const T& ds)                       \
  {                                             \
    answer = CODE;                              \
  }

#define ANSWER_F(T,CODE)                        \
  void visit(const T& ds)                       \
  {                                             \
    answer = CODE(ds);                          \
  }

#endif
<commit_msg>Revert "Remove declaration using SiconosVisitor::visit; to avoid double declaration"<commit_after>/* Siconos-Kernel, Copyright INRIA 2005-2012.
* Siconos is a program dedicated to modeling, simulation and control
* of non smooth dynamical systems.
* Siconos is a free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
* Siconos 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Siconos; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
*
* Contact: Vincent ACARY, siconos-team@lists.gforge.inria.fr
*/

/*! \file Question.hpp
  \brief ask something to a class with a visitor */

/** example :
 *
 * struct ForMass : public Question<SP::SiconosMatrix>
 * {
 *    void visit(const LagrangianDS& ds)
 *    {
 *       Question::answer = ds.mass();
 *    }
 *
 * }
 * SP::DynamicalSystem ds
 * [...]
 *
 * SP::SiconosMatrix mass = ask<ForMass>(*ds);
 */

/* use boost array for the initialization of non const reference */
//#include <boost/type_traits.hpp>

#ifndef Question_hpp
#define Question_hpp

#include "SiconosVisitor.hpp"

#if (__cplusplus >= 201103L) && !defined(USE_BOOST_FOR_CXX11)
#include <type_traits>
#include <array>
#else
#include <boost/type_traits/remove_reference.hpp>
#include <boost/array.hpp>
#endif

/** a generic return value visitor */
template <class AnswerType>
struct Question : public SiconosVisitor
{
  typedef AnswerType type;
  type answer;

  Question() : answer(std11::array<typename std11::remove_reference<AnswerType>::type, 1>()[0])
  {};
  Question(AnswerType ref) : answer(ref) {};

};

/** get some value from a visitable object with the help of a
    GeneralQuestion
    \param v a visitable object
 */
template <class GeneralQuestion, class Visitable>
typename GeneralQuestion::type ask(const Visitable& v)
{
  GeneralQuestion t;

  v.accept(t);

  return t.answer;

}

/** get some value from a visitable object with the help of a
    parameterized GeneralQuestion
    \param v a visitable object
    \param arg the GeneralQuestion argument
 */
template <class GeneralQuestion, class Visitable, class Argument>
typename GeneralQuestion::type ask(const Visitable& v, const Argument& arg)
{
  GeneralQuestion t(arg);

  v.accept(t);

  return t.answer;

}

/** apply a SiconosVisitor to a visitable object
 * \param v a visitable object
 */
template <class Visitor, class Visitable>
void apply(const Visitable& v)
{
  static Visitor t;

  v.accept(t);

}

/** apply a parameterized SiconosVisitor to a visitable object
 * \param v a visitable object
 * \param arg the SiconosVisitor argument
 */
template <class VisitorWithArgument, class Visitable, class Argument>
void apply(const Visitable& v, const Argument& arg)
{
  VisitorWithArgument t(arg);

  v.accept(t);

}

/** apply a parameterized SiconosVisitor to a visitable object
 * \param v a visitable object
 * \param arg1 the first SiconosVisitor argument
 * \param arg2 the second SiconosVisitor argument
 */
template <class VisitorWith2Arguments, class Visitable, class Argument1, class Argument2>
void apply(const Visitable& v, const Argument1& arg1, const Argument2& arg2)
{
  VisitorWith2Arguments t(arg1, arg2);

  v.accept(t);

}

#define ANSWER(T,CODE)                          \
  using SiconosVisitor::visit;                  \
  void visit(const T& ds)                       \
  {                                             \
    answer = ds . CODE;                         \
  }

#define ANSWER_V(T,CODE)                        \
  using SiconosVisitor::visit;                  \
  void visit(const T& ds)                       \
  {                                             \
    answer = CODE;                              \
  }

#define ANSWER_F(T,CODE)                        \
  using SiconosVisitor::visit;                  \
  void visit(const T& ds)                       \
  {                                             \
    answer = CODE(ds);                          \
  }

#endif
<|endoftext|>


<commit_before>/*
    Realm of Aesir client
    Copyright (C) 2016  Michael de Lang

    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU Affero General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    This program 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 Affero General Public License for more details.

    You should have received a copy of the GNU Affero General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/

#include "sprite.h"

#include <array>
#include <SDL.h>
#include <SDL_opengl.h>
#include <SDL_image.h>
#include <glm/gtc/type_ptr.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include <easylogging++.h>

#include "shader_utils.h"
#include "texture_manager.h"

using namespace std;

#ifdef EXPERIMENTAL_OPTIONAL
using namespace experimental;
#endif

sprite::sprite(string const & image, string const & vertex_shader, string const & fragment_shader,
    glm::mat4 const projection_matrix, glm::vec4 const position, optional<glm::vec4> const clip) noexcept
     : _image(image), _texture(create_texture_from_image(image)) {

    _program_id = create_shader_program(vertex_shader, fragment_shader);
    _projection = projection_matrix;

    array<GLfloat, 16> vertexData;
    if(clip) {
        if(clip.value().x < 0 || clip.value().x > _texture._width || clip.value().y < 0 || clip.value().y > _texture._height) {
            LOG(FATAL) << "clip out of bounds";
        }

        float x = position.x;
        float y = position.y;
        float w = position.z;
        float h = position.w;

        LOG(INFO) << "[sprite] " << x << " " << y << " " << w << " " << h << endl;

        vertexData = {
            x, y, 0.0f, 0.0f,
            x+w, y, 1.0f, 0.0f,
            x, y, 0.0f, 1.0f,
            x+y, y+h, 1.0f, 1.0f
        };

        vertexData[2] = clip.value().x / _texture._width;
        vertexData[3] = clip.value().y / _texture._height;

        vertexData[6] = (clip.value().x + clip.value().z) / _texture._width;
        vertexData[7] = clip.value().y / _texture._height;

        vertexData[10] = clip.value().x / _texture._width;
        vertexData[11] = (clip.value().y + clip.value().w) / _texture._height;

        vertexData[14] = (clip.value().x + clip.value().z) / _texture._width;
        vertexData[15] = (clip.value().y + clip.value().w) / _texture._height;
    } else {
        vertexData = {
            0.0f, 0.0f, 0.0f, 0.0f,
            1.0f, 0.0f, 1.0f, 0.0f,
            0.0f, 1.0f, 0.0f, 1.0f,
            1.0f, 1.0f, 1.0f, 1.0f
        };
    }

    glGenBuffers(1, &_buffer_object);
    glGenVertexArrays(1, &_vertex_array_id);
    glBindVertexArray(_vertex_array_id);

    glBindBuffer(GL_ARRAY_BUFFER, _buffer_object);
    glBufferData(GL_ARRAY_BUFFER, sizeof(vertexData), vertexData.data(), GL_DYNAMIC_DRAW);

    glEnableVertexAttribArray(0);
    glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 4 * sizeof(GLfloat), (GLvoid*)0);

    glEnableVertexAttribArray(1);
    glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 4 * sizeof(GLfloat), (GLvoid*)(2 * sizeof(GLfloat)));

    glBindVertexArray(0);

    glUseProgram(_program_id);

    _projection_location = glGetUniformLocation(_program_id, "projection");
    if(_projection_location < 0) {
        LOG(FATAL) << "[tile] projection location not found in shader" << endl;
    }
    glUniformMatrix4fv(_projection_location, 1, GL_FALSE, glm::value_ptr(_projection));

    _textureunit_location = glGetUniformLocation(_program_id, "textureUnit");
    if(_textureunit_location < 0) {
        LOG(FATAL) << "[tile] textureUnit not found in shader" << endl;
    }
    glUniform1i(_textureunit_location, GL_TEXTURE0);

    glUseProgram(0);
}

sprite::~sprite() noexcept {
    glDeleteBuffers(1, &_buffer_object);
    glDeleteProgram(_program_id);
    delete_texture(_image);
}

void sprite::render() const noexcept {
    //LOG(INFO) << "[tile] rendering " << _program_id << " - " << _texture_id << " - " << _buffer_object << endl;
    glUseProgram(_program_id);

    glActiveTexture(GL_TEXTURE0);

    glBindTexture(GL_TEXTURE_2D, _texture._texture_id);
    glBindVertexArray(_vertex_array_id);

    glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);

    glBindVertexArray(0);

    glUseProgram(0);
}

void sprite::set_projection(glm::mat4& projection) noexcept {
    _projection = projection;
    glUniformMatrix4fv(_projection_location, 1, GL_FALSE, glm::value_ptr(_projection));
}
<commit_msg>Fix vertex data error<commit_after>/*
    Realm of Aesir client
    Copyright (C) 2016  Michael de Lang

    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU Affero General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    This program 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 Affero General Public License for more details.

    You should have received a copy of the GNU Affero General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/

#include "sprite.h"

#include <array>
#include <SDL.h>
#include <SDL_opengl.h>
#include <SDL_image.h>
#include <glm/gtc/type_ptr.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include <easylogging++.h>

#include "shader_utils.h"
#include "texture_manager.h"

using namespace std;

#ifdef EXPERIMENTAL_OPTIONAL
using namespace experimental;
#endif

sprite::sprite(string const & image, string const & vertex_shader, string const & fragment_shader,
    glm::mat4 const projection_matrix, glm::vec4 const position, optional<glm::vec4> const clip) noexcept
     : _image(image), _texture(create_texture_from_image(image)) {

    _program_id = create_shader_program(vertex_shader, fragment_shader);
    _projection = projection_matrix;

    array<GLfloat, 16> vertexData;

    float x = position.x;
    float y = position.y;
    float w = position.z;
    float h = position.w;

    vertexData = {
        x, y, 0.0f, 0.0f,
        x+w, y, 1.0f, 0.0f,
        x, y+h, 0.0f, 1.0f,
        x+w, y+h, 1.0f, 1.0f
    };

    if(clip) {
        if(clip.value().x < 0 || clip.value().x > _texture._width || clip.value().y < 0 || clip.value().y > _texture._height) {
            LOG(FATAL) << "clip out of bounds";
        }

        vertexData[2] = clip.value().x / _texture._width;
        vertexData[3] = clip.value().y / _texture._height;

        vertexData[6] = (clip.value().x + clip.value().z) / _texture._width;
        vertexData[7] = clip.value().y / _texture._height;

        vertexData[10] = clip.value().x / _texture._width;
        vertexData[11] = (clip.value().y + clip.value().w) / _texture._height;

        vertexData[14] = (clip.value().x + clip.value().z) / _texture._width;
        vertexData[15] = (clip.value().y + clip.value().w) / _texture._height;
    }

    glGenBuffers(1, &_buffer_object);
    glGenVertexArrays(1, &_vertex_array_id);
    glBindVertexArray(_vertex_array_id);

    glBindBuffer(GL_ARRAY_BUFFER, _buffer_object);
    glBufferData(GL_ARRAY_BUFFER, sizeof(vertexData), vertexData.data(), GL_DYNAMIC_DRAW);

    glEnableVertexAttribArray(0);
    glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 4 * sizeof(GLfloat), (GLvoid*)0);

    glEnableVertexAttribArray(1);
    glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 4 * sizeof(GLfloat), (GLvoid*)(2 * sizeof(GLfloat)));

    glBindVertexArray(0);

    glUseProgram(_program_id);

    _projection_location = glGetUniformLocation(_program_id, "projection");
    if(_projection_location < 0) {
        LOG(FATAL) << "[tile] projection location not found in shader" << endl;
    }
    glUniformMatrix4fv(_projection_location, 1, GL_FALSE, glm::value_ptr(_projection));

    _textureunit_location = glGetUniformLocation(_program_id, "textureUnit");
    if(_textureunit_location < 0) {
        LOG(FATAL) << "[tile] textureUnit not found in shader" << endl;
    }
    glUniform1i(_textureunit_location, GL_TEXTURE0);

    glUseProgram(0);
}

sprite::~sprite() noexcept {
    glDeleteBuffers(1, &_buffer_object);
    glDeleteProgram(_program_id);
    delete_texture(_image);
}

void sprite::render() const noexcept {
    //LOG(INFO) << "[tile] rendering " << _program_id << " - " << _texture_id << " - " << _buffer_object << endl;
    glUseProgram(_program_id);

    glActiveTexture(GL_TEXTURE0);

    glBindTexture(GL_TEXTURE_2D, _texture._texture_id);
    glBindVertexArray(_vertex_array_id);

    glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);

    glBindVertexArray(0);

    glUseProgram(0);
}

void sprite::set_projection(glm::mat4& projection) noexcept {
    _projection = projection;
    glUniformMatrix4fv(_projection_location, 1, GL_FALSE, glm::value_ptr(_projection));
}
<|endoftext|>


<commit_before><commit_msg>INTEGRATION: CWS canvas05 (1.13.2); FILE MERGED 2008/04/21 07:31:09 thb 1.13.2.3: RESYNC: (1.13-1.14); FILE MERGED 2007/12/20 22:18:58 thb 1.13.2.2: #i81092# #i78888# #i78925# #i79258# #i79437# #i84784# Large canvas rework, completing various areas such as color spaces, bitmap data access, true sprite and non-sprite implementations, and upstreaming the canvas parts of rodos emf+ rendering 2007/10/01 13:02:02 thb 1.13.2.1: #i78888# #i78925# #i79258# #i79437# Merge from CWS picom<commit_after><|endoftext|>


<commit_before>template<typename T>
T* newCopiedArray(const T* source, size_t source_count, size_t destination_size) /*strong*/
{
	T* new_array = nullptr;
	try {
		new_array = new T[destination_size];
		std::copy(source, source + source_count, new_array); //Throws if an element assignment throws
	}
	catch (...) {
		delete[] new_array;
		throw;
	}
	return new_array;
}

template <typename T>
class allocator
{
protected:
	allocator(size_t size = 0);
	~allocator();
	auto swap(allocator & other) -> void;

	allocator(allocator const &) = delete;
	auto operator =(allocator const &)->allocator & = delete;

	T * ptr_;
	size_t size_;
	size_t count_;
};

template<typename T>
allocator<T>::allocator(size_t size = 0)
{
	ptr_ = new T[size];
}

template<typename T>
allocator<T>::~allocator()
{
	delete[] ptr_;
}

template<typename T>
auto allocator<T>::swap(allocator & other) -> void
{
	if (count_ > other.size_ || other.count_ > size_) {

	}
}
<commit_msg>size_t size = 0 ==> size_t size<commit_after>template<typename T>
T* newCopiedArray(const T* source, size_t source_count, size_t destination_size) /*strong*/
{
	T* new_array = nullptr;
	try {
		new_array = new T[destination_size];
		std::copy(source, source + source_count, new_array); //Throws if an element assignment throws
	}
	catch (...) {
		delete[] new_array;
		throw;
	}
	return new_array;
}

template <typename T>
class allocator
{
protected:
	allocator(size_t size = 0);
	~allocator();
	auto swap(allocator & other) -> void;

	allocator(allocator const &) = delete;
	auto operator =(allocator const &)->allocator & = delete;

	T * ptr_;
	size_t size_;
	size_t count_;
};

template<typename T>
allocator<T>::allocator(size_t size)
{
	ptr_ = new T[size];
}

template<typename T>
allocator<T>::~allocator()
{
	delete[] ptr_;
}

template<typename T>
auto allocator<T>::swap(allocator & other) -> void
{
	if (count_ > other.size_ || other.count_ > size_) {

	}
}
<|endoftext|>