<commit_before>#ifndef __STAN__GM__COMMAND_HPP__
#define __STAN__GM__COMMAND_HPP__

#include <cmath>
#include <cstddef>
#include <ctime>
#include <iomanip>
#include <iostream>
#include <fstream>
#include <boost/random/additive_combine.hpp> // L'Ecuyer RNG
#include <boost/random/mersenne_twister.hpp>
#include <boost/random/uniform_01.hpp>
#include <boost/random/uniform_real_distribution.hpp>
#include <stan/io/cmd_line.hpp>
#include <stan/io/dump.hpp>
#include <stan/mcmc/hmc.hpp>
#include <stan/mcmc/nuts.hpp>
#include <stan/mcmc/prob_grad_ad.hpp>
#include <stan/mcmc/prob_grad.hpp>
#include <stan/mcmc/sampler.hpp>

namespace stan {

  namespace gm {

    void hmc_command(const stan::io::cmd_line& command,
                     stan::mcmc::prob_grad& model) {

      std::string sample_file = "samples.csv";
      command.val("sample_file",sample_file);
      std::fstream sample_file_stream(sample_file.c_str(), std::fstream::out);

      unsigned int num_iterations = 2000U;
      command.val("num_iterations",num_iterations);

      unsigned int num_burnin = num_iterations / 2;
      command.val("num_burnin",num_burnin);

      unsigned int calculated_thin = (num_iterations - num_burnin) / 1000U;
      unsigned int num_thin = (calculated_thin > 1) ? calculated_thin : 1U;
      command.val("num_thin",num_thin);

      double step_size = 0.01;
      command.val("step_size",step_size);

      unsigned int num_steps = 50;
      command.val("num_steps",num_steps);

      std::cout << "HMC" << std::endl;
      std::cout << "sample_file=" << sample_file << std::endl;
      std::cout << "num_iterations=" << num_iterations << std::endl;
      std::cout << "num_burnin=" << num_burnin << std::endl;
      std::cout << "num_thin=" << num_thin << std::endl;
      std::cout << "step_size=" << step_size << std::endl;
      std::cout << "num_steps=" << num_steps << std::endl;

      stan::mcmc::hmc sampler(model,step_size,num_steps);

      std::vector<double> params_r;
      std::vector<int> params_i;
      for (unsigned int m = 0; m < num_iterations; ++m) {
        std::cout << "iteration=" << (m + 1);
        if (m < num_burnin) {
          std::cout << " burning in" << std::endl;
          sampler.next();
          continue;
        }
        if (((m - num_burnin) % num_thin) != 0) {
          std::cout << " thinning" << std::endl;
          sampler.next();
          continue;
        }
        std::cout << " saving" << std::endl;
        stan::mcmc::sample sample = sampler.next();
        sample.params_r(params_r);
        sample.params_i(params_i);
        model.write_csv(params_r,params_i,sample_file_stream);
      }
      sample_file_stream.close();
    }

    // void pad_help_option(std::string option) {
    //   std::cout << "  " << option;
    //   for (unsigned int i = option.size(); i < 20; ++i)
    //     std::cout << ' ';
    // }

    void print_nuts_help(std::string cmd) {
      using stan::io::pad_help_option;

      std::cout << std::endl;
      std::cout << "Compiled Stan Graphical Model Command" << std::endl;
      std::cout << std::endl;

      std::cout << "USAGE:  " << cmd << " [options]" << std::endl;
      std::cout << std::endl;

      std::cout << "OPTIONS:" << std::endl;
      std::cout << std::endl;

      pad_help_option("--help");
      std::cout << "Display this information" << std::endl;
      std::cout << std::endl;

      pad_help_option("--data=<file>");
      std::cout << "Read data from specified dump-format file" << std::endl;
      pad_help_option();
      std::cout << "  (required if model declares data)" << std::endl;
      std::cout << std::endl;

      pad_help_option("--seed=<int>");
      std::cout << "Set random number generation seed" << std::endl;
      std::cout << std::endl;

      pad_help_option("--chain_id=<int>");
      std::cout << "Set chain identifier" << std::endl;
      pad_help_option();
      std::cout << "  (default = 1)" << std::endl;

      pad_help_option("--init=<file>");
      std::cout << "Use initial values from specified file or zero values if <file>=0"
                << std::endl;
      pad_help_option();
      std::cout << "    (default is random initialization)" << std::endl;
      std::cout << std::endl;

      pad_help_option("--iter=<+int>");
      std::cout << "Total number of iterations, including burn in"
                << std::endl;
      pad_help_option();
      std::cout << "    (default = 2000)" << std::endl;
      std::cout << std::endl;

      pad_help_option("--burnin=<+int>");
      std::cout << "Discard the specified number of initial samples"
                << std::endl;
      pad_help_option();
      std::cout << "    (default = iter / 2)" << std::endl;
      std::cout << std::endl;

      pad_help_option("--thin=<+int>");
      std::cout << "Period between saved samples after burn in" << std::endl;
      pad_help_option();
      std::cout << "    (default = max(1, floor(iter - burnin) / 1000))"
                << std::endl;
      std::cout << std::endl;

      pad_help_option("--delta=<+float>");
      std::cout << "Initial parameter for NUTS step-size tuning." << std::endl;
      pad_help_option();
      std::cout << "    (default = 0.5)" << std::endl;
      std::cout << std::endl;

      pad_help_option("--samples=<file>");
      std::cout << "File into which samples are written." << std::endl;
      pad_help_option();
      std::cout << "    (default = samples.csv)" << std::endl;
      std::cout << std::endl;

      pad_help_option("--append_samples");
      std::cout << "Append samples to existing samples file if it exists"
                << std::endl;
      pad_help_option();
      std::cout << "    (default erases existing samples file before writing)"
                << std::endl;
      std::cout << std::endl;

      pad_help_option("--refresh=<+int>");
      std::cout << "Period between samples producing progress output"
                << std::endl;
      pad_help_option();
      std::cout << "    (default = max(1,iter/200))" << std::endl;
      std::cout << std::endl;

      pad_help_option("--test_grad");
      std::cout << "Test gradient calculations using finite differences"
                << std::endl;

      std::cout << std::endl;
    }

    bool do_print(int refresh) {
      return refresh > 0;
    }

    bool do_print(int n, int refresh) {
      return do_print(refresh)
        && ((n + 1) % refresh == 0);
    }

    template <typename T_model>
    int nuts_command(int argc, const char* argv[]) {

      stan::io::cmd_line command(argc,argv);

      if (command.has_flag("help")) {
        print_nuts_help(argv[0]);
        return 0;
      }

      std::string data_path;
      command.val("data",data_path);
      std::fstream data_stream(data_path.c_str(),std::fstream::in);
      stan::io::dump data_var_context(data_stream);
      data_stream.close();

      T_model model(data_var_context);

      std::string sample_file = "samples.csv";
      command.val("samples",sample_file);

      unsigned int num_iterations = 2000U;
      command.val("iter",num_iterations);

      unsigned int num_burnin = num_iterations / 2;
      command.val("burnin",num_burnin);

      unsigned int calculated_thin = (num_iterations - num_burnin) / 1000U;
      unsigned int num_thin = (calculated_thin > 1) ? calculated_thin : 1U;
      command.val("thin",num_thin);

      double delta = 0.5;
      command.val("delta", delta);

      int refresh = 1;
      command.val("refresh",refresh);

      int random_seed = 0;
      if (command.has_key("seed")) {
        bool well_formed = command.val("seed",random_seed);
        if (!well_formed) {
          std::string seed_val;
          command.val("seed",seed_val);
          std::cerr << "value for seed must be integer"
                    << "; found value=" << seed_val << std::endl;
          return -1;
        }
      } else {
        random_seed = std::time(0);
      }

      int chain_id = 1;
      if (command.has_key("chain_id")) {
        bool well_formed = command.val("chain_id",chain_id);
        if (!well_formed || chain_id < 0) {
          std::string chain_id_val;
          command.val("chain_id",chain_id_val);
          std::cerr << "value for chain_id must be positive integer"
                    << "; found chain_id=" << chain_id_val
                    << std::endl;
          return -1;
        }
      }

      // FASTER, but no parallel guarantees
      // typedef boost::mt19937 rng_t;
      // rng_t base_rng(static_cast<unsigned int>(random_seed + chain_id - 1);

      typedef boost::ecuyer1988 rng_t;
      rng_t base_rng(random_seed);
      // (2**50 = 1T samples, 1000 chains)
      static long unsigned int DISCARD_STRIDE = (1 << 50);
      base_rng.discard(DISCARD_STRIDE * (chain_id - 1));

      std::vector<int> params_i;
      std::vector<double> params_r;

      std::string init_val;
      // parameter initialization
      if (command.has_key("init")) {
        command.val("init",init_val);
        if (init_val == "0") {
          params_i = std::vector<int>(model.num_params_i(),0);
          params_r = std::vector<double>(model.num_params_r(),0.0);
        } else {
          std::cout << "init file=" << init_val << std::endl;

          std::fstream init_stream(init_val.c_str(),std::fstream::in);
          stan::io::dump init_var_context(init_stream);
          init_stream.close();
          model.transform_inits(init_var_context,params_i,params_r);
        }
      } else {
        init_val = "random initialization";
        // init_rng generates uniformly from -2 to 2
        boost::random::uniform_real_distribution<double>
          init_range_distribution(-2.0,2.0);
        boost::variate_generator<rng_t&,
                       boost::random::uniform_real_distribution<double> >
          init_rng(base_rng,init_range_distribution);

        params_i = std::vector<int>(model.num_params_i(),0);
        params_r = std::vector<double>(model.num_params_r());
        for (size_t i = 0; i < params_r.size(); ++i)
          params_r[i] = init_rng();
      }

      std::cout << "NUTS" << std::endl;
      std::cout << "sample_file=" << sample_file << std::endl;
      std::cout << "init=" << init_val << std::endl;
      std::cout << "num_iterations=" << num_iterations << std::endl;
      std::cout << "num_burnin=" << num_burnin << std::endl;
      std::cout << "num_thin=" << num_thin << std::endl;
      std::cout << "delta=" << delta << std::endl;
      std::cout << "random seed=" << random_seed
                << " (" << (command.has_key("seed")
                            ? "user specified"
                            : "randomly generated") << ")"
                << std::endl;
      std::cout << "chain id=" << chain_id
                << " (" << (command.has_key("seed")
                            ? "user specified"
                            : "randomly generated") << ")"
                << std::endl;

      if (command.has_flag("test_grad")) {
        std::cout << std::endl << "TEST GRADIENT MODE" << std::endl;
        model.test_gradients(params_r,params_i);
        return 0;
      }

      std::fstream sample_file_stream(sample_file.c_str(), std::fstream::out);
      model.write_csv_header(sample_file_stream);
      int it_print_width = std::ceil(std::log10(num_iterations));
      std::cout << std::endl;

      stan::mcmc::nuts<rng_t> sampler(model, delta, -1, base_rng);
      sampler.adapt_on();
      for (unsigned int m = 0; m < num_iterations; ++m) {
        if (do_print(m,refresh)) {
          std::cout << "\rIteration: ";
          std::cout << std::setw(it_print_width) << (m + 1)
                    << " / " << num_iterations;
          std::cout << " [" << std::setw(3)
                    << static_cast<int>((100.0 * (m + 1))/num_iterations)
                    << "%] ";
          std::cout << ((m < num_burnin) ? " (Adapting)" : " (Sampling)");
          std::cout.flush();
        }
        if (m < num_burnin) {
          sampler.next(); // discard
        } else {
          sampler.adapt_off();
          if (((m - num_burnin) % num_thin) != 0) {
            sampler.next();
            continue;
          } else {
            stan::mcmc::sample sample = sampler.next();
            sample.params_r(params_r);
            sample.params_i(params_i);
            model.write_csv(params_r,params_i,sample_file_stream);
          }
        }
      }
      sample_file_stream.close();
      std::cout << std::endl << std::endl;
      return 0;
    }

  } // namespace prob

} // namespace stan

