<commit_before>#ifndef UTIL_BOX_H__
#define UTIL_BOX_H__

#include <sstream>
#include <iostream>
#include <type_traits>

#include "point.hpp"

namespace util {

// forward declaration
template <typename T, int N>
class box;

template <typename Derived, typename T, int N>
class box_base {

public:

	/**
	 * Default constructor.
	 */
	box_base() {}

	template <typename S>
	box_base(const point<S,N>& min, const point<S,N>& max) :
		_min(min),
		_max(max) {}

	template <typename D,typename S>
	box_base(const box_base<D,S,N>& other) :
		_min(other.min()),
		_max(other.max()) {}

	template <typename S>
	operator box<S,N>() const { return box<S,N>(_min, _max); }

	const point<T,N>& min() const { return _min; }
	point<T,N>& min() { return _min; }
	const point<T,N>& max() const { return _max; }
	point<T,N>& max() { return _max; }

	bool valid() { return isZero(); }

	template <typename D, typename S>
	bool intersects(const box_base<D,S,N>& other) const {

		// empty boxes do not intersect
		if (isZero() || other.isZero())
			return false;

		// two non-intersecting boxes are separated by a plane parallel to
		// either dimension

		for (int i = 0; i < N; i++)
			if (max()[i] <= other.min()[i] || min()[i] >= other.max()[i])
				return false;

		return true;
	}

	template <typename D, typename S>
	Derived intersection(const box_base<D,S,N>& other) const {

		Derived result;

		if (!intersects(other))
			return result;

		for (int i = 0; i < N; i++) {

			result.min()[i] = std::max(min()[i], other.min()[i]);
			result.max()[i] = std::min(max()[i], other.max()[i]);
		}

		return result;
	}

	template <typename S, int M>
	bool contains(const point<S,M>& point) const {

		for (int i = 0; i < std::min(N, M); i++)
			if (max()[i] <= point[i] || min()[i] > point[i])
				return false;

		return true;
	}

	/**
	 * Extend this box, such that it fits the given point.
	 */
	template <typename S>
	void fit(const point<S,N>& point) {

		if (isZero()) {

			for (int i = 0; i < N; i++) {

				min()[i] = point[i];
				max()[i] = point[i];
			}

			return;
		}

		for (int i = 0; i < N; i++) {

			min()[i] = std::min(point[i], min()[i]);
			max()[i] = std::max(point[i], max()[i]);
		}
	}

	/**
	 * Extend the x and y dimensions of the box, such that it fits the given
	 * box.
	 */
	template <typename D, typename S, int M>
	void fit(const box_base<D,S,M>& other) {

		if (isZero()) {

			for (int i = 0; i < std::min(N, M); i++) {

				min()[i] = other.min()[i];
				max()[i] = other.max()[i];
			}

			return;
		}

		for (int i = 0; i < std::min(N, M); i++) {

			min()[i] = std::min(other.min()[i], min()[i]);
			max()[i] = std::max(other.max()[i], max()[i]);
		}
	}

	/**
	 * Extend this box, such that it fits the given box.
	 */
	template <typename D, typename S, int M>
	Derived& operator+=(const box_base<D,S,M>& other) {

		this->fit(other);

		return static_cast<Derived&>(*this);
	}

	/**
	 * Add two boxes, i.e., create one that fits both.
	 */
	template <typename D, typename S, int M>
	Derived operator+(const box_base<D,S,M>& other) const {

		Derived b(*this);
		return (b += other);
	}

	bool isZero() const {

		for (int i = 0; i < N; i++)
			if (min()[i] != 0 || min()[i] != 0)
				return false;

		return true;
	}

	template <typename S, int M>
	Derived& operator+=(const point<S,M>& p) {

		for (int i = 0; i < std::min(N, M); i++) {

			min()[i] += p[i];
			max()[i] += p[i];
		}

		return static_cast<Derived&>(*this);
	}

	template <typename S, int M>
	Derived& operator-=(const point<S,M>& p) {

		for (int i = 0; i < std::min(N, M); i++) {

			min()[i] -= p[i];
			max()[i] -= p[i];
		}

		return static_cast<Derived&>(*this);
	}

	template <typename S>
	Derived& operator*=(const S& s) {

		min() *= s;
		max() *= s;

		return static_cast<Derived&>(*this);
	}

	template <typename S>
	Derived& operator/=(const S& s) {

		min() /= s;
		max() /= s;

		return static_cast<Derived&>(*this);
	}

	template <typename D, typename S>
	bool operator==(const box_base<D,S,N>& other) const {

		return (min() == other.min() && max() == other.max());
	}

	template <typename D, typename S>
	bool operator!=(const box_base<D,S,N>& other) const {

		return !(*this == other);
	}

private:

	point<T,N> _min;
	point<T,N> _max;
};

template <typename T, int N>
class box : public box_base<box<T,N>, T, N> {

	typedef box_base<box<T,N>, T, N> base_type;

public:

	template <typename S>
	box(const point<S,N>& min, const point<S,N>& max) :
		base_type(
				min,
				max) {}
};

template <typename T>
class box<T,2> : public box_base<box<T,2>, T, 2> {

	typedef box_base<box<T,2>, T, 2> base_type;

public:

	box() : base_type() {}

	box(T minX, T minY, T maxX, T maxY) :
		base_type(
				point<T,2>(minX, minY),
				point<T,2>(maxX, maxY)) {}

	template <typename S>
	box(const point<S,2>& min, const point<S,2>& max) :
		base_type(
				min,
				max) {}

	using base_type::min;
	using base_type::max;

	T width() const {

		return max().x() - min().x();
	}

	T height() const {

		return max().y() - min().y();
	}

	T area() const {

		return width()*height();
	}

	using base_type::contains;

	template <typename S>
	bool contains(S x, S y) const {

		return contains(point<S,2>(x, y));
	}
};

template <typename T>
class box<T, 3> : public box_base<box<T, 3>, T, 3> {

	typedef box_base<box<T,3>, T, 3> base_type;

public:

	box() : base_type() {}

	box(T minX, T minY, T minZ, T maxX, T maxY, T maxZ) :
		base_type(
				point<T,3>(minX, minY, minZ),
				point<T,3>(maxX, maxY, maxZ)) {}

	template <typename S>
	box(const point<S,3>& min, const point<S,3>& max) :
		base_type(
				min,
				max) {}

	using base_type::min;
	using base_type::max;

	T width() const {

		return max().x() - min().x();
	}

	T height() const {

		return max().y() - min().y();
	}

	T depth() const {

		return max().z() - min().z();
	}

	T volume() const {

		return width()*height()*depth();
	}

	using base_type::contains;

	template <typename S>
	bool contains(S x, S y, S z) const {

		return contains(point<S,3>(x, y, z));
	}
};

} // namespace util

template <typename T, int N, typename PointType>
util::box<T,N> operator+(const util::box<T,N>& p, const PointType& o) {

	util::box<T,N> result(p);

	return result += o;
}

template <typename T, int N, typename PointType>
util::box<T,N> operator-(const util::box<T,N>& p, const PointType& o) {

	util::box<T,N> result(p);

	return result -= o;
}

template <typename T, int N, typename S>
util::box<T,N> operator*(const util::box<T,N>& p, const S& s) {

	util::box<T,N> result(p);

	return result *= s;
}

template <typename S, typename T, int N>
util::box<S,N> operator*(const S& s, const util::box<T,N>& p) {

	util::box<S,N> result(p);

	return result *= s;
}

template <typename T, int N, typename S>
util::box<T,N> operator/(const util::box<T,N>& p, const S& s) {

	util::box<T,N> result(p);

	return result /= s;
}

template <typename T, int N>
std::ostream& operator<<(std::ostream& os, const util::box<T,N>& box) {

	os <<  "[" << box.min() << ", " << box.max() << "]";

	return os;
}

#endif // UTIL_BOX_H__

<commit_msg>added center() to box<commit_after>#ifndef UTIL_BOX_H__
#define UTIL_BOX_H__

#include <sstream>
#include <iostream>
#include <type_traits>

#include "point.hpp"

namespace util {

// forward declaration
template <typename T, int N>
class box;

template <typename Derived, typename T, int N>
class box_base {

public:

	/**
	 * Default constructor.
	 */
	box_base() {}

	template <typename S>
	box_base(const point<S,N>& min, const point<S,N>& max) :
		_min(min),
		_max(max) {}

	template <typename D,typename S>
	box_base(const box_base<D,S,N>& other) :
		_min(other.min()),
		_max(other.max()) {}

	template <typename S>
	operator box<S,N>() const { return box<S,N>(_min, _max); }

	const point<T,N>& min() const { return _min; }
	point<T,N>& min() { return _min; }
	const point<T,N>& max() const { return _max; }
	point<T,N>& max() { return _max; }

	bool valid() { return isZero(); }

	point<T,N> center() const { return (_min + _max)/2.0; }

	template <typename D, typename S>
	bool intersects(const box_base<D,S,N>& other) const {

		// empty boxes do not intersect
		if (isZero() || other.isZero())
			return false;

		// two non-intersecting boxes are separated by a plane parallel to
		// either dimension

		for (int i = 0; i < N; i++)
			if (max()[i] <= other.min()[i] || min()[i] >= other.max()[i])
				return false;

		return true;
	}

	template <typename D, typename S>
	Derived intersection(const box_base<D,S,N>& other) const {

		Derived result;

		if (!intersects(other))
			return result;

		for (int i = 0; i < N; i++) {

			result.min()[i] = std::max(min()[i], other.min()[i]);
			result.max()[i] = std::min(max()[i], other.max()[i]);
		}

		return result;
	}

	template <typename S, int M>
	bool contains(const point<S,M>& point) const {

		for (int i = 0; i < std::min(N, M); i++)
			if (max()[i] <= point[i] || min()[i] > point[i])
				return false;

		return true;
	}

	/**
	 * Extend this box, such that it fits the given point.
	 */
	template <typename S>
	void fit(const point<S,N>& point) {

		if (isZero()) {

			for (int i = 0; i < N; i++) {

				min()[i] = point[i];
				max()[i] = point[i];
			}

			return;
		}

		for (int i = 0; i < N; i++) {

			min()[i] = std::min(point[i], min()[i]);
			max()[i] = std::max(point[i], max()[i]);
		}
	}

