<commit_before>#include "MaxRectsBinaryPack2.h"
#include "math.h"

#include <ee/std_functor.h>
#include <ee/math_common.h>

#include <assert.h>

namespace etexpacker
{

static const float SCALE = 1.0f;
static const int PADDING = 0;

MaxRectsBinaryPack2::MaxRectsBinaryPack2()
{
}

MaxRectsBinaryPack2::~MaxRectsBinaryPack2()
{
	for_each(m_roots.begin(), m_roots.end(), ee::DeletePointerFunctor<ee::TPNode>());
}

void MaxRectsBinaryPack2::GetSize(std::vector<RectSize>& sizes) const
{
	for (int i = 0, n = m_roots.size(); i < n; ++i) {
		ee::TPNode* root = m_roots[i];
		sizes.push_back(RectSize(root->GetWidth(), root->GetHeight()));
	}
}

void MaxRectsBinaryPack2::Pack(PACK_STRATEGY strategy, int static_size, int max_size,
							   int min_size, const std::vector<RectSize>& rects, std::vector<Rect>& output)
{
	if (rects.empty()) {
		return;
	}

	// prepare data
	int sz = rects.size();
	output.clear();
	output.resize(sz);

	std::vector<Sprite> sprs;
	sprs.reserve(sz);
	for (int i = 0; i < sz; ++i) {
		sprs.push_back(Sprite(&rects[i], &output[i]));
	}
	std::sort(sprs.begin(), sprs.end(), SpriteCmp(e_max_edge));

	// compute area
	int area = 0;
	for (int i = 0; i < sz; ++i) {
		area += rects[i].width * rects[i].height;
	}

	switch(strategy)
	{
	case PACK_AUTO:
		PackAuto(sprs, area);
		break;
	case PACK_SQUARE:
		PackSquare(sprs, area);
		break;
	case PACK_SQUARE_MULTI:
		PackSquareMulti(sprs, static_size);
		break;
	case PACK_SQUARE_MULTI_AUTO:
		PackSquareMultiAuto(sprs, area, max_size, min_size);
		break;
	default:
		output.clear();
	}
}

ee::TPNode* MaxRectsBinaryPack2::NewRoot(int w, int h)
{
	ee::TPNode* root = new ee::TPNode(w, h);
	ee::TPNode* c = new ee::TPNode(w, h);
	root->SetChild(c);
	return root;
}

bool MaxRectsBinaryPack2::Insert(ee::TPNode* root, const Sprite* spr, int tex_id) const
{
	ee::TPNode* n = NULL;
	int w = static_cast<int>(spr->size->width * SCALE + PADDING * 2),
		h = static_cast<int>(spr->size->height * SCALE + PADDING * 2);
	float scale = 1.0f;

	bool rot = false;
	if (h > w) {
		rot = true ;
	}

	if (rot)
	{
		if (root->IsRoomEnough(h, w)) {
			n = root->Insert(h, w);
		} else {
			rot = !rot;
			n = root->Insert(w, h);
		}
	}
	else
	{
		if (root->IsRoomEnough(w, h)) {
			n = root->Insert(w, h);
		} else {
			rot = !rot;
			n = root->Insert(h, w);
		}
	}

	if (!n) {
		return false;
	} else {
		spr->pos->tex_id = tex_id;
		spr->pos->x = n->GetMinX() + PADDING;
		spr->pos->y = n->GetMinY() + PADDING;
		if (n->IsRotated() && !rot || !n->IsRotated() && rot) {
			spr->pos->width = h - PADDING * 2;
			spr->pos->height = w - PADDING * 2;
		} else {
			spr->pos->width = w - PADDING * 2;
			spr->pos->height = h - PADDING * 2;
		}
		return true;
	}
}

void MaxRectsBinaryPack2::PackAuto(const std::vector<Sprite>& sprs, int area)
{
	int edge = ee::next_p2((int)ceil(sqrt((float)area)));
	int w = edge, h = (edge >> 1);

	bool success = false;
	while (!success)
	{
		ee::TPNode* root = NewRoot(w, h);
		for (int i = 0, n = sprs.size(); i < n; ++i) {
			success = Insert(root, &sprs[i]);
			if (!success) {
				break;
			}
		}

		if (success) {
			m_roots.push_back(root);
		} else {
			delete root;
		}

 		if (w == h) {
 			w *= 2;
 		} else if (w == h * 2) {
 			w /= 2;
 			h *= 2;
 		} else {
 			assert(h == w * 2);
 			w *= 2;
 		}
	}
}

void MaxRectsBinaryPack2::PackSquare(const std::vector<Sprite>& sprs, int area)
{
	int edge = ee::next_p2((int)ceil(sqrt((float)area)));
	bool success = false;
	while (!success)
	{
		ee::TPNode* root = NewRoot(edge, edge);
		for (int i = 0, n = sprs.size(); i < n; ++i) {
			success = Insert(root, &sprs[i]);
			if (!success) {
				break;
			}
		}

		if (success) {
			m_roots.push_back(root);
		} else {
			delete root;
		}

		edge *= 2;
	}
}

static inline
int CalArea(const std::vector<Sprite>& list) {
	int area = 0;
	for (int i = 0, n = list.size(); i < n; ++i) {
		area += list[i].pos->width * list[i].pos->height;
	}
	return area;
}

void MaxRectsBinaryPack2::PackSquareMulti(std::vector<Sprite>& sprs, int static_size)
{
	std::vector<Sprite> curr_list = sprs;

	int curr_tex = 0;
	while (!curr_list.empty())
	{
		std::vector<Sprite> success_list, fail_list;

		ee::TPNode* root = NewRoot(static_size, static_size);
		for (int i = 0, n = curr_list.size(); i < n; ++i)
		{
			const Sprite& spr = curr_list[i];
			bool success = Insert(root, &spr, m_roots.size());
			if (success) {
				spr.pos->tex_id = curr_tex;
				success_list.push_back(spr);
			} else {
				fail_list.push_back(spr);
			}
		}

		curr_list = fail_list;
		m_roots.push_back(root);
		++curr_tex;
	}
}

void MaxRectsBinaryPack2::PackSquareMultiAuto(std::vector<Sprite>& sprs, int area,
											  int max_size, int min_size)
{
	if (sprs.empty()) {
		return;
	}

	static const float AREA_SCALE_LIMIT = 0.8f;
	static const float AREA_SCALE_LIMIT_STEP = 0.05f;

//	static const float AREA_LIMIT = 64 * 64;
	static const int EDGE_LIMIT = 128;
	static const int LEFT_AREA_LIMIT = 25000;

	float area_scale_limit = AREA_SCALE_LIMIT;

	int edge = std::max(std::min(ee::next_p2((int)ceil(sqrt((float)area))), max_size), min_size);
	int need_edge = ee::next_p2(std::max(sprs[0].size->width, sprs[0].size->height));
	if (edge == need_edge) {
		area_scale_limit = 0;
	}

	std::vector<Sprite> curr_list = sprs;

	float fail_scale = -1;

	int curr_tex = 0;
	while (!curr_list.empty())
	{
		std::vector<Sprite> success_list, fail_list;

		ee::TPNode* root = NewRoot(edge, edge);
		for (int i = 0, n = curr_list.size(); i < n; ++i)
		{
			const Sprite& spr = curr_list[i];
			bool success = Insert(root, &spr, m_roots.size());
			if (success) {
				spr.pos->tex_id = curr_tex;
				success_list.push_back(spr);
			} else {
				fail_list.push_back(spr);
			}
		}

		int used_area = CalArea(success_list);
		float used_area_rate = (float)used_area / (edge*edge);
		int left_area = edge*edge - used_area;
		if (success_list.empty() || used_area_rate < fail_scale)
		{
			if (edge * 2 <= max_size) {
				edge *= 2;
			} else {
				edge = max_size;
			}
			delete root;
		}
		else if (used_area_rate > area_scale_limit || edge < EDGE_LIMIT/* || left_area < LEFT_AREA_LIMIT*/)
		{
			fail_scale = -1;
			area_scale_limit = std::min(area_scale_limit * (1 + AREA_SCALE_LIMIT_STEP), AREA_SCALE_LIMIT);
			curr_list = fail_list;
			area = area - used_area;
			edge = std::max(std::min(ee::next_p2((int)ceil(sqrt((float)area))), max_size), min_size);
			m_roots.push_back(root);
			++curr_tex;
		}
		else
		{
			fail_scale = used_area_rate;
			area_scale_limit *= (1 - AREA_SCALE_LIMIT_STEP);
			edge = std::max(edge / 2, min_size);
			delete root;
		}
	}

	MergeSquareMultiAuto(sprs, max_size);
}

bool MaxRectsBinaryPack2::MergeSquareMultiAuto(std::vector<Sprite>& sprs, int max_size)
{
	std::vector<int> ids;
	int count = 0;
	for (int i = 0, n = m_roots.size(); i < n; ++i) {
		ee::TPNode* n0 = m_roots[i];
		if (n0->GetWidth() * 2 >= max_size || n0->GetHeight() * 2 >= max_size) {
			continue;
		}
		ids.push_back(i);
		for (int j = 0, m = m_roots.size(); j < m; ++j) {
			ee::TPNode* n1 = m_roots[j];
			if (n1->GetWidth() * 2 >= max_size || n1->GetHeight() * 2 >= max_size) {
				continue;
			}
			if (j != i && n0->GetWidth() == n1->GetWidth() && n0->GetHeight() == n1->GetHeight()) {
				ids.push_back(j);
			}
		}
		if (ids.size() >= 4) {
			break;
		} else {
			ids.clear();
		}
	}
	if (ids.size() < 4) {
		return false;
	}

	std::vector<ee::TPNode*> remove_nodes;

	std::vector<int> map_id;
	ee::TPNode* new_root = NewRoot(m_roots[ids[0]]->GetWidth() * 2, m_roots[ids[0]]->GetHeight() * 2);
	std::vector<ee::TPNode*> new_roots;
	for (int i = 0, n = m_roots.size(); i < n; ++i) {
		if (i != ids[0] && i != ids[1] && i != ids[2] && i != ids[3]) {
			map_id.push_back(new_roots.size());
			new_roots.push_back(m_roots[i]);
		} else {
			remove_nodes.push_back(m_roots[i]);
			map_id.push_back(m_roots.size() - 4);
		}
	}
	new_roots.push_back(new_root);

	std::vector<Rect> tmp_rects;
	tmp_rects.reserve(sprs.size());
	for (int i = 0, n = sprs.size(); i < n; ++i) {
		const Sprite& spr = sprs[i];
		tmp_rects.push_back(*spr.pos);
		if (spr.pos->tex_id == ids[0] || spr.pos->tex_id == ids[1] ||
			spr.pos->tex_id == ids[2] || spr.pos->tex_id == ids[3]) {
			bool success = Insert(new_root, &spr, m_roots.size() - 4);
			if (!success) {
				// todo
				for (int i = 0, n = tmp_rects.size(); i < n; ++i) {
					*sprs[i].pos = tmp_rects[i];
				}
				delete new_root;
				return false;
			}
		} else {
			spr.pos->tex_id = map_id[spr.pos->tex_id];
		}
	}

	m_roots = new_roots;
	for (int i = 0, n = remove_nodes.size(); i < n; ++i) {
		delete remove_nodes[i];
	}

	MergeSquareMultiAuto(sprs, max_size);
	return true;
}

void MaxRectsBinaryPack2::SortRoots(const std::vector<Sprite>& sprs)
{
	std::vector<ee::TPNode*> sorted(m_roots);
	std::sort(sorted.begin(), sorted.end(), NodeCmp());
	std::vector<int> map_id;
	for (int i = 0, n = m_roots.size(); i < n; ++i) {
		for (int j = 0, m = sorted.size(); j < m; ++j) {
			if (m_roots[i] == sorted[j]) {
				map_id.push_back(j);
				break;
			}
		}
	}
	assert(map_id.size() == m_roots.size());

	m_roots = sorted;
	for (int i = 0, n = sprs.size(); i < n; ++i) {
		sprs[i].pos->tex_id = map_id[sprs[i].pos->tex_id];
	}
}

bool MaxRectsBinaryPack2::NodeCmp::operator() (const ee::TPNode* n0, ee::TPNode* n1) const
{
	return n0->GetWidth() * n0->GetHeight() > n1->GetWidth() * n1->GetHeight();
}

}<commit_msg>[FIXED] tex pack, min edge<commit_after>#include "MaxRectsBinaryPack2.h"
#include "math.h"

