<commit_before>

#include "histoBook.h"
#include "TKey.h"
#include "TObject.h"

// constructor sets the name of the file for saving
histoBook::histoBook( string name, string input, string inDir ){

	if (name.find(  ".root") != std::string::npos){
		filename = name;
	} else
		filename = name + ".root";

	currentDir = "/";

	file = new TFile( filename.c_str(), "recreate" );
	file->cd();

	// make the legend and draw it once to apply styles etc.
	// for some reason needed to make styling work on the first draw
	legend = new TLegend( 0.65, 0.65, 0.9, 0.9);
	legend->SetFillColor( kWhite );
	legend->Draw();
	legend->Clear();

	globalStyle();

	// if an input was given merge it into the live record
	if ( input.length() >= 5 ){
		TFile * fin = new TFile( input.c_str() );
		cd ( inDir );
		fin->cd( inDir.c_str() );
		loadRootDir( gDirectory, inDir );
	}

}
// destructor
histoBook::~histoBook(){

	delete legend;

	save();
	file->Close();
}
void histoBook::save() {

	file->Write();
}

void histoBook::loadRootDir( TDirectory* tDir, string path ){

	//cout << "histoBook.loadRootDir] Path : " << path << endl;

	TList* list;

	if ( tDir ){
		list = tDir->GetListOfKeys();
	} else {
		cout << "[histoBook.loadRootDir] Bad Directory Given " << endl;
		return;
	}

	TIter next(list);
	TKey* key;
	TObject* obj;

	while ( (key = (TKey*)next()) ) {

		obj = key->ReadObj() ;

		if ( 0 == strcmp(obj->IsA()->GetName(),"TDirectoryFile") ){
			TDirectoryFile* dir = (TDirectoryFile*)obj;

			string nPath = path + dir->GetName();
			if ( path == (string) "" )
				nPath = path + dir->GetName();
			else
				nPath = path + "/" + dir->GetName();

			cd( nPath );
			loadRootDir( dir, nPath );
		} else if ( obj ){
			if (    (strcmp(obj->IsA()->GetName(),"TProfile")!=0) && (!obj->InheritsFrom("TH2") && (!obj->InheritsFrom("TH1"))) ) {
				// not a 1d or 2d histogram
			} else {
				// add it to the book
				//cout << "Adding : " << obj->GetName() << endl;
				add( obj->GetName(), (TH1*)obj->Clone( obj->GetName() ) );
			}

		}
	}

}

void histoBook::add( string name, TH1* h ){

	string oName = name;
	if ( name.length() <= 1 || !h )
		return;

	name = currentDir + name;

	// dont allow duplicated name overites
	if ( book[ name ] ){
		cout << "[histoBook.add] Duplicate histogram name in this directory " << currentDir << " / " << oName << endl;
		return;
	}

	// save the histo to the map
	book[ name ] = h;

}
/*
*
* TODO:: add support for full subdirectory trees
*/
string histoBook::cd( string sdir  ){

	string old = currentDir;

	char* csdir = (char*)sdir.c_str();
	file->cd();

	if ( file->GetDirectory( csdir ) ){
		file->cd( csdir );
	} else {
		cout << "[histoBook.cd] creating directory " << sdir << endl;
		file->mkdir( csdir );
		file->cd( csdir );
	}

	currentDir = sdir;

	return old;
}

