<commit_before>#include "../headers/geosAlgorithm.h"
#include "../headers/platform.h"
#include "../headers/util.h"
#include <typeinfo>

namespace geos {

ConvexHull::ConvexHull(CGAlgorithms *newCgAlgorithms) {
	cgAlgorithms=newCgAlgorithms;
	pointLocator=new PointLocator();
}

ConvexHull::~ConvexHull() {
	delete pointLocator;
}

Geometry* ConvexHull::getConvexHull(Geometry *newGeometry) {
	geometry=newGeometry;
	UniqueCoordinateArrayFilter *filter=new UniqueCoordinateArrayFilter();
	geometry->apply(filter);
	CoordinateList *pts=filter->getCoordinates();
	if (pts->getSize()==0) {
		Geometry *g=new GeometryCollection(new vector<Geometry*>(),geometry->getPrecisionModel(),geometry->getSRID());
		delete filter;
		return g;
	}
	if (pts->getSize()==1) {
		Geometry *g=new Point(pts->getAt(0),geometry->getPrecisionModel(),geometry->getSRID());
		delete filter;
		return g;
	}
	if (pts->getSize()==2) {
		pts=CoordinateListFactory::internalFactory->createCoordinateList(pts);
		Geometry *g=new LineString(pts,geometry->getPrecisionModel(),geometry->getSRID());
		delete filter;
		return g;
	}
	// sort points for Graham scan.
	CoordinateList *cH;
	if (pts->getSize()>10) {
		//Probably should be somewhere between 50 and 100?
		CoordinateList *rpts=reduce(pts);
		// Use Graham scan to find convex hull.
		cH=grahamScan(preSort(rpts));
		delete filter;
		delete rpts;
	} else {
		// Use Graham scan to find convex hull.
		cH=grahamScan(preSort(pts));
		delete filter;
	}
	// Convert array to linear ring.
	Geometry *g=lineOrPolygon(cH);
	delete cH;
	return g;
}

CoordinateList* ConvexHull::reduce(CoordinateList *pts) {
	auto_ptr<BigQuad> bigQuad(makeBigQuad(pts));
	// Build a linear ring defining a big poly.
	CoordinateList *bigPoly=CoordinateListFactory::internalFactory->createCoordinateList();
	bigPoly->add(bigQuad->westmost);
	if (CoordinateList::indexOf(&(bigQuad->northmost),bigPoly)==-1) {
		bigPoly->add(bigQuad->northmost);
	}
	if (CoordinateList::indexOf(&(bigQuad->eastmost),bigPoly)==-1) {
		bigPoly->add(bigQuad->eastmost);
	}
	if (CoordinateList::indexOf(&(bigQuad->southmost),bigPoly)==-1) {
		bigPoly->add(bigQuad->southmost);
	}
	if (bigPoly->getSize()<3) {
		delete bigPoly;
		return pts;
	}
	bigPoly->add(bigQuad->westmost);
	LinearRing *bQ=new LinearRing(bigPoly,geometry->getPrecisionModel(),geometry->getSRID());
	// load an array with all points not in the big poly
	// and the defining points.

//!!!Note to self: this might not work properly because of sorting.

	CoordinateList *cl=CoordinateListFactory::internalFactory->createCoordinateList(bigPoly);
	for(int i=0;i<pts->getSize();i++) {
		if (pointLocator->locate(pts->getAt(i),bQ)==Location::EXTERIOR) {
			cl->add(pts->getAt(i));
		}
	}
	// Return this array as the reduced problem.
	delete bQ;
	return cl;
}

CoordinateList* ConvexHull::preSort(CoordinateList *pts) {
	Coordinate t;
	// find the lowest point in the set. If two or more points have
	// the same minimum y coordinate choose the one with the minimu x.
	// This focal point is put in array location pts[0].
	for(int i=1;i<pts->getSize();i++) {
		if ((pts->getAt(i).y<pts->getAt(0).y) || ((pts->getAt(i).y==pts->getAt(0).y) && (pts->getAt(i).x<pts->getAt(0).x))) {
			t=pts->getAt(0);
			pts->setAt(pts->getAt(i),0);
			pts->setAt(t,i);
		}
	}
	// sort the points radially around the focal point.
	radialSort(pts);
	return pts;
}

CoordinateList* ConvexHull::grahamScan(CoordinateList *c) {
	Coordinate p;
	Coordinate p1;
	Coordinate p2;
	vector<Coordinate> *ps=new vector<Coordinate>();
	ps->push_back(c->getAt(0));
	ps->push_back(c->getAt(1));
	ps->push_back(c->getAt(2));
	p=c->getAt(2);
	for(int i=3;i<c->getSize();i++) {
		p=ps->back();
		ps->pop_back();
		while (cgAlgorithms->computeOrientation(ps->back(),p,c->getAt(i))>0) {
			p=ps->back();
			ps->pop_back();
		}
		ps->push_back(p);
		ps->push_back(c->getAt(i));
		p=c->getAt(i);
	}
	ps->push_back(c->getAt(0));
	p=c->getAt(0);
	CoordinateList *cl=CoordinateListFactory::internalFactory->createCoordinateList();
	cl->setPoints(*ps);
	delete ps;
	return cl;
}

void ConvexHull::radialSort(CoordinateList *p) {
	// A selection sort routine, assumes the pivot point is
	// the first point (i.e., p[0]).
	Coordinate t;
	for(int i=1;i<(p->getSize()-1);i++) {
		int min=i;
		for(int j=i+1;j
getSize();j++) {
			if (polarCompare(p->getAt(0),p->getAt(j),p->getAt(min))<0) {
				min=j;
			}
		}
		t=p->getAt(i);
		p->setAt(p->getAt(min),i);
		p->setAt(t,min);
	}
}

int ConvexHull::polarCompare(Coordinate o, Coordinate p, Coordinate q) {
	// Given two points p and q compare them with respect to their radial
	// ordering about point o. -1, 0 or 1 depending on whether p is less than,
	// equal to or greater than q. First checks radial ordering then if both
	// points lie on the same line, check distance to o.
	double dxp=p.x-o.x;
	double dyp=p.y-o.y;
	double dxq=q.x-o.x;
	double dyq=q.y-o.y;
	double alph=atan2(dxp, dyp);
	double beta=atan2(dxq, dyq);
	if (alph<beta) {
		return -1;
	}
	if (alph>beta) {
		return 1;
	}
	double op=dxp*dxp+dyp*dyp;
	double oq=dxq*dxq+dyq*dyq;
	if (op<oq) {
		return -1;
	}
	if (op>oq) {
		return 1;
	}
	return 0;
}

/**
*@return    whether the three coordinates are collinear and c2 lies between
*      c1 and c3 inclusive
*/
bool ConvexHull::isBetween(Coordinate c1, Coordinate c2, Coordinate c3) {
	if (cgAlgorithms->computeOrientation(c1, c2, c3)!=0) {
		return false;
	}
	if (c1.x!=c3.x) {
		if (c1.x<=c2.x && c2.x<=c3.x) {
			return true;
		}
		if (c3.x<=c2.x && c2.x<=c1.x) {
			return true;
		}
	}
	if (c1.y!=c3.y) {
		if (c1.y<=c2.y && c2.y<=c3.y) {
			return true;
		}
		if (c3.y<=c2.y && c2.y<=c1.y) {
			return true;
		}
	}
	return false;
}

BigQuad* ConvexHull::makeBigQuad(CoordinateList *pts) {
	BigQuad *bigQuad=new BigQuad();
	bigQuad->northmost=pts->getAt(0);
	bigQuad->southmost=pts->getAt(0);
	bigQuad->westmost=pts->getAt(0);
	bigQuad->eastmost=pts->getAt(0);
	for (int i=1;i<pts->getSize();i++) {
		if (pts->getAt(i).x<bigQuad->westmost.x) {
			bigQuad->westmost=pts->getAt(i);
		}
		if (pts->getAt(i).x>bigQuad->eastmost.x) {
			bigQuad->eastmost=pts->getAt(i);
		}
		if (pts->getAt(i).y<bigQuad->southmost.y) {
			bigQuad->southmost=pts->getAt(i);
		}
		if (pts->getAt(i).y>bigQuad->northmost.y) {
			bigQuad->northmost=pts->getAt(i);
		}
	}
	return bigQuad;
}

/**
*@param  vertices  the vertices of a linear ring, which may or may not be
*      flattened (i.e. vertices collinear)
*@return           a 2-vertex LineString if the vertices are
*      collinear;otherwise, a Polygon with unnecessary
*      (collinear) vertices removed
*/
Geometry* ConvexHull::lineOrPolygon(CoordinateList *newCoordinates) {
	CoordinateList *coordinates=cleanRing(newCoordinates);
	if (coordinates->getSize()==3) {
		CoordinateList *cl1=CoordinateListFactory::internalFactory->createCoordinateList();
		cl1->add(coordinates->getAt(0));
		cl1->add(coordinates->getAt(1));
		delete coordinates;
		return new LineString(cl1,geometry->getPrecisionModel(),geometry->getSRID());
	}
	LinearRing *linearRing=new LinearRing(coordinates,geometry->getPrecisionModel(),geometry->getSRID());
	return new Polygon(linearRing,geometry->getPrecisionModel(),geometry->getSRID());
}

/**
*@param  vertices  the vertices of a linear ring, which may or may not be
*      flattened (i.e. vertices collinear)
*@return           the coordinates with unnecessary (collinear) vertices
*      removed
*/
CoordinateList* ConvexHull::cleanRing(CoordinateList *original) {
	Assert::equals(original->getAt(0),original->getAt(original->getSize()-1));
	CoordinateList *cleanedRing=CoordinateListFactory::internalFactory->createCoordinateList();
	Coordinate previousDistinctCoordinate;
	Coordinate currentCoordinate;
	Coordinate nextCoordinate;
	previousDistinctCoordinate.setNull();
	for(int i=0;i<=original->getSize()-2;i++) {
		currentCoordinate=original->getAt(i);
		nextCoordinate=original->getAt(i+1);
		if (currentCoordinate==nextCoordinate) {
			continue;
		}
		if (!(previousDistinctCoordinate==Coordinate::getNull()) &&
			isBetween(previousDistinctCoordinate,currentCoordinate, nextCoordinate)) {
			continue;
		}
		cleanedRing->add(currentCoordinate);
		previousDistinctCoordinate=currentCoordinate;
	}
	cleanedRing->add(original->getAt(original->getSize()-1));
	return cleanedRing;
}

}

<commit_msg><commit_after>#include "../headers/geosAlgorithm.h"
#include "../headers/platform.h"
#include "../headers/util.h"
#include <typeinfo>

