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

#include "openmc/cell.h"
#include "openmc/constants.h"
#include "openmc/error.h"
#include "openmc/file_utils.h"
#include "openmc/geometry.h"
#include "openmc/geometry_aux.h"
#include "openmc/material.h"
#include "openmc/string_utils.h"
#include "openmc/settings.h"
#include "openmc/surface.h"

#ifdef DAGMC
#include "uwuw.hpp"
#include "dagmcmetadata.hpp"
#endif
#include <fmt/core.h>

#include <string>
#include <sstream>
#include <algorithm>
#include <fstream>

namespace openmc {

#ifdef DAGMC
const bool dagmc_enabled = true;
#else
const bool dagmc_enabled = false;
#endif

}

#ifdef DAGMC

namespace openmc {

const std::string DAGMC_FILENAME = "dagmc.h5m";

namespace model {

moab::DagMC* DAG;

} // namespace model

std::string dagmc_file() {
  std::string filename = settings::path_input + DAGMC_FILENAME;
  if (!file_exists(filename)) {
    fatal_error("Geometry DAGMC file '" + filename + "' does not exist!");
  }
  return filename;
}

bool get_uwuw_materials_xml(std::string& s) {
  std::string filename = dagmc_file();
  UWUW uwuw(filename.c_str());

  std::stringstream ss;
  bool uwuw_mats_present = false;
  if (uwuw.material_library.size() != 0) {
    uwuw_mats_present = true;
    // write header
    ss << "<?xml version=\"1.0\"?>\n";
    ss << "<materials>\n";
    const auto& mat_lib = uwuw.material_library;
    // write materials
    for (auto mat : mat_lib) { ss << mat.second->openmc("atom"); }
    // write footer
    ss << "</materials>";
    s = ss.str();
  }

  return uwuw_mats_present;
}

bool read_uwuw_materials(pugi::xml_document& doc) {
  std::string s;
  bool found_uwuw_mats = get_uwuw_materials_xml(s);
  if (found_uwuw_mats) {
    pugi::xml_parse_result result = doc.load_string(s.c_str());
    if (!result) {
      throw std::runtime_error{"Error reading UWUW materials"};
    }
  }
  return found_uwuw_mats;
}

bool write_uwuw_materials_xml() {
  std::string s;
  bool found_uwuw_mats = get_uwuw_materials_xml(s);
    // if there is a material library in the file
  if (found_uwuw_mats) {
    // write a material.xml file
    std::ofstream mats_xml("materials.xml");
    mats_xml << s;
    mats_xml.close();
  }

  return found_uwuw_mats;
}

void legacy_assign_material(std::string mat_string, DAGCell* c)
{
  bool mat_found_by_name = false;
  // attempt to find a material with a matching name
  to_lower(mat_string);
  for (const auto& m : model::materials) {
    std::string m_name = m->name();
    to_lower(m_name);
    if (mat_string == m_name) {
      // assign the material with that name
      if (!mat_found_by_name) {
        mat_found_by_name = true;
        c->material_.push_back(m->id_);
      // report error if more than one material is found
      } else {
        fatal_error(fmt::format(
          "More than one material found with name {}. Please ensure materials "
          "have unique names if using this property to assign materials.",
          mat_string));
      }
    }
  }

  // if no material was set using a name, assign by id
  if (!mat_found_by_name) {
    try {
      auto id = std::stoi(mat_string);
      c->material_.emplace_back(id);
    } catch (const std::invalid_argument&) {
      fatal_error(fmt::format(
        "No material {} found for volume (cell) {}", mat_string, c->id_));
    }
  }

  if (settings::verbosity >= 10) {
    const auto& m = model::materials[model::material_map.at(c->material_[0])];
    std::stringstream msg;
    msg << "DAGMC material " << mat_string << " was assigned";
    if (mat_found_by_name) {
      msg << " using material name: " << m->name_;
    } else {
      msg << " using material id: " << m->id_;
    }
    write_message(msg.str(), 10);
  }
}

void load_dagmc_geometry()
{
  if (!model::DAG) {
    model::DAG = new moab::DagMC();
  }

  // --- Materials ---

  // create uwuw instance
  auto filename = dagmc_file();
  UWUW uwuw(filename.c_str());

  // check for uwuw material definitions
  bool using_uwuw = !uwuw.material_library.empty();

  // notify user if UWUW materials are going to be used
  if (using_uwuw) {
    write_message("Found UWUW Materials in the DAGMC geometry file.", 6);
  }

  int32_t dagmc_univ_id = 0; // universe is always 0 for DAGMC runs

  // load the DAGMC geometry
  moab::ErrorCode rval = model::DAG->load_file(filename.c_str());
  MB_CHK_ERR_CONT(rval);

  // initialize acceleration data structures
  rval = model::DAG->init_OBBTree();
  MB_CHK_ERR_CONT(rval);

  // parse model metadata
  dagmcMetaData DMD(model::DAG, false, false);
  DMD.load_property_data();

  std::vector<std::string> keywords {"temp"};
  std::map<std::string, std::string> dum;
  std::string delimiters = ":/";
  rval = model::DAG->parse_properties(keywords, dum, delimiters.c_str());
  MB_CHK_ERR_CONT(rval);

  // --- Cells (Volumes) ---

  // initialize cell objects
  int n_cells = model::DAG->num_entities(3);
  moab::EntityHandle graveyard = 0;
  for (int i = 0; i < n_cells; i++) {
    moab::EntityHandle vol_handle = model::DAG->entity_by_index(3, i+1);

    // set cell ids using global IDs
    DAGCell* c = new DAGCell();
    c->dag_index_ = i+1;
    c->id_ = model::DAG->id_by_index(3, c->dag_index_);
    c->dagmc_ptr_ = model::DAG;
    c->universe_ = dagmc_univ_id; // set to zero for now
    c->fill_ = C_NONE; // no fill, single universe

    model::cells.emplace_back(c);
    model::cell_map[c->id_] = i;

    // Populate the Universe vector and dict
    auto it = model::universe_map.find(dagmc_univ_id);
    if (it == model::universe_map.end()) {
      model::universes.push_back(std::make_unique<Universe>());
      model::universes.back()->id_ = dagmc_univ_id;
      model::universes.back()->cells_.push_back(i);
      model::universe_map[dagmc_univ_id] = model::universes.size() - 1;
    } else {
      model::universes[it->second]->cells_.push_back(i);
    }

    // MATERIALS

    // determine volume material assignment
    std::string mat_str = DMD.get_volume_property("material", vol_handle);

    if (mat_str.empty()) {
      fatal_error(fmt::format("Volume {} has no material assignment.", c->id_));
    }

    to_lower(mat_str);

    if (mat_str == "graveyard") {
      graveyard = vol_handle;
    }

    // material void checks
    if (mat_str == "void" || mat_str == "vacuum" || mat_str == "graveyard") {
      c->material_.push_back(MATERIAL_VOID);
    } else {
      if (using_uwuw) {
        // lookup material in uwuw if present
        std::string uwuw_mat = DMD.volume_material_property_data_eh[vol_handle];
        if (uwuw.material_library.count(uwuw_mat) != 0) {
          // Note: material numbers are set by UWUW
          int mat_number = uwuw.material_library.get_material(uwuw_mat).metadata["mat_number"].asInt();
          c->material_.push_back(mat_number);
        } else {
          fatal_error(fmt::format("Material with value {} not found in the "
            "UWUW material library", mat_str));
        }
      } else {
        legacy_assign_material(mat_str, c);
      }
    }

    // check for temperature assignment
    std::string temp_value;

    // no temperature if void
    if (c->material_[0] == MATERIAL_VOID) continue;

    // assign cell temperature
    const auto& mat = model::materials[model::material_map.at(c->material_[0])];
    if (model::DAG->has_prop(vol_handle, "temp")) {
      rval = model::DAG->prop_value(vol_handle, "temp", temp_value);
      MB_CHK_ERR_CONT(rval);
      double temp = std::stod(temp_value);
      c->sqrtkT_.push_back(std::sqrt(K_BOLTZMANN * temp));
    } else {
      c->sqrtkT_.push_back(std::sqrt(K_BOLTZMANN * mat->temperature()));
    }

  }

  // allocate the cell overlap count if necessary
  if (settings::check_overlaps) {
    model::overlap_check_count.resize(model::cells.size(), 0);
  }

  if (!graveyard) {
    warning("No graveyard volume found in the DagMC model."
            "This may result in lost particles and rapid simulation failure.");
  }

  // --- Surfaces ---

  // initialize surface objects
  int n_surfaces = model::DAG->num_entities(2);

  for (int i = 0; i < n_surfaces; i++) {
    moab::EntityHandle surf_handle = model::DAG->entity_by_index(2, i+1);

    // set cell ids using global IDs
    DAGSurface* s = new DAGSurface();
    s->dag_index_ = i+1;
    s->id_ = model::DAG->id_by_index(2, s->dag_index_);
    s->dagmc_ptr_ = model::DAG;

    // set BCs
    std::string bc_value = DMD.get_surface_property("boundary", surf_handle);
    to_lower(bc_value);
    if (bc_value.empty() || bc_value == "transmit" || bc_value == "transmission") {
      // Leave the bc_ a nullptr
    } else if (bc_value == "vacuum") {
      s->bc_ = std::make_shared<VacuumBC>();
    } else if (bc_value == "reflective" || bc_value == "reflect" || bc_value == "reflecting") {
      s->bc_ = std::make_shared<ReflectiveBC>();
    } else if (bc_value == "white") {
      fatal_error("White boundary condition not supported in DAGMC.");
    } else if (bc_value == "periodic") {
      fatal_error("Periodic boundary condition not supported in DAGMC.");
    } else {
      fatal_error(fmt::format("Unknown boundary condition \"{}\" specified "
        "on surface {}", bc_value, s->id_));
    }

    // graveyard check
    moab::Range parent_vols;
    rval = model::DAG->moab_instance()->get_parent_meshsets(surf_handle, parent_vols);
    MB_CHK_ERR_CONT(rval);

    // if this surface belongs to the graveyard
    if (graveyard && parent_vols.find(graveyard) != parent_vols.end()) {
      // set graveyard surface BC's to vacuum
      s->bc_ = std::make_shared<VacuumBC>();
    }

    // add to global array and map
    model::surfaces.emplace_back(s);
    model::surface_map[s->id_] = i;
  }

  return;
}

void read_geometry_dagmc()
{
  write_message("Reading DAGMC geometry...", 5);
  load_dagmc_geometry();

  model::root_universe = find_root_universe();
}

void free_memory_dagmc()
{
  delete model::DAG;
}

}
#endif
<commit_msg>Add missing surface source flag on DagMC surface<commit_after>#include "openmc/dagmc.h"

#include "openmc/cell.h"
#include "openmc/constants.h"
#include "openmc/container_util.h"
#include "openmc/error.h"
#include "openmc/file_utils.h"
#include "openmc/geometry.h"
#include "openmc/geometry_aux.h"
#include "openmc/material.h"
#include "openmc/string_utils.h"
#include "openmc/settings.h"
#include "openmc/surface.h"

#ifdef DAGMC
#include "uwuw.hpp"
#include "dagmcmetadata.hpp"
#endif
#include <fmt/core.h>

#include <string>
#include <sstream>
#include <algorithm>
#include <fstream>

namespace openmc {

#ifdef DAGMC
const bool dagmc_enabled = true;
#else
const bool dagmc_enabled = false;
#endif

}

#ifdef DAGMC

