<commit_before>#include "omp.h"

 inline
 kth_cv_omp::kth_cv_omp(const std::string in_path,
		const std::string in_actionNames,
		const field<std::string> in_all_people,
		const int in_scale_factor,
		const int in_shift,
		const int in_scene, //only for kth
		const int in_segment_length,
		const int in_dim
 ):path(in_path), actionNames(in_actionNames), all_people (in_all_people), scale_factor(in_scale_factor), shift(in_shift), total_scenes(in_scene), segment_length(in_segment_length), dim(in_dim)
 {
   actions.load( actionNames );

 }

 // Log-Euclidean Distance
 inline
 void
 kth_cv_omp::logEucl()
 {

   int n_actions = actions.n_rows;
   int n_peo =  all_people.n_rows;

   float acc;
   acc = 0;

   int n_test = n_peo*n_actions*total_scenes - 1; // - person13_handclapping_d3
   vec real_labels;
   vec est_labels;
   field<std::string> test_video_list(n_test);

   real_labels.zeros(n_test);
   est_labels.zeros(n_test);

   int k=0;

   for (int sc = 1; sc<=total_scenes; ++sc) //scene
   {
     for (int pe = 0; pe< n_peo; ++pe)
     {
       for (int act=0; act<n_actions; ++act)
       {
	 if(  !( ( sc==3 && pe==12) && act==1) ) //person13_handclapping_d3
	 {

	   //load number of segments

	   vec total_seg;
	   int num_s;
	   std::stringstream load_sub_path;
	   std::stringstream load_num_seg;

	   load_sub_path  << path << "/kth-cov-mat/sc" << sc << "/scale" << scale_factor << "-shift"<< shift ;
	   load_num_seg << load_sub_path.str() << "/num_seg_"<< all_people (pe) << "_" << actions(act) << "_dim" << dim  << ".dat";
	   total_seg.load( load_num_seg.str());
	   num_s = total_seg(0);
	   uvec  est_lab_segm;
	   est_lab_segm.zeros(num_s);
	   vec count = zeros<vec>( n_actions );

	   for (int s=0; s<num_s; ++s)
	   {
	     std::stringstream load_cov_seg;
	     load_cov_seg << load_sub_path.str() << "/LogMcov_seg" << s << "_"<< all_people (pe) << "_" << actions(act) << "_dim" << dim  << ".h5";

	     //cout << "LogMcov_seg" << s << "_"<< all_people (pe) << "_" << actions(act) << "_dim" << dim  << ".h5" << endl;
	     //debe devolver el est_labe de ese segmento
	     est_lab_segm(s) = logEucl_one_seg_est_lab( pe, load_sub_path.str(),  load_cov_seg.str());
	     count( est_lab_segm(s) )++;
	     //getchar();
	   }

	   uword  index_video;
	   double max_val = count.max(index_video);
	   //est_lab_segm.t().print("est_lab_segm");
	   cout << "This video is " << actions(act) << " and was classified as class: " << actions(index_video ) << endl;

	   real_labels(k) = act;
	   est_labels(k) = index_video;
	   test_video_list(k) = load_sub_path.str();

	   real_labels.save("Log_Eucl_real_labels.dat", raw_ascii);
	   est_labels.save("Log_Eucl_est_labels.dat", raw_ascii);
	   test_video_list.save("Log_Eucl_test_video_list.dat", raw_ascii);
	   k++;

	   if (index_video == act)  {
	     acc++;

	   }

	   //getchar();
	 }
       }

     }
   }

   cout << "Performance: " << acc*100/n_test << " %" << endl;

 }

 inline
 uword
 kth_cv_omp::logEucl_one_seg_est_lab(int pe_test, std::string load_sub_path, std::string segm_name)
 {
   //wall_clock timer;
   //timer.tic();

   mat logMtest_cov;
   logMtest_cov.load(segm_name);

   int n_actions = actions.n_rows;
   int n_peo =  all_people.n_rows;

   double dist, tmp_dist;
   tmp_dist = datum::inf;

   double est_lab;
   //cout << "Comparing with person ";

   for (int pe_tr = 0; pe_tr< n_peo; ++pe_tr)
   {
     if (pe_tr!= pe_test)
     {

       //cout << " " << all_people (pe_tr);

       for (int sc = 1; sc<=total_scenes; ++sc) //scene
       {
	 for (int act=0; act<n_actions; ++act)
	 {
	   vec total_seg;
	   int num_s;
	   std::stringstream load_num_seg;
	   load_num_seg << load_sub_path << "/num_seg_"<< all_people (pe_tr) << "_" << actions(act) << "_dim" << dim  << ".dat";
	   total_seg.load( load_num_seg.str());
	   num_s = total_seg(0);

	   vec dist_segm_s<zeros> (num_s);

	   #pragma omp for
	   for (int s_tr=0; s_tr<num_s; ++s_tr)
	   {
	     std::stringstream load_cov_seg_tr;
	     load_cov_seg_tr << load_sub_path << "/LogMcov_seg" << s_tr << "_" << all_people (pe_tr) << "_" << actions(act) << "_dim" << dim  << ".h5";

	     //cout << "Comparing with cov_seg" << s_tr << "_"<< all_people (pe_tr) << "_" << actions(act) << "_dim" << dim  << ".h5" << endl;
	     mat logMtrain_cov;
	     logMtrain_cov.load( load_cov_seg_tr.str() );

	     //logMtest_cov.print("logMtest_cov");
	     //train_cov.print("train_cov");

	     dist_segm_s(s_tr) = norm( logMtest_cov - logMtrain_cov, "fro");

	     //cout << "dist " << dis
	     //cout << "Press a key" << endl;
	     //getchar();
	   }
	   #pragma omp barrier
	   dist_segm_s.t().print("dist_segm_s");
	   getchar();
	 }
       }
     }
   }

   //double n = timer.toc();
   //cout << "number of seconds: " << n << endl;
   //cout << " est_lab "<< est_lab << endl << endl;
   //getchar();
   return est_lab;

 }

 //DO IT
 // Stein Divergence

 inline
 void
 kth_cv_omp::SteinDiv()
 {

   int n_actions = actions.n_rows;
   int n_peo =  all_people.n_rows;

   float acc;
   acc = 0;

      int n_test = n_peo*n_actions*total_scenes - 1; // - person13_handclapping_d3

   vec real_labels;
   vec est_labels;
   field<std::string> test_video_list(n_test);

   real_labels.zeros(n_test);
   est_labels.zeros(n_test);

   int k=0;

   for (int sc = 1; sc<=total_scenes; ++sc) //scene
   {
     for (int pe = 0; pe< n_peo; ++pe)
     {
       for (int act=0; act<n_actions; ++act)
       {
	 if(  !( ( sc==3 && pe==12) && act==1) ) //person13_handclapping_d3
	 {
	   //load number of segments

	   vec total_seg;
	   int num_s;
	   std::stringstream load_sub_path;
	   std::stringstream load_num_seg;

	   load_sub_path  << path << "/kth-cov-mat/sc" << sc << "/scale" << scale_factor << "-shift"<< shift ;
	   load_num_seg << load_sub_path.str() << "/num_seg_"<< all_people (pe) << "_" << actions(act) << "_dim" << dim  << ".dat";
	   total_seg.load( load_num_seg.str());
	   num_s = total_seg(0);
	   uvec  est_lab_segm;
	   est_lab_segm.zeros(num_s);
	   vec count = zeros<vec>( n_actions );

	   for (int s=0; s<num_s; ++s)
	   {
	     std::stringstream load_cov_seg;
	     load_cov_seg << load_sub_path.str() << "/cov_seg" << s << "_"<< all_people (pe) << "_" << actions(act) << "_dim" << dim  << ".h5";

	     est_lab_segm(s) = SteinDiv_one_seg_est_lab( pe, load_sub_path.str(),  load_cov_seg.str());
	     count( est_lab_segm(s) )++;
	     //getchar();
	   }

	   uword  index_video;
	   double max_val = count.max(index_video);
	   //est_lab_segm.t().print("est_lab_segm");
	   cout << "This video is " << actions(act) << " and was classified as class: " << actions(index_video ) << endl;

	   real_labels(k) = act;
	   est_labels(k) = index_video;
	   test_video_list(k) = load_sub_path.str();

	   real_labels.save("Stein_div_real_labels.dat", raw_ascii);
	   est_labels.save("Stein_div__est_labels.dat", raw_ascii);
	   test_video_list.save("Stein_div_test_video_list.dat", raw_ascii);
	   k++;

	   if (index_video == act)  {
	     acc++;

	   }

	   //getchar();
	 }

       }
     }
   }

   cout << "Performance: " << acc*100/n_test << " %" << endl;

 }

 //DO IT!!!!!!!!!
 inline
 uword
 kth_cv_omp::SteinDiv_one_seg_est_lab(int pe_test, std::string load_sub_path, std::string segm_name)
 {
   //wall_clock timer;
   //timer.tic();

   mat test_cov;
   test_cov.load(segm_name);

   int n_actions = actions.n_rows;
   int n_peo =  all_people.n_rows;

   double dist_stein, tmp_dist;
   tmp_dist = datum::inf;

   double est_lab;
   //cout << "Comparing with person ";

   for (int pe_tr = 0; pe_tr< n_peo; ++pe_tr)
   {
     if (pe_tr!= pe_test)
     {

       //cout << " " << all_people (pe_tr);

       for (int sc = 1; sc<=total_scenes; ++sc) //scene
       {
	 for (int act=0; act<n_actions; ++act)
	 {
	   vec total_seg;
	   int num_s;
	   std::stringstream load_num_seg;
	   load_num_seg << load_sub_path << "/num_seg_"<< all_people (pe_tr) << "_" << actions(act) << "_dim" << dim  << ".dat";
	   total_seg.load( load_num_seg.str());
	   num_s = total_seg(0);

	   for (int s_tr=0; s_tr<num_s; ++s_tr)
	   {
	     std::stringstream load_cov_seg_tr;
	     load_cov_seg_tr << load_sub_path << "/cov_seg" << s_tr << "_" << all_people (pe_tr) << "_" << actions(act) << "_dim" << dim  << ".h5";

	     mat train_cov;
	     train_cov.load( load_cov_seg_tr.str() );

	     //Esto vienen de PartI4. No recuerdo mas :(
	     double det_op1 = det( diagmat( (test_cov + train_cov)/2 ) );
	     double det_op2 = det( diagmat( ( test_cov%train_cov ) ) );
	     dist_stein =  log( det_op1 ) - 0.5*log( det_op2 ) ;

	     //dist_stein = norm( logMtest_cov - logMtrain_cov, "fro");

	     //cout << "dist " << dist << endl;

	     if (dist_stein < tmp_dist)
	     {
	       //cout << "Es menor" << endl;
	       tmp_dist = dist_stein;
	       est_lab = act;
	     }
	     //cout << "Press a key" << endl;
	     //getchar();
	   }
	 }
       }
     }
   }

   //double n = timer.toc();
   //cout << "number of seconds: " << n << endl;
   //cout << " est_lab "<< est_lab << endl << endl;
   //getchar();
   return est_lab;

 }

 <commit_msg>try oPenMP<commit_after>#include "omp.h"

 inline
 kth_cv_omp::kth_cv_omp(const std::string in_path,
		const std::string in_actionNames,
		const field<std::string> in_all_people,
		const int in_scale_factor,
		const int in_shift,
		const int in_scene, //only for kth
		const int in_segment_length,
		const int in_dim
 ):path(in_path), actionNames(in_actionNames), all_people (in_all_people), scale_factor(in_scale_factor), shift(in_shift), total_scenes(in_scene), segment_length(in_segment_length), dim(in_dim)
 {
   actions.load( actionNames );

 }

 // Log-Euclidean Distance
 inline
 void
 kth_cv_omp::logEucl()
 {

   int n_actions = actions.n_rows;
   int n_peo =  all_people.n_rows;

   float acc;
   acc = 0;

   int n_test = n_peo*n_actions*total_scenes - 1; // - person13_handclapping_d3
   vec real_labels;
   vec est_labels;
   field<std::string> test_video_list(n_test);

   real_labels.zeros(n_test);
   est_labels.zeros(n_test);

   int k=0;

   for (int sc = 1; sc<=total_scenes; ++sc) //scene
   {
     for (int pe = 0; pe< n_peo; ++pe)
     {
       for (int act=0; act<n_actions; ++act)
       {
	 if(  !( ( sc==3 && pe==12) && act==1) ) //person13_handclapping_d3
	 {

	   //load number of segments

	   vec total_seg;
	   int num_s;
	   std::stringstream load_sub_path;
	   std::stringstream load_num_seg;

	   load_sub_path  << path << "/kth-cov-mat/sc" << sc << "/scale" << scale_factor << "-shift"<< shift ;
	   load_num_seg << load_sub_path.str() << "/num_seg_"<< all_people (pe) << "_" << actions(act) << "_dim" << dim  << ".dat";
	   total_seg.load( load_num_seg.str());
	   num_s = total_seg(0);
	   uvec  est_lab_segm;
	   est_lab_segm.zeros(num_s);
	   vec count = zeros<vec>( n_actions );

	   for (int s=0; s<num_s; ++s)
	   {
	     std::stringstream load_cov_seg;
	     load_cov_seg << load_sub_path.str() << "/LogMcov_seg" << s << "_"<< all_people (pe) << "_" << actions(act) << "_dim" << dim  << ".h5";

	     //cout << "LogMcov_seg" << s << "_"<< all_people (pe) << "_" << actions(act) << "_dim" << dim  << ".h5" << endl;
	     //debe devolver el est_labe de ese segmento
	     est_lab_segm(s) = logEucl_one_seg_est_lab( pe, load_sub_path.str(),  load_cov_seg.str());
	     count( est_lab_segm(s) )++;
	     //getchar();
	   }

	   uword  index_video;
	   double max_val = count.max(index_video);
	   //est_lab_segm.t().print("est_lab_segm");
	   cout << "This video is " << actions(act) << " and was classified as class: " << actions(index_video ) << endl;

	   real_labels(k) = act;
	   est_labels(k) = index_video;
	   test_video_list(k) = load_sub_path.str();

	   real_labels.save("Log_Eucl_real_labels.dat", raw_ascii);
	   est_labels.save("Log_Eucl_est_labels.dat", raw_ascii);
	   test_video_list.save("Log_Eucl_test_video_list.dat", raw_ascii);
	   k++;

	   if (index_video == act)  {
	     acc++;

	   }

	   //getchar();
	 }
       }

     }
   }

   cout << "Performance: " << acc*100/n_test << " %" << endl;

 }

 inline
 uword
 kth_cv_omp::logEucl_one_seg_est_lab(int pe_test, std::string load_sub_path, std::string segm_name)
 {
   //wall_clock timer;
   //timer.tic();

   mat logMtest_cov;
   logMtest_cov.load(segm_name);

   int n_actions = actions.n_rows;
   int n_peo =  all_people.n_rows;

   double dist, tmp_dist;
   tmp_dist = datum::inf;

   double est_lab;
   //cout << "Comparing with person ";

   for (int pe_tr = 0; pe_tr< n_peo; ++pe_tr)
   {
     if (pe_tr!= pe_test)
     {

       //cout << " " << all_people (pe_tr);

       for (int sc = 1; sc<=total_scenes; ++sc) //scene
       {
	 for (int act=0; act<n_actions; ++act)
	 {
	   vec total_seg;
	   int num_s;
	   std::stringstream load_num_seg;
	   load_num_seg << load_sub_path << "/num_seg_"<< all_people (pe_tr) << "_" << actions(act) << "_dim" << dim  << ".dat";
	   total_seg.load( load_num_seg.str());
	   num_s = total_seg(0);

	   vec dist_segm_s<zeros> (num_s);

	   #pragma omp for
	   for (int s_tr=0; s_tr<num_s; ++s_tr)
	   {
	     std::stringstream load_cov_seg_tr;
	     load_cov_seg_tr << load_sub_path << "/LogMcov_seg" << s_tr << "_" << all_people (pe_tr) << "_" << actions(act) << "_dim" << dim  << ".h5";

	     //cout << "Comparing with cov_seg" << s_tr << "_"<< all_people (pe_tr) << "_" << actions(act) << "_dim" << dim  << ".h5" << endl;
	     mat logMtrain_cov;
	     logMtrain_cov.load( load_cov_seg_tr.str() );

	     //logMtest_cov.print("logMtest_cov");
	     //train_cov.print("train_cov");

	     dist_segm_s(s_tr) = norm( logMtest_cov - logMtrain_cov, "fro");

	     //cout << "dist " << dis
	     //cout << "Press a key" << endl;
	     //getchar();
	   }
	   #pragma omp barrier

	   dist_segm_s.t().print("dist_segm_s");
	   getchar();
	 }
       }
     }
   }

   //double n = timer.toc();
   //cout << "number of seconds: " << n << endl;
   //cout << " est_lab "<< est_lab << endl << endl;
   //getchar();
   return est_lab;

 }

 //DO IT
 // Stein Divergence

 inline
 void
 kth_cv_omp::SteinDiv()
 {

   int n_actions = actions.n_rows;
   int n_peo =  all_people.n_rows;

   float acc;
   acc = 0;

      int n_test = n_peo*n_actions*total_scenes - 1; // - person13_handclapping_d3

   vec real_labels;
   vec est_labels;
   field<std::string> test_video_list(n_test);

   real_labels.zeros(n_test);
   est_labels.zeros(n_test);

   int k=0;

   for (int sc = 1; sc<=total_scenes; ++sc) //scene
   {
     for (int pe = 0; pe< n_peo; ++pe)
     {
       for (int act=0; act<n_actions; ++act)
       {
	 if(  !( ( sc==3 && pe==12) && act==1) ) //person13_handclapping_d3
	 {
	   //load number of segments

	   vec total_seg;
	   int num_s;
	   std::stringstream load_sub_path;
	   std::stringstream load_num_seg;

	   load_sub_path  << path << "/kth-cov-mat/sc" << sc << "/scale" << scale_factor << "-shift"<< shift ;
	   load_num_seg << load_sub_path.str() << "/num_seg_"<< all_people (pe) << "_" << actions(act) << "_dim" << dim  << ".dat";
	   total_seg.load( load_num_seg.str());
	   num_s = total_seg(0);
	   uvec  est_lab_segm;
	   est_lab_segm.zeros(num_s);
	   vec count = zeros<vec>( n_actions );

	   for (int s=0; s<num_s; ++s)
	   {
	     std::stringstream load_cov_seg;
	     load_cov_seg << load_sub_path.str() << "/cov_seg" << s << "_"<< all_people (pe) << "_" << actions(act) << "_dim" << dim  << ".h5";

	     est_lab_segm(s) = SteinDiv_one_seg_est_lab( pe, load_sub_path.str(),  load_cov_seg.str());
	     count( est_lab_segm(s) )++;
	     //getchar();
	   }

	   uword  index_video;
	   double max_val = count.max(index_video);
	   //est_lab_segm.t().print("est_lab_segm");
	   cout << "This video is " << actions(act) << " and was classified as class: " << actions(index_video ) << endl;

	   real_labels(k) = act;
	   est_labels(k) = index_video;
	   test_video_list(k) = load_sub_path.str();

	   real_labels.save("Stein_div_real_labels.dat", raw_ascii);
	   est_labels.save("Stein_div__est_labels.dat", raw_ascii);
	   test_video_list.save("Stein_div_test_video_list.dat", raw_ascii);
	   k++;

	   if (index_video == act)  {
	     acc++;

	   }

	   //getchar();
	 }

       }
     }
   }

   cout << "Performance: " << acc*100/n_test << " %" << endl;

 }

 //DO IT!!!!!!!!!
 inline
 uword
 kth_cv_omp::SteinDiv_one_seg_est_lab(int pe_test, std::string load_sub_path, std::string segm_name)
 {
   //wall_clock timer;
   //timer.tic();

   mat test_cov;
   test_cov.load(segm_name);

   int n_actions = actions.n_rows;
   int n_peo =  all_people.n_rows;

   double dist_stein, tmp_dist;
   tmp_dist = datum::inf;

   double est_lab;
   //cout << "Comparing with person ";

   for (int pe_tr = 0; pe_tr< n_peo; ++pe_tr)
   {
     if (pe_tr!= pe_test)
     {

       //cout << " " << all_people (pe_tr);

       for (int sc = 1; sc<=total_scenes; ++sc) //scene
       {
	 for (int act=0; act<n_actions; ++act)
	 {
	   vec total_seg;
	   int num_s;
	   std::stringstream load_num_seg;
	   load_num_seg << load_sub_path << "/num_seg_"<< all_people (pe_tr) << "_" << actions(act) << "_dim" << dim  << ".dat";
	   total_seg.load( load_num_seg.str());
	   num_s = total_seg(0);

	   for (int s_tr=0; s_tr<num_s; ++s_tr)
	   {
	     std::stringstream load_cov_seg_tr;
	     load_cov_seg_tr << load_sub_path << "/cov_seg" << s_tr << "_" << all_people (pe_tr) << "_" << actions(act) << "_dim" << dim  << ".h5";

	     mat train_cov;
	     train_cov.load( load_cov_seg_tr.str() );

	     //Esto vienen de PartI4. No recuerdo mas :(
	     double det_op1 = det( diagmat( (test_cov + train_cov)/2 ) );
	     double det_op2 = det( diagmat( ( test_cov%train_cov ) ) );
	     dist_stein =  log( det_op1 ) - 0.5*log( det_op2 ) ;

	     //dist_stein = norm( logMtest_cov - logMtrain_cov, "fro");

	     //cout << "dist " << dist << endl;

	     if (dist_stein < tmp_dist)
	     {
	       //cout << "Es menor" << endl;
	       tmp_dist = dist_stein;
	       est_lab = act;
	     }
	     //cout << "Press a key" << endl;
	     //getchar();
	   }
	 }
       }
     }
   }

   //double n = timer.toc();
   //cout << "number of seconds: " << n << endl;
   //cout << " est_lab "<< est_lab << endl << endl;
   //getchar();
   return est_lab;

 }

 <|endoftext|>


