<commit_before>/*
* SMARTCARDPP
*
* This software is released under either the GNU Library General Public
* License (see LICENSE.LGPL) or the BSD License (see LICENSE.BSD).
*
* Note that the only valid version of the LGPL license as far as this
* project is concerned is the original GNU Library General Public License
* Version 2.1, February 1999
*
*/

#include "common.h"
#include "SCError.h"

SCError::SCError(long err) : runtime_error("smart card API error"),error(err)
{
	std::ostringstream buf;
	switch(err & 0xFFFFFFFF)
	{
		case 0x80100017 : //SCARD_E_READER_UNAVAILABLE
			buf << "No smart card readers"; break;
		case 0x80100069 : //SCARD_W_REMOVED_CARD
			buf << "No card in specified reader"; break;
		case 0x80100011 : //SCARD_E_INVALID_VALUE .. needs trapping
			buf << "Another application is using the card"; break;
		case 0x8010000b : //SCARD_E_SHARING_VIOLATION
			buf << "The smart card cannot be accessed because of other connections outstanding"; break;
		case 0x8010000f : //SCARD_E_PROTO_MISMATCH
			buf << "The requested protocols are incompatible with the protocol currently in use with the smart card"; break;
		case 0x8010001D : // SCARD_E_NO_SERVICE
			buf << "Smart card manager (PC/SC service) is not running"; break;
		case 0x80100066 : // SCARD_W_UNRESPONSIVE_CARD
			buf << "The card is not responding to reset"; break;
		default:
			buf << "exception:'" << runtime_error::what() <<
				"' code:'0x" <<std::hex << std::setfill('0') <<
				std::setw(8) << error << "'";
	}
	desc = buf.str();
}

void SCError::check(long err, int cid, int tid)
{
	if(err)
		SCardLog::writeMessage("[%i:%i][%s:%d] ERROR CODE RECIEVED 0x%08X", cid, tid, __FUNC__, __LINE__, err);

    if((int)err == SCARD_W_RESET_CARD)
    {
        SCardLog::writeMessage("[%i:%i][%s:%d] SCARD_W_RESET_CARD", cid, tid, __FUNC__, __LINE__, err);
        throw CardResetError();
    }
    else if((int)err == SCARD_E_NOT_TRANSACTED)
    {
        SCardLog::writeMessage("[%i:%i][%s:%d] SCARD_E_NOT_TRANSACTED", cid, tid, __FUNC__, __LINE__, err);
        throw CardResetError();
    }
    else if((int)err == SCARD_E_NO_SMARTCARD)
    {
        SCardLog::writeMessage("[%i:%i][%s:%d] SCARD_E_NO_SMARTCARD", cid, tid, __FUNC__, __LINE__, err);
        throw NoCardInReaderError();
    }
    else if((int)err == SCARD_W_REMOVED_CARD)
    {
        SCardLog::writeMessage("[%i:%i][%s:%d] SCARD_W_REMOVED_CARD", cid, tid, __FUNC__, __LINE__, err);
        throw NoCardInReaderError();
    }
    else if((int)err == SCARD_W_UNRESPONSIVE_CARD)
    {
        SCardLog::writeMessage("[%i:%i][%s:%d] SCARD_W_UNRESPONSIVE_CARD", cid, tid, __FUNC__, __LINE__, err);
        throw NoCardInReaderError();
    }
    else if((int)err == SCARD_E_NO_READERS_AVAILABLE)
    {
        SCardLog::writeMessage("[%i:%i][%s:%d] SCARD_E_NO_READERS_AVAILABLE", cid, tid, __FUNC__, __LINE__, err);
        throw NoReadersAvailible();
    }
    else if((int)err == ERROR_NO_MEDIA_IN_DRIVE)
    {
        SCardLog::writeMessage("[%i:%i][%s:%d] ERROR_NO_MEDIA_IN_DRIVE", cid, tid, __FUNC__, __LINE__, err);
        throw NoCardInReaderError();
    }
    else if((int)err == SCARD_E_READER_UNAVAILABLE)
    {
        SCardLog::writeMessage("[%i:%i][%s:%d] SCARD_E_READER_UNAVAILABLE", cid, tid, __FUNC__, __LINE__, err);
        throw NoCardInReaderError();
    }
    else if((int)err == SCARD_E_SHARING_VIOLATION)
    {
        SCardLog::writeMessage("[%i:%i][%s:%d] SCARD_E_SHARING_VIOLATION", cid, tid, __FUNC__, __LINE__, err);
        throw CardResetError();
    }
    else if((int)err == SCARD_E_TIMEOUT)
    {
        SCardLog::writeMessage("[%i:%i][%s:%d] SCARD_E_TIMEOUT", cid, tid, __FUNC__, __LINE__, err);
        return;
    }

	if (err)
	{
		throw SCError(err);
	}
}
<commit_msg>#23996 Try again on SCARD_W_UNRESPONSIVE_CARD error<commit_after>/*
* SMARTCARDPP
*
* This software is released under either the GNU Library General Public
* License (see LICENSE.LGPL) or the BSD License (see LICENSE.BSD).
*
* Note that the only valid version of the LGPL license as far as this
* project is concerned is the original GNU Library General Public License
* Version 2.1, February 1999
*
*/

#include "common.h"
#include "SCError.h"

SCError::SCError(long err) : runtime_error("smart card API error"),error(err)
{
	std::ostringstream buf;
	switch(err & 0xFFFFFFFF)
	{
		case 0x80100017 : //SCARD_E_READER_UNAVAILABLE
			buf << "No smart card readers"; break;
		case 0x80100069 : //SCARD_W_REMOVED_CARD
			buf << "No card in specified reader"; break;
		case 0x80100011 : //SCARD_E_INVALID_VALUE .. needs trapping
			buf << "Another application is using the card"; break;
		case 0x8010000b : //SCARD_E_SHARING_VIOLATION
			buf << "The smart card cannot be accessed because of other connections outstanding"; break;
		case 0x8010000f : //SCARD_E_PROTO_MISMATCH
			buf << "The requested protocols are incompatible with the protocol currently in use with the smart card"; break;
		case 0x8010001D : // SCARD_E_NO_SERVICE
			buf << "Smart card manager (PC/SC service) is not running"; break;
		case 0x80100066 : // SCARD_W_UNRESPONSIVE_CARD
			buf << "The card is not responding to reset"; break;
		default:
			buf << "exception:'" << runtime_error::what() <<
				"' code:'0x" <<std::hex << std::setfill('0') <<
				std::setw(8) << error << "'";
	}
	desc = buf.str();
}

void SCError::check(long err, int cid, int tid)
{
	if(err)
		SCardLog::writeMessage("[%i:%i][%s:%d] ERROR CODE RECIEVED 0x%08X", cid, tid, __FUNC__, __LINE__, err);

    if((int)err == SCARD_W_RESET_CARD)
    {
        SCardLog::writeMessage("[%i:%i][%s:%d] SCARD_W_RESET_CARD", cid, tid, __FUNC__, __LINE__, err);
        throw CardResetError();
    }
    else if((int)err == SCARD_E_NOT_TRANSACTED)
    {
        SCardLog::writeMessage("[%i:%i][%s:%d] SCARD_E_NOT_TRANSACTED", cid, tid, __FUNC__, __LINE__, err);
        throw CardResetError();
    }
    else if((int)err == SCARD_E_NO_SMARTCARD)
    {
        SCardLog::writeMessage("[%i:%i][%s:%d] SCARD_E_NO_SMARTCARD", cid, tid, __FUNC__, __LINE__, err);
        throw NoCardInReaderError();
    }
    else if((int)err == SCARD_W_REMOVED_CARD)
    {
        SCardLog::writeMessage("[%i:%i][%s:%d] SCARD_W_REMOVED_CARD", cid, tid, __FUNC__, __LINE__, err);
        throw NoCardInReaderError();
    }
    else if((int)err == SCARD_W_UNRESPONSIVE_CARD)
    {
        SCardLog::writeMessage("[%i:%i][%s:%d] SCARD_W_UNRESPONSIVE_CARD", cid, tid, __FUNC__, __LINE__, err);
        throw CardResetError();
    }
    else if((int)err == SCARD_E_NO_READERS_AVAILABLE)
    {
        SCardLog::writeMessage("[%i:%i][%s:%d] SCARD_E_NO_READERS_AVAILABLE", cid, tid, __FUNC__, __LINE__, err);
        throw NoReadersAvailible();
    }
    else if((int)err == ERROR_NO_MEDIA_IN_DRIVE)
    {
        SCardLog::writeMessage("[%i:%i][%s:%d] ERROR_NO_MEDIA_IN_DRIVE", cid, tid, __FUNC__, __LINE__, err);
        throw NoCardInReaderError();
    }
    else if((int)err == SCARD_E_READER_UNAVAILABLE)
    {
        SCardLog::writeMessage("[%i:%i][%s:%d] SCARD_E_READER_UNAVAILABLE", cid, tid, __FUNC__, __LINE__, err);
        throw NoCardInReaderError();
    }
    else if((int)err == SCARD_E_SHARING_VIOLATION)
    {
        SCardLog::writeMessage("[%i:%i][%s:%d] SCARD_E_SHARING_VIOLATION", cid, tid, __FUNC__, __LINE__, err);
        throw CardResetError();
    }
    else if((int)err == SCARD_E_TIMEOUT)
    {
        SCardLog::writeMessage("[%i:%i][%s:%d] SCARD_E_TIMEOUT", cid, tid, __FUNC__, __LINE__, err);
        return;
    }

	if (err)
	{
		throw SCError(err);
	}
}
<|endoftext|>


<commit_before>#ifndef _SPATIAL_MATH_TEST_INL_
#define _SPATIAL_MATH_TEST_INL_

//#include "SM_Calc.h"
#include "sm_const.h"

#include <float.h>

#include <algorithm>