namespace openmc {

const std::string DAGMC_FILENAME = "dagmc.h5m";

namespace model {

moab::DagMC* DAG;

} // namespace model

std::string dagmc_file() {
  std::string filename = settings::path_input + DAGMC_FILENAME;
  if (!file_exists(filename)) {
    fatal_error("Geometry DAGMC file '" + filename + "' does not exist!");
  }
  return filename;
}

bool get_uwuw_materials_xml(std::string& s) {
  std::string filename = dagmc_file();
  UWUW uwuw(filename.c_str());

  std::stringstream ss;
  bool uwuw_mats_present = false;
  if (uwuw.material_library.size() != 0) {
    uwuw_mats_present = true;
    // write header
    ss << "<?xml version=\"1.0\"?>\n";
    ss << "<materials>\n";
    const auto& mat_lib = uwuw.material_library;
    // write materials
    for (auto mat : mat_lib) { ss << mat.second->openmc("atom"); }
    // write footer
    ss << "</materials>";
    s = ss.str();
  }

  return uwuw_mats_present;
}

bool read_uwuw_materials(pugi::xml_document& doc) {
  std::string s;
  bool found_uwuw_mats = get_uwuw_materials_xml(s);
  if (found_uwuw_mats) {
    pugi::xml_parse_result result = doc.load_string(s.c_str());
    if (!result) {
      throw std::runtime_error{"Error reading UWUW materials"};
    }
  }
  return found_uwuw_mats;
}

bool write_uwuw_materials_xml() {
  std::string s;
  bool found_uwuw_mats = get_uwuw_materials_xml(s);
    // if there is a material library in the file
  if (found_uwuw_mats) {
    // write a material.xml file
    std::ofstream mats_xml("materials.xml");
    mats_xml << s;
    mats_xml.close();
  }

  return found_uwuw_mats;
}

void legacy_assign_material(std::string mat_string, DAGCell* c)
{
  bool mat_found_by_name = false;
  // attempt to find a material with a matching name
  to_lower(mat_string);
  for (const auto& m : model::materials) {
    std::string m_name = m->name();
    to_lower(m_name);
    if (mat_string == m_name) {
      // assign the material with that name
      if (!mat_found_by_name) {
        mat_found_by_name = true;
        c->material_.push_back(m->id_);
      // report error if more than one material is found
      } else {
        fatal_error(fmt::format(
          "More than one material found with name {}. Please ensure materials "
          "have unique names if using this property to assign materials.",
          mat_string));
      }
    }
  }

  // if no material was set using a name, assign by id
  if (!mat_found_by_name) {
    try {
      auto id = std::stoi(mat_string);
      c->material_.emplace_back(id);
    } catch (const std::invalid_argument&) {
      fatal_error(fmt::format(
        "No material {} found for volume (cell) {}", mat_string, c->id_));
    }
  }

  if (settings::verbosity >= 10) {
    const auto& m = model::materials[model::material_map.at(c->material_[0])];
    std::stringstream msg;
    msg << "DAGMC material " << mat_string << " was assigned";
    if (mat_found_by_name) {
      msg << " using material name: " << m->name_;
    } else {
      msg << " using material id: " << m->id_;
    }
    write_message(msg.str(), 10);
  }
}

void load_dagmc_geometry()
{
  if (!model::DAG) {
    model::DAG = new moab::DagMC();
  }

  // --- Materials ---

  // create uwuw instance
  auto filename = dagmc_file();
  UWUW uwuw(filename.c_str());

  // check for uwuw material definitions
  bool using_uwuw = !uwuw.material_library.empty();

  // notify user if UWUW materials are going to be used
  if (using_uwuw) {
    write_message("Found UWUW Materials in the DAGMC geometry file.", 6);
  }

  int32_t dagmc_univ_id = 0; // universe is always 0 for DAGMC runs

  // load the DAGMC geometry
  moab::ErrorCode rval = model::DAG->load_file(filename.c_str());
  MB_CHK_ERR_CONT(rval);

  // initialize acceleration data structures
  rval = model::DAG->init_OBBTree();
  MB_CHK_ERR_CONT(rval);

  // parse model metadata
  dagmcMetaData DMD(model::DAG, false, false);
  DMD.load_property_data();

  std::vector<std::string> keywords {"temp"};
  std::map<std::string, std::string> dum;
  std::string delimiters = ":/";
  rval = model::DAG->parse_properties(keywords, dum, delimiters.c_str());
  MB_CHK_ERR_CONT(rval);

  // --- Cells (Volumes) ---

  // initialize cell objects
  int n_cells = model::DAG->num_entities(3);
  moab::EntityHandle graveyard = 0;
  for (int i = 0; i < n_cells; i++) {
    moab::EntityHandle vol_handle = model::DAG->entity_by_index(3, i+1);

    // set cell ids using global IDs
    DAGCell* c = new DAGCell();
    c->dag_index_ = i+1;
    c->id_ = model::DAG->id_by_index(3, c->dag_index_);
    c->dagmc_ptr_ = model::DAG;
    c->universe_ = dagmc_univ_id; // set to zero for now
    c->fill_ = C_NONE; // no fill, single universe

    model::cells.emplace_back(c);
    model::cell_map[c->id_] = i;

    // Populate the Universe vector and dict
    auto it = model::universe_map.find(dagmc_univ_id);
    if (it == model::universe_map.end()) {
      model::universes.push_back(std::make_unique<Universe>());
      model::universes.back()->id_ = dagmc_univ_id;
      model::universes.back()->cells_.push_back(i);
      model::universe_map[dagmc_univ_id] = model::universes.size() - 1;
    } else {
      model::universes[it->second]->cells_.push_back(i);
    }

    // MATERIALS

    // determine volume material assignment
    std::string mat_str = DMD.get_volume_property("material", vol_handle);

    if (mat_str.empty()) {
      fatal_error(fmt::format("Volume {} has no material assignment.", c->id_));
    }

    to_lower(mat_str);

    if (mat_str == "graveyard") {
      graveyard = vol_handle;
    }

    // material void checks
    if (mat_str == "void" || mat_str == "vacuum" || mat_str == "graveyard") {
      c->material_.push_back(MATERIAL_VOID);
    } else {
      if (using_uwuw) {
        // lookup material in uwuw if present
        std::string uwuw_mat = DMD.volume_material_property_data_eh[vol_handle];
        if (uwuw.material_library.count(uwuw_mat) != 0) {
          // Note: material numbers are set by UWUW
          int mat_number = uwuw.material_library.get_material(uwuw_mat).metadata["mat_number"].asInt();
          c->material_.push_back(mat_number);
        } else {
          fatal_error(fmt::format("Material with value {} not found in the "
            "UWUW material library", mat_str));
        }
      } else {
        legacy_assign_material(mat_str, c);
      }
    }

    // check for temperature assignment
    std::string temp_value;

    // no temperature if void
    if (c->material_[0] == MATERIAL_VOID) continue;

    // assign cell temperature
    const auto& mat = model::materials[model::material_map.at(c->material_[0])];
    if (model::DAG->has_prop(vol_handle, "temp")) {
      rval = model::DAG->prop_value(vol_handle, "temp", temp_value);
      MB_CHK_ERR_CONT(rval);
      double temp = std::stod(temp_value);
      c->sqrtkT_.push_back(std::sqrt(K_BOLTZMANN * temp));
    } else {
      c->sqrtkT_.push_back(std::sqrt(K_BOLTZMANN * mat->temperature()));
    }

  }

  // allocate the cell overlap count if necessary
  if (settings::check_overlaps) {
    model::overlap_check_count.resize(model::cells.size(), 0);
  }

  if (!graveyard) {
    warning("No graveyard volume found in the DagMC model."
            "This may result in lost particles and rapid simulation failure.");
  }

  // --- Surfaces ---

  // initialize surface objects
  int n_surfaces = model::DAG->num_entities(2);

  for (int i = 0; i < n_surfaces; i++) {
    moab::EntityHandle surf_handle = model::DAG->entity_by_index(2, i+1);

    // set cell ids using global IDs
    DAGSurface* s = new DAGSurface();
    s->dag_index_ = i+1;
    s->id_ = model::DAG->id_by_index(2, s->dag_index_);
    s->dagmc_ptr_ = model::DAG;

    if (contains(settings::src_write_surf_id, s->id_)) {
      s->surf_src_ = true;
    }

    // set BCs
    std::string bc_value = DMD.get_surface_property("boundary", surf_handle);
    to_lower(bc_value);
    if (bc_value.empty() || bc_value == "transmit" || bc_value == "transmission") {
      // Leave the bc_ a nullptr
    } else if (bc_value == "vacuum") {
      s->bc_ = std::make_shared<VacuumBC>();
    } else if (bc_value == "reflective" || bc_value == "reflect" || bc_value == "reflecting") {
      s->bc_ = std::make_shared<ReflectiveBC>();
    } else if (bc_value == "white") {
      fatal_error("White boundary condition not supported in DAGMC.");
    } else if (bc_value == "periodic") {
      fatal_error("Periodic boundary condition not supported in DAGMC.");
    } else {
      fatal_error(fmt::format("Unknown boundary condition \"{}\" specified "
        "on surface {}", bc_value, s->id_));
    }

    // graveyard check
    moab::Range parent_vols;
    rval = model::DAG->moab_instance()->get_parent_meshsets(surf_handle, parent_vols);
    MB_CHK_ERR_CONT(rval);

    // if this surface belongs to the graveyard
    if (graveyard && parent_vols.find(graveyard) != parent_vols.end()) {
      // set graveyard surface BC's to vacuum
      s->bc_ = std::make_shared<VacuumBC>();
    }

    // add to global array and map
    model::surfaces.emplace_back(s);
    model::surface_map[s->id_] = i;
  }

  return;
}

void read_geometry_dagmc()
{
  write_message("Reading DAGMC geometry...", 5);
  load_dagmc_geometry();

  model::root_universe = find_root_universe();
}

void free_memory_dagmc()
{
  delete model::DAG;
}

}
#endif
<|endoftext|>


<commit_before>#include "common.h"
#include "parser.h"
#include "wrap.h"
#include "ir.h"
#include "cps.h"
#include "compile.h"
#include "optimize.h"
#include <iostream>
#include "assets.h"

using namespace cirth;

int main(int argc, char** argv) {
  std::string str;
  std::ostringstream os;
  os << assets::PRELUDE_CTH << "\n";

  while(getline(std::cin, str)) {
    os << str << '\n';
  }

  try {
    // force counters
    UPDATE_FIELD; // gets 0
    LOOKUP_FIELD; // gets 1

    std::vector<PTR<ast::Expression> > ast;
    bool r = parser::parse(os.str(), ast);
    if(!r) throw expectation_failure("failed parsing!");

    std::vector<PTR<ir::Expression> > ir;
    wrap::ir_prepend(ir);
    ir::Name lastval(NULL_VALUE);
    ir::convert(ast, ir, lastval);
    lastval = NULL_VALUE;
    ast.clear();
    optimize::ir(ir);

    PTR<cps::Expression> cps;
    cps::transform(ir, lastval, cps);
    ir.clear();
    optimize::cps(cps);

    compile::compile(cps, std::cout);
  } catch (const std::exception& e) {
    std::cerr << "failure: " << e.what() << std::endl;
    return 1;
  }

  return 0;
}
<commit_msg>first commandline option<commit_after>#include "common.h"
#include "parser.h"
#include "wrap.h"
#include "ir.h"
#include "cps.h"
#include "compile.h"
#include "optimize.h"
#include <iostream>
#include "assets.h"

using namespace cirth;

int main(int argc, char** argv) {

  bool include_prelude = true;

  for(int i = 1; i < argc;) {
    if(argv[i] == std::string("--skip-prelude")) {
      include_prelude = false;
      ++i;
      continue;
    }
    if(argv[i] == std::string("--help")) {
      std::cout << "usage: " << argv[0] << " [--skip_prelude]" << std::endl;
      std::cout << "  source comes in stdin, C comes out stdout" << std::endl;
      return 0;
    }
    std::cerr << "unknown argument! try --help" << std::endl;
    return 1;
  }

  std::string str;
  std::ostringstream os;
  if(include_prelude) os << assets::PRELUDE_CTH << "\n";

  while(getline(std::cin, str)) {
    os << str << '\n';
  }

  try {
    // force counters
    UPDATE_FIELD; // gets 0
    LOOKUP_FIELD; // gets 1

    std::vector<PTR<ast::Expression> > ast;
    bool r = parser::parse(os.str(), ast);
    if(!r) throw expectation_failure("failed parsing!");

    std::vector<PTR<ir::Expression> > ir;
    wrap::ir_prepend(ir);
    ir::Name lastval(NULL_VALUE);
    ir::convert(ast, ir, lastval);
    lastval = NULL_VALUE;
    ast.clear();
    optimize::ir(ir);

    PTR<cps::Expression> cps;
    cps::transform(ir, lastval, cps);
    ir.clear();
    optimize::cps(cps);

    compile::compile(cps, std::cout);
  } catch (const std::exception& e) {
    std::cerr << "failure: " << e.what() << std::endl;
    return 1;
  }

  return 0;
}
<|endoftext|>


<commit_before>#include <stdint.h>
#include <iostream>

#include "demo.pb.h"
#include "netmessages.pb.h"

#include "bitstream.h"
#include "debug.h"
#include "demo.h"
#include "entity.h"
#include "state.h"
#include "death_recording_visitor.h"

#define INSTANCE_BASELINE_TABLE "instancebaseline"
#define KEY_HISTORY_SIZE 32
#define MAX_EDICTS 0x800
#define MAX_KEY_SIZE 0x400
#define MAX_VALUE_SIZE 0x4000

enum UpdateFlag {
  UF_LeavePVS = 1,
  UF_Delete = 2,
  UF_EnterPVS = 4,
};

State *state = 0;

