<commit_before>#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>

#include "config.h"

#include "parse.hpp"
#include "ast.hpp"
#include "parse_op.hpp"
#include "peg.hpp"
#include "expand.hpp"

extern "C" {
//#include <gc_backptr.h>
  void GC_dump();
  extern unsigned GC_alloc_count;
}

//#include "symbol_table.hpp"

void parse_maps(ast::Environ & env) {
  SourceFile * code = new_source_file(SOURCE_PREFIX "grammer.ins");
  const char * s = code->begin();
  try {
    while (s != code->end()) {
      parse_parse::Res r = parse_parse::parse(SourceStr(code, s, code->end()));
      read_macro(r.parse, env);
      s = r.end;
    }
  } catch (Error * err) {
    fprintf(stderr, "%s\n", err->message().c_str());
    exit(1);
  }
}

int main(int argc, const char *argv[])
{
  GC_disable();
  //GC_free_space_divisor = 32;

  assert(setvbuf(stdin, 0, _IOLBF, 0) == 0);
  assert(setvbuf(stdout, 0, _IOLBF, 0) == 0);
  parse_exp_->init();
  ast::Environ env;
  try {
    parse_peg(SOURCE_PREFIX "grammer.in");
  } catch (Error * err) {
    fprintf(stderr, "%s\n", err->message().c_str());
    exit(1);
  }
  SourceFile * prelude = new_source_file(SOURCE_PREFIX "prelude.zlh");
  SourceFile * code = NULL;
  try {
    unsigned offset = 1;
    bool debug_mode = false;
    bool zls_mode = false;
    bool for_ct = false;
    bool load_prelude = true;
    if (argc > offset && strcmp(argv[offset], "-d") == 0) {
      debug_mode = true;
      offset++;
    }
    if (argc > offset && strcmp(argv[offset], "-s") == 0) {
      zls_mode = true;
        offset++;
    }
    if (argc > offset && strcmp(argv[offset], "-C") == 0) {
      for_ct = true;
        offset++;
    }
    if (argc > offset && strcmp(argv[offset], "-P") == 0) {
      load_prelude = false;
      offset++;
    }
    String base_name;
    String output_fn;
    if (argc > offset) {
      code = new_source_file(argv[offset]);
      const char * dot = strrchr(argv[offset], '.');
      if (!dot) {
          base_name = argv[offset];
          output_fn = base_name;
      } else {
        StringBuf buf;
        buf.append(argv[offset], dot);
        base_name = buf.freeze(); // will also reset buf
        if (strcmp(dot, ".zls") == 0)
          buf.append(argv[offset]);
        else
          buf.append(argv[offset], dot);
        buf.append(".zls");
        output_fn = buf.freeze();
      }
    } else {
        code = new_source_file(STDIN_FILENO);
        output_fn = "a.out.zls";
    }
    //const Syntax * res = parse_str("TEST", SourceStr(code->entity(), code->begin(), code->end()));
    //res->print();
    //printf("\n");
    //exit(0);
    //printf("%d\n%s", ast::MACRO_PRELUDE_END - ast::MACRO_PRELUDE, ast::MACRO_PRELUDE);
    if (zls_mode) {
      printf("ZLS MODE\n");
      parse_stmts_raw(SourceStr(code, code->begin(), code->end()), env);
    } else {
      parse_maps(env);
      parse_stmts(parse_str("SLIST", SourceStr(prelude, prelude->begin(), prelude->end())),env);
      if (debug_mode && load_prelude) {
        SourceFile * prelude_body = new_source_file(SOURCE_PREFIX "prelude.zl");
        parse_stmts(parse_str("SLIST", SourceStr(prelude_body, prelude_body->begin(), prelude_body->end())), env);
        //SourceFile * class_body = new_source_file(SOURCE_PREFIX "class.zl");
        //parse_stmts(parse_str("SLIST", SourceStr(class_body, class_body->begin(), class_body->end())), env);
      } else if (load_prelude) {
        load_macro_lib(SOURCE_PREFIX "prelude-fct.so", env);
      }
      //if (load_prelude && !for_ct)
        //ast::import_file(SOURCE_PREFIX "test/class-new_abi.zl", env);
        //ast::include_file(SOURCE_PREFIX "test/class-this_reg.zlh", env);
      parse_stmts(parse_str("SLIST", SourceStr(code, code->begin(), code->end())),env);
    }
    ast::CompileWriter out;
    out.open(output_fn, "w");
    if (for_ct)
      out.for_macro_sep_c = new ast::CompileWriter::ForMacroSepC;
    //printf("FORCING COLLECTION\n");
    //GC_gcollect();
    //GC_dump();
    ast::compile(env.top_level_symbols, out);
    //ast::CompileWriter out2(ast::CompileWriter::ZLE);
    //out2.open("a.out.zle", "w");
    //ast::compile(env.top_level_symbols, out2);
    //AST::ExecEnviron env;
    //ast->eval(env);
    if (for_ct) {
      out.close();
      StringBuf buf;
      buf.printf("zls -g -fexceptions -shared -fpic -o %s-fct.so %s", ~base_name, ~output_fn);
      String line = buf.freeze();
      printf("%s\n", ~line);
      int res = system(~line);
      if (res == -1) {
        perror("system(\"zls ...\")");
        exit(2);
      } else if (res != 0) {
        exit(1);
      }
    }
    out.for_macro_sep_c = NULL;

    //fprintf(stderr, "---------------------------------------------\n");
    //GC_generate_random_backtrace();
    //fprintf(stderr, "---------------------------------------------\n");
    //GC_generate_random_backtrace();
    //fprintf(stderr, "---------------------------------------------\n");
    //GC_generate_random_backtrace();
    //fprintf(stderr, "---------------------------------------------\n");
    //GC_generate_random_backtrace();
    //fprintf(stderr, "---------------------------------------------\n");
    //GC_generate_random_backtrace();
    //fprintf(stderr, "---------------------------------------------\n");

  } catch (Error * err) {
    //if (!err->source)
    //  err->source = code->entity();
    fprintf(stderr, "%s\n", err->message().c_str());
    exit(2);
  }

  //sleep(600);
}

// int main(int argc, const char *argv[])
// {
//   printf("%u %u %u\n", sizeof(Syntax), sizeof(Syntax::D), sizeof(Syntax::Data));
//   printf("XXX %u\n", sizeof(SymbolName));
//   printf("XXX %u\n", sizeof(SourceStr));
//   Syntax syn;

//   int res = main2(argc,argv);

//   printf("FORCING COLLECTION 2\n");
//   GC_gcollect();

// //   fprintf(stderr, "---------------------------------------------\n");
// //   GC_generate_random_backtrace();
// //   fprintf(stderr, "---------------------------------------------\n");
// //   GC_generate_random_backtrace();
// //   fprintf(stderr, "---------------------------------------------\n");
// //   GC_generate_random_backtrace();
// //   fprintf(stderr, "---------------------------------------------\n");
// //   GC_generate_random_backtrace();
// //   fprintf(stderr, "---------------------------------------------\n");
// //   GC_generate_random_backtrace();
// //   fprintf(stderr, "---------------------------------------------\n");

//   return res;
// }

<commit_msg>Reenable GC.<commit_after>#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>

#include "config.h"

#include "parse.hpp"
#include "ast.hpp"
#include "parse_op.hpp"
#include "peg.hpp"
#include "expand.hpp"

extern "C" {
//#include <gc_backptr.h>
  void GC_dump();
  extern unsigned GC_alloc_count;
}

//#include "symbol_table.hpp"

void parse_maps(ast::Environ & env) {
  SourceFile * code = new_source_file(SOURCE_PREFIX "grammer.ins");
  const char * s = code->begin();
  try {
    while (s != code->end()) {
      parse_parse::Res r = parse_parse::parse(SourceStr(code, s, code->end()));
      read_macro(r.parse, env);
      s = r.end;
    }
  } catch (Error * err) {
    fprintf(stderr, "%s\n", err->message().c_str());
    exit(1);
  }
}

int main(int argc, const char *argv[])
{
  //GC_disable();
  //GC_free_space_divisor = 32;

  assert(setvbuf(stdin, 0, _IOLBF, 0) == 0);
  assert(setvbuf(stdout, 0, _IOLBF, 0) == 0);
  parse_exp_->init();
  ast::Environ env;
  try {
    parse_peg(SOURCE_PREFIX "grammer.in");
  } catch (Error * err) {
    fprintf(stderr, "%s\n", err->message().c_str());
    exit(1);
  }
  SourceFile * prelude = new_source_file(SOURCE_PREFIX "prelude.zlh");
  SourceFile * code = NULL;
  try {
    unsigned offset = 1;
    bool debug_mode = false;
    bool zls_mode = false;
    bool for_ct = false;
    bool load_prelude = true;
    if (argc > offset && strcmp(argv[offset], "-d") == 0) {
      debug_mode = true;
      offset++;
    }
    if (argc > offset && strcmp(argv[offset], "-s") == 0) {
      zls_mode = true;
        offset++;
    }
    if (argc > offset && strcmp(argv[offset], "-C") == 0) {
      for_ct = true;
        offset++;
    }
    if (argc > offset && strcmp(argv[offset], "-P") == 0) {
      load_prelude = false;
      offset++;
    }
    String base_name;
    String output_fn;
    if (argc > offset) {
      code = new_source_file(argv[offset]);
      const char * dot = strrchr(argv[offset], '.');
      if (!dot) {
          base_name = argv[offset];
          output_fn = base_name;
      } else {
        StringBuf buf;
        buf.append(argv[offset], dot);
        base_name = buf.freeze(); // will also reset buf
        if (strcmp(dot, ".zls") == 0)
          buf.append(argv[offset]);
        else
          buf.append(argv[offset], dot);
        buf.append(".zls");
        output_fn = buf.freeze();
      }
    } else {
        code = new_source_file(STDIN_FILENO);
        output_fn = "a.out.zls";
    }
    //const Syntax * res = parse_str("TEST", SourceStr(code->entity(), code->begin(), code->end()));
    //res->print();
    //printf("\n");
    //exit(0);
    //printf("%d\n%s", ast::MACRO_PRELUDE_END - ast::MACRO_PRELUDE, ast::MACRO_PRELUDE);
    if (zls_mode) {
      printf("ZLS MODE\n");
      parse_stmts_raw(SourceStr(code, code->begin(), code->end()), env);
    } else {
      parse_maps(env);
      parse_stmts(parse_str("SLIST", SourceStr(prelude, prelude->begin(), prelude->end())),env);
      if (debug_mode && load_prelude) {
        SourceFile * prelude_body = new_source_file(SOURCE_PREFIX "prelude.zl");
        parse_stmts(parse_str("SLIST", SourceStr(prelude_body, prelude_body->begin(), prelude_body->end())), env);
        //SourceFile * class_body = new_source_file(SOURCE_PREFIX "class.zl");
        //parse_stmts(parse_str("SLIST", SourceStr(class_body, class_body->begin(), class_body->end())), env);
      } else if (load_prelude) {
        load_macro_lib(SOURCE_PREFIX "prelude-fct.so", env);
      }
      //if (load_prelude && !for_ct)
        //ast::import_file(SOURCE_PREFIX "test/class-new_abi.zl", env);
        //ast::include_file(SOURCE_PREFIX "test/class-this_reg.zlh", env);
      parse_stmts(parse_str("SLIST", SourceStr(code, code->begin(), code->end())),env);
    }
    ast::CompileWriter out;
    out.open(output_fn, "w");
    if (for_ct)
      out.for_macro_sep_c = new ast::CompileWriter::ForMacroSepC;
    //printf("FORCING COLLECTION\n");
    //GC_gcollect();
    //GC_dump();
    ast::compile(env.top_level_symbols, out);
    //ast::CompileWriter out2(ast::CompileWriter::ZLE);
    //out2.open("a.out.zle", "w");
    //ast::compile(env.top_level_symbols, out2);
    //AST::ExecEnviron env;
    //ast->eval(env);
    if (for_ct) {
      out.close();
      StringBuf buf;
      buf.printf("zls -g -fexceptions -shared -fpic -o %s-fct.so %s", ~base_name, ~output_fn);
      String line = buf.freeze();
      printf("%s\n", ~line);
      int res = system(~line);
      if (res == -1) {
        perror("system(\"zls ...\")");
        exit(2);
      } else if (res != 0) {
        exit(1);
      }
    }
    out.for_macro_sep_c = NULL;

    //fprintf(stderr, "---------------------------------------------\n");
    //GC_generate_random_backtrace();
    //fprintf(stderr, "---------------------------------------------\n");
    //GC_generate_random_backtrace();
    //fprintf(stderr, "---------------------------------------------\n");
    //GC_generate_random_backtrace();
    //fprintf(stderr, "---------------------------------------------\n");
    //GC_generate_random_backtrace();
    //fprintf(stderr, "---------------------------------------------\n");
    //GC_generate_random_backtrace();
    //fprintf(stderr, "---------------------------------------------\n");

  } catch (Error * err) {
    //if (!err->source)
    //  err->source = code->entity();
    fprintf(stderr, "%s\n", err->message().c_str());
    exit(2);
  }

  //sleep(600);
}

// int main(int argc, const char *argv[])
// {
//   printf("%u %u %u\n", sizeof(Syntax), sizeof(Syntax::D), sizeof(Syntax::Data));
//   printf("XXX %u\n", sizeof(SymbolName));
//   printf("XXX %u\n", sizeof(SourceStr));
//   Syntax syn;

//   int res = main2(argc,argv);