namespace sm
{

inline
bool is_between(float bound0, float bound1, float test)
{
	if (bound0 < bound1) {
		return test < bound1 + FLT_EPSILON && test > bound0 - FLT_EPSILON;
	} else {
		return test < bound0 + FLT_EPSILON && test > bound1 - FLT_EPSILON;
	}
}

inline
bool is_point_at_line_left(const vec2& v, const vec2& s, const vec2& e)
{
	return (v.y - s.y) * (e.x - s.x) - (v.x - s.x) * (e.y - s.y) > FLT_EPSILON;
}

inline
bool is_point_in_rect(const vec2& v, const rect& r)
{
	return v.x > r.xmin && v.x < r.xmax
		&& v.y > r.ymin && v.y < r.ymax;
}

inline
bool is_point_in_area(const vec2& v, const std::vector<vec2>& area)
{
	bool odd_nodes = false;
	for (int i = 0, n = area.size(), j = n - 1; i < n; ++i)
	{
		if ((area[i].y < v.y && area[j].y >= v.y ||
			 area[j].y < v.y && area[i].y >= v.y) &&
			(area[i].x <= v.x || area[j].x <= v.x))
		{
			odd_nodes ^= (area[i].x + (v.y - area[i].y) / (area[j].y - area[i].y) * (area[j].x - area[i].x) < v.x);
		}
		j = i;
	}
	return odd_nodes;
}

inline
bool is_point_in_circle(const vec2& v, const vec2& center, float radius)
{
	return (v - center).LengthSquared() < radius * radius;
}

inline
bool is_point_in_convex(const vec2& pos, const std::vector<vec2>& convex)
{
	if (convex.size() < 3) {
		return false;
	}

	int count = 0;
	for (int i = 0, n = convex.size(); i < n; ++i)
	{
		vec2 s = convex[i],
			     e = i == convex.size() - 1 ? convex[0] : convex[i + 1];
		if (is_point_at_line_left(pos, s, e)) {
			++count;
		}
	}
	return count == convex.size() || count == 0;
}

inline
bool is_point_intersect_polyline(const vec2& point, const std::vector<vec2>& polyline)
{
	rect r(point, SM_LARGE_EPSILON, SM_LARGE_EPSILON);
	return is_rect_intersect_polyline(r, polyline, true);
}

inline
bool is_segment_intersect_segment(const vec2& s0, const vec2& e0, const vec2& s1, const vec2& e1)
{
	return is_point_at_line_left(s0, s1, e1) != is_point_at_line_left(e0, s1, e1)
		&& is_point_at_line_left(s1, s0, e0) != is_point_at_line_left(e1, s0, e0);
}

inline
bool is_rect_contain_point(const rect& r, const vec2& v)
{
	return v.x >= r.xmin && v.x <= r.xmax
		&& v.y >= r.ymin && v.y <= r.ymax;
}

inline
bool is_rect_contain_rect(const rect& r0, const rect& r1)
{
	return r1.xmin >= r0.xmin && r1.xmax <= r0.xmax
		&& r1.ymin >= r0.ymin && r1.ymax <= r0.ymax;
}

inline
bool is_rect_intersect_rect(const rect& r0, const rect& r1)
{
	return !(r0.xmin >= r1.xmax || r0.xmax <= r1.xmin || r0.ymin >= r1.ymax || r0.ymax <= r1.ymin);
}

inline
bool is_rect_intersect_polyline(const rect& r, const std::vector<vec2>& poly, bool loop)
{
	if (poly.size() < 2) return false;

	for (size_t i = 0, n = poly.size() - 1; i < n; ++i)
	{
		if (is_rect_intersect_segment(r, poly[i], poly[i+1]))
			return true;
	}

	if (loop && is_rect_intersect_segment(r, poly[poly.size() - 1], poly[0]))
		return true;

	return false;
}

inline
bool is_rect_intersect_polygon(const rect& rect, const std::vector<vec2>& poly)
{
	if (poly.size() < 3) {
		return false;
	}

	if (is_point_in_area(rect.Center(), poly) || is_point_in_rect(poly[0], rect)) {
		return true;
	}

	std::vector<vec2> poly2;
	poly2.push_back(vec2(rect.xmin, rect.ymin));
	poly2.push_back(vec2(rect.xmax, rect.ymin));
	poly2.push_back(vec2(rect.xmax, rect.ymax));
	poly2.push_back(vec2(rect.xmin, rect.ymax));

	return is_polygon_intersect_polygon(poly, poly2);
}

inline
bool is_ray_intersect_triangle(const vec3& ray_ori, const vec3& ray_dir,
							   const vec3& tri0, const vec3& tri1,
							   const vec3& tri2, vec3& out)
{
		// Idea: Tomas Moeller and Ben Trumbore
	// in Fast, Minimum Storage Ray/Triangle Intersection

	// Find vectors for two edges sharing vert0
	vec3 edge1 = tri1 - tri0,
		 edge2 = tri2 - tri0;

	// Begin calculating determinant - also used to calculate U parameter
	vec3 pvec = ray_dir.Cross(edge2);

	// If determinant is near zero, ray lies in sm_plane of triangle
	float det = edge1.Dot(pvec);

	// *** Culling branch ***
	/*if (det < FLT_EPSILON)
		return NULL;

	// Calculate distance from vert0 to ray origin
	struct sm_vec3 tvec;
	sm_vec3_vector(&tvec, rayOrig, &vert0);

	// Calculate U parameter and test bounds
	float u = sm_vec3_dot(&tvec, &pvec);
	if (u < 0 || u > det)
		return NULL;

	// Prepare to test V parameter
	struct sm_vec3 qvec;
	sm_vec3_cross(&qvec, &tvec, &edge1);

	// Calculate V parameter and test bounds
	float v = sm_vec3_dot(rayDir, &qvec);
	if (v < 0 || u + v > det)
		return NULL;

	// Calculate t, scale parameters, ray intersects triangle
	float t = sm_vec3_dot(&edge2, &qvec) / det;*/

	// *** Non-culling branch ***
	if (det > -FLT_EPSILON && det < FLT_EPSILON) {
		return false;
	}
	float inv_det = 1.0f / det;

	// Calculate distance from vert0 to ray origin
	vec3 tvec = ray_ori - tri0;

	// Calculate U parameter and test bounds
	float u = tvec.Dot(pvec) * inv_det;
	if (u < 0.0f || u > 1.0f) {
		return false;
	}

	// Prepare to test V parameter
	vec3 qvec = tvec.Cross(tri1);

	// Calculate V parameter and test bounds
	float v = ray_dir.Dot(qvec) * inv_det;
	if (v < 0.0f || u + v > 1.0f) {
		return false;
	}

	// Calculate t, ray intersects triangle
	float t = tri2.Dot(qvec) * inv_det;

	// Calculate intersection point and test ray length and direction
	out.x = ray_ori.x + ray_dir.x * t;
	out.y = ray_ori.y + ray_dir.y * t;
	out.z = ray_ori.z + ray_dir.z * t;

	vec3 vec = out - ray_ori;
	if (vec.Dot(ray_dir) < 0 ||
		vec.Length() > ray_dir.Length()) {
		return false;
	}

	return true;
}

inline
bool is_ray_intersect_aabb(const vec3& ray_ori, const vec3& ray_dir,
						   const vec3& aabb_min, const vec3& aabb_max)
{
	// SLAB based optimized ray/AABB intersection routine
	// Idea taken from http://ompf.org/ray/

	float l1 = (aabb_min.x - ray_ori.x) / ray_dir.x;
	float l2 = (aabb_max.x - ray_ori.x) / ray_dir.x;
	float lmin = std::min(l1, l2);
	float lmax = std::max(l1, l2);

	l1 = (aabb_min.y - ray_ori.y) / ray_dir.y;
	l2 = (aabb_max.y - ray_ori.y) / ray_dir.y;
	lmin = std::max(std::min(l1, l2), lmin);
	lmax = std::min(std::max(l1, l2), lmax);

	l1 = (aabb_min.z - ray_ori.z) / ray_dir.z;
	l2 = (aabb_max.z - ray_ori.z) / ray_dir.z;
	lmin = std::max(std::min(l1, l2), lmin);
	lmax = std::min(std::max(l1, l2), lmax);

	if ((lmax >= 0.0f) & (lmax >= lmin)) {
		// Consider length
		vec3 ray_dst(ray_ori.x + ray_dir.x , ray_ori.y + ray_dir.y , ray_ori.z + ray_dir.z),
			 ray_min(std::min(ray_dst.x, ray_ori.x), std::min(ray_dst.y, ray_ori.y), std::min(ray_dst.z, ray_ori.z)),
			 ray_max(std::max(ray_dst.x, ray_ori.x), std::max(ray_dst.y, ray_ori.y), std::max(ray_dst.z, ray_ori.z));
		return
			(ray_min.x < aabb_max.x) && (ray_max.x > aabb_min.x) &&
			(ray_min.y < aabb_max.y) && (ray_max.y > aabb_min.y) &&
			(ray_min.z < aabb_max.z) && (ray_max.z > aabb_min.z);
	} else {
		return false;
	}
}

}

#endif // _SPATIAL_MATH_TEST_INL_<commit_msg>fix compile warning<commit_after>#ifndef _SPATIAL_MATH_TEST_INL_
#define _SPATIAL_MATH_TEST_INL_

//#include "SM_Calc.h"
#include "sm_const.h"

#include <float.h>

#include <algorithm>