namespace geos {

ConvexHull::ConvexHull(CGAlgorithms *newCgAlgorithms) {
	cgAlgorithms=newCgAlgorithms;
	pointLocator=new PointLocator();
}

ConvexHull::~ConvexHull() {
	delete pointLocator;
}

Geometry* ConvexHull::getConvexHull(Geometry *newGeometry) {
	geometry=newGeometry;
	UniqueCoordinateArrayFilter *filter=new UniqueCoordinateArrayFilter();
	geometry->apply(filter);
	CoordinateList *pts=filter->getCoordinates();
	if (pts->getSize()==0) {
		Geometry *g=new GeometryCollection(new vector<Geometry*>(),geometry->getPrecisionModel(),geometry->getSRID());
		delete filter;
		return g;
	}
	if (pts->getSize()==1) {
		Geometry *g=new Point(pts->getAt(0),geometry->getPrecisionModel(),geometry->getSRID());
		delete filter;
		return g;
	}
	if (pts->getSize()==2) {
		pts=CoordinateListFactory::internalFactory->createCoordinateList(pts);
		Geometry *g=new LineString(pts,geometry->getPrecisionModel(),geometry->getSRID());
		delete filter;
		return g;
	}
	// sort points for Graham scan.
	CoordinateList *cH;
	if (pts->getSize()>10) {
		//Probably should be somewhere between 50 and 100?
		CoordinateList *rpts=reduce(pts);
		// Use Graham scan to find convex hull.
		cH=grahamScan(preSort(rpts));
		delete filter;
		if ( rpts != pts ) delete rpts; // sometimes reduce returns untouched input
	} else {
		// Use Graham scan to find convex hull.
		cH=grahamScan(preSort(pts));
		delete filter;
	}
	// Convert array to linear ring.
	Geometry *g=lineOrPolygon(cH);
	delete cH;
	return g;
}

CoordinateList* ConvexHull::reduce(CoordinateList *pts) {
	auto_ptr<BigQuad> bigQuad(makeBigQuad(pts));
	// Build a linear ring defining a big poly.
	CoordinateList *bigPoly=CoordinateListFactory::internalFactory->createCoordinateList();
	bigPoly->add(bigQuad->westmost);
	if (CoordinateList::indexOf(&(bigQuad->northmost),bigPoly)==-1) {
		bigPoly->add(bigQuad->northmost);
	}
	if (CoordinateList::indexOf(&(bigQuad->eastmost),bigPoly)==-1) {
		bigPoly->add(bigQuad->eastmost);
	}
	if (CoordinateList::indexOf(&(bigQuad->southmost),bigPoly)==-1) {
		bigPoly->add(bigQuad->southmost);
	}
	if (bigPoly->getSize()<3) {
		delete bigPoly;
		return pts;
	}
	bigPoly->add(bigQuad->westmost);
	LinearRing *bQ=new LinearRing(bigPoly,geometry->getPrecisionModel(),geometry->getSRID());
	// load an array with all points not in the big poly
	// and the defining points.

//!!!Note to self: this might not work properly because of sorting.

	CoordinateList *cl=CoordinateListFactory::internalFactory->createCoordinateList(bigPoly);
	for(int i=0;i<pts->getSize();i++) {
		if (pointLocator->locate(pts->getAt(i),bQ)==Location::EXTERIOR) {
			cl->add(pts->getAt(i));
		}
	}
	// Return this array as the reduced problem.
	delete bQ;
	return cl;
}

CoordinateList* ConvexHull::preSort(CoordinateList *pts) {
	Coordinate t;
	// find the lowest point in the set. If two or more points have
	// the same minimum y coordinate choose the one with the minimu x.
	// This focal point is put in array location pts[0].
	for(int i=1;i<pts->getSize();i++) {
		if ((pts->getAt(i).y<pts->getAt(0).y) || ((pts->getAt(i).y==pts->getAt(0).y) && (pts->getAt(i).x<pts->getAt(0).x))) {
			t=pts->getAt(0);
			pts->setAt(pts->getAt(i),0);
			pts->setAt(t,i);
		}
	}
	// sort the points radially around the focal point.
	radialSort(pts);
	return pts;
}

CoordinateList* ConvexHull::grahamScan(CoordinateList *c) {
	Coordinate p;
	Coordinate p1;
	Coordinate p2;
	vector<Coordinate> *ps=new vector<Coordinate>();
	ps->push_back(c->getAt(0));
	ps->push_back(c->getAt(1));
	ps->push_back(c->getAt(2));
	p=c->getAt(2);
	for(int i=3;i<c->getSize();i++) {
		p=ps->back();
		ps->pop_back();
		while (cgAlgorithms->computeOrientation(ps->back(),p,c->getAt(i))>0) {
			p=ps->back();
			ps->pop_back();
		}
		ps->push_back(p);
		ps->push_back(c->getAt(i));
		p=c->getAt(i);
	}
	ps->push_back(c->getAt(0));
	p=c->getAt(0);
	CoordinateList *cl=CoordinateListFactory::internalFactory->createCoordinateList();
	cl->setPoints(*ps);
	delete ps;
	return cl;
}

void ConvexHull::radialSort(CoordinateList *p) {
	// A selection sort routine, assumes the pivot point is
	// the first point (i.e., p[0]).
	Coordinate t;
	for(int i=1;i<(p->getSize()-1);i++) {
		int min=i;
		for(int j=i+1;j
getSize();j++) {
			if (polarCompare(p->getAt(0),p->getAt(j),p->getAt(min))<0) {
				min=j;
			}
		}
		t=p->getAt(i);
		p->setAt(p->getAt(min),i);
		p->setAt(t,min);
	}
}

int ConvexHull::polarCompare(Coordinate o, Coordinate p, Coordinate q) {
	// Given two points p and q compare them with respect to their radial
	// ordering about point o. -1, 0 or 1 depending on whether p is less than,
	// equal to or greater than q. First checks radial ordering then if both
	// points lie on the same line, check distance to o.
	double dxp=p.x-o.x;
	double dyp=p.y-o.y;
	double dxq=q.x-o.x;
	double dyq=q.y-o.y;
	double alph=atan2(dxp, dyp);
	double beta=atan2(dxq, dyq);
	if (alph<beta) {
		return -1;
	}
	if (alph>beta) {
		return 1;
	}
	double op=dxp*dxp+dyp*dyp;
	double oq=dxq*dxq+dyq*dyq;
	if (op<oq) {
		return -1;
	}
	if (op>oq) {
		return 1;
	}
	return 0;
}

/**
*@return    whether the three coordinates are collinear and c2 lies between
*      c1 and c3 inclusive
*/
bool ConvexHull::isBetween(Coordinate c1, Coordinate c2, Coordinate c3) {
	if (cgAlgorithms->computeOrientation(c1, c2, c3)!=0) {
		return false;
	}
	if (c1.x!=c3.x) {
		if (c1.x<=c2.x && c2.x<=c3.x) {
			return true;
		}
		if (c3.x<=c2.x && c2.x<=c1.x) {
			return true;
		}
	}
	if (c1.y!=c3.y) {
		if (c1.y<=c2.y && c2.y<=c3.y) {
			return true;
		}
		if (c3.y<=c2.y && c2.y<=c1.y) {
			return true;
		}
	}
	return false;
}

BigQuad* ConvexHull::makeBigQuad(CoordinateList *pts) {
	BigQuad *bigQuad=new BigQuad();
	bigQuad->northmost=pts->getAt(0);
	bigQuad->southmost=pts->getAt(0);
	bigQuad->westmost=pts->getAt(0);
	bigQuad->eastmost=pts->getAt(0);
	for (int i=1;i<pts->getSize();i++) {
		if (pts->getAt(i).x<bigQuad->westmost.x) {
			bigQuad->westmost=pts->getAt(i);
		}
		if (pts->getAt(i).x>bigQuad->eastmost.x) {
			bigQuad->eastmost=pts->getAt(i);
		}
		if (pts->getAt(i).y<bigQuad->southmost.y) {
			bigQuad->southmost=pts->getAt(i);
		}
		if (pts->getAt(i).y>bigQuad->northmost.y) {
			bigQuad->northmost=pts->getAt(i);
		}
	}
	return bigQuad;
}

/**
*@param  vertices  the vertices of a linear ring, which may or may not be
*      flattened (i.e. vertices collinear)
*@return           a 2-vertex LineString if the vertices are
*      collinear;otherwise, a Polygon with unnecessary
*      (collinear) vertices removed
*/
Geometry* ConvexHull::lineOrPolygon(CoordinateList *newCoordinates) {
	CoordinateList *coordinates=cleanRing(newCoordinates);
	if (coordinates->getSize()==3) {
		CoordinateList *cl1=CoordinateListFactory::internalFactory->createCoordinateList();
		cl1->add(coordinates->getAt(0));
		cl1->add(coordinates->getAt(1));
		delete coordinates;
		return new LineString(cl1,geometry->getPrecisionModel(),geometry->getSRID());
	}
	LinearRing *linearRing=new LinearRing(coordinates,geometry->getPrecisionModel(),geometry->getSRID());
	return new Polygon(linearRing,geometry->getPrecisionModel(),geometry->getSRID());
}

/**
*@param  vertices  the vertices of a linear ring, which may or may not be
*      flattened (i.e. vertices collinear)
*@return           the coordinates with unnecessary (collinear) vertices
*      removed
*/
CoordinateList* ConvexHull::cleanRing(CoordinateList *original) {
	Assert::equals(original->getAt(0),original->getAt(original->getSize()-1));
	CoordinateList *cleanedRing=CoordinateListFactory::internalFactory->createCoordinateList();
	Coordinate previousDistinctCoordinate;
	Coordinate currentCoordinate;
	Coordinate nextCoordinate;
	previousDistinctCoordinate.setNull();
	for(int i=0;i<=original->getSize()-2;i++) {
		currentCoordinate=original->getAt(i);
		nextCoordinate=original->getAt(i+1);
		if (currentCoordinate==nextCoordinate) {
			continue;
		}
		if (!(previousDistinctCoordinate==Coordinate::getNull()) &&
			isBetween(previousDistinctCoordinate,currentCoordinate, nextCoordinate)) {
			continue;
		}
		cleanedRing->add(currentCoordinate);
		previousDistinctCoordinate=currentCoordinate;
	}
	cleanedRing->add(original->getAt(original->getSize()-1));
	return cleanedRing;
}

}

<|endoftext|>


<commit_before>/* +---------------------------------------------------------------------------+
   |                 The Mobile Robot Programming Toolkit (MRPT)               |
   |                                                                           |
   |                          http://www.mrpt.org/                             |
   |                                                                           |
   | Copyright (c) 2005-2013, Individual contributors, see AUTHORS file        |
   | Copyright (c) 2005-2013, MAPIR group, University of Malaga                |
   | Copyright (c) 2012-2013, University of Almeria                            |
   | All rights reserved.                                                      |
   |                                                                           |
   | Redistribution and use in source and binary forms, with or without        |
   | modification, are permitted provided that the following conditions are    |
   | met:                                                                      |
   |    * Redistributions of source code must retain the above copyright       |
   |      notice, this list of conditions and the following disclaimer.        |
   |    * Redistributions in binary form must reproduce the above copyright    |
   |      notice, this list of conditions and the following disclaimer in the  |
   |      documentation and/or other materials provided with the distribution. |
   |    * Neither the name of the copyright holders nor the                    |
   |      names of its contributors may be used to endorse or promote products |
   |      derived from this software without specific prior written permission.|
   |                                                                           |
   | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS       |
   | 'AS IS' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED |
   | TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR|
   | PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE |
   | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL|
   | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR|
   |  SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)       |
   | HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,       |
   | STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN  |
   | ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE           |
   | POSSIBILITY OF SUCH DAMAGE.                                               |
   +---------------------------------------------------------------------------+ */

#include <mrpt/obs.h>
#include <mrpt/base.h>
#include <gtest/gtest.h>

using namespace mrpt;
using namespace mrpt::slam;
using namespace mrpt::utils;
using namespace mrpt::math;
using namespace std;

// Defined in run_unittests.cpp
namespace mrpt { namespace utils {
	extern std::string MRPT_GLOBAL_UNITTEST_SRC_DIR;
  }
}

// Create a set of classes, then serialize and deserialize to test possible bugs:
TEST(SerializeTestObs, WriteReadToMem)
{
	const mrpt::utils::TRuntimeClassId* lstClasses[] = {
		// Observations:
		CLASS_ID(CObservation2DRangeScan),
		CLASS_ID(CObservation3DRangeScan),
		CLASS_ID(CObservationBearingRange),
		CLASS_ID(CObservationBatteryState),
		CLASS_ID(CObservationWirelessPower),
		CLASS_ID(CObservationRFID),
		CLASS_ID(CObservationBeaconRanges),
		CLASS_ID(CObservationComment),
		CLASS_ID(CObservationGasSensors),
		CLASS_ID(CObservationGPS),
		CLASS_ID(CObservationImage),
		CLASS_ID(CObservationReflectivity),
		CLASS_ID(CObservationIMU),
		CLASS_ID(CObservationOdometry),
		CLASS_ID(CObservationRange),
		CLASS_ID(CObservationStereoImages),
		// Actions:
		CLASS_ID(CActionRobotMovement2D),
		CLASS_ID(CActionRobotMovement3D)
		};

	for (size_t i=0;i<sizeof(lstClasses)/sizeof(lstClasses[0]);i++)
	{
		try
		{
			CMemoryStream  buf;
			{
				CSerializable* o = static_cast<CSerializable*>(lstClasses[i]->createObject());
				buf << *o;
				delete o;
			}

			CSerializablePtr recons;
			buf.Seek(0);
			buf >> recons;
		}
		catch(std::exception &e)
		{
			GTEST_FAIL() <<
				"Exception during serialization test for class '"<< lstClasses[i]->className <<"':\n" << e.what() << endl;
		}
	}
}