uint32_t read_var_int(const char *data, size_t length, size_t *offset) {
  uint32_t b;
  int count = 0;
  uint32_t result = 0;

  do {
    XASSERT(count != 5, "Corrupt data.");
    XASSERT(*offset <= length, "Premature end of stream.");

    b = data[(*offset)++];
    result |= (b & 0x7F) << (7 * count);
    ++count;
  } while (b & 0x80);

  return result;
}

void dump_SVC_SendTable(const CSVCMsg_SendTable &table) {
  XASSERT(state, "SVC_SendTable but no state created.");

  SendTable &converted = state->create_send_table(table.net_table_name(), table.needs_decoder());

  size_t prop_count = table.props_size();
  for (size_t i = 0; i < prop_count; ++i) {
    const CSVCMsg_SendTable_sendprop_t &prop = table.props(i);

    SendProp c(
        static_cast<SP_Types>(prop.type()),
        prop.var_name(),
        prop.flags(),
        prop.priority(),
        prop.dt_name(),
        prop.num_elements(),
        prop.low_value(),
        prop.high_value(),
        prop.num_bits());

    converted.props.add(c);
  }
}

void dump_DEM_SendTables(const CDemoSendTables &tables) {
  const char *data = tables.data().c_str();
  size_t offset = 0;
  size_t length = tables.data().length();

  while (offset < length) {
    uint32_t command = read_var_int(data, length, &offset);
    uint32_t size = read_var_int(data, length, &offset);
    XASSERT(offset + size <= length, "Reading data outside of table.");

    XASSERT(command == svc_SendTable, "Command %u in DEM_SendTables.", command);

    CSVCMsg_SendTable send_table;
    send_table.ParseFromArray(&(data[offset]), size);
    dump_SVC_SendTable(send_table);

    offset += size;
  }
}

const StringTableEntry &get_baseline_for(int class_i) {
  XASSERT(state, "No state created.");

  StringTable &instance_baseline = state->get_string_table(INSTANCE_BASELINE_TABLE);

  char buf[32];
  sprintf(buf, "%d", class_i);

  return instance_baseline.get(buf);
}

uint32_t read_entity_header(uint32_t *base, Bitstream &stream) {
  uint32_t value = stream.get_bits(6);

  if (value & 0x30) {
    uint32_t a = (value >> 4) & 3;
    uint32_t b = (a == 3) ? 16 : 0;

    value = stream.get_bits(4 * a + b) << 4 | (value & 0xF);
  }

  *base += value + 1;

  unsigned int update_flags = 0;

  if (!stream.get_bits(1)) {
    if (stream.get_bits(1)) {
      update_flags |= UF_EnterPVS;
    }
  } else {
    update_flags |= UF_LeavePVS;
    if (stream.get_bits(1)) {
      update_flags |= UF_Delete;
    }
  }

  return update_flags;
}

void read_entity_enter_pvs(uint32_t entity_id, Bitstream &stream, Visitor& visitor) {
  uint32_t class_i = stream.get_bits(state->class_bits);
  uint32_t serial = stream.get_bits(10);

  XASSERT(entity_id < MAX_EDICTS, "Entity %ld exceeds max edicts.", entity_id);

  const Class &clazz = state->get_class(class_i);
  const FlatSendTable &flat_send_table = state->flat_send_tables[clazz.dt_name];

  Entity &entity = state->entities[entity_id];

  if (entity.id != -1) {
    visitor.visit_entity_deleted(entity);
  }

  entity = Entity(entity_id, clazz, flat_send_table);

  const StringTableEntry &baseline = get_baseline_for(class_i);
  Bitstream baseline_stream(baseline.value);
  entity.update(baseline_stream);

  entity.update(stream);

  visitor.visit_entity_created(entity);
}

void read_entity_update(uint32_t entity_id, Bitstream &stream, Visitor& visitor) {
  XASSERT(entity_id < MAX_ENTITIES, "Entity id too big");

  Entity &entity = state->entities[entity_id];
  XASSERT(entity.id != -1, "Entity %d is not set up.", entity_id);

  entity.update(stream);

  visitor.visit_entity_updated(entity);
}

void dump_SVC_PacketEntities(const CSVCMsg_PacketEntities &entities, Visitor& visitor) {
  Bitstream stream(entities.entity_data());

  uint32_t entity_id = -1;
  size_t found = 0;
  uint32_t update_type;

  while (found < entities.updated_entries()) {
    update_type = read_entity_header(&entity_id, stream);

    if (update_type & UF_EnterPVS) {
      read_entity_enter_pvs(entity_id, stream, visitor);
    } else if (update_type & UF_LeavePVS) {
      XASSERT(entities.is_delta(), "Leave PVS on full update");

      if (update_type & UF_Delete) {
        visitor.visit_entity_deleted(state->entities[entity_id]);

        state->entities[entity_id].id = -1;
      }
    } else {
      read_entity_update(entity_id, stream, visitor);
    }

    ++found;
  }

  if (entities.is_delta()) {
    while (stream.get_bits(1)) {
      entity_id = stream.get_bits(11);
      visitor.visit_entity_deleted(state->entities[entity_id]);
      state->entities[entity_id].id = -1;
    }
  }
}

void dump_SVC_ServerInfo(const CSVCMsg_ServerInfo &info) {
  XASSERT(!state, "Already seen SVC_ServerInfo.");

  state = new State(info.max_classes());
}

void dump_DEM_ClassInfo(const CDemoClassInfo &info) {
  XASSERT(state, "DEM_ClassInfo but no state.");

  for (size_t i = 0; i < info.classes_size(); ++i) {
    const CDemoClassInfo_class_t &clazz = info.classes(i);
    state->create_class(clazz.class_id(), clazz.table_name(), clazz.network_name());
  }

  for (auto iter = state->send_tables.begin(); iter != state->send_tables.end(); ++iter) {
    SendTable &table = *iter;

    for (size_t i = 0; i < table.props.size(); ++i) {
      SendProp &prop = table.props[i];

      prop.in_table = &table;

      if (prop.type == SP_Array) {
        XASSERT(i > 0, "Array prop %s is at index zero.", prop.var_name.c_str());
        prop.array_prop = &(table.props[i - 1]);
      }
    }
  }

  state->compile_send_tables();
}

void read_string_table_key(uint32_t first_bit, Bitstream &stream, char *buf,
    size_t buf_length, std::vector<std::string> &key_history) {
  if (first_bit && stream.get_bits(1)) {
    XERROR("Not sure how to read this key");
  } else {
    uint32_t is_substring = stream.get_bits(1);

    if (is_substring) {
      uint32_t from_index = stream.get_bits(5);
      uint32_t from_length = stream.get_bits(5);
      key_history[from_index].copy(buf, from_length, 0);

      stream.read_string(buf + from_length, buf_length - from_length);
    } else {
      stream.read_string(buf, buf_length);
    }
  }
}

void update_string_table(StringTable &table, size_t num_entries, const std::string &data) {
  // These do something with precaches. This isn't a client so I'm assuming this
  // is irrelevant.
  if (table.flags & 2) {
    return;
  }

  Bitstream stream(data);

  uint32_t first_bit = stream.get_bits(1);

  std::vector<std::string> key_history;

  uint32_t entry_id = -1;
  size_t entries_read = 0;
  while (entries_read < num_entries) {
    if (!stream.get_bits(1)) {
      entry_id = stream.get_bits(table.entry_bits);
    } else {
      entry_id += 1;
    }

    XASSERT(entry_id < table.max_entries, "Entry id too large");

    char key_buffer[MAX_KEY_SIZE];
    char *key = 0;
    if (stream.get_bits(1)) {
      read_string_table_key(first_bit, stream, key_buffer, MAX_KEY_SIZE, key_history);

      key = key_buffer;

      // So technically we should only store the first 32 characters but I'm lazy.
      if (key_history.size() == KEY_HISTORY_SIZE) {
        key_history.erase(key_history.begin());
      }

      key_history.push_back(key);
    }

    char value_buffer[MAX_VALUE_SIZE];
    char *value = 0;
    size_t bit_length = 0;
    size_t length = 0;
    if (stream.get_bits(1)) {
      if (table.flags & ST_FixedLength) {
        length = table.user_data_size;
        bit_length = table.user_data_size_bits;
      } else {
        length = stream.get_bits(14);
        bit_length = 8 * length;
      }

      XASSERT(length < MAX_VALUE_SIZE, "Message too long.");

      stream.read_bits(value_buffer, bit_length);
    }

    if (entry_id < table.count()) {
      StringTableEntry &item = table.get(entry_id);

      if (key) {
        XASSERT(item.key == key, "Entry's keys don't match.");
      }

      if (value) {
        // This is kind of bad because if the server sends us a zero length string we'll consider
        // it to be uninitialized.
        XASSERT(item.value.size() == 0, "String table already has this value");
        item.value = std::string(value, length);
      }
    } else {
      XASSERT(key, "Creating a new string table entry but no key specified.");

      table.put(key, std::string(value_buffer, length));
    }

    ++entries_read;
  }
}

void handle_SVC_CreateStringTable(const CSVCMsg_CreateStringTable &table) {
  XASSERT(state, "SVC_CreateStringTable but no state.");

  StringTable &converted = state->create_string_table(table.name(),
      (size_t) table.max_entries(), table.flags(), table.user_data_fixed_size(),
      table.user_data_size(), table.user_data_size_bits());

  update_string_table(converted, table.num_entries(), table.string_data());
}

void handle_SVC_UpdateStringTable(const CSVCMsg_UpdateStringTable &update) {
  XASSERT(state, "SVC_UpdateStringTable but no state.");

  StringTable &table = state->get_string_table(update.table_id());

  update_string_table(table, update.num_changed_entries(), update.string_data());
}

void clear_entities(Visitor& visitor) {
  for (size_t i = 0; i < MAX_ENTITIES; ++i) {
    Entity &entity = state->entities[i];

    if (entity.id != -1) {
      visitor.visit_entity_deleted(entity);
      entity.id = -1;
    }
  }
}

void dump_DEM_Packet(const CDemoPacket &packet, Visitor& visitor) {
  const char *data = packet.data().c_str();
  size_t offset = 0;
  size_t length = packet.data().length();

  while (offset < length) {
    uint32_t command = read_var_int(data, length, &offset);
    uint32_t size = read_var_int(data, length, &offset);
    XASSERT(offset + size <= length, "Reading data outside of packet.");

    if (command == svc_ServerInfo) {
      CSVCMsg_ServerInfo info;
      info.ParseFromArray(&(data[offset]), size);

      dump_SVC_ServerInfo(info);
    } else if (command == svc_PacketEntities) {
      CSVCMsg_PacketEntities entities;
      entities.ParseFromArray(&(data[offset]), size);

      dump_SVC_PacketEntities(entities, visitor);
    } else if (command == svc_CreateStringTable) {
      CSVCMsg_CreateStringTable table;
      table.ParseFromArray(&(data[offset]), size);

      handle_SVC_CreateStringTable(table);
    } else if (command == svc_UpdateStringTable) {
      CSVCMsg_UpdateStringTable table;
      table.ParseFromArray(&(data[offset]), size);

      handle_SVC_UpdateStringTable(table);
    }

    offset += size;
  }
}

void dump(const char *file, Visitor& visitor) {
  Demo demo(file);

  for (int frame = 0; !demo.eof(); ++frame) {
    int tick = 0;
    size_t size;
    bool compressed;
    size_t uncompressed_size;

    EDemoCommands command = demo.get_message_type(&tick, &compressed);
    demo.read_message(compressed, &size, &uncompressed_size);

    visitor.visit_tick(tick);

    if (command == DEM_ClassInfo) {
      CDemoClassInfo info;
      info.ParseFromArray(demo.expose_buffer(), uncompressed_size);

      dump_DEM_ClassInfo(info);
    } else if (command == DEM_SendTables) {
      CDemoSendTables tables;
      tables.ParseFromArray(demo.expose_buffer(), uncompressed_size);

      dump_DEM_SendTables(tables);
    } else if (command == DEM_Packet || command == DEM_SignonPacket) {
      CDemoPacket packet;
      packet.ParseFromArray(demo.expose_buffer(), uncompressed_size);

      dump_DEM_Packet(packet, visitor);
    }
  }
}

int main(int argc, char **argv) {
  if (argc <= 1) {
    printf("Usage: %s something.dem\n", argv[0]);
    return 1;
  }

  DeathRecordingVisitor v;
  dump(argv[1], v);
  return 0;
}

<commit_msg>Remove clear_entities, fixes #9<commit_after>#include <stdint.h>
#include <iostream>

#include "demo.pb.h"
#include "netmessages.pb.h"

#include "bitstream.h"
#include "debug.h"
#include "demo.h"
#include "entity.h"
#include "state.h"
#include "death_recording_visitor.h"

