<commit_before>/*
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 3 of the License, or
 * (at your option) any later version.
 *
 * Written (W) 2015 Wu Lin
 * Written (W) 2012 Jacob Walker
 *
 * Adapted from WeightedDegreeRBFKernel.cpp
 */

#include <shogun/kernel/LinearARDKernel.h>

#ifdef HAVE_LINALG_LIB
#include <shogun/mathematics/linalg/linalg.h>
#endif

using namespace shogun;

CLinearARDKernel::CLinearARDKernel() : CDotKernel()
{
	initialize();
}

CLinearARDKernel::~CLinearARDKernel()
{
	CKernel::cleanup();
}

void CLinearARDKernel::initialize()
{
	m_ARD_type=KT_SCALAR;
	m_weights=SGMatrix<float64_t>(1,1);
	m_weights.set_const(1.0);
	SG_ADD(&m_weights, "weights", "Feature weights", MS_AVAILABLE,
			GRADIENT_AVAILABLE);
	SG_ADD((int *)(&m_ARD_type), "type", "ARD kernel type", MS_NOT_AVAILABLE);
}

#ifdef HAVE_LINALG_LIB
CLinearARDKernel::CLinearARDKernel(int32_t size) : CDotKernel(size)
{
	initialize();
}

CLinearARDKernel::CLinearARDKernel(CDotFeatures* l,
		CDotFeatures* r, int32_t size)	: CDotKernel(size)
{
	initialize();
	init(l,r);
}

bool CLinearARDKernel::init(CFeatures* l, CFeatures* r)
{
	cleanup();
	CDotKernel::init(l, r);
	int32_t dim=((CDotFeatures*) l)->get_dim_feature_space();
	if (m_ARD_type==KT_FULL)
	{
		REQUIRE(m_weights.num_cols==dim, "Dimension mismatch between features (%d) and weights (%d)\n",
			dim, m_weights.num_cols);
	}
	else if (m_ARD_type==KT_DIAG)
	{
		REQUIRE(m_weights.num_rows==dim, "Dimension mismatch between features (%d) and weights (%d)\n",
			dim, m_weights.num_rows);
	}
	return init_normalizer();
}

SGMatrix<float64_t> CLinearARDKernel::compute_right_product(SGVector<float64_t>right_vec,
	float64_t & scalar_weight)
{
	SGMatrix<float64_t> right;

	if (m_ARD_type==KT_SCALAR)
	{
		right=SGMatrix<float64_t>(right_vec.vector,right_vec.vlen,1,false);
		scalar_weight*=m_weights[0];
	}
	else
	{
		SGMatrix<float64_t> rtmp(right_vec.vector,right_vec.vlen,1,false);

		if(m_ARD_type==KT_DIAG)
			right=linalg::elementwise_product(m_weights, rtmp);
		else if(m_ARD_type==KT_FULL)
			right=linalg::matrix_product(m_weights, rtmp);
		else
			SG_ERROR("Unsupported ARD type\n");
	}
	return right;
}

float64_t CLinearARDKernel::compute_helper(SGVector<float64_t> avec, SGVector<float64_t>bvec)
{
	SGMatrix<float64_t> left;
	SGMatrix<float64_t> left_transpose;
	float64_t scalar_weight=1.0;
	if (m_ARD_type==KT_SCALAR)
	{
		left=SGMatrix<float64_t>(avec.vector,1,avec.vlen,false);
		scalar_weight=m_weights[0];
	}
	else
	{
		SGMatrix<float64_t> ltmp(avec.vector,avec.vlen,1,false);
		if(m_ARD_type==KT_DIAG)
			left_transpose=linalg::elementwise_product(m_weights, ltmp);
		else if(m_ARD_type==KT_FULL)
			left_transpose=linalg::matrix_product(m_weights, ltmp);
		else
			SG_ERROR("Unsupported ARD type\n");
		left=SGMatrix<float64_t>(left_transpose.matrix,1,left_transpose.num_rows,false);
	}
	SGMatrix<float64_t> right=compute_right_product(bvec, scalar_weight);
	SGMatrix<float64_t> res=linalg::matrix_product(left, right);
	return res[0]*scalar_weight;
}

float64_t CLinearARDKernel::compute(int32_t idx_a, int32_t idx_b)
{
	REQUIRE(lhs && rhs, "Features not set!\n");
	SGVector<float64_t> avec=((CDotFeatures *)lhs)->get_computed_dot_feature_vector(idx_a);
	SGVector<float64_t> bvec=((CDotFeatures *)rhs)->get_computed_dot_feature_vector(idx_b);

	return compute_helper(avec, bvec);
}

float64_t CLinearARDKernel::compute_gradient_helper(SGVector<float64_t> avec,
	SGVector<float64_t> bvec, float64_t scale, index_t index)
{
	float64_t result;

	if(m_ARD_type==KT_DIAG)
	{
		result=2.0*avec[index]*bvec[index]*m_weights[index];
	}
	else
	{
		SGMatrix<float64_t> left(avec.vector,1,avec.vlen,false);
		SGMatrix<float64_t> right(bvec.vector,bvec.vlen,1,false);
		SGMatrix<float64_t> res;

		if (m_ARD_type==KT_SCALAR)
		{
			res=linalg::matrix_product(left, right);
			result=2.0*res[0]*m_weights[0];
		}
		else if(m_ARD_type==KT_FULL)
		{
			int32_t row_index=index%m_weights.num_rows;
			int32_t col_index=index/m_weights.num_rows;
			//index is a linearized index of m_weights (column-major)
			//m_weights is a d-by-p matrix, where p is #dimension of features
			SGVector<float64_t> row_vec=m_weights.get_row_vector(row_index);
			SGMatrix<float64_t> row_vec_r(row_vec.vector,row_vec.vlen,1,false);

			res=linalg::matrix_product(left, row_vec_r);
			result=res[0]*bvec[col_index];

			SGMatrix<float64_t> row_vec_l(row_vec.vector,1,row_vec.vlen,false);
			res=linalg::matrix_product(row_vec_l, right);
			result+=res[0]*avec[col_index];

		}
		else
		{
			SG_ERROR("Unsupported ARD type\n");
		}

	}
	return result*scale;
}

SGMatrix<float64_t> CLinearARDKernel::get_parameter_gradient(
	const TParameter* param, index_t index)
{
	REQUIRE(lhs && rhs, "Features not set!\n");

	int32_t row_index, col_index;
	if (m_ARD_type!=KT_SCALAR)
	{
		REQUIRE(index>=0, "Index (%d) must be non-negative\n",index);
		if (m_ARD_type==KT_DIAG)
		{
			REQUIRE(index<m_weights.num_rows, "Index (%d) must be within #dimension of weights (%d)\n",
				index, m_weights.num_rows);
		}
		else if(m_ARD_type==KT_FULL)
		{
			row_index=index%m_weights.num_rows;
			col_index=index/m_weights.num_rows;
			REQUIRE(row_index<m_weights.num_rows,
				"Row index (%d) must be within #row of weights (%d)\n",
				row_index, m_weights.num_rows);
			REQUIRE(col_index<m_weights.num_cols,
				"Column index (%d) must be within #column of weights (%d)\n",
				col_index, m_weights.num_cols);
		}
	}
	if (!strcmp(param->m_name, "weights"))
	{
		SGMatrix<float64_t> derivative(num_lhs, num_rhs);

		for (index_t j=0; j<num_lhs; j++)
		{
			SGVector<float64_t> avec=((CDotFeatures *)lhs)->get_computed_dot_feature_vector(j);
			for (index_t k=0; k<num_rhs; k++)
			{
				SGVector<float64_t> bvec=((CDotFeatures *)rhs)->get_computed_dot_feature_vector(k);
				derivative(j,k)=compute_gradient_helper(avec, bvec, 1.0, index);
			}
		}
		return derivative;
	}
	else
	{
		SG_ERROR("Can't compute derivative wrt %s parameter\n", param->m_name);
		return SGMatrix<float64_t>();
	}
}

SGMatrix<float64_t> CLinearARDKernel::get_weights()
{
	return SGMatrix<float64_t>(m_weights);
}

void CLinearARDKernel::set_weights(SGMatrix<float64_t> weights)
{
	REQUIRE(weights.num_cols>0 && weights.num_rows>0,
		"Weight Matrix (%d-by-%d) must not be empty\n",
		weights.num_rows, weights.num_cols);
	if (weights.num_cols>1)
	{
		m_ARD_type=KT_FULL;
	}
	else
	{
		if (weights.num_rows==1)
		{
			m_ARD_type=KT_SCALAR;
		}
		else
		{
			m_ARD_type=KT_DIAG;
		}
	}
	m_weights=weights;
}

void CLinearARDKernel::set_scalar_weights(float64_t weight)
{
	SGMatrix<float64_t> weights(1,1);
	weights(0,0)=weight;
	set_weights(weights);
}

void CLinearARDKernel::set_vector_weights(SGVector<float64_t> weights)
{
	SGMatrix<float64_t> weights_mat(weights.vlen,1);
	std::copy(weights.vector, weights.vector+weights.vlen, weights_mat.matrix);
	set_weights(weights_mat);
}

void CLinearARDKernel::set_matrix_weights(SGMatrix<float64_t> weights)
{
	set_weights(weights);
}
#endif //HAVE_LINALG_LIB
<commit_msg>update the precondition<commit_after>/*
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 3 of the License, or
 * (at your option) any later version.
 *
 * Written (W) 2015 Wu Lin
 * Written (W) 2012 Jacob Walker
 *
 * Adapted from WeightedDegreeRBFKernel.cpp
 */

#include <shogun/kernel/LinearARDKernel.h>

#ifdef HAVE_LINALG_LIB
#include <shogun/mathematics/linalg/linalg.h>
#endif

using namespace shogun;

CLinearARDKernel::CLinearARDKernel() : CDotKernel()
{
	initialize();
}

CLinearARDKernel::~CLinearARDKernel()
{
	CKernel::cleanup();
}

void CLinearARDKernel::initialize()
{
	m_ARD_type=KT_SCALAR;
	m_weights=SGMatrix<float64_t>(1,1);
	m_weights.set_const(1.0);
	SG_ADD(&m_weights, "weights", "Feature weights", MS_AVAILABLE,
			GRADIENT_AVAILABLE);
	SG_ADD((int *)(&m_ARD_type), "type", "ARD kernel type", MS_NOT_AVAILABLE);
}

#ifdef HAVE_LINALG_LIB
CLinearARDKernel::CLinearARDKernel(int32_t size) : CDotKernel(size)
{
	initialize();
}

CLinearARDKernel::CLinearARDKernel(CDotFeatures* l,
		CDotFeatures* r, int32_t size)	: CDotKernel(size)
{
	initialize();
	init(l,r);
}

bool CLinearARDKernel::init(CFeatures* l, CFeatures* r)
{
	cleanup();
	CDotKernel::init(l, r);
	int32_t dim=((CDotFeatures*) l)->get_dim_feature_space();
	if (m_ARD_type==KT_FULL)
	{
		REQUIRE(m_weights.num_cols==dim, "Dimension mismatch between features (%d) and weights (%d)\n",
			dim, m_weights.num_cols);
	}
	else if (m_ARD_type==KT_DIAG)
	{
		REQUIRE(m_weights.num_rows==dim, "Dimension mismatch between features (%d) and weights (%d)\n",
			dim, m_weights.num_rows);
	}
	return init_normalizer();
}