	/**
	 * Extend the x and y dimensions of the box, such that it fits the given
	 * box.
	 */
	template <typename D, typename S, int M>
	void fit(const box_base<D,S,M>& other) {

		if (isZero()) {

			for (int i = 0; i < std::min(N, M); i++) {

				min()[i] = other.min()[i];
				max()[i] = other.max()[i];
			}

			return;
		}

		for (int i = 0; i < std::min(N, M); i++) {

			min()[i] = std::min(other.min()[i], min()[i]);
			max()[i] = std::max(other.max()[i], max()[i]);
		}
	}

	/**
	 * Extend this box, such that it fits the given box.
	 */
	template <typename D, typename S, int M>
	Derived& operator+=(const box_base<D,S,M>& other) {

		this->fit(other);

		return static_cast<Derived&>(*this);
	}

	/**
	 * Add two boxes, i.e., create one that fits both.
	 */
	template <typename D, typename S, int M>
	Derived operator+(const box_base<D,S,M>& other) const {

		Derived b(*this);
		return (b += other);
	}

	bool isZero() const {

		for (int i = 0; i < N; i++)
			if (min()[i] != 0 || min()[i] != 0)
				return false;

		return true;
	}

	template <typename S, int M>
	Derived& operator+=(const point<S,M>& p) {

		for (int i = 0; i < std::min(N, M); i++) {

			min()[i] += p[i];
			max()[i] += p[i];
		}

		return static_cast<Derived&>(*this);
	}

	template <typename S, int M>
	Derived& operator-=(const point<S,M>& p) {

		for (int i = 0; i < std::min(N, M); i++) {

			min()[i] -= p[i];
			max()[i] -= p[i];
		}

		return static_cast<Derived&>(*this);
	}

	template <typename S>
	Derived& operator*=(const S& s) {

		min() *= s;
		max() *= s;

		return static_cast<Derived&>(*this);
	}

	template <typename S>
	Derived& operator/=(const S& s) {

		min() /= s;
		max() /= s;

		return static_cast<Derived&>(*this);
	}

	template <typename D, typename S>
	bool operator==(const box_base<D,S,N>& other) const {

		return (min() == other.min() && max() == other.max());
	}

	template <typename D, typename S>
	bool operator!=(const box_base<D,S,N>& other) const {

		return !(*this == other);
	}

private:

	point<T,N> _min;
	point<T,N> _max;
};

template <typename T, int N>
class box : public box_base<box<T,N>, T, N> {

	typedef box_base<box<T,N>, T, N> base_type;

public:

	template <typename S>
	box(const point<S,N>& min, const point<S,N>& max) :
		base_type(
				min,
				max) {}
};

template <typename T>
class box<T,2> : public box_base<box<T,2>, T, 2> {

	typedef box_base<box<T,2>, T, 2> base_type;

public:

	box() : base_type() {}

	box(T minX, T minY, T maxX, T maxY) :
		base_type(
				point<T,2>(minX, minY),
				point<T,2>(maxX, maxY)) {}

	template <typename S>
	box(const point<S,2>& min, const point<S,2>& max) :
		base_type(
				min,
				max) {}

	using base_type::min;
	using base_type::max;

	T width() const {

		return max().x() - min().x();
	}

	T height() const {

		return max().y() - min().y();
	}

	T area() const {

		return width()*height();
	}

	using base_type::contains;

	template <typename S>
	bool contains(S x, S y) const {

		return contains(point<S,2>(x, y));
	}
};

template <typename T>
class box<T, 3> : public box_base<box<T, 3>, T, 3> {

	typedef box_base<box<T,3>, T, 3> base_type;

public:

	box() : base_type() {}

	box(T minX, T minY, T minZ, T maxX, T maxY, T maxZ) :
		base_type(
				point<T,3>(minX, minY, minZ),
				point<T,3>(maxX, maxY, maxZ)) {}

	template <typename S>
	box(const point<S,3>& min, const point<S,3>& max) :
		base_type(
				min,
				max) {}

	using base_type::min;
	using base_type::max;

	T width() const {

		return max().x() - min().x();
	}

	T height() const {

		return max().y() - min().y();
	}

	T depth() const {

		return max().z() - min().z();
	}

	T volume() const {

		return width()*height()*depth();
	}

	using base_type::contains;

	template <typename S>
	bool contains(S x, S y, S z) const {

		return contains(point<S,3>(x, y, z));
	}
};

} // namespace util

template <typename T, int N, typename PointType>
util::box<T,N> operator+(const util::box<T,N>& p, const PointType& o) {

	util::box<T,N> result(p);

	return result += o;
}

template <typename T, int N, typename PointType>
util::box<T,N> operator-(const util::box<T,N>& p, const PointType& o) {

	util::box<T,N> result(p);

	return result -= o;
}

template <typename T, int N, typename S>
util::box<T,N> operator*(const util::box<T,N>& p, const S& s) {

	util::box<T,N> result(p);

	return result *= s;
}

template <typename S, typename T, int N>
util::box<S,N> operator*(const S& s, const util::box<T,N>& p) {

	util::box<S,N> result(p);

	return result *= s;
}

template <typename T, int N, typename S>
util::box<T,N> operator/(const util::box<T,N>& p, const S& s) {

	util::box<T,N> result(p);

	return result /= s;
}

template <typename T, int N>
std::ostream& operator<<(std::ostream& os, const util::box<T,N>& box) {

	os <<  "[" << box.min() << ", " << box.max() << "]";

	return os;
}

#endif // UTIL_BOX_H__

<|endoftext|>


<commit_before>#include "Arduino.h"
#include "DFR_Key.h"

static int DEFAULT_KEY_PIN = 0;
static int DEFAULT_THRESHOLD = 5;

/*
	To use any alternate set of values you will need to enable it by a define.
	The define should NOT be done in code or it will impact all users. Visual
	Studio users can set 'DF_ROBOT_V1' in the Preprocessor definitions of the
	project, or add '-DDF_ROBOT_V1' under advanced options.

	Users of the standard Arduino IDE should create the file 'platform.local.txt'
	under <arduino_install>/hardware.arduino/avr and add the following line but
	be aware that when you upgrade your IDE this file may need to be re-created:

	compiler.cpp.extra_flags=-DDF_ROBOT_V1

	If further values are added in the future then of course adjust the name
	of the define that you specify accordingly.
*/
#ifdef DF_ROBOT_V1
	static int RIGHTKEY_ARV = 0;	//that's read "analogue read value"
	static int UPKEY_ARV	= 98;
	static int DOWNKEY_ARV	= 254;
	static int LEFTKEY_ARV	= 407;
	static int SELKEY_ARV	= 638;
	static int NOKEY_ARV	= 1023;
#else
	static int RIGHTKEY_ARV = 0;
	static int UPKEY_ARV	= 144;
	static int DOWNKEY_ARV	= 329;
	static int LEFTKEY_ARV	= 505;
	static int SELKEY_ARV	= 742;
	static int NOKEY_ARV	= 1023;
#endif

DFR_Key::DFR_Key()
{
  _refreshRate = 10;
  _keyPin = DEFAULT_KEY_PIN;
  _threshold = DEFAULT_THRESHOLD;
  _keyIn = NO_KEY;
  _curInput = NO_KEY;
  _curKey = NO_KEY;
  _prevInput = NO_KEY;
  _prevKey = NO_KEY;
  _oldTime = 0;
}

int DFR_Key::getKey()
{
 if (millis() > _oldTime + _refreshRate)
 {
    _prevInput = _curInput;
    _curInput = analogRead(_keyPin);

    if (_curInput == _prevInput)
    {
      _change = false;
      _curKey = _prevKey;
    }
    else
    {
      _change = true;
      _prevKey = _curKey;

      if (_curInput > UPKEY_ARV - _threshold && _curInput < UPKEY_ARV + _threshold ) _curKey = UP_KEY;
      else if (_curInput > DOWNKEY_ARV - _threshold && _curInput < DOWNKEY_ARV + _threshold ) _curKey = DOWN_KEY;
      else if (_curInput > RIGHTKEY_ARV - _threshold && _curInput < RIGHTKEY_ARV + _threshold ) _curKey = RIGHT_KEY;
      else if (_curInput > LEFTKEY_ARV - _threshold && _curInput < LEFTKEY_ARV + _threshold ) _curKey = LEFT_KEY;
      else if (_curInput > SELKEY_ARV - _threshold && _curInput < SELKEY_ARV + _threshold ) _curKey = SELECT_KEY;
      else _curKey = NO_KEY;
   }

   if (_change) return _curKey; else return SAMPLE_WAIT;
   _oldTime = millis();
 }
}

void DFR_Key::setRate(int rate)
{
  _refreshRate = rate;
}<commit_msg>All: Increase the key thresholds to accomodate my aging keypad shield.<commit_after>#include "Arduino.h"
#include "DFR_Key.h"

static int DEFAULT_KEY_PIN = 0;
static int DEFAULT_THRESHOLD = 20;

/*
	To use any alternate set of values you will need to enable it by a define.
	The define should NOT be done in code or it will impact all users. Visual
	Studio users can set 'DF_ROBOT_V1' in the Preprocessor definitions of the
	project, or add '-DDF_ROBOT_V1' under advanced options.

	Users of the standard Arduino IDE should create the file 'platform.local.txt'
	under <arduino_install>/hardware.arduino/avr and add the following line but
	be aware that when you upgrade your IDE this file may need to be re-created:

	compiler.cpp.extra_flags=-DDF_ROBOT_V1

	If further values are added in the future then of course adjust the name
	of the define that you specify accordingly.
*/
#ifdef DF_ROBOT_V1
	static int RIGHTKEY_ARV = 0;	//that's read "analogue read value"
	static int UPKEY_ARV	= 98;
	static int DOWNKEY_ARV	= 254;
	static int LEFTKEY_ARV	= 407;
	static int SELKEY_ARV	= 638;
	static int NOKEY_ARV	= 1023;
#else
	static int RIGHTKEY_ARV = 0;
	static int UPKEY_ARV	= 144;
	static int DOWNKEY_ARV	= 329;
	static int LEFTKEY_ARV	= 505;
	static int SELKEY_ARV	= 742;
	static int NOKEY_ARV	= 1023;
#endif

DFR_Key::DFR_Key()
{
  _refreshRate = 10;
  _keyPin = DEFAULT_KEY_PIN;
  _threshold = DEFAULT_THRESHOLD;
  _keyIn = NO_KEY;
  _curInput = NO_KEY;
  _curKey = NO_KEY;
  _prevInput = NO_KEY;
  _prevKey = NO_KEY;
  _oldTime = 0;
}