<commit_before>
#include "rbridge.h"

#include <boost/foreach.hpp>

#include "../JASP-Common/base64.h"
#include "../JASP-Common/lib_json/json.h"
#include "../JASP-Common/sharedmemory.h"

RInside *rbridge_rinside;
DataSet *rbridge_dataSet;

using namespace std;

RCallback rbridge_runCallback;
boost::function<std::string(const std::string &)> rbridge_fileNameSource;
boost::function<std::string()> rbridge_stateFileSource;

Rcpp::DataFrame rbridge_readDataSetSEXP(SEXP columns, SEXP columnsAsNumeric, SEXP columnsAsOrdinal, SEXP columnsAsNominal, SEXP allColumns);
Rcpp::DataFrame rbridge_readDataSetHeaderSEXP(SEXP columns, SEXP columnsAsNumeric, SEXP columnsAsOrdinal, SEXP columnsAsNominal, SEXP allColumns);
std::map<std::string, Column::ColumnType> rbridge_marshallSEXPs(SEXP columns, SEXP columnsAsNumeric, SEXP columnsAsOrdinal, SEXP columnsAsNominal, SEXP allColumns);
SEXP rbridge_callbackSEXP(SEXP results);
SEXP rbridge_requestTempFileNameSEXP(SEXP extension);
SEXP rbridge_requestStateFileNameSEXP();

int rbridge_callback(SEXP results);
Rcpp::DataFrame rbridge_readDataSet(const std::map<std::string, Column::ColumnType> &columns);
Rcpp::DataFrame rbridge_readDataSetHeader(const std::map<std::string, Column::ColumnType> &columns);

void rbridge_makeFactor(Rcpp::IntegerVector &v, const std::vector<std::string> &levels, bool ordinal = false);
void rbridge_makeFactor(Rcpp::IntegerVector &v, const Labels &levels, bool ordinal = false);

void rbridge_init()
{
	rbridge_dataSet = NULL;
	rbridge_runCallback = NULL;
	rbridge_fileNameSource = NULL;
	rbridge_stateFileSource = NULL;

	rbridge_rinside = new RInside();

	RInside &rInside = rbridge_rinside->instance();

	rInside[".readDatasetToEndNative"] = Rcpp::InternalFunction(&rbridge_readDataSetSEXP);
	rInside[".readDataSetHeaderNative"] = Rcpp::InternalFunction(&rbridge_readDataSetHeaderSEXP);
	rInside[".callbackNative"] = Rcpp::InternalFunction(&rbridge_callbackSEXP);
	rInside[".requestTempFileNameNative"] = Rcpp::InternalFunction(&rbridge_requestTempFileNameSEXP);
	rInside[".requestStateFileNameNative"] = Rcpp::InternalFunction(&rbridge_requestStateFileNameSEXP);
	rInside[".baseCitation"] = "Love, J., Selker, R., Verhagen, J., Smira, M., Wild, A., Marsman, M., Gronau, Q., Morey, R., Rouder, J. & Wagenmakers, E. J. (2014). JASP (Version 0.5)[Computer software].";

	rInside["jasp.analyses"] = Rcpp::List();
	rInside.parseEvalQNT("suppressPackageStartupMessages(library(\"RJSONIO\"))");
	rInside.parseEvalQNT("suppressPackageStartupMessages(library(\"JASP\"))");
	rInside.parseEvalQNT("suppressPackageStartupMessages(library(\"methods\"))");
}

void rbridge_setDataSet(DataSet *dataSet)
{
	rbridge_dataSet = dataSet;
}

void rbridge_setFileNameSource(boost::function<string (const string &)> source)
{
	rbridge_fileNameSource = source;
}