<commit_msg>expanded mrpt-obs unit tests to include the last added class<commit_after>/* +---------------------------------------------------------------------------+
   |                 The Mobile Robot Programming Toolkit (MRPT)               |
   |                                                                           |
   |                          http://www.mrpt.org/                             |
   |                                                                           |
   | Copyright (c) 2005-2013, Individual contributors, see AUTHORS file        |
   | Copyright (c) 2005-2013, MAPIR group, University of Malaga                |
   | Copyright (c) 2012-2013, University of Almeria                            |
   | All rights reserved.                                                      |
   |                                                                           |
   | Redistribution and use in source and binary forms, with or without        |
   | modification, are permitted provided that the following conditions are    |
   | met:                                                                      |
   |    * Redistributions of source code must retain the above copyright       |
   |      notice, this list of conditions and the following disclaimer.        |
   |    * Redistributions in binary form must reproduce the above copyright    |
   |      notice, this list of conditions and the following disclaimer in the  |
   |      documentation and/or other materials provided with the distribution. |
   |    * Neither the name of the copyright holders nor the                    |
   |      names of its contributors may be used to endorse or promote products |
   |      derived from this software without specific prior written permission.|
   |                                                                           |
   | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS       |
   | 'AS IS' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED |
   | TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR|
   | PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE |
   | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL|
   | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR|
   |  SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)       |
   | HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,       |
   | STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN  |
   | ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE           |
   | POSSIBILITY OF SUCH DAMAGE.                                               |
   +---------------------------------------------------------------------------+ */

#include <mrpt/obs.h>
#include <mrpt/base.h>
#include <gtest/gtest.h>

using namespace mrpt;
using namespace mrpt::slam;
using namespace mrpt::utils;
using namespace mrpt::math;
using namespace std;

// Defined in run_unittests.cpp
namespace mrpt { namespace utils {
	extern std::string MRPT_GLOBAL_UNITTEST_SRC_DIR;
  }
}

// Create a set of classes, then serialize and deserialize to test possible bugs:
TEST(SerializeTestObs, WriteReadToMem)
{
	const mrpt::utils::TRuntimeClassId* lstClasses[] = {
		// Observations:
		CLASS_ID(CObservation2DRangeScan),
		CLASS_ID(CObservation3DRangeScan),
		CLASS_ID(CObservationBearingRange),
		CLASS_ID(CObservationBatteryState),
		CLASS_ID(CObservationWirelessPower),
		CLASS_ID(CObservationRFID),
		CLASS_ID(CObservationBeaconRanges),
		CLASS_ID(CObservationComment),
		CLASS_ID(CObservationGasSensors),
		CLASS_ID(CObservationGPS),
		CLASS_ID(CObservationImage),
		CLASS_ID(CObservationReflectivity),
		CLASS_ID(CObservationIMU),
		CLASS_ID(CObservationOdometry),
		CLASS_ID(CObservationRange),
		CLASS_ID(CObservationStereoImages),
		CLASS_ID(CObservationCANBusJ1939),
		// Actions:
		CLASS_ID(CActionRobotMovement2D),
		CLASS_ID(CActionRobotMovement3D)
		};

	for (size_t i=0;i<sizeof(lstClasses)/sizeof(lstClasses[0]);i++)
	{
		try
		{
			CMemoryStream  buf;
			{
				CSerializable* o = static_cast<CSerializable*>(lstClasses[i]->createObject());
				buf << *o;
				delete o;
			}

			CSerializablePtr recons;
			buf.Seek(0);
			buf >> recons;
		}
		catch(std::exception &e)
		{
			GTEST_FAIL() <<
				"Exception during serialization test for class '"<< lstClasses[i]->className <<"':\n" << e.what() << endl;
		}
	}
}

<|endoftext|>


<commit_before>// Copyright (C) 2012-2015 Leap Motion, Inc. All rights reserved.
#include "stdafx.h"
#include <autowiring/config_descriptor.h>
#include <autowiring/config.h>
#include <autowiring/ConfigRegistry.h>
#include <autowiring/observable.h>

namespace aw = autowiring;

class AutoConfig_FromTableTest :
  public testing::Test
{};

namespace {
  class DataDownloader {
  public:
    std::string api_path;
    int timeout;

    static aw::config_descriptor GetConfigDescriptor(void) {
      return{
        { "api_path", &DataDownloader::api_path },
        { "timeout", &DataDownloader::timeout }
      };
    }
  };
}

// A simulated map of key-value pairs.  In a real use case, this might be populated from a
// configuration file or downloaded from a network source.
static std::unordered_map<std::string, std::string> sc_config = {
  { "api_path", "http://example.com/v3/endpoint" },
  { "timeout", "299" }
};

TEST_F(AutoConfig_FromTableTest, SimpleConfigurationReadIn) {
  AutoCurrentContext ctxt;

  // Load in all of the keys:
  for(const auto& key : sc_config)
    ctxt->Config.Set(key.first.c_str(), key.second.c_str());

  // Now instantiate and see if we get valid values:
  AutoRequired<DataDownloader> ddld;
  ASSERT_STREQ("http://example.com/v3/endpoint", ddld->api_path.c_str());
  ASSERT_EQ(299, ddld->timeout);
}

// A simulated set of users and user data:
static std::unordered_map<std::string, std::string> sc_allusers[] = {
  {
    { "user_name", "Code McKenzy" },
    { "user_email", "code@mckenzy.com" },
    { "user_age", "30" },
    { "user_valid", "true" }
  },
  {
    { "user_name", "Louis Stalwart" },
    { "user_email", "louie@gmail.com" },
    { "user_age", "22" },
    { "user_valid", "false" }
  }
};

namespace {
  class UserTest {
  public:
    // This key is loaded in from the root context

    // These are specific to this context:
    std::string user_name;
    std::string user_email;
    int user_age;
    bool user_valid;

    static aw::config_descriptor GetConfigDescriptor(void) {
      return{
        { "user_name", &UserTest::user_name },
        { "user_email", &UserTest::user_email },
        { "user_age", &UserTest::user_age },
        { "user_valid", &UserTest::user_valid }
      };
    }
  };
}

TEST_F(AutoConfig_FromTableTest, HeirarchialAssignment) {
  AutoCurrentContext ctxt;

  // Load in all of the root keys:
  for (const auto& key : sc_config)
    ctxt->Config.Set(key.first.c_str(), key.second.c_str());

  // Then start creating subcontexts for all of the user classes:
  for (auto& user_key : sc_allusers) {
    AutoCreateContext child;
    AutoRequired<UserTest> ut;
    for (auto& key : user_key)
      child->Config.Set(key.first.c_str(), key.second.c_str());
  }
}
<commit_msg>Add some additional checks to FromTableTest<commit_after>// Copyright (C) 2012-2015 Leap Motion, Inc. All rights reserved.
#include "stdafx.h"
#include <autowiring/config_descriptor.h>
#include <autowiring/config.h>
#include <autowiring/ConfigRegistry.h>
#include <autowiring/observable.h>

namespace aw = autowiring;

class AutoConfig_FromTableTest :
  public testing::Test
{};

namespace {
  // An example object that might be responsible for downloading data from a server.  The
  // path and timeout parameters, which such a class might use, are described in a config
  // descriptor.
  class DataDownloader {
  public:
    std::string api_path;
    int timeout;

    static aw::config_descriptor GetConfigDescriptor(void) {
      return{
        { "api_path", &DataDownloader::api_path },
        { "timeout", &DataDownloader::timeout }
      };
    }
  };
}

// A simulated map of key-value pairs.  In a real use case, this might be populated from a
// configuration file or downloaded from a network source.
static std::unordered_map<std::string, std::string> sc_config = {
  { "api_path", "http://example.com/v3/endpoint" },
  { "timeout", "299" }
};

TEST_F(AutoConfig_FromTableTest, SimpleConfigurationReadIn) {
  AutoCurrentContext ctxt;

  // Load in all of the keys:
  for(const auto& key : sc_config)
    ctxt->Config.Set(key.first.c_str(), key.second.c_str());

  // Now instantiate and see if we get valid values:
  AutoRequired<DataDownloader> ddld;
  ASSERT_STREQ("http://example.com/v3/endpoint", ddld->api_path.c_str());
  ASSERT_EQ(299, ddld->timeout);
}

// A simulated set of users and user data:
static std::unordered_map<std::string, std::string> sc_allusers[] = {
  {
    { "user_name", "Code McKenzy" },
    { "user_email", "code@mckenzy.com" },
    { "user_age", "30" },
    { "user_valid", "true" }
  },
  {
    { "user_name", "Louis Stalwart" },
    { "user_email", "louie@gmail.com" },
    { "user_age", "22" },
    { "user_valid", "false" }
  }
};

namespace {
  // A single user in a hypothetical database of users
  class UserTest {
  public:
    // These are specific to this context:
    std::string user_name;
    std::string user_email;
    int user_age;
    bool user_valid;

    static aw::config_descriptor GetConfigDescriptor(void) {
      return{
        { "user_name", &UserTest::user_name },
        { "user_email", &UserTest::user_email },
        { "user_age", &UserTest::user_age },
        { "user_valid", &UserTest::user_valid }
      };
    }
  };
}

TEST_F(AutoConfig_FromTableTest, HeirarchialAssignment) {
  AutoCurrentContext ctxt;

  // Load in all of the root keys:
  for (const auto& key : sc_config)
    ctxt->Config.Set(key.first.c_str(), key.second.c_str());

  // Then start creating subcontexts for all of the user classes:
  for (auto& user_key : sc_allusers) {
    AutoCreateContext child;

    // Set all configuration keys in the configuration block:
    for (auto& key : user_key)
      child->Config.Set(key.first.c_str(), key.second.c_str());

    // Inject after the fact, verify key assignments are all correct
    AutoRequired<UserTest> ut{ child };
    ASSERT_EQ(user_key["user_name"], ut->user_name);
    ASSERT_EQ(user_key["user_email"], ut->user_email);
    ASSERT_EQ(user_key["user_age"], std::to_string(ut->user_age));
    ASSERT_EQ(user_key["user_valid"] == "true", ut->user_valid);
  }
}
<|endoftext|>


<commit_before>extern "C" {
#include <link-grammar/api.h>
}

extern "C" int sat_encode(Sentence sent, Parse_Options  opts);
extern "C" Linkage sat_create_linkage(int k, Sentence sent, Parse_Options  opts);
extern "C" void sat_sentence_delete(Sentence sent);

#include "word-tag.hpp"

/**
 *    Base class for all SAT encodings
 */
class SATEncoder {
public:

  // Construct the encoder based on given sentence
  SATEncoder(Sentence sent, Parse_Options  opts)
    : _sent(sent), _opts(opts), _solver(new Solver()), _variables(new Variables(sent)) {
    // Preprocess word tags of the sentence
    build_word_tags();
  }

  // Create the formula from the sentence
  void encode();

  // Solve the formula, returning the next linkage.
  Linkage get_next_linkage();

protected:

  /**
   *  Methods that generate various link-grammar constraints.
   */

  // Top-level method that generates satisfaction conditions for every
  // word in the sentence
  void generate_satisfaction_conditions();

  // Generates satisfaction conditions for the word-tag expression e
  void generate_satisfaction_for_expression(int w, int& dfs_position, Exp* e, char* var, int parrent_cost);

  // Handle the case of NULL expression of a word
  virtual void handle_null_expression(int w) = 0;

  // Determine if this word-tag must be satisfied and generate appropriate clauses
  virtual void determine_satisfaction(int w, char* name) = 0;

  // Generates satisfaction condition for the connector (wi, pi)
  virtual void generate_satisfaction_for_connector(int wi, int pi, const char* Ci,
						   char dir, bool multi, int cost, char* var) = 0;

