<commit_before>#include "../common/numbers.h"
#include "materials.h"

#include <deal.II/base/utilities.h>

Materials::Materials (dealii::ParameterHandler &prm)
    : is_eigen_problem_(prm.get_bool("do eigenvalue calculations")),
      do_nda_(prm.get_bool("do nda")),
      n_group_(prm.get_integer("number of groups")),
      n_material_(prm.get_integer("number of materials")) {
  ProcessMaterials(prm);
}

Materials::~Materials () {}

void Materials::ProcessMaterials (dealii::ParameterHandler &prm) {
  if (n_group_>1) {
    prm.enter_subsection ("sigma_t, group=1 to G");
    {
      for (int m=0; m<n_material_; ++m) {
        std::ostringstream os;
        os << "material " << m + 1;
        std::vector<std::string> strings =
            dealii::Utilities::split_string_list (prm.get(os.str()));
        AssertThrow (strings.size () == n_group_,
            dealii::ExcMessage ("n_group_ is not equal to group number of sigma_t"));
        std::vector<double> tmp, inv_tmp;
        for (int g=0; g<n_group_; ++g) {
          tmp.push_back (std::atof (strings[g].c_str ()));
          inv_tmp.push_back (1.0/tmp[g]);
        }
        sigt_[m] = tmp;
        inv_sigt_[m] = inv_tmp;
      }
    }
    prm.leave_subsection ();

    // This block takes in scattering transfer matrices
    for (int m=0; m<n_material_; ++m) {
      std::ostringstream osm;
      osm << "sigma_s, material " << m + 1;
      dealii::FullMatrix<double> tmp_sigs (n_group_, n_group_);
      prm.enter_subsection (osm.str());
      {
        for (int gin=0; gin<n_group_; ++gin) {
          std::ostringstream os;
          os << "g_in=" << gin + 1;
          std::vector<std::string> strings =
              dealii::Utilities::split_string_list (prm.get(os.str()));
          AssertThrow (strings.size()==n_group_,
                       dealii::ExcMessage("sigma_s should have n_group_ entries per in group"));
          for (int g=0; g<n_group_; ++g) {
            tmp_sigs(gin, g) = std::atof (strings[g].c_str());
          }
        }
      }
      prm.leave_subsection ();
      sigs_[m] = tmp_sigs;
      sigs_per_ster_[m] = tmp_sigs;
      sigs_per_ster_[m] *= bconst::kInvFourPi;
    }

    if (!is_eigen_problem_) {
      prm.enter_subsection ("Q, group=1 to G");
      {
        for (int m=0; m<n_material_; ++m) {
          std::ostringstream os;
          os << "material " << m + 1;
          std::vector<std::string> strings = dealii::Utilities::split_string_list (prm.get (os.str ()));
          AssertThrow (strings.size () == n_group_,
                       dealii::ExcMessage ("n_group_ is not equal to group number of Q"));
          std::vector<double> tmp_q;
          for (int g=0; g<n_group_; ++g)
            tmp_q.push_back (std::atof (strings[g].c_str ()));
          q_[m] = tmp_q;
          q_per_ster_[m] = tmp_q;
          std::for_each(q_per_ster_[m].begin(), q_per_ster_[m].end(),
              [&](double &val){return val*bconst::kInvFourPi;});
        }
      }
      prm.leave_subsection ();
    }
  } else {
    prm.enter_subsection ("one-group sigma_t");
    {
      std::cout << "are we here1" << std::endl;
      std::vector<std::string> strings =
          dealii::Utilities::split_string_list (prm.get("values"));
      AssertThrow (strings.size()>=n_material_,
          dealii::ExcMessage("One-group sigma_t should have n_material_ entries"));
      std::cout << "are we here2" << std::endl;

      for (int m=0; m<n_material_; ++m) {
        std::vector<double> tmp = {std::atof (strings[m].c_str())};
        std::vector<double> inv_tmp = {1.0 / std::atof (strings[m].c_str())};
        sigt_[m] = tmp;
        inv_sigt_[m] = inv_tmp;
      }
      std::cout << "are we here3" << std::endl;

    }
    prm.leave_subsection ();

    prm.enter_subsection ("one-group sigma_s");
    {
      std::vector<std::string> strings =
          dealii::Utilities::split_string_list (prm.get("values"));
      AssertThrow (strings.size()==n_material_,
          dealii::ExcMessage("One-group sigma_s should have n_material_ entries"));
      for (int m=0; m<n_material_; ++m) {
        dealii::FullMatrix<double> tmp(1,1);
        std::cout << "material" << m << std::endl;
        tmp(0,0) = std::atof(strings[m].c_str());
        sigs_[m] = tmp;
        sigs_per_ster_[m] = tmp;
        sigs_per_ster_[m] *= bconst::kInvFourPi;
      }
      std::cout << "are we here 9" << std::endl;
    }
    prm.leave_subsection ();

    if (!is_eigen_problem_) {
      prm.enter_subsection ("one-group Q");
      {
        std::vector<std::string> strings = dealii::Utilities::split_string_list (prm.get("values"));
        AssertThrow (strings.size()==n_material_,
                     dealii::ExcMessage("One-group Q should have n_material_ entries"));
        std::vector<double> tmp_sigt (n_material_);
        for (int m=0; m<n_material_; ++m) {
          std::vector<double> tmp = {std::atof (strings[m].c_str())};
          q_[m] = tmp;
          std::vector<double> tmp_per_ster = {std::atof(strings[m].c_str())/bconst::kFourPi};
          q_per_ster_[m] = tmp_per_ster;
        }
      }
      prm.leave_subsection ();
    }
  }

  // This block is for eigenvalue problems
  if (is_eigen_problem_)
    ProcessEigenMaterials (prm);
  std::cout << "are we here end1" << std::endl;
}

void Materials::ProcessEigenMaterials (dealii::ParameterHandler &prm) {
  prm.enter_subsection ("fissile material IDs");
  {
    std::ostringstream os;
    os << "fissile material ids";
    std::vector<std::string> strings = dealii::Utilities::split_string_list (prm.get (os.str ()));
    AssertThrow (strings.size () > 0,
                 dealii::ExcMessage ("Fissile material IDs must be inserted for eigen problems"));
    // std::set<int> fissile_ids;
    for (int i=0; i<strings.size(); ++i)
      fissile_ids_.insert (std::atoi(strings[i].c_str())-1);
  }
  prm.leave_subsection ();

  for (int m=0; m<n_material_; ++m) {
    if (fissile_ids_.find(m)!=fissile_ids_.end())
      is_material_fissile_[m] = true;
    else
      is_material_fissile_[m] = false;
  }
  AssertThrow (!is_material_fissile_.empty (),
      dealii::ExcMessage ("Please specify at least one valid ID for fissile materials"));
  std::cout << "are we here 7" << std::endl;
  if (n_group_>1) {
    prm.enter_subsection ("chi, group=1 to G");
    {
      for (int m=0; m<n_material_;++m) {
        std::vector<double> tmp(n_group_);
        if (is_material_fissile_[m]) {
          std::ostringstream os;
          os << "material " << m + 1;
          std::vector<std::string> strings =
              dealii::Utilities::split_string_list (prm.get(os.str()));
          AssertThrow (strings.size () == n_group_,
              dealii::ExcMessage ("n_group_ is not equal to group number of chi"));
          std::vector<double> tmp(n_group_);
          for (int g=0; g<n_group_; ++g)
            tmp[g] = std::atof (strings[g].c_str ());
        }
        chi_[m] = tmp;
      }
    }
    prm.leave_subsection ();

    prm.enter_subsection ("nu_sigf, group=1 to G");
    {
      for (int m=0; m<n_material_;++m) {
        std::vector<double> tmp(n_group_);
        if (is_material_fissile_[m]) {
          std::ostringstream os;
          os << "material " << m + 1;
          std::vector<std::string> strings =
              dealii::Utilities::split_string_list (prm.get (os.str ()));
          AssertThrow (strings.size () == n_group_,
              dealii::ExcMessage ("n_group_ is not equal to group number of nusigf"));
          std::vector<double> tmp(n_group_);
          for (int g=0; g<n_group_; ++g)
            tmp[g] = std::atof (strings[g].c_str ());
        }
        nu_sigf_[m] = tmp;
      }
    }
    prm.leave_subsection ();
  } else {
    // the following is for one-group
    prm.enter_subsection ("one-group chi");
    {
      std::cout << "are we here 6" << std::endl;
      std::vector<std::string> strings =
          dealii::Utilities::split_string_list (prm.get("values"));
      std::cout << "chi size " << strings.size() << " materi " << n_material_ << std::endl;
      AssertThrow (strings.size()==n_material_,
          dealii::ExcMessage("One-group chi should have n_material_ entries"));
      std::vector<double> tmp_sigt (n_material_);
      for (int m=0; m<n_material_; ++m) {
        std::vector<double> tmp {is_material_fissile_[m] ?
            std::atof (strings[m].c_str()) : 0.0};
        chi_[m] = tmp;
      }
    }
    prm.leave_subsection ();
    std::cout << "are we here 5" << std::endl;
    prm.enter_subsection ("one-group nu_sigf");
    {
      std::vector<std::string> strings = dealii::Utilities::split_string_list (prm.get("values"));
      AssertThrow (strings.size()==n_material_,
          dealii::ExcMessage("One-group sigma_t should have n_material_ entries"));
      std::vector<double> tmp_sigt (n_material_);
      for (int m=0; m<n_material_; ++m)
      {
        std::vector<double> tmp {is_material_fissile_[m] ?
            std::atof (strings[m].c_str()) : 0.0};
        nu_sigf_[m] = tmp;
      }
    }
    prm.leave_subsection ();
  }
  std::cout << "are we here 4" << std::endl;
  for (int m=0; m<n_material_; ++m)
  {
    dealii::FullMatrix<double> tmp (n_group_, n_group_);
    if (is_material_fissile_[m])
      for (int gin=0; gin<n_group_; ++gin)
        for (int g=0; g<n_group_; ++g)
          tmp(gin,g) = chi_[m][g] * nu_sigf_[m][gin];

    fiss_transfer_[m] = tmp;
    fiss_transfer_per_ster_[m] = tmp;
    fiss_transfer_per_ster_[m] *= bconst::kInvFourPi;
  }
  std::cout << "are we here end" << std::endl;

}

std::unordered_map<int, std::vector<double>>
Materials::GetSigT () const {
  return sigt_;
}

std::unordered_map<int, std::vector<double>>
Materials::GetInvSigT () const {
  return inv_sigt_;
}

std::unordered_map<int, std::vector<double>> Materials::GetQ() const {
  return q_;
}

std::unordered_map<int, std::vector<double>>
Materials::GetQPerSter() const {
  return q_per_ster_;
}

std::unordered_map<int, dealii::FullMatrix<double>>
Materials::GetSigS() const {
  return sigs_;
}

std::unordered_map<int, dealii::FullMatrix<double>>
Materials::GetSigSPerSter () const {
  return sigs_per_ster_;
}

std::unordered_map<int, dealii::FullMatrix<double>>
Materials::GetFissTransfer () const {
  return fiss_transfer_;
}

std::unordered_map<int, dealii::FullMatrix<double>>
Materials::GetFissTransferPerSter () const {
  return fiss_transfer_per_ster_;
}

std::unordered_map<int, std::vector<double>> Materials::GetNuSigf () const {
  return nu_sigf_;
}

std::unordered_map<int, bool> Materials::GetFissileIDMap () const {
  return is_material_fissile_;
}
<commit_msg>deleted debugging stuff<commit_after>#include "../common/numbers.h"
#include "materials.h"

#include <deal.II/base/utilities.h>

Materials::Materials (dealii::ParameterHandler &prm)
    : is_eigen_problem_(prm.get_bool("do eigenvalue calculations")),
      do_nda_(prm.get_bool("do nda")),
      n_group_(prm.get_integer("number of groups")),
      n_material_(prm.get_integer("number of materials")) {
  ProcessMaterials(prm);
}

