<commit_before>
// ListenThread.cpp

// Implements the cListenThread class representing the thread that listens for client connections

#include "Globals.h"
#include "ListenThread.h"

cListenThread::cListenThread(cCallback & a_Callback, cSocket::eFamily a_Family) :
	super("ListenThread"),
	m_Callback(a_Callback),
	m_Family(a_Family)
{
}

cListenThread::~cListenThread()
{
	// TODO
}

bool cListenThread::Initialize(const AString & a_PortsString)
{
	ASSERT(m_Sockets.empty());  // Not yet started

	if (!CreateSockets(a_PortsString))
	{
		return false;
	}

	return true;
}

bool cListenThread::Start(void)
{
	if (m_Sockets.empty())
	{
		// There are no sockets listening, either forgotten to initialize or the user specified no listening ports
		// Report as successful, though
		return true;
	}
	return super::Start();
}

void cListenThread::Stop(void)
{
	if (m_Sockets.empty())
	{
		// No sockets means no thread was running in the first place
		return;
	}

	m_ShouldTerminate = true;

	// Close one socket to wake the thread up from the select() call
	m_Sockets[0].CloseSocket();

	// Wait for the thread to finish
	super::Wait();

	// Clean up all sockets
	m_Sockets.clear();
}

void cListenThread::SetReuseAddr(bool a_Reuse)
{
	ASSERT(m_Sockets.empty());  // Must not have been Initialize()d yet

	m_ShouldReuseAddr = a_Reuse;
}

bool cListenThread::CreateSockets(const AString & a_PortsString)
{
	AStringVector Ports = StringSplit(a_PortsString, ",");

	if (Ports.empty())
	{
		return false;
	}

	const char * FamilyStr = "";
	switch (m_Family)
	{
		case cSocket::IPv4: FamilyStr = "IPv4: "; break;
		case cSocket::IPv6: FamilyStr = "IPv6: "; break;
		default:
		{
			ASSERT(!"Unknown address family");
			break;
		}
	}

	for (AStringVector::const_iterator itr = Ports.begin(), end = Ports.end(); itr != end; ++itr)
	{
		int Port = atoi(Trim(*itr).c_str());
		if ((Port <= 0) || (Port > 65535))
		{
			LOGWARNING("Invalid port specified: \"%s\".", Trim(*itr).c_str());
			continue;
		}
		m_Sockets.push_back(cSocket::CreateSocket(m_Family));
		if (!m_Sockets.back().IsValid())
		{
			LOGERROR("Cannot create listening socket for port %d: \"%s\"", Port, cSocket::GetLastErrorString().c_str());
			m_Sockets.pop_back();
			continue;
		}

		if (m_ShouldReuseAddr)
		{
			if (!m_Sockets.back().SetReuseAddress())
			{
				LOG("Port %d cannot reuse addr, syscall failed: \"%s\".", Port, cSocket::GetLastErrorString().c_str());
			}
		}

		// Bind to port:
		bool res = false;
		switch (m_Family)
		{
			case cSocket::IPv4: res = m_Sockets.back().BindToAnyIPv4(Port); break;
			case cSocket::IPv6: res = m_Sockets.back().BindToAnyIPv6(Port); break;
			default:
			{
				ASSERT(!"Unknown address family");
				res = false;
			}
		}
		if (!res)
		{
			LOGWARNING("Cannot bind port %d: \"%s\".", Port, cSocket::GetLastErrorString().c_str());
			m_Sockets.pop_back();
			continue;
		}

		if (!m_Sockets.back().Listen())
		{
			LOGWARNING("Cannot listen on port %d: \"%s\".", Port, cSocket::GetLastErrorString().c_str());
			m_Sockets.pop_back();
			continue;
		}

		LOGD("%sPort %d is open for connections", FamilyStr, Port);
	}  // for itr - Ports[]

	return !(m_Sockets.empty());
}

void cListenThread::Execute(void)
{
	if (m_Sockets.empty())
	{
		LOGD("Empty cListenThread, ending thread now.");
		return;
	}

	// Find the highest socket number:
	cSocket::xSocket Highest = m_Sockets[0].GetSocket();
	for (cSockets::iterator itr = m_Sockets.begin(), end = m_Sockets.end(); itr != end; ++itr)
	{
		if (itr->GetSocket() > Highest)
		{
			Highest = itr->GetSocket();
		}
	}  // for itr - m_Sockets[]

	while (!m_ShouldTerminate)
	{
		// Put all sockets into a FD set:
		fd_set fdRead;
		FD_ZERO(&fdRead);
		for (cSockets::iterator itr = m_Sockets.begin(), end = m_Sockets.end(); itr != end; ++itr)
		{
			FD_SET(itr->GetSocket(), &fdRead);
		}  // for itr - m_Sockets[]

		if (select(Highest + 1, &fdRead, NULL, NULL, NULL) == -1)
		{
			LOG("select(R) call failed in cListenThread: \"%s\"", cSocket::GetLastErrorString().c_str());
			continue;
		}
		for (cSockets::iterator itr = m_Sockets.begin(), end = m_Sockets.end(); itr != end; ++itr)
		{
			if (FD_ISSET(itr->GetSocket(), &fdRead))
			{
				cSocket Client = itr->Accept();
				m_Callback.OnConnectionAccepted(Client);
			}
		}  // for itr - m_Sockets[]
	}  // while (!m_ShouldTerminate)
}

<commit_msg>Listening ports are now logged<commit_after>
// ListenThread.cpp

// Implements the cListenThread class representing the thread that listens for client connections

#include "Globals.h"
#include "ListenThread.h"

cListenThread::cListenThread(cCallback & a_Callback, cSocket::eFamily a_Family) :
	super("ListenThread"),
	m_Callback(a_Callback),
	m_Family(a_Family)
{
}

cListenThread::~cListenThread()
{
	// TODO
}

bool cListenThread::Initialize(const AString & a_PortsString)
{
	ASSERT(m_Sockets.empty());  // Not yet started

	if (!CreateSockets(a_PortsString))
	{
		return false;
	}

	return true;
}

bool cListenThread::Start(void)
{
	if (m_Sockets.empty())
	{
		// There are no sockets listening, either forgotten to initialize or the user specified no listening ports
		// Report as successful, though
		return true;
	}
	return super::Start();
}

void cListenThread::Stop(void)
{
	if (m_Sockets.empty())
	{
		// No sockets means no thread was running in the first place
		return;
	}

	m_ShouldTerminate = true;

	// Close one socket to wake the thread up from the select() call
	m_Sockets[0].CloseSocket();

	// Wait for the thread to finish
	super::Wait();

	// Clean up all sockets
	m_Sockets.clear();
}

void cListenThread::SetReuseAddr(bool a_Reuse)
{
	ASSERT(m_Sockets.empty());  // Must not have been Initialize()d yet

	m_ShouldReuseAddr = a_Reuse;
}

bool cListenThread::CreateSockets(const AString & a_PortsString)
{
	AStringVector Ports = StringSplit(a_PortsString, ",");

	if (Ports.empty())
	{
		return false;
	}

	const char * FamilyStr = "";
	switch (m_Family)
	{
		case cSocket::IPv4: FamilyStr = "IPv4: "; break;
		case cSocket::IPv6: FamilyStr = "IPv6: "; break;
		default:
		{
			ASSERT(!"Unknown address family");
			break;
		}
	}

	for (AStringVector::const_iterator itr = Ports.begin(), end = Ports.end(); itr != end; ++itr)
	{
		int Port = atoi(Trim(*itr).c_str());
		if ((Port <= 0) || (Port > 65535))
		{
			LOGWARNING("Invalid port specified: \"%s\".", Trim(*itr).c_str());
			continue;
		}
		m_Sockets.push_back(cSocket::CreateSocket(m_Family));
		if (!m_Sockets.back().IsValid())
		{
			LOGERROR("Cannot create listening socket for port %d: \"%s\"", Port, cSocket::GetLastErrorString().c_str());
			m_Sockets.pop_back();
			continue;
		}

		if (m_ShouldReuseAddr)
		{
			if (!m_Sockets.back().SetReuseAddress())
			{
				LOG("Port %d cannot reuse addr, syscall failed: \"%s\".", Port, cSocket::GetLastErrorString().c_str());
			}
		}

		// Bind to port:
		bool res = false;
		switch (m_Family)
		{
			case cSocket::IPv4: res = m_Sockets.back().BindToAnyIPv4(Port); break;
			case cSocket::IPv6: res = m_Sockets.back().BindToAnyIPv6(Port); break;
			default:
			{
				ASSERT(!"Unknown address family");
				res = false;
			}
		}
		if (!res)
		{
			LOGWARNING("Cannot bind port %d: \"%s\".", Port, cSocket::GetLastErrorString().c_str());
			m_Sockets.pop_back();
			continue;
		}

		if (!m_Sockets.back().Listen())
		{
			LOGWARNING("Cannot listen on port %d: \"%s\".", Port, cSocket::GetLastErrorString().c_str());
			m_Sockets.pop_back();
			continue;
		}

		LOGINFO("%sPort %d is open for connections", FamilyStr, Port);
	}  // for itr - Ports[]

	return !(m_Sockets.empty());
}

void cListenThread::Execute(void)
{
	if (m_Sockets.empty())
	{
		LOGD("Empty cListenThread, ending thread now.");
		return;
	}

	// Find the highest socket number:
	cSocket::xSocket Highest = m_Sockets[0].GetSocket();
	for (cSockets::iterator itr = m_Sockets.begin(), end = m_Sockets.end(); itr != end; ++itr)
	{
		if (itr->GetSocket() > Highest)
		{
			Highest = itr->GetSocket();
		}
	}  // for itr - m_Sockets[]

	while (!m_ShouldTerminate)
	{
		// Put all sockets into a FD set:
		fd_set fdRead;
		FD_ZERO(&fdRead);
		for (cSockets::iterator itr = m_Sockets.begin(), end = m_Sockets.end(); itr != end; ++itr)
		{
			FD_SET(itr->GetSocket(), &fdRead);
		}  // for itr - m_Sockets[]

		if (select(Highest + 1, &fdRead, NULL, NULL, NULL) == -1)
		{
			LOG("select(R) call failed in cListenThread: \"%s\"", cSocket::GetLastErrorString().c_str());
			continue;
		}
		for (cSockets::iterator itr = m_Sockets.begin(), end = m_Sockets.end(); itr != end; ++itr)
		{
			if (FD_ISSET(itr->GetSocket(), &fdRead))
			{
				cSocket Client = itr->Accept();
				m_Callback.OnConnectionAccepted(Client);
			}
		}  // for itr - m_Sockets[]
	}  // while (!m_ShouldTerminate)
}