#define INSTANCE_BASELINE_TABLE "instancebaseline"
#define KEY_HISTORY_SIZE 32
#define MAX_EDICTS 0x800
#define MAX_KEY_SIZE 0x400
#define MAX_VALUE_SIZE 0x4000

enum UpdateFlag {
  UF_LeavePVS = 1,
  UF_Delete = 2,
  UF_EnterPVS = 4,
};

State *state = 0;

uint32_t read_var_int(const char *data, size_t length, size_t *offset) {
  uint32_t b;
  int count = 0;
  uint32_t result = 0;

  do {
    XASSERT(count != 5, "Corrupt data.");
    XASSERT(*offset <= length, "Premature end of stream.");

    b = data[(*offset)++];
    result |= (b & 0x7F) << (7 * count);
    ++count;
  } while (b & 0x80);

  return result;
}

void dump_SVC_SendTable(const CSVCMsg_SendTable &table) {
  XASSERT(state, "SVC_SendTable but no state created.");

  SendTable &converted = state->create_send_table(table.net_table_name(), table.needs_decoder());

  size_t prop_count = table.props_size();
  for (size_t i = 0; i < prop_count; ++i) {
    const CSVCMsg_SendTable_sendprop_t &prop = table.props(i);

    SendProp c(
        static_cast<SP_Types>(prop.type()),
        prop.var_name(),
        prop.flags(),
        prop.priority(),
        prop.dt_name(),
        prop.num_elements(),
        prop.low_value(),
        prop.high_value(),
        prop.num_bits());

    converted.props.add(c);
  }
}

void dump_DEM_SendTables(const CDemoSendTables &tables) {
  const char *data = tables.data().c_str();
  size_t offset = 0;
  size_t length = tables.data().length();

  while (offset < length) {
    uint32_t command = read_var_int(data, length, &offset);
    uint32_t size = read_var_int(data, length, &offset);
    XASSERT(offset + size <= length, "Reading data outside of table.");

    XASSERT(command == svc_SendTable, "Command %u in DEM_SendTables.", command);

    CSVCMsg_SendTable send_table;
    send_table.ParseFromArray(&(data[offset]), size);
    dump_SVC_SendTable(send_table);

    offset += size;
  }
}

const StringTableEntry &get_baseline_for(int class_i) {
  XASSERT(state, "No state created.");

  StringTable &instance_baseline = state->get_string_table(INSTANCE_BASELINE_TABLE);

  char buf[32];
  sprintf(buf, "%d", class_i);

  return instance_baseline.get(buf);
}

uint32_t read_entity_header(uint32_t *base, Bitstream &stream) {
  uint32_t value = stream.get_bits(6);

  if (value & 0x30) {
    uint32_t a = (value >> 4) & 3;
    uint32_t b = (a == 3) ? 16 : 0;

    value = stream.get_bits(4 * a + b) << 4 | (value & 0xF);
  }

  *base += value + 1;

  unsigned int update_flags = 0;

  if (!stream.get_bits(1)) {
    if (stream.get_bits(1)) {
      update_flags |= UF_EnterPVS;
    }
  } else {
    update_flags |= UF_LeavePVS;
    if (stream.get_bits(1)) {
      update_flags |= UF_Delete;
    }
  }

  return update_flags;
}

void read_entity_enter_pvs(uint32_t entity_id, Bitstream &stream, Visitor& visitor) {
  uint32_t class_i = stream.get_bits(state->class_bits);
  uint32_t serial = stream.get_bits(10);

  XASSERT(entity_id < MAX_EDICTS, "Entity %ld exceeds max edicts.", entity_id);

  const Class &clazz = state->get_class(class_i);
  const FlatSendTable &flat_send_table = state->flat_send_tables[clazz.dt_name];

  Entity &entity = state->entities[entity_id];

  if (entity.id != -1) {
    visitor.visit_entity_deleted(entity);
  }

  entity = Entity(entity_id, clazz, flat_send_table);

  const StringTableEntry &baseline = get_baseline_for(class_i);
  Bitstream baseline_stream(baseline.value);
  entity.update(baseline_stream);

  entity.update(stream);

  visitor.visit_entity_created(entity);
}

void read_entity_update(uint32_t entity_id, Bitstream &stream, Visitor& visitor) {
  XASSERT(entity_id < MAX_ENTITIES, "Entity id too big");

  Entity &entity = state->entities[entity_id];
  XASSERT(entity.id != -1, "Entity %d is not set up.", entity_id);

  entity.update(stream);

  visitor.visit_entity_updated(entity);
}

void dump_SVC_PacketEntities(const CSVCMsg_PacketEntities &entities, Visitor& visitor) {
  Bitstream stream(entities.entity_data());

  uint32_t entity_id = -1;
  size_t found = 0;
  uint32_t update_type;

  while (found < entities.updated_entries()) {
    update_type = read_entity_header(&entity_id, stream);

    if (update_type & UF_EnterPVS) {
      read_entity_enter_pvs(entity_id, stream, visitor);
    } else if (update_type & UF_LeavePVS) {
      XASSERT(entities.is_delta(), "Leave PVS on full update");

      if (update_type & UF_Delete) {
        visitor.visit_entity_deleted(state->entities[entity_id]);

        state->entities[entity_id].id = -1;
      }
    } else {
      read_entity_update(entity_id, stream, visitor);
    }

    ++found;
  }

  if (entities.is_delta()) {
    while (stream.get_bits(1)) {
      entity_id = stream.get_bits(11);
      visitor.visit_entity_deleted(state->entities[entity_id]);
      state->entities[entity_id].id = -1;
    }
  }
}

void dump_SVC_ServerInfo(const CSVCMsg_ServerInfo &info) {
  XASSERT(!state, "Already seen SVC_ServerInfo.");

  state = new State(info.max_classes());
}

void dump_DEM_ClassInfo(const CDemoClassInfo &info) {
  XASSERT(state, "DEM_ClassInfo but no state.");

  for (size_t i = 0; i < info.classes_size(); ++i) {
    const CDemoClassInfo_class_t &clazz = info.classes(i);
    state->create_class(clazz.class_id(), clazz.table_name(), clazz.network_name());
  }

  for (auto iter = state->send_tables.begin(); iter != state->send_tables.end(); ++iter) {
    SendTable &table = *iter;

    for (size_t i = 0; i < table.props.size(); ++i) {
      SendProp &prop = table.props[i];

      prop.in_table = &table;

      if (prop.type == SP_Array) {
        XASSERT(i > 0, "Array prop %s is at index zero.", prop.var_name.c_str());
        prop.array_prop = &(table.props[i - 1]);
      }
    }
  }

  state->compile_send_tables();
}

void read_string_table_key(uint32_t first_bit, Bitstream &stream, char *buf,
    size_t buf_length, std::vector<std::string> &key_history) {
  if (first_bit && stream.get_bits(1)) {
    XERROR("Not sure how to read this key");
  } else {
    uint32_t is_substring = stream.get_bits(1);

    if (is_substring) {
      uint32_t from_index = stream.get_bits(5);
      uint32_t from_length = stream.get_bits(5);
      key_history[from_index].copy(buf, from_length, 0);

      stream.read_string(buf + from_length, buf_length - from_length);
    } else {
      stream.read_string(buf, buf_length);
    }
  }
}

void update_string_table(StringTable &table, size_t num_entries, const std::string &data) {
  // These do something with precaches. This isn't a client so I'm assuming this
  // is irrelevant.
  if (table.flags & 2) {
    return;
  }

  Bitstream stream(data);

  uint32_t first_bit = stream.get_bits(1);

  std::vector<std::string> key_history;

  uint32_t entry_id = -1;
  size_t entries_read = 0;
  while (entries_read < num_entries) {
    if (!stream.get_bits(1)) {
      entry_id = stream.get_bits(table.entry_bits);
    } else {
      entry_id += 1;
    }

    XASSERT(entry_id < table.max_entries, "Entry id too large");

    char key_buffer[MAX_KEY_SIZE];
    char *key = 0;
    if (stream.get_bits(1)) {
      read_string_table_key(first_bit, stream, key_buffer, MAX_KEY_SIZE, key_history);

      key = key_buffer;

      // So technically we should only store the first 32 characters but I'm lazy.
      if (key_history.size() == KEY_HISTORY_SIZE) {
        key_history.erase(key_history.begin());
      }

      key_history.push_back(key);
    }

    char value_buffer[MAX_VALUE_SIZE];
    char *value = 0;
    size_t bit_length = 0;
    size_t length = 0;
    if (stream.get_bits(1)) {
      if (table.flags & ST_FixedLength) {
        length = table.user_data_size;
        bit_length = table.user_data_size_bits;
      } else {
        length = stream.get_bits(14);
        bit_length = 8 * length;
      }

      XASSERT(length < MAX_VALUE_SIZE, "Message too long.");

      stream.read_bits(value_buffer, bit_length);
    }

    if (entry_id < table.count()) {
      StringTableEntry &item = table.get(entry_id);

      if (key) {
        XASSERT(item.key == key, "Entry's keys don't match.");
      }

      if (value) {
        // This is kind of bad because if the server sends us a zero length string we'll consider
        // it to be uninitialized.
        XASSERT(item.value.size() == 0, "String table already has this value");
        item.value = std::string(value, length);
      }
    } else {
      XASSERT(key, "Creating a new string table entry but no key specified.");

      table.put(key, std::string(value_buffer, length));
    }

    ++entries_read;
  }
}

void handle_SVC_CreateStringTable(const CSVCMsg_CreateStringTable &table) {
  XASSERT(state, "SVC_CreateStringTable but no state.");

  StringTable &converted = state->create_string_table(table.name(),
      (size_t) table.max_entries(), table.flags(), table.user_data_fixed_size(),
      table.user_data_size(), table.user_data_size_bits());

  update_string_table(converted, table.num_entries(), table.string_data());
}

void handle_SVC_UpdateStringTable(const CSVCMsg_UpdateStringTable &update) {
  XASSERT(state, "SVC_UpdateStringTable but no state.");

  StringTable &table = state->get_string_table(update.table_id());

  update_string_table(table, update.num_changed_entries(), update.string_data());
}

void dump_DEM_Packet(const CDemoPacket &packet, Visitor& visitor) {
  const char *data = packet.data().c_str();
  size_t offset = 0;
  size_t length = packet.data().length();

  while (offset < length) {
    uint32_t command = read_var_int(data, length, &offset);
    uint32_t size = read_var_int(data, length, &offset);
    XASSERT(offset + size <= length, "Reading data outside of packet.");

    if (command == svc_ServerInfo) {
      CSVCMsg_ServerInfo info;
      info.ParseFromArray(&(data[offset]), size);

      dump_SVC_ServerInfo(info);
    } else if (command == svc_PacketEntities) {
      CSVCMsg_PacketEntities entities;
      entities.ParseFromArray(&(data[offset]), size);

      dump_SVC_PacketEntities(entities, visitor);
    } else if (command == svc_CreateStringTable) {
      CSVCMsg_CreateStringTable table;
      table.ParseFromArray(&(data[offset]), size);

      handle_SVC_CreateStringTable(table);
    } else if (command == svc_UpdateStringTable) {
      CSVCMsg_UpdateStringTable table;
      table.ParseFromArray(&(data[offset]), size);

      handle_SVC_UpdateStringTable(table);
    }

    offset += size;
  }
}

void dump(const char *file, Visitor& visitor) {
  Demo demo(file);

  for (int frame = 0; !demo.eof(); ++frame) {
    int tick = 0;
    size_t size;
    bool compressed;
    size_t uncompressed_size;

    EDemoCommands command = demo.get_message_type(&tick, &compressed);
    demo.read_message(compressed, &size, &uncompressed_size);

    visitor.visit_tick(tick);

    if (command == DEM_ClassInfo) {
      CDemoClassInfo info;
      info.ParseFromArray(demo.expose_buffer(), uncompressed_size);

      dump_DEM_ClassInfo(info);
    } else if (command == DEM_SendTables) {
      CDemoSendTables tables;
      tables.ParseFromArray(demo.expose_buffer(), uncompressed_size);

      dump_DEM_SendTables(tables);
    } else if (command == DEM_Packet || command == DEM_SignonPacket) {
      CDemoPacket packet;
      packet.ParseFromArray(demo.expose_buffer(), uncompressed_size);

      dump_DEM_Packet(packet, visitor);
    }
  }
}

int main(int argc, char **argv) {
  if (argc <= 1) {
    printf("Usage: %s something.dem\n", argv[0]);
    return 1;
  }

  DeathRecordingVisitor v;
  dump(argv[1], v);
  return 0;
}

<|endoftext|>