SGMatrix<float64_t> CLinearARDKernel::compute_right_product(SGVector<float64_t>right_vec,
	float64_t & scalar_weight)
{
	SGMatrix<float64_t> right;

	if (m_ARD_type==KT_SCALAR)
	{
		right=SGMatrix<float64_t>(right_vec.vector,right_vec.vlen,1,false);
		scalar_weight*=m_weights[0];
	}
	else
	{
		SGMatrix<float64_t> rtmp(right_vec.vector,right_vec.vlen,1,false);

		if(m_ARD_type==KT_DIAG)
			right=linalg::elementwise_product(m_weights, rtmp);
		else if(m_ARD_type==KT_FULL)
			right=linalg::matrix_product(m_weights, rtmp);
		else
			SG_ERROR("Unsupported ARD type\n");
	}
	return right;
}

float64_t CLinearARDKernel::compute_helper(SGVector<float64_t> avec, SGVector<float64_t>bvec)
{
	SGMatrix<float64_t> left;
	SGMatrix<float64_t> left_transpose;
	float64_t scalar_weight=1.0;
	if (m_ARD_type==KT_SCALAR)
	{
		left=SGMatrix<float64_t>(avec.vector,1,avec.vlen,false);
		scalar_weight=m_weights[0];
	}
	else
	{
		SGMatrix<float64_t> ltmp(avec.vector,avec.vlen,1,false);
		if(m_ARD_type==KT_DIAG)
			left_transpose=linalg::elementwise_product(m_weights, ltmp);
		else if(m_ARD_type==KT_FULL)
			left_transpose=linalg::matrix_product(m_weights, ltmp);
		else
			SG_ERROR("Unsupported ARD type\n");
		left=SGMatrix<float64_t>(left_transpose.matrix,1,left_transpose.num_rows,false);
	}
	SGMatrix<float64_t> right=compute_right_product(bvec, scalar_weight);
	SGMatrix<float64_t> res=linalg::matrix_product(left, right);
	return res[0]*scalar_weight;
}

float64_t CLinearARDKernel::compute(int32_t idx_a, int32_t idx_b)
{
	REQUIRE(lhs, "Left features not set!\n");
	REQUIRE(rhs, "Right features not set!\n");
	SGVector<float64_t> avec=((CDotFeatures *)lhs)->get_computed_dot_feature_vector(idx_a);
	SGVector<float64_t> bvec=((CDotFeatures *)rhs)->get_computed_dot_feature_vector(idx_b);

	return compute_helper(avec, bvec);
}

float64_t CLinearARDKernel::compute_gradient_helper(SGVector<float64_t> avec,
	SGVector<float64_t> bvec, float64_t scale, index_t index)
{
	float64_t result;

	if(m_ARD_type==KT_DIAG)
	{
		result=2.0*avec[index]*bvec[index]*m_weights[index];
	}
	else
	{
		SGMatrix<float64_t> left(avec.vector,1,avec.vlen,false);
		SGMatrix<float64_t> right(bvec.vector,bvec.vlen,1,false);
		SGMatrix<float64_t> res;

		if (m_ARD_type==KT_SCALAR)
		{
			res=linalg::matrix_product(left, right);
			result=2.0*res[0]*m_weights[0];
		}
		else if(m_ARD_type==KT_FULL)
		{
			int32_t row_index=index%m_weights.num_rows;
			int32_t col_index=index/m_weights.num_rows;
			//index is a linearized index of m_weights (column-major)
			//m_weights is a d-by-p matrix, where p is #dimension of features
			SGVector<float64_t> row_vec=m_weights.get_row_vector(row_index);
			SGMatrix<float64_t> row_vec_r(row_vec.vector,row_vec.vlen,1,false);

			res=linalg::matrix_product(left, row_vec_r);
			result=res[0]*bvec[col_index];

			SGMatrix<float64_t> row_vec_l(row_vec.vector,1,row_vec.vlen,false);
			res=linalg::matrix_product(row_vec_l, right);
			result+=res[0]*avec[col_index];

		}
		else
		{
			SG_ERROR("Unsupported ARD type\n");
		}

	}
	return result*scale;
}

SGMatrix<float64_t> CLinearARDKernel::get_parameter_gradient(
	const TParameter* param, index_t index)
{
	REQUIRE(lhs, "Left features not set!\n");
	REQUIRE(rhs, "Right features not set!\n");

	int32_t row_index, col_index;
	if (m_ARD_type!=KT_SCALAR)
	{
		REQUIRE(index>=0, "Index (%d) must be non-negative\n",index);
		if (m_ARD_type==KT_DIAG)
		{
			REQUIRE(index<m_weights.num_rows, "Index (%d) must be within #dimension of weights (%d)\n",
				index, m_weights.num_rows);
		}
		else if(m_ARD_type==KT_FULL)
		{
			row_index=index%m_weights.num_rows;
			col_index=index/m_weights.num_rows;
			REQUIRE(row_index<m_weights.num_rows,
				"Row index (%d) must be within #row of weights (%d)\n",
				row_index, m_weights.num_rows);
			REQUIRE(col_index<m_weights.num_cols,
				"Column index (%d) must be within #column of weights (%d)\n",
				col_index, m_weights.num_cols);
		}
	}
	if (!strcmp(param->m_name, "weights"))
	{
		SGMatrix<float64_t> derivative(num_lhs, num_rhs);

		for (index_t j=0; j<num_lhs; j++)
		{
			SGVector<float64_t> avec=((CDotFeatures *)lhs)->get_computed_dot_feature_vector(j);
			for (index_t k=0; k<num_rhs; k++)
			{
				SGVector<float64_t> bvec=((CDotFeatures *)rhs)->get_computed_dot_feature_vector(k);
				derivative(j,k)=compute_gradient_helper(avec, bvec, 1.0, index);
			}
		}
		return derivative;
	}
	else
	{
		SG_ERROR("Can't compute derivative wrt %s parameter\n", param->m_name);
		return SGMatrix<float64_t>();
	}
}

SGMatrix<float64_t> CLinearARDKernel::get_weights()
{
	return SGMatrix<float64_t>(m_weights);
}

void CLinearARDKernel::set_weights(SGMatrix<float64_t> weights)
{
	REQUIRE(weights.num_cols>0 && weights.num_rows>0,
		"Weight Matrix (%d-by-%d) must not be empty\n",
		weights.num_rows, weights.num_cols);
	if (weights.num_cols>1)
	{
		m_ARD_type=KT_FULL;
	}
	else
	{
		if (weights.num_rows==1)
		{
			m_ARD_type=KT_SCALAR;
		}
		else
		{
			m_ARD_type=KT_DIAG;
		}
	}
	m_weights=weights;
}

void CLinearARDKernel::set_scalar_weights(float64_t weight)
{
	SGMatrix<float64_t> weights(1,1);
	weights(0,0)=weight;
	set_weights(weights);
}

void CLinearARDKernel::set_vector_weights(SGVector<float64_t> weights)
{
	SGMatrix<float64_t> weights_mat(weights.vlen,1);
	std::copy(weights.vector, weights.vector+weights.vlen, weights_mat.matrix);
	set_weights(weights_mat);
}

void CLinearARDKernel::set_matrix_weights(SGMatrix<float64_t> weights)
{
	set_weights(weights);
}
#endif //HAVE_LINALG_LIB
<|endoftext|>


<commit_before>#include <stdexcept>
#include "units.hpp"

namespace Sass {

  /* the conversion matrix can be readed the following way */
  /* if you go down, the factor is for the numerator (multiply) */
  /* if you go right, the factor is for the denominator (divide) */
  /* and yes, we actually use both, not sure why, but why not!? */

  const double size_conversion_factors[6][6] =
  {
             /*  in         cm         pc         mm         pt         px        */
    /* in   */ { 1,         2.54,      6,         25.4,      72,        96,       },
    /* cm   */ { 1.0/2.54,  1,         6.0/2.54,  10,        72.0/2.54, 96.0/2.54 },
    /* pc   */ { 1.0/6.0,   2.54/6.0,  1,         25.4/6.0,  72.0/6.0,  96.0/6.0  },
    /* mm   */ { 1.0/25.4,  1.0/10.0,  6.0/25.4,  1,         72.0/25.4, 96.0/25.4 },
    /* pt   */ { 1.0/72.0,  2.54/72.0, 6.0/72.0,  25.4/72.0, 1,         96.0/72.0 },
    /* px   */ { 1.0/96.0,  2.54/96.0, 6.0/96.0,  25.4/96.0, 72.0/96.0, 1,        }
  };

  const double angle_conversion_factors[4][4] =
  {
             /*  deg        grad       rad        turn      */
    /* deg  */ { 1,         40.0/36.0, PI/180.0,  1.0/360.0 },
    /* grad */ { 36.0/40.0, 1,         PI/200.0,  1.0/400.0 },
    /* rad  */ { 180.0/PI,  200.0/PI,  1,         0.5/PI    },
    /* turn */ { 360.0,     400.0,     2.0*PI,    1         }
  };

  const double time_conversion_factors[2][2] =
  {
             /*  s          ms        */
    /* s    */ { 1,         1000.0    },
    /* ms   */ { 1/1000.0,  1         }
  };
  const double frequency_conversion_factors[2][2] =
  {
             /*  Hz         kHz       */
    /* Hz   */ { 1,         1/1000.0  },
    /* kHz  */ { 1000.0,    1         }
  };
  const double resolution_conversion_factors[3][3] =
  {
             /*  dpi        dpcm       dppx     */
    /* dpi  */ { 1,         2.54,      96       },
    /* dpcm */ { 1/2.54,    1,         96/2.54  },
    /* dppx */ { 1/96.0,    2.54/96,   1        }
  };

  SassUnitType get_unit_type(SassUnit unit)
  {
    switch (unit & 0xFF00)
    {
      case SIZE: return SIZE; break;
      case ANGLE: return ANGLE; break;
      case TIME: return TIME; break;
      case FREQUENCY: return FREQUENCY; break;
      case RESOLUTION: return RESOLUTION; break;
      default: return INCOMMENSURABLE; break;
    }
  };

  SassUnit string_to_unit(const string& s)
  {
    // size units
    if      (s == "px") return PX;
    else if (s == "pt") return PT;
    else if (s == "pc") return PC;
    else if (s == "mm") return MM;
    else if (s == "cm") return CM;
    else if (s == "in") return IN;
    // angle units
    else if (s == "deg") return DEG;
    else if (s == "grad") return GRAD;
    else if (s == "rad") return RAD;
    else if (s == "turn") return TURN;
    // time units
    else if (s == "s") return SEC;
    else if (s == "ms") return MSEC;
    // frequency units
    else if (s == "Hz") return HERTZ;
    else if (s == "kHz") return KHERTZ;
    // resolutions units
    else if (s == "dpi") return DPI;
    else if (s == "dpcm") return DPCM;
    else if (s == "dppx") return DPPX;
    // for unknown units
    else return UNKNOWN;
  }

  const char* unit_to_string(SassUnit unit)
  {
    switch (unit) {
      // size units
      case PX: return "px"; break;
      case PT: return "pt"; break;
      case PC: return "pc"; break;
      case MM: return "mm"; break;
      case CM: return "cm"; break;
      case IN: return "in"; break;
      // angle units
      case DEG: return "deg"; break;
      case GRAD: return "grad"; break;
      case RAD: return "rad"; break;
      case TURN: return "turn"; break;
      // time units
      case SEC: return "s"; break;
      case MSEC: return "ms"; break;
      // frequency units
      case HERTZ: return "Hz"; break;
      case KHERTZ: return "kHz"; break;
      // resolutions units
      case DPI: return "dpi"; break;
      case DPCM: return "dpcm"; break;
      case DPPX: return "dppx"; break;
      // for unknown units
      default: return ""; break;;
    }
  }