<|endoftext|>


<commit_before>#include <set>
#include "Game/Physics/MergeBuilder.h"

#ifdef DEBUG
#define DEBUG_MAPSPEW
#endif
#ifdef DEBUG_MAPSPEW
#include <iostream>
#include <sstream>
#endif

using namespace Wulf;
using namespace Wulf::Physics;

MergeNode::MergeNode(Map::Node const& node)
	: topLeft(node.x, node.y), type(NodeToTile(node))
	, width(0), height(0)
	, done(false)
	, mTileData(nullptr)
{
}

bool MergeNode::compatible(MergeNode const* other) const
{
	if (other == nullptr || other->done || other->type != type || other->type == TileType::Door)
		return false;
	return true;
}

// This returns the tiledata for the merged mass.
// It is safe to call multiple times as it only returns one TileData.
TileData* MergeNode::toTile()
{
	if (mTileData != nullptr)
		return mTileData;
	// Because short + short coerces to int if left to itself.
	coord brx = topLeft.x + width, bry = topLeft.y + height;
	mTileData = new TileData(topLeft, coords(brx, bry), type);
	return mTileData;
}

std::tuple<std::string, std::string, std::string> MergeNode::toString(coords tile) const
{
#ifdef DEBUG_MAPSPEW
	std::string contents;
	if (type == TileType::Empty) {
		contents = ".";
	} else if (type == TileType::Pickup) {
		contents = "x";
	} else if (type == TileType::Sprite) {
		contents = "~";
	} else if (type == TileType::Door) {
		contents = "D";
	} else {
		contents = "#";
	}

	std::stringstream a, b, c;
	coords bottomRight(topLeft.x - width, topLeft.y + height);
	if (tile == topLeft) {
		a << "/-";
		b << "|";
	} else if (tile.x == topLeft.x) {
		a << "|" << contents;
		b << "|";
	} else if (tile.y == topLeft.y) {
		a << "--";
		b << contents;
	} else {
		a << contents << contents;
		b << contents;
	}
	b << contents;
	if (tile.y == topLeft.y) {
		if (tile.x == bottomRight.x) {
			a << "\\";
			b << "|";
		} else {
			a << "-";
			b << contents;
		}
	} else if (tile.x == bottomRight.x) {
		a << "|";
		b << "|";
	} else {
		a << contents;
		b << contents;
	}
	if (tile.x == topLeft.x) {
		if (tile.y == bottomRight.y) {
			c << "\\-";
		} else {
			c << "|" << contents;
		}
	} else if (tile.y == bottomRight.y) {
		c << "--";
	} else {
		c << contents << contents;
	}
	if (tile == bottomRight) {
		c << "/";
	} else if (tile.x == bottomRight.x) {
		c << "|";
	} else if (tile.y == bottomRight.y) {
		c << "-";
	} else {
		c << contents;
	}
	return std::make_tuple(a.str(), b.str(), c.str());
#else
	return std::make_tuple("", "", "");
#endif
}

MergeBuilder::MergeBuilder(Map::Map const& map)
{
	for (auto& xnodes : nodes)
		std::fill(xnodes.begin(), xnodes.end(), nullptr);
	loadMap(map);
	performMerges();
}
MergeBuilder::~MergeBuilder()
{
	// Use a set because we have duplicate pointers
	std::set<MergeNode*> pointrs;
	for (auto& xnodes : nodes) {
		pointrs.insert(xnodes.begin(), xnodes.end());
	}
	for (MergeNode* node : pointrs) {
		delete node;
	}
}

inline
void MergeBuilder::loadMap(Map::Map const& map)
{
	const auto& mapNodes = map.nodes;
	for (int x = 0; x < xsize; x++) {
		const auto& xnodes = mapNodes[x];
		for (int y = 0; y < ysize; y++) {
			const auto& node = xnodes[y];
			// Filter out walls the player can never hit
			if (node.wall && !node.visibleWall) {
				// Make sure corners are included
				byte i = 0;
				for (Map::Node *neighbour : node.neighbours) {
					if (neighbour != nullptr && neighbour->visibleWall) {
						i++;
					}
				}
				if (i < 2)
					continue;
			}
			nodes[x][y] = new MergeNode(node);
		}
	}
}
inline
int MergeBuilder::verticalMerge(int x, int y)
{
	MergeNode *node = nodes[x][y];
	int i = 1;
	while (y + i < ysize) { // Ensure we stay within bounds
		MergeNode *other = nodes[x][y + i];
		// Check if the node is the same kind as us. (includes a nullptr check)
		if (!node->compatible(other))
			break;

		// Eat the node
		node->height++;
		delete other;
		nodes[x][y + i] = node;

		i++;
	}
	return i - 1;
}

inline
void MergeBuilder::horizontalMerge(int x, int y)
{
	MergeNode *node = nodes[x][y];
	int i = 1;
	// Consume horizontally
	while (x + i < xsize) {
		// Make sure that we can consume all x tiles for our height
		for (int j = 0; j <= node->height; j++) {
			MergeNode *other = nodes[x + i][y + j];
			if (!node->compatible(other)) {
				return;
			}
		}
		node->width++;
		// Eat all nodes for our height
		for (int j = 0; j <= node->height; j++) {
			delete nodes[x + i][y + j];
			nodes[x + i][y + j] = node;
		}

		i++;
	}
}

inline
void MergeBuilder::performMerges()
{
	for (int x = 0; x < xsize; x++) {
		for (int y = 0; y < ysize; y++) {
			MergeNode *node = nodes[x][y];
			if (node == nullptr || node->done || node->type == TileType::Door)
				continue;
			// Merge vertically first due to how the loop is layed out.
			int yadd = verticalMerge(x, y);
			horizontalMerge(x, y);
			node->done = true;
			// yadd lets us skip consumed nodes for the next iteration of y.
			y += yadd;
		}
	}
}

std::vector<std::pair<coords, TileData*>> MergeBuilder::getTileData() const
{
	std::vector<std::pair<coords, TileData*>> ret;
	ret.reserve(xsize * ysize);
	const coord xhalf = Map::Map::halfwidth;
	const coord yhalf = Map::Map::halfheight;

	// SPAM
	DebugOutput();

	for (coord x = 0; x < xsize; x++) {
		for (coord y = 0; y < ysize; y++) {
			MergeNode* node = nodes[x][y];
			if (node == nullptr)
				continue;
			coord nodeX = -(x - xhalf); // I don't know why this is negative, but it is.
			coord nodeY = y - yhalf;
			ret.emplace_back(coords(nodeX, nodeY), node->toTile());
		}
	}

	return ret;
}

void MergeBuilder::DebugOutput() const
{
#ifdef DEBUG_MAPSPEW
	const coord xhalf = Map::Map::halfwidth;
	const coord yhalf = Map::Map::halfheight;

	coord xcoord, ycoord;

	std::cout << " vim: nowrap listchars=" << std::endl;
	std::cout.setf(std::ios_base::right);
	std::cout.fill(' ');
	std::cout.width(3);
	std::cout << "  ";
	std::ostringstream bluh;
	bluh << "   ";
	for (byte x = 0; x < xsize; ++x) {
		std::cout.width(3);
		std::cout << -(x - xhalf);
		bluh << "***";
	}
	std::cout << std::endl;
	std::cout << bluh.str() << std::endl;
	for (byte y = 0; y < ysize; ++y) {
		ycoord = (y - yhalf);
		std::stringstream a, b, c;
		a << "   *";
		b.width(3);
		b << ycoord << '*';
		c << "   *";
		for (byte x = 0; x < xsize; ++x) {
			xcoord = -(x - xhalf);
			MergeNode *node = nodes[x][y];
			if (node == nullptr) {
				a << "   ";
				b << "   ";
				c << "   ";
				continue;
			}
			auto lines = node->toString(coords(xcoord, ycoord));
			a << std::get<0>(lines);
			b << std::get<1>(lines);
			c << std::get<2>(lines);
		}
		std::cout << a.str() << std::endl;
		std::cout << b.str() << std::endl;
		std::cout << c.str() << std::endl;
	}
#endif
}
<commit_msg>Prevent pickups being merged<commit_after>#include <set>
#include "Game/Physics/MergeBuilder.h"

#ifdef DEBUG
#define DEBUG_MAPSPEW
#endif
#ifdef DEBUG_MAPSPEW
#include <iostream>
#include <sstream>
#endif

using namespace Wulf;
using namespace Wulf::Physics;

bool notMergable(TileType type)
{
	return type == TileType::Door || type == TileType::Pickup;
}

MergeNode::MergeNode(Map::Node const& node)
	: topLeft(node.x, node.y), type(NodeToTile(node))
	, width(0), height(0)
	, done(false)
	, mTileData(nullptr)
{
}

bool MergeNode::compatible(MergeNode const* other) const
{
	if (other == nullptr || other->done || other->type != type || notMergable(other->type))
		return false;
	return true;
}

// This returns the tiledata for the merged mass.
// It is safe to call multiple times as it only returns one TileData.
TileData* MergeNode::toTile()
{
	if (mTileData != nullptr)
		return mTileData;
	// Because short + short coerces to int if left to itself.
	coord brx = topLeft.x + width, bry = topLeft.y + height;
	mTileData = new TileData(topLeft, coords(brx, bry), type);
	return mTileData;
}

