<commit_before>#include "net/resolve.h"
#include "base/logging.h"

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <string>

#ifdef _WIN32
#include <WinSock2.h>
#include <Ws2tcpip.h>
#undef min
#undef max
#else
#if defined(__FreeBSD__) || defined(__SYMBIAN32__)
#include <netinet/in.h>
#else
#include <arpa/inet.h>
#endif
#include <netdb.h>
#include <sys/socket.h>
#include <unistd.h>
#endif

namespace net {

void Init()
{
#ifdef _WIN32
	// WSA does its own internal reference counting, no need to keep track of if we inited or not.
	WSADATA wsaData = {0};
	WSAStartup(MAKEWORD(2, 2), &wsaData);
#endif
}

void Shutdown()
{
#ifdef _WIN32
	WSACleanup();
#endif
}

char *DNSResolveTry(const char *host, const char **err)
{
	struct hostent *hent;
	if((hent = gethostbyname(host)) == NULL)
	{
		*err = "Can't get IP";
		return NULL;
	}
	int iplen = 15; //XXX.XXX.XXX.XXX
	char *ip = (char *)malloc(iplen+1);
	memset(ip, 0, iplen+1);
	char *iptoa = inet_ntoa(*(in_addr *)hent->h_addr_list[0]);
	if (iptoa == NULL)
	{
		*err = "Can't resolve host";
		free(ip);
		return NULL;
	}
	strncpy(ip, iptoa, iplen);
	return ip;
}

char *DNSResolve(const char *host)
{
	const char *err;
	char *ip = DNSResolveTry(host, &err);
	if (ip == NULL)
	{
		perror(err);
		exit(1);
	}
	return ip;
}

bool DNSResolve(const std::string &host, const std::string &service, addrinfo **res, std::string &error)
{
	addrinfo hints = {0};
	// TODO: Might be uses to lookup other values.
	hints.ai_socktype = SOCK_STREAM;
#ifdef BLACKBERRY
	hints.ai_flags = 0;
#elif ANDROID
	hints.ai_flags = AI_ADDRCONFIG;
#else
	// AI_V4MAPPED seems to have issues on some platforms, not sure we should include it:
	// http://stackoverflow.com/questions/1408030/what-is-the-purpose-of-the-ai-v4mapped-flag-in-getaddrinfo
	hints.ai_flags = /*AI_V4MAPPED |*/ AI_ADDRCONFIG;
#endif
	hints.ai_protocol = IPPROTO_TCP;

	const char *servicep = service.length() == 0 ? NULL : service.c_str();

	*res = NULL;
	int result = getaddrinfo(host.c_str(), servicep, &hints, res);
	if (result == EAI_AGAIN) {
		// Temporary failure.  Since this already blocks, let's just try once more.
#ifdef _WIN32
		Sleep(1);
#else
		sleep(1);
#endif
		result = getaddrinfo(host.c_str(), servicep, &hints, res);
	}

	if (result != 0) {
#ifdef _WIN32
		error = gai_strerrorA(result);
#else
		error = gai_strerror(result);
#endif
		if (*res != NULL)
			freeaddrinfo(*res);
		*res = NULL;
		return false;
	}

	return true;
}

void DNSResolveFree(addrinfo *res)
{
	if (res != NULL)
		freeaddrinfo(res);
}

int inet_pton(int af, const char* src, void* dst)
{
	if (af == AF_INET)
	{
		unsigned char *ip = (unsigned char *)dst;
		int k = 0, x = 0;
		char ch;
		for (int i = 0; (ch = src[i]) != 0; i++)
		{
			if (ch == '.')
			{
				ip[k++] = x;
				if (k == 4)
					return 0;
				x = 0;
			}
			else if (ch < '0' || ch > '9')
				return 0;
			else
				x = x * 10 + ch - '0';
			if (x > 255)
				return 0;
		}
		ip[k++] = x;
		if (k != 4)
			return 0;
	}
	else if (af == AF_INET6)
	{
		unsigned short* ip = ( unsigned short* )dst;
		int i;
		for (i = 0; i < 8; i++) ip[i] = 0;
		int k = 0;
		unsigned int x = 0;
		char ch;
		int marknum = 0;
		for (i = 0; src[i] != 0; i++)
		{
			if (src[i] == ':')
				marknum++;
		}
		for (i = 0; (ch = src[i]) != 0; i++)
		{
			if (ch == ':')
			{
				x = ((x & 0xFF00) >> 8) | ((x & 0x00FF) << 8);
				ip[k++] = x;
				if (k == 8)
					return 0;
				x = 0;
				if (i > 0 && src[i - 1] == ':')
					k += 7 - marknum;
			}
			else if (ch >= '0' && ch <= '9')
				x = x * 16 + ch - '0';
			else if (ch >= 'a' && ch <= 'f')
				x = x * 16 + ch - 'a' + 10;
			else if (ch >= 'A' && ch <= 'F')
				x = x * 16 + ch - 'A' + 10;
			else
				return 0;
			if (x > 0xFFFF)
				return 0;
		}
		x = ((x & 0xFF00) >> 8) | ((x & 0x00FF) << 8);
		ip[k++] = x;
		if (k != 8)
			return 0;
	}
	return 1;
}

}
<commit_msg>Update Symbian to GCC 4.8.3<commit_after>#include "net/resolve.h"
#include "base/logging.h"

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <string>

#ifdef _WIN32
#include <WinSock2.h>
#include <Ws2tcpip.h>
#undef min
#undef max
#else
#if defined(__FreeBSD__)
#include <netinet/in.h>
#else
#include <arpa/inet.h>
#endif
#include <netdb.h>
#include <sys/socket.h>
#include <unistd.h>
#endif

namespace net {

void Init()
{
#ifdef _WIN32
	// WSA does its own internal reference counting, no need to keep track of if we inited or not.
	WSADATA wsaData = {0};
	WSAStartup(MAKEWORD(2, 2), &wsaData);
#endif
}

void Shutdown()
{
#ifdef _WIN32
	WSACleanup();
#endif
}

char *DNSResolveTry(const char *host, const char **err)
{
	struct hostent *hent;
	if((hent = gethostbyname(host)) == NULL)
	{
		*err = "Can't get IP";
		return NULL;
	}
	int iplen = 15; //XXX.XXX.XXX.XXX
	char *ip = (char *)malloc(iplen+1);
	memset(ip, 0, iplen+1);
	char *iptoa = inet_ntoa(*(in_addr *)hent->h_addr_list[0]);
	if (iptoa == NULL)
	{
		*err = "Can't resolve host";
		free(ip);
		return NULL;
	}
	strncpy(ip, iptoa, iplen);
	return ip;
}

char *DNSResolve(const char *host)
{
	const char *err;
	char *ip = DNSResolveTry(host, &err);
	if (ip == NULL)
	{
		perror(err);
		exit(1);
	}
	return ip;
}

bool DNSResolve(const std::string &host, const std::string &service, addrinfo **res, std::string &error)
{
	addrinfo hints = {0};
	// TODO: Might be uses to lookup other values.
	hints.ai_socktype = SOCK_STREAM;
#ifdef BLACKBERRY
	hints.ai_flags = 0;
#elif ANDROID
	hints.ai_flags = AI_ADDRCONFIG;
#else
	// AI_V4MAPPED seems to have issues on some platforms, not sure we should include it:
	// http://stackoverflow.com/questions/1408030/what-is-the-purpose-of-the-ai-v4mapped-flag-in-getaddrinfo
	hints.ai_flags = /*AI_V4MAPPED |*/ AI_ADDRCONFIG;
#endif
	hints.ai_protocol = IPPROTO_TCP;

	const char *servicep = service.length() == 0 ? NULL : service.c_str();

	*res = NULL;
	int result = getaddrinfo(host.c_str(), servicep, &hints, res);
	if (result == EAI_AGAIN) {
		// Temporary failure.  Since this already blocks, let's just try once more.
#ifdef _WIN32
		Sleep(1);
#else
		sleep(1);
#endif
		result = getaddrinfo(host.c_str(), servicep, &hints, res);
	}

	if (result != 0) {
#ifdef _WIN32
		error = gai_strerrorA(result);
#else
		error = gai_strerror(result);
#endif
		if (*res != NULL)
			freeaddrinfo(*res);
		*res = NULL;
		return false;
	}

	return true;
}

void DNSResolveFree(addrinfo *res)
{
	if (res != NULL)
		freeaddrinfo(res);
}

int inet_pton(int af, const char* src, void* dst)
{
	if (af == AF_INET)
	{
		unsigned char *ip = (unsigned char *)dst;
		int k = 0, x = 0;
		char ch;
		for (int i = 0; (ch = src[i]) != 0; i++)
		{
			if (ch == '.')
			{
				ip[k++] = x;
				if (k == 4)
					return 0;
				x = 0;
			}
			else if (ch < '0' || ch > '9')
				return 0;
			else
				x = x * 10 + ch - '0';
			if (x > 255)
				return 0;
		}
		ip[k++] = x;
		if (k != 4)
			return 0;
	}
	else if (af == AF_INET6)
	{
		unsigned short* ip = ( unsigned short* )dst;
		int i;
		for (i = 0; i < 8; i++) ip[i] = 0;
		int k = 0;
		unsigned int x = 0;
		char ch;
		int marknum = 0;
		for (i = 0; src[i] != 0; i++)
		{
			if (src[i] == ':')
				marknum++;
		}
		for (i = 0; (ch = src[i]) != 0; i++)
		{
			if (ch == ':')
			{
				x = ((x & 0xFF00) >> 8) | ((x & 0x00FF) << 8);
				ip[k++] = x;
				if (k == 8)
					return 0;
				x = 0;
				if (i > 0 && src[i - 1] == ':')
					k += 7 - marknum;
			}
			else if (ch >= '0' && ch <= '9')
				x = x * 16 + ch - '0';
			else if (ch >= 'a' && ch <= 'f')
				x = x * 16 + ch - 'a' + 10;
			else if (ch >= 'A' && ch <= 'F')
				x = x * 16 + ch - 'A' + 10;
			else
				return 0;
			if (x > 0xFFFF)
				return 0;
		}
		x = ((x & 0xFF00) >> 8) | ((x & 0x00FF) << 8);
		ip[k++] = x;
		if (k != 8)
			return 0;
	}
	return 1;
}

}
<|endoftext|>


<commit_before>#include "stdafx.h"
#ifdef _WIN32
#include "OculusInterface.hpp"
#include "AnnLogger.hpp"
#include "AnnException.hpp"

using namespace std;
using namespace OVR;
using namespace Annwvyn;

void OculusInterface::abortOnFailure()
{
	session = {};
	luid = {};
	hmdDesc = {};

	//Notify user
	AnnDebug() << "Error: Cannot create Oculus Session";
	//Debug HMD is now handled by the configuration utility and the runtime.
	AnnDebug() << "Please make sure Oculus Home is installed on your system and "
		"please check if you have correctly plugged HDMI and USB on the Rift and Tracker";

	displayWin32ErrorMessage(L"Error: Cannot create Oculus Session!",
		L"Please make sure Oculus Home is installed on your system\n"
		L"and check HDMI and USB connection to your Rift and Tracker");

	//Cleanup
	ovr_Shutdown();
	//Return an error
	AnnDebug("Unable to get a session from the Oculus Runtime. Closing program and returning 0xDEAD60D error");
	//Stop program
	throw AnnInitializationError((ANN_ERR_CRITIC), "Unable to create an Oculus session");
}

OculusInterface::OculusInterface()
{
	AnnDebug() << "Init Oculus Interface object";
	//Init Oculus Virtual Reality library
	ovr_Initialize(nullptr);

	//Declare this client to the Oculus service
	stringstream clientIentifier;
	clientIentifier << "EngineName: Annwvyn\n";
	clientIentifier << "EngineVersion: " << AnnEngine::getAnnwvynVersion();
	AnnDebug() << "Identifier string sent to the Oculus Service : \n" << clientIentifier.str();
	ovr_IdentifyClient(clientIentifier.str().c_str());

	//Attempt to create OVR session
	if (ovr_Create(&session, &luid) != ovrSuccess)
		abortOnFailure();

	//Fill the hmdDesc structure
	hmdDesc = ovr_GetHmdDesc(session);

	//Print to log all known information about the headset
	customReport();
}

OculusInterface::~OculusInterface()
{
	//Set the performance HUD to Off
	ovr_SetInt(getSession(), "PerfHudMode", ovrPerfHud_Off);

	AnnDebug() << "Shutdown OculusInterface object";
	ovr_Destroy(getSession());
	ovr_Shutdown();
	AnnDebug("LibOVR Shutdown... No longer can communicate with OculusService");
}

void OculusInterface::customReport() const
{
	//Print to the logger a bunch of information
	AnnDebug() << "========================================================";
	AnnDebug() << "OVR version " << ovr_GetVersionString();
	AnnDebug() << "Detected the following Oculus Rift VR Headset :";
	AnnDebug() << "Product name : " << hmdDesc.ProductName;
	AnnDebug() << "Serial number : " << hmdDesc.SerialNumber;
	AnnDebug() << "Manufacturer : " << hmdDesc.Manufacturer;
	AnnDebug() << "Display Resolution : " << hmdDesc.Resolution.w << "x" << hmdDesc.Resolution.h;
	AnnDebug() << "Display refresh rate : " << hmdDesc.DisplayRefreshRate << "Hz";
	AnnDebug() << "Type of HMD identifier : " << hmdDesc.Type;
	AnnDebug() << "Firmware version : " << hmdDesc.FirmwareMajor << "." << hmdDesc.FirmwareMinor;
	AnnDebug() << "========================================================";
}

ovrHmdDesc OculusInterface::getHmdDesc() const
{
	return hmdDesc;
}

ovrSession OculusInterface::getSession() const
{
	return session;
}