<commit_before>#include <thread>
#include <functional>
#include <vector>
#include <cstdint>
#include <cstdio>
#include <queue>
#include <mutex>
#include <string>
#include <condition_variable>

class dispatch_queue
{
	typedef std::function<void(void)> fp_t;

  public:
	dispatch_queue(std::string name, size_t thread_cnt = 1);
	~dispatch_queue();

	// dispatch and copy
	void dispatch(const fp_t& op);
	// dispatch and move
	void dispatch(fp_t&& op);

	// Deleted operations
	dispatch_queue(const dispatch_queue& rhs) = delete;
	dispatch_queue& operator=(const dispatch_queue& rhs) = delete;
	dispatch_queue(dispatch_queue&& rhs) = delete;
	dispatch_queue& operator=(dispatch_queue&& rhs) = delete;

  private:
	std::string name_;
	std::mutex lock_;
	std::vector<std::thread> threads_;
	std::queue<fp_t> q_;
	std::condition_variable cv_;
	bool quit_ = false;

	void dispatch_thread_handler(void);
};

dispatch_queue::dispatch_queue(std::string name, size_t thread_cnt) :
	name_{std::move(name)}, threads_(thread_cnt)
{
	printf("Creating dispatch queue: %s\n", name_.c_str());
	printf("Dispatch threads: %zu\n", thread_cnt);

	for(size_t i = 0; i < threads_.size(); i++)
	{
		threads_[i] = std::thread(&dispatch_queue::dispatch_thread_handler, this);
	}
}

dispatch_queue::~dispatch_queue()
{
	printf("Destructor: Destroying dispatch threads...\n");

	// Signal to dispatch threads that it's time to wrap up
	std::unique_lock<std::mutex> lock(lock_);
	quit_ = true;
	lock.unlock();
	cv_.notify_all();

	// Wait for threads to finish before we exit
	for(size_t i = 0; i < threads_.size(); i++)
	{
		if(threads_[i].joinable())
		{
			printf("Destructor: Joining thread %zu until completion\n", i);
			threads_[i].join();
		}
	}
}

void dispatch_queue::dispatch(const fp_t& op)
{
	std::unique_lock<std::mutex> lock(lock_);
	q_.push(op);

	// Manual unlocking is done before notifying, to avoid waking up
	// the waiting thread only to block again (see notify_one for details)
	lock.unlock();
	cv_.notify_one();
}

void dispatch_queue::dispatch(fp_t&& op)
{
	std::unique_lock<std::mutex> lock(lock_);
	q_.push(std::move(op));

	// Manual unlocking is done before notifying, to avoid waking up
	// the waiting thread only to block again (see notify_one for details)
	lock.unlock();
	cv_.notify_one();
}

void dispatch_queue::dispatch_thread_handler(void)
{
	std::unique_lock<std::mutex> lock(lock_);

	do
	{
		// Wait until we have data or a quit signal
		cv_.wait(lock, [this] {
			return (q_.size() || quit_);
		});

		// after wait, we own the lock
		if(!quit_ && q_.size())
		{
			auto op = std::move(q_.front());
			q_.pop();

			// unlock now that we're done messing with the queue
			lock.unlock();

			op();

			lock.lock();
		}
	} while(!quit_);
}

int main(void)
{
	int r = 0;
	dispatch_queue q("Phillip's Demo Dispatch Queue", 4);

	q.dispatch([] {
		printf("Dispatch 1!\n");
	});
	q.dispatch([] {
		printf("Dispatch 2!\n");
	});
	q.dispatch([] {
		printf("Dispatch 3!\n");
	});
	q.dispatch([] {
		printf("Dispatch 4!\n");
	});

	return r;
}
<commit_msg>Simplify dispatch example by removing manual unlocks<commit_after>#include <thread>
#include <functional>
#include <vector>
#include <cstdint>
#include <cstdio>
#include <queue>
#include <mutex>
#include <string>
#include <condition_variable>

class dispatch_queue
{
	typedef std::function<void(void)> fp_t;

  public:
	dispatch_queue(std::string name, size_t thread_cnt = 1);
	~dispatch_queue();

	// dispatch and copy
	void dispatch(const fp_t& op);
	// dispatch and move
	void dispatch(fp_t&& op);

	// Deleted operations
	dispatch_queue(const dispatch_queue& rhs) = delete;
	dispatch_queue& operator=(const dispatch_queue& rhs) = delete;
	dispatch_queue(dispatch_queue&& rhs) = delete;
	dispatch_queue& operator=(dispatch_queue&& rhs) = delete;

  private:
	std::string name_;
	std::mutex lock_;
	std::vector<std::thread> threads_;
	std::queue<fp_t> q_;
	std::condition_variable cv_;
	bool quit_ = false;

	void dispatch_thread_handler(void);
};

dispatch_queue::dispatch_queue(std::string name, size_t thread_cnt) :
	name_{std::move(name)}, threads_(thread_cnt)
{
	printf("Creating dispatch queue: %s\n", name_.c_str());
	printf("Dispatch threads: %zu\n", thread_cnt);

	for(size_t i = 0; i < threads_.size(); i++)
	{
		threads_[i] = std::thread(&dispatch_queue::dispatch_thread_handler, this);
	}
}

dispatch_queue::~dispatch_queue()
{
	printf("Destructor: Destroying dispatch threads...\n");

	// Signal to dispatch threads that it's time to wrap up
	std::unique_lock<std::mutex> lock(lock_);
	quit_ = true;
	cv_.notify_all();
	lock.unlock();

	// Wait for threads to finish before we exit
	for(size_t i = 0; i < threads_.size(); i++)
	{
		if(threads_[i].joinable())
		{
			printf("Destructor: Joining thread %zu until completion\n", i);
			threads_[i].join();
		}
	}
}

void dispatch_queue::dispatch(const fp_t& op)
{
	std::unique_lock<std::mutex> lock(lock_);
	q_.push(op);
	cv_.notify_one();
}

void dispatch_queue::dispatch(fp_t&& op)
{
	std::unique_lock<std::mutex> lock(lock_);
	q_.push(std::move(op));
	cv_.notify_one();
}

void dispatch_queue::dispatch_thread_handler(void)
{
	std::unique_lock<std::mutex> lock(lock_);

	do
	{
		// Wait until we have data or a quit signal
		cv_.wait(lock, [this] {
			return (q_.size() || quit_);
		});

		// after wait, we own the lock
		if(!quit_ && q_.size())
		{
			auto op = std::move(q_.front());
			q_.pop();

			// unlock now that we're done messing with the queue
			lock.unlock();

			op();

			lock.lock();
		}
	} while(!quit_);
}

int main(void)
{
	int r = 0;
	dispatch_queue q("Phillip's Demo Dispatch Queue", 4);

	q.dispatch([] {
		printf("Dispatch 1!\n");
	});
	q.dispatch([] {
		printf("Dispatch 2!\n");
	});
	q.dispatch([] {
		printf("Dispatch 3!\n");
	});
	q.dispatch([] {
		printf("Dispatch 4!\n");
	});

	return r;
}
<|endoftext|>


<commit_before>#include "VirtualMachine.h"
#include "Machine.h"
#include <unistd.h>

extern "C" TVMMainEntry VMLoadModule(const char *module);
extern "C" void VMUnloadModule(void);
void incrementTicks(void*);

volatile unsigned int ticks;

TVMStatus VMStart(int tickms, int machinetickms, int argc, char *argv[])
{
  ticks = 0;
  TVMMainEntry mainFunc = VMLoadModule(argv[0]);
  MachineInitialize(machinetickms);
  MachineRequestAlarm((tickms*1000), incrementTicks, NULL);
  MachineEnableSignals();
  if (mainFunc)
  {
    mainFunc(argc, argv);
    VMUnloadModule();
    return VM_STATUS_SUCCESS;
  }

  return VM_STATUS_FAILURE;
} //VMStart

TVMStatus VMFileWrite(int filedescriptor, void *data, int *length)
{
  if (!data || !length)
  {
    return VM_STATUS_ERROR_INVALID_PARAMETER;
  }
//  MachineFileWrite(filedescriptor, data, length, , );
  if(write(filedescriptor, data, *length))
  {
    return VM_STATUS_SUCCESS;
  }
  return VM_STATUS_FAILURE;
} // VMFileWrite

TVMStatus VMThreadSleep(TVMTick tick)
{
  ticks = 0;
  if (tick == VM_TIMEOUT_IMMEDIATE)
  {
    // the current process yields the remainder of its processing quantum to the next ready process of equal priority.
  }
  else if (tick == VM_TIMEOUT_INFINITE)
  {
    return VM_STATUS_ERROR_INVALID_PARAMETER;
  }
  else
  {
    while (ticks < tick);
    //this should not just be a blind wait loop; should probably pass run time to next thread. Update later.
  } //does nothing while the number of ticks that have passed since entering this function is less than the number to sleep on

  return VM_STATUS_SUCCESS;
}

void incrementTicks(void*)
{
  ticks += 1;
}//helper function for sleeping

<commit_msg>VMFileOpen() written (incomplete)<commit_after>#include "VirtualMachine.h"
#include "Machine.h"
#include <unistd.h>

extern "C" TVMMainEntry VMLoadModule(const char *module);
extern "C" void VMUnloadModule(void);
void incrementTicks(void*);

volatile unsigned int ticks;

TVMStatus VMStart(int tickms, int machinetickms, int argc, char *argv[])
{
  ticks = 0;
  TVMMainEntry mainFunc = VMLoadModule(argv[0]);
  MachineInitialize(machinetickms);
  MachineRequestAlarm((tickms*1000), incrementTicks, NULL);
  MachineEnableSignals();
  if (mainFunc)
  {
    mainFunc(argc, argv);
    VMUnloadModule();
    return VM_STATUS_SUCCESS;
  }

  return VM_STATUS_FAILURE;
} //VMStart

TVMStatus VMFileOpen(const char *filename, int flags, int mode, int *filedescriptor)
{
  if (filename == NULL || filedescriptor == NULL)
  {
    return VM_STATUS_ERROR_INVALID_PARAMETER;
  }
  //change thread state to VM_THREAD_STATE_WAITING
  MachineFileOpen(filename, flags, mode, filedescriptor, NULL);
  // void MachineFileOpen(const char *filename, int flags, int mode, TMachineFileCallback callback, void *calldata);

  //change thread state to VM_THREAD_STATE_READY
  return VM_STATUS_SUCCESS;
//  return VM_STATUS_FAILURE;
} // VMFileOpen

TVMStatus VMFileWrite(int filedescriptor, void *data, int *length)
{
  if (!data || !length)
  {
    return VM_STATUS_ERROR_INVALID_PARAMETER;
  }
//  MachineFileWrite(filedescriptor, data, length, , );
  if(write(filedescriptor, data, *length))
  {
    return VM_STATUS_SUCCESS;
  }
  return VM_STATUS_FAILURE;
} // VMFileWrite

TVMStatus VMThreadSleep(TVMTick tick)
{
  ticks = 0;
  if (tick == VM_TIMEOUT_IMMEDIATE)
  {
    // the current process yields the remainder of its processing quantum to the next ready process of equal priority.
  }
  else if (tick == VM_TIMEOUT_INFINITE)
  {
    return VM_STATUS_ERROR_INVALID_PARAMETER;
  }
  else
  {
    while (ticks < tick);
    //this should not just be a blind wait loop; should probably pass run time to next thread. Update later.
  } //does nothing while the number of ticks that have passed since entering this function is less than the number to sleep on

  return VM_STATUS_SUCCESS;
}

void incrementTicks(void*)
{
  ticks += 1;
}//helper function for sleeping

<|endoftext|>


<commit_before>#include "MessagingController.h"
#include "IqrfCdcChannel.h"
#include "IqrfSpiChannel.h"
#include "DpaHandler.h"

#include "IClient.h"
//TODO temporary here
#include "TestClient.h"

//TODO temporary here
#include "IMessaging.h"
#include "UdpMessaging.h"
#include "MqMessaging.h"
#include "MqttMessaging.h"
#include "SchedulerMessaging.h"

#include "SimpleSerializer.h"
#include "JsonSerializer.h"

#include "IqrfLogging.h"
#include "PlatformDep.h"

void MessagingController::executeDpaTransaction(DpaTransaction& dpaTransaction)
{
  m_dpaTransactionQueue->pushToQueue(&dpaTransaction);
  //TODO wait here for something
}

