<commit_before>#ifndef DUNEMS_HMM_CELL_NUMBERING_HH
#define DUNEMS_HMM_CELL_NUMBERING_HH

#include <dune/fem/quadrature/cachingquadrature.hh>

namespace Dune {
// comparison class for the CellProblemNumberingManager:
template< class GridPartType, class DomainType, class EntityPointerType >
struct classcomp
{
  bool operator()(const std::pair< EntityPointerType, int >& left_entity_pair,
                  const std::pair< EntityPointerType, int >& right_entity_pair) const {
    // compare the barycenteres of the entities with the lexicographic order, than compare the int's (number of local
    // base function)

    typedef Fem::CachingQuadrature< GridPartType, 0 > Quadrature;

    // ------ right element

    const typename EntityPointerType::Entity::Geometry& geometry_right = ( *(right_entity_pair.first) ).geometry();

    Quadrature quadrature_right( ( *(right_entity_pair.first) ), 0 );

    // local barycenter (with respect to entity)
    const typename Quadrature::CoordinateType& local_point_right = quadrature_right.point(0);

    DomainType barycenter_right_entity = geometry_right.global(local_point_right);

    // ------ left element

    const typename EntityPointerType::Entity::Geometry& geometry_left = ( *(left_entity_pair.first) ).geometry();

    Quadrature quadrature_left( ( *(left_entity_pair.first) ), 0 );

    // local barycenter (with respect to entity)
    const typename Quadrature::CoordinateType& local_point_left = quadrature_left.point(0);

    DomainType barycenter_left_entity = geometry_left.global(local_point_left);

    enum { dimension = GridPartType::GridType::dimension };

    int current_axis = dimension - 1;

    while (current_axis >= 0)
    {
      if (barycenter_left_entity[current_axis] < barycenter_right_entity[current_axis])
      { return true; } else if (barycenter_left_entity[current_axis] > barycenter_right_entity[current_axis])
      { return false; }

      current_axis -= 1;
    }

    if (left_entity_pair.second < right_entity_pair.second)
    {
      return true;
    } else
    { return false; }

    return true;
  } // ()
};

// comparison class for the CellProblemNumberingManager (just comparison of two entities!)
template< class GridPartType, class DomainType, class EntityPointerType >
struct entity_compare
{
  bool operator()(EntityPointerType left_entity,
                  EntityPointerType right_entity) const {
    // compare the barycenteres of the entities with the lexicographic order

    typedef CachingQuadrature< GridPartType, 0 > Quadrature;

    // ------ right element

    const typename EntityPointerType::Entity::Geometry& geometry_right = (*right_entity).geometry();

    Quadrature quadrature_right(*right_entity, 0);

    // local barycenter (with respect to entity)
    const typename Quadrature::CoordinateType& local_point_right = quadrature_right.point(0);

    DomainType barycenter_right_entity = geometry_right.global(local_point_right);

    // ------ left element

    const typename EntityPointerType::Entity::Geometry& geometry_left = (*left_entity).geometry();

    Quadrature quadrature_left(*left_entity, 0);

    // local barycenter (with respect to entity)
    const typename Quadrature::CoordinateType& local_point_left = quadrature_left.point(0);

    DomainType barycenter_left_entity = geometry_left.global(local_point_left);

    enum { dimension = GridPartType::GridType::dimension };

    int current_axis = dimension - 1;

    while (current_axis >= 0)
    {
      if (barycenter_left_entity[current_axis] < barycenter_right_entity[current_axis])
      { return true; } else if (barycenter_left_entity[current_axis] > barycenter_right_entity[current_axis])
      { return false; }

      current_axis -= 1;
    }

    return false;
  } // ()
};

// only for the combination entity + number of local base function on entity
template< class DiscreteFunctionSpaceType >
class CellProblemNumberingManager
{
public:
  typedef typename DiscreteFunctionSpaceType::GridPartType GridPartType;
  typedef typename GridPartType::GridType                  GridType;

  typedef typename GridType::template Codim< 0 >::Entity         EntityType;
  typedef typename GridType::template  Codim< 0 >::EntityPointer EntityPointerType;

  typedef typename DiscreteFunctionSpaceType::BaseFunctionSetType BaseFunctionSetType;
  typedef typename DiscreteFunctionSpaceType::IteratorType        IteratorType;

  typedef typename DiscreteFunctionSpaceType::DomainType DomainType;

  typedef classcomp< GridPartType, DomainType, EntityPointerType > CompClass;

  typedef std::map< std::pair< EntityPointerType, int >, int, CompClass > CellNumMapType;

  // for the comparison of two entities:
  typedef entity_compare< GridPartType, DomainType, EntityPointerType > CompEntityClass;

  typedef std::map< EntityPointerType, int, CompEntityClass > CellNumMapNLType;

  CellNumMapType* cell_numbering_map_;
  CellNumMapNLType* cell_numbering_map_NL_;

  // simpliefied: in general we need CellNumMapType for the cell problem numering in the linear setting (entity and
  // local number of base function) and in the nonlinear case we need CellNumMapNLType (NL stands for nonlinear).
  // CellNumMapType is also required in the nonlinear case if we use test function reconstruction (TFR)

  inline explicit CellProblemNumberingManager(DiscreteFunctionSpaceType& discreteFunctionSpace) {
    cell_numbering_map_ = new CellNumMapType;
    cell_numbering_map_NL_ = new CellNumMapNLType;

    int counter = 0;
    int number_of_entity = 0;

    IteratorType endit = discreteFunctionSpace.end();
    for (IteratorType it = discreteFunctionSpace.begin(); it != endit; ++it)
    {
      cell_numbering_map_NL_->insert( std::make_pair(EntityPointerType(*it), number_of_entity) );

      const BaseFunctionSetType baseSet
        = discreteFunctionSpace.baseFunctionSet(*it);

      // number of base functions on entity
      const int numBaseFunctions = baseSet.size();

      for (int i = 0; i < numBaseFunctions; ++i)
      {
        std::pair< EntityPointerType, int > idPair(EntityPointerType(*it), i);
        cell_numbering_map_->insert( std::make_pair(idPair, counter) );
        counter++;
      }

      number_of_entity++;
    }
  }

  // use 'cp_num_manager.get_number_of_cell_problem( it, i )'
  inline int get_number_of_cell_problem(EntityPointerType& ent, const int& numOfBaseFunction) const {
    std::pair< EntityPointerType, int > idPair(ent, numOfBaseFunction);
    // !TODO this can create elements
    return (*cell_numbering_map_)[idPair];
  }

  // use 'cp_num_manager.get_number_of_cell_problem( it )'
  // Note: 'get_number_of_cell_problem( it )' is NOT equal to 'get_number_of_cell_problem( it , 0 )'!
  inline int get_number_of_cell_problem(EntityPointerType& ent) const {
    // !TODO this can create elements
    return (*cell_numbering_map_NL_)[ent];
  }
};
} //namespace Dune {
#endif // DUNEMS_HMM_CELL_NUMBERING_HH
<commit_msg>nembering-manager: fix memleak and silent creation of new elements<commit_after>#ifndef DUNEMS_HMM_CELL_NUMBERING_HH
#define DUNEMS_HMM_CELL_NUMBERING_HH

#include <utility>
#include <map>

#include <dune/fem/quadrature/cachingquadrature.hh>

namespace Dune {
//! comparison class for the CellProblemNumberingManager:
template< class GridPartType, class DomainType, class EntityPointerType >
struct classcomp
{
  bool operator()(const std::pair< EntityPointerType, int >& left_entity_pair,
                  const std::pair< EntityPointerType, int >& right_entity_pair) const {
    // compare the barycenteres of the entities with the lexicographic order, than compare the int's (number of local
    // base function)

    typedef Fem::CachingQuadrature< GridPartType, 0 > Quadrature;

    // ------ right element

    const typename EntityPointerType::Entity::Geometry& geometry_right = ( *(right_entity_pair.first) ).geometry();

    Quadrature quadrature_right( ( *(right_entity_pair.first) ), 0 );

    // local barycenter (with respect to entity)
    const typename Quadrature::CoordinateType& local_point_right = quadrature_right.point(0);

    DomainType barycenter_right_entity = geometry_right.global(local_point_right);

    // ------ left element

    const typename EntityPointerType::Entity::Geometry& geometry_left = ( *(left_entity_pair.first) ).geometry();

    Quadrature quadrature_left( ( *(left_entity_pair.first) ), 0 );

    // local barycenter (with respect to entity)
    const typename Quadrature::CoordinateType& local_point_left = quadrature_left.point(0);

    DomainType barycenter_left_entity = geometry_left.global(local_point_left);

    enum { dimension = GridPartType::GridType::dimension };

    int current_axis = dimension - 1;

    while (current_axis >= 0)
    {
      if (barycenter_left_entity[current_axis] < barycenter_right_entity[current_axis])
      { return true; } else if (barycenter_left_entity[current_axis] > barycenter_right_entity[current_axis])
      { return false; }

      current_axis -= 1;
    }

    if (left_entity_pair.second < right_entity_pair.second)
    {
      return true;
    } else
    { return false; }

    return true;
  } // ()
};

//! comparison class for the CellProblemNumberingManager (just comparison of two entities!)
template< class GridPartType, class DomainType, class EntityPointerType >
struct entity_compare
{
  bool operator()(EntityPointerType left_entity,
                  EntityPointerType right_entity) const {
    // compare the barycenteres of the entities with the lexicographic order

    typedef Fem::CachingQuadrature< GridPartType, 0 > Quadrature;

    // ------ right element

    const typename EntityPointerType::Entity::Geometry& geometry_right = (*right_entity).geometry();

    Quadrature quadrature_right(*right_entity, 0);

    // local barycenter (with respect to entity)
    const typename Quadrature::CoordinateType& local_point_right = quadrature_right.point(0);

    DomainType barycenter_right_entity = geometry_right.global(local_point_right);

    // ------ left element

    const typename EntityPointerType::Entity::Geometry& geometry_left = (*left_entity).geometry();

    Quadrature quadrature_left(*left_entity, 0);

    // local barycenter (with respect to entity)
    const typename Quadrature::CoordinateType& local_point_left = quadrature_left.point(0);

    DomainType barycenter_left_entity = geometry_left.global(local_point_left);

    enum { dimension = GridPartType::GridType::dimension };

    int current_axis = dimension - 1;

    while (current_axis >= 0)
    {
      if (barycenter_left_entity[current_axis] < barycenter_right_entity[current_axis])
      { return true; } else if (barycenter_left_entity[current_axis] > barycenter_right_entity[current_axis])
      { return false; }

      current_axis -= 1;
    }

    return false;
  } // ()
};

//! only for the combination entity + number of local base function on entity
template< class DiscreteFunctionSpaceType >
class CellProblemNumberingManager
{
public:
  typedef typename DiscreteFunctionSpaceType::GridPartType GridPartType;
  typedef typename GridPartType::GridType                  GridType;

