<commit_before>/* Luwra
 * Minimal-overhead Lua wrapper for C++
 *
 * Copyright (C) 2015, Ole Krüger <ole@vprsm.de>
 */

#ifndef LUWRA_TYPES_H_
#define LUWRA_TYPES_H_

#include "common.hpp"

#include <utility>
#include <tuple>
#include <string>
#include <type_traits>
#include <limits>

LUWRA_NS_BEGIN

/* Lua types */
using Integer = lua_Integer;
using Number = lua_Number;
using State = lua_State;
using CFunction = lua_CFunction;

/**
 * A value on the stack
 */
template <typename T>
struct Value {
	static_assert(
		sizeof(T) == -1,
		"Parameter to Value is not supported"
	);
};

/**
 * Convenient wrapped for `Value<T>::push`.
 */
template <typename T> static inline
int push(State* state, T value) {
	return Value<T>::push(state, value);
}

/**
 * Convenient wrapper for `Value<T>::read`.
 */
template <typename T> static inline
T read(State* state, int index) {
	return Value<T>::read(state, index);
}

/**
 * Define a template specialization of `Value` for `type` with a `retrf(State*, int)` which
 * extracts it from the stack and a `pushf(State*, type)` which pushes the value on the stack again.
 * This assumes that only one value will be pushed onto the stack.
 */
#define LUWRA_DEF_VALUE(type, retrf, pushf)                          \
	template <>                                                      \
	struct Value<type> {                                             \
		static inline                                                \
		type read(State* state, int n) {                             \
			return retrf(state, n);                                  \
		}                                                            \
                                                                     \
		static inline                                                \
		int push(State* state, type value) {                         \
			pushf(state, value);                                     \
			return 1;                                                \
		}                                                            \
	}

#ifndef luaL_checkboolean
	/**
	 * Check if the value at index `n` is a boolean and retrieve its value.
	 */
	#define luaL_checkboolean(state, n) \
		(luaL_checktype(state, n, LUA_TBOOLEAN), lua_toboolean(state, n))
#endif

#ifndef luaL_checkcfunction
	/**
	 * Check if the value at index `n` is a C function and retrieve it.
	 */
	#define luaL_checkcfunction(state, n) \
		(luaL_checktype(state, n, LUA_TCFUNCTION), lua_toboolean(state, n))
#endif

#ifndef luaL_pushstdstring
	/**
	 * push a `std::string` as string onto the stack.
	 */
	#define luaL_pushstdstring(state, stdstring) \
		(lua_pushstring(state, (stdstring).c_str()))
#endif

namespace internal {
	template <typename T>
	struct NumericTransportValue {
		static_assert(
			sizeof(T) == -1,
			"Parameter to NumericTransportValue is not a numeric base type"
		);
	};

	// Transport unit `Integer`
	template <>
	struct NumericTransportValue<Integer> {
		static inline
		Integer read(State* state, int index) {
			return luaL_checkinteger(state, index);
		}

		static inline
		int push(State* state, Integer value) {
			lua_pushinteger(state, value);
			return 1;
		}
	};

	// Transport unit `Number`
	template <>
	struct NumericTransportValue<Number> {
		static inline
		Number read(State* state, int index) {
			return luaL_checknumber(state, index);
		}

		static inline
		int push(State* state, Number value) {
			lua_pushnumber(state, value);
			return 1;
		}
	};

	// Base for `Value<I>` specializations which uses `B` as transport unit, where `I` is smaller
	// than `B`.
	template <typename I, typename B>
	struct NumericContainedValueBase {
		static constexpr
		bool qualifies =
			// TODO: Remove warning about comparsion between signed and unsigned integers
			std::numeric_limits<I>::max() <= std::numeric_limits<B>::max()
			&& std::numeric_limits<I>::lowest() >= std::numeric_limits<B>::lowest();

		static inline
		I read(State* state, int index) {
			return
				static_cast<I>(NumericTransportValue<B>::read(state, index));
		}

		static inline
		int push(State* state, I value) {
			NumericTransportValue<B>::push(state, static_cast<B>(value));
			return 1;
		}
	};

	// Base for `Value<I>` specializations which uses `B` as transport unit, where `I` is bigger
	// than `B`.
	template <typename I, typename B>
	struct NumericTruncatingValueBase {
		static inline
		I read(State* state, int index) {
			return static_cast<I>(NumericTransportValue<B>::read(state, index));
		}

		static inline
		int push(State*, I) {
			static_assert(
				sizeof(I) == -1,
				"You must not use 'Value<I>::push' specializations which inherit from NumericTruncatingValueBase"
			);

			return -1;
		}
	};

	// Base for `Value<I>` specializations which uses `B` as transport unit
	template <typename I, typename B>
	using NumericValueBase =
		typename std::conditional<
			std::is_same<I, B>::value,
			NumericTransportValue<B>,
			typename std::conditional<
				NumericContainedValueBase<I, B>::qualifies,
				NumericContainedValueBase<I, B>,
				NumericTruncatingValueBase<I, B>
			>::type
		>::type;
}

/**
 * Define an integral type which will be transported via `base`.
 */
#define LUWRA_DEF_NUMERIC(base, type) \
	template <> \
	struct Value<type>: internal::NumericValueBase<type, base> {};

// Lua-dependent types
LUWRA_DEF_NUMERIC(Number, float)
LUWRA_DEF_NUMERIC(Number, double)
LUWRA_DEF_NUMERIC(Number, long double)

// Integral types
LUWRA_DEF_NUMERIC(Integer, signed   char)
LUWRA_DEF_NUMERIC(Integer, unsigned char)
LUWRA_DEF_NUMERIC(Integer, signed   short)
LUWRA_DEF_NUMERIC(Integer, unsigned short)
LUWRA_DEF_NUMERIC(Integer, signed   int)
LUWRA_DEF_NUMERIC(Integer, unsigned int)
LUWRA_DEF_NUMERIC(Integer, signed   long int)
LUWRA_DEF_NUMERIC(Integer, unsigned long int)
LUWRA_DEF_NUMERIC(Integer, signed   long long int)
LUWRA_DEF_NUMERIC(Integer, unsigned long long int)

// C/C++ types
LUWRA_DEF_VALUE(bool,        luaL_checkboolean, lua_pushboolean);
LUWRA_DEF_VALUE(const char*, luaL_checkstring,  lua_pushstring);
LUWRA_DEF_VALUE(std::string, luaL_checkstring,  luaL_pushstdstring);

// Do not export these macros
#undef LUWRA_DEF_VALUE
#undef LUWRA_DEF_NUMERIC

/**
 * C Functions may be pushed aswell.
 */
template <>
struct Value<CFunction> {
	static inline
	int push(State* state, CFunction fun) {
		lua_pushcfunction(state, fun);
		return 1;
	}
};

/**
 * An arbitrary value on an execution stack.
 * Note: this value is only available as long as it exists on its originating stack.
 */
struct Arbitrary {
	State* state;
	int index;
};

template <>
struct Value<Arbitrary> {
	static inline
	Arbitrary read(State* state, int index) {
		if (index < 0)
			index = lua_gettop(state) + (index + 1);

		return Arbitrary {state, index};
	}

	static inline
	int push(State* state, const Arbitrary& value) {
		lua_pushvalue(value.state, value.index);

		if (value.state != state)
			lua_xmove(value.state, state, 1);

		return 1;
	}
};

namespace internal {
	template <typename>
	struct StackPusher;

	template <size_t I>
	struct StackPusher<std::index_sequence<I>> {
		template <typename... T> static inline
		int push(State* state, const std::tuple<T...>& package) {
			using R = typename std::tuple_element<I, std::tuple<T...>>::type;
			return std::max(0, Value<R>::push(state, std::get<I>(package)));
		}
	};

	template <size_t I, size_t... Is>
	struct StackPusher<std::index_sequence<I, Is...>> {
		template <typename... T> static inline
		int push(State* state, const std::tuple<T...>& package) {
			return
				StackPusher<std::index_sequence<I>>::push(state, package)
				+ StackPusher<std::index_sequence<Is...>>::push(state, package);
		}
	};
}

/**
 * Allows you to use multiple return values.
 */
template <typename... A>
struct Value<std::tuple<A...>> {
	static inline
	int push(State* state, const std::tuple<A...>& value) {
		return internal::StackPusher<std::make_index_sequence<sizeof...(A)>>::push(state, value);
	}
};

/**
 * Fix specialization for const types.
 */
template <typename T>
struct Value<const T>: Value<T> {};

/**
 * Fix specialization for volatile types.
 */
template <typename T>
struct Value<volatile T>: Value<T> {};

LUWRA_NS_END

#endif
<commit_msg>Add alias Value specialization for string literals<commit_after>/* Luwra
 * Minimal-overhead Lua wrapper for C++
 *
 * Copyright (C) 2015, Ole Krüger <ole@vprsm.de>
 */

#ifndef LUWRA_TYPES_H_
#define LUWRA_TYPES_H_

#include "common.hpp"

#include <utility>
#include <tuple>
#include <string>
#include <type_traits>
#include <limits>

LUWRA_NS_BEGIN

/* Lua types */
using Integer = lua_Integer;
using Number = lua_Number;
using State = lua_State;
using CFunction = lua_CFunction;

/**
 * A value on the stack
 */
template <typename T>
struct Value {
	static_assert(
		sizeof(T) == -1,
		"Parameter to Value is not supported"
	);
};

/**
 * Convenient wrapped for `Value<T>::push`.
 */
template <typename T> static inline
int push(State* state, T value) {
	return Value<T>::push(state, value);
}

/**
 * Convenient wrapper for `Value<T>::read`.
 */
template <typename T> static inline
T read(State* state, int index) {
	return Value<T>::read(state, index);
}

/**
 * Define a template specialization of `Value` for `type` with a `retrf(State*, int)` which
 * extracts it from the stack and a `pushf(State*, type)` which pushes the value on the stack again.
 * This assumes that only one value will be pushed onto the stack.
 */
#define LUWRA_DEF_VALUE(type, retrf, pushf)                          \
	template <>                                                      \
	struct Value<type> {                                             \
		static inline                                                \
		type read(State* state, int n) {                             \
			return retrf(state, n);                                  \
		}                                                            \
                                                                     \
		static inline                                                \
		int push(State* state, type value) {                         \
			pushf(state, value);                                     \
			return 1;                                                \
		}                                                            \
	}

#ifndef luaL_checkboolean
	/**
	 * Check if the value at index `n` is a boolean and retrieve its value.
	 */
	#define luaL_checkboolean(state, n) \
		(luaL_checktype(state, n, LUA_TBOOLEAN), lua_toboolean(state, n))
#endif

#ifndef luaL_checkcfunction
	/**
	 * Check if the value at index `n` is a C function and retrieve it.
	 */
	#define luaL_checkcfunction(state, n) \
		(luaL_checktype(state, n, LUA_TCFUNCTION), lua_toboolean(state, n))
#endif

#ifndef luaL_pushstdstring
	/**
	 * push a `std::string` as string onto the stack.
	 */
	#define luaL_pushstdstring(state, stdstring) \
		(lua_pushstring(state, (stdstring).c_str()))
#endif

namespace internal {
	template <typename T>
	struct NumericTransportValue {
		static_assert(
			sizeof(T) == -1,
			"Parameter to NumericTransportValue is not a numeric base type"
		);
	};

	// Transport unit `Integer`
	template <>
	struct NumericTransportValue<Integer> {
		static inline
		Integer read(State* state, int index) {
			return luaL_checkinteger(state, index);
		}

		static inline
		int push(State* state, Integer value) {
			lua_pushinteger(state, value);
			return 1;
		}
	};

	// Transport unit `Number`
	template <>
	struct NumericTransportValue<Number> {
		static inline
		Number read(State* state, int index) {
			return luaL_checknumber(state, index);
		}

		static inline
		int push(State* state, Number value) {
			lua_pushnumber(state, value);
			return 1;
		}
	};