//   printf("FORCING COLLECTION 2\n");
//   GC_gcollect();

// //   fprintf(stderr, "---------------------------------------------\n");
// //   GC_generate_random_backtrace();
// //   fprintf(stderr, "---------------------------------------------\n");
// //   GC_generate_random_backtrace();
// //   fprintf(stderr, "---------------------------------------------\n");
// //   GC_generate_random_backtrace();
// //   fprintf(stderr, "---------------------------------------------\n");
// //   GC_generate_random_backtrace();
// //   fprintf(stderr, "---------------------------------------------\n");
// //   GC_generate_random_backtrace();
// //   fprintf(stderr, "---------------------------------------------\n");

//   return res;
// }

<|endoftext|>


<commit_before>9d7aeba3-4b02-11e5-bf4c-28cfe9171a43<commit_msg>Did ANOTHER thing<commit_after>9d8b2a33-4b02-11e5-b38b-28cfe9171a43<|endoftext|>


<commit_before>#include <fstream>
#include <iostream>
#include <sstream>
#include <string>
#include <vector>
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <map>

void parse_data(std::ifstream &instream_data, std::vector <std::vector <std::string> >& vec_data,
	std::map<std::string, std::vector <std::vector <std::string> > >& map_data){
	int count=0;
	while (instream_data){
		std::string s;
	    if (!getline( instream_data, s )){
	    	break;
	    }
	    std::istringstream ss( s );
	    std::vector <std::string> record;
	    while (ss){
	      std::string s;
	      if (!getline( ss, s, ',' )){
	      	break;
	      }
	      record.push_back( s );
	    }
	    vec_data.push_back(record);
	    std::string full_name= vec_data[count][1];
	    std::string modified_name="";
	    int x=0;
	    while(x<full_name.size()){
	    	if(full_name[x]!='\\'){
	    		modified_name.push_back(full_name[x]);
	    	}else{
	    		modified_name.pop_back();
	    		break;
	    	}
	    	x++;
	    }
		map_data.insert(std::make_pair(modified_name, vec_data));
		count++;
	}
}

int main(){
	std::vector <std::vector <std::string> > data;
	std::map<std::string, std::vector <std::vector <std::string> > > map_player_salary;

	std::vector <std::vector <std::string> > pitcher_data;
	std::map<std::string, std::vector <std::vector <std::string> > > map_pitcher_player;

	std::vector <std::vector <std::string> > batter_data;
	std::map<std::string, std::vector <std::vector <std::string> > > map_batter_player;

	std::ifstream infile( "2017_MLB_Player_Salary_Info.md" );
	std::ifstream infile_pitcher( "2017_MLB_Pitcher_Info.md" );
	std::ifstream infile_batter( "2017_MLB_Batter_Info.md" );

	//parse_data for salary info
	parse_data(infile, data, map_player_salary);

	//test if player salary data works
	for(int x=0; x<data.size(); x++){
		if((data[x][21])!=""){
			std::cout<<"Name: "<< data[x][1]<<" Salary: "<< data[x][21]<<std::endl;
		}
	}
	if(map_player_salary.find("Clayton Kershaw")!=map_player_salary.end()){
		std::cout<<"map works!!"<<std::endl;
	}

	//parse data for pitcher info
	parse_data(infile_pitcher, pitcher_data, map_pitcher_player);

	//test if pitcher player data works
	for(int x=0; x<pitcher_data.size(); x++){
		if((pitcher_data[x][1])!="Name"){
			std::cout<<"Name: "<< pitcher_data[x][1]<<" ERA: "<< pitcher_data[x][8]<<std::endl;
		}
	}
	if(map_pitcher_player.find("Mike Wright")!=map_pitcher_player.end()){
		std::cout<<"map works!!"<<std::endl;
	}

	//parse data for batter info
	parse_data(infile_batter, batter_data, map_batter_player);

	//test if pitcher player data works
	for(int x=0; x<pitcher_data.size(); x++){
		if((pitcher_data[x][1])!="Name"){
			std::cout<<"Name: "<< pitcher_data[x][1]<<" ERA: "<< pitcher_data[x][8]<<std::endl;
		}
	}
	if(map_pitcher_player.find("Mike Wright")!=map_pitcher_player.end()){
		std::cout<<"map works!!"<<std::endl;
	}

	return 0;
}
<commit_msg>Added batter testing info<commit_after>#include <fstream>
#include <iostream>
#include <sstream>
#include <string>
#include <vector>
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <map>

void parse_data(std::ifstream &instream_data, std::vector <std::vector <std::string> >& vec_data,
	std::map<std::string, std::vector <std::vector <std::string> > >& map_data){
	int count=0;
	while (instream_data){
		std::string s;
	    if (!getline( instream_data, s )){
	    	break;
	    }
	    std::istringstream ss( s );
	    std::vector <std::string> record;
	    while (ss){
	      std::string s;
	      if (!getline( ss, s, ',' )){
	      	break;
	      }
	      record.push_back( s );
	    }
	    vec_data.push_back(record);
	    std::string full_name= vec_data[count][1];
	    std::string modified_name="";
	    int x=0;
	    while(x<full_name.size()){
	    	if(full_name[x]!='\\'){
	    		modified_name.push_back(full_name[x]);
	    	}else{
	    		modified_name.pop_back();
	    		break;
	    	}
	    	x++;
	    }
		map_data.insert(std::make_pair(modified_name, vec_data));
		count++;
	}
}

int main(){
	std::vector <std::vector <std::string> > data;
	std::map<std::string, std::vector <std::vector <std::string> > > map_player_salary;

	std::vector <std::vector <std::string> > pitcher_data;
	std::map<std::string, std::vector <std::vector <std::string> > > map_pitcher_player;

	std::vector <std::vector <std::string> > batter_data;
	std::map<std::string, std::vector <std::vector <std::string> > > map_batter_player;

	std::ifstream infile( "2017_MLB_Player_Salary_Info.md" );
	std::ifstream infile_pitcher( "2017_MLB_Pitcher_Info.md" );
	std::ifstream infile_batter( "2017_MLB_Batter_Info.md" );

	//parse_data for salary info
	parse_data(infile, data, map_player_salary);

	//test if player salary data works
	for(int x=0; x<data.size(); x++){
		if((data[x][21])!=""){
			std::cout<<"Name: "<< data[x][1]<<" Salary: "<< data[x][21]<<std::endl;
		}
	}
	if(map_player_salary.find("Clayton Kershaw")!=map_player_salary.end()){
		std::cout<<"map works!!"<<std::endl;
	}

	//parse data for pitcher info
	parse_data(infile_pitcher, pitcher_data, map_pitcher_player);

	//test if pitcher player data works
	for(int x=0; x<pitcher_data.size(); x++){
		if((pitcher_data[x][1])!="Name"){
			std::cout<<"Name: "<< pitcher_data[x][1]<<" ERA: "<< pitcher_data[x][8]<<std::endl;
		}
	}
	if(map_pitcher_player.find("Mike Wright")!=map_pitcher_player.end()){
		std::cout<<"map works!!"<<std::endl;
	}

	//parse data for batter info
	parse_data(infile_batter, batter_data, map_batter_player);

	//test if pitcher player data works
	for(int x=0; x<batter_data.size(); x++){
		if((batter_data[x][1])!="Name"){
			std::cout<<"Name: "<< batter_data[x][1]<<" BA: "<< batter_data[x][18]<<std::endl;
		}
	}
	if(map_batter_player.find("Jose Abreu")!=map_batter_player.end()){
		std::cout<<"map works!!"<<std::endl;
	}

	return 0;
}
<|endoftext|>


<commit_before>a3039c97-ad5b-11e7-9537-ac87a332f658<commit_msg>My Backup<commit_after>a373806b-ad5b-11e7-8bc3-ac87a332f658<|endoftext|>


<commit_before>daafa505-ad58-11e7-9e65-ac87a332f658<commit_msg>The previous fix has been fixed<commit_after>db3bb94a-ad58-11e7-8b74-ac87a332f658<|endoftext|>


<commit_before>#include <iostream>
#include <cv.h>
#include <highgui.h>
#include <exception>
#include <string>
#include <algorithm>

using namespace std;
using namespace cv;

RNG rng(12345);

typedef vector<Mat> MinecraftFont;

void printChar(const Mat& c)
{
    cout << "CHAR!" << endl;
    cout << c.rows << "/" << c.cols << endl;
    for (int i = 0; i < c.rows; ++i) {
        for (int j = 0; j < c.cols; ++j) {
            cout << bool(int(c.at<uchar>(i, j))) << " ";
        }
        cout << endl;
    }
}

char recognizeChar(const MinecraftFont& mf, const Mat& whiteOnBlacImg)
{
    Mat candidate(whiteOnBlacImg.size(), whiteOnBlacImg.type());
    cv::threshold(whiteOnBlacImg, candidate, 0.1, 255, CV_THRESH_BINARY_INV);

    double similarity = 1.0/0.0;
    char result = 0;
    for (int f = 32; f < mf.size(); ++f) {
        if ((candidate.rows > mf[f].rows) || (candidate.cols > mf[f].cols)) {
            // TODO: resize here
            continue;
        }
        for (int si = 0; si < mf[f].rows - candidate.rows + 1; si++) {
            for (int sj = 0; sj < mf[f].cols - candidate.cols + 1; sj++) {
                //cout << "ij " << si << " " << sj << endl;
                Rect charRect = Rect(sj, si, candidate.cols, candidate.rows);
                Mat windowNonBinary(mf[f], charRect);
                //Mat window(windowNonBinary.size(), windowNonBinary.type());
                Mat window = windowNonBinary;
                /*if (f == '1') {
                    cout << si << " " << sj << endl;
                    printChar(window);
                    printChar(candidate);
                    //printChar(whiteOnBlacImg);
                }*/
                double current_similarity = norm(candidate, window);
                //printChar(window);
                if (current_similarity < similarity) {
                    //cout << current_similarity << " vs " << similarity << " " << int(f) << endl;
                    /*cout << "~~~~~~" << endl;
                    printChar(window);
                    cout << "------" << endl;
                    printChar(candidate);
                    cout << "~~~~~~" << endl;*/
                    result = f;
                    similarity = current_similarity;
                }
            }
        }
    }
    return result;
}

struct contour_sorter // 'less' for contours
{
    bool operator ()( const vector<Point>& a, const vector<Point> & b )
    {
        Rect ra(boundingRect(a));
        Rect rb(boundingRect(b));
        //return (ra.y < rb.y) || ((ra.y == rb.y) && (ra.x < rb.x));
        return (ra.br().y < rb.br().y) || ((ra.br().y == rb.br().y) && (ra.br().x < ra.br().x));
    }
};

void ScreenShotBB(const Mat& src, const Mat& processed_image, const MinecraftFont& mf)
{
    vector<vector<Point> > contours;
    vector<Vec4i> hierarchy;
    findContours(processed_image, contours, hierarchy, CV_RETR_TREE, CV_CHAIN_APPROX_SIMPLE, Point(0, 0));
    sort(contours.begin(), contours.end(), contour_sorter());
    vector<vector<Point> > contours_poly( contours.size() );
    vector<Rect> boundRect( contours.size() );
    // TODO: copy src to drawing
    Mat drawing = src;
    /*Mat drawing;
    cvtColor(processed_image, drawing, CV_GRAY2RGB);*/
    for( int i = 0; i < contours.size(); i++ ) {
        Scalar color = Scalar( rng.uniform(0, 255), rng.uniform(0,255), rng.uniform(0,255) );
        approxPolyDP( Mat(contours[i]), contours_poly[i], 3, true );
        boundRect[i] = boundingRect( Mat(contours_poly[i]) );
         //drawContours( drawing, contours_poly, i, color, 1, 8, vector<Vec4i>(), 0, Point() );
        rectangle( drawing, boundRect[i].tl(), boundRect[i].br(), color, 1, 1, 0 );
        Mat c(processed_image, boundRect[i]);
        printChar(c);

        char rc = recognizeChar(mf, c);

        //cout << "~~~~~~~~~~" << endl;
        if (rc > 31) {
            //cout << "OCR char: " << rc << " " << int(rc) << endl;
            cout << rc;
        } else {
            cout << "Char not recognized!" << endl;
        }
        // cout << "~~~~~~~~~~" << endl;
        cout << endl;
    }
    namedWindow("Contours", CV_WINDOW_AUTOSIZE);
    imshow("Contours", drawing);
    waitKey(0);
}

MinecraftFont LoadMinecraftFontImg(const std::string& imgName)
{
    MinecraftFont font;

    Mat src = imread(imgName, 1);
    Mat srcGray;
    cvtColor(src, srcGray, CV_BGR2GRAY);
    Mat drawing = src;
    for(int i = 4; i < src.cols - 16; i += 16) {
        for (int j = 4; j < src.rows - 16; j += 16) {
            Scalar color = Scalar( rng.uniform(0, 255), rng.uniform(0,255), rng.uniform(0,255) );
            Rect charRect = Rect(j, i, 16, 16);
            rectangle(drawing, charRect.tl(), charRect.br(), color, 0, 0, 0);
            Mat c(srcGray, charRect);
            Mat cc;
            c.copyTo(cc);
            font.push_back(c);
        }
    }
    namedWindow("Font", CV_WINDOW_AUTOSIZE);
    imshow("Font", src);
    //waitKey(0);
    return font;
}