  typedef typename GridType::template Codim< 0 >::Entity         EntityType;
  typedef typename GridType::template  Codim< 0 >::EntityPointer EntityPointerType;

  typedef typename DiscreteFunctionSpaceType::BaseFunctionSetType BaseFunctionSetType;
  typedef typename DiscreteFunctionSpaceType::IteratorType        IteratorType;

  typedef typename DiscreteFunctionSpaceType::DomainType DomainType;

  typedef classcomp< GridPartType, DomainType, EntityPointerType > CompClass;

  typedef std::map< std::pair< EntityPointerType, int >, int, CompClass > CellNumMapType;

  // for the comparison of two entities:
  typedef entity_compare< GridPartType, DomainType, EntityPointerType > CompEntityClass;

  typedef std::map< EntityPointerType, int, CompEntityClass > CellNumMapNLType;

  CellNumMapType cell_numbering_map_;
  CellNumMapNLType cell_numbering_map_NL_;

  /** simpliefied: in general we need CellNumMapType for the cell problem numering in the linear setting (entity and
   * local number of base function) and in the nonlinear case we need CellNumMapNLType (NL stands for nonlinear).
   * CellNumMapType is also required in the nonlinear case if we use test function reconstruction (TFR)
   **/
  inline explicit CellProblemNumberingManager(DiscreteFunctionSpaceType& discreteFunctionSpace)
  {
    int counter = 0;
    int number_of_entity = 0;

    const IteratorType endit = discreteFunctionSpace.end();
    for (IteratorType it = discreteFunctionSpace.begin(); it != endit; ++it)
    {
      cell_numbering_map_NL_.insert( std::make_pair(EntityPointerType(*it), number_of_entity) );

      const BaseFunctionSetType baseSet
        = discreteFunctionSpace.baseFunctionSet(*it);

      // number of base functions on entity
      const int numBaseFunctions = baseSet.size();

      for (int i = 0; i < numBaseFunctions; ++i)
      {
        std::pair< EntityPointerType, int > idPair(EntityPointerType(*it), i);
        cell_numbering_map_.insert( std::make_pair(idPair, counter) );
        counter++;
      }
      number_of_entity++;
    }
  }

  //! use 'cp_num_manager.get_number_of_cell_problem( it, i )'
  inline int get_number_of_cell_problem(EntityPointerType& ent, const int& numOfBaseFunction) const {
    const typename CellNumMapType::key_type idPair(ent, numOfBaseFunction);
    auto it = cell_numbering_map_.find(idPair);
    if (it != cell_numbering_map_.end() )
      return it->second;
    else
      DUNE_THROW(Dune::RangeError, "no number for entity");
  }

  /** use 'cp_num_manager.get_number_of_cell_problem( it )'
   * \attention 'get_number_of_cell_problem( it )' is NOT equal to 'get_number_of_cell_problem( it , 0 )'!
   **/
  inline int get_number_of_cell_problem(EntityPointerType& ent) const {
    auto it = cell_numbering_map_NL_.find(ent);
    if (it != cell_numbering_map_NL_.end() )
      return it->second;
    else
      DUNE_THROW(Dune::RangeError, "no number for entity");
  }
};
} //namespace Dune {
#endif // DUNEMS_HMM_CELL_NUMBERING_HH
<|endoftext|>


<commit_before>#include <iostream>
#include <string>
#include <vector>
#include <algorithm>
#include <cmath>
#include <cstdlib>
#define PI 3.14159265
#define SMALL_NUMBER 1e-5

using namespace std;
const string notAValidShape = "Not a valid Shape";

class Coord {
	public:
		float x, y;

	Coord (float a, float b) {
		x = a;
		y = b;
	}
};

bool areValuesInCloseProximity (float a, float b, float maxDiff) {
	return abs (a - b) < maxDiff;
}

float computeAngle (Coord mid, Coord left, Coord right) {
	const float deg = 180.0f / PI;

	// x values of 2 points are same, subtract a small number to the non-mid point to avoid divide-by-zero
	if (left.x == mid.x) {
		left.x -= SMALL_NUMBER;
	}

	if (right.x == mid.x) {
		right.x -= SMALL_NUMBER;
	}

	float gradML = (left.y - mid.y) / (left.x - mid.x),
		gradMR = (mid.y - right.y) / (mid.x - right.x);
	float eq = abs ((gradML - gradMR) / (1+(gradMR*gradML)));

	return atan (eq) * deg;
}

float computeEdgeLength (Coord a, Coord b) {
	float l1 = b.x - a.x, l2 = b.y - a.y;
	return sqrt ((l1*l1) + (l2*l2));
}

vector< float > getInteriorAngles (vector< Coord >& coords) {
	vector< float > angles = vector< float > ();
	const unsigned int numOfCoords = coords.size ();

	// First point is a special case, handle it differently
	// Since the last point on list is same as 1st point (to ensure closed shape), use second-last point
	// as the right point of the first point.
	angles.push_back (computeAngle(coords [0], coords [1], coords [numOfCoords - 2]));

	// For rest of points, take the point, take 1 before it & 1 after it & compute angle (after gradients)
	for (int i = 1; i < numOfCoords - 1; i++) {
		angles.push_back (computeAngle (coords [i], coords [i-1], coords [i+1]));
	}

	return angles;
}

string identifyTriangle (vector< Coord >& coords) {
	const string triangle = "Triangle";
	const vector< float > interiorAngles = getInteriorAngles (coords);
	const float error = 4.0f;
	unsigned int flags = 0;

	if (areValuesInCloseProximity (interiorAngles [0], interiorAngles [1], error)) {
		flags |= 1;
	}

	if (areValuesInCloseProximity (interiorAngles [0], interiorAngles [2], error)) {
		flags |= 2;
	}

	if (areValuesInCloseProximity (interiorAngles [1], interiorAngles [2], error)) {
		flags |= 4;
	}

	if (!flags) {
		return "Scalene " + triangle;
	}

	if (flags == 7) {
		return "Equilateral " + triangle;
	}

	return "Isoceles " + triangle;
}

string identifyQuadrilateral (vector< Coord >& coords) {
	const vector< float > interiorAngles = getInteriorAngles (coords);
	const float error = 4.0f;

	// step 1: check if all interior angles are same (90 degree)
	/*if (!areValuesInCloseProximity (interiorAngles [0], 90.0f, error)) {
		return notAValidShape;
	}*/
	cout << interiorAngles [0] << " " << interiorAngles [1] << " " << interiorAngles [2] << " " << interiorAngles [3] << endl;
	for (int i = 1; i < interiorAngles.size (); i++) {
		if (!areValuesInCloseProximity (interiorAngles [0], interiorAngles [i], error)) {
			return notAValidShape;
		}
	}

	// Step 2: Compute Aspect ratio to determine whether quad. is a square or rectangle
	const float firstEdgeLength = computeEdgeLength (coords [0], coords [1]),
		secondEdgeLength = computeEdgeLength (coords [1], coords [2]);

	if (areValuesInCloseProximity (firstEdgeLength, secondEdgeLength, 5.0f)) {
		return "Square";
	}

	return "Rectangle";
}

bool isRegularPentagon (vector< Coord >& coords) {
	const vector< float > interiorAngles = getInteriorAngles (coords);
	const float error = 4.0f;

	// step 1: check if all interior angles are same (90 degree)
	/*if (!areValuesInCloseProximity (interiorAngles [0], 90.0f, error)) {
		return notAValidShape;
	}*/

	for (int i = 1; i < interiorAngles.size (); i++) {
		if (!areValuesInCloseProximity (interiorAngles [0], interiorAngles [i], error)) {
			return false;
		}
	}

	return true;
}

bool isRegularHexagon (vector< Coord >& coords) {
	const vector< float > interiorAngles = getInteriorAngles (coords);
	const float error = 4.0f;

	// step 1: check if all interior angles are same (90 degree)
	/*if (!areValuesInCloseProximity (interiorAngles [0], 90.0f, error)) {
		return notAValidShape;
	}*/

	for (int i = 1; i < interiorAngles.size (); i++) {
		if (!areValuesInCloseProximity (interiorAngles [0], interiorAngles [i], error)) {
			return false;
		}
	}

	return true;
}

string detectShapeDecisionTree (vector< Coord >& coords) {
	switch (coords.size ()) {
		case 0: case 3:
			return notAValidShape;
		case 1:
			return "Point";
		case 2:
			return "Straight Line";
		case 4:
			return identifyTriangle (coords);
		case 5:
			return identifyQuadrilateral (coords);
		case 6:
			return (isRegularPentagon (coords) ? "Pentagon" : notAValidShape);
		case 7:
			return (isRegularHexagon (coords) ? "Hexagon" : notAValidShape);
		default:
			return "circle";
	}
}

int main () {
	vector< Coord > coords = vector< Coord > ();

	/* Pentagon
	coords.push_back (Coord (550,450));
	coords.push_back (Coord (455,519));
	coords.push_back (Coord (491,631));
	coords.push_back (Coord (609,631));
	coords.push_back (Coord (645,519));
	coords.push_back (Coord (550,450));
	*/

	/* Hexagon
	coords.push_back (Coord (600,463));
	coords.push_back (Coord (500,463));
	coords.push_back (Coord (450,550));
	coords.push_back (Coord (500,637));
	coords.push_back (Coord (600,637));
	coords.push_back (Coord (650,550));
	coords.push_back (Coord (600,463));
	*/

	/* Quadrilateral
	coords.push_back (Coord (200,200));
	coords.push_back (Coord (500,200));
	coords.push_back (Coord (500,330));
	coords.push_back (Coord (200,330));
	coords.push_back (Coord (200,200));
	*/

	coords.push_back (Coord (550,450));
	coords.push_back (Coord (463,600));
	coords.push_back (Coord (637,600));
	coords.push_back (Coord (550,450));

	cout << detectShapeDecisionTree (coords) << endl;
}<commit_msg>add vatsal's code for opengl<commit_after>#include <string.h>
#include <GL/glut.h>
#include <GL/glu.h>
#include <GL/gl.h>
#include <iostream>
#include <string>
#include <vector>
#include <algorithm>
#include <cmath>
#include <cstdlib>
#define PI 3.14159265
#define SMALL_NUMBER 1e-5