void rbridge_setStateFileSource(boost::function<string ()> source)
{
	rbridge_stateFileSource = source;
}

SEXP rbridge_requestTempFileNameSEXP(SEXP extension)
{
	if (rbridge_fileNameSource == NULL)
		return R_NilValue;

	string extensionAsString = Rcpp::as<string>(extension);

	return Rcpp::CharacterVector(rbridge_fileNameSource(extensionAsString));
}

SEXP rbridge_requestStateFileNameSEXP()
{
	if (rbridge_stateFileSource == NULL)
		return R_NilValue;

	return Rcpp::CharacterVector(rbridge_stateFileSource());
}

string rbridge_run(const string &name, const string &options, const string &perform, int ppi, RCallback callback)
{
	SEXP results;

	rbridge_runCallback = callback;

	RInside &rInside = rbridge_rinside->instance();

	rInside["name"] = name;
	rInside["options.as.json.string"] = options;
	rInside["perform"] = perform;
	rInside[".ppi"] = ppi;
	rInside.parseEval("run(name=name, options.as.json.string=options.as.json.string, perform)", results);

	rbridge_runCallback = NULL;

	return Rcpp::as<string>(results);
}

Rcpp::DataFrame rbridge_readDataSet(const std::map<std::string, Column::ColumnType> &columns)
{
	if (rbridge_dataSet == NULL)
	{
		std::cout << "rbridge dataset not set!\n";
		std::cout.flush();
	}

	Rcpp::List list(columns.size());
	Rcpp::CharacterVector columnNames;

	int colNo = 0;

	typedef pair<const string, Column::ColumnType> ColumnInfo;

	BOOST_FOREACH(const ColumnInfo &columnInfo, columns)
	{
		(void)columns;

		string columnName = columnInfo.first;

		string base64 = Base64::encode("X", columnName, Base64::RVarEncoding);
		columnNames.push_back(base64);

		Column &column = rbridge_dataSet->columns().get(columnName);
		Column::ColumnType columnType = column.columnType();

		Column::ColumnType requestedType = columnInfo.second;
		if (requestedType == Column::ColumnTypeUnknown)
			requestedType = columnType;

		int rowCount = column.rowCount();
		int rowNo = 0;

		if (requestedType == Column::ColumnTypeScale)
		{
			if (columnType == Column::ColumnTypeScale)
			{
				Rcpp::NumericVector v(rowCount);

				BOOST_FOREACH(double value, column.AsDoubles)
				{
					(void)column;
					v[rowNo++] = value;
				}

				list[colNo++] = v;
			}
			else if (columnType == Column::ColumnTypeOrdinal || columnType == Column::ColumnTypeNominal)
			{
				Rcpp::IntegerVector v(rowCount);

				BOOST_FOREACH(int value, column.AsInts)
				{
					(void)column;
					v[rowNo++] = column.actualFromRaw(value);
				}

				list[colNo++] = v;
			}
			else // columnType == Column::ColumnTypeNominalText
			{
				Rcpp::IntegerVector v(rowCount);

				BOOST_FOREACH(int value, column.AsInts)
				{
					(void)column;
					if (value == INT_MIN)
						v[rowNo++] = INT_MIN;
					else
						v[rowNo++] = value + 1;
				}

				rbridge_makeFactor(v, column.labels());

				list[colNo++] = v;
			}
		}
		else // if (requestedType != Column::ColumnTypeScale)
		{
			bool ordinal = (requestedType == Column::ColumnTypeOrdinal);

			Rcpp::IntegerVector v(rowCount);

			if (columnType != Column::ColumnTypeScale)
			{
				BOOST_FOREACH(int value, column.AsInts)
				{
					(void)column;
					if (value == INT_MIN)
						v[rowNo++] = INT_MIN;
					else
						v[rowNo++] = value + 1;
				}

				rbridge_makeFactor(v, column.labels(), ordinal);
			}
			else
			{
				// scale to nominal or ordinal (doesn't really make sense, but we have to do something)

				set<int> uniqueValues;

				BOOST_FOREACH(double value, column.AsDoubles)
				{
					(void)column;
					int intValue = (int)(value * 1000);
					uniqueValues.insert(intValue);
				}

				int index = 0;
				map<int, int> valueToIndex;
				vector<string> labels;

				BOOST_FOREACH(int value, uniqueValues)
				{
					(void)uniqueValues;
					valueToIndex[value] = index;

					stringstream ss;
					ss << ((double)value / 1000);
					labels.push_back(ss.str());

					index++;
				}

				BOOST_FOREACH(double value, column.AsDoubles)
				{
					(void)column;

					if (isnan(value))
						v[rowNo++] = INT_MIN;
					else
					{
						v[rowNo++] = valueToIndex[(int)(value * 1000)] + 1;
					}
				}

				rbridge_makeFactor(v, labels, ordinal);
			}

			list[colNo++] = v;
		}
	}

	list.attr("names") = columnNames;

	Rcpp::DataFrame dataFrame = Rcpp::DataFrame(list);

	return dataFrame;
}

Rcpp::DataFrame rbridge_readDataSetHeader(const std::map<string, Column::ColumnType> &columns)
{
	if (rbridge_dataSet == NULL)
	{
		std::cout << "rbridge dataset not set!\n";
		std::cout.flush();
	}

	Rcpp::List list(columns.size());
	Rcpp::CharacterVector columnNames;

	int colNo = 0;

	typedef pair<const string, Column::ColumnType> ColumnInfo;

	BOOST_FOREACH(const ColumnInfo &columnInfo, columns)
	{
		(void)columns;

		string columnName = columnInfo.first;

		string base64 = Base64::encode("X", columnName, Base64::RVarEncoding);
		columnNames.push_back(base64);

		Columns &columns = rbridge_dataSet->columns();
		Column &column = columns.get(columnName);
		Column::ColumnType columnType = column.columnType();

		Column::ColumnType requestedType = columnInfo.second;
		if (requestedType == Column::ColumnTypeUnknown)
			requestedType = columnType;

		if (requestedType == Column::ColumnTypeScale)
		{
			if (columnType == Column::ColumnTypeScale)
			{
				list[colNo++] = Rcpp::NumericVector(0);
			}
			else if (columnType == Column::ColumnTypeOrdinal || columnType == Column::ColumnTypeNominal)
			{
				list[colNo++] = Rcpp::IntegerVector(0);
			}
			else
			{
				Rcpp::IntegerVector v(0);
				rbridge_makeFactor(v, column.labels());
				list[colNo++] = v;
			}
		}
		else
		{
			bool ordinal = (requestedType == Column::ColumnTypeOrdinal);

			Rcpp::IntegerVector v(0);
			rbridge_makeFactor(v, column.labels(), ordinal);

			list[colNo++] = v;
		}
	}

	list.attr("names") = columnNames;

	Rcpp::DataFrame dataFrame = Rcpp::DataFrame(list);

	return dataFrame;
}

void rbridge_makeFactor(Rcpp::IntegerVector &v, const Labels &levels, bool ordinal)
{
	Rcpp::CharacterVector labels;

	if (levels.size() == 0)
	{
		labels.push_back(".");
	}
	else
	{
		for (int i = 0; i < levels.size(); i++)
			labels.push_back(levels.at(i).text());
	}

	v.attr("levels") = labels;

	vector<string> cla55;
	if (ordinal)
		cla55.push_back("ordered");
	cla55.push_back("factor");

	v.attr("class") = cla55;
}

void rbridge_makeFactor(Rcpp::IntegerVector &v, const std::vector<string> &levels, bool ordinal)
{
	v.attr("levels") = levels;

	vector<string> cla55;
	if (ordinal)
		cla55.push_back("ordered");
	cla55.push_back("factor");

	v.attr("class") = cla55;
}

int rbridge_callback(SEXP results)
{
	if (rbridge_runCallback != NULL)
	{
		if (Rf_isNull(results))
		{
			return rbridge_runCallback("null");
		}
		else
		{
			return rbridge_runCallback(Rcpp::as<string>(results));
		}
	}
	else
	{
		return 0;
	}
}

std::map<string, Column::ColumnType> rbridge_marshallSEXPs(SEXP columns, SEXP columnsAsNumeric, SEXP columnsAsOrdinal, SEXP columnsAsNominal, SEXP allColumns)
{
	map<string, Column::ColumnType> columnsRequested;

	if (Rf_isLogical(allColumns) && Rcpp::as<bool>(allColumns))
	{
		BOOST_FOREACH(const Column &column, rbridge_dataSet->columns())
			columnsRequested[column.name()] = Column::ColumnTypeUnknown;
	}

	if (Rf_isString(columns))
	{
		vector<string> temp = Rcpp::as<vector<string> >(columns);
		for (int i = 0; i < temp.size(); i++)
			columnsRequested[temp.at(i)] = Column::ColumnTypeUnknown;
	}

	if (Rf_isString(columnsAsNumeric))
	{
		vector<string> temp = Rcpp::as<vector<string> >(columnsAsNumeric);
		for (int i = 0; i < temp.size(); i++)
			columnsRequested[temp.at(i)] = Column::ColumnTypeScale;
	}

	if (Rf_isString(columnsAsOrdinal))
	{
		vector<string> temp = Rcpp::as<vector<string> >(columnsAsOrdinal);
		for (int i = 0; i < temp.size(); i++)
			columnsRequested[temp.at(i)] = Column::ColumnTypeOrdinal;
	}

	if (Rf_isString(columnsAsNominal))
	{
		vector<string> temp = Rcpp::as<vector<string> >(columnsAsNominal);
		for (int i = 0; i < temp.size(); i++)
			columnsRequested[temp.at(i)] = Column::ColumnTypeNominal;
	}

	return columnsRequested;
}

SEXP rbridge_callbackSEXP(SEXP results)
{
	Rcpp::NumericVector control(1);
	control[0] = rbridge_callback(results);
	return control;
}

Rcpp::DataFrame rbridge_readDataSetSEXP(SEXP columns, SEXP columnsAsNumeric, SEXP columnsAsOrdinal, SEXP columnsAsNominal, SEXP allColumns)
{
	map<string, Column::ColumnType> columnsRequested = rbridge_marshallSEXPs(columns, columnsAsNumeric, columnsAsOrdinal, columnsAsNominal, allColumns);
	return rbridge_readDataSet(columnsRequested);
}

Rcpp::DataFrame rbridge_readDataSetHeaderSEXP(SEXP columns, SEXP columnsAsNumeric, SEXP columnsAsOrdinal, SEXP columnsAsNominal, SEXP allColumns)
{
	map<string, Column::ColumnType> columnsRequested = rbridge_marshallSEXPs(columns, columnsAsNumeric, columnsAsOrdinal, columnsAsNominal, allColumns);
	return rbridge_readDataSetHeader(columnsRequested);
}
<commit_msg>Fix to scale to nominal marshalling<commit_after>
#include "rbridge.h"

#include <boost/foreach.hpp>

#include "../JASP-Common/base64.h"
#include "../JASP-Common/lib_json/json.h"
#include "../JASP-Common/sharedmemory.h"

RInside *rbridge_rinside;
DataSet *rbridge_dataSet;

using namespace std;

RCallback rbridge_runCallback;
boost::function<std::string(const std::string &)> rbridge_fileNameSource;
boost::function<std::string()> rbridge_stateFileSource;

Rcpp::DataFrame rbridge_readDataSetSEXP(SEXP columns, SEXP columnsAsNumeric, SEXP columnsAsOrdinal, SEXP columnsAsNominal, SEXP allColumns);
Rcpp::DataFrame rbridge_readDataSetHeaderSEXP(SEXP columns, SEXP columnsAsNumeric, SEXP columnsAsOrdinal, SEXP columnsAsNominal, SEXP allColumns);
std::map<std::string, Column::ColumnType> rbridge_marshallSEXPs(SEXP columns, SEXP columnsAsNumeric, SEXP columnsAsOrdinal, SEXP columnsAsNominal, SEXP allColumns);
SEXP rbridge_callbackSEXP(SEXP results);
SEXP rbridge_requestTempFileNameSEXP(SEXP extension);
SEXP rbridge_requestStateFileNameSEXP();

int rbridge_callback(SEXP results);
Rcpp::DataFrame rbridge_readDataSet(const std::map<std::string, Column::ColumnType> &columns);
Rcpp::DataFrame rbridge_readDataSetHeader(const std::map<std::string, Column::ColumnType> &columns);

void rbridge_makeFactor(Rcpp::IntegerVector &v, const std::vector<std::string> &levels, bool ordinal = false);
void rbridge_makeFactor(Rcpp::IntegerVector &v, const Labels &levels, bool ordinal = false);