int main(int argc, const char** argv)
{
    cout << "Hi!" << endl;
    auto font = LoadMinecraftFontImg("minecraft_fixedwidth_font.png");
    /*for (int f = 0; f < font.size(); ++f) {
        cout << "NEW CHAR " << char(f) << endl;
        printChar(font[f]);
    }*/

    if (argc != 3) {
        cerr << "Bad args" << endl;
        throw std::exception();
    }
    string input_image_name(argv[1]);
    string output_image_name(argv[2]);
    Mat image;
    image = imread(input_image_name, 1);
    if (!image.data) {
        throw std::exception();
    }

    Mat processed_image;
    Mat gray_image;
    cvtColor(image, gray_image, CV_BGR2GRAY);
    threshold(gray_image, processed_image, 222, -1, THRESH_TOZERO);

    imwrite(output_image_name, processed_image);
    ScreenShotBB(image, processed_image, font);

    //namedWindow("Color image", CV_WINDOW_AUTOSIZE);
    //namedWindow("Processed image", CV_WINDOW_AUTOSIZE);

    //imshow("Color image", image);
    //imshow("Processed image", processed_image);
}
<commit_msg>Now XYZ coordinates extraction almost works!<commit_after>#include <iostream>
#include <cv.h>
#include <highgui.h>
#include <exception>
#include <string>
#include <algorithm>

using namespace std;
using namespace cv;

RNG rng(12345);

typedef vector<Mat> MinecraftFont;

void printChar(const Mat& c)
{
    cout << "CHAR!" << endl;
    cout << c.rows << "/" << c.cols << endl;
    for (int i = 0; i < c.rows; ++i) {
        for (int j = 0; j < c.cols; ++j) {
            cout << bool(int(c.at<uchar>(i, j))) << " ";
        }
        cout << endl;
    }
}

char recognizeChar(const MinecraftFont& mf, const Mat& whiteOnBlacImg)
{
    Mat candidate(whiteOnBlacImg.size(), whiteOnBlacImg.type());
    cv::threshold(whiteOnBlacImg, candidate, 0.1, 255, CV_THRESH_BINARY_INV);

    double similarity = 1.0/0.0;
    char result = 0;
    for (int f = 32; f < mf.size(); ++f) {
        if ((candidate.rows > mf[f].rows) || (candidate.cols > mf[f].cols)) {
            // TODO: resize here
            continue;
        }
        for (int si = 0; si < mf[f].rows - candidate.rows + 1; si++) {
            for (int sj = 0; sj < mf[f].cols - candidate.cols + 1; sj++) {
                //cout << "ij " << si << " " << sj << endl;
                Rect charRect = Rect(sj, si, candidate.cols, candidate.rows);
                Mat windowNonBinary(mf[f], charRect);
                //Mat window(windowNonBinary.size(), windowNonBinary.type());
                Mat window = windowNonBinary;
                /*if (f == '1') {
                    cout << si << " " << sj << endl;
                    printChar(window);
                    printChar(candidate);
                    //printChar(whiteOnBlacImg);
                }*/
                double current_similarity = norm(candidate, window);
                //printChar(window);
                if (current_similarity < similarity) {
                    //cout << current_similarity << " vs " << similarity << " " << int(f) << endl;
                    /*cout << "~~~~~~" << endl;
                    printChar(window);
                    cout << "------" << endl;
                    printChar(candidate);
                    cout << "~~~~~~" << endl;*/
                    result = f;
                    similarity = current_similarity;
                }
            }
        }
    }
    return result;
}

struct contour_sorter // 'less' for contours
{
    bool operator ()( const vector<Point>& a, const vector<Point> & b )
    {
        Rect ra(boundingRect(a));
        Rect rb(boundingRect(b));
        //return (ra.y < rb.y) || ((ra.y == rb.y) && (ra.x < rb.x));
        return (ra.br().y < rb.br().y) || ((ra.br().y == rb.br().y) && (ra.br().x < ra.br().x));
    }
};

bool yOverlap(const Rect& r1, const Rect& r2)
{
    return (r1.y >= r2.y && r1.y <= r2.y + r2.height) || (r2.y >= r1.y && r2.y <= r1.y + r1.height);
}

void ScreenShotBB(const Mat& src, const Mat& processed_image, const MinecraftFont& mf)
{
    vector<vector<Point> > contours;
    vector<Vec4i> hierarchy;
    findContours(processed_image, contours, hierarchy, CV_RETR_EXTERNAL, CV_CHAIN_APPROX_SIMPLE, Point(0, 0));
    sort(contours.begin(), contours.end(), contour_sorter());
    vector<vector<Point> > contours_poly( contours.size() );
    vector<Rect> boundRect( contours.size() );
    vector<Rect> firstCharsInLine( contours.size() );
    // TODO: copy src to drawing
    Mat drawing = src;
    /*Mat drawing;
    cvtColor(processed_image, drawing, CV_GRAY2RGB);*/
    for( int i = 0; i < contours.size(); i++ ) {
        approxPolyDP( Mat(contours[i]), contours_poly[i], 3, true );
        boundRect[i] = boundingRect( Mat(contours_poly[i]) );
         //drawContours( drawing, contours_poly, i, color, 1, 8, vector<Vec4i>(), 0, Point() );
    }

    vector<Rect> X;
    vector<Rect> Y;
    vector<Rect> Z;

    vector<Rect> rectsToDraw;

    for (int i = 0; i < boundRect.size(); i++) {
        Mat c(processed_image, boundRect[i]);
        //printChar(c);

        char rc = recognizeChar(mf, c);
        if (rc == 'X' || rc == 'Y' || rc == 'Z') {
            cout << rc << endl;
            rectsToDraw.push_back(boundRect[i]);
        }
        switch (rc) {
            case 'X':
                X.push_back(boundRect[i]);
                break;
            case 'Y':
                Y.push_back(boundRect[i]);
                break;
            case 'Z':
                Z.push_back(boundRect[i]);
                break;
            default:
                break;
        }
    }
    Rect XYZ_line;
    for (int x = 0; x < X.size(); x++)
        for (int y = 0; y < Y.size(); y++)
            for (int z = 0; z < Z.size(); z++)
                if (yOverlap(X[x], Y[y]) && yOverlap(X[x], Z[z]) && yOverlap(Y[y], Z[z])) {
                    cout << "FOUND!" << endl;
                    XYZ_line = Rect(0, X[x].tl().y, src.cols, X[x].height);
                    rectsToDraw.push_back(XYZ_line);
                }
    vector<Rect> chars_in_XYZ_line;
    for (int i = 0; i < boundRect.size(); i++) {
        if (yOverlap(boundRect[i], XYZ_line)) {
            chars_in_XYZ_line.push_back(boundRect[i]);
            rectsToDraw.push_back(boundRect[i]);
        }
    }
    cout << "-----" << endl;
    sort(chars_in_XYZ_line.begin(), chars_in_XYZ_line.end(), [](const Rect& r1, const Rect& r2){return r1.x < r2.x;});
    for (int i = 0; i < chars_in_XYZ_line.size(); i++) {
        Mat c(processed_image, chars_in_XYZ_line[i]);
        char rc = recognizeChar(mf, c);
        cout << rc;
    }
    cout << "-----" << endl;
    rectsToDraw = chars_in_XYZ_line;
    for (int i = 0; i < rectsToDraw.size(); i++) {
        Scalar color = Scalar( rng.uniform(0, 255), rng.uniform(0,255), rng.uniform(0,255) );
        rectangle( drawing, rectsToDraw[i].tl(), rectsToDraw[i].br(), color, 1, 1, 0 );
    }
    cout << "Showing the window" << endl;
    namedWindow("Contours", CV_WINDOW_AUTOSIZE);
    imshow("Contours", drawing);
    waitKey(0);
}

MinecraftFont LoadMinecraftFontImg(const std::string& imgName)
{
    MinecraftFont font;

    Mat src = imread(imgName, 1);
    Mat srcGray;
    cvtColor(src, srcGray, CV_BGR2GRAY);
    Mat drawing = src;
    for(int i = 4; i < src.cols - 16; i += 16) {
        for (int j = 4; j < src.rows - 16; j += 16) {
            Scalar color = Scalar( rng.uniform(0, 255), rng.uniform(0,255), rng.uniform(0,255) );
            Rect charRect = Rect(j, i, 16, 16);
            rectangle(drawing, charRect.tl(), charRect.br(), color, 0, 0, 0);
            Mat c(srcGray, charRect);
            Mat cc;
            c.copyTo(cc);
            font.push_back(c);
        }
    }
    namedWindow("Font", CV_WINDOW_AUTOSIZE);
    imshow("Font", src);
    //waitKey(0);
    return font;
}

int main(int argc, const char** argv)
{
    cout << "Hi!" << endl;
    auto font = LoadMinecraftFontImg("minecraft_fixedwidth_font.png");
    /*for (int f = 0; f < font.size(); ++f) {
        cout << "NEW CHAR " << char(f) << endl;
        printChar(font[f]);
    }*/

    if (argc != 3) {
        cerr << "Bad args" << endl;
        throw std::exception();
    }
    string input_image_name(argv[1]);
    string output_image_name(argv[2]);
    Mat image;
    image = imread(input_image_name, 1);
    if (!image.data) {
        throw std::exception();
    }

    Mat processed_image;
    Mat gray_image;
    cvtColor(image, gray_image, CV_BGR2GRAY);
    threshold(gray_image, processed_image, 222, -1, THRESH_TOZERO);

    imwrite(output_image_name, processed_image);
    ScreenShotBB(image, processed_image, font);

    //namedWindow("Color image", CV_WINDOW_AUTOSIZE);
    //namedWindow("Processed image", CV_WINDOW_AUTOSIZE);

    //imshow("Color image", image);
    //imshow("Processed image", processed_image);
}
<|endoftext|>


<commit_before>/*
  PureBackup - human-readable backup output
  Copyright (C) 2005 Ben Wilhelm

  This program 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; version 2 of the license only.

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

  You should have received a copy of the GNU General Public License
  along with this program; if not, write to the Free Software
  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301
*/

#include "parse.h"
#include "debug.h"
#include "tree.h"
#include "state.h"

#include <string>
#include <fstream>
#include <set>

using namespace std;

// Makes sure everything up to this is virtual
MountTree *getMountpointLocation(const string &loc) {
  const char *tpt = loc.c_str();
  MountTree *cpos = getRoot();
  while(*tpt) {
    CHECK(*tpt == '/');
    tpt++;
    CHECK(*tpt);

    CHECK(cpos->type == MTT_UNINITTED || cpos->type == MTT_VIRTUAL);
    cpos->type = MTT_VIRTUAL;

    // isolate the next path component
    const char *tpn = strchr(tpt, '/');
    if(!tpn)
      tpn = tpt + strlen(tpt);

    string linkage = string(tpt, tpn);
    cpos = &cpos->virtual_links[linkage];

    tpt = tpn;
  }
  return cpos;
}

void createMountpoint(const string &loc, const string &type, const string &source) {
  MountTree *dpt =getMountpointLocation(loc);
  CHECK(dpt);
  CHECK(dpt->type == MTT_UNINITTED);

  if(type == "file") {
    dpt->type = MTT_FILE;
    dpt->file_source = source;
    dpt->file_scanned = false;
  } else {
    CHECK(0);
  }

}

void printAll() {
  printf("ROOT\n");
  getRoot()->print(2);
}

void readConfig(const string &conffile) {
  // First we init root
  {
    getRoot()->type = MTT_UNINITTED;
  }

  ifstream ifs(conffile.c_str());
  kvData kvd;
  while(getkvData(ifs, kvd)) {
    if(kvd.category == "mountpoint") {
      createMountpoint(kvd.consume("mount"), kvd.consume("type"), kvd.consume("source"));
    } else {
      CHECK(0);
    }
  }

  CHECK(getRoot()->checkSanity());
  printAll();
}

void scanPaths() {
  getRoot()->scan();
  CHECK(getRoot()->checkSanity());
  //printAll();
}

enum { TYPE_CREATE, TYPE_DELETE, TYPE_COPY, TYPE_APPEND, TYPE_STORE, TYPE_END };
string type_strs[] = { "CREATE", "DELETE", "COPY", "APPEND", "STORE" };

class Instruction {
public:
  vector<pair<bool, string> > depends;
  vector<pair<bool, string> > removes;
  vector<pair<bool, string> > creates;

  int type;

  string textout() const;
};

void dumpa(string *str, const string &txt, const vector<pair<bool, string> > &vek) {
  *str += "  " + txt + "\n";
  for(int i = 0; i < vek.size(); i++)
    *str += StringPrintf("    %d:%s\n", vek[i].first, vek[i].second.c_str());
}

string Instruction::textout() const {
  string rvx;
  CHECK(type >= 0 && type < TYPE_END);
  rvx = type_strs[type] + "\n";
  dumpa(&rvx, "Depends:", depends);
  dumpa(&rvx, "Removes:", removes);
  dumpa(&rvx, "Creates:", creates);
  return rvx;
}