using namespace std;

/*********************************************************************************/
const string notAValidShape = "Not a valid Shape";

class Coord {
	public:
		float x, y;

	Coord (float a, float b) {
		x = a;
		y = b;
	}

	Coord () {}
};

bool areValuesInCloseProximity (float a, float b, float maxDiff) {
	return abs (a - b) < maxDiff;
}

float computeAngle (Coord mid, Coord left, Coord right) {
	const float deg = 180.0f / PI;

	// x values of 2 points are same, subtract a small number to the non-mid point to avoid divide-by-zero
	if (left.x == mid.x) {
		left.x -= SMALL_NUMBER;
	}

	if (right.x == mid.x) {
		right.x -= SMALL_NUMBER;
	}

	float gradML = (left.y - mid.y) / (left.x - mid.x),
		gradMR = (mid.y - right.y) / (mid.x - right.x);
	float eq = abs ((gradML - gradMR) / (1+(gradMR*gradML)));

	return atan (eq) * deg;
}

float computeEdgeLength (Coord a, Coord b) {
	float l1 = b.x - a.x, l2 = b.y - a.y;
	return sqrt ((l1*l1) + (l2*l2));
}

vector< float > getInteriorAngles (vector< Coord >& coords) {
	vector< float > angles = vector< float > ();
	const unsigned int numOfCoords = coords.size ();

	// First point is a special case, handle it differently
	// Since the last point on list is same as 1st point (to ensure closed shape), use second-last point
	// as the right point of the first point.
	angles.push_back (computeAngle(coords [0], coords [1], coords [numOfCoords - 2]));

	// For rest of points, take the point, take 1 before it & 1 after it & compute angle (after gradients)
	for (int i = 1; i < numOfCoords - 1; i++) {
		angles.push_back (computeAngle (coords [i], coords [i-1], coords [i+1]));
	}

	return angles;
}

string identifyTriangle (vector< Coord >& coords) {
	const string triangle = "Triangle";
	const vector< float > interiorAngles = getInteriorAngles (coords);
	const float error = 10.0f;
	unsigned int flags = 0;

	if (areValuesInCloseProximity (interiorAngles [0], interiorAngles [1], error)) {
		flags |= 1;
	}

	if (areValuesInCloseProximity (interiorAngles [0], interiorAngles [2], error)) {
		flags |= 2;
	}

	if (areValuesInCloseProximity (interiorAngles [1], interiorAngles [2], error)) {
		flags |= 4;
	}

	if (!flags) {
		return "Scalene " + triangle;
	}

	if (flags == 7) {
		return "Equilateral " + triangle;
	}

	return "Isoceles " + triangle;
}

string identifyQuadrilateral (vector< Coord >& coords) {
	const vector< float > interiorAngles = getInteriorAngles (coords);
	const float error = 4.0f;

	// step 1: check if all interior angles are same (90 degree)
	/*if (!areValuesInCloseProximity (interiorAngles [0], 90.0f, error)) {
		return notAValidShape;
	}*/

	for (int i = 1; i < interiorAngles.size (); i++) {
		if (!areValuesInCloseProximity (interiorAngles [0], interiorAngles [i], error)) {
			return notAValidShape;
		}
	}

	// Step 2: Compute Aspect ratio to determine whether quad. is a square or rectangle
	const float firstEdgeLength = computeEdgeLength (coords [0], coords [1]),
		secondEdgeLength = computeEdgeLength (coords [1], coords [2]);

	if (areValuesInCloseProximity (firstEdgeLength, secondEdgeLength, 5.0f)) {
		return "Square";
	}

	return "Rectangle";
}

bool isRegularPentagon (vector< Coord >& coords) {
	const vector< float > interiorAngles = getInteriorAngles (coords);
	const float error = 4.0f;

	// step 1: check if all interior angles are same (90 degree)
	/*if (!areValuesInCloseProximity (interiorAngles [0], 90.0f, error)) {
		return notAValidShape;
	}*/

	for (int i = 1; i < interiorAngles.size (); i++) {
		if (!areValuesInCloseProximity (interiorAngles [0], interiorAngles [i], error)) {
			return false;
		}
	}

	return true;
}

bool isRegularHexagon (vector< Coord >& coords) {
	const vector< float > interiorAngles = getInteriorAngles (coords);
	const float error = 4.0f;

	// step 1: check if all interior angles are same (90 degree)
	/*if (!areValuesInCloseProximity (interiorAngles [0], 90.0f, error)) {
		return notAValidShape;
	}*/

	for (int i = 1; i < interiorAngles.size (); i++) {
		if (!areValuesInCloseProximity (interiorAngles [0], interiorAngles [i], error)) {
			return false;
		}
	}

	return true;
}

string detectShapeDecisionTree (vector< Coord >& coords) {
	switch (coords.size ()) {
		case 0: case 3:
			return notAValidShape;
		case 1:
			return "Point";
		case 2:
			return "Straight Line";
		case 4:
			return identifyTriangle (coords);
		case 5:
			return identifyQuadrilateral (coords);
		case 6:
			return (isRegularPentagon (coords) ? "Pentagon" : notAValidShape);
		case 7:
			return (isRegularHexagon (coords) ? "Hexagon" : notAValidShape);
		default:
			return "circle";
	}
}

/*********************************************************************************/

Coord w;
Coord s;

vector< Coord > coords = vector< Coord > ();
int mouseClickFlag = 0,userFlag=0,finalcoords;
/* Initialize OpenGL Graphics */
void initGL() {
   glClearColor(0.0,1.0,1.0,0);
	glColor3f(0.0,0.0,0.0);
	gluOrtho2D(0 , 640 , 0 , 480);
}

void displayText( float x, float y, int r, int g, int b, const char *string ) {
	int j = strlen( string );

	glColor3f( r, g, b );
	glRasterPos2f( x, y );
	for( int i = 0; i < j; i++ ) {
		glutBitmapCharacter( GLUT_BITMAP_TIMES_ROMAN_24, string[i] );
	}
	glFlush();
}
void lineDraw(Coord p, Coord q){
	glEnable(GL_LINE_SMOOTH);
	glLineWidth(2.5);
	glColor3f(0.0,0.0,0.0);
	glBegin(GL_LINES);
	glVertex2f(p.x,p.y);
	glVertex2f(q.x,q.y);
	glEnd();
	glFlush();
}

void onMouseClickCallback(int button, int state, int x, int y) {
if(userFlag==1){
    if(button == GLUT_LEFT_BUTTON && state == GLUT_DOWN) {
    		y = 480 - y;
		Coord mycoord = Coord(x,y);
		coords.push_back(mycoord);
		cout<<mycoord.x<<" "<<mycoord.y<<"\n";
		cout<<coords[0].x<<" "<<coords[0].y;
		glPointSize(5);
		glColor3f(1.0,0.0,0.0);
		glBegin(GL_POINTS);
		glVertex2d(x, y);
		glEnd();
		glFlush();
		switch(mouseClickFlag){
			case 0: mouseClickFlag=1;
				w.x=x;
				w.y=y;
				break;
			case 1: mouseClickFlag=2;
				s.x=x;
				s.y=y;
				lineDraw(w,s);
				break;
			case 2: w.x=s.x;
				w.y=s.y;
				s.x=x;
				s.y=y;
				mouseClickFlag=2;
				lineDraw(w,s);
				break;

		}

	}
}
else
{}
}

void keyboard(unsigned char key, int x, int y)
{
	if (key == 32) {
	if(userFlag == 0)
	{
		glClear(GL_COLOR_BUFFER_BIT);
		glutSwapBuffers();
		userFlag=1;

	} else if(userFlag==1){
	glClear(GL_COLOR_BUFFER_BIT);
	glutSwapBuffers();
	finalcoords = coords.size();
	coords[finalcoords-1].x=coords[0].x;
	coords[finalcoords-1].y=coords[0].y;

	cout << endl << "*********THE SHAPE IS**********" << endl << detectShapeDecisionTree (coords) << endl;

	}
	}

}

void display() {
   glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // Clear color and depth buffers
   glMatrixMode(GL_MODELVIEW);     // To operate on model-view matrix
   displayText(220,450,0,0,0,"Mini Project in OpenGL");
   displayText(265,430,0,0,0,"on the topic");
   displayText(185,410,0,0,0,"Shape Detection - Open Challenge");
   displayText(225,370,0,0,0,"under the guidance of");
   displayText(235,340,0,0,0,"Mr. Pankaj Badoni");
   displayText(225,320,0,0,0,"(Assistant Proffessor)");
   displayText(135,300,0,0,0,"School of Computer Science and Engineering");
   displayText(255,210,0,0,0,"Submitted by");
   displayText(120,160,0,0,0,"Vatsal Jain");
   displayText(400,160,0,0,0,"Raghav Dua");

}

int main(int argc, char** argv) {
   Coord w;
   Coord s;
   glutInit(&argc, argv);            // Initialize GLUT
   glutInitDisplayMode(GLUT_SINGLE); // Enable single buffered mode
   glutInitWindowSize(640, 480);   // Set the window's initial width & height
   glutInitWindowPosition(100, 100); // Position the window's initial top-left corner
   glutCreateWindow("Object Guessing Algorithm");          // Create window with the given title
   glutDisplayFunc(display);       // Register callback handler for window re-paint event
   glutKeyboardFunc(keyboard);
   glutMouseFunc(onMouseClickCallback);
   initGL();                       // Our own OpenGL initialization
   glutMainLoop();                 // Enter the infinite event-processing loop
   return 0;
}