#include <ee/std_functor.h>
#include <ee/math_common.h>

#include <assert.h>

namespace etexpacker
{

static const float SCALE = 1.0f;
static const int PADDING = 0;

MaxRectsBinaryPack2::MaxRectsBinaryPack2()
{
}

MaxRectsBinaryPack2::~MaxRectsBinaryPack2()
{
	for_each(m_roots.begin(), m_roots.end(), ee::DeletePointerFunctor<ee::TPNode>());
}

void MaxRectsBinaryPack2::GetSize(std::vector<RectSize>& sizes) const
{
	for (int i = 0, n = m_roots.size(); i < n; ++i) {
		ee::TPNode* root = m_roots[i];
		sizes.push_back(RectSize(root->GetWidth(), root->GetHeight()));
	}
}

void MaxRectsBinaryPack2::Pack(PACK_STRATEGY strategy, int static_size, int max_size,
							   int min_size, const std::vector<RectSize>& rects, std::vector<Rect>& output)
{
	if (rects.empty()) {
		return;
	}

	// prepare data
	int sz = rects.size();
	output.clear();
	output.resize(sz);

	std::vector<Sprite> sprs;
	sprs.reserve(sz);
	for (int i = 0; i < sz; ++i) {
		sprs.push_back(Sprite(&rects[i], &output[i]));
	}
	std::sort(sprs.begin(), sprs.end(), SpriteCmp(e_max_edge));

	// compute area
	int area = 0;
	for (int i = 0; i < sz; ++i) {
		area += rects[i].width * rects[i].height;
	}

	switch(strategy)
	{
	case PACK_AUTO:
		PackAuto(sprs, area);
		break;
	case PACK_SQUARE:
		PackSquare(sprs, area);
		break;
	case PACK_SQUARE_MULTI:
		PackSquareMulti(sprs, static_size);
		break;
	case PACK_SQUARE_MULTI_AUTO:
		PackSquareMultiAuto(sprs, area, max_size, min_size);
		break;
	default:
		output.clear();
	}
}

ee::TPNode* MaxRectsBinaryPack2::NewRoot(int w, int h)
{
	ee::TPNode* root = new ee::TPNode(w, h);
	ee::TPNode* c = new ee::TPNode(w, h);
	root->SetChild(c);
	return root;
}

bool MaxRectsBinaryPack2::Insert(ee::TPNode* root, const Sprite* spr, int tex_id) const
{
	ee::TPNode* n = NULL;
	int w = static_cast<int>(spr->size->width * SCALE + PADDING * 2),
		h = static_cast<int>(spr->size->height * SCALE + PADDING * 2);
	float scale = 1.0f;

	bool rot = false;
	if (h > w) {
		rot = true ;
	}

	if (rot)
	{
		if (root->IsRoomEnough(h, w)) {
			n = root->Insert(h, w);
		} else {
			rot = !rot;
			n = root->Insert(w, h);
		}
	}
	else
	{
		if (root->IsRoomEnough(w, h)) {
			n = root->Insert(w, h);
		} else {
			rot = !rot;
			n = root->Insert(h, w);
		}
	}

	if (!n) {
		return false;
	} else {
		spr->pos->tex_id = tex_id;
		spr->pos->x = n->GetMinX() + PADDING;
		spr->pos->y = n->GetMinY() + PADDING;
		if (n->IsRotated() && !rot || !n->IsRotated() && rot) {
			spr->pos->width = h - PADDING * 2;
			spr->pos->height = w - PADDING * 2;
		} else {
			spr->pos->width = w - PADDING * 2;
			spr->pos->height = h - PADDING * 2;
		}
		return true;
	}
}

void MaxRectsBinaryPack2::PackAuto(const std::vector<Sprite>& sprs, int area)
{
	int edge = ee::next_p2((int)ceil(sqrt((float)area)));
	int w = edge, h = (edge >> 1);

	bool success = false;
	while (!success)
	{
		ee::TPNode* root = NewRoot(w, h);
		for (int i = 0, n = sprs.size(); i < n; ++i) {
			success = Insert(root, &sprs[i]);
			if (!success) {
				break;
			}
		}

		if (success) {
			m_roots.push_back(root);
		} else {
			delete root;
		}

 		if (w == h) {
 			w *= 2;
 		} else if (w == h * 2) {
 			w /= 2;
 			h *= 2;
 		} else {
 			assert(h == w * 2);
 			w *= 2;
 		}
	}
}

void MaxRectsBinaryPack2::PackSquare(const std::vector<Sprite>& sprs, int area)
{
	int edge = ee::next_p2((int)ceil(sqrt((float)area)));
	bool success = false;
	while (!success)
	{
		ee::TPNode* root = NewRoot(edge, edge);
		for (int i = 0, n = sprs.size(); i < n; ++i) {
			success = Insert(root, &sprs[i]);
			if (!success) {
				break;
			}
		}

		if (success) {
			m_roots.push_back(root);
		} else {
			delete root;
		}

		edge *= 2;
	}
}

static inline
int CalArea(const std::vector<Sprite>& list) {
	int area = 0;
	for (int i = 0, n = list.size(); i < n; ++i) {
		area += list[i].pos->width * list[i].pos->height;
	}
	return area;
}

void MaxRectsBinaryPack2::PackSquareMulti(std::vector<Sprite>& sprs, int static_size)
{
	std::vector<Sprite> curr_list = sprs;

	int curr_tex = 0;
	while (!curr_list.empty())
	{
		std::vector<Sprite> success_list, fail_list;

		ee::TPNode* root = NewRoot(static_size, static_size);
		for (int i = 0, n = curr_list.size(); i < n; ++i)
		{
			const Sprite& spr = curr_list[i];
			bool success = Insert(root, &spr, m_roots.size());
			if (success) {
				spr.pos->tex_id = curr_tex;
				success_list.push_back(spr);
			} else {
				fail_list.push_back(spr);
			}
		}

		curr_list = fail_list;
		m_roots.push_back(root);
		++curr_tex;
	}
}

void MaxRectsBinaryPack2::PackSquareMultiAuto(std::vector<Sprite>& sprs, int area,
											  int max_size, int min_size)
{
	if (sprs.empty()) {
		return;
	}

	static const float AREA_SCALE_LIMIT = 0.8f;
	static const float AREA_SCALE_LIMIT_STEP = 0.05f;

//	static const float AREA_LIMIT = 64 * 64;
	static const int EDGE_LIMIT = 128;
	static const int LEFT_AREA_LIMIT = 25000;

	float area_scale_limit = AREA_SCALE_LIMIT;

	int edge = std::max(std::min(ee::next_p2((int)ceil(sqrt((float)area))), max_size), min_size);
	for (auto& spr : sprs) {
		edge = std::max(edge, ee::next_p2(spr.size->width));
		edge = std::max(edge, ee::next_p2(spr.size->height));
	}
	int need_edge = ee::next_p2(std::max(sprs[0].size->width, sprs[0].size->height));
	if (edge == need_edge) {
		area_scale_limit = 0;
	}

	std::vector<Sprite> curr_list = sprs;

	float fail_scale = -1;

	int curr_tex = 0;
	while (!curr_list.empty())
	{
		std::vector<Sprite> success_list, fail_list;

		ee::TPNode* root = NewRoot(edge, edge);
		for (int i = 0, n = curr_list.size(); i < n; ++i)
		{
			const Sprite& spr = curr_list[i];
			bool success = Insert(root, &spr, m_roots.size());
			if (success) {
				spr.pos->tex_id = curr_tex;
				success_list.push_back(spr);
			} else {
				fail_list.push_back(spr);
			}
		}

		int used_area = CalArea(success_list);
		float used_area_rate = (float)used_area / (edge*edge);
		int left_area = edge*edge - used_area;
		if (success_list.empty() || used_area_rate < fail_scale)
		{
			if (edge * 2 <= max_size) {
				edge *= 2;
			} else {
				edge = max_size;
			}
			delete root;
		}
		else if (used_area_rate > area_scale_limit || edge < EDGE_LIMIT/* || left_area < LEFT_AREA_LIMIT*/)
		{
			fail_scale = -1;
			area_scale_limit = std::min(area_scale_limit * (1 + AREA_SCALE_LIMIT_STEP), AREA_SCALE_LIMIT);
			curr_list = fail_list;
			area = area - used_area;
			edge = std::max(std::min(ee::next_p2((int)ceil(sqrt((float)area))), max_size), min_size);
			m_roots.push_back(root);
			++curr_tex;
		}
		else
		{
			fail_scale = used_area_rate;
			area_scale_limit *= (1 - AREA_SCALE_LIMIT_STEP);
			edge = std::max(edge / 2, min_size);
			delete root;
		}
	}

	MergeSquareMultiAuto(sprs, max_size);
}

bool MaxRectsBinaryPack2::MergeSquareMultiAuto(std::vector<Sprite>& sprs, int max_size)
{
	std::vector<int> ids;
	int count = 0;
	for (int i = 0, n = m_roots.size(); i < n; ++i) {
		ee::TPNode* n0 = m_roots[i];
		if (n0->GetWidth() * 2 >= max_size || n0->GetHeight() * 2 >= max_size) {
			continue;
		}
		ids.push_back(i);
		for (int j = 0, m = m_roots.size(); j < m; ++j) {
			ee::TPNode* n1 = m_roots[j];
			if (n1->GetWidth() * 2 >= max_size || n1->GetHeight() * 2 >= max_size) {
				continue;
			}
			if (j != i && n0->GetWidth() == n1->GetWidth() && n0->GetHeight() == n1->GetHeight()) {
				ids.push_back(j);
			}
		}
		if (ids.size() >= 4) {
			break;
		} else {
			ids.clear();
		}
	}
	if (ids.size() < 4) {
		return false;
	}

	std::vector<ee::TPNode*> remove_nodes;

	std::vector<int> map_id;
	ee::TPNode* new_root = NewRoot(m_roots[ids[0]]->GetWidth() * 2, m_roots[ids[0]]->GetHeight() * 2);
	std::vector<ee::TPNode*> new_roots;
	for (int i = 0, n = m_roots.size(); i < n; ++i) {
		if (i != ids[0] && i != ids[1] && i != ids[2] && i != ids[3]) {
			map_id.push_back(new_roots.size());
			new_roots.push_back(m_roots[i]);
		} else {
			remove_nodes.push_back(m_roots[i]);
			map_id.push_back(m_roots.size() - 4);
		}
	}
	new_roots.push_back(new_root);

	std::vector<Rect> tmp_rects;
	tmp_rects.reserve(sprs.size());
	for (int i = 0, n = sprs.size(); i < n; ++i) {
		const Sprite& spr = sprs[i];
		tmp_rects.push_back(*spr.pos);
		if (spr.pos->tex_id == ids[0] || spr.pos->tex_id == ids[1] ||
			spr.pos->tex_id == ids[2] || spr.pos->tex_id == ids[3]) {
			bool success = Insert(new_root, &spr, m_roots.size() - 4);
			if (!success) {
				// todo
				for (int i = 0, n = tmp_rects.size(); i < n; ++i) {
					*sprs[i].pos = tmp_rects[i];
				}
				delete new_root;
				return false;
			}
		} else {
			spr.pos->tex_id = map_id[spr.pos->tex_id];
		}
	}

	m_roots = new_roots;
	for (int i = 0, n = remove_nodes.size(); i < n; ++i) {
		delete remove_nodes[i];
	}

	MergeSquareMultiAuto(sprs, max_size);
	return true;
}

void MaxRectsBinaryPack2::SortRoots(const std::vector<Sprite>& sprs)
{
	std::vector<ee::TPNode*> sorted(m_roots);
	std::sort(sorted.begin(), sorted.end(), NodeCmp());
	std::vector<int> map_id;
	for (int i = 0, n = m_roots.size(); i < n; ++i) {
		for (int j = 0, m = sorted.size(); j < m; ++j) {
			if (m_roots[i] == sorted[j]) {
				map_id.push_back(j);
				break;
			}
		}
	}
	assert(map_id.size() == m_roots.size());

	m_roots = sorted;
	for (int i = 0, n = sprs.size(); i < n; ++i) {
		sprs[i].pos->tex_id = map_id[sprs[i].pos->tex_id];
	}
}

bool MaxRectsBinaryPack2::NodeCmp::operator() (const ee::TPNode* n0, ee::TPNode* n1) const
{
	return n0->GetWidth() * n0->GetHeight() > n1->GetWidth() * n1->GetHeight();
}

}<|endoftext|>