int DFR_Key::getKey()
{
 if (millis() > _oldTime + _refreshRate)
 {
    _prevInput = _curInput;
    _curInput = analogRead(_keyPin);

    if (_curInput == _prevInput)
    {
      _change = false;
      _curKey = _prevKey;
    }
    else
    {
      _change = true;
      _prevKey = _curKey;

      if (_curInput > UPKEY_ARV - _threshold && _curInput < UPKEY_ARV + _threshold ) _curKey = UP_KEY;
      else if (_curInput > DOWNKEY_ARV - _threshold && _curInput < DOWNKEY_ARV + _threshold ) _curKey = DOWN_KEY;
      else if (_curInput > RIGHTKEY_ARV - _threshold && _curInput < RIGHTKEY_ARV + _threshold ) _curKey = RIGHT_KEY;
      else if (_curInput > LEFTKEY_ARV - _threshold && _curInput < LEFTKEY_ARV + _threshold ) _curKey = LEFT_KEY;
      else if (_curInput > SELKEY_ARV - _threshold && _curInput < SELKEY_ARV + _threshold ) _curKey = SELECT_KEY;
      else _curKey = NO_KEY;
   }

   if (_change) return _curKey; else return SAMPLE_WAIT;
   _oldTime = millis();
 }
}

void DFR_Key::setRate(int rate)
{
  _refreshRate = rate;
}<|endoftext|>


<commit_before>#include "mnetracer.h"

using namespace UTILSLIB;

static const char* defaultTracerFileName("default_MNETracer_file.json");
bool MNETracer::ms_bIsEnabled(false);
std::ofstream MNETracer::ms_OutputFileStream;
bool MNETracer::ms_bIsFirstEvent(true);
long long MNETracer::ms_iZeroTime(0);

//=============================================================================================================

MNETracer::MNETracer(const std::string &file, const std::string &function, int lineNumber)
: m_bIsInitialized(false)
, m_bPrintToTerminal(false)
, m_sFileName(file)
, m_sFunctionName(function)
, m_iLineNumber(lineNumber)
, m_iThreadId("0")
, m_iBeginTime(0)
, m_iEndTime(0)
, m_dDurationMilis(0.)
{
    if (ms_bIsEnabled)
    {
        initialize();
        writeBeginEvent();
    }
}

//=============================================================================================================

MNETracer::~MNETracer()
{
    if (ms_bIsEnabled && m_bIsInitialized)
    {
        registerFinalTime();
        writeEndEvent();
        if (m_bPrintToTerminal)
        {
            calculateDuration();
            printDurationMiliSec();
        }
    }
}

//=============================================================================================================

void MNETracer::enable(const std::string &jsonFileName)
{
    ms_OutputFileStream.open(jsonFileName);
    writeHeader();
    setZeroTime();
    if (ms_OutputFileStream.is_open())
    {
        ms_bIsEnabled = true;
    }
}

//=============================================================================================================

void MNETracer::enable()
{
    enable(defaultTracerFileName);
}

//=============================================================================================================

void MNETracer::disable()
{
    if (ms_bIsEnabled)
    {
        writeFooter();
        ms_OutputFileStream.flush();
        ms_OutputFileStream.close();
        ms_bIsEnabled = false;
    }
}

//=============================================================================================================

void MNETracer::start(const std::string &jsonFileName)
{
    enable(jsonFileName);
}

//=============================================================================================================

void MNETracer::start()
{
    enable();
}

//=============================================================================================================

void MNETracer::stop()
{
    disable();
}

//=============================================================================================================

void MNETracer::traceQuantity(const std::string &name, long val)
{
    long long timeNow = getTimeNow() - ms_iZeroTime;
    std::string s;
    s.append("{\"name\":\"").append(name).append("\",\"ph\":\"C\",\"ts\":");
    s.append(std::to_string(timeNow)).append(",\"pid\":1,\"tid\":1");
    s.append(",\"args\":{\"").append(name).append("\":").append(std::to_string(val)).append("}}\n");
    writeToFile(s);
}

//=============================================================================================================

void MNETracer::initialize()
{
    registerConstructionTime();
    registerThreadId();
    formatFileName();
//    formatFunctionName();
    m_bIsInitialized = true;
}

//=============================================================================================================

void MNETracer::setZeroTime()
{
    ms_iZeroTime = getTimeNow();
}

//=============================================================================================================

void MNETracer::registerConstructionTime()
{
    m_iBeginTime = getTimeNow() - ms_iZeroTime;
}

//=============================================================================================================

void MNETracer::registerFinalTime()
{
    m_iEndTime = getTimeNow() - ms_iZeroTime;
}

//=============================================================================================================

long long MNETracer::getTimeNow()
{
    auto timeNow = std::chrono::high_resolution_clock::now();
    return std::chrono::time_point_cast<std::chrono::microseconds>(timeNow).time_since_epoch().count();
}

//=============================================================================================================

void MNETracer::registerThreadId()
{
    auto longId = std::hash<std::thread::id>{}(std::this_thread::get_id());
    m_iThreadId = std::to_string(longId).substr(0, 5);
}

//=============================================================================================================

void MNETracer::formatFunctionName()
{
    const char* pattern(" __cdecl");
    constexpr int patternLenght(8);
    size_t pos = m_sFunctionName.find(pattern);
    if (pos != std::string::npos) {
        m_sFunctionName.replace(pos, patternLenght, "");
    }
}

//=============================================================================================================

void MNETracer::formatFileName()
{
    const char* patternIn("\\");
    const char* patternOut("\\\\");
    constexpr int patternOutLength(4);
    size_t start_pos = 0;
    while ((start_pos = m_sFileName.find(patternIn, start_pos)) != std::string::npos)
    {
        m_sFileName.replace(start_pos, 1, patternOut);
        start_pos += patternOutLength;
    }
}

//=============================================================================================================

void MNETracer::calculateDuration()
{
    m_dDurationMilis = (m_iEndTime - m_iBeginTime) * 0.001;
}

//=============================================================================================================

void MNETracer::printDurationMiliSec()
{
    std::cout << "Scope: " << m_sFileName << " - " << m_sFunctionName << " DurationMs: " << m_dDurationMilis << "ms.\n";
}

//=============================================================================================================

void MNETracer::writeHeader()
{
    writeToFile("{\"displayTimeUnit\": \"ms\",\"traceEvents\":[\n");
}

//=============================================================================================================

void MNETracer::writeFooter()
{
    writeToFile("]}");
}

//=============================================================================================================

void MNETracer::writeToFile(const std::string &str)
{
    ms_outFileMutex.lock();
    if(ms_OutputFileStream.is_open()) {
        ms_OutputFileStream << str;
    }
    ms_outFileMutex.unlock();
}

//=============================================================================================================

void MNETracer::writeBeginEvent()
{
    std::string s;
    if (!ms_bIsFirstEvent)
        s.append(",");

    s.append("{\"name\":\"").append(m_sFunctionName).append("\",\"cat\":\"bst\",");
    s.append("\"ph\":\"B\",\"ts\":").append(std::to_string(m_iBeginTime)).append(",\"pid\":1,\"tid\":");
    s.append(m_iThreadId).append(",\"args\":{\"file path\":\"").append(m_sFileName).append("\",\"line number\":");
    s.append(std::to_string(m_iLineNumber)).append("}}\n");
    writeToFile(s);
    ms_bIsFirstEvent = false;
}

//=============================================================================================================

void MNETracer::writeEndEvent()
{
    std::string s;
    s.append(",{\"name\":\"").append(m_sFunctionName).append("\",\"cat\":\"bst\",");
    s.append("\"ph\":\"E\",\"ts\":").append(std::to_string(m_iEndTime)).append(",\"pid\":1,\"tid\":");
    s.append(m_iThreadId).append(",\"args\":{\"file path\":\"").append(m_sFileName).append("\",\"line number\":");
    s.append(std::to_string(m_iLineNumber)).append("}}\n");
    writeToFile(s);
}

//=============================================================================================================

bool MNETracer::printToTerminalIsSet()
{
    return m_bPrintToTerminal;
}

//=============================================================================================================

void MNETracer::setPrintToTerminal(bool s)
{
    m_bPrintToTerminal = s;
}
<commit_msg>actually define the mutex<commit_after>#include "mnetracer.h"

using namespace UTILSLIB;

static const char* defaultTracerFileName("default_MNETracer_file.json");
bool MNETracer::ms_bIsEnabled(false);
std::ofstream MNETracer::ms_OutputFileStream;
bool MNETracer::ms_bIsFirstEvent(true);
std::mutex MNETracer::ms_outFileMutex;
long long MNETracer::ms_iZeroTime(0);

//=============================================================================================================

MNETracer::MNETracer(const std::string &file, const std::string &function, int lineNumber)
: m_bIsInitialized(false)
, m_bPrintToTerminal(false)
, m_sFileName(file)
, m_sFunctionName(function)
, m_iLineNumber(lineNumber)
, m_iThreadId("0")
, m_iBeginTime(0)
, m_iEndTime(0)
, m_dDurationMilis(0.)
{
    if (ms_bIsEnabled)
    {
        initialize();
        writeBeginEvent();
    }
}

//=============================================================================================================

MNETracer::~MNETracer()
{
    if (ms_bIsEnabled && m_bIsInitialized)
    {
        registerFinalTime();
        writeEndEvent();
        if (m_bPrintToTerminal)
        {
            calculateDuration();
            printDurationMiliSec();
        }
    }
}

//=============================================================================================================

void MNETracer::enable(const std::string &jsonFileName)
{
    ms_OutputFileStream.open(jsonFileName);
    writeHeader();
    setZeroTime();
    if (ms_OutputFileStream.is_open())
    {
        ms_bIsEnabled = true;
    }
}

//=============================================================================================================

void MNETracer::enable()
{
    enable(defaultTracerFileName);
}

//=============================================================================================================

void MNETracer::disable()
{
    if (ms_bIsEnabled)
    {
        writeFooter();
        ms_OutputFileStream.flush();
        ms_OutputFileStream.close();
        ms_bIsEnabled = false;
    }
}

//=============================================================================================================

void MNETracer::start(const std::string &jsonFileName)
{
    enable(jsonFileName);
}

//=============================================================================================================

void MNETracer::start()
{
    enable();
}

//=============================================================================================================

void MNETracer::stop()
{
    disable();
}

//=============================================================================================================

void MNETracer::traceQuantity(const std::string &name, long val)
{
    long long timeNow = getTimeNow() - ms_iZeroTime;
    std::string s;
    s.append("{\"name\":\"").append(name).append("\",\"ph\":\"C\",\"ts\":");
    s.append(std::to_string(timeNow)).append(",\"pid\":1,\"tid\":1");
    s.append(",\"args\":{\"").append(name).append("\":").append(std::to_string(val)).append("}}\n");
    writeToFile(s);
}