/*
int main () {
	vector< Coord > coords = vector< Coord > ();

	/* Pentagon
	coords.push_back (Coord (550,450));
	coords.push_back (Coord (455,519));
	coords.push_back (Coord (491,631));
	coords.push_back (Coord (609,631));
	coords.push_back (Coord (645,519));
	coords.push_back (Coord (550,450));
	*

	/* Hexagon
	coords.push_back (Coord (600,463));
	coords.push_back (Coord (500,463));
	coords.push_back (Coord (450,550));
	coords.push_back (Coord (500,637));
	coords.push_back (Coord (600,637));
	coords.push_back (Coord (650,550));
	coords.push_back (Coord (600,463));
	*

	/* Quadrilateral
	coords.push_back (Coord (200,200));
	coords.push_back (Coord (500,200));
	coords.push_back (Coord (500,330));
	coords.push_back (Coord (200,330));
	coords.push_back (Coord (200,200));
	*

	coords.push_back (Coord (550,450));
	coords.push_back (Coord (463,600));
	coords.push_back (Coord (637,600));
	coords.push_back (Coord (550,450));

	cout << detectShapeDecisionTree (coords) << endl;
}
*/<|endoftext|>


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

#include <celero/Statistics.h>
#include <celero/PimplImpl.h>

#include <algorithm>
#include <cmath>
#include <limits>

using namespace celero;

class Statistics::Impl
{
	public:
		Impl() :
			sampleSize(0),
			M1(0),
			M2(0),
			M3(0),
			M4(0),
			min(std::numeric_limits<decltype(Impl::min)>::max()),
			max(std::numeric_limits<decltype(Impl::max)>::min())
		{
		}

		explicit Impl(const Statistics& other) :
			sampleSize(other.pimpl->sampleSize),
			M1(other.pimpl->M1),
			M2(other.pimpl->M2),
			M3(other.pimpl->M3),
			M4(other.pimpl->M4),
			min(other.pimpl->min),
			max(other.pimpl->max)
		{
		}

		size_t sampleSize;
		double M1;
		double M2;
		double M3;
		double M4;
		uint64_t min;
		uint64_t max;
};

Statistics::Statistics()
{
}

Statistics::Statistics(const Statistics& other) :
	pimpl(other)
{
}

Statistics::~Statistics()
{
}

Statistics Statistics::operator+(const Statistics& other)
{
	Statistics combined;

	combined.pimpl->sampleSize = this->pimpl->sampleSize + other.pimpl->sampleSize;

	const auto delta = other.pimpl->M1 - this->pimpl->M1;
	const auto delta2 = delta*delta;
	const auto delta3 = delta*delta2;
	const auto delta4 = delta2*delta2;

	combined.pimpl->M1 = (this->pimpl->sampleSize*this->pimpl->M1 + other.pimpl->sampleSize*other.pimpl->M1) / combined.pimpl->sampleSize;

	combined.pimpl->M2 = this->pimpl->M2 + other.pimpl->M2 +
		delta2 * this->pimpl->sampleSize * other.pimpl->sampleSize / combined.pimpl->sampleSize;

	combined.pimpl->M3 = this->pimpl->M3 + other.pimpl->M3 +
		delta3 * this->pimpl->sampleSize * other.pimpl->sampleSize * (this->pimpl->sampleSize - other.pimpl->sampleSize)/(combined.pimpl->sampleSize*combined.pimpl->sampleSize);

	combined.pimpl->M3 += 3.0*delta * (this->pimpl->sampleSize*other.pimpl->M2 - other.pimpl->sampleSize*this->pimpl->M2) / combined.pimpl->sampleSize;

	combined.pimpl->M4 = this->pimpl->M4 + other.pimpl->M4 + delta4*this->pimpl->sampleSize*other.pimpl->sampleSize * (this->pimpl->sampleSize*this->pimpl->sampleSize - this->pimpl->sampleSize*other.pimpl->sampleSize + other.pimpl->sampleSize*other.pimpl->sampleSize) /
		(combined.pimpl->sampleSize*combined.pimpl->sampleSize*combined.pimpl->sampleSize);

	combined.pimpl->M4 += 6.0*delta2 * (this->pimpl->sampleSize*this->pimpl->sampleSize*other.pimpl->M2 + other.pimpl->sampleSize*other.pimpl->sampleSize*this->pimpl->M2)/(combined.pimpl->sampleSize*combined.pimpl->sampleSize) +
		4.0*delta*(this->pimpl->sampleSize*other.pimpl->M3 - other.pimpl->sampleSize*this->pimpl->M3) / combined.pimpl->sampleSize;

	return combined;
}

Statistics& Statistics::operator=(const Statistics& other)
{
	this->pimpl->sampleSize = other.pimpl->sampleSize;
	this->pimpl->M1 = other.pimpl->M1;
	this->pimpl->M2 = other.pimpl->M2;
	this->pimpl->M3 = other.pimpl->M3;
	this->pimpl->M4 = other.pimpl->M4;
	this->pimpl->min = other.pimpl->min;
	this->pimpl->max = other.pimpl->max;

	return *this;
}

Statistics& Statistics::operator+=(const Statistics& other)
{
	const auto combined = *this + other;
	*this = combined;
	return *this;
}

///
/// Resets all accumulated statistics.
///
void Statistics::reset()
{
	this->pimpl->sampleSize = 0;
	this->pimpl->M1 = 0;
	this->pimpl->M2 = 0;
	this->pimpl->M3 = 0;
	this->pimpl->M4 = 0;
	this->pimpl->min = std::numeric_limits<decltype(this->pimpl->min)>::max();
	this->pimpl->max = std::numeric_limits<decltype(this->pimpl->max)>::min();
}

///
/// Adds a statistical sample.
///
void Statistics::addSample(uint64_t x)
{
	const auto n1 = this->pimpl->sampleSize;
	this->pimpl->sampleSize++;

	const auto delta = x - this->pimpl->M1;
	const auto delta_n = delta / this->pimpl->sampleSize;
	const auto delta_n2 = delta_n * delta_n;
	const auto term1 = delta * delta_n * n1;

	this->pimpl->M1 += delta_n;
	this->pimpl->M4 += term1 * delta_n2 * (this->pimpl->sampleSize*this->pimpl->sampleSize - 3*this->pimpl->sampleSize + 3) + 6 * delta_n2 * this->pimpl->M2 - 4 * delta_n * this->pimpl->M3;
	this->pimpl->M3 += term1 * delta_n * (this->pimpl->sampleSize - 2) - 3 * delta_n * this->pimpl->M2;
	this->pimpl->M2 += term1;

	this->pimpl->min = std::min(this->pimpl->min, x);
	this->pimpl->max = std::max(this->pimpl->max, x);
}

size_t Statistics::getSize() const
{
	return this->pimpl->sampleSize;
}

double Statistics::getMean() const
{
	return this->pimpl->M1;
}

double Statistics::getVariance() const
{
	if(this->pimpl->sampleSize > 1)
	{
		return this->pimpl->M2/(this->pimpl->sampleSize-1);
	}

	return 0.0;
}

double Statistics::getStandardDeviation() const
{
	return std::sqrt(this->getVariance());
}

double Statistics::getSkewness() const
{
	if(this->pimpl->sampleSize > 2)
	{
		return sqrt(this->pimpl->sampleSize) * this->pimpl->M3/pow(this->pimpl->M2, 1.5);
	}

	return 0.0;
}

double Statistics::getKurtosis() const
{
	if(this->pimpl->sampleSize > 3)
	{
		if(this->pimpl->M2 != 0)
		{
			return this->pimpl->sampleSize*this->pimpl->M4 / (this->pimpl->M2*this->pimpl->M2) - 3.0;
		}
	}

	return 0.0;
}

double Statistics::getZScore() const
{
	const auto sd = this->getStandardDeviation();

	if(sd != 0.0)
	{
		auto mean = this->getMean();
		auto hypothesis = static_cast<double>(this->getMin());
		return (mean - hypothesis)/sd;
	}

	return 0.0;
}

uint64_t Statistics::getMin() const
{
	return this->pimpl->min;
}

uint64_t Statistics::getMax() const
{
	return this->pimpl->max;
}
<commit_msg>Adding <algorithm> header for VS2013 compilation.<commit_after>///
/// \author	John Farrier
///
/// \copyright Copyright 2014 John Farrier
///
/// Licensed under the Apache License, Version 2.0 (the "License");
/// you may not use this file except in compliance with the License.
/// You may obtain a copy of the License at
///
/// http://www.apache.org/licenses/LICENSE-2.0
///
/// Unless required by applicable law or agreed to in writing, software
/// distributed under the License is distributed on an "AS IS" BASIS,
/// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
/// See the License for the specific language governing permissions and
/// limitations under the License.
///

#include <celero/Statistics.h>
#include <celero/PimplImpl.h>

#include <algorithm>
#include <cmath>
#include <limits>
#include <algorithm>

using namespace celero;

class Statistics::Impl
{
	public:
		Impl() :
			sampleSize(0),
			M1(0),
			M2(0),
			M3(0),
			M4(0),
			min(std::numeric_limits<decltype(Impl::min)>::max()),
			max(std::numeric_limits<decltype(Impl::max)>::min())
		{
		}

		explicit Impl(const Statistics& other) :
			sampleSize(other.pimpl->sampleSize),
			M1(other.pimpl->M1),
			M2(other.pimpl->M2),
			M3(other.pimpl->M3),
			M4(other.pimpl->M4),
			min(other.pimpl->min),
			max(other.pimpl->max)
		{
		}

		size_t sampleSize;
		double M1;
		double M2;
		double M3;
		double M4;
		uint64_t min;
		uint64_t max;
};

Statistics::Statistics()
{
}

Statistics::Statistics(const Statistics& other) :
	pimpl(other)
{
}

Statistics::~Statistics()
{
}