namespace sm
{

inline
bool is_between(float bound0, float bound1, float test)
{
	if (bound0 < bound1) {
		return test < bound1 + FLT_EPSILON && test > bound0 - FLT_EPSILON;
	} else {
		return test < bound0 + FLT_EPSILON && test > bound1 - FLT_EPSILON;
	}
}

inline
bool is_point_at_line_left(const vec2& v, const vec2& s, const vec2& e)
{
	return (v.y - s.y) * (e.x - s.x) - (v.x - s.x) * (e.y - s.y) > FLT_EPSILON;
}

inline
bool is_point_in_rect(const vec2& v, const rect& r)
{
	return v.x > r.xmin && v.x < r.xmax
		&& v.y > r.ymin && v.y < r.ymax;
}

inline
bool is_point_in_area(const vec2& v, const std::vector<vec2>& area)
{
	bool odd_nodes = false;
	for (int i = 0, n = area.size(), j = n - 1; i < n; ++i)
	{
		if (((area[i].y < v.y && area[j].y >= v.y) ||
			 (area[j].y < v.y && area[i].y >= v.y)) &&
			(area[i].x <= v.x || area[j].x <= v.x))
		{
			odd_nodes ^= (area[i].x + (v.y - area[i].y) / (area[j].y - area[i].y) * (area[j].x - area[i].x) < v.x);
		}
		j = i;
	}
	return odd_nodes;
}

inline
bool is_point_in_circle(const vec2& v, const vec2& center, float radius)
{
	return (v - center).LengthSquared() < radius * radius;
}

inline
bool is_point_in_convex(const vec2& pos, const std::vector<vec2>& convex)
{
	if (convex.size() < 3) {
		return false;
	}

	int count = 0;
	for (int i = 0, n = convex.size(); i < n; ++i)
	{
		vec2 s = convex[i],
			     e = i == convex.size() - 1 ? convex[0] : convex[i + 1];
		if (is_point_at_line_left(pos, s, e)) {
			++count;
		}
	}
	return count == convex.size() || count == 0;
}

inline
bool is_point_intersect_polyline(const vec2& point, const std::vector<vec2>& polyline)
{
	rect r(point, SM_LARGE_EPSILON, SM_LARGE_EPSILON);
	return is_rect_intersect_polyline(r, polyline, true);
}

inline
bool is_segment_intersect_segment(const vec2& s0, const vec2& e0, const vec2& s1, const vec2& e1)
{
	return is_point_at_line_left(s0, s1, e1) != is_point_at_line_left(e0, s1, e1)
		&& is_point_at_line_left(s1, s0, e0) != is_point_at_line_left(e1, s0, e0);
}

inline
bool is_rect_contain_point(const rect& r, const vec2& v)
{
	return v.x >= r.xmin && v.x <= r.xmax
		&& v.y >= r.ymin && v.y <= r.ymax;
}

inline
bool is_rect_contain_rect(const rect& r0, const rect& r1)
{
	return r1.xmin >= r0.xmin && r1.xmax <= r0.xmax
		&& r1.ymin >= r0.ymin && r1.ymax <= r0.ymax;
}

inline
bool is_rect_intersect_rect(const rect& r0, const rect& r1)
{
	return !(r0.xmin >= r1.xmax || r0.xmax <= r1.xmin || r0.ymin >= r1.ymax || r0.ymax <= r1.ymin);
}

inline
bool is_rect_intersect_polyline(const rect& r, const std::vector<vec2>& poly, bool loop)
{
	if (poly.size() < 2) return false;

	for (size_t i = 0, n = poly.size() - 1; i < n; ++i)
	{
		if (is_rect_intersect_segment(r, poly[i], poly[i+1]))
			return true;
	}

	if (loop && is_rect_intersect_segment(r, poly[poly.size() - 1], poly[0]))
		return true;

	return false;
}

inline
bool is_rect_intersect_polygon(const rect& rect, const std::vector<vec2>& poly)
{
	if (poly.size() < 3) {
		return false;
	}

	if (is_point_in_area(rect.Center(), poly) || is_point_in_rect(poly[0], rect)) {
		return true;
	}

	std::vector<vec2> poly2;
	poly2.push_back(vec2(rect.xmin, rect.ymin));
	poly2.push_back(vec2(rect.xmax, rect.ymin));
	poly2.push_back(vec2(rect.xmax, rect.ymax));
	poly2.push_back(vec2(rect.xmin, rect.ymax));

	return is_polygon_intersect_polygon(poly, poly2);
}

inline
bool is_ray_intersect_triangle(const vec3& ray_ori, const vec3& ray_dir,
							   const vec3& tri0, const vec3& tri1,
							   const vec3& tri2, vec3& out)
{
		// Idea: Tomas Moeller and Ben Trumbore
	// in Fast, Minimum Storage Ray/Triangle Intersection

	// Find vectors for two edges sharing vert0
	vec3 edge1 = tri1 - tri0,
		 edge2 = tri2 - tri0;

	// Begin calculating determinant - also used to calculate U parameter
	vec3 pvec = ray_dir.Cross(edge2);

	// If determinant is near zero, ray lies in sm_plane of triangle
	float det = edge1.Dot(pvec);

	// *** Culling branch ***
	/*if (det < FLT_EPSILON)
		return NULL;

	// Calculate distance from vert0 to ray origin
	struct sm_vec3 tvec;
	sm_vec3_vector(&tvec, rayOrig, &vert0);

	// Calculate U parameter and test bounds
	float u = sm_vec3_dot(&tvec, &pvec);
	if (u < 0 || u > det)
		return NULL;

	// Prepare to test V parameter
	struct sm_vec3 qvec;
	sm_vec3_cross(&qvec, &tvec, &edge1);

	// Calculate V parameter and test bounds
	float v = sm_vec3_dot(rayDir, &qvec);
	if (v < 0 || u + v > det)
		return NULL;

	// Calculate t, scale parameters, ray intersects triangle
	float t = sm_vec3_dot(&edge2, &qvec) / det;*/

	// *** Non-culling branch ***
	if (det > -FLT_EPSILON && det < FLT_EPSILON) {
		return false;
	}
	float inv_det = 1.0f / det;

	// Calculate distance from vert0 to ray origin
	vec3 tvec = ray_ori - tri0;

	// Calculate U parameter and test bounds
	float u = tvec.Dot(pvec) * inv_det;
	if (u < 0.0f || u > 1.0f) {
		return false;
	}

	// Prepare to test V parameter
	vec3 qvec = tvec.Cross(tri1);

	// Calculate V parameter and test bounds
	float v = ray_dir.Dot(qvec) * inv_det;
	if (v < 0.0f || u + v > 1.0f) {
		return false;
	}

	// Calculate t, ray intersects triangle
	float t = tri2.Dot(qvec) * inv_det;

	// Calculate intersection point and test ray length and direction
	out.x = ray_ori.x + ray_dir.x * t;
	out.y = ray_ori.y + ray_dir.y * t;
	out.z = ray_ori.z + ray_dir.z * t;

	vec3 vec = out - ray_ori;
	if (vec.Dot(ray_dir) < 0 ||
		vec.Length() > ray_dir.Length()) {
		return false;
	}

	return true;
}

inline
bool is_ray_intersect_aabb(const vec3& ray_ori, const vec3& ray_dir,
						   const vec3& aabb_min, const vec3& aabb_max)
{
	// SLAB based optimized ray/AABB intersection routine
	// Idea taken from http://ompf.org/ray/

	float l1 = (aabb_min.x - ray_ori.x) / ray_dir.x;
	float l2 = (aabb_max.x - ray_ori.x) / ray_dir.x;
	float lmin = std::min(l1, l2);
	float lmax = std::max(l1, l2);

	l1 = (aabb_min.y - ray_ori.y) / ray_dir.y;
	l2 = (aabb_max.y - ray_ori.y) / ray_dir.y;
	lmin = std::max(std::min(l1, l2), lmin);
	lmax = std::min(std::max(l1, l2), lmax);

	l1 = (aabb_min.z - ray_ori.z) / ray_dir.z;
	l2 = (aabb_max.z - ray_ori.z) / ray_dir.z;
	lmin = std::max(std::min(l1, l2), lmin);
	lmax = std::min(std::max(l1, l2), lmax);

	if ((lmax >= 0.0f) & (lmax >= lmin)) {
		// Consider length
		vec3 ray_dst(ray_ori.x + ray_dir.x , ray_ori.y + ray_dir.y , ray_ori.z + ray_dir.z),
			 ray_min(std::min(ray_dst.x, ray_ori.x), std::min(ray_dst.y, ray_ori.y), std::min(ray_dst.z, ray_ori.z)),
			 ray_max(std::max(ray_dst.x, ray_ori.x), std::max(ray_dst.y, ray_ori.y), std::max(ray_dst.z, ray_ori.z));
		return
			(ray_min.x < aabb_max.x) && (ray_max.x > aabb_min.x) &&
			(ray_min.y < aabb_max.y) && (ray_max.y > aabb_min.y) &&
			(ray_min.z < aabb_max.z) && (ray_max.z > aabb_min.z);
	} else {
		return false;
	}
}

}

#endif // _SPATIAL_MATH_TEST_INL_<|endoftext|>


<commit_before>#include "Strategy.h"

void CPUBase::copy_to(const LabelData *in, cl::Context *, cl::Program *,
                      cl::CommandQueue *) {
  l = *in;
}

LabelData CPUBase::copy_from() { return std::move(l); }

void CPUOnePass::execute() {
  size_t nr = 2;
  for (size_t y = 0; y < l.height; ++y) {
    for (size_t x = 0; x < l.width; ++x) {
      if (l.data[l.width * y + x] == 1) {
        mark_explore(x, y, &l, 1, nr);
        ++nr;
      }
    }
  }
}

void GPUBase::copy_to(const LabelData *l, cl::Context *c, cl::Program *p,
                      cl::CommandQueue *q) {
  queue = q;
  program = p;
  width = l->width;
  height = l->height;

  cl_int err;
  auto size = width * height * sizeof(LABELTYPE);
  buf = new cl::Buffer(*c, CL_MEM_READ_WRITE, size, nullptr, &err);
  CHECKERR

  /**
   * TODO: check if blocking read does this correctly itself
   */
  cl::Event event;
  err = queue->enqueueWriteBuffer(*buf, CL_FALSE, 0, size, l->data, 0, &event);
  event.wait();
}

void GPUNeighbourPropagation::execute() {
  cl_int err;

  cl::Kernel kernel(*program, "label_with_id", &err);
  CHECKERR

  err = kernel.setArg(0, *buf);
  CHECKERR
  err = kernel.setArg(1, (cl_int)width);
  CHECKERR

  cl::Event event;
  err = queue->enqueueNDRangeKernel(kernel, cl::NullRange,
                                    cl::NDRange(width, height),
                                    cl::NDRange(1, 1), NULL, &event);
  CHECKERR

  event.wait();
}

LabelData GPUBase::copy_from() {
  LabelData ret(width, height);

  auto size = width * height * sizeof(LABELTYPE);
  queue->enqueueReadBuffer(*buf, CL_TRUE, 0, size, ret.data);

  delete buf;

  return ret;
}
<commit_msg>Blocking write seems to actually write, and not defer till later<commit_after>#include "Strategy.h"

void CPUBase::copy_to(const LabelData *in, cl::Context *, cl::Program *,
                      cl::CommandQueue *) {
  l = *in;
}

LabelData CPUBase::copy_from() { return std::move(l); }

void CPUOnePass::execute() {
  size_t nr = 2;
  for (size_t y = 0; y < l.height; ++y) {
    for (size_t x = 0; x < l.width; ++x) {
      if (l.data[l.width * y + x] == 1) {
        mark_explore(x, y, &l, 1, nr);
        ++nr;
      }
    }
  }
}

void GPUBase::copy_to(const LabelData *l, cl::Context *c, cl::Program *p,
                      cl::CommandQueue *q) {
  queue = q;
  program = p;
  width = l->width;
  height = l->height;

  cl_int err;
  auto size = width * height * sizeof(LABELTYPE);
  buf = new cl::Buffer(*c, CL_MEM_READ_WRITE, size, nullptr, &err);
  CHECKERR

  err = queue->enqueueWriteBuffer(*buf, CL_TRUE, 0, size, l->data);
}

void GPUNeighbourPropagation::execute() {
  cl_int err;

  cl::Kernel kernel(*program, "label_with_id", &err);
  CHECKERR

  err = kernel.setArg(0, *buf);
  CHECKERR
  err = kernel.setArg(1, (cl_int)width);
  CHECKERR

  cl::Event event;
  err = queue->enqueueNDRangeKernel(kernel, cl::NullRange,
                                    cl::NDRange(width, height),
                                    cl::NDRange(1, 1), NULL, &event);
  CHECKERR

  event.wait();
}

LabelData GPUBase::copy_from() {
  LabelData ret(width, height);

  auto size = width * height * sizeof(LABELTYPE);
  queue->enqueueReadBuffer(*buf, CL_TRUE, 0, size, ret.data);

  delete buf;

  return ret;
}
<|endoftext|>


<commit_before>#include "state_comp.hpp"

#include <core/ecs/serializer_impl.hpp>

namespace mo {
namespace sys {
namespace state {

	using namespace unit_literals;

	struct State_comp::Persisted_state {
		bool delete_dead;

		Persisted_state(const State_comp& c)
			: delete_dead(c._delete_dead) {}
	};

	sf2_structDef(State_comp::Persisted_state,
		sf2_member(delete_dead)
	)

	void State_comp::load(ecs::Entity_state& state) {
		auto s = state.read_to(Persisted_state{*this});
		_delete_dead = s.delete_dead;
	}
	void State_comp::store(ecs::Entity_state& state) {
		state.write_from(Persisted_state{*this});
	}

	namespace {
		Time required_time_for(Entity_state state)noexcept {
			switch(state) {
				case Entity_state::idle:			return  0_s;
				case Entity_state::walking:			return  0.1_s;
				case Entity_state::attacking_melee:	return  0.1_s;
				case Entity_state::attacking_range:	return  0.1_s;
				case Entity_state::interacting:		return  0.1_s;
				case Entity_state::taking:			return  0.5_s;
				case Entity_state::change_weapon:	return  0.5_s;
				case Entity_state::damaged:			return  0.1_s;
				case Entity_state::healed:			return  0.1_s;
				case Entity_state::dead:			return  0_s;
				case Entity_state::dying:			return  2.0_s;
				case Entity_state::resurrected:		return  0.1_s;
			}

			INVARIANT(false, "Unexpected state "<<static_cast<int>(state));
		}
		bool is_background(Entity_state state)noexcept {
			switch(state) {
				case Entity_state::idle:			return true;
				case Entity_state::walking:			return true;
				case Entity_state::attacking_melee:	return false;
				case Entity_state::attacking_range:	return false;
				case Entity_state::interacting:		return false;
				case Entity_state::taking:			return true;
				case Entity_state::change_weapon:	return true;
				case Entity_state::damaged:			return false;
				case Entity_state::healed:			return false;
				case Entity_state::dead:			return true;
				case Entity_state::dying:			return false;
				case Entity_state::resurrected:		return false;
			}

			INVARIANT(false, "Unexpected state "<<static_cast<int>(state));
		}
		int priority(Entity_state state)noexcept {
			switch(state) {
				case Entity_state::idle:			return 0;
				case Entity_state::walking:			return 1;
				case Entity_state::attacking_melee:	return 3;
				case Entity_state::attacking_range:	return 3;
				case Entity_state::interacting:		return 2;
				case Entity_state::taking:			return 2;
				case Entity_state::change_weapon:	return 3;
				case Entity_state::damaged:			return 4;
				case Entity_state::healed:			return 2;
				case Entity_state::dead:			return 10;
				case Entity_state::dying:			return 10;
				case Entity_state::resurrected:		return 5;
			}

			INVARIANT(false, "Unexpected state "<<static_cast<int>(state));
		}