  // Definition of link_cw((wi, pi), wj) variables when wj is an ordinary word
  void generate_link_cw_ordinary_definition(int wi, int pi, const char* Ci, char dir, int cost, int wj);

  // Generates order constraints for the elements of a conjunction.
  void generate_conjunct_order_constraints(int w, Exp *e1, Exp* e2, int& dfs_position);

  /**
   *  Methods used for optimizing conjunction ordering constraints
   */

  // Number of connectors in an expression
  int num_connectors(Exp* e);

  // This expression can be matched without using any connectors of
  // the given direction
  static int  empty_connectors(Exp* exp, char dir);

  // This expression can be matched while using a connector of the
  // given direction
  static int  non_empty_connectors(Exp* exp, char dir);

  // Trailing connectors of a given direction in the given expression
  void trailing_connectors(int w, Exp* exp, char dir, int& dfs_position,
			   std::vector<PositionConnector*>& connectors);
  bool trailing_connectors_and_aux(int w, E_list* l, char dir, int& dfs_position,
				   std::vector<PositionConnector*>& connectors);

  // Connectors of the given direction that cannot be trailing
  // connectors
  void certainly_non_trailing(int w, Exp* exp, char dir, int& dfs_position,
			      std::vector<PositionConnector*>& connectors, bool has_right);

  // Connectors that can act as leading connectors of a given
  // direction in the given direction
  void leading_connectors(int w, Exp* exp, char dir, int& dfs_position,
			  std::vector<PositionConnector*>& connectors);

  /**
   *  Definitions of linked(wi, wj) variables.
   */

  // Define all linked(wi, wj) variables
  virtual void generate_linked_definitions() = 0;

  // In order to reduce the number of clauses, some linked(wi, wj)
  // variables can apriori be eliminated. The information about pairs
  // of words that can be linked is kept in this matrix.
  MatrixUpperTriangle<int> _linked_possible;

  /**
   *  Planarity constraints
   */

  // Generates clauses that forbid link-crossing
  void generate_planarity_conditions();
  // Stronger planarity pruning
  void generate_linked_min_max_planarity();

  /**
   *  Connectivity constraints
   */

#ifdef _CONNECTIVITY_
  // Generate clauses that encode the connectivity requirement of the
  // linkage. Experiments showed that it is better to check the
  // connectivity aposteriori and this method has been excised.
  void generate_connectivity();
#endif

  // Helper method for connectivity_components
  static void dfs(int node, const MatrixUpperTriangle<int>& graph, int component, std::vector<int>& components);

  // Extract connectivity components of a linkage. Return true iff the linkage is connected.
  bool connectivity_components(std::vector<int>& components);

  // Generate clauses that prohibit all disconnected linkages that
  // have the specified connectivity components.
  void generate_disconnectivity_prohibiting(std::vector<int> components);

  /**
   *   Encoding specific clauses - override to add clauses that are
   *   specific to a certain encoding
   */
  virtual void generate_encoding_specific_clauses() {}

  /**
   *   Post-processing - PP pruning
   */

  // Generates PP pruning clauses.
  void pp_prune();
  bool post_process_linkage(Linkage linkage);

  /**
   *   Power pruning
   */
  // Generate definition of epsilon variables that are used for power
  // pruning
  void generate_epsilon_definitions();
  bool generate_epsilon_for_expression(int w, int& dfs_position, Exp* e, char* var, bool root, char dir);

  // Power pruning
  void power_prune();
  // auxiliary method that extends power pruning clauses with additional literals
  // (e.g., link should not be power-prunned if there words are fat-linked)
  virtual void add_additional_power_pruning_conditions(vec<Lit>& clause, int wl, int wr)
  {}

  /**
   *   Cost cutoff
   */

  // Cost cutoff treshold value. Nodes of the expression tree are
  // pruned if their cost exceeds this value. Cost cutoff is performed
  // during satisfaction condition generating.
  static const int _cost_cutoff = 2;

  /**
   *   Creating clauses and passing them to the MiniSAT solver
   */

  // Add the specified clause to the solver
  void add_clause(vec<Lit>& clause) {
#ifdef _DEBUG
    print_clause(clause);
#endif
    for (int i = 0; i < clause.size(); i++) {
      while (var(clause[i]) >= _solver->nVars()) {
	_solver->newVar();
      }
    }
    _solver->addClause(clause);
  }

  // Print clause literals to standard output
  static void print_clause(const vec<Lit>& clause) {
    static int num = 1;

    cout << "Clause: ." << num++ << ". ";
    for (int i = 0; i < clause.size(); i++)
      cout << (sign(clause[i]) ? '-' : '+') << var(clause[i]) << " ";
    cout << endl;
  }

  /**
   *   Conversion of various formula types to CNF. Clauses obtained
   *   are automatically passed to the SAT Solver.
   */
  void generate_literal(Lit l);
  void generate_and_definition(Lit lhs, vec<Lit>& rhs);
  void generate_or_definition(Lit lhs, vec<Lit>& rhs);
  void generate_xor_definition(Lit lhs, vec<Lit>& rhs);
  void generate_equivalence_definition(Lit l1, Lit l2);
  void generate_classical_and_definition(Lit lhs, vec<Lit>& rhs);
  void generate_and(vec<Lit>& vect);
  void generate_or(vec<Lit>& vect);
  void generate_xor_conditions(vec<Lit>& vect);
  void generate_conditional_or_definition(Lit condition, Lit lhs, vec<Lit>& rhs);
  void generate_conditional_lr_implication_or_definition(Lit condition, Lit lhs, vec<Lit>& rhs);
  void generate_conditional_lr_implication_or_definition(Lit condition1, Lit condition2, Lit lhs, vec<Lit>& rhs);

  /*
   *   Word tags of the words in a sentence kept in a preprocessed
   *   form. This enables users to get information about the
   *   connectors in a very eficient way.
   */
  // Word tags
  std::vector<WordTag> _word_tags;

  // Initializes _word_tags array
  void build_word_tags();

  // Find all matching connectors between two words
  void find_all_matches_between_words(int w1, int w2,
				      std::vector<std::pair<const PositionConnector*, const PositionConnector*> >& matches);

  // Check if the connector (wi, pi) can match any word in [l, r)
  bool matches_in_interval(int wi, int pi, int l, int r);

  // Join several expressions corresponding to different dictionary
  // entries of a word into a single expression.
  Exp* join_alternatives(int w);

  // Erase auxiliary expression tree nodes obtained by joining several
  // expressions into one.
  void free_alternatives(Exp* e);

  /**
   * Decoding
   */

  // Convert propositional model to a parse info structure
  virtual bool extract_links(Parse_info pi) = 0;

  // Create linkage from a propositional model
  Linkage create_linkage();

  // Generate clause that prohibits the current model
  void generate_linkage_prohibiting();

  // Object that contains all information about the variable
  // encoding.
  Variables* _variables;

  // The MiniSAT solver instance. The solver keeps the set of clauses.
  Solver* _solver;

  // Sentence that is being parsed.
  Sentence _sent;

  // Parse options.
  Parse_Options  _opts;

};

/*******************************************************************************
 *       SAT encoding for sentences that do not contain conjunction.           *
 *******************************************************************************/
class SATEncoderConjunctionFreeSentences : public SATEncoder {
public:
  SATEncoderConjunctionFreeSentences(Sentence sent, Parse_Options  opts)
    : SATEncoder(sent, opts) {
  }

  virtual void handle_null_expression(int w);
  virtual void determine_satisfaction(int w, char* name);
  virtual void generate_satisfaction_for_connector(int wi, int pi, const char* Ci,
						   char dir, bool multi, int cost, char* var);

  virtual void generate_linked_definitions();
  virtual bool extract_links(Parse_info pi);

  virtual void generate_encoding_specific_clauses();
};

/*******************************************************************************
 *              SAT encoding for sentences that contain conjunction.           *
 *******************************************************************************/
class SATEncoderConjunctiveSentences : public SATEncoder {
public:
  SATEncoderConjunctiveSentences(Sentence sent, Parse_Options  opts)
    : SATEncoder(sent, opts) {
    init_connective_words();
  }

private:
  virtual void handle_null_expression(int w);
  virtual void determine_satisfaction(int w, char* name);

  virtual void generate_satisfaction_for_connector(int wi, int pi, const char* Ci,
						   char dir, bool multi, int cost, char* var);

  virtual void add_additional_power_pruning_conditions(vec<Lit>& clause, int wl, int wr);

  virtual void generate_encoding_specific_clauses();

  // various fat-link conditions
  void either_tag_or_fat_link(int w, Lit tag);
  void generate_fat_link_up_definitions();
  void generate_fat_link_down_definitions();
  void generate_fat_link_up_between_down_conditions();
  void generate_fat_link_comma_conditions();
  void generate_fat_link_crossover_conditions();
  void generate_fat_link_Left_Wall_not_inside();
  void generate_fat_link_linked_upperside();
  void generate_fat_link_existence();
  void generate_fat_link_neighbor();
  void generate_label_compatibility();

  // link_cw variables

  bool link_cw_possible(int wi, int pi, const char* Ci, char dir, int w, int llim, int rlim);
  bool link_cw_possible_with_fld(int wi, int pi, const char* Ci, char dir, int w, int llim, int rlim);

  void generate_link_cw_connective_impossible         (int wi, int pi, const char* Ci, int wj);
  void generate_link_cw_connective_definition         (int wi, int pi, const char* Cj, int wj);

  // link_top_cw variables
  void generate_link_top_cw_up_definition                  (int wi,
							    int wj, int pj, const char* Cj, bool multi);
  void generate_link_top_cw_iff_link_cw                    (int wi,
							    int wj, int pj, const char* Cj);
  // link_top_ww
  void generate_link_top_ww_connective_comma_definition    (Lit lhs, int wi, int wj);

  // link_ww
  virtual void generate_linked_definitions();

  // Linkage extraction from the model
  void get_satisfied_link_top_cw_connectors(int word, int top_word, std::vector<int>& link_top_cw_vars);
  virtual bool extract_links(Parse_info pi);

  // Initialize the vector of connective words of this sentence
  void init_connective_words();

  // Words that are connectives or commas
  std::vector<int> _connectives;

  // Cache isConnectiveOrComma results for faster checking
  std::vector<bool> _is_connective_or_comma;

  bool isConnectiveOrComma(int w) {
    return _is_connective_or_comma[w];
  }
};
<commit_msg>fix more memleaks in sat solver<commit_after>extern "C" {
#include <link-grammar/api.h>
}

extern "C" int sat_encode(Sentence sent, Parse_Options  opts);
extern "C" Linkage sat_create_linkage(int k, Sentence sent, Parse_Options  opts);
extern "C" void sat_sentence_delete(Sentence sent);

#include "word-tag.hpp"

/**
 *    Base class for all SAT encodings
 */
class SATEncoder {
public:

  // Construct the encoder based on given sentence
  SATEncoder(Sentence sent, Parse_Options  opts)
    : _sent(sent), _opts(opts), _solver(new Solver()), _variables(new Variables(sent)) {
    // Preprocess word tags of the sentence
    build_word_tags();
  }

  ~SATEncoder()
  {
    delete _variables;
    delete _solver;
  }

  // Create the formula from the sentence
  void encode();

  // Solve the formula, returning the next linkage.
  Linkage get_next_linkage();

protected:

  /**
   *  Methods that generate various link-grammar constraints.
   */

  // Top-level method that generates satisfaction conditions for every
  // word in the sentence
  void generate_satisfaction_conditions();

  // Generates satisfaction conditions for the word-tag expression e
  void generate_satisfaction_for_expression(int w, int& dfs_position, Exp* e, char* var, int parrent_cost);

  // Handle the case of NULL expression of a word
  virtual void handle_null_expression(int w) = 0;

  // Determine if this word-tag must be satisfied and generate appropriate clauses
  virtual void determine_satisfaction(int w, char* name) = 0;

  // Generates satisfaction condition for the connector (wi, pi)
  virtual void generate_satisfaction_for_connector(int wi, int pi, const char* Ci,
						   char dir, bool multi, int cost, char* var) = 0;

  // Definition of link_cw((wi, pi), wj) variables when wj is an ordinary word
  void generate_link_cw_ordinary_definition(int wi, int pi, const char* Ci, char dir, int cost, int wj);