//called from task queue thread passed by lambda in task queue ctor
void MessagingController::executeDpaTransactionFunc(DpaTransaction* dpaTransaction)
{
  if (m_dpaHandler) {
    try {
      m_dpaHandler->ExecuteDpaTransaction(*dpaTransaction);
    }
    catch (std::exception& e) {
      CATCH_EX("Error in ExecuteDpaTransaction: ", std::exception, e);
      dpaTransaction->processFinish(DpaRequest::kCreated);
    }
  }
  else {
    TRC_ERR("Dpa interface is not working");
    dpaTransaction->processFinish(DpaRequest::kCreated);
  }
}

void MessagingController::registerAsyncDpaMessageHandler(std::function<void(const DpaMessage&)> asyncHandler)
{
  m_asyncHandler = asyncHandler;
  m_dpaHandler->RegisterAsyncMessageHandler([&](const DpaMessage& dpaMessage) {
    m_asyncHandler(dpaMessage);
  });
}

MessagingController::MessagingController(const std::string& iqrfPortName)
  :m_iqrfInterface(nullptr)
  ,m_dpaHandler(nullptr)
  ,m_dpaTransactionQueue(nullptr)
  ,m_iqrfPortName(iqrfPortName)
  ,m_scheduler(nullptr)
{
}

MessagingController::~MessagingController ()
{
}

std::set<IMessaging*>& MessagingController::getSetOfMessaging()
{
  return m_protocols;
}

void MessagingController::registerMessaging(IMessaging& messaging)
{
  m_protocols.insert(&messaging);
}

void MessagingController::unregisterMessaging(IMessaging& messaging)
{
  m_protocols.erase(&messaging);
}

void MessagingController::watchDog()
{
  TRC_ENTER("");
  m_running = true;
  try {
    start();
    //TODO wait on condition until 3000
    while (m_running)
    {
      std::this_thread::sleep_for(std::chrono::milliseconds(1000));
      //TODO
      //watch worker threads and possibly restart
    }
  }
  catch (std::exception& e) {
    CATCH_EX("error", std::exception, e);
  }

  stop();
  TRC_LEAVE("");
}

void MessagingController::startClients()
{
  TRC_ENTER("");

  ///////// Messagings ///////////////////////////////////
  //TODO load Messagings plugins
  MqttMessaging* mqttMessaging = ant_new MqttMessaging();
  m_messagings.push_back(mqttMessaging);

  MqMessaging* mqMessaging = ant_new MqMessaging();
  m_messagings.push_back(mqMessaging);

  ///////// Serializers ///////////////////////////////////
  //TODO load Serializers plugins
  DpaTaskSimpleSerializerFactory* simpleSerializer = ant_new DpaTaskSimpleSerializerFactory();
  m_serializers.push_back(simpleSerializer);

  DpaTaskJsonSerializerFactory* jsonSerializer = ant_new DpaTaskJsonSerializerFactory();
  m_serializers.push_back(jsonSerializer);

  //////// Clients //////////////////////////////////
  //TODO load clients plugins
  IClient* client1 = ant_new TestClient("TestClient1");
  client1->setDaemon(this);
  client1->setMessaging(mqttMessaging);
  client1->setSerializer(simpleSerializer);
  m_clients.insert(std::make_pair(client1->getClientName(), client1));

  IClient* client2 = ant_new TestClient("TestClient2");
  client2->setDaemon(this);
  client2->setMessaging(mqttMessaging);
  client2->setSerializer(jsonSerializer);
  m_clients.insert(std::make_pair(client2->getClientName(), client2));

  IClient* clientIqrfapp = ant_new TestClient("TestClientIqrfapp");
  clientIqrfapp->setDaemon(this);
  clientIqrfapp->setMessaging(mqMessaging);
  clientIqrfapp->setSerializer(simpleSerializer);
  m_clients.insert(std::make_pair(clientIqrfapp->getClientName(), clientIqrfapp));

  /////////////////////
  for (auto cli : m_clients) {
    cli.second->start();
  }

  for (auto ms : m_messagings) {
    ms->start();
  }

  TRC_LEAVE("");
}

void MessagingController::stopClients()
{
  TRC_ENTER("");
  for (auto cli : m_clients) {
    cli.second->stop();
    delete cli.second;
  }
  m_clients.clear();

  for (auto ms : m_messagings) {
    ms->stop();
    delete ms;
  }
  m_messagings.clear();

  for (auto sr : m_serializers) {
    delete sr;
  }
  m_serializers.clear();

  TRC_LEAVE("");
}

void MessagingController::start()
{
  TRC_ENTER("");

  try {
    size_t found = m_iqrfPortName.find("spi");
    if (found != std::string::npos)
      m_iqrfInterface = ant_new IqrfSpiChannel(m_iqrfPortName);
    else
      m_iqrfInterface = ant_new IqrfCdcChannel(m_iqrfPortName);

    m_dpaHandler = ant_new DpaHandler(m_iqrfInterface);

    m_dpaHandler->Timeout(100);    // Default timeout is infinite
  }
  catch (std::exception& ae) {
    TRC_ERR("There was an error during DPA handler creation: " << ae.what());
  }

  m_dpaTransactionQueue = ant_new TaskQueue<DpaTransaction*>([&](DpaTransaction* trans) {
    executeDpaTransactionFunc(trans);
  });

  m_scheduler = ant_new SchedulerMessaging();

  startClients();

  m_scheduler->start();

  TRC_INF("daemon started");
  TRC_LEAVE("");
}

void MessagingController::stop()
{
  TRC_ENTER("");
  TRC_INF("daemon stops");

  m_scheduler->stop();

  stopClients();

  delete m_scheduler;

  //TODO unregister call-backs first ?
  delete m_iqrfInterface;
  delete m_dpaTransactionQueue;
  delete m_dpaHandler;

  TRC_LEAVE("");
}

void MessagingController::exit()
{
  TRC_INF("exiting ...");
  m_running = false;
}
<commit_msg>Reactivated UDP<commit_after>#include "MessagingController.h"
#include "IqrfCdcChannel.h"
#include "IqrfSpiChannel.h"
#include "DpaHandler.h"

#include "IClient.h"
//TODO temporary here
#include "TestClient.h"

//TODO temporary here
#include "IMessaging.h"
#include "UdpMessaging.h"
#include "MqMessaging.h"
#include "MqttMessaging.h"
#include "SchedulerMessaging.h"

#include "SimpleSerializer.h"
#include "JsonSerializer.h"

#include "IqrfLogging.h"
#include "PlatformDep.h"

void MessagingController::executeDpaTransaction(DpaTransaction& dpaTransaction)
{
  m_dpaTransactionQueue->pushToQueue(&dpaTransaction);
  //TODO wait here for something
}

//called from task queue thread passed by lambda in task queue ctor
void MessagingController::executeDpaTransactionFunc(DpaTransaction* dpaTransaction)
{
  if (m_dpaHandler) {
    try {
      m_dpaHandler->ExecuteDpaTransaction(*dpaTransaction);
    }
    catch (std::exception& e) {
      CATCH_EX("Error in ExecuteDpaTransaction: ", std::exception, e);
      dpaTransaction->processFinish(DpaRequest::kCreated);
    }
  }
  else {
    TRC_ERR("Dpa interface is not working");
    dpaTransaction->processFinish(DpaRequest::kCreated);
  }
}

void MessagingController::registerAsyncDpaMessageHandler(std::function<void(const DpaMessage&)> asyncHandler)
{
  m_asyncHandler = asyncHandler;
  m_dpaHandler->RegisterAsyncMessageHandler([&](const DpaMessage& dpaMessage) {
    m_asyncHandler(dpaMessage);
  });
}

MessagingController::MessagingController(const std::string& iqrfPortName)
  :m_iqrfInterface(nullptr)
  ,m_dpaHandler(nullptr)
  ,m_dpaTransactionQueue(nullptr)
  ,m_iqrfPortName(iqrfPortName)
  ,m_scheduler(nullptr)
{
}

MessagingController::~MessagingController ()
{
}

std::set<IMessaging*>& MessagingController::getSetOfMessaging()
{
  return m_protocols;
}

void MessagingController::registerMessaging(IMessaging& messaging)
{
  m_protocols.insert(&messaging);
}

void MessagingController::unregisterMessaging(IMessaging& messaging)
{
  m_protocols.erase(&messaging);
}

void MessagingController::watchDog()
{
  TRC_ENTER("");
  m_running = true;
  try {
    start();
    //TODO wait on condition until 3000
    while (m_running)
    {
      std::this_thread::sleep_for(std::chrono::milliseconds(1000));
      //TODO
      //watch worker threads and possibly restart
    }
  }
  catch (std::exception& e) {
    CATCH_EX("error", std::exception, e);
  }

  stop();
  TRC_LEAVE("");
}

void MessagingController::startClients()
{
  TRC_ENTER("");

  ///////// Messagings ///////////////////////////////////
  //TODO load Messagings plugins
  MqttMessaging* mqttMessaging = ant_new MqttMessaging();
  m_messagings.push_back(mqttMessaging);

  MqMessaging* mqMessaging = ant_new MqMessaging();
  m_messagings.push_back(mqMessaging);

  UdpMessaging* udpMessaging = ant_new UdpMessaging();
  udpMessaging->setDaemon(this);
  m_messagings.push_back(udpMessaging);

  ///////// Serializers ///////////////////////////////////
  //TODO load Serializers plugins
  DpaTaskSimpleSerializerFactory* simpleSerializer = ant_new DpaTaskSimpleSerializerFactory();
  m_serializers.push_back(simpleSerializer);

  DpaTaskJsonSerializerFactory* jsonSerializer = ant_new DpaTaskJsonSerializerFactory();
  m_serializers.push_back(jsonSerializer);

  //////// Clients //////////////////////////////////
  //TODO load clients plugins
  IClient* client1 = ant_new TestClient("TestClient1");
  client1->setDaemon(this);
  client1->setMessaging(mqttMessaging);
  client1->setSerializer(simpleSerializer);
  m_clients.insert(std::make_pair(client1->getClientName(), client1));

  IClient* client2 = ant_new TestClient("TestClient2");
  client2->setDaemon(this);
  client2->setMessaging(mqttMessaging);
  client2->setSerializer(jsonSerializer);
  m_clients.insert(std::make_pair(client2->getClientName(), client2));

  IClient* clientIqrfapp = ant_new TestClient("TestClientIqrfapp");
  clientIqrfapp->setDaemon(this);
  clientIqrfapp->setMessaging(mqMessaging);
  clientIqrfapp->setSerializer(simpleSerializer);
  m_clients.insert(std::make_pair(clientIqrfapp->getClientName(), clientIqrfapp));

  /////////////////////
  for (auto cli : m_clients) {
    cli.second->start();
  }

  for (auto ms : m_messagings) {
    ms->start();
  }

  TRC_LEAVE("");
}

void MessagingController::stopClients()
{
  TRC_ENTER("");
  for (auto cli : m_clients) {
    cli.second->stop();
    delete cli.second;
  }
  m_clients.clear();

  for (auto ms : m_messagings) {
    ms->stop();
    delete ms;
  }
  m_messagings.clear();

  for (auto sr : m_serializers) {
    delete sr;
  }
  m_serializers.clear();

  TRC_LEAVE("");
}

void MessagingController::start()
{
  TRC_ENTER("");

  try {
    size_t found = m_iqrfPortName.find("spi");
    if (found != std::string::npos)
      m_iqrfInterface = ant_new IqrfSpiChannel(m_iqrfPortName);
    else
      m_iqrfInterface = ant_new IqrfCdcChannel(m_iqrfPortName);

    m_dpaHandler = ant_new DpaHandler(m_iqrfInterface);

    m_dpaHandler->Timeout(100);    // Default timeout is infinite
  }
  catch (std::exception& ae) {
    TRC_ERR("There was an error during DPA handler creation: " << ae.what());
  }

  m_dpaTransactionQueue = ant_new TaskQueue<DpaTransaction*>([&](DpaTransaction* trans) {
    executeDpaTransactionFunc(trans);
  });

  m_scheduler = ant_new SchedulerMessaging();

  startClients();

  m_scheduler->start();

  TRC_INF("daemon started");
  TRC_LEAVE("");
}

void MessagingController::stop()
{
  TRC_ENTER("");
  TRC_INF("daemon stops");

  m_scheduler->stop();

  stopClients();

  delete m_scheduler;

  //TODO unregister call-backs first ?
  delete m_iqrfInterface;
  delete m_dpaTransactionQueue;
  delete m_dpaHandler;

  TRC_LEAVE("");
}

void MessagingController::exit()
{
  TRC_INF("exiting ...");
  m_running = false;
}
<|endoftext|>


<commit_before>#include "llvm/Pass.h"
#include "llvm/IR/Instructions.h"
#include "llvm/IR/Module.h"
#include "llvm/IR/Function.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/ADT/DenseSet.h"
#include "llvm/IR/IRBuilder.h"
#include "llvm/IR/TypeBuilder.h"