//=============================================================================================================

void MNETracer::initialize()
{
    registerConstructionTime();
    registerThreadId();
    formatFileName();
//    formatFunctionName();
    m_bIsInitialized = true;
}

//=============================================================================================================

void MNETracer::setZeroTime()
{
    ms_iZeroTime = getTimeNow();
}

//=============================================================================================================

void MNETracer::registerConstructionTime()
{
    m_iBeginTime = getTimeNow() - ms_iZeroTime;
}

//=============================================================================================================

void MNETracer::registerFinalTime()
{
    m_iEndTime = getTimeNow() - ms_iZeroTime;
}

//=============================================================================================================

long long MNETracer::getTimeNow()
{
    auto timeNow = std::chrono::high_resolution_clock::now();
    return std::chrono::time_point_cast<std::chrono::microseconds>(timeNow).time_since_epoch().count();
}

//=============================================================================================================

void MNETracer::registerThreadId()
{
    auto longId = std::hash<std::thread::id>{}(std::this_thread::get_id());
    m_iThreadId = std::to_string(longId).substr(0, 5);
}

//=============================================================================================================

void MNETracer::formatFunctionName()
{
    const char* pattern(" __cdecl");
    constexpr int patternLenght(8);
    size_t pos = m_sFunctionName.find(pattern);
    if (pos != std::string::npos) {
        m_sFunctionName.replace(pos, patternLenght, "");
    }
}

//=============================================================================================================

void MNETracer::formatFileName()
{
    const char* patternIn("\\");
    const char* patternOut("\\\\");
    constexpr int patternOutLength(4);
    size_t start_pos = 0;
    while ((start_pos = m_sFileName.find(patternIn, start_pos)) != std::string::npos)
    {
        m_sFileName.replace(start_pos, 1, patternOut);
        start_pos += patternOutLength;
    }
}

//=============================================================================================================

void MNETracer::calculateDuration()
{
    m_dDurationMilis = (m_iEndTime - m_iBeginTime) * 0.001;
}

//=============================================================================================================

void MNETracer::printDurationMiliSec()
{
    std::cout << "Scope: " << m_sFileName << " - " << m_sFunctionName << " DurationMs: " << m_dDurationMilis << "ms.\n";
}

//=============================================================================================================

void MNETracer::writeHeader()
{
    writeToFile("{\"displayTimeUnit\": \"ms\",\"traceEvents\":[\n");
}

//=============================================================================================================

void MNETracer::writeFooter()
{
    writeToFile("]}");
}

//=============================================================================================================

void MNETracer::writeToFile(const std::string &str)
{
    ms_outFileMutex.lock();
    if(ms_OutputFileStream.is_open()) {
        ms_OutputFileStream << str;
    }
    ms_outFileMutex.unlock();
}

//=============================================================================================================

void MNETracer::writeBeginEvent()
{
    std::string s;
    if (!ms_bIsFirstEvent)
        s.append(",");

    s.append("{\"name\":\"").append(m_sFunctionName).append("\",\"cat\":\"bst\",");
    s.append("\"ph\":\"B\",\"ts\":").append(std::to_string(m_iBeginTime)).append(",\"pid\":1,\"tid\":");
    s.append(m_iThreadId).append(",\"args\":{\"file path\":\"").append(m_sFileName).append("\",\"line number\":");
    s.append(std::to_string(m_iLineNumber)).append("}}\n");
    writeToFile(s);
    ms_bIsFirstEvent = false;
}

//=============================================================================================================

void MNETracer::writeEndEvent()
{
    std::string s;
    s.append(",{\"name\":\"").append(m_sFunctionName).append("\",\"cat\":\"bst\",");
    s.append("\"ph\":\"E\",\"ts\":").append(std::to_string(m_iEndTime)).append(",\"pid\":1,\"tid\":");
    s.append(m_iThreadId).append(",\"args\":{\"file path\":\"").append(m_sFileName).append("\",\"line number\":");
    s.append(std::to_string(m_iLineNumber)).append("}}\n");
    writeToFile(s);
}

//=============================================================================================================

bool MNETracer::printToTerminalIsSet()
{
    return m_bPrintToTerminal;
}

//=============================================================================================================

void MNETracer::setPrintToTerminal(bool s)
{
    m_bPrintToTerminal = s;
}
<|endoftext|>


<commit_before>/*
 * TTUnitTest
 * Copyright © 2011, Timothy Place and Trond Lossius
 *
 * License: This code is licensed under the terms of the "New BSD License"
 * http://creativecommons.org/licenses/BSD/
 */

#include <limits>
#include "TTUnitTest.h"

static const TTFloat32 kTTTestFloat32Epsilon = 0.00001f;
static const TTFloat64 kTTTestFloat64Epsilon = 0.000000001;
static const TTFloat32 kTTTestFloat32Infinity = std::numeric_limits<float>::infinity();
static const TTFloat64 kTTTestFloat64Infinity = std::numeric_limits<double>::infinity();

TTBoolean TTTestFloatEquivalence(TTFloat32 aFloat, TTFloat32 bFloat, TTBoolean expectedResult, TTFloat32 epsilon)
{
	if (epsilon <= 0.) {
		TTLogMessage("		TTTestFloatEquivalence: epsilon must be a positive number\n");
		return false;
	}

	TTBoolean result;

	if ((aFloat == kTTTestFloat32Infinity)||(bFloat == kTTTestFloat32Infinity)) {
		if (aFloat==bFloat)
			result = true;
		else
			result = false;
	}
	else {
		TTFloat32 aAbs = fabs(aFloat);
		TTFloat32 bAbs = fabs(bFloat);
		TTFloat32 absoluteOrRelative = (1.0f > aAbs ? 1.0f : aAbs);
		absoluteOrRelative = (absoluteOrRelative > bAbs ? absoluteOrRelative : bAbs);
		if (fabs(aFloat - bFloat) <= epsilon * absoluteOrRelative)
			result = true;
		else
			result = false;
	}
	// Was this the expected result?
	if (result == expectedResult)
		return true;
	else {
		TTLogMessage("\n");
		TTLogMessage("		TTTestFloatEquivalence: Unexpected result\n");
		TTLogMessage("\n");
		TTLogMessage("		aFloat  = %.8e\n", aFloat);
		TTLogMessage("		bFloat  = %.8e\n", bFloat);
		TTLogMessage("		result  = %s\n", (result)?"true":"false");
		TTLogMessage("\n");
		return false;
	}
}

TTBoolean TTTestFloatEquivalence(TTFloat64 aFloat, TTFloat64 bFloat, TTBoolean expectedResult, TTFloat64 epsilon)
{
	if (epsilon <= 0.) {
		TTLogMessage("		TTTestFloatEquivalence: epsilon must be a positive number\n");
		return false;
	}

	TTBoolean result;

	if ((aFloat == kTTTestFloat64Infinity)||(bFloat == kTTTestFloat64Infinity)) {
		if (aFloat==bFloat)
			result = true;
		else
			result = false;
	}
	else {
		TTFloat64 aAbs = fabs(aFloat);
		TTFloat64 bAbs = fabs(bFloat);
		TTFloat64 absoluteOrRelative = (1.0f > aAbs ? 1.0f : aAbs);
		absoluteOrRelative = (absoluteOrRelative > bAbs ? absoluteOrRelative : bAbs);
		if (fabs(aFloat - bFloat) <= epsilon * absoluteOrRelative)
			result = true;
		else
			result = false;
	}
	// Was this the expected result?
	if (result == expectedResult)
		return true;
	else {
		TTLogMessage("\n");
		TTLogMessage("		TTTestFloatEquivalence: Unexpected result\n");
		TTLogMessage("\n");
		TTLogMessage("		aFloat  = %.15e\n", aFloat);
		TTLogMessage("		bFloat  = %.15e\n", bFloat);
		TTLogMessage("		result  = %s\n", (result)?"true":"false");
		TTLogMessage("\n");
		return false;
	}
}

TTBoolean TTTestFloat32ArrayEquivalence(TTValue &aFloat, TTValue &bFloat, TTBoolean expectedResult, TTFloat32 epsilon)
{
    TTInt32 i;
    TTBoolean result;

    // Compare vector size
    if (aFloat.getSize()!=bFloat.getSize())
        result = false;
    else
    {
        // Compare member by member
        result = true;
        for (i=0; i<aFloat.getSize(); i++)
            result = result && TTTestFloatEquivalence(TTFloat32(aFloat.getFloat32(i)), TTFloat32(bFloat.getFloat32(i)), expectedResult, epsilon);
    }

    return result;
}

TTBoolean TTTestFloat64ArrayEquivalence(TTValue &aFloat, TTValue &bFloat, TTBoolean expectedResult, TTFloat64 epsilon)
{
    TTInt32 i;
    TTBoolean result;

    // Compare vector size
    if (aFloat.getSize()!=bFloat.getSize())
        result = false;
    else
    {
        // Compare member by member
        result = true;
        for (i=0; i<aFloat.getSize(); i++)
            result = result && TTTestFloatEquivalence(aFloat.getFloat64(i), bFloat.getFloat64(i), expectedResult, epsilon);
    }

    return result;
}

void TTTestLog(const char *fmtstring, ...)
{
	char	str[4096];
	char	fullstr[4096];
	va_list	ap;

	va_start(ap, fmtstring);
	vsnprintf(str, 4000, fmtstring, ap);
	va_end(ap);
	str[4095] = 0;

	strncpy(fullstr, "		", 4095);
	strncat(fullstr, str, 4095);
	strncat(fullstr, "\n", 4095);
	TTLogMessage(fullstr);
}

void TTTestAssertion(const char* aTestName, TTBoolean aTestResult, int& testAssertionCount, int& errorCount)
{
	testAssertionCount++;

	if (aTestResult)
		TTLogMessage("	PASS -- ");
	else {
		TTLogMessage("	FAIL -- ");
		errorCount++;
	}
	TTLogMessage(aTestName);
	TTLogMessage("\n");
	if (!aTestResult)
		TTLogMessage("\n");
}

TTErr TTTestFinish(int testAssertionCount, int errorCount, TTValue& returnedTestInfo)
{
	TTDictionaryPtr d = new TTDictionary;

	d->setSchema(TT("TestInfo"));
	d->append(TT("testAssertionCount"), testAssertionCount);
	d->append(TT("errorCount"), errorCount);
	returnedTestInfo = d;

	TTTestLog("\n");
	TTTestLog("Number of assertions: %ld", testAssertionCount);
	TTTestLog("Number of failed assertions: %ld", errorCount);
	TTTestLog("\n");

	if (errorCount)
		return kTTErrGeneric;
	else
		return kTTErrNone;
}