#endif
<commit_msg>removed warning. left shift count >= width of type<commit_after>#ifndef __STAN__GM__COMMAND_HPP__
#define __STAN__GM__COMMAND_HPP__

#include <cmath>
#include <cstddef>
#include <ctime>
#include <iomanip>
#include <iostream>
#include <fstream>
#include <boost/random/additive_combine.hpp> // L'Ecuyer RNG
#include <boost/random/mersenne_twister.hpp>
#include <boost/random/uniform_01.hpp>
#include <boost/random/uniform_real_distribution.hpp>
#include <stan/io/cmd_line.hpp>
#include <stan/io/dump.hpp>
#include <stan/mcmc/hmc.hpp>
#include <stan/mcmc/nuts.hpp>
#include <stan/mcmc/prob_grad_ad.hpp>
#include <stan/mcmc/prob_grad.hpp>
#include <stan/mcmc/sampler.hpp>

namespace stan {

  namespace gm {

    void hmc_command(const stan::io::cmd_line& command,
                     stan::mcmc::prob_grad& model) {

      std::string sample_file = "samples.csv";
      command.val("sample_file",sample_file);
      std::fstream sample_file_stream(sample_file.c_str(), std::fstream::out);

      unsigned int num_iterations = 2000U;
      command.val("num_iterations",num_iterations);

      unsigned int num_burnin = num_iterations / 2;
      command.val("num_burnin",num_burnin);

      unsigned int calculated_thin = (num_iterations - num_burnin) / 1000U;
      unsigned int num_thin = (calculated_thin > 1) ? calculated_thin : 1U;
      command.val("num_thin",num_thin);

      double step_size = 0.01;
      command.val("step_size",step_size);

      unsigned int num_steps = 50;
      command.val("num_steps",num_steps);

      std::cout << "HMC" << std::endl;
      std::cout << "sample_file=" << sample_file << std::endl;
      std::cout << "num_iterations=" << num_iterations << std::endl;
      std::cout << "num_burnin=" << num_burnin << std::endl;
      std::cout << "num_thin=" << num_thin << std::endl;
      std::cout << "step_size=" << step_size << std::endl;
      std::cout << "num_steps=" << num_steps << std::endl;

      stan::mcmc::hmc sampler(model,step_size,num_steps);

      std::vector<double> params_r;
      std::vector<int> params_i;
      for (unsigned int m = 0; m < num_iterations; ++m) {
        std::cout << "iteration=" << (m + 1);
        if (m < num_burnin) {
          std::cout << " burning in" << std::endl;
          sampler.next();
          continue;
        }
        if (((m - num_burnin) % num_thin) != 0) {
          std::cout << " thinning" << std::endl;
          sampler.next();
          continue;
        }
        std::cout << " saving" << std::endl;
        stan::mcmc::sample sample = sampler.next();
        sample.params_r(params_r);
        sample.params_i(params_i);
        model.write_csv(params_r,params_i,sample_file_stream);
      }
      sample_file_stream.close();
    }

    // void pad_help_option(std::string option) {
    //   std::cout << "  " << option;
    //   for (unsigned int i = option.size(); i < 20; ++i)
    //     std::cout << ' ';
    // }

    void print_nuts_help(std::string cmd) {
      using stan::io::pad_help_option;

      std::cout << std::endl;
      std::cout << "Compiled Stan Graphical Model Command" << std::endl;
      std::cout << std::endl;

      std::cout << "USAGE:  " << cmd << " [options]" << std::endl;
      std::cout << std::endl;

      std::cout << "OPTIONS:" << std::endl;
      std::cout << std::endl;

      pad_help_option("--help");
      std::cout << "Display this information" << std::endl;
      std::cout << std::endl;

      pad_help_option("--data=<file>");
      std::cout << "Read data from specified dump-format file" << std::endl;
      pad_help_option();
      std::cout << "  (required if model declares data)" << std::endl;
      std::cout << std::endl;

      pad_help_option("--seed=<int>");
      std::cout << "Set random number generation seed" << std::endl;
      std::cout << std::endl;

      pad_help_option("--chain_id=<int>");
      std::cout << "Set chain identifier" << std::endl;
      pad_help_option();
      std::cout << "  (default = 1)" << std::endl;

      pad_help_option("--init=<file>");
      std::cout << "Use initial values from specified file or zero values if <file>=0"
                << std::endl;
      pad_help_option();
      std::cout << "    (default is random initialization)" << std::endl;
      std::cout << std::endl;

      pad_help_option("--iter=<+int>");
      std::cout << "Total number of iterations, including burn in"
                << std::endl;
      pad_help_option();
      std::cout << "    (default = 2000)" << std::endl;
      std::cout << std::endl;

      pad_help_option("--burnin=<+int>");
      std::cout << "Discard the specified number of initial samples"
                << std::endl;
      pad_help_option();
      std::cout << "    (default = iter / 2)" << std::endl;
      std::cout << std::endl;

      pad_help_option("--thin=<+int>");
      std::cout << "Period between saved samples after burn in" << std::endl;
      pad_help_option();
      std::cout << "    (default = max(1, floor(iter - burnin) / 1000))"
                << std::endl;
      std::cout << std::endl;

      pad_help_option("--delta=<+float>");
      std::cout << "Initial parameter for NUTS step-size tuning." << std::endl;
      pad_help_option();
      std::cout << "    (default = 0.5)" << std::endl;
      std::cout << std::endl;

      pad_help_option("--samples=<file>");
      std::cout << "File into which samples are written." << std::endl;
      pad_help_option();
      std::cout << "    (default = samples.csv)" << std::endl;
      std::cout << std::endl;

      pad_help_option("--append_samples");
      std::cout << "Append samples to existing samples file if it exists"
                << std::endl;
      pad_help_option();
      std::cout << "    (default erases existing samples file before writing)"
                << std::endl;
      std::cout << std::endl;

      pad_help_option("--refresh=<+int>");
      std::cout << "Period between samples producing progress output"
                << std::endl;
      pad_help_option();
      std::cout << "    (default = max(1,iter/200))" << std::endl;
      std::cout << std::endl;

      pad_help_option("--test_grad");
      std::cout << "Test gradient calculations using finite differences"
                << std::endl;

      std::cout << std::endl;
    }

    bool do_print(int refresh) {
      return refresh > 0;
    }

    bool do_print(int n, int refresh) {
      return do_print(refresh)
        && ((n + 1) % refresh == 0);
    }