void rbridge_init()
{
	rbridge_dataSet = NULL;
	rbridge_runCallback = NULL;
	rbridge_fileNameSource = NULL;
	rbridge_stateFileSource = NULL;

	rbridge_rinside = new RInside();

	RInside &rInside = rbridge_rinside->instance();

	rInside[".readDatasetToEndNative"] = Rcpp::InternalFunction(&rbridge_readDataSetSEXP);
	rInside[".readDataSetHeaderNative"] = Rcpp::InternalFunction(&rbridge_readDataSetHeaderSEXP);
	rInside[".callbackNative"] = Rcpp::InternalFunction(&rbridge_callbackSEXP);
	rInside[".requestTempFileNameNative"] = Rcpp::InternalFunction(&rbridge_requestTempFileNameSEXP);
	rInside[".requestStateFileNameNative"] = Rcpp::InternalFunction(&rbridge_requestStateFileNameSEXP);
	rInside[".baseCitation"] = "Love, J., Selker, R., Verhagen, J., Smira, M., Wild, A., Marsman, M., Gronau, Q., Morey, R., Rouder, J. & Wagenmakers, E. J. (2014). JASP (Version 0.5)[Computer software].";

	rInside["jasp.analyses"] = Rcpp::List();
	rInside.parseEvalQNT("suppressPackageStartupMessages(library(\"RJSONIO\"))");
	rInside.parseEvalQNT("suppressPackageStartupMessages(library(\"JASP\"))");
	rInside.parseEvalQNT("suppressPackageStartupMessages(library(\"methods\"))");
}

void rbridge_setDataSet(DataSet *dataSet)
{
	rbridge_dataSet = dataSet;
}

void rbridge_setFileNameSource(boost::function<string (const string &)> source)
{
	rbridge_fileNameSource = source;
}

void rbridge_setStateFileSource(boost::function<string ()> source)
{
	rbridge_stateFileSource = source;
}

SEXP rbridge_requestTempFileNameSEXP(SEXP extension)
{
	if (rbridge_fileNameSource == NULL)
		return R_NilValue;

	string extensionAsString = Rcpp::as<string>(extension);

	return Rcpp::CharacterVector(rbridge_fileNameSource(extensionAsString));
}

SEXP rbridge_requestStateFileNameSEXP()
{
	if (rbridge_stateFileSource == NULL)
		return R_NilValue;

	return Rcpp::CharacterVector(rbridge_stateFileSource());
}

string rbridge_run(const string &name, const string &options, const string &perform, int ppi, RCallback callback)
{
	SEXP results;

	rbridge_runCallback = callback;

	RInside &rInside = rbridge_rinside->instance();

	rInside["name"] = name;
	rInside["options.as.json.string"] = options;
	rInside["perform"] = perform;
	rInside[".ppi"] = ppi;
	rInside.parseEval("run(name=name, options.as.json.string=options.as.json.string, perform)", results);

	rbridge_runCallback = NULL;

	return Rcpp::as<string>(results);
}

Rcpp::DataFrame rbridge_readDataSet(const std::map<std::string, Column::ColumnType> &columns)
{
	if (rbridge_dataSet == NULL)
	{
		std::cout << "rbridge dataset not set!\n";
		std::cout.flush();
	}

	Rcpp::List list(columns.size());
	Rcpp::CharacterVector columnNames;

	int colNo = 0;

	typedef pair<const string, Column::ColumnType> ColumnInfo;

	BOOST_FOREACH(const ColumnInfo &columnInfo, columns)
	{
		(void)columns;

		string columnName = columnInfo.first;

		string base64 = Base64::encode("X", columnName, Base64::RVarEncoding);
		columnNames.push_back(base64);

		Column &column = rbridge_dataSet->columns().get(columnName);
		Column::ColumnType columnType = column.columnType();

		Column::ColumnType requestedType = columnInfo.second;
		if (requestedType == Column::ColumnTypeUnknown)
			requestedType = columnType;

		int rowCount = column.rowCount();
		int rowNo = 0;

		if (requestedType == Column::ColumnTypeScale)
		{
			if (columnType == Column::ColumnTypeScale)
			{
				Rcpp::NumericVector v(rowCount);

				BOOST_FOREACH(double value, column.AsDoubles)
				{
					(void)column;
					v[rowNo++] = value;
				}

				list[colNo++] = v;
			}
			else if (columnType == Column::ColumnTypeOrdinal || columnType == Column::ColumnTypeNominal)
			{
				Rcpp::IntegerVector v(rowCount);

				BOOST_FOREACH(int value, column.AsInts)
				{
					(void)column;
					v[rowNo++] = column.actualFromRaw(value);
				}

				list[colNo++] = v;
			}
			else // columnType == Column::ColumnTypeNominalText
			{
				Rcpp::IntegerVector v(rowCount);

				BOOST_FOREACH(int value, column.AsInts)
				{
					(void)column;
					if (value == INT_MIN)
						v[rowNo++] = INT_MIN;
					else
						v[rowNo++] = value + 1;
				}

				rbridge_makeFactor(v, column.labels());

				list[colNo++] = v;
			}
		}
		else // if (requestedType != Column::ColumnTypeScale)
		{
			bool ordinal = (requestedType == Column::ColumnTypeOrdinal);

			Rcpp::IntegerVector v(rowCount);

			if (columnType != Column::ColumnTypeScale)
			{
				BOOST_FOREACH(int value, column.AsInts)
				{
					(void)column;
					if (value == INT_MIN)
						v[rowNo++] = INT_MIN;
					else
						v[rowNo++] = value + 1;
				}

				rbridge_makeFactor(v, column.labels(), ordinal);
			}
			else
			{
				// scale to nominal or ordinal (doesn't really make sense, but we have to do something)

				set<int> uniqueValues;

				BOOST_FOREACH(double value, column.AsDoubles)
				{
					(void)column;

					if (isnan(value))
						continue;

					int intValue = (int)(value * 1000);
					uniqueValues.insert(intValue);
				}

				int index = 0;
				map<int, int> valueToIndex;
				vector<string> labels;

				BOOST_FOREACH(int value, uniqueValues)
				{
					(void)value;
					(void)uniqueValues;

					valueToIndex[value] = index;

					stringstream ss;
					ss << ((double)value / 1000);
					labels.push_back(ss.str());

					index++;
				}

				BOOST_FOREACH(double value, column.AsDoubles)
				{
					(void)column;

					if (isnan(value))
						v[rowNo++] = INT_MIN;
					else
					{
						v[rowNo++] = valueToIndex[(int)(value * 1000)] + 1;
					}
				}

				rbridge_makeFactor(v, labels, ordinal);
			}

			list[colNo++] = v;
		}
	}

	list.attr("names") = columnNames;

	Rcpp::DataFrame dataFrame = Rcpp::DataFrame(list);

	return dataFrame;
}

Rcpp::DataFrame rbridge_readDataSetHeader(const std::map<string, Column::ColumnType> &columns)
{
	if (rbridge_dataSet == NULL)
	{
		std::cout << "rbridge dataset not set!\n";
		std::cout.flush();
	}

	Rcpp::List list(columns.size());
	Rcpp::CharacterVector columnNames;

	int colNo = 0;

	typedef pair<const string, Column::ColumnType> ColumnInfo;

	BOOST_FOREACH(const ColumnInfo &columnInfo, columns)
	{
		(void)columns;

		string columnName = columnInfo.first;

		string base64 = Base64::encode("X", columnName, Base64::RVarEncoding);
		columnNames.push_back(base64);

		Columns &columns = rbridge_dataSet->columns();
		Column &column = columns.get(columnName);
		Column::ColumnType columnType = column.columnType();

		Column::ColumnType requestedType = columnInfo.second;
		if (requestedType == Column::ColumnTypeUnknown)
			requestedType = columnType;

		if (requestedType == Column::ColumnTypeScale)
		{
			if (columnType == Column::ColumnTypeScale)
			{
				list[colNo++] = Rcpp::NumericVector(0);
			}
			else if (columnType == Column::ColumnTypeOrdinal || columnType == Column::ColumnTypeNominal)
			{
				list[colNo++] = Rcpp::IntegerVector(0);
			}
			else
			{
				Rcpp::IntegerVector v(0);
				rbridge_makeFactor(v, column.labels());
				list[colNo++] = v;
			}
		}
		else
		{
			bool ordinal = (requestedType == Column::ColumnTypeOrdinal);

			Rcpp::IntegerVector v(0);
			rbridge_makeFactor(v, column.labels(), ordinal);

			list[colNo++] = v;
		}
	}

	list.attr("names") = columnNames;

	Rcpp::DataFrame dataFrame = Rcpp::DataFrame(list);

	return dataFrame;
}

void rbridge_makeFactor(Rcpp::IntegerVector &v, const Labels &levels, bool ordinal)
{
	Rcpp::CharacterVector labels;

	if (levels.size() == 0)
	{
		labels.push_back(".");
	}
	else
	{
		for (int i = 0; i < levels.size(); i++)
			labels.push_back(levels.at(i).text());
	}

	v.attr("levels") = labels;

	vector<string> cla55;
	if (ordinal)
		cla55.push_back("ordered");
	cla55.push_back("factor");

	v.attr("class") = cla55;
}

void rbridge_makeFactor(Rcpp::IntegerVector &v, const std::vector<string> &levels, bool ordinal)
{
	v.attr("levels") = levels;

	vector<string> cla55;
	if (ordinal)
		cla55.push_back("ordered");
	cla55.push_back("factor");

	v.attr("class") = cla55;
}

int rbridge_callback(SEXP results)
{
	if (rbridge_runCallback != NULL)
	{
		if (Rf_isNull(results))
		{
			return rbridge_runCallback("null");
		}
		else
		{
			return rbridge_runCallback(Rcpp::as<string>(results));
		}
	}
	else
	{
		return 0;
	}
}

std::map<string, Column::ColumnType> rbridge_marshallSEXPs(SEXP columns, SEXP columnsAsNumeric, SEXP columnsAsOrdinal, SEXP columnsAsNominal, SEXP allColumns)
{
	map<string, Column::ColumnType> columnsRequested;

	if (Rf_isLogical(allColumns) && Rcpp::as<bool>(allColumns))
	{
		BOOST_FOREACH(const Column &column, rbridge_dataSet->columns())
			columnsRequested[column.name()] = Column::ColumnTypeUnknown;
	}

	if (Rf_isString(columns))
	{
		vector<string> temp = Rcpp::as<vector<string> >(columns);
		for (int i = 0; i < temp.size(); i++)
			columnsRequested[temp.at(i)] = Column::ColumnTypeUnknown;
	}

	if (Rf_isString(columnsAsNumeric))
	{
		vector<string> temp = Rcpp::as<vector<string> >(columnsAsNumeric);
		for (int i = 0; i < temp.size(); i++)
			columnsRequested[temp.at(i)] = Column::ColumnTypeScale;
	}

	if (Rf_isString(columnsAsOrdinal))
	{
		vector<string> temp = Rcpp::as<vector<string> >(columnsAsOrdinal);
		for (int i = 0; i < temp.size(); i++)
			columnsRequested[temp.at(i)] = Column::ColumnTypeOrdinal;
	}

	if (Rf_isString(columnsAsNominal))
	{
		vector<string> temp = Rcpp::as<vector<string> >(columnsAsNominal);
		for (int i = 0; i < temp.size(); i++)
			columnsRequested[temp.at(i)] = Column::ColumnTypeNominal;
	}

	return columnsRequested;
}

SEXP rbridge_callbackSEXP(SEXP results)
{
	Rcpp::NumericVector control(1);
	control[0] = rbridge_callback(results);
	return control;
}

Rcpp::DataFrame rbridge_readDataSetSEXP(SEXP columns, SEXP columnsAsNumeric, SEXP columnsAsOrdinal, SEXP columnsAsNominal, SEXP allColumns)
{
	map<string, Column::ColumnType> columnsRequested = rbridge_marshallSEXPs(columns, columnsAsNumeric, columnsAsOrdinal, columnsAsNominal, allColumns);
	return rbridge_readDataSet(columnsRequested);
}

Rcpp::DataFrame rbridge_readDataSetHeaderSEXP(SEXP columns, SEXP columnsAsNumeric, SEXP columnsAsOrdinal, SEXP columnsAsNominal, SEXP allColumns)
{
	map<string, Column::ColumnType> columnsRequested = rbridge_marshallSEXPs(columns, columnsAsNumeric, columnsAsOrdinal, columnsAsNominal, allColumns);
	return rbridge_readDataSetHeader(columnsRequested);
}
<|endoftext|>


<commit_before>/* Copyright 2017 The TensorFlow Authors. 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.
==============================================================================*/

#include "tensorflow/core/grappler/op_types.h"