#endif<commit_msg>Correct some oculus initialization things<commit_after>#include "stdafx.h"
#ifdef _WIN32
#include "OculusInterface.hpp"
#include "AnnLogger.hpp"
#include "AnnException.hpp"

using namespace std;
using namespace OVR;
using namespace Annwvyn;

void OculusInterface::abortOnFailure()
{
	session = {};
	luid = {};
	hmdDesc = {};

	//Notify user
	AnnDebug() << "Error: Cannot create Oculus Session";
	//Debug HMD is now handled by the configuration utility and the runtime.
	AnnDebug() << "Please make sure Oculus Home is installed on your system and "
		"please check if you have correctly plugged HDMI and USB on the Rift and Tracker";

	displayWin32ErrorMessage(L"Error: Cannot create Oculus Session!",
		L"Please make sure Oculus Home is installed on your system\n"
		L"and check HDMI and USB connection to your Rift and Tracker");

	//Cleanup
	ovr_Shutdown();
	//Return an error
	AnnDebug() << "Unable to Initialize client library or get a session valid from the Oculus Runtime. Closing program and returning 0xDEAD60D error";
	//Stop program
	throw AnnInitializationError((ANN_ERR_CRITIC), "Unable to create an Oculus session");
}

OculusInterface::OculusInterface()
{
	AnnDebug() << "Init Oculus Interface object";
	//Init Oculus Virtual Reality library
	if (OVR_FAILURE(ovr_Initialize(nullptr)))
		abortOnFailure();

	//Declare this client to the Oculus service
	stringstream clientIentifier;
	clientIentifier << "EngineName: Annwvyn\n";
	clientIentifier << "EngineVersion: " << AnnEngine::getAnnwvynVersion();
	AnnDebug() << "Identifier string sent to the Oculus Service : \n" << clientIentifier.str();
	ovr_IdentifyClient(clientIentifier.str().c_str());

	//Attempt to create OVR session
	if (OVR_FAILURE(ovr_Create(&session, &luid)))
		abortOnFailure();

	//Fill the hmdDesc structure
	hmdDesc = ovr_GetHmdDesc(session);

	//Print to log all known information about the headset
	customReport();
}

OculusInterface::~OculusInterface()
{
	//Set the performance HUD to Off
	ovr_SetInt(getSession(), "PerfHudMode", ovrPerfHud_Off);

	AnnDebug() << "Shutdown OculusInterface object";
	ovr_Destroy(getSession());
	ovr_Shutdown();
	AnnDebug("LibOVR Shutdown... No longer can communicate with OculusService");
}

inline Ogre::Vector3 oculusToOgreVect3(const ovrVector3f & v) { return{ v.x, v.y, v.z }; }
inline Ogre::Quaternion oculusToOgreQuat(const ovrQuatf & q) { return{ q.w, q.x, q.y, q.z }; }

void OculusInterface::customReport() const
{
	//Print to the logger a bunch of information
	AnnDebug() << "========================================================";
	AnnDebug() << "OVR version " << ovr_GetVersionString();
	AnnDebug() << "Detected the following Oculus Rift VR Headset :";
	AnnDebug() << "Product name : " << hmdDesc.ProductName;
	AnnDebug() << "Serial number : " << hmdDesc.SerialNumber;
	AnnDebug() << "Manufacturer : " << hmdDesc.Manufacturer;
	AnnDebug() << "Display Resolution : " << hmdDesc.Resolution.w << "x" << hmdDesc.Resolution.h;
	AnnDebug() << "Display refresh rate : " << hmdDesc.DisplayRefreshRate << "Hz";
	AnnDebug() << "Type of HMD identifier : " << hmdDesc.Type;
	AnnDebug() << "Firmware version : " << hmdDesc.FirmwareMajor << "." << hmdDesc.FirmwareMinor;

	const auto trackerCount{ ovr_GetTrackerCount(session) };
	AnnDebug() << "Detected " << trackerCount << " Oculus Sensors";

	for (auto i{ 0u }; i < trackerCount; ++i)
	{
		const auto trackerPose = ovr_GetTrackerPose(session, i).Pose;
		AnnDebug() << "Tracker_" << i + 1 << " Pose : " << oculusToOgreVect3(trackerPose.Position) << "; " << oculusToOgreQuat(trackerPose.Orientation);
	}
	AnnDebug() << "========================================================";
}

ovrHmdDesc OculusInterface::getHmdDesc() const
{
	return hmdDesc;
}

ovrSession OculusInterface::getSession() const
{
	return session;
}

#endif<|endoftext|>


<commit_before>/************************************************************************
*
* CppSharp
* Licensed under the simplified BSD license. All rights reserved.
*
************************************************************************/

#include "Parser.h"
#include "Interop.h"

#include <clang/AST/ASTContext.h>

//-----------------------------------//

static CppSharp::AST::RawCommentKind
ConvertCommentKind(clang::RawComment::CommentKind Kind)
{
	using clang::RawComment;
	using namespace CppSharp::AST;

	switch(Kind)
	{
	case RawComment::RCK_Invalid: return RawCommentKind::Invalid;
	case RawComment::RCK_OrdinaryBCPL: return RawCommentKind::OrdinaryBCPL;
	case RawComment::RCK_OrdinaryC: return RawCommentKind::OrdinaryC;
	case RawComment::RCK_BCPLSlash: return RawCommentKind::BCPLSlash;
	case RawComment::RCK_BCPLExcl: return RawCommentKind::BCPLExcl;
	case RawComment::RCK_JavaDoc: return RawCommentKind::JavaDoc;
	case RawComment::RCK_Qt: return RawCommentKind::Qt;
	case RawComment::RCK_Merged: return RawCommentKind::Merged;
	}

	llvm_unreachable("Unknown comment kind");
}

CppSharp::AST::RawComment^ Parser::WalkRawComment(const clang::RawComment* RC)
{
	using namespace clang;
    using namespace clix;

	auto &SM = C->getSourceManager();
	auto Comment = gcnew CppSharp::AST::RawComment();
	Comment->Kind = ConvertCommentKind(RC->getKind());
	Comment->Text = marshalString<E_UTF8>(RC->getRawText(SM));
	Comment->BriefText = marshalString<E_UTF8>(RC->getBriefText(*AST));

	return Comment;
}

static CppSharp::AST::InlineCommandComment::RenderKind
ConvertRenderKind(clang::comments::InlineCommandComment::RenderKind Kind)
{
	using namespace clang::comments;
	switch(Kind)
	{
	case InlineCommandComment::RenderNormal:
		return CppSharp::AST::InlineCommandComment::RenderKind::RenderNormal;
	case InlineCommandComment::RenderBold:
		return CppSharp::AST::InlineCommandComment::RenderKind::RenderBold;
	case InlineCommandComment::RenderMonospaced:
		return CppSharp::AST::InlineCommandComment::RenderKind::RenderMonospaced;
	case InlineCommandComment::RenderEmphasized:
		return CppSharp::AST::InlineCommandComment::RenderKind::RenderEmphasized;
	}
	llvm_unreachable("Unknown render kind");
}

static CppSharp::AST::ParamCommandComment::PassDirection
ConvertParamPassDirection(clang::comments::ParamCommandComment::PassDirection Dir)
{
	using namespace clang::comments;
	switch(Dir)
	{
	case ParamCommandComment::In:
		return CppSharp::AST::ParamCommandComment::PassDirection::In;
	case ParamCommandComment::Out:
		return CppSharp::AST::ParamCommandComment::PassDirection::Out;
	case ParamCommandComment::InOut:
		return CppSharp::AST::ParamCommandComment::PassDirection::InOut;
	}
	llvm_unreachable("Unknown parameter pass direction");
}

static void HandleBlockCommand(const clang::comments::BlockCommandComment *CK,
							   CppSharp::AST::BlockCommandComment^ BC)
{
	using namespace clix;

	BC->CommandId = CK->getCommandID();
	for (unsigned I = 0, E = CK->getNumArgs(); I != E; ++I)
	{
		auto Arg = CppSharp::AST::BlockCommandComment::Argument();
		Arg.Text = marshalString<E_UTF8>(CK->getArgText(I));
		BC->Arguments->Add(Arg);
	}
}

static CppSharp::AST::Comment^ ConvertCommentBlock(clang::comments::Comment* C)
{
    using namespace clang;
	using clang::comments::Comment;

    using namespace clix;
	using namespace CppSharp::AST;

	// This needs to have an underscore else we get an ICE under VS2012.
	CppSharp::AST::Comment^ _Comment;

	switch(C->getCommentKind())
	{
	case Comment::BlockCommandCommentKind:
	{
		auto CK = cast<const clang::comments::BlockCommandComment>(C);
		auto BC = gcnew BlockCommandComment();
		_Comment = BC;
		HandleBlockCommand(CK, BC);
		break;
	}
	case Comment::ParamCommandCommentKind:
	{
		auto CK = cast<clang::comments::ParamCommandComment>(C);
		auto PC = gcnew ParamCommandComment();
		_Comment = PC;
		HandleBlockCommand(CK, PC);
		PC->Direction = ConvertParamPassDirection(CK->getDirection());
		PC->ParamIndex = CK->getParamIndex();
		break;
	}
	case Comment::TParamCommandCommentKind:
	{
		auto CK = cast<clang::comments::TParamCommandComment>(C);
		_Comment = gcnew TParamCommandComment();
		auto TC = gcnew TParamCommandComment();
		_Comment = TC;
		HandleBlockCommand(CK, TC);
		if (CK->isPositionValid())
			for (unsigned I = 0, E = CK->getDepth(); I != E; ++I)
				TC->Position->Add(CK->getIndex(I));
		break;
	}
	case Comment::VerbatimBlockCommentKind:
	{
		auto CK = cast<clang::comments::VerbatimBlockComment>(C);
		auto VB = gcnew VerbatimBlockComment();
		_Comment = VB;
		for (auto I = CK->child_begin(), E = CK->child_end(); I != E; ++I)
		{
			auto Line = ConvertCommentBlock(*I);
			VB->Lines->Add(dynamic_cast<VerbatimBlockLineComment^>(Line));
		}
		break;
	}
	case Comment::VerbatimLineCommentKind:
	{
		auto CK = cast<clang::comments::VerbatimLineComment>(C);
		auto VL = gcnew VerbatimLineComment();
		_Comment = VL;
		VL->Text = marshalString<E_UTF8>(CK->getText());
		break;
	}
	case Comment::ParagraphCommentKind:
	{
		auto CK = cast<clang::comments::ParagraphComment>(C);
		auto PC = gcnew ParagraphComment();
		_Comment = PC;
		for (auto I = CK->child_begin(), E = CK->child_end(); I != E; ++I)
		{
			auto Content = ConvertCommentBlock(*I);
			PC->Content->Add(dynamic_cast<InlineContentComment^>(Content));
		}
		PC->IsWhitespace = CK->isWhitespace();
		break;
	}
	case Comment::FullCommentKind:
	{
		auto CK = cast<clang::comments::FullComment>(C);
		auto FC = gcnew FullComment();
		_Comment = FC;
		for (auto I = CK->child_begin(), E = CK->child_end(); I != E; ++I)
		{
			auto Content = ConvertCommentBlock(*I);
			FC->Blocks->Add(dynamic_cast<BlockContentComment^>(Content));
		}
		break;
	}
	case Comment::HTMLStartTagCommentKind:
	{
		auto CK = cast<clang::comments::HTMLStartTagComment>(C);
		auto TC = gcnew HTMLStartTagComment();
		_Comment = TC;
		TC->TagName = marshalString<E_UTF8>(CK->getTagName());
		for (unsigned I = 0, E = CK->getNumAttrs(); I != E; ++E)
		{
			auto A = CK->getAttr(I);
			auto Attr = CppSharp::AST::HTMLStartTagComment::Attribute();
			Attr.Name = marshalString<E_UTF8>(A.Name);
			Attr.Value = marshalString<E_UTF8>(A.Value);
			TC->Attributes->Add(Attr);
		}
		break;
	}
	case Comment::HTMLEndTagCommentKind:
	{
		auto CK = cast<clang::comments::HTMLEndTagComment>(C);
		auto TC = gcnew HTMLEndTagComment();
		_Comment = TC;
		TC->TagName = marshalString<E_UTF8>(CK->getTagName());
		break;
	}
	case Comment::TextCommentKind:
	{
		auto CK = cast<clang::comments::TextComment>(C);
		auto TC = gcnew TextComment();
		_Comment = TC;
		TC->Text = marshalString<E_UTF8>(CK->getText());
		break;
	}
	case Comment::InlineCommandCommentKind:
	{
		auto CK = cast<clang::comments::InlineCommandComment>(C);
		auto IC = gcnew InlineCommandComment();
		_Comment = IC;
		IC->Kind = ConvertRenderKind(CK->getRenderKind());
		for (unsigned I = 0, E = CK->getNumArgs(); I != E; ++I)
		{
			auto Arg = CppSharp::AST::InlineCommandComment::Argument();
			Arg.Text = marshalString<E_UTF8>(CK->getArgText(I));
			IC->Arguments->Add(Arg);
		}
		break;
	}
	case Comment::VerbatimBlockLineCommentKind:
	{
		auto CK = cast<clang::comments::VerbatimBlockLineComment>(C);
		auto VL = gcnew VerbatimBlockLineComment();
		_Comment = VL;
		VL->Text = marshalString<E_UTF8>(CK->getText());
		break;
	}
	case Comment::NoCommentKind: return nullptr;
	default:
		llvm_unreachable("Unknown comment kind");
	}

	assert(_Comment && "Invalid comment instance");
	return _Comment;
}