void histoBook::make( xmlConfig * config, string nodeName ){

	if ( config && config->nodeExists( nodeName ) ){

		string hName = config->tagName( nodeName );
		if ( "" == hName )
			hName = nodeName;

		string type = config->getString( nodeName + ":type", "1D" );

		if ( "1D" == type ){
			make1D( hName, config->getString( nodeName + ":title", hName ),
					config->getInt( nodeName + ":nBinsX", 1 ), config->getDouble( nodeName + ":x1", 0 ),
					config->getDouble( nodeName + ":x2", 1 ) );

		} else if ( "2D" == type ){
			make2D( hName, config->getString( nodeName + ":title", hName ),
					config->getInt( nodeName + ":nBinsX", 1 ), config->getDouble( nodeName + ":x1", 0 ),
					config->getDouble( nodeName + ":x2", 1 ),
					config->getInt( nodeName + ":nBinsY", 1 ), config->getDouble( nodeName + ":y1", 0 ),
					config->getDouble( nodeName + ":y2", 1 ) );

	}

}

void histoBook::make1F( string name, string title, uint nBins, double low, double hi  ){

	TH1F* h;
	h = new TH1F( name.c_str(), title.c_str(), nBins, low, hi );

	this->add( name, h );
}

void histoBook::make1D( string name, string title, uint nBins, double low, double hi  ){

	TH1D* h;
	h = new TH1D( name.c_str(), title.c_str(), nBins, low, hi );

	this->add( name, h );
}

void histoBook::make1D( string name, string title, uint nBins, const Double_t* bins  ){

	TH1D* h;
	h = new TH1D( name.c_str(), title.c_str(), nBins, bins );

	this->add( name, h );
}

void histoBook::make2D( string name, string title, uint nBinsX, double lowX, double hiX, uint nBinsY, double lowY, double hiY ){

	TH2D* h;

	h = new TH2D( name.c_str(), title.c_str(), nBinsX, lowX, hiX, nBinsY, lowY, hiY );

	this->add( name, h );
}
void histoBook::make2D( string name, string title, uint nBinsX, const Double_t* xBins, uint nBinsY, double lowY, double hiY ){

	TH2D* h;
	h = new TH2D( name.c_str(), title.c_str(), nBinsX, xBins, nBinsY, lowY, hiY );

	this->add( name, h );
}

TH1* histoBook::get( string name, string sdir  ){
	if ( sdir.compare("") == 0)
		sdir = currentDir;
	return book[ ( sdir  + name  ) ];
}
TH2* histoBook::get2D( string name, string sdir  ){
	if ( sdir.compare("") == 0)
		sdir = currentDir;
	return (TH2*)book[ ( sdir  + name  ) ];
}

void histoBook::fill( string name, double bin, double weight ){
	if ( get( name ) != 0)
		get( name )->Fill( bin, weight );
}

void histoBook::globalStyle(){

	gStyle->SetCanvasColor(kWhite);     // background is no longer mouse-dropping white
  	gStyle->SetPalette(1,0);            // blue to red false color palette. Use 9 for b/w
  	gStyle->SetCanvasBorderMode(0);     // turn off canvas borders
  	gStyle->SetPadBorderMode(0);
  	gStyle->SetPaintTextFormat("5.2f");  // What precision to put numbers if plotted with "TEXT"

  	// For publishing:
  	gStyle->SetLineWidth(2.);
  	gStyle->SetTextSize(0.7);
  	gStyle->SetLabelSize(0.05,"xy");
  	gStyle->SetTitleSize(0.05,"xy");
  	gStyle->SetTitleOffset(1.0,"x");
  	gStyle->SetTitleOffset(1.5,"y");
  	gStyle->SetPadTopMargin(0.1);
  	gStyle->SetPadRightMargin(0.1);
  	gStyle->SetPadBottomMargin(0.16);
  	gStyle->SetPadLeftMargin(0.2);

  	gStyle->SetFillColor(-1);
	gStyle->SetFillStyle(4000);

}

histoBook* histoBook::style( string histName ){
	styling = histName;
	return this;
}

histoBook* histoBook::set( string param, string p1, string p2, string p3, string p4 ){

	// force the param name to lowercase
	transform(param.begin(), param.end(), param.begin(), ::tolower);

    TH1* h = get( styling );
    if ( h ){

	    if ( "title" == param ){
	    	h->SetTitle( p1.c_str() );
	    } else if ( "x" == param ){
	    	h->GetXaxis()->SetTitle( p1.c_str() );
	    } else if ( "y" == param ){
	    	h->GetYaxis()->SetTitle( p1.c_str() );
	    } else if ( "legend" == param ){
	    	if ( p2 == "")
	    		p2="lpf";
	    	legend->AddEntry( h, p1.c_str(), p2.c_str() );
			legend->Draw();
	    } else if ( "draw" == param ){
	    	drawOption = p1;
	    }
	}

	return this;
}

histoBook* histoBook::set( string param, double p1, double p2, double p3, double p4  ){

	transform(param.begin(), param.end(), param.begin(), ::tolower);

    TH1* h = get( styling );
    if ( h ){

	    if ( "linecolor" == param ){

	    	h->SetLineColor( (int) p1 );
	    } else if ( "domain" == param ){
	    	double min = p1;
	    	double max = p2;
		    h->GetXaxis()->SetRangeUser( min, max );
	    } else if ( "dynamicdomain" == param ){
	    	double thresh = p1;
	    	int min = (int)p2;
	    	int max = (int)p3;
	    	int axis = (int)p4;		// 1 = x, 2 = y

	    	if ( 1 != axis && 2 != axis )
	    		axis = 1;

	    	if ( thresh >= 0) {
	    		if ( -1 >= min )
	    			min = h->FindFirstBinAbove( thresh, axis );
	    		if ( -1 >= max )
	    			max = h->FindLastBinAbove( thresh, axis );
	    	}

	    	if ( 1 == axis )
		  	  h->GetXaxis()->SetRange( min, max );
		  	else if ( 2 == axis )
		  		h->GetYaxis()->SetRange( min, max );

	    }  else if ( "range" == param ){

	    	double min = p1;
	    	double max = p2;

	    	h->GetYaxis()->SetRangeUser( min, max );
	    } else if ( "markercolor" == param ) {
	    	h->SetMarkerColor( (int)p1 );
	    } else if ( "markerstyle" == param ) {
	    	h->SetMarkerStyle( (int)p1 );
	    } else if ( "legend" == param ){
	    	// p1 - alignmentX
	    	// p2 - alignmentY
	    	// p3 - width
	    	// p4 - height

	    	// make sure option is valid
	    	if ( !(legendAlignment::center == p1 || legendAlignment::left == p1 || legendAlignment::right == p1) )
	    		p1 = legendAlignment::best;
	    	if ( !(legendAlignment::center == p2 || legendAlignment::top == p2 || legendAlignment::bottom == p2) )
	    		p2 = legendAlignment::best;
	    	placeLegend( p1, p2, p3, p4 );
	    } else if ( "numberofticks" == param ){
	    	// p1 - # of primary divisions
	    	// p2 - # of secondary divisions
	    	// p3 - axis : 0 or 1 = x, 2 = y

	    	if ( p2 == -1 )
	    		p2 = 0;

		    if ( 2 == (int)p3 )
		    	h->GetYaxis()->SetNdivisions( (int) p1, (int) p2, 0, true );
		    else
		    	h->GetXaxis()->SetNdivisions( (int) p1, (int) p2, 0, true );
	    }

    }

	return this;
}

histoBook* histoBook::draw(string name, Option_t* opt ){

	// no parameters
	if ( name == ""){
		TH1* h = get( styling );
		if ( h ){
			// use the draw option set in its styling
			h->Draw( drawOption.c_str() );
			drawOption = "";
		}
	} else {
		TH1* h = get( name );
		if ( h ){
			h->Draw( opt );
		}
	}

	return this;
}

histoBook* histoBook::placeLegend( int alignmentX, int alignmentY, double width, double height ){

	double mR = 1 - gPad->GetRightMargin();
	double mL = gPad->GetLeftMargin();
	double mT = 1- gPad->GetTopMargin();
	double mB = gPad->GetBottomMargin();

	double x1, x2, y1, y2;

	if ( width <= 0 || width > 1 )
		width = .2;
	if ( height <= 0 || height > 1 )
		height = .2;

	// alignment best needs a current histo
	if ( !(get( styling )) ){
		if ( legendAlignment::best == alignmentX )
			alignmentX = legendAlignment::right;
		if ( legendAlignment::best == alignmentY )
			alignmentY = legendAlignment::top;
	} else {

		//TODO

	}

	if ( 	legendAlignment::left ==  alignmentX ){
		x1 =  mL ;
		x2 =  mL + width;
	}
	if ( 	legendAlignment::right ==  alignmentX ){
		x1 =  mR - width;
		x2 =  mR ;
	}
	if ( 	legendAlignment::center ==  alignmentX ){
		x1 =  0.55 - width/2.0;
		x2 =  0.55 + width/2.0;
	}
	if ( 	legendAlignment::top ==  alignmentY ){
		y1 =  mT - height;
		y2 = mT ;
	}
	if ( 	legendAlignment::bottom ==  alignmentY ){
		y1 =  mB ;
		y2 =  mB + height;
	}
	if ( 	legendAlignment::center ==  alignmentY ){
		y1 =  0.55 - height/2.0;
		y2 =  0.55 + height/2.0;
	}
	legend->SetX1NDC( x1 );
	legend->SetX2NDC( x2 );
	legend->SetY1NDC( y1 );
	legend->SetY2NDC( y2 );

	return this;
}<commit_msg>test upstream<commit_after>

#include "histoBook.h"
#include "TKey.h"
#include "TObject.h"

// constructor sets the name of the file for saving
histoBook::histoBook( string name, string input, string inDir ){

	if (name.find(  ".root") != std::string::npos){
		filename = name;
	} else
		filename = name + ".root";

	currentDir = "/";

	file = new TFile( filename.c_str(), "recreate" );
	file->cd();

	// make the legend and draw it once to apply styles etc.
	// for some reason needed to make styling work on the first draw
	legend = new TLegend( 0.65, 0.65, 0.9, 0.9);
	legend->SetFillColor( kWhite );
	legend->Draw();
	legend->Clear();

	globalStyle();

	// if an input was given merge it into the live record
	if ( input.length() >= 5 ){
		TFile * fin = new TFile( input.c_str() );
		cd ( inDir );
		fin->cd( inDir.c_str() );
		loadRootDir( gDirectory, inDir );
	}

}
// destructor
histoBook::~histoBook(){

	delete legend;

	save();
	file->Close();
}
void histoBook::save() {

	file->Write();
}

void histoBook::loadRootDir( TDirectory* tDir, string path ){

	//cout << "histoBook.loadRootDir] Path : " << path << endl;

	TList* list;

	if ( tDir ){
		list = tDir->GetListOfKeys();
	} else {
		cout << "[histoBook.loadRootDir] Bad Directory Given " << endl;
		return;
	}

	TIter next(list);
	TKey* key;
	TObject* obj;

	while ( (key = (TKey*)next()) ) {

		obj = key->ReadObj() ;

		if ( 0 == strcmp(obj->IsA()->GetName(),"TDirectoryFile") ){
			TDirectoryFile* dir = (TDirectoryFile*)obj;

			string nPath = path + dir->GetName();
			if ( path == (string) "" )
				nPath = path + dir->GetName();
			else
				nPath = path + "/" + dir->GetName();

			cd( nPath );
			loadRootDir( dir, nPath );
		} else if ( obj ){
			if (    (strcmp(obj->IsA()->GetName(),"TProfile")!=0) && (!obj->InheritsFrom("TH2") && (!obj->InheritsFrom("TH1"))) ) {
				// not a 1d or 2d histogram
			} else {
				// add it to the book
				//cout << "Adding : " << obj->GetName() << endl;
				add( obj->GetName(), (TH1*)obj->Clone( obj->GetName() ) );
			}

		}
	}

}

void histoBook::add( string name, TH1* h ){

	string oName = name;
	if ( name.length() <= 1 || !h )
		return;

	name = currentDir + name;

	// dont allow duplicated name overites
	if ( book[ name ] ){
		cout << "[histoBook.add] Duplicate histogram name in this directory " << currentDir << " / " << oName << endl;
		return;
	}

	// save the histo to the map
	book[ name ] = h;

}
/*
*
* TODO:: add support for full subdirectory trees
*/
string histoBook::cd( string sdir  ){

	string old = currentDir;

	char* csdir = (char*)sdir.c_str();
	file->cd();

	if ( file->GetDirectory( csdir ) ){
		file->cd( csdir );
	} else {
		cout << "[histoBook.cd] creating directory " << sdir << endl;
		file->mkdir( csdir );
		file->cd( csdir );
	}

	currentDir = sdir;

	return old;
}

void histoBook::make( xmlConfig * config, string nodeName ){

	if ( config && config->nodeExists( nodeName ) ){

		string hName = config->tagName( nodeName );
		if ( "" == hName )
			hName = nodeName;

		string type = config->getString( nodeName + ":type", "1D" );

		if ( "1D" == type ){
			make1D( hName, config->getString( nodeName + ":title", hName ),
					config->getInt( nodeName + ":nBinsX", 1 ), config->getDouble( nodeName + ":x1", 0 ),
					config->getDouble( nodeName + ":x2", 1 ) );

		} else if ( "2D" == type ){
			make2D( hName, config->getString( nodeName + ":title", hName ),
					config->getInt( nodeName + ":nBinsX", 1 ), config->getDouble( nodeName + ":x1", 0 ),
					config->getDouble( nodeName + ":x2", 1 ),
					config->getInt( nodeName + ":nBinsY", 1 ), config->getDouble( nodeName + ":y1", 0 ),
					config->getDouble( nodeName + ":y2", 1 ) );
		}

	}

}

void histoBook::make1F( string name, string title, uint nBins, double low, double hi  ){

	TH1F* h;
	h = new TH1F( name.c_str(), title.c_str(), nBins, low, hi );

	this->add( name, h );
}

void histoBook::make1D( string name, string title, uint nBins, double low, double hi  ){

	TH1D* h;
	h = new TH1D( name.c_str(), title.c_str(), nBins, low, hi );

	this->add( name, h );
}

void histoBook::make1D( string name, string title, uint nBins, const Double_t* bins  ){

	TH1D* h;
	h = new TH1D( name.c_str(), title.c_str(), nBins, bins );

	this->add( name, h );
}

void histoBook::make2D( string name, string title, uint nBinsX, double lowX, double hiX, uint nBinsY, double lowY, double hiY ){

	TH2D* h;

	h = new TH2D( name.c_str(), title.c_str(), nBinsX, lowX, hiX, nBinsY, lowY, hiY );

	this->add( name, h );
}
void histoBook::make2D( string name, string title, uint nBinsX, const Double_t* xBins, uint nBinsY, double lowY, double hiY ){

	TH2D* h;
	h = new TH2D( name.c_str(), title.c_str(), nBinsX, xBins, nBinsY, lowY, hiY );

	this->add( name, h );
}

TH1* histoBook::get( string name, string sdir  ){
	if ( sdir.compare("") == 0)
		sdir = currentDir;
	return book[ ( sdir  + name  ) ];
}
TH2* histoBook::get2D( string name, string sdir  ){
	if ( sdir.compare("") == 0)
		sdir = currentDir;
	return (TH2*)book[ ( sdir  + name  ) ];
}

void histoBook::fill( string name, double bin, double weight ){
	if ( get( name ) != 0)
		get( name )->Fill( bin, weight );
}

void histoBook::globalStyle(){

	gStyle->SetCanvasColor(kWhite);     // background is no longer mouse-dropping white
  	gStyle->SetPalette(1,0);            // blue to red false color palette. Use 9 for b/w
  	gStyle->SetCanvasBorderMode(0);     // turn off canvas borders
  	gStyle->SetPadBorderMode(0);
  	gStyle->SetPaintTextFormat("5.2f");  // What precision to put numbers if plotted with "TEXT"

  	// For publishing:
  	gStyle->SetLineWidth(2.);
  	gStyle->SetTextSize(0.7);
  	gStyle->SetLabelSize(0.05,"xy");
  	gStyle->SetTitleSize(0.05,"xy");
  	gStyle->SetTitleOffset(1.0,"x");
  	gStyle->SetTitleOffset(1.5,"y");
  	gStyle->SetPadTopMargin(0.1);
  	gStyle->SetPadRightMargin(0.1);
  	gStyle->SetPadBottomMargin(0.16);
  	gStyle->SetPadLeftMargin(0.2);

  	gStyle->SetFillColor(-1);
	gStyle->SetFillStyle(4000);

}

histoBook* histoBook::style( string histName ){
	styling = histName;
	return this;
}

histoBook* histoBook::set( string param, string p1, string p2, string p3, string p4 ){

	// force the param name to lowercase
	transform(param.begin(), param.end(), param.begin(), ::tolower);

    TH1* h = get( styling );
    if ( h ){

	    if ( "title" == param ){
	    	h->SetTitle( p1.c_str() );
	    } else if ( "x" == param ){
	    	h->GetXaxis()->SetTitle( p1.c_str() );
	    } else if ( "y" == param ){
	    	h->GetYaxis()->SetTitle( p1.c_str() );
	    } else if ( "legend" == param ){
	    	if ( p2 == "")
	    		p2="lpf";
	    	legend->AddEntry( h, p1.c_str(), p2.c_str() );
			legend->Draw();
	    } else if ( "draw" == param ){
	    	drawOption = p1;
	    }
	}

	return this;
}

histoBook* histoBook::set( string param, double p1, double p2, double p3, double p4  ){

	transform(param.begin(), param.end(), param.begin(), ::tolower);

    TH1* h = get( styling );
    if ( h ){

	    if ( "linecolor" == param ){

	    	h->SetLineColor( (int) p1 );
	    } else if ( "domain" == param ){
	    	double min = p1;
	    	double max = p2;
		    h->GetXaxis()->SetRangeUser( min, max );
	    } else if ( "dynamicdomain" == param ){
	    	double thresh = p1;
	    	int min = (int)p2;
	    	int max = (int)p3;
	    	int axis = (int)p4;		// 1 = x, 2 = y

	    	if ( 1 != axis && 2 != axis )
	    		axis = 1;

	    	if ( thresh >= 0) {
	    		if ( -1 >= min )
	    			min = h->FindFirstBinAbove( thresh, axis );
	    		if ( -1 >= max )
	    			max = h->FindLastBinAbove( thresh, axis );
	    	}

	    	if ( 1 == axis )
		  	  h->GetXaxis()->SetRange( min, max );
		  	else if ( 2 == axis )
		  		h->GetYaxis()->SetRange( min, max );

	    }  else if ( "range" == param ){

	    	double min = p1;
	    	double max = p2;

	    	h->GetYaxis()->SetRangeUser( min, max );
	    } else if ( "markercolor" == param ) {
	    	h->SetMarkerColor( (int)p1 );
	    } else if ( "markerstyle" == param ) {
	    	h->SetMarkerStyle( (int)p1 );
	    } else if ( "legend" == param ){
	    	// p1 - alignmentX
	    	// p2 - alignmentY
	    	// p3 - width
	    	// p4 - height

	    	// make sure option is valid
	    	if ( !(legendAlignment::center == p1 || legendAlignment::left == p1 || legendAlignment::right == p1) )
	    		p1 = legendAlignment::best;
	    	if ( !(legendAlignment::center == p2 || legendAlignment::top == p2 || legendAlignment::bottom == p2) )
	    		p2 = legendAlignment::best;
	    	placeLegend( p1, p2, p3, p4 );
	    } else if ( "numberofticks" == param ){
	    	// p1 - # of primary divisions
	    	// p2 - # of secondary divisions
	    	// p3 - axis : 0 or 1 = x, 2 = y

	    	if ( p2 == -1 )
	    		p2 = 0;

		    if ( 2 == (int)p3 )
		    	h->GetYaxis()->SetNdivisions( (int) p1, (int) p2, 0, true );
		    else
		    	h->GetXaxis()->SetNdivisions( (int) p1, (int) p2, 0, true );
	    }

    }

	return this;
}

histoBook* histoBook::draw(string name, Option_t* opt ){

	// no parameters
	if ( name == ""){
		TH1* h = get( styling );
		if ( h ){
			// use the draw option set in its styling
			h->Draw( drawOption.c_str() );
			drawOption = "";
		}
	} else {
		TH1* h = get( name );
		if ( h ){
			h->Draw( opt );
		}
	}

	return this;
}

histoBook* histoBook::placeLegend( int alignmentX, int alignmentY, double width, double height ){

	double mR = 1 - gPad->GetRightMargin();
	double mL = gPad->GetLeftMargin();
	double mT = 1- gPad->GetTopMargin();
	double mB = gPad->GetBottomMargin();

	double x1, x2, y1, y2;

	if ( width <= 0 || width > 1 )
		width = .2;
	if ( height <= 0 || height > 1 )
		height = .2;

	// alignment best needs a current histo
	if ( !(get( styling )) ){
		if ( legendAlignment::best == alignmentX )
			alignmentX = legendAlignment::right;
		if ( legendAlignment::best == alignmentY )
			alignmentY = legendAlignment::top;
	} else {

		//TODO

	}

	if ( 	legendAlignment::left ==  alignmentX ){
		x1 =  mL ;
		x2 =  mL + width;
	}
	if ( 	legendAlignment::right ==  alignmentX ){
		x1 =  mR - width;
		x2 =  mR ;
	}
	if ( 	legendAlignment::center ==  alignmentX ){
		x1 =  0.55 - width/2.0;
		x2 =  0.55 + width/2.0;
	}
	if ( 	legendAlignment::top ==  alignmentY ){
		y1 =  mT - height;
		y2 = mT ;
	}
	if ( 	legendAlignment::bottom ==  alignmentY ){
		y1 =  mB ;
		y2 =  mB + height;
	}
	if ( 	legendAlignment::center ==  alignmentY ){
		y1 =  0.55 - height/2.0;
		y2 =  0.55 + height/2.0;
	}
	legend->SetX1NDC( x1 );
	legend->SetX2NDC( x2 );
	legend->SetY1NDC( y1 );
	legend->SetY2NDC( y2 );

	return this;
}<|endoftext|>


<commit_before>#include <cmath>
#include <cstdarg>
#include <iostream>

#include "opencv2/core.hpp"
using namespace cv;

#include "math.hpp"

float median(std::vector<float>& v)
{
	const int n = v.size();
	assert(n > 0);
	if (n == 1) return v[0];

	std::sort(v.begin(), v.end());
	return v[n / 2];
}

float mean(std::vector<float>& v)
{
	const int n = v.size();
	if (n == 0) return 0.f;

	float sum = std::accumulate(std::begin(v), std::end(v), 0.0);
	return sum / n;
}

float var(std::vector<float>& v)
{
	const int n = v.size();
	if (n == 0) return 0.f;

	float _mean = mean(v);
	return sqrt(std::accumulate(std::begin(v), std::end(v), 0.f,
		[&](const float b, const float e) {
			float diff = e - _mean;
			return b + diff * diff;
		}) / n);
}

float randInt(const float min, const float max)
{
	return roundf(rand() / (float)RAND_MAX * (max - min) + min);
}

Rect randomCrop(const Mat& img, const float w2hrat)
{
	int h    = img.rows,
	    w    = img.cols,
	    minh = 8,
	    minw = 8;

	int x0, y0, dx, dy;
	while (1)
	{
		x0 = randInt(0,    w - minw);
		y0 = randInt(0,    h - minh);
		dy = randInt(minh, h - 1 - y0);
		if (w2hrat > 1e-5) // Valid aspect ratio
		{
			dx = roundf((float) dy * w2hrat);
			if (dx < minw || x0 + dx + 1 > w) continue;
		}
		else
			dx = randInt(minw, w - 1 - x0);

		return Rect(x0, y0, dx, dy);
	}
}

Rect randomCrop(const Mat& img, const Rect good_crop, const float thresh)
{
	Rect crop = randomCrop(img);
	while (cropOverlap(good_crop, crop) > thresh)
		crop = randomCrop(img);
	return crop;
}

float cropOverlap(const Rect crop1, const Rect crop2)
{
	int x1a = crop1.x,
	    y1a = crop1.y,
	    x1b = crop1.x + crop1.width,
	    y1b = crop1.y + crop1.height,
	    x2a = crop2.x,
	    y2a = crop2.y,
	    x2b = crop2.x + crop2.width,
	    y2b = crop2.y + crop2.height;

	int ow = max(0, min(x1b, x2b) - max(x1a, x2a)),
	    oh = max(0, min(y1b, y2b) - max(y1a, y2a));

	int oA = ow * oh;
	if (oA == 0) return 0;

	int A1 = crop1.width * crop1.height,
	    A2 = crop2.width * crop2.height;

	return oA / (float) (A1 + A2 - oA);
}

<commit_msg>Change minh, minw in randomCrop<commit_after>#include <cmath>
#include <cstdarg>
#include <iostream>

#include "opencv2/core.hpp"
using namespace cv;

#include "math.hpp"

float median(std::vector<float>& v)
{
	const int n = v.size();
	assert(n > 0);
	if (n == 1) return v[0];

	std::sort(v.begin(), v.end());
	return v[n / 2];
}

float mean(std::vector<float>& v)
{
	const int n = v.size();
	if (n == 0) return 0.f;

	float sum = std::accumulate(std::begin(v), std::end(v), 0.0);
	return sum / n;
}

float var(std::vector<float>& v)
{
	const int n = v.size();
	if (n == 0) return 0.f;

	float _mean = mean(v);
	return sqrt(std::accumulate(std::begin(v), std::end(v), 0.f,
		[&](const float b, const float e) {
			float diff = e - _mean;
			return b + diff * diff;
		}) / n);
}

float randInt(const float min, const float max)
{
	return roundf(rand() / (float)RAND_MAX * (max - min) + min);
}

Rect randomCrop(const Mat& img, const float w2hrat)
{
	int h    = img.rows,
	    w    = img.cols,
	    minh = max(32, h / 8),
	    minw = max(32, w / 8);

	int x0, y0, dx, dy;
	while (1)
	{
		x0 = randInt(0,    w - minw);
		y0 = randInt(0,    h - minh);
		dy = randInt(minh, h - 1 - y0);
		if (w2hrat > 1e-5) // Valid aspect ratio
		{
			dx = roundf((float) dy * w2hrat);
			if (dx < minw || x0 + dx + 1 > w) continue;
		}
		else
			dx = randInt(minw, w - 1 - x0);

		return Rect(x0, y0, dx, dy);
	}
}

Rect randomCrop(const Mat& img, const Rect good_crop, const float thresh)
{
	Rect crop = randomCrop(img);
	while (cropOverlap(good_crop, crop) > thresh)
		crop = randomCrop(img);
	return crop;
}

float cropOverlap(const Rect crop1, const Rect crop2)
{
	int x1a = crop1.x,
	    y1a = crop1.y,
	    x1b = crop1.x + crop1.width,
	    y1b = crop1.y + crop1.height,
	    x2a = crop2.x,
	    y2a = crop2.y,
	    x2b = crop2.x + crop2.width,
	    y2b = crop2.y + crop2.height;

	int ow = max(0, min(x1b, x2b) - max(x1a, x2a)),
	    oh = max(0, min(y1b, y2b) - max(y1a, y2a));

	int oA = ow * oh;
	if (oA == 0) return 0;

	int A1 = crop1.width * crop1.height,
	    A2 = crop2.width * crop2.height;

	return oA / (float) (A1 + A2 - oA);
}

<|endoftext|>


<commit_before>{% extends '0key_output.cpp' %}

{% block templateargs %}
{{state_type}}, counter, &{{update_func}}, &get_count
{% endblock %}

{% block output %}
{{output_tuple_type}} {{output_tuple_name}};
{{output_tuple_set_func}}({{output_tuple_name}}_tmp);
{% endblock %}

<commit_msg>remove newlines in template<commit_after>{% extends '0key_output.cpp' %}

{% block templateargs %}{{state_type}}, counter, &{{update_func}}, &get_count{% endblock %}

{% block output %}
{{output_tuple_type}} {{output_tuple_name}};
{{output_tuple_set_func}}({{output_tuple_name}}_tmp);
{% endblock %}

<|endoftext|>


<commit_before>#include "vast/index.h"

#include <cppa/cppa.hpp>
#include "vast/bitmap_index.h"
#include "vast/segment.h"
#include "vast/expression.h"
#include "vast/partition.h"
#include "vast/uuid.h"
#include "vast/io/serialization.h"

using namespace cppa;

namespace vast {

index_actor::index_actor(path directory, size_t batch_size)
  : dir_{std::move(directory)},
    batch_size_{batch_size}
{
}

char const* index_actor::description() const
{
  return "index";
}

void index_actor::act()
{
  chaining(false);
  trap_exit(true);

  traverse(
      dir_,
      [&](path const& p) -> bool
      {
        if (! exists(p / "coverage"))
        {
          // If the meta data of a partition does not exist, we have a file
          // system inconsistency and ignore the partition.
          VAST_LOG_ACTOR_WARN("couldn't find meta data for partition " << p);
        }
        else
        {
          auto part = spawn<partition_actor, monitored>(p, batch_size_);
          partitions_.emplace(p.basename(), part);
        }

        return true;
      });

  if (! partitions_.empty())
  {
    auto active = partitions_.rbegin();
    VAST_LOG_ACTOR_INFO("sets existing partition as active: " << active->first);
    active_ = active->second;
  }

  become(
      on(atom("EXIT"), arg_match) >> [=](uint32_t reason)
      {
        if (partitions_.empty())
          quit(reason);
        else
          for (auto& p : partitions_)
            send_exit(p.second, reason);
      },
      on(atom("DOWN"), arg_match) >> [=](uint32_t reason)
      {
        VAST_LOG_ACTOR_DEBUG("got DOWN from " << VAST_ACTOR_ID(last_sender()));

        for (auto i = partitions_.begin(); i != partitions_.end(); ++i)
          if (i->second == last_sender())
          {
            partitions_.erase(i);
            break;
          }

        if (reason == exit::stop)
        {
          if (partitions_.empty())
            quit(exit::stop);
        }
        else
        {
          if (reason != exit::error)
            VAST_LOG_ACTOR_WARN(
                "terminates with unknown exit code from " <<
               VAST_ACTOR_ID(last_sender()) << ": " << reason);

          quit(exit::error);
        }
      },
      on(atom("partition"), arg_match) >> [=](std::string const& part)
      {
        auto part_dir = path{part};

        if (exists(dir_ / part_dir))
          VAST_LOG_ACTOR_INFO("appends to existing partition " << part);
        else
          VAST_LOG_ACTOR_INFO("creates new partition " << part);

        if (! partitions_.count(part_dir))
        {
          auto d = dir_ / part_dir;
          auto a = spawn<partition_actor, monitored>(d, batch_size_);
          partitions_.emplace(part_dir, a);
        }

        VAST_LOG_ACTOR_INFO("sets active partition to " << part_dir);
        active_ = partitions_[part_dir];
        assert(active_);
      },
      on_arg_match >> [=](expr::ast const& ast)
      {
        if (partitions_.empty())
        {
          VAST_LOG_ACTOR_WARN("has no partitions to answer: " << ast);
          return;
        }

        for (auto i = partitions_.rbegin(); i != partitions_.rend(); ++i)
        {
          send(i->second, ast, last_sender());
          VAST_LOG_ACTOR_DEBUG("sent predicate " << ast <<
                               " to partition " << VAST_ACTOR_ID(i->second));
        }
      },
      on_arg_match >> [=](segment const& s)
      {
        if (partitions_.empty())
        {
          auto id = uuid::random();
          VAST_LOG_ACTOR_INFO("creates new random partition " << id);
          auto part_dir = dir_ / to<string>(id);
          assert(! exists(part_dir));
          auto p = spawn<partition_actor, monitored>(part_dir, batch_size_);
          active_ = p;
          partitions_.emplace(part_dir.basename(), std::move(p));
        }

        forward_to(active_);
        return make_any_tuple(atom("segment"), atom("ack"), s.id());
      },
      on(atom("delete")) >> [=]
      {
        if (partitions_.empty())
        {
          VAST_LOG_ACTOR_WARN("ignores request to delete empty index");
          return;
        }

        become(
            keep_behavior,
            on(atom("DOWN"), arg_match) >> [=](uint32_t reason)
            {
              if (reason != exit::kill)
                VAST_LOG_ACTOR_WARN(
                    "got DOWN from " << VAST_ACTOR_ID(last_sender()) <<
                    " with unexpected exit code " << reason);

              for (auto i = partitions_.begin(); i != partitions_.end(); ++i)
                if (i->second == last_sender())
                {
                  partitions_.erase(i);
                  break;
                }

              if (partitions_.empty())
              {
                if (! rm(dir_))
                {
                  VAST_LOG_ACTOR_ERROR("failed to delete index directory: " <<
                                       dir_);
                  quit(exit::error);
                  return;
                }

                VAST_LOG_ACTOR_INFO("deleted index: " << dir_);
                unbecome();
              }
            }
        );

        for (auto& p : partitions_)
          send_exit(p.second, exit::kill);
      });
}

} // namespace vast
<commit_msg>Consider "done" as normal exit status.<commit_after>#include "vast/index.h"

#include <cppa/cppa.hpp>
#include "vast/bitmap_index.h"
#include "vast/segment.h"
#include "vast/expression.h"
#include "vast/partition.h"
#include "vast/uuid.h"
#include "vast/io/serialization.h"

using namespace cppa;

namespace vast {

index_actor::index_actor(path directory, size_t batch_size)
  : dir_{std::move(directory)},
    batch_size_{batch_size}
{
}

char const* index_actor::description() const
{
  return "index";
}

void index_actor::act()
{
  chaining(false);
  trap_exit(true);

  traverse(
      dir_,
      [&](path const& p) -> bool
      {
        if (! exists(p / "coverage"))
        {
          // If the meta data of a partition does not exist, we have a file
          // system inconsistency and ignore the partition.
          VAST_LOG_ACTOR_WARN("couldn't find meta data for partition " << p);
        }
        else
        {
          auto part = spawn<partition_actor, monitored>(p, batch_size_);
          partitions_.emplace(p.basename(), part);
        }

        return true;
      });

  if (! partitions_.empty())
  {
    auto active = partitions_.rbegin();
    VAST_LOG_ACTOR_INFO("sets existing partition as active: " << active->first);
    active_ = active->second;
  }

  become(
      on(atom("EXIT"), arg_match) >> [=](uint32_t reason)
      {
        if (partitions_.empty())
          quit(reason);
        else
          for (auto& p : partitions_)
            send_exit(p.second, reason);
      },
      on(atom("DOWN"), arg_match) >> [=](uint32_t reason)
      {
        VAST_LOG_ACTOR_DEBUG("got DOWN from " << VAST_ACTOR_ID(last_sender()));

        for (auto i = partitions_.begin(); i != partitions_.end(); ++i)
          if (i->second == last_sender())
          {
            partitions_.erase(i);
            break;
          }

        if (reason == exit::stop || reason == exit::done)
        {
          if (partitions_.empty())
            quit(reason);
        }
        else
        {
          if (reason != exit::error)
            VAST_LOG_ACTOR_WARN(
                "terminates with unknown exit code from " <<
               VAST_ACTOR_ID(last_sender()) << ": " << reason);

          quit(exit::error);
        }
      },
      on(atom("partition"), arg_match) >> [=](std::string const& part)
      {
        auto part_dir = path{part};

        if (exists(dir_ / part_dir))
          VAST_LOG_ACTOR_INFO("appends to existing partition " << part);
        else
          VAST_LOG_ACTOR_INFO("creates new partition " << part);

        if (! partitions_.count(part_dir))
        {
          auto d = dir_ / part_dir;
          auto a = spawn<partition_actor, monitored>(d, batch_size_);
          partitions_.emplace(part_dir, a);
        }

        VAST_LOG_ACTOR_INFO("sets active partition to " << part_dir);
        active_ = partitions_[part_dir];
        assert(active_);
      },
      on_arg_match >> [=](expr::ast const& ast)
      {
        if (partitions_.empty())
        {
          VAST_LOG_ACTOR_WARN("has no partitions to answer: " << ast);
          return;
        }

        for (auto i = partitions_.rbegin(); i != partitions_.rend(); ++i)
        {
          send(i->second, ast, last_sender());
          VAST_LOG_ACTOR_DEBUG("sent predicate " << ast <<
                               " to partition " << VAST_ACTOR_ID(i->second));
        }
      },
      on_arg_match >> [=](segment const& s)
      {
        if (partitions_.empty())
        {
          auto id = uuid::random();
          VAST_LOG_ACTOR_INFO("creates new random partition " << id);
          auto part_dir = dir_ / to<string>(id);
          assert(! exists(part_dir));
          auto p = spawn<partition_actor, monitored>(part_dir, batch_size_);
          active_ = p;
          partitions_.emplace(part_dir.basename(), std::move(p));
        }

        forward_to(active_);
        return make_any_tuple(atom("segment"), atom("ack"), s.id());
      },
      on(atom("delete")) >> [=]
      {
        if (partitions_.empty())
        {
          VAST_LOG_ACTOR_WARN("ignores request to delete empty index");
          return;
        }

        become(
            keep_behavior,
            on(atom("DOWN"), arg_match) >> [=](uint32_t reason)
            {
              if (reason != exit::kill)
                VAST_LOG_ACTOR_WARN(
                    "got DOWN from " << VAST_ACTOR_ID(last_sender()) <<
                    " with unexpected exit code " << reason);

              for (auto i = partitions_.begin(); i != partitions_.end(); ++i)
                if (i->second == last_sender())
                {
                  partitions_.erase(i);
                  break;
                }

              if (partitions_.empty())
              {
                if (! rm(dir_))
                {
                  VAST_LOG_ACTOR_ERROR("failed to delete index directory: " <<
                                       dir_);
                  quit(exit::error);
                  return;
                }

                VAST_LOG_ACTOR_INFO("deleted index: " << dir_);
                unbecome();
              }
            }
        );

        for (auto& p : partitions_)
          send_exit(p.second, exit::kill);
      });
}

} // namespace vast
<|endoftext|>


<commit_before>#ifndef LUACPP_REGISTER_ANY_FUNCTION_HPP
#define LUACPP_REGISTER_ANY_FUNCTION_HPP

#include "luacpp/stack.hpp"
#include "luacpp/register_closure.hpp"
#include "luacpp/from_lua_cast.hpp"
#include "luacpp/coroutine.hpp"
#include <silicium/detail/integer_sequence.hpp>

namespace lua
{
	namespace detail
	{
		struct call_environment
		{
			lua_State &L;
			bool *suspend_requested;
		};

		template <class T>
		struct argument_converter
		{
			T operator()(call_environment const &env, int address) const
			{
				return from_lua_cast<T>(env.L, address);
			}
		};

		template <class T>
		struct argument_converter<T const &> : argument_converter<T>
		{
		};

		template <>
		struct argument_converter<coroutine>
		{
			coroutine operator()(call_environment const &env, int) const
			{
				return coroutine(env.L, env.suspend_requested);
			}
		};

		template <class ...Parameters, std::size_t ...Indices, class Function>
		auto call_with_converted_arguments(Function &func, call_environment const &env, ranges::v3::integer_sequence<Indices...>)
		{
			return func(argument_converter<Parameters>()(env, 1 + Indices)...);
		}

		template <class NonVoid>
		struct caller
		{
			template <class F, class ...Arguments>
			result_or_yield operator()(call_environment const &env, F const &f, Arguments &&...args) const
			{
				assert(!env.suspend_requested || !*env.suspend_requested); //TODO
				NonVoid result = f(std::forward<Arguments>(args)...);
				push(env.L, std::move(result));
				if (sizeof...(Arguments))
				{
					int const top = lua_gettop(&env.L);
					lua_replace(&env.L, (top - sizeof...(Arguments)));
					lua_pop(&env.L, (sizeof...(Arguments) - 1));
				}
				return 1;
			}
		};

		template <>
		struct caller<void>
		{
			template <class F, class ...Arguments>
			result_or_yield operator()(call_environment const &env, F const &f, Arguments &&...args) const
			{
				f(std::forward<Arguments>(args)...);
				lua_pop(&env.L, sizeof...(Arguments));
				if (env.suspend_requested && *env.suspend_requested)
				{
					return yield();
				}
				return 0;
			}
		};

		template <class F, class R, class ...Parameters>
		stack_value register_any_function_helper(stack &s, F func, R (F::*)(Parameters...) const)
		{
			return register_closure(s, [func
#ifndef _MSC_VER
				= std::move(func)
#endif
			](lua_State *L)
			{
				bool suspend_requested = false;
				call_environment env{*L, &suspend_requested};
				return caller<R>()(env, [
#ifdef _MSC_VER
					func, &env
#else
				&
#endif
				]()
				{
					return call_with_converted_arguments<Parameters...>(func, env, typename ranges::v3::make_integer_sequence<sizeof...(Parameters)>::type());
				});
			});
		}

		template <class F, class R, class ...Parameters>
		stack_value register_any_function_helper(stack &s, F func, R (F::*)(Parameters...))
		{
			return register_closure(s, [func
#ifndef _MSC_VER
				= std::move(func)
#endif
			](lua_State *L) mutable
			{
				bool suspend_requested = false;
				call_environment env{*L, &suspend_requested};
				return caller<R>()(env, [&]()
				{
					return call_with_converted_arguments<Parameters...>(func, env, typename ranges::v3::make_integer_sequence<sizeof...(Parameters)>::type());
				});
			});
		}
	}

	template <class Function>
	stack_value register_any_function(stack &s, Function &&f)
	{
		typedef typename std::decay<Function>::type clean_function;
		auto call_operator = &clean_function::operator();
		return detail::register_any_function_helper<clean_function>(s, std::forward<Function>(f), call_operator);
	}
}

#endif
<commit_msg>silence a warning inside lua_pop<commit_after>#ifndef LUACPP_REGISTER_ANY_FUNCTION_HPP
#define LUACPP_REGISTER_ANY_FUNCTION_HPP

#include "luacpp/stack.hpp"
#include "luacpp/register_closure.hpp"
#include "luacpp/from_lua_cast.hpp"
#include "luacpp/coroutine.hpp"
#include <silicium/detail/integer_sequence.hpp>

namespace lua
{
	namespace detail
	{
		struct call_environment
		{
			lua_State &L;
			bool *suspend_requested;
		};

		template <class T>
		struct argument_converter
		{
			T operator()(call_environment const &env, int address) const
			{
				return from_lua_cast<T>(env.L, address);
			}
		};

		template <class T>
		struct argument_converter<T const &> : argument_converter<T>
		{
		};

		template <>
		struct argument_converter<coroutine>
		{
			coroutine operator()(call_environment const &env, int) const
			{
				return coroutine(env.L, env.suspend_requested);
			}
		};

		template <class ...Parameters, std::size_t ...Indices, class Function>
		auto call_with_converted_arguments(Function &func, call_environment const &env, ranges::v3::integer_sequence<Indices...>)
		{
			return func(argument_converter<Parameters>()(env, 1 + Indices)...);
		}

		template <class NonVoid>
		struct caller
		{
			template <class F, class ...Arguments>
			result_or_yield operator()(call_environment const &env, F const &f, Arguments &&...args) const
			{
				assert(!env.suspend_requested || !*env.suspend_requested); //TODO
				NonVoid result = f(std::forward<Arguments>(args)...);
				push(env.L, std::move(result));
				if (sizeof...(Arguments))
				{
					int const top = lua_gettop(&env.L);
					lua_replace(&env.L, (top - sizeof...(Arguments)));
					lua_pop(&env.L, (sizeof...(Arguments) - 1));
				}
				return 1;
			}
		};

		template <>
		struct caller<void>
		{
			template <class F, class ...Arguments>
			result_or_yield operator()(call_environment const &env, F const &f, Arguments &&...args) const
			{
				f(std::forward<Arguments>(args)...);
				lua_pop(&env.L, static_cast<int>(sizeof...(Arguments)));
				if (env.suspend_requested && *env.suspend_requested)
				{
					return yield();
				}
				return 0;
			}
		};

		template <class F, class R, class ...Parameters>
		stack_value register_any_function_helper(stack &s, F func, R (F::*)(Parameters...) const)
		{
			return register_closure(s, [func
#ifndef _MSC_VER
				= std::move(func)
#endif
			](lua_State *L)
			{
				bool suspend_requested = false;
				call_environment env{*L, &suspend_requested};
				return caller<R>()(env, [
#ifdef _MSC_VER
					func, &env
#else
				&
#endif
				]()
				{
					return call_with_converted_arguments<Parameters...>(func, env, typename ranges::v3::make_integer_sequence<sizeof...(Parameters)>::type());
				});
			});
		}

		template <class F, class R, class ...Parameters>
		stack_value register_any_function_helper(stack &s, F func, R (F::*)(Parameters...))
		{
			return register_closure(s, [func
#ifndef _MSC_VER
				= std::move(func)
#endif
			](lua_State *L) mutable
			{
				bool suspend_requested = false;
				call_environment env{*L, &suspend_requested};
				return caller<R>()(env, [&]()
				{
					return call_with_converted_arguments<Parameters...>(func, env, typename ranges::v3::make_integer_sequence<sizeof...(Parameters)>::type());
				});
			});
		}
	}

	template <class Function>
	stack_value register_any_function(stack &s, Function &&f)
	{
		typedef typename std::decay<Function>::type clean_function;
		auto call_operator = &clean_function::operator();
		return detail::register_any_function_helper<clean_function>(s, std::forward<Function>(f), call_operator);
	}
}

#endif
<|endoftext|>


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

#include <pthread.h>
#include <stdint.h>
#include <string.h>
#include "vmStructs.h"
#include "vmEntry.h"

NativeCodeCache* VMStructs::_libjvm = NULL;

bool VMStructs::_has_class_names = false;
bool VMStructs::_has_class_loader_data = false;
bool VMStructs::_has_thread_bridge = false;
bool VMStructs::_has_perm_gen = false;

int VMStructs::_klass_name_offset = -1;
int VMStructs::_symbol_length_offset = -1;
int VMStructs::_symbol_length_and_refcount_offset = -1;
int VMStructs::_symbol_body_offset = -1;
int VMStructs::_class_loader_data_offset = -1;
int VMStructs::_methods_offset = -1;
int VMStructs::_thread_osthread_offset = -1;
int VMStructs::_thread_anchor_offset = -1;
int VMStructs::_osthread_id_offset = -1;
int VMStructs::_anchor_sp_offset = -1;
int VMStructs::_anchor_pc_offset = -1;
int VMStructs::_frame_size_offset = -1;

jfieldID VMStructs::_eetop;
jfieldID VMStructs::_tid;
jfieldID VMStructs::_klass = NULL;
int VMStructs::_tls_index = -1;
intptr_t VMStructs::_env_offset;

VMStructs::GetStackTraceFunc VMStructs::_get_stack_trace = NULL;
VMStructs::UnsafeParkFunc VMStructs::_unsafe_park = NULL;
VMStructs::FindBlobFunc VMStructs::_find_blob = NULL;
VMStructs::LockFunc VMStructs::_lock_func;
VMStructs::LockFunc VMStructs::_unlock_func;

uintptr_t VMStructs::readSymbol(const char* symbol_name) {
    const void* symbol = _libjvm->findSymbol(symbol_name);
    if (symbol == NULL) {
        // Avoid JVM crash in case of missing symbols
        return 0;
    }
    return *(uintptr_t*)symbol;
}

void VMStructs::init(NativeCodeCache* libjvm) {
    _libjvm = libjvm;

    initOffsets();
    initJvmFunctions();

    JNIEnv* env = VM::jni();
    initThreadBridge(env);
    initLogging(env);
    env->ExceptionClear();
}

void VMStructs::initOffsets() {
    uintptr_t entry = readSymbol("gHotSpotVMStructs");
    uintptr_t stride = readSymbol("gHotSpotVMStructEntryArrayStride");
    uintptr_t type_offset = readSymbol("gHotSpotVMStructEntryTypeNameOffset");
    uintptr_t field_offset = readSymbol("gHotSpotVMStructEntryFieldNameOffset");
    uintptr_t offset_offset = readSymbol("gHotSpotVMStructEntryOffsetOffset");
    uintptr_t address_offset = readSymbol("gHotSpotVMStructEntryAddressOffset");

    if (entry == 0 || stride == 0) {
        return;
    }

    while (true) {
        const char* type = *(const char**)(entry + type_offset);
        const char* field = *(const char**)(entry + field_offset);
        if (type == NULL || field == NULL) {
            break;
        }

        if (strcmp(type, "Klass") == 0) {
            if (strcmp(field, "_name") == 0) {
                _klass_name_offset = *(int*)(entry + offset_offset);
            }
        } else if (strcmp(type, "Symbol") == 0) {
            if (strcmp(field, "_length") == 0) {
                _symbol_length_offset = *(int*)(entry + offset_offset);
            } else if (strcmp(field, "_length_and_refcount") == 0) {
                _symbol_length_and_refcount_offset = *(int*)(entry + offset_offset);
            } else if (strcmp(field, "_body") == 0) {
                _symbol_body_offset = *(int*)(entry + offset_offset);
            }
        } else if (strcmp(type, "InstanceKlass") == 0) {
            if (strcmp(field, "_class_loader_data") == 0) {
                _class_loader_data_offset = *(int*)(entry + offset_offset);
            } else if (strcmp(field, "_methods") == 0) {
                _methods_offset = *(int*)(entry + offset_offset);
            }
        } else if (strcmp(type, "java_lang_Class") == 0) {
            if (strcmp(field, "_klass_offset") == 0) {
                int klass_offset = **(int**)(entry + address_offset);
                _klass = (jfieldID)(uintptr_t)(klass_offset << 2 | 2);
            }
        } else if (strcmp(type, "JavaThread") == 0) {
            if (strcmp(field, "_osthread") == 0) {
                _thread_osthread_offset = *(int*)(entry + offset_offset);
            } else if (strcmp(field, "_anchor") == 0) {
                _thread_anchor_offset = *(int*)(entry + offset_offset);
            }
        } else if (strcmp(type, "OSThread") == 0) {
            if (strcmp(field, "_thread_id") == 0) {
                _osthread_id_offset = *(int*)(entry + offset_offset);
            }
        } else if (strcmp(type, "JavaFrameAnchor") == 0) {
            if (strcmp(field, "_last_Java_sp") == 0) {
                _anchor_sp_offset = *(int*)(entry + offset_offset);
            } else if (strcmp(field, "_last_Java_pc") == 0) {
                _anchor_pc_offset = *(int*)(entry + offset_offset);
            }
        } else if (strcmp(type, "CodeBlob") == 0) {
            if (strcmp(field, "_frame_size") == 0) {
                _frame_size_offset = *(int*)(entry + offset_offset);
            }
        } else if (strcmp(type, "PermGen") == 0) {
            _has_perm_gen = true;
        }

        entry += stride;
    }

    _has_class_names = _klass_name_offset >= 0
            && (_symbol_length_offset >= 0 || _symbol_length_and_refcount_offset >= 0)
            && _symbol_body_offset >= 0
            && _klass != NULL;
}

void VMStructs::initJvmFunctions() {
    _get_stack_trace = (GetStackTraceFunc)_libjvm->findSymbol("_ZN8JvmtiEnv13GetStackTraceEP10JavaThreadiiP15_jvmtiFrameInfoPi");
    if (_get_stack_trace == NULL) {
        _get_stack_trace = (GetStackTraceFunc)_libjvm->findSymbol("_ZN8JvmtiEnv13GetStackTraceEP10JavaThreadiiP14jvmtiFrameInfoPi");
    }

    _unsafe_park = (UnsafeParkFunc)_libjvm->findSymbol("Unsafe_Park");
    if (_unsafe_park == NULL) {
        // In some macOS builds of JDK 11 Unsafe_Park appears to have a C++ decorated name
        _unsafe_park = (UnsafeParkFunc)_libjvm->findSymbol("_ZL11Unsafe_ParkP7JNIEnv_P8_jobjecthl");
    }

    if (_frame_size_offset >= 0) {
        _find_blob = (FindBlobFunc)_libjvm->findSymbol("_ZN9CodeCache16find_blob_unsafeEPv");
        if (_find_blob == NULL) {
            _find_blob = (FindBlobFunc)_libjvm->findSymbol("_ZN9CodeCache9find_blobEPv");
        }
    }

    if (VM::hotspot_version() == 8 && _class_loader_data_offset >= 0 && _methods_offset >= 0 && _klass != NULL) {
        _lock_func = (LockFunc)_libjvm->findSymbol("_ZN7Monitor28lock_without_safepoint_checkEv");
        _unlock_func = (LockFunc)_libjvm->findSymbol("_ZN7Monitor6unlockEv");
        _has_class_loader_data = _lock_func != NULL && _unlock_func != NULL;
    }
}

void VMStructs::initThreadBridge(JNIEnv* env) {
    // Get eetop field - a bridge from Java Thread to VMThread
    jthread thread;
    if (VM::jvmti()->GetCurrentThread(&thread) != 0) {
        return;
    }

    jclass thread_class = env->GetObjectClass(thread);
    _eetop = env->GetFieldID(thread_class, "eetop", "J");
    _tid = env->GetFieldID(thread_class, "tid", "J");
    if (_eetop == NULL || _tid == NULL) {
        return;
    }

    VMThread* vm_thread = VMThread::fromJavaThread(env, thread);
    if (vm_thread == NULL) {
        return;
    }

    // Workaround for JDK-8132510: it's not safe to call GetEnv() inside a signal handler
    // since JDK 9, so we do it only for threads already registered in ThreadLocalStorage
    if (VM::hotspot_version() >= 9) {
        for (int i = 0; i < 1024; i++) {
            if (pthread_getspecific((pthread_key_t)i) == vm_thread) {
                _tls_index = i;
                break;
            }
        }
    }

    _env_offset = (intptr_t)env - (intptr_t)vm_thread;
    _has_thread_bridge = true;
}

void VMStructs::initLogging(JNIEnv* env) {
    // Workaround for JDK-8238460
    if (VM::hotspot_version() >= 15) {
        VMManagement* management = VM::management();
        if (management != NULL) {
            management->ExecuteDiagnosticCommand(env, env->NewStringUTF("VM.log what=jni+resolve=error"));
        }
    }
}

bool VMStructs::hasJNIEnv() {
    return _tls_index < 0 || pthread_getspecific((pthread_key_t)_tls_index) != NULL;
}
<commit_msg>Fixed possible deadlock on non-HotSpot JVMs<commit_after>/*
 * Copyright 2017 Andrei Pangin
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include <pthread.h>
#include <stdint.h>
#include <string.h>
#include "vmStructs.h"
#include "vmEntry.h"

NativeCodeCache* VMStructs::_libjvm = NULL;

bool VMStructs::_has_class_names = false;
bool VMStructs::_has_class_loader_data = false;
bool VMStructs::_has_thread_bridge = false;
bool VMStructs::_has_perm_gen = false;

int VMStructs::_klass_name_offset = -1;
int VMStructs::_symbol_length_offset = -1;
int VMStructs::_symbol_length_and_refcount_offset = -1;
int VMStructs::_symbol_body_offset = -1;
int VMStructs::_class_loader_data_offset = -1;
int VMStructs::_methods_offset = -1;
int VMStructs::_thread_osthread_offset = -1;
int VMStructs::_thread_anchor_offset = -1;
int VMStructs::_osthread_id_offset = -1;
int VMStructs::_anchor_sp_offset = -1;
int VMStructs::_anchor_pc_offset = -1;
int VMStructs::_frame_size_offset = -1;

jfieldID VMStructs::_eetop;
jfieldID VMStructs::_tid;
jfieldID VMStructs::_klass = NULL;
int VMStructs::_tls_index = -1;
intptr_t VMStructs::_env_offset;

VMStructs::GetStackTraceFunc VMStructs::_get_stack_trace = NULL;
VMStructs::UnsafeParkFunc VMStructs::_unsafe_park = NULL;
VMStructs::FindBlobFunc VMStructs::_find_blob = NULL;
VMStructs::LockFunc VMStructs::_lock_func;
VMStructs::LockFunc VMStructs::_unlock_func;

uintptr_t VMStructs::readSymbol(const char* symbol_name) {
    const void* symbol = _libjvm->findSymbol(symbol_name);
    if (symbol == NULL) {
        // Avoid JVM crash in case of missing symbols
        return 0;
    }
    return *(uintptr_t*)symbol;
}

void VMStructs::init(NativeCodeCache* libjvm) {
    _libjvm = libjvm;

    initOffsets();
    initJvmFunctions();

    JNIEnv* env = VM::jni();
    initThreadBridge(env);
    initLogging(env);
    env->ExceptionClear();
}

void VMStructs::initOffsets() {
    uintptr_t entry = readSymbol("gHotSpotVMStructs");
    uintptr_t stride = readSymbol("gHotSpotVMStructEntryArrayStride");
    uintptr_t type_offset = readSymbol("gHotSpotVMStructEntryTypeNameOffset");
    uintptr_t field_offset = readSymbol("gHotSpotVMStructEntryFieldNameOffset");
    uintptr_t offset_offset = readSymbol("gHotSpotVMStructEntryOffsetOffset");
    uintptr_t address_offset = readSymbol("gHotSpotVMStructEntryAddressOffset");

    if (entry == 0 || stride == 0) {
        return;
    }

    while (true) {
        const char* type = *(const char**)(entry + type_offset);
        const char* field = *(const char**)(entry + field_offset);
        if (type == NULL || field == NULL) {
            break;
        }

        if (strcmp(type, "Klass") == 0) {
            if (strcmp(field, "_name") == 0) {
                _klass_name_offset = *(int*)(entry + offset_offset);
            }
        } else if (strcmp(type, "Symbol") == 0) {
            if (strcmp(field, "_length") == 0) {
                _symbol_length_offset = *(int*)(entry + offset_offset);
            } else if (strcmp(field, "_length_and_refcount") == 0) {
                _symbol_length_and_refcount_offset = *(int*)(entry + offset_offset);
            } else if (strcmp(field, "_body") == 0) {
                _symbol_body_offset = *(int*)(entry + offset_offset);
            }
        } else if (strcmp(type, "InstanceKlass") == 0) {
            if (strcmp(field, "_class_loader_data") == 0) {
                _class_loader_data_offset = *(int*)(entry + offset_offset);
            } else if (strcmp(field, "_methods") == 0) {
                _methods_offset = *(int*)(entry + offset_offset);
            }
        } else if (strcmp(type, "java_lang_Class") == 0) {
            if (strcmp(field, "_klass_offset") == 0) {
                int klass_offset = **(int**)(entry + address_offset);
                _klass = (jfieldID)(uintptr_t)(klass_offset << 2 | 2);
            }
        } else if (strcmp(type, "JavaThread") == 0) {
            if (strcmp(field, "_osthread") == 0) {
                _thread_osthread_offset = *(int*)(entry + offset_offset);
            } else if (strcmp(field, "_anchor") == 0) {
                _thread_anchor_offset = *(int*)(entry + offset_offset);
            }
        } else if (strcmp(type, "OSThread") == 0) {
            if (strcmp(field, "_thread_id") == 0) {
                _osthread_id_offset = *(int*)(entry + offset_offset);
            }
        } else if (strcmp(type, "JavaFrameAnchor") == 0) {
            if (strcmp(field, "_last_Java_sp") == 0) {
                _anchor_sp_offset = *(int*)(entry + offset_offset);
            } else if (strcmp(field, "_last_Java_pc") == 0) {
                _anchor_pc_offset = *(int*)(entry + offset_offset);
            }
        } else if (strcmp(type, "CodeBlob") == 0) {
            if (strcmp(field, "_frame_size") == 0) {
                _frame_size_offset = *(int*)(entry + offset_offset);
            }
        } else if (strcmp(type, "PermGen") == 0) {
            _has_perm_gen = true;
        }

        entry += stride;
    }

    _has_class_names = _klass_name_offset >= 0
            && (_symbol_length_offset >= 0 || _symbol_length_and_refcount_offset >= 0)
            && _symbol_body_offset >= 0
            && _klass != NULL;
}

void VMStructs::initJvmFunctions() {
    _get_stack_trace = (GetStackTraceFunc)_libjvm->findSymbol("_ZN8JvmtiEnv13GetStackTraceEP10JavaThreadiiP15_jvmtiFrameInfoPi");
    if (_get_stack_trace == NULL) {
        _get_stack_trace = (GetStackTraceFunc)_libjvm->findSymbol("_ZN8JvmtiEnv13GetStackTraceEP10JavaThreadiiP14jvmtiFrameInfoPi");
    }

    _unsafe_park = (UnsafeParkFunc)_libjvm->findSymbol("Unsafe_Park");
    if (_unsafe_park == NULL) {
        // In some macOS builds of JDK 11 Unsafe_Park appears to have a C++ decorated name
        _unsafe_park = (UnsafeParkFunc)_libjvm->findSymbol("_ZL11Unsafe_ParkP7JNIEnv_P8_jobjecthl");
    }

    if (_frame_size_offset >= 0) {
        _find_blob = (FindBlobFunc)_libjvm->findSymbol("_ZN9CodeCache16find_blob_unsafeEPv");
        if (_find_blob == NULL) {
            _find_blob = (FindBlobFunc)_libjvm->findSymbol("_ZN9CodeCache9find_blobEPv");
        }
    }

    if (VM::hotspot_version() == 8 && _class_loader_data_offset >= 0 && _methods_offset >= 0 && _klass != NULL) {
        _lock_func = (LockFunc)_libjvm->findSymbol("_ZN7Monitor28lock_without_safepoint_checkEv");
        _unlock_func = (LockFunc)_libjvm->findSymbol("_ZN7Monitor6unlockEv");
        _has_class_loader_data = _lock_func != NULL && _unlock_func != NULL;
    }
}

void VMStructs::initThreadBridge(JNIEnv* env) {
    // Get eetop field - a bridge from Java Thread to VMThread
    jthread thread;
    if (VM::jvmti()->GetCurrentThread(&thread) != 0) {
        return;
    }

    jclass thread_class = env->GetObjectClass(thread);
    _eetop = env->GetFieldID(thread_class, "eetop", "J");
    _tid = env->GetFieldID(thread_class, "tid", "J");
    if (_eetop == NULL || _tid == NULL) {
        return;
    }

    VMThread* vm_thread = VMThread::fromJavaThread(env, thread);
    if (vm_thread == NULL) {
        return;
    }

    // Workaround for JDK-8132510: it's not safe to call GetEnv() inside a signal handler
    // since JDK 9, so we do it only for threads already registered in ThreadLocalStorage
    if (VM::hotspot_version() >= 9 || VM::hotspot_version() == 0) {
        for (int i = 0; i < 1024; i++) {
            if (pthread_getspecific((pthread_key_t)i) == vm_thread) {
                _tls_index = i;
                break;
            }
        }
    }

    _env_offset = (intptr_t)env - (intptr_t)vm_thread;
    _has_thread_bridge = true;
}

void VMStructs::initLogging(JNIEnv* env) {
    // Workaround for JDK-8238460
    if (VM::hotspot_version() >= 15) {
        VMManagement* management = VM::management();
        if (management != NULL) {
            management->ExecuteDiagnosticCommand(env, env->NewStringUTF("VM.log what=jni+resolve=error"));
        }
    }
}

bool VMStructs::hasJNIEnv() {
    return _tls_index < 0 || pthread_getspecific((pthread_key_t)_tls_index) != NULL;
}
<|endoftext|>


<commit_before>/*!
  \copyright (c) RDO-Team, 2011
  \file      rdortp.cpp
  \authors   Барс Александр
  \authors   Урусов Андрей (rdo@rk9.bmstu.ru)
  \date      11.06.2006
  \brief     Типы ресурсов
  \indent    4T
*/

// ---------------------------------------------------------------------------- PCH
#include "simulator/compiler/parser/pch.h"
// ----------------------------------------------------------------------- INCLUDES
#include <boost/bind.hpp>
// ----------------------------------------------------------------------- SYNOPSIS
#include "simulator/compiler/parser/rdortp.h"
#include "simulator/compiler/parser/rdoparser.h"
#include "simulator/compiler/parser/rdoparser_lexer.h"
#include "simulator/runtime/calc/resource/calc_resource.h"
// --------------------------------------------------------------------------------

OPEN_RDO_PARSER_NAMESPACE

namespace
{

rdo::runtime::LPRDOResource createSimpleResource(
	const rdo::runtime::LPRDORuntime runtime,
	const rdo::runtime::RDOResource::ParamList& params,
	const rdo::runtime::LPIResourceType& type,
	std::size_t resource_id,
	std::size_t type_id,
	bool trace,
	bool temporary,
	bool isNested)
{
	return rdo::Factory<rdo::runtime::RDOResource>::create(runtime, params, type, resource_id, type_id, trace, temporary, isNested);
}

rdo::runtime::LPRDOPROCResource createProcessResource(
	const rdo::runtime::LPRDORuntime runtime,
	const rdo::runtime::RDOResource::ParamList& params,
	const rdo::runtime::LPIResourceType& type,
	std::size_t resource_id,
	std::size_t type_id,
	bool trace,
	bool temporary)
{
	return rdo::Factory<rdo::runtime::RDOPROCResource>::create(runtime, params, type, resource_id, type_id, trace, temporary);
}

rdo::runtime::LPRDOPROCTransact createProcessTransact(
	const rdo::runtime::LPRDORuntime runtime,
	const rdo::runtime::RDOResource::ParamList& params,
	const rdo::runtime::LPIResourceType& type,
	std::size_t resource_id,
	std::size_t type_id,
	bool trace,
	bool temporary)
{
	return rdo::Factory<rdo::runtime::RDOPROCTransact>::create(runtime, params, type, resource_id, type_id, trace, temporary);
}

}

int rtplex(YYSTYPE* lpval, YYLTYPE* llocp, void* lexer)
{
	LEXER->m_lpval = lpval;
	LEXER->m_lploc = llocp;
	return LEXER->yylex();
}

void rtperror(YYLTYPE* /*llocp*/, void* /*lexer*/, const char* /*message*/)
{}

// --------------------------------------------------------------------------------
// -------------------- RDORTPResType
// --------------------------------------------------------------------------------
RDORTPResType::RDORTPResType(const LPRDOParser& pParser, const RDOParserSrcInfo& src_info, bool permanent)
	: RDOParserSrcInfo(src_info)
	, RDOResourceTypeList(pParser->getRTP_id(), pParser->runtime())
	, m_number(pParser->getRTP_id()) // TODO кажется ненужным
	, m_permanent(permanent)
{
	pParser->insertRTPResType(LPRDORTPResType(this));
}

RDORTPResType::~RDORTPResType()
{}

int RDORTPResType::getNumber() const
{
	return m_number;
}

bool RDORTPResType::isPermanent() const
{
	return m_permanent;
}

bool RDORTPResType::isTemporary() const
{
	return !m_permanent;
}

const RDORTPResType::ParamList& RDORTPResType::getParams() const
{
	return m_params;
}

runtime::RDOType::TypeID RDORTPResType::typeID() const
{
	return runtime::RDOType::t_pointer;
}

LPRDORSSResource RDORTPResType::createRes(const LPRDOParser& pParser, const RDOParserSrcInfo& src_info)
{
	return rdo::Factory<RDORSSResource>::create(pParser, src_info, this);
}

void RDORTPResType::addParam(const LPRDORTPParam& param)
{
	if (findRTPParam(param->name()))
	{
		RDOParser::s_parser()->error().error(param->src_info(), rdo::format("Параметр уже существует: %s", param->name().c_str()));
	}
	m_params.push_back(param);
}

void RDORTPResType::addParam(const std::string& /*param_name*/, rdo::runtime::RDOType::TypeID /*param_typeID*/)
{}

LPRDORTPParam RDORTPResType::findRTPParam(const std::string& paramName) const
{
	ParamList::const_iterator it = std::find_if(m_params.begin(), m_params.end(), compareName<RDORTPParam>(paramName));
	return it != m_params.end() ? *it : LPRDORTPParam();
}

std::size_t RDORTPResType::getRTPParamNumber(const std::string& paramName) const
{
	ParamList::const_iterator it = std::find_if(m_params.begin(), m_params.end(), compareName<RDORTPParam>(paramName));
	return it != m_params.end() ? it - m_params.begin() : UNDEFINED_PARAM;
}

void RDORTPResType::writeModelStructure(std::ostream& stream) const
{
	stream << getNumber() << " " << name() << " " << getParams().size() << std::endl;
	for (std::size_t i = 0; i < getParams().size(); i++)
	{
		stream << "  " << (i+1) << " ";
		getParams().at(i)->writeModelStructure(stream);
	}
}

std::string RDORTPResType::name() const
{
	static std::string s_name;
	s_name = src_text();
	return s_name;
}

LPIType RDORTPResType::type_cast(const LPIType& pFrom, const RDOParserSrcInfo& from_src_info, const RDOParserSrcInfo& to_src_info, const RDOParserSrcInfo& src_info) const
{
	switch (pFrom.object_dynamic_cast<rdo::runtime::RDOType>()->typeID())
	{
	case rdo::runtime::RDOType::t_pointer:
		{
			LPIType pThisRTPType(const_cast<RDORTPResType*>(this));

			//! Это один и тот же тип
			if (pThisRTPType == pFrom)
				return pThisRTPType;

			//! Типы разные, сгенерим ошибку
			parser::g_error().push_only(src_info,    "Несоответствие типов ресурсов");
			parser::g_error().push_only(to_src_info, to_src_info.src_text());
			parser::g_error().push_done();
			break;
		}
	default:
		{
			parser::g_error().push_only(src_info,    rdo::format("Ожидается тип ресурса, найдено: %s", from_src_info.src_text().c_str()));
			parser::g_error().push_only(to_src_info, rdo::format("См. тип: %s", to_src_info.src_text().c_str()));
			parser::g_error().push_done();
			break;
		}
	}

	return LPIType(NULL);
}

LPRDOValue RDORTPResType::value_cast(const LPRDOValue& pFrom, const RDOParserSrcInfo& to_src_info, const RDOParserSrcInfo& src_info) const
{
	ASSERT(pFrom);

	LPRDORTPResType pRTPResType = pFrom->typeInfo()->itype().object_dynamic_cast<RDORTPResType>();
	if (pRTPResType)
	{
		LPIType pThisType = const_cast<RDORTPResType*>(this);

		//! Это один и тот же тип
		if (pThisType == pRTPResType.object_dynamic_cast<IType>())
			return pFrom;

		//! Типы разные, сгенерим ошибку
		parser::g_error().push_only(src_info,    "Несоответствие типов ресурсов");
		parser::g_error().push_only(to_src_info,  rdo::format(  "Ожидается: %s", to_src_info.src_text().c_str()));
		parser::g_error().push_only(src_info,  rdo::format(  "Пришел: %s", pFrom->src_text().c_str()));
		parser::g_error().push_only(to_src_info, to_src_info.src_text());
		parser::g_error().push_done();
	}
	parser::g_error().push_only(src_info,    rdo::format("Ожидается ресурс, найдено: %s", pFrom->src_text().c_str()));
	parser::g_error().push_only(to_src_info, rdo::format("См. тип: %s", to_src_info.src_text().c_str()));
	parser::g_error().push_done();

	return LPRDOValue(NULL);
}

rdo::runtime::LPRDOCalc RDORTPResType::calc_cast(const rdo::runtime::LPRDOCalc& pCalc, const LPIType& pType) const
{
	return pCalc;
}

rdo::runtime::RDOValue RDORTPResType::get_default() const
{
	NEVER_REACH_HERE;
	return rdo::runtime::RDOValue();
	//return rdo::runtime::RDOValue (pResourceType,pResource);
}

namespace
{

LPExpression contextTypeOfResourceType(const LPRDORTPResType& resourceType, const RDOParserSrcInfo& srcInfo)
{
	return rdo::Factory<Expression>::create(
		rdo::Factory<TypeInfo>::create(resourceType, srcInfo),
		rdo::runtime::LPRDOCalc(NULL),
		srcInfo
	);
}

}

Context::LPFindResult RDORTPResType::onFindContext(const std::string& method, const Context::Params& params, const RDOParserSrcInfo& srcInfo) const
{
	if (method == Context::METHOD_GET)
	{
		const std::string paramName = params.identifier();

		const std::size_t parNumb = getRTPParamNumber(paramName);
		if (parNumb == RDORTPResType::UNDEFINED_PARAM)
		{
			RDOParser::s_parser()->error().error(srcInfo, rdo::format("Неизвестный параметр ресурса: %s", paramName.c_str()));
		}

		Context::Params params_;
		params_[RDORSSResource::GET_RESOURCE] = params.get<LPExpression>(RDORSSResource::GET_RESOURCE);
		params_[RDOParam::CONTEXT_PARAM_PARAM_ID] = parNumb;

		LPContext pParam = findRTPParam(paramName);
		ASSERT(pParam);
		return pParam->find(Context::METHOD_GET, params_, srcInfo);
	}

	if (method == Context::METHOD_OPERATOR_DOT)
	{
		const std::string paramName = params.identifier();

		const std::size_t parNumb = getRTPParamNumber(paramName);
		if (parNumb == RDORTPResType::UNDEFINED_PARAM)
			return rdo::Factory<FindResult>::create();

		LPRDOParam pParam = findRTPParam(paramName);
		ASSERT(pParam);

		Context::Params params_;
		params_[RDORSSResource::GET_RESOURCE] = params.get<LPExpression>(RDORSSResource::GET_RESOURCE);
		params_[RDOParam::CONTEXT_PARAM_PARAM_ID] = parNumb;
		params_[Context::Params::IDENTIFIER] = paramName;

		LPRDORTPResType pParamType =
			pParam->getTypeInfo()->itype().object_dynamic_cast<RDORTPResType>();

		if (!pParamType)
			return rdo::Factory<FindResult>::create(SwitchContext(pParam, params_));

		Context::LPFindResult result = pParam->find(Context::METHOD_GET, params_, srcInfo);
		LPExpression pNestedResource = result->getCreateExpression()();

		Context::Params params__;
		params__[RDORSSResource::GET_RESOURCE] = pNestedResource;

		return rdo::Factory<FindResult>::create(SwitchContext(pParamType, params__));
	}

	if (method == Context::METHOD_TYPE_OF)
	{
		LPRDORTPResType pThis(const_cast<RDORTPResType*>(this));
		return rdo::Factory<FindResult>::create(CreateExpression(boost::bind(&contextTypeOfResourceType, pThis, srcInfo)));
	}

	return rdo::Factory<FindResult>::create();
}

void RDORTPResType::setSubtype(Subtype type)
{
	ASSERT(!m_subtype.is_initialized() || m_subtype.get() == type);
	m_subtype = type;
}

void RDORTPResType::setupRuntimeFactory()
{
	Subtype subtype = m_subtype.is_initialized()
		? m_subtype.get()
		: RT_SIMPLE;

	runtime::RDOResourceTypeList::Create create;
	switch (subtype)
	{
	case RT_SIMPLE:
		create = boost::bind(&createSimpleResource, _1, _2, _3, _4, _5, _6, _7, _8);
		break;
	case RT_PROCESS_RESOURCE:
		create = boost::bind(&createProcessResource, _1, _2, _3, _4, _5, _6, _7);
		break;
	case RT_PROCESS_TRANSACT:
		create = boost::bind(&createProcessTransact, _1, _2, _3, _4, _5, _6, _7);
		break;
	default:
		NEVER_REACH_HERE;
	}
	setFactoryMethod(create);
}

/*
// --------------------------------------------------------------------------------
// -------------------- RDORTPFuzzyMembershiftFun - ф-ия принадлежности нечеткого терма
// --------------------------------------------------------------------------------
RDORTPFuzzyMembershiftFun::RDORTPFuzzyMembershiftFun(const LPRDOParser& pParser):
	RDOParserObject(pParser)
{
	for (std::size_t i = 0; i < m_points.size(); i++)
	{
//		double x = m_points[i]->getX();
	}

	Items::iterator it = m_points.begin();
	while (it != m_points.end())
	{
		double x = (*it)->getX();
		it++;
	}
}
// --------------------------------------------------------------------------------
// -------------------- RDORTPFuzzyTerm - нечеткий термин
// --------------------------------------------------------------------------------
RDORTPFuzzyTerm::RDORTPFuzzyTerm(const LPRDOParser& pParser, const RDOParserSrcInfo& src_info, RDORTPFuzzyMembershiftFun* pMembersfift_fun):
	RDOParserObject(pParser)
{

}*/

CLOSE_RDO_PARSER_NAMESPACE
<commit_msg>заплатка для контекста типа ресурса<commit_after>/*!
  \copyright (c) RDO-Team, 2011
  \file      rdortp.cpp
  \authors   Барс Александр
  \authors   Урусов Андрей (rdo@rk9.bmstu.ru)
  \date      11.06.2006
  \brief     Типы ресурсов
  \indent    4T
*/

// ---------------------------------------------------------------------------- PCH
#include "simulator/compiler/parser/pch.h"
// ----------------------------------------------------------------------- INCLUDES
#include <boost/bind.hpp>
// ----------------------------------------------------------------------- SYNOPSIS
#include "simulator/compiler/parser/rdortp.h"
#include "simulator/compiler/parser/rdoparser.h"
#include "simulator/compiler/parser/rdoparser_lexer.h"
#include "simulator/runtime/calc/resource/calc_resource.h"
// --------------------------------------------------------------------------------

OPEN_RDO_PARSER_NAMESPACE

namespace
{

rdo::runtime::LPRDOResource createSimpleResource(
	const rdo::runtime::LPRDORuntime runtime,
	const rdo::runtime::RDOResource::ParamList& params,
	const rdo::runtime::LPIResourceType& type,
	std::size_t resource_id,
	std::size_t type_id,
	bool trace,
	bool temporary,
	bool isNested)
{
	return rdo::Factory<rdo::runtime::RDOResource>::create(runtime, params, type, resource_id, type_id, trace, temporary, isNested);
}

rdo::runtime::LPRDOPROCResource createProcessResource(
	const rdo::runtime::LPRDORuntime runtime,
	const rdo::runtime::RDOResource::ParamList& params,
	const rdo::runtime::LPIResourceType& type,
	std::size_t resource_id,
	std::size_t type_id,
	bool trace,
	bool temporary)
{
	return rdo::Factory<rdo::runtime::RDOPROCResource>::create(runtime, params, type, resource_id, type_id, trace, temporary);
}

rdo::runtime::LPRDOPROCTransact createProcessTransact(
	const rdo::runtime::LPRDORuntime runtime,
	const rdo::runtime::RDOResource::ParamList& params,
	const rdo::runtime::LPIResourceType& type,
	std::size_t resource_id,
	std::size_t type_id,
	bool trace,
	bool temporary)
{
	return rdo::Factory<rdo::runtime::RDOPROCTransact>::create(runtime, params, type, resource_id, type_id, trace, temporary);
}

}

int rtplex(YYSTYPE* lpval, YYLTYPE* llocp, void* lexer)
{
	LEXER->m_lpval = lpval;
	LEXER->m_lploc = llocp;
	return LEXER->yylex();
}

void rtperror(YYLTYPE* /*llocp*/, void* /*lexer*/, const char* /*message*/)
{}

// --------------------------------------------------------------------------------
// -------------------- RDORTPResType
// --------------------------------------------------------------------------------
RDORTPResType::RDORTPResType(const LPRDOParser& pParser, const RDOParserSrcInfo& src_info, bool permanent)
	: RDOParserSrcInfo(src_info)
	, RDOResourceTypeList(pParser->getRTP_id(), pParser->runtime())
	, m_number(pParser->getRTP_id()) // TODO кажется ненужным
	, m_permanent(permanent)
{
	pParser->insertRTPResType(LPRDORTPResType(this));
}

RDORTPResType::~RDORTPResType()
{}

int RDORTPResType::getNumber() const
{
	return m_number;
}

bool RDORTPResType::isPermanent() const
{
	return m_permanent;
}

bool RDORTPResType::isTemporary() const
{
	return !m_permanent;
}

const RDORTPResType::ParamList& RDORTPResType::getParams() const
{
	return m_params;
}

runtime::RDOType::TypeID RDORTPResType::typeID() const
{
	return runtime::RDOType::t_pointer;
}

LPRDORSSResource RDORTPResType::createRes(const LPRDOParser& pParser, const RDOParserSrcInfo& src_info)
{
	return rdo::Factory<RDORSSResource>::create(pParser, src_info, this);
}

void RDORTPResType::addParam(const LPRDORTPParam& param)
{
	if (findRTPParam(param->name()))
	{
		RDOParser::s_parser()->error().error(param->src_info(), rdo::format("Параметр уже существует: %s", param->name().c_str()));
	}
	m_params.push_back(param);
}

void RDORTPResType::addParam(const std::string& /*param_name*/, rdo::runtime::RDOType::TypeID /*param_typeID*/)
{}

LPRDORTPParam RDORTPResType::findRTPParam(const std::string& paramName) const
{
	ParamList::const_iterator it = std::find_if(m_params.begin(), m_params.end(), compareName<RDORTPParam>(paramName));
	return it != m_params.end() ? *it : LPRDORTPParam();
}

std::size_t RDORTPResType::getRTPParamNumber(const std::string& paramName) const
{
	ParamList::const_iterator it = std::find_if(m_params.begin(), m_params.end(), compareName<RDORTPParam>(paramName));
	return it != m_params.end() ? it - m_params.begin() : UNDEFINED_PARAM;
}

void RDORTPResType::writeModelStructure(std::ostream& stream) const
{
	stream << getNumber() << " " << name() << " " << getParams().size() << std::endl;
	for (std::size_t i = 0; i < getParams().size(); i++)
	{
		stream << "  " << (i+1) << " ";
		getParams().at(i)->writeModelStructure(stream);
	}
}

std::string RDORTPResType::name() const
{
	static std::string s_name;
	s_name = src_text();
	return s_name;
}

LPIType RDORTPResType::type_cast(const LPIType& pFrom, const RDOParserSrcInfo& from_src_info, const RDOParserSrcInfo& to_src_info, const RDOParserSrcInfo& src_info) const
{
	switch (pFrom.object_dynamic_cast<rdo::runtime::RDOType>()->typeID())
	{
	case rdo::runtime::RDOType::t_pointer:
		{
			LPIType pThisRTPType(const_cast<RDORTPResType*>(this));

			//! Это один и тот же тип
			if (pThisRTPType == pFrom)
				return pThisRTPType;

			//! Типы разные, сгенерим ошибку
			parser::g_error().push_only(src_info,    "Несоответствие типов ресурсов");
			parser::g_error().push_only(to_src_info, to_src_info.src_text());
			parser::g_error().push_done();
			break;
		}
	default:
		{
			parser::g_error().push_only(src_info,    rdo::format("Ожидается тип ресурса, найдено: %s", from_src_info.src_text().c_str()));
			parser::g_error().push_only(to_src_info, rdo::format("См. тип: %s", to_src_info.src_text().c_str()));
			parser::g_error().push_done();
			break;
		}
	}

	return LPIType(NULL);
}

LPRDOValue RDORTPResType::value_cast(const LPRDOValue& pFrom, const RDOParserSrcInfo& to_src_info, const RDOParserSrcInfo& src_info) const
{
	ASSERT(pFrom);

	LPRDORTPResType pRTPResType = pFrom->typeInfo()->itype().object_dynamic_cast<RDORTPResType>();
	if (pRTPResType)
	{
		LPIType pThisType = const_cast<RDORTPResType*>(this);

		//! Это один и тот же тип
		if (pThisType == pRTPResType.object_dynamic_cast<IType>())
			return pFrom;

		//! Типы разные, сгенерим ошибку
		parser::g_error().push_only(src_info,    "Несоответствие типов ресурсов");
		parser::g_error().push_only(to_src_info,  rdo::format(  "Ожидается: %s", to_src_info.src_text().c_str()));
		parser::g_error().push_only(src_info,  rdo::format(  "Пришел: %s", pFrom->src_text().c_str()));
		parser::g_error().push_only(to_src_info, to_src_info.src_text());
		parser::g_error().push_done();
	}
	parser::g_error().push_only(src_info,    rdo::format("Ожидается ресурс, найдено: %s", pFrom->src_text().c_str()));
	parser::g_error().push_only(to_src_info, rdo::format("См. тип: %s", to_src_info.src_text().c_str()));
	parser::g_error().push_done();

	return LPRDOValue(NULL);
}

rdo::runtime::LPRDOCalc RDORTPResType::calc_cast(const rdo::runtime::LPRDOCalc& pCalc, const LPIType& pType) const
{
	return pCalc;
}

rdo::runtime::RDOValue RDORTPResType::get_default() const
{
	NEVER_REACH_HERE;
	return rdo::runtime::RDOValue();
	//return rdo::runtime::RDOValue (pResourceType,pResource);
}

namespace
{

LPExpression contextTypeOfResourceType(const LPRDORTPResType& resourceType, const RDOParserSrcInfo& srcInfo)
{
	return rdo::Factory<Expression>::create(
		rdo::Factory<TypeInfo>::create(resourceType, srcInfo),
		rdo::runtime::LPRDOCalc(NULL),
		srcInfo
	);
}

}

Context::LPFindResult RDORTPResType::onFindContext(const std::string& method, const Context::Params& params, const RDOParserSrcInfo& srcInfo) const
{
	if (method == Context::METHOD_GET)
	{
		const std::string paramName = params.identifier();

		const std::size_t parNumb = getRTPParamNumber(paramName);
		if (parNumb == RDORTPResType::UNDEFINED_PARAM)
		{
			RDOParser::s_parser()->error().error(srcInfo, rdo::format("Неизвестный параметр ресурса: %s", paramName.c_str()));
		}

		Context::Params params_;
		params_[RDORSSResource::GET_RESOURCE] = params.get<LPExpression>(RDORSSResource::GET_RESOURCE);
		params_[RDOParam::CONTEXT_PARAM_PARAM_ID] = parNumb;

		LPContext pParam = findRTPParam(paramName);
		ASSERT(pParam);
		return pParam->find(Context::METHOD_GET, params_, srcInfo);
	}

	if (method == Context::METHOD_OPERATOR_DOT)
	{
		const std::string paramName = params.identifier();

		const std::size_t parNumb = getRTPParamNumber(paramName);
		if (parNumb == RDORTPResType::UNDEFINED_PARAM)
			return rdo::Factory<FindResult>::create();

		if (!params.exists(RDORSSResource::GET_RESOURCE))
			RDOParser::s_parser()->error().error(srcInfo, rdo::format("Недопустимая конструкция"));

		LPRDOParam pParam = findRTPParam(paramName);
		ASSERT(pParam);

		Context::Params params_;
		params_[RDORSSResource::GET_RESOURCE] = params.get<LPExpression>(RDORSSResource::GET_RESOURCE);
		params_[RDOParam::CONTEXT_PARAM_PARAM_ID] = parNumb;
		params_[Context::Params::IDENTIFIER] = paramName;

		LPRDORTPResType pParamType =
			pParam->getTypeInfo()->itype().object_dynamic_cast<RDORTPResType>();

		if (!pParamType)
			return rdo::Factory<FindResult>::create(SwitchContext(pParam, params_));

		Context::LPFindResult result = pParam->find(Context::METHOD_GET, params_, srcInfo);
		LPExpression pNestedResource = result->getCreateExpression()();

		Context::Params params__;
		params__[RDORSSResource::GET_RESOURCE] = pNestedResource;

		return rdo::Factory<FindResult>::create(SwitchContext(pParamType, params__));
	}

	if (method == Context::METHOD_TYPE_OF)
	{
		LPRDORTPResType pThis(const_cast<RDORTPResType*>(this));
		return rdo::Factory<FindResult>::create(CreateExpression(boost::bind(&contextTypeOfResourceType, pThis, srcInfo)));
	}

	return rdo::Factory<FindResult>::create();
}

void RDORTPResType::setSubtype(Subtype type)
{
	ASSERT(!m_subtype.is_initialized() || m_subtype.get() == type);
	m_subtype = type;
}

void RDORTPResType::setupRuntimeFactory()
{
	Subtype subtype = m_subtype.is_initialized()
		? m_subtype.get()
		: RT_SIMPLE;

	runtime::RDOResourceTypeList::Create create;
	switch (subtype)
	{
	case RT_SIMPLE:
		create = boost::bind(&createSimpleResource, _1, _2, _3, _4, _5, _6, _7, _8);
		break;
	case RT_PROCESS_RESOURCE:
		create = boost::bind(&createProcessResource, _1, _2, _3, _4, _5, _6, _7);
		break;
	case RT_PROCESS_TRANSACT:
		create = boost::bind(&createProcessTransact, _1, _2, _3, _4, _5, _6, _7);
		break;
	default:
		NEVER_REACH_HERE;
	}
	setFactoryMethod(create);
}

/*
// --------------------------------------------------------------------------------
// -------------------- RDORTPFuzzyMembershiftFun - ф-ия принадлежности нечеткого терма
// --------------------------------------------------------------------------------
RDORTPFuzzyMembershiftFun::RDORTPFuzzyMembershiftFun(const LPRDOParser& pParser):
	RDOParserObject(pParser)
{
	for (std::size_t i = 0; i < m_points.size(); i++)
	{
//		double x = m_points[i]->getX();
	}

	Items::iterator it = m_points.begin();
	while (it != m_points.end())
	{
		double x = (*it)->getX();
		it++;
	}
}
// --------------------------------------------------------------------------------
// -------------------- RDORTPFuzzyTerm - нечеткий термин
// --------------------------------------------------------------------------------
RDORTPFuzzyTerm::RDORTPFuzzyTerm(const LPRDOParser& pParser, const RDOParserSrcInfo& src_info, RDORTPFuzzyMembershiftFun* pMembersfift_fun):
	RDOParserObject(pParser)
{

}*/

CLOSE_RDO_PARSER_NAMESPACE
<|endoftext|>