Materials::~Materials () {}

void Materials::ProcessMaterials (dealii::ParameterHandler &prm) {
  if (n_group_>1) {
    prm.enter_subsection ("sigma_t, group=1 to G");
    {
      for (int m=0; m<n_material_; ++m) {
        std::ostringstream os;
        os << "material " << m + 1;
        std::vector<std::string> strings =
            dealii::Utilities::split_string_list (prm.get(os.str()));
        AssertThrow (strings.size () == n_group_,
            dealii::ExcMessage ("n_group_ is not equal to group number of sigma_t"));
        std::vector<double> tmp, inv_tmp;
        for (int g=0; g<n_group_; ++g) {
          tmp.push_back (std::atof (strings[g].c_str ()));
          inv_tmp.push_back (1.0/tmp[g]);
        }
        sigt_[m] = tmp;
        inv_sigt_[m] = inv_tmp;
      }
    }
    prm.leave_subsection ();

    // This block takes in scattering transfer matrices
    for (int m=0; m<n_material_; ++m) {
      std::ostringstream osm;
      osm << "sigma_s, material " << m + 1;
      dealii::FullMatrix<double> tmp_sigs (n_group_, n_group_);
      prm.enter_subsection (osm.str());
      {
        for (int gin=0; gin<n_group_; ++gin) {
          std::ostringstream os;
          os << "g_in=" << gin + 1;
          std::vector<std::string> strings =
              dealii::Utilities::split_string_list (prm.get(os.str()));
          AssertThrow (strings.size()==n_group_,
                       dealii::ExcMessage("sigma_s should have n_group_ entries per in group"));
          for (int g=0; g<n_group_; ++g) {
            tmp_sigs(gin, g) = std::atof (strings[g].c_str());
          }
        }
      }
      prm.leave_subsection ();
      sigs_[m] = tmp_sigs;
      sigs_per_ster_[m] = tmp_sigs;
      sigs_per_ster_[m] *= bconst::kInvFourPi;
    }

    if (!is_eigen_problem_) {
      prm.enter_subsection ("Q, group=1 to G");
      {
        for (int m=0; m<n_material_; ++m) {
          std::ostringstream os;
          os << "material " << m + 1;
          std::vector<std::string> strings = dealii::Utilities::split_string_list (prm.get (os.str ()));
          AssertThrow (strings.size () == n_group_,
                       dealii::ExcMessage ("n_group_ is not equal to group number of Q"));
          std::vector<double> tmp_q;
          for (int g=0; g<n_group_; ++g)
            tmp_q.push_back (std::atof (strings[g].c_str ()));
          q_[m] = tmp_q;
          q_per_ster_[m] = tmp_q;
          std::for_each(q_per_ster_[m].begin(), q_per_ster_[m].end(),
              [&](double &val){return val*bconst::kInvFourPi;});
        }
      }
      prm.leave_subsection ();
    }
  } else {
    prm.enter_subsection ("one-group sigma_t");
    {
      std::vector<std::string> strings =
          dealii::Utilities::split_string_list (prm.get("values"));
      AssertThrow (strings.size()>=n_material_,
          dealii::ExcMessage("One-group sigma_t should have n_material_ entries"));

      for (int m=0; m<n_material_; ++m) {
        std::vector<double> tmp = {std::atof (strings[m].c_str())};
        std::vector<double> inv_tmp = {1.0 / std::atof (strings[m].c_str())};
        sigt_[m] = tmp;
        inv_sigt_[m] = inv_tmp;
      }
    }
    prm.leave_subsection ();

    prm.enter_subsection ("one-group sigma_s");
    {
      std::vector<std::string> strings =
          dealii::Utilities::split_string_list (prm.get("values"));
      AssertThrow (strings.size()==n_material_,
          dealii::ExcMessage("One-group sigma_s should have n_material_ entries"));
      for (int m=0; m<n_material_; ++m) {
        dealii::FullMatrix<double> tmp(1,1);
        tmp(0,0) = std::atof(strings[m].c_str());
        sigs_[m] = tmp;
        sigs_per_ster_[m] = tmp;
        sigs_per_ster_[m] *= bconst::kInvFourPi;
      }
    }
    prm.leave_subsection ();

    if (!is_eigen_problem_) {
      prm.enter_subsection ("one-group Q");
      {
        std::vector<std::string> strings = dealii::Utilities::split_string_list (prm.get("values"));
        AssertThrow (strings.size()==n_material_,
                     dealii::ExcMessage("One-group Q should have n_material_ entries"));
        std::vector<double> tmp_sigt (n_material_);
        for (int m=0; m<n_material_; ++m) {
          std::vector<double> tmp = {std::atof (strings[m].c_str())};
          q_[m] = tmp;
          std::vector<double> tmp_per_ster = {std::atof(strings[m].c_str())/bconst::kFourPi};
          q_per_ster_[m] = tmp_per_ster;
        }
      }
      prm.leave_subsection ();
    }
  }

  // This block is for eigenvalue problems
  if (is_eigen_problem_)
    ProcessEigenMaterials (prm);
}

void Materials::ProcessEigenMaterials (dealii::ParameterHandler &prm) {
  prm.enter_subsection ("fissile material IDs");
  {
    std::ostringstream os;
    os << "fissile material ids";
    std::vector<std::string> strings = dealii::Utilities::split_string_list (prm.get (os.str ()));
    AssertThrow (strings.size () > 0,
                 dealii::ExcMessage ("Fissile material IDs must be inserted for eigen problems"));
    // std::set<int> fissile_ids;
    for (int i=0; i<strings.size(); ++i)
      fissile_ids_.insert (std::atoi(strings[i].c_str())-1);
  }
  prm.leave_subsection ();

  for (int m=0; m<n_material_; ++m) {
    if (fissile_ids_.find(m)!=fissile_ids_.end())
      is_material_fissile_[m] = true;
    else
      is_material_fissile_[m] = false;
  }
  AssertThrow (!is_material_fissile_.empty (),
      dealii::ExcMessage ("Please specify at least one valid ID for fissile materials"));
  if (n_group_>1) {
    prm.enter_subsection ("chi, group=1 to G");
    {
      for (int m=0; m<n_material_;++m) {
        std::vector<double> tmp(n_group_);
        if (is_material_fissile_[m]) {
          std::ostringstream os;
          os << "material " << m + 1;
          std::vector<std::string> strings =
              dealii::Utilities::split_string_list (prm.get(os.str()));
          AssertThrow (strings.size () == n_group_,
              dealii::ExcMessage ("n_group_ is not equal to group number of chi"));
          std::vector<double> tmp(n_group_);
          for (int g=0; g<n_group_; ++g)
            tmp[g] = std::atof (strings[g].c_str ());
        }
        chi_[m] = tmp;
      }
    }
    prm.leave_subsection ();

    prm.enter_subsection ("nu_sigf, group=1 to G");
    {
      for (int m=0; m<n_material_;++m) {
        std::vector<double> tmp(n_group_);
        if (is_material_fissile_[m]) {
          std::ostringstream os;
          os << "material " << m + 1;
          std::vector<std::string> strings =
              dealii::Utilities::split_string_list (prm.get (os.str ()));
          AssertThrow (strings.size () == n_group_,
              dealii::ExcMessage ("n_group_ is not equal to group number of nusigf"));
          std::vector<double> tmp(n_group_);
          for (int g=0; g<n_group_; ++g)
            tmp[g] = std::atof (strings[g].c_str ());
        }
        nu_sigf_[m] = tmp;
      }
    }
    prm.leave_subsection ();
  } else {
    // the following is for one-group
    prm.enter_subsection ("one-group chi");
    {
      std::vector<std::string> strings =
          dealii::Utilities::split_string_list (prm.get("values"));
      AssertThrow (strings.size()==n_material_,
          dealii::ExcMessage("One-group chi should have n_material_ entries"));
      std::vector<double> tmp_sigt (n_material_);
      for (int m=0; m<n_material_; ++m) {
        std::vector<double> tmp {is_material_fissile_[m] ?
            std::atof (strings[m].c_str()) : 0.0};
        chi_[m] = tmp;
      }
    }
    prm.leave_subsection ();
    prm.enter_subsection ("one-group nu_sigf");
    {
      std::vector<std::string> strings = dealii::Utilities::split_string_list (prm.get("values"));
      AssertThrow (strings.size()==n_material_,
          dealii::ExcMessage("One-group sigma_t should have n_material_ entries"));
      std::vector<double> tmp_sigt (n_material_);
      for (int m=0; m<n_material_; ++m)
      {
        std::vector<double> tmp {is_material_fissile_[m] ?
            std::atof (strings[m].c_str()) : 0.0};
        nu_sigf_[m] = tmp;
      }
    }
    prm.leave_subsection ();
  }
  for (int m=0; m<n_material_; ++m)
  {
    dealii::FullMatrix<double> tmp (n_group_, n_group_);
    if (is_material_fissile_[m])
      for (int gin=0; gin<n_group_; ++gin)
        for (int g=0; g<n_group_; ++g)
          tmp(gin,g) = chi_[m][g] * nu_sigf_[m][gin];

    fiss_transfer_[m] = tmp;
    fiss_transfer_per_ster_[m] = tmp;
    fiss_transfer_per_ster_[m] *= bconst::kInvFourPi;
  }
}

std::unordered_map<int, std::vector<double>>
Materials::GetSigT () const {
  return sigt_;
}

std::unordered_map<int, std::vector<double>>
Materials::GetInvSigT () const {
  return inv_sigt_;
}

std::unordered_map<int, std::vector<double>> Materials::GetQ() const {
  return q_;
}

std::unordered_map<int, std::vector<double>>
Materials::GetQPerSter() const {
  return q_per_ster_;
}

std::unordered_map<int, dealii::FullMatrix<double>>
Materials::GetSigS() const {
  return sigs_;
}

std::unordered_map<int, dealii::FullMatrix<double>>
Materials::GetSigSPerSter () const {
  return sigs_per_ster_;
}

std::unordered_map<int, dealii::FullMatrix<double>>
Materials::GetFissTransfer () const {
  return fiss_transfer_;
}

std::unordered_map<int, dealii::FullMatrix<double>>
Materials::GetFissTransferPerSter () const {
  return fiss_transfer_per_ster_;
}

std::unordered_map<int, std::vector<double>> Materials::GetNuSigf () const {
  return nu_sigf_;
}

std::unordered_map<int, bool> Materials::GetFissileIDMap () const {
  return is_material_fissile_;
}
<|endoftext|>


<commit_before>/*
 * (cd ../lib && make all-c)
 * afl-g++ -std=gnu++11 -fPIC -O -I../lib fuzz.c ../lib/graph.cc ../lib/murmur32s.pico ../lib/murmur32v.pico ../lib/xxh32s.pico ../lib/xxh64s.pico ../lib/fastdiv.pico ../lib/jenkins2v.pico
 *
 * ./a.out && mv fuzz.dat ${INPUTDIR:?}
 * afl-fuzz -i ${INPUTDIR:?} -o ${OUTPUTDIR:?} ./a.out @@
 */

#include <fcntl.h>
#include <stdbool.h>
#include <stddef.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <unistd.h>

#include "rgph_defs.h"
#include "rgph_graph.h"

static const char letters[] = "abcdefghijklmnopqrstuvwxyz";

struct fuzz_entry {
	uint64_t index;
	uint8_t has_index;
	uint8_t keylen;
	char key[54];
};

struct fuzz_header {
	size_t nverts;
	unsigned long seed;
	int alloc_flags;
	int build_flags;
	int assign_flags;
	unsigned int nentries;
	struct fuzz_entry entries[];
};

struct iterator_state {
	size_t pos;
	size_t nentries;
	struct fuzz_entry *entries;
	struct rgph_entry out;
};