std::tuple<std::string, std::string, std::string> MergeNode::toString(coords tile) const
{
#ifdef DEBUG_MAPSPEW
	std::string contents;
	if (type == TileType::Empty) {
		contents = ".";
	} else if (type == TileType::Pickup) {
		contents = "x";
	} else if (type == TileType::Sprite) {
		contents = "~";
	} else if (type == TileType::Door) {
		contents = "D";
	} else {
		contents = "#";
	}

	std::stringstream a, b, c;
	coords bottomRight(topLeft.x - width, topLeft.y + height);
	if (tile == topLeft) {
		a << "/-";
		b << "|";
	} else if (tile.x == topLeft.x) {
		a << "|" << contents;
		b << "|";
	} else if (tile.y == topLeft.y) {
		a << "--";
		b << contents;
	} else {
		a << contents << contents;
		b << contents;
	}
	b << contents;
	if (tile.y == topLeft.y) {
		if (tile.x == bottomRight.x) {
			a << "\\";
			b << "|";
		} else {
			a << "-";
			b << contents;
		}
	} else if (tile.x == bottomRight.x) {
		a << "|";
		b << "|";
	} else {
		a << contents;
		b << contents;
	}
	if (tile.x == topLeft.x) {
		if (tile.y == bottomRight.y) {
			c << "\\-";
		} else {
			c << "|" << contents;
		}
	} else if (tile.y == bottomRight.y) {
		c << "--";
	} else {
		c << contents << contents;
	}
	if (tile == bottomRight) {
		c << "/";
	} else if (tile.x == bottomRight.x) {
		c << "|";
	} else if (tile.y == bottomRight.y) {
		c << "-";
	} else {
		c << contents;
	}
	return std::make_tuple(a.str(), b.str(), c.str());
#else
	return std::make_tuple("", "", "");
#endif
}

MergeBuilder::MergeBuilder(Map::Map const& map)
{
	for (auto& xnodes : nodes)
		std::fill(xnodes.begin(), xnodes.end(), nullptr);
	loadMap(map);
	performMerges();
}
MergeBuilder::~MergeBuilder()
{
	// Use a set because we have duplicate pointers
	std::set<MergeNode*> pointrs;
	for (auto& xnodes : nodes) {
		pointrs.insert(xnodes.begin(), xnodes.end());
	}
	for (MergeNode* node : pointrs) {
		delete node;
	}
}

inline
void MergeBuilder::loadMap(Map::Map const& map)
{
	const auto& mapNodes = map.nodes;
	for (int x = 0; x < xsize; x++) {
		const auto& xnodes = mapNodes[x];
		for (int y = 0; y < ysize; y++) {
			const auto& node = xnodes[y];
			// Filter out walls the player can never hit
			if (node.wall && !node.visibleWall) {
				// Make sure corners are included
				byte i = 0;
				for (Map::Node *neighbour : node.neighbours) {
					if (neighbour != nullptr && neighbour->visibleWall) {
						i++;
					}
				}
				if (i < 2)
					continue;
			}
			nodes[x][y] = new MergeNode(node);
		}
	}
}
inline
int MergeBuilder::verticalMerge(int x, int y)
{
	MergeNode *node = nodes[x][y];
	int i = 1;
	while (y + i < ysize) { // Ensure we stay within bounds
		MergeNode *other = nodes[x][y + i];
		// Check if the node is the same kind as us. (includes a nullptr check)
		if (!node->compatible(other))
			break;

		// Eat the node
		node->height++;
		delete other;
		nodes[x][y + i] = node;

		i++;
	}
	return i - 1;
}

inline
void MergeBuilder::horizontalMerge(int x, int y)
{
	MergeNode *node = nodes[x][y];
	int i = 1;
	// Consume horizontally
	while (x + i < xsize) {
		// Make sure that we can consume all x tiles for our height
		for (int j = 0; j <= node->height; j++) {
			MergeNode *other = nodes[x + i][y + j];
			if (!node->compatible(other)) {
				return;
			}
		}
		node->width++;
		// Eat all nodes for our height
		for (int j = 0; j <= node->height; j++) {
			delete nodes[x + i][y + j];
			nodes[x + i][y + j] = node;
		}

		i++;
	}
}

inline
void MergeBuilder::performMerges()
{
	for (int x = 0; x < xsize; x++) {
		for (int y = 0; y < ysize; y++) {
			MergeNode *node = nodes[x][y];
			if (node == nullptr || node->done || notMergable(node->type))
				continue;
			// Merge vertically first due to how the loop is layed out.
			int yadd = verticalMerge(x, y);
			horizontalMerge(x, y);
			node->done = true;
			// yadd lets us skip consumed nodes for the next iteration of y.
			y += yadd;
		}
	}
}

std::vector<std::pair<coords, TileData*>> MergeBuilder::getTileData() const
{
	std::vector<std::pair<coords, TileData*>> ret;
	ret.reserve(xsize * ysize);
	const coord xhalf = Map::Map::halfwidth;
	const coord yhalf = Map::Map::halfheight;

	// SPAM
	DebugOutput();

	for (coord x = 0; x < xsize; x++) {
		for (coord y = 0; y < ysize; y++) {
			MergeNode* node = nodes[x][y];
			if (node == nullptr)
				continue;
			coord nodeX = -(x - xhalf); // I don't know why this is negative, but it is.
			coord nodeY = y - yhalf;
			ret.emplace_back(coords(nodeX, nodeY), node->toTile());
		}
	}

	return ret;
}

void MergeBuilder::DebugOutput() const
{
#ifdef DEBUG_MAPSPEW
	const coord xhalf = Map::Map::halfwidth;
	const coord yhalf = Map::Map::halfheight;

	coord xcoord, ycoord;

	std::cout << " vim: nowrap listchars=" << std::endl;
	std::cout.setf(std::ios_base::right);
	std::cout.fill(' ');
	std::cout.width(3);
	std::cout << "  ";
	std::ostringstream bluh;
	bluh << "   ";
	for (byte x = 0; x < xsize; ++x) {
		std::cout.width(3);
		std::cout << -(x - xhalf);
		bluh << "***";
	}
	std::cout << std::endl;
	std::cout << bluh.str() << std::endl;
	for (byte y = 0; y < ysize; ++y) {
		ycoord = (y - yhalf);
		std::stringstream a, b, c;
		a << "   *";
		b.width(3);
		b << ycoord << '*';
		c << "   *";
		for (byte x = 0; x < xsize; ++x) {
			xcoord = -(x - xhalf);
			MergeNode *node = nodes[x][y];
			if (node == nullptr) {
				a << "   ";
				b << "   ";
				c << "   ";
				continue;
			}
			auto lines = node->toString(coords(xcoord, ycoord));
			a << std::get<0>(lines);
			b << std::get<1>(lines);
			c << std::get<2>(lines);
		}
		std::cout << a.str() << std::endl;
		std::cout << b.str() << std::endl;
		std::cout << c.str() << std::endl;
	}
#endif
}
<|endoftext|>


<commit_before>// ======================================================================== //
// Copyright 2009-2018 Intel Corporation                                    //
//                                                                          //
// 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.                                           //
// ======================================================================== //

#undef NDEBUG

// sg
#include "SceneGraph.h"
#include "sg/common/Texture2D.h"
#include "sg/geometry/TriangleMesh.h"

#define TINYOBJLOADER_IMPLEMENTATION  // define this in only *one* .cc
#include "../3rdParty/tiny_obj_loader.h"

#include <cstring>
#include <sstream>

#define USE_INSTANCES 0

namespace ospray {
  namespace sg {

    std::shared_ptr<Texture2D> loadTexture(const FileName &fullPath,
                                           const bool preferLinear = false)
    {
      std::shared_ptr<Texture2D> tex = Texture2D::load(fullPath, preferLinear);
      if (!tex)
        std::cout << "could not load texture " << fullPath.str() << " !\n";

      return tex;
    }

    void addTextureIfNeeded(Material &node,
                            const std::string &name,
                            const FileName &texName,
                            const FileName &containingPath,
                            bool preferLinear = false)
    {
      if (!texName.str().empty()) {
        auto tex = loadTexture(containingPath + texName, preferLinear);
        if (tex) {
          tex->setName(name);
          node.setChild(name, tex);
        }
      }
    }

    static inline void parseParameterString(std::string typeAndValueString,
                                            std::string &paramType,
                                            ospcommon::utility::Any &paramValue)
    {
      std::stringstream typeAndValueStream(typeAndValueString);
      std::string paramValueString;
      getline(typeAndValueStream, paramValueString);

      std::vector<float> floats;
      std::stringstream valueStream(typeAndValueString);
      float val;
      while (valueStream >> val)
        floats.push_back(val);

      if (floats.size() == 1) {
        paramType = "float";
        paramValue = floats[0];
      } else if (floats.size() == 2) {
        paramType = "vec2f";
        paramValue = vec2f(floats[0], floats[1]);
      } else if (floats.size() == 3) {
        paramType = "vec3f";
        paramValue = vec3f(floats[0], floats[1], floats[2]);
      } else {
        // Unknown type.
        paramValue = typeAndValueString;
      }
    }

    static inline std::shared_ptr<MaterialList> createSgMaterials(
        std::vector<tinyobj::material_t> &mats, const FileName &containingPath)
    {
      auto sgMaterials =
          createNode("materialList", "MaterialList")->nodeAs<MaterialList>();

      if (mats.empty()) {
        sgMaterials->push_back(createNode("default", "Material")->nodeAs<Material>());
        return sgMaterials;
      }

      for (auto &mat : mats) {
        auto matNodePtr = createNode(mat.name, "Material")->nodeAs<Material>();
        auto &matNode   = *matNodePtr;
        bool addOBJparams = true;

        for (auto &param : mat.unknown_parameter) {
          if (param.first == "type") {
            matNode["type"] = param.second;
            if (param.second != "OBJMaterial" && param.second != "default")
              addOBJparams = false;
          } else {
            std::string paramType;
            ospcommon::utility::Any paramValue;
            if (param.first.find("Map") != std::string::npos)
            {
              addTextureIfNeeded(matNode, param.first,
                                 param.second, containingPath);
            }
            else
            {
              parseParameterString(param.second, paramType, paramValue);
              try {
                matNode.createChildWithValue(param.first, paramType, paramValue);
              } catch (const std::runtime_error &) {
                // NOTE(jda) - silently move on if parsed node type doesn't exist
                // maybe it's a texture, try it
                std::cout << "attempting to load param as texture: "
                          << param.first << " " << param.second << std::endl;
                addTextureIfNeeded(matNode, param.first,
                                   param.second, containingPath);
              }
            }
          }
        }

        if (addOBJparams) {
          matNode["d"]  = mat.dissolve;
          matNode["Kd"] = vec3f(mat.diffuse[0], mat.diffuse[1], mat.diffuse[2]);
          matNode["Ks"] =
            vec3f(mat.specular[0], mat.specular[1], mat.specular[2]);

          addTextureIfNeeded(
              matNode, "map_Kd", mat.diffuse_texname, containingPath);
          addTextureIfNeeded(
              matNode, "map_Ks", mat.specular_texname, containingPath);
          addTextureIfNeeded(matNode,
              "map_Ns",
              mat.specular_highlight_texname,
              containingPath,
              true);
          addTextureIfNeeded(
              matNode, "map_bump", mat.bump_texname, containingPath);
          addTextureIfNeeded(
              matNode, "map_d", mat.alpha_texname, containingPath, true);
        }

        sgMaterials->push_back(matNodePtr);
      }

      return sgMaterials;
    }