vector<Instruction> sortInst(const vector<Instruction> &oinst) {
  vector<Instruction> buckets[TYPE_END];
  map<pair<bool, string>, int> leftToUse;
  for(int i = 0; i < oinst.size(); i++) {
    CHECK(oinst[i].type >= 0 && oinst[i].type < TYPE_END);
    buckets[oinst[i].type].push_back(oinst[i]);
    for(int j = 0; j < oinst[i].depends.size(); j++)
      leftToUse[oinst[i].depends[j]]++;
  }
  CHECK(buckets[0].size() == 1);

  set<pair<bool, string> > live;

  vector<Instruction> kinstr;

  while(1) {
    int tcl = 0;
    for(int i = 0; i < TYPE_END; i++)
      tcl += buckets[i].size();
    if(!tcl)
      break;
    printf("Starting pass, %d instructions left\n", tcl);
    for(int i = 0; i < TYPE_END; i++) {
      for(int j = 0; j < buckets[i].size(); j++) {
        bool good = true;
        for(int k = 0; good && k < buckets[i][j].depends.size(); k++)
          if(!live.count(buckets[i][j].depends[k]))
            good = false;
        for(int k = 0; good && k < buckets[i][j].removes.size(); k++)
          if(!(leftToUse[buckets[i][j].removes[k]] == 0 || leftToUse[buckets[i][j].removes[k]] == 1 && count(buckets[i][j].depends.begin(), buckets[i][j].depends.end(), buckets[i][j].removes[k])))
            good = false;
        if(!good)
          continue;
        //dprintf("%s\n", buckets[i][j].textout().c_str());
        for(int k = 0; k < buckets[i][j].depends.size(); k++)
          leftToUse[buckets[i][j].depends[k]]--;
        for(int k = 0; k < buckets[i][j].removes.size(); k++) {
          CHECK(live.count(buckets[i][j].removes[k]));
          live.erase(buckets[i][j].removes[k]);
        }
        for(int k = 0; k < buckets[i][j].creates.size(); k++) {
          pair<bool, string> ite = buckets[i][j].creates[k];
          CHECK(!live.count(ite));
          live.insert(buckets[i][j].creates[k]);
        }
        kinstr.push_back(buckets[i][j]);
        buckets[i].erase(buckets[i].begin() + j);
        j--;
      }
    }
  }

  return kinstr;
}

int main() {
  readConfig("purebackup.conf");
  scanPaths();

  map<string, Item> realitems;
  getRoot()->dumpItems(&realitems, "");
  dprintf("%d items found\n", realitems.size());

  State origstate;
  origstate.readFile("state0");

  map<pair<bool, string>, Item> citem;
  map<long long, vector<pair<bool, string> > > citemsizemap;
  set<string> ftc;

  Instruction fi;
  fi.type = TYPE_CREATE;

  vector<Instruction> inst;

  for(map<string, Item>::iterator itr = realitems.begin(); itr != realitems.end(); itr++) {
    CHECK(itr->second.size >= 0);
    CHECK(itr->second.timestamp >= 0);
    ftc.insert(itr->first);
  }

  for(map<string, Item>::const_iterator itr = origstate.getItemDb().begin(); itr != origstate.getItemDb().end(); itr++) {
    CHECK(itr->second.size >= 0);
    CHECK(itr->second.timestamp >= 0);
    CHECK(citem.count(make_pair(false, itr->first)) == 0);
    citem[make_pair(false, itr->first)] = itr->second;
    citemsizemap[itr->second.size].push_back(make_pair(false, itr->first));
    fi.creates.push_back(make_pair(false, itr->first));
    ftc.insert(itr->first);
  }

  // FTC is the union of the files in realitems and origstate
  // citem is the items that we can look at
  // citemsizemap is the same, only organized by size
  for(set<string>::iterator itr = ftc.begin(); itr != ftc.end(); itr++) {
    if(realitems.count(*itr)) {
      const Item &ite = realitems.find(*itr)->second;
      bool got = false;

      // First, we check to see if it's the same file as existed before
      if(!got && citem.count(make_pair(false, *itr))) {
        const Item &pite = citem.find(make_pair(false, *itr))->second;
        if(ite.size == pite.size && ite.timestamp == pite.timestamp) {
          // It's identical!
          printf("Preserve file %s\n", itr->c_str());
          fi.creates.push_back(make_pair(true, *itr));
          got = true;
        } else if(ite.size == pite.size && ite.checksum() == pite.checksum()) {
          // It's touched! But we currently don't care!
          printf("Preserve file %s\n", itr->c_str());
          fi.creates.push_back(make_pair(true, *itr));
          got = true;
        } else if(ite.size > pite.size && ite.checksumPart(pite.size) == pite.checksum()) {
          // It's appended!
          printf("Appendination on %s, dude!\n", itr->c_str());
          Instruction ti;
          ti.type = TYPE_APPEND;
          ti.creates.push_back(make_pair(true, *itr));
          ti.depends.push_back(make_pair(false, *itr));
          ti.removes.push_back(make_pair(false, *itr));
          inst.push_back(ti);
          got = true;
        }
      }

      // Okay, now we see if it's been copied from somewhere
      if(!got) {
        const vector<pair<bool, string> > &sli = citemsizemap[ite.size];
        printf("Trying %d originals\n", sli.size());
        for(int k = 0; k < sli.size(); k++) {
          CHECK(ite.size == citem[sli[k]].size);
          printf("Comparing with %d:%s\n", sli[k].first, sli[k].second.c_str());
          printf("%s vs %s\n", ite.checksum().toString().c_str(), citem[sli[k]].checksum().toString().c_str());
          if(ite.checksum() == citem[sli[k]].checksum()) {
            printf("Holy crapcock! Copying %s from %s:%d! MADNESS\n", itr->c_str(), sli[k].second.c_str(), sli[k].first);
            Instruction ti;
            ti.type = TYPE_COPY;
            ti.creates.push_back(make_pair(true, *itr));
            ti.depends.push_back(sli[k]);
            if(citem.count(make_pair(false, *itr)))
              ti.removes.push_back(make_pair(false, *itr));
            inst.push_back(ti);
            got = true;
            break;
          }
        }
      }

      // And now we give up and just create it
      if(!got) {
        printf("Creating %s from GALACTIC ETHER\n", itr->c_str());
        Instruction ti;
        ti.type = TYPE_STORE;
        ti.creates.push_back(make_pair(true, *itr));
        if(citem.count(make_pair(false, *itr)))
          ti.removes.push_back(make_pair(false, *itr));
        inst.push_back(ti);
        got = true;
      }

      CHECK(got);

      citem[make_pair(true, *itr)] = ite;
      citemsizemap[ite.size].push_back(make_pair(true, *itr));

    } else {
      CHECK(citem.count(make_pair(false, *itr)));
      printf("Delete file %s\n", itr->c_str());
      Instruction ti;
      ti.type = TYPE_DELETE;
      ti.removes.push_back(make_pair(false, *itr));
      inst.push_back(ti);
    }
  }

  inst.push_back(fi);

  inst = sortInst(inst);

  for(int i = 0; i < inst.size(); i++)
    printf("%s\n", inst[i].textout().c_str());

}
<commit_msg><commit_after>/*
  PureBackup - human-readable backup output
  Copyright (C) 2005 Ben Wilhelm

  This program 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; version 2 of the license only.

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

  You should have received a copy of the GNU General Public License
  along with this program; if not, write to the Free Software
  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301
*/

#include "parse.h"
#include "debug.h"
#include "tree.h"
#include "state.h"

#include <string>
#include <fstream>
#include <set>

using namespace std;

// Makes sure everything up to this is virtual
MountTree *getMountpointLocation(const string &loc) {
  const char *tpt = loc.c_str();
  MountTree *cpos = getRoot();
  while(*tpt) {
    CHECK(*tpt == '/');
    tpt++;
    CHECK(*tpt);

    CHECK(cpos->type == MTT_UNINITTED || cpos->type == MTT_VIRTUAL);
    cpos->type = MTT_VIRTUAL;

    // isolate the next path component
    const char *tpn = strchr(tpt, '/');
    if(!tpn)
      tpn = tpt + strlen(tpt);

    string linkage = string(tpt, tpn);
    cpos = &cpos->virtual_links[linkage];

    tpt = tpn;
  }
  return cpos;
}

void createMountpoint(const string &loc, const string &type, const string &source) {
  MountTree *dpt =getMountpointLocation(loc);
  CHECK(dpt);
  CHECK(dpt->type == MTT_UNINITTED);

  if(type == "file") {
    dpt->type = MTT_FILE;
    dpt->file_source = source;
    dpt->file_scanned = false;
  } else {
    CHECK(0);
  }

}

void printAll() {
  printf("ROOT\n");
  getRoot()->print(2);
}

void readConfig(const string &conffile) {
  // First we init root
  {
    getRoot()->type = MTT_UNINITTED;
  }

  ifstream ifs(conffile.c_str());
  kvData kvd;
  while(getkvData(ifs, kvd)) {
    if(kvd.category == "mountpoint") {
      createMountpoint(kvd.consume("mount"), kvd.consume("type"), kvd.consume("source"));
    } else {
      CHECK(0);
    }
  }

  CHECK(getRoot()->checkSanity());
  printAll();
}

void scanPaths() {
  getRoot()->scan();
  CHECK(getRoot()->checkSanity());
  //printAll();
}

enum { TYPE_CREATE, TYPE_ROTATE, TYPE_DELETE, TYPE_COPY, TYPE_APPEND, TYPE_STORE, TYPE_END };
string type_strs[] = { "CREATE", "ROTATE", "DELETE", "COPY", "APPEND", "STORE" };

class Instruction {
public:
  vector<pair<bool, string> > depends;
  vector<pair<bool, string> > removes;
  vector<pair<bool, string> > creates;

  int type;

  string textout() const;
};

void dumpa(string *str, const string &txt, const vector<pair<bool, string> > &vek) {
  *str += "  " + txt + "\n";
  for(int i = 0; i < vek.size(); i++)
    *str += StringPrintf("    %d:%s\n", vek[i].first, vek[i].second.c_str());
}

string Instruction::textout() const {
  string rvx;
  CHECK(type >= 0 && type < TYPE_END);
  rvx = type_strs[type] + "\n";
  dumpa(&rvx, "Depends:", depends);
  dumpa(&rvx, "Removes:", removes);
  dumpa(&rvx, "Creates:", creates);
  return rvx;
}

void loopprocess(int pos, vector<int> *loop, const vector<Instruction> &inst,
    const map<pair<bool, string>, vector<int> > &depon,
    const map<pair<bool, string>, int> &creates,
    const set<pair<bool, string> > &removed,
    vector<bool> *noprob) {

  //printf("Entering loopprocess %d\n", pos);
  //printf("%s\n", inst[pos].textout().c_str());

  if((*noprob)[pos])
    return;

  if(loop->size() && loop->back() == pos)
    return;

  //printf("Pushback %d\n", pos);

  loop->push_back(pos);

  if(set<int>(loop->begin(), loop->end()).size() != loop->size()) {
    //printf("LOOP!\n");
    //for(int i = 0; i < loop->size(); i++)
      //printf("%d\n", (*loop)[i]);
    return;
  }

  //printf("Starting depends %d\n", pos);
  vector<int> bku = *loop;
  // Anything this depends on must exist
  for(int i = 0; i < inst[pos].depends.size(); i++) {
    CHECK(creates.count(inst[pos].depends[i]));
    loopprocess(creates.find(inst[pos].depends[i])->second, loop, inst, depon, creates, removed, noprob);
    if(*loop != bku)
      return;
  }

  //printf("Starting removes %d\n", pos);
  // Anything this removes must have its dependencies complete
  for(int i = 0; i < inst[pos].removes.size(); i++) {
    if(!depon.count(inst[pos].removes[i]))
      continue;
    const vector<int> &dpa = depon.find(inst[pos].removes[i])->second;
    for(int j = 0; j < dpa.size(); j++) {
      loopprocess(dpa[j], loop, inst, depon, creates, removed, noprob);
      if(*loop != bku)
        return;
    }
  }
  //printf("Done %d\n", pos);

  loop->pop_back();

  (*noprob)[pos] = true;
}

vector<Instruction> deloop(const vector<Instruction> &inst) {
  map<pair<bool, string>, vector<int> > depon;
  map<pair<bool, string>, int> creates;
  set<pair<bool, string> > removed;
  vector<bool> noprob(inst.size());
  for(int i = 0; i < inst.size(); i++) {
    for(int j = 0; j < inst[i].depends.size(); j++)
      depon[inst[i].depends[j]].push_back(i);
    for(int j = 0; j < inst[i].creates.size(); j++) {
      CHECK(!creates.count(inst[i].creates[j]));
      creates[inst[i].creates[j]] = i;
    }
    for(int j = 0; j < inst[i].removes.size(); j++) {
      CHECK(!removed.count(inst[i].removes[j]));
      removed.insert(inst[i].removes[j]);
    }
  }
  for(int i = 0; i < inst.size(); i++) {
    vector<int> loop;
    loopprocess(i, &loop, inst, depon, creates, removed, &noprob);
    if(loop.size()) {
      printf("Loop! %d\n", loop.size());
      CHECK(loop.size() >= 3);
      CHECK(loop.front() == loop.back());
      set<int> lps(loop.begin(), loop.end());
      CHECK(lps.size() == loop.size() - 1);

      // TODO: preserve the actual rotation order
      Instruction rotinstr;
      rotinstr.type = TYPE_ROTATE;
      for(set<int>::iterator it = lps.begin(); it != lps.end(); it++) {
        CHECK(inst[*it].type == TYPE_COPY);
        rotinstr.depends.insert(rotinstr.depends.end(), inst[*it].depends.begin(), inst[*it].depends.end());
        rotinstr.removes.insert(rotinstr.removes.end(), inst[*it].removes.begin(), inst[*it].removes.end());
        rotinstr.creates.insert(rotinstr.creates.end(), inst[*it].creates.begin(), inst[*it].creates.end());
      }
      CHECK((set<pair<bool, string> >(rotinstr.depends.begin(), rotinstr.depends.end()).size() == rotinstr.depends.size()));
      CHECK((set<pair<bool, string> >(rotinstr.removes.begin(), rotinstr.removes.end()).size() == rotinstr.removes.size()));
      CHECK((set<pair<bool, string> >(rotinstr.creates.begin(), rotinstr.creates.end()).size() == rotinstr.creates.size()));

      vector<Instruction> nistr;
      for(int i = 0; i < inst.size(); i++)
        if(!lps.count(i))
          nistr.push_back(inst[i]);
      nistr.push_back(rotinstr);
      return deloop(nistr);

    }
  }
  return inst;
}