static inline size_t
min(size_t a, size_t b)
{

	return a < b ? a : b;
}

static inline size_t
max(size_t a, size_t b)
{

	return a > b ? a : b;
}

static const struct rgph_entry *
iterator_func(void *state)
{
	struct iterator_state *s = (struct iterator_state *)state;
	struct fuzz_entry *in = &s->entries[s->pos];
	struct rgph_entry *out = &s->out;

	if (s->pos == s->nentries)
		return NULL;

	out->key = out->data = in->key;
	out->keylen = out->datalen = min(sizeof(in->key), in->keylen);
	out->index = in->index;
	out->has_index = in->has_index;

	s->pos++;
	return out;
}

int
write_sample_input(void)
{
	fuzz_header h;
	FILE *f;
	size_t i;

	memset(&h, 0, sizeof(h));

	f = fopen("fuzz.dat", "w");
	if (f == NULL)
		return EXIT_FAILURE;

	h.nverts = h.nentries = sizeof(letters) - 1;
	h.seed = 123456789;
	h.alloc_flags = 0;
	h.build_flags = 0;
	h.assign_flags = 0;

	if (fwrite(&h, 1, sizeof(h), f) != sizeof(h)) {
		fclose(f);
		return EXIT_FAILURE;
	}

	for (i = 0; i < sizeof(letters) - 1; i++) {
		struct fuzz_entry e;

		e.index = i;
		e.has_index = true;
		e.keylen = 2;
		memcpy(e.key, &letters[i], 2);

		if (fwrite(&e, 1, sizeof(e), f) != sizeof(e)) {
			fclose(f);
			return EXIT_FAILURE;
		}
	}

	fclose(f);
	return EXIT_SUCCESS;
}

int
main(int argc, char *argv[])
{
	iterator_state state;
	struct stat st;
	struct fuzz_header *h;
	struct rgph_graph *g;
	void *buf;
	size_t flen;
	unsigned long seed;
	int build_flags, fd, i, res;

	if (argc < 2)
		return write_sample_input();

	fd = open(argv[1], O_RDONLY);
	if (fd == -1)
		return EXIT_FAILURE;

	if (fstat(fd, &st) == -1) {
		close(fd);
		return EXIT_FAILURE;
	}

	flen = max(st.st_size, sizeof(*h));

	buf = mmap(NULL, flen, PROT_READ, MAP_FILE | MAP_PRIVATE, fd, 0);
	h = (struct fuzz_header *)buf;
	close(fd);

	if (buf == MAP_FAILED)
		return EXIT_FAILURE;

	g = rgph_alloc_graph(h->nverts, h->alloc_flags);
	if (g == NULL)
		return EXIT_FAILURE;

	seed = h->seed;
	build_flags = h->build_flags;
	state.entries = h->entries;
	state.nentries = min(h->nentries,
	    (flen - sizeof(*h)) / sizeof(h->entries[0]));

	for (i = 0; true; i++) {
		size_t dup[2];

		state.pos = 0;
		res = rgph_build_graph(g, build_flags, seed++,
		    &iterator_func, &state);
		if (res == RGPH_SUCCESS || res != RGPH_AGAIN)
			break;

		state.pos = 0;
		res = rgph_find_duplicates(g, &iterator_func, &state, dup);
		if (res == RGPH_SUCCESS)
			break;

		/* Some hashes are weak. Rotate them periodically. */
		if ((i % 8) == 7) {
			int next_hash = (build_flags & RGPH_HASH_MASK) + 1;

			if (next_hash >= RGPH_HASH_LAST)
				next_hash = 0;

			build_flags &= ~RGPH_HASH_MASK;
			build_flags |= next_hash;
		}
	}

	res = rgph_assign(g, h->assign_flags);

	rgph_free_graph(g);

	return res == RGPH_SUCCESS ? EXIT_SUCCESS : EXIT_FAILURE;
}
<commit_msg>It's now .cc.<commit_after>/*
 * (cd ../lib && make all-c)
 * afl-g++ -std=gnu++11 -fPIC -O -I../lib fuzz.cc ../lib/graph.cc ../lib/murmur32s.pico ../lib/murmur32v.pico ../lib/xxh32s.pico ../lib/xxh64s.pico ../lib/fastdiv.pico ../lib/jenkins2v.pico
 *
 * ./a.out && mv fuzz.dat ${INPUTDIR:?}
 * afl-fuzz -i ${INPUTDIR:?} -o ${OUTPUTDIR:?} ./a.out @@
 */

#include <fcntl.h>
#include <stdbool.h>
#include <stddef.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <unistd.h>

#include "rgph_defs.h"
#include "rgph_graph.h"

static const char letters[] = "abcdefghijklmnopqrstuvwxyz";

struct fuzz_entry {
	uint64_t index;
	uint8_t has_index;
	uint8_t keylen;
	char key[54];
};

struct fuzz_header {
	size_t nverts;
	unsigned long seed;
	int alloc_flags;
	int build_flags;
	int assign_flags;
	unsigned int nentries;
	struct fuzz_entry entries[];
};

struct iterator_state {
	size_t pos;
	size_t nentries;
	struct fuzz_entry *entries;
	struct rgph_entry out;
};

static inline size_t
min(size_t a, size_t b)
{

	return a < b ? a : b;
}

static inline size_t
max(size_t a, size_t b)
{

	return a > b ? a : b;
}

static const struct rgph_entry *
iterator_func(void *state)
{
	struct iterator_state *s = (struct iterator_state *)state;
	struct fuzz_entry *in = &s->entries[s->pos];
	struct rgph_entry *out = &s->out;

	if (s->pos == s->nentries)
		return NULL;

	out->key = out->data = in->key;
	out->keylen = out->datalen = min(sizeof(in->key), in->keylen);
	out->index = in->index;
	out->has_index = in->has_index;

	s->pos++;
	return out;
}

int
write_sample_input(void)
{
	fuzz_header h;
	FILE *f;
	size_t i;

	memset(&h, 0, sizeof(h));

	f = fopen("fuzz.dat", "w");
	if (f == NULL)
		return EXIT_FAILURE;

	h.nverts = h.nentries = sizeof(letters) - 1;
	h.seed = 123456789;
	h.alloc_flags = 0;
	h.build_flags = 0;
	h.assign_flags = 0;

	if (fwrite(&h, 1, sizeof(h), f) != sizeof(h)) {
		fclose(f);
		return EXIT_FAILURE;
	}

	for (i = 0; i < sizeof(letters) - 1; i++) {
		struct fuzz_entry e;

		e.index = i;
		e.has_index = true;
		e.keylen = 2;
		memcpy(e.key, &letters[i], 2);

		if (fwrite(&e, 1, sizeof(e), f) != sizeof(e)) {
			fclose(f);
			return EXIT_FAILURE;
		}
	}

	fclose(f);
	return EXIT_SUCCESS;
}

int
main(int argc, char *argv[])
{
	iterator_state state;
	struct stat st;
	struct fuzz_header *h;
	struct rgph_graph *g;
	void *buf;
	size_t flen;
	unsigned long seed;
	int build_flags, fd, i, res;

	if (argc < 2)
		return write_sample_input();

	fd = open(argv[1], O_RDONLY);
	if (fd == -1)
		return EXIT_FAILURE;

	if (fstat(fd, &st) == -1) {
		close(fd);
		return EXIT_FAILURE;
	}

	flen = max(st.st_size, sizeof(*h));

	buf = mmap(NULL, flen, PROT_READ, MAP_FILE | MAP_PRIVATE, fd, 0);
	h = (struct fuzz_header *)buf;
	close(fd);

	if (buf == MAP_FAILED)
		return EXIT_FAILURE;

	g = rgph_alloc_graph(h->nverts, h->alloc_flags);
	if (g == NULL)
		return EXIT_FAILURE;

	seed = h->seed;
	build_flags = h->build_flags;
	state.entries = h->entries;
	state.nentries = min(h->nentries,
	    (flen - sizeof(*h)) / sizeof(h->entries[0]));

	for (i = 0; true; i++) {
		size_t dup[2];

		state.pos = 0;
		res = rgph_build_graph(g, build_flags, seed++,
		    &iterator_func, &state);
		if (res == RGPH_SUCCESS || res != RGPH_AGAIN)
			break;

		state.pos = 0;
		res = rgph_find_duplicates(g, &iterator_func, &state, dup);
		if (res == RGPH_SUCCESS)
			break;

		/* Some hashes are weak. Rotate them periodically. */
		if ((i % 8) == 7) {
			int next_hash = (build_flags & RGPH_HASH_MASK) + 1;

			if (next_hash >= RGPH_HASH_LAST)
				next_hash = 0;

			build_flags &= ~RGPH_HASH_MASK;
			build_flags |= next_hash;
		}
	}

	res = rgph_assign(g, h->assign_flags);

	rgph_free_graph(g);

	return res == RGPH_SUCCESS ? EXIT_SUCCESS : EXIT_FAILURE;
}
<|endoftext|>


<commit_before>// REQUIRES: x86-registered-target,x86-64-registered-target
// RUN: %clang_cc1 -triple x86_64-apple-darwin -std=c++11 -S %s -o %t-64.s
// RUN: FileCheck -check-prefix CHECK-LP64 --input-file=%t-64.s %s
// RUN: %clang_cc1 -triple i386-apple-darwin -std=c++11 -S %s -o %t-32.s
// RUN: FileCheck -check-prefix CHECK-LP32 --input-file=%t-32.s %s

extern "C" int printf(...);

int f1(int arg)  { return arg; };

int f2(float arg) { return int(arg); };

typedef int (*fp1)(int);

typedef int (*fp2)(float);

struct A {
  operator fp1() { return f1; }
  operator fp2() { return f2; }
} a;

// Test for function reference.
typedef int (&fr1)(int);
typedef int (&fr2)(float);

struct B {
  operator fr1() { return f1; }
  operator fr2() { return f2; }
} b;

int main()
{
 int i = a(10); // Calls f1 via pointer returned from conversion function
 printf("i = %d\n", i);

 int j = b(20); // Calls f1 via pointer returned from conversion function
 printf("j = %d\n", j);
 return 0;
}

// CHECK-LP64: callq __ZN1AcvPFiiEEv
// CHECK-LP64: callq __ZN1BcvRFiiEEv

// CHECK-LP32: calll L__ZN1AcvPFiiEEv
// CHECK-LP32: calll L__ZN1BcvRFiiEEv

<commit_msg>Check IR on this test.<commit_after>// RUN: %clang_cc1 -triple x86_64-apple-darwin -std=c++11 -emit-llvm %s -o - | \
// RUN: FileCheck %s
// RUN: %clang_cc1 -triple i386-apple-darwin -std=c++11 -emit-llvm %s -o - | \
// RUN: FileCheck %s

extern "C" int printf(...);

int f1(int arg)  { return arg; };

int f2(float arg) { return int(arg); };

typedef int (*fp1)(int);

typedef int (*fp2)(float);

struct A {
  operator fp1() { return f1; }
  operator fp2() { return f2; }
} a;

// Test for function reference.
typedef int (&fr1)(int);
typedef int (&fr2)(float);

struct B {
  operator fr1() { return f1; }
  operator fr2() { return f2; }
} b;

int main()
{
 int i = a(10); // Calls f1 via pointer returned from conversion function
 printf("i = %d\n", i);

 int j = b(20); // Calls f1 via pointer returned from conversion function
 printf("j = %d\n", j);
 return 0;
}

// CHECK: call i32 (i32)* (%struct.A*)* @_ZN1AcvPFiiEEv
// CHECK: call i32 (i32)* (%struct.B*)* @_ZN1BcvRFiiEEv
<|endoftext|>


<commit_before>#include "Utils/Testing.hpp"

#include "Messaging/MessageQueue.hpp"

using namespace Core;
using namespace Messaging;

using namespace fakeit;
using namespace std::placeholders;