Statistics Statistics::operator+(const Statistics& other)
{
	Statistics combined;

	combined.pimpl->sampleSize = this->pimpl->sampleSize + other.pimpl->sampleSize;

	const auto delta = other.pimpl->M1 - this->pimpl->M1;
	const auto delta2 = delta*delta;
	const auto delta3 = delta*delta2;
	const auto delta4 = delta2*delta2;

	combined.pimpl->M1 = (this->pimpl->sampleSize*this->pimpl->M1 + other.pimpl->sampleSize*other.pimpl->M1) / combined.pimpl->sampleSize;

	combined.pimpl->M2 = this->pimpl->M2 + other.pimpl->M2 +
		delta2 * this->pimpl->sampleSize * other.pimpl->sampleSize / combined.pimpl->sampleSize;

	combined.pimpl->M3 = this->pimpl->M3 + other.pimpl->M3 +
		delta3 * this->pimpl->sampleSize * other.pimpl->sampleSize * (this->pimpl->sampleSize - other.pimpl->sampleSize)/(combined.pimpl->sampleSize*combined.pimpl->sampleSize);

	combined.pimpl->M3 += 3.0*delta * (this->pimpl->sampleSize*other.pimpl->M2 - other.pimpl->sampleSize*this->pimpl->M2) / combined.pimpl->sampleSize;

	combined.pimpl->M4 = this->pimpl->M4 + other.pimpl->M4 + delta4*this->pimpl->sampleSize*other.pimpl->sampleSize * (this->pimpl->sampleSize*this->pimpl->sampleSize - this->pimpl->sampleSize*other.pimpl->sampleSize + other.pimpl->sampleSize*other.pimpl->sampleSize) /
		(combined.pimpl->sampleSize*combined.pimpl->sampleSize*combined.pimpl->sampleSize);

	combined.pimpl->M4 += 6.0*delta2 * (this->pimpl->sampleSize*this->pimpl->sampleSize*other.pimpl->M2 + other.pimpl->sampleSize*other.pimpl->sampleSize*this->pimpl->M2)/(combined.pimpl->sampleSize*combined.pimpl->sampleSize) +
		4.0*delta*(this->pimpl->sampleSize*other.pimpl->M3 - other.pimpl->sampleSize*this->pimpl->M3) / combined.pimpl->sampleSize;

	return combined;
}

Statistics& Statistics::operator=(const Statistics& other)
{
	this->pimpl->sampleSize = other.pimpl->sampleSize;
	this->pimpl->M1 = other.pimpl->M1;
	this->pimpl->M2 = other.pimpl->M2;
	this->pimpl->M3 = other.pimpl->M3;
	this->pimpl->M4 = other.pimpl->M4;
	this->pimpl->min = other.pimpl->min;
	this->pimpl->max = other.pimpl->max;

	return *this;
}

Statistics& Statistics::operator+=(const Statistics& other)
{
	const auto combined = *this + other;
	*this = combined;
	return *this;
}

///
/// Resets all accumulated statistics.
///
void Statistics::reset()
{
	this->pimpl->sampleSize = 0;
	this->pimpl->M1 = 0;
	this->pimpl->M2 = 0;
	this->pimpl->M3 = 0;
	this->pimpl->M4 = 0;
	this->pimpl->min = std::numeric_limits<decltype(this->pimpl->min)>::max();
	this->pimpl->max = std::numeric_limits<decltype(this->pimpl->max)>::min();
}

///
/// Adds a statistical sample.
///
void Statistics::addSample(uint64_t x)
{
	const auto n1 = this->pimpl->sampleSize;
	this->pimpl->sampleSize++;

	const auto delta = x - this->pimpl->M1;
	const auto delta_n = delta / this->pimpl->sampleSize;
	const auto delta_n2 = delta_n * delta_n;
	const auto term1 = delta * delta_n * n1;

	this->pimpl->M1 += delta_n;
	this->pimpl->M4 += term1 * delta_n2 * (this->pimpl->sampleSize*this->pimpl->sampleSize - 3*this->pimpl->sampleSize + 3) + 6 * delta_n2 * this->pimpl->M2 - 4 * delta_n * this->pimpl->M3;
	this->pimpl->M3 += term1 * delta_n * (this->pimpl->sampleSize - 2) - 3 * delta_n * this->pimpl->M2;
	this->pimpl->M2 += term1;

	this->pimpl->min = std::min(this->pimpl->min, x);
	this->pimpl->max = std::max(this->pimpl->max, x);
}

size_t Statistics::getSize() const
{
	return this->pimpl->sampleSize;
}

double Statistics::getMean() const
{
	return this->pimpl->M1;
}

double Statistics::getVariance() const
{
	if(this->pimpl->sampleSize > 1)
	{
		return this->pimpl->M2/(this->pimpl->sampleSize-1);
	}

	return 0.0;
}

double Statistics::getStandardDeviation() const
{
	return std::sqrt(this->getVariance());
}

double Statistics::getSkewness() const
{
	if(this->pimpl->sampleSize > 2)
	{
		return sqrt(this->pimpl->sampleSize) * this->pimpl->M3/pow(this->pimpl->M2, 1.5);
	}

	return 0.0;
}

double Statistics::getKurtosis() const
{
	if(this->pimpl->sampleSize > 3)
	{
		if(this->pimpl->M2 != 0)
		{
			return this->pimpl->sampleSize*this->pimpl->M4 / (this->pimpl->M2*this->pimpl->M2) - 3.0;
		}
	}

	return 0.0;
}

double Statistics::getZScore() const
{
	const auto sd = this->getStandardDeviation();

	if(sd != 0.0)
	{
		auto mean = this->getMean();
		auto hypothesis = static_cast<double>(this->getMin());
		return (mean - hypothesis)/sd;
	}

	return 0.0;
}

uint64_t Statistics::getMin() const
{
	return this->pimpl->min;
}

uint64_t Statistics::getMax() const
{
	return this->pimpl->max;
}
<|endoftext|>


<commit_before>#include <stingray/toolkit/regex.h>

#ifdef PLATFORM_POSIX
#	include <regex.h>
#else
#	warning No regex support on nonposix systems!
#endif

#include <stingray/toolkit/StringUtils.h>
#include <stingray/toolkit/exception.h>
#include <stingray/toolkit/variant.h>

namespace stingray
{

	struct RegexMatch
	{
		int	Begin;
		int	End;

		RegexMatch() : Begin(0), End(0) { }

		int GetLength() const
		{
			int len = End - Begin;
			TOOLKIT_CHECK(len > 0, "Submatch length is negative!");
			return len;
		}

		std::string ToString() const { return StringBuilder() % "(" % Begin % ", " % End % ")"; }
	};

	typedef std::vector<RegexMatch>						RegexMatchVec;

	typedef variant<TypeList<std::string, int>::type>	ReplacementEntry;
	typedef std::vector<ReplacementEntry>				ReplacementEntryVec;

	class ReplacementEntryVisitor : public static_visitor<std::string>
	{
	private:
		const char*				_srcString;
		const RegexMatchVec&	_matches;

	public:
		ReplacementEntryVisitor(const char* srcString, const RegexMatchVec& matches)
			: _srcString(srcString), _matches(matches)
		{ }

		std::string operator () (int matchNumber) const
		{
			int i = matchNumber;
			TOOLKIT_CHECK(i >= 0 && i < (int)_matches.size(), IndexOutOfRangeException(i, _matches.size()));
			std::string res = std::string(_srcString + _matches[i].Begin, _matches[i].GetLength());
			return res;
		}

		std::string operator () (const std::string& str) const
		{ return str; }
	};

	template < typename PlatformRegex >
	class BasicRegexImpl : public PlatformRegex
	{
	public:
		BasicRegexImpl(const std::string& str)
			: PlatformRegex(str)
		{ }

		bool Search(const std::string& str, smatch& m, regex_constants::match_flag_type flags)
		{
			TOOLKIT_CHECK(flags == regex_constants::match_default, NotImplementedException());

			RegexMatchVec matches;
			if (!this->DoMatch(str.c_str(), matches))
				return false;

			for (size_t i = 0; i < matches.size(); ++i)
			{
				RegexMatch& submatch = matches[i];
				m._results.push_back(str.substr(submatch.Begin, submatch.GetLength()));
				m._positions.push_back(submatch.Begin);
			}
			return true;
		}

		std::string Replace(const std::string& str, const regex& re, const std::string& replacement, regex_constants::match_flag_type flags)
		{
			TOOLKIT_CHECK((flags & ~regex_constants::format_first_only) == 0, NotImplementedException());

			ReplacementEntryVec replacement_entries;
			PlatformRegex group_regex("\\\\(\\d+)"); // TODO: cache this somewhere
			RegexMatchVec group_matches;

			size_t replacement_begin = 0;
			do
			{
				if (!group_regex.DoMatch(replacement.c_str() + replacement_begin, group_matches))
				{
					if (replacement_begin < replacement.size())
						replacement_entries.push_back(replacement.substr(replacement_begin));
					break;
				}

				if (group_matches[0].Begin > 0)
					replacement_entries.push_back(replacement.substr(replacement_begin, group_matches[0].Begin));
				replacement_entries.push_back(FromString<int>(replacement.substr(group_matches[1].Begin, group_matches[1].GetLength())));
				replacement_begin += group_matches[0].End;
			} while (true);

			int begin = 0;
			std::string result;

			RegexMatchVec matches;
			do
			{
				if (!this->DoMatch(str.c_str() + begin, matches))
				{
					result += str.substr(begin);
					break;
				}

				ReplacementEntryVisitor visitor(str.c_str() + begin, matches);

				result += str.substr(begin, matches[0].Begin);
				for (ReplacementEntryVec::const_iterator it = replacement_entries.begin(); it != replacement_entries.end(); ++it)
					result += apply_visitor(visitor, *it);
				begin += matches[0].End;
			} while (true);

			return result;
		}
	};

#ifdef PLATFORM_POSIX
	class PosixRegexImpl
	{
	private:
		std::string	_str;
		regex_t		_regex;

	public:
		PosixRegexImpl(const std::string& str)
			: _str(str)
		{
			ReplaceAll(_str, "\\d", "[0-9]");

			int ret = regcomp(&_regex, _str.c_str(), REG_EXTENDED);
			TOOLKIT_CHECK(ret == 0, StringBuilder() % "Could not compile regex '" % _str % "', ret = " % ret % "\n" % GetRegexError(_regex, ret));
		}

		~PosixRegexImpl()
		{ regfree(&_regex); }

		bool DoMatch(const char* str, RegexMatchVec& matches) const
		{
			std::vector<regmatch_t> posix_matches(32);
			int ret = regexec(&_regex, str, posix_matches.size(), posix_matches.data(), 0);

			if (ret == REG_NOMATCH)
				return false;

			if (ret != 0)
				TOOLKIT_THROW(StringBuilder() % "Could not execute regex '" % _str % "' for string '" % str % "', ret = " % ret % "\n" % GetRegexError(_regex, ret));

			int count = 0;
			while (posix_matches[count].rm_so > 0)
				++count;

			matches.resize(count);
			for (int i = 0; i < count; ++i)
			{
				matches[i].Begin = posix_matches[i].rm_so;
				matches[i].End = posix_matches[i].rm_eo;
			}
			return true;
		}