  // Generates order constraints for the elements of a conjunction.
  void generate_conjunct_order_constraints(int w, Exp *e1, Exp* e2, int& dfs_position);

  /**
   *  Methods used for optimizing conjunction ordering constraints
   */

  // Number of connectors in an expression
  int num_connectors(Exp* e);

  // This expression can be matched without using any connectors of
  // the given direction
  static int  empty_connectors(Exp* exp, char dir);

  // This expression can be matched while using a connector of the
  // given direction
  static int  non_empty_connectors(Exp* exp, char dir);

  // Trailing connectors of a given direction in the given expression
  void trailing_connectors(int w, Exp* exp, char dir, int& dfs_position,
			   std::vector<PositionConnector*>& connectors);
  bool trailing_connectors_and_aux(int w, E_list* l, char dir, int& dfs_position,
				   std::vector<PositionConnector*>& connectors);

  // Connectors of the given direction that cannot be trailing
  // connectors
  void certainly_non_trailing(int w, Exp* exp, char dir, int& dfs_position,
			      std::vector<PositionConnector*>& connectors, bool has_right);

  // Connectors that can act as leading connectors of a given
  // direction in the given direction
  void leading_connectors(int w, Exp* exp, char dir, int& dfs_position,
			  std::vector<PositionConnector*>& connectors);

  /**
   *  Definitions of linked(wi, wj) variables.
   */

  // Define all linked(wi, wj) variables
  virtual void generate_linked_definitions() = 0;

  // In order to reduce the number of clauses, some linked(wi, wj)
  // variables can apriori be eliminated. The information about pairs
  // of words that can be linked is kept in this matrix.
  MatrixUpperTriangle<int> _linked_possible;

  /**
   *  Planarity constraints
   */

  // Generates clauses that forbid link-crossing
  void generate_planarity_conditions();
  // Stronger planarity pruning
  void generate_linked_min_max_planarity();

  /**
   *  Connectivity constraints
   */

#ifdef _CONNECTIVITY_
  // Generate clauses that encode the connectivity requirement of the
  // linkage. Experiments showed that it is better to check the
  // connectivity aposteriori and this method has been excised.
  void generate_connectivity();
#endif

  // Helper method for connectivity_components
  static void dfs(int node, const MatrixUpperTriangle<int>& graph, int component, std::vector<int>& components);

  // Extract connectivity components of a linkage. Return true iff the linkage is connected.
  bool connectivity_components(std::vector<int>& components);

  // Generate clauses that prohibit all disconnected linkages that
  // have the specified connectivity components.
  void generate_disconnectivity_prohibiting(std::vector<int> components);

  /**
   *   Encoding specific clauses - override to add clauses that are
   *   specific to a certain encoding
   */
  virtual void generate_encoding_specific_clauses() {}

  /**
   *   Post-processing - PP pruning
   */

  // Generates PP pruning clauses.
  void pp_prune();
  bool post_process_linkage(Linkage linkage);

  /**
   *   Power pruning
   */
  // Generate definition of epsilon variables that are used for power
  // pruning
  void generate_epsilon_definitions();
  bool generate_epsilon_for_expression(int w, int& dfs_position, Exp* e, char* var, bool root, char dir);

  // Power pruning
  void power_prune();
  // auxiliary method that extends power pruning clauses with additional literals
  // (e.g., link should not be power-prunned if there words are fat-linked)
  virtual void add_additional_power_pruning_conditions(vec<Lit>& clause, int wl, int wr)
  {}

  /**
   *   Cost cutoff
   */

  // Cost cutoff treshold value. Nodes of the expression tree are
  // pruned if their cost exceeds this value. Cost cutoff is performed
  // during satisfaction condition generating.
  static const int _cost_cutoff = 2;

  /**
   *   Creating clauses and passing them to the MiniSAT solver
   */

  // Add the specified clause to the solver
  void add_clause(vec<Lit>& clause) {
#ifdef _DEBUG
    print_clause(clause);
#endif
    for (int i = 0; i < clause.size(); i++) {
      while (var(clause[i]) >= _solver->nVars()) {
	_solver->newVar();
      }
    }
    _solver->addClause(clause);
  }

  // Print clause literals to standard output
  static void print_clause(const vec<Lit>& clause) {
    static int num = 1;

    cout << "Clause: ." << num++ << ". ";
    for (int i = 0; i < clause.size(); i++)
      cout << (sign(clause[i]) ? '-' : '+') << var(clause[i]) << " ";
    cout << endl;
  }

  /**
   *   Conversion of various formula types to CNF. Clauses obtained
   *   are automatically passed to the SAT Solver.
   */
  void generate_literal(Lit l);
  void generate_and_definition(Lit lhs, vec<Lit>& rhs);
  void generate_or_definition(Lit lhs, vec<Lit>& rhs);
  void generate_xor_definition(Lit lhs, vec<Lit>& rhs);
  void generate_equivalence_definition(Lit l1, Lit l2);
  void generate_classical_and_definition(Lit lhs, vec<Lit>& rhs);
  void generate_and(vec<Lit>& vect);
  void generate_or(vec<Lit>& vect);
  void generate_xor_conditions(vec<Lit>& vect);
  void generate_conditional_or_definition(Lit condition, Lit lhs, vec<Lit>& rhs);
  void generate_conditional_lr_implication_or_definition(Lit condition, Lit lhs, vec<Lit>& rhs);
  void generate_conditional_lr_implication_or_definition(Lit condition1, Lit condition2, Lit lhs, vec<Lit>& rhs);

  /*
   *   Word tags of the words in a sentence kept in a preprocessed
   *   form. This enables users to get information about the
   *   connectors in a very eficient way.
   */
  // Word tags
  std::vector<WordTag> _word_tags;

  // Initializes _word_tags array
  void build_word_tags();

  // Find all matching connectors between two words
  void find_all_matches_between_words(int w1, int w2,
				      std::vector<std::pair<const PositionConnector*, const PositionConnector*> >& matches);

  // Check if the connector (wi, pi) can match any word in [l, r)
  bool matches_in_interval(int wi, int pi, int l, int r);

  // Join several expressions corresponding to different dictionary
  // entries of a word into a single expression.
  Exp* join_alternatives(int w);

  // Erase auxiliary expression tree nodes obtained by joining several
  // expressions into one.
  void free_alternatives(Exp* e);

  /**
   * Decoding
   */

  // Convert propositional model to a parse info structure
  virtual bool extract_links(Parse_info pi) = 0;

  // Create linkage from a propositional model
  Linkage create_linkage();

  // Generate clause that prohibits the current model
  void generate_linkage_prohibiting();

  // Object that contains all information about the variable
  // encoding.
  Variables* _variables;

  // The MiniSAT solver instance. The solver keeps the set of clauses.
  Solver* _solver;

  // Sentence that is being parsed.
  Sentence _sent;

  // Parse options.
  Parse_Options  _opts;

};

/*******************************************************************************
 *       SAT encoding for sentences that do not contain conjunction.           *
 *******************************************************************************/
class SATEncoderConjunctionFreeSentences : public SATEncoder {
public:
  SATEncoderConjunctionFreeSentences(Sentence sent, Parse_Options  opts)
    : SATEncoder(sent, opts) {
  }

  virtual void handle_null_expression(int w);
  virtual void determine_satisfaction(int w, char* name);
  virtual void generate_satisfaction_for_connector(int wi, int pi, const char* Ci,
						   char dir, bool multi, int cost, char* var);

  virtual void generate_linked_definitions();
  virtual bool extract_links(Parse_info pi);

  virtual void generate_encoding_specific_clauses();
};

/*******************************************************************************
 *              SAT encoding for sentences that contain conjunction.           *
 *******************************************************************************/
class SATEncoderConjunctiveSentences : public SATEncoder {
public:
  SATEncoderConjunctiveSentences(Sentence sent, Parse_Options  opts)
    : SATEncoder(sent, opts) {
    init_connective_words();
  }

private:
  virtual void handle_null_expression(int w);
  virtual void determine_satisfaction(int w, char* name);

  virtual void generate_satisfaction_for_connector(int wi, int pi, const char* Ci,
						   char dir, bool multi, int cost, char* var);

  virtual void add_additional_power_pruning_conditions(vec<Lit>& clause, int wl, int wr);

  virtual void generate_encoding_specific_clauses();

  // various fat-link conditions
  void either_tag_or_fat_link(int w, Lit tag);
  void generate_fat_link_up_definitions();
  void generate_fat_link_down_definitions();
  void generate_fat_link_up_between_down_conditions();
  void generate_fat_link_comma_conditions();
  void generate_fat_link_crossover_conditions();
  void generate_fat_link_Left_Wall_not_inside();
  void generate_fat_link_linked_upperside();
  void generate_fat_link_existence();
  void generate_fat_link_neighbor();
  void generate_label_compatibility();

  // link_cw variables

  bool link_cw_possible(int wi, int pi, const char* Ci, char dir, int w, int llim, int rlim);
  bool link_cw_possible_with_fld(int wi, int pi, const char* Ci, char dir, int w, int llim, int rlim);

  void generate_link_cw_connective_impossible         (int wi, int pi, const char* Ci, int wj);
  void generate_link_cw_connective_definition         (int wi, int pi, const char* Cj, int wj);

  // link_top_cw variables
  void generate_link_top_cw_up_definition                  (int wi,
							    int wj, int pj, const char* Cj, bool multi);
  void generate_link_top_cw_iff_link_cw                    (int wi,
							    int wj, int pj, const char* Cj);
  // link_top_ww
  void generate_link_top_ww_connective_comma_definition    (Lit lhs, int wi, int wj);

  // link_ww
  virtual void generate_linked_definitions();

  // Linkage extraction from the model
  void get_satisfied_link_top_cw_connectors(int word, int top_word, std::vector<int>& link_top_cw_vars);
  virtual bool extract_links(Parse_info pi);

  // Initialize the vector of connective words of this sentence
  void init_connective_words();

  // Words that are connectives or commas
  std::vector<int> _connectives;

  // Cache isConnectiveOrComma results for faster checking
  std::vector<bool> _is_connective_or_comma;

  bool isConnectiveOrComma(int w) {
    return _is_connective_or_comma[w];
  }
};
<|endoftext|>


<commit_before>#include "stdafx.h"

#include "ThreadManager.h"
#include "Ini.h"
#include "SceneThread.h"
#include "SceneManager.h"
#include "Config.h"

ThreadManager*    g_pThreadManager=NULL ;

ThreadManager::ThreadManager( )
{
__ENTER_FUNCTION

    m_pThreadPool = new ThreadPool ;
    Assert( m_pThreadPool ) ;

    m_pServerThread = new ServerThread ;
    Assert( m_pServerThread ) ;

    m_nThreads = 0 ;

__LEAVE_FUNCTION
}

ThreadManager::~ThreadManager( )
{
__ENTER_FUNCTION

    SAFE_DELETE( m_pThreadPool) ;
    SAFE_DELETE( m_pServerThread) ;

__LEAVE_FUNCTION
}