namespace {

  class Content : public Core::IEntity {
    TYPE_INFO(Content, Core::IEntity, "content")
  };

  struct EventSink {
    virtual Core::IEntity::Unique onRequest(const Content&) = 0;
    virtual void onResponse(const Response&) = 0;
    virtual void onResponseContent(const Content&) = 0;
    virtual void onResponseStatus(const Status&) = 0;
    virtual void onEvent(const Event&) const = 0;
    virtual void onEventContent(const Content&) const = 0;
  };

}

TEST_CASE("message queue is routing an event to a generic client", "[MessageQueue]") {
  auto content = Content::makeUnique();
  auto contentPtr = content.get();

  Mock<EventSink> eventSink;
  When(Method(eventSink, onEvent)).Do([=](const Event& event) {
    REQUIRE(event.getEventType() == "created");
    REQUIRE(event.getResource() == "resource");
    REQUIRE(event.getContent() == contentPtr);
    return Status::OK;
  });

  Mock<ILogger> loggerInstanse;
  Fake(Method(loggerInstanse, message));
  auto logger = ILogger::Shared(&loggerInstanse.get(), [](...) {});

  auto queue = MessageQueue::makeUnique(logger);

  auto client = queue->createClient("clientId");
  client->setOnEvent(std::bind(&EventSink::onEvent, &eventSink.get(), _1));

  auto event = Event::makeUnique("created", "resource", std::move(content));
  queue->addEvent(std::move(event));
  queue->idle();

  Verify(Method(eventSink, onEvent));
}

TEST_CASE("message queue is not routing an event to a deleted generic client", "[MessageQueue]") {
  Mock<ILogger> loggerInstanse;
  Fake(Method(loggerInstanse, message));

  auto logger = ILogger::Shared(&loggerInstanse.get(), [](...) {});
  auto queue = MessageQueue::makeUnique(logger);

  {
    Mock<EventSink> eventSink;
    auto client = queue->createClient("clientId");
    client->setOnEvent(std::bind(&EventSink::onEvent, &eventSink.get(), _1));
    client.reset();
  }

  queue->addEvent(Event::makeUnique("created", "resource"));
  queue->idle();
}

TEST_CASE("message queue is routing a response to a generic client", "[MessageQueue]") {
  auto requestContent = Content::makeUnique();
  auto requestContentPtr = requestContent.get();
  auto responseContent = Content::makeUnique();
  auto responseContentPtr = responseContent.get();

  Mock<EventSink> eventSink;
  When(Method(eventSink, onRequest)).Do([&](const Content& param) {
    REQUIRE(&param == requestContentPtr);
    return std::move(responseContent);
  });

  When(Method(eventSink, onResponse)).Do([=](const Response& response) {
    REQUIRE(response.getRequestType() == "get");
    REQUIRE(response.getReceiver() == "clientId");
    REQUIRE(response.getResource() == "resource");
    REQUIRE(&response.getContent() == responseContentPtr);
    return Status::OK;
  });

  Mock<ILogger> loggerInstanse;
  Fake(Method(loggerInstanse, message));
  auto logger = ILogger::Shared(&loggerInstanse.get(), [](...) {});

  auto queue = MessageQueue::makeUnique(logger);

  auto client = queue->createClient("clientId");
  client->setOnResponse(std::bind(&EventSink::onResponse, &eventSink.get(), _1));

  queue->createController("resource_controller_before");
  auto controller = queue->createController("resource");
  queue->createController("resource_controller_after");

  controller->addOnRequest("get", [&](const Content& c){ return eventSink.get().onRequest(c); });

  client->sendRequest("get", "resource", std::move(requestContent));
  queue->idle();

  Verify(Method(eventSink, onRequest));
  Verify(Method(eventSink, onResponse));
}

TEST_CASE("message queue is routing an event to a resource client", "[MessageQueue]") {
  auto content = Content::makeUnique();
  auto contentPtr = content.get();

  Mock<EventSink> eventSink;
  When(Method(eventSink, onEventContent)).Do([=](const Content& param) {
    REQUIRE(&param == contentPtr);
    return Status::OK;
  });

  Mock<ILogger> loggerInstanse;
  Fake(Method(loggerInstanse, message));
  auto logger = ILogger::Shared(&loggerInstanse.get(), [](...) {});

  auto queue = MessageQueue::makeUnique(logger);

  auto client = queue->createClient("clientId", "resource");
  client->addOnEvent("created", [&](const Content& c){ eventSink.get().onEventContent(c); });

  auto event = Event::makeUnique("created", "resource", std::move(content));
  queue->addEvent(std::move(event));
  queue->idle();

  Verify(Method(eventSink, onEventContent));
}

TEST_CASE("message queue is routing a response to a resource client", "[MessageQueue]") {
  auto requestContent = Content::makeUnique();
  auto requestContentPtr = requestContent.get();
  auto responseContent = Content::makeUnique();
  auto responseContentPtr = responseContent.get();

  Mock<EventSink> eventSink;
  When(Method(eventSink, onRequest)).Do([&](const Content& param) {
    REQUIRE(&param == requestContentPtr);
    return std::move(responseContent);
  });

  When(Method(eventSink, onResponseContent)).Do([=](const Content& param) {
    REQUIRE(&param == responseContentPtr);
    return Status::OK;
  });

  Mock<ILogger> loggerInstanse;
  Fake(Method(loggerInstanse, message));
  auto logger = ILogger::Shared(&loggerInstanse.get(), [](...) {});

  auto queue = MessageQueue::makeUnique(logger);

  auto client = queue->createClient("clientId", "resource");
  client->addOnResponse("get", [&](const Content& c){ return eventSink.get().onResponseContent(c); });

  queue->createController("resource_controller_before");
  auto controller = queue->createController("resource");
  queue->createController("resource_controller_after");
  controller->addOnRequest("get", [&](const Content& c){ return eventSink.get().onRequest(c); });

  client->sendRequest("get", std::move(requestContent));
  queue->idle();

  Verify(Method(eventSink, onRequest));
  Verify(Method(eventSink, onResponseContent));
}

TEST_CASE("message queue is failing to route a response to an implicitly deleted client", "[MessageQueue]") {
  auto requestContent = Content::makeUnique();
  auto responseContent = Content::makeUnique();

  Mock<EventSink> eventSink;
  When(Method(eventSink, onRequest)).Do([&](const Content&) {
    return std::move(responseContent);
  });

  Mock<ILogger> loggerInstanse;
  Fake(Method(loggerInstanse, message));
  Fake(Method(loggerInstanse, error));

  auto logger = ILogger::Shared(&loggerInstanse.get(), [](...) {});
  auto queue = MessageQueue::makeUnique(logger);

  QueueResourceClient* clientPtr;
  {
    auto client = queue->createClient("clientId", "resource");
    clientPtr = client.get();
  }

  auto controller = queue->createController("resource");
  controller->addOnRequest("get", [&](const Content& c) { return eventSink.get().onRequest(c); });

  clientPtr->sendRequest("get", std::move(requestContent));
  queue->idle();

  Verify(Method(eventSink, onRequest));
  Verify(Method(loggerInstanse, message));
  Verify(Method(loggerInstanse, error));
}

TEST_CASE("message queue is failing to route a response to an explicitly deleted client", "[MessageQueue]") {
  auto requestContent = Content::makeUnique();
  auto responseContent = Content::makeUnique();

  Mock<EventSink> eventSink;
  When(Method(eventSink, onRequest)).Do([&](const Content&) {
    return std::move(responseContent);
  });

  Mock<ILogger> loggerInstanse;
  Fake(Method(loggerInstanse, message));
  Fake(Method(loggerInstanse, error));

  auto logger = ILogger::Shared(&loggerInstanse.get(), [](...) {});
  auto queue = MessageQueue::makeUnique(logger);

  auto client = queue->createClient("clientId", "resource");
  auto controller = queue->createController("resource");
  controller->addOnRequest("get", [&](const Content& c) { return eventSink.get().onRequest(c); });

  client->sendRequest("get", std::move(requestContent));
  queue->removeClient(*client);
  queue->idle();

  Verify(Method(eventSink, onRequest));
  Verify(Method(loggerInstanse, message));
  Verify(Method(loggerInstanse, error));
}

TEST_CASE("message queue is failing to route a request if there is no controller to handle it", "[MessageQueue]") {
  auto requestContent = Content::makeUnique();

  Mock<EventSink> eventSink;

  When(Method(eventSink, onResponseStatus)).Do([=](const Status& status) {
    REQUIRE(status.getStatusCode() == StatusCode::NotFound);
    return Status::OK;
  });

  Mock<ILogger> loggerInstanse;
  Fake(Method(loggerInstanse, message));
  Fake(Method(loggerInstanse, error));
  auto logger = ILogger::Shared(&loggerInstanse.get(), [](...) {});

  auto queue = MessageQueue::makeUnique(logger);

  auto client = queue->createClient("clientId", "resource");
  client->addOnResponse("get", [&](const Status& c){ return eventSink.get().onResponseStatus(c); });

  client->sendRequest("get", std::move(requestContent));
  queue->idle();

  Verify(Method(eventSink, onResponseStatus));
}

TEST_CASE("message queue is failing to route a request if the controller was implicitly deleted", "[MessageQueue]") {
  auto requestContent = Content::makeUnique();
  auto responseContent = Content::makeUnique();

  Mock<EventSink> eventSink;

  When(Method(eventSink, onResponseStatus)).Do([=](const Status& status) {
    REQUIRE(status.getStatusCode() == StatusCode::NotFound);
    return Status::OK;
  });

  Mock<ILogger> loggerInstanse;
  Fake(Method(loggerInstanse, message));
  Fake(Method(loggerInstanse, error));
  auto logger = ILogger::Shared(&loggerInstanse.get(), [](...) {});

  auto queue = MessageQueue::makeUnique(logger);

  auto client = queue->createClient("clientId", "resource");
  client->addOnResponse("get", [&](const Status& c){ return eventSink.get().onResponseStatus(c); });

  {
    auto controller = queue->createController("resource");
    controller->addOnRequest("get", [&](const Content& c) { return eventSink.get().onRequest(c); });
  }

  client->sendRequest("get", std::move(requestContent));
  queue->idle();

  Verify(Method(eventSink, onResponseStatus));
}

TEST_CASE("message queue is failing to route a request if the controller was explicitly deleted", "[MessageQueue]") {
  auto requestContent = Content::makeUnique();
  auto responseContent = Content::makeUnique();

  Mock<EventSink> eventSink;

  When(Method(eventSink, onResponseStatus)).Do([=](const Status& status) {
    REQUIRE(status.getStatusCode() == StatusCode::NotFound);
    return Status::OK;
  });

  Mock<ILogger> loggerInstanse;
  Fake(Method(loggerInstanse, message));
  Fake(Method(loggerInstanse, error));
  auto logger = ILogger::Shared(&loggerInstanse.get(), [](...) {});

  auto queue = MessageQueue::makeUnique(logger);

  auto client = queue->createClient("clientId", "resource");
  client->addOnResponse("get", [&](const Status& c){ return eventSink.get().onResponseStatus(c); });
  auto controller = queue->createController("resource");

  client->sendRequest("get", std::move(requestContent));
  queue->removeController(*controller);
  queue->idle();

  Verify(Method(eventSink, onResponseStatus));
}
<commit_msg>Removing the implicite deletion support<commit_after>#include "Utils/Testing.hpp"

#include "Messaging/MessageQueue.hpp"

using namespace Core;
using namespace Messaging;

using namespace fakeit;
using namespace std::placeholders;

namespace {

  class Content : public Core::IEntity {
    TYPE_INFO(Content, Core::IEntity, "content")
  };