<commit_msg>TTUnitTest: adding #ifdefs around log posts when the float-comparison fails.  I think any posting should be done by the code that calls these functions rather than these functions themselves.  But maybe others disagree?  It was cluttering my console window when debugging, so I just went ahead and did it, but we can discuss and revert if needed...<commit_after>/*
 * TTUnitTest
 * Copyright © 2011, Timothy Place and Trond Lossius
 *
 * License: This code is licensed under the terms of the "New BSD License"
 * http://creativecommons.org/licenses/BSD/
 */

#include <limits>
#include "TTUnitTest.h"

static const TTFloat32 kTTTestFloat32Epsilon = 0.00001f;
static const TTFloat64 kTTTestFloat64Epsilon = 0.000000001;
static const TTFloat32 kTTTestFloat32Infinity = std::numeric_limits<float>::infinity();
static const TTFloat64 kTTTestFloat64Infinity = std::numeric_limits<double>::infinity();

TTBoolean TTTestFloatEquivalence(TTFloat32 aFloat, TTFloat32 bFloat, TTBoolean expectedResult, TTFloat32 epsilon)
{
	if (epsilon <= 0.) {
		TTLogMessage("		TTTestFloatEquivalence: epsilon must be a positive number\n");
		return false;
	}

	TTBoolean result;

	if ((aFloat == kTTTestFloat32Infinity)||(bFloat == kTTTestFloat32Infinity)) {
		if (aFloat==bFloat)
			result = true;
		else
			result = false;
	}
	else {
		TTFloat32 aAbs = fabs(aFloat);
		TTFloat32 bAbs = fabs(bFloat);
		TTFloat32 absoluteOrRelative = (1.0f > aAbs ? 1.0f : aAbs);
		absoluteOrRelative = (absoluteOrRelative > bAbs ? absoluteOrRelative : bAbs);
		if (fabs(aFloat - bFloat) <= epsilon * absoluteOrRelative)
			result = true;
		else
			result = false;
	}
	// Was this the expected result?
	if (result == expectedResult)
		return true;
	else {
#ifdef NOISY_FAILURE
		TTLogMessage("\n");
		TTLogMessage("		TTTestFloatEquivalence: Unexpected result\n");
		TTLogMessage("\n");
		TTLogMessage("		aFloat  = %.8e\n", aFloat);
		TTLogMessage("		bFloat  = %.8e\n", bFloat);
		TTLogMessage("		result  = %s\n", (result)?"true":"false");
		TTLogMessage("\n");
#endif
		return false;
	}
}

TTBoolean TTTestFloatEquivalence(TTFloat64 aFloat, TTFloat64 bFloat, TTBoolean expectedResult, TTFloat64 epsilon)
{
	if (epsilon <= 0.) {
		TTLogMessage("		TTTestFloatEquivalence: epsilon must be a positive number\n");
		return false;
	}

	TTBoolean result;

	if ((aFloat == kTTTestFloat64Infinity)||(bFloat == kTTTestFloat64Infinity)) {
		if (aFloat==bFloat)
			result = true;
		else
			result = false;
	}
	else {
		TTFloat64 aAbs = fabs(aFloat);
		TTFloat64 bAbs = fabs(bFloat);
		TTFloat64 absoluteOrRelative = (1.0f > aAbs ? 1.0f : aAbs);
		absoluteOrRelative = (absoluteOrRelative > bAbs ? absoluteOrRelative : bAbs);
		if (fabs(aFloat - bFloat) <= epsilon * absoluteOrRelative)
			result = true;
		else
			result = false;
	}
	// Was this the expected result?
	if (result == expectedResult)
		return true;
	else {
#ifdef NOISY_FAILURE
		TTLogMessage("\n");
		TTLogMessage("		TTTestFloatEquivalence: Unexpected result\n");
		TTLogMessage("\n");
		TTLogMessage("		aFloat  = %.15e\n", aFloat);
		TTLogMessage("		bFloat  = %.15e\n", bFloat);
		TTLogMessage("		result  = %s\n", (result)?"true":"false");
		TTLogMessage("\n");
#endif
		return false;
	}
}

TTBoolean TTTestFloat32ArrayEquivalence(TTValue &aFloat, TTValue &bFloat, TTBoolean expectedResult, TTFloat32 epsilon)
{
    TTInt32 i;
    TTBoolean result;

    // Compare vector size
    if (aFloat.getSize()!=bFloat.getSize())
        result = false;
    else
    {
        // Compare member by member
        result = true;
        for (i=0; i<aFloat.getSize(); i++)
            result = result && TTTestFloatEquivalence(TTFloat32(aFloat.getFloat32(i)), TTFloat32(bFloat.getFloat32(i)), expectedResult, epsilon);
    }

    return result;
}

TTBoolean TTTestFloat64ArrayEquivalence(TTValue &aFloat, TTValue &bFloat, TTBoolean expectedResult, TTFloat64 epsilon)
{
    TTInt32 i;
    TTBoolean result;

    // Compare vector size
    if (aFloat.getSize()!=bFloat.getSize())
        result = false;
    else
    {
        // Compare member by member
        result = true;
        for (i=0; i<aFloat.getSize(); i++)
            result = result && TTTestFloatEquivalence(aFloat.getFloat64(i), bFloat.getFloat64(i), expectedResult, epsilon);
    }

    return result;
}

void TTTestLog(const char *fmtstring, ...)
{
	char	str[4096];
	char	fullstr[4096];
	va_list	ap;

	va_start(ap, fmtstring);
	vsnprintf(str, 4000, fmtstring, ap);
	va_end(ap);
	str[4095] = 0;

	strncpy(fullstr, "		", 4095);
	strncat(fullstr, str, 4095);
	strncat(fullstr, "\n", 4095);
	TTLogMessage(fullstr);
}

void TTTestAssertion(const char* aTestName, TTBoolean aTestResult, int& testAssertionCount, int& errorCount)
{
	testAssertionCount++;

	if (aTestResult)
		TTLogMessage("	PASS -- ");
	else {
		TTLogMessage("	FAIL -- ");
		errorCount++;
	}
	TTLogMessage(aTestName);
	TTLogMessage("\n");
	if (!aTestResult)
		TTLogMessage("\n");
}

TTErr TTTestFinish(int testAssertionCount, int errorCount, TTValue& returnedTestInfo)
{
	TTDictionaryPtr d = new TTDictionary;

	d->setSchema(TT("TestInfo"));
	d->append(TT("testAssertionCount"), testAssertionCount);
	d->append(TT("errorCount"), errorCount);
	returnedTestInfo = d;

	TTTestLog("\n");
	TTTestLog("Number of assertions: %ld", testAssertionCount);
	TTTestLog("Number of failed assertions: %ld", errorCount);
	TTTestLog("\n");

	if (errorCount)
		return kTTErrGeneric;
	else
		return kTTErrNone;
}

<|endoftext|>


<commit_before>/*
 * Copyright (C) 2013 The Android Open Source Project
 *
 * 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.
 */

// Determine coverage of font given its raw "cmap" OpenType table

#define LOG_TAG "Minikin"
#include <cutils/log.h>

#include <vector>
using std::vector;

#include <minikin/SparseBitSet.h>
#include <minikin/CmapCoverage.h>

namespace android {

// These could perhaps be optimized to use __builtin_bswap16 and friends.
static uint32_t readU16(const uint8_t* data, size_t offset) {
    return data[offset] << 8 | data[offset + 1];
}

static uint32_t readU32(const uint8_t* data, size_t offset) {
    return data[offset] << 24 | data[offset + 1] << 16 | data[offset + 2] << 8 | data[offset + 3];
}

static void addRange(vector<uint32_t> &coverage, uint32_t start, uint32_t end) {
#ifdef VERBOSE_DEBUG
    ALOGD("adding range %d-%d\n", start, end);
#endif
    if (coverage.empty() || coverage.back() < start) {
        coverage.push_back(start);
        coverage.push_back(end);
    } else {
        coverage.back() = end;
    }
}

// Get the coverage information out of a Format 12 subtable, storing it in the coverage vector
static bool getCoverageFormat4(vector<uint32_t>& coverage, const uint8_t* data, size_t size) {
    const size_t kSegCountOffset = 6;
    const size_t kEndCountOffset = 14;
    const size_t kHeaderSize = 16;
    const size_t kSegmentSize = 8;  // total size of array elements for one segment
    if (kEndCountOffset > size) {
        return false;
    }
    size_t segCount = readU16(data, kSegCountOffset) >> 1;
    if (kHeaderSize + segCount * kSegmentSize > size) {
        return false;
    }
    for (size_t i = 0; i < segCount; i++) {
        int end = readU16(data, kEndCountOffset + 2 * i);
        int start = readU16(data, kHeaderSize + 2 * (segCount + i));
        int rangeOffset = readU16(data, kHeaderSize + 2 * (3 * segCount + i));
        if (rangeOffset == 0) {
            int delta = readU16(data, kHeaderSize + 2 * (2 * segCount + i));
            if (((end + delta) & 0xffff) > end - start) {
                addRange(coverage, start, end + 1);
            } else {
                for (int j = start; j < end + 1; j++) {
                    if (((j + delta) & 0xffff) != 0) {
                        addRange(coverage, j, j + 1);
                    }
                }
            }
        } else {
            for (int j = start; j < end + 1; j++) {
                uint32_t actualRangeOffset = kHeaderSize + 6 * segCount + rangeOffset +
                    (i + j - start) * 2;
                if (actualRangeOffset + 2 > size) {
                    // invalid rangeOffset is considered a "warning" by OpenType Sanitizer
                    continue;
                }
                int glyphId = readU16(data, actualRangeOffset);
                if (glyphId != 0) {
                    addRange(coverage, j, j + 1);
                }
            }
        }
    }
    return true;
}

// Get the coverage information out of a Format 12 subtable, storing it in the coverage vector
static bool getCoverageFormat12(vector<uint32_t>& coverage, const uint8_t* data, size_t size) {
    const size_t kNGroupsOffset = 12;
    const size_t kFirstGroupOffset = 16;
    const size_t kGroupSize = 12;
    const size_t kStartCharCodeOffset = 0;
    const size_t kEndCharCodeOffset = 4;
    if (kFirstGroupOffset > size) {
        return false;
    }
    uint32_t nGroups = readU32(data, kNGroupsOffset);
    if (kFirstGroupOffset + nGroups * kGroupSize > size) {
        return false;
    }
    for (uint32_t i = 0; i < nGroups; i++) {
        uint32_t groupOffset = kFirstGroupOffset + i * kGroupSize;
        uint32_t start = readU32(data, groupOffset + kStartCharCodeOffset);
        uint32_t end = readU32(data, groupOffset + kEndCharCodeOffset);
        addRange(coverage, start, end + 1);  // file is inclusive, vector is exclusive
    }
    return true;
}

bool CmapCoverage::getCoverage(SparseBitSet& coverage, const uint8_t* cmap_data, size_t cmap_size) {
    vector<uint32_t> coverageVec;
    const size_t kHeaderSize = 4;
    const size_t kNumTablesOffset = 2;
    const size_t kTableSize = 8;
    const size_t kPlatformIdOffset = 0;
    const size_t kEncodingIdOffset = 2;
    const size_t kOffsetOffset = 4;
    const int kMicrosoftPlatformId = 3;
    const int kUnicodeBmpEncodingId = 1;
    const int kUnicodeUcs4EncodingId = 10;
    if (kHeaderSize > cmap_size) {
        return false;
    }
    int numTables = readU16(cmap_data, kNumTablesOffset);
    if (kHeaderSize + numTables * kTableSize > cmap_size) {
        return false;
    }
    int bestTable = -1;
    for (int i = 0; i < numTables; i++) {
        uint16_t platformId = readU16(cmap_data, kHeaderSize + i * kTableSize + kPlatformIdOffset);
        uint16_t encodingId = readU16(cmap_data, kHeaderSize + i * kTableSize + kEncodingIdOffset);
        if (platformId == kMicrosoftPlatformId && encodingId == kUnicodeUcs4EncodingId) {
            bestTable = i;
            break;
        } else if (platformId == kMicrosoftPlatformId && encodingId == kUnicodeBmpEncodingId) {
            bestTable = i;
        }
    }
#ifdef VERBOSE_DEBUG
    ALOGD("best table = %d\n", bestTable);
#endif
    if (bestTable < 0) {
        return false;
    }
    uint32_t offset = readU32(cmap_data, kHeaderSize + bestTable * kTableSize + kOffsetOffset);
    if (offset + 2 > cmap_size) {
        return false;
    }
    uint16_t format = readU16(cmap_data, offset);
    bool success = false;
    const uint8_t* tableData = cmap_data + offset;
    const size_t tableSize = cmap_size - offset;
    if (format == 4) {
        success = getCoverageFormat4(coverageVec, tableData, tableSize);
    } else if (format == 12) {
        success = getCoverageFormat12(coverageVec, tableData, tableSize);
    }
    if (success) {
        coverage.initFromRanges(&coverageVec.front(), coverageVec.size() >> 1);
    }
#ifdef VERBOSE_DEBUG
    for (size_t i = 0; i < coverageVec.size(); i += 2) {
        ALOGD("%x:%x\n", coverageVec[i], coverageVec[i + 1]);
    }
    ALOGD("success = %d", success);
#endif
    return success;
}

}  // namespace android
<commit_msg>Avoid integer overflows in parsing fonts am: 6299a6ba13<commit_after>/*
 * Copyright (C) 2013 The Android Open Source Project
 *
 * 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.
 */