    void importOBJ(const std::shared_ptr<Node> &world, const FileName &fileName)
    {
      tinyobj::attrib_t attrib;
      std::vector<tinyobj::shape_t> shapes;
      std::vector<tinyobj::material_t> materials;

      std::string err;
      const std::string containingPath = fileName.path();

      std::cout << "parsing OBJ input file... \n";
      bool ret = tinyobj::LoadObj(&attrib,
                                  &shapes,
                                  &materials,
                                  &err,
                                  fileName.c_str(),
                                  containingPath.c_str());

#if 0 // NOTE(jda) - enable if you want to see warnings from TinyOBJ
      if (!err.empty())
        std::cerr << "#ospsg: obj parsing warning(s)...\n" << err << std::endl;
#endif

      if (!ret) {
        std::cerr << "#ospsg: FATAL error parsing obj file, no geometry added"
                  << " to the scene!" << std::endl;
        return;
      }

      auto sgMaterials = createSgMaterials(materials, containingPath);

      std::string base_name = fileName.name() + '_';
      int shapeId           = 0;

      std::cout << "...adding found triangle groups to the scene...\n";

      size_t shapeCounter = 0;
      size_t numShapes    = shapes.size();
      size_t increment    = numShapes / size_t(10);
      int    incrementer  = 0;

#if !USE_INSTANCES
      auto objInstance = createNode("instance", "Instance");
      world->add(objInstance);
#endif
      for (auto &shape : shapes) {
        for (int numVertsInFace : shape.mesh.num_face_vertices) {
          if (numVertsInFace != 3) {
            std::cerr << "Warning: more thant 3 verts in face!";
            PRINT(numVertsInFace);
          }
        }

        if (shapeCounter++ > (increment * incrementer + 1))
          std::cout << incrementer++ * 10 << "%\n";

        auto name = base_name + std::to_string(shapeId++) + '_' + shape.name;
        auto mesh = createNode(name, "TriangleMesh")->nodeAs<TriangleMesh>();

        auto v = createNode("vertex", "DataVector3f")->nodeAs<DataVector3f>();
        auto numSrcIndices = shape.mesh.indices.size();
        v->v.reserve(numSrcIndices);

        auto vi = createNode("index", "DataVector3i")->nodeAs<DataVector3i>();
        vi->v.reserve(numSrcIndices / 3);

        auto vn = createNode("normal", "DataVector3f")->nodeAs<DataVector3f>();
        vn->v.reserve(numSrcIndices);

        auto vt =
            createNode("texcoord", "DataVector2f")->nodeAs<DataVector2f>();
        vt->v.reserve(numSrcIndices);

        for (size_t i = 0; i < shape.mesh.indices.size(); i += 3) {
          auto idx0 = shape.mesh.indices[i + 0];
          auto idx1 = shape.mesh.indices[i + 1];
          auto idx2 = shape.mesh.indices[i + 2];

          auto prim = vec3i(i + 0, i + 1, i + 2);
          vi->push_back(prim);

          v->push_back(vec3f(attrib.vertices[idx0.vertex_index * 3 + 0],
                             attrib.vertices[idx0.vertex_index * 3 + 1],
                             attrib.vertices[idx0.vertex_index * 3 + 2]));
          v->push_back(vec3f(attrib.vertices[idx1.vertex_index * 3 + 0],
                             attrib.vertices[idx1.vertex_index * 3 + 1],
                             attrib.vertices[idx1.vertex_index * 3 + 2]));
          v->push_back(vec3f(attrib.vertices[idx2.vertex_index * 3 + 0],
                             attrib.vertices[idx2.vertex_index * 3 + 1],
                             attrib.vertices[idx2.vertex_index * 3 + 2]));

          // TODO create missing normals&texcoords if only some faces have them
          if (!attrib.normals.empty() && idx0.normal_index != -1) {
            vn->push_back(vec3f(attrib.normals[idx0.normal_index * 3 + 0],
                                attrib.normals[idx0.normal_index * 3 + 1],
                                attrib.normals[idx0.normal_index * 3 + 2]));
            vn->push_back(vec3f(attrib.normals[idx1.normal_index * 3 + 0],
                                attrib.normals[idx1.normal_index * 3 + 1],
                                attrib.normals[idx1.normal_index * 3 + 2]));
            vn->push_back(vec3f(attrib.normals[idx2.normal_index * 3 + 0],
                                attrib.normals[idx2.normal_index * 3 + 1],
                                attrib.normals[idx2.normal_index * 3 + 2]));
          }

          if (!attrib.texcoords.empty() && idx0.texcoord_index != -1) {
            vt->push_back(vec2f(attrib.texcoords[idx0.texcoord_index * 2 + 0],
                                attrib.texcoords[idx0.texcoord_index * 2 + 1]));
            vt->push_back(vec2f(attrib.texcoords[idx1.texcoord_index * 2 + 0],
                                attrib.texcoords[idx1.texcoord_index * 2 + 1]));
            vt->push_back(vec2f(attrib.texcoords[idx2.texcoord_index * 2 + 0],
                                attrib.texcoords[idx2.texcoord_index * 2 + 1]));
          }
        }

        mesh->add(v);
        mesh->add(vi);
        if (!vn->empty())
          mesh->add(vn);
        if (!vt->empty())
          mesh->add(vt);

        auto pmids = createNode("prim.materialID",
                                "DataVector1i")->nodeAs<DataVector1i>();

        auto numMatIds = shape.mesh.material_ids.size();
        pmids->v.reserve(numMatIds);

        for (auto id : shape.mesh.material_ids)
          pmids->v.push_back(id);

        mesh->add(pmids);
        mesh->add(sgMaterials);

        auto model = createNode(name + "_model", "Model");
        model->add(mesh);

        // TODO: Large .obj models with lots of groups run much slower with each
        //       group put in a separate instance. In the future, we want to
        //       support letting the user (ospExampleViewer, for starters)
        //       specify if each group should be placed in an instance or not.
#if USE_INSTANCES
        auto instance = createNode(name + "_instance", "Instance");
        instance->setChild("model", model);
        model->setParent(instance);

        world->add(instance);
#else
        (*objInstance)["model"].add(mesh);
#endif

      }

      std::cout << "...finished import!\n";
    }

    OSPSG_REGISTER_IMPORT_FUNCTION(importOBJ, obj);

  }  // ::ospray::sg
}  // ::ospray
<commit_msg>Fix OBJ material importer<commit_after>// ======================================================================== //
// Copyright 2009-2018 Intel Corporation                                    //
//                                                                          //
// 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.                                           //
// ======================================================================== //

#undef NDEBUG

// sg
#include "SceneGraph.h"
#include "sg/common/Texture2D.h"
#include "sg/geometry/TriangleMesh.h"

#define TINYOBJLOADER_IMPLEMENTATION  // define this in only *one* .cc
#include "../3rdParty/tiny_obj_loader.h"

#include <cstring>
#include <sstream>

#define USE_INSTANCES 0

namespace ospray {
  namespace sg {

    std::shared_ptr<Texture2D> loadTexture(const FileName &fullPath,
                                           const bool preferLinear = false)
    {
      std::shared_ptr<Texture2D> tex = Texture2D::load(fullPath, preferLinear);
      if (!tex)
        std::cout << "could not load texture " << fullPath.str() << " !\n";

      return tex;
    }

    void addTextureIfNeeded(Material &node,
                            const std::string &name,
                            const FileName &texName,
                            const FileName &containingPath,
                            bool preferLinear = false)
    {
      if (!texName.str().empty()) {
        auto tex = loadTexture(containingPath + texName, preferLinear);
        if (tex) {
          tex->setName(name);
          node.setChild(name, tex);
        }
      }
    }

    static inline void parseParameterString(std::string typeAndValueString,
                                            std::string &paramType,
                                            ospcommon::utility::Any &paramValue)
    {
      std::stringstream typeAndValueStream(typeAndValueString);
      std::string paramValueString;
      getline(typeAndValueStream, paramValueString);

      std::vector<float> floats;
      std::stringstream valueStream(typeAndValueString);
      float val;
      while (valueStream >> val)
        floats.push_back(val);

      if (floats.size() == 1) {
        paramType = "float";
        paramValue = floats[0];
      } else if (floats.size() == 2) {
        paramType = "vec2f";
        paramValue = vec2f(floats[0], floats[1]);
      } else if (floats.size() == 3) {
        paramType = "vec3f";
        paramValue = vec3f(floats[0], floats[1], floats[2]);
      } else {
        // Unknown type.
        paramValue = typeAndValueString;
      }
    }

    static inline std::shared_ptr<MaterialList> createSgMaterials(
        std::vector<tinyobj::material_t> &mats, const FileName &containingPath)
    {
      auto sgMaterials =
          createNode("materialList", "MaterialList")->nodeAs<MaterialList>();

      if (mats.empty()) {
        sgMaterials->push_back(createNode("default", "Material")->nodeAs<Material>());
        return sgMaterials;
      }

      for (auto &mat : mats) {
        auto matNodePtr = createNode(mat.name, "Material")->nodeAs<Material>();
        auto &matNode   = *matNodePtr;
        bool addOBJparams = true;

        for (auto &param : mat.unknown_parameter) {
          if (param.first == "type") {
            matNode["type"] = param.second;
            if (param.second != "OBJMaterial" && param.second != "default")
              addOBJparams = false;
          } else {
            std::string paramType;
            ospcommon::utility::Any paramValue;
            if (param.first.find("Map") != std::string::npos)
            {
              addTextureIfNeeded(matNode, param.first,
                                 param.second, containingPath);
            }
            else
            {
              parseParameterString(param.second, paramType, paramValue);
              try {
                matNode.createChildWithValue(param.first, paramType, paramValue);
              } catch (const std::runtime_error &) {
                // NOTE(jda) - silently move on if parsed node type doesn't exist
                // maybe it's a texture, try it
                std::cout << "attempting to load param as texture: "
                          << param.first << " " << param.second << std::endl;
                addTextureIfNeeded(matNode, param.first,
                                   param.second, containingPath);
              }
            }
          }
        }

        if (addOBJparams) {
          matNode["d"]  = mat.dissolve;
          matNode["Kd"] = vec3f(mat.diffuse[0], mat.diffuse[1], mat.diffuse[2]);
          matNode["Ks"] =
            vec3f(mat.specular[0], mat.specular[1], mat.specular[2]);
          matNode["Ns"] = mat.shininess;

          addTextureIfNeeded(
              matNode, "map_Kd", mat.diffuse_texname, containingPath);
          addTextureIfNeeded(
              matNode, "map_Ks", mat.specular_texname, containingPath);
          addTextureIfNeeded(matNode,
              "map_Ns",
              mat.specular_highlight_texname,
              containingPath,
              true);
          addTextureIfNeeded(
              matNode, "map_bump", mat.bump_texname, containingPath);
          addTextureIfNeeded(
              matNode, "map_d", mat.alpha_texname, containingPath, true);
        }

        sgMaterials->push_back(matNodePtr);
      }

      return sgMaterials;
    }