  // throws incompatibleUnits exceptions
  double conversion_factor(const string& s1, const string& s2, bool strict)
  {
    // assert for same units
    if (s1 == s2) return 1;
    // get unit enum from string
    SassUnit u1 = string_to_unit(s1);
    SassUnit u2 = string_to_unit(s2);
    // query unit group types
    SassUnitType t1 = get_unit_type(u1);
    SassUnitType t2 = get_unit_type(u2);
    // get absolute offset
    // used for array acces
    size_t i1 = u1 - t1;
    size_t i2 = u2 - t2;
    // error if units are not of the same group
    // don't error for multiplication and division
    if (strict && t1 != t2) throw incompatibleUnits(u1, u2);
    // only process known units
    if (u1 != UNKNOWN && u2 != UNKNOWN) {
      switch (t1) {
        case SIZE: return size_conversion_factors[i1][i2]; break;
        case ANGLE: return angle_conversion_factors[i1][i2]; break;
        case TIME: return time_conversion_factors[i1][i2]; break;
        case FREQUENCY: return frequency_conversion_factors[i1][i2]; break;
        case RESOLUTION: return resolution_conversion_factors[i1][i2]; break;
        // ToDo: should we throw error here?
        case INCOMMENSURABLE: return 0; break;
      }
    }
    // fallback
    return 1;
  }

}
<commit_msg>undefine mingw32 pseudo modifier IN<commit_after>#include <stdexcept>
#include "units.hpp"

#ifdef IN
#undef IN
#endif

namespace Sass {

  /* the conversion matrix can be readed the following way */
  /* if you go down, the factor is for the numerator (multiply) */
  /* if you go right, the factor is for the denominator (divide) */
  /* and yes, we actually use both, not sure why, but why not!? */

  const double size_conversion_factors[6][6] =
  {
             /*  in         cm         pc         mm         pt         px        */
    /* in   */ { 1,         2.54,      6,         25.4,      72,        96,       },
    /* cm   */ { 1.0/2.54,  1,         6.0/2.54,  10,        72.0/2.54, 96.0/2.54 },
    /* pc   */ { 1.0/6.0,   2.54/6.0,  1,         25.4/6.0,  72.0/6.0,  96.0/6.0  },
    /* mm   */ { 1.0/25.4,  1.0/10.0,  6.0/25.4,  1,         72.0/25.4, 96.0/25.4 },
    /* pt   */ { 1.0/72.0,  2.54/72.0, 6.0/72.0,  25.4/72.0, 1,         96.0/72.0 },
    /* px   */ { 1.0/96.0,  2.54/96.0, 6.0/96.0,  25.4/96.0, 72.0/96.0, 1,        }
  };

  const double angle_conversion_factors[4][4] =
  {
             /*  deg        grad       rad        turn      */
    /* deg  */ { 1,         40.0/36.0, PI/180.0,  1.0/360.0 },
    /* grad */ { 36.0/40.0, 1,         PI/200.0,  1.0/400.0 },
    /* rad  */ { 180.0/PI,  200.0/PI,  1,         0.5/PI    },
    /* turn */ { 360.0,     400.0,     2.0*PI,    1         }
  };

  const double time_conversion_factors[2][2] =
  {
             /*  s          ms        */
    /* s    */ { 1,         1000.0    },
    /* ms   */ { 1/1000.0,  1         }
  };
  const double frequency_conversion_factors[2][2] =
  {
             /*  Hz         kHz       */
    /* Hz   */ { 1,         1/1000.0  },
    /* kHz  */ { 1000.0,    1         }
  };
  const double resolution_conversion_factors[3][3] =
  {
             /*  dpi        dpcm       dppx     */
    /* dpi  */ { 1,         2.54,      96       },
    /* dpcm */ { 1/2.54,    1,         96/2.54  },
    /* dppx */ { 1/96.0,    2.54/96,   1        }
  };

  SassUnitType get_unit_type(SassUnit unit)
  {
    switch (unit & 0xFF00)
    {
      case SIZE: return SIZE; break;
      case ANGLE: return ANGLE; break;
      case TIME: return TIME; break;
      case FREQUENCY: return FREQUENCY; break;
      case RESOLUTION: return RESOLUTION; break;
      default: return INCOMMENSURABLE; break;
    }
  };

  SassUnit string_to_unit(const string& s)
  {
    // size units
    if      (s == "px") return PX;
    else if (s == "pt") return PT;
    else if (s == "pc") return PC;
    else if (s == "mm") return MM;
    else if (s == "cm") return CM;
    else if (s == "in") return IN;
    // angle units
    else if (s == "deg") return DEG;
    else if (s == "grad") return GRAD;
    else if (s == "rad") return RAD;
    else if (s == "turn") return TURN;
    // time units
    else if (s == "s") return SEC;
    else if (s == "ms") return MSEC;
    // frequency units
    else if (s == "Hz") return HERTZ;
    else if (s == "kHz") return KHERTZ;
    // resolutions units
    else if (s == "dpi") return DPI;
    else if (s == "dpcm") return DPCM;
    else if (s == "dppx") return DPPX;
    // for unknown units
    else return UNKNOWN;
  }

  const char* unit_to_string(SassUnit unit)
  {
    switch (unit) {
      // size units
      case PX: return "px"; break;
      case PT: return "pt"; break;
      case PC: return "pc"; break;
      case MM: return "mm"; break;
      case CM: return "cm"; break;
      case IN: return "in"; break;
      // angle units
      case DEG: return "deg"; break;
      case GRAD: return "grad"; break;
      case RAD: return "rad"; break;
      case TURN: return "turn"; break;
      // time units
      case SEC: return "s"; break;
      case MSEC: return "ms"; break;
      // frequency units
      case HERTZ: return "Hz"; break;
      case KHERTZ: return "kHz"; break;
      // resolutions units
      case DPI: return "dpi"; break;
      case DPCM: return "dpcm"; break;
      case DPPX: return "dppx"; break;
      // for unknown units
      default: return ""; break;;
    }
  }

  // throws incompatibleUnits exceptions
  double conversion_factor(const string& s1, const string& s2, bool strict)
  {
    // assert for same units
    if (s1 == s2) return 1;
    // get unit enum from string
    SassUnit u1 = string_to_unit(s1);
    SassUnit u2 = string_to_unit(s2);
    // query unit group types
    SassUnitType t1 = get_unit_type(u1);
    SassUnitType t2 = get_unit_type(u2);
    // get absolute offset
    // used for array acces
    size_t i1 = u1 - t1;
    size_t i2 = u2 - t2;
    // error if units are not of the same group
    // don't error for multiplication and division
    if (strict && t1 != t2) throw incompatibleUnits(u1, u2);
    // only process known units
    if (u1 != UNKNOWN && u2 != UNKNOWN) {
      switch (t1) {
        case SIZE: return size_conversion_factors[i1][i2]; break;
        case ANGLE: return angle_conversion_factors[i1][i2]; break;
        case TIME: return time_conversion_factors[i1][i2]; break;
        case FREQUENCY: return frequency_conversion_factors[i1][i2]; break;
        case RESOLUTION: return resolution_conversion_factors[i1][i2]; break;
        // ToDo: should we throw error here?
        case INCOMMENSURABLE: return 0; break;
      }
    }
    // fallback
    return 1;
  }

}
<|endoftext|>