	// Base for `Value<I>` specializations which uses `B` as transport unit, where `I` is smaller
	// than `B`.
	template <typename I, typename B>
	struct NumericContainedValueBase {
		static constexpr
		bool qualifies =
			// TODO: Remove warning about comparsion between signed and unsigned integers
			std::numeric_limits<I>::max() <= std::numeric_limits<B>::max()
			&& std::numeric_limits<I>::lowest() >= std::numeric_limits<B>::lowest();

		static inline
		I read(State* state, int index) {
			return
				static_cast<I>(NumericTransportValue<B>::read(state, index));
		}

		static inline
		int push(State* state, I value) {
			NumericTransportValue<B>::push(state, static_cast<B>(value));
			return 1;
		}
	};

	// Base for `Value<I>` specializations which uses `B` as transport unit, where `I` is bigger
	// than `B`.
	template <typename I, typename B>
	struct NumericTruncatingValueBase {
		static inline
		I read(State* state, int index) {
			return static_cast<I>(NumericTransportValue<B>::read(state, index));
		}

		static inline
		int push(State*, I) {
			static_assert(
				sizeof(I) == -1,
				"You must not use 'Value<I>::push' specializations which inherit from NumericTruncatingValueBase"
			);

			return -1;
		}
	};

	// Base for `Value<I>` specializations which uses `B` as transport unit
	template <typename I, typename B>
	using NumericValueBase =
		typename std::conditional<
			std::is_same<I, B>::value,
			NumericTransportValue<B>,
			typename std::conditional<
				NumericContainedValueBase<I, B>::qualifies,
				NumericContainedValueBase<I, B>,
				NumericTruncatingValueBase<I, B>
			>::type
		>::type;
}

/**
 * Define an integral type which will be transported via `base`.
 */
#define LUWRA_DEF_NUMERIC(base, type) \
	template <> \
	struct Value<type>: internal::NumericValueBase<type, base> {};

// Lua-dependent types
LUWRA_DEF_NUMERIC(Number, float)
LUWRA_DEF_NUMERIC(Number, double)
LUWRA_DEF_NUMERIC(Number, long double)

// Integral types
LUWRA_DEF_NUMERIC(Integer, signed   char)
LUWRA_DEF_NUMERIC(Integer, unsigned char)
LUWRA_DEF_NUMERIC(Integer, signed   short)
LUWRA_DEF_NUMERIC(Integer, unsigned short)
LUWRA_DEF_NUMERIC(Integer, signed   int)
LUWRA_DEF_NUMERIC(Integer, unsigned int)
LUWRA_DEF_NUMERIC(Integer, signed   long int)
LUWRA_DEF_NUMERIC(Integer, unsigned long int)
LUWRA_DEF_NUMERIC(Integer, signed   long long int)
LUWRA_DEF_NUMERIC(Integer, unsigned long long int)

// C/C++ types
LUWRA_DEF_VALUE(bool,        luaL_checkboolean, lua_pushboolean);
LUWRA_DEF_VALUE(const char*, luaL_checkstring,  lua_pushstring);
LUWRA_DEF_VALUE(std::string, luaL_checkstring,  luaL_pushstdstring);

// Do not export these macros
#undef LUWRA_DEF_VALUE
#undef LUWRA_DEF_NUMERIC

// Alias for string literals
template <size_t n>
struct Value<char[n]>: Value<const char*> {};

// Alias for const string literals
template <size_t n>
struct Value<const char[n]>: Value<const char*> {};

/**
 * C Functions may be pushed aswell.
 */
template <>
struct Value<CFunction> {
	static inline
	int push(State* state, CFunction fun) {
		lua_pushcfunction(state, fun);
		return 1;
	}
};

/**
 * An arbitrary value on an execution stack.
 * Note: this value is only available as long as it exists on its originating stack.
 */
struct Arbitrary {
	State* state;
	int index;
};

template <>
struct Value<Arbitrary> {
	static inline
	Arbitrary read(State* state, int index) {
		if (index < 0)
			index = lua_gettop(state) + (index + 1);

		return Arbitrary {state, index};
	}

	static inline
	int push(State* state, const Arbitrary& value) {
		lua_pushvalue(value.state, value.index);

		if (value.state != state)
			lua_xmove(value.state, state, 1);

		return 1;
	}
};

namespace internal {
	template <typename>
	struct StackPusher;

	template <size_t I>
	struct StackPusher<std::index_sequence<I>> {
		template <typename... T> static inline
		int push(State* state, const std::tuple<T...>& package) {
			using R = typename std::tuple_element<I, std::tuple<T...>>::type;
			return std::max(0, Value<R>::push(state, std::get<I>(package)));
		}
	};

	template <size_t I, size_t... Is>
	struct StackPusher<std::index_sequence<I, Is...>> {
		template <typename... T> static inline
		int push(State* state, const std::tuple<T...>& package) {
			return
				StackPusher<std::index_sequence<I>>::push(state, package)
				+ StackPusher<std::index_sequence<Is...>>::push(state, package);
		}
	};
}

/**
 * Allows you to use multiple return values.
 */
template <typename... A>
struct Value<std::tuple<A...>> {
	static inline
	int push(State* state, const std::tuple<A...>& value) {
		return internal::StackPusher<std::make_index_sequence<sizeof...(A)>>::push(state, value);
	}
};

/**
 * Fix specialization for const types.
 */
template <typename T>
struct Value<const T>: Value<T> {};

/**
 * Fix specialization for volatile types.
 */
template <typename T>
struct Value<volatile T>: Value<T> {};

LUWRA_NS_END

#endif
<|endoftext|>


<commit_before>/*! \file
 */

#include "Grid.h"

Grid::Grid() {
}

// deconstructor
Grid::~Grid() {
}

// initialization
int Grid::reinit() {
  for (int id=0; id<365; id++) {
    //the following are the original algorithm, and
    //  modified as below by Yi (2013 Feb):
    //  double ampl;
    //  ampl = exp(7.42 +0.045 *gd.lat)/3600.;
    //  gd.alldaylengths[id] = ampl * (sin ((id -79) *0.01721)) +12.0;
    double daylength = 0.0;
    //http://www.jgiesen.de/astro/solarday.htm
    //http://www.gandraxa.com/length_of_day.xml
    //make sure all arguments in sin, cos and tan are
    //  in unit of arc (not degree)
    double pi =3.14159;
    double m = 1- tan(gd.lat*pi/180.0)* tan(23.45*cos(id*pi/182.625)*pi/180.0);
    m = fmax(m, 0.);
    m = fmin(m, 2.);
    double b = acos(1-m)/pi;
    daylength = b*24;
    gd.alldaylengths[id] = daylength;
  }

  //check for the validity of grid level data
  if(gd.fri<0|| gd.fri>2000) {
    gd.fri =2000;
  }

  //testing
  //gd.fri = 60;
  //gd.pfseason[1] = 0.80;
  //gd.pfsize[1] = 0.80;

  if(gd.topsoil <0 || gd.botsoil <0) {
    return -2;
  }

  return 0;
}

//'ed' for the whole grid
void Grid::setEnvData(EnvData* edp) {
  grded = edp;
}

//'bd' for the whole grid
void Grid::setBgcData(BgcData* bdp) {
  grdbd = bdp;
}

//inputs
void Grid::setRegionData(RegionData* rdp) {
  rd = rdp;
}

<commit_msg>Update comment in Grid.cpp<commit_after>/*! \file
 */

#include "Grid.h"

Grid::Grid() {
}

// deconstructor
Grid::~Grid() {
}

// initialization
int Grid::reinit() {
  for (int id=0; id<365; id++) {
    //the following are the original algorithm, and
    //  modified as below by Yi (2013 Feb):
    //  double ampl;
    //  ampl = exp(7.42 +0.045 *gd.lat)/3600.;
    //  gd.alldaylengths[id] = ampl * (sin ((id -79) *0.01721)) +12.0;
    double daylength = 0.0;
    //http://www.jgiesen.de/astro/solarday.htm
    //http://www.gandraxa.com/length_of_day.xml
    //make sure all arguments in sin, cos and tan are
    //  in unit of arc (not degree)
    double pi =3.14159;
    double m = 1- tan(gd.lat*pi/180.0)* tan(23.45*cos(id*pi/182.625)*pi/180.0);
    m = fmax(m, 0.);
    m = fmin(m, 2.);
    double b = acos(1-m)/pi;
    daylength = b*24;
    gd.alldaylengths[id] = daylength;
  }

  //check for the validity of grid level data
  if(gd.fri<0|| gd.fri>2000) {
    gd.fri =2000;
  }

  // 06-05-14
  // If grid fire related parameters are not
  // set here, then they are read and set from your
  // input netCDF files (grid.nc and firestatistics.nc?)
  //gd.fri = 60;
  //gd.pfseason[1] = 0.80;
  //gd.pfsize[1] = 0.80;

  if(gd.topsoil <0 || gd.botsoil <0) {
    return -2;
  }

  return 0;
}

//'ed' for the whole grid
void Grid::setEnvData(EnvData* edp) {
  grded = edp;
}

//'bd' for the whole grid
void Grid::setBgcData(BgcData* bdp) {
  grdbd = bdp;
}

//inputs
void Grid::setRegionData(RegionData* rdp) {
  rd = rdp;
}

<|endoftext|>


<commit_before>#include "Test.h"

#include <string>

using namespace std;
using namespace std::literals;

extern "C" size_t test_strspn(const char *, const char *);

class StrspnTest : public evil::Test {};

TEST_F(StrspnTest, null_s1) {
    evil::UBChecker checker{1};
    ASSERT_EQ(0, test_strspn(NULL, ""));
}

TEST_F(StrspnTest, null_s2) {
    evil::UBChecker checker{1};
    ASSERT_EQ(0, test_strspn("", NULL));
}

TEST_F(StrspnTest, empty_s1) {
    ASSERT_EQ(0, test_strspn("", "a"));
}

TEST_F(StrspnTest, empty_s2) {
    ASSERT_EQ(0, test_strspn("a", ""));
}

TEST_F(StrspnTest, single_char_in_s2) {
    ASSERT_EQ(2, test_strspn("aaba", "a"));
    ASSERT_EQ(0, test_strspn("aaba", "c"));
}

TEST_F(StrspnTest, multiple_chars_in_s2) {
    ASSERT_EQ(5, test_strspn("aababc", "ab"));
}
<commit_msg>Fix warning in strspn test<commit_after>#include "Test.h"

#include <string>

using namespace std;
using namespace std::literals;

extern "C" size_t test_strspn(const char *, const char *);

class StrspnTest : public evil::Test {};

TEST_F(StrspnTest, null_s1) {
    evil::UBChecker checker{1};
    ASSERT_EQ(0u, test_strspn(NULL, ""));
}

TEST_F(StrspnTest, null_s2) {
    evil::UBChecker checker{1};
    ASSERT_EQ(0u, test_strspn("", NULL));
}

TEST_F(StrspnTest, empty_s1) {
    ASSERT_EQ(0u, test_strspn("", "a"));
}

TEST_F(StrspnTest, empty_s2) {
    ASSERT_EQ(0u, test_strspn("a", ""));
}

TEST_F(StrspnTest, single_char_in_s2) {
    ASSERT_EQ(2u, test_strspn("aaba", "a"));
    ASSERT_EQ(0u, test_strspn("aaba", "c"));
}

TEST_F(StrspnTest, multiple_chars_in_s2) {
    ASSERT_EQ(5u, test_strspn("aababc", "ab"));
}
<|endoftext|>


<commit_before>/*  This file is part of the Vc library.

    Copyright (C) 2010 Matthias Kretz <kretz@kde.org>

    Vc is free software: you can redistribute it and/or modify
    it under the terms of the GNU Lesser General Public License as
    published by the Free Software Foundation, either version 3 of
    the License, or (at your option) any later version.

    Vc is distributed in the hope that it will be useful, but
    WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU Lesser General Public License for more details.

    You should have received a copy of the GNU Lesser General Public
    License along with Vc.  If not, see <http://www.gnu.org/licenses/>.

*/

#include <Vc/Vc>
#include "unittest.h"
#include <iostream>
#include <limits>