	private:
		static std::string GetRegexError(const regex_t& regex, int errCode)
		{
			std::string result(256, '~');
			result.resize(regerror(errCode, &regex, &result[0], result.size()));
			return result;
		}
	};

	typedef PosixRegexImpl	PlatformRegexImpl;
#endif

	class regex::Impl : public BasicRegexImpl<PlatformRegexImpl>
	{
	public:
		Impl(const std::string& str) : BasicRegexImpl<PlatformRegexImpl>(str) { }
	};

	regex::regex(const std::string& str)
		: _impl(new Impl(str))
	{ }

	regex::regex(const regex& other)
		: _impl(other._impl)
	{ }

	regex::~regex()
	{ }

	regex& regex::operator = (const regex& other)
	{
		_impl = other._impl;
		return *this;
	}

	bool regex_search(const std::string& str, smatch& m, const regex& re, regex_constants::match_flag_type flags)
	{
		return re._impl->Search(str, m, flags);
	}

	std::string regex_replace(const std::string& str, const regex& re, const std::string& replacement, regex_constants::match_flag_type flags)
	{
		return re._impl->Replace(str, re, replacement, flags);
	}

}
<commit_msg>fixed regex.cpp<commit_after>#include <stingray/toolkit/regex.h>

#ifdef PLATFORM_POSIX
#	include <regex.h>
#else
#	warning No regex support on nonposix systems!
#endif

#include <stingray/toolkit/StringUtils.h>
#include <stingray/toolkit/exception.h>
#include <stingray/toolkit/variant.h>

namespace stingray
{

	struct RegexMatch
	{
		int	Begin;
		int	End;

		RegexMatch() : Begin(0), End(0) { }

		int GetLength() const
		{
			int len = End - Begin;
			TOOLKIT_CHECK(len > 0, "Submatch length is negative!");
			return len;
		}

		std::string ToString() const { return StringBuilder() % "(" % Begin % ", " % End % ")"; }
	};

	typedef std::vector<RegexMatch>						RegexMatchVec;

	typedef variant<TypeList<std::string, int>::type>	ReplacementEntry;
	typedef std::vector<ReplacementEntry>				ReplacementEntryVec;

	class ReplacementEntryVisitor : public static_visitor<std::string>
	{
	private:
		const char*				_srcString;
		const RegexMatchVec&	_matches;

	public:
		ReplacementEntryVisitor(const char* srcString, const RegexMatchVec& matches)
			: _srcString(srcString), _matches(matches)
		{ }

		std::string operator () (int matchNumber) const
		{
			int i = matchNumber;
			TOOLKIT_CHECK(i >= 0 && i < (int)_matches.size(), IndexOutOfRangeException(i, _matches.size()));
			std::string res = std::string(_srcString + _matches[i].Begin, _matches[i].GetLength());
			return res;
		}

		std::string operator () (const std::string& str) const
		{ return str; }
	};

	template < typename PlatformRegex >
	class BasicRegexImpl : public PlatformRegex
	{
	public:
		BasicRegexImpl(const std::string& str)
			: PlatformRegex(str)
		{ }

		bool Search(const std::string& str, smatch& m, regex_constants::match_flag_type flags)
		{
			m._results.clear();
			m._positions.clear();

			TOOLKIT_CHECK(flags == regex_constants::match_default, NotImplementedException());

			RegexMatchVec matches;
			if (!this->DoMatch(str.c_str(), matches))
				return false;

			for (size_t i = 0; i < matches.size(); ++i)
			{
				RegexMatch& submatch = matches[i];
				m._results.push_back(str.substr(submatch.Begin, submatch.GetLength()));
				m._positions.push_back(submatch.Begin);
			}
			return true;
		}

		std::string Replace(const std::string& str, const regex& re, const std::string& replacement, regex_constants::match_flag_type flags)
		{
			TOOLKIT_CHECK((flags & ~regex_constants::format_first_only) == 0, NotImplementedException());

			ReplacementEntryVec replacement_entries;
			PlatformRegex group_regex("\\\\(\\d+)"); // TODO: cache this somewhere
			RegexMatchVec group_matches;

			size_t replacement_begin = 0;
			do
			{
				if (!group_regex.DoMatch(replacement.c_str() + replacement_begin, group_matches))
				{
					if (replacement_begin < replacement.size())
						replacement_entries.push_back(replacement.substr(replacement_begin));
					break;
				}

				if (group_matches.at(0).Begin > 0)
					replacement_entries.push_back(replacement.substr(replacement_begin, group_matches.at(0).Begin));
				replacement_entries.push_back(FromString<int>(replacement.substr(group_matches.at(1).Begin, group_matches.at(1).GetLength())));
				replacement_begin += group_matches.at(0).End;
			} while (true);

			int begin = 0;
			std::string result;

			RegexMatchVec matches;
			do
			{
				if (!this->DoMatch(str.c_str() + begin, matches))
				{
					result += str.substr(begin);
					break;
				}

				ReplacementEntryVisitor visitor(str.c_str() + begin, matches);

				result += str.substr(begin, matches.at(0).Begin);
				for (ReplacementEntryVec::const_iterator it = replacement_entries.begin(); it != replacement_entries.end(); ++it)
					result += apply_visitor(visitor, *it);
				begin += matches.at(0).End;
			} while (true);

			return result;
		}
	};

#ifdef PLATFORM_POSIX
	class PosixRegexImpl
	{
	private:
		std::string	_str;
		regex_t		_regex;

	public:
		PosixRegexImpl(const std::string& str)
			: _str(str)
		{
			ReplaceAll(_str, "\\d", "[0-9]");

			int ret = regcomp(&_regex, _str.c_str(), REG_EXTENDED);
			TOOLKIT_CHECK(ret == 0, StringBuilder() % "Could not compile regex '" % _str % "', ret = " % ret % "\n" % GetRegexError(_regex, ret));
		}

		~PosixRegexImpl()
		{ regfree(&_regex); }

		bool DoMatch(const char* str, RegexMatchVec& matches) const
		{
			std::vector<regmatch_t> posix_matches(32);
			int ret = regexec(&_regex, str, posix_matches.size(), posix_matches.data(), 0);

			if (ret == REG_NOMATCH)
				return false;

			if (ret != 0)
				TOOLKIT_THROW(StringBuilder() % "Could not execute regex '" % _str % "' for string '" % str % "', ret = " % ret % "\n" % GetRegexError(_regex, ret));

			int count = 0;
			while (posix_matches[count].rm_so >= 0)
				++count;

			matches.resize(count);
			for (int i = 0; i < count; ++i)
			{
				matches[i].Begin = posix_matches[i].rm_so;
				matches[i].End = posix_matches[i].rm_eo;
			}
			return true;
		}

	private:
		static std::string GetRegexError(const regex_t& regex, int errCode)
		{
			std::string result(256, '~');
			result.resize(regerror(errCode, &regex, &result[0], result.size()));
			return result;
		}
	};

	typedef PosixRegexImpl	PlatformRegexImpl;
#endif

	class regex::Impl : public BasicRegexImpl<PlatformRegexImpl>
	{
	public:
		Impl(const std::string& str) : BasicRegexImpl<PlatformRegexImpl>(str) { }
	};

	regex::regex(const std::string& str)
		: _impl(new Impl(str))
	{ }

	regex::regex(const regex& other)
		: _impl(other._impl)
	{ }

	regex::~regex()
	{ }

	regex& regex::operator = (const regex& other)
	{
		_impl = other._impl;
		return *this;
	}

	bool regex_search(const std::string& str, smatch& m, const regex& re, regex_constants::match_flag_type flags)
	{
		return re._impl->Search(str, m, flags);
	}

	std::string regex_replace(const std::string& str, const regex& re, const std::string& replacement, regex_constants::match_flag_type flags)
	{
		return re._impl->Replace(str, re, replacement, flags);
	}

}
<|endoftext|>


<commit_before>// stl includes
#include <stdexcept>

// Qt includes
#include <QRgb>

// hyperion-remote includes
#include "JsonConnection.h"

JsonConnection::JsonConnection(const std::string & a, bool printJson) :
	_printJson(printJson),
	_socket()
{
	QString address(a.c_str());
	QStringList parts = address.split(":");
	if (parts.size() != 2)
	{
		throw std::runtime_error(QString("Wrong address: unable to parse address (%1)").arg(address).toStdString());
	}

	bool ok;
	uint16_t port = parts[1].toUShort(&ok);
	if (!ok)
	{
		throw std::runtime_error(QString("Wrong address: Unable to parse the port number (%1)").arg(parts[1]).toStdString());
	}

	_socket.connectToHost(parts[0], port);
	if (!_socket.waitForConnected())
	{
		throw std::runtime_error("Unable to connect to host");
	}

	std::cout << "Connected to " << a << std::endl;
}

JsonConnection::~JsonConnection()
{
	_socket.close();
}

void JsonConnection::setColor(std::vector<QColor> colors, int priority, int duration)
{
	std::cout << "Set color to " << colors[0].red() << " " << colors[0].green() << " " << colors[0].blue() << (colors.size() > 1 ? " + ..." : "") << std::endl;

	// create command
	Json::Value command;
	command["command"] = "color";
	command["priority"] = priority;
	Json::Value & rgbValue = command["color"];
	for (const QColor & color : colors)
	{
		rgbValue.append(color.red());
		rgbValue.append(color.green());
		rgbValue.append(color.blue());
	}
	if (duration > 0)
	{
		command["duration"] = duration;
	}

	// send command message
	Json::Value reply = sendMessage(command);

	// parse reply message
	parseReply(reply);
}

void JsonConnection::setImage(QImage image, int priority, int duration)
{
	std::cout << "Set image has size: " << image.width() << "x" << image.height() << std::endl;

	// ensure the image has RGB888 format
	image = image.convertToFormat(QImage::Format_ARGB32_Premultiplied);
	QByteArray binaryImage;
	binaryImage.reserve(image.width() * image.height() * 3);
	for (int i = 0; i < image.height(); ++i)
	{
		const QRgb * scanline = reinterpret_cast<const QRgb *>(image.scanLine(i));
		for (int j = 0; j < image.width(); ++j)
		{
			binaryImage.append((char) qRed(scanline[j]));
			binaryImage.append((char) qGreen(scanline[j]));
			binaryImage.append((char) qBlue(scanline[j]));
		}
	}
	const QByteArray base64Image = binaryImage.toBase64();

	// create command
	Json::Value command;
	command["command"] = "image";
	command["priority"] = priority;
	command["imagewidth"] = image.width();
	command["imageheight"] = image.height();
	command["imagedata"] = std::string(base64Image.data(), base64Image.size());
	if (duration > 0)
	{
		command["duration"] = duration;
	}

	// send command message
	Json::Value reply = sendMessage(command);

	// parse reply message
	parseReply(reply);
}