<commit_before>#include <iostream>

using namespace std;
struct Value;

template<typename T>
class Slice {
public:
  Slice(size_t len)
  : mem_(new T[len]),
    beg_(mem_),
    len_(len),
    cap_(len)
  { }

  template<typename Allocator>
  Slice(size_t len, Allocator& allocator)
  : mem_(allocator.template alloc<T>(len)),
    beg_(mem_),
    len_(len),
    cap_(len)
  { }

  template<typename Allocator>
  Slice(size_t len, Allocator* allocator)
  : mem_(allocator->template alloc<T>(len)),
    beg_(mem_),
    len_(len),
    cap_(len)
  { }
private:
  T*     mem_;
  T*     beg_;
  size_t len_;
  size_t cap_;
};

class New {
public:
  template<typename T>
  T* alloc(size_t size) {
    cout << "Allocating " << size << " things!" << endl;
    return new T[size];
  }
};

template<>
int* New::alloc(size_t size) {
  cout << "Allocating " << size << " ints!" << endl;
  return new int[size];
}

typedef Slice<int> int_slice;
typedef Slice<char> char_slice;
typedef Slice<Value> val_slice;

struct Value {
  enum Type {
    NUMBER,
    INT_SLICE,
    STRING,
  } type;

  enum Color {
    BLACK,
    GRAY,
    WHITE
  } color;

  union Content {
    double number;
    int_slice ints;
    char_slice chars;
    val_slice vals;
    Content() { }
  } content;
};

int main() {
  cout << "size of Slice: " << sizeof(Slice<Value>) << endl;
  cout << "size of Value: " << sizeof(Value) << endl;
  auto my_new = New();
  auto ints = Slice<int>(20, my_new);
  cout << "size of ints: " << sizeof(ints) << endl;
  auto vals = Slice<Value>(14, &my_new);
  cout << "size of vals: " << sizeof(vals) << endl;
  return 0;
}
<commit_msg>formatting<commit_after>#include <iostream>

using namespace std;
struct Value;

template<typename T>
class Slice {

public:

  Slice(size_t len)
  : mem_(new T[len]),
    beg_(mem_),
    len_(len),
    cap_(len)
  { }

  template<typename Allocator>
  Slice(size_t len, Allocator& allocator)
  : mem_(allocator.template alloc<T>(len)),
    beg_(mem_),
    len_(len),
    cap_(len)
  { }

  template<typename Allocator>
  Slice(size_t len, Allocator* allocator)
  : mem_(allocator->template alloc<T>(len)),
    beg_(mem_),
    len_(len),
    cap_(len)
  { }

private:

  T*     mem_;
  T*     beg_;
  size_t len_;
  size_t cap_;

};

class New {
public:
  template<typename T>
  T* alloc(size_t size) {
    cout << "Allocating " << size << " things!" << endl;
    return new T[size];
  }
};

template<>
int* New::alloc(size_t size) {
  cout << "Allocating " << size << " ints!" << endl;
  return new int[size];
}

typedef Slice<int> int_slice;
typedef Slice<char> char_slice;
typedef Slice<Value> val_slice;

struct Value {
  enum Type {
    NUMBER,
    INT_SLICE,
    STRING,
  } type;

  enum Color {
    BLACK,
    GRAY,
    WHITE
  } color;

  union Content {
    double number;
    int_slice ints;
    char_slice chars;
    val_slice vals;
    Content() { }
  } content;
};

int main() {
  cout << "size of Slice: " << sizeof(Slice<Value>) << endl;
  cout << "size of Value: " << sizeof(Value) << endl;
  auto my_new = New();
  auto ints = Slice<int>(20, my_new);
  cout << "size of ints: " << sizeof(ints) << endl;
  auto vals = Slice<Value>(14, &my_new);
  cout << "size of vals: " << sizeof(vals) << endl;
  return 0;
}
<|endoftext|>


<commit_before>#include "http/json/json_adapter.hpp"

bool is_null(cJSON *json) {
    return json->type == cJSON_NULL;
}

//Functions to make accessing cJSON *objects easier

bool get_bool(cJSON *json) {
    if (json->type == cJSON_True) {
        return true;
    } else if (json->type == cJSON_False) {
        return false;
    } else {
        throw schema_mismatch_exc_t(strprintf("Expected bool instead got: %s\n", cJSON_print_std_string(json).c_str()).c_str());
    }
}

std::string get_string(cJSON *json) {
    if (json->type == cJSON_String) {
        return std::string(json->valuestring);
    } else {
        throw schema_mismatch_exc_t(strprintf("Expected string instead got: %s\n", cJSON_print_std_string(json).c_str()).c_str());
    }
}

int get_int(cJSON *json) {
    if (json->type == cJSON_Number) {
        return json->valueint;
    } else {
        throw schema_mismatch_exc_t(strprintf("Expected int instead got: %s\n", cJSON_print_std_string(json).c_str()).c_str());
    }
}

double get_double(cJSON *json) {
    if (json->type == cJSON_Number) {
        return json->valuedouble;
    } else {
        throw schema_mismatch_exc_t(strprintf("Expected double instead got: %s\n", cJSON_print_std_string(json).c_str()).c_str());
    }
}

json_array_iterator_t get_array_it(cJSON *json) {
    if (json->type == cJSON_Array) {
        return json_array_iterator_t(json);
    } else {
        BREAKPOINT;
        throw schema_mismatch_exc_t(strprintf("Expected array instead got: %s\n", cJSON_print_std_string(json).c_str()).c_str());
    }
}

json_object_iterator_t get_object_it(cJSON *json) {
    if (json->type == cJSON_Object) {
        return json_object_iterator_t(json);
    } else {
        throw schema_mismatch_exc_t(strprintf("Expected object instead got: %s\n", cJSON_print_std_string(json).c_str()).c_str());
    }
}

//implementation for json_adapter_if_t
json_adapter_if_t::json_adapter_map_t json_adapter_if_t::get_subfields() {
    json_adapter_map_t res = get_subfields_impl();
    for (json_adapter_map_t::iterator it = res.begin(); it != res.end(); it++) {
        it->second->superfields.insert(it->second->superfields.end(),
                                      superfields.begin(),
                                      superfields.end());

        it->second->superfields.push_back(get_change_callback());
    }
    return res;
}

cJSON *json_adapter_if_t::render() {
    return render_impl();
}

void json_adapter_if_t::apply(cJSON *change) {
    try {
        apply_impl(change);
    } catch (std::runtime_error e) {
        std::string s = cJSON_print_std_string(change);
        throw schema_mismatch_exc_t(strprintf("Failed to apply change: %s", s.c_str()));
    }
    boost::shared_ptr<subfield_change_functor_t> change_callback = get_change_callback();
    if (change_callback) {
        get_change_callback()->on_change();
    }

    for (std::vector<boost::shared_ptr<subfield_change_functor_t> >::iterator it = superfields.begin();
         it != superfields.end();
         ++it) {
        if (*it) {
            (*it)->on_change();
        }
    }
}

void json_adapter_if_t::erase() {
    erase_impl();

    boost::shared_ptr<subfield_change_functor_t> change_callback = get_change_callback();
    if (change_callback) {
        get_change_callback()->on_change();
    }

    for (std::vector<boost::shared_ptr<subfield_change_functor_t> >::iterator it = superfields.begin();
         it != superfields.end();
         ++it) {
        if (*it) {
            (*it)->on_change();
        }
    }
}

void json_adapter_if_t::reset() {
    reset_impl();

    boost::shared_ptr<subfield_change_functor_t> change_callback = get_change_callback();
    if (change_callback) {
        get_change_callback()->on_change();
    }

    for (std::vector<boost::shared_ptr<subfield_change_functor_t> >::iterator it = superfields.begin();
         it != superfields.end();
         ++it) {
        if (*it) {
            (*it)->on_change();
        }
    }
}

// ctx-less JSON adapter for time_t
json_adapter_if_t::json_adapter_map_t get_json_subfields(time_t *) {
    return json_adapter_if_t::json_adapter_map_t();
}

cJSON *render_as_json(time_t *target) {
    return cJSON_CreateNumber(*target);
}

void apply_json_to(cJSON *change, time_t *target) {
    *target = get_int(change);
}

void on_subfield_change(time_t *) { }

// ctx-less JSON adapter for bool
json_adapter_if_t::json_adapter_map_t get_json_subfields(bool *) {
    return json_adapter_if_t::json_adapter_map_t();
}

cJSON *render_as_json(bool *target) {
    return cJSON_CreateBool(*target);
}

void apply_json_to(cJSON *change, bool *target) {
    *target = get_bool(change);
}

void on_subfield_change(bool *) { }

namespace std {

// ctx-less JSON adapter for std::string

json_adapter_if_t::json_adapter_map_t get_json_subfields(std::string *) {
    return std::map<std::string, boost::shared_ptr<json_adapter_if_t> >();
}

cJSON *render_as_json(std::string *target) {
    return cJSON_CreateString(target->c_str());
}

void apply_json_to(cJSON *change, std::string *target) {
    *target = get_string(change);
}

void on_subfield_change(std::string *) { }

}  // namespace std