    void importOBJ(const std::shared_ptr<Node> &world, const FileName &fileName)
    {
      tinyobj::attrib_t attrib;
      std::vector<tinyobj::shape_t> shapes;
      std::vector<tinyobj::material_t> materials;

      std::string err;
      const std::string containingPath = fileName.path();

      std::cout << "parsing OBJ input file... \n";
      bool ret = tinyobj::LoadObj(&attrib,
                                  &shapes,
                                  &materials,
                                  &err,
                                  fileName.c_str(),
                                  containingPath.c_str());

#if 0 // NOTE(jda) - enable if you want to see warnings from TinyOBJ
      if (!err.empty())
        std::cerr << "#ospsg: obj parsing warning(s)...\n" << err << std::endl;
#endif

      if (!ret) {
        std::cerr << "#ospsg: FATAL error parsing obj file, no geometry added"
                  << " to the scene!" << std::endl;
        return;
      }

      auto sgMaterials = createSgMaterials(materials, containingPath);

      std::string base_name = fileName.name() + '_';
      int shapeId           = 0;

      std::cout << "...adding found triangle groups to the scene...\n";

      size_t shapeCounter = 0;
      size_t numShapes    = shapes.size();
      size_t increment    = numShapes / size_t(10);
      int    incrementer  = 0;

#if !USE_INSTANCES
      auto objInstance = createNode("instance", "Instance");
      world->add(objInstance);
#endif
      for (auto &shape : shapes) {
        for (int numVertsInFace : shape.mesh.num_face_vertices) {
          if (numVertsInFace != 3) {
            std::cerr << "Warning: more thant 3 verts in face!";
            PRINT(numVertsInFace);
          }
        }

        if (shapeCounter++ > (increment * incrementer + 1))
          std::cout << incrementer++ * 10 << "%\n";

        auto name = base_name + std::to_string(shapeId++) + '_' + shape.name;
        auto mesh = createNode(name, "TriangleMesh")->nodeAs<TriangleMesh>();

        auto v = createNode("vertex", "DataVector3f")->nodeAs<DataVector3f>();
        auto numSrcIndices = shape.mesh.indices.size();
        v->v.reserve(numSrcIndices);

        auto vi = createNode("index", "DataVector3i")->nodeAs<DataVector3i>();
        vi->v.reserve(numSrcIndices / 3);

        auto vn = createNode("normal", "DataVector3f")->nodeAs<DataVector3f>();
        vn->v.reserve(numSrcIndices);

        auto vt =
            createNode("texcoord", "DataVector2f")->nodeAs<DataVector2f>();
        vt->v.reserve(numSrcIndices);

        for (size_t i = 0; i < shape.mesh.indices.size(); i += 3) {
          auto idx0 = shape.mesh.indices[i + 0];
          auto idx1 = shape.mesh.indices[i + 1];
          auto idx2 = shape.mesh.indices[i + 2];

          auto prim = vec3i(i + 0, i + 1, i + 2);
          vi->push_back(prim);

          v->push_back(vec3f(attrib.vertices[idx0.vertex_index * 3 + 0],
                             attrib.vertices[idx0.vertex_index * 3 + 1],
                             attrib.vertices[idx0.vertex_index * 3 + 2]));
          v->push_back(vec3f(attrib.vertices[idx1.vertex_index * 3 + 0],
                             attrib.vertices[idx1.vertex_index * 3 + 1],
                             attrib.vertices[idx1.vertex_index * 3 + 2]));
          v->push_back(vec3f(attrib.vertices[idx2.vertex_index * 3 + 0],
                             attrib.vertices[idx2.vertex_index * 3 + 1],
                             attrib.vertices[idx2.vertex_index * 3 + 2]));

          // TODO create missing normals&texcoords if only some faces have them
          if (!attrib.normals.empty() && idx0.normal_index != -1) {
            vn->push_back(vec3f(attrib.normals[idx0.normal_index * 3 + 0],
                                attrib.normals[idx0.normal_index * 3 + 1],
                                attrib.normals[idx0.normal_index * 3 + 2]));
            vn->push_back(vec3f(attrib.normals[idx1.normal_index * 3 + 0],
                                attrib.normals[idx1.normal_index * 3 + 1],
                                attrib.normals[idx1.normal_index * 3 + 2]));
            vn->push_back(vec3f(attrib.normals[idx2.normal_index * 3 + 0],
                                attrib.normals[idx2.normal_index * 3 + 1],
                                attrib.normals[idx2.normal_index * 3 + 2]));
          }

          if (!attrib.texcoords.empty() && idx0.texcoord_index != -1) {
            vt->push_back(vec2f(attrib.texcoords[idx0.texcoord_index * 2 + 0],
                                attrib.texcoords[idx0.texcoord_index * 2 + 1]));
            vt->push_back(vec2f(attrib.texcoords[idx1.texcoord_index * 2 + 0],
                                attrib.texcoords[idx1.texcoord_index * 2 + 1]));
            vt->push_back(vec2f(attrib.texcoords[idx2.texcoord_index * 2 + 0],
                                attrib.texcoords[idx2.texcoord_index * 2 + 1]));
          }
        }

        mesh->add(v);
        mesh->add(vi);
        if (!vn->empty())
          mesh->add(vn);
        if (!vt->empty())
          mesh->add(vt);

        auto pmids = createNode("prim.materialID",
                                "DataVector1i")->nodeAs<DataVector1i>();

        auto numMatIds = shape.mesh.material_ids.size();
        pmids->v.reserve(numMatIds);

        for (auto id : shape.mesh.material_ids)
          pmids->v.push_back(id);

        mesh->add(pmids);
        mesh->add(sgMaterials);

        auto model = createNode(name + "_model", "Model");
        model->add(mesh);

        // TODO: Large .obj models with lots of groups run much slower with each
        //       group put in a separate instance. In the future, we want to
        //       support letting the user (ospExampleViewer, for starters)
        //       specify if each group should be placed in an instance or not.
#if USE_INSTANCES
        auto instance = createNode(name + "_instance", "Instance");
        instance->setChild("model", model);
        model->setParent(instance);

        world->add(instance);
#else
        (*objInstance)["model"].add(mesh);
#endif

      }

      std::cout << "...finished import!\n";
    }

    OSPSG_REGISTER_IMPORT_FUNCTION(importOBJ, obj);

  }  // ::ospray::sg
}  // ::ospray
<|endoftext|>


<commit_before>// Copyright (c) 2010 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "chrome/browser/extensions/extension_apitest.h"

#include "chrome/browser/browser.h"
#include "chrome/browser/pref_service.h"
#include "chrome/browser/profile.h"
#include "chrome/common/pref_names.h"

IN_PROC_BROWSER_TEST_F(ExtensionApiTest, Tabs) {
  ASSERT_TRUE(StartHTTPServer());

  // The test creates a tab and checks that the URL of the new tab
  // is that of the new tab page.  Make sure the pref that controls
  // this is set.
  browser()->profile()->GetPrefs()->SetBoolean(
      prefs::kHomePageIsNewTabPage, true);

  ASSERT_TRUE(RunExtensionTest("tabs/basics")) << message_;
}

IN_PROC_BROWSER_TEST_F(ExtensionApiTest, TabGetCurrent) {
  ASSERT_TRUE(StartHTTPServer());
  ASSERT_TRUE(RunExtensionTest("tabs/get_current")) << message_;
}

IN_PROC_BROWSER_TEST_F(ExtensionApiTest, TabConnect) {
  ASSERT_TRUE(StartHTTPServer());
  ASSERT_TRUE(RunExtensionTest("tabs/connect")) << message_;
}

IN_PROC_BROWSER_TEST_F(ExtensionApiTest, TabOnRemoved) {
  ASSERT_TRUE(StartHTTPServer());
  ASSERT_TRUE(RunExtensionTest("tabs/on_removed")) << message_;
}

IN_PROC_BROWSER_TEST_F(ExtensionApiTest, CaptureVisibleTab) {
  ASSERT_TRUE(StartHTTPServer());
  ASSERT_TRUE(RunExtensionTest("tabs/capture_visible_tab")) << message_;
}

IN_PROC_BROWSER_TEST_F(ExtensionApiTest, TabsOnUpdated) {
  ASSERT_TRUE(StartHTTPServer());

  ASSERT_TRUE(RunExtensionTest("tabs/on_updated")) << message_;
}
<commit_msg>Marked ExtensionApiTest.Tabs browsertest as flaky.<commit_after>// Copyright (c) 2010 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "chrome/browser/extensions/extension_apitest.h"

#include "chrome/browser/browser.h"
#include "chrome/browser/pref_service.h"
#include "chrome/browser/profile.h"
#include "chrome/common/pref_names.h"

// Tabs is flaky on chromeos debug build.
// http://crbug.com/48920
#if defined(OS_CHROMEOS) && !defined(NDEBUG)
#define MAYBE_Tabs FLAKY_Tabs
#else
#define MAYBE_Tabs Tabs
#endif

IN_PROC_BROWSER_TEST_F(ExtensionApiTest, MAYBE_Tabs) {
  ASSERT_TRUE(StartHTTPServer());

  // The test creates a tab and checks that the URL of the new tab
  // is that of the new tab page.  Make sure the pref that controls
  // this is set.
  browser()->profile()->GetPrefs()->SetBoolean(
      prefs::kHomePageIsNewTabPage, true);

  ASSERT_TRUE(RunExtensionTest("tabs/basics")) << message_;
}