void Parser::HandleComments(clang::Decl* D, CppSharp::AST::Declaration^ Decl)
{
    using namespace clang;
	using namespace clang::comments;
    using namespace clix;

    const RawComment* RC = 0;
    if (!(RC = AST->getRawCommentForAnyRedecl(D)))
		return;

	auto RawComment = WalkRawComment(RC);
	Decl->Comment = RawComment;

	if (FullComment* FC = RC->parse(*AST, &C->getPreprocessor(), D))
	{
		auto CB = safe_cast<CppSharp::AST::FullComment^>(ConvertCommentBlock(FC));
		RawComment->FullComment = CB;
	}

	// Debug Text
    SourceManager& SM = C->getSourceManager();
    const LangOptions& LangOpts = C->getLangOpts();

    auto Range = CharSourceRange::getTokenRange(D->getSourceRange());

    bool Invalid;
    StringRef DeclText = Lexer::getSourceText(Range, SM, LangOpts, &Invalid);
    //assert(!Invalid && "Should have a valid location");

    if (!Invalid)
        Decl->DebugText = marshalString<E_UTF8>(DeclText);
}
<commit_msg>Fix typo in HTML Comment processing code where the wrong variable was being incremented.<commit_after>/************************************************************************
*
* CppSharp
* Licensed under the simplified BSD license. All rights reserved.
*
************************************************************************/

#include "Parser.h"
#include "Interop.h"

#include <clang/AST/ASTContext.h>

//-----------------------------------//

static CppSharp::AST::RawCommentKind
ConvertCommentKind(clang::RawComment::CommentKind Kind)
{
	using clang::RawComment;
	using namespace CppSharp::AST;

	switch(Kind)
	{
	case RawComment::RCK_Invalid: return RawCommentKind::Invalid;
	case RawComment::RCK_OrdinaryBCPL: return RawCommentKind::OrdinaryBCPL;
	case RawComment::RCK_OrdinaryC: return RawCommentKind::OrdinaryC;
	case RawComment::RCK_BCPLSlash: return RawCommentKind::BCPLSlash;
	case RawComment::RCK_BCPLExcl: return RawCommentKind::BCPLExcl;
	case RawComment::RCK_JavaDoc: return RawCommentKind::JavaDoc;
	case RawComment::RCK_Qt: return RawCommentKind::Qt;
	case RawComment::RCK_Merged: return RawCommentKind::Merged;
	}

	llvm_unreachable("Unknown comment kind");
}

CppSharp::AST::RawComment^ Parser::WalkRawComment(const clang::RawComment* RC)
{
	using namespace clang;
    using namespace clix;

	auto &SM = C->getSourceManager();
	auto Comment = gcnew CppSharp::AST::RawComment();
	Comment->Kind = ConvertCommentKind(RC->getKind());
	Comment->Text = marshalString<E_UTF8>(RC->getRawText(SM));
	Comment->BriefText = marshalString<E_UTF8>(RC->getBriefText(*AST));

	return Comment;
}

static CppSharp::AST::InlineCommandComment::RenderKind
ConvertRenderKind(clang::comments::InlineCommandComment::RenderKind Kind)
{
	using namespace clang::comments;
	switch(Kind)
	{
	case InlineCommandComment::RenderNormal:
		return CppSharp::AST::InlineCommandComment::RenderKind::RenderNormal;
	case InlineCommandComment::RenderBold:
		return CppSharp::AST::InlineCommandComment::RenderKind::RenderBold;
	case InlineCommandComment::RenderMonospaced:
		return CppSharp::AST::InlineCommandComment::RenderKind::RenderMonospaced;
	case InlineCommandComment::RenderEmphasized:
		return CppSharp::AST::InlineCommandComment::RenderKind::RenderEmphasized;
	}
	llvm_unreachable("Unknown render kind");
}

static CppSharp::AST::ParamCommandComment::PassDirection
ConvertParamPassDirection(clang::comments::ParamCommandComment::PassDirection Dir)
{
	using namespace clang::comments;
	switch(Dir)
	{
	case ParamCommandComment::In:
		return CppSharp::AST::ParamCommandComment::PassDirection::In;
	case ParamCommandComment::Out:
		return CppSharp::AST::ParamCommandComment::PassDirection::Out;
	case ParamCommandComment::InOut:
		return CppSharp::AST::ParamCommandComment::PassDirection::InOut;
	}
	llvm_unreachable("Unknown parameter pass direction");
}

static void HandleBlockCommand(const clang::comments::BlockCommandComment *CK,
							   CppSharp::AST::BlockCommandComment^ BC)
{
	using namespace clix;

	BC->CommandId = CK->getCommandID();
	for (unsigned I = 0, E = CK->getNumArgs(); I != E; ++I)
	{
		auto Arg = CppSharp::AST::BlockCommandComment::Argument();
		Arg.Text = marshalString<E_UTF8>(CK->getArgText(I));
		BC->Arguments->Add(Arg);
	}
}

static CppSharp::AST::Comment^ ConvertCommentBlock(clang::comments::Comment* C)
{
    using namespace clang;
	using clang::comments::Comment;

    using namespace clix;
	using namespace CppSharp::AST;

	// This needs to have an underscore else we get an ICE under VS2012.
	CppSharp::AST::Comment^ _Comment;

	switch(C->getCommentKind())
	{
	case Comment::BlockCommandCommentKind:
	{
		auto CK = cast<const clang::comments::BlockCommandComment>(C);
		auto BC = gcnew BlockCommandComment();
		_Comment = BC;
		HandleBlockCommand(CK, BC);
		break;
	}
	case Comment::ParamCommandCommentKind:
	{
		auto CK = cast<clang::comments::ParamCommandComment>(C);
		auto PC = gcnew ParamCommandComment();
		_Comment = PC;
		HandleBlockCommand(CK, PC);
		PC->Direction = ConvertParamPassDirection(CK->getDirection());
		PC->ParamIndex = CK->getParamIndex();
		break;
	}
	case Comment::TParamCommandCommentKind:
	{
		auto CK = cast<clang::comments::TParamCommandComment>(C);
		_Comment = gcnew TParamCommandComment();
		auto TC = gcnew TParamCommandComment();
		_Comment = TC;
		HandleBlockCommand(CK, TC);
		if (CK->isPositionValid())
			for (unsigned I = 0, E = CK->getDepth(); I != E; ++I)
				TC->Position->Add(CK->getIndex(I));
		break;
	}
	case Comment::VerbatimBlockCommentKind:
	{
		auto CK = cast<clang::comments::VerbatimBlockComment>(C);
		auto VB = gcnew VerbatimBlockComment();
		_Comment = VB;
		for (auto I = CK->child_begin(), E = CK->child_end(); I != E; ++I)
		{
			auto Line = ConvertCommentBlock(*I);
			VB->Lines->Add(dynamic_cast<VerbatimBlockLineComment^>(Line));
		}
		break;
	}
	case Comment::VerbatimLineCommentKind:
	{
		auto CK = cast<clang::comments::VerbatimLineComment>(C);
		auto VL = gcnew VerbatimLineComment();
		_Comment = VL;
		VL->Text = marshalString<E_UTF8>(CK->getText());
		break;
	}
	case Comment::ParagraphCommentKind:
	{
		auto CK = cast<clang::comments::ParagraphComment>(C);
		auto PC = gcnew ParagraphComment();
		_Comment = PC;
		for (auto I = CK->child_begin(), E = CK->child_end(); I != E; ++I)
		{
			auto Content = ConvertCommentBlock(*I);
			PC->Content->Add(dynamic_cast<InlineContentComment^>(Content));
		}
		PC->IsWhitespace = CK->isWhitespace();
		break;
	}
	case Comment::FullCommentKind:
	{
		auto CK = cast<clang::comments::FullComment>(C);
		auto FC = gcnew FullComment();
		_Comment = FC;
		for (auto I = CK->child_begin(), E = CK->child_end(); I != E; ++I)
		{
			auto Content = ConvertCommentBlock(*I);
			FC->Blocks->Add(dynamic_cast<BlockContentComment^>(Content));
		}
		break;
	}
	case Comment::HTMLStartTagCommentKind:
	{
		auto CK = cast<clang::comments::HTMLStartTagComment>(C);
		auto TC = gcnew HTMLStartTagComment();
		_Comment = TC;
		TC->TagName = marshalString<E_UTF8>(CK->getTagName());
		for (unsigned I = 0, E = CK->getNumAttrs(); I != E; ++I)
		{
			auto A = CK->getAttr(I);
			auto Attr = CppSharp::AST::HTMLStartTagComment::Attribute();
			Attr.Name = marshalString<E_UTF8>(A.Name);
			Attr.Value = marshalString<E_UTF8>(A.Value);
			TC->Attributes->Add(Attr);
		}
		break;
	}
	case Comment::HTMLEndTagCommentKind:
	{
		auto CK = cast<clang::comments::HTMLEndTagComment>(C);
		auto TC = gcnew HTMLEndTagComment();
		_Comment = TC;
		TC->TagName = marshalString<E_UTF8>(CK->getTagName());
		break;
	}
	case Comment::TextCommentKind:
	{
		auto CK = cast<clang::comments::TextComment>(C);
		auto TC = gcnew TextComment();
		_Comment = TC;
		TC->Text = marshalString<E_UTF8>(CK->getText());
		break;
	}
	case Comment::InlineCommandCommentKind:
	{
		auto CK = cast<clang::comments::InlineCommandComment>(C);
		auto IC = gcnew InlineCommandComment();
		_Comment = IC;
		IC->Kind = ConvertRenderKind(CK->getRenderKind());
		for (unsigned I = 0, E = CK->getNumArgs(); I != E; ++I)
		{
			auto Arg = CppSharp::AST::InlineCommandComment::Argument();
			Arg.Text = marshalString<E_UTF8>(CK->getArgText(I));
			IC->Arguments->Add(Arg);
		}
		break;
	}
	case Comment::VerbatimBlockLineCommentKind:
	{
		auto CK = cast<clang::comments::VerbatimBlockLineComment>(C);
		auto VL = gcnew VerbatimBlockLineComment();
		_Comment = VL;
		VL->Text = marshalString<E_UTF8>(CK->getText());
		break;
	}
	case Comment::NoCommentKind: return nullptr;
	default:
		llvm_unreachable("Unknown comment kind");
	}

	assert(_Comment && "Invalid comment instance");
	return _Comment;
}

void Parser::HandleComments(clang::Decl* D, CppSharp::AST::Declaration^ Decl)
{
    using namespace clang;
	using namespace clang::comments;
    using namespace clix;

    const RawComment* RC = 0;
    if (!(RC = AST->getRawCommentForAnyRedecl(D)))
		return;

	auto RawComment = WalkRawComment(RC);
	Decl->Comment = RawComment;

	if (FullComment* FC = RC->parse(*AST, &C->getPreprocessor(), D))
	{
		auto CB = safe_cast<CppSharp::AST::FullComment^>(ConvertCommentBlock(FC));
		RawComment->FullComment = CB;
	}

	// Debug Text
    SourceManager& SM = C->getSourceManager();
    const LangOptions& LangOpts = C->getLangOpts();

    auto Range = CharSourceRange::getTokenRange(D->getSourceRange());

    bool Invalid;
    StringRef DeclText = Lexer::getSourceText(Range, SM, LangOpts, &Invalid);
    //assert(!Invalid && "Should have a valid location");

    if (!Invalid)
        Decl->DebugText = marshalString<E_UTF8>(DeclText);
}
<|endoftext|>


<commit_before>/**
 * File    : D.cpp
 * Author  : Kazune Takahashi
 * Created : 2018-10-14 21:35:05
 * Powered by Visual Studio Code
 */

#include <iostream>
#include <iomanip>   // << fixed << setprecision(xxx)
#include <algorithm> // do { } while ( next_permutation(A, A+xxx) ) ;
#include <vector>
#include <string> // to_string(nnn) // substr(m, n) // stoi(nnn)
#include <complex>
#include <tuple>
#include <queue>
#include <stack>
#include <map> // if (M.find(key) != M.end()) { }
#include <set>
#include <functional>
#include <random> // auto rd = bind(uniform_int_distribution<int>(0, 9), mt19937(19920725));
#include <chrono> // std::chrono::system_clock::time_point start_time, end_time;
// start = std::chrono::system_clock::now();
// double elapsed = std::chrono::duration_cast<std::chrono::milliseconds>(end_time-start_time).count();
#include <cctype>
#include <cassert>
#include <cmath>
#include <cstdio>
#include <cstdlib>
using namespace std;

#define DEBUG 0 // change 0 -> 1 if we need debug.

typedef long long ll;

// const int dx[4] = {1, 0, -1, 0};
// const int dy[4] = {0, 1, 0, -1};

// const int C = 1e6+10;
// const ll M = 1000000007;

int N, M;
ll q;
ll x[2010];
ll p[2010];
ll r[2010];
int ok[2010];

int main()
{
  cin >> N >> M >> q;
  for (auto i = 0; i < M; i++)
  {
    cin >> x[i] >> p[i];
  }
  for (auto i = 0; i < M; i++)
  {
    r[i] = p[i] * N / q;
    cerr << "r[" << i << "] = " << r[i] << endl;
  }
  ll rem = N;
  for (auto i = 0; i < M; i++)
  {
    rem -= r[i];
  }
  cerr << "rem = " << rem << endl;
  for (auto i = 0; i < M; i++)
  {
    if (abs(p[i] * N - r[i] * q) > abs(p[i] * N - (r[i] + 1) * q))
    {
      ok[i] = 2;
    }
    else if (abs(p[i] * N - r[i] * q) == abs(p[i] * N - (r[i] + 1) * q))
    {
      ok[i] = 1;
    }
    else
    {
      ok[i] = 0;
    }
    cerr << "ok[" << i << "] = " << ok[i] << endl;
  }
  for (int i = M - 1; i >= 0; i--)
  {
    if (ok[i] == 2 && rem > 0)
    {
      r[i]++;
      rem--;
    }
  }
  for (int i = M - 1; i >= 0; i--)
  {
    if (ok[i] == 1 && rem > 0)
    {
      r[i]++;
      rem--;
    }
  }
  r[0] += rem;
  for (auto i = 0; i < M; i++)
  {
    cerr << "r[" << i << "] = " << r[i] << endl;
  }
  double E = 0;
  for (auto i = 0; i < M; i++)
  {
    E += abs(p[i] / (double)q - r[i] / (double)N) * x[i];
  }
  cout << fixed << setprecision(12) << E * N << endl;
}<commit_msg>tried D.cpp to 'D'<commit_after>/**
 * File    : D.cpp
 * Author  : Kazune Takahashi
 * Created : 2018-10-14 21:35:05
 * Powered by Visual Studio Code
 */