using namespace Vc;

/*
 *   V \  M | float | double | ushort | short | uint | int
 * ---------+----------------------------------------------
 *  float_v |   X   |        |    X   |   X   |      |
 * sfloat_v |   X   |        |    X   |   X   |      |
 * double_v |       |    X   |        |       |      |
 *    int_v |       |        |        |   X   |      |  X
 *   uint_v |       |        |    X   |       |   X  |
 *  short_v |       |        |        |   X   |      |
 * ushort_v |       |        |    X   |       |      |
 */
template<typename A, typename B> struct TPair { typedef A V; typedef B M; };

typedef TPair<float_v, float> float_float;
typedef TPair<float_v, unsigned short> float_ushort;
typedef TPair<float_v, short> float_short;

typedef TPair<sfloat_v, float> sfloat_float;
typedef TPair<sfloat_v, unsigned short> sfloat_ushort;
typedef TPair<sfloat_v, short> sfloat_short;

typedef TPair<double_v, double> double_double;
typedef TPair<short_v, short> short_short;
typedef TPair<ushort_v, unsigned short> ushort_ushort;

typedef TPair<int_v, int> int_int;
typedef TPair<int_v, short> int_short;

typedef TPair<uint_v, unsigned int> uint_uint;
typedef TPair<uint_v, unsigned short> uint_ushort;

template<typename Pair> void testDeinterlace()
{
    typedef typename Pair::V V;
    typedef typename Pair::M M;
    typedef typename V::IndexType I;

    const bool isSigned = std::numeric_limits<M>::is_signed;

    const typename V::EntryType offset = isSigned ? -512 : 0;
    const V _0246 = static_cast<V>(I::IndexesFromZero()) * 2 + offset;

    M memory[1024];
    for (int i = 0; i < 1024; ++i) {
        memory[i] = i;
        if (isSigned) {
            memory[i] -= 512;
        }
    }

    V a, b;

    for (int i = 0; i < 1024 - 2 * V::Size; ++i) {
        if (reinterpret_cast<ptrdiff_t>(&memory[i]) & (VectorAlignment - 1)) {
            Vc::deinterleave(&a, &b, &memory[i], Unaligned);
        } else {
            Vc::deinterleave(&a, &b, &memory[i]);
        }
        COMPARE(_0246 + i,     a);
        COMPARE(_0246 + i + 1, b);
    }
}

int main()
{
    runTest(testDeinterlace<float_float>);
    runTest(testDeinterlace<float_ushort>);
    runTest(testDeinterlace<float_short>);
    runTest(testDeinterlace<sfloat_float>);
    runTest(testDeinterlace<sfloat_ushort>);
    runTest(testDeinterlace<sfloat_short>);
    runTest(testDeinterlace<double_double>);
    runTest(testDeinterlace<int_int>);
    runTest(testDeinterlace<int_short>);
    runTest(testDeinterlace<uint_uint>);
    runTest(testDeinterlace<uint_ushort>);
    runTest(testDeinterlace<short_short>);
    runTest(testDeinterlace<ushort_ushort>);
}
<commit_msg>use the correct type for pointer casts<commit_after>/*  This file is part of the Vc library.

    Copyright (C) 2010 Matthias Kretz <kretz@kde.org>

    Vc is free software: you can redistribute it and/or modify
    it under the terms of the GNU Lesser General Public License as
    published by the Free Software Foundation, either version 3 of
    the License, or (at your option) any later version.

    Vc is distributed in the hope that it will be useful, but
    WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU Lesser General Public License for more details.

    You should have received a copy of the GNU Lesser General Public
    License along with Vc.  If not, see <http://www.gnu.org/licenses/>.

*/

#include <Vc/Vc>
#include "unittest.h"
#include <iostream>
#include <limits>

using namespace Vc;

/*
 *   V \  M | float | double | ushort | short | uint | int
 * ---------+----------------------------------------------
 *  float_v |   X   |        |    X   |   X   |      |
 * sfloat_v |   X   |        |    X   |   X   |      |
 * double_v |       |    X   |        |       |      |
 *    int_v |       |        |        |   X   |      |  X
 *   uint_v |       |        |    X   |       |   X  |
 *  short_v |       |        |        |   X   |      |
 * ushort_v |       |        |    X   |       |      |
 */
template<typename A, typename B> struct TPair { typedef A V; typedef B M; };

typedef TPair<float_v, float> float_float;
typedef TPair<float_v, unsigned short> float_ushort;
typedef TPair<float_v, short> float_short;

typedef TPair<sfloat_v, float> sfloat_float;
typedef TPair<sfloat_v, unsigned short> sfloat_ushort;
typedef TPair<sfloat_v, short> sfloat_short;

typedef TPair<double_v, double> double_double;
typedef TPair<short_v, short> short_short;
typedef TPair<ushort_v, unsigned short> ushort_ushort;

typedef TPair<int_v, int> int_int;
typedef TPair<int_v, short> int_short;

typedef TPair<uint_v, unsigned int> uint_uint;
typedef TPair<uint_v, unsigned short> uint_ushort;

template<typename Pair> void testDeinterlace()
{
    typedef typename Pair::V V;
    typedef typename Pair::M M;
    typedef typename V::IndexType I;

    const bool isSigned = std::numeric_limits<M>::is_signed;

    const typename V::EntryType offset = isSigned ? -512 : 0;
    const V _0246 = static_cast<V>(I::IndexesFromZero()) * 2 + offset;

    M memory[1024];
    for (int i = 0; i < 1024; ++i) {
        memory[i] = i;
        if (isSigned) {
            memory[i] -= 512;
        }
    }

    V a, b;

    for (int i = 0; i < 1024 - 2 * V::Size; ++i) {
        if (reinterpret_cast<uintptr_t>(&memory[i]) & (VectorAlignment - 1)) {
            Vc::deinterleave(&a, &b, &memory[i], Unaligned);
        } else {
            Vc::deinterleave(&a, &b, &memory[i]);
        }
        COMPARE(_0246 + i,     a);
        COMPARE(_0246 + i + 1, b);
    }
}

int main()
{
    runTest(testDeinterlace<float_float>);
    runTest(testDeinterlace<float_ushort>);
    runTest(testDeinterlace<float_short>);
    runTest(testDeinterlace<sfloat_float>);
    runTest(testDeinterlace<sfloat_ushort>);
    runTest(testDeinterlace<sfloat_short>);
    runTest(testDeinterlace<double_double>);
    runTest(testDeinterlace<int_int>);
    runTest(testDeinterlace<int_short>);
    runTest(testDeinterlace<uint_uint>);
    runTest(testDeinterlace<uint_ushort>);
    runTest(testDeinterlace<short_short>);
    runTest(testDeinterlace<ushort_ushort>);
}
<|endoftext|>


<commit_before>
#include "Vjoin_fadd.h"
#include "verilated.h"
#include "verilated_vcd_c.h"

#include <list>

#include <time.h>

#define DEBUG_TRACE 1

vluint64_t global_time = 0;
VerilatedVcdC* tfp = 0;

void advance_half_clock(Vjoin_fadd *top) {
#ifdef TRACE
  tfp->dump(global_time);
#endif

  top->eval();
  top->clk = !top->clk;
  top->eval();

  global_time++;
  if (Verilated::gotFinish())
    exit(0);
}

void advance_clock(Vjoin_fadd *top, int nclocks=1) {

  for( int i=0;i<nclocks;i++) {
    for (int clk=0; clk<2; clk++) {
      advance_half_clock(top);
    }
  }
}

void sim_finish(bool pass) {
#ifdef TRACE
  tfp->close();
#endif

#if 0
  if (pass)
    printf("\nTB:PASS\n");
  else
    printf("\nTB:FAILED\n");
#endif

  exit(0);
}

struct InputPacketA {
  int inp_a;
};

struct InputPacketB {
  int inp_b;
};

struct OutputPacket {
  int nset ;
  int sum;
};

double sc_time_stamp() {
  return 0;
}

std::list<InputPacketA>  inpa_list;
std::list<InputPacketB>  inpb_list;
std::list<OutputPacket> out_list;

void try_send_packet(Vjoin_fadd *top) {
  top->sumRetry = (rand()&0xF)==0; // randomly, one every 8 packets

  if (!top->inp_aRetry) {
    top->inp_a = rand();
    if (inpa_list.empty() || (rand() & 0x3)) { // Once every 4
      top->inp_aValid = 0;
    }else{
      top->inp_aValid = 1;
    }
  }

  if (!top->inp_bRetry) {
    top->inp_b = rand();

    if (inpb_list.empty() || (rand() & 0x7)) { // Once every 8 cycles
      top->inp_bValid = 0;
    }else{
      top->inp_bValid = 1;
    }
  }

  if (top->inp_aValid && !top->inp_aRetry) {
    if (inpa_list.empty()) {
      fprintf(stderr,"ERROR: Internal error, could not be empty inpa\n");
    }
    InputPacketA inp = inpa_list.back();
    top->inp_a = inp.inp_a;
#ifdef DEBUG_TRACE
    printf("@%lld inp_a=%d\n",global_time, inp.inp_a);
#endif
    inpa_list.pop_back();
  }

  if (top->inp_bValid && !top->inp_bRetry) {
    if (inpb_list.empty()) {
      fprintf(stderr,"ERROR: Internal error, could not be empty inpb\n");
    }
    InputPacketB inp = inpb_list.back();
    top->inp_b = inp.inp_b;
#ifdef DEBUG_TRACE
    printf("@%lld inp_b=%d\n",global_time, inp.inp_b);
#endif
    inpb_list.pop_back();
  }

}

void error_found(Vjoin_fadd *top) {
  advance_half_clock(top);
  advance_half_clock(top);
  sim_finish(false);
}

void try_recv_packet(Vjoin_fadd *top) {

  if (top->sumValid && out_list.empty()) {
    printf("ERROR: unexpected result %d\n",top->sum);
    error_found(top);
    return;
  }

  if (top->sumRetry)
    return;

  if (!top->sumValid)
    return;

  if (out_list.empty())
    return;

#ifdef DEBUG_TRACE
    printf("@%lld sum=%d\n",global_time, top->sum);
#endif
  OutputPacket o = out_list.back();
  if (top->sum != o.sum) {
    printf("ERROR: expected %d but sum is %d\n",o.sum,top->sum);
    error_found(top);
  }

  out_list.pop_back();
}

int main(int argc, char **argv, char **env) {
  int i;
  int clk;
  Verilated::commandArgs(argc, argv);
  // init top verilog instance
  Vjoin_fadd* top = new Vjoin_fadd;

  int t = (int)time(0);
  srand(t);
  printf("My RAND Seed is %d\n",t);

#ifdef TRACE
  // init trace dump
  Verilated::traceEverOn(true);
  tfp = new VerilatedVcdC;

  top->trace(tfp, 99);
  tfp->open("output.vcd");
#endif

  // initialize simulation inputs
  top->clk = 1;
  top->reset = 1;

  advance_clock(top,4); // May be larger as required by reset state machines
  //-------------------------------------------------------
  top->reset = 0;
  top->inp_a = 1;
  top->inp_b = 2;
  top->inp_aValid = 0;
  top->inp_bValid = 0;
  top->sumRetry = 1;

  advance_clock(top,1);

#if 1
  for(int i =0;i<1024;i++) {
    try_send_packet(top);
    advance_half_clock(top);
    try_recv_packet(top);
    advance_half_clock(top);

    if (((rand() & 0x3)==0) && inpa_list.size() < 3 && inpb_list.size() < 3 ) {
      InputPacketA ia;
      InputPacketB ib;
      ia.inp_a = rand() & 0xFF;
      ib.inp_b = rand() & 0xFF;
      inpa_list.push_front(ia);
      inpb_list.push_front(ib);

      OutputPacket o;
      o.sum = (ia.inp_a + ib.inp_b) & 0xFF;

      out_list.push_front(o);
    }
    //advance_clock(top,1);
  }
#endif

  sim_finish(true);
}