		Entity_state get_next(Entity_state state)noexcept {
			switch(state) {
				case Entity_state::dying:
					return Entity_state::dead;

				default:
					return Entity_state::idle;
			}
		}
	}

	void State_comp::state(Entity_state s, float magnitude)noexcept {
		INVARIANT(magnitude>=0 && magnitude<=1, "magnitude is out of range: "+util::to_string(magnitude));

		auto& cstate = _state_primary.left>0_s ? _state_primary : _state_background;

		if(priority(cstate.s)>priority(s) && cstate.left>0_s)
			return;

		auto& state = is_background(s) ? _state_background : _state_primary;

		state.s=s;
		state.magnitude=magnitude;
		state.left=required_time_for(s);
	}

	auto State_comp::update(Time dt)noexcept -> util::maybe<State_data&> {
		if(_state_background.left>0_s) {
			_state_background.left-=dt;

			// time is up, lets idle
			if(_state_background.left<=0_s) {
				state(get_next(_state_background.s));
			}
		}

		if(_state_primary.left>0_s) {
			_state_primary.left-=dt;
			if(_state_primary.left<=0_s) {
				state(get_next(_state_primary.s));
			}
		}

		auto& cstate = _state_primary.left>0_s ? _state_primary : _state_background;

		if(cstate!=_state_last) {
			_state_last = cstate;
			return util::justPtr(&cstate);
		}

		return util::nothing();
	}

}
}
}
<commit_msg>fixed undead zombies (& others)<commit_after>#include "state_comp.hpp"

#include <core/ecs/serializer_impl.hpp>

namespace mo {
namespace sys {
namespace state {

	using namespace unit_literals;

	struct State_comp::Persisted_state {
		bool delete_dead;

		Persisted_state(const State_comp& c)
			: delete_dead(c._delete_dead) {}
	};

	sf2_structDef(State_comp::Persisted_state,
		sf2_member(delete_dead)
	)

	void State_comp::load(ecs::Entity_state& state) {
		auto s = state.read_to(Persisted_state{*this});
		_delete_dead = s.delete_dead;
	}
	void State_comp::store(ecs::Entity_state& state) {
		state.write_from(Persisted_state{*this});
	}

	namespace {
		Time required_time_for(Entity_state state)noexcept {
			switch(state) {
				case Entity_state::idle:			return  0_s;
				case Entity_state::walking:			return  0.1_s;
				case Entity_state::attacking_melee:	return  0.1_s;
				case Entity_state::attacking_range:	return  0.1_s;
				case Entity_state::interacting:		return  0.1_s;
				case Entity_state::taking:			return  0.5_s;
				case Entity_state::change_weapon:	return  0.5_s;
				case Entity_state::damaged:			return  0.1_s;
				case Entity_state::healed:			return  0.1_s;
				case Entity_state::dead:			return  0_s;
				case Entity_state::dying:			return  2.0_s;
				case Entity_state::resurrected:		return  0.1_s;
			}

			INVARIANT(false, "Unexpected state "<<static_cast<int>(state));
		}
		bool is_background(Entity_state state)noexcept {
			switch(state) {
				case Entity_state::idle:			return true;
				case Entity_state::walking:			return true;
				case Entity_state::attacking_melee:	return false;
				case Entity_state::attacking_range:	return false;
				case Entity_state::interacting:		return false;
				case Entity_state::taking:			return true;
				case Entity_state::change_weapon:	return true;
				case Entity_state::damaged:			return false;
				case Entity_state::healed:			return false;
				case Entity_state::dead:			return true;
				case Entity_state::dying:			return false;
				case Entity_state::resurrected:		return false;
			}

			INVARIANT(false, "Unexpected state "<<static_cast<int>(state));
		}
		int priority(Entity_state state)noexcept {
			switch(state) {
				case Entity_state::idle:			return 0;
				case Entity_state::walking:			return 1;
				case Entity_state::attacking_melee:	return 3;
				case Entity_state::attacking_range:	return 3;
				case Entity_state::interacting:		return 2;
				case Entity_state::taking:			return 2;
				case Entity_state::change_weapon:	return 3;
				case Entity_state::damaged:			return 4;
				case Entity_state::healed:			return 2;
				case Entity_state::dead:			return 10;
				case Entity_state::dying:			return 10;
				case Entity_state::resurrected:		return 5;
			}

			INVARIANT(false, "Unexpected state "<<static_cast<int>(state));
		}

		Entity_state get_next(Entity_state state)noexcept {
			switch(state) {
				case Entity_state::dying:
					return Entity_state::dead;

				case Entity_state::dead:
					return Entity_state::dead;

				default:
					return Entity_state::idle;
			}
		}
	}

	void State_comp::state(Entity_state s, float magnitude)noexcept {
		INVARIANT(magnitude>=0 && magnitude<=1, "magnitude is out of range: "+util::to_string(magnitude));

		auto& cstate = _state_primary.left>0_s ? _state_primary : _state_background;

		if(priority(cstate.s)>priority(s) && cstate.left>0_s)
			return;

		auto& state = is_background(s) ? _state_background : _state_primary;

		state.s=s;
		state.magnitude=magnitude;
		state.left=required_time_for(s);
	}

	auto State_comp::update(Time dt)noexcept -> util::maybe<State_data&> {
		if(_state_background.left>0_s) {
			_state_background.left-=dt;

			// time is up, lets idle
			if(_state_background.left<=0_s) {
				state(get_next(_state_background.s));
			}
		}

		if(_state_primary.left>0_s) {
			_state_primary.left-=dt;
			if(_state_primary.left<=0_s) {
				state(get_next(_state_primary.s));
			}
		}

		auto& cstate = _state_primary.left>0_s ? _state_primary : _state_background;

		if(cstate!=_state_last) {
			_state_last = cstate;
			return util::justPtr(&cstate);
		}

		return util::nothing();
	}

}
}
}
<|endoftext|>


<commit_before>#include <uv.h>
#include <dbt.h>
#include <iostream>
#include <iomanip>
#include <atlstr.h>

// Include Windows headers
#include <windows.h>
#include <stdio.h>
#include <tchar.h>
#include <strsafe.h>
#include <Setupapi.h>

#include "detection.h"
#include "deviceList.h"

using namespace std;

/**********************************
 * Local defines
 **********************************/
#define VID_TAG "VID_"
#define PID_TAG "PID_"

#define LIBRARY_NAME    ("setupapi.dll")

#define DllImport   __declspec( dllimport )

/**********************************
 * Local typedefs
 **********************************/

/**********************************
 * Local Variables
 **********************************/
GUID GUID_DEVINTERFACE_USB_DEVICE = { 0xA5DCBF10L, 0x6530, 0x11D2, 0x90, 0x1F, 0x00, 0xC0, 0x4F, 0xB9, 0x51, 0xED};

HWND handle;
DWORD threadId;
HANDLE threadHandle;

HANDLE deviceChangedEvent;

ListResultItem_t* currentDevice;
bool isAdded;
bool isRunning = false;

HINSTANCE hinstLib;

typedef BOOL        (WINAPI  *_SetupDiEnumDeviceInfo) (HDEVINFO DeviceInfoSet, DWORD MemberIndex, PSP_DEVINFO_DATA DeviceInfoData);
typedef HDEVINFO    (WINAPI  *_SetupDiGetClassDevs) (const GUID *ClassGuid, PCTSTR Enumerator, HWND hwndParent, DWORD Flags);
typedef BOOL        (WINAPI  *_SetupDiDestroyDeviceInfoList) (HDEVINFO DeviceInfoSet);
typedef BOOL        (WINAPI  *_SetupDiGetDeviceInstanceId) (HDEVINFO DeviceInfoSet, PSP_DEVINFO_DATA DeviceInfoData, PTSTR DeviceInstanceId, DWORD DeviceInstanceIdSize, PDWORD RequiredSize);
typedef BOOL        (WINAPI  *_SetupDiGetDeviceRegistryProperty) (HDEVINFO DeviceInfoSet, PSP_DEVINFO_DATA DeviceInfoData, DWORD Property, PDWORD PropertyRegDataType, PBYTE PropertyBuffer, DWORD PropertyBufferSize, PDWORD RequiredSize);

_SetupDiEnumDeviceInfo DllSetupDiEnumDeviceInfo;
_SetupDiGetClassDevs DllSetupDiGetClassDevs;
_SetupDiDestroyDeviceInfoList DllSetupDiDestroyDeviceInfoList;
_SetupDiGetDeviceInstanceId DllSetupDiGetDeviceInstanceId;
_SetupDiGetDeviceRegistryProperty DllSetupDiGetDeviceRegistryProperty;

/**********************************
 * Local Helper Functions protoypes
 **********************************/
void UpdateDevice(PDEV_BROADCAST_DEVICEINTERFACE pDevInf, WPARAM wParam, DeviceState_t state);
DWORD WINAPI ListenerThread( LPVOID lpParam );

void BuildInitialDeviceList();

void NotifyAsync(uv_work_t* req);
void NotifyFinished(uv_work_t* req);

void ExtractDeviceInfo(HDEVINFO hDevInfo, SP_DEVINFO_DATA* pspDevInfoData, TCHAR* buf, DWORD buffSize, ListResultItem_t* resultItem);

/**********************************
 * Public Functions
 **********************************/
void NotifyAsync(uv_work_t* req)
{
    WaitForSingleObject(deviceChangedEvent, INFINITE);
}

void NotifyFinished(uv_work_t* req)
{
    if (isRunning)
    {
        if(isAdded)
        {
            NotifyAdded(currentDevice);
        }
        else
        {
            NotifyRemoved(currentDevice);
            delete currentDevice;
        }

        uv_queue_work(uv_default_loop(), req, NotifyAsync, (uv_after_work_cb)NotifyFinished);
    }
}

void LoadFunctions()
{

    bool success = true;

    hinstLib = LoadLibrary(LIBRARY_NAME);
    success = (hinstLib == NULL) ? false : true;

    if (hinstLib != NULL)
    {
        DllSetupDiEnumDeviceInfo = (_SetupDiEnumDeviceInfo) GetProcAddress(hinstLib, "SetupDiEnumDeviceInfo");
        success = (DllSetupDiEnumDeviceInfo == NULL) ? false : true;

        DllSetupDiGetClassDevs = (_SetupDiGetClassDevs) GetProcAddress(hinstLib, "SetupDiGetClassDevsA");
        success = (DllSetupDiGetClassDevs == NULL) ? false : true;

        DllSetupDiDestroyDeviceInfoList = (_SetupDiDestroyDeviceInfoList) GetProcAddress(hinstLib, "SetupDiDestroyDeviceInfoList");
        success = (DllSetupDiDestroyDeviceInfoList == NULL) ? false : true;

        DllSetupDiGetDeviceInstanceId = (_SetupDiGetDeviceInstanceId) GetProcAddress(hinstLib, "SetupDiGetDeviceInstanceIdA");
        success = (DllSetupDiGetDeviceInstanceId == NULL) ? false : true;

        DllSetupDiGetDeviceRegistryProperty = (_SetupDiGetDeviceRegistryProperty) GetProcAddress(hinstLib, "SetupDiGetDeviceRegistryPropertyA");
        success = (DllSetupDiGetDeviceRegistryProperty == NULL) ? false : true;
    }

    if(!success)
    {
        printf("Could not load library functions from dll -> abort (Check if %s is available)\r\n", LIBRARY_NAME);
        exit(1);
    }
}