#include <iostream>
#include <iomanip>   // << fixed << setprecision(xxx)
#include <algorithm> // do { } while ( next_permutation(A, A+xxx) ) ;
#include <vector>
#include <string> // to_string(nnn) // substr(m, n) // stoi(nnn)
#include <complex>
#include <tuple>
#include <queue>
#include <stack>
#include <map> // if (M.find(key) != M.end()) { }
#include <set>
#include <functional>
#include <random> // auto rd = bind(uniform_int_distribution<int>(0, 9), mt19937(19920725));
#include <chrono> // std::chrono::system_clock::time_point start_time, end_time;
// start = std::chrono::system_clock::now();
// double elapsed = std::chrono::duration_cast<std::chrono::milliseconds>(end_time-start_time).count();
#include <cctype>
#include <cassert>
#include <cmath>
#include <cstdio>
#include <cstdlib>
using namespace std;

#define DEBUG 0 // change 0 -> 1 if we need debug.

typedef long long ll;

// const int dx[4] = {1, 0, -1, 0};
// const int dy[4] = {0, 1, 0, -1};

// const int C = 1e6+10;
// const ll M = 1000000007;

int N, M;
ll q;
ll x[2010];
ll p[2010];
ll r[2010];
int ok[2010];

int main()
{
  cin >> N >> M >> q;
  for (auto i = 0; i < M; i++)
  {
    cin >> x[i] >> p[i];
  }
  for (auto i = 0; i < M; i++)
  {
    r[i] = p[i] * N / q;
    cerr << "r[" << i << "] = " << r[i] << endl;
  }
  ll rem = N;
  for (auto i = 0; i < M; i++)
  {
    rem -= r[i];
  }
  cerr << "rem = " << rem << endl;
  for (auto i = 0; i < M; i++)
  {
    if (abs(p[i] * N - r[i] * q) > abs(p[i] * N - (r[i] + 1) * q))
    {
      ok[i] = 2;
    }
    else if (abs(p[i] * N - r[i] * q) == abs(p[i] * N - (r[i] + 1) * q))
    {
      ok[i] = 1;
    }
    else
    {
      ok[i] = 0;
    }
    cerr << "ok[" << i << "] = " << ok[i] << endl;
  }
  for (int i = M - 1; i >= 0; i--)
  {
    if (ok[i] == 2 && rem > 0)
    {
      r[i]++;
      rem--;
    }
  }
  for (int i = M - 1; i >= 0; i--)
  {
    if (ok[i] == 1 && rem > 0)
    {
      r[i]++;
      rem--;
    }
  }
  r[0] += rem;
  for (auto i = 0; i < M; i++)
  {
    cerr << "r[" << i << "] = " << r[i] << endl;
  }
  double E = 0;
  for (auto i = 0; i < M; i++)
  {
    cerr << fixed << setprecision(3) << abs(p[i] / (double)q - r[i] / (double)N) << endl;
    E += abs(p[i] / (double)q - r[i] / (double)N) * x[i];
  }
  cout << fixed << setprecision(12) << E * N << endl;
}<|endoftext|>


<commit_before>// 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.

#ifndef __STOUT_HASHMAP_HPP__
#define __STOUT_HASHMAP_HPP__

#include <functional>
#include <list>
#include <map>
#include <unordered_map>
#include <utility>

#include <boost/get_pointer.hpp>

#include "foreach.hpp"
#include "hashset.hpp"
#include "none.hpp"
#include "option.hpp"

// Provides a hash map via 'std::unordered_map'. We inherit from it to add
// new functions as well as to provide better names for some of the
// existing functions.

template <typename Key,
          typename Value,
          typename Hash = std::hash<Key>,
          typename Equal = std::equal_to<Key>>
class hashmap : public std::unordered_map<Key, Value, Hash, Equal>
{
public:
  // An explicit default constructor is needed so
  // 'const hashmap<T> map;' is not an error.
  hashmap() {}

  // An implicit constructor for converting from a std::map.
  //
  // TODO(benh): Allow any arbitrary type that supports 'begin()' and
  // 'end()' passed into the specified 'emplace'?
  hashmap(const std::map<Key, Value>& map)
  {
    std::unordered_map<Key, Value, Hash, Equal>::reserve(map.size());

    for (auto iterator = map.begin(); iterator != map.end(); ++iterator) {
      std::unordered_map<Key, Value, Hash, Equal>::emplace(
          iterator->first,
          iterator->second);
    }
  }

  // An implicit constructor for converting from an r-value std::map.
  //
  // TODO(benh): Allow any arbitrary type that supports 'begin()' and
  // 'end()' passed into the specified 'insert'?
  hashmap(std::map<Key, Value>&& map)
  {
    // NOTE: We're using 'insert' here with a move iterator in order
    // to avoid copies because we know we have an r-value paramater.
    std::unordered_map<Key, Value, Hash, Equal>::insert(
        std::make_move_iterator(map.begin()),
        std::make_move_iterator(map.end()));
  }

  // Allow simple construction via initializer list.
  hashmap(std::initializer_list<std::pair<Key, Value>> list)
  {
    std::unordered_map<Key, Value, Hash, Equal>::reserve(list.size());

    for (auto iterator = list.begin(); iterator != list.end(); ++iterator) {
      std::unordered_map<Key, Value, Hash, Equal>::emplace(
          iterator->first,
          iterator->second);
    }
  }

  // Checks whether this map contains a binding for a key.
  bool contains(const Key& key) const
  {
    return std::unordered_map<Key, Value, Hash, Equal>::count(key) > 0;
  }

  // Checks whether there exists a bound value in this map.
  bool containsValue(const Value& v) const
  {
    foreachvalue (const Value& value, *this) {
      if (value == v) {
        return true;
      }
    }
    return false;
  }

  // Inserts a key, value pair into the map replacing an old value
  // if the key is already present.
  void put(const Key& key, const Value& value)
  {
    std::unordered_map<Key, Value, Hash, Equal>::erase(key);
    std::unordered_map<Key, Value, Hash, Equal>::insert(
        std::pair<Key, Value>(key, value));
  }

  // Returns an Option for the binding to the key.
  Option<Value> get(const Key& key) const
  {
    auto it = std::unordered_map<Key, Value, Hash, Equal>::find(key);
    if (it == std::unordered_map<Key, Value, Hash, Equal>::end()) {
      return None();
    }
    return it->second;
  }

  // Returns the set of keys in this map.
  // TODO(vinod/bmahler): Should return a list instead.
  hashset<Key> keys() const
  {
    hashset<Key> result;
    foreachkey (const Key& key, *this) {
      result.insert(key);
    }
    return result;
  }

  // Returns the list of values in this map.
  std::list<Value> values() const
  {
    std::list<Value> result;
    foreachvalue (const Value& value, *this) {
      result.push_back(value);
    }
    return result;
  }
};

#endif // __STOUT_HASHMAP_HPP__
<commit_msg>Removed unused header include from stout's `hashmap`.<commit_after>// 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.

#ifndef __STOUT_HASHMAP_HPP__
#define __STOUT_HASHMAP_HPP__

#include <functional>
#include <list>
#include <map>
#include <unordered_map>
#include <utility>

#include "foreach.hpp"
#include "hashset.hpp"
#include "none.hpp"
#include "option.hpp"

// Provides a hash map via 'std::unordered_map'. We inherit from it to add
// new functions as well as to provide better names for some of the
// existing functions.

template <typename Key,
          typename Value,
          typename Hash = std::hash<Key>,
          typename Equal = std::equal_to<Key>>
class hashmap : public std::unordered_map<Key, Value, Hash, Equal>
{
public:
  // An explicit default constructor is needed so
  // 'const hashmap<T> map;' is not an error.
  hashmap() {}

  // An implicit constructor for converting from a std::map.
  //
  // TODO(benh): Allow any arbitrary type that supports 'begin()' and
  // 'end()' passed into the specified 'emplace'?
  hashmap(const std::map<Key, Value>& map)
  {
    std::unordered_map<Key, Value, Hash, Equal>::reserve(map.size());

    for (auto iterator = map.begin(); iterator != map.end(); ++iterator) {
      std::unordered_map<Key, Value, Hash, Equal>::emplace(
          iterator->first,
          iterator->second);
    }
  }

  // An implicit constructor for converting from an r-value std::map.
  //
  // TODO(benh): Allow any arbitrary type that supports 'begin()' and
  // 'end()' passed into the specified 'insert'?
  hashmap(std::map<Key, Value>&& map)
  {
    // NOTE: We're using 'insert' here with a move iterator in order
    // to avoid copies because we know we have an r-value paramater.
    std::unordered_map<Key, Value, Hash, Equal>::insert(
        std::make_move_iterator(map.begin()),
        std::make_move_iterator(map.end()));
  }

  // Allow simple construction via initializer list.
  hashmap(std::initializer_list<std::pair<Key, Value>> list)
  {
    std::unordered_map<Key, Value, Hash, Equal>::reserve(list.size());

    for (auto iterator = list.begin(); iterator != list.end(); ++iterator) {
      std::unordered_map<Key, Value, Hash, Equal>::emplace(
          iterator->first,
          iterator->second);
    }
  }

  // Checks whether this map contains a binding for a key.
  bool contains(const Key& key) const
  {
    return std::unordered_map<Key, Value, Hash, Equal>::count(key) > 0;
  }

  // Checks whether there exists a bound value in this map.
  bool containsValue(const Value& v) const
  {
    foreachvalue (const Value& value, *this) {
      if (value == v) {
        return true;
      }
    }
    return false;
  }

  // Inserts a key, value pair into the map replacing an old value
  // if the key is already present.
  void put(const Key& key, const Value& value)
  {
    std::unordered_map<Key, Value, Hash, Equal>::erase(key);
    std::unordered_map<Key, Value, Hash, Equal>::insert(
        std::pair<Key, Value>(key, value));
  }

  // Returns an Option for the binding to the key.
  Option<Value> get(const Key& key) const
  {
    auto it = std::unordered_map<Key, Value, Hash, Equal>::find(key);
    if (it == std::unordered_map<Key, Value, Hash, Equal>::end()) {
      return None();
    }
    return it->second;
  }

  // Returns the set of keys in this map.
  // TODO(vinod/bmahler): Should return a list instead.
  hashset<Key> keys() const
  {
    hashset<Key> result;
    foreachkey (const Key& key, *this) {
      result.insert(key);
    }
    return result;
  }

  // Returns the list of values in this map.
  std::list<Value> values() const
  {
    std::list<Value> result;
    foreachvalue (const Value& value, *this) {
      result.push_back(value);
    }
    return result;
  }
};

#endif // __STOUT_HASHMAP_HPP__
<|endoftext|>


<commit_before>//--------------------------------*-C++-*------------------------------------//
// $Id$
// Geoffrey Furnish
// 17 October 1994
//---------------------------------------------------------------------------//
// This example program demonstrates the use of the plstream C++ class, and
// some aspects of its improvements over the klunky C API, mostly those
// relating to 2-d plotting.
//---------------------------------------------------------------------------//

#include <stdlib.h>
#include <math.h>

#include "plstream.h"

//---------------------------------------------------------------------------//
// In the real world, the user has his own Matrix class, so he just includes
// the header for it.  Here we conjure up a dopey stand in.

class Matrix {
    int nx, ny;
    float *v;
  public:
    Matrix( int _nx, int _ny ) : nx(_nx), ny(_ny) { v = new float[nx*ny]; }
    ~Matrix() { delete[] v; }

    float& operator()( int i, int j )
    {
	// Should do bounds checking, pass for now.
	return v[ j*ny + i ];
    }

    float operator()( int i, int j ) const
    {
	// Should do bounds checking, pass for now.
	return v[ j*ny + i ];
    }

    void redim( int i, int j )
    {
	delete[] v;
	nx = i, ny = j;
	v = new float[nx*ny];
    }
};

//---------------------------------------------------------------------------//
// To perform contouring, we have to concretize the abstract contouring
// interface.  Do this by deriving from Contourable_Data, and implementing
// the indexing operator.

class ContourableMatrix : public Contourable_Data {
    int nx, ny;
    Matrix m;
    int wrapy;			// periodic in 2nd coord ?
  public:
    ContourableMatrix( int _nx, int _ny, int wy =0 )
	: Contourable_Data(_nx,_ny),
	  nx(_nx), ny(_ny), m(nx,ny), wrapy(wy)
    {}
    void elements( int& _nx, int& _ny ) const
    {
	_nx = nx;
	if (wrapy)
	    _ny = ny +1;
	else
	    _ny = ny;
    }
    PLFLT& operator()( int i, int j )
    {
	if (wrapy) j %= ny;
	return m(i,j);
    }
    PLFLT operator()( int i, int j ) const
    {
	if (wrapy) j %= ny;
	return m(i,j);
    }
};

//---------------------------------------------------------------------------//
// For general mesh plotting, we also need to concretize the abstract
// coordinate interface.  Do this by deriving from Coord_2d and filling in
// the blanks.