<commit_msg>fix TB:FAIL notification<commit_after>
#include "Vjoin_fadd.h"
#include "verilated.h"
#include "verilated_vcd_c.h"

#include <list>

#include <time.h>

#define DEBUG_TRACE 1

vluint64_t global_time = 0;
VerilatedVcdC* tfp = 0;

void advance_half_clock(Vjoin_fadd *top) {
#ifdef TRACE
  tfp->dump(global_time);
#endif

  top->eval();
  top->clk = !top->clk;
  top->eval();

  global_time++;
  if (Verilated::gotFinish())
    exit(0);
}

void advance_clock(Vjoin_fadd *top, int nclocks=1) {

  for( int i=0;i<nclocks;i++) {
    for (int clk=0; clk<2; clk++) {
      advance_half_clock(top);
    }
  }
}

void sim_finish(bool pass) {
#ifdef TRACE
  tfp->close();
#endif

#if 1
  if (pass)
    printf("\nTB:PASS\n");
  else
    printf("\nTB:FAILED\n");
#endif

  exit(0);
}

struct InputPacketA {
  int inp_a;
};

struct InputPacketB {
  int inp_b;
};

struct OutputPacket {
  int nset ;
  int sum;
};

double sc_time_stamp() {
  return 0;
}

std::list<InputPacketA>  inpa_list;
std::list<InputPacketB>  inpb_list;
std::list<OutputPacket> out_list;

void try_send_packet(Vjoin_fadd *top) {
  top->sumRetry = (rand()&0xF)==0; // randomly, one every 8 packets

  if (!top->inp_aRetry) {
    top->inp_a = rand();
    if (inpa_list.empty() || (rand() & 0x3)) { // Once every 4
      top->inp_aValid = 0;
    }else{
      top->inp_aValid = 1;
    }
  }

  if (!top->inp_bRetry) {
    top->inp_b = rand();

    if (inpb_list.empty() || (rand() & 0x7)) { // Once every 8 cycles
      top->inp_bValid = 0;
    }else{
      top->inp_bValid = 1;
    }
  }

  if (top->inp_aValid && !top->inp_aRetry) {
    if (inpa_list.empty()) {
      fprintf(stderr,"ERROR: Internal error, could not be empty inpa\n");
    }
    InputPacketA inp = inpa_list.back();
    top->inp_a = inp.inp_a;
#ifdef DEBUG_TRACE
    printf("@%lld inp_a=%d\n",global_time, inp.inp_a);
#endif
    inpa_list.pop_back();
  }

  if (top->inp_bValid && !top->inp_bRetry) {
    if (inpb_list.empty()) {
      fprintf(stderr,"ERROR: Internal error, could not be empty inpb\n");
    }
    InputPacketB inp = inpb_list.back();
    top->inp_b = inp.inp_b;
#ifdef DEBUG_TRACE
    printf("@%lld inp_b=%d\n",global_time, inp.inp_b);
#endif
    inpb_list.pop_back();
  }

}

void error_found(Vjoin_fadd *top) {
  advance_half_clock(top);
  advance_half_clock(top);
  sim_finish(false);
}

void try_recv_packet(Vjoin_fadd *top) {

  if (top->sumValid && out_list.empty()) {
    printf("ERROR: unexpected result %d\n",top->sum);
    error_found(top);
    return;
  }

  if (top->sumRetry)
    return;

  if (!top->sumValid)
    return;

  if (out_list.empty())
    return;

#ifdef DEBUG_TRACE
    printf("@%lld sum=%d\n",global_time, top->sum);
#endif
  OutputPacket o = out_list.back();
  if (top->sum != o.sum) {
    printf("ERROR: expected %d but sum is %d\n",o.sum,top->sum);
    error_found(top);
  }

  out_list.pop_back();
}

int main(int argc, char **argv, char **env) {
  int i;
  int clk;
  Verilated::commandArgs(argc, argv);
  // init top verilog instance
  Vjoin_fadd* top = new Vjoin_fadd;

  int t = (int)time(0);
  srand(t);
  printf("My RAND Seed is %d\n",t);

#ifdef TRACE
  // init trace dump
  Verilated::traceEverOn(true);
  tfp = new VerilatedVcdC;

  top->trace(tfp, 99);
  tfp->open("output.vcd");
#endif

  // initialize simulation inputs
  top->clk = 1;
  top->reset = 1;

  advance_clock(top,4); // May be larger as required by reset state machines
  //-------------------------------------------------------
  top->reset = 0;
  top->inp_a = 1;
  top->inp_b = 2;
  top->inp_aValid = 0;
  top->inp_bValid = 0;
  top->sumRetry = 1;

  advance_clock(top,1);

#if 1
  for(int i =0;i<1024;i++) {
    try_send_packet(top);
    advance_half_clock(top);
    try_recv_packet(top);
    advance_half_clock(top);

    if (((rand() & 0x3)==0) && inpa_list.size() < 3 && inpb_list.size() < 3 ) {
      InputPacketA ia;
      InputPacketB ib;
      ia.inp_a = rand() & 0xFF;
      ib.inp_b = rand() & 0xFF;
      inpa_list.push_front(ia);
      inpb_list.push_front(ib);

      OutputPacket o;
      o.sum = (ia.inp_a + ib.inp_b) & 0xFF;

      out_list.push_front(o);
    }
    //advance_clock(top,1);
  }
#endif

  sim_finish(true);
}

<|endoftext|>


<commit_before>#include "Boost_Float.hxx"
#include "Positive_Matrix_With_Prefactor.hxx"
#include "../Timers.hxx"

#include <boost/program_options.hpp>
#include <boost/filesystem.hpp>

namespace po = boost::program_options;

void read_input(const boost::filesystem::path &input_file,
                std::vector<El::BigFloat> &objectives,
                std::vector<El::BigFloat> &normalization,
                std::vector<Positive_Matrix_With_Prefactor> &matrices);

void write_output(const boost::filesystem::path &output_dir,
                  const std::vector<El::BigFloat> &objectives,
                  const std::vector<El::BigFloat> &normalization,
                  const std::vector<Positive_Matrix_With_Prefactor> &matrices,
                  Timers &timers);

int main(int argc, char **argv)
{
  El::Environment env(argc, argv);

  try
    {
      int precision;
      boost::filesystem::path input_file, output_dir;
      bool debug(false);

      po::options_description options("Basic options");
      options.add_options()("help,h", "Show this helpful message.");
      options.add_options()(
        "input,i", po::value<boost::filesystem::path>(&input_file)->required(),
        "Mathematica or XML file with SDP definition");
      options.add_options()(
        "output,o",
        po::value<boost::filesystem::path>(&output_dir)->required(),
        "Directory to place output");
      options.add_options()(
        "precision", po::value<int>(&precision)->required(),
        "The precision, in the number of bits, for numbers in the "
        "computation. ");
      options.add_options()("debug",
                            po::value<bool>(&debug)->default_value(false),
                            "Write out debugging output.");

      po::positional_options_description positional;
      positional.add("precision", 1);
      positional.add("input", 1);
      positional.add("output", 1);

      po::variables_map variables_map;
      po::store(po::parse_command_line(argc, argv, options), variables_map);

      if(variables_map.count("help") != 0)
        {
          std::cout << options << '\n';
          return 0;
        }

      po::notify(variables_map);

      if(!boost::filesystem::exists(input_file))
        {
          throw std::runtime_error("Input file '" + input_file.string()
                                   + "' does not exist");
        }
      if(boost::filesystem::is_directory(input_file))
        {
          throw std::runtime_error("Input file '" + input_file.string()
                                   + "' is a directory, not a file");
        }

      if(boost::filesystem::exists(output_dir)
         && !boost::filesystem::is_directory(output_dir))
        {
          throw std::runtime_error("Output directory '" + output_dir.string()
                                   + "' exists and is not a directory");
        }

      El::gmp::SetPrecision(precision);
      // El::gmp wants base-2 bits, but boost::multiprecision want
      // base-10 digits.
      Boost_Float::default_precision(precision*log(2)/log(10));

      std::vector<El::BigFloat> objectives, normalization;
      std::vector<Positive_Matrix_With_Prefactor> matrices;
      Timers timers(debug);
      auto &read_input_timer(timers.add_and_start("read_input"));
      read_input(input_file, objectives, normalization, matrices);
      read_input_timer.stop();
      auto &write_output_timer(timers.add_and_start("write_output"));
      write_output(output_dir, objectives, normalization, matrices, timers);
      write_output_timer.stop();
      if(debug)
        {
          timers.write_profile(output_dir.string() + "/profiling."
                               + std::to_string(El::mpi::Rank()));
        }
    }
  catch(std::exception &e)
    {
      std::cerr << "Error: " << e.what() << "\n" << std::flush;
      El::mpi::Abort(El::mpi::COMM_WORLD, 1);
    }
  catch(...)
    {
      std::cerr << "Unknown Error\n" << std::flush;
      El::mpi::Abort(El::mpi::COMM_WORLD, 1);
    }
}
<commit_msg>clang-format<commit_after>#include "Boost_Float.hxx"
#include "Positive_Matrix_With_Prefactor.hxx"
#include "../Timers.hxx"

#include <boost/program_options.hpp>
#include <boost/filesystem.hpp>

namespace po = boost::program_options;

void read_input(const boost::filesystem::path &input_file,
                std::vector<El::BigFloat> &objectives,
                std::vector<El::BigFloat> &normalization,
                std::vector<Positive_Matrix_With_Prefactor> &matrices);

void write_output(const boost::filesystem::path &output_dir,
                  const std::vector<El::BigFloat> &objectives,
                  const std::vector<El::BigFloat> &normalization,
                  const std::vector<Positive_Matrix_With_Prefactor> &matrices,
                  Timers &timers);

int main(int argc, char **argv)
{
  El::Environment env(argc, argv);

  try
    {
      int precision;
      boost::filesystem::path input_file, output_dir;
      bool debug(false);

      po::options_description options("Basic options");
      options.add_options()("help,h", "Show this helpful message.");
      options.add_options()(
        "input,i", po::value<boost::filesystem::path>(&input_file)->required(),
        "Mathematica or XML file with SDP definition");
      options.add_options()(
        "output,o",
        po::value<boost::filesystem::path>(&output_dir)->required(),
        "Directory to place output");
      options.add_options()(
        "precision", po::value<int>(&precision)->required(),
        "The precision, in the number of bits, for numbers in the "
        "computation. ");
      options.add_options()("debug",
                            po::value<bool>(&debug)->default_value(false),
                            "Write out debugging output.");

      po::positional_options_description positional;
      positional.add("precision", 1);
      positional.add("input", 1);
      positional.add("output", 1);

      po::variables_map variables_map;
      po::store(po::parse_command_line(argc, argv, options), variables_map);

      if(variables_map.count("help") != 0)
        {
          std::cout << options << '\n';
          return 0;
        }

      po::notify(variables_map);

      if(!boost::filesystem::exists(input_file))
        {
          throw std::runtime_error("Input file '" + input_file.string()
                                   + "' does not exist");
        }
      if(boost::filesystem::is_directory(input_file))
        {
          throw std::runtime_error("Input file '" + input_file.string()
                                   + "' is a directory, not a file");
        }

      if(boost::filesystem::exists(output_dir)
         && !boost::filesystem::is_directory(output_dir))
        {
          throw std::runtime_error("Output directory '" + output_dir.string()
                                   + "' exists and is not a directory");
        }

      El::gmp::SetPrecision(precision);
      // El::gmp wants base-2 bits, but boost::multiprecision want
      // base-10 digits.
      Boost_Float::default_precision(precision * log(2) / log(10));

      std::vector<El::BigFloat> objectives, normalization;
      std::vector<Positive_Matrix_With_Prefactor> matrices;
      Timers timers(debug);
      auto &read_input_timer(timers.add_and_start("read_input"));
      read_input(input_file, objectives, normalization, matrices);
      read_input_timer.stop();
      auto &write_output_timer(timers.add_and_start("write_output"));
      write_output(output_dir, objectives, normalization, matrices, timers);
      write_output_timer.stop();
      if(debug)
        {
          timers.write_profile(output_dir.string() + "/profiling."
                               + std::to_string(El::mpi::Rank()));
        }
    }
  catch(std::exception &e)
    {
      std::cerr << "Error: " << e.what() << "\n" << std::flush;
      El::mpi::Abort(El::mpi::COMM_WORLD, 1);
    }
  catch(...)
    {
      std::cerr << "Unknown Error\n" << std::flush;
      El::mpi::Abort(El::mpi::COMM_WORLD, 1);
    }
}
<|endoftext|>