vector<Instruction> sortInst(vector<Instruction> oinst) {
  oinst = deloop(oinst);

  vector<Instruction> buckets[TYPE_END];
  map<pair<bool, string>, int> leftToUse;
  for(int i = 0; i < oinst.size(); i++) {
    CHECK(oinst[i].type >= 0 && oinst[i].type < TYPE_END);
    buckets[oinst[i].type].push_back(oinst[i]);
    for(int j = 0; j < oinst[i].depends.size(); j++)
      leftToUse[oinst[i].depends[j]]++;
  }
  CHECK(buckets[0].size() == 1);

  set<pair<bool, string> > live;

  vector<Instruction> kinstr;

  while(1) {
    int tcl = 0;
    for(int i = 0; i < TYPE_END; i++)
      tcl += buckets[i].size();
    if(!tcl)
      break;
    printf("Starting pass, %d instructions left\n", tcl);
    for(int i = 0; i < TYPE_END; i++) {
      for(int j = 0; j < buckets[i].size(); j++) {
        bool good = true;
        for(int k = 0; good && k < buckets[i][j].depends.size(); k++)
          if(!live.count(buckets[i][j].depends[k]))
            good = false;
        for(int k = 0; good && k < buckets[i][j].removes.size(); k++)
          if(!(leftToUse[buckets[i][j].removes[k]] == 0 || leftToUse[buckets[i][j].removes[k]] == 1 && count(buckets[i][j].depends.begin(), buckets[i][j].depends.end(), buckets[i][j].removes[k])))
            good = false;
        if(!good)
          continue;
        //dprintf("%s\n", buckets[i][j].textout().c_str());
        for(int k = 0; k < buckets[i][j].depends.size(); k++)
          leftToUse[buckets[i][j].depends[k]]--;
        for(int k = 0; k < buckets[i][j].removes.size(); k++) {
          CHECK(live.count(buckets[i][j].removes[k]));
          live.erase(buckets[i][j].removes[k]);
        }
        for(int k = 0; k < buckets[i][j].creates.size(); k++) {
          pair<bool, string> ite = buckets[i][j].creates[k];
          CHECK(!live.count(ite));
          live.insert(buckets[i][j].creates[k]);
        }
        kinstr.push_back(buckets[i][j]);
        buckets[i].erase(buckets[i].begin() + j);
        j--;
      }
    }
    for(int i = 0; i < TYPE_END; i++)
      tcl -= buckets[i].size();
    CHECK(tcl != 0);
  }

  return kinstr;
}

int main() {
  readConfig("purebackup.conf");
  scanPaths();

  map<string, Item> realitems;
  getRoot()->dumpItems(&realitems, "");
  dprintf("%d items found\n", realitems.size());

  State origstate;
  origstate.readFile("state0");

  map<pair<bool, string>, Item> citem;
  map<long long, vector<pair<bool, string> > > citemsizemap;
  set<string> ftc;

  Instruction fi;
  fi.type = TYPE_CREATE;

  vector<Instruction> inst;

  for(map<string, Item>::iterator itr = realitems.begin(); itr != realitems.end(); itr++) {
    CHECK(itr->second.size >= 0);
    CHECK(itr->second.timestamp >= 0);
    ftc.insert(itr->first);
  }

  for(map<string, Item>::const_iterator itr = origstate.getItemDb().begin(); itr != origstate.getItemDb().end(); itr++) {
    CHECK(itr->second.size >= 0);
    CHECK(itr->second.timestamp >= 0);
    CHECK(citem.count(make_pair(false, itr->first)) == 0);
    citem[make_pair(false, itr->first)] = itr->second;
    citemsizemap[itr->second.size].push_back(make_pair(false, itr->first));
    fi.creates.push_back(make_pair(false, itr->first));
    ftc.insert(itr->first);
  }

  // FTC is the union of the files in realitems and origstate
  // citem is the items that we can look at
  // citemsizemap is the same, only organized by size
  for(set<string>::iterator itr = ftc.begin(); itr != ftc.end(); itr++) {
    if(realitems.count(*itr)) {
      const Item &ite = realitems.find(*itr)->second;
      bool got = false;

      // First, we check to see if it's the same file as existed before
      if(!got && citem.count(make_pair(false, *itr))) {
        const Item &pite = citem.find(make_pair(false, *itr))->second;
        if(ite.size == pite.size && ite.timestamp == pite.timestamp) {
          // It's identical!
          printf("Preserve file %s\n", itr->c_str());
          fi.creates.push_back(make_pair(true, *itr));
          got = true;
        } else if(ite.size == pite.size && ite.checksum() == pite.checksum()) {
          // It's touched! But we currently don't care!
          printf("Preserve file %s\n", itr->c_str());
          fi.creates.push_back(make_pair(true, *itr));
          got = true;
        } else if(ite.size > pite.size && ite.checksumPart(pite.size) == pite.checksum()) {
          // It's appended!
          printf("Appendination on %s, dude!\n", itr->c_str());
          Instruction ti;
          ti.type = TYPE_APPEND;
          ti.creates.push_back(make_pair(true, *itr));
          ti.depends.push_back(make_pair(false, *itr));
          ti.removes.push_back(make_pair(false, *itr));
          inst.push_back(ti);
          got = true;
        }
      }

      // Okay, now we see if it's been copied from somewhere
      if(!got) {
        const vector<pair<bool, string> > &sli = citemsizemap[ite.size];
        printf("Trying %d originals\n", sli.size());
        for(int k = 0; k < sli.size(); k++) {
          CHECK(ite.size == citem[sli[k]].size);
          printf("Comparing with %d:%s\n", sli[k].first, sli[k].second.c_str());
          printf("%s vs %s\n", ite.checksum().toString().c_str(), citem[sli[k]].checksum().toString().c_str());
          if(ite.checksum() == citem[sli[k]].checksum()) {
            printf("Holy crapcock! Copying %s from %s:%d! MADNESS\n", itr->c_str(), sli[k].second.c_str(), sli[k].first);
            Instruction ti;
            ti.type = TYPE_COPY;
            ti.creates.push_back(make_pair(true, *itr));
            ti.depends.push_back(sli[k]);
            if(citem.count(make_pair(false, *itr)))
              ti.removes.push_back(make_pair(false, *itr));
            inst.push_back(ti);
            got = true;
            break;
          }
        }
      }

      // And now we give up and just create it
      if(!got) {
        printf("Creating %s from GALACTIC ETHER\n", itr->c_str());
        Instruction ti;
        ti.type = TYPE_STORE;
        ti.creates.push_back(make_pair(true, *itr));
        if(citem.count(make_pair(false, *itr)))
          ti.removes.push_back(make_pair(false, *itr));
        inst.push_back(ti);
        got = true;
      }

      CHECK(got);

      citem[make_pair(true, *itr)] = ite;
      citemsizemap[ite.size].push_back(make_pair(true, *itr));

    } else {
      CHECK(citem.count(make_pair(false, *itr)));
      printf("Delete file %s\n", itr->c_str());
      Instruction ti;
      ti.type = TYPE_DELETE;
      ti.removes.push_back(make_pair(false, *itr));
      inst.push_back(ti);
    }
  }

  inst.push_back(fi);

  inst = sortInst(inst);

  for(int i = 0; i < inst.size(); i++)
    printf("%s\n", inst[i].textout().c_str());

}
<|endoftext|>


<commit_before>/*
Copyright (c) 2001 Peter Dimov and Multi Media Ltd.
Copyright (c) 2016 Modified Work Barrett Adair

Distributed under the Boost Software License, Version 1.0.
(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)

HEADER GUARDS INTENTIONALLY OMITTED
DO NOT INCLUDE THIS HEADER DIRECTLY

*/

#undef BOOST_CLBL_TRTS_INCLUDE_QUALIFIERS
#undef BOOST_CLBL_TRTS_INCLUDE_ABOMINABLE_QUALIFIERS

#define BOOST_CLBL_TRTS_INCLUDE_QUALIFIERS
#define BOOST_CLBL_TRTS_INCLUDE_ABOMINABLE_QUALIFIERS
#include <boost/callable_traits/detail/unguarded/pmf_2.hpp>
#undef BOOST_CLBL_TRTS_INCLUDE_QUALIFIERS
#undef BOOST_CLBL_TRTS_INCLUDE_ABOMINABLE_QUALIFIERS

#define BOOST_CLBL_TRTS_INCLUDE_QUALIFIERS const
#define BOOST_CLBL_TRTS_INCLUDE_ABOMINABLE_QUALIFIERS \
    BOOST_CLBL_TRTS_ABOMINABLE_CONST
#include <boost/callable_traits/detail/unguarded/pmf_2.hpp>
#undef BOOST_CLBL_TRTS_INCLUDE_QUALIFIERS
#undef BOOST_CLBL_TRTS_INCLUDE_ABOMINABLE_QUALIFIERS

#define BOOST_CLBL_TRTS_INCLUDE_QUALIFIERS volatile
#define BOOST_CLBL_TRTS_INCLUDE_ABOMINABLE_QUALIFIERS \
    BOOST_CLBL_TRTS_ABOMINABLE_VOLATILE
#include <boost/callable_traits/detail/unguarded/pmf_2.hpp>
#undef BOOST_CLBL_TRTS_INCLUDE_QUALIFIERS
#undef BOOST_CLBL_TRTS_INCLUDE_ABOMINABLE_QUALIFIERS

#define BOOST_CLBL_TRTS_INCLUDE_QUALIFIERS const volatile
#define BOOST_CLBL_TRTS_INCLUDE_ABOMINABLE_QUALIFIERS \
    BOOST_CLBL_TRTS_ABOMINABLE_CONST BOOST_CLBL_TRTS_ABOMINABLE_VOLATILE
#include <boost/callable_traits/detail/unguarded/pmf_2.hpp>
#undef BOOST_CLBL_TRTS_INCLUDE_QUALIFIERS
#undef BOOST_CLBL_TRTS_INCLUDE_ABOMINABLE_QUALIFIERS

#ifndef BOOST_CLBL_TRTS_DISABLE_REFERENCE_QUALIFIERS

#define BOOST_CLBL_TRTS_INCLUDE_QUALIFIERS &
#define BOOST_CLBL_TRTS_INCLUDE_ABOMINABLE_QUALIFIERS &
#include <boost/callable_traits/detail/unguarded/pmf_2.hpp>
#undef BOOST_CLBL_TRTS_INCLUDE_QUALIFIERS
#undef BOOST_CLBL_TRTS_INCLUDE_ABOMINABLE_QUALIFIERS

#define BOOST_CLBL_TRTS_INCLUDE_QUALIFIERS &&
#define BOOST_CLBL_TRTS_INCLUDE_ABOMINABLE_QUALIFIERS &&
#include <boost/callable_traits/detail/unguarded/pmf_2.hpp>
#undef BOOST_CLBL_TRTS_INCLUDE_QUALIFIERS
#undef BOOST_CLBL_TRTS_INCLUDE_ABOMINABLE_QUALIFIERS

#define BOOST_CLBL_TRTS_INCLUDE_QUALIFIERS const &
#define BOOST_CLBL_TRTS_INCLUDE_ABOMINABLE_QUALIFIERS const &
#include <boost/callable_traits/detail/unguarded/pmf_2.hpp>
#undef BOOST_CLBL_TRTS_INCLUDE_QUALIFIERS
#undef BOOST_CLBL_TRTS_INCLUDE_ABOMINABLE_QUALIFIERS

#define BOOST_CLBL_TRTS_INCLUDE_QUALIFIERS volatile &
#define BOOST_CLBL_TRTS_INCLUDE_ABOMINABLE_QUALIFIERS volatile &
#include <boost/callable_traits/detail/unguarded/pmf_2.hpp>
#undef BOOST_CLBL_TRTS_INCLUDE_QUALIFIERS
#undef BOOST_CLBL_TRTS_INCLUDE_ABOMINABLE_QUALIFIERS

#define BOOST_CLBL_TRTS_INCLUDE_QUALIFIERS const volatile &
#define BOOST_CLBL_TRTS_INCLUDE_ABOMINABLE_QUALIFIERS const volatile &
#include <boost/callable_traits/detail/unguarded/pmf_2.hpp>
#undef BOOST_CLBL_TRTS_INCLUDE_QUALIFIERS
#undef BOOST_CLBL_TRTS_INCLUDE_ABOMINABLE_QUALIFIERS

#define BOOST_CLBL_TRTS_INCLUDE_QUALIFIERS const &&
#define BOOST_CLBL_TRTS_INCLUDE_ABOMINABLE_QUALIFIERS const &&
#include <boost/callable_traits/detail/unguarded/pmf_2.hpp>
#undef BOOST_CLBL_TRTS_INCLUDE_QUALIFIERS
#undef BOOST_CLBL_TRTS_INCLUDE_ABOMINABLE_QUALIFIERS