// ctx-less JSON adapter for uuid_t
json_adapter_if_t::json_adapter_map_t get_json_subfields(uuid_t *) {
    return std::map<std::string, boost::shared_ptr<json_adapter_if_t> >();
}

cJSON *render_as_json(const uuid_t *uuid) {
    if (uuid->is_nil()) {
        return cJSON_CreateNull();
    } else {
        return cJSON_CreateString(uuid_to_str(*uuid).c_str());
    }
}

void apply_json_to(cJSON *change, uuid_t *uuid) {
    if (change->type == cJSON_NULL) {
        *uuid = nil_uuid();
    } else {
        try {
            *uuid = str_to_uuid(get_string(change));
        } catch (std::runtime_error) {
            throw schema_mismatch_exc_t(strprintf("String %s, did not parse as uuid", cJSON_print_unformatted_std_string(change).c_str()));
        }
    }
}

void on_subfield_change(uuid_t *) { }

// ctx-less JSON adapter for uint64_t
json_adapter_if_t::json_adapter_map_t get_json_subfields(uint64_t *) {
    return json_adapter_if_t::json_adapter_map_t();
}

cJSON *render_as_json(uint64_t *target) {
    return cJSON_CreateNumber(*target);
}

void apply_json_to(cJSON *change, uint64_t *target) {
    *target = get_int(change);
}

void on_subfield_change(uint64_t *) { }

// ctx-less JSON adapter for int
json_adapter_if_t::json_adapter_map_t get_json_subfields(int *) {
    return json_adapter_if_t::json_adapter_map_t();
}

cJSON *render_as_json(int *target) {
    return cJSON_CreateNumber(*target);
}

void apply_json_to(cJSON *change, int *target) {
    *target = get_int(change);
}

void on_subfield_change(int *) { }
<commit_msg>Commented out breakpoint which would prevent throwing.<commit_after>#include "http/json/json_adapter.hpp"

bool is_null(cJSON *json) {
    return json->type == cJSON_NULL;
}

//Functions to make accessing cJSON *objects easier

bool get_bool(cJSON *json) {
    if (json->type == cJSON_True) {
        return true;
    } else if (json->type == cJSON_False) {
        return false;
    } else {
        throw schema_mismatch_exc_t(strprintf("Expected bool instead got: %s\n", cJSON_print_std_string(json).c_str()).c_str());
    }
}

std::string get_string(cJSON *json) {
    if (json->type == cJSON_String) {
        return std::string(json->valuestring);
    } else {
        throw schema_mismatch_exc_t(strprintf("Expected string instead got: %s\n", cJSON_print_std_string(json).c_str()).c_str());
    }
}

int get_int(cJSON *json) {
    if (json->type == cJSON_Number) {
        return json->valueint;
    } else {
        throw schema_mismatch_exc_t(strprintf("Expected int instead got: %s\n", cJSON_print_std_string(json).c_str()).c_str());
    }
}

double get_double(cJSON *json) {
    if (json->type == cJSON_Number) {
        return json->valuedouble;
    } else {
        throw schema_mismatch_exc_t(strprintf("Expected double instead got: %s\n", cJSON_print_std_string(json).c_str()).c_str());
    }
}

json_array_iterator_t get_array_it(cJSON *json) {
    if (json->type == cJSON_Array) {
        return json_array_iterator_t(json);
    } else {
        //BREAKPOINT;
        throw schema_mismatch_exc_t(strprintf("Expected array instead got: %s\n", cJSON_print_std_string(json).c_str()).c_str());
    }
}

json_object_iterator_t get_object_it(cJSON *json) {
    if (json->type == cJSON_Object) {
        return json_object_iterator_t(json);
    } else {
        throw schema_mismatch_exc_t(strprintf("Expected object instead got: %s\n", cJSON_print_std_string(json).c_str()).c_str());
    }
}

//implementation for json_adapter_if_t
json_adapter_if_t::json_adapter_map_t json_adapter_if_t::get_subfields() {
    json_adapter_map_t res = get_subfields_impl();
    for (json_adapter_map_t::iterator it = res.begin(); it != res.end(); it++) {
        it->second->superfields.insert(it->second->superfields.end(),
                                      superfields.begin(),
                                      superfields.end());

        it->second->superfields.push_back(get_change_callback());
    }
    return res;
}

cJSON *json_adapter_if_t::render() {
    return render_impl();
}

void json_adapter_if_t::apply(cJSON *change) {
    try {
        apply_impl(change);
    } catch (std::runtime_error e) {
        std::string s = cJSON_print_std_string(change);
        throw schema_mismatch_exc_t(strprintf("Failed to apply change: %s", s.c_str()));
    }
    boost::shared_ptr<subfield_change_functor_t> change_callback = get_change_callback();
    if (change_callback) {
        get_change_callback()->on_change();
    }

    for (std::vector<boost::shared_ptr<subfield_change_functor_t> >::iterator it = superfields.begin();
         it != superfields.end();
         ++it) {
        if (*it) {
            (*it)->on_change();
        }
    }
}

void json_adapter_if_t::erase() {
    erase_impl();

    boost::shared_ptr<subfield_change_functor_t> change_callback = get_change_callback();
    if (change_callback) {
        get_change_callback()->on_change();
    }

    for (std::vector<boost::shared_ptr<subfield_change_functor_t> >::iterator it = superfields.begin();
         it != superfields.end();
         ++it) {
        if (*it) {
            (*it)->on_change();
        }
    }
}

void json_adapter_if_t::reset() {
    reset_impl();

    boost::shared_ptr<subfield_change_functor_t> change_callback = get_change_callback();
    if (change_callback) {
        get_change_callback()->on_change();
    }

    for (std::vector<boost::shared_ptr<subfield_change_functor_t> >::iterator it = superfields.begin();
         it != superfields.end();
         ++it) {
        if (*it) {
            (*it)->on_change();
        }
    }
}

// ctx-less JSON adapter for time_t
json_adapter_if_t::json_adapter_map_t get_json_subfields(time_t *) {
    return json_adapter_if_t::json_adapter_map_t();
}

cJSON *render_as_json(time_t *target) {
    return cJSON_CreateNumber(*target);
}

void apply_json_to(cJSON *change, time_t *target) {
    *target = get_int(change);
}

void on_subfield_change(time_t *) { }

// ctx-less JSON adapter for bool
json_adapter_if_t::json_adapter_map_t get_json_subfields(bool *) {
    return json_adapter_if_t::json_adapter_map_t();
}

cJSON *render_as_json(bool *target) {
    return cJSON_CreateBool(*target);
}

void apply_json_to(cJSON *change, bool *target) {
    *target = get_bool(change);
}

void on_subfield_change(bool *) { }

namespace std {

// ctx-less JSON adapter for std::string

json_adapter_if_t::json_adapter_map_t get_json_subfields(std::string *) {
    return std::map<std::string, boost::shared_ptr<json_adapter_if_t> >();
}

cJSON *render_as_json(std::string *target) {
    return cJSON_CreateString(target->c_str());
}

void apply_json_to(cJSON *change, std::string *target) {
    *target = get_string(change);
}

void on_subfield_change(std::string *) { }

}  // namespace std

// ctx-less JSON adapter for uuid_t
json_adapter_if_t::json_adapter_map_t get_json_subfields(uuid_t *) {
    return std::map<std::string, boost::shared_ptr<json_adapter_if_t> >();
}

cJSON *render_as_json(const uuid_t *uuid) {
    if (uuid->is_nil()) {
        return cJSON_CreateNull();
    } else {
        return cJSON_CreateString(uuid_to_str(*uuid).c_str());
    }
}

void apply_json_to(cJSON *change, uuid_t *uuid) {
    if (change->type == cJSON_NULL) {
        *uuid = nil_uuid();
    } else {
        try {
            *uuid = str_to_uuid(get_string(change));
        } catch (std::runtime_error) {
            throw schema_mismatch_exc_t(strprintf("String %s, did not parse as uuid", cJSON_print_unformatted_std_string(change).c_str()));
        }
    }
}

void on_subfield_change(uuid_t *) { }

// ctx-less JSON adapter for uint64_t
json_adapter_if_t::json_adapter_map_t get_json_subfields(uint64_t *) {
    return json_adapter_if_t::json_adapter_map_t();
}

cJSON *render_as_json(uint64_t *target) {
    return cJSON_CreateNumber(*target);
}

void apply_json_to(cJSON *change, uint64_t *target) {
    *target = get_int(change);
}

void on_subfield_change(uint64_t *) { }

// ctx-less JSON adapter for int
json_adapter_if_t::json_adapter_map_t get_json_subfields(int *) {
    return json_adapter_if_t::json_adapter_map_t();
}

cJSON *render_as_json(int *target) {
    return cJSON_CreateNumber(*target);
}

void apply_json_to(cJSON *change, int *target) {
    *target = get_int(change);
}

void on_subfield_change(int *) { }
<|endoftext|>


<commit_before>
#include "texture.h"

#include <cassert>

#include <scm/gl_core/config.h>
#include <scm/gl_core/render_device.h>
#include <scm/gl_core/render_device/opengl/gl3_core.h>
#include <scm/gl_core/render_device/opengl/util/assert.h>
#include <scm/gl_core/render_device/opengl/util/binding_guards.h>
#include <scm/gl_core/render_device/opengl/util/error_helper.h>

namespace scm {
namespace gl {

namespace util {
} // namespace util

texture::texture(render_device& in_device)
  : context_bindable_object()
  , render_device_resource(in_device)
{
    const opengl::gl3_core& glapi = in_device.opengl3_api();

    glapi.glGenTextures(1, &(context_bindable_object::_gl_object_id));
    if (0 == _gl_object_id) {
        state().set(object_state::OS_BAD);
    }

    gl_assert(glapi, leaving texture::texture());
}

texture::~texture()
{
    const opengl::gl3_core& glapi = parent_device().opengl3_api();

    assert(0 != _gl_object_id);
    glapi.glDeleteTextures(1, &(context_bindable_object::_gl_object_id));

    gl_assert(glapi, leaving texture::~texture());
}

void
texture::bind(const render_context& in_context, int in_unit) const
{
    const opengl::gl3_core& glapi = in_context.opengl_api();
    assert(0 != object_id());
    assert(0 != object_target());
    assert(0 != object_binding());

    if (SCM_GL_CORE_USE_EXT_DIRECT_STATE_ACCESS) {
        glapi.glBindMultiTextureEXT(GL_TEXTURE0 + in_unit, object_target(), object_id());
        //glapi.glEnableIndexedEXT(object_target(), _occupied_texture_unit);
    }
    else {
        glapi.glActiveTexture(GL_TEXTURE0 + in_unit);
        glapi.glBindTexture(object_target(), object_id());

        // AMD bug!!! overwritten by sampler object anyway
        glapi.glTexParameteri(object_target(), GL_TEXTURE_MIN_FILTER, GL_NEAREST);
        glapi.glTexParameteri(object_target(), GL_TEXTURE_MAG_FILTER, GL_NEAREST);
        //glapi.glTexParameteri(object_target(), GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
        //glapi.glTexParameteri(object_target(), GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
        //glapi.glTexParameteri(object_target(), GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);

        //glapi.glTexParameteri(object_target(), GL_TEXTURE_SWIZZLE_R, GL_RED);
        //glapi.glTexParameteri(object_target(), GL_TEXTURE_SWIZZLE_G, GL_GREEN);
        //glapi.glTexParameteri(object_target(), GL_TEXTURE_SWIZZLE_B, GL_BLUE);
        //glapi.glTexParameteri(object_target(), GL_TEXTURE_SWIZZLE_A, GL_ALPHA);

        //glapi.glEnable(object_target());
        glapi.glActiveTexture(GL_TEXTURE0);
    }

    gl_assert(glapi, leaving texture::bind());
}

void
texture::unbind(const render_context& in_context, int in_unit) const
{
    const opengl::gl3_core& glapi = in_context.opengl_api();
    assert(0 != object_id());
    assert(0 != object_target());
    assert(0 != object_binding());

    if (SCM_GL_CORE_USE_EXT_DIRECT_STATE_ACCESS) {
        glapi.glBindMultiTextureEXT(GL_TEXTURE0 + in_unit, object_target(), 0);
        //glapi.glDisableIndexedEXT(object_target(), _occupied_texture_unit);
    }
    else {
        glapi.glActiveTexture(GL_TEXTURE0 + in_unit);
        glapi.glBindTexture(object_target(), 0);
        //glapi.glDisable(object_target());
        glapi.glActiveTexture(GL_TEXTURE0);
    }

    gl_assert(glapi, leaving texture::unbind());
}

} // namespace gl
} // namespace scm
<commit_msg>added ATi/AMD workaround guards to texture binding<commit_after>
#include "texture.h"