<commit_before>
#include "serialport.h"
#include <list>
#include "win/disphelper.h"

#include "win/stdafx.h"
#include "win/enumser.h"

#ifdef WIN32

#define MAX_BUFFER_SIZE 1000

std::list<int> g_closingHandles;
int bufferSize;
void ErrorCodeToString(const char* prefix, int errorCode, char *errorStr) {
  switch(errorCode) {
  case ERROR_FILE_NOT_FOUND:
    sprintf(errorStr, "%s: File not found", prefix);
    break;
  case ERROR_INVALID_HANDLE:
    sprintf(errorStr, "%s: Invalid handle", prefix);
    break;
  case ERROR_ACCESS_DENIED:
    sprintf(errorStr, "%s: Access denied", prefix);
    break;
  case ERROR_OPERATION_ABORTED:
    sprintf(errorStr, "%s: operation aborted", prefix);
    break;
  default:
    sprintf(errorStr, "%s: Unknown error code %d", prefix, errorCode);
    break;
  }
}

void EIO_Open(uv_work_t* req) {
  OpenBaton* data = static_cast<OpenBaton*>(req->data);

  HANDLE file = CreateFile(
    data->path,
    GENERIC_READ | GENERIC_WRITE,
    0,
    NULL,
    OPEN_EXISTING,
    FILE_FLAG_OVERLAPPED,
    NULL);
  if (file == INVALID_HANDLE_VALUE) {
    DWORD errorCode = GetLastError();
    char temp[100];
    sprintf(temp, "Opening %s", data->path);
    ErrorCodeToString(temp, errorCode, data->errorString);
    return;
  }

  bufferSize = data->bufferSize;
  if(bufferSize > MAX_BUFFER_SIZE) {
    bufferSize = MAX_BUFFER_SIZE;
  }

  DCB dcb = { 0 };
  dcb.DCBlength = sizeof(DCB);
  if(!BuildCommDCB("9600,n,8,1", &dcb)) {
    ErrorCodeToString("BuildCommDCB", GetLastError(), data->errorString);
    return;
  }

  dcb.fBinary = true;
  dcb.BaudRate = data->baudRate;
  dcb.ByteSize = data->dataBits;
  switch(data->parity) {
  case SERIALPORT_PARITY_NONE:
    dcb.Parity = NOPARITY;
    break;
  case SERIALPORT_PARITY_MARK:
    dcb.Parity = MARKPARITY;
    break;
  case SERIALPORT_PARITY_EVEN:
    dcb.Parity = EVENPARITY;
    break;
  case SERIALPORT_PARITY_ODD:
    dcb.Parity = ODDPARITY;
    break;
  case SERIALPORT_PARITY_SPACE:
    dcb.Parity = SPACEPARITY;
    break;
  }
  switch(data->stopBits) {
  case SERIALPORT_STOPBITS_ONE:
    dcb.StopBits = ONESTOPBIT;
    break;
  case SERIALPORT_STOPBITS_ONE_FIVE:
    dcb.StopBits = ONE5STOPBITS;
    break;
  case SERIALPORT_STOPBITS_TWO:
    dcb.StopBits = TWOSTOPBITS;
    break;
  }

  if(!SetCommState(file, &dcb)) {
    ErrorCodeToString("SetCommState", GetLastError(), data->errorString);
    return;
  }

  // Set the com port read/write timeouts
  DWORD serialBitsPerByte = 8/*std data bits*/ + 1/*start bit*/;
  serialBitsPerByte += (data->parity   == SERIALPORT_PARITY_NONE ) ? 0 : 1;
  serialBitsPerByte += (data->stopBits == SERIALPORT_STOPBITS_ONE) ? 1 : 2;
  DWORD msPerByte = (data->baudRate > 0) ?
                    ((1000 * serialBitsPerByte + data->baudRate - 1) / data->baudRate) :
                    1;
  if (msPerByte < 1) {
    msPerByte = 1;
  }
  COMMTIMEOUTS commTimeouts = {0};
  commTimeouts.ReadIntervalTimeout = msPerByte; // Minimize chance of concatenating of separate serial port packets on read
  commTimeouts.ReadTotalTimeoutMultiplier  = 0; // Do not allow big read timeout when big read buffer used
  commTimeouts.ReadTotalTimeoutConstant    = 1000; // Total read timeout (period of read loop)
  commTimeouts.WriteTotalTimeoutConstant   = 1000; // Const part of write timeout
  commTimeouts.WriteTotalTimeoutMultiplier = msPerByte; // Variable part of write timeout (per byte)
  if(!SetCommTimeouts(file, &commTimeouts)) {
    ErrorCodeToString("SetCommTimeouts", GetLastError(), data->errorString);
    return;
  }

  // Remove garbage data in RX/TX queues
  PurgeComm(file, PURGE_RXCLEAR);
  PurgeComm(file, PURGE_TXCLEAR);

  data->result = (int)file;
}

struct WatchPortBaton {
public:
  HANDLE fd;
  DWORD bytesRead;
  char buffer[MAX_BUFFER_SIZE];
  char errorString[1000];
  DWORD errorCode;
  bool disconnected;
  v8::Persistent<v8::Value> dataCallback;
  v8::Persistent<v8::Value> errorCallback;
  v8::Persistent<v8::Value> disconnectedCallback;
};

void EIO_WatchPort(uv_work_t* req) {
  WatchPortBaton* data = static_cast<WatchPortBaton*>(req->data);
  data->bytesRead = 0;
  data->disconnected = false;

  // Event used by GetOverlappedResult(..., TRUE) to wait for incoming data or timeout
  // Event MUST be used if program has several simultaneous asynchronous operations
  // on the same handle (i.e. ReadFile and WriteFile)
  HANDLE hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);

  while(true) {
    OVERLAPPED ov = {0};
    ov.hEvent = hEvent;

    // Start read operation - synchrounous or asynchronous
    DWORD bytesReadSync = 0;
    if(!ReadFile((HANDLE)data->fd, data->buffer, bufferSize, &bytesReadSync, &ov)) {
      data->errorCode = GetLastError();
      if(data->errorCode != ERROR_IO_PENDING) {
        // Read operation error
        if(data->errorCode == ERROR_OPERATION_ABORTED) {
          data->disconnected = true;
        }
        else {
          ErrorCodeToString("Reading from COM port (ReadFile)", data->errorCode, data->errorString);
        }
        break;
      }

      // Read operation is asynchronous and is pending
      // We MUST wait for operation completion before deallocation of OVERLAPPED struct
      // or read data buffer

      // Wait for async read operation completion or timeout
      DWORD bytesReadAsync = 0;
      if(!GetOverlappedResult((HANDLE)data->fd, &ov, &bytesReadAsync, TRUE)) {
        // Read operation error
        data->errorCode = GetLastError();
        if(data->errorCode == ERROR_OPERATION_ABORTED) {
          data->disconnected = true;
        }
        else {
          ErrorCodeToString("Reading from COM port (GetOverlappedResult)", data->errorCode, data->errorString);
        }
        break;
      }
      else {
        // Read operation completed asynchronously
        data->bytesRead = bytesReadAsync;
      }
    }
    else {
      // Read operation completed synchronously
      data->bytesRead = bytesReadSync;
    }

    // Return data received if any
    if(data->bytesRead > 0) {
      break;
    }
  }

  CloseHandle(hEvent);
}

bool IsClosingHandle(int fd) {
  for(std::list<int>::iterator it=g_closingHandles.begin(); it!=g_closingHandles.end(); it++) {
    if(fd == *it) {
      g_closingHandles.remove(fd);
      return true;
    }
  }
  return false;
}

void EIO_AfterWatchPort(uv_work_t* req) {
  WatchPortBaton* data = static_cast<WatchPortBaton*>(req->data);
  if(data->disconnected) {
    v8::Handle<v8::Value> argv[1];
    v8::Function::Cast(*data->disconnectedCallback)->Call(v8::Context::GetCurrent()->Global(), 0, argv);
    goto cleanup;
  }

  if(data->bytesRead > 0) {
    v8::Handle<v8::Value> argv[1];
    argv[0] = node::Buffer::New(data->buffer, data->bytesRead)->handle_;
    v8::Function::Cast(*data->dataCallback)->Call(v8::Context::GetCurrent()->Global(), 1, argv);
  } else if(data->errorCode > 0) {
    if(data->errorCode == ERROR_INVALID_HANDLE && IsClosingHandle((int)data->fd)) {
      goto cleanup;
    } else {
      v8::Handle<v8::Value> argv[1];
      argv[0] = v8::Exception::Error(v8::String::New(data->errorString));
      v8::Function::Cast(*data->errorCallback)->Call(v8::Context::GetCurrent()->Global(), 1, argv);
      Sleep(100); // prevent the errors from occurring too fast
    }
  }
  AfterOpenSuccess((int)data->fd, data->dataCallback, data->disconnectedCallback, data->errorCallback);

cleanup:
  data->dataCallback.Dispose();
  data->errorCallback.Dispose();
  delete data;
  delete req;
}

void AfterOpenSuccess(int fd, v8::Handle<v8::Value> dataCallback, v8::Handle<v8::Value> disconnectedCallback, v8::Handle<v8::Value> errorCallback) {
  WatchPortBaton* baton = new WatchPortBaton();
  memset(baton, 0, sizeof(WatchPortBaton));
  baton->fd = (HANDLE)fd;
  baton->dataCallback = v8::Persistent<v8::Value>::New(dataCallback);
  baton->errorCallback = v8::Persistent<v8::Value>::New(errorCallback);
  baton->disconnectedCallback = v8::Persistent<v8::Value>::New(disconnectedCallback);

  uv_work_t* req = new uv_work_t();
  req->data = baton;

  uv_queue_work(uv_default_loop(), req, EIO_WatchPort, EIO_AfterWatchPort);
}

void EIO_Write(uv_work_t* req) {
  QueuedWrite* queuedWrite = static_cast<QueuedWrite*>(req->data);
  WriteBaton* data = static_cast<WriteBaton*>(queuedWrite->baton);
  data->result = 0;

  OVERLAPPED ov = {0};
  // Event used by GetOverlappedResult(..., TRUE) to wait for outgoing data or timeout
  // Event MUST be used if program has several simultaneous asynchronous operations
  // on the same handle (i.e. ReadFile and WriteFile)
  ov.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);

  // Start write operation - synchrounous or asynchronous
  DWORD bytesWrittenSync = 0;
  if(!WriteFile((HANDLE)data->fd, data->bufferData, data->bufferLength, &bytesWrittenSync, &ov)) {
    DWORD lastError = GetLastError();
    if(lastError != ERROR_IO_PENDING) {
      // Write operation error
      ErrorCodeToString("Writing to COM port (WriteFile)", lastError, data->errorString);
    }
    else {
      // Write operation is asynchronous and is pending
      // We MUST wait for operation completion before deallocation of OVERLAPPED struct
      // or write data buffer

      // Wait for async write operation completion or timeout
      DWORD bytesWrittenAsync = 0;
      if(!GetOverlappedResult((HANDLE)data->fd, &ov, &bytesWrittenAsync, TRUE)) {
        // Write operation error
        DWORD lastError = GetLastError();
        ErrorCodeToString("Writing to COM port (GetOverlappedResult)", lastError, data->errorString);
      }
      else {
        // Write operation completed asynchronously
        data->result = bytesWrittenAsync;
      }
    }
  }
  else {
    // Write operation completed synchronously
    data->result = bytesWrittenSync;
  }

  CloseHandle(ov.hEvent);
}