    template <typename T_model>
    int nuts_command(int argc, const char* argv[]) {

      stan::io::cmd_line command(argc,argv);

      if (command.has_flag("help")) {
        print_nuts_help(argv[0]);
        return 0;
      }

      std::string data_path;
      command.val("data",data_path);
      std::fstream data_stream(data_path.c_str(),std::fstream::in);
      stan::io::dump data_var_context(data_stream);
      data_stream.close();

      T_model model(data_var_context);

      std::string sample_file = "samples.csv";
      command.val("samples",sample_file);

      unsigned int num_iterations = 2000U;
      command.val("iter",num_iterations);

      unsigned int num_burnin = num_iterations / 2;
      command.val("burnin",num_burnin);

      unsigned int calculated_thin = (num_iterations - num_burnin) / 1000U;
      unsigned int num_thin = (calculated_thin > 1) ? calculated_thin : 1U;
      command.val("thin",num_thin);

      double delta = 0.5;
      command.val("delta", delta);

      int refresh = 1;
      command.val("refresh",refresh);

      int random_seed = 0;
      if (command.has_key("seed")) {
        bool well_formed = command.val("seed",random_seed);
        if (!well_formed) {
          std::string seed_val;
          command.val("seed",seed_val);
          std::cerr << "value for seed must be integer"
                    << "; found value=" << seed_val << std::endl;
          return -1;
        }
      } else {
        random_seed = std::time(0);
      }

      int chain_id = 1;
      if (command.has_key("chain_id")) {
        bool well_formed = command.val("chain_id",chain_id);
        if (!well_formed || chain_id < 0) {
          std::string chain_id_val;
          command.val("chain_id",chain_id_val);
          std::cerr << "value for chain_id must be positive integer"
                    << "; found chain_id=" << chain_id_val
                    << std::endl;
          return -1;
        }
      }

      // FASTER, but no parallel guarantees
      // typedef boost::mt19937 rng_t;
      // rng_t base_rng(static_cast<unsigned int>(random_seed + chain_id - 1);

      typedef boost::ecuyer1988 rng_t;
      rng_t base_rng(random_seed);
      // (2**50 = 1T samples, 1000 chains)
      static long unsigned int DISCARD_STRIDE = (1UL << 50);
      base_rng.discard(DISCARD_STRIDE * (chain_id - 1));

      std::vector<int> params_i;
      std::vector<double> params_r;

      std::string init_val;
      // parameter initialization
      if (command.has_key("init")) {
        command.val("init",init_val);
        if (init_val == "0") {
          params_i = std::vector<int>(model.num_params_i(),0);
          params_r = std::vector<double>(model.num_params_r(),0.0);
        } else {
          std::cout << "init file=" << init_val << std::endl;

          std::fstream init_stream(init_val.c_str(),std::fstream::in);
          stan::io::dump init_var_context(init_stream);
          init_stream.close();
          model.transform_inits(init_var_context,params_i,params_r);
        }
      } else {
        init_val = "random initialization";
        // init_rng generates uniformly from -2 to 2
        boost::random::uniform_real_distribution<double>
          init_range_distribution(-2.0,2.0);
        boost::variate_generator<rng_t&,
                       boost::random::uniform_real_distribution<double> >
          init_rng(base_rng,init_range_distribution);

        params_i = std::vector<int>(model.num_params_i(),0);
        params_r = std::vector<double>(model.num_params_r());
        for (size_t i = 0; i < params_r.size(); ++i)
          params_r[i] = init_rng();
      }

      std::cout << "NUTS" << std::endl;
      std::cout << "sample_file=" << sample_file << std::endl;
      std::cout << "init=" << init_val << std::endl;
      std::cout << "num_iterations=" << num_iterations << std::endl;
      std::cout << "num_burnin=" << num_burnin << std::endl;
      std::cout << "num_thin=" << num_thin << std::endl;
      std::cout << "delta=" << delta << std::endl;
      std::cout << "random seed=" << random_seed
                << " (" << (command.has_key("seed")
                            ? "user specified"
                            : "randomly generated") << ")"
                << std::endl;
      std::cout << "chain id=" << chain_id
                << " (" << (command.has_key("seed")
                            ? "user specified"
                            : "randomly generated") << ")"
                << std::endl;

      if (command.has_flag("test_grad")) {
        std::cout << std::endl << "TEST GRADIENT MODE" << std::endl;
        model.test_gradients(params_r,params_i);
        return 0;
      }

      std::fstream sample_file_stream(sample_file.c_str(), std::fstream::out);
      model.write_csv_header(sample_file_stream);
      int it_print_width = std::ceil(std::log10(num_iterations));
      std::cout << std::endl;

      stan::mcmc::nuts<rng_t> sampler(model, delta, -1, base_rng);
      sampler.adapt_on();
      for (unsigned int m = 0; m < num_iterations; ++m) {
        if (do_print(m,refresh)) {
          std::cout << "\rIteration: ";
          std::cout << std::setw(it_print_width) << (m + 1)
                    << " / " << num_iterations;
          std::cout << " [" << std::setw(3)
                    << static_cast<int>((100.0 * (m + 1))/num_iterations)
                    << "%] ";
          std::cout << ((m < num_burnin) ? " (Adapting)" : " (Sampling)");
          std::cout.flush();
        }
        if (m < num_burnin) {
          sampler.next(); // discard
        } else {
          sampler.adapt_off();
          if (((m - num_burnin) % num_thin) != 0) {
            sampler.next();
            continue;
          } else {
            stan::mcmc::sample sample = sampler.next();
            sample.params_r(params_r);
            sample.params_i(params_i);
            model.write_csv(params_r,params_i,sample_file_stream);
          }
        }
      }
      sample_file_stream.close();
      std::cout << std::endl << std::endl;
      return 0;
    }

  } // namespace prob

} // namespace stan

#endif
<|endoftext|>


<commit_before>#include "ResourceManager.h"

namespace gines
{

}<commit_msg>ResourceManager uus versio jee<commit_after>#pragma region PreProcessor

#include "ResourceManager.h"