  struct EventSink {
    virtual Core::IEntity::Unique onRequest(const Content&) = 0;
    virtual void onResponse(const Response&) = 0;
    virtual void onResponseContent(const Content&) = 0;
    virtual void onResponseStatus(const Status&) = 0;
    virtual void onEvent(const Event&) const = 0;
    virtual void onEventContent(const Content&) const = 0;
  };

}

TEST_CASE("message queue is routing an event to a generic client", "[MessageQueue]") {
  auto content = Content::makeUnique();
  auto contentPtr = content.get();

  Mock<EventSink> eventSink;
  When(Method(eventSink, onEvent)).Do([=](const Event& event) {
    REQUIRE(event.getEventType() == "created");
    REQUIRE(event.getResource() == "resource");
    REQUIRE(event.getContent() == contentPtr);
    return Status::OK;
  });

  Mock<ILogger> loggerInstanse;
  Fake(Method(loggerInstanse, message));
  auto logger = ILogger::Shared(&loggerInstanse.get(), [](...) {});

  auto queue = MessageQueue::makeUnique(logger);

  auto client = queue->createClient("clientId");
  client->setOnEvent(std::bind(&EventSink::onEvent, &eventSink.get(), _1));

  auto event = Event::makeUnique("created", "resource", std::move(content));
  queue->addEvent(std::move(event));
  queue->idle();

  Verify(Method(eventSink, onEvent));
}

TEST_CASE("message queue is not routing an event to a deleted generic client", "[MessageQueue]") {
  Mock<ILogger> loggerInstanse;
  Fake(Method(loggerInstanse, message));

  auto logger = ILogger::Shared(&loggerInstanse.get(), [](...) {});
  auto queue = MessageQueue::makeUnique(logger);

  {
    Mock<EventSink> eventSink;
    auto client = queue->createClient("clientId");
    client->setOnEvent(std::bind(&EventSink::onEvent, &eventSink.get(), _1));
    client.reset();
  }

  queue->addEvent(Event::makeUnique("created", "resource"));
  queue->idle();
}

TEST_CASE("message queue is routing a response to a generic client", "[MessageQueue]") {
  auto requestContent = Content::makeUnique();
  auto requestContentPtr = requestContent.get();
  auto responseContent = Content::makeUnique();
  auto responseContentPtr = responseContent.get();

  Mock<EventSink> eventSink;
  When(Method(eventSink, onRequest)).Do([&](const Content& param) {
    REQUIRE(&param == requestContentPtr);
    return std::move(responseContent);
  });

  When(Method(eventSink, onResponse)).Do([=](const Response& response) {
    REQUIRE(response.getRequestType() == "get");
    REQUIRE(response.getReceiver() == "clientId");
    REQUIRE(response.getResource() == "resource");
    REQUIRE(&response.getContent() == responseContentPtr);
    return Status::OK;
  });

  Mock<ILogger> loggerInstanse;
  Fake(Method(loggerInstanse, message));
  auto logger = ILogger::Shared(&loggerInstanse.get(), [](...) {});

  auto queue = MessageQueue::makeUnique(logger);

  auto client = queue->createClient("clientId");
  client->setOnResponse(std::bind(&EventSink::onResponse, &eventSink.get(), _1));

  queue->createController("resource_controller_before");
  auto controller = queue->createController("resource");
  queue->createController("resource_controller_after");

  controller->addOnRequest("get", [&](const Content& c){ return eventSink.get().onRequest(c); });

  client->sendRequest("get", "resource", std::move(requestContent));
  queue->idle();

  Verify(Method(eventSink, onRequest));
  Verify(Method(eventSink, onResponse));
}

TEST_CASE("message queue is routing an event to a resource client", "[MessageQueue]") {
  auto content = Content::makeUnique();
  auto contentPtr = content.get();

  Mock<EventSink> eventSink;
  When(Method(eventSink, onEventContent)).Do([=](const Content& param) {
    REQUIRE(&param == contentPtr);
    return Status::OK;
  });

  Mock<ILogger> loggerInstanse;
  Fake(Method(loggerInstanse, message));
  auto logger = ILogger::Shared(&loggerInstanse.get(), [](...) {});

  auto queue = MessageQueue::makeUnique(logger);

  auto client = queue->createClient("clientId", "resource");
  client->addOnEvent("created", [&](const Content& c){ eventSink.get().onEventContent(c); });

  auto event = Event::makeUnique("created", "resource", std::move(content));
  queue->addEvent(std::move(event));
  queue->idle();

  Verify(Method(eventSink, onEventContent));
}

TEST_CASE("message queue is routing a response to a resource client", "[MessageQueue]") {
  auto requestContent = Content::makeUnique();
  auto requestContentPtr = requestContent.get();
  auto responseContent = Content::makeUnique();
  auto responseContentPtr = responseContent.get();

  Mock<EventSink> eventSink;
  When(Method(eventSink, onRequest)).Do([&](const Content& param) {
    REQUIRE(&param == requestContentPtr);
    return std::move(responseContent);
  });

  When(Method(eventSink, onResponseContent)).Do([=](const Content& param) {
    REQUIRE(&param == responseContentPtr);
    return Status::OK;
  });

  Mock<ILogger> loggerInstanse;
  Fake(Method(loggerInstanse, message));
  auto logger = ILogger::Shared(&loggerInstanse.get(), [](...) {});

  auto queue = MessageQueue::makeUnique(logger);

  auto client = queue->createClient("clientId", "resource");
  client->addOnResponse("get", [&](const Content& c){ return eventSink.get().onResponseContent(c); });

  queue->createController("resource_controller_before");
  auto controller = queue->createController("resource");
  queue->createController("resource_controller_after");
  controller->addOnRequest("get", [&](const Content& c){ return eventSink.get().onRequest(c); });

  client->sendRequest("get", std::move(requestContent));
  queue->idle();

  Verify(Method(eventSink, onRequest));
  Verify(Method(eventSink, onResponseContent));
}

TEST_CASE("message queue is failing to route a response to an explicitly deleted client", "[MessageQueue]") {
  auto requestContent = Content::makeUnique();
  auto responseContent = Content::makeUnique();

  Mock<EventSink> eventSink;
  When(Method(eventSink, onRequest)).Do([&](const Content&) {
    return std::move(responseContent);
  });

  Mock<ILogger> loggerInstanse;
  Fake(Method(loggerInstanse, message));
  Fake(Method(loggerInstanse, error));

  auto logger = ILogger::Shared(&loggerInstanse.get(), [](...) {});
  auto queue = MessageQueue::makeUnique(logger);

  auto client = queue->createClient("clientId", "resource");
  auto controller = queue->createController("resource");
  controller->addOnRequest("get", [&](const Content& c) { return eventSink.get().onRequest(c); });

  client->sendRequest("get", std::move(requestContent));
  queue->removeClient(*client);
  queue->idle();

  Verify(Method(eventSink, onRequest));
  Verify(Method(loggerInstanse, message));
  Verify(Method(loggerInstanse, error));
}

TEST_CASE("message queue is failing to route a request if there is no controller to handle it", "[MessageQueue]") {
  auto requestContent = Content::makeUnique();

  Mock<EventSink> eventSink;

  When(Method(eventSink, onResponseStatus)).Do([=](const Status& status) {
    REQUIRE(status.getStatusCode() == StatusCode::NotFound);
    return Status::OK;
  });

  Mock<ILogger> loggerInstanse;
  Fake(Method(loggerInstanse, message));
  Fake(Method(loggerInstanse, error));
  auto logger = ILogger::Shared(&loggerInstanse.get(), [](...) {});

  auto queue = MessageQueue::makeUnique(logger);

  auto client = queue->createClient("clientId", "resource");
  client->addOnResponse("get", [&](const Status& c){ return eventSink.get().onResponseStatus(c); });

  client->sendRequest("get", std::move(requestContent));
  queue->idle();

  Verify(Method(eventSink, onResponseStatus));
}

TEST_CASE("message queue is failing to route a request if the controller was explicitly deleted", "[MessageQueue]") {
  auto requestContent = Content::makeUnique();
  auto responseContent = Content::makeUnique();

  Mock<EventSink> eventSink;

  When(Method(eventSink, onResponseStatus)).Do([=](const Status& status) {
    REQUIRE(status.getStatusCode() == StatusCode::NotFound);
    return Status::OK;
  });

  Mock<ILogger> loggerInstanse;
  Fake(Method(loggerInstanse, message));
  Fake(Method(loggerInstanse, error));
  auto logger = ILogger::Shared(&loggerInstanse.get(), [](...) {});

  auto queue = MessageQueue::makeUnique(logger);

  auto client = queue->createClient("clientId", "resource");
  client->addOnResponse("get", [&](const Status& c){ return eventSink.get().onResponseStatus(c); });
  auto controller = queue->createController("resource");

  client->sendRequest("get", std::move(requestContent));
  queue->removeController(*controller);
  queue->idle();

  Verify(Method(eventSink, onResponseStatus));
}
<|endoftext|>


<commit_before>// REQUIRES: python27
// RUN: sed 's/placeholder_for_f/f/' %s > %t.cpp
// RUN: clang-tidy -checks=-*,misc-use-override %t.cpp -- -std=c++11 | FileCheck -check-prefix=CHECK-SANITY %s
// RUN: not diff -U0 %s %t.cpp | %python %S/../../clang-tidy/tool/clang-tidy-diff.py -checks=-*,misc-use-override -- -std=c++11 2>&1 | FileCheck %s
struct A {
  virtual void f() {}
  virtual void g() {}
};
// CHECK-NOT: warning
struct B : public A {
  void placeholder_for_f() {}
// CHECK-SANITY: [[@LINE-1]]:8: warning: Use exactly
// CHECK: [[@LINE-2]]:8: warning: Use exactly
  void g() {}
// CHECK-SANITY: [[@LINE-1]]:8: warning: Use exactly
// CHECK-NOT: warning:
};
// CHECK-SANITY-NOT: Suppressed
// CHECK: Suppressed 1 warnings (1 due to line filter).
<commit_msg>Suppress clang-tools-extra/test/clang-tidy/clang-tidy-diff.cpp on win32 due to dos path issue.<commit_after>// REQUIRES: python27
// RUN: sed 's/placeholder_for_f/f/' %s > %t.cpp
// RUN: clang-tidy -checks=-*,misc-use-override %t.cpp -- -std=c++11 | FileCheck -check-prefix=CHECK-SANITY %s
// RUN: not diff -U0 %s %t.cpp | %python %S/../../clang-tidy/tool/clang-tidy-diff.py -checks=-*,misc-use-override -- -std=c++11 2>&1 | FileCheck %s
struct A {
  virtual void f() {}
  virtual void g() {}
};
// CHECK-NOT: warning
struct B : public A {
  void placeholder_for_f() {}
// CHECK-SANITY: [[@LINE-1]]:8: warning: Use exactly
// CHECK: [[@LINE-2]]:8: warning: Use exactly
  void g() {}
// CHECK-SANITY: [[@LINE-1]]:8: warning: Use exactly
// CHECK-NOT: warning:
};
// CHECK-SANITY-NOT: Suppressed
// CHECK: Suppressed 1 warnings (1 due to line filter).

// FIXME: clang-tidy-diff.py is incompatible to dos path. Excluding win32.
// REQUIRES: shell
<|endoftext|>