class CoordinateMatrix : public Coord_2d {
    int nx, ny;
    Matrix m;
    int wrapy;
  public:
    CoordinateMatrix( int _nx, int _ny, int wy =0 )
	: nx(_nx), ny(_ny), m(nx,ny), wrapy(wy)
    {}

    float operator() ( int ix, int iy ) const
    {
	if (wrapy) iy %= ny;
	return m(ix,iy);
    }

    float& operator() ( int ix, int iy )
    {
	if (wrapy) iy %= ny;
	return m(ix,iy);
    }

    void elements( int& _nx, int& _ny )
    {
	_nx = nx;
	if (wrapy)
	    _ny = ny + 1;
	else
	    _ny = ny;
    }

    void min_max( float& _min, float& _max )
    {
	_min = _max = m(0,0);
	for( int i=0; i < nx; i++ )
	    for( int j=0; j < ny; j++ ) {
		if (m(i,j) < _min) _min = m(i,j);
		if (m(i,j) > _max) _max = m(i,j);
	    }
    }
};

void plot1( plstream& pls );
void plot2( plstream& pls );

//---------------------------------------------------------------------------//
// Finally!
//---------------------------------------------------------------------------//

main()
{
    plstream pls;

    plot1( pls );
    plot2( pls );
}

//---------------------------------------------------------------------------//
// Just a simple little routine to show simple use of the plstream object.
//---------------------------------------------------------------------------//

void plot1( plstream& pls )
{
    pls.col( Red );
    pls.env( 0., 1., 0., 1., 0, 0 );

    pls.col( Yellow );
    pllab("(x)", "(y)", "#frPLplot Example 1 - y=x#u2");

    float x[6], y[6];
    for( int i=0; i < 6; i++ ) {
	x[i] = .2 * i;
	y[i] = x[i] * x[i];
    }

    pls.col( Cyan );
    pls.poin( 6, x, y, 9 );

    pls.col( Green );
    pls.line( 6, x, y );
}

//---------------------------------------------------------------------------//
// Demonstration of contouring using the C++ abstract interface which does
// not impose fascist requirements on storage order/format of user data as
// the C and Fortran API's do.
//---------------------------------------------------------------------------//

void plot2( plstream& pls )
{
    pls.adv(0);

// First declare some objects to hold the data and the coordinates.  Note,
// if you don't want to go to the trouble of making these derived classes so
// easy to use (const and non-const indexing operators, etc), such as if you
// have existing code using a Matrix class, and all you want to do now is
// plot it, then you could just make these derived classes have a
// constructor taking a Matrix (previously calculated somewhere else) by
// reference through the constructor.  That way the calculation engine can
// continue to use the normal container class, and only the plotting code
// needs the auxiliary class to concretize the C++ abstract contouring
// interface.

// Since this is a "polar" plot ( :-), see below), we need to enable the
// "wrapy" option in our special purpose data and coordinate classes.  Note
// that this allows "reconnection" of lines, etc, with trivial effort, IFF
// done from C++.  For C-- and Dogtran, one would have to copy the data to a
// new buffer, and pad one side with an image copy of the other side.

    ContourableMatrix d(64,64,1);
    CoordinateMatrix  xg(64,64,1), yg(64,64,1);

    int i, j;
    float twopi = 2.*3.1415927;

// Set up the data and coordinate matrices.

    for( i=0; i < 64; i++ ) {
	float r = i/64.;
	for( j=0; j < 64; j++ ) {
	    float theta = twopi * j/64.;

	    xg(i,j) = r * cos(theta);
	    yg(i,j) = r * sin(theta);;
	    d(i,j) = exp(-r*r)*cos(twopi*2*r)*sin(3*theta);
	}
    }

// Now draw a normal shaded plot.

    float zmin = -1., zmax = 1.;
    int NCONTR = 20;
    float shade_min, shade_max, sh_color;
    int sh_cmap =1, sh_width;
    int min_color = 1, min_width = 0, max_color = 0, max_width = 0;

    pls.vpor( .1, .9, .1, .9 );
    pls.wind( 0., 1., 0., twopi );

    for (i = 0; i < NCONTR; i++) {
	shade_min = zmin + (zmax - zmin) * i / (float) NCONTR;
	shade_max = zmin + (zmax - zmin) * (i +1) / (float) NCONTR;
	sh_color = i / (float) (NCONTR-1);
	sh_width = 2;
	plpsty(0);

	pls.shade( d, 0., 1., 0., twopi,
		   shade_min, shade_max, sh_cmap, sh_color, sh_width,
		   min_color, min_width, max_color, max_width,
		   1, NULL );
    }

    pls.col(Red);
    pls.box("bcnst", 0.0, 0, "bcnstv", 0.0, 0);

// Now do it again, but with the coordinate transformation taken into
// account.

    pls.adv(0);

    cxx_pltr2 tr( xg, yg );

    pls.vpas( .1, .9, .1, .9, 1. );
    pls.wind( -1., 1., -1., 1. );

    for (i = 0; i < NCONTR; i++) {
	shade_min = zmin + (zmax - zmin) * i / (float) NCONTR;
	shade_max = zmin + (zmax - zmin) * (i +1) / (float) NCONTR;
	sh_color = i / (float) (NCONTR-1);
	sh_width = 2;
	plpsty(0);

	pls.shade( d, 0., 1., 0., twopi,
		   shade_min, shade_max, sh_cmap, sh_color, sh_width,
		   min_color, min_width, max_color, max_width,
		   0, &tr );
    }

    pls.col(Red);

// Now draw the border around the drawing region.

    float x[65], y[65];

    for( i=0; i < 65; i++ ) {
	x[i] = xg(63,i);
	y[i] = yg(63,i);
    }

    pls.line( 65, x, y );

// Finally, let's "squoosh" the plot, and draw it all again.

    float X1 = 1., X2 = .1, Y1 = 1.2, Y2 = -.2;

    for( i=0; i < 64; i++ ) {
	float r = i/64.;
	for( j=0; j < 64; j++ ) {
	    float theta = twopi * j / 64.;

	    xg(i,j) = X1 * r * cos(theta) +
		X2 * r*r * cos(2*theta);

	    yg(i,j) = Y1 * r * sin(theta) +
		Y2 * r*r * sin(2*theta);
	}
    }

    float xmin, xmax, ymin, ymax;
    xg.min_max(xmin, xmax), yg.min_max(ymin, ymax);

    pls.adv(0);

    pls.vpas( .1, .9, .1, .9, 1. );
    pls.wind( xmin, xmax, ymin, ymax );

    for (i = 0; i < NCONTR; i++) {
	shade_min = zmin + (zmax - zmin) * i / (float) NCONTR;
	shade_max = zmin + (zmax - zmin) * (i +1) / (float) NCONTR;
	sh_color = i / (float) (NCONTR-1);
	sh_width = 2;
	plpsty(0);

	pls.shade( d, 0., 1., 0., twopi,
		   shade_min, shade_max, sh_cmap, sh_color, sh_width,
		   min_color, min_width, max_color, max_width,
		   0, &tr );
    }

    pls.col(Red);

// Now draw the border around the drawing region.

    for( i=0; i < 65; i++ ) {
	x[i] = xg(63,i);
	y[i] = yg(63,i);
    }

    pls.line( 65, x, y );
}
<commit_msg>Switched from float to PLFLT so it would work with double precision library. Can't do this with templates b/c we don't distinguish between precision in the namespace.  One of these days I'll get around to this, but not today.<commit_after>//--------------------------------*-C++-*------------------------------------//
// $Id$
// Geoffrey Furnish
// 17 October 1994
//---------------------------------------------------------------------------//
// This example program demonstrates the use of the plstream C++ class, and
// some aspects of its improvements over the klunky C API, mostly those
// relating to 2-d plotting.
//---------------------------------------------------------------------------//

#include <stdlib.h>
#include <math.h>

#include "plstream.h"

//---------------------------------------------------------------------------//
// In the real world, the user has his own Matrix class, so he just includes
// the header for it.  Here we conjure up a dopey stand in.

class Matrix {
    int nx, ny;
    PLFLT *v;
  public:
    Matrix( int _nx, int _ny ) : nx(_nx), ny(_ny) { v = new PLFLT[nx*ny]; }
    ~Matrix() { delete[] v; }

    PLFLT& operator()( int i, int j )
    {
	// Should do bounds checking, pass for now.
	return v[ j*ny + i ];
    }

    PLFLT operator()( int i, int j ) const
    {
	// Should do bounds checking, pass for now.
	return v[ j*ny + i ];
    }

    void redim( int i, int j )
    {
	delete[] v;
	nx = i, ny = j;
	v = new PLFLT[nx*ny];
    }
};

//---------------------------------------------------------------------------//
// To perform contouring, we have to concretize the abstract contouring
// interface.  Do this by deriving from Contourable_Data, and implementing
// the indexing operator.

class ContourableMatrix : public Contourable_Data {
    int nx, ny;
    Matrix m;
    int wrapy;			// periodic in 2nd coord ?
  public:
    ContourableMatrix( int _nx, int _ny, int wy =0 )
	: Contourable_Data(_nx,_ny),
	  nx(_nx), ny(_ny), m(nx,ny), wrapy(wy)
    {}
    void elements( int& _nx, int& _ny ) const
    {
	_nx = nx;
	if (wrapy)
	    _ny = ny +1;
	else
	    _ny = ny;
    }
    PLFLT& operator()( int i, int j )
    {
	if (wrapy) j %= ny;
	return m(i,j);
    }
    PLFLT operator()( int i, int j ) const
    {
	if (wrapy) j %= ny;
	return m(i,j);
    }
};

//---------------------------------------------------------------------------//
// For general mesh plotting, we also need to concretize the abstract
// coordinate interface.  Do this by deriving from Coord_2d and filling in
// the blanks.

class CoordinateMatrix : public Coord_2d {
    int nx, ny;
    Matrix m;
    int wrapy;
  public:
    CoordinateMatrix( int _nx, int _ny, int wy =0 )
	: nx(_nx), ny(_ny), m(nx,ny), wrapy(wy)
    {}

    PLFLT operator() ( int ix, int iy ) const
    {
	if (wrapy) iy %= ny;
	return m(ix,iy);
    }

    PLFLT& operator() ( int ix, int iy )
    {
	if (wrapy) iy %= ny;
	return m(ix,iy);
    }

    void elements( int& _nx, int& _ny )
    {
	_nx = nx;
	if (wrapy)
	    _ny = ny + 1;
	else
	    _ny = ny;
    }

    void min_max( PLFLT& _min, PLFLT& _max )
    {
	_min = _max = m(0,0);
	for( int i=0; i < nx; i++ )
	    for( int j=0; j < ny; j++ ) {
		if (m(i,j) < _min) _min = m(i,j);
		if (m(i,j) > _max) _max = m(i,j);
	    }
    }
};

void plot1( plstream& pls );
void plot2( plstream& pls );

//---------------------------------------------------------------------------//
// Finally!
//---------------------------------------------------------------------------//

main()
{
    plstream pls;

    plot1( pls );
    plot2( pls );
}

//---------------------------------------------------------------------------//
// Just a simple little routine to show simple use of the plstream object.
//---------------------------------------------------------------------------//

void plot1( plstream& pls )
{
    pls.col( Red );
    pls.env( 0., 1., 0., 1., 0, 0 );

    pls.col( Yellow );
    pllab("(x)", "(y)", "#frPLplot Example 1 - y=x#u2");

    PLFLT x[6], y[6];
    for( int i=0; i < 6; i++ ) {
	x[i] = .2 * i;
	y[i] = x[i] * x[i];
    }

    pls.col( Cyan );
    pls.poin( 6, x, y, 9 );

    pls.col( Green );
    pls.line( 6, x, y );
}

//---------------------------------------------------------------------------//
// Demonstration of contouring using the C++ abstract interface which does
// not impose fascist requirements on storage order/format of user data as
// the C and Fortran API's do.
//---------------------------------------------------------------------------//