// Determine coverage of font given its raw "cmap" OpenType table

#define LOG_TAG "Minikin"
#include <cutils/log.h>

#include <vector>
using std::vector;

#include <minikin/SparseBitSet.h>
#include <minikin/CmapCoverage.h>

namespace android {

// These could perhaps be optimized to use __builtin_bswap16 and friends.
static uint32_t readU16(const uint8_t* data, size_t offset) {
    return ((uint32_t)data[offset]) << 8 | ((uint32_t)data[offset + 1]);
}

static uint32_t readU32(const uint8_t* data, size_t offset) {
    return ((uint32_t)data[offset]) << 24 | ((uint32_t)data[offset + 1]) << 16 |
        ((uint32_t)data[offset + 2]) << 8 | ((uint32_t)data[offset + 3]);
}

static void addRange(vector<uint32_t> &coverage, uint32_t start, uint32_t end) {
#ifdef VERBOSE_DEBUG
    ALOGD("adding range %d-%d\n", start, end);
#endif
    if (coverage.empty() || coverage.back() < start) {
        coverage.push_back(start);
        coverage.push_back(end);
    } else {
        coverage.back() = end;
    }
}

// Get the coverage information out of a Format 12 subtable, storing it in the coverage vector
static bool getCoverageFormat4(vector<uint32_t>& coverage, const uint8_t* data, size_t size) {
    const size_t kSegCountOffset = 6;
    const size_t kEndCountOffset = 14;
    const size_t kHeaderSize = 16;
    const size_t kSegmentSize = 8;  // total size of array elements for one segment
    if (kEndCountOffset > size) {
        return false;
    }
    size_t segCount = readU16(data, kSegCountOffset) >> 1;
    if (kHeaderSize + segCount * kSegmentSize > size) {
        return false;
    }
    for (size_t i = 0; i < segCount; i++) {
        int end = readU16(data, kEndCountOffset + 2 * i);
        int start = readU16(data, kHeaderSize + 2 * (segCount + i));
        int rangeOffset = readU16(data, kHeaderSize + 2 * (3 * segCount + i));
        if (rangeOffset == 0) {
            int delta = readU16(data, kHeaderSize + 2 * (2 * segCount + i));
            if (((end + delta) & 0xffff) > end - start) {
                addRange(coverage, start, end + 1);
            } else {
                for (int j = start; j < end + 1; j++) {
                    if (((j + delta) & 0xffff) != 0) {
                        addRange(coverage, j, j + 1);
                    }
                }
            }
        } else {
            for (int j = start; j < end + 1; j++) {
                uint32_t actualRangeOffset = kHeaderSize + 6 * segCount + rangeOffset +
                    (i + j - start) * 2;
                if (actualRangeOffset + 2 > size) {
                    // invalid rangeOffset is considered a "warning" by OpenType Sanitizer
                    continue;
                }
                int glyphId = readU16(data, actualRangeOffset);
                if (glyphId != 0) {
                    addRange(coverage, j, j + 1);
                }
            }
        }
    }
    return true;
}

// Get the coverage information out of a Format 12 subtable, storing it in the coverage vector
static bool getCoverageFormat12(vector<uint32_t>& coverage, const uint8_t* data, size_t size) {
    const size_t kNGroupsOffset = 12;
    const size_t kFirstGroupOffset = 16;
    const size_t kGroupSize = 12;
    const size_t kStartCharCodeOffset = 0;
    const size_t kEndCharCodeOffset = 4;
    const size_t kMaxNGroups = 0xfffffff0 / kGroupSize;  // protection against overflow
    // For all values < kMaxNGroups, kFirstGroupOffset + nGroups * kGroupSize fits in 32 bits.
    if (kFirstGroupOffset > size) {
        return false;
    }
    uint32_t nGroups = readU32(data, kNGroupsOffset);
    if (nGroups >= kMaxNGroups || kFirstGroupOffset + nGroups * kGroupSize > size) {
        return false;
    }
    for (uint32_t i = 0; i < nGroups; i++) {
        uint32_t groupOffset = kFirstGroupOffset + i * kGroupSize;
        uint32_t start = readU32(data, groupOffset + kStartCharCodeOffset);
        uint32_t end = readU32(data, groupOffset + kEndCharCodeOffset);
        addRange(coverage, start, end + 1);  // file is inclusive, vector is exclusive
    }
    return true;
}

bool CmapCoverage::getCoverage(SparseBitSet& coverage, const uint8_t* cmap_data, size_t cmap_size) {
    vector<uint32_t> coverageVec;
    const size_t kHeaderSize = 4;
    const size_t kNumTablesOffset = 2;
    const size_t kTableSize = 8;
    const size_t kPlatformIdOffset = 0;
    const size_t kEncodingIdOffset = 2;
    const size_t kOffsetOffset = 4;
    const int kMicrosoftPlatformId = 3;
    const int kUnicodeBmpEncodingId = 1;
    const int kUnicodeUcs4EncodingId = 10;
    if (kHeaderSize > cmap_size) {
        return false;
    }
    int numTables = readU16(cmap_data, kNumTablesOffset);
    if (kHeaderSize + numTables * kTableSize > cmap_size) {
        return false;
    }
    int bestTable = -1;
    for (int i = 0; i < numTables; i++) {
        uint16_t platformId = readU16(cmap_data, kHeaderSize + i * kTableSize + kPlatformIdOffset);
        uint16_t encodingId = readU16(cmap_data, kHeaderSize + i * kTableSize + kEncodingIdOffset);
        if (platformId == kMicrosoftPlatformId && encodingId == kUnicodeUcs4EncodingId) {
            bestTable = i;
            break;
        } else if (platformId == kMicrosoftPlatformId && encodingId == kUnicodeBmpEncodingId) {
            bestTable = i;
        }
    }
#ifdef VERBOSE_DEBUG
    ALOGD("best table = %d\n", bestTable);
#endif
    if (bestTable < 0) {
        return false;
    }
    uint32_t offset = readU32(cmap_data, kHeaderSize + bestTable * kTableSize + kOffsetOffset);
    if (offset + 2 > cmap_size) {
        return false;
    }
    uint16_t format = readU16(cmap_data, offset);
    bool success = false;
    const uint8_t* tableData = cmap_data + offset;
    const size_t tableSize = cmap_size - offset;
    if (format == 4) {
        success = getCoverageFormat4(coverageVec, tableData, tableSize);
    } else if (format == 12) {
        success = getCoverageFormat12(coverageVec, tableData, tableSize);
    }
    if (success) {
        coverage.initFromRanges(&coverageVec.front(), coverageVec.size() >> 1);
    }
#ifdef VERBOSE_DEBUG
    for (size_t i = 0; i < coverageVec.size(); i += 2) {
        ALOGD("%x:%x\n", coverageVec[i], coverageVec[i + 1]);
    }
    ALOGD("success = %d", success);
#endif
    return success;
}

}  // namespace android
<|endoftext|>


<commit_before><commit_msg>WaE: MSVC2008 C2220 unsafe mix of types in operation<commit_after><|endoftext|>


<commit_before>/* **** **** **** **** **** **** **** **** *
 *
 *         _/        _/        _/
 *        _/_/_/    _/_/_/    _/_/_/
 *       _/    _/  _/    _/  _/    _/
 *      _/    _/  _/    _/  _/    _/
 *     _/_/_/    _/_/_/    _/_/_/
 *
 * bit by bit
 * bit_by_bit.hpp
 *
 * author: ISHII 2bit
 * mail:   2bit@backspace.tokyo
 *
 * **** **** **** **** **** **** **** **** */