BOOL ThreadManager::Init( UINT MaxSceneCount )
{
__ENTER_FUNCTION

    BOOL ret = FALSE ;

    //根据配置文件读取需要使用的场景，为每个场景分配一个线程；
    //读取场景数量
    UINT count = MaxSceneCount ;

    Assert( count<=MAX_SCENE ) ;

    UINT uMaxThreadCount = 0 ;
    UINT i ;
    for( i=0; i<count; i++ )
    {
        //读取场景“i”
        SceneID_t SceneID = (SceneID_t)(g_Config.m_SceneInfo.m_pScene[i].m_SceneID) ;
        Assert( SceneID<MAX_SCENE ) ;

        UINT ServerID = g_Config.m_SceneInfo.m_pScene[i].m_ServerID ;
        if( ServerID != g_Config.m_ConfigInfo.m_ServerID )
        {//不是当前服务器的程序运行的场景
            continue ;
        }
        if( g_Config.m_SceneInfo.m_pScene[i].m_IsActive==0 )
        {//不是激活的场景
            continue ;
        }

        if( (ID_t)uMaxThreadCount<g_Config.m_SceneInfo.m_pScene[i].m_ThreadIndex )
        {
            uMaxThreadCount = g_Config.m_SceneInfo.m_pScene[i].m_ThreadIndex ;
        }
    }

    SceneThread* pSceneThread=NULL ;
    for( i=0; i<=uMaxThreadCount; i++ )
    {
        pSceneThread = new SceneThread ;
        Assert( pSceneThread ) ;

        ret = m_pThreadPool->AddThread( i, pSceneThread ) ;
        Assert( ret ) ;

        m_nThreads ++ ;
    }

    /**
    for ( i = 0; i < uMaxThreadCount; i++ )
    {
        Thread** m_pThread = m_pThreadPool->GetThread();
        SceneThread* pSceneThread1 = (SceneThread*)( m_pThread[ i ] );
        LERR( "uThreadIndex: %d, obj: %d , sizeof( pSceneThread1 ):%d", i, pSceneThread1, sizeof( pSceneThread1 ) );
    }
    **/ //my debug

    for( i=0; i<count; i++ )
    {
        //读取场景“i”
        SceneID_t SceneID = (SceneID_t)(g_Config.m_SceneInfo.m_pScene[i].m_SceneID) ;
        Assert( SceneID<MAX_SCENE ) ;

        UINT ServerID = g_Config.m_SceneInfo.m_pScene[i].m_ServerID ;
        if( ServerID != g_Config.m_ConfigInfo.m_ServerID )
        {//不是当前服务器的程序运行的场景
            continue ;
        }
        if( g_Config.m_SceneInfo.m_pScene[i].m_IsActive==0 )
        {//不是激活的场景
            continue ;
        }

        SceneThread* pSceneThread = (SceneThread*)(m_pThreadPool->GetThreadByIndex(g_Config.m_SceneInfo.m_pScene[i].m_ThreadIndex)) ;
        if( pSceneThread==NULL )
        {
            AssertEx(FALSE,"没有创建所需的线程") ;
        }
        else
        {

            Scene* pScene = g_pSceneManager->GetScene(SceneID) ;
            pSceneThread->AddScene( pScene );

        }
    }

    if( m_pServerThread->IsActive() )
    {
        m_nThreads ++ ;
    }

    return TRUE ;

__LEAVE_FUNCTION

    return FALSE ;
}

BOOL ThreadManager::Start( )
{
__ENTER_FUNCTION

    BOOL ret ;

    m_pServerThread->start() ;

    MySleep( 500 ) ;

    ret = m_pThreadPool->Start( ) ;

    return ret ;

__LEAVE_FUNCTION

    return FALSE ;
}

BOOL ThreadManager::Stop( )
{
__ENTER_FUNCTION

    if( m_pServerThread )
    {
        m_pServerThread->stop( ) ;
    }

    return m_pThreadPool->Stop( ) ;

__LEAVE_FUNCTION

    return FALSE ;
}

<commit_msg>Revert "fix some bug"<commit_after>#include "stdafx.h"

#include "ThreadManager.h"
#include "Ini.h"
#include "SceneThread.h"
#include "SceneManager.h"
#include "Config.h"

ThreadManager*    g_pThreadManager=NULL ;

ThreadManager::ThreadManager( )
{
__ENTER_FUNCTION

    m_pThreadPool = new ThreadPool ;
    Assert( m_pThreadPool ) ;

    m_pServerThread = new ServerThread ;
    Assert( m_pServerThread ) ;

    m_nThreads = 0 ;

__LEAVE_FUNCTION
}

ThreadManager::~ThreadManager( )
{
__ENTER_FUNCTION

    SAFE_DELETE( m_pThreadPool) ;
    SAFE_DELETE( m_pServerThread) ;

__LEAVE_FUNCTION
}

BOOL ThreadManager::Init( UINT MaxSceneCount )
{
__ENTER_FUNCTION

    BOOL ret = FALSE ;

    //根据配置文件读取需要使用的场景，为每个场景分配一个线程；
    //读取场景数量
    UINT count = MaxSceneCount ;

    Assert( count<=MAX_SCENE ) ;

    UINT uMaxThreadCount = 0 ;
    UINT i ;
    for( i=0; i<count; i++ )
    {
        //读取场景“i”
        SceneID_t SceneID = (SceneID_t)(g_Config.m_SceneInfo.m_pScene[i].m_SceneID) ;
        Assert( SceneID<MAX_SCENE ) ;

        UINT ServerID = g_Config.m_SceneInfo.m_pScene[i].m_ServerID ;
        if( ServerID != g_Config.m_ConfigInfo.m_ServerID )
        {//不是当前服务器的程序运行的场景
            continue ;
        }
        if( g_Config.m_SceneInfo.m_pScene[i].m_IsActive==0 )
        {//不是激活的场景
            continue ;
        }

        if( (ID_t)uMaxThreadCount<g_Config.m_SceneInfo.m_pScene[i].m_ThreadIndex )
        {
            uMaxThreadCount = g_Config.m_SceneInfo.m_pScene[i].m_ThreadIndex ;
        }
    }

    SceneThread* pSceneThread=NULL ;
    for( i=0; i<=uMaxThreadCount; i++ )
    {
        pSceneThread = new SceneThread ;
        Assert( pSceneThread ) ;

        LERR( "FILE: %s, i: %d", __FILE__, i )
        ret = m_pThreadPool->AddThread( i, pSceneThread ) ;
        Assert( ret ) ;

        m_nThreads ++ ;
    }

    for ( i = 0; i < uMaxThreadCount; i++ )
    {
        Thread** m_pThread = m_pThreadPool->GetThread();
        SceneThread* pSceneThread1 = (SceneThread*)( m_pThread[ i ] );
        LERR( "uThreadIndex: %d, obj: %d , sizeof( pSceneThread1 ):%d", i, pSceneThread1, sizeof( pSceneThread1 ) );
    }

    for( i=0; i<count; i++ )
    {
        //读取场景“i”
        SceneID_t SceneID = (SceneID_t)(g_Config.m_SceneInfo.m_pScene[i].m_SceneID) ;
        Assert( SceneID<MAX_SCENE ) ;

        UINT ServerID = g_Config.m_SceneInfo.m_pScene[i].m_ServerID ;
        if( ServerID != g_Config.m_ConfigInfo.m_ServerID )
        {//不是当前服务器的程序运行的场景
            continue ;
        }
        if( g_Config.m_SceneInfo.m_pScene[i].m_IsActive==0 )
        {//不是激活的场景
            continue ;
        }

        LERR( "FILE: %s, LINE: %d, m_ThreadIndex: %d", __FILE__, __LINE__, g_Config.m_SceneInfo.m_pScene[i].m_ThreadIndex );
        SceneThread* pSceneThread = (SceneThread*)(m_pThreadPool->GetThreadByIndex(g_Config.m_SceneInfo.m_pScene[i].m_ThreadIndex)) ;
        if( pSceneThread==NULL )
        {
            AssertEx(FALSE,"没有创建所需的线程") ;
        }
        else
        {

            Scene* pScene = g_pSceneManager->GetScene(SceneID) ;
            pSceneThread->AddScene( pScene );

    LERR( "FILE: %s, LINE: %d", __FILE__, __LINE__ );
        }
    }

    LERR( "FILE: %s, LINE: %d", __FILE__, __LINE__ );
    if( m_pServerThread->IsActive() )
    {
        m_nThreads ++ ;
    }

    return TRUE ;

__LEAVE_FUNCTION

    return FALSE ;
}

BOOL ThreadManager::Start( )
{
__ENTER_FUNCTION

    BOOL ret ;

    m_pServerThread->start() ;

    MySleep( 500 ) ;

    ret = m_pThreadPool->Start( ) ;

    return ret ;

__LEAVE_FUNCTION

    return FALSE ;
}

BOOL ThreadManager::Stop( )
{
__ENTER_FUNCTION

    if( m_pServerThread )
    {
        m_pServerThread->stop( ) ;
    }

    return m_pThreadPool->Stop( ) ;

__LEAVE_FUNCTION

    return FALSE ;
}

<|endoftext|>


<commit_before>// Bindings
#include "PyROOT.h"
#include "Adapters.h"
#include "Utility.h"

// ROOT
#include "TInterpreter.h"
#include "TBaseClass.h"
#include "TClass.h"
#include "TClassEdit.h"
#include "TDataType.h"
#include "TDataMember.h"
#include "TMethod.h"
#include "TFunction.h"
#include "TMethodArg.h"
#include "TList.h"
#include "TError.h"

//= TReturnTypeAdapter =======================================================
std::string PyROOT::TReturnTypeAdapter::Name( unsigned int mod ) const
{
// get the name of the return type that is being adapted
   std::string name = fName;

   if ( ! ( mod & Rflx::QUALIFIED ) )
      name = TClassEdit::CleanType( fName.c_str(), 1 );

   if ( mod & Rflx::FINAL )
      name = Utility::ResolveTypedef( name );

   return name;
}

//= TMemberAdapter ===========================================================
PyROOT::TMemberAdapter::TMemberAdapter( TMethod* meth ) : fMember( meth )
{
   /* empty */
}

//____________________________________________________________________________
PyROOT::TMemberAdapter::operator TMethod*() const
{
// cast the adapter to a TMethod* being adapted, returns 0 on failure
   return dynamic_cast< TMethod* >( const_cast< TDictionary* >( fMember ) );
}

//____________________________________________________________________________
PyROOT::TMemberAdapter::TMemberAdapter( TFunction* func ) : fMember( func )
{
   /* empty */
}

//____________________________________________________________________________
PyROOT::TMemberAdapter::operator TFunction*() const
{
// cast the adapter to a TFunction* being adapted, returns 0 on failure
   return dynamic_cast< TFunction* >( const_cast< TDictionary* >( fMember ) );
}

//____________________________________________________________________________
PyROOT::TMemberAdapter::TMemberAdapter( TDataMember* mb ) : fMember( mb )
{
   /* empty */
}

//____________________________________________________________________________
PyROOT::TMemberAdapter::operator TDataMember*() const
{
// cast the adapter to a TDataMember* being adapted, returns 0 on failure
   return dynamic_cast< TDataMember* >( const_cast< TDictionary* >( fMember ) );
}

//____________________________________________________________________________
PyROOT::TMemberAdapter::TMemberAdapter( TMethodArg* ma ) : fMember( ma )
{
   /* empty */
}

//____________________________________________________________________________
PyROOT::TMemberAdapter::operator TMethodArg*() const
{
// cast the adapter to a TMethodArg* being adapted, returns 0 on failure
   return dynamic_cast< TMethodArg* >( const_cast< TDictionary* >( fMember ) );
}

//____________________________________________________________________________
std::string PyROOT::TMemberAdapter::Name( unsigned int mod ) const
{
// Return name of the type described by fMember
   TMethodArg* arg = (TMethodArg*)*this;

   if ( arg ) {

      std::string name = arg->GetTypeName();
      if ( mod & Rflx::QUALIFIED )
         name = arg->GetFullTypeName();

      if ( mod & Rflx::FINAL )
         name = Utility::ResolveTypedef( name );

      return name;

   } else if ( mod & Rflx::FINAL )
      return Utility::ResolveTypedef( fMember->GetName() );

// new with cling, TMethod names are fully scoped ...
   TMethod* m = (TMethod*)*this;
   if (m && m->GetClass()) {
      std::string scoped_name = m->GetName();
      std::string class_name = m->GetClass()->GetName();
      std::string::size_type pos = scoped_name.find(class_name + "::");
      if (pos == 0)      // only accept found at start
         return scoped_name.substr(class_name.size() + 2 /* for :: */, std::string::npos);
   }

   return fMember->GetName();
}

//____________________________________________________________________________
Bool_t PyROOT::TMemberAdapter::IsEnum() const
{
// test if the adapted member is of an enum type
   return fMember->Property() & kIsEnum;
}

//____________________________________________________________________________
Bool_t PyROOT::TMemberAdapter::IsPublic() const
{
// test if the adapted member represents an public (data) member
   return fMember->Property() & kIsPublic;
}