<commit_before>/*
Dwarf Therapist
Copyright (c) 2009 Trey Stout (chmod)

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/
#include <QtCore>
#include <QtDebug>

#include "dfinstance.h"
#include "dwarfmodel.h"
#include "dwarf.h"
#include "skill.h"wh
#include "labor.h"
#include "profession.h"
#include "statetableview.h"
#include "defines.h"
#include "dwarftherapist.h"

#include "columntypes.h"
#include "gridview.h"
#include "viewcolumnset.h"
#include "viewcolumn.h"
#include "laborcolumn.h"
#include "skillcolumn.h"
#include "spacercolumn.h"

DwarfModel::DwarfModel(QObject *parent)
	: QStandardItemModel(parent)
	, m_df(0)
	, m_group_by(GB_NOTHING)
	, m_selected_col(-1)
{}

DwarfModel::~DwarfModel() {
	clear_all();
}

void DwarfModel::clear_all() {
	clear_pending();
	foreach(Dwarf *d, m_dwarves) {
		delete d;
	}
	m_dwarves.clear();
	m_grouped_dwarves.clear();
	clear();
}

void DwarfModel::section_right_clicked(int col) {
	if (col == m_selected_col) {
		m_selected_col = -1; // turn off the guides
	} else {
		m_selected_col = col;
	}
	emit dataChanged(index(0, col), index(rowCount()-1, col));
}

void DwarfModel::load_dwarves() {
	// clear id->dwarf map
	foreach(Dwarf *d, m_dwarves) {
		delete d;
	}
	m_dwarves.clear();
	if (rowCount())
		removeRows(0, rowCount());

	m_df->attach();
	foreach(Dwarf *d, m_df->load_dwarves()) {
		m_dwarves[d->id()] = d;
	}
	m_df->detach();
	/*! Let's try to guess the wave a dwarf arrived in based on ID.
	The game appears to assign ids to creates in a serial manner.
	Since at least 1 season seems to pass in between waves there is a
	high likelihood that dwarves arriving in a new wave will be folling
	several other creatures such as groundhogs and the like, thus
	producing a gap in IDs of more than 1
	*/
	int last_id = 0;
	int wave = 0;
	QList<int> ids = m_dwarves.uniqueKeys(); // get all ids
	qSort(ids); // now in order;
	for (int i = 0; i < ids.size(); ++i) {
		int id = ids.at(i);
		if ((id - last_id) > 5)
			wave++;
		last_id = id;
		m_dwarves[id]->set_migration_wave(wave);
	}

}

void DwarfModel::build_rows() {
	// don't need to go delete the dwarf pointers in here, since the earlier foreach should have
	// deleted them
	m_grouped_dwarves.clear();
	clear();

	// populate dwarf maps
	foreach(Dwarf *d, m_dwarves) {
		switch (m_group_by) {
			case GB_NOTHING:
				m_grouped_dwarves[QString::number(d->id())].append(d);
				break;
			case GB_PROFESSION:
				m_grouped_dwarves[d->profession()].append(d);
				break;
			case GB_LEGENDARY:
				{
					int legendary_skills = 0;
					foreach(Skill s, *d->get_skills()) {
						if (s.rating() >= 15)
							legendary_skills++;
					}
					if (legendary_skills)
						m_grouped_dwarves["Legends"].append(d);
					else
						m_grouped_dwarves["Losers"].append(d);
					break;
				}
			case GB_SEX:
				if (d->is_male())
					m_grouped_dwarves["Males"].append(d);
				else
					m_grouped_dwarves["Females"].append(d);
				break;
			case GB_HAPPINESS:
				m_grouped_dwarves[QString::number(d->get_happiness())].append(d);
				break;
			case GB_MIGRATION_WAVE:
				m_grouped_dwarves[QString("Wave %1").arg(d->migration_wave())].append(d);
				break;
		}
	}

	int start_col = 1;
	setHorizontalHeaderItem(0, new QStandardItem);
	emit clear_spacers();
	QSettings *s = DT->user_settings();
	int width = s->value("options/grid/cell_size", DEFAULT_CELL_SIZE).toInt();
	foreach(ViewColumnSet *set, m_gridview->sets()) {
		foreach(ViewColumn *col, set->columns()) {
			QStandardItem *header = new QStandardItem(col->title());
			header->setData(col->bg_color(), Qt::BackgroundColorRole);
			setHorizontalHeaderItem(start_col++, header);
			switch (col->type()) {
				case CT_SPACER:
					{
						SpacerColumn *c = static_cast<SpacerColumn*>(col);
						emit set_index_as_spacer(start_col - 1);
						emit preferred_header_size(start_col - 1, c->width());
					}
					break;
				default:
					emit preferred_header_size(start_col - 1, width);
			}
		}
	}

	//FIXME : jump to prof and jump to pending change
	if (m_group_by == GB_PROFESSION) {
		// sort professions by column labors
		QStringList group_order;
		foreach(ViewColumnSet *set, m_gridview->sets()) {
			foreach(ViewColumn *col, set->columns()) {
				int skill = -1;
				if (col->type() == CT_LABOR) {
					LaborColumn *lc = static_cast<LaborColumn*>(col);
					skill = lc->skill_id();
				} else if (col->type() == CT_SKILL) {
					SkillColumn *sc = static_cast<SkillColumn*>(col);
					skill = sc->skill_id();
				}
				if (skill != -1) {
					group_order << GameDataReader::ptr()->get_skill_name(skill);
				}
			}
		}
		foreach(QString prof_name, group_order) {
			if (m_grouped_dwarves.contains(prof_name)) {
				build_row(prof_name);
			}
		}
		foreach(QString key, m_grouped_dwarves.uniqueKeys()) {
			if (!group_order.contains(key)) {
				build_row(key);
			}
		}
	} else {
		foreach(QString key, m_grouped_dwarves.uniqueKeys()) {
			build_row(key);
		}
	}
}

void DwarfModel::build_row(const QString &key) {
	QIcon icn_f(":img/female.png");
	QIcon icn_m(":img/male.png");
	QStandardItem *root = 0;
	QList<QStandardItem*> root_row;

	if (m_group_by != GB_NOTHING) {
		// we need a root element to hold group members...
		QString title = QString("%1 (%2)").arg(key).arg(m_grouped_dwarves.value(key).size());
		root = new QStandardItem(title);
		root->setData(true, DR_IS_AGGREGATE);
		root->setData(0, DR_RATING);
		root_row << root;
	}

	if (root) { // we have a parent, so we should draw an aggregate row
		foreach(ViewColumnSet *set, m_gridview->sets()) {
			foreach(ViewColumn *col, set->columns()) {
				QStandardItem *item = col->build_aggregate(key, m_grouped_dwarves[key]);
				root_row << item;
			}
		}
	}

	foreach(Dwarf *d, m_grouped_dwarves.value(key)) {
        Profession *p = GameDataReader::ptr()->get_profession(d->raw_profession());
        QString name = d->nice_name();
        if (p && p->is_military())
            name = "[M]" + name;
		QStandardItem *i_name = new QStandardItem(name);

		i_name->setToolTip(d->tooltip_text());
		i_name->setStatusTip(d->nice_name());
		i_name->setData(false, DR_IS_AGGREGATE);
		i_name->setData(0, DR_RATING);
		i_name->setData(d->id(), DR_ID);
        i_name->setData(d->raw_profession(), DR_SORT_VALUE);

		if (d->is_male()) {
			i_name->setIcon(icn_m);
		} else {
			i_name->setIcon(icn_f);
		}

		QList<QStandardItem*> items;
		items << i_name;
		foreach(ViewColumnSet *set, m_gridview->sets()) {
			foreach(ViewColumn *col, set->columns()) {
				QStandardItem *item = col->build_cell(d);
				items << item;
			}
		}

		if (root) {
			root->appendRow(items);
		} else {
			appendRow(items);
		}
		d->m_name_idx = indexFromItem(i_name);
	}
	if (root) {
		appendRow(root_row);
	}
}

void DwarfModel::cell_activated(const QModelIndex &idx) {
    QStandardItem *item = itemFromIndex(idx);
    bool is_aggregate = item->data(DR_IS_AGGREGATE).toBool();
    if (idx.column() == 0) {
        if (is_aggregate)
            return; // no double clicking aggregate names
        int dwarf_id = item->data(DR_ID).toInt(); // TODO: handle no id
        if (!dwarf_id) {
            LOGW << "double clicked what should have been a dwarf name, but the ID wasn't set!";
            return;
        }
        Dwarf *d = get_dwarf_by_id(dwarf_id);
        d->show_details();
        return;
    }

	COLUMN_TYPE type = static_cast<COLUMN_TYPE>(idx.data(DwarfModel::DR_COL_TYPE).toInt());
	if (type != CT_LABOR)
		return;

	Q_ASSERT(item);

	int labor_id = item->data(DR_LABOR_ID).toInt();
	int dwarf_id = item->data(DR_ID).toInt(); // TODO: handle no id
	if (is_aggregate) {
		QModelIndex first_col = idx.sibling(idx.row(), 0);

		// first find out how many are enabled...
		int enabled_count = 0;
		QString group_name = idx.data(DwarfModel::DR_GROUP_NAME).toString();
		int children = rowCount(first_col);

		foreach(Dwarf *d, m_grouped_dwarves.value(group_name)) {
			if (d->is_labor_enabled(labor_id))
				enabled_count++;
		}

		// if none or some are enabled, enable all of them
		bool enabled = (enabled_count < children);
		foreach(Dwarf *d, m_grouped_dwarves.value(group_name)) {
			d->set_labor(labor_id, enabled);
		}

		// tell the view what we touched...
		setData(idx, idx.data(DR_DUMMY).toInt()+1, DR_DUMMY); // redraw the aggregate...
		for(int i = 0; i < rowCount(first_col); ++i) {
			QModelIndex tmp_index = index(i, idx.column(), first_col);
			setData(tmp_index, tmp_index.data(DR_DUMMY).toInt()+1, DR_DUMMY);
		}
	} else {
        if (!dwarf_id) {
            LOGW << "dwarf_id was 0 for cell at" << idx << "!";
        } else {
		    QModelIndex aggregate_col = index(idx.parent().row(), idx.column());
		    if (aggregate_col.isValid())
		    	setData(aggregate_col, aggregate_col.data(DR_DUMMY).toInt()+1, DR_DUMMY); // redraw the aggregate...
		    setData(idx, idx.data(DR_DUMMY).toInt()+1, DR_DUMMY); // redraw the aggregate...
		    m_dwarves[dwarf_id]->toggle_labor(labor_id);
        }
	}
	calculate_pending();
	TRACE << "toggling" << labor_id << "for dwarf:" << dwarf_id;
}

void DwarfModel::set_group_by(int group_by) {
	LOGD << "group_by now set to" << group_by;
	m_group_by = static_cast<GROUP_BY>(group_by);
	if (m_df)
		build_rows();
}

void DwarfModel::calculate_pending() {
	int changes = 0;
	foreach(Dwarf *d, m_dwarves) {
		changes += d->pending_changes();
	}
	emit new_pending_changes(changes);
}

void DwarfModel::clear_pending() {
	foreach(Dwarf *d, m_dwarves) {
		if (d->pending_changes()) {
			d->clear_pending();
		}
	}
	//reset();
	emit new_pending_changes(0);
	emit need_redraw();
}

void DwarfModel::commit_pending() {
	foreach(Dwarf *d, m_dwarves) {
		if (d->pending_changes()) {
			d->commit_pending();
		}
	}
	load_dwarves();
	emit new_pending_changes(0);
	emit need_redraw();
}