using namespace llvm;

namespace {
	struct PointerObservation : public FunctionPass {
		static char ID;
		PointerObservation() : FunctionPass(ID) {}

		bool runOnFunction(Function& f) override {

      // Identify injection points
DenseSet<Instruction*> pointerInstructions;
for(BasicBlock &bb : f) {
  	for(Instruction &i : bb) {
  		if (GetElementPtrInst* gep = dyn_cast<GetElementPtrInst>(&i)) {
        pointerInstructions.insert(gep);
  		}
  	}
}

      // Inject instructions
      for (Instruction *i : pointerInstructions) {
        errs() << "Injections print operation\n";
        IRBuilder<> builder(i);
        Function *printfFunction = getPrintFPrototype(i->getContext(), i->getModule());

        builder.CreateCall(printfFunction, geti8StrVal(*i->getModule(), "test\n", "name"));
      }

			return true;
		}

    Function *getPrintFPrototype(LLVMContext &ctx, Module *mod) {
      FunctionType *printf_type = TypeBuilder<int(char*, ...), false>::get(getGlobalContext());
      Function *func = cast<Function>(mod->getOrInsertFunction("printf", printf_type, AttributeSet().addAttribute(mod->getContext(), 1U, Attribute::NoAlias)));
      return func;
    }

    Constant* geti8StrVal(Module& M, char const* str, Twine const& name) {
      LLVMContext& ctx = getGlobalContext();
      Constant* strConstant = ConstantDataArray::getString(ctx, str);
      GlobalVariable* GVStr =
          new GlobalVariable(M, strConstant->getType(), true,
                             GlobalValue::InternalLinkage, strConstant, name);
      Constant* zero = Constant::getNullValue(IntegerType::getInt32Ty(ctx));
      Constant* indices[] = {zero, zero};
      Constant* strVal = ConstantExpr::getGetElementPtr(Type::getInt8PtrTy(ctx), GVStr, indices, true);
      return strVal;
    }

	};

}

char PointerObservation::ID = 0;
static RegisterPass<PointerObservation> X("PointerObservation", "Injects print calls before pointer operations", false, false);<commit_msg>Strange formatting error<commit_after>#include "llvm/Pass.h"
#include "llvm/IR/Instructions.h"
#include "llvm/IR/Module.h"
#include "llvm/IR/Function.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/ADT/DenseSet.h"
#include "llvm/IR/IRBuilder.h"
#include "llvm/IR/TypeBuilder.h"

using namespace llvm;

namespace {
	struct PointerObservation : public FunctionPass {
		static char ID;
		PointerObservation() : FunctionPass(ID) {}

		bool runOnFunction(Function& f) override {

      // Identify injection points
      DenseSet<Instruction*> pointerInstructions;
      for(BasicBlock &bb : f) {
        	for(Instruction &i : bb) {
        		if (GetElementPtrInst* gep = dyn_cast<GetElementPtrInst>(&i)) {
              pointerInstructions.insert(gep);
        		}
        	}
      }

      // Inject instructions
      for (Instruction *i : pointerInstructions) {
        errs() << "Injections print operation\n";
        IRBuilder<> builder(i);
        Function *printfFunction = getPrintFPrototype(i->getContext(), i->getModule());

        builder.CreateCall(printfFunction, geti8StrVal(*i->getModule(), "test\n", "name"));
      }

			return true;
		}

    Function *getPrintFPrototype(LLVMContext &ctx, Module *mod) {
      FunctionType *printf_type = TypeBuilder<int(char*, ...), false>::get(getGlobalContext());
      Function *func = cast<Function>(mod->getOrInsertFunction("printf", printf_type, AttributeSet().addAttribute(mod->getContext(), 1U, Attribute::NoAlias)));
      return func;
    }

    Constant* geti8StrVal(Module& M, char const* str, Twine const& name) {
      LLVMContext& ctx = getGlobalContext();
      Constant* strConstant = ConstantDataArray::getString(ctx, str);
      GlobalVariable* GVStr =
          new GlobalVariable(M, strConstant->getType(), true,
                             GlobalValue::InternalLinkage, strConstant, name);
      Constant* zero = Constant::getNullValue(IntegerType::getInt32Ty(ctx));
      Constant* indices[] = {zero, zero};
      Constant* strVal = ConstantExpr::getGetElementPtr(Type::getInt8PtrTy(ctx), GVStr, indices, true);
      return strVal;
    }

	};

}

char PointerObservation::ID = 0;
static RegisterPass<PointerObservation> X("PointerObservation", "Injects print calls before pointer operations", false, false);<|endoftext|>


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

// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_unotools.hxx"

#ifndef UNOTOOLS_INC_SHAREDUNOCOMPONENT_HXX
#include <unotools/sharedunocomponent.hxx>
#endif

#ifndef _COM_SUN_STAR_LANG_XCOMPONENT_HPP_
#include <com/sun/star/lang/XComponent.hpp>
#endif
#ifndef _COM_SUN_STAR_UTIL_XCLOSEABLE_HPP_
#include <com/sun/star/util/XCloseable.hpp>
#endif

#ifndef _CPPUHELPER_IMPLBASE1_HXX_
#include <cppuhelper/implbase1.hxx>
#endif

#ifndef _TOOLS_DEBUG_HXX
#include <tools/debug.hxx>
#endif

//............................................................................
namespace utl
{
//............................................................................

    using ::com::sun::star::uno::XInterface;
    using ::com::sun::star::uno::Reference;
    using ::com::sun::star::uno::Exception;
    using ::com::sun::star::uno::UNO_QUERY;
    using ::com::sun::star::uno::RuntimeException;
    using ::com::sun::star::lang::XComponent;
    using ::com::sun::star::lang::EventObject;
    using ::com::sun::star::util::XCloseable;
    using ::com::sun::star::util::XCloseListener;
    using ::com::sun::star::util::CloseVetoException;

    //========================================================================
    //= DisposableComponent
    //========================================================================
    //------------------------------------------------------------------------
    DisposableComponent::DisposableComponent( const Reference< XInterface >& _rxComponent )
        :m_xComponent( _rxComponent, UNO_QUERY )
    {
        DBG_ASSERT( m_xComponent.is() || !_rxComponent.is(), "DisposableComponent::DisposableComponent: should be an XComponent!" );
    }

    //------------------------------------------------------------------------
    DisposableComponent::~DisposableComponent()
    {
        if ( m_xComponent.is() )
        {
            try
            {
                m_xComponent->dispose();
            }
            catch( const Exception& )
            {
                OSL_ENSURE( sal_False, "DisposableComponent::~DisposableComponent: caught an exception!" );
            }
            m_xComponent.clear();
        }
    }

    //========================================================================
    //= CloseableComponentImpl
    //========================================================================
    DBG_NAME( CloseableComponentImpl )
    typedef ::cppu::WeakImplHelper1 <   XCloseListener
                                    >   CloseableComponentImpl_Base;
    class CloseableComponentImpl : public CloseableComponentImpl_Base
    {
    private:
        Reference< XCloseable > m_xCloseable;

    public:
        CloseableComponentImpl( const Reference< XInterface >& _rxComponent );

        /** closes the component

            @nofail
        */
        void    nf_closeComponent();

    protected:
        virtual ~CloseableComponentImpl();

        // XCloseListener overridables
        virtual void SAL_CALL queryClosing( const EventObject& Source, ::sal_Bool GetsOwnership ) throw (CloseVetoException, RuntimeException);
        virtual void SAL_CALL notifyClosing( const EventObject& Source ) throw (RuntimeException);

        // XEventListener overridables
        virtual void SAL_CALL disposing( const ::com::sun::star::lang::EventObject& Source ) throw (::com::sun::star::uno::RuntimeException);

    private:
        /** starts or stops being a CloseListener at the component

            Only to be called upon construction of the instance, or when the component
            is to be closed.

        @nofail
        */
        void    impl_nf_switchListening( bool _bListen );

    private:
        CloseableComponentImpl();                                           // never implemented
        CloseableComponentImpl( const CloseableComponentImpl& );            // never implemented
        CloseableComponentImpl& operator=( const CloseableComponentImpl& ); // never implemented
    };

    //------------------------------------------------------------------------
    CloseableComponentImpl::CloseableComponentImpl( const Reference< XInterface >& _rxComponent )
        :m_xCloseable( _rxComponent, UNO_QUERY )
    {
        DBG_CTOR( CloseableComponentImpl, NULL );
        DBG_ASSERT( m_xCloseable.is() || !_rxComponent.is(), "CloseableComponentImpl::CloseableComponentImpl: component is not an XCloseable!" );
        impl_nf_switchListening( true );
    }
    //------------------------------------------------------------------------
    CloseableComponentImpl::~CloseableComponentImpl()
    {
        nf_closeComponent();
        DBG_DTOR( CloseableComponentImpl, NULL );
    }

    //------------------------------------------------------------------------
    void CloseableComponentImpl::nf_closeComponent()
    {
        if ( !m_xCloseable.is() )
            // nothing to do
            return;

        // stop listening
        impl_nf_switchListening( false );

        // close
        try
        {
            m_xCloseable->close( sal_True );
        }
        catch( const CloseVetoException& ) { /* fine */ }
        catch( const Exception& )
        {
            OSL_ENSURE( sal_False, "CloseableComponentImpl::nf_closeComponent: caught an unexpected exception!" );
        }

        // reset
        m_xCloseable.clear();
    }

    //------------------------------------------------------------------------
    void CloseableComponentImpl::impl_nf_switchListening( bool _bListen )
    {
        if ( !m_xCloseable.is() )
            return;

        try
        {
            if ( _bListen )
                m_xCloseable->addCloseListener( this );
            else
                m_xCloseable->removeCloseListener( this );
        }
        catch( const Exception& )
        {
            OSL_ENSURE( sal_False, "CloseableComponentImpl::impl_nf_switchListening: caught an exception!" );
        }
    }

    //--------------------------------------------------------------------
    void SAL_CALL CloseableComponentImpl::queryClosing( const EventObject&
    #ifdef DBG_UTIL
    Source
    #endif
    , ::sal_Bool /*GetsOwnership*/ ) throw (CloseVetoException, RuntimeException)
    {
        // as long as we live, somebody wants to keep the object alive. So, veto the
        // closing
        DBG_ASSERT( Source.Source == m_xCloseable, "CloseableComponentImpl::queryClosing: where did this come from?" );
        throw CloseVetoException();
    }

    //--------------------------------------------------------------------
    void SAL_CALL CloseableComponentImpl::notifyClosing( const EventObject&
    #ifdef DBG_UTIL
    Source
    #endif
    ) throw (RuntimeException)
    {
        DBG_ASSERT( Source.Source == m_xCloseable, "CloseableComponentImpl::notifyClosing: where did this come from?" );

        // this should be unreachable: As long as we're a CloseListener, we veto the closing. If we're going
        // to close the component ourself, then we revoke ourself as listener *before* the close call. So,
        // if this here fires, something went definately wrong.
        DBG_ERROR( "CloseableComponentImpl::notifyClosing: unreachable!" );
    }

    //--------------------------------------------------------------------
    void SAL_CALL CloseableComponentImpl::disposing( const EventObject&
    #ifdef DBG_UTIL
    Source
    #endif
    ) throw (RuntimeException)
    {
        DBG_ASSERT( Source.Source == m_xCloseable, "CloseableComponentImpl::disposing: where did this come from?" );
        DBG_ERROR( "CloseableComponentImpl::disposing: unreachable!" );
            // same reasoning for this assertion as in ->notifyClosing
    }

    //========================================================================
    //= CloseableComponentImpl
    //========================================================================
    DBG_NAME( CloseableComponent )
    //------------------------------------------------------------------------
    CloseableComponent::CloseableComponent( const Reference< XInterface >& _rxComponent )
        :m_pImpl( new CloseableComponentImpl( _rxComponent ) )
    {
        DBG_CTOR( CloseableComponent, NULL );
    }