void plot2( plstream& pls )
{
    pls.adv(0);

// First declare some objects to hold the data and the coordinates.  Note,
// if you don't want to go to the trouble of making these derived classes so
// easy to use (const and non-const indexing operators, etc), such as if you
// have existing code using a Matrix class, and all you want to do now is
// plot it, then you could just make these derived classes have a
// constructor taking a Matrix (previously calculated somewhere else) by
// reference through the constructor.  That way the calculation engine can
// continue to use the normal container class, and only the plotting code
// needs the auxiliary class to concretize the C++ abstract contouring
// interface.

// Since this is a "polar" plot ( :-), see below), we need to enable the
// "wrapy" option in our special purpose data and coordinate classes.  Note
// that this allows "reconnection" of lines, etc, with trivial effort, IFF
// done from C++.  For C-- and Dogtran, one would have to copy the data to a
// new buffer, and pad one side with an image copy of the other side.

    ContourableMatrix d(64,64,1);
    CoordinateMatrix  xg(64,64,1), yg(64,64,1);

    int i, j;
    PLFLT twopi = 2.*3.1415927;

// Set up the data and coordinate matrices.

    for( i=0; i < 64; i++ ) {
	PLFLT r = i/64.;
	for( j=0; j < 64; j++ ) {
	    PLFLT theta = twopi * j/64.;

	    xg(i,j) = r * cos(theta);
	    yg(i,j) = r * sin(theta);;
	    d(i,j) = exp(-r*r)*cos(twopi*2*r)*sin(3*theta);
	}
    }

// Now draw a normal shaded plot.

    PLFLT zmin = -1., zmax = 1.;
    int NCONTR = 20;
    PLFLT shade_min, shade_max, sh_color;
    int sh_cmap =1, sh_width;
    int min_color = 1, min_width = 0, max_color = 0, max_width = 0;

    pls.vpor( .1, .9, .1, .9 );
    pls.wind( 0., 1., 0., twopi );

    for (i = 0; i < NCONTR; i++) {
	shade_min = zmin + (zmax - zmin) * i / (PLFLT) NCONTR;
	shade_max = zmin + (zmax - zmin) * (i +1) / (PLFLT) NCONTR;
	sh_color = i / (PLFLT) (NCONTR-1);
	sh_width = 2;
	plpsty(0);

	pls.shade( d, 0., 1., 0., twopi,
		   shade_min, shade_max, sh_cmap, sh_color, sh_width,
		   min_color, min_width, max_color, max_width,
		   1, NULL );
    }

    pls.col(Red);
    pls.box("bcnst", 0.0, 0, "bcnstv", 0.0, 0);

// Now do it again, but with the coordinate transformation taken into
// account.

    pls.adv(0);

    cxx_pltr2 tr( xg, yg );

    pls.vpas( .1, .9, .1, .9, 1. );
    pls.wind( -1., 1., -1., 1. );

    for (i = 0; i < NCONTR; i++) {
	shade_min = zmin + (zmax - zmin) * i / (PLFLT) NCONTR;
	shade_max = zmin + (zmax - zmin) * (i +1) / (PLFLT) NCONTR;
	sh_color = i / (PLFLT) (NCONTR-1);
	sh_width = 2;
	plpsty(0);

	pls.shade( d, 0., 1., 0., twopi,
		   shade_min, shade_max, sh_cmap, sh_color, sh_width,
		   min_color, min_width, max_color, max_width,
		   0, &tr );
    }

    pls.col(Red);

// Now draw the border around the drawing region.

    PLFLT x[65], y[65];

    for( i=0; i < 65; i++ ) {
	x[i] = xg(63,i);
	y[i] = yg(63,i);
    }

    pls.line( 65, x, y );

// Finally, let's "squoosh" the plot, and draw it all again.

    PLFLT X1 = 1., X2 = .1, Y1 = 1.2, Y2 = -.2;

    for( i=0; i < 64; i++ ) {
	PLFLT r = i/64.;
	for( j=0; j < 64; j++ ) {
	    PLFLT theta = twopi * j / 64.;

	    xg(i,j) = X1 * r * cos(theta) +
		X2 * r*r * cos(2*theta);

	    yg(i,j) = Y1 * r * sin(theta) +
		Y2 * r*r * sin(2*theta);
	}
    }

    PLFLT xmin, xmax, ymin, ymax;
    xg.min_max(xmin, xmax), yg.min_max(ymin, ymax);

    pls.adv(0);

    pls.vpas( .1, .9, .1, .9, 1. );
    pls.wind( xmin, xmax, ymin, ymax );

    for (i = 0; i < NCONTR; i++) {
	shade_min = zmin + (zmax - zmin) * i / (PLFLT) NCONTR;
	shade_max = zmin + (zmax - zmin) * (i +1) / (PLFLT) NCONTR;
	sh_color = i / (PLFLT) (NCONTR-1);
	sh_width = 2;
	plpsty(0);

	pls.shade( d, 0., 1., 0., twopi,
		   shade_min, shade_max, sh_cmap, sh_color, sh_width,
		   min_color, min_width, max_color, max_width,
		   0, &tr );
    }

    pls.col(Red);

// Now draw the border around the drawing region.

    for( i=0; i < 65; i++ ) {
	x[i] = xg(63,i);
	y[i] = yg(63,i);
    }

    pls.line( 65, x, y );
}
<|endoftext|>


<commit_before>/**
 * \file dcs/testbed/libvirt/sensors.hpp
 *
 * \brief A set of sensor classes for libvirt-based Virtual Machines.
 *
 * \author Marco Guazzone (marco.guazzone@gmail.com)
 *
 *

 *
 * Copyright (C) 2012       Marco Guazzone (marco.guazzone@gmail.com)
 *                          [Distributed Computing System (DCS) Group,
 *                           Computer Science Institute,
 *                           Department of Science and Technological Innovation,
 *                           University of Piemonte Orientale,
 *                           Alessandria (Italy)]
 *
 * This file is part of dcsxx-testbed (below referred to as "this program").
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published
 * by the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
 */

#ifndef DCS_TESTBED_LIBVIRT_SENSORS_HPP
#define DCS_TESTBED_LIBVIRT_SENSORS_HPP

#include <boost/cstdint.hpp>
#include <cerrno>
#include <cstddef>
#include <cstdlib>
#include <cstring>
#include <ctime>
#include <dcs/assert.hpp>
#include <dcs/exception.hpp>
#include <dcs/testbed/base_sensor.hpp>
#include <dcs/testbed/libvirt/detail/utility.hpp>
#include <iomanip>
#include <iostream>
#include <libvirt/libvirt.h>
#include <libvirt/virterror.h>
#include <sstream>
#include <stdexcept>
#include <string>
#include <unistd.h>

namespace dcs { namespace testbed { namespace libvirt {

template <typename TraitsT>
class cpu_utilization_sensor: public base_sensor<TraitsT>
{
	private: typedef base_sensor<TraitsT> base_type;
	public: typedef typename base_type::traits_type traits_type;
	public: typedef typename base_type::observation_type observation_type;
	private: typedef typename traits_type::real_type real_type;

	public: cpu_utilization_sensor(::virConnectPtr p_conn, ::virDomainPtr p_dom)
	: p_conn_(p_conn),
	  p_dom_(p_dom),
	  cpu_util_(0),
	  first_(true),
	  norm_(true)
	{
	}

	public: void normalized(bool value)
	{
		norm_ = value;
	}

	public: bool normalized() const
	{
		return norm_;
	}

	private: void do_sense()
	{
		int ret;

		if (!first_)
		{
			prev_time_ = cur_time_;
			prev_node_info_ = cur_node_info_;
		}

		ret = ::clock_gettime(CLOCK_REALTIME, &cur_time_);
		if (-1 == ret)
		{
			::std::ostringstream oss;
			oss << "Failed to get clock time info: " << ::std::strerror(errno);

			DCS_EXCEPTION_THROW(::std::runtime_error, oss.str());
		}

		// Get the CPU time used (in ns)
		ret = ::virDomainGetInfo(p_dom_, &cur_node_info_);
		if (-1 == ret)
		{
			::std::ostringstream oss;
			oss << "Failed to get domain info: " << detail::last_error(p_conn_);

			DCS_EXCEPTION_THROW(::std::runtime_error, oss.str());
		}

		if (first_)
		{
			first_ = false;

			prev_time_ = cur_time_;
			prev_node_info_ = cur_node_info_;
		}
		else
		{
			::boost::uint64_t ns_elapsed = (cur_time_.tv_sec-prev_time_.tv_sec)*1.0e9+(cur_time_.tv_nsec-prev_time_.tv_nsec);
			::boost::uint64_t ns_used = cur_node_info_.cpuTime-prev_node_info_.cpuTime;

			cpu_util_ = static_cast<double>(ns_used/static_cast<long double>(ns_elapsed));

			if (norm_)
			{
				int nvcpus = detail::num_vcpus(p_conn_, p_dom_, VIR_DOMAIN_VCPU_MAXIMUM);

				cpu_util_ /= static_cast<double>(nvcpus);
			}
DCS_DEBUG_TRACE("nsec-used: " << ns_used << " - nsec-elaps: " << ns_elapsed << " --> UTIL: " << static_cast<double>(ns_used/static_cast<long double>(ns_elapsed)));//XXX
		}
	}

	private: void do_reset()
	{
		cpu_util_ = 0;
		first_ = true;
//		prev_time_ = cur_time_ = 0;
	}

	private: bool do_has_observations() const
	{
		return !first_;
	}

	private: ::std::vector<observation_type> do_observations() const
	{
		::std::vector<observation_type> obs;

		if (this->has_observations())
		{
			observation_type ob(0, "", cpu_util_);
			obs.push_back(ob);
		}

		return obs;
	}

	private: ::virConnectPtr p_conn_;
	private: ::virDomainPtr p_dom_;
	private: real_type cpu_util_;
	private: bool first_;
	private: bool norm_;
	private: ::timespec prev_time_;
	private: ::timespec cur_time_;
	private: ::virDomainInfo prev_node_info_;
	private: ::virDomainInfo cur_node_info_;
}; // cpu_utilization_sensor

}}} // Namespace dcs::testbed::libvirt

#endif // DCS_TESTBED_LIBVIRT_SENSORS_HPP
<commit_msg>(change:minor) Fixed debug message<commit_after>/**
 * \file dcs/testbed/libvirt/sensors.hpp
 *
 * \brief A set of sensor classes for libvirt-based Virtual Machines.
 *
 * \author Marco Guazzone (marco.guazzone@gmail.com)
 *
 *

 *
 * Copyright (C) 2012       Marco Guazzone (marco.guazzone@gmail.com)
 *                          [Distributed Computing System (DCS) Group,
 *                           Computer Science Institute,
 *                           Department of Science and Technological Innovation,
 *                           University of Piemonte Orientale,
 *                           Alessandria (Italy)]
 *
 * This file is part of dcsxx-testbed (below referred to as "this program").
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published
 * by the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
 */

#ifndef DCS_TESTBED_LIBVIRT_SENSORS_HPP
#define DCS_TESTBED_LIBVIRT_SENSORS_HPP

#include <boost/cstdint.hpp>
#include <cerrno>
#include <cstddef>
#include <cstdlib>
#include <cstring>
#include <ctime>
#include <dcs/assert.hpp>
#include <dcs/exception.hpp>
#include <dcs/testbed/base_sensor.hpp>
#include <dcs/testbed/libvirt/detail/utility.hpp>
#include <iomanip>
#include <iostream>
#include <libvirt/libvirt.h>
#include <libvirt/virterror.h>
#include <sstream>
#include <stdexcept>
#include <string>
#include <unistd.h>

namespace dcs { namespace testbed { namespace libvirt {

template <typename TraitsT>
class cpu_utilization_sensor: public base_sensor<TraitsT>
{
	private: typedef base_sensor<TraitsT> base_type;
	public: typedef typename base_type::traits_type traits_type;
	public: typedef typename base_type::observation_type observation_type;
	private: typedef typename traits_type::real_type real_type;

	public: cpu_utilization_sensor(::virConnectPtr p_conn, ::virDomainPtr p_dom)
	: p_conn_(p_conn),
	  p_dom_(p_dom),
	  cpu_util_(0),
	  first_(true),
	  norm_(true)
	{
	}

	public: void normalized(bool value)
	{
		norm_ = value;
	}

	public: bool normalized() const
	{
		return norm_;
	}

	private: void do_sense()
	{
		int ret;

		if (!first_)
		{
			prev_time_ = cur_time_;
			prev_node_info_ = cur_node_info_;
		}

		ret = ::clock_gettime(CLOCK_REALTIME, &cur_time_);
		if (-1 == ret)
		{
			::std::ostringstream oss;
			oss << "Failed to get clock time info: " << ::std::strerror(errno);

			DCS_EXCEPTION_THROW(::std::runtime_error, oss.str());
		}

		// Get the CPU time used (in ns)
		ret = ::virDomainGetInfo(p_dom_, &cur_node_info_);
		if (-1 == ret)
		{
			::std::ostringstream oss;
			oss << "Failed to get domain info: " << detail::last_error(p_conn_);

			DCS_EXCEPTION_THROW(::std::runtime_error, oss.str());
		}

		if (first_)
		{
			first_ = false;

			prev_time_ = cur_time_;
			prev_node_info_ = cur_node_info_;
		}
		else
		{
			::boost::uint64_t ns_elapsed = (cur_time_.tv_sec-prev_time_.tv_sec)*1.0e9+(cur_time_.tv_nsec-prev_time_.tv_nsec);
			::boost::uint64_t ns_used = cur_node_info_.cpuTime-prev_node_info_.cpuTime;

			cpu_util_ = static_cast<double>(ns_used/static_cast<long double>(ns_elapsed));

			if (norm_)
			{
				int nvcpus = detail::num_vcpus(p_conn_, p_dom_, VIR_DOMAIN_VCPU_MAXIMUM);

				cpu_util_ /= static_cast<double>(nvcpus);
			}
DCS_DEBUG_TRACE("nsec-used: " << ns_used << " - nsec-elaps: " << ns_elapsed << " --> UTIL: " << cpu_util_);//XXX
		}
	}

	private: void do_reset()
	{
		cpu_util_ = 0;
		first_ = true;
//		prev_time_ = cur_time_ = 0;
	}

	private: bool do_has_observations() const
	{
		return !first_;
	}

	private: ::std::vector<observation_type> do_observations() const
	{
		::std::vector<observation_type> obs;

		if (this->has_observations())
		{
			observation_type ob(0, "", cpu_util_);
			obs.push_back(ob);
		}

		return obs;
	}

	private: ::virConnectPtr p_conn_;
	private: ::virDomainPtr p_dom_;
	private: real_type cpu_util_;
	private: bool first_;
	private: bool norm_;
	private: ::timespec prev_time_;
	private: ::timespec cur_time_;
	private: ::virDomainInfo prev_node_info_;
	private: ::virDomainInfo cur_node_info_;
}; // cpu_utilization_sensor

}}} // Namespace dcs::testbed::libvirt

#endif // DCS_TESTBED_LIBVIRT_SENSORS_HPP
<|endoftext|>


<commit_before>#ifndef SYSCALL_IO_H_
#define SYSCALL_IO_H_

struct linux_dirent {
    unsigned long   d_ino;
    unsigned long   d_off;
    unsigned short  d_reclen;
    char            d_name[1];
};

/*
 * This file defines Linux specific system calls (i.e. not POSIX).
 */
namespace Syscall {