<commit_before>/*
 * Copyright 2014 The Imaging Source Europe GmbH
 *
 * 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 "utils.h"

#include "internal.h"

#include <algorithm>
#include <cstring>
#include <sys/ioctl.h>
#include <errno.h>
#include <limits>

#define IOCTL_RETRY 4

using namespace tcam;

std::string tcam::propertyType2String (TCAM_PROPERTY_TYPE type)
{
    switch (type)
    {
        case TCAM_PROPERTY_TYPE_BOOLEAN: return "BOOLEAN";
        case TCAM_PROPERTY_TYPE_INTEGER: return "INTEGER";
        case TCAM_PROPERTY_TYPE_DOUBLE: return "DOUBLE";
        case TCAM_PROPERTY_TYPE_STRING: return "STRING";
        case TCAM_PROPERTY_TYPE_ENUMERATION: return "ENUMERATION";
        case TCAM_PROPERTY_TYPE_BUTTON: return "BUTTON";
        case TCAM_PROPERTY_TYPE_UNKNOWN:
        default:
            return "";
    }
}

std::vector<std::string> tcam::split_string (const std::string& to_split, const std::string &delim)
{
    std::vector<std::string> vec;

    size_t beg = 0;
    size_t end = 0;

    while (end != std::string::npos)
    {
        end = to_split.find_first_of(delim, beg);

        std::string s = to_split.substr(beg, end - beg);

        vec.push_back(s);

        beg = end + delim.size();
    }

    return vec;
}

int tcam::tcam_xioctl (int fd, int request, void *arg)
{
    int ret = 0;
    int tries= IOCTL_RETRY;
    do
    {
        ret = ioctl(fd, request, arg);
        // ret = v4l2_ioctl(fd, request, arg);
    }
    while (ret && tries-- &&
           ((errno == EINTR) || (errno == EAGAIN) || (errno == ETIMEDOUT)));

    if (ret && (tries <= 0))
    {
        tcam_log(TCAM_LOG_ERROR,"ioctl (%i) retried %i times - giving up: %s)\n", request, IOCTL_RETRY, strerror(errno));
    }

    return (ret);

}

std::vector<double> tcam::create_steps_for_range (double min, double max)
{
    std::vector<double> vec;

    if (max <= min)
        return vec;

    vec.push_back(min);

    // we do not want every framerate to have unnecessary decimals
    // e.g. 1.345678 instead of 1.00000
    double current_step = (int)min;

    // 0.0 is not a valid framerate
    if (current_step < 1.0)
        current_step = 1.0;

    while (current_step < max)
    {
        vec.push_back(current_step);

        if (current_step < 20.0)
        {
            current_step += 1;
        }
        else if (current_step < 100.0)
        {
            current_step += 10.0;
        }
        else if (current_step < 1000.0)
        {
            current_step += 50.0;
        }
        else
        {
            current_step += 100.0;
        }
    }

    if (vec.back() != max)
    {
        vec.push_back(max);
    }
    return vec;
}

uint64_t tcam::get_buffer_length (unsigned int width, unsigned int height, uint32_t fourcc)
{
    if (width == 0 || height == 0 || fourcc == 0)
    {
        return 0;
    }

    uint64_t size = width * height * (img::get_bits_per_pixel(fourcc) / 8);

    return size;
}

unsigned int tcam::tcam_get_required_buffer_size (const struct tcam_video_format* format)
{
    if (format == nullptr)
    {
        return 0;
    }

    return get_buffer_length(format->width, format->height, format->fourcc);
}

uint32_t tcam::get_pitch_length (unsigned int width, uint32_t fourcc)
{
    if (width == 0 || fourcc == 0)
    {
        return 0;
    }

    return width * (img::get_bits_per_pixel(fourcc) / 8);
}

bool tcam::is_buffer_complete (const struct tcam_image_buffer* buffer)
{
    auto size = tcam::get_buffer_length(buffer->format.width,
                                        buffer->format.height,
                                        buffer->format.fourcc);

    if (size != buffer->length)
    {
        return false;
    }
    return true;
}

tcam_image_size tcam::calculate_auto_center (const tcam_image_size& sensor, const tcam_image_size& image)
{
    tcam_image_size ret = {};

    if (image.width > sensor.width || image.height > sensor.height)
    {
        return ret;
    }

    ret.width = (sensor.width / 2) - (image.width /2);
    ret.height = (sensor.height / 2) - (image.height / 2);

    return ret;
}

std::shared_ptr<Property> tcam::find_property (std::vector<std::shared_ptr<Property>>& properties,
                                               TCAM_PROPERTY_ID property_id)
{
    for (auto& p : properties)
    {
        if (p->get_ID() == property_id)
        {
            return p;
        }
    }

    return nullptr;
}

std::shared_ptr<Property> tcam::find_property (std::vector<std::shared_ptr<Property>>& properties,
                                               const std::string& property_name)
{

    auto f = [&property_name] (const std::shared_ptr<Property>& p)
        {
            if (p->get_name().compare(property_name) == 0)
                return true;
            return false;
        };

    auto iter = std::find_if(properties.begin(), properties.end(), f);

    if (iter != properties.end())
    {
        return *iter;
    }

    return nullptr;
}

bool tcam::compare_double (double val1, double val2)
{
    return std::fabs(val1 - val2) < std::numeric_limits<double>::epsilon();
}

bool tcam::are_equal (const tcam_image_size& s1,
                      const tcam_image_size& s2)
{
    if (s1.height == s2.height
        && s1.width == s2.width)
    {
        return true;
    }
    return false;
}

bool tcam::are_equal (const struct tcam_resolution_description& res1,
                      const struct tcam_resolution_description& res2)
{
    if (res1.type == res2.type
        && res1.framerate_count == res2.framerate_count
        && are_equal(res1.max_size, res2.max_size)
        && are_equal(res1.min_size,res2.min_size))
    {
        return true;
    }

    return false;
}

bool tcam::are_equal (const struct tcam_video_format_description& fmt1,
                      const struct tcam_video_format_description& fmt2)
{
    if (fmt1.fourcc == fmt2.fourcc
        && fmt1.binning == fmt2.binning
        && fmt1.skipping == fmt2.skipping
        && fmt1.resolution_count == fmt2.resolution_count
        && strcmp(fmt1.description, fmt2.description) == 0)
    {
        return true;
    }

    return false;
}

bool tcam::is_smaller(const tcam_image_size &s1, const tcam_image_size &s2)
{
    if (s1.height <= s2.height && s1.width <= s2.width)
    {
        return true;
    }
    return false;
};

TCAM_PROPERTY_ID tcam::generate_unique_property_id ()
{
    static unsigned int id_to_use;
    static unsigned int id_prefix = 0x199f0000;

    TCAM_PROPERTY_ID new_id = id_prefix ^ id_to_use;
    id_to_use++;
    return new_id;
}
<commit_msg>Add missing include<commit_after>/*
 * Copyright 2014 The Imaging Source Europe GmbH
 *
 * 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 "utils.h"

#include "internal.h"

#include <algorithm>
#include <cstring>
#include <sys/ioctl.h>
#include <errno.h>
#include <limits>
#include <cmath>

#define IOCTL_RETRY 4

using namespace tcam;

std::string tcam::propertyType2String (TCAM_PROPERTY_TYPE type)
{
    switch (type)
    {
        case TCAM_PROPERTY_TYPE_BOOLEAN: return "BOOLEAN";
        case TCAM_PROPERTY_TYPE_INTEGER: return "INTEGER";
        case TCAM_PROPERTY_TYPE_DOUBLE: return "DOUBLE";
        case TCAM_PROPERTY_TYPE_STRING: return "STRING";
        case TCAM_PROPERTY_TYPE_ENUMERATION: return "ENUMERATION";
        case TCAM_PROPERTY_TYPE_BUTTON: return "BUTTON";
        case TCAM_PROPERTY_TYPE_UNKNOWN:
        default:
            return "";
    }
}

std::vector<std::string> tcam::split_string (const std::string& to_split, const std::string &delim)
{
    std::vector<std::string> vec;

    size_t beg = 0;
    size_t end = 0;

    while (end != std::string::npos)
    {
        end = to_split.find_first_of(delim, beg);

        std::string s = to_split.substr(beg, end - beg);

        vec.push_back(s);

        beg = end + delim.size();
    }

    return vec;
}

int tcam::tcam_xioctl (int fd, int request, void *arg)
{
    int ret = 0;
    int tries= IOCTL_RETRY;
    do
    {
        ret = ioctl(fd, request, arg);
        // ret = v4l2_ioctl(fd, request, arg);
    }
    while (ret && tries-- &&
           ((errno == EINTR) || (errno == EAGAIN) || (errno == ETIMEDOUT)));

    if (ret && (tries <= 0))
    {
        tcam_log(TCAM_LOG_ERROR,"ioctl (%i) retried %i times - giving up: %s)\n", request, IOCTL_RETRY, strerror(errno));
    }

    return (ret);

}

std::vector<double> tcam::create_steps_for_range (double min, double max)
{
    std::vector<double> vec;

    if (max <= min)
        return vec;

    vec.push_back(min);

    // we do not want every framerate to have unnecessary decimals
    // e.g. 1.345678 instead of 1.00000
    double current_step = (int)min;

    // 0.0 is not a valid framerate
    if (current_step < 1.0)
        current_step = 1.0;

    while (current_step < max)
    {
        vec.push_back(current_step);

        if (current_step < 20.0)
        {
            current_step += 1;
        }
        else if (current_step < 100.0)
        {
            current_step += 10.0;
        }
        else if (current_step < 1000.0)
        {
            current_step += 50.0;
        }
        else
        {
            current_step += 100.0;
        }
    }

    if (vec.back() != max)
    {
        vec.push_back(max);
    }
    return vec;
}

uint64_t tcam::get_buffer_length (unsigned int width, unsigned int height, uint32_t fourcc)
{
    if (width == 0 || height == 0 || fourcc == 0)
    {
        return 0;
    }

    uint64_t size = width * height * (img::get_bits_per_pixel(fourcc) / 8);

    return size;
}

unsigned int tcam::tcam_get_required_buffer_size (const struct tcam_video_format* format)
{
    if (format == nullptr)
    {
        return 0;
    }

    return get_buffer_length(format->width, format->height, format->fourcc);
}

uint32_t tcam::get_pitch_length (unsigned int width, uint32_t fourcc)
{
    if (width == 0 || fourcc == 0)
    {
        return 0;
    }

    return width * (img::get_bits_per_pixel(fourcc) / 8);
}

bool tcam::is_buffer_complete (const struct tcam_image_buffer* buffer)
{
    auto size = tcam::get_buffer_length(buffer->format.width,
                                        buffer->format.height,
                                        buffer->format.fourcc);

    if (size != buffer->length)
    {
        return false;
    }
    return true;
}

tcam_image_size tcam::calculate_auto_center (const tcam_image_size& sensor, const tcam_image_size& image)
{
    tcam_image_size ret = {};

    if (image.width > sensor.width || image.height > sensor.height)
    {
        return ret;
    }

    ret.width = (sensor.width / 2) - (image.width /2);
    ret.height = (sensor.height / 2) - (image.height / 2);

    return ret;
}

std::shared_ptr<Property> tcam::find_property (std::vector<std::shared_ptr<Property>>& properties,
                                               TCAM_PROPERTY_ID property_id)
{
    for (auto& p : properties)
    {
        if (p->get_ID() == property_id)
        {
            return p;
        }
    }

    return nullptr;
}

std::shared_ptr<Property> tcam::find_property (std::vector<std::shared_ptr<Property>>& properties,
                                               const std::string& property_name)
{

    auto f = [&property_name] (const std::shared_ptr<Property>& p)
        {
            if (p->get_name().compare(property_name) == 0)
                return true;
            return false;
        };

    auto iter = std::find_if(properties.begin(), properties.end(), f);

    if (iter != properties.end())
    {
        return *iter;
    }

    return nullptr;
}

bool tcam::compare_double (double val1, double val2)
{
    return std::fabs(val1 - val2) < std::numeric_limits<double>::epsilon();
}

bool tcam::are_equal (const tcam_image_size& s1,
                      const tcam_image_size& s2)
{
    if (s1.height == s2.height
        && s1.width == s2.width)
    {
        return true;
    }
    return false;
}

bool tcam::are_equal (const struct tcam_resolution_description& res1,
                      const struct tcam_resolution_description& res2)
{
    if (res1.type == res2.type
        && res1.framerate_count == res2.framerate_count
        && are_equal(res1.max_size, res2.max_size)
        && are_equal(res1.min_size,res2.min_size))
    {
        return true;
    }

    return false;
}

bool tcam::are_equal (const struct tcam_video_format_description& fmt1,
                      const struct tcam_video_format_description& fmt2)
{
    if (fmt1.fourcc == fmt2.fourcc
        && fmt1.binning == fmt2.binning
        && fmt1.skipping == fmt2.skipping
        && fmt1.resolution_count == fmt2.resolution_count
        && strcmp(fmt1.description, fmt2.description) == 0)
    {
        return true;
    }

    return false;
}

bool tcam::is_smaller(const tcam_image_size &s1, const tcam_image_size &s2)
{
    if (s1.height <= s2.height && s1.width <= s2.width)
    {
        return true;
    }
    return false;
};

TCAM_PROPERTY_ID tcam::generate_unique_property_id ()
{
    static unsigned int id_to_use;
    static unsigned int id_prefix = 0x199f0000;

    TCAM_PROPERTY_ID new_id = id_prefix ^ id_to_use;
    id_to_use++;
    return new_id;
}
<|endoftext|>


<commit_before>#ifndef LYZA_JSON_VALUE__
# define LYZA_JSON_VALUE__

# include <map>
# include <string>
# include <vector>
# include <sstream>

# include "fct/variant.hpp"

namespace lyza { namespace json {

class value {
	public:
		class null {};
		typedef bool boolean;
		typedef double number;
		typedef std::string string;
		typedef std::vector<value> array;
		typedef std::map<std::string, value> object;

	public:
		value()
			: var_(null())
		{
		}

	private:
		struct string_visitor {
			typedef std::string ret_type;

			ret_type operator()(null) const
			{
				return "null";
			}

			ret_type operator()(bool b) const
			{
				return b ? "true" : "false";
			}

			ret_type operator()(double d) const
			{
				std::ostringstream ss;

				ss << d;
				return ss.str();
			}

			ret_type operator()(std::string const& s) const
			{
				return "\"" + s + "\"";
			}

			ret_type operator()(std::vector<value> const& v) const
			{
				bool first = true;
				std::string acc;

				acc += "[";
				for (auto& it : v) {
					if (!first)
						acc += ",";
					else
						first = false;
					acc += it.to_string();
				}
				acc += "]";

				return acc;
			}

			ret_type operator()(std::map<std::string, value> const& m) const
			{
				bool first = true;
				std::string acc;

				acc += "{";
				for (auto& it : m) {
					if (!first)
						acc += ",";
					else
						first = false;
					acc += "\"" + it.first + "\"" + ":" + it.second.to_string();
				}
				acc += "}";

				return acc;
			}
		};

	public:
# define DEF_CTOR(T)\
		value(T const& t) : var_(t) { }\
		value(T&& t) : var_(std::move(t)) { }

		DEF_CTOR(null)
		DEF_CTOR(array)
		DEF_CTOR(string)
		DEF_CTOR(object)

		value(int i) : var_(static_cast<number>(i)) { }
		value(number d) : var_(d) { }
		value(boolean b) : var_(b) { }

		value(const char* s)
			: var_(string(s))
		{
		}

		value(value const& v)
			: var_(v.var_)
		{
		}

		value(value&& v)
			: var_(std::move(v.var_))
		{
		}

	public:
# define DEF_OP(T)\
		value& operator=(T const& t) { var_ = t; return *this; }\
		value& operator=(T&& t) { var_ = std::move(t); return *this; }

		DEF_OP(null)
		DEF_OP(array)
		DEF_OP(string)
		DEF_OP(object)

		value& operator=(int i)
		{
			var_ = static_cast<number>(i);
			return *this;
		}

		value& operator=(number d)
		{
			var_ = d;
			return *this;
		}

		value& operator=(const char* s)
		{
			var_ = string(s);
			return *this;
		}

		value& operator=(value const& v)
		{
			var_ = v.var_;
			return *this;
		}

		value& operator=(value&& v)
		{
			var_ = std::move(v.var_);
			return *this;
		}

	public:
		std::string to_string() const
		{
			return var_.apply_visitor(string_visitor());
		}

		static std::string to_string(value const& v)
		{
			return v.var_.apply_visitor(string_visitor());
		}

	public:
		typedef
			functional::variant<
				null,
				std::vector<value>,
				bool,
				std::string,
				number,
				std::map<std::string, value>
			> t;

	private:
		t var_;
};

typedef value::object object;
typedef value::boolean boolean;
typedef value::string string;
typedef value::number number;
typedef value::array array;
typedef value::null null;

}}

#endif
<commit_msg>Add to_string method for every ctors in variant<commit_after>#ifndef LYZA_JSON_VALUE__
# define LYZA_JSON_VALUE__

# include <map>
# include <string>
# include <vector>
# include <sstream>

# include "fct/variant.hpp"

namespace lyza { namespace json {

class value {
	public:
		class null {};
		typedef bool boolean;
		typedef double number;
		typedef std::string string;
		typedef std::vector<value> array;
		typedef std::map<std::string, value> object;

	public:
		value()
			: var_(null())
		{
		}

	private:
		struct string_visitor {
			typedef std::string ret_type;

			ret_type operator()(null) const
			{
				return "null";
			}

			ret_type operator()(bool b) const
			{
				return b ? "true" : "false";
			}

			ret_type operator()(double d) const
			{
				std::ostringstream ss;

				ss << d;
				return ss.str();
			}

			ret_type operator()(std::string const& s) const
			{
				return "\"" + s + "\"";
			}

			ret_type operator()(std::vector<value> const& v) const
			{
				bool first = true;
				std::string acc;

				acc += "[";
				for (auto& it : v) {
					if (!first)
						acc += ",";
					else
						first = false;
					acc += to_string(it);
				}
				acc += "]";

				return acc;
			}

			ret_type operator()(std::map<std::string, value> const& m) const
			{
				bool first = true;
				std::string acc;

				acc += "{";
				for (auto& it : m) {
					if (!first)
						acc += ",";
					else
						first = false;
					acc += "\"" + it.first + "\"" + ":" + to_string(it.second);
				}
				acc += "}";

				return acc;
			}
		};

	public:
# define DEF_CTOR(T)\
		value(T const& t) : var_(t) { }\
		value(T&& t) : var_(std::move(t)) { }

		DEF_CTOR(null)
		DEF_CTOR(array)
		DEF_CTOR(string)
		DEF_CTOR(object)

		value(int i) : var_(static_cast<number>(i)) { }
		value(number d) : var_(d) { }
		value(boolean b) : var_(b) { }

		value(const char* s)
			: var_(string(s))
		{
		}

		value(value const& v)
			: var_(v.var_)
		{
		}

		value(value&& v)
			: var_(std::move(v.var_))
		{
		}

	public:
# define DEF_OP(T)\
		value& operator=(T const& t) { var_ = t; return *this; }\
		value& operator=(T&& t) { var_ = std::move(t); return *this; }

		DEF_OP(null)
		DEF_OP(array)
		DEF_OP(string)
		DEF_OP(object)

		value& operator=(int i)
		{
			var_ = static_cast<number>(i);
			return *this;
		}

		value& operator=(number d)
		{
			var_ = d;
			return *this;
		}

		value& operator=(const char* s)
		{
			var_ = string(s);
			return *this;
		}

		value& operator=(value const& v)
		{
			var_ = v.var_;
			return *this;
		}

		value& operator=(value&& v)
		{
			var_ = std::move(v.var_);
			return *this;
		}

	private:
		static string_visitor& get_visitor()
		{
			static string_visitor v;
			return v;
		}

	public:
		static std::string to_string(value const& v)
		{
			return v.var_.apply_visitor(get_visitor());
		}

		template <typename T>
		static std::string to_string(T const& v)
		{
			return get_visitor()(v);
		}

	public:
		typedef
			functional::variant<
				null,
				std::vector<value>,
				bool,
				std::string,
				number,
				std::map<std::string, value>
			> t;

	private:
		t var_;
};

typedef value::object object;
typedef value::boolean boolean;
typedef value::string string;
typedef value::number number;
typedef value::array array;
typedef value::null null;

}}

#endif
<|endoftext|>


<commit_before>/*
 * Copyright © 2008, 2009 Intel Corporation
 *
 * Permission is hereby granted, free of charge, to any person obtaining a
 * copy of this software and associated documentation files (the "Software"),
 * to deal in the Software without restriction, including without limitation
 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
 * and/or sell copies of the Software, and to permit persons to whom the
 * Software is furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice (including the next
 * paragraph) shall be included in all copies or substantial portions of the
 * Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
 * DEALINGS IN THE SOFTWARE.
 */