    //------------------------------------------------------------------------
    CloseableComponent::~CloseableComponent()
    {
        // close the component, deliver ownership to anybody who wants to veto the close
        m_pImpl->nf_closeComponent();
        DBG_DTOR( CloseableComponent, NULL );
    }

//............................................................................
}   // namespace utl
//............................................................................
<commit_msg>INTEGRATION: CWS changefileheader (1.6.84); FILE MERGED 2008/04/01 16:03:33 thb 1.6.84.3: #i85898# Stripping all external header guards 2008/04/01 12:59:55 thb 1.6.84.2: #i85898# Stripping all external header guards 2008/03/31 13:03:40 rt 1.6.84.1: #i87441# Change license header to LPGL v3.<commit_after>/*************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2008 by Sun Microsystems, Inc.
 *
 * OpenOffice.org - a multi-platform office productivity suite
 *
 * $RCSfile: sharedunocomponent.cxx,v $
 * $Revision: 1.7 $
 *
 * This file is part of OpenOffice.org.
 *
 * OpenOffice.org is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License version 3
 * only, as published by the Free Software Foundation.
 *
 * OpenOffice.org is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License version 3 for more details
 * (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU Lesser General Public License
 * version 3 along with OpenOffice.org.  If not, see
 * <http://www.openoffice.org/license.html>
 * for a copy of the LGPLv3 License.
 *
 ************************************************************************/

// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_unotools.hxx"
#include <unotools/sharedunocomponent.hxx>
#include <com/sun/star/lang/XComponent.hpp>
#include <com/sun/star/util/XCloseable.hpp>
#include <cppuhelper/implbase1.hxx>
#include <tools/debug.hxx>

//............................................................................
namespace utl
{
//............................................................................

    using ::com::sun::star::uno::XInterface;
    using ::com::sun::star::uno::Reference;
    using ::com::sun::star::uno::Exception;
    using ::com::sun::star::uno::UNO_QUERY;
    using ::com::sun::star::uno::RuntimeException;
    using ::com::sun::star::lang::XComponent;
    using ::com::sun::star::lang::EventObject;
    using ::com::sun::star::util::XCloseable;
    using ::com::sun::star::util::XCloseListener;
    using ::com::sun::star::util::CloseVetoException;

    //========================================================================
    //= DisposableComponent
    //========================================================================
    //------------------------------------------------------------------------
    DisposableComponent::DisposableComponent( const Reference< XInterface >& _rxComponent )
        :m_xComponent( _rxComponent, UNO_QUERY )
    {
        DBG_ASSERT( m_xComponent.is() || !_rxComponent.is(), "DisposableComponent::DisposableComponent: should be an XComponent!" );
    }

    //------------------------------------------------------------------------
    DisposableComponent::~DisposableComponent()
    {
        if ( m_xComponent.is() )
        {
            try
            {
                m_xComponent->dispose();
            }
            catch( const Exception& )
            {
                OSL_ENSURE( sal_False, "DisposableComponent::~DisposableComponent: caught an exception!" );
            }
            m_xComponent.clear();
        }
    }

    //========================================================================
    //= CloseableComponentImpl
    //========================================================================
    DBG_NAME( CloseableComponentImpl )
    typedef ::cppu::WeakImplHelper1 <   XCloseListener
                                    >   CloseableComponentImpl_Base;
    class CloseableComponentImpl : public CloseableComponentImpl_Base
    {
    private:
        Reference< XCloseable > m_xCloseable;

    public:
        CloseableComponentImpl( const Reference< XInterface >& _rxComponent );

        /** closes the component

            @nofail
        */
        void    nf_closeComponent();

    protected:
        virtual ~CloseableComponentImpl();

        // XCloseListener overridables
        virtual void SAL_CALL queryClosing( const EventObject& Source, ::sal_Bool GetsOwnership ) throw (CloseVetoException, RuntimeException);
        virtual void SAL_CALL notifyClosing( const EventObject& Source ) throw (RuntimeException);

        // XEventListener overridables
        virtual void SAL_CALL disposing( const ::com::sun::star::lang::EventObject& Source ) throw (::com::sun::star::uno::RuntimeException);

    private:
        /** starts or stops being a CloseListener at the component

            Only to be called upon construction of the instance, or when the component
            is to be closed.

        @nofail
        */
        void    impl_nf_switchListening( bool _bListen );

    private:
        CloseableComponentImpl();                                           // never implemented
        CloseableComponentImpl( const CloseableComponentImpl& );            // never implemented
        CloseableComponentImpl& operator=( const CloseableComponentImpl& ); // never implemented
    };

    //------------------------------------------------------------------------
    CloseableComponentImpl::CloseableComponentImpl( const Reference< XInterface >& _rxComponent )
        :m_xCloseable( _rxComponent, UNO_QUERY )
    {
        DBG_CTOR( CloseableComponentImpl, NULL );
        DBG_ASSERT( m_xCloseable.is() || !_rxComponent.is(), "CloseableComponentImpl::CloseableComponentImpl: component is not an XCloseable!" );
        impl_nf_switchListening( true );
    }
    //------------------------------------------------------------------------
    CloseableComponentImpl::~CloseableComponentImpl()
    {
        nf_closeComponent();
        DBG_DTOR( CloseableComponentImpl, NULL );
    }

    //------------------------------------------------------------------------
    void CloseableComponentImpl::nf_closeComponent()
    {
        if ( !m_xCloseable.is() )
            // nothing to do
            return;

        // stop listening
        impl_nf_switchListening( false );

        // close
        try
        {
            m_xCloseable->close( sal_True );
        }
        catch( const CloseVetoException& ) { /* fine */ }
        catch( const Exception& )
        {
            OSL_ENSURE( sal_False, "CloseableComponentImpl::nf_closeComponent: caught an unexpected exception!" );
        }

        // reset
        m_xCloseable.clear();
    }

    //------------------------------------------------------------------------
    void CloseableComponentImpl::impl_nf_switchListening( bool _bListen )
    {
        if ( !m_xCloseable.is() )
            return;

        try
        {
            if ( _bListen )
                m_xCloseable->addCloseListener( this );
            else
                m_xCloseable->removeCloseListener( this );
        }
        catch( const Exception& )
        {
            OSL_ENSURE( sal_False, "CloseableComponentImpl::impl_nf_switchListening: caught an exception!" );
        }
    }

    //--------------------------------------------------------------------
    void SAL_CALL CloseableComponentImpl::queryClosing( const EventObject&
    #ifdef DBG_UTIL
    Source
    #endif
    , ::sal_Bool /*GetsOwnership*/ ) throw (CloseVetoException, RuntimeException)
    {
        // as long as we live, somebody wants to keep the object alive. So, veto the
        // closing
        DBG_ASSERT( Source.Source == m_xCloseable, "CloseableComponentImpl::queryClosing: where did this come from?" );
        throw CloseVetoException();
    }

    //--------------------------------------------------------------------
    void SAL_CALL CloseableComponentImpl::notifyClosing( const EventObject&
    #ifdef DBG_UTIL
    Source
    #endif
    ) throw (RuntimeException)
    {
        DBG_ASSERT( Source.Source == m_xCloseable, "CloseableComponentImpl::notifyClosing: where did this come from?" );

        // this should be unreachable: As long as we're a CloseListener, we veto the closing. If we're going
        // to close the component ourself, then we revoke ourself as listener *before* the close call. So,
        // if this here fires, something went definately wrong.
        DBG_ERROR( "CloseableComponentImpl::notifyClosing: unreachable!" );
    }

    //--------------------------------------------------------------------
    void SAL_CALL CloseableComponentImpl::disposing( const EventObject&
    #ifdef DBG_UTIL
    Source
    #endif
    ) throw (RuntimeException)
    {
        DBG_ASSERT( Source.Source == m_xCloseable, "CloseableComponentImpl::disposing: where did this come from?" );
        DBG_ERROR( "CloseableComponentImpl::disposing: unreachable!" );
            // same reasoning for this assertion as in ->notifyClosing
    }

    //========================================================================
    //= CloseableComponentImpl
    //========================================================================
    DBG_NAME( CloseableComponent )
    //------------------------------------------------------------------------
    CloseableComponent::CloseableComponent( const Reference< XInterface >& _rxComponent )
        :m_pImpl( new CloseableComponentImpl( _rxComponent ) )
    {
        DBG_CTOR( CloseableComponent, NULL );
    }

    //------------------------------------------------------------------------
    CloseableComponent::~CloseableComponent()
    {
        // close the component, deliver ownership to anybody who wants to veto the close
        m_pImpl->nf_closeComponent();
        DBG_DTOR( CloseableComponent, NULL );
    }

//............................................................................
}   // namespace utl
//............................................................................
<|endoftext|>


<commit_before>// Copyright (c) 2010 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.
//
// HttpAlternateProtocols is an in-memory data structure used for keeping track
// of which HTTP HostPortPairs have an alternate protocol that can be used
// instead of HTTP on a different port.

#include "net/http/http_alternate_protocols.h"
#include "testing/gtest/include/gtest/gtest.h"

namespace net {
namespace {

TEST(HttpAlternateProtocols, Basic) {
  HttpAlternateProtocols alternate_protocols;
  HostPortPair test_host_port_pair;
  test_host_port_pair.host = "foo";
  test_host_port_pair.port = 80;
  EXPECT_FALSE(
      alternate_protocols.HasAlternateProtocolFor(test_host_port_pair));
  alternate_protocols.SetAlternateProtocolFor(
      test_host_port_pair, 443, HttpAlternateProtocols::NPN_SPDY_1);
  ASSERT_TRUE(alternate_protocols.HasAlternateProtocolFor(test_host_port_pair));
  const HttpAlternateProtocols::PortProtocolPair alternate =
      alternate_protocols.GetAlternateProtocolFor(test_host_port_pair);
  EXPECT_EQ(443, alternate.port);
  EXPECT_EQ(HttpAlternateProtocols::NPN_SPDY_1, alternate.protocol);
}

TEST(HttpAlternateProtocols, SetBroken) {
  HttpAlternateProtocols alternate_protocols;
  HostPortPair test_host_port_pair;
  test_host_port_pair.host = "foo";
  test_host_port_pair.port = 80;
  alternate_protocols.MarkBrokenAlternateProtocolFor(test_host_port_pair);
  ASSERT_TRUE(alternate_protocols.HasAlternateProtocolFor(test_host_port_pair));
  HttpAlternateProtocols::PortProtocolPair alternate =
      alternate_protocols.GetAlternateProtocolFor(test_host_port_pair);
  EXPECT_EQ(HttpAlternateProtocols::BROKEN, alternate.protocol);

  alternate_protocols.SetAlternateProtocolFor(
      test_host_port_pair,
      1234,
      HttpAlternateProtocols::NPN_SPDY_1),
  alternate = alternate_protocols.GetAlternateProtocolFor(test_host_port_pair);
  EXPECT_EQ(HttpAlternateProtocols::BROKEN, alternate.protocol)
      << "Second attempt should be ignored.";
}

}  // namespace
}  // namespace net
<commit_msg>Fix HttpAlternateProtocols unit test.<commit_after>// Copyright (c) 2010 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.
//
// HttpAlternateProtocols is an in-memory data structure used for keeping track
// of which HTTP HostPortPairs have an alternate protocol that can be used
// instead of HTTP on a different port.

#include "net/http/http_alternate_protocols.h"
#include "testing/gtest/include/gtest/gtest.h"

namespace net {
namespace {

TEST(HttpAlternateProtocols, Basic) {
  HttpAlternateProtocols alternate_protocols;
  HostPortPair test_host_port_pair;
  test_host_port_pair.host = "foo";
  test_host_port_pair.port = 80;
  EXPECT_FALSE(
      alternate_protocols.HasAlternateProtocolFor(test_host_port_pair));
  alternate_protocols.SetAlternateProtocolFor(
      test_host_port_pair, 443, HttpAlternateProtocols::NPN_SPDY_1);
  ASSERT_TRUE(alternate_protocols.HasAlternateProtocolFor(test_host_port_pair));
  const HttpAlternateProtocols::PortProtocolPair alternate =
      alternate_protocols.GetAlternateProtocolFor(test_host_port_pair);
  EXPECT_EQ(443, alternate.port);
  EXPECT_EQ(HttpAlternateProtocols::NPN_SPDY_1, alternate.protocol);
}

TEST(HttpAlternateProtocols, SetBroken) {
  HttpAlternateProtocols alternate_protocols;
  HostPortPair test_host_port_pair;
  test_host_port_pair.host = "foo";
  test_host_port_pair.port = 80;
  alternate_protocols.MarkBrokenAlternateProtocolFor(test_host_port_pair);
  ASSERT_TRUE(alternate_protocols.HasAlternateProtocolFor(test_host_port_pair));
  HttpAlternateProtocols::PortProtocolPair alternate =
      alternate_protocols.GetAlternateProtocolFor(test_host_port_pair);
  EXPECT_EQ(HttpAlternateProtocols::BROKEN, alternate.protocol);

  alternate_protocols.SetAlternateProtocolFor(
      test_host_port_pair,
      1234,
      HttpAlternateProtocols::NPN_SPDY_1);
  alternate = alternate_protocols.GetAlternateProtocolFor(test_host_port_pair);
  EXPECT_EQ(HttpAlternateProtocols::BROKEN, alternate.protocol)
      << "Second attempt should be ignored.";
}

}  // namespace
}  // namespace net
<|endoftext|>