void JsonConnection::setEffect(const std::string &effectName, const std::string & effectArgs, int priority, int duration)
{
	std::cout << "Start effect " << effectName << std::endl;

	// create command
	Json::Value command;
	command["command"] = "effect";
	command["priority"] = priority;
	Json::Value & effect = command["effect"];
	effect["name"] = effectName;
	if (effectArgs.size() > 0)
	{
		Json::Reader reader;
		if (!reader.parse(effectArgs, effect["args"], false))
		{
			throw std::runtime_error("Error in effect arguments: " + reader.getFormattedErrorMessages());
		}
	}
	if (duration > 0)
	{
		command["duration"] = duration;
	}

	// send command message
	Json::Value reply = sendMessage(command);

	// parse reply message
	parseReply(reply);
}

QString JsonConnection::getServerInfo()
{
	std::cout << "Get server info" << std::endl;

	// create command
	Json::Value command;
	command["command"] = "serverinfo";

	// send command message
	Json::Value reply = sendMessage(command);

	// parse reply message
	if (parseReply(reply))
	{
		if (!reply.isMember("info") || !reply["info"].isObject())
		{
			throw std::runtime_error("No info available in result");
		}

		const Json::Value & info = reply["info"];
		return QString(info.toStyledString().c_str());
	}

	return QString();
}

void JsonConnection::clear(int priority)
{
	std::cout << "Clear priority channel " << priority << std::endl;

	// create command
	Json::Value command;
	command["command"] = "clear";
	command["priority"] = priority;

	// send command message
	Json::Value reply = sendMessage(command);

	// parse reply message
	parseReply(reply);
}

void JsonConnection::clearAll()
{
	std::cout << "Clear all priority channels" << std::endl;

	// create command
	Json::Value command;
	command["command"] = "clearall";

	// send command message
	Json::Value reply = sendMessage(command);

	// parse reply message
	parseReply(reply);
}

void JsonConnection::setTransform(std::string * transformId, double * saturation, double * value, double * saturationL, double * luminance, ColorTransformValues *threshold, ColorTransformValues *gamma, ColorTransformValues *blacklevel, ColorTransformValues *whitelevel)
{
	std::cout << "Set color transforms" << std::endl;

	// create command
	Json::Value command;
	command["command"] = "transform";
	Json::Value & transform = command["transform"];

	if (transformId != nullptr)
	{
		transform["id"] = *transformId;
	}

	if (saturation != nullptr)
	{
		transform["saturationGain"] = *saturation;
	}

	if (value != nullptr)
	{
		transform["valueGain"] = *value;
	}

	if (saturationL != nullptr)
	{
		transform["saturationLGain"] = *saturationL;
	}

	if (luminance != nullptr)
	{
		transform["luminanceGain"] = *luminance;
	}
	if (threshold != nullptr)
	{
		Json::Value & v = transform["threshold"];
		v.append(threshold->valueRed);
		v.append(threshold->valueGreen);
		v.append(threshold->valueBlue);
	}

	if (gamma != nullptr)
	{
		Json::Value & v = transform["gamma"];
		v.append(gamma->valueRed);
		v.append(gamma->valueGreen);
		v.append(gamma->valueBlue);
	}

	if (blacklevel != nullptr)
	{
		Json::Value & v = transform["blacklevel"];
		v.append(blacklevel->valueRed);
		v.append(blacklevel->valueGreen);
		v.append(blacklevel->valueBlue);
	}

	if (whitelevel != nullptr)
	{
		Json::Value & v = transform["whitelevel"];
		v.append(whitelevel->valueRed);
		v.append(whitelevel->valueGreen);
		v.append(whitelevel->valueBlue);
	}

	// send command message
	Json::Value reply = sendMessage(command);

	// parse reply message
	parseReply(reply);
}

void JsonConnection::setCorrection(std::string * correctionId, int * red, int * green, int * blue)
{
	std::cout << "Set color corrections" << std::endl;

	// create command
	Json::Value command;
	command["command"] = "correction";
	Json::Value & correction = command["correction"];

	if (correctionId != nullptr)
	{
		correction["id"] = *correctionId;
	}

	if (red != nullptr)
	{
		correction["red"] = *red;
	}

	if (green != nullptr)
	{
		correction["green"] = *green;
	}

	if (blue != nullptr)
	{
		correction["blue"] = *blue;
	}

	// send command message
	Json::Value reply = sendMessage(command);

	// parse reply message
	parseReply(reply);
}

void JsonConnection::setTemperature(std::string * temperatureId, int * red, int * green, int * blue)
{
	std::cout << "Set color temperature corrections" << std::endl;

	// create command
	Json::Value command;
	command["command"] = "temperature";
	Json::Value & temperature = command["temperature"];

	if (temperatureId != nullptr)
	{
		temperature["id"] = *temperatureId;
	}

	if (red != nullptr)
	{
		temperature["red"] = *red;
	}

	if (green != nullptr)
	{
		temperature["green"] = *green;
	}

	if (blue != nullptr)
	{
		temperature["blue"] = *blue;
	}

	// send command message
	Json::Value reply = sendMessage(command);

	// parse reply message
	parseReply(reply);
}

Json::Value JsonConnection::sendMessage(const Json::Value & message)
{
	// serialize message (FastWriter already appends a newline)
	std::string serializedMessage = Json::FastWriter().write(message);

	// print command if requested
	if (_printJson)
	{
		std::cout << "Command: " << serializedMessage;
	}

	// write message
	_socket.write(serializedMessage.c_str());
	if (!_socket.waitForBytesWritten())
	{
		throw std::runtime_error("Error while writing data to host");
	}

	// read reply data
	QByteArray serializedReply;
	while (!serializedReply.contains('\n'))
	{
		// receive reply
		if (!_socket.waitForReadyRead())
		{
			throw std::runtime_error("Error while reading data from host");
		}

		serializedReply += _socket.readAll();
	}
	int bytes = serializedReply.indexOf('\n') + 1;     // Find the end of message

	// print reply if requested
	if (_printJson)
	{
		std::cout << "Reply: " << std::string(serializedReply.data(), bytes);
	}

	// parse reply data
	Json::Reader jsonReader;
	Json::Value reply;
	if (!jsonReader.parse(serializedReply.constData(), serializedReply.constData() + bytes, reply))
	{
		throw std::runtime_error("Error while parsing reply: invalid json");
	}

	return reply;
}

bool JsonConnection::parseReply(const Json::Value &reply)
{
	bool success = false;
	std::string reason = "No error info";

	try
	{
		success = reply.get("success", false).asBool();
		if (!success)
			reason = reply.get("error", reason).asString();
	}
	catch (const std::runtime_error &)
	{
		// Some json parsing error: ignore and set parsing error
	}

	if (!success)
	{
		throw std::runtime_error("Error: " + reason);
	}

	return success;
}
<commit_msg>Update JsonConnection.cpp<commit_after>// stl includes
#include <stdexcept>

// Qt includes
#include <QRgb>

// hyperion-remote includes
#include "JsonConnection.h"

JsonConnection::JsonConnection(const std::string & a, bool printJson) :
	_printJson(printJson),
	_socket()
{
	QString address(a.c_str());
	QStringList parts = address.split(":");
	if (parts.size() != 2)
	{
		throw std::runtime_error(QString("Wrong address: unable to parse address (%1)").arg(address).toStdString());
	}

	bool ok;
	uint16_t port = parts[1].toUShort(&ok);
	if (!ok)
	{
		throw std::runtime_error(QString("Wrong address: Unable to parse the port number (%1)").arg(parts[1]).toStdString());
	}

	_socket.connectToHost(parts[0], port);
	if (!_socket.waitForConnected())
	{
		throw std::runtime_error("Unable to connect to host");
	}

	std::cout << "Connected to " << a << std::endl;
}

JsonConnection::~JsonConnection()
{
	_socket.close();
}

void JsonConnection::setColor(std::vector<QColor> colors, int priority, int duration)
{
	std::cout << "Set color to " << colors[0].red() << " " << colors[0].green() << " " << colors[0].blue() << (colors.size() > 1 ? " + ..." : "") << std::endl;

	// create command
	Json::Value command;
	command["command"] = "color";
	command["priority"] = priority;
	Json::Value & rgbValue = command["color"];
	for (const QColor & color : colors)
	{
		rgbValue.append(color.red());
		rgbValue.append(color.green());
		rgbValue.append(color.blue());
	}
	if (duration > 0)
	{
		command["duration"] = duration;
	}

	// send command message
	Json::Value reply = sendMessage(command);

	// parse reply message
	parseReply(reply);
}

void JsonConnection::setImage(QImage image, int priority, int duration)
{
	std::cout << "Set image has size: " << image.width() << "x" << image.height() << std::endl;

	// ensure the image has RGB888 format
	image = image.convertToFormat(QImage::Format_ARGB32_Premultiplied);
	QByteArray binaryImage;
	binaryImage.reserve(image.width() * image.height() * 3);
	for (int i = 0; i < image.height(); ++i)
	{
		const QRgb * scanline = reinterpret_cast<const QRgb *>(image.scanLine(i));
		for (int j = 0; j < image.width(); ++j)
		{
			binaryImage.append((char) qRed(scanline[j]));
			binaryImage.append((char) qGreen(scanline[j]));
			binaryImage.append((char) qBlue(scanline[j]));
		}
	}
	const QByteArray base64Image = binaryImage.toBase64();

	// create command
	Json::Value command;
	command["command"] = "image";
	command["priority"] = priority;
	command["imagewidth"] = image.width();
	command["imageheight"] = image.height();
	command["imagedata"] = std::string(base64Image.data(), base64Image.size());
	if (duration > 0)
	{
		command["duration"] = duration;
	}

	// send command message
	Json::Value reply = sendMessage(command);

	// parse reply message
	parseReply(reply);
}