//____________________________________________________________________________
Bool_t PyROOT::TMemberAdapter::IsStatic() const
{
// test if the adapted member represents a class (data) member
   return fMember->Property() & kIsStatic;
}

//____________________________________________________________________________
size_t PyROOT::TMemberAdapter::FunctionParameterSize( Bool_t required ) const
{
// get the total number of parameters that the adapted function/method takes
   TFunction* func = (TFunction*)fMember;
   if ( ! func )
      return 0;

   if ( required == true )
      return func->GetNargs() - func->GetNargsOpt();

   return func->GetNargs();
}

//____________________________________________________________________________
PyROOT::TMemberAdapter PyROOT::TMemberAdapter::FunctionParameterAt( size_t nth ) const
{
// get the type info of the function parameter at position nth
   return (TMethodArg*)((TFunction*)fMember)->GetListOfMethodArgs()->At( nth );
}

//____________________________________________________________________________
std::string PyROOT::TMemberAdapter::FunctionParameterNameAt( size_t nth ) const
{
// get the formal name, if available, of the function parameter at position nth
   const char* name =
      ((TMethodArg*)((TFunction*)fMember)->GetListOfMethodArgs()->At( nth ))->GetName();

   if ( name )
      return name;
   return "";
}

//____________________________________________________________________________
std::string PyROOT::TMemberAdapter::FunctionParameterDefaultAt( size_t nth ) const
{
// get the default value, if available, of the function parameter at position nth
   TMethodArg* arg = (TMethodArg*)((TFunction*)fMember)->GetListOfMethodArgs()->At( nth );
   const char* def = arg->GetDefault();

   if ( ! def )
      return "";

// special case for strings: "some value" -> ""some value"
   if ( strstr( Utility::ResolveTypedef( arg->GetTypeName() ).c_str(), "char*" ) ) {
      std::string sdef = "\"";
      sdef += def;
      sdef += "\"";
      return sdef;
   }

   return def;
}

//____________________________________________________________________________
PyROOT::TReturnTypeAdapter PyROOT::TMemberAdapter::ReturnType() const
{
// get the return type of the wrapped function/method
   return TReturnTypeAdapter( ((TFunction*)fMember)->GetReturnTypeName() );
}

//____________________________________________________________________________
PyROOT::TScopeAdapter PyROOT::TMemberAdapter::DeclaringScope() const
{
// get the declaring scope (class) of the wrapped function/method
   TMethod* method = (TMethod*)*this;
   if ( method )
      return method->GetClass();

// happens for free-standing functions (i.e. global scope)
   return std::string( "" );
}

//= TBaseAdapter =============================================================
std::string PyROOT::TBaseAdapter::Name() const
{
// get the name of the base class that is being adapted
   return fBase->GetName();
}

//= TScopeAdapter ============================================================
PyROOT::TScopeAdapter::TScopeAdapter( TClass* klass ) : fClass( klass )
{
// wrap a class (scope)
   if ( fClass.GetClass() != 0 )
      fName = fClass->GetName();
}

//____________________________________________________________________________
PyROOT::TScopeAdapter::TScopeAdapter( const std::string& name ) :
   fClass( name.c_str() ), fName( name )
{
   /* empty */
}

PyROOT::TScopeAdapter::TScopeAdapter( const TMemberAdapter& mb ) :
      fClass( mb.Name( Rflx::SCOPED ).c_str() ),
      fName( mb.Name( Rflx::QUALIFIED | Rflx::SCOPED ) )
{
   /* empty */
}

//____________________________________________________________________________
PyROOT::TScopeAdapter PyROOT::TScopeAdapter::ByName( const std::string& name, Bool_t quiet )
{
// lookup a scope (class) by name
   Int_t oldEIL = gErrorIgnoreLevel;
   if ( quiet )
      gErrorIgnoreLevel = 3000;
   TClass* klass = TClass::GetClass( name.c_str() );
   gErrorIgnoreLevel = oldEIL;

   return klass;
}

//____________________________________________________________________________
std::string PyROOT::TScopeAdapter::Name( unsigned int mod ) const
{
// Return name of type described by fClass
   if ( ! fClass.GetClass() || ! fClass->Property() ) {
   // fundamental types have no class, and unknown classes have no property
      std::string name = fName;

      if ( ! ( mod & Rflx::QUALIFIED ) )
         name = TClassEdit::CleanType( fName.c_str(), 1 );

      if ( mod & Rflx::FINAL )
         name = Utility::ResolveTypedef( name );

      return name;
   }

   if ( mod & Rflx::FINAL ) {
   /* The following G__ClassInfo lookup is badly broken ...
      G__ClassInfo* clInfo = (G__ClassInfo*)fClass->GetClassInfo();
      if ( mod & Rflx::SCOPED )
         return (clInfo && clInfo->Fullname()) ? clInfo->Fullname() : fClass->GetName();

   // unscoped name ...
      std::string actual = (clInfo && clInfo->Name()) ? clInfo->Name() : fClass->GetName();

   // in case of missing dictionaries, the scope won't have been stripped
      if ( ! ( clInfo && clInfo->IsValid() ) ) {
         std::string::size_type pos = actual.substr( 0, actual.find( '<' ) ).rfind( "::" );
         if ( pos != std::string::npos ) {
         // this is somewhat of a gamble, but the alternative is a guaranteed crash
            actual = actual.substr( pos + 2, std::string::npos );
         }
      }

      return actual;
   */
      return fClass->GetName();

   } else if ( ! ( mod & Rflx::SCOPED ) ) {
   /* The following G__ClassInfo lookup is badly broken ...
      G__ClassInfo* clInfo = (G__ClassInfo*)fClass->GetClassInfo();
      return (clInfo && clInfo->Name()) ? clInfo->Name() : fClass->GetName();
   */
      return fClass->GetName();
   }

   return fClass->GetName();
}

//____________________________________________________________________________
size_t PyROOT::TScopeAdapter::BaseSize() const
{
// get the total number of base classes that this class has
   if ( fClass.GetClass() && fClass->GetListOfBases() != 0 )
      return fClass->GetListOfBases()->GetSize();

   return 0;
}

//____________________________________________________________________________
PyROOT::TBaseAdapter PyROOT::TScopeAdapter::BaseAt( size_t nth ) const
{
// get the nth base of this class
   return (TBaseClass*)fClass->GetListOfBases()->At( nth );
}

//____________________________________________________________________________
size_t PyROOT::TScopeAdapter::FunctionMemberSize() const
{
// get the total number of methods that this class has
   if ( fClass.GetClass() )
      return fClass->GetListOfMethods()->GetSize();

   return 0;
}

//____________________________________________________________________________
PyROOT::TMemberAdapter PyROOT::TScopeAdapter::FunctionMemberAt( size_t nth ) const
{
// get the nth method of this class
   return (TMethod*)fClass->GetListOfMethods()->At( nth );
}

//____________________________________________________________________________
size_t PyROOT::TScopeAdapter::DataMemberSize() const
{
// get the total number of data members that this class has
   if ( fClass.GetClass() )
      return fClass->GetListOfDataMembers()->GetSize();

   return 0;
}

//____________________________________________________________________________
PyROOT::TMemberAdapter PyROOT::TScopeAdapter::DataMemberAt( size_t nth ) const
{
// get the nth data member of this class
   return (TDataMember*)fClass->GetListOfDataMembers()->At( nth );
}

//____________________________________________________________________________
PyROOT::TScopeAdapter::operator Bool_t() const
{
// check the validity of this scope (class)
   if ( fName.empty() )
      return false;

   Bool_t b = kFALSE;

   Int_t oldEIL = gErrorIgnoreLevel;
   gErrorIgnoreLevel = 3000;
   TClass* klass = TClass::GetClass( Name( Rflx::QUALIFIED | Rflx::SCOPED ).c_str() );
   if ( klass ) b = gInterpreter->ClassInfo_IsValid( klass->GetClassInfo() );
   gErrorIgnoreLevel = oldEIL;
   return b;
}

//____________________________________________________________________________
Bool_t PyROOT::TScopeAdapter::IsComplete() const
{
// verify whether the dictionary of this class is fully available
   Bool_t b = kFALSE;

   TClass* klass = TClass::GetClass( Name( Rflx::SCOPED ).c_str() );
   if ( klass ) b = gInterpreter->ClassInfo_IsLoaded( klass->GetClassInfo() );
   return b;
}

//____________________________________________________________________________
Bool_t PyROOT::TScopeAdapter::IsClass() const
{
// test if this scope represents a class
   if ( fClass.GetClass() ) {
   // some inverted logic: we don't have a TClass, but a builtin will be recognized, so
   // if it is NOT a builtin, it is a class or struct (but may be missing dictionary)
      return (fClass->Property() & kIsClass) || ! (fClass->Property() & kIsFundamental);
   }

// no class can mean either is no class (i.e. builtin), or no dict but coming in
// through PyCintex/Reflex ... as a workaround, use TDataTypes that has a full
// enumeration of builtin types
   return TDataType( Name( Rflx::FINAL | Rflx::SCOPED ).c_str() ).GetType() == kOther_t;
}

//____________________________________________________________________________
Bool_t PyROOT::TScopeAdapter::IsStruct() const
{
// test if this scope represents a struct
   if ( fClass.GetClass() ) {
   // same logic as for IsClass() above ...
      return (fClass->Property() & kIsStruct) || ! (fClass->Property() & kIsFundamental);
   }

// same logic as for IsClass() above ...
   return TDataType( Name( Rflx::FINAL | Rflx::SCOPED ).c_str() ).GetType() == kOther_t;
}

//____________________________________________________________________________
Bool_t PyROOT::TScopeAdapter::IsNamespace() const
{
// test if this scope represents a namespace
   if ( fClass.GetClass() )
      return fClass->Property() & kIsNamespace;

   return kFALSE;
}

//____________________________________________________________________________
Bool_t PyROOT::TScopeAdapter::IsAbstract() const
{
// test if this scope represents an abstract class
   if ( fClass.GetClass() )
      return fClass->Property() & kIsAbstract;   // assume set only for classes

   return kFALSE;
}
<commit_msg>gInterpreter->ClassInfo_IsValid crashes on NULL input ... protect<commit_after>// Bindings
#include "PyROOT.h"
#include "Adapters.h"
#include "Utility.h"

// ROOT
#include "TInterpreter.h"
#include "TBaseClass.h"
#include "TClass.h"
#include "TClassEdit.h"
#include "TDataType.h"
#include "TDataMember.h"
#include "TMethod.h"
#include "TFunction.h"
#include "TMethodArg.h"
#include "TList.h"
#include "TError.h"

//= TReturnTypeAdapter =======================================================
std::string PyROOT::TReturnTypeAdapter::Name( unsigned int mod ) const
{
// get the name of the return type that is being adapted
   std::string name = fName;

   if ( ! ( mod & Rflx::QUALIFIED ) )
      name = TClassEdit::CleanType( fName.c_str(), 1 );

   if ( mod & Rflx::FINAL )
      name = Utility::ResolveTypedef( name );

   return name;
}

//= TMemberAdapter ===========================================================
PyROOT::TMemberAdapter::TMemberAdapter( TMethod* meth ) : fMember( meth )
{
   /* empty */
}

//____________________________________________________________________________
PyROOT::TMemberAdapter::operator TMethod*() const
{
// cast the adapter to a TMethod* being adapted, returns 0 on failure
   return dynamic_cast< TMethod* >( const_cast< TDictionary* >( fMember ) );
}

//____________________________________________________________________________
PyROOT::TMemberAdapter::TMemberAdapter( TFunction* func ) : fMember( func )
{
   /* empty */
}

//____________________________________________________________________________
PyROOT::TMemberAdapter::operator TFunction*() const
{
// cast the adapter to a TFunction* being adapted, returns 0 on failure
   return dynamic_cast< TFunction* >( const_cast< TDictionary* >( fMember ) );
}

//____________________________________________________________________________
PyROOT::TMemberAdapter::TMemberAdapter( TDataMember* mb ) : fMember( mb )
{
   /* empty */
}