#define BOOST_CLBL_TRTS_INCLUDE_QUALIFIERS volatile &&
#define BOOST_CLBL_TRTS_INCLUDE_ABOMINABLE_QUALIFIERS volatile &&
#include <boost/callable_traits/detail/unguarded/pmf_2.hpp>
#undef BOOST_CLBL_TRTS_INCLUDE_QUALIFIERS
#undef BOOST_CLBL_TRTS_INCLUDE_ABOMINABLE_QUALIFIERS

#define BOOST_CLBL_TRTS_INCLUDE_QUALIFIERS const volatile &&
#define BOOST_CLBL_TRTS_INCLUDE_ABOMINABLE_QUALIFIERS const volatile &&
#include <boost/callable_traits/detail/unguarded/pmf_2.hpp>
#undef BOOST_CLBL_TRTS_INCLUDE_QUALIFIERS
#undef BOOST_CLBL_TRTS_INCLUDE_ABOMINABLE_QUALIFIERS

#endif // #ifndef BOOST_CLBL_TRTS_DISABLE_REFERENCE_QUALIFIERS
<commit_msg>Delete pmf.hpp<commit_after><|endoftext|>


<commit_before>#include <cstdio>
#include <cmath>
#include <vector>
#include <random>
#include <chrono>

namespace NQueens
{
    class Board
    {
        std::default_random_engine generator;
        std::vector<int> rows;
        int refillInterval;

        int getConflictCount(int row, int col) const
        {
            int count = 0;

            for (int i = 0; i < (int)rows.size(); ++i)
                if (i != col && (rows[i] == row || abs(rows[i] - row) == abs(i - col)))
                    count++;

            return count;
        }

    public:
        Board(unsigned seed, int n, int interval): generator(seed), rows(n), refillInterval(interval)
        {
            Refill();
        }

        void Refill()
        {
            for (int i = 0; i < (int)rows.size(); ++i)
                rows[i] = i;

            for (int i = 0; i < (int)rows.size(); ++i)
                std::swap(rows[i], rows[generator() % (int)rows.size()]);
        }

        void Solve()
        {
            int moveCount = 0;

            while (true)
            {
                std::vector<int> candidates;

                for (int i = 0; i < (int)rows.size(); ++i)
                    if (getConflictCount(rows[i], i) > 0)
                        candidates.push_back(i);
                if (candidates.empty())
                    return;

                int worstQueenColumn = candidates[generator() % candidates.size()];
                candidates.clear();
                int minConflictCount = (int)rows.size();
                for (int i = 0; i < (int)rows.size(); ++i)
                {
                    int conflictCount = getConflictCount(i, worstQueenColumn);
                    if (conflictCount < minConflictCount)
                    {
                        minConflictCount = conflictCount;
                        candidates.clear();
                    }
                    if (conflictCount == minConflictCount)
                        candidates.push_back(i);
                }
                if (!candidates.empty())
                    rows[worstQueenColumn] = candidates[generator() % candidates.size()];

                ++moveCount;
                if (refillInterval == moveCount)
                {
                    Refill();
                    moveCount = 0;
                }
            }
        }

        void Print() const
        {
            for (int i = 0; i < (int)rows.size(); ++i)
            {
                for (int j = 0; j < (int)rows.size(); ++j)
                    printf(rows[j] == i ? "*" : "_");

                printf("\n");
            }
        }
    };
}

int main()
{
    int n;
    scanf("%d", &n);
    if (n < 0)
        return 1;

    NQueens::Board queens(std::chrono::system_clock::now().time_since_epoch().count(), n, 2 * n);
    queens.Solve();
    queens.Print();
    return 0;
}
<commit_msg>nqueens: improved random index generation using `std::uniform_int_distribution` instead of calculating indexes using remainder<commit_after>#include <cstdio>
#include <cmath>
#include <vector>
#include <random>
#include <chrono>

namespace NQueens
{
    class Board
    {
        std::default_random_engine generator;
        std::vector<int> rows;
        int refillInterval;

        int getConflictCount(int row, int col) const
        {
            int count = 0;

            for (int i = 0; i < (int)rows.size(); ++i)
                if (i != col && (rows[i] == row || abs(rows[i] - row) == abs(i - col)))
                    count++;

            return count;
        }

    public:
        Board(unsigned seed, int n, int interval): generator(seed), rows(n), refillInterval(interval)
        {
            Refill();
        }

        void Refill()
        {
            for (int i = 0; i < (int)rows.size(); ++i)
                rows[i] = i;

            for (int i = 0; i < (int)rows.size(); ++i)
            {
                std::uniform_int_distribution<> distribution(0, (int)rows.size() - 1);
                std::swap(rows[i], rows[distribution(generator)]);
            }
        }

        void Solve()
        {
            int moveCount = 0;

            while (true)
            {
                std::vector<int> candidates;

                for (int i = 0; i < (int)rows.size(); ++i)
                    if (getConflictCount(rows[i], i) > 0)
                        candidates.push_back(i);
                if (candidates.empty())
                    return;

                std::uniform_int_distribution<> worstDistribution(0, (int)candidates.size() - 1);
                int worstQueenColumn = candidates[worstDistribution(generator)];
                candidates.clear();
                int minConflictCount = (int)rows.size();
                for (int i = 0; i < (int)rows.size(); ++i)
                {
                    int conflictCount = getConflictCount(i, worstQueenColumn);
                    if (conflictCount < minConflictCount)
                    {
                        minConflictCount = conflictCount;
                        candidates.clear();
                    }
                    if (conflictCount == minConflictCount)
                        candidates.push_back(i);
                }
                if (!candidates.empty())
                {
                    std::uniform_int_distribution<> bestDistribution(0, (int)candidates.size() - 1);
                    rows[worstQueenColumn] = candidates[bestDistribution(generator)];
                }

                ++moveCount;
                if (refillInterval == moveCount)
                {
                    Refill();
                    moveCount = 0;
                }
            }
        }

        void Print() const
        {
            for (int i = 0; i < (int)rows.size(); ++i)
            {
                for (int j = 0; j < (int)rows.size(); ++j)
                    printf(rows[j] == i ? "*" : "_");

                printf("\n");
            }
        }
    };
}

int main()
{
    int n;
    scanf("%d", &n);
    if (n < 0)
        return 1;

    NQueens::Board queens(std::chrono::system_clock::now().time_since_epoch().count(), n, 2 * n);
    queens.Solve();
    queens.Print();
    return 0;
}
<|endoftext|>


<commit_before>#include "httpd.h"
#include <stdio.h>
#include <string.h>
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif

int  opterr = 1;
int  optind = 1;
int  optopt;
char *optarg;

static int getopt(int argc, char** argv, const char* opts) {
	static int sp = 1;
	register int c;
	register char *cp;

	if(sp == 1) {
		if(optind >= argc ||
				argv[optind][0] != '-' || argv[optind][1] == '\0')
			return(EOF);
		else if(strcmp(argv[optind], "--") == 0) {
			optind++;
			return(EOF);
		}
	}
	optopt = c = argv[optind][sp];
	if(c == ':' || (cp=strchr((char*)opts, c)) == NULL) {
		if(argv[optind][++sp] == '\0') {
			optind++;
			sp = 1;
		}
		return('?');
	}
	if(*++cp == ':') {
		if(argv[optind][sp+1] != '\0')
			optarg = &argv[optind++][sp+1];
		else if(++optind >= argc) {
			sp = 1;
			return('?');
		} else
			optarg = argv[optind++];
		sp = 1;
	} else {
		if(argv[optind][++sp] == '\0') {
			sp = 1;
			optind++;
		}
		optarg = NULL;
	}
	return(c);
}

typedef std::map<std::string, std::string>	Config;
typedef std::map<std::string, Config>		ConfigList;
ConfigList loadConfigs(const char* filename) {
	ConfigList configs;
	Config config;
	char buffer[BUFSIZ];
	FILE* fp = fopen(filename, "r");
	std::string profile = "global";
	while(fp && fgets(buffer, sizeof(buffer), fp)) {
		char* line = buffer;
		char* ptr = strpbrk(line, "\r\n");
		if (*line == '#') continue;
		if (ptr) *ptr = 0;
		ptr = strchr(line, ']');
		if (*line == '[' && ptr) {
			*ptr = 0;
			if (config.size())
				configs[profile] = config;
			config.clear();
			profile = line+1;
			continue;
		}
		ptr = strchr(line, '=');
		if (ptr && *line != ';') {
			*ptr++ = 0;
			config[line] = ptr;
		}
	}
	configs[profile] = config;
	if (fp) fclose(fp);
	return configs;
}

bool loadAuthfile(const char* filename, std::vector<tthttpd::server::AuthInfo>& auths) {
	char buffer[BUFSIZ];
	auths.clear();
	FILE* fp = fopen(filename, "r");
	if (!fp) return false;
	while(fp && fgets(buffer, sizeof(buffer), fp)) {
		char* line = buffer;
		char* ptr = strpbrk(line, "\r\n");
		if (ptr) *ptr = 0;
		ptr = strchr(line, ':');
		if (ptr) *ptr++ = 0;
		tthttpd::server::AuthInfo info;
		info.user = line;
		info.pass = ptr;
		auths.push_back(info);
	}
	fclose(fp);
	return true;
}

int main(int argc, char* argv[]) {
	int c;
	const char* root = ".";
	const char* port = "www";
	const char* cfg = NULL;
	bool spawn_exec = false;
	int verbose = 0;
	int family = AF_UNSPEC;

#ifdef _WIN32
	WSADATA wsaData;
	WSAStartup(MAKEWORD(2, 2), &wsaData);
#endif

	opterr = 0;
	while ((c = getopt(argc, (char**)argv, "46p:c:d:xvh") != -1)) {
		switch (optopt) {
		case '4': family = AF_INET;  break;
		case '6': family = AF_INET6; break;
		case 'p': port = optarg; break;
		case 'c': cfg = optarg; break;
		case 'd': root = optarg; break;
		case 'v': verbose++; break;
#ifdef PACKAGE_VERSION
		case 'V':
			printf("%s\n", PACKAGE_VERSION);
			break;
#endif
		case 'x': spawn_exec = true; break;
		case 'h': argc = 0; break;
		case '?': break;
		default: argc = 0; break;
		}
		optarg = NULL;
	}

	if (argc == 0) {
		const char* lines[] = {
#ifdef PACKAGE_VERSION
			"tthttpd (tinytinyhttpd) " PACKAGE_VERSION<
#else
			"tthttpd (tinytinyhttpd)",
#endif
			"  usage: tthttpd [-4|-6] [-p server-port] [-c config-file] [-d root-dir] [-v] [-x] [-h]",
			"  -4 : ipv4 only",
			"  -6 : ipv6 only",
			"  -p : server port (name or numeric)",
			"  -c : config file",
			"  -d : root directory",
			"  -v : verbose mode (-vvv mean level 3)",
			"  -x : spawn file as cgi if possible",
			"  -h : show this usage",
#ifdef PACKAGE_VERSION
			"  -V : show version",
#endif
			NULL
		};
		for (const char** ptr = lines; *ptr; ptr++)
			std::cerr << *ptr << std::endl;
		exit(1);
	}

	tthttpd::server httpd(port);
	httpd.bindRoot(root);
	httpd.spawn_executable = spawn_exec;
	httpd.verbose_mode = verbose;
	httpd.family = family;
	if (cfg) {
		ConfigList configs = loadConfigs(cfg);
		Config config;
		Config::iterator it;
		std::string val;

		val = configs["global"]["path"];
#ifdef _WIN32
		if (val.size()) {
			std::string tmp = "PATH=";
			tmp += val;
			putenv(tmp.c_str());
		}
#else
		if (val.size()) setenv("PATH", val.c_str(), true);
#endif
		val = configs["global"]["root"];
		if (val.size()) httpd.bindRoot(val);
		val = configs["global"]["ipv4_only"];
		if (val == "on") httpd.family = AF_INET;
		val = configs["global"]["ipv6_only"];
		if (val == "on") httpd.family = AF_INET6;
		val = configs["global"]["hostname"];
		if (val.size()) httpd.hostname = val;
		val = configs["global"]["port"];
		if (val.size()) httpd.port = val;
		val = configs["global"]["indexpages"];
		if (val.size()) httpd.default_pages = tthttpd::split_string(val, ",");
		val = configs["global"]["charset"];
		if (val.size()) httpd.fs_charset = val;
		val = configs["global"]["chroot"];
		if (val.size()) httpd.chroot = val;
		val = configs["global"]["user"];
		if (val.size()) httpd.user = val;
		val = configs["global"]["debug"];
		if (val == "on") httpd.verbose_mode = 1;
		else if (val.size()) httpd.verbose_mode = atol(val.c_str());
		val = configs["global"]["spawnexec"];
		if (val == "on") httpd.spawn_executable = true;

		config = configs["request/aliases"];
		for (it = config.begin(); it != config.end(); it++)
			httpd.request_aliases[it->first] = it->second;

		config = configs["mime/types"];
		for (it = config.begin(); it != config.end(); it++)
			httpd.mime_types[it->first] = it->second;

		config = configs["request/environments"];
		for (it = config.begin(); it != config.end(); it++)
			httpd.request_environments[it->first] = it->second;

		config = configs["authentication"];
		for (it = config.begin(); it != config.end(); it++) {
			tthttpd::server::BasicAuthInfo basic_auth_info;
			basic_auth_info.target = it->first;
			std::vector<std::string> infos = tthttpd::split_string(it->second, ",");
			basic_auth_info.method = infos[0];
			basic_auth_info.realm = infos[1];
			std::vector<tthttpd::server::AuthInfo> auth_infos;
			if (loadAuthfile(infos[2].c_str(), auth_infos))
				basic_auth_info.auths = auth_infos;
			httpd.basic_auths.push_back(basic_auth_info);
		}

	} else {
#ifdef _WIN32
	httpd.mime_types["cgi"] = "@c:/strawberry/perl/bin/perl.exe";
	httpd.mime_types["php"] = "@c:/progra~1/php/php-cgi.exe";
	httpd.mime_types["rb"] = "@c:/ruby/bin/ruby.exe";
	httpd.mime_types["py"] = "@c:/python25/python.exe";
#else
	httpd.mime_types["cgi"] = "@/usr/bin/perl";
	httpd.mime_types["php"] = "@/usr/bin/php-cgi";
	httpd.mime_types["rb"] = "@/usr/bin/ruby";
	httpd.mime_types["py"] = "@/usr/bin/python";
#endif
	}

	httpd.start();
	httpd.wait();
	// Ctrl-C to break

	return 0;
}
<commit_msg>< to ,<commit_after>#include "httpd.h"
#include <stdio.h>
#include <string.h>
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif

int  opterr = 1;
int  optind = 1;
int  optopt;
char *optarg;

static int getopt(int argc, char** argv, const char* opts) {
	static int sp = 1;
	register int c;
	register char *cp;

	if(sp == 1) {
		if(optind >= argc ||
				argv[optind][0] != '-' || argv[optind][1] == '\0')
			return(EOF);
		else if(strcmp(argv[optind], "--") == 0) {
			optind++;
			return(EOF);
		}
	}
	optopt = c = argv[optind][sp];
	if(c == ':' || (cp=strchr((char*)opts, c)) == NULL) {
		if(argv[optind][++sp] == '\0') {
			optind++;
			sp = 1;
		}
		return('?');
	}
	if(*++cp == ':') {
		if(argv[optind][sp+1] != '\0')
			optarg = &argv[optind++][sp+1];
		else if(++optind >= argc) {
			sp = 1;
			return('?');
		} else
			optarg = argv[optind++];
		sp = 1;
	} else {
		if(argv[optind][++sp] == '\0') {
			sp = 1;
			optind++;
		}
		optarg = NULL;
	}
	return(c);
}

typedef std::map<std::string, std::string>	Config;
typedef std::map<std::string, Config>		ConfigList;
ConfigList loadConfigs(const char* filename) {
	ConfigList configs;
	Config config;
	char buffer[BUFSIZ];
	FILE* fp = fopen(filename, "r");
	std::string profile = "global";
	while(fp && fgets(buffer, sizeof(buffer), fp)) {
		char* line = buffer;
		char* ptr = strpbrk(line, "\r\n");
		if (*line == '#') continue;
		if (ptr) *ptr = 0;
		ptr = strchr(line, ']');
		if (*line == '[' && ptr) {
			*ptr = 0;
			if (config.size())
				configs[profile] = config;
			config.clear();
			profile = line+1;
			continue;
		}
		ptr = strchr(line, '=');
		if (ptr && *line != ';') {
			*ptr++ = 0;
			config[line] = ptr;
		}
	}
	configs[profile] = config;
	if (fp) fclose(fp);
	return configs;
}

bool loadAuthfile(const char* filename, std::vector<tthttpd::server::AuthInfo>& auths) {
	char buffer[BUFSIZ];
	auths.clear();
	FILE* fp = fopen(filename, "r");
	if (!fp) return false;
	while(fp && fgets(buffer, sizeof(buffer), fp)) {
		char* line = buffer;
		char* ptr = strpbrk(line, "\r\n");
		if (ptr) *ptr = 0;
		ptr = strchr(line, ':');
		if (ptr) *ptr++ = 0;
		tthttpd::server::AuthInfo info;
		info.user = line;
		info.pass = ptr;
		auths.push_back(info);
	}
	fclose(fp);
	return true;
}

int main(int argc, char* argv[]) {
	int c;
	const char* root = ".";
	const char* port = "www";
	const char* cfg = NULL;
	bool spawn_exec = false;
	int verbose = 0;
	int family = AF_UNSPEC;

#ifdef _WIN32
	WSADATA wsaData;
	WSAStartup(MAKEWORD(2, 2), &wsaData);
#endif

	opterr = 0;
	while ((c = getopt(argc, (char**)argv, "46p:c:d:xvh") != -1)) {
		switch (optopt) {
		case '4': family = AF_INET;  break;
		case '6': family = AF_INET6; break;
		case 'p': port = optarg; break;
		case 'c': cfg = optarg; break;
		case 'd': root = optarg; break;
		case 'v': verbose++; break;
#ifdef PACKAGE_VERSION
		case 'V':
			printf("%s\n", PACKAGE_VERSION);
			break;
#endif
		case 'x': spawn_exec = true; break;
		case 'h': argc = 0; break;
		case '?': break;
		default: argc = 0; break;
		}
		optarg = NULL;
	}

	if (argc == 0) {
		const char* lines[] = {
#ifdef PACKAGE_VERSION
			"tthttpd (tinytinyhttpd) " PACKAGE_VERSION,
#else
			"tthttpd (tinytinyhttpd)",
#endif
			"  usage: tthttpd [-4|-6] [-p server-port] [-c config-file] [-d root-dir] [-v] [-x] [-h]",
			"  -4 : ipv4 only",
			"  -6 : ipv6 only",
			"  -p : server port (name or numeric)",
			"  -c : config file",
			"  -d : root directory",
			"  -v : verbose mode (-vvv mean level 3)",
			"  -x : spawn file as cgi if possible",
			"  -h : show this usage",
#ifdef PACKAGE_VERSION
			"  -V : show version",
#endif
			NULL
		};
		for (const char** ptr = lines; *ptr; ptr++)
			std::cerr << *ptr << std::endl;
		exit(1);
	}

	tthttpd::server httpd(port);
	httpd.bindRoot(root);
	httpd.spawn_executable = spawn_exec;
	httpd.verbose_mode = verbose;
	httpd.family = family;
	if (cfg) {
		ConfigList configs = loadConfigs(cfg);
		Config config;
		Config::iterator it;
		std::string val;

		val = configs["global"]["path"];
#ifdef _WIN32
		if (val.size()) {
			std::string tmp = "PATH=";
			tmp += val;
			putenv(tmp.c_str());
		}
#else
		if (val.size()) setenv("PATH", val.c_str(), true);
#endif
		val = configs["global"]["root"];
		if (val.size()) httpd.bindRoot(val);
		val = configs["global"]["ipv4_only"];
		if (val == "on") httpd.family = AF_INET;
		val = configs["global"]["ipv6_only"];
		if (val == "on") httpd.family = AF_INET6;
		val = configs["global"]["hostname"];
		if (val.size()) httpd.hostname = val;
		val = configs["global"]["port"];
		if (val.size()) httpd.port = val;
		val = configs["global"]["indexpages"];
		if (val.size()) httpd.default_pages = tthttpd::split_string(val, ",");
		val = configs["global"]["charset"];
		if (val.size()) httpd.fs_charset = val;
		val = configs["global"]["chroot"];
		if (val.size()) httpd.chroot = val;
		val = configs["global"]["user"];
		if (val.size()) httpd.user = val;
		val = configs["global"]["debug"];
		if (val == "on") httpd.verbose_mode = 1;
		else if (val.size()) httpd.verbose_mode = atol(val.c_str());
		val = configs["global"]["spawnexec"];
		if (val == "on") httpd.spawn_executable = true;

		config = configs["request/aliases"];
		for (it = config.begin(); it != config.end(); it++)
			httpd.request_aliases[it->first] = it->second;

		config = configs["mime/types"];
		for (it = config.begin(); it != config.end(); it++)
			httpd.mime_types[it->first] = it->second;

		config = configs["request/environments"];
		for (it = config.begin(); it != config.end(); it++)
			httpd.request_environments[it->first] = it->second;

		config = configs["authentication"];
		for (it = config.begin(); it != config.end(); it++) {
			tthttpd::server::BasicAuthInfo basic_auth_info;
			basic_auth_info.target = it->first;
			std::vector<std::string> infos = tthttpd::split_string(it->second, ",");
			basic_auth_info.method = infos[0];
			basic_auth_info.realm = infos[1];
			std::vector<tthttpd::server::AuthInfo> auth_infos;
			if (loadAuthfile(infos[2].c_str(), auth_infos))
				basic_auth_info.auths = auth_infos;
			httpd.basic_auths.push_back(basic_auth_info);
		}

	} else {
#ifdef _WIN32
	httpd.mime_types["cgi"] = "@c:/strawberry/perl/bin/perl.exe";
	httpd.mime_types["php"] = "@c:/progra~1/php/php-cgi.exe";
	httpd.mime_types["rb"] = "@c:/ruby/bin/ruby.exe";
	httpd.mime_types["py"] = "@c:/python25/python.exe";
#else
	httpd.mime_types["cgi"] = "@/usr/bin/perl";
	httpd.mime_types["php"] = "@/usr/bin/php-cgi";
	httpd.mime_types["rb"] = "@/usr/bin/ruby";
	httpd.mime_types["py"] = "@/usr/bin/python";
#endif
	}

	httpd.start();
	httpd.wait();
	// Ctrl-C to break

	return 0;
}
<|endoftext|>


<commit_before>#include "scope.h"
#include "details/ir/emit.h"

using namespace Yuni;

namespace ny {
namespace ir {
namespace Producer {

namespace {

bool extractParameterDetails(Scope& scope, AST::Node& node, uint32_t& lvid, AnyString& name) {
	bool isRef = false;
	bool isConst = false;
	AST::Node* typeNode = nullptr;
	for (auto& child: node.children) {
		switch (child.rule) {
			case AST::rgIdentifier: {
				name = child.text;
				break;
			}
			case AST::rgRef:
				isRef   = true;
				break;
			case AST::rgConst:
				isConst = true;
				break;
			case AST::rgCref:
				isRef   = true;
				isConst = true;
				break;
			case AST::rgVarType: {
				for (auto& typeChild: child.children) {
					switch (typeChild.rule) {
						case AST::rgType: {
							typeNode = &typeChild;
							break;
						}
						default:
							return unexpectedNode(child, "on/scope/fail/param/details/type");
					}
				}
				break;
			}
			default:
				return unexpectedNode(child, "on/scope/fail/param/details");
		}
	}
	if (typeNode != nullptr) {
		if (!scope.visitASTType(*typeNode, lvid))
			return false;
		switch (lvid) {
			default: {
				if (isRef)
					ir::emit::type::qualifierRef(scope.ircode(), lvid, true);
				if (isConst)
					ir::emit::type::qualifierConst(scope.ircode(), lvid, true);
				break;
			}
			case (uint32_t) -1: {
				lvid = 0; // let's pretend no type was given
				break;
			}
			case 0: // void
				return error(*typeNode) << "void is not a valid parameter type";
		}
	}
	return true;
}

bool findParameter(Scope& scope, AST::Node& node, uint32_t& lvid, AnyString& name) {
	bool hasParameter = false;
	for (auto& child: node.children) {
		if (unlikely(child.rule != AST::rgFuncParams))
			return unexpectedNode(child, "on/scope/fail");
		for (auto& paramsChild: child.children) {
			if (unlikely(paramsChild.rule != AST::rgFuncParam))
				return unexpectedNode(paramsChild, "on/scope/fail/params");
			if (unlikely(hasParameter))
				return error(paramsChild) << "'on scope fail' accepts only one parameter";
			hasParameter = true;
			if (!extractParameterDetails(scope, paramsChild, lvid, name))
				return false;
		}
	}
	return true;
}

} // namespace

bool Scope::visitASTExprOnScopeFail(AST::Node& scopeNode, AST::Node& scopeFailNode) {
	assert(scopeNode.rule == AST::rgScope);
	assert(scopeFailNode.rule == AST::rgOnScopeFail);
	uint32_t lvidType = 0;
	AnyString name;
	if (!findParameter(*this, scopeFailNode, lvidType, name))
		return false;
	auto& irout = ircode();
	ir::emit::trace(irout, "begin 'on scope fail'");
	// skip the entire block
	uint32_t ignJmp = ir::emit::jmp(irout);
	// label to trigger the error handler
	uint32_t startLabel = ir::emit::label(irout, nextvar());
	uint32_t var = [&]() -> uint32_t {
		if (name.empty())
			return 0;
		// the error itself
		uint32_t var = ir::emit::alloc(irout, nextvar());
		if (lvidType != 0) {
			auto& operands    = irout.emit<isa::Op::follow>();
			operands.follower = var;
			operands.lvid     = lvidType;
			operands.symlink  = 0;
		}
		return var;
	}();
	// register the 'on scope fail'
	emitDebugpos(scopeFailNode);
	ir::emit::on::scopefail(irout, var, startLabel);
	{
		if (not visitASTExprScope(scopeNode))
			return false;
	}
	// jmp at the end of the original scope
	uint32_t jmpOffset = ir::emit::jmp(irout);
	onScopeFailExitLabels.emplace_back(scopeFailNode, jmpOffset, var);
	// emit label to skip the entire block
	irout.at<ir::isa::Op::jmp>(ignJmp).label = ir::emit::label(irout, nextvar());
	ir::emit::trace(irout, "end 'on scope fail'");
	return true;
}

} // namespace Producer
} // namespace ir
} // namespace ny
<commit_msg>semantic: on-scope-fail: register after code to avoid invalid reuse<commit_after>#include "scope.h"
#include "details/ir/emit.h"

using namespace Yuni;