QVector<Dwarf*> DwarfModel::get_dirty_dwarves() {
	QVector<Dwarf*> dwarves;
	foreach(Dwarf *d, m_dwarves) {
		if (d->pending_changes())
			dwarves.append(d);
	}
	return dwarves;
}
<commit_msg>stupid typo<commit_after>/*
Dwarf Therapist
Copyright (c) 2009 Trey Stout (chmod)

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/
#include <QtCore>
#include <QtDebug>

#include "dfinstance.h"
#include "dwarfmodel.h"
#include "dwarf.h"
#include "skill.h"
#include "labor.h"
#include "profession.h"
#include "statetableview.h"
#include "defines.h"
#include "dwarftherapist.h"

#include "columntypes.h"
#include "gridview.h"
#include "viewcolumnset.h"
#include "viewcolumn.h"
#include "laborcolumn.h"
#include "skillcolumn.h"
#include "spacercolumn.h"

DwarfModel::DwarfModel(QObject *parent)
	: QStandardItemModel(parent)
	, m_df(0)
	, m_group_by(GB_NOTHING)
	, m_selected_col(-1)
{}

DwarfModel::~DwarfModel() {
	clear_all();
}

void DwarfModel::clear_all() {
	clear_pending();
	foreach(Dwarf *d, m_dwarves) {
		delete d;
	}
	m_dwarves.clear();
	m_grouped_dwarves.clear();
	clear();
}

void DwarfModel::section_right_clicked(int col) {
	if (col == m_selected_col) {
		m_selected_col = -1; // turn off the guides
	} else {
		m_selected_col = col;
	}
	emit dataChanged(index(0, col), index(rowCount()-1, col));
}

void DwarfModel::load_dwarves() {
	// clear id->dwarf map
	foreach(Dwarf *d, m_dwarves) {
		delete d;
	}
	m_dwarves.clear();
	if (rowCount())
		removeRows(0, rowCount());

	m_df->attach();
	foreach(Dwarf *d, m_df->load_dwarves()) {
		m_dwarves[d->id()] = d;
	}
	m_df->detach();
	/*! Let's try to guess the wave a dwarf arrived in based on ID.
	The game appears to assign ids to creates in a serial manner.
	Since at least 1 season seems to pass in between waves there is a
	high likelihood that dwarves arriving in a new wave will be folling
	several other creatures such as groundhogs and the like, thus
	producing a gap in IDs of more than 1
	*/
	int last_id = 0;
	int wave = 0;
	QList<int> ids = m_dwarves.uniqueKeys(); // get all ids
	qSort(ids); // now in order;
	for (int i = 0; i < ids.size(); ++i) {
		int id = ids.at(i);
		if ((id - last_id) > 5)
			wave++;
		last_id = id;
		m_dwarves[id]->set_migration_wave(wave);
	}

}

void DwarfModel::build_rows() {
	// don't need to go delete the dwarf pointers in here, since the earlier foreach should have
	// deleted them
	m_grouped_dwarves.clear();
	clear();

	// populate dwarf maps
	foreach(Dwarf *d, m_dwarves) {
		switch (m_group_by) {
			case GB_NOTHING:
				m_grouped_dwarves[QString::number(d->id())].append(d);
				break;
			case GB_PROFESSION:
				m_grouped_dwarves[d->profession()].append(d);
				break;
			case GB_LEGENDARY:
				{
					int legendary_skills = 0;
					foreach(Skill s, *d->get_skills()) {
						if (s.rating() >= 15)
							legendary_skills++;
					}
					if (legendary_skills)
						m_grouped_dwarves["Legends"].append(d);
					else
						m_grouped_dwarves["Losers"].append(d);
					break;
				}
			case GB_SEX:
				if (d->is_male())
					m_grouped_dwarves["Males"].append(d);
				else
					m_grouped_dwarves["Females"].append(d);
				break;
			case GB_HAPPINESS:
				m_grouped_dwarves[QString::number(d->get_happiness())].append(d);
				break;
			case GB_MIGRATION_WAVE:
				m_grouped_dwarves[QString("Wave %1").arg(d->migration_wave())].append(d);
				break;
		}
	}

	int start_col = 1;
	setHorizontalHeaderItem(0, new QStandardItem);
	emit clear_spacers();
	QSettings *s = DT->user_settings();
	int width = s->value("options/grid/cell_size", DEFAULT_CELL_SIZE).toInt();
	foreach(ViewColumnSet *set, m_gridview->sets()) {
		foreach(ViewColumn *col, set->columns()) {
			QStandardItem *header = new QStandardItem(col->title());
			header->setData(col->bg_color(), Qt::BackgroundColorRole);
			setHorizontalHeaderItem(start_col++, header);
			switch (col->type()) {
				case CT_SPACER:
					{
						SpacerColumn *c = static_cast<SpacerColumn*>(col);
						emit set_index_as_spacer(start_col - 1);
						emit preferred_header_size(start_col - 1, c->width());
					}
					break;
				default:
					emit preferred_header_size(start_col - 1, width);
			}
		}
	}

	//FIXME : jump to prof and jump to pending change
	if (m_group_by == GB_PROFESSION) {
		// sort professions by column labors
		QStringList group_order;
		foreach(ViewColumnSet *set, m_gridview->sets()) {
			foreach(ViewColumn *col, set->columns()) {
				int skill = -1;
				if (col->type() == CT_LABOR) {
					LaborColumn *lc = static_cast<LaborColumn*>(col);
					skill = lc->skill_id();
				} else if (col->type() == CT_SKILL) {
					SkillColumn *sc = static_cast<SkillColumn*>(col);
					skill = sc->skill_id();
				}
				if (skill != -1) {
					group_order << GameDataReader::ptr()->get_skill_name(skill);
				}
			}
		}
		foreach(QString prof_name, group_order) {
			if (m_grouped_dwarves.contains(prof_name)) {
				build_row(prof_name);
			}
		}
		foreach(QString key, m_grouped_dwarves.uniqueKeys()) {
			if (!group_order.contains(key)) {
				build_row(key);
			}
		}
	} else {
		foreach(QString key, m_grouped_dwarves.uniqueKeys()) {
			build_row(key);
		}
	}
}

void DwarfModel::build_row(const QString &key) {
	QIcon icn_f(":img/female.png");
	QIcon icn_m(":img/male.png");
	QStandardItem *root = 0;
	QList<QStandardItem*> root_row;

	if (m_group_by != GB_NOTHING) {
		// we need a root element to hold group members...
		QString title = QString("%1 (%2)").arg(key).arg(m_grouped_dwarves.value(key).size());
		root = new QStandardItem(title);
		root->setData(true, DR_IS_AGGREGATE);
		root->setData(0, DR_RATING);
		root_row << root;
	}

	if (root) { // we have a parent, so we should draw an aggregate row
		foreach(ViewColumnSet *set, m_gridview->sets()) {
			foreach(ViewColumn *col, set->columns()) {
				QStandardItem *item = col->build_aggregate(key, m_grouped_dwarves[key]);
				root_row << item;
			}
		}
	}

	foreach(Dwarf *d, m_grouped_dwarves.value(key)) {
        Profession *p = GameDataReader::ptr()->get_profession(d->raw_profession());
        QString name = d->nice_name();
        if (p && p->is_military())
            name = "[M]" + name;
		QStandardItem *i_name = new QStandardItem(name);

		i_name->setToolTip(d->tooltip_text());
		i_name->setStatusTip(d->nice_name());
		i_name->setData(false, DR_IS_AGGREGATE);
		i_name->setData(0, DR_RATING);
		i_name->setData(d->id(), DR_ID);
        i_name->setData(d->raw_profession(), DR_SORT_VALUE);

		if (d->is_male()) {
			i_name->setIcon(icn_m);
		} else {
			i_name->setIcon(icn_f);
		}

		QList<QStandardItem*> items;
		items << i_name;
		foreach(ViewColumnSet *set, m_gridview->sets()) {
			foreach(ViewColumn *col, set->columns()) {
				QStandardItem *item = col->build_cell(d);
				items << item;
			}
		}

		if (root) {
			root->appendRow(items);
		} else {
			appendRow(items);
		}
		d->m_name_idx = indexFromItem(i_name);
	}
	if (root) {
		appendRow(root_row);
	}
}

void DwarfModel::cell_activated(const QModelIndex &idx) {
    QStandardItem *item = itemFromIndex(idx);
    bool is_aggregate = item->data(DR_IS_AGGREGATE).toBool();
    if (idx.column() == 0) {
        if (is_aggregate)
            return; // no double clicking aggregate names
        int dwarf_id = item->data(DR_ID).toInt(); // TODO: handle no id
        if (!dwarf_id) {
            LOGW << "double clicked what should have been a dwarf name, but the ID wasn't set!";
            return;
        }
        Dwarf *d = get_dwarf_by_id(dwarf_id);
        d->show_details();
        return;
    }

	COLUMN_TYPE type = static_cast<COLUMN_TYPE>(idx.data(DwarfModel::DR_COL_TYPE).toInt());
	if (type != CT_LABOR)
		return;

	Q_ASSERT(item);

	int labor_id = item->data(DR_LABOR_ID).toInt();
	int dwarf_id = item->data(DR_ID).toInt(); // TODO: handle no id
	if (is_aggregate) {
		QModelIndex first_col = idx.sibling(idx.row(), 0);

		// first find out how many are enabled...
		int enabled_count = 0;
		QString group_name = idx.data(DwarfModel::DR_GROUP_NAME).toString();
		int children = rowCount(first_col);

		foreach(Dwarf *d, m_grouped_dwarves.value(group_name)) {
			if (d->is_labor_enabled(labor_id))
				enabled_count++;
		}

		// if none or some are enabled, enable all of them
		bool enabled = (enabled_count < children);
		foreach(Dwarf *d, m_grouped_dwarves.value(group_name)) {
			d->set_labor(labor_id, enabled);
		}

		// tell the view what we touched...
		setData(idx, idx.data(DR_DUMMY).toInt()+1, DR_DUMMY); // redraw the aggregate...
		for(int i = 0; i < rowCount(first_col); ++i) {
			QModelIndex tmp_index = index(i, idx.column(), first_col);
			setData(tmp_index, tmp_index.data(DR_DUMMY).toInt()+1, DR_DUMMY);
		}
	} else {
        if (!dwarf_id) {
            LOGW << "dwarf_id was 0 for cell at" << idx << "!";
        } else {
		    QModelIndex aggregate_col = index(idx.parent().row(), idx.column());
		    if (aggregate_col.isValid())
		    	setData(aggregate_col, aggregate_col.data(DR_DUMMY).toInt()+1, DR_DUMMY); // redraw the aggregate...
		    setData(idx, idx.data(DR_DUMMY).toInt()+1, DR_DUMMY); // redraw the aggregate...
		    m_dwarves[dwarf_id]->toggle_labor(labor_id);
        }
	}
	calculate_pending();
	TRACE << "toggling" << labor_id << "for dwarf:" << dwarf_id;
}

void DwarfModel::set_group_by(int group_by) {
	LOGD << "group_by now set to" << group_by;
	m_group_by = static_cast<GROUP_BY>(group_by);
	if (m_df)
		build_rows();
}

void DwarfModel::calculate_pending() {
	int changes = 0;
	foreach(Dwarf *d, m_dwarves) {
		changes += d->pending_changes();
	}
	emit new_pending_changes(changes);
}

void DwarfModel::clear_pending() {
	foreach(Dwarf *d, m_dwarves) {
		if (d->pending_changes()) {
			d->clear_pending();
		}
	}
	//reset();
	emit new_pending_changes(0);
	emit need_redraw();
}

void DwarfModel::commit_pending() {
	foreach(Dwarf *d, m_dwarves) {
		if (d->pending_changes()) {
			d->commit_pending();
		}
	}
	load_dwarves();
	emit new_pending_changes(0);
	emit need_redraw();
}

QVector<Dwarf*> DwarfModel::get_dirty_dwarves() {
	QVector<Dwarf*> dwarves;
	foreach(Dwarf *d, m_dwarves) {
		if (d->pending_changes())
			dwarves.append(d);
	}
	return dwarves;
}
<|endoftext|>


<commit_before>static int clear_stack(lua_State *lua) {
    lua_pop(lua, lua_gettop(lua));
    return 0;
}

internal s32 lua_graphics_load_texture(lua_State *lua) {
    char *filename = (char *)lua_tostring(lua, 1);

    Texture texture = graphics_load_texture(filename);
    // Can't just push the texture as userdata because it gets
    // deleted after scope finishes
    lua_newtable(lua);
    lua_pushnumber(lua, texture.width);
    lua_setfield(lua, -2, "width");
    lua_pushnumber(lua, texture.height);
    lua_setfield(lua, -2, "height");
    lua_pushnumber(lua, texture.gl_handle);
    lua_setfield(lua, -2, "handle");
    // This should be used to determine if the proper type
    // is being passed into C functions from Lua
    lua_pushstring(lua, "__TEXTURE__");
    lua_setfield(lua, -2, "__type");
    return 1;
}