void Start()
{
    isRunning = true;
    threadHandle = CreateThread(
        NULL,                   // default security attributes
        0,                      // use default stack size
        ListenerThread,         // thread function name
        NULL,                   // argument to thread function
        0,                      // use default creation flags
        &threadId);

    uv_work_t* req = new uv_work_t();
    uv_queue_work(uv_default_loop(), req, NotifyAsync, (uv_after_work_cb)NotifyFinished);
}

void Stop()
{
    isRunning = false;
    SetEvent(deviceChangedEvent);

    // ExitThread(threadHandle);
}

void InitDetection()
{

    LoadFunctions();

    deviceChangedEvent = CreateEvent(NULL, false /* auto-reset event */, false /* non-signalled state */, "");

    BuildInitialDeviceList();

    Start();
}

void EIO_Find(uv_work_t* req)
{

    ListBaton* data = static_cast<ListBaton*>(req->data);

    CreateFilteredList(&data->results, data->vid, data->pid);
}

/**********************************
 * Local Functions
 **********************************/
void ToUpper(char * buf)
{
    char* c = buf;
    while (*c != '\0')
    {
        *c = toupper((unsigned char)*c);
        c++;
    }
}

void extractVidPid(char * buf, ListResultItem_t * item)
{
    if(buf == NULL)
    {
        return;
    }

    ToUpper(buf);

    char* string;
    char* temp;
    char* pidStr, *vidStr;
    int vid = 0;
    int pid = 0;

    string = new char[strlen(buf) + 1];
    memcpy(string, buf, strlen(buf) + 1);

    vidStr = strstr(string, VID_TAG);
    pidStr = strstr(string, PID_TAG);

    if(vidStr != NULL)
    {
        temp = (char*) (vidStr + strlen(VID_TAG));
        temp[4] = '\0';
        vid = strtol (temp, NULL, 16);
    }

    if(pidStr != NULL)
    {
        temp = (char*) (pidStr + strlen(PID_TAG));
        temp[4] = '\0';
        pid = strtol (temp, NULL, 16);
    }
    item->vendorId = vid;
    item->productId = pid;

    delete string;
}

LRESULT CALLBACK DetectCallback(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
    if (msg == WM_DEVICECHANGE)
    {
        if ( DBT_DEVICEARRIVAL == wParam || DBT_DEVICEREMOVECOMPLETE == wParam )
        {
            PDEV_BROADCAST_HDR pHdr = (PDEV_BROADCAST_HDR)lParam;
            PDEV_BROADCAST_DEVICEINTERFACE pDevInf;

            if(pHdr->dbch_devicetype == DBT_DEVTYP_DEVICEINTERFACE)
            {
                pDevInf = (PDEV_BROADCAST_DEVICEINTERFACE)pHdr;
                UpdateDevice(pDevInf, wParam, (DBT_DEVICEARRIVAL == wParam) ? DeviceState_Connect : DeviceState_Disconnect);
            }
        }
    }

    return 1;
}

DWORD WINAPI ListenerThread( LPVOID lpParam )
{

    const char *className = "ListnerThread";

    WNDCLASSA wincl = {0};
    wincl.hInstance = GetModuleHandle(0);
    wincl.lpszClassName = className;
    wincl.lpfnWndProc = DetectCallback;

    if (!RegisterClassA(&wincl))
    {
        DWORD le = GetLastError();
        printf("RegisterClassA() failed [Error: %x]\r\n", le);
        return 1;
    }//if

    HWND hwnd = CreateWindowExA(WS_EX_TOPMOST, className, className, 0, 0, 0, 0, 0, NULL, 0, 0, 0);
    if (!hwnd)
    {
        DWORD le = GetLastError();
        printf("CreateWindowExA() failed [Error: %x]\r\n", le);
        return 1;
    }//if

    DEV_BROADCAST_DEVICEINTERFACE_A notifyFilter = {0};
    notifyFilter.dbcc_size = sizeof(notifyFilter);
    notifyFilter.dbcc_devicetype = DBT_DEVTYP_DEVICEINTERFACE;
    notifyFilter.dbcc_classguid = GUID_DEVINTERFACE_USB_DEVICE;

    HDEVNOTIFY hDevNotify = RegisterDeviceNotificationA(hwnd, &notifyFilter, DEVICE_NOTIFY_WINDOW_HANDLE);
    if (!hDevNotify)
    {
        DWORD le = GetLastError();
        printf("RegisterDeviceNotificationA() failed [Error: %x]\r\n", le);
        return 1;
    }//if

    MSG msg;
    for (;;) // ctrl-c to exit ;)
    {
        BOOL bRet = GetMessage(&msg, hwnd, 0, 0);
        if ((bRet == 0) || (bRet == -1))
        {
            break;
        }

        TranslateMessage(&msg);
        DispatchMessage(&msg);
    }//while

    return 0;
}

void BuildInitialDeviceList()
{
    TCHAR buf[MAX_PATH];
    DWORD dwFlag = (DIGCF_ALLCLASSES | DIGCF_PRESENT);
    HDEVINFO hDevInfo = DllSetupDiGetClassDevs(NULL, "USB", NULL, dwFlag);

    if( INVALID_HANDLE_VALUE == hDevInfo )
    {
        return;
    }

    SP_DEVINFO_DATA* pspDevInfoData = (SP_DEVINFO_DATA*) HeapAlloc(GetProcessHeap(), 0, sizeof(SP_DEVINFO_DATA));
    pspDevInfoData->cbSize = sizeof(SP_DEVINFO_DATA);
    for(int i=0; DllSetupDiEnumDeviceInfo(hDevInfo, i, pspDevInfoData); i++)
    {
        DWORD nSize=0 ;

        if ( !DllSetupDiGetDeviceInstanceId(hDevInfo, pspDevInfoData, buf, sizeof(buf), &nSize) )
        {
            break;
        }

        DeviceItem_t* item = new DeviceItem_t();
        item->deviceState = DeviceState_Connect;

        DWORD DataT;
        DllSetupDiGetDeviceRegistryProperty(hDevInfo, pspDevInfoData, SPDRP_HARDWAREID, &DataT, (PBYTE)buf, MAX_PATH, &nSize);

        AddItemToList(buf, item);
        ExtractDeviceInfo(hDevInfo, pspDevInfoData, buf, MAX_PATH, &item->deviceParams);
    }

    if ( pspDevInfoData )
    {
        HeapFree(GetProcessHeap(), 0, pspDevInfoData);
    }

    if(hDevInfo)
    {
        DllSetupDiDestroyDeviceInfoList(hDevInfo);
    }
}

void ExtractDeviceInfo(HDEVINFO hDevInfo, SP_DEVINFO_DATA* pspDevInfoData, TCHAR* buf, DWORD buffSize, ListResultItem_t* resultItem)
{
    DWORD DataT;
    DWORD nSize;
    static int dummy = 1;

    resultItem->locationId = 0;
    resultItem->deviceAddress = dummy++;

    // device found
    if ( DllSetupDiGetDeviceRegistryProperty(hDevInfo, pspDevInfoData, SPDRP_FRIENDLYNAME, &DataT, (PBYTE)buf, buffSize, &nSize) )
    {
        resultItem->deviceName = buf;
    }
    else if ( DllSetupDiGetDeviceRegistryProperty(hDevInfo, pspDevInfoData, SPDRP_DEVICEDESC, &DataT, (PBYTE)buf, buffSize, &nSize) )
    {
        resultItem->deviceName = buf;
    }
    if ( DllSetupDiGetDeviceRegistryProperty(hDevInfo, pspDevInfoData, SPDRP_MFG, &DataT, (PBYTE)buf, buffSize, &nSize) )
    {
        resultItem->manufacturer = buf;
    }
    if ( DllSetupDiGetDeviceRegistryProperty(hDevInfo, pspDevInfoData, SPDRP_HARDWAREID, &DataT, (PBYTE)buf, buffSize, &nSize) )
    {
        // Use this to extract VID / PID
        extractVidPid(buf, resultItem);
    }
}

void UpdateDevice(PDEV_BROADCAST_DEVICEINTERFACE pDevInf, WPARAM wParam, DeviceState_t state)
{
    // dbcc_name:
    // \\?\USB#Vid_04e8&Pid_503b#0002F9A9828E0F06#{a5dcbf10-6530-11d2-901f-00c04fb951ed}
    // convert to
    // USB\Vid_04e8&Pid_503b\0002F9A9828E0F06
    CString szDevId = pDevInf->dbcc_name+4;
    int idx = szDevId.ReverseFind(_T('#'));

    szDevId.Truncate(idx);
    szDevId.Replace(_T('#'), _T('\\'));
    szDevId.MakeUpper();

    CString szClass;
    idx = szDevId.Find(_T('\\'));
    szClass = szDevId.Left(idx);

    // if we are adding device, we only need present devices
    // otherwise, we need all devices
    DWORD dwFlag = DBT_DEVICEARRIVAL != wParam ? DIGCF_ALLCLASSES : (DIGCF_ALLCLASSES | DIGCF_PRESENT);
    HDEVINFO hDevInfo = DllSetupDiGetClassDevs(NULL, szClass, NULL, dwFlag);
    if( INVALID_HANDLE_VALUE == hDevInfo )
    {
        return;
    }

    SP_DEVINFO_DATA* pspDevInfoData = (SP_DEVINFO_DATA*) HeapAlloc(GetProcessHeap(), 0, sizeof(SP_DEVINFO_DATA));
    pspDevInfoData->cbSize = sizeof(SP_DEVINFO_DATA);
    for(int i=0; DllSetupDiEnumDeviceInfo(hDevInfo, i, pspDevInfoData); i++)
    {
        DWORD nSize=0 ;
        TCHAR buf[MAX_PATH];

        if ( !DllSetupDiGetDeviceInstanceId(hDevInfo, pspDevInfoData, buf, sizeof(buf), &nSize) )
        {
            break;
        }

        if ( szDevId == buf )
        {
            DWORD DataT;
            DWORD nSize;
            DllSetupDiGetDeviceRegistryProperty(hDevInfo, pspDevInfoData, SPDRP_HARDWAREID, &DataT, (PBYTE)buf, MAX_PATH, &nSize);

            if(state == DeviceState_Connect)
            {
                DeviceItem_t* device = new DeviceItem_t();

                AddItemToList(buf, device);
                ExtractDeviceInfo(hDevInfo, pspDevInfoData, buf, MAX_PATH, &device->deviceParams);

                currentDevice = &device->deviceParams;
                isAdded = true;
            }
            else
            {
                ListResultItem_t* item = NULL;
                if(IsItemAlreadyStored(buf))
                {
                    DeviceItem_t* deviceItem = GetItemFromList(buf);
                    if(deviceItem)
                    {
                        item = CopyElement(&deviceItem->deviceParams);
                    }
                    RemoveItemFromList(deviceItem);
                    delete deviceItem;
                }

                if(item == NULL)
                {
                    item = new ListResultItem_t();
                    ExtractDeviceInfo(hDevInfo, pspDevInfoData, buf, MAX_PATH, item);
                }
                currentDevice = item;
                isAdded = false;
            }

            break;
        }
    }

    if ( pspDevInfoData )
    {
        HeapFree(GetProcessHeap(), 0, pspDevInfoData);
    }

    if(hDevInfo)
    {
        DllSetupDiDestroyDeviceInfoList(hDevInfo);
    }

    SetEvent(deviceChangedEvent);
}<commit_msg>unique listener thread name<commit_after>#include <uv.h>
#include <dbt.h>
#include <iostream>
#include <iomanip>
#include <atlstr.h>