#pragma once

#include "constants.hpp"
#include "type_utils.hpp"
#include "container_utils.hpp"
#include "reusable_array.hpp"
#include "thread_utils.hpp"
#include "math_utils.hpp"
#include "stop_watch.hpp"
<commit_msg>include logger.hpp in bit_by_bit.hpp<commit_after>/* **** **** **** **** **** **** **** **** *
 *
 *         _/        _/        _/
 *        _/_/_/    _/_/_/    _/_/_/
 *       _/    _/  _/    _/  _/    _/
 *      _/    _/  _/    _/  _/    _/
 *     _/_/_/    _/_/_/    _/_/_/
 *
 * bit by bit
 * bit_by_bit.hpp
 *
 * author: ISHII 2bit
 * mail:   2bit@backspace.tokyo
 *
 * **** **** **** **** **** **** **** **** */

#pragma once

#include "constants.hpp"
#include "type_utils.hpp"
#include "container_utils.hpp"
#include "reusable_array.hpp"
#include "thread_utils.hpp"
#include "math_utils.hpp"
#include "stop_watch.hpp"
#include "logger.hpp"<|endoftext|>


<commit_before>/******************************************************************************
 * (C) Copyright 2020 AMIQ Consulting
 *
 * 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.
 *
 * MODULE:      BLOG
 * PROJECT:     Non-blocking socket communication in SV using DPI-C
 * Description: This is a code snippet from the Blog article mentioned on PROJECT
 * Link:
 *******************************************************************************/

#include <arpa/inet.h>
#include <errno.h>
#include <poll.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <unistd.h>
#include <netinet/tcp.h>
#include <thread>
#include <cstring>
#include <string>

//#include <svdpi.h>

#define BUFFER_SIZE 512

extern "C" void recv_callback(char * msg);
extern "C" void consume_time();

static int run_finished = 0;

//Client Arguments
struct ConnConfiguration {
	int port;		    // the port number
	char *hostname;     // the name of server's host
};

enum class ConnectionState {
	UNCONFIGURED, CONFIGURED, CONNECTED
};

struct Connection {
	// Use this to get the actual connection
	static Connection &instance() {
		static Connection conn;
		return conn;
	}

	~Connection() {
		if (sock_fd != -1) {
			close(sock_fd);
		}
	}

	std::string state_to_string() const {
		switch (state) {
		case ConnectionState::UNCONFIGURED:
			return "Unconfigured";
		case ConnectionState::CONFIGURED:
			return "Configured";
		case ConnectionState::CONNECTED:
			return "Connected";
		default:
			break;
		}

		return "Error";
	}

	ConnectionState get_state() const {
		return state;
	}

	void set_state(const ConnectionState new_state) {
		// blabla checks
		if (state == ConnectionState::CONNECTED
				&& new_state == ConnectionState::CONFIGURED) {
			// Cleanup
			close(sock_fd);
			sock_fd = -1;
		}

		state = new_state;
	}

	void set_sockfd(const int sockfd) {
		sock_fd = sockfd;

		// Assign pollfd events
		recv_event.fd = sockfd;
		recv_event.events = POLLIN;

		send_event.fd = sockfd;
		send_event.events = POLLOUT;
	}

	// How many miliseconds to wait for socket events when reading/writing to it
	void set_timeout(const int miliseconds) {
		timeout = miliseconds;
	}

	/**
	 * Throws:
	 * 	 -1 on error
	 * 	 1 if sending would block (unlikely)
	 *
	 * Returns number of bytes sent to remote
	 */
	int do_send(const char *data, int len) {

		int status = can_use_connection();
		if (!status) {
			return status;
		}

		int event_ready = poll(&send_event, 1, timeout);
		if (event_ready == -1) {
			throw -1;
		}

		int can_send = send_event.revents & POLLOUT;
		if (!can_send) {
			throw 1;
		}

		int sent = send(sock_fd, data, len, 0);
		return sent;
	}

	/**
	 * Throws:
	 * 	 -1 on error
	 * 	 1 if recv would block
	 *
	 * Returns number of bytes received from remote
	 */
	int do_recv(char *data, int len) {
		int status = can_use_connection();
		if (!status) {
			return status;
		}

		int event_ready = poll(&recv_event, 1, timeout);

		if (event_ready == -1) {
			throw -1;
		}

		int can_read = recv_event.revents & POLLIN;
		if (!can_read) {
			throw 1;
		}

		int received = recv(sock_fd, data, len, 0);

		return received;
	}

	void do_recv_forever() {
		int r;
		char data[BUFFER_SIZE+1];

		// receive transactions forever
		while (!run_finished) {

			try{
				r = do_recv(data, BUFFER_SIZE);
				if (r > 0) {
					data[r] = 0;
					recv_callback(data);
				}
			} catch (int e) {

				// Call to consume_time gives the SV simulator some indication that
				// it can schedule another SV thread for execution. If this exported SV
				// task is never executed, the simulator will continue to poll on the
				// socket for receive, without giving any chance to the send thread to execute.
				// This function is called only when there is nothing to read

				// (1) - means timeout on poll
				if(e == 1){
					consume_time();
				}

				else if(e == -1){
					printf("\n Error while polling socket! errno = %s \n", std::strerror(errno));
				}

			}
		}
	}

private:

	int sock_fd;

	ConnectionState state;

	pollfd recv_event;
	pollfd send_event;

	int timeout;

	Connection() {
		state = ConnectionState::UNCONFIGURED;
		sock_fd = -1;
		timeout = 0;
	}

	Connection(const Connection &) = delete;
	Connection &operator=(const Connection &) = delete;

	int can_use_connection() const {
		if (state != ConnectionState::CONNECTED) {
			//printf("Client is not connected to remote!\n");
			//printf("Client is in state '%s'", state_to_string().c_str());
			return false;
		}

		return true;
	}
};

// Use this to configure the remote host (the Python server)
// Returns 0 if the connection succedeed, 1 otherwise
extern "C" int configure(const char *hostname, int port) {
	Connection &conn = Connection::instance();

	conn.set_state(ConnectionState::CONFIGURED);

	// Create socket
	int sockfd = socket(AF_INET, SOCK_STREAM | SOCK_NONBLOCK, 0);

	if (sockfd == -1) {
		perror("Failed to create socket");
		exit(1);
	}

	// Assign PORT
	struct sockaddr_in servaddr;
	memset(&servaddr, 0, sizeof(servaddr));
	servaddr.sin_family = AF_INET;
	servaddr.sin_port = htons(port);

	// See if we got an ip or a hostname (like localhost)
	struct hostent *server = gethostbyname(hostname);
	if (server == NULL) {
		servaddr.sin_addr.s_addr = inet_addr(hostname);
	} else {
		memcpy((char *) &(servaddr.sin_addr.s_addr), server->h_addr,
		server->h_length);
	}

	// Try to connect
	int status = 0;
	do {
		status = connect(sockfd, (sockaddr *) &servaddr, sizeof(servaddr));
	} while (status != 0 && status != EINPROGRESS);

	if (status != 0) {
		perror("Connect failed");
		exit(1);
	}

	printf("Connected to %s:%u\n", hostname, port);

	conn.set_state(ConnectionState::CONNECTED);
	conn.set_sockfd(sockfd);

	return conn.get_state() != ConnectionState::CONNECTED;
}

extern "C" void set_timeout(const int miliseconds) {
	Connection &conn = Connection::instance();
	conn.set_timeout(miliseconds);
}

extern "C" int send_data(const char *data, int len) {
	Connection &conn = Connection::instance();
	int result;
	try{
		result = conn.do_send(data, len);
	}
	catch (int i){
		if(i == -1){
			consume_time();
		}
		else if(i == 1){
			printf("\n Error while polling socket! errno = %s \n", std::strerror(errno));
		}
		return -1;
	}
	return result;
}

extern "C" int recv_thread() {
	Connection &conn = Connection::instance();
	conn.do_recv_forever();

	// During the test, the task is enabled, therefore must return 0
	// At the end of the test, the task is disabled, therefore must return 1
	return run_finished;
}

extern "C" void set_run_finish() {
	printf("\n-------------------Called set_run_finish-------------------------\n");
	run_finished = 1;
}
<commit_msg>Update client.cc<commit_after>/******************************************************************************
 * (C) Copyright 2020 AMIQ Consulting
 *
 * 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.
 *
 * MODULE:      BLOG
 * PROJECT:     Non-blocking socket communication in SV using DPI-C
 * Description: This is a code snippet from the Blog article mentioned on PROJECT
 * Link:
 *******************************************************************************/

#include <arpa/inet.h>
#include <errno.h>
#include <poll.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <unistd.h>
#include <netinet/tcp.h>
#include <thread>
#include <cstring>
#include <string>

//#include <svdpi.h>

#define BUFFER_SIZE 512

extern "C" void recv_callback(char * msg);
extern "C" void consume_time();

static int run_finished = 0;

//Client Arguments
struct ConnConfiguration {
	int port;		    // the port number
	char *hostname;     // the name of server's host
};

enum class ConnectionState {
	UNCONFIGURED, CONFIGURED, CONNECTED
};

struct Connection {
	// Use this to get the actual connection
	static Connection &instance() {
		static Connection conn;
		return conn;
	}

	~Connection() {
		if (sock_fd != -1) {
			close(sock_fd);
		}
	}

	std::string state_to_string() const {
		switch (state) {
		case ConnectionState::UNCONFIGURED:
			return "Unconfigured";
		case ConnectionState::CONFIGURED:
			return "Configured";
		case ConnectionState::CONNECTED:
			return "Connected";
		default:
			break;
		}

		return "Error";
	}

	ConnectionState get_state() const {
		return state;
	}

	void set_state(const ConnectionState new_state) {
		// blabla checks
		if (state == ConnectionState::CONNECTED
				&& new_state == ConnectionState::CONFIGURED) {
			// Cleanup
			close(sock_fd);
			sock_fd = -1;
		}

		state = new_state;
	}

	void set_sockfd(const int sockfd) {
		sock_fd = sockfd;

		// Assign pollfd events
		recv_event.fd = sockfd;
		recv_event.events = POLLIN;

		send_event.fd = sockfd;
		send_event.events = POLLOUT;
	}

	// How many miliseconds to wait for socket events when reading/writing to it
	void set_timeout(const int miliseconds) {
		timeout = miliseconds;
	}