#include <stdio.h>
#include <stdarg.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>

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

#include "ast.h"
#include "glsl_parser_extras.h"
#include "glsl_parser.h"
#include "ir_print_visitor.h"

void
_mesa_glsl_error(YYLTYPE *locp, _mesa_glsl_parse_state *state,
		 const char *fmt, ...)
{
   char buf[1024];
   int len;
   va_list ap;

   state->error = true;

   len = snprintf(buf, sizeof(buf), "%u:%u(%u): error: ",
		  locp->source, locp->first_line, locp->first_column);

   va_start(ap, fmt);
   vsnprintf(buf + len, sizeof(buf) - len, fmt, ap);
   va_end(ap);

   printf("%s\n", buf);
}

ast_node::~ast_node()
{
   /* empty */
}

void
_mesa_ast_type_qualifier_print(const struct ast_type_qualifier *q)
{
   if (q->constant)
      printf("const ");

   if (q->invariant)
      printf("invariant ");

   if (q->attribute)
      printf("attribute ");

   if (q->varying)
      printf("varying ");

   if (q->in && q->out)
      printf("inout ");
   else {
      if (q->in)
	 printf("in ");

      if (q->out)
	 printf("out ");
   }

   if (q->centroid)
      printf("centroid ");
   if (q->uniform)
      printf("uniform ");
   if (q->smooth)
      printf("smooth ");
   if (q->flat)
      printf("flat ");
   if (q->noperspective)
      printf("noperspective ");
}

void
ast_node::print(void) const
{
   printf("node_%d ", type);
}

ast_node::ast_node(void)
{
   make_empty_list(this);
}

static void
ast_opt_array_size_print(bool is_array, const ast_expression *array_size)
{
   if (is_array) {
      printf("[ ");

      if (array_size)
	 array_size->print();

      printf("] ");
   }
}

void
ast_compound_statement::print(void) const
{
   const struct simple_node *ptr;

   printf("{\n");

   foreach(ptr, & statements) {
      ((ast_node *)ptr)->print();
   }

   printf("}\n");
}

ast_compound_statement::ast_compound_statement(int new_scope,
					       ast_node *statements)
{
   this->new_scope = new_scope;
   make_empty_list(& this->statements);

   if (statements != NULL) {
      /* This seems odd, but it works.  The simple_list is,
       * basically, a circular list.  insert_at_tail adds
       * the specified node to the list before the current
       * head.
       */
      insert_at_tail((struct simple_node *) statements,
		     & this->statements);
   }
}

void
ast_expression::print(void) const
{
   switch (oper) {
   case ast_assign:
   case ast_mul_assign:
   case ast_div_assign:
   case ast_mod_assign:
   case ast_add_assign:
   case ast_sub_assign:
   case ast_ls_assign:
   case ast_rs_assign:
   case ast_and_assign:
   case ast_xor_assign:
   case ast_or_assign:
      subexpressions[0]->print();
      printf("%s ", operator_string(oper));
      subexpressions[1]->print();
      break;

   case ast_field_selection:
      subexpressions[0]->print();
      printf(". %s ", primary_expression.identifier);
      break;

   case ast_plus:
   case ast_neg:
   case ast_bit_not:
   case ast_logic_not:
   case ast_pre_inc:
   case ast_pre_dec:
      printf("%s ", operator_string(oper));
      subexpressions[0]->print();
      break;

   case ast_post_inc:
   case ast_post_dec:
      subexpressions[0]->print();
      printf("%s ", operator_string(oper));
      break;

   case ast_conditional:
      subexpressions[0]->print();
      printf("? ");
      subexpressions[1]->print();
      printf(": ");
      subexpressions[1]->print();
      break;

   case ast_array_index:
      subexpressions[0]->print();
      printf("[ ");
      subexpressions[1]->print();
      printf("] ");
      break;

   case ast_function_call: {
      ast_expression *parameters = subexpressions[1];

      subexpressions[0]->print();
      printf("( ");

      if (parameters != NULL) {
	 struct simple_node *ptr;

	 parameters->print();
	 foreach (ptr, (struct simple_node *) parameters) {
	    printf(", ");
	    ((ast_node *)ptr)->print();
	 }
      }

      printf(") ");
      break;
   }

   case ast_identifier:
      printf("%s ", primary_expression.identifier);
      break;

   case ast_int_constant:
      printf("%d ", primary_expression.int_constant);
      break;

   case ast_uint_constant:
      printf("%u ", primary_expression.uint_constant);
      break;

   case ast_float_constant:
      printf("%f ", primary_expression.float_constant);
      break;

   case ast_bool_constant:
      printf("%s ",
	     primary_expression.bool_constant
	     ? "true" : "false");
      break;

   case ast_sequence: {
      struct simple_node *ptr;
      struct simple_node *const head = first_elem(& expressions);

      printf("( ");
      foreach (ptr, & expressions) {
	 if (ptr != head)
	    printf(", ");

	 ((ast_node *)ptr)->print();
      }
      printf(") ");
      break;
   }

   default:
      assert(0);
      break;
   }
}

ast_expression::ast_expression(int oper,
			       ast_expression *ex0,
			       ast_expression *ex1,
			       ast_expression *ex2)
{
   this->oper = ast_operators(oper);
   this->subexpressions[0] = ex0;
   this->subexpressions[1] = ex1;
   this->subexpressions[2] = ex2;
   make_empty_list(& expressions);
}

void
ast_expression_statement::print(void) const
{
   if (expression)
      expression->print();

   printf("; ");
}

ast_expression_statement::ast_expression_statement(ast_expression *ex) :
   expression(ex)
{
   /* empty */
}

void
ast_function::print(void) const
{
   struct simple_node *ptr;

   return_type->print();
   printf(" %s (", identifier);

   foreach(ptr, & parameters) {
      ((ast_node *)ptr)->print();
   }

   printf(")");
}

ast_function::ast_function(void)
{
   make_empty_list(& parameters);
}

void
ast_fully_specified_type::print(void) const
{
   _mesa_ast_type_qualifier_print(& qualifier);
   specifier->print();
}

void
ast_parameter_declarator::print(void) const
{
   type->print();
   if (identifier)
      printf("%s ", identifier);
   ast_opt_array_size_print(is_array, array_size);
}

void
ast_function_definition::print(void) const
{
   prototype->print();
   body->print();
}

void
ast_declaration::print(void) const
{
   printf("%s ", identifier);
   ast_opt_array_size_print(is_array, array_size);

   if (initializer) {
      printf("= ");
      initializer->print();
   }
}

ast_declaration::ast_declaration(char *identifier, int is_array,
				 ast_expression *array_size,
				 ast_expression *initializer)
{
   this->identifier = identifier;
   this->is_array = is_array;
   this->array_size = array_size;
   this->initializer = initializer;
}

void
ast_declarator_list::print(void) const
{
   struct simple_node *head;
   struct simple_node *ptr;

   assert(type || invariant);

   if (type)
      type->print();
   else
      printf("invariant ");

   head = first_elem(& declarations);
   foreach (ptr, & declarations) {
      if (ptr != head)
	 printf(", ");

      ((ast_node *)ptr)->print();
   }

   printf("; ");
}

ast_declarator_list::ast_declarator_list(ast_fully_specified_type *type)
{
   this->type = type;
   make_empty_list(& this->declarations);
}