IN_PROC_BROWSER_TEST_F(ExtensionApiTest, TabGetCurrent) {
  ASSERT_TRUE(StartHTTPServer());
  ASSERT_TRUE(RunExtensionTest("tabs/get_current")) << message_;
}

IN_PROC_BROWSER_TEST_F(ExtensionApiTest, TabConnect) {
  ASSERT_TRUE(StartHTTPServer());
  ASSERT_TRUE(RunExtensionTest("tabs/connect")) << message_;
}

IN_PROC_BROWSER_TEST_F(ExtensionApiTest, TabOnRemoved) {
  ASSERT_TRUE(StartHTTPServer());
  ASSERT_TRUE(RunExtensionTest("tabs/on_removed")) << message_;
}

IN_PROC_BROWSER_TEST_F(ExtensionApiTest, CaptureVisibleTab) {
  ASSERT_TRUE(StartHTTPServer());
  ASSERT_TRUE(RunExtensionTest("tabs/capture_visible_tab")) << message_;
}

IN_PROC_BROWSER_TEST_F(ExtensionApiTest, TabsOnUpdated) {
  ASSERT_TRUE(StartHTTPServer());

  ASSERT_TRUE(RunExtensionTest("tabs/on_updated")) << message_;
}
<|endoftext|>


<commit_before>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: anydata.cxx,v $
 *
 *  $Revision: 1.3 $
 *
 *  last change: $Author: hr $ $Date: 2006-06-19 23:22:20 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    This library is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *    Lesser General Public License for more details.
 *
 *    You should have received a copy of the GNU Lesser General Public
 *    License along with this library; if not, write to the Free Software
 *    Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/

#include "anydata.hxx"

#ifndef INCLUDED_SHARABLE_SEQUENCE_HXX
#include "sequence.hxx"
#endif
#ifndef INCLUDED_DATA_FLAGS_HXX
#include "flags.hxx"
#endif
#ifndef CONFIGMGR_UPDATEACCESSOR_HXX
#include "updateaccessor.hxx"
#endif

#ifndef CONFIGMGR_TYPECONVERTER_HXX
#include "typeconverter.hxx"
#endif

namespace configmgr
{
//-----------------------------------------------------------------------------
    namespace sharable
    {
//-----------------------------------------------------------------------------
        namespace Type = data::Type;
        namespace uno = ::com::sun::star::uno;
        typedef AnyData::TypeCode TypeCode;
        using memory::Pointer;
//-----------------------------------------------------------------------------

TypeCode getTypeCode(uno::Type const & _aType)
{
    switch (_aType.getTypeClass())
    {
    case uno::TypeClass_ANY:
    case uno::TypeClass_VOID:
        return Type::value_any;

    case uno::TypeClass_STRING:
        return Type::value_string;

    case uno::TypeClass_BOOLEAN:
        return Type::value_boolean;

    case uno::TypeClass_SHORT:
        return Type::value_short;

    case uno::TypeClass_LONG:
        return Type::value_int;

    case uno::TypeClass_HYPER:
        return Type::value_long;

    case uno::TypeClass_FLOAT:
    case uno::TypeClass_DOUBLE:
        return Type::value_double;

    case uno::TypeClass_SEQUENCE:
        {
            uno::Type aElementType = getSequenceElementType(_aType);

            if (aElementType.getTypeClass() == uno::TypeClass_BYTE)
                return Type::value_binary;

            OSL_ASSERT(aElementType != _aType); // would cause infinite recursion
            TypeCode aElementTC = getTypeCode(aElementType);

            OSL_ASSERT(Type::value_invalid & Type::flag_sequence); // ensure check works for invalid types

            if (aElementTC & Type::flag_sequence) // no sequence of sequence
                return Type::value_invalid;

            return TypeCode( aElementTC | Type::flag_sequence );
        }
    default:
        return Type::value_invalid;
    }
}
//-----------------------------------------------------------------------------

static uno::Type getUnoSimpleType( TypeCode _aSimpleType)
{
    OSL_ENSURE( _aSimpleType == (_aSimpleType & Type::mask_basetype), "Invalid type code" );

    switch (_aSimpleType)
    {
    case Type::value_string:
        return ::getCppuType(static_cast<rtl::OUString const *>(0));

    case Type::value_boolean:
        return ::getBooleanCppuType();

    case Type::value_short:
        return ::getCppuType(static_cast<sal_Int16 const *>(0));

    case Type::value_int:
        return ::getCppuType(static_cast<sal_Int32 const *>(0));

    case Type::value_long:
        return ::getCppuType(static_cast<sal_Int64 const *>(0));

    case Type::value_double:
        return ::getCppuType(static_cast<double const *>(0));

    case Type::value_binary:
        return ::getCppuType(static_cast<uno::Sequence<sal_Int8> const *>(0));

    case Type::value_any:
        //return ::getVoidCppuType();
        return ::getCppuType(static_cast<uno::Any const *>(0));

    default:
        OSL_ENSURE( false, "Invalid type code" );
        return ::getVoidCppuType();
    }
}
//-----------------------------------------------------------------------------

static uno::Type getUnoSequenceType( TypeCode _aSimpleType)
{
    OSL_ENSURE( _aSimpleType == (_aSimpleType & Type::mask_basetype), "Invalid type code" );

    switch (_aSimpleType)
    {
    case Type::value_string:
        return ::getCppuType(static_cast<uno::Sequence<rtl::OUString> const *>(0));

    case Type::value_boolean:
        return ::getCppuType(static_cast<uno::Sequence<sal_Bool> const *>(0));

    case Type::value_short:
        return ::getCppuType(static_cast<uno::Sequence<sal_Int16> const *>(0));

    case Type::value_int:
        return ::getCppuType(static_cast<uno::Sequence<sal_Int32> const *>(0));

    case Type::value_long:
        return ::getCppuType(static_cast<uno::Sequence<sal_Int64> const *>(0));

    case Type::value_double:
        return ::getCppuType(static_cast<uno::Sequence<double> const *>(0));

    case Type::value_binary:
        return ::getCppuType(static_cast<uno::Sequence<uno::Sequence<sal_Int8> > const *>(0));

    case Type::value_any: // results from value_invalid
    default:
        OSL_ENSURE( false, "Invalid type code" );
        return ::getVoidCppuType();
    }
}
//-----------------------------------------------------------------------------

uno::Type getUnoType( TypeCode _aType)
{
    OSL_ENSURE( _aType == (_aType & Type::mask_valuetype), "Invalid type code" );

    if (_aType & Type::flag_sequence)
        return getUnoSequenceType( TypeCode(_aType & Type::mask_basetype));

    else
        return getUnoSimpleType(_aType);
}
//-----------------------------------------------------------------------------

static
AnyData allocSimpleData(memory::Allocator const& _anAllocator, TypeCode _aSimpleType, uno::Any const & _aAny)
{
    OSL_ENSURE( _aSimpleType == (_aSimpleType & Type::mask_basetype), "Invalid type code" );

    AnyData aResult;
    aResult.data = 0;

    switch (_aSimpleType)
    {
    case Type::value_string:
        {
            rtl::OUString sValue;
            OSL_VERIFY(_aAny >>= sValue );
            aResult.stringValue = allocString(_anAllocator,sValue);
        }
        break;

    case Type::value_boolean:
        OSL_VERIFY(_aAny >>= aResult.boolValue );
        break;

    case Type::value_short:
        OSL_VERIFY(_aAny >>= aResult.shortValue);
        break;

    case Type::value_int:
        OSL_VERIFY(_aAny >>= aResult.intValue);
        break;

    case Type::value_long:
        {
            sal_Int64 nValue;
            OSL_VERIFY(_aAny >>= nValue);

            Address aStorage = _anAllocator.allocate( sizeof nValue );
            *static_cast<sal_Int64*>( _anAllocator.access(aStorage) ) = nValue;
            aResult.longValue = aStorage;
        }
        break;

    case Type::value_double:
        {
            double dValue;
            OSL_VERIFY(_aAny >>= dValue);

            Address aStorage = _anAllocator.allocate( sizeof dValue );
            *static_cast<double*>( _anAllocator.access(aStorage) ) = dValue;
            aResult.doubleValue = aStorage;
        }
        break;

    case Type::value_binary:
        {
            uno::Sequence<sal_Int8> aValue;
            OSL_VERIFY(_aAny >>= aValue);
            aResult.binaryValue = allocBinary(_anAllocator,aValue);
        }
        break;

    case Type::value_any:
        OSL_ENSURE( false, "Trying to allocate void value" );
        break;

    default:
        OSL_ENSURE( false, "Invalid type code" );
        break;
    }

    return aResult;
}
//-----------------------------------------------------------------------------

template <class E>
inline
sal_Sequence const * extractSequenceData(uno::Sequence< E > & _rSeq, uno::Any const & _aAny)
{
    if (_aAny >>= _rSeq)
    {
        return _rSeq.get();
    }

    else
    {
        OSL_ENSURE(false, "Could not extract sequence from Any");
        return NULL;
    }
}
//-----------------------------------------------------------------------------

static
AnyData allocSequenceData(memory::Allocator const& _anAllocator, TypeCode _aSimpleType, uno::Any const & _aAny)
{
    OSL_ENSURE( _aSimpleType == (_aSimpleType & Type::mask_basetype), "Invalid type code" );

    Sequence aSequence = 0;

    switch (_aSimpleType)
    {
    case Type::value_string:
        {
            uno::Sequence<rtl::OUString> aSeqValue;
            if (sal_Sequence const * pData = extractSequenceData(aSeqValue,_aAny))
                aSequence = allocSequence(_anAllocator,_aSimpleType,pData);
        }
        break;

    case Type::value_boolean:
        {
            uno::Sequence<sal_Bool> aSeqValue;
            if (sal_Sequence const * pData = extractSequenceData(aSeqValue,_aAny))
                aSequence = allocSequence(_anAllocator,_aSimpleType,pData);
        }
        break;

    case Type::value_short:
        {
            uno::Sequence<sal_Int16> aSeqValue;
            if (sal_Sequence const * pData = extractSequenceData(aSeqValue,_aAny))
                aSequence = allocSequence(_anAllocator,_aSimpleType,pData);
        }
        break;

    case Type::value_int:
        {
            uno::Sequence<sal_Int32> aSeqValue;
            if (sal_Sequence const * pData = extractSequenceData(aSeqValue,_aAny))
                aSequence = allocSequence(_anAllocator,_aSimpleType,pData);
        }
        break;

    case Type::value_long:
        {
            uno::Sequence<sal_Int64> aSeqValue;
            if (sal_Sequence const * pData = extractSequenceData(aSeqValue,_aAny))
                aSequence = allocSequence(_anAllocator,_aSimpleType,pData);
        }
        break;

    case Type::value_double:
        {
            uno::Sequence<double> aSeqValue;
            if (sal_Sequence const * pData = extractSequenceData(aSeqValue,_aAny))
                aSequence = allocSequence(_anAllocator,_aSimpleType,pData);
        }
        break;

    case Type::value_binary:
        {
            uno::Sequence<uno::Sequence<sal_Int8> > aSeqValue;
            if (sal_Sequence const * pData = extractSequenceData(aSeqValue,_aAny))
                aSequence = allocSequence(_anAllocator,_aSimpleType,pData);
        }
        break;

    case Type::value_any: // results from value_invalid
    default:
        OSL_ENSURE( false, "Invalid type code" );
        break;
    }

    AnyData aResult;
    aResult.sequenceValue = aSequence;
    return aResult;
}
//-----------------------------------------------------------------------------

AnyData allocData(memory::Allocator const& _anAllocator, TypeCode _aType, uno::Any const & _aAny)
{
    OSL_ENSURE( _aType == (_aType & Type::mask_valuetype), "Invalid type code" );
    OSL_ENSURE( _aType == getTypeCode(_aAny.getValueType()), "Type code does not match value" );

    if (_aType & Type::flag_sequence)
        return allocSequenceData(_anAllocator,TypeCode( _aType & Type::mask_basetype),_aAny);

    else
        return allocSimpleData(_anAllocator,_aType,_aAny);
}
//-----------------------------------------------------------------------------
/*
AnyData copyData(memory::Allocator const& _anAllocator, TypeCode _aType, AnyData _aData)
{
    OSL_ENSURE( _aType == (_aType & Type::mask_valuetype), "Invalid type code" );
}
*/
//-----------------------------------------------------------------------------

static
void freeSimpleData(memory::Allocator const& _anAllocator, TypeCode _aSimpleType, AnyData const & _aData)
{
    OSL_ENSURE( _aSimpleType == (_aSimpleType & Type::mask_basetype), "Invalid type code" );

    switch (_aSimpleType)
    {
    case Type::value_string:
        freeString(_anAllocator, _aData.stringValue);
        break;

    case Type::value_boolean:
    case Type::value_short:
    case Type::value_int:
        // nothing to do
        break;

        // free memory for oversized values
    case Type::value_long:
        _anAllocator.deallocate(_aData.longValue);
        break;

    case Type::value_double:
        _anAllocator.deallocate(_aData.doubleValue);
        break;

    case Type::value_binary:
        freeBinary(_anAllocator, _aData.binaryValue);
        break;

    case Type::value_any:
        // nothing to do for void value
        break;

    default:
        OSL_ENSURE( false, "Invalid type code" );
        break;
    }
}
//-----------------------------------------------------------------------------

void    freeData(memory::Allocator const& _anAllocator, TypeCode _aType, AnyData _aData)
{
    OSL_ENSURE( _aType == (_aType & Type::mask_valuetype), "Invalid type code" );

    if (_aType & Type::flag_sequence)
        freeSequence(_anAllocator,TypeCode(_aType & Type::mask_basetype),_aData.sequenceValue);

    else
        freeSimpleData(_anAllocator,_aType,_aData);
}
//-----------------------------------------------------------------------------

static
uno::Any readSimpleData(memory::Accessor const& _anAccessor, TypeCode _aSimpleType, AnyData const & _aData)
{
    OSL_ENSURE( _aSimpleType == (_aSimpleType & Type::mask_basetype), "Invalid type code" );

    switch (_aSimpleType)
    {
    case Type::value_string:
        {
            rtl::OUString sValue = readString(_anAccessor,_aData.stringValue);
            return uno::makeAny(sValue);
        }

    case Type::value_boolean:
        return uno::makeAny( _aData.boolValue );

    case Type::value_short:
        return uno::makeAny( _aData.shortValue );

    case Type::value_int:
        return uno::makeAny( _aData.intValue );

    case Type::value_long:
        {
            void const * pStorage = _anAccessor.validate( Pointer(_aData.longValue) );
            sal_Int64 const * pValue = static_cast<sal_Int64 const *>(pStorage);
            return uno::makeAny( *pValue );
        }

    case Type::value_double:
        {
            void const * pStorage = _anAccessor.validate( Pointer(_aData.doubleValue) );
            double const * pValue = static_cast<double const *>(pStorage);
            return uno::makeAny( *pValue );
        }

    case Type::value_binary:
        {
            uno::Sequence<sal_Int8> aValue = readBinary( _anAccessor, _aData.binaryValue );
            return uno::makeAny( aValue );
        }

    case Type::value_any: // void value
        return uno::Any();

    default:
        OSL_ENSURE( false, "Invalid type code" );
        return uno::Any();
    }
}
//-----------------------------------------------------------------------------

uno::Any readData(memory::Accessor const& _anAccessor, TypeCode _aType, AnyData _aData)
{
    OSL_ENSURE( _aType == (_aType & Type::mask_valuetype), "Invalid type code" );

    if (_aType & Type::flag_sequence)
        return readAnySequence(_anAccessor,TypeCode(_aType & Type::mask_basetype),_aData.sequenceValue);

    else
        return readSimpleData(_anAccessor,_aType,_aData);
}

//-----------------------------------------------------------------------------
    }
//-----------------------------------------------------------------------------
} // namespace