// Include Windows headers
#include <windows.h>
#include <stdio.h>
#include <tchar.h>
#include <strsafe.h>
#include <Setupapi.h>

#include "detection.h"
#include "deviceList.h"

using namespace std;

/**********************************
 * Local defines
 **********************************/
#define VID_TAG "VID_"
#define PID_TAG "PID_"

#define LIBRARY_NAME    ("setupapi.dll")

#define DllImport   __declspec( dllimport )

/**********************************
 * Local typedefs
 **********************************/

/**********************************
 * Local Variables
 **********************************/
GUID GUID_DEVINTERFACE_USB_DEVICE = { 0xA5DCBF10L, 0x6530, 0x11D2, 0x90, 0x1F, 0x00, 0xC0, 0x4F, 0xB9, 0x51, 0xED};

HWND handle;
DWORD threadId;
HANDLE threadHandle;

HANDLE deviceChangedEvent;

ListResultItem_t* currentDevice;
bool isAdded;
bool isRunning = false;

HINSTANCE hinstLib;

typedef BOOL        (WINAPI  *_SetupDiEnumDeviceInfo) (HDEVINFO DeviceInfoSet, DWORD MemberIndex, PSP_DEVINFO_DATA DeviceInfoData);
typedef HDEVINFO    (WINAPI  *_SetupDiGetClassDevs) (const GUID *ClassGuid, PCTSTR Enumerator, HWND hwndParent, DWORD Flags);
typedef BOOL        (WINAPI  *_SetupDiDestroyDeviceInfoList) (HDEVINFO DeviceInfoSet);
typedef BOOL        (WINAPI  *_SetupDiGetDeviceInstanceId) (HDEVINFO DeviceInfoSet, PSP_DEVINFO_DATA DeviceInfoData, PTSTR DeviceInstanceId, DWORD DeviceInstanceIdSize, PDWORD RequiredSize);
typedef BOOL        (WINAPI  *_SetupDiGetDeviceRegistryProperty) (HDEVINFO DeviceInfoSet, PSP_DEVINFO_DATA DeviceInfoData, DWORD Property, PDWORD PropertyRegDataType, PBYTE PropertyBuffer, DWORD PropertyBufferSize, PDWORD RequiredSize);

_SetupDiEnumDeviceInfo DllSetupDiEnumDeviceInfo;
_SetupDiGetClassDevs DllSetupDiGetClassDevs;
_SetupDiDestroyDeviceInfoList DllSetupDiDestroyDeviceInfoList;
_SetupDiGetDeviceInstanceId DllSetupDiGetDeviceInstanceId;
_SetupDiGetDeviceRegistryProperty DllSetupDiGetDeviceRegistryProperty;

/**********************************
 * Local Helper Functions protoypes
 **********************************/
void UpdateDevice(PDEV_BROADCAST_DEVICEINTERFACE pDevInf, WPARAM wParam, DeviceState_t state);
DWORD WINAPI ListenerThread( LPVOID lpParam );

void BuildInitialDeviceList();

void NotifyAsync(uv_work_t* req);
void NotifyFinished(uv_work_t* req);

void ExtractDeviceInfo(HDEVINFO hDevInfo, SP_DEVINFO_DATA* pspDevInfoData, TCHAR* buf, DWORD buffSize, ListResultItem_t* resultItem);

/**********************************
 * Public Functions
 **********************************/
void NotifyAsync(uv_work_t* req)
{
    WaitForSingleObject(deviceChangedEvent, INFINITE);
}

void NotifyFinished(uv_work_t* req)
{
    if (isRunning)
    {
        if(isAdded)
        {
            NotifyAdded(currentDevice);
        }
        else
        {
            NotifyRemoved(currentDevice);
            delete currentDevice;
        }

        uv_queue_work(uv_default_loop(), req, NotifyAsync, (uv_after_work_cb)NotifyFinished);
    }
}

void LoadFunctions()
{

    bool success = true;

    hinstLib = LoadLibrary(LIBRARY_NAME);
    success = (hinstLib == NULL) ? false : true;

    if (hinstLib != NULL)
    {
        DllSetupDiEnumDeviceInfo = (_SetupDiEnumDeviceInfo) GetProcAddress(hinstLib, "SetupDiEnumDeviceInfo");
        success = (DllSetupDiEnumDeviceInfo == NULL) ? false : true;

        DllSetupDiGetClassDevs = (_SetupDiGetClassDevs) GetProcAddress(hinstLib, "SetupDiGetClassDevsA");
        success = (DllSetupDiGetClassDevs == NULL) ? false : true;

        DllSetupDiDestroyDeviceInfoList = (_SetupDiDestroyDeviceInfoList) GetProcAddress(hinstLib, "SetupDiDestroyDeviceInfoList");
        success = (DllSetupDiDestroyDeviceInfoList == NULL) ? false : true;

        DllSetupDiGetDeviceInstanceId = (_SetupDiGetDeviceInstanceId) GetProcAddress(hinstLib, "SetupDiGetDeviceInstanceIdA");
        success = (DllSetupDiGetDeviceInstanceId == NULL) ? false : true;

        DllSetupDiGetDeviceRegistryProperty = (_SetupDiGetDeviceRegistryProperty) GetProcAddress(hinstLib, "SetupDiGetDeviceRegistryPropertyA");
        success = (DllSetupDiGetDeviceRegistryProperty == NULL) ? false : true;
    }

    if(!success)
    {
        printf("Could not load library functions from dll -> abort (Check if %s is available)\r\n", LIBRARY_NAME);
        exit(1);
    }
}

void Start()
{
    isRunning = true;
    threadHandle = CreateThread(
        NULL,                   // default security attributes
        0,                      // use default stack size
        ListenerThread,         // thread function name
        NULL,                   // argument to thread function
        0,                      // use default creation flags
        &threadId);

    uv_work_t* req = new uv_work_t();
    uv_queue_work(uv_default_loop(), req, NotifyAsync, (uv_after_work_cb)NotifyFinished);
}

void Stop()
{
    isRunning = false;
    SetEvent(deviceChangedEvent);

    // ExitThread(threadHandle);
}

void InitDetection()
{

    LoadFunctions();

    deviceChangedEvent = CreateEvent(NULL, false /* auto-reset event */, false /* non-signalled state */, "");

    BuildInitialDeviceList();

    Start();
}

void EIO_Find(uv_work_t* req)
{

    ListBaton* data = static_cast<ListBaton*>(req->data);

    CreateFilteredList(&data->results, data->vid, data->pid);
}

/**********************************
 * Local Functions
 **********************************/
void ToUpper(char * buf)
{
    char* c = buf;
    while (*c != '\0')
    {
        *c = toupper((unsigned char)*c);
        c++;
    }
}

void extractVidPid(char * buf, ListResultItem_t * item)
{
    if(buf == NULL)
    {
        return;
    }

    ToUpper(buf);

    char* string;
    char* temp;
    char* pidStr, *vidStr;
    int vid = 0;
    int pid = 0;

    string = new char[strlen(buf) + 1];
    memcpy(string, buf, strlen(buf) + 1);

    vidStr = strstr(string, VID_TAG);
    pidStr = strstr(string, PID_TAG);

    if(vidStr != NULL)
    {
        temp = (char*) (vidStr + strlen(VID_TAG));
        temp[4] = '\0';
        vid = strtol (temp, NULL, 16);
    }

    if(pidStr != NULL)
    {
        temp = (char*) (pidStr + strlen(PID_TAG));
        temp[4] = '\0';
        pid = strtol (temp, NULL, 16);
    }
    item->vendorId = vid;
    item->productId = pid;

    delete string;
}

LRESULT CALLBACK DetectCallback(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
    if (msg == WM_DEVICECHANGE)
    {
        if ( DBT_DEVICEARRIVAL == wParam || DBT_DEVICEREMOVECOMPLETE == wParam )
        {
            PDEV_BROADCAST_HDR pHdr = (PDEV_BROADCAST_HDR)lParam;
            PDEV_BROADCAST_DEVICEINTERFACE pDevInf;

            if(pHdr->dbch_devicetype == DBT_DEVTYP_DEVICEINTERFACE)
            {
                pDevInf = (PDEV_BROADCAST_DEVICEINTERFACE)pHdr;
                UpdateDevice(pDevInf, wParam, (DBT_DEVICEARRIVAL == wParam) ? DeviceState_Connect : DeviceState_Disconnect);
            }
        }
    }

    return 1;
}

DWORD WINAPI ListenerThread( LPVOID lpParam )
{

    const char *className = "ListnerThreadUsbDetection";

    WNDCLASSA wincl = {0};
    wincl.hInstance = GetModuleHandle(0);
    wincl.lpszClassName = className;
    wincl.lpfnWndProc = DetectCallback;

    if (!RegisterClassA(&wincl))
    {
        DWORD le = GetLastError();
        printf("RegisterClassA() failed [Error: %x]\r\n", le);
        return 1;
    }//if

    HWND hwnd = CreateWindowExA(WS_EX_TOPMOST, className, className, 0, 0, 0, 0, 0, NULL, 0, 0, 0);
    if (!hwnd)
    {
        DWORD le = GetLastError();
        printf("CreateWindowExA() failed [Error: %x]\r\n", le);
        return 1;
    }//if

    DEV_BROADCAST_DEVICEINTERFACE_A notifyFilter = {0};
    notifyFilter.dbcc_size = sizeof(notifyFilter);
    notifyFilter.dbcc_devicetype = DBT_DEVTYP_DEVICEINTERFACE;
    notifyFilter.dbcc_classguid = GUID_DEVINTERFACE_USB_DEVICE;

    HDEVNOTIFY hDevNotify = RegisterDeviceNotificationA(hwnd, &notifyFilter, DEVICE_NOTIFY_WINDOW_HANDLE);
    if (!hDevNotify)
    {
        DWORD le = GetLastError();
        printf("RegisterDeviceNotificationA() failed [Error: %x]\r\n", le);
        return 1;
    }//if

    MSG msg;
    for (;;) // ctrl-c to exit ;)
    {
        BOOL bRet = GetMessage(&msg, hwnd, 0, 0);
        if ((bRet == 0) || (bRet == -1))
        {
            break;
        }

        TranslateMessage(&msg);
        DispatchMessage(&msg);
    }//while

    return 0;
}