void
ast_jump_statement::print(void) const
{
   switch (mode) {
   case ast_continue:
      printf("continue; ");
      break;
   case ast_break:
      printf("break; ");
      break;
   case ast_return:
      printf("return ");
      if (opt_return_value)
	 opt_return_value->print();

      printf("; ");
      break;
   case ast_discard:
      printf("discard; ");
      break;
   }
}

ast_jump_statement::ast_jump_statement(int mode, ast_expression *return_value)
{
   this->mode = ast_jump_modes(mode);

   if (mode == ast_return)
      opt_return_value = return_value;
}

void
ast_selection_statement::print(void) const
{
   printf("if ( ");
   condition->print();
   printf(") ");

   then_statement->print();

   if (else_statement) {
      printf("else ");
      else_statement->print();
   }

}

ast_selection_statement::ast_selection_statement(ast_expression *condition,
						 ast_node *then_statement,
						 ast_node *else_statement)
{
   this->condition = condition;
   this->then_statement = then_statement;
   this->else_statement = else_statement;
}

void
ast_iteration_statement::print(void) const
{
   switch (mode) {
   case ast_for:
      printf("for( ");
      if (init_statement)
	 init_statement->print();
      printf("; ");

      if (condition)
	 condition->print();
      printf("; ");

      if (rest_expression)
	 rest_expression->print();
      printf(") ");

      body->print();
      break;

   case ast_while:
      printf("while ( ");
      if (condition)
	 condition->print();
      printf(") ");
      body->print();
      break;

   case ast_do_while:
      printf("do ");
      body->print();
      printf("while ( ");
      if (condition)
	 condition->print();
      printf("); ");
      break;
   }
}

ast_iteration_statement::ast_iteration_statement(int mode,
						 ast_node *init,
						 ast_node *condition,
						 ast_expression *rest_expression,
						 ast_node *body)
{
   this->mode = ast_iteration_modes(mode);
   this->init_statement = init;
   this->condition = condition;
   this->rest_expression = rest_expression;
   this->body = body;
}

void
ast_struct_specifier::print(void) const
{
   struct simple_node *ptr;

   printf("struct %s { ", name);
   foreach (ptr, & declarations) {
      ((ast_node *)ptr)->print();
   }
   printf("} ");
}

ast_struct_specifier::ast_struct_specifier(char *identifier,
					   ast_node *declarator_list)
{
   name = identifier;

   /* This seems odd, but it works.  The simple_list is,
    * basically, a circular list.  insert_at_tail adds
    * the specified node to the list before the current
    * head.
    */
   insert_at_tail((struct simple_node *) declarator_list,
		  & declarations);
}

static char *
load_text_file(const char *file_name, size_t *size)
{
	char *text = NULL;
	struct stat st;
	ssize_t total_read = 0;
	int fd = open(file_name, O_RDONLY);

	*size = 0;
	if (fd < 0) {
		return NULL;
	}

	if (fstat(fd, & st) == 0) {
	   text = (char *) malloc(st.st_size + 1);
		if (text != NULL) {
			do {
				ssize_t bytes = read(fd, text + total_read,
						     st.st_size - total_read);
				if (bytes < 0) {
					free(text);
					text = NULL;
					break;
				}

				if (bytes == 0) {
					break;
				}

				total_read += bytes;
			} while (total_read < st.st_size);

			text[total_read] = '\0';
			*size = total_read;
		}
	}

	close(fd);

	return text;
}

int
main(int argc, char **argv)
{
   struct _mesa_glsl_parse_state state;
   char *shader;
   size_t shader_len;
   struct simple_node *ptr;
   exec_list instructions;

   if (argc < 3) {
      printf("Usage: %s [v|g|f] <shader_file>\n", argv[0]);
      return EXIT_FAILURE;
   }

   switch (argv[1][0]) {
   case 'v':
      state.target = vertex_shader;
      break;
   case 'g':
      state.target = geometry_shader;
      break;
   case 'f':
      state.target = fragment_shader;
      break;
   default:
      printf("Usage: %s [v|g|f] <shader_file>\n", argv[0]);
      return EXIT_FAILURE;
   }

   shader = load_text_file(argv[2], & shader_len);

   state.scanner = NULL;
   make_empty_list(& state.translation_unit);
   state.symbols = new glsl_symbol_table;
   state.error = false;

   _mesa_glsl_lexer_ctor(& state, shader, shader_len);
   _mesa_glsl_parse(& state);
   _mesa_glsl_lexer_dtor(& state);

   foreach (ptr, & state.translation_unit) {
      ((ast_node *)ptr)->print();
   }

   _mesa_ast_to_hir(&instructions, &state);

   printf("\n\n");

   if (!state.error) {
      foreach_iter(exec_list_iterator, iter, instructions) {
	 ir_print_visitor v;

	 ((ir_instruction *)iter.get())->accept(& v);
      }
   }

   delete state.symbols;

   return 0;
}
<commit_msg>Make the standalone parser return an exit code so we can automate testing.<commit_after>/*
 * Copyright © 2008, 2009 Intel Corporation
 *
 * Permission is hereby granted, free of charge, to any person obtaining a
 * copy of this software and associated documentation files (the "Software"),
 * to deal in the Software without restriction, including without limitation
 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
 * and/or sell copies of the Software, and to permit persons to whom the
 * Software is furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice (including the next
 * paragraph) shall be included in all copies or substantial portions of the
 * Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
 * DEALINGS IN THE SOFTWARE.
 */
#include <stdio.h>
#include <stdarg.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>

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

#include "ast.h"
#include "glsl_parser_extras.h"
#include "glsl_parser.h"
#include "ir_print_visitor.h"

void
_mesa_glsl_error(YYLTYPE *locp, _mesa_glsl_parse_state *state,
		 const char *fmt, ...)
{
   char buf[1024];
   int len;
   va_list ap;

   state->error = true;

   len = snprintf(buf, sizeof(buf), "%u:%u(%u): error: ",
		  locp->source, locp->first_line, locp->first_column);

   va_start(ap, fmt);
   vsnprintf(buf + len, sizeof(buf) - len, fmt, ap);
   va_end(ap);

   printf("%s\n", buf);
}

ast_node::~ast_node()
{
   /* empty */
}

void
_mesa_ast_type_qualifier_print(const struct ast_type_qualifier *q)
{
   if (q->constant)
      printf("const ");

   if (q->invariant)
      printf("invariant ");

   if (q->attribute)
      printf("attribute ");

   if (q->varying)
      printf("varying ");

   if (q->in && q->out)
      printf("inout ");
   else {
      if (q->in)
	 printf("in ");

      if (q->out)
	 printf("out ");
   }

   if (q->centroid)
      printf("centroid ");
   if (q->uniform)
      printf("uniform ");
   if (q->smooth)
      printf("smooth ");
   if (q->flat)
      printf("flat ");
   if (q->noperspective)
      printf("noperspective ");
}

void
ast_node::print(void) const
{
   printf("node_%d ", type);
}

ast_node::ast_node(void)
{
   make_empty_list(this);
}

static void
ast_opt_array_size_print(bool is_array, const ast_expression *array_size)
{
   if (is_array) {
      printf("[ ");

      if (array_size)
	 array_size->print();

      printf("] ");
   }
}

void
ast_compound_statement::print(void) const
{
   const struct simple_node *ptr;

   printf("{\n");

   foreach(ptr, & statements) {
      ((ast_node *)ptr)->print();
   }

   printf("}\n");
}

ast_compound_statement::ast_compound_statement(int new_scope,
					       ast_node *statements)
{
   this->new_scope = new_scope;
   make_empty_list(& this->statements);

   if (statements != NULL) {
      /* This seems odd, but it works.  The simple_list is,
       * basically, a circular list.  insert_at_tail adds
       * the specified node to the list before the current
       * head.
       */
      insert_at_tail((struct simple_node *) statements,
		     & this->statements);
   }
}

void
ast_expression::print(void) const
{
   switch (oper) {
   case ast_assign:
   case ast_mul_assign:
   case ast_div_assign:
   case ast_mod_assign:
   case ast_add_assign:
   case ast_sub_assign:
   case ast_ls_assign:
   case ast_rs_assign:
   case ast_and_assign:
   case ast_xor_assign:
   case ast_or_assign:
      subexpressions[0]->print();
      printf("%s ", operator_string(oper));
      subexpressions[1]->print();
      break;

   case ast_field_selection:
      subexpressions[0]->print();
      printf(". %s ", primary_expression.identifier);
      break;

   case ast_plus:
   case ast_neg:
   case ast_bit_not:
   case ast_logic_not:
   case ast_pre_inc:
   case ast_pre_dec:
      printf("%s ", operator_string(oper));
      subexpressions[0]->print();
      break;

   case ast_post_inc:
   case ast_post_dec:
      subexpressions[0]->print();
      printf("%s ", operator_string(oper));
      break;

   case ast_conditional:
      subexpressions[0]->print();
      printf("? ");
      subexpressions[1]->print();
      printf(": ");
      subexpressions[1]->print();
      break;

   case ast_array_index:
      subexpressions[0]->print();
      printf("[ ");
      subexpressions[1]->print();
      printf("] ");
      break;

   case ast_function_call: {
      ast_expression *parameters = subexpressions[1];

      subexpressions[0]->print();
      printf("( ");

      if (parameters != NULL) {
	 struct simple_node *ptr;

	 parameters->print();
	 foreach (ptr, (struct simple_node *) parameters) {
	    printf(", ");
	    ((ast_node *)ptr)->print();
	 }
      }

      printf(") ");
      break;
   }

   case ast_identifier:
      printf("%s ", primary_expression.identifier);
      break;

   case ast_int_constant:
      printf("%d ", primary_expression.int_constant);
      break;

   case ast_uint_constant:
      printf("%u ", primary_expression.uint_constant);
      break;

   case ast_float_constant:
      printf("%f ", primary_expression.float_constant);
      break;

   case ast_bool_constant:
      printf("%s ",
	     primary_expression.bool_constant
	     ? "true" : "false");
      break;

   case ast_sequence: {
      struct simple_node *ptr;
      struct simple_node *const head = first_elem(& expressions);

      printf("( ");
      foreach (ptr, & expressions) {
	 if (ptr != head)
	    printf(", ");

	 ((ast_node *)ptr)->print();
      }
      printf(") ");
      break;
   }

   default:
      assert(0);
      break;
   }
}

ast_expression::ast_expression(int oper,
			       ast_expression *ex0,
			       ast_expression *ex1,
			       ast_expression *ex2)
{
   this->oper = ast_operators(oper);
   this->subexpressions[0] = ex0;
   this->subexpressions[1] = ex1;
   this->subexpressions[2] = ex2;
   make_empty_list(& expressions);
}

void
ast_expression_statement::print(void) const
{
   if (expression)
      expression->print();

   printf("; ");
}

ast_expression_statement::ast_expression_statement(ast_expression *ex) :
   expression(ex)
{
   /* empty */
}

void
ast_function::print(void) const
{
   struct simple_node *ptr;

   return_type->print();
   printf(" %s (", identifier);

   foreach(ptr, & parameters) {
      ((ast_node *)ptr)->print();
   }

   printf(")");
}

ast_function::ast_function(void)
{
   make_empty_list(& parameters);
}

void
ast_fully_specified_type::print(void) const
{
   _mesa_ast_type_qualifier_print(& qualifier);
   specifier->print();
}

void
ast_parameter_declarator::print(void) const
{
   type->print();
   if (identifier)
      printf("%s ", identifier);
   ast_opt_array_size_print(is_array, array_size);
}

void
ast_function_definition::print(void) const
{
   prototype->print();
   body->print();
}

void
ast_declaration::print(void) const
{
   printf("%s ", identifier);
   ast_opt_array_size_print(is_array, array_size);

   if (initializer) {
      printf("= ");
      initializer->print();
   }
}

ast_declaration::ast_declaration(char *identifier, int is_array,
				 ast_expression *array_size,
				 ast_expression *initializer)
{
   this->identifier = identifier;
   this->is_array = is_array;
   this->array_size = array_size;
   this->initializer = initializer;
}