namespace tensorflow {
namespace grappler {

bool IsConcat(const NodeDef& node) {
  const auto op = node.op();
  return op == "Concat" || op == "ConcatV2";
}

bool IsConstant(const NodeDef& node) {
  const auto op = node.op();
  return op == "Const";
}

bool IsDequeueOp(const NodeDef& node) {
  static const std::set<std::string> dequeue_ops = {
      "QueueDequeueManyV2", "QueueDequeueMany", "QueueDequeueV2",
      "QueueDequeue"};
  return dequeue_ops.count(node.op()) > 0;
}

bool IsMerge(const NodeDef& node) {
  const auto op = node.op();
  return op == "Merge";
}

bool IsPlaceholder(const NodeDef& node) {
  const auto op = node.op();
  return op == "Placeholder" || op == "PlaceholderV2" ||
         op == "PlaceholderWithDefault";
}

bool IsTranspose(const NodeDef& node) {
  const auto op = node.op();
  return op == "Transpose";
}

bool IsVariable(const NodeDef& node) {
  const auto op = node.op();
  return op == "Variable" || op == "VariableV2" || op == "AutoReloadVariable" ||
         op == "VarHandleOp" || op == "TemporaryVariable";
}

}  // end namespace grappler
}  // end namespace tensorflow
<commit_msg>Add QueueDequeueUpTo to the list of dequeue ops<commit_after>/* Copyright 2017 The TensorFlow Authors. 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.
==============================================================================*/

#include "tensorflow/core/grappler/op_types.h"

namespace tensorflow {
namespace grappler {

bool IsConcat(const NodeDef& node) {
  const auto op = node.op();
  return op == "Concat" || op == "ConcatV2";
}

bool IsConstant(const NodeDef& node) {
  const auto op = node.op();
  return op == "Const";
}

bool IsDequeueOp(const NodeDef& node) {
  static const std::set<std::string> dequeue_ops = {
      "QueueDequeueManyV2", "QueueDequeueMany",   "QueueDequeueV2",
      "QueueDequeue",       "QueueDequeueUpToV2", "QueueDequeueUpTo"};
  return dequeue_ops.count(node.op()) > 0;
}

bool IsMerge(const NodeDef& node) {
  const auto op = node.op();
  return op == "Merge";
}

bool IsPlaceholder(const NodeDef& node) {
  const auto op = node.op();
  return op == "Placeholder" || op == "PlaceholderV2" ||
         op == "PlaceholderWithDefault";
}

bool IsTranspose(const NodeDef& node) {
  const auto op = node.op();
  return op == "Transpose";
}

bool IsVariable(const NodeDef& node) {
  const auto op = node.op();
  return op == "Variable" || op == "VariableV2" || op == "AutoReloadVariable" ||
         op == "VarHandleOp" || op == "TemporaryVariable";
}

}  // end namespace grappler
}  // end namespace tensorflow
<|endoftext|>


<commit_before>#include "../src/ForceFields/LennardJonesFF.h"
#include "../src/ForceFields/ForceFieldManager.h"
#include "../src/Simulation/StandardSimulation.h"
#include "../src/Moves/MoveManager.h"
#include "../src/Moves/TranslateMove.h"
#include "../src/Moves/InsertParticleMove.h"
#include "../src/Moves/DeleteParticleMove.h"
#include "../src/Particles/Site.h"
#include "../src/Particles/Molecule.h"
#include "../src/Worlds/World.h"
#include "../src/Worlds/WorldManager.h"
#include "TestAccumulator.h"
#include "json/json.h"
#include "gtest/gtest.h"
#include "../src/Observers/DLMFileObserver.h"
#include <fstream>

using namespace SAPHRON;

// Grand canonical simulation tests.
TEST(GrandCanonicalEnsembleTests, Default)
{
	auto N = 500;
	auto sigma = 1.;
	auto eps = 1.;
	auto T = 1.50;
	auto V = 250.047;
	auto rcut = 3.*sigma;

	// Prototype particle.
	Site lj({0, 0, 0}, {0, 0, 0}, "LJ");

	// Initialze world, set chemical potential and pack with lj.
	World world(1, 1, 1, rcut);
	world.SetNeighborRadius(rcut + 1.0);
	world.PackWorld({&lj}, {1.0}, N, 0.6);
	world.SetChemicalPotential("LJ", 2.0);
	world.SetTemperature(T);
	world.SetVolume(V, true); // Override volume. This will be fixed.

	// Initialize world manager.
	WorldManager wm;
	wm.AddWorld(&world);

	ASSERT_EQ(N, world.GetParticleCount());
	ASSERT_DOUBLE_EQ(V, world.GetVolume());

	// Initialize LJ forcefield.
	LennardJonesFF ff(eps, sigma);
	ForceFieldManager ffm;
	ffm.AddNonBondedForceField("LJ", "LJ", ff);

	// Initialize moves.
	MoveManager mm;
	TranslateMove move1(0.22);
	mm.AddMove(&move1, 75);
	InsertParticleMove move2({"LJ"}, wm, 500);
	mm.AddMove(&move2, 12);
	DeleteParticleMove move3({"LJ"});
	mm.AddMove(&move3, 12);

	// Initialize observer.
	SimFlags flags;
	flags.world_on();
	flags.simulation_on();

	DLMFileObserver dlm("gcmc.test", flags);

	// Initialize ensemble.
	StandardSimulation ensemble(&wm, &ffm, &mm);
	ensemble.AddObserver(&dlm);
	ASSERT_EQ(N, world.GetParticleCount());

	// Run
	ensemble.Run(10000);
}<commit_msg>Updated GCMC test.<commit_after>#include "../src/ForceFields/LennardJonesFF.h"
#include "../src/ForceFields/ForceFieldManager.h"
#include "../src/Simulation/StandardSimulation.h"
#include "../src/Moves/MoveManager.h"
#include "../src/Moves/TranslateMove.h"
#include "../src/Moves/InsertParticleMove.h"
#include "../src/Moves/DeleteParticleMove.h"
#include "../src/Particles/Site.h"
#include "../src/Particles/Molecule.h"
#include "../src/Worlds/World.h"
#include "../src/Worlds/WorldManager.h"
#include "TestAccumulator.h"
#include "json/json.h"
#include "gtest/gtest.h"
#include "../src/Observers/DLMFileObserver.h"
#include <fstream>

using namespace SAPHRON;

// Grand canonical simulation tests.
TEST(GrandCanonicalEnsembleTests, Default)
{
	auto N = 500;
	auto sigma = 1.;
	auto eps = 1.;
	auto T = 1.50;
	auto V = 512.0;
	auto rcut = 3.*sigma;

	// Prototype particle.
	Site lj({0, 0, 0}, {0, 0, 0}, "LJ");

	// Initialze world, set chemical potential and pack with lj.
	World world(1, 1, 1, rcut);
	world.SetNeighborRadius(rcut + 1.0);
	world.PackWorld({&lj}, {1.0}, N, 0.6);
	world.SetChemicalPotential("LJ", -2.0);
	world.SetTemperature(T);
	world.SetVolume(V, true); // Override volume. This will be fixed.

	// Initialize world manager.
	WorldManager wm;
	wm.AddWorld(&world);

	ASSERT_EQ(N, world.GetParticleCount());
	ASSERT_DOUBLE_EQ(V, world.GetVolume());

	// Initialize LJ forcefield.
	LennardJonesFF ff(eps, sigma);
	ForceFieldManager ffm;
	ffm.AddNonBondedForceField("LJ", "LJ", ff);

	// Initialize moves.
	MoveManager mm;
	TranslateMove move1(0.22);
	mm.AddMove(&move1, 75);
	InsertParticleMove move2({"LJ"}, wm, 500);
	mm.AddMove(&move2, 12);
	DeleteParticleMove move3({"LJ"});
	mm.AddMove(&move3, 12);

	// Initialize observer.
	SimFlags flags;
	flags.world_on();
	flags.simulation_on();

	TestAccumulator observer(flags, 1, 6000);

	// Initialize ensemble.
	StandardSimulation ensemble(&wm, &ffm, &mm);
	ensemble.AddObserver(&observer);
	ASSERT_EQ(N, world.GetParticleCount());

	// Run
	ensemble.Run(20000);

	auto rhos = observer.GetAverageDensities();
	ASSERT_NEAR(rhos[&world], 0.64, 1e-2);
	auto Ps = observer.GetAveragePressures();
	ASSERT_NEAR(Ps[&world].isotropic(), 1.04, 1e-2);
}<|endoftext|>


<commit_before>#ifndef ENTT_SIGNAL_SIGH_HPP
#define ENTT_SIGNAL_SIGH_HPP

#include <algorithm>
#include <utility>
#include <vector>
#include <functional>
#include <type_traits>
#include "../config/config.h"
#include "delegate.hpp"
#include "fwd.hpp"

namespace entt {

/**
 * @cond TURN_OFF_DOXYGEN
 * Internal details not to be documented.
 */

namespace internal {

template<typename, typename>
struct invoker;

template<typename Ret, typename... Args, typename Collector>
struct invoker<Ret(Args...), Collector> {
    virtual ~invoker() = default;

    bool invoke(Collector &collector, const delegate<Ret(Args...)> &delegate, Args... args) const {
        return collector(delegate(args...));
    }
};

template<typename... Args, typename Collector>
struct invoker<void(Args...), Collector> {
    virtual ~invoker() = default;

    bool invoke(Collector &, const delegate<void(Args...)> &delegate, Args... args) const {
        return (delegate(args...), true);
    }
};

template<typename Ret>
struct null_collector {
    using result_type = Ret;
    bool operator()(result_type) const ENTT_NOEXCEPT { return true; }
};

template<>
struct null_collector<void> {
    using result_type = void;
    bool operator()() const ENTT_NOEXCEPT { return true; }
};

template<typename>
struct default_collector;

template<typename Ret, typename... Args>
struct default_collector<Ret(Args...)> {
    using collector_type = null_collector<Ret>;
};

template<typename Function>
using default_collector_type = typename default_collector<Function>::collector_type;

}

/**
 * Internal details not to be documented.
 * @endcond TURN_OFF_DOXYGEN
 */

/**
 * @brief Sink implementation.
 *
 * Primary template isn't defined on purpose. All the specializations give a
 * compile-time error unless the template parameter is a function type.
 *
 * @tparam Function A valid function type.
 */
template<typename Function>
class sink;

/**
 * @brief Unmanaged signal handler declaration.
 *
 * Primary template isn't defined on purpose. All the specializations give a
 * compile-time error unless the template parameter is a function type.
 *
 * @tparam Function A valid function type.
 * @tparam Collector Type of collector to use, if any.
 */
template<typename Function, typename Collector = internal::default_collector_type<Function>>
struct sigh;

/**
 * @brief Sink implementation.
 *
 * A sink is an opaque object used to connect listeners to signals.

 * The function type for a listener is the one of the signal to which it
 * belongs.
 *
 * The clear separation between a signal and a sink permits to store the former
 * as private data member without exposing the publish functionality to the
 * users of a class.
 *
 * @tparam Ret Return type of a function type.
 * @tparam Args Types of arguments of a function type.
 */
template<typename Ret, typename... Args>
class sink<Ret(Args...)> {
    /*! @brief A signal is allowed to create sinks. */
    template<typename, typename>
    friend struct sigh;

    template<typename Type>
    Type * payload_type(Ret(*)(Type *, Args...));

    sink(std::vector<delegate<Ret(Args...)>> *ref) ENTT_NOEXCEPT
        : calls{ref}
    {}

public:
    /**
     * @brief Returns false if at least a listener is connected to the sink.
     * @return True if the sink has no listeners connected, false otherwise.
     */
    bool empty() const ENTT_NOEXCEPT {
        return calls->empty();
    }

    /**
     * @brief Connects a free function to a signal.
     *
     * The signal handler performs checks to avoid multiple connections for free
     * functions.
     *
     * @tparam Function A valid free function pointer.
     */
    template<auto Function>
    void connect() {
        disconnect<Function>();
        delegate<Ret(Args...)> delegate{};
        delegate.template connect<Function>();
        calls->emplace_back(std::move(delegate));
    }

    /**
     * @brief Connects a member function or a free function with payload to a
     * signal.
     *
     * The signal isn't responsible for the connected object or the payload.
     * Users must always guarantee that the lifetime of the instance overcomes
     * the one  of the delegate. On the other side, the signal handler performs
     * checks to avoid multiple connections for the same function.

     * When used to connect a free function with payload, its signature must be
     * such that the instance is the first argument before the ones used to
     * define the delegate itself.
     *
     * @tparam Candidate Member or free function to connect to the signal.
     * @tparam Type Type of class or type of payload.
     * @param value_or_instance A valid pointer that fits the purpose.
     */
    template<auto Candidate, typename Type>
    void connect(Type *value_or_instance) {
        disconnect<Candidate>(value_or_instance);
        delegate<Ret(Args...)> delegate{};
        delegate.template connect<Candidate>(value_or_instance);
        calls->emplace_back(std::move(delegate));
    }

    /**
     * @brief Disconnects a free function from a signal.
     * @tparam Function A valid free function pointer.
     */
    template<auto Function>
    void disconnect() {
        delegate<Ret(Args...)> delegate{};
        delegate.template connect<Function>();
        calls->erase(std::remove(calls->begin(), calls->end(), std::move(delegate)), calls->end());
    }