#include <cassert>

#include <scm/gl_core/config.h>
#include <scm/gl_core/render_device.h>
#include <scm/gl_core/render_device/opengl/gl3_core.h>
#include <scm/gl_core/render_device/opengl/util/assert.h>
#include <scm/gl_core/render_device/opengl/util/binding_guards.h>
#include <scm/gl_core/render_device/opengl/util/error_helper.h>

namespace scm {
namespace gl {

namespace util {
} // namespace util

texture::texture(render_device& in_device)
  : context_bindable_object()
  , render_device_resource(in_device)
{
    const opengl::gl3_core& glapi = in_device.opengl3_api();

    glapi.glGenTextures(1, &(context_bindable_object::_gl_object_id));
    if (0 == _gl_object_id) {
        state().set(object_state::OS_BAD);
    }

    gl_assert(glapi, leaving texture::texture());
}

texture::~texture()
{
    const opengl::gl3_core& glapi = parent_device().opengl3_api();

    assert(0 != _gl_object_id);
    glapi.glDeleteTextures(1, &(context_bindable_object::_gl_object_id));

    gl_assert(glapi, leaving texture::~texture());
}

void
texture::bind(const render_context& in_context, int in_unit) const
{
    const opengl::gl3_core& glapi = in_context.opengl_api();
    assert(0 != object_id());
    assert(0 != object_target());
    assert(0 != object_binding());

    if (SCM_GL_CORE_USE_EXT_DIRECT_STATE_ACCESS) {
        glapi.glBindMultiTextureEXT(GL_TEXTURE0 + in_unit, object_target(), object_id());
        //glapi.glEnableIndexedEXT(object_target(), _occupied_texture_unit);
    }
    else {
        glapi.glActiveTexture(GL_TEXTURE0 + in_unit);
        glapi.glBindTexture(object_target(), object_id());

        if (SCM_GL_CORE_USE_WORKAROUND_AMD) {
            // AMD bug!!! overwritten by sampler object anyway
            glapi.glTexParameteri(object_target(), GL_TEXTURE_MIN_FILTER, GL_NEAREST);
            glapi.glTexParameteri(object_target(), GL_TEXTURE_MAG_FILTER, GL_NEAREST);
        }
        //glapi.glTexParameteri(object_target(), GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
        //glapi.glTexParameteri(object_target(), GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
        //glapi.glTexParameteri(object_target(), GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);

        //glapi.glTexParameteri(object_target(), GL_TEXTURE_SWIZZLE_R, GL_RED);
        //glapi.glTexParameteri(object_target(), GL_TEXTURE_SWIZZLE_G, GL_GREEN);
        //glapi.glTexParameteri(object_target(), GL_TEXTURE_SWIZZLE_B, GL_BLUE);
        //glapi.glTexParameteri(object_target(), GL_TEXTURE_SWIZZLE_A, GL_ALPHA);

        //glapi.glEnable(object_target());
        glapi.glActiveTexture(GL_TEXTURE0);
    }

    gl_assert(glapi, leaving texture::bind());
}

void
texture::unbind(const render_context& in_context, int in_unit) const
{
    const opengl::gl3_core& glapi = in_context.opengl_api();
    assert(0 != object_id());
    assert(0 != object_target());
    assert(0 != object_binding());

    if (SCM_GL_CORE_USE_EXT_DIRECT_STATE_ACCESS) {
        glapi.glBindMultiTextureEXT(GL_TEXTURE0 + in_unit, object_target(), 0);
        //glapi.glDisableIndexedEXT(object_target(), _occupied_texture_unit);
    }
    else {
        glapi.glActiveTexture(GL_TEXTURE0 + in_unit);
        glapi.glBindTexture(object_target(), 0);
        //glapi.glDisable(object_target());
        glapi.glActiveTexture(GL_TEXTURE0);
    }

    gl_assert(glapi, leaving texture::unbind());
}

} // namespace gl
} // namespace scm
<|endoftext|>


<commit_before>// Copyright (c) 2014-2015 Dr. Colin Hirsch and Daniel Frey
// Please see LICENSE for license or visit https://github.com/ColinH/PEGTL/

#ifndef PEGTL_INTERNAL_INPUT_DATA_HH
#define PEGTL_INTERNAL_INPUT_DATA_HH

#include <cstdlib>

namespace pegtl
{
   namespace internal
   {
      struct input_data
      {
         input_data( const std::size_t line, const std::size_t column, const char * begin, const char * end, const char * source, const input_data * from = 0 )
               : line( line ),
                 column( column ),
                 begin( begin ),
                 end( end ),
                 source( source ),
                 from( from )
         { }

         std::size_t line;
         std::size_t column;

         const char * begin;
         const char * end;
         const char * source;

         const input_data * from;
      };

   } // internal

} // pegtl

#endif
<commit_msg>Default pointer parameter 'const input_data *' should be nullptr<commit_after>// Copyright (c) 2014-2015 Dr. Colin Hirsch and Daniel Frey
// Please see LICENSE for license or visit https://github.com/ColinH/PEGTL/

#ifndef PEGTL_INTERNAL_INPUT_DATA_HH
#define PEGTL_INTERNAL_INPUT_DATA_HH

#include <cstdlib>

namespace pegtl
{
   namespace internal
   {
      struct input_data
      {
         input_data( const std::size_t line, const std::size_t column, const char * begin, const char * end, const char * source, const input_data * from = nullptr )
               : line( line ),
                 column( column ),
                 begin( begin ),
                 end( end ),
                 source( source ),
                 from( from )
         { }

         std::size_t line;
         std::size_t column;

         const char * begin;
         const char * end;
         const char * source;

         const input_data * from;
      };

   } // internal

} // pegtl

#endif
<|endoftext|>


<commit_before>/*************************************************************************
 *
 *  $RCSfile: MasterPagesSelector.hxx,v $
 *
 *  $Revision: 1.4 $
 *
 *  last change: $Author: rt $ $Date: 2005-01-31 14:55:05 $
 *
 *  The Contents of this file are made available subject to the terms of
 *  either of the following licenses
 *
 *         - GNU Lesser General Public License Version 2.1
 *         - Sun Industry Standards Source License Version 1.1
 *
 *  Sun Microsystems Inc., October, 2000
 *
 *  GNU Lesser General Public License Version 2.1
 *  =============================================
 *  Copyright 2000 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
 *
 *
 *  Sun Industry Standards Source License Version 1.1
 *  =================================================
 *  The contents of this file are subject to the Sun Industry Standards
 *  Source License Version 1.1 (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.openoffice.org/license.html.
 *
 *  Software provided under this License is provided on an "AS IS" basis,
 *  WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
 *  WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
 *  MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
 *  See the License for the specific provisions governing your rights and
 *  obligations concerning the Software.
 *
 *  The Initial Developer of the Original Code is: Sun Microsystems, Inc.
 *
 *  Copyright: 2000 by Sun Microsystems, Inc.
 *
 *  All Rights Reserved.
 *
 *  Contributor(s): _______________________________________
 *
 *
 ************************************************************************/

#ifndef SD_TOOLPANEL_CONTROLS_MASTER_PAGES_SELECTOR_HXX
#define SD_TOOLPANEL_CONTROLS_MASTER_PAGES_SELECTOR_HXX

#include "../TaskPaneTreeNode.hxx"
#include "MasterPageContainer.hxx"

#ifndef _PRESENTATION_HXX
#include "pres.hxx"
#endif
#include <sfx2/shell.hxx>
#include <vcl/image.hxx>
#include "glob.hxx"

class MouseEvent;
class SdDrawDocument;
class SdPage;
class SfxModule;

namespace sd {
class DrawViewShell;
class TemplateEntry;
class TemplateDir;
class ViewShellBase;
}