#define AUTONAME(T_NAME)\
		string Name = #T_NAME;\
		for (int a = 1; a <= 4; a++) {\
		if (T_NAME ## No < (10 ^ a)) {\
		Name += "0";}}\
		Name += to_string(T_NAME ## No);

#define AUTOIDENTIFIER(T_NAME)\
		int Identifier = T_NAME ## No + 10000;

#define ADDDATA(T_NAME)\
		T_NAME ## s.push_back(new ## T_NAME);\
		T_NAME ## Names.push_back(Name);\
		T_NAME ## Identifiers.push_back(Identifier);\
		T_NAME ## Filenames.push_back(Filename);\
		T_NAME ## No++;

#define FIND(T_NAME, TYPE, T_SEARCH, P_SEARCH)\
		list< ## TYPE ## >::iterator tit = T_NAME ## s.begin();\
		for (list< ## T_SEARCH ## >::iterator it = T_NAME ## P_SEARCH ## s.begin(); it != T_NAME ## P_SEARCH ## s.end(); ++it) {\
		if (*it == ## P_SEARCH) {return *tit;}\
		++tit;}\
		cout << "Error: Couldn't find a ## T_NAME ## with ## P_SEARCH ## '" << ## P_SEARCH ## << "'.\n";\
		return 0;

#define REMOVE(T_NAME, TYPE, COMPARE_A, COMPARE_B)\
	list<## TYPE ##>::iterator ia = T_NAME ## s.begin();\
	list<string>::iterator ic = T_NAME ##Names.begin();\
	list<int>::iterator id = T_NAME ##Identifiers.begin();\
	list<string>::iterator ie = T_NAME ##Filenames.begin();\
	while (COMPARE_A != T_NAME ## COMPARE_B ## s.end() && * ## COMPARE_A != Deletable){\
	++ia;++ic;++id;++ie;}\
	if (COMPARE_A != T_NAME ## COMPARE_B ## s.end()){\
	destroy ## T_NAME ## (*ia);\
	T_NAME ## s.erase(ia);\
	T_NAME ## Names.erase(ic);\
	T_NAME ## Identifiers.erase(id);\
	T_NAME ## Filenames.erase(ie);\
	T_NAME ## No--;\
	return true;}return false;

#define POPULATE(T_NAME, TYPE)\
	bool ResourceManager::add ## T_NAME ## (string Filename){AUTONAME(T_NAME);return add ## T_NAME ## (Filename, Name);}\
	bool ResourceManager::add ## T_NAME ## (string Filename, int Identifier){AUTONAME(T_NAME);return create ## T_NAME ## (Filename, Identifier, Name);}\
	bool ResourceManager::add ## T_NAME ## (string Filename, string Name){AUTOIDENTIFIER(T_NAME);return create ## T_NAME ## (Filename, Identifier, Name);}\
	bool ResourceManager::add ## T_NAME ## (string Filename, int Identifier, string Name){return ResourceManager::create ## T_NAME ## (Filename, Identifier, Name);}\
	TYPE ResourceManager::find ## T_NAME ## (int Identifier){FIND(T_NAME, TYPE, int, Identifier);}\
	TYPE ResourceManager::find ## T_NAME ## (string Name){FIND(T_NAME, TYPE, string, Name);}\
	TYPE ResourceManager::find ## T_NAME ## (int Identifier, string Name){TYPE a = find ## T_NAME ## (Identifier); TYPE b = find ## T_NAME ## (Name); return (a == b) ? a : 0;}\
	bool ResourceManager::remove ## T_NAME ## (TYPE Deletable){REMOVE(T_NAME, TYPE, ia, );}\
	bool ResourceManager::remove ## T_NAME ## (int Deletable){REMOVE(T_NAME, TYPE, id, Identifier);}\
	bool ResourceManager::remove ## T_NAME ## (string Deletable){REMOVE(T_NAME, TYPE, ic, Name);}

#pragma endregion

ResourceManager::ResourceManager()
{
	TextFileNo = 0;
	TextureNo = 0;
}
ResourceManager::~ResourceManager()
{
	for (list<list<string>*>::iterator tit = TextFiles.begin(); tit != TextFiles.end(); ++tit) {
		destroyTextFile(*tit);
	}

	for (list<GLuint>::iterator tit = Textures.begin(); tit != Textures.end(); ++tit) {
		destroyTexture(*tit);
	}
}

bool ResourceManager::createTextFile(string Filename, int Identifier, string Name)
{
	string line;

	ifstream myfile("example.txt");

	if (myfile.is_open())
	{
		list<string> newList;
		int length = 0;

		while (getline(myfile, line))
		{
			newList.push_back(line);
			length++;
		}
		myfile.close();

		TextFiles.push_back(&newList);
		TextFileLengths.push_back(length);
		TextFileNames.push_back(Name);
		TextFileIdentifiers.push_back(Identifier);
		TextFileFilenames.push_back(Filename);
		TextFileNo++;
		return true;
	}
	else
	{
		return false;
	}
}
void ResourceManager::destroyTextFile(list<string>* Deletable)
{
	delete &Deletable;
}

POPULATE(TextFile, list<string>*);

bool ResourceManager::createTexture(string Filename, int Identifier, string Name)
{
	SDL_Surface* surface = IMG_Load(Filename.c_str());

	if (!surface) {
		cout << "Error: File '" << Filename << "' NULL\n";
		return false;
	}

	GLuint newTexture = surfaceToTexture(surface);

	SDL_FreeSurface(surface);

	if (newTexture == 0){
		cout << "Error: Texture '" << Filename << "' NULL\n";
		return false;
	}
	ADDDATA(Texture);
	return true;
}
void ResourceManager::destroyTexture(GLuint Deletable)
{
	glDeleteTextures(1, &Deletable);
}
GLuint ResourceManager::surfaceToTexture(SDL_Surface* surface)
{
	GLuint TextureID = 0;

	glGenTextures(1, &TextureID);
	glBindTexture(GL_TEXTURE_2D, TextureID);

	int Mode = GL_RGB;

	if (surface->format->BytesPerPixel == 4) {
		Mode = GL_RGBA;
	}

	glTexImage2D(GL_TEXTURE_2D, 0, Mode, surface->w, surface->h, 0, Mode, GL_UNSIGNED_BYTE, surface->pixels);

	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);

	return TextureID;
}

POPULATE(Texture, GLuint);

bool ResourceManager::createSound(string Filename, int Identifier, string Name)
{
	Mix_Chunk* newSound = Mix_LoadWAV(Filename.c_str());
	if (newSound == NULL)
	{
		cout << "Failed to load sound effect from " << Filename << "! SDL_mixer Error: %s\n", Mix_GetError();
		return false;
	}

	ADDDATA(Sound);
	return true;
}
void ResourceManager::destroySound(Mix_Chunk* Deletable)
{
	Mix_FreeChunk(Deletable);
}

POPULATE(Sound, Mix_Chunk*)

bool ResourceManager::createMusic(string Filename, int Identifier, string Name)
{
	//Load music
	Mix_Music* newMusic = Mix_LoadMUS(Filename.c_str());
	if (newMusic == NULL)
	{
		cout << "Failed to load music from " << Filename << "! SDL_mixer Error: %s\n", Mix_GetError();
		return false;
	}

	ADDDATA(Music);
	return true;
}
void ResourceManager::destroyMusic(Mix_Music* Deletable)
{
	Mix_FreeMusic(Deletable);
}

POPULATE(Music, Mix_Music*)

<|endoftext|>


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

#if !defined(_WIN32)
#include "iceoryx_utils/internal/posix_wrapper/message_queue.hpp"
#include "iceoryx_utils/internal/posix_wrapper/unix_domain_socket.hpp"

#include "test.hpp"

#include <chrono>

using namespace ::testing;
using namespace iox;
using namespace iox::posix;

#if defined(__APPLE__)
using IpcChannelTypes = Types<UnixDomainSocket>;
#else
using IpcChannelTypes = Types<MessageQueue, UnixDomainSocket>;
#endif

constexpr char goodName[] = "channel_test";
constexpr char anotherGoodName[] = "horst";
constexpr char theUnknown[] = "WhoeverYouAre";
constexpr char slashName[] = "/miau";
constexpr char invalidName[] = "x";

/// @req
/// @brief This test suite verifies that the abstract interface IpcChannelType is fulfilled by both the UnixDomainSocket
/// class and the MessageQueue class
/// @pre server and client object are allocated and move to the member object of the fixture
/// @post StdErr is capture and outputed to StdCout
/// @note Specific functionality of the underlying implementations of an IpcChannelType are tested in
/// "UnixDomainSocket_test"
template <typename T>
class IpcChannel_test : public Test
{
  public:
    using IpcChannelType = T;

    void SetUp()
    {
        auto serverResult = IpcChannelType::create(
            goodName, IpcChannelMode::BLOCKING, IpcChannelSide::SERVER, MaxMsgSize, MaxMsgNumber);
        ASSERT_THAT(serverResult.has_error(), Eq(false));
        server = std::move(serverResult.value());
        internal::CaptureStderr();

        auto clientResult = IpcChannelType::create(
            goodName, IpcChannelMode::BLOCKING, IpcChannelSide::CLIENT, MaxMsgSize, MaxMsgNumber);
        ASSERT_THAT(clientResult.has_error(), Eq(false));
        client = std::move(clientResult.value());
    }

    void TearDown()
    {
        std::string output = internal::GetCapturedStderr();
        if (Test::HasFailure())
        {
            std::cout << output << std::endl;
        }
    }

    ~IpcChannel_test()
    {
    }

    static const size_t MaxMsgSize;
    static constexpr uint64_t MaxMsgNumber = 10U;
    IpcChannelType server;
    IpcChannelType client;
};

template <typename T>
const size_t IpcChannel_test<T>::MaxMsgSize = IpcChannelType::MAX_MESSAGE_SIZE;
template <typename T>
constexpr uint64_t IpcChannel_test<T>::MaxMsgNumber;

/// we require TYPED_TEST since we support gtest 1.8 for our safety targets
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
TYPED_TEST_CASE(IpcChannel_test, IpcChannelTypes);
#pragma GCC diagnostic pop

TYPED_TEST(IpcChannel_test, CreateWithTooLargeMessageSizeLeadsToError)
{
    auto serverResult = TestFixture::IpcChannelType::create(goodName,
                                                            IpcChannelMode::BLOCKING,
                                                            IpcChannelSide::SERVER,
                                                            TestFixture::MaxMsgSize + 1,
                                                            TestFixture::MaxMsgNumber);
    EXPECT_TRUE(serverResult.has_error());
    ASSERT_THAT(serverResult.get_error(), Eq(IpcChannelError::MAX_MESSAGE_SIZE_EXCEEDED));
}

TYPED_TEST(IpcChannel_test, CreateNoNameLeadsToError)
{
    auto serverResult = TestFixture::IpcChannelType::create("", IpcChannelMode::BLOCKING, IpcChannelSide::SERVER);
    EXPECT_TRUE(serverResult.has_error());
    ASSERT_THAT(serverResult.get_error(), Eq(IpcChannelError::INVALID_CHANNEL_NAME));
}

TYPED_TEST(IpcChannel_test, CreateWithLeadingSlashWorks)
{
    auto serverResult =
        TestFixture::IpcChannelType::create(slashName, IpcChannelMode::BLOCKING, IpcChannelSide::SERVER);
    EXPECT_FALSE(serverResult.has_error());
}

TYPED_TEST(IpcChannel_test, CreateAgainWorks)
{
    // if there is a leftover from a crashed channel, we can create a new one. This is simulated by creating twice
    auto first = TestFixture::IpcChannelType::create(anotherGoodName, IpcChannelMode::BLOCKING, IpcChannelSide::SERVER);
    EXPECT_FALSE(first.has_error());
    auto second =
        TestFixture::IpcChannelType::create(anotherGoodName, IpcChannelMode::BLOCKING, IpcChannelSide::SERVER);
    EXPECT_FALSE(second.has_error());
}

TYPED_TEST(IpcChannel_test, CreateAgainAndEmptyWorks)
{
    using namespace iox::units;
    using namespace std::chrono;

    auto serverResult =
        TestFixture::IpcChannelType::create(anotherGoodName, IpcChannelMode::BLOCKING, IpcChannelSide::SERVER);
    EXPECT_FALSE(serverResult.has_error());
    auto server = std::move(serverResult.value());

    auto clientResult =
        TestFixture::IpcChannelType::create(anotherGoodName, IpcChannelMode::BLOCKING, IpcChannelSide::CLIENT);
    EXPECT_FALSE(clientResult.has_error());
    auto client = std::move(clientResult.value());

    // send and receive as usual
    std::string message = "Hey, I'm talking to you";
    bool sent = client.send(message).has_error();
    EXPECT_FALSE(sent);

    auto receivedMessage = server.receive();
    ASSERT_THAT(receivedMessage.has_error(), Eq(false));
    EXPECT_EQ(message, *receivedMessage);

    // send a message, create the server again and there is no message
    std::string newMessage = "I'm still talking to you brother";
    sent = client.send(newMessage).has_error();
    EXPECT_FALSE(sent);

    auto second =
        TestFixture::IpcChannelType::create(anotherGoodName, IpcChannelMode::BLOCKING, IpcChannelSide::SERVER);
    EXPECT_FALSE(second.has_error());
    server = std::move(second.value());

    Duration timeout = 100_ms;
    auto received = server.timedReceive(timeout);
    ASSERT_TRUE(received.has_error());
    ASSERT_THAT(received.get_error(), Eq(IpcChannelError::TIMEOUT));
}

TYPED_TEST(IpcChannel_test, ClientWithoutServerLeadsToNoSuchChannelError)
{
    auto clientResult =
        TestFixture::IpcChannelType::create(anotherGoodName, IpcChannelMode::BLOCKING, IpcChannelSide::CLIENT);
    EXPECT_TRUE(clientResult.has_error());
    ASSERT_THAT(clientResult.get_error(), Eq(IpcChannelError::NO_SUCH_CHANNEL));
}

TYPED_TEST(IpcChannel_test, NotDestroyingServerLeadsToNonOutdatedClient)
{
    auto serverResult =
        TestFixture::IpcChannelType::create(anotherGoodName, IpcChannelMode::BLOCKING, IpcChannelSide::SERVER);
    EXPECT_FALSE(serverResult.has_error());
    auto server = std::move(serverResult.value());

    auto clientResult =
        TestFixture::IpcChannelType::create(anotherGoodName, IpcChannelMode::BLOCKING, IpcChannelSide::CLIENT);
    EXPECT_FALSE(clientResult.has_error());
    auto client = std::move(clientResult.value());

    auto outdated = client.isOutdated();
    EXPECT_FALSE(outdated.has_error());
    EXPECT_FALSE(outdated.value());
}

TYPED_TEST(IpcChannel_test, DestroyingServerLeadsToOutdatedClient)
{
    if (std::is_same<typename TestFixture::IpcChannelType, UnixDomainSocket>::value)
    {
        // isOutdated cannot be realized for unix domain sockets
        return;
    }

    auto serverResult =
        TestFixture::IpcChannelType::create(anotherGoodName, IpcChannelMode::BLOCKING, IpcChannelSide::SERVER);
    EXPECT_FALSE(serverResult.has_error());
    auto server = std::move(serverResult.value());

    auto clientResult =
        TestFixture::IpcChannelType::create(anotherGoodName, IpcChannelMode::BLOCKING, IpcChannelSide::CLIENT);
    EXPECT_FALSE(clientResult.has_error());
    auto client = std::move(clientResult.value());

    // destroy the server and the client is outdated
    auto dest = server.destroy();
    ASSERT_FALSE(dest.has_error());

    auto outdated = client.isOutdated();
    EXPECT_FALSE(outdated.has_error());
    EXPECT_TRUE(outdated.value());
}

TYPED_TEST(IpcChannel_test, UnlinkExistingOneWorks)
{
    auto first = TestFixture::IpcChannelType::create(anotherGoodName, IpcChannelMode::BLOCKING, IpcChannelSide::SERVER);
    EXPECT_FALSE(first.has_error());
    auto ret = TestFixture::IpcChannelType::unlinkIfExists(anotherGoodName);
    EXPECT_FALSE(ret.has_error());
    EXPECT_TRUE(ret.value());
}

TYPED_TEST(IpcChannel_test, UnlinkNonExistingOneWorks)
{
    auto ret = TestFixture::IpcChannelType::unlinkIfExists(theUnknown);
    EXPECT_FALSE(ret.has_error());
    EXPECT_FALSE(ret.value());
}

TYPED_TEST(IpcChannel_test, SendAndReceiveWorks)
{
    std::string message = "Hey, I'm talking to you";
    bool sent = this->client.send(message).has_error();
    EXPECT_FALSE(sent);

    std::string anotherMessage = "This is a message";
    sent = this->client.send(anotherMessage).has_error();
    EXPECT_FALSE(sent);

    auto receivedMessage = this->server.receive();
    ASSERT_THAT(receivedMessage.has_error(), Eq(false));
    EXPECT_EQ(message, *receivedMessage);

    receivedMessage = this->server.receive();
    ASSERT_THAT(receivedMessage.has_error(), Eq(false));
    EXPECT_EQ(anotherMessage, *receivedMessage);
}

TYPED_TEST(IpcChannel_test, InvalidAfterDestroy)
{
    this->client.destroy();
    ASSERT_FALSE(this->client.isInitialized());
    this->server.destroy();
    ASSERT_FALSE(this->server.isInitialized());
}

TYPED_TEST(IpcChannel_test, SendAfterClientDestroyLeadsToError)
{
    auto dest = this->client.destroy();
    ASSERT_FALSE(dest.has_error());

    std::string message = "Should never be sent";
    bool sendError = this->client.send(message).has_error();
    EXPECT_TRUE(sendError);
}

TYPED_TEST(IpcChannel_test, SendAfterServerDestroyLeadsToError)
{
    if (std::is_same<typename TestFixture::IpcChannelType, MessageQueue>::value)
    {
        // We still can send to the message queue is we destroy the server
        // it would be outdated, this is checked in another test
        return;
    }

    auto dest = this->server.destroy();
    ASSERT_FALSE(dest.has_error());

    std::string message = "Try to send me";
    auto sendResult = this->client.send(message);
    EXPECT_TRUE(sendResult.has_error());
}

TYPED_TEST(IpcChannel_test, ReceiveAfterServerDestroyLeadsToError)
{
    std::string message = "hello world!";
    bool sendError = this->client.send(message).has_error();
    EXPECT_FALSE(sendError);

    auto dest = this->server.destroy();
    ASSERT_FALSE(dest.has_error());

    bool receiveError = this->server.receive().has_error();
    EXPECT_THAT(receiveError, Eq(true));
}

TYPED_TEST(IpcChannel_test, SendMoreThanAllowedLeadsToError)
{
    std::string shortMessage = "Iceoryx rules.";
    ASSERT_THAT(this->client.send(shortMessage).has_error(), Eq(false));

    std::string longMessage(this->server.MAX_MESSAGE_SIZE + 8, 'x');
    ASSERT_THAT(this->client.send(longMessage).has_error(), Eq(true));

    auto receivedMessage = this->server.receive();
    ASSERT_THAT(receivedMessage.has_error(), Eq(false));
    EXPECT_EQ(shortMessage, receivedMessage.value());
}

TYPED_TEST(IpcChannel_test, SendMaxMessageSizeWorks)
{
    std::string message(this->MaxMsgSize - 1, 'x');
    auto clientReturn = this->client.send(message);
    ASSERT_THAT(clientReturn.has_error(), Eq(false));

    auto receivedMessage = this->server.receive();
    ASSERT_THAT(receivedMessage.has_error(), Eq(false));
    EXPECT_EQ(message, receivedMessage.value());
}

TYPED_TEST(IpcChannel_test, wildCreate)
{
    auto result = TestFixture::IpcChannelType::create();
    ASSERT_THAT(result.has_error(), Eq(true));
}

#if !defined(__APPLE__)
TYPED_TEST(IpcChannel_test, TimedSendWorks)
{
    using namespace iox::units;
    using namespace std::chrono;

    std::string msg = "ISG rules. And some more                                                                        "
                      "data to have a bit                                                                              "
                      "longer message";

    Duration maxTimeout = 100_ms;
    Duration minTimeoutTolerance = 10_ms;
    Duration maxTimeoutTolerance = 20_ms;

    // send till it breaks
    for (;;)
    {
        auto before = system_clock::now();
        auto result = this->client.timedSend(msg, maxTimeout);
        auto after = system_clock::now();
        if (result.has_error())
        {
            ASSERT_THAT(result.get_error(), Eq(IpcChannelError::TIMEOUT));
            // Do not exceed timeout
            auto timeDiff = units::Duration(after - before);
            EXPECT_LT(timeDiff, maxTimeout + maxTimeoutTolerance);

            // Check if timedSend has blocked for ~maxTimeout and has not returned immediately
            EXPECT_GT(timeDiff, maxTimeout - minTimeoutTolerance);

            break;
        }
    }
}
#endif

TYPED_TEST(IpcChannel_test, TimedReceiveWorks)
{
    using namespace iox::units;
    using namespace std::chrono;

    std::string msg = "very useful text for tranmission";
    Duration timeout = 100_ms;
    Duration minTimeoutTolerance = 10_ms;
    Duration maxTimeoutTolerance = 20_ms;

    this->client.send(msg);

    auto received = this->server.timedReceive(timeout);
    ASSERT_FALSE(received.has_error());

    EXPECT_EQ(received.value(), msg);

    auto before = system_clock::now();
    received = this->server.timedReceive(timeout);
    auto after = system_clock::now();

    ASSERT_TRUE(received.has_error());
    ASSERT_THAT(received.get_error(), Eq(IpcChannelError::TIMEOUT));

    // Do not exceed timeout
    auto timeDiff = units::Duration(after - before);
    EXPECT_LT(timeDiff, timeout + maxTimeoutTolerance);

    // Check if timedReceive has blocked for ~timeout and has not returned immediately
    EXPECT_GT(timeDiff, timeout - minTimeoutTolerance);
}
#endif
<commit_msg>iox-#381 Remove unused variables in IpcChannel_test<commit_after>// Copyright (c) 2019 by Robert Bosch GmbH. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#if !defined(_WIN32)
#include "iceoryx_utils/internal/posix_wrapper/message_queue.hpp"
#include "iceoryx_utils/internal/posix_wrapper/unix_domain_socket.hpp"

#include "test.hpp"

#include <chrono>

using namespace ::testing;
using namespace iox;
using namespace iox::posix;

#if defined(__APPLE__)
using IpcChannelTypes = Types<UnixDomainSocket>;
#else
using IpcChannelTypes = Types<MessageQueue, UnixDomainSocket>;
#endif

constexpr char goodName[] = "channel_test";
constexpr char anotherGoodName[] = "horst";
constexpr char theUnknown[] = "WhoeverYouAre";
constexpr char slashName[] = "/miau";

/// @req
/// @brief This test suite verifies that the abstract interface IpcChannelType is fulfilled by both the UnixDomainSocket
/// class and the MessageQueue class
/// @pre server and client object are allocated and move to the member object of the fixture
/// @post StdErr is capture and outputed to StdCout
/// @note Specific functionality of the underlying implementations of an IpcChannelType are tested in
/// "UnixDomainSocket_test"
template <typename T>
class IpcChannel_test : public Test
{
  public:
    using IpcChannelType = T;

    void SetUp()
    {
        auto serverResult = IpcChannelType::create(
            goodName, IpcChannelMode::BLOCKING, IpcChannelSide::SERVER, MaxMsgSize, MaxMsgNumber);
        ASSERT_THAT(serverResult.has_error(), Eq(false));
        server = std::move(serverResult.value());
        internal::CaptureStderr();

        auto clientResult = IpcChannelType::create(
            goodName, IpcChannelMode::BLOCKING, IpcChannelSide::CLIENT, MaxMsgSize, MaxMsgNumber);
        ASSERT_THAT(clientResult.has_error(), Eq(false));
        client = std::move(clientResult.value());
    }

    void TearDown()
    {
        std::string output = internal::GetCapturedStderr();
        if (Test::HasFailure())
        {
            std::cout << output << std::endl;
        }
    }

    ~IpcChannel_test()
    {
    }

    static const size_t MaxMsgSize;
    static constexpr uint64_t MaxMsgNumber = 10U;
    IpcChannelType server;
    IpcChannelType client;
};

template <typename T>
const size_t IpcChannel_test<T>::MaxMsgSize = IpcChannelType::MAX_MESSAGE_SIZE;
template <typename T>
constexpr uint64_t IpcChannel_test<T>::MaxMsgNumber;

/// we require TYPED_TEST since we support gtest 1.8 for our safety targets
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
TYPED_TEST_CASE(IpcChannel_test, IpcChannelTypes);
#pragma GCC diagnostic pop

TYPED_TEST(IpcChannel_test, CreateWithTooLargeMessageSizeLeadsToError)
{
    auto serverResult = TestFixture::IpcChannelType::create(goodName,
                                                            IpcChannelMode::BLOCKING,
                                                            IpcChannelSide::SERVER,
                                                            TestFixture::MaxMsgSize + 1,
                                                            TestFixture::MaxMsgNumber);
    EXPECT_TRUE(serverResult.has_error());
    ASSERT_THAT(serverResult.get_error(), Eq(IpcChannelError::MAX_MESSAGE_SIZE_EXCEEDED));
}

TYPED_TEST(IpcChannel_test, CreateNoNameLeadsToError)
{
    auto serverResult = TestFixture::IpcChannelType::create("", IpcChannelMode::BLOCKING, IpcChannelSide::SERVER);
    EXPECT_TRUE(serverResult.has_error());
    ASSERT_THAT(serverResult.get_error(), Eq(IpcChannelError::INVALID_CHANNEL_NAME));
}

TYPED_TEST(IpcChannel_test, CreateWithLeadingSlashWorks)
{
    auto serverResult =
        TestFixture::IpcChannelType::create(slashName, IpcChannelMode::BLOCKING, IpcChannelSide::SERVER);
    EXPECT_FALSE(serverResult.has_error());
}

TYPED_TEST(IpcChannel_test, CreateAgainWorks)
{
    // if there is a leftover from a crashed channel, we can create a new one. This is simulated by creating twice
    auto first = TestFixture::IpcChannelType::create(anotherGoodName, IpcChannelMode::BLOCKING, IpcChannelSide::SERVER);
    EXPECT_FALSE(first.has_error());
    auto second =
        TestFixture::IpcChannelType::create(anotherGoodName, IpcChannelMode::BLOCKING, IpcChannelSide::SERVER);
    EXPECT_FALSE(second.has_error());
}

TYPED_TEST(IpcChannel_test, CreateAgainAndEmptyWorks)
{
    using namespace iox::units;
    using namespace std::chrono;

    auto serverResult =
        TestFixture::IpcChannelType::create(anotherGoodName, IpcChannelMode::BLOCKING, IpcChannelSide::SERVER);
    EXPECT_FALSE(serverResult.has_error());
    auto server = std::move(serverResult.value());

    auto clientResult =
        TestFixture::IpcChannelType::create(anotherGoodName, IpcChannelMode::BLOCKING, IpcChannelSide::CLIENT);
    EXPECT_FALSE(clientResult.has_error());
    auto client = std::move(clientResult.value());

    // send and receive as usual
    std::string message = "Hey, I'm talking to you";
    bool sent = client.send(message).has_error();
    EXPECT_FALSE(sent);

    auto receivedMessage = server.receive();
    ASSERT_THAT(receivedMessage.has_error(), Eq(false));
    EXPECT_EQ(message, *receivedMessage);

    // send a message, create the server again and there is no message
    std::string newMessage = "I'm still talking to you brother";
    sent = client.send(newMessage).has_error();
    EXPECT_FALSE(sent);

    auto second =
        TestFixture::IpcChannelType::create(anotherGoodName, IpcChannelMode::BLOCKING, IpcChannelSide::SERVER);
    EXPECT_FALSE(second.has_error());
    server = std::move(second.value());

    Duration timeout = 100_ms;
    auto received = server.timedReceive(timeout);
    ASSERT_TRUE(received.has_error());
    ASSERT_THAT(received.get_error(), Eq(IpcChannelError::TIMEOUT));
}

TYPED_TEST(IpcChannel_test, ClientWithoutServerLeadsToNoSuchChannelError)
{
    auto clientResult =
        TestFixture::IpcChannelType::create(anotherGoodName, IpcChannelMode::BLOCKING, IpcChannelSide::CLIENT);
    EXPECT_TRUE(clientResult.has_error());
    ASSERT_THAT(clientResult.get_error(), Eq(IpcChannelError::NO_SUCH_CHANNEL));
}

TYPED_TEST(IpcChannel_test, NotDestroyingServerLeadsToNonOutdatedClient)
{
    auto serverResult =
        TestFixture::IpcChannelType::create(anotherGoodName, IpcChannelMode::BLOCKING, IpcChannelSide::SERVER);
    EXPECT_FALSE(serverResult.has_error());
    auto server = std::move(serverResult.value());

    auto clientResult =
        TestFixture::IpcChannelType::create(anotherGoodName, IpcChannelMode::BLOCKING, IpcChannelSide::CLIENT);
    EXPECT_FALSE(clientResult.has_error());
    auto client = std::move(clientResult.value());

    auto outdated = client.isOutdated();
    EXPECT_FALSE(outdated.has_error());
    EXPECT_FALSE(outdated.value());
}

TYPED_TEST(IpcChannel_test, DestroyingServerLeadsToOutdatedClient)
{
    if (std::is_same<typename TestFixture::IpcChannelType, UnixDomainSocket>::value)
    {
        // isOutdated cannot be realized for unix domain sockets
        return;
    }

    auto serverResult =
        TestFixture::IpcChannelType::create(anotherGoodName, IpcChannelMode::BLOCKING, IpcChannelSide::SERVER);
    EXPECT_FALSE(serverResult.has_error());
    auto server = std::move(serverResult.value());

    auto clientResult =
        TestFixture::IpcChannelType::create(anotherGoodName, IpcChannelMode::BLOCKING, IpcChannelSide::CLIENT);
    EXPECT_FALSE(clientResult.has_error());
    auto client = std::move(clientResult.value());

    // destroy the server and the client is outdated
    auto dest = server.destroy();
    ASSERT_FALSE(dest.has_error());

    auto outdated = client.isOutdated();
    EXPECT_FALSE(outdated.has_error());
    EXPECT_TRUE(outdated.value());
}

TYPED_TEST(IpcChannel_test, UnlinkExistingOneWorks)
{
    auto first = TestFixture::IpcChannelType::create(anotherGoodName, IpcChannelMode::BLOCKING, IpcChannelSide::SERVER);
    EXPECT_FALSE(first.has_error());
    auto ret = TestFixture::IpcChannelType::unlinkIfExists(anotherGoodName);
    EXPECT_FALSE(ret.has_error());
    EXPECT_TRUE(ret.value());
}

TYPED_TEST(IpcChannel_test, UnlinkNonExistingOneWorks)
{
    auto ret = TestFixture::IpcChannelType::unlinkIfExists(theUnknown);
    EXPECT_FALSE(ret.has_error());
    EXPECT_FALSE(ret.value());
}

TYPED_TEST(IpcChannel_test, SendAndReceiveWorks)
{
    std::string message = "Hey, I'm talking to you";
    bool sent = this->client.send(message).has_error();
    EXPECT_FALSE(sent);

    std::string anotherMessage = "This is a message";
    sent = this->client.send(anotherMessage).has_error();
    EXPECT_FALSE(sent);

    auto receivedMessage = this->server.receive();
    ASSERT_THAT(receivedMessage.has_error(), Eq(false));
    EXPECT_EQ(message, *receivedMessage);

    receivedMessage = this->server.receive();
    ASSERT_THAT(receivedMessage.has_error(), Eq(false));
    EXPECT_EQ(anotherMessage, *receivedMessage);
}

TYPED_TEST(IpcChannel_test, InvalidAfterDestroy)
{
    this->client.destroy();
    ASSERT_FALSE(this->client.isInitialized());
    this->server.destroy();
    ASSERT_FALSE(this->server.isInitialized());
}

TYPED_TEST(IpcChannel_test, SendAfterClientDestroyLeadsToError)
{
    auto dest = this->client.destroy();
    ASSERT_FALSE(dest.has_error());

    std::string message = "Should never be sent";
    bool sendError = this->client.send(message).has_error();
    EXPECT_TRUE(sendError);
}

TYPED_TEST(IpcChannel_test, SendAfterServerDestroyLeadsToError)
{
    if (std::is_same<typename TestFixture::IpcChannelType, MessageQueue>::value)
    {
        // We still can send to the message queue is we destroy the server
        // it would be outdated, this is checked in another test
        return;
    }

    auto dest = this->server.destroy();
    ASSERT_FALSE(dest.has_error());

    std::string message = "Try to send me";
    auto sendResult = this->client.send(message);
    EXPECT_TRUE(sendResult.has_error());
}

TYPED_TEST(IpcChannel_test, ReceiveAfterServerDestroyLeadsToError)
{
    std::string message = "hello world!";
    bool sendError = this->client.send(message).has_error();
    EXPECT_FALSE(sendError);

    auto dest = this->server.destroy();
    ASSERT_FALSE(dest.has_error());

    bool receiveError = this->server.receive().has_error();
    EXPECT_THAT(receiveError, Eq(true));
}

TYPED_TEST(IpcChannel_test, SendMoreThanAllowedLeadsToError)
{
    std::string shortMessage = "Iceoryx rules.";
    ASSERT_THAT(this->client.send(shortMessage).has_error(), Eq(false));

    std::string longMessage(this->server.MAX_MESSAGE_SIZE + 8, 'x');
    ASSERT_THAT(this->client.send(longMessage).has_error(), Eq(true));

    auto receivedMessage = this->server.receive();
    ASSERT_THAT(receivedMessage.has_error(), Eq(false));
    EXPECT_EQ(shortMessage, receivedMessage.value());
}

TYPED_TEST(IpcChannel_test, SendMaxMessageSizeWorks)
{
    std::string message(this->MaxMsgSize - 1, 'x');
    auto clientReturn = this->client.send(message);
    ASSERT_THAT(clientReturn.has_error(), Eq(false));

    auto receivedMessage = this->server.receive();
    ASSERT_THAT(receivedMessage.has_error(), Eq(false));
    EXPECT_EQ(message, receivedMessage.value());
}

TYPED_TEST(IpcChannel_test, wildCreate)
{
    auto result = TestFixture::IpcChannelType::create();
    ASSERT_THAT(result.has_error(), Eq(true));
}

#if !defined(__APPLE__)
TYPED_TEST(IpcChannel_test, TimedSendWorks)
{
    using namespace iox::units;
    using namespace std::chrono;

    std::string msg = "ISG rules. And some more                                                                        "
                      "data to have a bit                                                                              "
                      "longer message";

    Duration maxTimeout = 100_ms;
    Duration minTimeoutTolerance = 10_ms;
    Duration maxTimeoutTolerance = 20_ms;

    // send till it breaks
    for (;;)
    {
        auto before = system_clock::now();
        auto result = this->client.timedSend(msg, maxTimeout);
        auto after = system_clock::now();
        if (result.has_error())
        {
            ASSERT_THAT(result.get_error(), Eq(IpcChannelError::TIMEOUT));
            // Do not exceed timeout
            auto timeDiff = units::Duration(after - before);
            EXPECT_LT(timeDiff, maxTimeout + maxTimeoutTolerance);

            // Check if timedSend has blocked for ~maxTimeout and has not returned immediately
            EXPECT_GT(timeDiff, maxTimeout - minTimeoutTolerance);

            break;
        }
    }
}
#endif

TYPED_TEST(IpcChannel_test, TimedReceiveWorks)
{
    using namespace iox::units;
    using namespace std::chrono;

    std::string msg = "very useful text for tranmission";
    Duration timeout = 100_ms;
    Duration minTimeoutTolerance = 10_ms;
    Duration maxTimeoutTolerance = 20_ms;

    this->client.send(msg);

    auto received = this->server.timedReceive(timeout);
    ASSERT_FALSE(received.has_error());

    EXPECT_EQ(received.value(), msg);

    auto before = system_clock::now();
    received = this->server.timedReceive(timeout);
    auto after = system_clock::now();

    ASSERT_TRUE(received.has_error());
    ASSERT_THAT(received.get_error(), Eq(IpcChannelError::TIMEOUT));

    // Do not exceed timeout
    auto timeDiff = units::Duration(after - before);
    EXPECT_LT(timeDiff, timeout + maxTimeoutTolerance);

    // Check if timedReceive has blocked for ~timeout and has not returned immediately
    EXPECT_GT(timeDiff, timeout - minTimeoutTolerance);
}
#endif
<|endoftext|>


<commit_before>#include <mimosa/format/format.hh>
#include <mimosa/format/print.hh>
#include <mimosa/stream/string-stream.hh>
#include <mimosa/tpl/dict.hh>
#include <mimosa/tpl/include.hh>
#include <mimosa/tpl/list.hh>
#include <mimosa/tpl/template.hh>
#include <mimosa/tpl/value.hh>

#include "torrent-db.hh"
#include "hefur.hh"
#include "stat-handler.hh"
#include "template-factory.hh"
#include "options.hh"

namespace hefur
{
  bool
  StatHandler::handle(mimosa::http::RequestReader &  request,
                      mimosa::http::ResponseWriter & response) const
  {
    auto tpl = TemplateFactory::instance().create("page.html");
    if (!tpl)
      return false;

    auto tpl_body = TemplateFactory::instance().create("stat.html");
    if (!tpl_body)
      return false;

    mimosa::tpl::Dict dict;
    HttpServer::commonDict(dict);
    dict.append("body", tpl_body);
    dict.append("title", "Hefur torrents");
    dict.append("tracker_http", mimosa::format::str(
                  "http://%v:%v/announce", request.host(), request.port()));
    dict.append("tracker_udp", mimosa::format::str(
                  "udp://%v:%v", request.host(), UDP_PORT));

    auto torrents = new mimosa::tpl::List("torrents");
    dict.append(torrents);
    TorrentDb & tdb = Hefur::instance().torrentDb();

    {
      mimosa::SharedMutex::ReadLocker locker(tdb.torrents_lock_);
      uint64_t total_leechers  = 0;
      uint64_t total_seeders   = 0;
      uint64_t total_length    = 0;
      uint64_t total_completed = 0;

      tdb.torrents_.foreach([&] (Torrent *it) {
          auto torrent = new mimosa::tpl::Dict("torrent");
          torrents->append(torrent);
          torrent->append("name", it->name());
          {
            mimosa::stream::StringStream ss;
            mimosa::format::printByteSize(ss, it->length());
            torrent->append("length", ss.str());
          }
          torrent->append("info_sha1", it->key());
          torrent->append("leechers", it->leechers());
          torrent->append("seeders", it->seeders());
          torrent->append("completed", it->completed());

          total_leechers  += it->leechers();
          total_seeders   += it->seeders();
          total_length    += it->length();
          total_completed += it->completed();
        });

      dict.append("total_leechers", total_leechers);
      dict.append("total_seeders", total_seeders);
      dict.append("total_completed", total_completed);
      {
        mimosa::stream::StringStream ss;
        mimosa::format::printByteSize(ss, total_length);
        dict.append("total_length", ss.str());
      }
    }

    tpl->execute(&response, dict);
    return true;
  }
}
<commit_msg>Stat title<commit_after>#include <mimosa/format/format.hh>
#include <mimosa/format/print.hh>
#include <mimosa/stream/string-stream.hh>
#include <mimosa/tpl/dict.hh>
#include <mimosa/tpl/include.hh>
#include <mimosa/tpl/list.hh>
#include <mimosa/tpl/template.hh>
#include <mimosa/tpl/value.hh>

#include "torrent-db.hh"
#include "hefur.hh"
#include "stat-handler.hh"
#include "template-factory.hh"
#include "options.hh"

namespace hefur
{
  bool
  StatHandler::handle(mimosa::http::RequestReader &  request,
                      mimosa::http::ResponseWriter & response) const
  {
    auto tpl = TemplateFactory::instance().create("page.html");
    if (!tpl)
      return false;

    auto tpl_body = TemplateFactory::instance().create("stat.html");
    if (!tpl_body)
      return false;

    mimosa::tpl::Dict dict;
    HttpServer::commonDict(dict);
    dict.append("body", tpl_body);
    dict.append("title", "Torrents");
    dict.append("tracker_http", mimosa::format::str(
                  "http://%v:%v/announce", request.host(), request.port()));
    dict.append("tracker_udp", mimosa::format::str(
                  "udp://%v:%v", request.host(), UDP_PORT));

    auto torrents = new mimosa::tpl::List("torrents");
    dict.append(torrents);
    TorrentDb & tdb = Hefur::instance().torrentDb();

    {
      mimosa::SharedMutex::ReadLocker locker(tdb.torrents_lock_);
      uint64_t total_leechers  = 0;
      uint64_t total_seeders   = 0;
      uint64_t total_length    = 0;
      uint64_t total_completed = 0;

      tdb.torrents_.foreach([&] (Torrent *it) {
          auto torrent = new mimosa::tpl::Dict("torrent");
          torrents->append(torrent);
          torrent->append("name", it->name());
          {
            mimosa::stream::StringStream ss;
            mimosa::format::printByteSize(ss, it->length());
            torrent->append("length", ss.str());
          }
          torrent->append("info_sha1", it->key());
          torrent->append("leechers", it->leechers());
          torrent->append("seeders", it->seeders());
          torrent->append("completed", it->completed());

          total_leechers  += it->leechers();
          total_seeders   += it->seeders();
          total_length    += it->length();
          total_completed += it->completed();
        });

      dict.append("total_leechers", total_leechers);
      dict.append("total_seeders", total_seeders);
      dict.append("total_completed", total_completed);
      {
        mimosa::stream::StringStream ss;
        mimosa::format::printByteSize(ss, total_length);
        dict.append("total_length", ss.str());
      }
    }

    tpl->execute(&response, dict);
    return true;
  }
}
<|endoftext|>


<commit_before>/*
	This file is part of cpp-ethereum.

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

	cpp-ethereum is distributed in the hope that it will be useful,
	but WITHOUT ANY WARRANTY; without even the implied warranty of
	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
	GNU General Public License for more details.

	You should have received a copy of the GNU General Public License
	along with cpp-ethereum.  If not, see <http://www.gnu.org/licenses/>.
*/
/** @file CommonEth.cpp
 * @author Gav Wood <i@gavwood.com>
 * @date 2014
 */

#include "CommonEth.h"
#include <random>
#include <libdevcrypto/SHA3.h>
#include "Exceptions.h"
using namespace std;
using namespace dev;
using namespace dev::eth;

namespace dev
{
namespace eth
{

const unsigned c_protocolVersion = 53;
const unsigned c_databaseVersion = 5;

template <size_t n> constexpr u256 eth_unit() { return eth_unit<n-1>() * u256(1000); }
template <> constexpr u256 eth_unit<0>() { return u256(1); }

static const vector<pair<u256, string>> g_units =
{
	{eth_unit<18>(), "Uether"},
	{eth_unit<17>(), "Vether"},
	{eth_unit<16>(), "Dether"},
	{eth_unit<15>(), "Nether"},
	{eth_unit<14>(), "Yether"},
	{eth_unit<13>(), "Zether"},
	{eth_unit<12>(), "Eether"},
	{eth_unit<11>(), "Pether"},
	{eth_unit<10>(), "Tether"},
	{eth_unit<9>(), "Gether"},
	{eth_unit<8>(), "Mether"},
	{eth_unit<7>(), "grand"},
	{eth_unit<6>(), "ether"},
	{eth_unit<5>(), "finney"},
	{eth_unit<4>(), "szabo"},
	{eth_unit<3>(), "Gwei"},
	{eth_unit<2>(), "Mwei"},
	{eth_unit<1>(), "Kwei"},
	{eth_unit<0>(), "wei"}
};

vector<pair<u256, string>> const& units()
{
	return g_units;
}

std::string formatBalance(bigint const& _b)
{
	ostringstream ret;
	u256 b;
	if (_b < 0)
	{
		ret << "-";
		b = (u256)-_b;
	}
	else
		b = (u256)_b;

	if (b > g_units[0].first * 10000)
	{
		ret << (b / g_units[0].first) << " " << g_units[0].second;
		return ret.str();
	}
	ret << setprecision(5);
	for (auto const& i: g_units)
		if (i.first != 1 && b >= i.first * 100)
		{
			ret << (double(b / (i.first / 1000)) / 1000.0) << " " << i.second;
			return ret.str();
		}
	ret << b << " wei";
	return ret.str();
}

}}
<commit_msg>Cleanups for ether denominations.<commit_after>/*
	This file is part of cpp-ethereum.

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

	cpp-ethereum is distributed in the hope that it will be useful,
	but WITHOUT ANY WARRANTY; without even the implied warranty of
	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
	GNU General Public License for more details.

	You should have received a copy of the GNU General Public License
	along with cpp-ethereum.  If not, see <http://www.gnu.org/licenses/>.
*/
/** @file CommonEth.cpp
 * @author Gav Wood <i@gavwood.com>
 * @date 2014
 */

#include "CommonEth.h"
#include <random>
#include <libdevcrypto/SHA3.h>
#include "Exceptions.h"
using namespace std;
using namespace dev;
using namespace dev::eth;

namespace dev
{
namespace eth
{

const unsigned c_protocolVersion = 53;
const unsigned c_databaseVersion = 5;

template <size_t n> constexpr u256 exp10()
{
	return exp10<n - 1>() * u256(10);
}

template <> constexpr u256 exp10<0>()
{
	return u256(1);
}

vector<pair<u256, string>> const& units()
{
	static const vector<pair<u256, string>> s_units =
	{
		{exp10<54>(), "Uether"},
		{exp10<51>(), "Vether"},
		{exp10<48>(), "Dether"},
		{exp10<45>(), "Nether"},
		{exp10<42>(), "Yether"},
		{exp10<39>(), "Zether"},
		{exp10<36>(), "Eether"},
		{exp10<33>(), "Pether"},
		{exp10<30>(), "Tether"},
		{exp10<27>(), "Gether"},
		{exp10<24>(), "Mether"},
		{exp10<21>(), "grand"},
		{exp10<18>(), "ether"},
		{exp10<15>(), "finney"},
		{exp10<12>(), "szabo"},
		{exp10<9>(), "Gwei"},
		{exp10<6>(), "Mwei"},
		{exp10<3>(), "Kwei"},
		{exp10<0>(), "wei"}
	};

	return s_units;
}

std::string formatBalance(bigint const& _b)
{
	ostringstream ret;
	u256 b;
	if (_b < 0)
	{
		ret << "-";
		b = (u256)-_b;
	}
	else
		b = (u256)_b;

	if (b > units()[0].first * 10000)
	{
		ret << (b / units()[0].first) << " " << units()[0].second;
		return ret.str();
	}
	ret << setprecision(5);
	for (auto const& i: units())
		if (i.first != 1 && b >= i.first * 100)
		{
			ret << (double(b / (i.first / 1000)) / 1000.0) << " " << i.second;
			return ret.str();
		}
	ret << b << " wei";
	return ret.str();
}

}}
<|endoftext|>


<commit_before>#pragma once
#ifndef __VALIJSON_CONSTRAINTS_CONSTRAINT_VISITOR_HPP
#define __VALIJSON_CONSTRAINTS_CONSTRAINT_VISITOR_HPP

namespace valijson {
namespace constraints {

class AllOfConstraint;
class AnyOfConstraint;
class DependenciesConstraint;
class EnumConstraint;
class LinearItemsConstraint;
class MaxItemsConstraint;
class MaximumConstraint;
class MaxLengthConstraint;
class MaxPropertiesConstraint;
class MinItemsConstraint;
class MinimumConstraint;
class MinLengthConstraint;
class MinPropertiesConstraint;
class MultipleOfDoubleConstraint;
class MultipleOfIntConstraint;
class NotConstraint;
class OneOfConstraint;
class PatternConstraint;
class PolyConstraint;
class PropertiesConstraint;
class RequiredConstraint;
class SingularItemsConstraint;
class TypeConstraint;
class UniqueItemsConstraint;

/// Interface to allow usage of the visitor pattern with Constraints
class ConstraintVisitor
{
protected:

    // Shorten type names for derived classes outside of this namespace
    typedef constraints::AllOfConstraint AllOfConstraint;
    typedef constraints::AnyOfConstraint AnyOfConstraint;
    typedef constraints::DependenciesConstraint DependenciesConstraint;
    typedef constraints::EnumConstraint EnumConstraint;
    typedef constraints::LinearItemsConstraint LinearItemsConstraint;
    typedef constraints::MaximumConstraint MaximumConstraint;
    typedef constraints::MaxItemsConstraint MaxItemsConstraint;
    typedef constraints::MaxLengthConstraint MaxLengthConstraint;
    typedef constraints::MaxPropertiesConstraint MaxPropertiesConstraint;
    typedef constraints::MinimumConstraint MinimumConstraint;
    typedef constraints::MinItemsConstraint MinItemsConstraint;
    typedef constraints::MinLengthConstraint MinLengthConstraint;
    typedef constraints::MinPropertiesConstraint MinPropertiesConstraint;
    typedef constraints::MultipleOfDoubleConstraint MultipleOfDoubleConstraint;
    typedef constraints::MultipleOfIntConstraint MultipleOfIntConstraint;
    typedef constraints::NotConstraint NotConstraint;
    typedef constraints::OneOfConstraint OneOfConstraint;
    typedef constraints::PatternConstraint PatternConstraint;
    typedef constraints::PolyConstraint PolyConstraint;
    typedef constraints::PropertiesConstraint PropertiesConstraint;
    typedef constraints::RequiredConstraint RequiredConstraint;
    typedef constraints::SingularItemsConstraint SingularItemsConstraint;
    typedef constraints::TypeConstraint TypeConstraint;
    typedef constraints::UniqueItemsConstraint UniqueItemsConstraint;

public:

    virtual bool visit(const AllOfConstraint &) = 0;
    virtual bool visit(const AnyOfConstraint &) = 0;
    virtual bool visit(const DependenciesConstraint &) = 0;
    virtual bool visit(const EnumConstraint &) = 0;
    virtual bool visit(const LinearItemsConstraint &) = 0;
    virtual bool visit(const MaximumConstraint &) = 0;
    virtual bool visit(const MaxItemsConstraint &) = 0;
    virtual bool visit(const MaxLengthConstraint &) = 0;
    virtual bool visit(const MaxPropertiesConstraint &) = 0;
    virtual bool visit(const MinimumConstraint &) = 0;
    virtual bool visit(const MinItemsConstraint &) = 0;
    virtual bool visit(const MinLengthConstraint &) = 0;
    virtual bool visit(const MinPropertiesConstraint &) = 0;
    virtual bool visit(const MultipleOfDoubleConstraint &) = 0;
    virtual bool visit(const MultipleOfIntConstraint &) = 0;
    virtual bool visit(const NotConstraint &) = 0;
    virtual bool visit(const OneOfConstraint &) = 0;
    virtual bool visit(const PatternConstraint &) = 0;
    virtual bool visit(const PolyConstraint &) = 0;
    virtual bool visit(const PropertiesConstraint &) = 0;
    virtual bool visit(const RequiredConstraint &) = 0;
    virtual bool visit(const SingularItemsConstraint &) = 0;
    virtual bool visit(const TypeConstraint &) = 0;
    virtual bool visit(const UniqueItemsConstraint &) = 0;
};

}  // namespace constraints
}  // namespace valijson

#endif
<commit_msg>Added an empty virtual destructor to the ConstraintVisitor class.<commit_after>#pragma once
#ifndef __VALIJSON_CONSTRAINTS_CONSTRAINT_VISITOR_HPP
#define __VALIJSON_CONSTRAINTS_CONSTRAINT_VISITOR_HPP

namespace valijson {
namespace constraints {

class AllOfConstraint;
class AnyOfConstraint;
class DependenciesConstraint;
class EnumConstraint;
class LinearItemsConstraint;
class MaxItemsConstraint;
class MaximumConstraint;
class MaxLengthConstraint;
class MaxPropertiesConstraint;
class MinItemsConstraint;
class MinimumConstraint;
class MinLengthConstraint;
class MinPropertiesConstraint;
class MultipleOfDoubleConstraint;
class MultipleOfIntConstraint;
class NotConstraint;
class OneOfConstraint;
class PatternConstraint;
class PolyConstraint;
class PropertiesConstraint;
class RequiredConstraint;
class SingularItemsConstraint;
class TypeConstraint;
class UniqueItemsConstraint;

/// Interface to allow usage of the visitor pattern with Constraints
class ConstraintVisitor
{
protected:
    virtual ~ConstraintVisitor() {}

    // Shorten type names for derived classes outside of this namespace
    typedef constraints::AllOfConstraint AllOfConstraint;
    typedef constraints::AnyOfConstraint AnyOfConstraint;
    typedef constraints::DependenciesConstraint DependenciesConstraint;
    typedef constraints::EnumConstraint EnumConstraint;
    typedef constraints::LinearItemsConstraint LinearItemsConstraint;
    typedef constraints::MaximumConstraint MaximumConstraint;
    typedef constraints::MaxItemsConstraint MaxItemsConstraint;
    typedef constraints::MaxLengthConstraint MaxLengthConstraint;
    typedef constraints::MaxPropertiesConstraint MaxPropertiesConstraint;
    typedef constraints::MinimumConstraint MinimumConstraint;
    typedef constraints::MinItemsConstraint MinItemsConstraint;
    typedef constraints::MinLengthConstraint MinLengthConstraint;
    typedef constraints::MinPropertiesConstraint MinPropertiesConstraint;
    typedef constraints::MultipleOfDoubleConstraint MultipleOfDoubleConstraint;
    typedef constraints::MultipleOfIntConstraint MultipleOfIntConstraint;
    typedef constraints::NotConstraint NotConstraint;
    typedef constraints::OneOfConstraint OneOfConstraint;
    typedef constraints::PatternConstraint PatternConstraint;
    typedef constraints::PolyConstraint PolyConstraint;
    typedef constraints::PropertiesConstraint PropertiesConstraint;
    typedef constraints::RequiredConstraint RequiredConstraint;
    typedef constraints::SingularItemsConstraint SingularItemsConstraint;
    typedef constraints::TypeConstraint TypeConstraint;
    typedef constraints::UniqueItemsConstraint UniqueItemsConstraint;

public:

    virtual bool visit(const AllOfConstraint &) = 0;
    virtual bool visit(const AnyOfConstraint &) = 0;
    virtual bool visit(const DependenciesConstraint &) = 0;
    virtual bool visit(const EnumConstraint &) = 0;
    virtual bool visit(const LinearItemsConstraint &) = 0;
    virtual bool visit(const MaximumConstraint &) = 0;
    virtual bool visit(const MaxItemsConstraint &) = 0;
    virtual bool visit(const MaxLengthConstraint &) = 0;
    virtual bool visit(const MaxPropertiesConstraint &) = 0;
    virtual bool visit(const MinimumConstraint &) = 0;
    virtual bool visit(const MinItemsConstraint &) = 0;
    virtual bool visit(const MinLengthConstraint &) = 0;
    virtual bool visit(const MinPropertiesConstraint &) = 0;
    virtual bool visit(const MultipleOfDoubleConstraint &) = 0;
    virtual bool visit(const MultipleOfIntConstraint &) = 0;
    virtual bool visit(const NotConstraint &) = 0;
    virtual bool visit(const OneOfConstraint &) = 0;
    virtual bool visit(const PatternConstraint &) = 0;
    virtual bool visit(const PolyConstraint &) = 0;
    virtual bool visit(const PropertiesConstraint &) = 0;
    virtual bool visit(const RequiredConstraint &) = 0;
    virtual bool visit(const SingularItemsConstraint &) = 0;
    virtual bool visit(const TypeConstraint &) = 0;
    virtual bool visit(const UniqueItemsConstraint &) = 0;
};

}  // namespace constraints
}  // namespace valijson

#endif
<|endoftext|>