    /**
     * @brief Disconnects a member function or a free function with payload from
     * a signal.
     * @tparam Candidate Member or free function to disconnect from the signal.
     * @tparam Type Type of class or type of payload.
     * @param value_or_instance A valid pointer that fits the purpose.
     */
    template<auto Candidate, typename Type>
    void disconnect(Type *value_or_instance) {
        delegate<Ret(Args...)> delegate{};
        delegate.template connect<Candidate>(value_or_instance);
        calls->erase(std::remove_if(calls->begin(), calls->end(), [delegate](const auto &other) {
            return other == delegate && other.instance() == delegate.instance();
        }), calls->end());
    }

    /**
     * @brief Disconnects member functions or free functions based on an
     * instance or specific payload.
     * @param value_or_instance A valid pointer that fits the purpose.
     */
    void disconnect(const void *value_or_instance) {
        calls->erase(std::remove_if(calls->begin(), calls->end(), [value_or_instance](const auto &delegate) {
            return value_or_instance == delegate.instance();
        }), calls->end());
    }

    /*! @brief Disconnects all the listeners from a signal. */
    void disconnect() {
        calls->clear();
    }

private:
    std::vector<delegate<Ret(Args...)>> *calls;
};

/**
 * @brief Unmanaged signal handler definition.
 *
 * Unmanaged signal handler. It works directly with naked pointers to classes
 * and pointers to member functions as well as pointers to free functions. Users
 * of this class are in charge of disconnecting instances before deleting them.
 *
 * This class serves mainly two purposes:
 *
 * * Creating signals used later to notify a bunch of listeners.
 * * Collecting results from a set of functions like in a voting system.
 *
 * The default collector does nothing. To properly collect data, define and use
 * a class that has a call operator the signature of which is `bool(Param)` and:
 *
 * * `Param` is a type to which `Ret` can be converted.
 * * The return type is true if the handler must stop collecting data, false
 * otherwise.
 *
 * @tparam Ret Return type of a function type.
 * @tparam Args Types of arguments of a function type.
 * @tparam Collector Type of collector to use, if any.
 */
template<typename Ret, typename... Args, typename Collector>
struct sigh<Ret(Args...), Collector>: private internal::invoker<Ret(Args...), Collector> {
    /*! @brief Unsigned integer type. */
    using size_type = typename std::vector<delegate<Ret(Args...)>>::size_type;
    /*! @brief Collector type. */
    using collector_type = Collector;
    /*! @brief Sink type. */
    using sink_type = entt::sink<Ret(Args...)>;

    /**
     * @brief Instance type when it comes to connecting member functions.
     * @tparam Class Type of class to which the member function belongs.
     */
    template<typename Class>
    using instance_type = Class *;

    /**
     * @brief Number of listeners connected to the signal.
     * @return Number of listeners currently connected.
     */
    size_type size() const ENTT_NOEXCEPT {
        return calls.size();
    }

    /**
     * @brief Returns false if at least a listener is connected to the signal.
     * @return True if the signal has no listeners connected, false otherwise.
     */
    bool empty() const ENTT_NOEXCEPT {
        return calls.empty();
    }

    /**
     * @brief Returns a sink object for the given signal.
     *
     * A sink is an opaque object used to connect listeners to signals.

     * The function type for a listener is the one of the signal to which it
     * belongs. The order of invocation of the listeners isn't guaranteed.
     *
     * @return A temporary sink object.
     */
    sink_type sink() ENTT_NOEXCEPT {
        return { &calls };
    }

    /**
     * @brief Triggers a signal.
     *
     * All the listeners are notified. Order isn't guaranteed.
     *
     * @param args Arguments to use to invoke listeners.
     */
    void publish(Args... args) const {
        for(auto pos = calls.size(); pos; --pos) {
            auto &call = calls[pos-1];
            call(args...);
        }
    }

    /**
     * @brief Collects return values from the listeners.
     * @param args Arguments to use to invoke listeners.
     * @return An instance of the collector filled with collected data.
     */
    collector_type collect(Args... args) const {
        collector_type collector;

        for(auto &&call: calls) {
            if(!this->invoke(collector, call, args...)) {
                break;
            }
        }

        return collector;
    }

    /**
     * @brief Swaps listeners between the two signals.
     * @param lhs A valid signal object.
     * @param rhs A valid signal object.
     */
    friend void swap(sigh &lhs, sigh &rhs) {
        using std::swap;
        swap(lhs.calls, rhs.calls);
    }

private:
    std::vector<delegate<Ret(Args...)>> calls;
};

}