namespace sd { namespace toolpanel { namespace controls {

class PreviewValueSet;

/** Base class of a menu that lets the user select from a list of
    templates or designs that are loaded from files.
*/
class MasterPagesSelector
    : public TreeNode,
      public SfxShell
{
public:
    static const int snSmallPreviewWidth;
    static const int snLargePreviewWidth;

    TYPEINFO();
    SFX_DECL_INTERFACE(SD_IF_SDMASTERPAGESSELECTOR);

    MasterPagesSelector (
        TreeNode* pParent,
        SdDrawDocument& rDocument,
        ViewShellBase& rBase);
    virtual ~MasterPagesSelector (void);

    virtual void LateInit (void);

    /** Return the height that this control needs to show all of its lines.
    */
    long GetRequiredHeight (int nWidth) const;

    /** The given master page, either the master page of a slide or a notes
        page, is cloned and inserted into mrDocument.  The necessary styles
        are copied as well.
    */
    static SdPage* AddMasterPage (
        SdDrawDocument* pTargetDocument,
        SdPage* pMasterPage,
        USHORT nInsertionIndex);

    virtual Size GetPreferredSize (void);
    virtual sal_Int32 GetPreferredWidth (sal_Int32 nHeight);
    virtual sal_Int32 GetPreferredHeight (sal_Int32 nWidth);
    virtual bool IsResizable (void);
    virtual ::Window* GetWindow (void);
    virtual sal_Int32 GetMinimumWidth (void);

    void Execute (SfxRequest& rRequest);
    void GetState (SfxItemSet& rItemSet);

    void SetPreviewWidth (int nPreviewWidth);

    /** Update the selection of previews according to whatever
        influences them appart from mouse and keyboard.  If, for
        example, the current page of the main pane changes, then call
        this method at the CurrentMasterPagesSelector to select the
        previews of the master pages that are assigned to the new
        current page.
    */
    virtual void UpdateSelection (void);

    virtual void Fill (void);
    virtual void Clear (void);

    void    SetSmartHelpId( const SmartId& aId, SmartIdUpdateMode aMode = SMART_SET_SMART );

protected:
    SdDrawDocument& mrDocument;
    ::std::auto_ptr<PreviewValueSet> mpPageSet;
    int mnPreviewWidth;
    ViewShellBase& mrBase;

    SdPage* GetSelectedMasterPage (void);

    /** Assign the given master page to all slides of the document.
        @param pMasterPage
            The master page to assign to all slides.
    */
    void AssignMasterPageToAllSlides (SdPage* pMasterPage);

    /** Assign the given master page to all slides that are selected in a
        slide sorter that is displayed in the lef or center pane.  When both
        panes display a slide sorter then the one in the center pane is
        used.
    */
    void AssignMasterPageToSelectedSlides (SdPage* pMasterPage);

    void AddItemForPage (
        const String& sURL,
        const String& sPageName,
        SdPage* pMasterPage,
        Image aPreview,
        bool bCreatePreview = true);
    void AddItemForToken (
        MasterPageContainer::Token aToken,
        bool bCreatePreview = true);

    /** Ask the master page container for the previews of all items and set
        them to the value set.  Call this function when the size of the
        previews has changed.
    */
    void FillPreviews (void);

    DECL_LINK(PreviewAvailableCallback, void*);

private:
    DECL_LINK(ClickHandler, PreviewValueSet*);
    DECL_LINK(RightClickHandler, MouseEvent*);

    static void ProvideStyles (
        SdDrawDocument* pSourceDoc,
        SdDrawDocument* pTargetDoc,
        SdPage* pPage);

    /** Assign the given master page to the list of pages.
        @param pMasterPage
            This master page will usually be a member of the list of all
            available master pages as provided by the MasterPageContainer.
        @param rPageList
            The pages to which to assign the master page.  These pages may
            be slides or master pages themselves.
    */
    void AssignMasterPageToPageList (
        SdPage* pMasterPage,
        const ::std::vector<SdPage*>& rPageList);

    /** Assign the given master page to the given page.
        @param pMasterPage
            In contrast to AssignMasterPageToPageList() this page is assumed
            to be in the target document, i.e. the same document that pPage
            is in.  The caller will usually call AddMasterPage() to create a
            clone of a master page in a another document to create it.
        @param rsBaseLayoutName
            The layout name of the given master page.  It is given so that
            it has not to be created on every call.  It could be generated
            from the given master page, though.
        @param pPage
            The page to which to assign the master page.  It can be a slide
            or a master page itself.
    */
    void AssignMasterPageToPage (
        SdPage* pMasterPage,
        const String& rsBaseLayoutName,
        SdPage* pPage);
};

} } } // end of namespace ::sd::toolpanel::controls