void BuildInitialDeviceList()
{
    TCHAR buf[MAX_PATH];
    DWORD dwFlag = (DIGCF_ALLCLASSES | DIGCF_PRESENT);
    HDEVINFO hDevInfo = DllSetupDiGetClassDevs(NULL, "USB", NULL, dwFlag);

    if( INVALID_HANDLE_VALUE == hDevInfo )
    {
        return;
    }

    SP_DEVINFO_DATA* pspDevInfoData = (SP_DEVINFO_DATA*) HeapAlloc(GetProcessHeap(), 0, sizeof(SP_DEVINFO_DATA));
    pspDevInfoData->cbSize = sizeof(SP_DEVINFO_DATA);
    for(int i=0; DllSetupDiEnumDeviceInfo(hDevInfo, i, pspDevInfoData); i++)
    {
        DWORD nSize=0 ;

        if ( !DllSetupDiGetDeviceInstanceId(hDevInfo, pspDevInfoData, buf, sizeof(buf), &nSize) )
        {
            break;
        }

        DeviceItem_t* item = new DeviceItem_t();
        item->deviceState = DeviceState_Connect;

        DWORD DataT;
        DllSetupDiGetDeviceRegistryProperty(hDevInfo, pspDevInfoData, SPDRP_HARDWAREID, &DataT, (PBYTE)buf, MAX_PATH, &nSize);

        AddItemToList(buf, item);
        ExtractDeviceInfo(hDevInfo, pspDevInfoData, buf, MAX_PATH, &item->deviceParams);
    }

    if ( pspDevInfoData )
    {
        HeapFree(GetProcessHeap(), 0, pspDevInfoData);
    }

    if(hDevInfo)
    {
        DllSetupDiDestroyDeviceInfoList(hDevInfo);
    }
}

void ExtractDeviceInfo(HDEVINFO hDevInfo, SP_DEVINFO_DATA* pspDevInfoData, TCHAR* buf, DWORD buffSize, ListResultItem_t* resultItem)
{
    DWORD DataT;
    DWORD nSize;
    static int dummy = 1;

    resultItem->locationId = 0;
    resultItem->deviceAddress = dummy++;

    // device found
    if ( DllSetupDiGetDeviceRegistryProperty(hDevInfo, pspDevInfoData, SPDRP_FRIENDLYNAME, &DataT, (PBYTE)buf, buffSize, &nSize) )
    {
        resultItem->deviceName = buf;
    }
    else if ( DllSetupDiGetDeviceRegistryProperty(hDevInfo, pspDevInfoData, SPDRP_DEVICEDESC, &DataT, (PBYTE)buf, buffSize, &nSize) )
    {
        resultItem->deviceName = buf;
    }
    if ( DllSetupDiGetDeviceRegistryProperty(hDevInfo, pspDevInfoData, SPDRP_MFG, &DataT, (PBYTE)buf, buffSize, &nSize) )
    {
        resultItem->manufacturer = buf;
    }
    if ( DllSetupDiGetDeviceRegistryProperty(hDevInfo, pspDevInfoData, SPDRP_HARDWAREID, &DataT, (PBYTE)buf, buffSize, &nSize) )
    {
        // Use this to extract VID / PID
        extractVidPid(buf, resultItem);
    }
}

void UpdateDevice(PDEV_BROADCAST_DEVICEINTERFACE pDevInf, WPARAM wParam, DeviceState_t state)
{
    // dbcc_name:
    // \\?\USB#Vid_04e8&Pid_503b#0002F9A9828E0F06#{a5dcbf10-6530-11d2-901f-00c04fb951ed}
    // convert to
    // USB\Vid_04e8&Pid_503b\0002F9A9828E0F06
    CString szDevId = pDevInf->dbcc_name+4;
    int idx = szDevId.ReverseFind(_T('#'));

    szDevId.Truncate(idx);
    szDevId.Replace(_T('#'), _T('\\'));
    szDevId.MakeUpper();

    CString szClass;
    idx = szDevId.Find(_T('\\'));
    szClass = szDevId.Left(idx);

    // if we are adding device, we only need present devices
    // otherwise, we need all devices
    DWORD dwFlag = DBT_DEVICEARRIVAL != wParam ? DIGCF_ALLCLASSES : (DIGCF_ALLCLASSES | DIGCF_PRESENT);
    HDEVINFO hDevInfo = DllSetupDiGetClassDevs(NULL, szClass, NULL, dwFlag);
    if( INVALID_HANDLE_VALUE == hDevInfo )
    {
        return;
    }

    SP_DEVINFO_DATA* pspDevInfoData = (SP_DEVINFO_DATA*) HeapAlloc(GetProcessHeap(), 0, sizeof(SP_DEVINFO_DATA));
    pspDevInfoData->cbSize = sizeof(SP_DEVINFO_DATA);
    for(int i=0; DllSetupDiEnumDeviceInfo(hDevInfo, i, pspDevInfoData); i++)
    {
        DWORD nSize=0 ;
        TCHAR buf[MAX_PATH];

        if ( !DllSetupDiGetDeviceInstanceId(hDevInfo, pspDevInfoData, buf, sizeof(buf), &nSize) )
        {
            break;
        }

        if ( szDevId == buf )
        {
            DWORD DataT;
            DWORD nSize;
            DllSetupDiGetDeviceRegistryProperty(hDevInfo, pspDevInfoData, SPDRP_HARDWAREID, &DataT, (PBYTE)buf, MAX_PATH, &nSize);

            if(state == DeviceState_Connect)
            {
                DeviceItem_t* device = new DeviceItem_t();

                AddItemToList(buf, device);
                ExtractDeviceInfo(hDevInfo, pspDevInfoData, buf, MAX_PATH, &device->deviceParams);

                currentDevice = &device->deviceParams;
                isAdded = true;
            }
            else
            {
                ListResultItem_t* item = NULL;
                if(IsItemAlreadyStored(buf))
                {
                    DeviceItem_t* deviceItem = GetItemFromList(buf);
                    if(deviceItem)
                    {
                        item = CopyElement(&deviceItem->deviceParams);
                    }
                    RemoveItemFromList(deviceItem);
                    delete deviceItem;
                }

                if(item == NULL)
                {
                    item = new ListResultItem_t();
                    ExtractDeviceInfo(hDevInfo, pspDevInfoData, buf, MAX_PATH, item);
                }
                currentDevice = item;
                isAdded = false;
            }

            break;
        }
    }

    if ( pspDevInfoData )
    {
        HeapFree(GetProcessHeap(), 0, pspDevInfoData);
    }

    if(hDevInfo)
    {
        DllSetupDiDestroyDeviceInfoList(hDevInfo);
    }

    SetEvent(deviceChangedEvent);
}<|endoftext|>


<commit_before>/*
 * Copyright 2012 Steven Gribble
 *
 *  This file is part of the UW CSE 333 course project sequence
 *  (333proj).
 *
 *  333proj is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation, either version 3 of the License, or
 *  (at your option) any later version.
 *
 *  333proj 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 General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with 333proj.  If not, see <http://www.gnu.org/licenses/>.
 */

#include <stdio.h>
#include <string>
#include <cstdlib>
#include <iostream>
#include <sstream>
#include <memory>

extern "C" {
  #include "libhw2/fileparser.h"
}

#include "./HttpUtils.h"
#include "./FileReader.h"

namespace hw4 {

bool FileReader::ReadFile(std::string *str) {
  std::string fullfile = basedir_ + "/" + fname_;

  // Read the file into memory, and store the file contents in the
  // output parameter "str."  Be careful to handle binary data
  // correctly; i.e., you probably want to use the two-argument
  // constructor to std::string (the one that includes a length as a
  // second argument).
  //
  // You might find ::ReadFile() from HW2's fileparser.h useful
  // here.  Be careful, though; remember that it uses malloc to
  // allocate memory, so you'll need to use free() to free up that
  // memory.  Alternatively, you can use a unique_ptr with a malloc/free
  // deleter to automatically manage this for you; see the comment in
  // HttpUtils.h above the MallocDeleter class for details.

  // MISSING:

  HWSize_t size;
  std::unique_ptr<char, MallocDeleter<char> > ptr { ::ReadFile(fullfile.c_str(), &size) };
  *str = std::string(ptr.get(), size);

  return true;
}

}  // namespace hw4
<commit_msg>CSE333: FileReader done<commit_after>/*
 * Copyright 2012 Steven Gribble
 *
 *  This file is part of the UW CSE 333 course project sequence
 *  (333proj).
 *
 *  333proj is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation, either version 3 of the License, or
 *  (at your option) any later version.
 *
 *  333proj 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 General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with 333proj.  If not, see <http://www.gnu.org/licenses/>.
 */

#include <stdio.h>
#include <string>
#include <cstdlib>
#include <iostream>
#include <sstream>
#include <memory>

extern "C" {
  #include "libhw2/fileparser.h"
}

#include "./HttpUtils.h"
#include "./FileReader.h"

namespace hw4 {

bool FileReader::ReadFile(std::string *str) {
  std::string fullfile = basedir_ + "/" + fname_;

  // Read the file into memory, and store the file contents in the
  // output parameter "str."  Be careful to handle binary data
  // correctly; i.e., you probably want to use the two-argument
  // constructor to std::string (the one that includes a length as a
  // second argument).
  //
  // You might find ::ReadFile() from HW2's fileparser.h useful
  // here.  Be careful, though; remember that it uses malloc to
  // allocate memory, so you'll need to use free() to free up that
  // memory.  Alternatively, you can use a unique_ptr with a malloc/free
  // deleter to automatically manage this for you; see the comment in
  // HttpUtils.h above the MallocDeleter class for details.

  // MISSING:

  HWSize_t size;
  std::unique_ptr<char, MallocDeleter<char> > ptr { ::ReadFile(fullfile.c_str(), &size) };

  if (ptr.get() == nullptr) return false;

  *str = std::string(ptr.get(), size);
  return true;
}

}  // namespace hw4
<|endoftext|>


<commit_before>/*************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2008 by Sun Microsystems, Inc.
 *
 * OpenOffice.org - a multi-platform office productivity suite
 *
 * $RCSfile: atkwindow.cxx,v $
 * $Revision: 1.7 $
 *
 * This file is part of OpenOffice.org.
 *
 * OpenOffice.org is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License version 3
 * only, as published by the Free Software Foundation.
 *
 * OpenOffice.org 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 version 3 for more details
 * (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU Lesser General Public License
 * version 3 along with OpenOffice.org.  If not, see
 * <http://www.openoffice.org/license.html>
 * for a copy of the LGPLv3 License.
 *
 ************************************************************************/

// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_vcl.hxx"

#include <plugins/gtk/gtkframe.hxx>
#include <vcl/window.hxx>

#include "atkwindow.hxx"
#include "atkregistry.hxx"

using namespace ::com::sun::star::accessibility;
using namespace ::com::sun::star::uno;