namespace ny {
namespace ir {
namespace Producer {

namespace {

bool extractParameterDetails(Scope& scope, AST::Node& node, uint32_t& lvid, AnyString& name) {
	bool isRef = false;
	bool isConst = false;
	AST::Node* typeNode = nullptr;
	for (auto& child: node.children) {
		switch (child.rule) {
			case AST::rgIdentifier: {
				name = child.text;
				break;
			}
			case AST::rgRef:
				isRef   = true;
				break;
			case AST::rgConst:
				isConst = true;
				break;
			case AST::rgCref:
				isRef   = true;
				isConst = true;
				break;
			case AST::rgVarType: {
				for (auto& typeChild: child.children) {
					switch (typeChild.rule) {
						case AST::rgType: {
							typeNode = &typeChild;
							break;
						}
						default:
							return unexpectedNode(child, "on/scope/fail/param/details/type");
					}
				}
				break;
			}
			default:
				return unexpectedNode(child, "on/scope/fail/param/details");
		}
	}
	if (typeNode != nullptr) {
		if (!scope.visitASTType(*typeNode, lvid))
			return false;
		switch (lvid) {
			default: {
				if (isRef)
					ir::emit::type::qualifierRef(scope.ircode(), lvid, true);
				if (isConst)
					ir::emit::type::qualifierConst(scope.ircode(), lvid, true);
				break;
			}
			case (uint32_t) -1: {
				lvid = 0; // let's pretend no type was given
				break;
			}
			case 0: // void
				return error(*typeNode) << "void is not a valid parameter type";
		}
	}
	return true;
}

bool findParameter(Scope& scope, AST::Node& node, uint32_t& lvid, AnyString& name) {
	bool hasParameter = false;
	for (auto& child: node.children) {
		if (unlikely(child.rule != AST::rgFuncParams))
			return unexpectedNode(child, "on/scope/fail");
		for (auto& paramsChild: child.children) {
			if (unlikely(paramsChild.rule != AST::rgFuncParam))
				return unexpectedNode(paramsChild, "on/scope/fail/params");
			if (unlikely(hasParameter))
				return error(paramsChild) << "'on scope fail' accepts only one parameter";
			hasParameter = true;
			if (!extractParameterDetails(scope, paramsChild, lvid, name))
				return false;
		}
	}
	return true;
}

} // namespace

bool Scope::visitASTExprOnScopeFail(AST::Node& scopeNode, AST::Node& scopeFailNode) {
	assert(scopeNode.rule == AST::rgScope);
	assert(scopeFailNode.rule == AST::rgOnScopeFail);
	uint32_t lvidType = 0;
	AnyString name;
	if (!findParameter(*this, scopeFailNode, lvidType, name))
		return false;
	auto& irout = ircode();
	ir::emit::trace(irout, "begin 'on scope fail'");
	// skip the entire block
	uint32_t ignJmp = ir::emit::jmp(irout);
	// label to trigger the error handler
	uint32_t startLabel = ir::emit::label(irout, nextvar());
	uint32_t var = [&]() -> uint32_t {
		if (name.empty())
			return 0;
		// the error itself
		uint32_t var = ir::emit::alloc(irout, nextvar());
		if (lvidType != 0) {
			auto& operands    = irout.emit<isa::Op::follow>();
			operands.follower = var;
			operands.lvid     = lvidType;
			operands.symlink  = 0;
		}
		return var;
	}();
	if (not visitASTExprScope(scopeNode))
		return false;
	// register the 'on scope fail' after the code for the error handler to not be reused
	emitDebugpos(scopeFailNode);
	ir::emit::on::scopefail(irout, var, startLabel);
	// jmp at the end of the original scope
	uint32_t jmpOffset = ir::emit::jmp(irout);
	onScopeFailExitLabels.emplace_back(scopeFailNode, jmpOffset, var);
	// emit label to skip the entire block
	irout.at<ir::isa::Op::jmp>(ignJmp).label = ir::emit::label(irout, nextvar());
	ir::emit::trace(irout, "end 'on scope fail'");
	return true;
}

} // namespace Producer
} // namespace ir
} // namespace ny
<|endoftext|>


<commit_before>// File: decoder.hh
// Decodes the names and types encoded by OCC

#ifndef H_SYNOPSIS_CPP_DECODER
#define H_SYNOPSIS_CPP_DECODER

#include <string>
#include <vector>

// Forward decl of Types::Type
namespace Types { class Type; }

// bad duplicate typedef.. hmm
typedef std::vector<std::string> ScopedName;

// Forward decl of Builder
class Builder;

class Lookup;

namespace std {
//. A specialization of the char_traits for unsigned char
  template<>
    struct char_traits<unsigned char>
    {
      typedef unsigned char	char_type;
      typedef int 	        int_type;
      typedef streampos 	pos_type;
      typedef streamoff 	off_type;
      typedef mbstate_t 	state_type;

      static void
      assign(char_type& __c1, const char_type& __c2)
      { __c1 = __c2; }

      static bool
      eq(const char_type& __c1, const char_type& __c2)
      { return __c1 == __c2; }

      static bool
      lt(const char_type& __c1, const char_type& __c2)
      { return __c1 < __c2; }

      static int
      compare(const char_type* __s1, const char_type* __s2, size_t __n)
      { return memcmp(__s1, __s2, __n); }

      static size_t
      length(const char_type* __s)
      { return strlen(reinterpret_cast<const char*>(__s)); }

      static const char_type*
      find(const char_type* __s, size_t __n, const char_type& __a)
      { return static_cast<const char_type*>(memchr(__s, __a, __n)); }

      static char_type*
      move(char_type* __s1, const char_type* __s2, size_t __n)
      { return static_cast<char_type*>(memmove(__s1, __s2, __n)); }

      static char_type*
      copy(char_type* __s1, const char_type* __s2, size_t __n)
      {  return static_cast<char_type*>(memcpy(__s1, __s2, __n)); }

      static char_type*
      assign(char_type* __s, size_t __n, char_type __a)
      { return static_cast<char_type*>(memset(__s, __a, __n)); }

      static char_type
      to_char_type(const int_type& __c)
      { return static_cast<char_type>(__c); }

      // To keep both the byte 0xff and the eof symbol 0xffffffff
      // from ending up as 0xffffffff.
      static int_type
      to_int_type(const char_type& __c)
      { return static_cast<int_type>(static_cast<unsigned char>(__c)); }

      static bool
      eq_int_type(const int_type& __c1, const int_type& __c2)
      { return __c1 == __c2; }

      static int_type
      eof() { return static_cast<int_type>(EOF); }

      static int_type
      not_eof(const int_type& __c)
      { return (__c == eof()) ? 0 : __c; }
  };
};

//. A string type for the encoded names and types
typedef std::basic_string<unsigned char> code;
//. A string iterator type for the encoded names and types
typedef code::iterator code_iter;

//. Insertion operator for encoded names and types
std::ostream& operator <<(std::ostream& o, const code& s);

//. Decoder for OCC encodings. This class can be used to decode the names and
//. types encoded by OCC for function and variable types and names.
class Decoder {
public:
    //. Constructor
    Decoder(Builder*);

    //. Convert a char* to a 'code' type
    static code toCode(char*);

    //. Initialise the type decoder
    void init(char*);

    //. Returns the iterator used in decoding
    code_iter& iter() { return m_iter; }

    //. Return a Type object from the encoded type.
    //. @preconditions You must call init() first.
    Types::Type* decodeType();

    //. Decodes a Qualified type. iter must be just after the Q
    Types::Type* decodeQualType();

    //. Decodes a Template type. iter must be just after the T
    Types::Type* decodeTemplate();

    //. Decodes a FuncPtr type. iter must be just after the F
    Types::Type* decodeFuncPtr();

    //. Decode a name
    std::string decodeName();

    //. Decode a qualified name
    ScopedName decodeQualified();

    //. Decode a name starting from the given iterator.
    //. Note the iterator passed need not be from the currently decoding
    //. string since this is a simple method.
    std::string decodeName(code_iter);

    //. Decode a name starting from the given char*
    std::string decodeName(char*);

    //. Decode a qualified name with only names in it
    void decodeQualName(ScopedName& names);

    //. Returns true if the char* is pointing to a name (that starts with a
    //. length). This is needed since char can be signed or unsigned, and
    //. explicitly casting to one or the other is ugly
    bool isName(char* ptr);

private:
    //. The encoded type string currently being decoded
    code m_string;
    //. The current position in m_enc_iter
    code_iter m_iter;

    //. The builder
    Builder* m_builder;

    //. The lookup
    Lookup* m_lookup;
};

inline bool Decoder::isName(char* ptr)
{
    code::value_type* iter = reinterpret_cast<code::value_type*>(ptr);
    return iter && iter[0] > 0x80;
}

#endif // header guard
<commit_msg>Wrap the char_traits in a check for G++ 3.2 or higher<commit_after>// File: decoder.hh
// Decodes the names and types encoded by OCC

#ifndef H_SYNOPSIS_CPP_DECODER
#define H_SYNOPSIS_CPP_DECODER

#include <string>
#include <vector>

// Forward decl of Types::Type
namespace Types { class Type; }

// bad duplicate typedef.. hmm
typedef std::vector<std::string> ScopedName;

// Forward decl of Builder
class Builder;

class Lookup;

#if defined(__GNUC__) && __GNUC__ >= 3 && __GNUC_MINOR__ >= 2
namespace std {
//. A specialization of the char_traits for unsigned char
  template<>
    struct char_traits<unsigned char>
    {
      typedef unsigned char	char_type;
      typedef int 	        int_type;
      typedef streampos 	pos_type;
      typedef streamoff 	off_type;
      typedef mbstate_t 	state_type;

      static void
      assign(char_type& __c1, const char_type& __c2)
      { __c1 = __c2; }

      static bool
      eq(const char_type& __c1, const char_type& __c2)
      { return __c1 == __c2; }

      static bool
      lt(const char_type& __c1, const char_type& __c2)
      { return __c1 < __c2; }

      static int
      compare(const char_type* __s1, const char_type* __s2, size_t __n)
      { return memcmp(__s1, __s2, __n); }

      static size_t
      length(const char_type* __s)
      { return strlen(reinterpret_cast<const char*>(__s)); }

      static const char_type*
      find(const char_type* __s, size_t __n, const char_type& __a)
      { return static_cast<const char_type*>(memchr(__s, __a, __n)); }

      static char_type*
      move(char_type* __s1, const char_type* __s2, size_t __n)
      { return static_cast<char_type*>(memmove(__s1, __s2, __n)); }

      static char_type*
      copy(char_type* __s1, const char_type* __s2, size_t __n)
      {  return static_cast<char_type*>(memcpy(__s1, __s2, __n)); }

      static char_type*
      assign(char_type* __s, size_t __n, char_type __a)
      { return static_cast<char_type*>(memset(__s, __a, __n)); }

      static char_type
      to_char_type(const int_type& __c)
      { return static_cast<char_type>(__c); }

      // To keep both the byte 0xff and the eof symbol 0xffffffff
      // from ending up as 0xffffffff.
      static int_type
      to_int_type(const char_type& __c)
      { return static_cast<int_type>(static_cast<unsigned char>(__c)); }

      static bool
      eq_int_type(const int_type& __c1, const int_type& __c2)
      { return __c1 == __c2; }

      static int_type
      eof() { return static_cast<int_type>(EOF); }

      static int_type
      not_eof(const int_type& __c)
      { return (__c == eof()) ? 0 : __c; }
  };
};
#endif

//. A string type for the encoded names and types
typedef std::basic_string<unsigned char> code;
//. A string iterator type for the encoded names and types
typedef code::iterator code_iter;

//. Insertion operator for encoded names and types
std::ostream& operator <<(std::ostream& o, const code& s);

//. Decoder for OCC encodings. This class can be used to decode the names and
//. types encoded by OCC for function and variable types and names.
class Decoder {
public:
    //. Constructor
    Decoder(Builder*);

    //. Convert a char* to a 'code' type
    static code toCode(char*);

    //. Initialise the type decoder
    void init(char*);

    //. Returns the iterator used in decoding
    code_iter& iter() { return m_iter; }

    //. Return a Type object from the encoded type.
    //. @preconditions You must call init() first.
    Types::Type* decodeType();

    //. Decodes a Qualified type. iter must be just after the Q
    Types::Type* decodeQualType();

    //. Decodes a Template type. iter must be just after the T
    Types::Type* decodeTemplate();

    //. Decodes a FuncPtr type. iter must be just after the F
    Types::Type* decodeFuncPtr();

    //. Decode a name
    std::string decodeName();

    //. Decode a qualified name
    ScopedName decodeQualified();

    //. Decode a name starting from the given iterator.
    //. Note the iterator passed need not be from the currently decoding
    //. string since this is a simple method.
    std::string decodeName(code_iter);

    //. Decode a name starting from the given char*
    std::string decodeName(char*);

    //. Decode a qualified name with only names in it
    void decodeQualName(ScopedName& names);

    //. Returns true if the char* is pointing to a name (that starts with a
    //. length). This is needed since char can be signed or unsigned, and
    //. explicitly casting to one or the other is ugly
    bool isName(char* ptr);

private:
    //. The encoded type string currently being decoded
    code m_string;
    //. The current position in m_enc_iter
    code_iter m_iter;

    //. The builder
    Builder* m_builder;

    //. The lookup
    Lookup* m_lookup;
};

inline bool Decoder::isName(char* ptr)
{
    code::value_type* iter = reinterpret_cast<code::value_type*>(ptr);
    return iter && iter[0] > 0x80;
}

#endif // header guard
<|endoftext|>