void EIO_Close(uv_work_t* req) {
  CloseBaton* data = static_cast<CloseBaton*>(req->data);

  g_closingHandles.push_back(data->fd);
  if(!CloseHandle((HANDLE)data->fd)) {
    ErrorCodeToString("closing connection", GetLastError(), data->errorString);
    return;
  }
}

/*
 * listComPorts.c -- list COM ports
 *
 * http://github.com/todbot/usbSearch/
 *
 * 2012, Tod E. Kurt, http://todbot.com/blog/
 *
 *
 * Uses DispHealper : http://disphelper.sourceforge.net/
 *
 * Notable VIDs & PIDs combos:
 * VID 0403 - FTDI
 *
 * VID 0403 / PID 6001 - Arduino Diecimila
 *
 */
void EIO_List(uv_work_t* req) {
  ListBaton* data = static_cast<ListBaton*>(req->data);

  {
    DISPATCH_OBJ(wmiSvc);
    DISPATCH_OBJ(colDevices);

    dhInitialize(TRUE);
    dhToggleExceptions(TRUE);

    dhGetObject(L"winmgmts:{impersonationLevel=impersonate}!\\\\.\\root\\cimv2", NULL, &wmiSvc);
    dhGetValue(L"%o", &colDevices, wmiSvc, L".ExecQuery(%S)", L"Select * from Win32_PnPEntity");

    int port_count = 0;
    FOR_EACH(objDevice, colDevices, NULL) {
      char* name = NULL;
      char* pnpid = NULL;
      char* manu = NULL;
      char* match;

      dhGetValue(L"%s", &name,  objDevice, L".Name");
      dhGetValue(L"%s", &pnpid, objDevice, L".PnPDeviceID");

      if( (match = strstr( name, "(COM" )) != NULL ) { // look for "(COM23)"
        // 'Manufacturuer' can be null, so only get it if we need it
        dhGetValue(L"%s", &manu, objDevice,  L".Manufacturer");
        port_count++;
        char* comname = strtok( match, "()");
        ListResultItem* resultItem = new ListResultItem();
        resultItem->comName = comname;
        resultItem->manufacturer = manu;
        resultItem->pnpId = pnpid;
        data->results.push_back(resultItem);
        dhFreeString(manu);
      }

      dhFreeString(name);
      dhFreeString(pnpid);
    } NEXT(objDevice);

    SAFE_RELEASE(colDevices);
    SAFE_RELEASE(wmiSvc);

    dhUninitialize(TRUE);
  }

  std::vector<UINT> ports;
  if (CEnumerateSerial::UsingQueryDosDevice(ports))
  {
    for (size_t i = 0; i < ports.size(); i++)
    {
      char comname[64] = { 0 };
      sprintf(comname, "COM%u", ports[i]);
      bool bFound = false;
      for (std::list<ListResultItem*>::iterator ri = data->results.begin(); ri != data->results.end(); ri++)
      {
        if (stricmp((*ri)->comName.c_str(), comname) == 0)
        {
          bFound = true;
          break;
        }
      }
      if (!bFound)
      {
        ListResultItem* resultItem = new ListResultItem();
        resultItem->comName = comname;
        resultItem->manufacturer = "";
        resultItem->pnpId = "";
        data->results.push_back(resultItem);
      }
    }
  }
}

void EIO_Flush(uv_work_t* req) {
  FlushBaton* data = static_cast<FlushBaton*>(req->data);

  if(!FlushFileBuffers((HANDLE)data->fd)) {
    ErrorCodeToString("flushing connection", GetLastError(), data->errorString);
    return;
  }
}

#endif
<commit_msg>fixes Errors when unplug device on windows Issue #95<commit_after>
#include "serialport.h"
#include <list>
#include "win/disphelper.h"

#include "win/stdafx.h"
#include "win/enumser.h"

#ifdef WIN32

#define MAX_BUFFER_SIZE 1000

// Declare type of pointer to CancelIoEx function
typedef BOOL (WINAPI *CancelIoExType)(HANDLE hFile, LPOVERLAPPED lpOverlapped);

std::list<int> g_closingHandles;
int bufferSize;
void ErrorCodeToString(const char* prefix, int errorCode, char *errorStr) {
  switch(errorCode) {
  case ERROR_FILE_NOT_FOUND:
    sprintf(errorStr, "%s: File not found", prefix);
    break;
  case ERROR_INVALID_HANDLE:
    sprintf(errorStr, "%s: Invalid handle", prefix);
    break;
  case ERROR_ACCESS_DENIED:
    sprintf(errorStr, "%s: Access denied", prefix);
    break;
  case ERROR_OPERATION_ABORTED:
    sprintf(errorStr, "%s: operation aborted", prefix);
    break;
  default:
    sprintf(errorStr, "%s: Unknown error code %d", prefix, errorCode);
    break;
  }
}

void EIO_Open(uv_work_t* req) {
  OpenBaton* data = static_cast<OpenBaton*>(req->data);

  HANDLE file = CreateFile(
    data->path,
    GENERIC_READ | GENERIC_WRITE,
    0,
    NULL,
    OPEN_EXISTING,
    FILE_FLAG_OVERLAPPED,
    NULL);
  if (file == INVALID_HANDLE_VALUE) {
    DWORD errorCode = GetLastError();
    char temp[100];
    sprintf(temp, "Opening %s", data->path);
    ErrorCodeToString(temp, errorCode, data->errorString);
    return;
  }

  bufferSize = data->bufferSize;
  if(bufferSize > MAX_BUFFER_SIZE) {
    bufferSize = MAX_BUFFER_SIZE;
  }

  DCB dcb = { 0 };
  dcb.DCBlength = sizeof(DCB);
  if(!BuildCommDCB("9600,n,8,1", &dcb)) {
    ErrorCodeToString("BuildCommDCB", GetLastError(), data->errorString);
    return;
  }

  dcb.fBinary = true;
  dcb.BaudRate = data->baudRate;
  dcb.ByteSize = data->dataBits;
  switch(data->parity) {
  case SERIALPORT_PARITY_NONE:
    dcb.Parity = NOPARITY;
    break;
  case SERIALPORT_PARITY_MARK:
    dcb.Parity = MARKPARITY;
    break;
  case SERIALPORT_PARITY_EVEN:
    dcb.Parity = EVENPARITY;
    break;
  case SERIALPORT_PARITY_ODD:
    dcb.Parity = ODDPARITY;
    break;
  case SERIALPORT_PARITY_SPACE:
    dcb.Parity = SPACEPARITY;
    break;
  }
  switch(data->stopBits) {
  case SERIALPORT_STOPBITS_ONE:
    dcb.StopBits = ONESTOPBIT;
    break;
  case SERIALPORT_STOPBITS_ONE_FIVE:
    dcb.StopBits = ONE5STOPBITS;
    break;
  case SERIALPORT_STOPBITS_TWO:
    dcb.StopBits = TWOSTOPBITS;
    break;
  }

  if(!SetCommState(file, &dcb)) {
    ErrorCodeToString("SetCommState", GetLastError(), data->errorString);
    return;
  }

  // Set the com port read/write timeouts
  DWORD serialBitsPerByte = 8/*std data bits*/ + 1/*start bit*/;
  serialBitsPerByte += (data->parity   == SERIALPORT_PARITY_NONE ) ? 0 : 1;
  serialBitsPerByte += (data->stopBits == SERIALPORT_STOPBITS_ONE) ? 1 : 2;
  DWORD msPerByte = (data->baudRate > 0) ?
                    ((1000 * serialBitsPerByte + data->baudRate - 1) / data->baudRate) :
                    1;
  if (msPerByte < 1) {
    msPerByte = 1;
  }
  COMMTIMEOUTS commTimeouts = {0};
  commTimeouts.ReadIntervalTimeout = msPerByte; // Minimize chance of concatenating of separate serial port packets on read
  commTimeouts.ReadTotalTimeoutMultiplier  = 0; // Do not allow big read timeout when big read buffer used
  commTimeouts.ReadTotalTimeoutConstant    = 1000; // Total read timeout (period of read loop)
  commTimeouts.WriteTotalTimeoutConstant   = 1000; // Const part of write timeout
  commTimeouts.WriteTotalTimeoutMultiplier = msPerByte; // Variable part of write timeout (per byte)
  if(!SetCommTimeouts(file, &commTimeouts)) {
    ErrorCodeToString("SetCommTimeouts", GetLastError(), data->errorString);
    return;
  }

  // Remove garbage data in RX/TX queues
  PurgeComm(file, PURGE_RXCLEAR);
  PurgeComm(file, PURGE_TXCLEAR);

  data->result = (int)file;
}

struct WatchPortBaton {
public:
  HANDLE fd;
  DWORD bytesRead;
  char buffer[MAX_BUFFER_SIZE];
  char errorString[1000];
  DWORD errorCode;
  bool disconnected;
  v8::Persistent<v8::Value> dataCallback;
  v8::Persistent<v8::Value> errorCallback;
  v8::Persistent<v8::Value> disconnectedCallback;
};

void EIO_WatchPort(uv_work_t* req) {
  WatchPortBaton* data = static_cast<WatchPortBaton*>(req->data);
  data->bytesRead = 0;
  data->disconnected = false;

  // Event used by GetOverlappedResult(..., TRUE) to wait for incoming data or timeout
  // Event MUST be used if program has several simultaneous asynchronous operations
  // on the same handle (i.e. ReadFile and WriteFile)
  HANDLE hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);

  while(true) {
    OVERLAPPED ov = {0};
    ov.hEvent = hEvent;

    // Start read operation - synchrounous or asynchronous
    DWORD bytesReadSync = 0;
    if(!ReadFile((HANDLE)data->fd, data->buffer, bufferSize, &bytesReadSync, &ov)) {
      data->errorCode = GetLastError();
      if(data->errorCode != ERROR_IO_PENDING) {
        // Read operation error
        if(data->errorCode == ERROR_OPERATION_ABORTED) {
          data->disconnected = true;
        }
        else {
          ErrorCodeToString("Reading from COM port (ReadFile)", data->errorCode, data->errorString);
        }
        break;
      }

      // Read operation is asynchronous and is pending
      // We MUST wait for operation completion before deallocation of OVERLAPPED struct
      // or read data buffer

      // Wait for async read operation completion or timeout
      DWORD bytesReadAsync = 0;
      if(!GetOverlappedResult((HANDLE)data->fd, &ov, &bytesReadAsync, TRUE)) {
        // Read operation error
        data->errorCode = GetLastError();
        if(data->errorCode == ERROR_OPERATION_ABORTED) {
          data->disconnected = true;
        }
        else {
          ErrorCodeToString("Reading from COM port (GetOverlappedResult)", data->errorCode, data->errorString);
        }
        break;
      }
      else {
        // Read operation completed asynchronously
        data->bytesRead = bytesReadAsync;
      }
    }
    else {
      // Read operation completed synchronously
      data->bytesRead = bytesReadSync;
    }

    // Return data received if any
    if(data->bytesRead > 0) {
      break;
    }
  }

  CloseHandle(hEvent);
}

bool IsClosingHandle(int fd) {
  for(std::list<int>::iterator it=g_closingHandles.begin(); it!=g_closingHandles.end(); it++) {
    if(fd == *it) {
      g_closingHandles.remove(fd);
      return true;
    }
  }
  return false;
}

void EIO_AfterWatchPort(uv_work_t* req) {
  WatchPortBaton* data = static_cast<WatchPortBaton*>(req->data);
  if(data->disconnected) {
    v8::Handle<v8::Value> argv[1];
    v8::Function::Cast(*data->disconnectedCallback)->Call(v8::Context::GetCurrent()->Global(), 0, argv);
    goto cleanup;
  }

  if(data->bytesRead > 0) {
    v8::Handle<v8::Value> argv[1];
    argv[0] = node::Buffer::New(data->buffer, data->bytesRead)->handle_;
    v8::Function::Cast(*data->dataCallback)->Call(v8::Context::GetCurrent()->Global(), 1, argv);
  } else if(data->errorCode > 0) {
    if(data->errorCode == ERROR_INVALID_HANDLE && IsClosingHandle((int)data->fd)) {
      goto cleanup;
    } else {
      v8::Handle<v8::Value> argv[1];
      argv[0] = v8::Exception::Error(v8::String::New(data->errorString));
      v8::Function::Cast(*data->errorCallback)->Call(v8::Context::GetCurrent()->Global(), 1, argv);
      Sleep(100); // prevent the errors from occurring too fast
    }
  }
  AfterOpenSuccess((int)data->fd, data->dataCallback, data->disconnectedCallback, data->errorCallback);

cleanup:
  data->dataCallback.Dispose();
  data->errorCallback.Dispose();
  delete data;
  delete req;
}