    #if SYSCALL_EXISTS(dup3)
    SYSTEM_CALL int     dup3(int, int, int);
    #endif
    SYSTEM_CALL int     getdents(unsigned int, struct linux_dirent *, unsigned int);
    SYSTEM_CALL int     getcwd(char *, size_t);

    #if SYSCALL_EXISTS(dup3)
    SYSTEM_CALL
    int dup3(int oldfd, int newfd, int flags)
    {
        return DO_SYSCALL(dup3, oldfd, newfd, flags);
    }
    #endif

    SYSTEM_CALL
    int getdents(unsigned int fd, struct linux_dirent *dirp, unsigned int count)
    {
        return DO_SYSCALL(getdents, fd, dirp, count);
    }

    SYSTEM_CALL
    int getcwd(char *buf, size_t size)
    {
        return DO_SYSCALL(getcwd, buf, size);
    }

    //
    // Some architectures have renamed select as _newselect.
    //
    #if !SYSCALL_EXISTS(select) && SYSCALL_EXISTS(_newselect)
    SYSTEM_CALL
    int select(int nfds, fd_set *reads_fds, fd_set *write_fds, fd_set *except_fds, struct timeval *timeout)
    {
        return DO_SYSCALL(_newselect, nfds, read_fds, write_fds, except_fds, timeout);
    }
    #endif
}

#endif
<commit_msg>target/linux: fix typo in _newselect<commit_after>#ifndef SYSCALL_IO_H_
#define SYSCALL_IO_H_

struct linux_dirent {
    unsigned long   d_ino;
    unsigned long   d_off;
    unsigned short  d_reclen;
    char            d_name[1];
};

/*
 * This file defines Linux specific system calls (i.e. not POSIX).
 */
namespace Syscall {

    #if SYSCALL_EXISTS(dup3)
    SYSTEM_CALL int     dup3(int, int, int);
    #endif
    SYSTEM_CALL int     getdents(unsigned int, struct linux_dirent *, unsigned int);
    SYSTEM_CALL int     getcwd(char *, size_t);

    #if SYSCALL_EXISTS(dup3)
    SYSTEM_CALL
    int dup3(int oldfd, int newfd, int flags)
    {
        return DO_SYSCALL(dup3, oldfd, newfd, flags);
    }
    #endif

    SYSTEM_CALL
    int getdents(unsigned int fd, struct linux_dirent *dirp, unsigned int count)
    {
        return DO_SYSCALL(getdents, fd, dirp, count);
    }

    SYSTEM_CALL
    int getcwd(char *buf, size_t size)
    {
        return DO_SYSCALL(getcwd, buf, size);
    }

    //
    // Some architectures have renamed select as _newselect.
    //
    #if !SYSCALL_EXISTS(select) && SYSCALL_EXISTS(_newselect)
    SYSTEM_CALL
    int select(int nfds, fd_set *read_fds, fd_set *write_fds, fd_set *except_fds, struct timeval *timeout)
    {
        return DO_SYSCALL(_newselect, nfds, read_fds, write_fds, except_fds, timeout);
    }
    #endif
}

#endif
<|endoftext|>


<commit_before>#include "ShapefileLoader.h"

#include "PlanarGraph.h"
#include "ArcData2D.h"

#include <Table.h>
#include <DBase3File.h>

#include <cassert>
#include <shapefil.h>
#include <iostream>
#include <cmath>
#include <sstream>

using namespace std;

ShapefileLoader::ShapefileLoader() : FileTypeHandler("ESRI Shapefile", false) {
  addExtension("shp");
}

std::shared_ptr<Graph>
ShapefileLoader::openGraph(const char * filename, const std::shared_ptr<NodeArray> & initial_nodes) {
  SHPHandle shp = SHPOpen(filename, "rb");
  if (!shp) {
    cerr << "failed to open shapefile\n";
    return 0;
  }

  double minb[4], maxb[4];
  int shape_count, global_shape_type;
  SHPGetInfo(shp, &shape_count, &global_shape_type, minb, maxb);

  std::shared_ptr<Graph> graph;

  map<string, int> nodes;
  map<string, pair<glm::dvec2, set<string> > > node_edges;
  map<string, int> waiting_faces;

  cerr << "loading shapefile (" << shape_count << ")\n";

  bool has_polygons = false;

  for (int i = 0; i < shape_count; i++) {
    SHPObject * o = SHPReadObject(shp, i);
    assert(o);

    switch (o->nSHPType) {
    case SHPT_POINT:
    case SHPT_POINTZ:
    case SHPT_POINTM:
      if (!graph.get()) {
	graph = std::make_shared<PlanarGraph>();
	graph->setNodeArray(initial_nodes);
	graph->getNodeArray().setHasSpatialData(true);
	graph->setNodeVisibility(false);
	graph->setEdgeVisibility(false);
	graph->setFaceVisibility(false);
      }
      assert(o->nVertices == 1);
      {
	int face_id = graph->addFace();
	double x = o->padfX[0], y = o->padfY[0], z = o->padfZ[0];
	int node_id = createNode2D(*graph, nodes, x, y);
	graph->addEdge(node_id, node_id, face_id, 0.0f);
	auto & fd = graph->getFaceAttributes(face_id);
	fd.centroid = glm::vec2(x, y);
	fd.mbr = glm::vec3(x, y, 0.0f);
      }
      break;
    case SHPT_MULTIPOINT:
    case SHPT_MULTIPOINTZ:
    case SHPT_MULTIPOINTM:
      assert(0);
#if 0
      if (!graph.get()) {
	graph = std::make_shared<PlanarGraph>();
	graph->setNodeArray(initial_nodes);
	graph->getNodeArray().setHasSpatialData(true);
      }
      for (int j = 0; j < o->nVertices; j++) {
	double x = o->padfX[j], y = o->padfY[j], z = o->padfZ[j];
	int node_id = createNode2D(*graph, nodes, x, y);
	graph->addEdge(node_id, node_id, -1, 0.0f);
      }
#endif
      break;
    case SHPT_ARC: // = polyline
    case SHPT_ARCZ:
    case SHPT_ARCM:
      if (!graph.get()) {
	graph = std::make_shared<PlanarGraph>();
	graph->setNodeArray(initial_nodes);
	graph->getNodeArray().setHasSpatialData(true);
	graph->getNodeArray().setHasArcData(true);
	graph->setNodeVisibility(false);
	graph->setEdgeVisibility(true);
	graph->setFaceVisibility(false);
      }
      {
	int hyperedge_id = graph->addFace();
	for (int j = 0; j < o->nParts; j++) {
	  int start = o->nParts > 1 ? o->panPartStart[j] : 0;
	  int end = o->nParts > 1 && j + 1 < o->nParts ? o->panPartStart[j + 1] : o->nVertices;
	  ArcData2D arc;
	  for (int k0 = start; k0 < end; k0++) {
	    double x = o->padfX[k0], y = o->padfY[k0], z = o->padfZ[k0];
	    arc.data.push_back(glm::dvec2(x, y));
	  }

	  int arc_id = graph->getNodeArray().addArcGeometry(arc);
	  pair<int, int> n = createNodesForArc(arc, *graph, nodes);
	  assert(arc_id);
	  assert(arc_id >= 1 && arc_id <= graph->getNodeArray().getArcGeometry().size());
	  int edge_id = graph->addEdge(n.first, n.second, hyperedge_id, 1.0f, arc_id);
	  assert(graph->getEdgeAttributes(edge_id).arc == arc_id);
	}
      }
      break;
    case SHPT_POLYGON:
    case SHPT_POLYGONZ:
    case SHPT_POLYGONM:
      if (!graph.get()) {
	cerr << "creating planar graph for shapefile\n";
	graph = std::make_shared<PlanarGraph>();
	graph->setNodeArray(initial_nodes);
	graph->getNodeArray().setHasSpatialData(true);
	graph->getNodeArray().setHasArcData(true);
	graph->setNodeVisibility(false);
	graph->setEdgeVisibility(false);
	graph->setFaceVisibility(true);
      }
      has_polygons = true;
      for (int j = 0; j < o->nParts; j++) {
	int start = o->nParts > 1 ? o->panPartStart[j] : 0;
	int end = o->nParts > 1 && j + 1 < o->nParts ? o->panPartStart[j + 1] : o->nVertices;
	int n = end - start;
	for (int k0 = 0; k0 + 1 < n; k0++) {
	  int k1 = start + (k0 % n), k2 = start + ((k0 + 1) % n);
	  glm::dvec2 v1(o->padfX[k1], o->padfY[k1]); //, o->padfZ[k]);
	  glm::dvec2 v2(o->padfX[k2], o->padfY[k2]); // o->padfZ[k + 1]);
	  ostringstream key1, key2;
	  key1 << v1.x << "/" << v1.y;
	  key2 << v2.x << "/" << v2.y;
	  pair<glm::dvec2, set<string> > & ne1 = node_edges[key1.str()];
	  pair<glm::dvec2, set<string> > & ne2 = node_edges[key2.str()];
	  ne1.first = v1;
	  ne2.first = v2;
	  ne1.second.insert(key2.str());
	  ne2.second.insert(key1.str());
	}
      }
      break;
    case SHPT_MULTIPATCH:
      cerr << "multipatches not supported\n";
      assert(0);
      break;
    default:
      cerr << "unhandled type\n";
      assert(0);
    }
    SHPDestroyObject(o);
  }

  if (has_polygons) {
    unsigned int connected_face_arcs = 0;
    cerr << "creating nodes (" << node_edges.size() << ")\n";
    for (map<string, pair<glm::dvec2, set<string> > >::iterator it = node_edges.begin(); it != node_edges.end(); it++) {
      if (it->second.second.size() >= 3) {
	createNode2D(*graph, nodes, it->second.first.x, it->second.first.y);
      }
    }
    cerr << "creating faces\n";
    for (int i = 0; i < shape_count; i++) {
      SHPObject * o = SHPReadObject(shp, i);
      assert(o);
      assert(o->nSHPType == SHPT_POLYGON || o->nSHPType == SHPT_POLYGONZ || o->nSHPType == SHPT_POLYGONM);
      // int region_id = graph->addRegion();
      int face_id = graph->addFace();
      double area = 0, centroid_x = 0, centroid_y = 0;
      assert(o->nParts >= 1); // could be zero to
      for (int j = 0; j < o->nParts; j++) {
	// int face_id = graph->addFace(region_id);
	// cerr << "handling polygon " << i << ", part " << j << endl;
	int start = o->panPartStart[j];
	if (j == 0 && start > 0) {
	  cerr << "invalid start " << start << endl;
	  start = 0;
	}
	int end = j + 1 < o->nParts ? o->panPartStart[j + 1] : o->nVertices;
	list<glm::dvec2> input;
	for (int k = start; k < end; k++) {
	  double x = o->padfX[k], y = o->padfY[k], z = o->padfZ[k];
	  input.push_back(glm::dvec2(x, y));
	  if (k + 1 < end) {
	    double a = o->padfX[k] * o->padfY[k + 1] - o->padfY[k] * o->padfX[k + 1];
	    area -= a;
	    centroid_x -= (o->padfX[k] + o->padfX[k + 1]) * a;
	    centroid_y -= (o->padfY[k] + o->padfY[k + 1]) * a;
	  }
	}
	if (input.size() > 1 &&
	    input.front().x == input.back().x &&
	    input.front().y == input.back().y) {
	  input.pop_back();
	}
	// cerr << "rolling vertices (" << input.size() << ")\n";
	bool node_found = false;
	for (int step = 0; step < input.size(); step++) {
	  ostringstream key1;
	  key1 << input.front().x << "/" << input.front().y;
	  if (nodes.find(key1.str()) != nodes.end()) {
	    node_found = true;
	    break;
	  } else {
	    input.push_back(input.front());
	    input.pop_front();
	  }
	}
	input.push_back(input.front());
	assert(input.size() >= 4);
	if (!node_found) { // island
	  createNode2D(*graph, nodes, input.front().x, input.front().y);
	}
	// ArcData2D arc;
	// for (list<glm::dvec3>::iterator it = input.begin(); it != input.end(); it++) {
	//   arc.data.push_back(*it);
	// }
	// pair<int, int> n = createNodesForArc(arc, graph, nodes);
	// assert(n.first == n.second);
	// int edge_id = graph->addEdge(n.first, n.second, face_id);
	// geometries.setArc(edge_id, arc);
	vector<ArcData2D> arcs;
	vector<int> face_nodes;
	for (auto & v : input) {
	  ostringstream key1;
	  key1 << v.x << "/" << v.y;
	  map<string, int>::iterator it2 = nodes.find(key1.str());
	  if (it2 != nodes.end()) {
	    if (!arcs.empty()) {
	      arcs.back().data.push_back(v);
	    }
	    face_nodes.push_back(it2->second);
	    arcs.push_back(ArcData2D());
	  }
	  assert(!arcs.empty());
	  arcs.back().data.push_back(v);
	}
	assert(face_nodes.front() == face_nodes.back());
	for (int l = 0; l + 1 < face_nodes.size(); l++) {
	  int node1 = face_nodes[l], node2 = face_nodes[l + 1];
	  if (node1 == node2) {
	    // cerr << "same nodes, size = " << face_nodes.size() << endl;
	  }

	  int arc_id = 0, pair_edge = -1;
	  ostringstream key1;
	  key1 << node2 << "/" << node1;
	  map<string, int>::iterator it = waiting_faces.find(key1.str());
	  if (it != waiting_faces.end()) {
	    pair_edge = it->second;
	    auto & ed = graph->getEdgeAttributes(pair_edge);
	    assert(ed.arc >= 1 && ed.arc <= graph->getNodeArray().getArcGeometry().size());
	    arc_id = -ed.arc;
	    waiting_faces.erase(it);
	    connected_face_arcs++;
	  } else {
	    arc_id = graph->getNodeArray().addArcGeometry(arcs[l]);
	    assert(arc_id >= 1 && arc_id <= graph->getNodeArray().getArcGeometry().size());
	  }

	  assert(arc_id);

	  int edge_id = graph->addEdge(node1, node2, face_id, 1.0f, arc_id);
	  if (pair_edge != -1) {
	    graph->connectEdgePair(edge_id, pair_edge);
	  } else {
	    graph->updateMBR(edge_id);
	    ostringstream key2;
	    key2 << node1 << "/" << node2;
	    waiting_faces[key2.str()] = edge_id;
	  }
	  assert(graph->getEdgeAttributes(edge_id).arc == arc_id);
	}
      }

      area *= 0.5;
      centroid_x /= (6.0*area);
      centroid_y /= (6.0*area);
      graph->setFaceCentroid(face_id, glm::vec2(centroid_x, centroid_y));

      SHPDestroyObject(o);
    }
    cerr << "ARCS: connected face arcs = " << connected_face_arcs << ", unconnected = " << waiting_faces.size() << endl;
  }

  SHPClose(shp);

  assert(graph.get());

  auto dbf = std::make_shared<table::DBase3File>(filename);

  if (dbf->getRecordCount() != shape_count) {
    cerr << "bad number of records\n";
  }

  table::Table & table = graph->getFaceData();
  for (auto & col : dbf->getColumns()) {
    table.addColumn(col);
  }

  graph->updateAppearance();

  return graph;
}
<commit_msg>remove call for deleted method setFaceCentroid<commit_after>#include "ShapefileLoader.h"