<commit_msg>INTEGRATION: CWS pchfix02 (1.3.18); FILE MERGED 2006/09/01 17:20:33 kaib 1.3.18.1: #i68856# Added header markers and pch files<commit_after>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: anydata.cxx,v $
 *
 *  $Revision: 1.4 $
 *
 *  last change: $Author: obo $ $Date: 2006-09-16 15:09:39 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    This library is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *    Lesser General Public License for more details.
 *
 *    You should have received a copy of the GNU Lesser General Public
 *    License along with this library; if not, write to the Free Software
 *    Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/

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

#include "anydata.hxx"

#ifndef INCLUDED_SHARABLE_SEQUENCE_HXX
#include "sequence.hxx"
#endif
#ifndef INCLUDED_DATA_FLAGS_HXX
#include "flags.hxx"
#endif
#ifndef CONFIGMGR_UPDATEACCESSOR_HXX
#include "updateaccessor.hxx"
#endif

#ifndef CONFIGMGR_TYPECONVERTER_HXX
#include "typeconverter.hxx"
#endif

namespace configmgr
{
//-----------------------------------------------------------------------------
    namespace sharable
    {
//-----------------------------------------------------------------------------
        namespace Type = data::Type;
        namespace uno = ::com::sun::star::uno;
        typedef AnyData::TypeCode TypeCode;
        using memory::Pointer;
//-----------------------------------------------------------------------------

TypeCode getTypeCode(uno::Type const & _aType)
{
    switch (_aType.getTypeClass())
    {
    case uno::TypeClass_ANY:
    case uno::TypeClass_VOID:
        return Type::value_any;

    case uno::TypeClass_STRING:
        return Type::value_string;

    case uno::TypeClass_BOOLEAN:
        return Type::value_boolean;

    case uno::TypeClass_SHORT:
        return Type::value_short;

    case uno::TypeClass_LONG:
        return Type::value_int;

    case uno::TypeClass_HYPER:
        return Type::value_long;

    case uno::TypeClass_FLOAT:
    case uno::TypeClass_DOUBLE:
        return Type::value_double;

    case uno::TypeClass_SEQUENCE:
        {
            uno::Type aElementType = getSequenceElementType(_aType);

            if (aElementType.getTypeClass() == uno::TypeClass_BYTE)
                return Type::value_binary;

            OSL_ASSERT(aElementType != _aType); // would cause infinite recursion
            TypeCode aElementTC = getTypeCode(aElementType);

            OSL_ASSERT(Type::value_invalid & Type::flag_sequence); // ensure check works for invalid types

            if (aElementTC & Type::flag_sequence) // no sequence of sequence
                return Type::value_invalid;

            return TypeCode( aElementTC | Type::flag_sequence );
        }
    default:
        return Type::value_invalid;
    }
}
//-----------------------------------------------------------------------------

static uno::Type getUnoSimpleType( TypeCode _aSimpleType)
{
    OSL_ENSURE( _aSimpleType == (_aSimpleType & Type::mask_basetype), "Invalid type code" );

    switch (_aSimpleType)
    {
    case Type::value_string:
        return ::getCppuType(static_cast<rtl::OUString const *>(0));

    case Type::value_boolean:
        return ::getBooleanCppuType();

    case Type::value_short:
        return ::getCppuType(static_cast<sal_Int16 const *>(0));

    case Type::value_int:
        return ::getCppuType(static_cast<sal_Int32 const *>(0));

    case Type::value_long:
        return ::getCppuType(static_cast<sal_Int64 const *>(0));

    case Type::value_double:
        return ::getCppuType(static_cast<double const *>(0));

    case Type::value_binary:
        return ::getCppuType(static_cast<uno::Sequence<sal_Int8> const *>(0));

    case Type::value_any:
        //return ::getVoidCppuType();
        return ::getCppuType(static_cast<uno::Any const *>(0));

    default:
        OSL_ENSURE( false, "Invalid type code" );
        return ::getVoidCppuType();
    }
}
//-----------------------------------------------------------------------------

static uno::Type getUnoSequenceType( TypeCode _aSimpleType)
{
    OSL_ENSURE( _aSimpleType == (_aSimpleType & Type::mask_basetype), "Invalid type code" );

    switch (_aSimpleType)
    {
    case Type::value_string:
        return ::getCppuType(static_cast<uno::Sequence<rtl::OUString> const *>(0));

    case Type::value_boolean:
        return ::getCppuType(static_cast<uno::Sequence<sal_Bool> const *>(0));

    case Type::value_short:
        return ::getCppuType(static_cast<uno::Sequence<sal_Int16> const *>(0));

    case Type::value_int:
        return ::getCppuType(static_cast<uno::Sequence<sal_Int32> const *>(0));

    case Type::value_long:
        return ::getCppuType(static_cast<uno::Sequence<sal_Int64> const *>(0));

    case Type::value_double:
        return ::getCppuType(static_cast<uno::Sequence<double> const *>(0));

    case Type::value_binary:
        return ::getCppuType(static_cast<uno::Sequence<uno::Sequence<sal_Int8> > const *>(0));

    case Type::value_any: // results from value_invalid
    default:
        OSL_ENSURE( false, "Invalid type code" );
        return ::getVoidCppuType();
    }
}
//-----------------------------------------------------------------------------

uno::Type getUnoType( TypeCode _aType)
{
    OSL_ENSURE( _aType == (_aType & Type::mask_valuetype), "Invalid type code" );

    if (_aType & Type::flag_sequence)
        return getUnoSequenceType( TypeCode(_aType & Type::mask_basetype));

    else
        return getUnoSimpleType(_aType);
}
//-----------------------------------------------------------------------------

static
AnyData allocSimpleData(memory::Allocator const& _anAllocator, TypeCode _aSimpleType, uno::Any const & _aAny)
{
    OSL_ENSURE( _aSimpleType == (_aSimpleType & Type::mask_basetype), "Invalid type code" );

    AnyData aResult;
    aResult.data = 0;

    switch (_aSimpleType)
    {
    case Type::value_string:
        {
            rtl::OUString sValue;
            OSL_VERIFY(_aAny >>= sValue );
            aResult.stringValue = allocString(_anAllocator,sValue);
        }
        break;

    case Type::value_boolean:
        OSL_VERIFY(_aAny >>= aResult.boolValue );
        break;

    case Type::value_short:
        OSL_VERIFY(_aAny >>= aResult.shortValue);
        break;

    case Type::value_int:
        OSL_VERIFY(_aAny >>= aResult.intValue);
        break;

    case Type::value_long:
        {
            sal_Int64 nValue;
            OSL_VERIFY(_aAny >>= nValue);

            Address aStorage = _anAllocator.allocate( sizeof nValue );
            *static_cast<sal_Int64*>( _anAllocator.access(aStorage) ) = nValue;
            aResult.longValue = aStorage;
        }
        break;

    case Type::value_double:
        {
            double dValue;
            OSL_VERIFY(_aAny >>= dValue);

            Address aStorage = _anAllocator.allocate( sizeof dValue );
            *static_cast<double*>( _anAllocator.access(aStorage) ) = dValue;
            aResult.doubleValue = aStorage;
        }
        break;

    case Type::value_binary:
        {
            uno::Sequence<sal_Int8> aValue;
            OSL_VERIFY(_aAny >>= aValue);
            aResult.binaryValue = allocBinary(_anAllocator,aValue);
        }
        break;

    case Type::value_any:
        OSL_ENSURE( false, "Trying to allocate void value" );
        break;

    default:
        OSL_ENSURE( false, "Invalid type code" );
        break;
    }

    return aResult;
}
//-----------------------------------------------------------------------------

template <class E>
inline
sal_Sequence const * extractSequenceData(uno::Sequence< E > & _rSeq, uno::Any const & _aAny)
{
    if (_aAny >>= _rSeq)
    {
        return _rSeq.get();
    }

    else
    {
        OSL_ENSURE(false, "Could not extract sequence from Any");
        return NULL;
    }
}
//-----------------------------------------------------------------------------

static
AnyData allocSequenceData(memory::Allocator const& _anAllocator, TypeCode _aSimpleType, uno::Any const & _aAny)
{
    OSL_ENSURE( _aSimpleType == (_aSimpleType & Type::mask_basetype), "Invalid type code" );

    Sequence aSequence = 0;

    switch (_aSimpleType)
    {
    case Type::value_string:
        {
            uno::Sequence<rtl::OUString> aSeqValue;
            if (sal_Sequence const * pData = extractSequenceData(aSeqValue,_aAny))
                aSequence = allocSequence(_anAllocator,_aSimpleType,pData);
        }
        break;

    case Type::value_boolean:
        {
            uno::Sequence<sal_Bool> aSeqValue;
            if (sal_Sequence const * pData = extractSequenceData(aSeqValue,_aAny))
                aSequence = allocSequence(_anAllocator,_aSimpleType,pData);
        }
        break;

    case Type::value_short:
        {
            uno::Sequence<sal_Int16> aSeqValue;
            if (sal_Sequence const * pData = extractSequenceData(aSeqValue,_aAny))
                aSequence = allocSequence(_anAllocator,_aSimpleType,pData);
        }
        break;

    case Type::value_int:
        {
            uno::Sequence<sal_Int32> aSeqValue;
            if (sal_Sequence const * pData = extractSequenceData(aSeqValue,_aAny))
                aSequence = allocSequence(_anAllocator,_aSimpleType,pData);
        }
        break;

    case Type::value_long:
        {
            uno::Sequence<sal_Int64> aSeqValue;
            if (sal_Sequence const * pData = extractSequenceData(aSeqValue,_aAny))
                aSequence = allocSequence(_anAllocator,_aSimpleType,pData);
        }
        break;

    case Type::value_double:
        {
            uno::Sequence<double> aSeqValue;
            if (sal_Sequence const * pData = extractSequenceData(aSeqValue,_aAny))
                aSequence = allocSequence(_anAllocator,_aSimpleType,pData);
        }
        break;

    case Type::value_binary:
        {
            uno::Sequence<uno::Sequence<sal_Int8> > aSeqValue;
            if (sal_Sequence const * pData = extractSequenceData(aSeqValue,_aAny))
                aSequence = allocSequence(_anAllocator,_aSimpleType,pData);
        }
        break;

    case Type::value_any: // results from value_invalid
    default:
        OSL_ENSURE( false, "Invalid type code" );
        break;
    }

    AnyData aResult;
    aResult.sequenceValue = aSequence;
    return aResult;
}
//-----------------------------------------------------------------------------

AnyData allocData(memory::Allocator const& _anAllocator, TypeCode _aType, uno::Any const & _aAny)
{
    OSL_ENSURE( _aType == (_aType & Type::mask_valuetype), "Invalid type code" );
    OSL_ENSURE( _aType == getTypeCode(_aAny.getValueType()), "Type code does not match value" );

    if (_aType & Type::flag_sequence)
        return allocSequenceData(_anAllocator,TypeCode( _aType & Type::mask_basetype),_aAny);

    else
        return allocSimpleData(_anAllocator,_aType,_aAny);
}
//-----------------------------------------------------------------------------
/*
AnyData copyData(memory::Allocator const& _anAllocator, TypeCode _aType, AnyData _aData)
{
    OSL_ENSURE( _aType == (_aType & Type::mask_valuetype), "Invalid type code" );
}
*/
//-----------------------------------------------------------------------------

static
void freeSimpleData(memory::Allocator const& _anAllocator, TypeCode _aSimpleType, AnyData const & _aData)
{
    OSL_ENSURE( _aSimpleType == (_aSimpleType & Type::mask_basetype), "Invalid type code" );

    switch (_aSimpleType)
    {
    case Type::value_string:
        freeString(_anAllocator, _aData.stringValue);
        break;

    case Type::value_boolean:
    case Type::value_short:
    case Type::value_int:
        // nothing to do
        break;

        // free memory for oversized values
    case Type::value_long:
        _anAllocator.deallocate(_aData.longValue);
        break;

    case Type::value_double:
        _anAllocator.deallocate(_aData.doubleValue);
        break;

    case Type::value_binary:
        freeBinary(_anAllocator, _aData.binaryValue);
        break;

    case Type::value_any:
        // nothing to do for void value
        break;

    default:
        OSL_ENSURE( false, "Invalid type code" );
        break;
    }
}
//-----------------------------------------------------------------------------

void    freeData(memory::Allocator const& _anAllocator, TypeCode _aType, AnyData _aData)
{
    OSL_ENSURE( _aType == (_aType & Type::mask_valuetype), "Invalid type code" );

    if (_aType & Type::flag_sequence)
        freeSequence(_anAllocator,TypeCode(_aType & Type::mask_basetype),_aData.sequenceValue);

    else
        freeSimpleData(_anAllocator,_aType,_aData);
}
//-----------------------------------------------------------------------------

static
uno::Any readSimpleData(memory::Accessor const& _anAccessor, TypeCode _aSimpleType, AnyData const & _aData)
{
    OSL_ENSURE( _aSimpleType == (_aSimpleType & Type::mask_basetype), "Invalid type code" );

    switch (_aSimpleType)
    {
    case Type::value_string:
        {
            rtl::OUString sValue = readString(_anAccessor,_aData.stringValue);
            return uno::makeAny(sValue);
        }

    case Type::value_boolean:
        return uno::makeAny( _aData.boolValue );

    case Type::value_short:
        return uno::makeAny( _aData.shortValue );

    case Type::value_int:
        return uno::makeAny( _aData.intValue );

    case Type::value_long:
        {
            void const * pStorage = _anAccessor.validate( Pointer(_aData.longValue) );
            sal_Int64 const * pValue = static_cast<sal_Int64 const *>(pStorage);
            return uno::makeAny( *pValue );
        }

    case Type::value_double:
        {
            void const * pStorage = _anAccessor.validate( Pointer(_aData.doubleValue) );
            double const * pValue = static_cast<double const *>(pStorage);
            return uno::makeAny( *pValue );
        }

    case Type::value_binary:
        {
            uno::Sequence<sal_Int8> aValue = readBinary( _anAccessor, _aData.binaryValue );
            return uno::makeAny( aValue );
        }

    case Type::value_any: // void value
        return uno::Any();

    default:
        OSL_ENSURE( false, "Invalid type code" );
        return uno::Any();
    }
}
//-----------------------------------------------------------------------------

uno::Any readData(memory::Accessor const& _anAccessor, TypeCode _aType, AnyData _aData)
{
    OSL_ENSURE( _aType == (_aType & Type::mask_valuetype), "Invalid type code" );

    if (_aType & Type::flag_sequence)
        return readAnySequence(_anAccessor,TypeCode(_aType & Type::mask_basetype),_aData.sequenceValue);

    else
        return readSimpleData(_anAccessor,_aType,_aData);
}

//-----------------------------------------------------------------------------
    }
//-----------------------------------------------------------------------------
} // namespace

<|endoftext|>