void
ast_declarator_list::print(void) const
{
   struct simple_node *head;
   struct simple_node *ptr;

   assert(type || invariant);

   if (type)
      type->print();
   else
      printf("invariant ");

   head = first_elem(& declarations);
   foreach (ptr, & declarations) {
      if (ptr != head)
	 printf(", ");

      ((ast_node *)ptr)->print();
   }

   printf("; ");
}

ast_declarator_list::ast_declarator_list(ast_fully_specified_type *type)
{
   this->type = type;
   make_empty_list(& this->declarations);
}

void
ast_jump_statement::print(void) const
{
   switch (mode) {
   case ast_continue:
      printf("continue; ");
      break;
   case ast_break:
      printf("break; ");
      break;
   case ast_return:
      printf("return ");
      if (opt_return_value)
	 opt_return_value->print();

      printf("; ");
      break;
   case ast_discard:
      printf("discard; ");
      break;
   }
}

ast_jump_statement::ast_jump_statement(int mode, ast_expression *return_value)
{
   this->mode = ast_jump_modes(mode);

   if (mode == ast_return)
      opt_return_value = return_value;
}

void
ast_selection_statement::print(void) const
{
   printf("if ( ");
   condition->print();
   printf(") ");

   then_statement->print();

   if (else_statement) {
      printf("else ");
      else_statement->print();
   }

}

ast_selection_statement::ast_selection_statement(ast_expression *condition,
						 ast_node *then_statement,
						 ast_node *else_statement)
{
   this->condition = condition;
   this->then_statement = then_statement;
   this->else_statement = else_statement;
}

void
ast_iteration_statement::print(void) const
{
   switch (mode) {
   case ast_for:
      printf("for( ");
      if (init_statement)
	 init_statement->print();
      printf("; ");

      if (condition)
	 condition->print();
      printf("; ");

      if (rest_expression)
	 rest_expression->print();
      printf(") ");

      body->print();
      break;

   case ast_while:
      printf("while ( ");
      if (condition)
	 condition->print();
      printf(") ");
      body->print();
      break;

   case ast_do_while:
      printf("do ");
      body->print();
      printf("while ( ");
      if (condition)
	 condition->print();
      printf("); ");
      break;
   }
}

ast_iteration_statement::ast_iteration_statement(int mode,
						 ast_node *init,
						 ast_node *condition,
						 ast_expression *rest_expression,
						 ast_node *body)
{
   this->mode = ast_iteration_modes(mode);
   this->init_statement = init;
   this->condition = condition;
   this->rest_expression = rest_expression;
   this->body = body;
}

void
ast_struct_specifier::print(void) const
{
   struct simple_node *ptr;

   printf("struct %s { ", name);
   foreach (ptr, & declarations) {
      ((ast_node *)ptr)->print();
   }
   printf("} ");
}

ast_struct_specifier::ast_struct_specifier(char *identifier,
					   ast_node *declarator_list)
{
   name = identifier;

   /* This seems odd, but it works.  The simple_list is,
    * basically, a circular list.  insert_at_tail adds
    * the specified node to the list before the current
    * head.
    */
   insert_at_tail((struct simple_node *) declarator_list,
		  & declarations);
}

static char *
load_text_file(const char *file_name, size_t *size)
{
	char *text = NULL;
	struct stat st;
	ssize_t total_read = 0;
	int fd = open(file_name, O_RDONLY);

	*size = 0;
	if (fd < 0) {
		return NULL;
	}

	if (fstat(fd, & st) == 0) {
	   text = (char *) malloc(st.st_size + 1);
		if (text != NULL) {
			do {
				ssize_t bytes = read(fd, text + total_read,
						     st.st_size - total_read);
				if (bytes < 0) {
					free(text);
					text = NULL;
					break;
				}

				if (bytes == 0) {
					break;
				}

				total_read += bytes;
			} while (total_read < st.st_size);

			text[total_read] = '\0';
			*size = total_read;
		}
	}

	close(fd);

	return text;
}

int
main(int argc, char **argv)
{
   struct _mesa_glsl_parse_state state;
   char *shader;
   size_t shader_len;
   struct simple_node *ptr;
   exec_list instructions;

   if (argc < 3) {
      printf("Usage: %s [v|g|f] <shader_file>\n", argv[0]);
      return EXIT_FAILURE;
   }

   switch (argv[1][0]) {
   case 'v':
      state.target = vertex_shader;
      break;
   case 'g':
      state.target = geometry_shader;
      break;
   case 'f':
      state.target = fragment_shader;
      break;
   default:
      printf("Usage: %s [v|g|f] <shader_file>\n", argv[0]);
      return EXIT_FAILURE;
   }

   shader = load_text_file(argv[2], & shader_len);

   state.scanner = NULL;
   make_empty_list(& state.translation_unit);
   state.symbols = new glsl_symbol_table;
   state.error = false;

   _mesa_glsl_lexer_ctor(& state, shader, shader_len);
   _mesa_glsl_parse(& state);
   _mesa_glsl_lexer_dtor(& state);

   foreach (ptr, & state.translation_unit) {
      ((ast_node *)ptr)->print();
   }

   _mesa_ast_to_hir(&instructions, &state);

   printf("\n\n");

   if (!state.error) {
      foreach_iter(exec_list_iterator, iter, instructions) {
	 ir_print_visitor v;

	 ((ir_instruction *)iter.get())->accept(& v);
      }
   }

   delete state.symbols;

   return state.error != 0;
}
<|endoftext|>


<commit_before>#include "MemcachedCache.h"

#include <libmemcached/memcached.h>

#include <QtEndian>
#include <QCoreApplication>
#include <QDebug>
#include <QReadLocker>
#include <QSettings>
#include <QStringList>
#include <QWriteLocker>

namespace FastCgiQt
{
	QReadWriteLock MemcachedCache::m_lock(QReadWriteLock::Recursive);

	MemcachedCache::MemcachedCache(const QString& cacheName)
		:
			m_memcached(memcached_create(NULL)),
			m_keyPrefix(cacheName + "::")
	{
		memcached_return rt;

		rt = memcached_server_add(m_memcached, "localhost", MEMCACHED_DEFAULT_PORT);
		Q_ASSERT(rt == MEMCACHED_SUCCESS);
	}

	MemcachedCache::~MemcachedCache()
	{
		memcached_free(m_memcached);
	}

	CacheBackend* MemcachedCacheFactory::getCacheBackend(const QString& cacheName) const
	{
		return new MemcachedCache(cacheName);
	}

	bool MemcachedCacheFactory::loadSettings()
	{
		QSettings settings(
			"." + QCoreApplication::applicationFilePath().split('/').last(),
			QSettings::IniFormat
		);
		if(settings.value("cache/backend") == "MemcachedCache")
		{
			return true;
		}
		return false;
	}

	CacheEntry MemcachedCache::value(const QString& key) const
	{
		QReadLocker lock(&m_lock);

		const QByteArray rawKey(key.toUtf8());

		char* rawData;
		size_t rawDataLength;
		uint32_t flags;
		memcached_return rt;

		rawData = memcached_get(
			m_memcached,
			rawKey.constData(),
			rawKey.length(),
			&rawDataLength,
			&flags,
			&rt
		);

		Q_ASSERT(rawDataLength >= sizeof(quint64) || !rawData);
		if(rawDataLength < sizeof(quint64) || !rawData)
		{
			return CacheEntry();
		}

		const quint64 timeStamp = qFromLittleEndian(*reinterpret_cast<quint64*>(rawData));
		const QByteArray data(rawData + sizeof(quint64), rawDataLength - sizeof(quint64));
		return CacheEntry(QDateTime::fromTime_t(timeStamp), data);
	}

	QReadWriteLock* MemcachedCache::readWriteLock() const
	{
		return &m_lock;
	}

	void MemcachedCache::setValue(const QString& key, const CacheEntry& entry)
	{
		QWriteLocker lock(&m_lock);

		// Binary key
		const QByteArray rawKey(key.toUtf8());

		// Binary data
		const quint64 dateTime(qToLittleEndian(static_cast<quint64>(entry.timeStamp().toTime_t())));
		QByteArray rawData(reinterpret_cast<const char*>(&dateTime), sizeof(quint64));
		rawData.append(entry.data());

		// Store in memcached
		memcached_return rt;
		rt = memcached_set(
			m_memcached,
			rawKey.constData(),
			rawKey.length(),
			rawData.constData(),
			rawData.length(),
			0, // expire
			0 // flags
		);
		Q_ASSERT(rt == MEMCACHED_SUCCESS);
	}

	void MemcachedCache::remove(const QString& key)
	{
		Q_UNUSED(key);
		QWriteLocker lock(&m_lock);
	}
}

Q_EXPORT_PLUGIN2(FastCgiQt_MemcachedCache, FastCgiQt::MemcachedCacheFactory)
<commit_msg>add organisation domain and application name to keying for memcached<commit_after>#include "MemcachedCache.h"

#include <libmemcached/memcached.h>

#include <QtEndian>
#include <QCoreApplication>
#include <QDebug>
#include <QReadLocker>
#include <QSettings>
#include <QStringList>
#include <QWriteLocker>

namespace FastCgiQt
{
	QReadWriteLock MemcachedCache::m_lock(QReadWriteLock::Recursive);

	MemcachedCache::MemcachedCache(const QString& cacheName)
		:
			m_memcached(memcached_create(NULL)),
			m_keyPrefix(QCoreApplication::organizationDomain() + '/' + QCoreApplication::applicationName() + '/' + cacheName + '/')
	{
		memcached_return rt;

		rt = memcached_server_add(m_memcached, "localhost", MEMCACHED_DEFAULT_PORT);
		Q_ASSERT(rt == MEMCACHED_SUCCESS);
	}

	MemcachedCache::~MemcachedCache()
	{
		memcached_free(m_memcached);
	}

	CacheBackend* MemcachedCacheFactory::getCacheBackend(const QString& cacheName) const
	{
		return new MemcachedCache(cacheName);
	}

	bool MemcachedCacheFactory::loadSettings()
	{
		QSettings settings(
			"." + QCoreApplication::applicationFilePath().split('/').last(),
			QSettings::IniFormat
		);
		if(settings.value("cache/backend") == "MemcachedCache")
		{
			return true;
		}
		return false;
	}

	CacheEntry MemcachedCache::value(const QString& key) const
	{
		QReadLocker lock(&m_lock);

		const QByteArray rawKey(key.toUtf8());

		char* rawData;
		size_t rawDataLength;
		uint32_t flags;
		memcached_return rt;

		rawData = memcached_get(
			m_memcached,
			rawKey.constData(),
			rawKey.length(),
			&rawDataLength,
			&flags,
			&rt
		);

		Q_ASSERT(rawDataLength >= sizeof(quint64) || !rawData);
		if(rawDataLength < sizeof(quint64) || !rawData)
		{
			return CacheEntry();
		}

		const quint64 timeStamp = qFromLittleEndian(*reinterpret_cast<quint64*>(rawData));
		const QByteArray data(rawData + sizeof(quint64), rawDataLength - sizeof(quint64));
		return CacheEntry(QDateTime::fromTime_t(timeStamp), data);
	}

	QReadWriteLock* MemcachedCache::readWriteLock() const
	{
		return &m_lock;
	}

	void MemcachedCache::setValue(const QString& key, const CacheEntry& entry)
	{
		QWriteLocker lock(&m_lock);

		// Binary key
		const QByteArray rawKey(key.toUtf8());

		// Binary data
		const quint64 dateTime(qToLittleEndian(static_cast<quint64>(entry.timeStamp().toTime_t())));
		QByteArray rawData(reinterpret_cast<const char*>(&dateTime), sizeof(quint64));
		rawData.append(entry.data());

		// Store in memcached
		memcached_return rt;
		rt = memcached_set(
			m_memcached,
			rawKey.constData(),
			rawKey.length(),
			rawData.constData(),
			rawData.length(),
			0, // expire
			0 // flags
		);
		Q_ASSERT(rt == MEMCACHED_SUCCESS);
	}