#include "PlanarGraph.h"
#include "ArcData2D.h"

#include <Table.h>
#include <DBase3File.h>

#include <cassert>
#include <shapefil.h>
#include <iostream>
#include <cmath>
#include <sstream>

using namespace std;

ShapefileLoader::ShapefileLoader() : FileTypeHandler("ESRI Shapefile", false) {
  addExtension("shp");
}

std::shared_ptr<Graph>
ShapefileLoader::openGraph(const char * filename, const std::shared_ptr<NodeArray> & initial_nodes) {
  SHPHandle shp = SHPOpen(filename, "rb");
  if (!shp) {
    cerr << "failed to open shapefile\n";
    return 0;
  }

  double minb[4], maxb[4];
  int shape_count, global_shape_type;
  SHPGetInfo(shp, &shape_count, &global_shape_type, minb, maxb);

  std::shared_ptr<Graph> graph;

  map<string, int> nodes;
  map<string, pair<glm::dvec2, set<string> > > node_edges;
  map<string, int> waiting_faces;

  cerr << "loading shapefile (" << shape_count << ")\n";

  bool has_polygons = false;

  for (int i = 0; i < shape_count; i++) {
    SHPObject * o = SHPReadObject(shp, i);
    assert(o);

    switch (o->nSHPType) {
    case SHPT_POINT:
    case SHPT_POINTZ:
    case SHPT_POINTM:
      if (!graph.get()) {
	graph = std::make_shared<PlanarGraph>();
	graph->setNodeArray(initial_nodes);
	graph->getNodeArray().setHasSpatialData(true);
	graph->setNodeVisibility(false);
	graph->setEdgeVisibility(false);
	graph->setFaceVisibility(false);
      }
      assert(o->nVertices == 1);
      {
	int face_id = graph->addFace();
	double x = o->padfX[0], y = o->padfY[0], z = o->padfZ[0];
	int node_id = createNode2D(*graph, nodes, x, y);
	graph->addEdge(node_id, node_id, face_id, 0.0f);
	auto & fd = graph->getFaceAttributes(face_id);
	fd.centroid = glm::vec2(x, y);
	fd.mbr = glm::vec3(x, y, 0.0f);
      }
      break;
    case SHPT_MULTIPOINT:
    case SHPT_MULTIPOINTZ:
    case SHPT_MULTIPOINTM:
      assert(0);
#if 0
      if (!graph.get()) {
	graph = std::make_shared<PlanarGraph>();
	graph->setNodeArray(initial_nodes);
	graph->getNodeArray().setHasSpatialData(true);
      }
      for (int j = 0; j < o->nVertices; j++) {
	double x = o->padfX[j], y = o->padfY[j], z = o->padfZ[j];
	int node_id = createNode2D(*graph, nodes, x, y);
	graph->addEdge(node_id, node_id, -1, 0.0f);
      }
#endif
      break;
    case SHPT_ARC: // = polyline
    case SHPT_ARCZ:
    case SHPT_ARCM:
      if (!graph.get()) {
	graph = std::make_shared<PlanarGraph>();
	graph->setNodeArray(initial_nodes);
	graph->getNodeArray().setHasSpatialData(true);
	graph->getNodeArray().setHasArcData(true);
	graph->setNodeVisibility(false);
	graph->setEdgeVisibility(true);
	graph->setFaceVisibility(false);
      }
      {
	int hyperedge_id = graph->addFace();
	for (int j = 0; j < o->nParts; j++) {
	  int start = o->nParts > 1 ? o->panPartStart[j] : 0;
	  int end = o->nParts > 1 && j + 1 < o->nParts ? o->panPartStart[j + 1] : o->nVertices;
	  ArcData2D arc;
	  for (int k0 = start; k0 < end; k0++) {
	    double x = o->padfX[k0], y = o->padfY[k0], z = o->padfZ[k0];
	    arc.data.push_back(glm::dvec2(x, y));
	  }

	  int arc_id = graph->getNodeArray().addArcGeometry(arc);
	  pair<int, int> n = createNodesForArc(arc, *graph, nodes);
	  assert(arc_id);
	  assert(arc_id >= 1 && arc_id <= graph->getNodeArray().getArcGeometry().size());
	  int edge_id = graph->addEdge(n.first, n.second, hyperedge_id, 1.0f, arc_id);
	  assert(graph->getEdgeAttributes(edge_id).arc == arc_id);
	}
      }
      break;
    case SHPT_POLYGON:
    case SHPT_POLYGONZ:
    case SHPT_POLYGONM:
      if (!graph.get()) {
	cerr << "creating planar graph for shapefile\n";
	graph = std::make_shared<PlanarGraph>();
	graph->setNodeArray(initial_nodes);
	graph->getNodeArray().setHasSpatialData(true);
	graph->getNodeArray().setHasArcData(true);
	graph->setNodeVisibility(false);
	graph->setEdgeVisibility(false);
	graph->setFaceVisibility(true);
      }
      has_polygons = true;
      for (int j = 0; j < o->nParts; j++) {
	int start = o->nParts > 1 ? o->panPartStart[j] : 0;
	int end = o->nParts > 1 && j + 1 < o->nParts ? o->panPartStart[j + 1] : o->nVertices;
	int n = end - start;
	for (int k0 = 0; k0 + 1 < n; k0++) {
	  int k1 = start + (k0 % n), k2 = start + ((k0 + 1) % n);
	  glm::dvec2 v1(o->padfX[k1], o->padfY[k1]); //, o->padfZ[k]);
	  glm::dvec2 v2(o->padfX[k2], o->padfY[k2]); // o->padfZ[k + 1]);
	  ostringstream key1, key2;
	  key1 << v1.x << "/" << v1.y;
	  key2 << v2.x << "/" << v2.y;
	  pair<glm::dvec2, set<string> > & ne1 = node_edges[key1.str()];
	  pair<glm::dvec2, set<string> > & ne2 = node_edges[key2.str()];
	  ne1.first = v1;
	  ne2.first = v2;
	  ne1.second.insert(key2.str());
	  ne2.second.insert(key1.str());
	}
      }
      break;
    case SHPT_MULTIPATCH:
      cerr << "multipatches not supported\n";
      assert(0);
      break;
    default:
      cerr << "unhandled type\n";
      assert(0);
    }
    SHPDestroyObject(o);
  }

  if (has_polygons) {
    unsigned int connected_face_arcs = 0;
    cerr << "creating nodes (" << node_edges.size() << ")\n";
    for (map<string, pair<glm::dvec2, set<string> > >::iterator it = node_edges.begin(); it != node_edges.end(); it++) {
      if (it->second.second.size() >= 3) {
	createNode2D(*graph, nodes, it->second.first.x, it->second.first.y);
      }
    }
    cerr << "creating faces\n";
    for (int i = 0; i < shape_count; i++) {
      SHPObject * o = SHPReadObject(shp, i);
      assert(o);
      assert(o->nSHPType == SHPT_POLYGON || o->nSHPType == SHPT_POLYGONZ || o->nSHPType == SHPT_POLYGONM);
      // int region_id = graph->addRegion();
      int face_id = graph->addFace();
      double area = 0, centroid_x = 0, centroid_y = 0;
      assert(o->nParts >= 1); // could be zero to
      for (int j = 0; j < o->nParts; j++) {
	// int face_id = graph->addFace(region_id);
	// cerr << "handling polygon " << i << ", part " << j << endl;
	int start = o->panPartStart[j];
	if (j == 0 && start > 0) {
	  cerr << "invalid start " << start << endl;
	  start = 0;
	}
	int end = j + 1 < o->nParts ? o->panPartStart[j + 1] : o->nVertices;
	list<glm::dvec2> input;
	for (int k = start; k < end; k++) {
	  double x = o->padfX[k], y = o->padfY[k], z = o->padfZ[k];
	  input.push_back(glm::dvec2(x, y));
	  if (k + 1 < end) {
	    double a = o->padfX[k] * o->padfY[k + 1] - o->padfY[k] * o->padfX[k + 1];
	    area -= a;
	    centroid_x -= (o->padfX[k] + o->padfX[k + 1]) * a;
	    centroid_y -= (o->padfY[k] + o->padfY[k + 1]) * a;
	  }
	}
	if (input.size() > 1 &&
	    input.front().x == input.back().x &&
	    input.front().y == input.back().y) {
	  input.pop_back();
	}
	// cerr << "rolling vertices (" << input.size() << ")\n";
	bool node_found = false;
	for (int step = 0; step < input.size(); step++) {
	  ostringstream key1;
	  key1 << input.front().x << "/" << input.front().y;
	  if (nodes.find(key1.str()) != nodes.end()) {
	    node_found = true;
	    break;
	  } else {
	    input.push_back(input.front());
	    input.pop_front();
	  }
	}
	input.push_back(input.front());
	assert(input.size() >= 4);
	if (!node_found) { // island
	  createNode2D(*graph, nodes, input.front().x, input.front().y);
	}
	// ArcData2D arc;
	// for (list<glm::dvec3>::iterator it = input.begin(); it != input.end(); it++) {
	//   arc.data.push_back(*it);
	// }
	// pair<int, int> n = createNodesForArc(arc, graph, nodes);
	// assert(n.first == n.second);
	// int edge_id = graph->addEdge(n.first, n.second, face_id);
	// geometries.setArc(edge_id, arc);
	vector<ArcData2D> arcs;
	vector<int> face_nodes;
	for (auto & v : input) {
	  ostringstream key1;
	  key1 << v.x << "/" << v.y;
	  map<string, int>::iterator it2 = nodes.find(key1.str());
	  if (it2 != nodes.end()) {
	    if (!arcs.empty()) {
	      arcs.back().data.push_back(v);
	    }
	    face_nodes.push_back(it2->second);
	    arcs.push_back(ArcData2D());
	  }
	  assert(!arcs.empty());
	  arcs.back().data.push_back(v);
	}
	assert(face_nodes.front() == face_nodes.back());
	for (int l = 0; l + 1 < face_nodes.size(); l++) {
	  int node1 = face_nodes[l], node2 = face_nodes[l + 1];
	  if (node1 == node2) {
	    // cerr << "same nodes, size = " << face_nodes.size() << endl;
	  }

	  int arc_id = 0, pair_edge = -1;
	  ostringstream key1;
	  key1 << node2 << "/" << node1;
	  map<string, int>::iterator it = waiting_faces.find(key1.str());
	  if (it != waiting_faces.end()) {
	    pair_edge = it->second;
	    auto & ed = graph->getEdgeAttributes(pair_edge);
	    assert(ed.arc >= 1 && ed.arc <= graph->getNodeArray().getArcGeometry().size());
	    arc_id = -ed.arc;
	    waiting_faces.erase(it);
	    connected_face_arcs++;
	  } else {
	    arc_id = graph->getNodeArray().addArcGeometry(arcs[l]);
	    assert(arc_id >= 1 && arc_id <= graph->getNodeArray().getArcGeometry().size());
	  }

	  assert(arc_id);

	  int edge_id = graph->addEdge(node1, node2, face_id, 1.0f, arc_id);
	  if (pair_edge != -1) {
	    graph->connectEdgePair(edge_id, pair_edge);
	  } else {
	    graph->updateMBR(edge_id);
	    ostringstream key2;
	    key2 << node1 << "/" << node2;
	    waiting_faces[key2.str()] = edge_id;
	  }
	  assert(graph->getEdgeAttributes(edge_id).arc == arc_id);
	}
      }

      area *= 0.5;
      centroid_x /= (6.0*area);
      centroid_y /= (6.0*area);
      graph->getFaceAttributes(face_id).centroid = glm::vec2(centroid_x, centroid_y);

      SHPDestroyObject(o);
    }
    cerr << "ARCS: connected face arcs = " << connected_face_arcs << ", unconnected = " << waiting_faces.size() << endl;
  }

  SHPClose(shp);

  assert(graph.get());

  auto dbf = std::make_shared<table::DBase3File>(filename);

  if (dbf->getRecordCount() != shape_count) {
    cerr << "bad number of records\n";
  }

  table::Table & table = graph->getFaceData();
  for (auto & col : dbf->getColumns()) {
    table.addColumn(col);
  }

  graph->updateAppearance();

  return graph;
}
<|endoftext|>