void AfterOpenSuccess(int fd, v8::Handle<v8::Value> dataCallback, v8::Handle<v8::Value> disconnectedCallback, v8::Handle<v8::Value> errorCallback) {
  WatchPortBaton* baton = new WatchPortBaton();
  memset(baton, 0, sizeof(WatchPortBaton));
  baton->fd = (HANDLE)fd;
  baton->dataCallback = v8::Persistent<v8::Value>::New(dataCallback);
  baton->errorCallback = v8::Persistent<v8::Value>::New(errorCallback);
  baton->disconnectedCallback = v8::Persistent<v8::Value>::New(disconnectedCallback);

  uv_work_t* req = new uv_work_t();
  req->data = baton;

  uv_queue_work(uv_default_loop(), req, EIO_WatchPort, EIO_AfterWatchPort);
}

void EIO_Write(uv_work_t* req) {
  QueuedWrite* queuedWrite = static_cast<QueuedWrite*>(req->data);
  WriteBaton* data = static_cast<WriteBaton*>(queuedWrite->baton);
  data->result = 0;

  OVERLAPPED ov = {0};
  // Event used by GetOverlappedResult(..., TRUE) to wait for outgoing data or timeout
  // Event MUST be used if program has several simultaneous asynchronous operations
  // on the same handle (i.e. ReadFile and WriteFile)
  ov.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);

  // Start write operation - synchrounous or asynchronous
  DWORD bytesWrittenSync = 0;
  if(!WriteFile((HANDLE)data->fd, data->bufferData, data->bufferLength, &bytesWrittenSync, &ov)) {
    DWORD lastError = GetLastError();
    if(lastError != ERROR_IO_PENDING) {
      // Write operation error
      ErrorCodeToString("Writing to COM port (WriteFile)", lastError, data->errorString);
    }
    else {
      // Write operation is asynchronous and is pending
      // We MUST wait for operation completion before deallocation of OVERLAPPED struct
      // or write data buffer

      // Wait for async write operation completion or timeout
      DWORD bytesWrittenAsync = 0;
      if(!GetOverlappedResult((HANDLE)data->fd, &ov, &bytesWrittenAsync, TRUE)) {
        // Write operation error
        DWORD lastError = GetLastError();
        ErrorCodeToString("Writing to COM port (GetOverlappedResult)", lastError, data->errorString);
      }
      else {
        // Write operation completed asynchronously
        data->result = bytesWrittenAsync;
      }
    }
  }
  else {
    // Write operation completed synchronously
    data->result = bytesWrittenSync;
  }

  CloseHandle(ov.hEvent);
}

void EIO_Close(uv_work_t* req) {
  CloseBaton* data = static_cast<CloseBaton*>(req->data);

  g_closingHandles.push_back(data->fd);

  HMODULE hKernel32 = LoadLibrary("kernel32.dll");
  // Look up function address
  CancelIoExType pCancelIoEx = (CancelIoExType)GetProcAddress(hKernel32, "CancelIoEx");
  // Do something with it
  if (pCancelIoEx)
  {
      // Function exists so call it
      // Cancel all pending IO Requests for the current device
      pCancelIoEx((HANDLE)data->fd, NULL);
  }
  if(!CloseHandle((HANDLE)data->fd)) {
    ErrorCodeToString("closing connection", GetLastError(), data->errorString);
    return;
  }
}

/*
 * listComPorts.c -- list COM ports
 *
 * http://github.com/todbot/usbSearch/
 *
 * 2012, Tod E. Kurt, http://todbot.com/blog/
 *
 *
 * Uses DispHealper : http://disphelper.sourceforge.net/
 *
 * Notable VIDs & PIDs combos:
 * VID 0403 - FTDI
 *
 * VID 0403 / PID 6001 - Arduino Diecimila
 *
 */
void EIO_List(uv_work_t* req) {
  ListBaton* data = static_cast<ListBaton*>(req->data);

  {
    DISPATCH_OBJ(wmiSvc);
    DISPATCH_OBJ(colDevices);

    dhInitialize(TRUE);
    dhToggleExceptions(TRUE);

    dhGetObject(L"winmgmts:{impersonationLevel=impersonate}!\\\\.\\root\\cimv2", NULL, &wmiSvc);
    dhGetValue(L"%o", &colDevices, wmiSvc, L".ExecQuery(%S)", L"Select * from Win32_PnPEntity");

    int port_count = 0;
    FOR_EACH(objDevice, colDevices, NULL) {
      char* name = NULL;
      char* pnpid = NULL;
      char* manu = NULL;
      char* match;

      dhGetValue(L"%s", &name,  objDevice, L".Name");
      dhGetValue(L"%s", &pnpid, objDevice, L".PnPDeviceID");

      if( (match = strstr( name, "(COM" )) != NULL ) { // look for "(COM23)"
        // 'Manufacturuer' can be null, so only get it if we need it
        dhGetValue(L"%s", &manu, objDevice,  L".Manufacturer");
        port_count++;
        char* comname = strtok( match, "()");
        ListResultItem* resultItem = new ListResultItem();
        resultItem->comName = comname;
        resultItem->manufacturer = manu;
        resultItem->pnpId = pnpid;
        data->results.push_back(resultItem);
        dhFreeString(manu);
      }

      dhFreeString(name);
      dhFreeString(pnpid);
    } NEXT(objDevice);

    SAFE_RELEASE(colDevices);
    SAFE_RELEASE(wmiSvc);

    dhUninitialize(TRUE);
  }

  std::vector<UINT> ports;
  if (CEnumerateSerial::UsingQueryDosDevice(ports))
  {
    for (size_t i = 0; i < ports.size(); i++)
    {
      char comname[64] = { 0 };
      sprintf(comname, "COM%u", ports[i]);
      bool bFound = false;
      for (std::list<ListResultItem*>::iterator ri = data->results.begin(); ri != data->results.end(); ri++)
      {
        if (stricmp((*ri)->comName.c_str(), comname) == 0)
        {
          bFound = true;
          break;
        }
      }
      if (!bFound)
      {
        ListResultItem* resultItem = new ListResultItem();
        resultItem->comName = comname;
        resultItem->manufacturer = "";
        resultItem->pnpId = "";
        data->results.push_back(resultItem);
      }
    }
  }
}

void EIO_Flush(uv_work_t* req) {
  FlushBaton* data = static_cast<FlushBaton*>(req->data);

  if(!FlushFileBuffers((HANDLE)data->fd)) {
    ErrorCodeToString("flushing connection", GetLastError(), data->errorString);
    return;
  }
}

#endif
<|endoftext|>


<commit_before>////////////////////////////////////////////////////////////////////////////
//
// Copyright 2016 Realm Inc.
//
// 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 "adapter.hpp"
#include "object_store.hpp"
#include "object_schema.hpp"

#include <realm/sync/changeset_cooker.hpp>
#include <realm/impl/transact_log.hpp>
#include <realm/impl/input_stream.hpp>

using namespace realm;

class InstructionHander {
public:
    InstructionHander(Group &group)
    : m_group(group)
    , m_schema(ObjectStore::schema_from_group(group)) {}

    Group &m_group;
    Schema m_schema;
    std::vector<Adapter::Instruction> parsed_instructions;
    size_t selected_table;
    std::string selected_object_type;
    ObjectSchema *selected_object_schema;

    // No selection needed:
    bool select_table(size_t group_index, size_t, const size_t*)
    {
        selected_table = group_index;
        selected_object_type = ObjectStore::object_type_for_table_name(m_group.get_table_name(selected_table));
        selected_object_schema = &*m_schema.find(selected_object_type);
        return true;
    }
    bool select_descriptor(size_t, const size_t*)
    {
        return true;
    }
    bool select_link_list(size_t, size_t, size_t)
    {
        return true;
    }
    bool insert_group_level_table(size_t, size_t, StringData)
    {
        return true;
    }
    bool erase_group_level_table(size_t, size_t)
    {
        return true;
    }
    bool rename_group_level_table(size_t, StringData)
    {
        return true;
    }
    bool move_group_level_table(size_t, size_t)
    {
        return true;
    }

    // Must have table selected:
    bool insert_empty_rows(size_t row_index, size_t n_rows, size_t, bool)
    {
        REALM_ASSERT(n_rows == 1);
        parsed_instructions.emplace_back(Adapter::Instruction{
            Adapter::Instruction::Type::Insertion,
            selected_object_type,
            row_index
        });
        return true;
    }
    bool erase_rows(size_t, size_t, size_t, bool)
    {
        return true;
    }
    bool swap_rows(size_t, size_t)
    {
        return true;
    }
    bool merge_rows(size_t, size_t)
    {
        return true;
    }
    bool clear_table()
    {
        return true;
    }
    bool set_int(size_t column_index, size_t row_index, int_fast64_t value, _impl::Instruction, size_t)
    {
        parsed_instructions.emplace_back(Adapter::Instruction(
            selected_object_type,
            row_index,
            selected_object_schema->persisted_properties[column_index].name,
            false,
            (int64_t)value
        ));
        return true;
    }
    bool add_int(size_t, size_t, int_fast64_t)
    {
        return true;
    }
    bool set_bool(size_t, size_t, bool, _impl::Instruction)
    {
        return true;
    }
    bool set_float(size_t, size_t, float, _impl::Instruction)
    {
        return true;
    }
    bool set_double(size_t, size_t, double, _impl::Instruction)
    {
        return true;
    }
    bool set_string(size_t, size_t, StringData, _impl::Instruction, size_t)
    {
        return true;
    }
    bool set_binary(size_t, size_t, BinaryData, _impl::Instruction)
    {
        return true;
    }
    bool set_olddatetime(size_t, size_t, OldDateTime, _impl::Instruction)
    {
        return true;
    }
    bool set_timestamp(size_t, size_t, Timestamp, _impl::Instruction)
    {
        return true;
    }
    bool set_table(size_t, size_t, _impl::Instruction)
    {
        return true;
    }
    bool set_mixed(size_t, size_t, const Mixed&, _impl::Instruction)
    {
        return true;
    }
    bool set_link(size_t, size_t, size_t, size_t, _impl::Instruction)
    {
        return true;
    }
    bool set_null(size_t, size_t, _impl::Instruction, size_t)
    {
        return true;
    }
    bool nullify_link(size_t, size_t, size_t)
    {
        return true;
    }
    bool insert_substring(size_t, size_t, size_t, StringData)
    {
        return true;
    }
    bool erase_substring(size_t, size_t, size_t, size_t)
    {
        return true;
    }
    bool optimize_table()
    {
        return true;
    }

    // Must have descriptor selected:
    bool insert_link_column(size_t, DataType, StringData, size_t, size_t)
    {
        return true;
    }
    bool insert_column(size_t, DataType, StringData, bool)
    {
        return true;
    }
    bool erase_link_column(size_t, size_t, size_t)
    {
        return true;
    }
    bool erase_column(size_t)
    {
        return true;
    }
    bool rename_column(size_t, StringData)
    {
        return true;
    }
    bool move_column(size_t, size_t)
    {
        return true;
    }
    bool add_search_index(size_t)
    {
        return true;
    }
    bool remove_search_index(size_t)
    {
        return true;
    }
    bool set_link_type(size_t, LinkType)
    {
        return true;
    }