internal s32 lua_graphics_draw_sprite(lua_State *lua) {
    // TODO(zedzull): This should probably check for the correct arguments
	luaL_checktype(lua, 1, LUA_TTABLE);
    lua_getfield(lua, 1, "__type");
    const char *type = luaL_checkstring(lua, -1);
    // TODO(darithorn): Check if type == "__TEXTURE__"
    lua_getfield(lua, 1, "width");
    lua_getfield(lua, 1, "height");
    lua_getfield(lua, 1, "handle");
    int width = luaL_checknumber(lua, -3);
    int height = luaL_checknumber(lua, -2);
    GLuint handle = (GLuint)luaL_checknumber(lua, -1);
    Texture texture = { width, height, handle };
    f32 x = lua_tonumber(lua, 2);
    f32 y = lua_tonumber(lua, 3);

    graphics_draw_sprite(texture, x, y);
    clear_stack(lua);
    return 0;
}

static int lua_graphics_draw_sprite_ex(lua_State *lua) {
    luaL_checktype(lua, 1, LUA_TTABLE);
    lua_getfield(lua, 1, "__type");
    const char *type = luaL_checkstring(lua, -1);
    // TODO(darithorn): Check if type == "__TEXTURE__"
    lua_getfield(lua, 1, "width");
    lua_getfield(lua, 1, "height");
    lua_getfield(lua, 1, "handle");
    int width = luaL_checknumber(lua, -3);
    int height = luaL_checknumber(lua, -2);
    GLuint handle = (GLuint)luaL_checknumber(lua, -1);
    Texture texture = { width, height, handle };
    float dest_x = lua_tonumber(lua, 2);
    float dest_y = lua_tonumber(lua, 3);
    float dest_width = lua_tonumber(lua, 4);
    float dest_height = lua_tonumber(lua, 5);
    float src_x = lua_tonumber(lua, 6);
    float src_y = lua_tonumber(lua, 7);
    float src_width = lua_tonumber(lua, 8);
    float src_height = lua_tonumber(lua, 9);

    graphics_draw_sprite_ex(texture,
                            dest_x, dest_y, dest_width, dest_height,
                            src_x, src_y, src_width, src_height);
    clear_stack(lua);
    return 0;
}

internal s32 lua_runtime_error(lua_State *lua) {
    luaL_traceback(lua, lua, lua_tostring(lua, lua_gettop(lua)), 1);
    printf("%s\n", lua_tolstring(lua, lua_gettop(lua), NULL));

    exit(1);

    return 0;
}

internal s32 safe_lua_call(lua_State *lua, s32 num_args, s32 num_returns) {
    s32 error_handler_pos = lua_gettop(lua) - num_args;

    lua_pushcfunction(lua, lua_runtime_error);
    lua_insert(lua, error_handler_pos);

    s32 result = lua_pcall(lua, num_args, num_returns, error_handler_pos);

    lua_remove(lua, error_handler_pos);

    return result;
}

internal lua_State *lua;

bool script_init(const char *file) {
    lua = luaL_newstate();
    luaL_openlibs(lua);

    lua_newtable(lua);

    // Bind graphics functions
    {
        lua_newtable(lua);

        lua_pushcfunction(lua, lua_graphics_load_texture);
        lua_setfield(lua, lua_gettop(lua) - 1, "load_texture");

        lua_pushcfunction(lua, lua_graphics_draw_sprite);
        lua_setfield(lua, lua_gettop(lua) - 1, "draw_sprite");

        lua_pushcfunction(lua, lua_graphics_draw_sprite_ex);
        lua_setfield(lua, lua_gettop(lua) - 1, "draw_sprite_ex");

        lua_setfield(lua, lua_gettop(lua) - 1, "graphics");
    }

    lua_setglobal(lua, "zull");

    s32 status = luaL_loadfile(lua, file);

    if (status == LUA_ERRFILE) {
        printf("Could not load '%s'!\n", file);
        return false;
    }

    if (status == LUA_ERRSYNTAX) {
        printf("%s\n", lua_tolstring(lua, lua_gettop(lua), NULL));
        return false;
    }

    safe_lua_call(lua, 0, 0);

    lua_getglobal(lua, "zull");
    lua_getfield(lua, lua_gettop(lua), "init");

    safe_lua_call(lua, 0, 0);

    return true;
}

// TODO(zedzull): If any of these built-in "callback" functions aren't present in the script, it generates a runtime error.
void script_update(f64 delta_time) {
    lua_getglobal(lua, "zull");
    lua_getfield(lua, lua_gettop(lua), "update");
    lua_pushnumber(lua, delta_time);

    safe_lua_call(lua, 1, 0);
}

void script_draw() {
    lua_getglobal(lua, "zull");
    lua_getfield(lua, lua_gettop(lua), "draw");

    safe_lua_call(lua, 0, 0);
}

void script_shutdown() {
    lua_getglobal(lua, "zull");
    lua_getfield(lua, lua_gettop(lua), "shutdown");

    safe_lua_call(lua, 0, 0);

    lua_close(lua);
}
<commit_msg>Added script_input_update<commit_after>static int clear_stack(lua_State *lua) {
    lua_pop(lua, lua_gettop(lua));
    return 0;
}

internal s32 lua_graphics_load_texture(lua_State *lua) {
    char *filename = (char *)lua_tostring(lua, 1);

    Texture texture = graphics_load_texture(filename);
    // Can't just push the texture as userdata because it gets
    // deleted after scope finishes
    lua_newtable(lua);
    lua_pushnumber(lua, texture.width);
    lua_setfield(lua, -2, "width");
    lua_pushnumber(lua, texture.height);
    lua_setfield(lua, -2, "height");
    lua_pushnumber(lua, texture.gl_handle);
    lua_setfield(lua, -2, "handle");
    // This should be used to determine if the proper type
    // is being passed into C functions from Lua
    lua_pushstring(lua, "__TEXTURE__");
    lua_setfield(lua, -2, "__type");
    return 1;
}

internal s32 lua_graphics_draw_sprite(lua_State *lua) {
    // TODO(zedzull): This should probably check for the correct arguments
	luaL_checktype(lua, 1, LUA_TTABLE);
    lua_getfield(lua, 1, "__type");
    const char *type = luaL_checkstring(lua, -1);
    // TODO(darithorn): Check if type == "__TEXTURE__"
    lua_getfield(lua, 1, "width");
    lua_getfield(lua, 1, "height");
    lua_getfield(lua, 1, "handle");
    int width = luaL_checknumber(lua, -3);
    int height = luaL_checknumber(lua, -2);
    GLuint handle = (GLuint)luaL_checknumber(lua, -1);
    Texture texture = { width, height, handle };
    f32 x = lua_tonumber(lua, 2);
    f32 y = lua_tonumber(lua, 3);

    graphics_draw_sprite(texture, x, y);
    clear_stack(lua);
    return 0;
}

static int lua_graphics_draw_sprite_ex(lua_State *lua) {
    luaL_checktype(lua, 1, LUA_TTABLE);
    lua_getfield(lua, 1, "__type");
    const char *type = luaL_checkstring(lua, -1);
    // TODO(darithorn): Check if type == "__TEXTURE__"
    lua_getfield(lua, 1, "width");
    lua_getfield(lua, 1, "height");
    lua_getfield(lua, 1, "handle");
    int width = luaL_checknumber(lua, -3);
    int height = luaL_checknumber(lua, -2);
    GLuint handle = (GLuint)luaL_checknumber(lua, -1);
    Texture texture = { width, height, handle };
    float dest_x = lua_tonumber(lua, 2);
    float dest_y = lua_tonumber(lua, 3);
    float dest_width = lua_tonumber(lua, 4);
    float dest_height = lua_tonumber(lua, 5);
    float src_x = lua_tonumber(lua, 6);
    float src_y = lua_tonumber(lua, 7);
    float src_width = lua_tonumber(lua, 8);
    float src_height = lua_tonumber(lua, 9);

    graphics_draw_sprite_ex(texture,
                            dest_x, dest_y, dest_width, dest_height,
                            src_x, src_y, src_width, src_height);
    clear_stack(lua);
    return 0;
}

internal s32 lua_runtime_error(lua_State *lua) {
    luaL_traceback(lua, lua, lua_tostring(lua, lua_gettop(lua)), 1);
    printf("%s\n", lua_tolstring(lua, lua_gettop(lua), NULL));

    exit(1);

    return 0;
}

internal s32 safe_lua_call(lua_State *lua, s32 num_args, s32 num_returns) {
    s32 error_handler_pos = lua_gettop(lua) - num_args;

    lua_pushcfunction(lua, lua_runtime_error);
    lua_insert(lua, error_handler_pos);

    s32 result = lua_pcall(lua, num_args, num_returns, error_handler_pos);

    lua_remove(lua, error_handler_pos);
    clear_stack(lua);
    return result;
}

internal lua_State *lua;

bool script_init(const char *file) {
    lua = luaL_newstate();
    luaL_openlibs(lua);

    lua_newtable(lua);

    // Bind graphics functions
    {
        lua_newtable(lua);

        lua_pushcfunction(lua, lua_graphics_load_texture);
        lua_setfield(lua, lua_gettop(lua) - 1, "load_texture");

        lua_pushcfunction(lua, lua_graphics_draw_sprite);
        lua_setfield(lua, lua_gettop(lua) - 1, "draw_sprite");

        lua_pushcfunction(lua, lua_graphics_draw_sprite_ex);
        lua_setfield(lua, lua_gettop(lua) - 1, "draw_sprite_ex");

        lua_setfield(lua, lua_gettop(lua) - 1, "graphics");
    }

    lua_setglobal(lua, "zull");

    s32 status = luaL_loadfile(lua, file);

    if (status == LUA_ERRFILE) {
        printf("Could not load '%s'!\n", file);
        return false;
    }

    if (status == LUA_ERRSYNTAX) {
        printf("%s\n", lua_tolstring(lua, lua_gettop(lua), NULL));
        return false;
    }

    safe_lua_call(lua, 0, 0);

    lua_getglobal(lua, "zull");
    lua_getfield(lua, lua_gettop(lua), "init");

    safe_lua_call(lua, 0, 0);

    return true;
}

// TODO(zedzull): If any of these built-in "callback" functions aren't present in the script, it generates a runtime error.
void script_update(f64 delta_time) {
    lua_getglobal(lua, "zull");
    lua_getfield(lua, lua_gettop(lua), "update");
    lua_pushnumber(lua, delta_time);

    safe_lua_call(lua, 1, 0);
}

void script_draw() {
    lua_getglobal(lua, "zull");
    lua_getfield(lua, lua_gettop(lua), "draw");

    safe_lua_call(lua, 0, 0);
}

void script_input_update(SDL_Event event) {
    lua_getglobal(lua, "zull");
    lua_getfield(lua, lua_gettop(lua), "input");
    lua_newtable(lua);
    lua_pushstring(lua, "__EVENT__");
    lua_setfield(lua, -2, "__type");
    if (event.type == SDL_KEYUP || event.type == SDL_KEYDOWN) {
        lua_pushstring(lua, SDL_GetKeyName(event.key.keysym.sym));
        lua_setfield(lua, -2, "key");
        if (event.key.state == SDL_RELEASED) {
            lua_pushstring(lua, "up");
        } else {
            lua_pushstring(lua, "down");
        }
        lua_setfield(lua, -2, "state");
    }
    safe_lua_call(lua, 1, 0);
}

void script_shutdown() {
    lua_getglobal(lua, "zull");
    lua_getfield(lua, lua_gettop(lua), "shutdown");

    safe_lua_call(lua, 0, 0);

    lua_close(lua);
}
<|endoftext|>