#endif
<commit_msg>INTEGRATION: CWS impress33 (1.3.120); FILE MERGED 2005/02/03 14:13:10 af 1.3.120.2: #i41507# Moved MasterPageContainer specific code into new MasterPagesContainerSelector class. 2005/02/01 15:48:53 af 1.3.120.1: #i41507# Added mnDefaultClickAction member.  Avoiding unnecessary copies of master pages.  Code cleanup.<commit_after>/*************************************************************************
 *
 *  $RCSfile: MasterPagesSelector.hxx,v $
 *
 *  $Revision: 1.5 $
 *
 *  last change: $Author: vg $ $Date: 2005-02-16 17:07:45 $
 *
 *  The Contents of this file are made available subject to the terms of
 *  either of the following licenses
 *
 *         - GNU Lesser General Public License Version 2.1
 *         - Sun Industry Standards Source License Version 1.1
 *
 *  Sun Microsystems Inc., October, 2000
 *
 *  GNU Lesser General Public License Version 2.1
 *  =============================================
 *  Copyright 2000 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
 *
 *
 *  Sun Industry Standards Source License Version 1.1
 *  =================================================
 *  The contents of this file are subject to the Sun Industry Standards
 *  Source License Version 1.1 (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.openoffice.org/license.html.
 *
 *  Software provided under this License is provided on an "AS IS" basis,
 *  WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
 *  WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
 *  MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
 *  See the License for the specific provisions governing your rights and
 *  obligations concerning the Software.
 *
 *  The Initial Developer of the Original Code is: Sun Microsystems, Inc.
 *
 *  Copyright: 2000 by Sun Microsystems, Inc.
 *
 *  All Rights Reserved.
 *
 *  Contributor(s): _______________________________________
 *
 *
 ************************************************************************/

#ifndef SD_TOOLPANEL_CONTROLS_MASTER_PAGES_SELECTOR_HXX
#define SD_TOOLPANEL_CONTROLS_MASTER_PAGES_SELECTOR_HXX

#include "../TaskPaneTreeNode.hxx"
#include "MasterPageContainer.hxx"

#ifndef _PRESENTATION_HXX
#include "pres.hxx"
#endif
#include <sfx2/shell.hxx>
#include <vcl/image.hxx>
#include "glob.hxx"

#include <queue>

class MouseEvent;
class SdDrawDocument;
class SdPage;
class SfxModule;

namespace sd {
class DrawViewShell;
class TemplateEntry;
class TemplateDir;
class ViewShellBase;
}

namespace sd { namespace toolpanel { namespace controls {

class PreviewValueSet;

/** Base class of a menu that lets the user select from a list of
    templates or designs that are loaded from files.
*/
class MasterPagesSelector
    : public TreeNode,
      public SfxShell
{
public:
    static const int snSmallPreviewWidth;
    static const int snLargePreviewWidth;

    TYPEINFO();
    SFX_DECL_INTERFACE(SD_IF_SDMASTERPAGESSELECTOR);

    MasterPagesSelector (
        TreeNode* pParent,
        SdDrawDocument& rDocument,
        ViewShellBase& rBase);
    virtual ~MasterPagesSelector (void);

    virtual void LateInit (void);

    /** Return the height that this control needs to show all of its lines.
    */
    long GetRequiredHeight (int nWidth) const;

    /** The given master page, either the master page of a slide or a notes
        page, is cloned and inserted into mrDocument.  The necessary styles
        are copied as well.
    */
    static SdPage* AddMasterPage (
        SdDrawDocument* pTargetDocument,
        SdPage* pMasterPage,
        USHORT nInsertionIndex);

    virtual Size GetPreferredSize (void);
    virtual sal_Int32 GetPreferredWidth (sal_Int32 nHeight);
    virtual sal_Int32 GetPreferredHeight (sal_Int32 nWidth);
    virtual bool IsResizable (void);
    virtual ::Window* GetWindow (void);
    virtual sal_Int32 GetMinimumWidth (void);

    void Execute (SfxRequest& rRequest);
    void GetState (SfxItemSet& rItemSet);

    void SetPreviewWidth (int nPreviewWidth);

    /** Update the selection of previews according to whatever
        influences them appart from mouse and keyboard.  If, for
        example, the current page of the main pane changes, then call
        this method at the CurrentMasterPagesSelector to select the
        previews of the master pages that are assigned to the new
        current page.

        The default implementation of this method ignores the call. This is
        used by e.g. the RecentMasterPagesSelector because it does not show
        the currently used master pages by default and thus is not
        influenced by its changes.
    */
    virtual void UpdateSelection (void);

    virtual void Fill (void) = 0;

    /** Make the selector empty.  This method clear the value set from any
        entries. Overload this method to add functionality, especially to
        destroy objects set as data items at the value set.
    */
    virtual void Clear (void);

    void    SetSmartHelpId( const SmartId& aId, SmartIdUpdateMode aMode = SMART_SET_SMART );

    /** Call this method to tell a selector object that the preview that
        belongs to the given page does not reflect the pages content
        anymore.  This method forwards the call to the variant that takes a
        value set index as argument so call that variant directly when the
        index is already present.
        @param pPage
            When NULL or a pointer to page is given that does not belong to
            the selector then the call is ignored.
    */
    virtual void InvalidatePreview (const SdPage* pPage) = 0;
    /** Invalidate the preview that is specified via an index into the value
        set.
    */
    void InvalidatePreview (USHORT nIndex);
    void InvalidateAllPreviews (void);

protected:
    SdDrawDocument& mrDocument;
    ::std::auto_ptr<PreviewValueSet> mpPageSet;
    int mnPreviewWidth;
    ViewShellBase& mrBase;
    /** Slot that is executed as default action when the left mouse button is
        clicked over a master page.
    */
    sal_uInt16 mnDefaultClickAction;
    /** Timer for scheduling updates of master page previews.
    */
    Timer maPreviewUpdateTimer;
    /** Pages with pointers in this queue have their previews updated
        eventually.  Filled by InvalidatePreview() and operated upon by
        UpdatePreviews().
    */
    ::std::queue<USHORT> maPreviewUpdateQueue;

    virtual SdPage* GetSelectedMasterPage (void);

    /** Assign the given master page to all slides of the document.
        @param pMasterPage
            The master page to assign to all slides.
    */
    void AssignMasterPageToAllSlides (SdPage* pMasterPage);

    /** Assign the given master page to all slides that are selected in a
        slide sorter that is displayed in the lef or center pane.  When both
        panes display a slide sorter then the one in the center pane is
        used.
    */
    void AssignMasterPageToSelectedSlides (SdPage* pMasterPage);

    void AddItemForPage (
        const String& sURL,
        const String& sPageName,
        SdPage* pMasterPage,
        Image aPreview,
        bool bCreatePreview = true);
    void AddItemForToken (
        MasterPageContainer::Token aToken,
        bool bCreatePreview = true);

    /** Ask the master page container for the previews of all items and set
        them to the value set.  Call this function when the size of the
        previews has changed.
    */
    virtual void UpdateAllPreviews (void) = 0;
    virtual void UpdatePreview (USHORT nIndex) = 0;

    DECL_LINK(ProcessPreviewUpdateRequest, Timer*);

private:
    DECL_LINK(ClickHandler, PreviewValueSet*);
    DECL_LINK(RightClickHandler, MouseEvent*);

    static void ProvideStyles (
        SdDrawDocument* pSourceDoc,
        SdDrawDocument* pTargetDoc,
        SdPage* pPage);

    /** Assign the given master page to the list of pages.
        @param pMasterPage
            This master page will usually be a member of the list of all
            available master pages as provided by the MasterPageContainer.
        @param rPageList
            The pages to which to assign the master page.  These pages may
            be slides or master pages themselves.
    */
    void AssignMasterPageToPageList (
        SdPage* pMasterPage,
        const ::std::vector<SdPage*>& rPageList);

    /** Assign the given master page to the given page.
        @param pMasterPage
            In contrast to AssignMasterPageToPageList() this page is assumed
            to be in the target document, i.e. the same document that pPage
            is in.  The caller will usually call AddMasterPage() to create a
            clone of a master page in a another document to create it.
        @param rsBaseLayoutName
            The layout name of the given master page.  It is given so that
            it has not to be created on every call.  It could be generated
            from the given master page, though.
        @param pPage
            The page to which to assign the master page.  It can be a slide
            or a master page itself.
    */
    void AssignMasterPageToPage (
        SdPage* pMasterPage,
        const String& rsBaseLayoutName,
        SdPage* pPage);

    SdPage* ProvideMasterPage (
        SdPage* pMasterPage,
        const ::std::vector<SdPage*>& rPageList);
};

} } } // end of namespace ::sd::toolpanel::controls

#endif
<|endoftext|>


<commit_before>// The MIT License (MIT)

// Copyright (c) 2014 Rapptz

// Permission is hereby granted, free of charge, to any person obtaining a copy of
// this software and associated documentation files (the "Software"), to deal in
// the Software without restriction, including without limitation the rights to
// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
// the Software, and to permit persons to whom the Software is furnished to do so,
// subject to the following conditions:

// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.

// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

#ifndef JSONPP_DUMP_HPP
#define JSONPP_DUMP_HPP

#include "type_traits.hpp"
#include <string>
#include <sstream>
#include <iosfwd>
#include <cmath>

namespace json {
inline namespace v1 {
struct option {
    enum : int {
        none = 0,
        allow_nan_inf = 1 << 0,
        minify = 1 << 1
    };
};

namespace detail {
template<typename OStream>
inline void indent_by(OStream& out, int indent, int depth) {
    out << '\n';
    for(int i = 0; i < (indent * depth); ++i) {
        out << ' ';
    }
}

template<typename OStream, typename T, EnableIf<is_null<T>> = 0>
inline OStream& dump(OStream& out, const T&, int /* indent */, int /* opts */, int /* depth */) {
    return out << "null";
}

template<typename OStream, typename T, EnableIf<is_bool<T>> = 0>
inline OStream& dump(OStream& out, const T& t, int /* indent */, int /* opts */, int /* depth */) {
    return out << (t ? "true" : "false");
}

template<typename OStream, typename T, EnableIf<is_number<T>> = 0>
inline OStream& dump(OStream& out, const T& t, int /* indent */, int opts, int /* depth */) {
    if((opts & option::allow_nan_inf) != option::allow_nan_inf && (std::isnan(t) || std::isinf(t))) {
        // stream null instead if nan is found
        return out << "null";
    }
    auto precision = out.precision();
    out.precision(17);
    out << t;
    out.precision(precision);
    return out;
}

template<typename OStream, typename T, EnableIf<is_string<T>> = 0>
inline OStream& dump(OStream& out, const T& t, int /* indent */, int /* opts */, int /* depth */) {
    out << '"';
    for(auto&& c : t) {
        switch(c) {
        case '"':
            out << "\\\"";
            break;
        case '\\':
            out << "\\\\";
            break;
        case '/':
            out << "\\/";
            break;
        case '\b':
            out << "\\b";
            break;
        case '\f':
            out << "\\f";
            break;
        case '\n':
            out << "\\n";
            break;
        case '\r':
            out << "\\r";
            break;
        case '\t':
            out << "\\t";
            break;
        default:
            if(c == 0x7F || static_cast<unsigned char>(c) < 0x20) {
                // prepare the stream state for formatting.
                out << "\\u";
                auto fill = out.fill();
                auto width = out.width();
                auto flags = out.flags();
                out.width(4);
                out.fill('0');
                out.flags(flags | out.hex);
                out << (c & 0xFF);
                out.width(width);
                out.fill(fill);
                out.flags(flags);
            }
            else {
                out << c;
            }
            break;
        }
    }
    return out << '"';
}

template<typename OStream, typename T, EnableIf<is_array<T>> = 0>
inline OStream& dump(OStream& out, const T& t, int indent, int opts, int depth) {
    bool prettify = (opts & option::minify) != option::minify;
    depth += prettify;
    out << '[';

    using std::begin;
    using std::end;
    auto&& first = begin(t);
    auto&& last  = end(t);
    bool first_pass = true;
    for(; first != last; ++first) {
        if(not first_pass) {
            out << ',';
        }

        if(prettify) {
            indent_by(out, indent, depth);
        }

        dump(out, *first, indent, opts, depth);
        first_pass = false;
    }

    if(prettify) {
        --depth;
        if(not first_pass) {
            indent_by(out, indent, depth);
        }
    }

    return out << ']';
}

template<typename OStream, typename T, EnableIf<std::is_arithmetic<T>> = 0>
inline void key(OStream& out, const T& t) {
    out << '"' << std::to_string(t) << '"';
}

template<typename OStream, typename T, DisableIf<std::is_arithmetic<T>> = 0>
inline void key(OStream& out, const T& t) {
    dump(out, t, 0, 0, 0);
}

template<typename OStream, typename T, EnableIf<is_object<T>> = 0>
inline OStream& dump(OStream& out, const T& t, int indent, int opts, int depth) {
    bool prettify = (opts & option::minify) != option::minify;
    depth += prettify;
    out << '{';

    using std::begin;
    using std::endl;

    auto&& first = begin(t);
    auto&& last  = end(t);
    bool first_pass = true;

    for(; first != last; ++first) {

        auto&& elem = *first;
        if(not first_pass) {
            out << ',';
        }

        if(prettify) {
            indent_by(out, indent, depth);
        }

        key(out, elem.first);
        out << ':';

        if(prettify) {
            out << ' ';
        }

        dump(out, elem.second, indent, opts, depth);
        first_pass = false;
    }

    if(prettify) {
        --depth;

        if(not first_pass) {
            indent_by(out, indent, depth);
        }
    }

    return out << '}';
}
} // detail

template<typename OStream, typename T>
inline OStream& dump(OStream& out, const T& t, int indent = 4, int opts = option::none) {
    using detail::dump;
    return dump(out, t, indent, opts, 0);
}
} // v1
} // json

#endif // JSONPP_DUMP_HPP
<commit_msg>Fix issue with returning std::basic_ostream& instead of OStream&.<commit_after>// The MIT License (MIT)

// Copyright (c) 2014 Rapptz

// Permission is hereby granted, free of charge, to any person obtaining a copy of
// this software and associated documentation files (the "Software"), to deal in
// the Software without restriction, including without limitation the rights to
// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
// the Software, and to permit persons to whom the Software is furnished to do so,
// subject to the following conditions:

// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.

// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

#ifndef JSONPP_DUMP_HPP
#define JSONPP_DUMP_HPP

#include "type_traits.hpp"
#include <string>
#include <sstream>
#include <iosfwd>
#include <cmath>

namespace json {
inline namespace v1 {
struct option {
    enum : int {
        none = 0,
        allow_nan_inf = 1 << 0,
        minify = 1 << 1
    };
};

namespace detail {
template<typename OStream>
inline void indent_by(OStream& out, int indent, int depth) {
    out << '\n';
    for(int i = 0; i < (indent * depth); ++i) {
        out << ' ';
    }
}

template<typename OStream, typename T, EnableIf<is_null<T>> = 0>
inline OStream& dump(OStream& out, const T&, int /* indent */, int /* opts */, int /* depth */) {
    out << "null";
    return out;
}

template<typename OStream, typename T, EnableIf<is_bool<T>> = 0>
inline OStream& dump(OStream& out, const T& t, int /* indent */, int /* opts */, int /* depth */) {
    out << (t ? "true" : "false");
    return out;
}

template<typename OStream, typename T, EnableIf<is_number<T>> = 0>
inline OStream& dump(OStream& out, const T& t, int /* indent */, int opts, int /* depth */) {
    if((opts & option::allow_nan_inf) != option::allow_nan_inf && (std::isnan(t) || std::isinf(t))) {
        // stream null instead if nan is found
        out << "null";
        return out;
    }
    auto precision = out.precision();
    out.precision(17);
    out << t;
    out.precision(precision);
    return out;
}

template<typename OStream, typename T, EnableIf<is_string<T>> = 0>
inline OStream& dump(OStream& out, const T& t, int /* indent */, int /* opts */, int /* depth */) {
    out << '"';
    for(auto&& c : t) {
        switch(c) {
        case '"':
            out << "\\\"";
            break;
        case '\\':
            out << "\\\\";
            break;
        case '/':
            out << "\\/";
            break;
        case '\b':
            out << "\\b";
            break;
        case '\f':
            out << "\\f";
            break;
        case '\n':
            out << "\\n";
            break;
        case '\r':
            out << "\\r";
            break;
        case '\t':
            out << "\\t";
            break;
        default:
            if(c == 0x7F || static_cast<unsigned char>(c) < 0x20) {
                // prepare the stream state for formatting.
                out << "\\u";
                auto fill = out.fill();
                auto width = out.width();
                auto flags = out.flags();
                out.width(4);
                out.fill('0');
                out.flags(flags | out.hex);
                out << (c & 0xFF);
                out.width(width);
                out.fill(fill);
                out.flags(flags);
            }
            else {
                out << c;
            }
            break;
        }
    }
    out << '"';
    return out;
}

template<typename OStream, typename T, EnableIf<is_array<T>> = 0>
inline OStream& dump(OStream& out, const T& t, int indent, int opts, int depth) {
    bool prettify = (opts & option::minify) != option::minify;
    depth += prettify;
    out << '[';

    using std::begin;
    using std::end;
    auto&& first = begin(t);
    auto&& last  = end(t);
    bool first_pass = true;
    for(; first != last; ++first) {
        if(not first_pass) {
            out << ',';
        }

        if(prettify) {
            indent_by(out, indent, depth);
        }

        dump(out, *first, indent, opts, depth);
        first_pass = false;
    }

    if(prettify) {
        --depth;
        if(not first_pass) {
            indent_by(out, indent, depth);
        }
    }

    out << ']';
    return out;
}

template<typename OStream, typename T, EnableIf<std::is_arithmetic<T>> = 0>
inline void key(OStream& out, const T& t) {
    out << '"' << std::to_string(t) << '"';
}

template<typename OStream, typename T, DisableIf<std::is_arithmetic<T>> = 0>
inline void key(OStream& out, const T& t) {
    dump(out, t, 0, 0, 0);
}

template<typename OStream, typename T, EnableIf<is_object<T>> = 0>
inline OStream& dump(OStream& out, const T& t, int indent, int opts, int depth) {
    bool prettify = (opts & option::minify) != option::minify;
    depth += prettify;
    out << '{';

    using std::begin;
    using std::endl;

    auto&& first = begin(t);
    auto&& last  = end(t);
    bool first_pass = true;

    for(; first != last; ++first) {

        auto&& elem = *first;
        if(not first_pass) {
            out << ',';
        }

        if(prettify) {
            indent_by(out, indent, depth);
        }

        key(out, elem.first);
        out << ':';

        if(prettify) {
            out << ' ';
        }

        dump(out, elem.second, indent, opts, depth);
        first_pass = false;
    }

    if(prettify) {
        --depth;

        if(not first_pass) {
            indent_by(out, indent, depth);
        }
    }

    out << '}';
    return out;
}
} // detail

template<typename OStream, typename T>
inline OStream& dump(OStream& out, const T& t, int indent = 4, int opts = option::none) {
    using detail::dump;
    return dump(out, t, indent, opts, 0);
}
} // v1
} // json

#endif // JSONPP_DUMP_HPP
<|endoftext|>


<commit_before>/*
	This file is part of cpp-ethereum.

	cpp-ethereum 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.

	cpp-ethereum 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 cpp-ethereum.  If not, see <http://www.gnu.org/licenses/>.
*/
/** @file WhisperHost.cpp
 * @author Gav Wood <i@gavwood.com>
 * @date 2014
 */

#include "WhisperHost.h"

#include <libdevcore/CommonIO.h>
#include <libdevcore/Log.h>
#include <libp2p/All.h>
using namespace std;
using namespace dev;
using namespace dev::p2p;
using namespace dev::shh;

WhisperHost::WhisperHost(): Worker("shh")
{
}

WhisperHost::~WhisperHost()
{
}

void WhisperHost::streamMessage(h256 _m, RLPStream& _s) const
{
	UpgradableGuard l(x_messages);
	if (m_messages.count(_m))
	{
		UpgradeGuard ll(l);
		auto const& m = m_messages.at(_m);
		cnote << "streamRLP: " << m.expiry() << m.ttl() << m.topic() << toHex(m.data());
		m.streamRLP(_s);
	}
}

void WhisperHost::inject(Envelope const& _m, WhisperPeer* _p)
{
	// this function processes messages originated both by local host (_p == null), and by remote peers (_p != null)

	cnote << this << ": inject: " << _m.expiry() << _m.ttl() << _m.topic() << toHex(_m.data());

	if (_m.expiry() <= (unsigned)time(0))
		return;

	auto h = _m.sha3();
	{
		UpgradableGuard l(x_messages);
		if (m_messages.count(h))
			return;
		UpgradeGuard ll(l);
		m_messages[h] = _m;
		m_expiryQueue.insert(make_pair(_m.expiry(), h));
	}

	int rating = 1; // rating for local host is based upon: 1. installed watch; 2. proof of work

	//if (bloomfilter.check)
	//{
		// rating *= 10;
		if (_p) // originated externally
			DEV_GUARDED(m_filterLock)
			{
				for (auto const& f: m_filters)
					if (f.second.filter.matches(_m))
						for (auto& i: m_watches)
							if (i.second.id == f.first)
							{
								i.second.changes.push_back(h);
								rating *= 10;
							}
			}
	//}

	// TODO p2p: capability-based rating
	for (auto i: peerSessions())
	{
		auto w = i.first->cap<WhisperPeer>().get();
		if (w == _p)
			w->addRating(rating);
		else
			w->noteNewMessage(h, _m);
	}
}

unsigned WhisperHost::installWatch(shh::Topics const& _t)
{
	InstalledFilter f(_t);
	h256 h = f.filter.sha3();
	unsigned ret = 0;

	DEV_GUARDED(m_filterLock)
	{
		auto it = m_filters.find(h);
		if (m_filters.end() == it)
			m_filters.insert(make_pair(h, f));
		else
			it->second.refCount++;

		m_bloom.addRaw(f.filter.exportBloom());
		ret = m_watches.size() ? m_watches.rbegin()->first + 1 : 0;
		m_watches[ret] = ClientWatch(h);
		cwatshh << "+++" << ret << h;
	}

	noteAdvertiseTopicsOfInterest();
	return ret;
}

h256s WhisperHost::watchMessages(unsigned _watchId)
{
	h256s ret;
	auto wit = m_watches.find(_watchId);
	if (wit == m_watches.end())
		return ret;
	TopicFilter f;
	{
		Guard l(m_filterLock);
		auto fit = m_filters.find(wit->second.id);
		if (fit == m_filters.end())
			return ret;
		f = fit->second.filter;
	}
	ReadGuard l(x_messages);
	for (auto const& m: m_messages)
		if (f.matches(m.second))
			ret.push_back(m.first);
	return ret;
}

void WhisperHost::uninstallWatch(unsigned _i)
{
	cwatshh << "XXX" << _i;

	DEV_GUARDED(m_filterLock)
	{
		auto it = m_watches.find(_i);
		if (it == m_watches.end())
			return;

		auto id = it->second.id;
		m_watches.erase(it);

		auto fit = m_filters.find(id);
		if (fit != m_filters.end())
		{
			m_bloom.removeRaw(fit->second.filter.exportBloom());
			if (!--fit->second.refCount)
				m_filters.erase(fit);
		}
	}

	noteAdvertiseTopicsOfInterest();
}

void WhisperHost::doWork()
{
	for (auto i: peerSessions())
		i.first->cap<WhisperPeer>().get()->sendMessages();
	cleanup();
}

void WhisperHost::cleanup()
{
	// remove old messages.
	// should be called every now and again.
	unsigned now = (unsigned)time(0);
	WriteGuard l(x_messages);
	for (auto it = m_expiryQueue.begin(); it != m_expiryQueue.end() && it->first <= now; it = m_expiryQueue.erase(it))
		m_messages.erase(it->second);
}

void WhisperHost::noteAdvertiseTopicsOfInterest()
{
	for (auto i: peerSessions())
		i.first->cap<WhisperPeer>().get()->noteAdvertiseTopicsOfInterest();
}
<commit_msg>minor update<commit_after>/*
	This file is part of cpp-ethereum.

	cpp-ethereum 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.

	cpp-ethereum 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 cpp-ethereum.  If not, see <http://www.gnu.org/licenses/>.
*/
/** @file WhisperHost.cpp
 * @author Gav Wood <i@gavwood.com>
 * @date 2014
 */

#include "WhisperHost.h"

#include <libdevcore/CommonIO.h>
#include <libdevcore/Log.h>
#include <libp2p/All.h>
using namespace std;
using namespace dev;
using namespace dev::p2p;
using namespace dev::shh;

WhisperHost::WhisperHost(): Worker("shh")
{
}

WhisperHost::~WhisperHost()
{
}

void WhisperHost::streamMessage(h256 _m, RLPStream& _s) const
{
	UpgradableGuard l(x_messages);
	if (m_messages.count(_m))
	{
		UpgradeGuard ll(l);
		auto const& m = m_messages.at(_m);
		cnote << "streamRLP: " << m.expiry() << m.ttl() << m.topic() << toHex(m.data());
		m.streamRLP(_s);
	}
}

void WhisperHost::inject(Envelope const& _m, WhisperPeer* _p)
{
	// this function processes messages originated both by local host (_p == null), and by remote peers (_p != null)

	cnote << this << ": inject: " << _m.expiry() << _m.ttl() << _m.topic() << toHex(_m.data());

	if (_m.expiry() <= (unsigned)time(0))
		return;

	auto h = _m.sha3();
	{
		UpgradableGuard l(x_messages);
		if (m_messages.count(h))
			return;
		UpgradeGuard ll(l);
		m_messages[h] = _m;
		m_expiryQueue.insert(make_pair(_m.expiry(), h));
	}

	int rating = 1; // rating for local host is based upon: 1. installed watch; 2. proof of work

	if (_p) // incoming message from remote peer
		DEV_GUARDED(m_filterLock)
			for (auto const& f: m_filters)
				if (f.second.filter.matches(_m))
					for (auto& i: m_watches)
						if (i.second.id == f.first)
						{
							i.second.changes.push_back(h);
							rating += 10; // subject to review
						}

	// TODO p2p: capability-based rating
	for (auto i: peerSessions())
	{
		auto w = i.first->cap<WhisperPeer>().get();
		if (w == _p)
			w->addRating(rating);
		else
			w->noteNewMessage(h, _m);
	}
}

unsigned WhisperHost::installWatch(shh::Topics const& _t)
{
	InstalledFilter f(_t);
	h256 h = f.filter.sha3();
	unsigned ret = 0;

	DEV_GUARDED(m_filterLock)
	{
		auto it = m_filters.find(h);
		if (m_filters.end() == it)
			m_filters.insert(make_pair(h, f));
		else
			it->second.refCount++;

		m_bloom.addRaw(f.filter.exportBloom());
		ret = m_watches.size() ? m_watches.rbegin()->first + 1 : 0;
		m_watches[ret] = ClientWatch(h);
		cwatshh << "+++" << ret << h;
	}

	noteAdvertiseTopicsOfInterest();
	return ret;
}

h256s WhisperHost::watchMessages(unsigned _watchId)
{
	h256s ret;
	auto wit = m_watches.find(_watchId);
	if (wit == m_watches.end())
		return ret;
	TopicFilter f;
	{
		Guard l(m_filterLock);
		auto fit = m_filters.find(wit->second.id);
		if (fit == m_filters.end())
			return ret;
		f = fit->second.filter;
	}
	ReadGuard l(x_messages);
	for (auto const& m: m_messages)
		if (f.matches(m.second))
			ret.push_back(m.first);
	return ret;
}

void WhisperHost::uninstallWatch(unsigned _i)
{
	cwatshh << "XXX" << _i;

	DEV_GUARDED(m_filterLock)
	{
		auto it = m_watches.find(_i);
		if (it == m_watches.end())
			return;

		auto id = it->second.id;
		m_watches.erase(it);

		auto fit = m_filters.find(id);
		if (fit != m_filters.end())
		{
			m_bloom.removeRaw(fit->second.filter.exportBloom());
			if (!--fit->second.refCount)
				m_filters.erase(fit);
		}
	}

	noteAdvertiseTopicsOfInterest();
}

void WhisperHost::doWork()
{
	for (auto i: peerSessions())
		i.first->cap<WhisperPeer>().get()->sendMessages();
	cleanup();
}

void WhisperHost::cleanup()
{
	// remove old messages.
	// should be called every now and again.
	unsigned now = (unsigned)time(0);
	WriteGuard l(x_messages);
	for (auto it = m_expiryQueue.begin(); it != m_expiryQueue.end() && it->first <= now; it = m_expiryQueue.erase(it))
		m_messages.erase(it->second);
}

void WhisperHost::noteAdvertiseTopicsOfInterest()
{
	for (auto i: peerSessions())
		i.first->cap<WhisperPeer>().get()->noteAdvertiseTopicsOfInterest();
}
<|endoftext|>


<commit_before>/*
 * GameKeeper Framework
 *
 * Copyright (C) 2013 Karol Herbst <gamekeeper@karolherbst.de>
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * 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., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 */

#include "pch.h"

#include <gamekeeper/core/boostpopropertyresolver.h>

#include <boost/program_options/variables_map.hpp>

GAMEKEEPER_NAMESPACE_START(core)

BoostPOPropertyResolver::BoostPOPropertyResolver(const boost::program_options::variables_map & map)
{
	for(auto p : map)
	{
		this->values.insert(this->values.end(), std::make_pair(p.first, p.second.value()));
	}
}

boost::any
BoostPOPropertyResolver::get(const std::string& key)
{
	auto it = this->values.find(key);
	if(it == this->values.end())
	{
		return nullptr;
	}
	return (*it).second;
}

GAMEKEEPER_NAMESPACE_END(core)
<commit_msg>core/boostpropertyresolver: return empty any if property not found<commit_after>/*
 * GameKeeper Framework
 *
 * Copyright (C) 2013 Karol Herbst <gamekeeper@karolherbst.de>
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * 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., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 */

#include "pch.h"

#include <gamekeeper/core/boostpopropertyresolver.h>

#include <boost/program_options/variables_map.hpp>

GAMEKEEPER_NAMESPACE_START(core)

BoostPOPropertyResolver::BoostPOPropertyResolver(const boost::program_options::variables_map & map)
{
	for(auto p : map)
	{
		this->values.insert(this->values.end(), std::make_pair(p.first, p.second.value()));
	}
}

boost::any
BoostPOPropertyResolver::get(const std::string& key)
{
	auto it = this->values.find(key);
	if(it == this->values.end())
	{
		return boost::any();
	}
	return (*it).second;
}

GAMEKEEPER_NAMESPACE_END(core)
<|endoftext|>