    // Must have linklist selected:
    bool link_list_set(size_t, size_t, size_t)
    {
        return true;
    }
    bool link_list_insert(size_t, size_t, size_t)
    {
        return true;
    }
    bool link_list_move(size_t, size_t)
    {
        return true;
    }
    bool link_list_swap(size_t, size_t)
    {
        return true;
    }
    bool link_list_erase(size_t, size_t)
    {
        return true;
    }
    bool link_list_nullify(size_t, size_t)
    {
        return true;
    }
    bool link_list_clear(size_t)
    {
        return true;
    }

    void parse_complete()
    {
    }
};

Adapter::Adapter(std::function<void(std::string)> realm_changed,
                 std::string local_root_dir, std::string server_base_url,
                 std::shared_ptr<SyncUser> user)
: m_global_notifier(GlobalNotifier::shared_notifier(
    std::make_unique<Adapter::Callback>([=](auto info) { realm_changed(info.second); }),
                                        local_root_dir, server_base_url, user,
                                        std::make_shared<sync::TrivialChangesetCooker>()))
{
    m_global_notifier->start();
}

std::vector<bool> Adapter::Callback::available(std::vector<GlobalNotifier::RealmInfo> realms,
                                               std::vector<bool> new_realms,
                                               bool all) {
    std::cout << "AVAILABLE" << std::endl;
    std::vector<bool> watch;
    for (auto realm : realms) {
        std::cout << realm.second << std::endl;
        watch.push_back(true);
        m_realm_changed(realm);
    }
    return watch;
}

void Adapter::Callback::realm_changed(GlobalNotifier::ChangeNotification changes) {
    std::cout << "CHANGED " << changes.get_path() << std::endl;
    m_realm_changed(changes.realm_info);
}

std::vector<Adapter::Instruction> Adapter::current(std::string realm_path) {
    auto realm = Realm::make_shared_realm(m_global_notifier->get_config(realm_path));
    auto sync_history = static_cast<sync::SyncHistory *>(realm->history());
    auto progress = sync_history->get_cooked_progress();
    auto version = progress.version;

    util::AppendBuffer<char> buffer;
    version = sync_history->fetch_next_cooked_changeset(version, buffer);

    std::cout << "Processing " << realm_path << " " << version << std::endl;

    InstructionHander handler(realm->read_group());
    _impl::SimpleInputStream stream(buffer.data(), buffer.size());
    _impl::TransactLogParser parser;
    parser.parse(stream, handler);

    realm->invalidate();

    return std::move(handler.parsed_instructions);
}

void Adapter::advance(std::string realm_path) {
    auto realm = Realm::make_shared_realm(m_global_notifier->get_config(realm_path));
    auto sync_history = static_cast<sync::SyncHistory *>(realm->history());
    auto progress = sync_history->get_cooked_progress();

    util::AppendBuffer<char> buffer;
    auto version = sync_history->fetch_next_cooked_changeset(progress.version, buffer);

    if (version) {
        sync_history->set_cooked_progress({version, 0});
    }

    realm->invalidate();
}
<commit_msg>support instructions for all basic property types<commit_after>////////////////////////////////////////////////////////////////////////////
//
// Copyright 2016 Realm Inc.
//
// 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 "adapter.hpp"
#include "object_store.hpp"
#include "object_schema.hpp"

#include <realm/sync/changeset_cooker.hpp>
#include <realm/impl/transact_log.hpp>
#include <realm/impl/input_stream.hpp>

using namespace realm;

class InstructionHander {
public:
    InstructionHander(Group &group)
    : m_group(group)
    , m_schema(ObjectStore::schema_from_group(group)) {}

    Group &m_group;
    Schema m_schema;
    std::vector<Adapter::Instruction> parsed_instructions;
    size_t selected_table;
    std::string selected_object_type;
    ObjectSchema *selected_object_schema;

    // No selection needed:
    bool select_table(size_t group_index, size_t, const size_t*)
    {
        selected_table = group_index;
        selected_object_type = ObjectStore::object_type_for_table_name(m_group.get_table_name(selected_table));
        selected_object_schema = &*m_schema.find(selected_object_type);
        return true;
    }
    bool select_descriptor(size_t, const size_t*)
    {
        return true;
    }
    bool select_link_list(size_t, size_t, size_t)
    {
        return true;
    }
    bool insert_group_level_table(size_t, size_t, StringData)
    {
        return true;
    }
    bool erase_group_level_table(size_t, size_t)
    {
        return true;
    }
    bool rename_group_level_table(size_t, StringData)
    {
        return true;
    }
    bool move_group_level_table(size_t, size_t)
    {
        return true;
    }

    // Must have table selected:
    bool insert_empty_rows(size_t row_index, size_t n_rows, size_t, bool)
    {
        REALM_ASSERT(n_rows == 1);
        parsed_instructions.emplace_back(Adapter::Instruction{
            Adapter::Instruction::Type::Insertion,
            selected_object_type,
            row_index
        });
        return true;
    }
    bool erase_rows(size_t, size_t, size_t, bool)
    {
        return true;
    }
    bool swap_rows(size_t, size_t)
    {
        return true;
    }
    bool merge_rows(size_t, size_t)
    {
        return true;
    }
    bool clear_table()
    {
        return true;
    }
    bool set_int(size_t column_index, size_t row_index, int_fast64_t value, _impl::Instruction, size_t)
    {
        parsed_instructions.emplace_back(Adapter::Instruction(
            selected_object_type,
            row_index,
            selected_object_schema->persisted_properties[column_index].name,
            false,
            (int64_t)value
        ));
        return true;
    }
    bool add_int(size_t, size_t, int_fast64_t)
    {
        return true;
    }
    bool set_bool(size_t column_index, size_t row_index, bool value, _impl::Instruction)
    {
        parsed_instructions.emplace_back(Adapter::Instruction(
            selected_object_type,
            row_index,
            selected_object_schema->persisted_properties[column_index].name,
            false,
            value
        ));
        return true;
    }
    bool set_float(size_t column_index, size_t row_index, float value, _impl::Instruction)
    {
        parsed_instructions.emplace_back(Adapter::Instruction(
            selected_object_type,
            row_index,
            selected_object_schema->persisted_properties[column_index].name,
            false,
            value
        ));
        return true;
    }
    bool set_double(size_t column_index, size_t row_index, double value, _impl::Instruction)
    {
        parsed_instructions.emplace_back(Adapter::Instruction(
            selected_object_type,
            row_index,
            selected_object_schema->persisted_properties[column_index].name,
            false,
            value
        ));
        return true;
    }
    bool set_string(size_t column_index, size_t row_index, StringData value, _impl::Instruction, size_t)
    {
        parsed_instructions.emplace_back(Adapter::Instruction(
            selected_object_type,
            row_index,
            selected_object_schema->persisted_properties[column_index].name,
            false,
            value
        ));
        return true;
    }
    bool set_binary(size_t column_index, size_t row_index, BinaryData value, _impl::Instruction)
    {
        parsed_instructions.emplace_back(Adapter::Instruction(
            selected_object_type,
            row_index,
            selected_object_schema->persisted_properties[column_index].name,
            false,
            value
        ));
        return true;
    }
    bool set_olddatetime(size_t, size_t, OldDateTime, _impl::Instruction)
    {
        return true;
    }
    bool set_timestamp(size_t column_index, size_t row_index, Timestamp value, _impl::Instruction)
    {
        parsed_instructions.emplace_back(Adapter::Instruction(
            selected_object_type,
            row_index,
            selected_object_schema->persisted_properties[column_index].name,
            false,
            value
        ));
        return true;
    }
    bool set_table(size_t, size_t, _impl::Instruction)
    {
        return true;
    }
    bool set_mixed(size_t, size_t, const Mixed&, _impl::Instruction)
    {
        return true;
    }
    bool set_link(size_t, size_t, size_t, size_t, _impl::Instruction)
    {
        return true;
    }
    bool set_null(size_t column_index, size_t row_index, _impl::Instruction, size_t)
    {
        parsed_instructions.emplace_back(Adapter::Instruction(
            selected_object_type,
            row_index,
            selected_object_schema->persisted_properties[column_index].name,
            true,
            (int64_t)0
        ));
        return true;
    }
    bool nullify_link(size_t, size_t, size_t)
    {
        return true;
    }
    bool insert_substring(size_t, size_t, size_t, StringData)
    {
        return true;
    }
    bool erase_substring(size_t, size_t, size_t, size_t)
    {
        return true;
    }
    bool optimize_table()
    {
        return true;
    }

    // Must have descriptor selected:
    bool insert_link_column(size_t, DataType, StringData, size_t, size_t)
    {
        return true;
    }
    bool insert_column(size_t, DataType, StringData, bool)
    {
        return true;
    }
    bool erase_link_column(size_t, size_t, size_t)
    {
        return true;
    }
    bool erase_column(size_t)
    {
        return true;
    }
    bool rename_column(size_t, StringData)
    {
        return true;
    }
    bool move_column(size_t, size_t)
    {
        return true;
    }
    bool add_search_index(size_t)
    {
        return true;
    }
    bool remove_search_index(size_t)
    {
        return true;
    }
    bool set_link_type(size_t, LinkType)
    {
        return true;
    }

    // Must have linklist selected:
    bool link_list_set(size_t, size_t, size_t)
    {
        return true;
    }
    bool link_list_insert(size_t, size_t, size_t)
    {
        return true;
    }
    bool link_list_move(size_t, size_t)
    {
        return true;
    }
    bool link_list_swap(size_t, size_t)
    {
        return true;
    }
    bool link_list_erase(size_t, size_t)
    {
        return true;
    }
    bool link_list_nullify(size_t, size_t)
    {
        return true;
    }
    bool link_list_clear(size_t)
    {
        return true;
    }

    void parse_complete()
    {
    }
};

Adapter::Adapter(std::function<void(std::string)> realm_changed,
                 std::string local_root_dir, std::string server_base_url,
                 std::shared_ptr<SyncUser> user)
: m_global_notifier(GlobalNotifier::shared_notifier(
    std::make_unique<Adapter::Callback>([=](auto info) { realm_changed(info.second); }),
                                        local_root_dir, server_base_url, user,
                                        std::make_shared<sync::TrivialChangesetCooker>()))
{
    m_global_notifier->start();
}

std::vector<bool> Adapter::Callback::available(std::vector<GlobalNotifier::RealmInfo> realms,
                                               std::vector<bool> new_realms,
                                               bool all) {
    std::cout << "AVAILABLE" << std::endl;
    std::vector<bool> watch;
    for (auto realm : realms) {
        std::cout << realm.second << std::endl;
        watch.push_back(true);
        m_realm_changed(realm);
    }
    return watch;
}

void Adapter::Callback::realm_changed(GlobalNotifier::ChangeNotification changes) {
    std::cout << "CHANGED " << changes.get_path() << std::endl;
    m_realm_changed(changes.realm_info);
}

std::vector<Adapter::Instruction> Adapter::current(std::string realm_path) {
    auto realm = Realm::make_shared_realm(m_global_notifier->get_config(realm_path));
    auto sync_history = static_cast<sync::SyncHistory *>(realm->history());
    auto progress = sync_history->get_cooked_progress();
    auto version = progress.version;

    util::AppendBuffer<char> buffer;
    version = sync_history->fetch_next_cooked_changeset(version, buffer);

    std::cout << "Processing " << realm_path << " " << version << std::endl;

    InstructionHander handler(realm->read_group());
    _impl::SimpleInputStream stream(buffer.data(), buffer.size());
    _impl::TransactLogParser parser;
    parser.parse(stream, handler);

    realm->invalidate();

    return std::move(handler.parsed_instructions);
}

void Adapter::advance(std::string realm_path) {
    auto realm = Realm::make_shared_realm(m_global_notifier->get_config(realm_path));
    auto sync_history = static_cast<sync::SyncHistory *>(realm->history());
    auto progress = sync_history->get_cooked_progress();

    util::AppendBuffer<char> buffer;
    auto version = sync_history->fetch_next_cooked_changeset(progress.version, buffer);

    if (version) {
        sync_history->set_cooked_progress({version, 0});
    }

    realm->invalidate();
}
<|endoftext|>