void JsonConnection::setEffect(const std::string &effectName, const std::string & effectArgs, int priority, int duration)
{
	std::cout << "Start effect " << effectName << std::endl;

	// create command
	Json::Value command;
	command["command"] = "effect";
	command["priority"] = priority;
	Json::Value & effect = command["effect"];
	effect["name"] = effectName;
	if (effectArgs.size() > 0)
	{
		Json::Reader reader;
		if (!reader.parse(effectArgs, effect["args"], false))
		{
			throw std::runtime_error("Error in effect arguments: " + reader.getFormattedErrorMessages());
		}
	}
	if (duration > 0)
	{
		command["duration"] = duration;
	}

	// send command message
	Json::Value reply = sendMessage(command);

	// parse reply message
	parseReply(reply);
}

QString JsonConnection::getServerInfo()
{
	std::cout << "Get server info" << std::endl;

	// create command
	Json::Value command;
	command["command"] = "serverinfo";

	// send command message
	Json::Value reply = sendMessage(command);

	// parse reply message
	if (parseReply(reply))
	{
		if (!reply.isMember("info") || !reply["info"].isObject())
		{
			throw std::runtime_error("No info available in result");
		}

		const Json::Value & info = reply["info"];
		return QString(info.toStyledString().c_str());
	}

	return QString();
}

void JsonConnection::clear(int priority)
{
	std::cout << "Clear priority channel " << priority << std::endl;

	// create command
	Json::Value command;
	command["command"] = "clear";
	command["priority"] = priority;

	// send command message
	Json::Value reply = sendMessage(command);

	// parse reply message
	parseReply(reply);
}

void JsonConnection::clearAll()
{
	std::cout << "Clear all priority channels" << std::endl;

	// create command
	Json::Value command;
	command["command"] = "clearall";

	// send command message
	Json::Value reply = sendMessage(command);

	// parse reply message
	parseReply(reply);
}

void JsonConnection::setTransform(std::string * transformId, double * saturation, double * value, double * saturationL, double * luminance, ColorTransformValues *threshold, ColorTransformValues *gamma, ColorTransformValues *blacklevel, ColorTransformValues *whitelevel)
{
	std::cout << "Set color transforms" << std::endl;

	// create command
	Json::Value command;
	command["command"] = "transform";
	Json::Value & transform = command["transform"];

	if (transformId != nullptr)
	{
		transform["id"] = *transformId;
	}

	if (saturation != nullptr)
	{
		transform["saturationGain"] = *saturation;
	}

	if (value != nullptr)
	{
		transform["valueGain"] = *value;
	}

	if (saturationL != nullptr)
	{
		transform["saturationLGain"] = *saturationL;
	}

	if (luminance != nullptr)
	{
		transform["luminanceGain"] = *luminance;
	}
	if (threshold != nullptr)
	{
		Json::Value & v = transform["threshold"];
		v.append(threshold->valueRed);
		v.append(threshold->valueGreen);
		v.append(threshold->valueBlue);
	}

	if (gamma != nullptr)
	{
		Json::Value & v = transform["gamma"];
		v.append(gamma->valueRed);
		v.append(gamma->valueGreen);
		v.append(gamma->valueBlue);
	}

	if (blacklevel != nullptr)
	{
		Json::Value & v = transform["blacklevel"];
		v.append(blacklevel->valueRed);
		v.append(blacklevel->valueGreen);
		v.append(blacklevel->valueBlue);
	}

	if (whitelevel != nullptr)
	{
		Json::Value & v = transform["whitelevel"];
		v.append(whitelevel->valueRed);
		v.append(whitelevel->valueGreen);
		v.append(whitelevel->valueBlue);
	}

	// send command message
	Json::Value reply = sendMessage(command);

	// parse reply message
	parseReply(reply);
}

void JsonConnection::setCorrection(std::string * correctionId, ColorCorrectionValues *correction)
{
	std::cout << "Set color corrections" << std::endl;

	// create command
	Json::Value command;
	command["command"] = "correction";
	Json::Value & correct = command["correction"];

	if (correctionId != nullptr)
	{
		correct["id"] = *correctionId;
	}

	if (correction != nullptr)
	{
		Json::Value & v = correction["correctionValues"];
		v.append(correction->valueRed);
		v.append(correction->valueGreen);
		v.append(correction->valueBlue);
	}

	// send command message
	Json::Value reply = sendMessage(command);

	// parse reply message
	parseReply(reply);
}

void JsonConnection::setTemperature(std::string * temperatureId, ColorCorrectionValues *temperature)
{
	std::cout << "Set color temperature corrections" << std::endl;

	// create command
	Json::Value command;
	command["command"] = "temperature";
	Json::Value & temp = command["temperature"];

	if (temperatureId != nullptr)
	{
		temp["id"] = *temperatureId;
	}

	if (temperature != nullptr)
	{
		Json::Value & v = temp["correctionValues"];
		v.append(temperature->valueRed);
		v.append(temperature->valueGreen);
		v.append(temperature->valueBlue);
	}

	// send command message
	Json::Value reply = sendMessage(command);

	// parse reply message
	parseReply(reply);
}

Json::Value JsonConnection::sendMessage(const Json::Value & message)
{
	// serialize message (FastWriter already appends a newline)
	std::string serializedMessage = Json::FastWriter().write(message);

	// print command if requested
	if (_printJson)
	{
		std::cout << "Command: " << serializedMessage;
	}

	// write message
	_socket.write(serializedMessage.c_str());
	if (!_socket.waitForBytesWritten())
	{
		throw std::runtime_error("Error while writing data to host");
	}

	// read reply data
	QByteArray serializedReply;
	while (!serializedReply.contains('\n'))
	{
		// receive reply
		if (!_socket.waitForReadyRead())
		{
			throw std::runtime_error("Error while reading data from host");
		}

		serializedReply += _socket.readAll();
	}
	int bytes = serializedReply.indexOf('\n') + 1;     // Find the end of message

	// print reply if requested
	if (_printJson)
	{
		std::cout << "Reply: " << std::string(serializedReply.data(), bytes);
	}

	// parse reply data
	Json::Reader jsonReader;
	Json::Value reply;
	if (!jsonReader.parse(serializedReply.constData(), serializedReply.constData() + bytes, reply))
	{
		throw std::runtime_error("Error while parsing reply: invalid json");
	}

	return reply;
}

bool JsonConnection::parseReply(const Json::Value &reply)
{
	bool success = false;
	std::string reason = "No error info";

	try
	{
		success = reply.get("success", false).asBool();
		if (!success)
			reason = reply.get("error", reason).asString();
	}
	catch (const std::runtime_error &)
	{
		// Some json parsing error: ignore and set parsing error
	}

	if (!success)
	{
		throw std::runtime_error("Error: " + reason);
	}

	return success;
}
<|endoftext|>


<commit_before>/****************************************************************************
**
** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/
**
** This file is part of the QtQml module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** GNU Lesser General Public License Usage
** This file may be used under the terms of the GNU Lesser General Public
** License version 2.1 as published by the Free Software Foundation and
** appearing in the file LICENSE.LGPL included in the packaging of this
** file. Please review the following information to ensure the GNU Lesser
** General Public License version 2.1 requirements will be met:
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU General
** Public License version 3.0 as published by the Free Software Foundation
** and appearing in the file LICENSE.GPL included in the packaging of this
** file. Please review the following information to ensure the GNU General
** Public License version 3.0 requirements will be met:
** http://www.gnu.org/copyleft/gpl.html.
**
** Other Usage
** Alternatively, this file may be used in accordance with the terms and
** conditions contained in a signed written agreement between you and Nokia.
**
**
**
**
**
**
** $QT_END_LICENSE$
**
****************************************************************************/

#include <QtQml/qqmlextensionplugin.h>
#include <QtQml/qqml.h>

#include "qquickfolderlistmodel.h"

QT_BEGIN_NAMESPACE

//![class decl]
class QmlFolderListModelPlugin : public QQmlExtensionPlugin
{
    Q_OBJECT
    Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QQmlExtensionInterface" FILE "folderlistmodel.json")

public:
    virtual void registerTypes(const char *uri)
    {
        Q_ASSERT(QLatin1String(uri) == QLatin1String("Qt.labs.folderlistmodel"));
#ifndef QT_NO_DIRMODEL
        qmlRegisterType<QQuickFolderListModel>(uri,1,0,"FolderListModel");
#endif
    }
};
//![class decl]

QT_END_NAMESPACE

#include "plugin.moc"
<commit_msg>Add a version 2 import for FolderListModel<commit_after>/****************************************************************************
**
** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/
**
** This file is part of the QtQml module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** GNU Lesser General Public License Usage
** This file may be used under the terms of the GNU Lesser General Public
** License version 2.1 as published by the Free Software Foundation and
** appearing in the file LICENSE.LGPL included in the packaging of this
** file. Please review the following information to ensure the GNU Lesser
** General Public License version 2.1 requirements will be met:
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU General
** Public License version 3.0 as published by the Free Software Foundation
** and appearing in the file LICENSE.GPL included in the packaging of this
** file. Please review the following information to ensure the GNU General
** Public License version 3.0 requirements will be met:
** http://www.gnu.org/copyleft/gpl.html.
**
** Other Usage
** Alternatively, this file may be used in accordance with the terms and
** conditions contained in a signed written agreement between you and Nokia.
**
**
**
**
**
**
** $QT_END_LICENSE$
**
****************************************************************************/

#include <QtQml/qqmlextensionplugin.h>
#include <QtQml/qqml.h>

#include "qquickfolderlistmodel.h"

QT_BEGIN_NAMESPACE

//![class decl]
class QmlFolderListModelPlugin : public QQmlExtensionPlugin
{
    Q_OBJECT
    Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QQmlExtensionInterface" FILE "folderlistmodel.json")

public:
    virtual void registerTypes(const char *uri)
    {
        Q_ASSERT(QLatin1String(uri) == QLatin1String("Qt.labs.folderlistmodel"));
#ifndef QT_NO_DIRMODEL
        qmlRegisterType<QQuickFolderListModel>(uri,1,0,"FolderListModel");
        qmlRegisterType<QQuickFolderListModel>(uri,2,0,"FolderListModel");
#endif
    }
};
//![class decl]

QT_END_NAMESPACE

#include "plugin.moc"
<|endoftext|>