	void MemcachedCache::remove(const QString& key)
	{
		Q_UNUSED(key);
		QWriteLocker lock(&m_lock);
	}
}

Q_EXPORT_PLUGIN2(FastCgiQt_MemcachedCache, FastCgiQt::MemcachedCacheFactory)
<|endoftext|>


<commit_before>#include <gtk/gtk.h>
#include <webkit/webkit.h>
#include <webkit/webkitwebview.h>

// stl for n00b debugging :)
#include <sstream>
#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
// std::clog << "debug output";

GtkWidget *window;
GtkWidget *scrolled_window;
GtkWidget *web_view;

void destroy (void)
{
  gtk_main_quit ();
}

void title_change (void)
{
  gtk_window_set_title(GTK_WINDOW (window), webkit_web_view_get_title(WEBKIT_WEB_VIEW (web_view)));
}

void new_window (
  WebKitWebView *web_view,
  WebKitWebFrame *frame,
  WebKitNetworkRequest *request)
{
  gchar *argv[3];
  argv[0] = const_cast<char*>("/usr/bin/xdg-open");
  argv[1] = const_cast<char*>(webkit_network_request_get_uri(request));
  argv[2] = NULL;
  g_spawn_async(NULL, argv, NULL, G_SPAWN_LEAVE_DESCRIPTORS_OPEN, NULL, NULL, NULL, NULL);
}

static gboolean download (
  WebKitWebView *web_view,
  WebKitWebFrame *frame,
  WebKitNetworkRequest *request,
  const char *mime_type,
  WebKitWebPolicyDecision *decision,
  gpointer user_data)
{
  // Any other mime types we should handle?
  if (strcmp(mime_type, "application/octet-stream") == 0) {
    WebKitDownload *download = webkit_download_new(request);
    GtkWidget *window = gtk_widget_get_toplevel (GTK_WIDGET(web_view));
    GtkWidget *dialog = gtk_file_chooser_dialog_new ("Save file",
      GTK_WINDOW(window),
      GTK_FILE_CHOOSER_ACTION_SAVE,
      GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
      GTK_STOCK_SAVE, GTK_RESPONSE_ACCEPT,
      NULL);
    gtk_file_chooser_set_do_overwrite_confirmation (GTK_FILE_CHOOSER (dialog), TRUE);
    gtk_file_chooser_set_current_name (GTK_FILE_CHOOSER (dialog), webkit_download_get_suggested_filename(download));

    // @TODO getting a warning 'Unable to retrieve the file info' for the
    // file as it does not exist yet... track down why?
    if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_ACCEPT) {
      gchar *destination = g_filename_to_uri(gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (dialog)), NULL, NULL);
      webkit_download_set_destination_uri (download, destination);
      webkit_download_start(download);
      g_free(destination);
    } else {
      webkit_download_cancel(download);
      g_object_unref(download);
    }

    gtk_widget_destroy (dialog);
    webkit_web_policy_decision_ignore(decision);
  }
  return TRUE;
}

int main(int argc, char* argv[])
{
  static gchar *url = const_cast<char*>("http://google.com");
  static gchar *name = const_cast<char*>("TopCube");
  static gint width = 800;
  static gint height = 600;
  static gint minwidth = 600;
  static gint minheight = 400;
  static GOptionEntry entries[] = {
    { "url", 'u', 0, G_OPTION_ARG_STRING, &url, "URL" },
    { "name", 'n', 0, G_OPTION_ARG_STRING, &name, "Window name" },
    { "width", 'W', 0, G_OPTION_ARG_INT, &width, "Width" },
    { "height", 'H', 0, G_OPTION_ARG_INT, &height, "Height" },
    { "minwidth", 'w', 0, G_OPTION_ARG_INT, &minwidth, "Minimum width" },
    { "minheight", 'h', 0, G_OPTION_ARG_INT, &minheight, "Minimum height" }
  };
  GError *error = NULL;
  GOptionContext *options;
  options = g_option_context_new("topcube options");
  g_option_context_add_main_entries (options, entries, NULL);
  g_option_context_add_group (options, gtk_get_option_group(TRUE));
  if (!g_option_context_parse (options, &argc, &argv, &error)) {
    g_print ("Error parsing options: %s\n", error->message);
    exit (1);
  }

  gtk_init (&argc, &argv);
  window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
  scrolled_window = gtk_scrolled_window_new (NULL, NULL);
  web_view = webkit_web_view_new ();

  gtk_signal_connect (GTK_OBJECT (window), "destroy", GTK_SIGNAL_FUNC (destroy), NULL);
  gtk_signal_connect (GTK_OBJECT (web_view), "title-changed", GTK_SIGNAL_FUNC (title_change), NULL);
  gtk_signal_connect (GTK_OBJECT (web_view), "mime-type-policy-decision-requested", GTK_SIGNAL_FUNC (download), NULL);
  gtk_signal_connect (GTK_OBJECT (web_view), "new-window-policy-decision-requested", GTK_SIGNAL_FUNC (new_window), NULL);

  gtk_container_add (GTK_CONTAINER (scrolled_window), web_view);
  gtk_container_add (GTK_CONTAINER (window), scrolled_window);

  webkit_web_view_load_uri (WEBKIT_WEB_VIEW (web_view), url);

  gtk_window_set_wmclass (GTK_WINDOW (window), name, name);
  gtk_window_set_default_size (GTK_WINDOW (window), width, height);

  GdkGeometry hints;
  hints.min_width = minwidth;
  hints.min_height = minheight;
  gtk_window_set_geometry_hints(GTK_WINDOW (window), GTK_WIDGET (scrolled_window), &hints, GDK_HINT_MIN_SIZE);

  gtk_widget_grab_focus (GTK_WIDGET(web_view));
  gtk_widget_show_all (window);
  gtk_main ();

  return 0;
}

<commit_msg>Disable right click menus in gtkwebkit client.<commit_after>#include <gtk/gtk.h>
#include <webkit/webkit.h>
#include <webkit/webkitwebview.h>

// stl for n00b debugging :)
#include <sstream>
#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
// std::clog << "debug output";

GtkWidget *window;
GtkWidget *scrolled_window;
GtkWidget *web_view;
WebKitWebSettings *settings;

void destroy (void)
{
  gtk_main_quit ();
}

void title_change (void)
{
  gtk_window_set_title(GTK_WINDOW (window), webkit_web_view_get_title(WEBKIT_WEB_VIEW (web_view)));
}

void new_window (
  WebKitWebView *web_view,
  WebKitWebFrame *frame,
  WebKitNetworkRequest *request)
{
  gchar *argv[3];
  argv[0] = const_cast<char*>("/usr/bin/xdg-open");
  argv[1] = const_cast<char*>(webkit_network_request_get_uri(request));
  argv[2] = NULL;
  g_spawn_async(NULL, argv, NULL, G_SPAWN_LEAVE_DESCRIPTORS_OPEN, NULL, NULL, NULL, NULL);
}

static gboolean download (
  WebKitWebView *web_view,
  WebKitWebFrame *frame,
  WebKitNetworkRequest *request,
  const char *mime_type,
  WebKitWebPolicyDecision *decision,
  gpointer user_data)
{
  // Any other mime types we should handle?
  if (strcmp(mime_type, "application/octet-stream") == 0) {
    WebKitDownload *download = webkit_download_new(request);
    GtkWidget *window = gtk_widget_get_toplevel (GTK_WIDGET(web_view));
    GtkWidget *dialog = gtk_file_chooser_dialog_new ("Save file",
      GTK_WINDOW(window),
      GTK_FILE_CHOOSER_ACTION_SAVE,
      GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
      GTK_STOCK_SAVE, GTK_RESPONSE_ACCEPT,
      NULL);
    gtk_file_chooser_set_do_overwrite_confirmation (GTK_FILE_CHOOSER (dialog), TRUE);
    gtk_file_chooser_set_current_name (GTK_FILE_CHOOSER (dialog), webkit_download_get_suggested_filename(download));

    // @TODO getting a warning 'Unable to retrieve the file info' for the
    // file as it does not exist yet... track down why?
    if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_ACCEPT) {
      gchar *destination = g_filename_to_uri(gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (dialog)), NULL, NULL);
      webkit_download_set_destination_uri (download, destination);
      webkit_download_start(download);
      g_free(destination);
    } else {
      webkit_download_cancel(download);
      g_object_unref(download);
    }

    gtk_widget_destroy (dialog);
    webkit_web_policy_decision_ignore(decision);
  }
  return TRUE;
}

int main(int argc, char* argv[])
{
  static gchar *url = const_cast<char*>("http://google.com");
  static gchar *name = const_cast<char*>("TopCube");
  static gint width = 800;
  static gint height = 600;
  static gint minwidth = 600;
  static gint minheight = 400;
  static GOptionEntry entries[] = {
    { "url", 'u', 0, G_OPTION_ARG_STRING, &url, "URL" },
    { "name", 'n', 0, G_OPTION_ARG_STRING, &name, "Window name" },
    { "width", 'W', 0, G_OPTION_ARG_INT, &width, "Width" },
    { "height", 'H', 0, G_OPTION_ARG_INT, &height, "Height" },
    { "minwidth", 'w', 0, G_OPTION_ARG_INT, &minwidth, "Minimum width" },
    { "minheight", 'h', 0, G_OPTION_ARG_INT, &minheight, "Minimum height" }
  };
  GError *error = NULL;
  GOptionContext *options;
  options = g_option_context_new("topcube options");
  g_option_context_add_main_entries (options, entries, NULL);
  g_option_context_add_group (options, gtk_get_option_group(TRUE));
  if (!g_option_context_parse (options, &argc, &argv, &error)) {
    g_print ("Error parsing options: %s\n", error->message);
    exit (1);
  }

  gtk_init (&argc, &argv);
  window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
  scrolled_window = gtk_scrolled_window_new (NULL, NULL);
  web_view = webkit_web_view_new ();

  // Modify default settings - disable right click menus.
  settings = webkit_web_view_get_settings (WEBKIT_WEB_VIEW(web_view));
  g_object_set(settings, "enable-default-context-menu", FALSE, NULL);

  gtk_signal_connect (GTK_OBJECT (window), "destroy", GTK_SIGNAL_FUNC (destroy), NULL);
  gtk_signal_connect (GTK_OBJECT (web_view), "title-changed", GTK_SIGNAL_FUNC (title_change), NULL);
  gtk_signal_connect (GTK_OBJECT (web_view), "mime-type-policy-decision-requested", GTK_SIGNAL_FUNC (download), NULL);
  gtk_signal_connect (GTK_OBJECT (web_view), "new-window-policy-decision-requested", GTK_SIGNAL_FUNC (new_window), NULL);

  gtk_container_add (GTK_CONTAINER (scrolled_window), web_view);
  gtk_container_add (GTK_CONTAINER (window), scrolled_window);

  webkit_web_view_load_uri (WEBKIT_WEB_VIEW (web_view), url);

  gtk_window_set_wmclass (GTK_WINDOW (window), name, name);
  gtk_window_set_default_size (GTK_WINDOW (window), width, height);

  GdkGeometry hints;
  hints.min_width = minwidth;
  hints.min_height = minheight;
  gtk_window_set_geometry_hints(GTK_WINDOW (window), GTK_WIDGET (scrolled_window), &hints, GDK_HINT_MIN_SIZE);

  gtk_widget_grab_focus (GTK_WIDGET(web_view));
  gtk_widget_show_all (window);
  gtk_main ();

  return 0;
}

<|endoftext|>