#endif // ENTT_SIGNAL_SIGH_HPP
<commit_msg>cleanup - thanks to @Kerndog73 (see #267)<commit_after>#ifndef ENTT_SIGNAL_SIGH_HPP
#define ENTT_SIGNAL_SIGH_HPP

#include <algorithm>
#include <utility>
#include <vector>
#include <functional>
#include <type_traits>
#include "../config/config.h"
#include "delegate.hpp"
#include "fwd.hpp"

namespace entt {

/**
 * @cond TURN_OFF_DOXYGEN
 * Internal details not to be documented.
 */

namespace internal {

template<typename, typename>
struct invoker;

template<typename Ret, typename... Args, typename Collector>
struct invoker<Ret(Args...), Collector> {
    bool invoke(Collector &collector, const delegate<Ret(Args...)> &delegate, Args... args) const {
        return collector(delegate(args...));
    }
};

template<typename... Args, typename Collector>
struct invoker<void(Args...), Collector> {
    bool invoke(Collector &, const delegate<void(Args...)> &delegate, Args... args) const {
        return (delegate(args...), true);
    }
};

template<typename Ret>
struct null_collector {
    using result_type = Ret;
    bool operator()(result_type) const ENTT_NOEXCEPT { return true; }
};

template<>
struct null_collector<void> {
    using result_type = void;
    bool operator()() const ENTT_NOEXCEPT { return true; }
};

template<typename>
struct default_collector;

template<typename Ret, typename... Args>
struct default_collector<Ret(Args...)> {
    using collector_type = null_collector<Ret>;
};

template<typename Function>
using default_collector_type = typename default_collector<Function>::collector_type;

}

/**
 * Internal details not to be documented.
 * @endcond TURN_OFF_DOXYGEN
 */

/**
 * @brief Sink implementation.
 *
 * Primary template isn't defined on purpose. All the specializations give a
 * compile-time error unless the template parameter is a function type.
 *
 * @tparam Function A valid function type.
 */
template<typename Function>
class sink;

/**
 * @brief Unmanaged signal handler declaration.
 *
 * Primary template isn't defined on purpose. All the specializations give a
 * compile-time error unless the template parameter is a function type.
 *
 * @tparam Function A valid function type.
 * @tparam Collector Type of collector to use, if any.
 */
template<typename Function, typename Collector = internal::default_collector_type<Function>>
struct sigh;

/**
 * @brief Sink implementation.
 *
 * A sink is an opaque object used to connect listeners to signals.

 * The function type for a listener is the one of the signal to which it
 * belongs.
 *
 * The clear separation between a signal and a sink permits to store the former
 * as private data member without exposing the publish functionality to the
 * users of a class.
 *
 * @tparam Ret Return type of a function type.
 * @tparam Args Types of arguments of a function type.
 */
template<typename Ret, typename... Args>
class sink<Ret(Args...)> {
    /*! @brief A signal is allowed to create sinks. */
    template<typename, typename>
    friend struct sigh;

    sink(std::vector<delegate<Ret(Args...)>> *ref) ENTT_NOEXCEPT
        : calls{ref}
    {}

public:
    /**
     * @brief Returns false if at least a listener is connected to the sink.
     * @return True if the sink has no listeners connected, false otherwise.
     */
    bool empty() const ENTT_NOEXCEPT {
        return calls->empty();
    }

    /**
     * @brief Connects a free function to a signal.
     *
     * The signal handler performs checks to avoid multiple connections for free
     * functions.
     *
     * @tparam Function A valid free function pointer.
     */
    template<auto Function>
    void connect() {
        disconnect<Function>();
        delegate<Ret(Args...)> delegate{};
        delegate.template connect<Function>();
        calls->emplace_back(std::move(delegate));
    }

    /**
     * @brief Connects a member function or a free function with payload to a
     * signal.
     *
     * The signal isn't responsible for the connected object or the payload.
     * Users must always guarantee that the lifetime of the instance overcomes
     * the one  of the delegate. On the other side, the signal handler performs
     * checks to avoid multiple connections for the same function.

     * When used to connect a free function with payload, its signature must be
     * such that the instance is the first argument before the ones used to
     * define the delegate itself.
     *
     * @tparam Candidate Member or free function to connect to the signal.
     * @tparam Type Type of class or type of payload.
     * @param value_or_instance A valid pointer that fits the purpose.
     */
    template<auto Candidate, typename Type>
    void connect(Type *value_or_instance) {
        disconnect<Candidate>(value_or_instance);
        delegate<Ret(Args...)> delegate{};
        delegate.template connect<Candidate>(value_or_instance);
        calls->emplace_back(std::move(delegate));
    }

    /**
     * @brief Disconnects a free function from a signal.
     * @tparam Function A valid free function pointer.
     */
    template<auto Function>
    void disconnect() {
        delegate<Ret(Args...)> delegate{};
        delegate.template connect<Function>();
        calls->erase(std::remove(calls->begin(), calls->end(), std::move(delegate)), calls->end());
    }

    /**
     * @brief Disconnects a member function or a free function with payload from
     * a signal.
     * @tparam Candidate Member or free function to disconnect from the signal.
     * @tparam Type Type of class or type of payload.
     * @param value_or_instance A valid pointer that fits the purpose.
     */
    template<auto Candidate, typename Type>
    void disconnect(Type *value_or_instance) {
        delegate<Ret(Args...)> delegate{};
        delegate.template connect<Candidate>(value_or_instance);
        calls->erase(std::remove_if(calls->begin(), calls->end(), [delegate](const auto &other) {
            return other == delegate && other.instance() == delegate.instance();
        }), calls->end());
    }

    /**
     * @brief Disconnects member functions or free functions based on an
     * instance or specific payload.
     * @param value_or_instance A valid pointer that fits the purpose.
     */
    void disconnect(const void *value_or_instance) {
        calls->erase(std::remove_if(calls->begin(), calls->end(), [value_or_instance](const auto &delegate) {
            return value_or_instance == delegate.instance();
        }), calls->end());
    }

    /*! @brief Disconnects all the listeners from a signal. */
    void disconnect() {
        calls->clear();
    }

private:
    std::vector<delegate<Ret(Args...)>> *calls;
};

/**
 * @brief Unmanaged signal handler definition.
 *
 * Unmanaged signal handler. It works directly with naked pointers to classes
 * and pointers to member functions as well as pointers to free functions. Users
 * of this class are in charge of disconnecting instances before deleting them.
 *
 * This class serves mainly two purposes:
 *
 * * Creating signals used later to notify a bunch of listeners.
 * * Collecting results from a set of functions like in a voting system.
 *
 * The default collector does nothing. To properly collect data, define and use
 * a class that has a call operator the signature of which is `bool(Param)` and:
 *
 * * `Param` is a type to which `Ret` can be converted.
 * * The return type is true if the handler must stop collecting data, false
 * otherwise.
 *
 * @tparam Ret Return type of a function type.
 * @tparam Args Types of arguments of a function type.
 * @tparam Collector Type of collector to use, if any.
 */
template<typename Ret, typename... Args, typename Collector>
struct sigh<Ret(Args...), Collector>: private internal::invoker<Ret(Args...), Collector> {
    /*! @brief Unsigned integer type. */
    using size_type = typename std::vector<delegate<Ret(Args...)>>::size_type;
    /*! @brief Collector type. */
    using collector_type = Collector;
    /*! @brief Sink type. */
    using sink_type = entt::sink<Ret(Args...)>;

    /**
     * @brief Instance type when it comes to connecting member functions.
     * @tparam Class Type of class to which the member function belongs.
     */
    template<typename Class>
    using instance_type = Class *;

    /**
     * @brief Number of listeners connected to the signal.
     * @return Number of listeners currently connected.
     */
    size_type size() const ENTT_NOEXCEPT {
        return calls.size();
    }

    /**
     * @brief Returns false if at least a listener is connected to the signal.
     * @return True if the signal has no listeners connected, false otherwise.
     */
    bool empty() const ENTT_NOEXCEPT {
        return calls.empty();
    }

    /**
     * @brief Returns a sink object for the given signal.
     *
     * A sink is an opaque object used to connect listeners to signals.

     * The function type for a listener is the one of the signal to which it
     * belongs. The order of invocation of the listeners isn't guaranteed.
     *
     * @return A temporary sink object.
     */
    sink_type sink() ENTT_NOEXCEPT {
        return { &calls };
    }

    /**
     * @brief Triggers a signal.
     *
     * All the listeners are notified. Order isn't guaranteed.
     *
     * @param args Arguments to use to invoke listeners.
     */
    void publish(Args... args) const {
        for(auto pos = calls.size(); pos; --pos) {
            auto &call = calls[pos-1];
            call(args...);
        }
    }

    /**
     * @brief Collects return values from the listeners.
     * @param args Arguments to use to invoke listeners.
     * @return An instance of the collector filled with collected data.
     */
    collector_type collect(Args... args) const {
        collector_type collector;

        for(auto &&call: calls) {
            if(!this->invoke(collector, call, args...)) {
                break;
            }
        }

        return collector;
    }

    /**
     * @brief Swaps listeners between the two signals.
     * @param lhs A valid signal object.
     * @param rhs A valid signal object.
     */
    friend void swap(sigh &lhs, sigh &rhs) {
        using std::swap;
        swap(lhs.calls, rhs.calls);
    }

private:
    std::vector<delegate<Ret(Args...)>> calls;
};

}

#endif // ENTT_SIGNAL_SIGH_HPP
<|endoftext|>


<commit_before>/*
 * cfibentry.cc
 *
 *  Created on: 15.07.2013
 *      Author: andreas
 */

#include <cfibentry.h>

using namespace ethercore;

cfibentry::cfibentry(
		cfibentry_owner *fib,
		uint8_t src_stage_table_id,
		uint8_t dst_stage_table_id,
		rofl::cmacaddr lladdr,
		uint64_t dpid,
		uint16_t vid,
		uint32_t out_port_no,
		bool tagged) :
		fib(fib),
		dpid(dpid),
		vid(vid),
		portno(out_port_no),
		tagged(tagged),
		lladdr(lladdr),
		src_stage_table_id(src_stage_table_id),
		dst_stage_table_id(dst_stage_table_id),
		entry_timeout(CFIBENTRY_DEFAULT_TIMEOUT),
		expiration_timer_id(0)
{
	flow_mod_configure(FLOW_MOD_ADD);

	//expiration_timer_id = register_timer(CFIBENTRY_ENTRY_EXPIRED, entry_timeout);
}

cfibentry::~cfibentry()
{
	flow_mod_configure(FLOW_MOD_DELETE);
#if 0
	rofl::crofbase *rofbase = fib->get_rofbase();
	rofl::crofdpt *dpt = rofbase->dpt_find(dpid);

	rofbase->send_barrier_request(dpt);
#endif
}

void
cfibentry::handle_timeout(int opaque, void *data)
{
	switch (opaque) {
	// intentionally disabled
#if 0
	case CFIBENTRY_ENTRY_EXPIRED: {
		flow_mod_configure(FLOW_MOD_DELETE);
		fib->fib_timer_expired(this);
	} break;
#endif
	}
}

void
cfibentry::set_portno(uint32_t portno)
{
	flow_mod_configure(FLOW_MOD_DELETE);

	this->portno = portno;

#if 0
	// intentionally disabled
	reset_timer(expiration_timer_id, entry_timeout);
#endif

	flow_mod_configure(FLOW_MOD_ADD);
}

void
cfibentry::flow_mod_configure(enum flow_mod_cmd_t flow_mod_cmd)
{
	try {
		rofl::crofbase *rofbase = fib->get_rofbase();
		rofl::crofdpt *dpt = rofbase->dpt_find(dpid);

		if ((NULL == dpt) || (rofl::openflow::OFP_VERSION_UNKNOWN == dpt->get_version())) {
			return;
		}

		rofl::cofflowmod fe(dpt->get_version());

		/* table 'src_stage_table_id':
		 *
		 * if src mac address is already known, move on to next table, otherwise, send packet to controller
		 *
		 * this allows the controller to learn yet unknown src macs when being received on a port
		 */
		if (true) {
			fe.reset();
			switch (flow_mod_cmd) {
			case FLOW_MOD_ADD:		fe.set_command(OFPFC_ADD);				break;
			case FLOW_MOD_MODIFY:	fe.set_command(OFPFC_MODIFY_STRICT); 	break;
			case FLOW_MOD_DELETE:	fe.set_command(OFPFC_DELETE_STRICT);	break;
			}
			fe.set_table_id(src_stage_table_id);
			fe.set_priority(0x8000);
			fe.set_idle_timeout(entry_timeout);
			fe.set_flags(rofl::openflow12::OFPFF_SEND_FLOW_REM);
			fe.match.set_in_port(portno);
			fe.match.set_vlan_vid(vid);
			fe.match.set_eth_src(lladdr); // yes, indeed: set_eth_src for dst
			fe.instructions.add_inst_goto_table().set_table_id(dst_stage_table_id);

			dpt->send_flow_mod_message(fe);
		}

		dpt->send_barrier_request();

		/* table 'dst_stage_table_id':
		 *
		 * add a second rule to dst-stage: checks for destination
		 */
		if (true) {
			fe.reset();
			switch (flow_mod_cmd) {
			case FLOW_MOD_ADD:		fe.set_command(OFPFC_ADD);				break;
			case FLOW_MOD_MODIFY:	fe.set_command(OFPFC_MODIFY_STRICT); 	break;
			case FLOW_MOD_DELETE:	fe.set_command(OFPFC_DELETE_STRICT);	break;
			}
			fe.set_table_id(dst_stage_table_id);
			fe.set_priority(0x8000);
			fe.set_idle_timeout(entry_timeout);
			fe.match.set_vlan_vid(vid);
			fe.match.set_eth_dst(lladdr);
			fe.instructions.add_inst_apply_actions();
			if (not tagged)
				fe.instructions.set_inst_apply_actions().get_actions().append_action_pop_vlan();
			fe.instructions.set_inst_apply_actions().get_actions().append_action_output(portno);

			dpt->send_flow_mod_message(fe);
		}

		dpt->send_barrier_request();

	} catch (rofl::eRofBaseNotFound& e) {

	} catch (rofl::eBadVersion& e) {
		logging::error << "[ethcore][cfibentry] data path already disconnected, unable to remove our entries" << std::endl;
	}
}

<commit_msg>ethcore => cfibentry => removing sending of Barrier Request messages<commit_after>/*
 * cfibentry.cc
 *
 *  Created on: 15.07.2013
 *      Author: andreas
 */

#include <cfibentry.h>

using namespace ethercore;

cfibentry::cfibentry(
		cfibentry_owner *fib,
		uint8_t src_stage_table_id,
		uint8_t dst_stage_table_id,
		rofl::cmacaddr lladdr,
		uint64_t dpid,
		uint16_t vid,
		uint32_t out_port_no,
		bool tagged) :
		fib(fib),
		dpid(dpid),
		vid(vid),
		portno(out_port_no),
		tagged(tagged),
		lladdr(lladdr),
		src_stage_table_id(src_stage_table_id),
		dst_stage_table_id(dst_stage_table_id),
		entry_timeout(CFIBENTRY_DEFAULT_TIMEOUT),
		expiration_timer_id(0)
{
	flow_mod_configure(FLOW_MOD_ADD);

	//expiration_timer_id = register_timer(CFIBENTRY_ENTRY_EXPIRED, entry_timeout);
}

cfibentry::~cfibentry()
{
	flow_mod_configure(FLOW_MOD_DELETE);
#if 0
	rofl::crofbase *rofbase = fib->get_rofbase();
	rofl::crofdpt *dpt = rofbase->dpt_find(dpid);

	//rofbase->send_barrier_request(dpt);
#endif
}

void
cfibentry::handle_timeout(int opaque, void *data)
{
	switch (opaque) {
	// intentionally disabled
#if 0
	case CFIBENTRY_ENTRY_EXPIRED: {
		flow_mod_configure(FLOW_MOD_DELETE);
		fib->fib_timer_expired(this);
	} break;
#endif
	}
}

void
cfibentry::set_portno(uint32_t portno)
{
	flow_mod_configure(FLOW_MOD_DELETE);

	this->portno = portno;

#if 0
	// intentionally disabled
	reset_timer(expiration_timer_id, entry_timeout);
#endif

	flow_mod_configure(FLOW_MOD_ADD);
}

void
cfibentry::flow_mod_configure(enum flow_mod_cmd_t flow_mod_cmd)
{
	try {
		rofl::crofbase *rofbase = fib->get_rofbase();
		rofl::crofdpt *dpt = rofbase->dpt_find(dpid);

		if ((NULL == dpt) || (rofl::openflow::OFP_VERSION_UNKNOWN == dpt->get_version())) {
			return;
		}

		rofl::cofflowmod fe(dpt->get_version());

		/* table 'src_stage_table_id':
		 *
		 * if src mac address is already known, move on to next table, otherwise, send packet to controller
		 *
		 * this allows the controller to learn yet unknown src macs when being received on a port
		 */
		if (true) {
			fe.reset();
			switch (flow_mod_cmd) {
			case FLOW_MOD_ADD:		fe.set_command(OFPFC_ADD);				break;
			case FLOW_MOD_MODIFY:	fe.set_command(OFPFC_MODIFY_STRICT); 	break;
			case FLOW_MOD_DELETE:	fe.set_command(OFPFC_DELETE_STRICT);	break;
			}
			fe.set_table_id(src_stage_table_id);
			fe.set_priority(0x8000);
			fe.set_idle_timeout(entry_timeout);
			fe.set_flags(rofl::openflow12::OFPFF_SEND_FLOW_REM);
			fe.match.set_in_port(portno);
			fe.match.set_vlan_vid(vid);
			fe.match.set_eth_src(lladdr); // yes, indeed: set_eth_src for dst
			fe.instructions.add_inst_goto_table().set_table_id(dst_stage_table_id);

			dpt->send_flow_mod_message(fe);
		}

		//dpt->send_barrier_request();

		/* table 'dst_stage_table_id':
		 *
		 * add a second rule to dst-stage: checks for destination
		 */
		if (true) {
			fe.reset();
			switch (flow_mod_cmd) {
			case FLOW_MOD_ADD:		fe.set_command(OFPFC_ADD);				break;
			case FLOW_MOD_MODIFY:	fe.set_command(OFPFC_MODIFY_STRICT); 	break;
			case FLOW_MOD_DELETE:	fe.set_command(OFPFC_DELETE_STRICT);	break;
			}
			fe.set_table_id(dst_stage_table_id);
			fe.set_priority(0x8000);
			fe.set_idle_timeout(entry_timeout);
			fe.match.set_vlan_vid(vid);
			fe.match.set_eth_dst(lladdr);
			fe.instructions.add_inst_apply_actions();
			if (not tagged)
				fe.instructions.set_inst_apply_actions().get_actions().append_action_pop_vlan();
			fe.instructions.set_inst_apply_actions().get_actions().append_action_output(portno);

			dpt->send_flow_mod_message(fe);
		}

		//dpt->send_barrier_request();

	} catch (rofl::eRofBaseNotFound& e) {

	} catch (rofl::eBadVersion& e) {
		logging::error << "[ethcore][cfibentry] data path already disconnected, unable to remove our entries" << std::endl;
	}
}

<|endoftext|>


<commit_before>/*
 * MRustC - Rust Compiler
 * - By John Hodge (Mutabah/thePowersGang)
 *
 * synexts/lang_item.cpp
 * - Binds language items to #[lang_item] tagged items
 */
#include <synext.hpp>
#include "../common.hpp"
#include "../ast/ast.hpp"
#include "../ast/crate.hpp"

void handle_lang_item(const Span& sp, AST::Crate& crate, const AST::Path& path, const ::std::string& name, AST::eItemType type)
{
    if(name == "phantom_fn") {
        // - Just save path
    }
    else if( name == "send" ) {
        // Don't care, Send is fully library in mrustc
        // - Needed for `static`
    }
    else if( name == "sync" ) {
        // Don't care, Sync is fully library in mrustc
        // - Needed for `static`
    }
    else if( name == "sized" ) {
        DEBUG("Bind 'sized' to " << path);
    }
    else if( name == "copy" ) {
        DEBUG("Bind 'copy' to " << path);
    }
    // ops traits
    else if( name == "drop" ) { DEBUG("Bind '"<<name<<"' to " << path); }
    else if( name == "add" ) { DEBUG("Bind '"<<name<<"' to " << path); }
    else if( name == "sub" ) { DEBUG("Bind '"<<name<<"' to " << path); }
    else if( name == "mul" ) { DEBUG("Bind '"<<name<<"' to " << path); }
    else if( name == "div" ) { DEBUG("Bind '"<<name<<"' to " << path); }
    else if( name == "rem" ) { DEBUG("Bind '"<<name<<"' to " << path); }

    else if( name == "neg" ) { DEBUG("Bind '"<<name<<"' to " << path); }
    else if( name == "not" ) { DEBUG("Bind '"<<name<<"' to " << path); }

    else if( name == "bitand" ) { DEBUG("Bind '"<<name<<"' to " << path); }
    else if( name == "bitor"  ) { DEBUG("Bind '"<<name<<"' to " << path); }
    else if( name == "bitxor" ) { DEBUG("Bind '"<<name<<"' to " << path); }
    else if( name == "shl" ) { DEBUG("Bind '"<<name<<"' to " << path); }
    else if( name == "shr" ) { DEBUG("Bind '"<<name<<"' to " << path); }

    else if( name == "add_assign" ) { DEBUG("Bind '"<<name<<"' to " << path); }
    else if( name == "sub_assign" ) { DEBUG("Bind '"<<name<<"' to " << path); }
    else if( name == "div_assign" ) { DEBUG("Bind '"<<name<<"' to " << path); }
    else if( name == "rem_assign" ) { DEBUG("Bind '"<<name<<"' to " << path); }
    else if( name == "mul_assign" ) { DEBUG("Bind '"<<name<<"' to " << path); }
    else if( name == "bitand_assign" ) { DEBUG("Bind '"<<name<<"' to " << path); }
    else if( name == "bitor_assign" ) { DEBUG("Bind '"<<name<<"' to " << path); }
    else if( name == "bitxor_assign" ) { DEBUG("Bind '"<<name<<"' to " << path); }
    else if( name == "shl_assign" ) { DEBUG("Bind '"<<name<<"' to " << path); }
    else if( name == "shr_assign" ) { DEBUG("Bind '"<<name<<"' to " << path); }

    else if( name == "index" ) { DEBUG("Bind '"<<name<<"' to " << path); }
    else if( name == "deref" ) { DEBUG("Bind '"<<name<<"' to " << path); }
    else if( name == "index_mut" ) { DEBUG("Bind '"<<name<<"' to " << path); }
    else if( name == "deref_mut" ) { DEBUG("Bind '"<<name<<"' to " << path); }
    else if( name == "fn"      ) { DEBUG("Bind '"<<name<<"' to " << path); }
    else if( name == "fn_mut"  ) { DEBUG("Bind '"<<name<<"' to " << path); }
    else if( name == "fn_once" ) { DEBUG("Bind '"<<name<<"' to " << path); }

    else if( name == "eq"  ) { DEBUG("Bind '"<<name<<"' to " << path); }
    else if( name == "ord" ) { DEBUG("Bind '"<<name<<"' to " << path); }
    else if( name == "unsize" ) { DEBUG("Bind '"<<name<<"' to " << path); }
    else if( name == "coerce_unsized" ) { DEBUG("Bind '"<<name<<"' to " << path); }

    else if( name == "iterator" ) { /* mrustc just desugars? */ }

    else if( name == "debug_trait" ) { /* TODO: Poke derive() with this */ }

    // Structs
    else if( name == "non_zero" ) { }
    else if( name == "phantom_data" ) { }
    else if( name == "range_full" ) { }
    else if( name == "range" ) { }
    else if( name == "range_from" ) { }
    else if( name == "range_to" ) { }
    else if( name == "unsafe_cell" ) { }

    // Functions
    else if( name == "panic" ) { }
    else if( name == "panic_bounds_check" ) { }
    else if( name == "panic_fmt" ) { }
    else if( name == "str_eq" ) { }
    // - builtin `box` support
    else if( name == "exchange_malloc" ) { }
    else if( name == "exchange_free" ) { }
    else if( name == "box_free" ) { }
    else if( name == "owned_box" ) { }

    else {
        ERROR(sp, E0000, "Unknown language item '" << name << "'");
    }

    auto rv = crate.m_lang_items.insert( ::std::make_pair( name, ::AST::Path(path) ) );
    if( !rv.second ) {
        ERROR(sp, E0000, "Duplicate definition of language item '" << name << "'");
    }
}

class Decorator_LangItem:
    public ExpandDecorator
{
public:
    AttrStage stage() const override { return AttrStage::EarlyPost; }
    void handle(const Span& sp, const AST::MetaItem& attr, AST::Crate& crate, const AST::Path& path, AST::Module& mod, AST::Item& i) const override
    {
        TU_MATCH_DEF(::AST::Item, (i), (e),
        (
            TODO(sp, "Unknown item type with #[lang=\""<<attr<<"\"] attached at " << path);
            ),
        (Function,
            handle_lang_item(sp, crate, path, attr.string(), AST::ITEM_FN);
            ),
        (Struct,
            handle_lang_item(sp, crate, path, attr.string(), AST::ITEM_STRUCT);
            ),
        (Trait,
            handle_lang_item(sp, crate, path, attr.string(), AST::ITEM_TRAIT);
            )
        )
    }

    void handle(const Span& sp, const AST::MetaItem& mi, AST::Crate& crate, const AST::Module& mod, AST::ImplDef& impl) const override {
        const ::std::string& name = mi.string();

             if( name == "i8" ) {}
        else if( name == "u8" ) {}
        else if( name == "i16" ) {}
        else if( name == "u16" ) {}
        else if( name == "i32" ) {}
        else if( name == "u32" ) {}
        else if( name == "i64" ) {}
        else if( name == "u64" ) {}
        else if( name == "isize" ) {}
        else if( name == "usize" ) {}
        else if( name == "const_ptr" ) {}
        else if( name == "mut_ptr" ) {}
        // rustc_unicode
        else if( name == "char" ) {}
        // collections
        //else if( name == "str" ) {}
        //else if( name == "slice" ) {}
        else {
            ERROR(sp, E0000, "Unknown lang item '" << name << "' on impl");
        }

        // TODO: Somehow annotate these impls to allow them to provide inherents?
    }
};

STATIC_DECORATOR("lang", Decorator_LangItem)

<commit_msg>Expand/lang - libcollections impl lang items<commit_after>/*
 * MRustC - Rust Compiler
 * - By John Hodge (Mutabah/thePowersGang)
 *
 * synexts/lang_item.cpp
 * - Binds language items to #[lang_item] tagged items
 */
#include <synext.hpp>
#include "../common.hpp"
#include "../ast/ast.hpp"
#include "../ast/crate.hpp"

void handle_lang_item(const Span& sp, AST::Crate& crate, const AST::Path& path, const ::std::string& name, AST::eItemType type)
{
    if(name == "phantom_fn") {
        // - Just save path
    }
    else if( name == "send" ) {
        // Don't care, Send is fully library in mrustc
        // - Needed for `static`
    }
    else if( name == "sync" ) {
        // Don't care, Sync is fully library in mrustc
        // - Needed for `static`
    }
    else if( name == "sized" ) {
        DEBUG("Bind 'sized' to " << path);
    }
    else if( name == "copy" ) {
        DEBUG("Bind 'copy' to " << path);
    }
    // ops traits
    else if( name == "drop" ) { DEBUG("Bind '"<<name<<"' to " << path); }
    else if( name == "add" ) { DEBUG("Bind '"<<name<<"' to " << path); }
    else if( name == "sub" ) { DEBUG("Bind '"<<name<<"' to " << path); }
    else if( name == "mul" ) { DEBUG("Bind '"<<name<<"' to " << path); }
    else if( name == "div" ) { DEBUG("Bind '"<<name<<"' to " << path); }
    else if( name == "rem" ) { DEBUG("Bind '"<<name<<"' to " << path); }

    else if( name == "neg" ) { DEBUG("Bind '"<<name<<"' to " << path); }
    else if( name == "not" ) { DEBUG("Bind '"<<name<<"' to " << path); }

    else if( name == "bitand" ) { DEBUG("Bind '"<<name<<"' to " << path); }
    else if( name == "bitor"  ) { DEBUG("Bind '"<<name<<"' to " << path); }
    else if( name == "bitxor" ) { DEBUG("Bind '"<<name<<"' to " << path); }
    else if( name == "shl" ) { DEBUG("Bind '"<<name<<"' to " << path); }
    else if( name == "shr" ) { DEBUG("Bind '"<<name<<"' to " << path); }

    else if( name == "add_assign" ) { DEBUG("Bind '"<<name<<"' to " << path); }
    else if( name == "sub_assign" ) { DEBUG("Bind '"<<name<<"' to " << path); }
    else if( name == "div_assign" ) { DEBUG("Bind '"<<name<<"' to " << path); }
    else if( name == "rem_assign" ) { DEBUG("Bind '"<<name<<"' to " << path); }
    else if( name == "mul_assign" ) { DEBUG("Bind '"<<name<<"' to " << path); }
    else if( name == "bitand_assign" ) { DEBUG("Bind '"<<name<<"' to " << path); }
    else if( name == "bitor_assign" ) { DEBUG("Bind '"<<name<<"' to " << path); }
    else if( name == "bitxor_assign" ) { DEBUG("Bind '"<<name<<"' to " << path); }
    else if( name == "shl_assign" ) { DEBUG("Bind '"<<name<<"' to " << path); }
    else if( name == "shr_assign" ) { DEBUG("Bind '"<<name<<"' to " << path); }

    else if( name == "index" ) { DEBUG("Bind '"<<name<<"' to " << path); }
    else if( name == "deref" ) { DEBUG("Bind '"<<name<<"' to " << path); }
    else if( name == "index_mut" ) { DEBUG("Bind '"<<name<<"' to " << path); }
    else if( name == "deref_mut" ) { DEBUG("Bind '"<<name<<"' to " << path); }
    else if( name == "fn"      ) { DEBUG("Bind '"<<name<<"' to " << path); }
    else if( name == "fn_mut"  ) { DEBUG("Bind '"<<name<<"' to " << path); }
    else if( name == "fn_once" ) { DEBUG("Bind '"<<name<<"' to " << path); }

    else if( name == "eq"  ) { DEBUG("Bind '"<<name<<"' to " << path); }
    else if( name == "ord" ) { DEBUG("Bind '"<<name<<"' to " << path); }
    else if( name == "unsize" ) { DEBUG("Bind '"<<name<<"' to " << path); }
    else if( name == "coerce_unsized" ) { DEBUG("Bind '"<<name<<"' to " << path); }

    else if( name == "iterator" ) { /* mrustc just desugars? */ }

    else if( name == "debug_trait" ) { /* TODO: Poke derive() with this */ }

    // Structs
    else if( name == "non_zero" ) { }
    else if( name == "phantom_data" ) { }
    else if( name == "range_full" ) { }
    else if( name == "range" ) { }
    else if( name == "range_from" ) { }
    else if( name == "range_to" ) { }
    else if( name == "unsafe_cell" ) { }

    // Functions
    else if( name == "panic" ) { }
    else if( name == "panic_bounds_check" ) { }
    else if( name == "panic_fmt" ) { }
    else if( name == "str_eq" ) { }
    // - builtin `box` support
    else if( name == "exchange_malloc" ) { }
    else if( name == "exchange_free" ) { }
    else if( name == "box_free" ) { }
    else if( name == "owned_box" ) { }

    else {
        ERROR(sp, E0000, "Unknown language item '" << name << "'");
    }

    auto rv = crate.m_lang_items.insert( ::std::make_pair( name, ::AST::Path(path) ) );
    if( !rv.second ) {
        ERROR(sp, E0000, "Duplicate definition of language item '" << name << "'");
    }
}

class Decorator_LangItem:
    public ExpandDecorator
{
public:
    AttrStage stage() const override { return AttrStage::EarlyPost; }
    void handle(const Span& sp, const AST::MetaItem& attr, AST::Crate& crate, const AST::Path& path, AST::Module& mod, AST::Item& i) const override
    {
        TU_MATCH_DEF(::AST::Item, (i), (e),
        (
            TODO(sp, "Unknown item type with #[lang=\""<<attr<<"\"] attached at " << path);
            ),
        (Function,
            handle_lang_item(sp, crate, path, attr.string(), AST::ITEM_FN);
            ),
        (Struct,
            handle_lang_item(sp, crate, path, attr.string(), AST::ITEM_STRUCT);
            ),
        (Trait,
            handle_lang_item(sp, crate, path, attr.string(), AST::ITEM_TRAIT);
            )
        )
    }

    void handle(const Span& sp, const AST::MetaItem& mi, AST::Crate& crate, const AST::Module& mod, AST::ImplDef& impl) const override {
        const ::std::string& name = mi.string();

             if( name == "i8" ) {}
        else if( name == "u8" ) {}
        else if( name == "i16" ) {}
        else if( name == "u16" ) {}
        else if( name == "i32" ) {}
        else if( name == "u32" ) {}
        else if( name == "i64" ) {}
        else if( name == "u64" ) {}
        else if( name == "isize" ) {}
        else if( name == "usize" ) {}
        else if( name == "const_ptr" ) {}
        else if( name == "mut_ptr" ) {}
        // rustc_unicode
        else if( name == "char" ) {}
        // collections
        else if( name == "str" ) {}
        else if( name == "slice" ) {}
        else {
            ERROR(sp, E0000, "Unknown lang item '" << name << "' on impl");
        }

        // TODO: Somehow annotate these impls to allow them to provide inherents?
    }
};

STATIC_DECORATOR("lang", Decorator_LangItem)

<|endoftext|>