extern "C" {

static void (* window_real_initialize) (AtkObject *obj, gpointer data) = NULL;
static void (* window_real_finalize) (GObject *obj) = NULL;
static G_CONST_RETURN gchar* (* window_real_get_name) (AtkObject *accessible) = NULL;

static gint
ooo_window_wrapper_clear_focus(gpointer)
{
    atk_focus_tracker_notify( NULL );
    return FALSE;
}

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

static gboolean
ooo_window_wrapper_real_focus_gtk (GtkWidget *, GdkEventFocus *)
{
    g_idle_add( ooo_window_wrapper_clear_focus, NULL );
    return FALSE;
}

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

static void
ooo_window_wrapper_real_initialize(AtkObject *obj, gpointer data)
{
    window_real_initialize(obj, data);

    GtkSalFrame *pFrame = GtkSalFrame::getFromWindow( GTK_WINDOW( data ) );
    if( pFrame )
    {
        Window *pWindow = pFrame->GetWindow();
        if( pWindow )
        {
            Reference< XAccessible > xAccessible( pWindow->GetAccessible(true) );
            ooo_wrapper_registry_add( xAccessible, obj );
            g_object_set_data( G_OBJECT(obj), "ooo:registry-key", xAccessible.get() );
        }
    }

    /* GetAtkRole returns ATK_ROLE_INVALID for all non VCL windows, i.e.
     * native Gtk+ file picker etc.
     */
    AtkRole newRole = GtkSalFrame::GetAtkRole( GTK_WINDOW( data ) );
    if( newRole != ATK_ROLE_INVALID )
        obj->role = newRole;

    if( obj->role == ATK_ROLE_TOOL_TIP )
    {
        /* HACK: Avoid endless loop when get_name is called from
         * gail_window_new() context, which leads to the code path
         * showing up in wrapper_factory_create_accessible with no
         * accessible assigned to the GtkWindow yet.
         */
        g_object_set_data( G_OBJECT( data ), "ooo:tooltip-accessible", obj );
    }

    g_signal_connect_after( GTK_WIDGET( data ), "focus-out-event",
                            G_CALLBACK (ooo_window_wrapper_real_focus_gtk),
                            NULL);
}

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

static G_CONST_RETURN gchar*
ooo_window_wrapper_real_get_name(AtkObject *accessible)
{
    G_CONST_RETURN gchar* name = NULL;

    if( accessible->role == ATK_ROLE_TOOL_TIP )
    {
        AtkObject *child = atk_object_ref_accessible_child(accessible, 0);
        if( child )
        {
            name = atk_object_get_name(child);
            g_object_unref(child);
        }

        return name;
    }

    return window_real_get_name(accessible);
}

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

static void
ooo_window_wrapper_real_finalize (GObject *obj)
{
    ooo_wrapper_registry_remove( (XAccessible *) g_object_get_data( obj, "ooo:registry-key" ));
    window_real_finalize( obj );
}

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

static void
ooo_window_wrapper_class_init (AtkObjectClass *klass, gpointer)
{
    AtkObjectClass *atk_class;
    GObjectClass *gobject_class;
    gpointer data;

    /*
     * Patch the gobject vtable of GailWindow to refer to our instance of
     * "initialize" and "get_name".
     */

    data = g_type_class_peek_parent( klass );
    atk_class = ATK_OBJECT_CLASS (data);

    window_real_initialize = atk_class->initialize;
    atk_class->initialize = ooo_window_wrapper_real_initialize;

    window_real_get_name = atk_class->get_name;
    atk_class->get_name = ooo_window_wrapper_real_get_name;

    gobject_class = G_OBJECT_CLASS (data);

    window_real_finalize = gobject_class->finalize;
    gobject_class->finalize = ooo_window_wrapper_real_finalize;
}

} // extern "C"

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

GType
ooo_window_wrapper_get_type (void)
{
    static GType type = 0;

    if (!type)
    {
        GType parent_type = g_type_from_name( "GailWindow" );

        if( ! parent_type )
        {
            g_warning( "Unknown type: GailWindow" );
            parent_type = ATK_TYPE_OBJECT;
        }

        GTypeQuery type_query;
        g_type_query( parent_type, &type_query );

        static const GTypeInfo typeInfo =
        {
            type_query.class_size,
            (GBaseInitFunc) NULL,
            (GBaseFinalizeFunc) NULL,
            (GClassInitFunc) ooo_window_wrapper_class_init,
            (GClassFinalizeFunc) NULL,
            NULL,
            type_query.instance_size,
            0,
            (GInstanceInitFunc) NULL,
            NULL
        } ;

        type = g_type_register_static (parent_type, "OOoWindowAtkObject", &typeInfo, (GTypeFlags)0) ;
    }

    return type;
}

void restore_gail_window_vtable (void)
{
    AtkObjectClass *atk_class;
    gpointer data;

    GType type = g_type_from_name( "GailWindow" );

    if( type == G_TYPE_INVALID )
        return;

    data = g_type_class_peek( type );
    atk_class = ATK_OBJECT_CLASS (data);

    atk_class->initialize = window_real_initialize;
    atk_class->get_name = window_real_get_name;
}

<commit_msg>INTEGRATION: CWS uaa06 (1.7.20); FILE MERGED 2008/05/16 05:20:58 obr 1.7.20.2: #i87426# replace FILLER role with option pane again for dialogs and alerts 2008/05/08 12:39:09 obr 1.7.20.1: #i87426# repaired broken a11y hierarchy of a number of dialogs<commit_after>/*************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2008 by Sun Microsystems, Inc.
 *
 * OpenOffice.org - a multi-platform office productivity suite
 *
 * $RCSfile: atkwindow.cxx,v $
 * $Revision: 1.8 $
 *
 * This file is part of OpenOffice.org.
 *
 * OpenOffice.org is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License version 3
 * only, as published by the Free Software Foundation.
 *
 * OpenOffice.org 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 version 3 for more details
 * (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU Lesser General Public License
 * version 3 along with OpenOffice.org.  If not, see
 * <http://www.openoffice.org/license.html>
 * for a copy of the LGPLv3 License.
 *
 ************************************************************************/

// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_vcl.hxx"

#include <plugins/gtk/gtkframe.hxx>
#include <vcl/window.hxx>

#include "atkwindow.hxx"
#include "atkwrapper.hxx"
#include "atkregistry.hxx"

#include <com/sun/star/accessibility/AccessibleRole.hpp>

using namespace ::com::sun::star::accessibility;
using namespace ::com::sun::star::uno;

extern "C" {

static void (* window_real_initialize) (AtkObject *obj, gpointer data) = NULL;
static void (* window_real_finalize) (GObject *obj) = NULL;
static G_CONST_RETURN gchar* (* window_real_get_name) (AtkObject *accessible) = NULL;

static void
init_from_window( AtkObject *accessible, Window *pWindow )
{
    static AtkRole aDefaultRole = ATK_ROLE_INVALID;

    // Special role for sub-menu and combo-box popups that are exposed directly
    // by their parents already.
    if( aDefaultRole == ATK_ROLE_INVALID )
        aDefaultRole = atk_role_register( "redundant object" );

    AtkRole role = aDefaultRole;

    // Determine the appropriate role for the GtkWindow
    switch( pWindow->GetAccessibleRole() )
    {
        case AccessibleRole::ALERT:
            role = ATK_ROLE_ALERT;
            break;

        case AccessibleRole::DIALOG:
            role = ATK_ROLE_DIALOG;
            break;

        case AccessibleRole::FRAME:
            role = ATK_ROLE_FRAME;
            break;

        /* Ignore window objects for sub-menus, combo- and list boxes,
         *  which are exposed as children of their parents.
         */
        case AccessibleRole::WINDOW:
        {
            USHORT type = WINDOW_WINDOW;
            bool parentIsMenuFloatingWindow = false;

            Window *pParent = pWindow->GetParent();
            if( pParent ) {
                type = pParent->GetType();
                parentIsMenuFloatingWindow = ( TRUE == pParent->IsMenuFloatingWindow() );
            }

            if( (WINDOW_LISTBOX != type) && (WINDOW_COMBOBOX != type) &&
                (WINDOW_MENUBARWINDOW != type) && ! parentIsMenuFloatingWindow )
            {
                role = ATK_ROLE_WINDOW;
            }
        }
        break;

        default:
        {
            Window *pChild = pWindow->GetChild( 0 );
            if( pChild )
            {
                if( WINDOW_HELPTEXTWINDOW == pChild->GetType() )
                {
                    role = ATK_ROLE_TOOL_TIP;
                    pChild->SetAccessibleRole( AccessibleRole::LABEL );
                    accessible->name = g_strdup( rtl::OUStringToOString( pChild->GetText(), RTL_TEXTENCODING_UTF8 ).getStr() );
                }
            }
            break;
        }
    }

    accessible->role = role;
}

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

static gint
ooo_window_wrapper_clear_focus(gpointer)
{
    atk_focus_tracker_notify( NULL );
    return FALSE;
}

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

static gboolean
ooo_window_wrapper_real_focus_gtk (GtkWidget *, GdkEventFocus *)
{
    g_idle_add( ooo_window_wrapper_clear_focus, NULL );
    return FALSE;
}

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

static void
ooo_window_wrapper_real_initialize(AtkObject *obj, gpointer data)
{
    window_real_initialize(obj, data);

    GtkSalFrame *pFrame = GtkSalFrame::getFromWindow( GTK_WINDOW( data ) );
    if( pFrame )
    {
        Window *pWindow = pFrame->GetWindow();
        if( pWindow )
        {
            init_from_window( obj, pWindow );

            Reference< XAccessible > xAccessible( pWindow->GetAccessible(true) );

            /* We need the wrapper object for the top-level XAccessible to be
             * in the wrapper registry when atk traverses the hierachy up on
             * focus events
             */
            if( WINDOW_BORDERWINDOW == pWindow->GetType() )
            {
                ooo_wrapper_registry_add( xAccessible, obj );
                g_object_set_data( G_OBJECT(obj), "ooo:atk-wrapper-key", xAccessible.get() );
            }
            else
            {
                AtkObject *child = atk_object_wrapper_new( xAccessible, obj );
                child->role = ATK_ROLE_FILLER;
                if( (ATK_ROLE_DIALOG == obj->role) || (ATK_ROLE_ALERT == obj->role) )
                    child->role = ATK_ROLE_OPTION_PANE;
                ooo_wrapper_registry_add( xAccessible, child );
            }
        }
    }

    g_signal_connect_after( GTK_WIDGET( data ), "focus-out-event",
                            G_CALLBACK (ooo_window_wrapper_real_focus_gtk),
                            NULL);
}

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

static void
ooo_window_wrapper_real_finalize (GObject *obj)
{
    ooo_wrapper_registry_remove( (XAccessible *) g_object_get_data( obj, "ooo:atk-wrapper-key" ));
    window_real_finalize( obj );
}

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

static void
ooo_window_wrapper_class_init (AtkObjectClass *klass, gpointer)
{
    AtkObjectClass *atk_class;
    GObjectClass *gobject_class;
    gpointer data;

    /*
     * Patch the gobject vtable of GailWindow to refer to our instance of
     * "initialize" and "get_name".
     */

    data = g_type_class_peek_parent( klass );
    atk_class = ATK_OBJECT_CLASS (data);

    window_real_initialize = atk_class->initialize;
    atk_class->initialize = ooo_window_wrapper_real_initialize;

    gobject_class = G_OBJECT_CLASS (data);

    window_real_finalize = gobject_class->finalize;
    gobject_class->finalize = ooo_window_wrapper_real_finalize;
}

} // extern "C"

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

GType
ooo_window_wrapper_get_type (void)
{
    static GType type = 0;

    if (!type)
    {
        GType parent_type = g_type_from_name( "GailWindow" );

        if( ! parent_type )
        {
            g_warning( "Unknown type: GailWindow" );
            parent_type = ATK_TYPE_OBJECT;
        }

        GTypeQuery type_query;
        g_type_query( parent_type, &type_query );

        static const GTypeInfo typeInfo =
        {
            type_query.class_size,
            (GBaseInitFunc) NULL,
            (GBaseFinalizeFunc) NULL,
            (GClassInitFunc) ooo_window_wrapper_class_init,
            (GClassFinalizeFunc) NULL,
            NULL,
            type_query.instance_size,
            0,
            (GInstanceInitFunc) NULL,
            NULL
        } ;

        type = g_type_register_static (parent_type, "OOoWindowAtkObject", &typeInfo, (GTypeFlags)0) ;
    }

    return type;
}

void restore_gail_window_vtable (void)
{
    AtkObjectClass *atk_class;
    gpointer data;

    GType type = g_type_from_name( "GailWindow" );

    if( type == G_TYPE_INVALID )
        return;

    data = g_type_class_peek( type );
    atk_class = ATK_OBJECT_CLASS (data);

    atk_class->initialize = window_real_initialize;
    atk_class->get_name = window_real_get_name;
}

<|endoftext|>