	/**
	 * Throws:
	 * 	 -1 on error
	 * 	 1 if sending would block (unlikely)
	 *
	 * Returns number of bytes sent to remote
	 */
	int do_send(const char *data, int len) {

		int status = can_use_connection();
		if (!status) {
			return status;
		}

		int event_ready = poll(&send_event, 1, timeout);
		if (event_ready == -1) {
			throw -1;
		}

		int can_send = send_event.revents & POLLOUT;
		if (!can_send) {
			throw 1;
		}

		int sent = send(sock_fd, data, len, 0);
		return sent;
	}

	/**
	 * Throws:
	 * 	 -1 on error
	 * 	 1 if recv would block
	 *
	 * Returns number of bytes received from remote
	 */
	int do_recv(char *data, int len) {
		int status = can_use_connection();
		if (!status) {
			return status;
		}

		int event_ready = poll(&recv_event, 1, timeout);

		if (event_ready == -1) {
			throw -1;
		}

		int can_read = recv_event.revents & POLLIN;
		if (!can_read) {
			throw 1;
		}

		int received = recv(sock_fd, data, len, 0);

		return received;
	}

	void do_recv_forever() {
		int r;
		char data[BUFFER_SIZE+1];

		// receive transactions forever
		while (!run_finished) {

			try{
				r = do_recv(data, BUFFER_SIZE);
				if (r > 0) {
					data[r] = 0;
					recv_callback(data);
				}
			} catch (int e) {

				// Call to consume_time gives the SV simulator some indication that
				// it can schedule another SV thread for execution. If this exported SV
				// task is never executed, the simulator will continue to poll on the
				// socket for receive, without giving any chance to the send thread to execute.
				// This function is called only when there is nothing to read

				// (1) - means timeout on poll
				if(e == 1){
					consume_time();
				}

				else if(e == -1){
					printf("\n Error while polling socket! errno = %s \n", std::strerror(errno));
				}

			}
		}
	}

private:

	int sock_fd;

	ConnectionState state;

	pollfd recv_event;
	pollfd send_event;

	int timeout;

	Connection() {
		state = ConnectionState::UNCONFIGURED;
		sock_fd = -1;
		timeout = 0;
	}

	Connection(const Connection &) = delete;
	Connection &operator=(const Connection &) = delete;

	int can_use_connection() const {
		if (state != ConnectionState::CONNECTED) {
			//printf("Client is not connected to remote!\n");
			//printf("Client is in state '%s'", state_to_string().c_str());
			return false;
		}

		return true;
	}
};

// Use this to configure the remote host (the Python server)
// Returns 0 if the connection succedeed, 1 otherwise
extern "C" int configure(const char *hostname, int port) {
	Connection &conn = Connection::instance();

	conn.set_state(ConnectionState::CONFIGURED);

	// Create socket
	int sockfd = socket(AF_INET, SOCK_STREAM | SOCK_NONBLOCK, 0);

	if (sockfd == -1) {
		perror("Failed to create socket");
		exit(1);
	}

	// Assign PORT
	struct sockaddr_in servaddr;
	memset(&servaddr, 0, sizeof(servaddr));
	servaddr.sin_family = AF_INET;
	servaddr.sin_port = htons(port);

	// See if we got an ip or a hostname (like localhost)
	struct hostent *server = gethostbyname(hostname);
	if (server == NULL) {
		servaddr.sin_addr.s_addr = inet_addr(hostname);
	} else {
		memcpy((char *) &(servaddr.sin_addr.s_addr), server->h_addr,
		server->h_length);
	}

	// Try to connect
	int status = 0;
	do {
		status = connect(sockfd, (sockaddr *) &servaddr, sizeof(servaddr));
	} while (status != 0 && status != EINPROGRESS);

	if (status != 0) {
		perror("Connect failed");
		exit(1);
	}

	printf("Connected to %s:%u\n", hostname, port);

	conn.set_state(ConnectionState::CONNECTED);
	conn.set_sockfd(sockfd);

	return conn.get_state() != ConnectionState::CONNECTED;
}

extern "C" void set_timeout(const int miliseconds) {
	Connection &conn = Connection::instance();
	conn.set_timeout(miliseconds);
}

extern "C" int send_data(const char *data, int len, int* result) {
	Connection &conn = Connection::instance();
	try{
		*result = conn.do_send(data, len);
	}
	catch (int i){
		if(i == -1){
			consume_time();
		}
		else if(i == 1){
			printf("\n Error while polling socket! errno = %s \n", std::strerror(errno));
		}
		return -1;
	}
	return run_finished;
}

extern "C" int recv_thread() {
	Connection &conn = Connection::instance();
	conn.do_recv_forever();

	// During the test, the task is enabled, therefore must return 0
	// At the end of the test, the task is disabled, therefore must return 1
	return run_finished;
}

extern "C" void set_run_finish() {
	printf("\n-------------------Called set_run_finish-------------------------\n");
	run_finished = 1;
}
<|endoftext|>


<commit_before>/*
 * Copyright 2015 - 2018 gtalent2@gmail.com
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
 */

#pragma once

#include "types.hpp"

namespace ox {

template<typename T>
[[nodiscard]] inline constexpr T rotateLeft(T i, std::size_t shift) {
	constexpr auto bits = sizeof(i) * 8;
	return (i << shift) | (i >> (bits - shift));
}

template<typename T>
[[nodiscard]] constexpr T onMask(int bits = sizeof(T) * 8) {
	T out = 0;
	for (auto i = 0; i < bits; i++) {
		out |= static_cast<T>(1) << i;
	}
	return out;
}

static_assert(onMask<int>(1) == 1);
static_assert(onMask<int>(2) == 3);
static_assert(onMask<int>(3) == 7);
static_assert(onMask<int>(4) == 15);

}
<commit_msg>[ox/std] Add noexcept to bitops functions<commit_after>/*
 * Copyright 2015 - 2018 gtalent2@gmail.com
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
 */

#pragma once

#include "types.hpp"

namespace ox {

template<typename T>
[[nodiscard]] inline constexpr T rotateLeft(T i, std::size_t shift) noexcept {
	constexpr auto bits = sizeof(i) * 8;
	return (i << shift) | (i >> (bits - shift));
}

template<typename T>
[[nodiscard]] constexpr T onMask(int bits = sizeof(T) << 3 /* *8 */) noexcept {
	T out = 0;
	for (auto i = 0; i < bits; i++) {
		out |= static_cast<T>(1) << i;
	}
	return out;
}

static_assert(onMask<int>(1) == 1);
static_assert(onMask<int>(2) == 3);
static_assert(onMask<int>(3) == 7);
static_assert(onMask<int>(4) == 15);

}
<|endoftext|>


<commit_before>/* vim: tabstop=2 shiftwidth=2 expandtab textwidth=80 linebreak wrap
 *
 * Copyright 2012 Matthew McCormick
 * Copyright 2013 Justin Crawford <Justasic@gmail.com>
 * Copyright 2015 Pawel 'l0ner' Soltys
 *
 * 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.
 */

// Based on: github.com/freebsd/freebsd/blob/master/usr.bin/top/machine.c
// Based on: Apple.cpp for load_string/mem_string and apple's documentation

#include <sys/types.h>
#include <unistd.h> // usleep

#include "getsysctl.h"
#include "cpu.h"

float cpu_percentage( unsigned int cpu_usage_delay )
{
  int32_t load1[CPUSTATES];
  int32_t load2[CPUSTATES];

  GETSYSCTL( "kern.cp_time", load1 );
  usleep( cpu_usage_delay );
  GETSYSCTL( "kern.cp_time", load2 );

  // Current load times
  unsigned long long current_user = load1[CP_USER];
  unsigned long long current_system = load1[CP_SYS];
  unsigned long long current_nice = load1[CP_NICE];
  unsigned long long current_idle = load1[CP_IDLE];
  // Next load times
  unsigned long long next_user = load2[CP_USER];
  unsigned long long next_system = load2[CP_SYS];
  unsigned long long next_nice = load2[CP_NICE];
  unsigned long long next_idle = load2[CP_IDLE];
  // Difference between the two
  unsigned long long diff_user = next_user - current_user;
  unsigned long long diff_system = next_system - current_system;
  unsigned long long diff_nice = next_nice - current_nice;
  unsigned long long diff_idle = next_idle - current_idle;

  return static_cast<float>( diff_user + diff_system + diff_nice ) /
    static_cast<float>( diff_user + diff_system + diff_nice + diff_idle ) *
    100.0;
}
<commit_msg>Fix for cpu sysctl failing on 64bit FreeBSD same as commit  80d70b7a4d5ee9a4ba79deae0e840c65ccaf4131<commit_after>/* vim: tabstop=2 shiftwidth=2 expandtab textwidth=80 linebreak wrap
 *
 * Copyright 2012 Matthew McCormick
 * Copyright 2013 Justin Crawford <Justasic@gmail.com>
 * Copyright 2015 Pawel 'l0ner' Soltys
 *
 * 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.
 */

// Based on: github.com/freebsd/freebsd/blob/master/usr.bin/top/machine.c
// Based on: Apple.cpp for load_string/mem_string and apple's documentation

#include <sys/types.h>
#include <unistd.h> // usleep

#include "getsysctl.h"
#include "cpu.h"

float cpu_percentage( unsigned int cpu_usage_delay )
{
#if __x86_64__ || __ppc64__
  u_int64_t load1[CPUSTATES];
  u_int64_t load2[CPUSTATES];
#else
  u_int32_t load1[CPUSTATES];
  u_int32_t load2[CPUSTATES];
#endif

  GETSYSCTL( "kern.cp_time", load1 );
  usleep( cpu_usage_delay );
  GETSYSCTL( "kern.cp_time", load2 );

  // Current load times
  unsigned long long current_user = load1[CP_USER];
  unsigned long long current_system = load1[CP_SYS];
  unsigned long long current_nice = load1[CP_NICE];
  unsigned long long current_idle = load1[CP_IDLE];
  // Next load times
  unsigned long long next_user = load2[CP_USER];
  unsigned long long next_system = load2[CP_SYS];
  unsigned long long next_nice = load2[CP_NICE];
  unsigned long long next_idle = load2[CP_IDLE];
  // Difference between the two
  unsigned long long diff_user = next_user - current_user;
  unsigned long long diff_system = next_system - current_system;
  unsigned long long diff_nice = next_nice - current_nice;
  unsigned long long diff_idle = next_idle - current_idle;

  return static_cast<float>( diff_user + diff_system + diff_nice ) /
    static_cast<float>( diff_user + diff_system + diff_nice + diff_idle ) *
    100.0;
}
<|endoftext|>