//____________________________________________________________________________
PyROOT::TMemberAdapter::operator TDataMember*() const
{
// cast the adapter to a TDataMember* being adapted, returns 0 on failure
   return dynamic_cast< TDataMember* >( const_cast< TDictionary* >( fMember ) );
}

//____________________________________________________________________________
PyROOT::TMemberAdapter::TMemberAdapter( TMethodArg* ma ) : fMember( ma )
{
   /* empty */
}

//____________________________________________________________________________
PyROOT::TMemberAdapter::operator TMethodArg*() const
{
// cast the adapter to a TMethodArg* being adapted, returns 0 on failure
   return dynamic_cast< TMethodArg* >( const_cast< TDictionary* >( fMember ) );
}

//____________________________________________________________________________
std::string PyROOT::TMemberAdapter::Name( unsigned int mod ) const
{
// Return name of the type described by fMember
   TMethodArg* arg = (TMethodArg*)*this;

   if ( arg ) {

      std::string name = arg->GetTypeName();
      if ( mod & Rflx::QUALIFIED )
         name = arg->GetFullTypeName();

      if ( mod & Rflx::FINAL )
         name = Utility::ResolveTypedef( name );

      return name;

   } else if ( mod & Rflx::FINAL )
      return Utility::ResolveTypedef( fMember->GetName() );

// new with cling, TMethod names are fully scoped ...
   TMethod* m = (TMethod*)*this;
   if (m && m->GetClass()) {
      std::string scoped_name = m->GetName();
      std::string class_name = m->GetClass()->GetName();
      std::string::size_type pos = scoped_name.find(class_name + "::");
      if (pos == 0)      // only accept found at start
         return scoped_name.substr(class_name.size() + 2 /* for :: */, std::string::npos);
   }

   return fMember->GetName();
}

//____________________________________________________________________________
Bool_t PyROOT::TMemberAdapter::IsEnum() const
{
// test if the adapted member is of an enum type
   return fMember->Property() & kIsEnum;
}

//____________________________________________________________________________
Bool_t PyROOT::TMemberAdapter::IsPublic() const
{
// test if the adapted member represents an public (data) member
   return fMember->Property() & kIsPublic;
}

//____________________________________________________________________________
Bool_t PyROOT::TMemberAdapter::IsStatic() const
{
// test if the adapted member represents a class (data) member
   return fMember->Property() & kIsStatic;
}

//____________________________________________________________________________
size_t PyROOT::TMemberAdapter::FunctionParameterSize( Bool_t required ) const
{
// get the total number of parameters that the adapted function/method takes
   TFunction* func = (TFunction*)fMember;
   if ( ! func )
      return 0;

   if ( required == true )
      return func->GetNargs() - func->GetNargsOpt();

   return func->GetNargs();
}

//____________________________________________________________________________
PyROOT::TMemberAdapter PyROOT::TMemberAdapter::FunctionParameterAt( size_t nth ) const
{
// get the type info of the function parameter at position nth
   return (TMethodArg*)((TFunction*)fMember)->GetListOfMethodArgs()->At( nth );
}

//____________________________________________________________________________
std::string PyROOT::TMemberAdapter::FunctionParameterNameAt( size_t nth ) const
{
// get the formal name, if available, of the function parameter at position nth
   const char* name =
      ((TMethodArg*)((TFunction*)fMember)->GetListOfMethodArgs()->At( nth ))->GetName();

   if ( name )
      return name;
   return "";
}

//____________________________________________________________________________
std::string PyROOT::TMemberAdapter::FunctionParameterDefaultAt( size_t nth ) const
{
// get the default value, if available, of the function parameter at position nth
   TMethodArg* arg = (TMethodArg*)((TFunction*)fMember)->GetListOfMethodArgs()->At( nth );
   const char* def = arg->GetDefault();

   if ( ! def )
      return "";

// special case for strings: "some value" -> ""some value"
   if ( strstr( Utility::ResolveTypedef( arg->GetTypeName() ).c_str(), "char*" ) ) {
      std::string sdef = "\"";
      sdef += def;
      sdef += "\"";
      return sdef;
   }

   return def;
}

//____________________________________________________________________________
PyROOT::TReturnTypeAdapter PyROOT::TMemberAdapter::ReturnType() const
{
// get the return type of the wrapped function/method
   return TReturnTypeAdapter( ((TFunction*)fMember)->GetReturnTypeName() );
}

//____________________________________________________________________________
PyROOT::TScopeAdapter PyROOT::TMemberAdapter::DeclaringScope() const
{
// get the declaring scope (class) of the wrapped function/method
   TMethod* method = (TMethod*)*this;
   if ( method )
      return method->GetClass();

// happens for free-standing functions (i.e. global scope)
   return std::string( "" );
}

//= TBaseAdapter =============================================================
std::string PyROOT::TBaseAdapter::Name() const
{
// get the name of the base class that is being adapted
   return fBase->GetName();
}

//= TScopeAdapter ============================================================
PyROOT::TScopeAdapter::TScopeAdapter( TClass* klass ) : fClass( klass )
{
// wrap a class (scope)
   if ( fClass.GetClass() != 0 )
      fName = fClass->GetName();
}

//____________________________________________________________________________
PyROOT::TScopeAdapter::TScopeAdapter( const std::string& name ) :
   fClass( name.c_str() ), fName( name )
{
   /* empty */
}

PyROOT::TScopeAdapter::TScopeAdapter( const TMemberAdapter& mb ) :
      fClass( mb.Name( Rflx::SCOPED ).c_str() ),
      fName( mb.Name( Rflx::QUALIFIED | Rflx::SCOPED ) )
{
   /* empty */
}

//____________________________________________________________________________
PyROOT::TScopeAdapter PyROOT::TScopeAdapter::ByName( const std::string& name, Bool_t quiet )
{
// lookup a scope (class) by name
   Int_t oldEIL = gErrorIgnoreLevel;
   if ( quiet )
      gErrorIgnoreLevel = 3000;
   TClass* klass = TClass::GetClass( name.c_str() );
   gErrorIgnoreLevel = oldEIL;

   return klass;
}

//____________________________________________________________________________
std::string PyROOT::TScopeAdapter::Name( unsigned int mod ) const
{
// Return name of type described by fClass
   if ( ! fClass.GetClass() || ! fClass->Property() ) {
   // fundamental types have no class, and unknown classes have no property
      std::string name = fName;

      if ( ! ( mod & Rflx::QUALIFIED ) )
         name = TClassEdit::CleanType( fName.c_str(), 1 );

      if ( mod & Rflx::FINAL )
         name = Utility::ResolveTypedef( name );

      return name;
   }

   if ( mod & Rflx::FINAL ) {
   /* The following G__ClassInfo lookup is badly broken ...
      G__ClassInfo* clInfo = (G__ClassInfo*)fClass->GetClassInfo();
      if ( mod & Rflx::SCOPED )
         return (clInfo && clInfo->Fullname()) ? clInfo->Fullname() : fClass->GetName();

   // unscoped name ...
      std::string actual = (clInfo && clInfo->Name()) ? clInfo->Name() : fClass->GetName();

   // in case of missing dictionaries, the scope won't have been stripped
      if ( ! ( clInfo && clInfo->IsValid() ) ) {
         std::string::size_type pos = actual.substr( 0, actual.find( '<' ) ).rfind( "::" );
         if ( pos != std::string::npos ) {
         // this is somewhat of a gamble, but the alternative is a guaranteed crash
            actual = actual.substr( pos + 2, std::string::npos );
         }
      }

      return actual;
   */
      return fClass->GetName();

   } else if ( ! ( mod & Rflx::SCOPED ) ) {
   /* The following G__ClassInfo lookup is badly broken ...
      G__ClassInfo* clInfo = (G__ClassInfo*)fClass->GetClassInfo();
      return (clInfo && clInfo->Name()) ? clInfo->Name() : fClass->GetName();
   */
      return fClass->GetName();
   }

   return fClass->GetName();
}

//____________________________________________________________________________
size_t PyROOT::TScopeAdapter::BaseSize() const
{
// get the total number of base classes that this class has
   if ( fClass.GetClass() && fClass->GetListOfBases() != 0 )
      return fClass->GetListOfBases()->GetSize();

   return 0;
}

//____________________________________________________________________________
PyROOT::TBaseAdapter PyROOT::TScopeAdapter::BaseAt( size_t nth ) const
{
// get the nth base of this class
   return (TBaseClass*)fClass->GetListOfBases()->At( nth );
}

//____________________________________________________________________________
size_t PyROOT::TScopeAdapter::FunctionMemberSize() const
{
// get the total number of methods that this class has
   if ( fClass.GetClass() )
      return fClass->GetListOfMethods()->GetSize();

   return 0;
}

//____________________________________________________________________________
PyROOT::TMemberAdapter PyROOT::TScopeAdapter::FunctionMemberAt( size_t nth ) const
{
// get the nth method of this class
   return (TMethod*)fClass->GetListOfMethods()->At( nth );
}

//____________________________________________________________________________
size_t PyROOT::TScopeAdapter::DataMemberSize() const
{
// get the total number of data members that this class has
   if ( fClass.GetClass() )
      return fClass->GetListOfDataMembers()->GetSize();

   return 0;
}

//____________________________________________________________________________
PyROOT::TMemberAdapter PyROOT::TScopeAdapter::DataMemberAt( size_t nth ) const
{
// get the nth data member of this class
   return (TDataMember*)fClass->GetListOfDataMembers()->At( nth );
}

//____________________________________________________________________________
PyROOT::TScopeAdapter::operator Bool_t() const
{
// check the validity of this scope (class)
   if ( fName.empty() )
      return false;

   Bool_t b = kFALSE;

   Int_t oldEIL = gErrorIgnoreLevel;
   gErrorIgnoreLevel = 3000;
   TClass* klass = TClass::GetClass( Name( Rflx::QUALIFIED | Rflx::SCOPED ).c_str() );
   if ( klass && klass->GetClassInfo() )
      b = gInterpreter->ClassInfo_IsValid( klass->GetClassInfo() );
   gErrorIgnoreLevel = oldEIL;
   return b;
}

//____________________________________________________________________________
Bool_t PyROOT::TScopeAdapter::IsComplete() const
{
// verify whether the dictionary of this class is fully available
   Bool_t b = kFALSE;

   TClass* klass = TClass::GetClass( Name( Rflx::SCOPED ).c_str() );
   if ( klass ) b = gInterpreter->ClassInfo_IsLoaded( klass->GetClassInfo() );
   return b;
}

//____________________________________________________________________________
Bool_t PyROOT::TScopeAdapter::IsClass() const
{
// test if this scope represents a class
   if ( fClass.GetClass() ) {
   // some inverted logic: we don't have a TClass, but a builtin will be recognized, so
   // if it is NOT a builtin, it is a class or struct (but may be missing dictionary)
      return (fClass->Property() & kIsClass) || ! (fClass->Property() & kIsFundamental);
   }

// no class can mean either is no class (i.e. builtin), or no dict but coming in
// through PyCintex/Reflex ... as a workaround, use TDataTypes that has a full
// enumeration of builtin types
   return TDataType( Name( Rflx::FINAL | Rflx::SCOPED ).c_str() ).GetType() == kOther_t;
}

//____________________________________________________________________________
Bool_t PyROOT::TScopeAdapter::IsStruct() const
{
// test if this scope represents a struct
   if ( fClass.GetClass() ) {
   // same logic as for IsClass() above ...
      return (fClass->Property() & kIsStruct) || ! (fClass->Property() & kIsFundamental);
   }

// same logic as for IsClass() above ...
   return TDataType( Name( Rflx::FINAL | Rflx::SCOPED ).c_str() ).GetType() == kOther_t;
}

//____________________________________________________________________________
Bool_t PyROOT::TScopeAdapter::IsNamespace() const
{
// test if this scope represents a namespace
   if ( fClass.GetClass() )
      return fClass->Property() & kIsNamespace;

   return kFALSE;
}

//____________________________________________________________________________
Bool_t PyROOT::TScopeAdapter::IsAbstract() const
{
// test if this scope represents an abstract class
   if ( fClass.GetClass() )
      return fClass->Property() & kIsAbstract;   // assume set only for classes

   return kFALSE;
}
<|endoftext|>