<commit_before>#include "editor.h"

using namespace fei;

void EditorScene::init()
{
	_editState = EditState::NONE;
	_mouseDown = false;
	_needInitUILayout = false;
	_editCircle.setRadius(64.0f);
	_editPolygon.setSolid(false);

	_editShapeObj.setColorAlpha(0.5f);

	Physics::getInstance()->setDoDebugDraw(true);
	Physics::getInstance()->setDebugDrawCamera(&_camera);
	Physics::getInstance()->setRatio(64.0f);

	setCamera(&_camera);

	_texture.setHasAlpha(true);
	add(&_texture);
	add(&_editShapeObj);
	add(&_uiLayer);

	_uiLayer.setCamera(&_uiCamera);
	_uiLayer.add(&_commandLabel);

	_fontCache.loadFont("res/font/wqy.ttc", 20);
	_commandLabel.setFontCache(&_fontCache);

	auto gravityFunc =
		[](std::vector<std::string> params)
		{
			double a = 0.0;
			double b = 0.0;
			if (params.size() == 2) {
				a = std::atof(params[0].c_str());
				b = std::atof(params[1].c_str());
				Physics::getInstance()->setGravity(Vec2(a, b));
			} else {
				return fut::CommandResult(fut::CommandResult::Type::ERROR, "Param size must be 2!");
			}
			return fut::CommandResult::Ok;
		};
	auto newRectFunc =
		[](std::vector<std::string> params)
		{
			double data[4] = {0.0};
			if (params.size() == 4) {
				for (int i = 0; i < 4; i++) {
					data[i] = std::atof(params[i].c_str());
				}
				auto body = Physics::getInstance()->createBody(Vec2::ZERO, Body::Type::DYNAMIC);
				Rect rect(data[0], data[1], data[2], data[3]);
				body->createFixture(&rect);
			} else {
				return fut::CommandResult(fut::CommandResult::Type::ERROR, "Param size must be 4!");
			}
			return fut::CommandResult::Ok;
		};
	auto newCircleFunc =
		[](std::vector<std::string> params)
		{
			double data[3] = {0.0};
			if (params.size() == 3) {
				for (int i = 0; i < 3; i++) {
					data[i] = std::atof(params[i].c_str());
				}
				auto body = Physics::getInstance()->createBody(Vec2::ZERO, Body::Type::DYNAMIC);
				Circle circle(Vec2(data[0], data[1]), data[2]);
				body->createFixture(&circle);
			} else {
				return fut::CommandResult(fut::CommandResult::Type::ERROR, "Param size must be 4!");
			}
			return fut::CommandResult::Ok;
		};
	auto newPolygonFunc =
		[](std::vector<std::string> params)
		{
			if (params.size() < 6) {
				auto ret = fut::CommandResult::Error;
				ret._result = "Vertices less than 3!";
				return ret;
			}
			Polygon poly;
			poly.setDataVector(fei::strVecToVec2Vec(params));
			auto body = Physics::getInstance()->createBody(Vec2::ZERO, Body::Type::DYNAMIC);
			body->createFixture(poly);
			return fut::CommandResult::Ok;
		};
	auto debugdrawFunc =
		[](std::vector<std::string> params)
		{
			if (params.size() == 1) {
				if (params[0] == "on") {
					Physics::getInstance()->setDoDebugDraw(true);
					return fut::CommandResult::Ok;
				} else if (params[0] == "off") {
					Physics::getInstance()->setDoDebugDraw(false);
					return fut::CommandResult::Ok;
				}
			}
			return fut::CommandResult(fut::CommandResult::Type::ERROR, "Param must be 'on' or 'off'!");
		};
	auto quitFunc =
		[](std::vector<std::string> params)
		{
			Application::getEngine()->exit();
			return fut::CommandResult::Ok;
		};
	auto loadImageFunc =
		[this](std::vector<std::string> params)
		{
			if (params.size() != 1) {
				return fut::CommandResult(fut::CommandResult::Type::ERROR, "Param must be image filename!");
			}
			_texture.load(params[0]);
			return fut::CommandResult::Ok;
		};
	auto editRectFunc =
		[this](std::vector<std::string> params)
		{
			editRect();
			return fut::CommandResult::Ok;
		};
	auto editCircleFunc =
		[this](std::vector<std::string> params)
		{
			editCircle();
			return fut::CommandResult::Ok;
		};
	auto editPolygonFunc =
		[this](std::vector<std::string> params)
		{
			editPolygon();
			return fut::CommandResult::Ok;
		};
	auto saveFunc =
		[this](std::vector<std::string> params)
		{
			if (params.size() >= 1) {
				_saveName = params[0];
			}
			return fut::CommandResult::Ok;
		};

	auto interpreter = _commandLabel.getInterpreter();
	interpreter->registerCommand({":set", "gravity"}, gravityFunc);
	interpreter->registerCommand({":set", "debugdraw"}, debugdrawFunc);
	interpreter->registerCommand({":new", "rect"}, newRectFunc);
	interpreter->registerCommand({":new", "circle"}, newCircleFunc);
	interpreter->registerCommand({":new", "polygon"}, newPolygonFunc);
	interpreter->registerCommand({":load", "img"}, loadImageFunc);
	interpreter->registerCommand({":edit", "rect"}, editRectFunc);
	interpreter->registerCommand({":edit", "circle"}, editCircleFunc);
	interpreter->registerCommand({":edit", "polygon"}, editPolygonFunc);
	interpreter->registerCommand({":w"}, saveFunc);
	interpreter->registerCommand({":q"}, quitFunc);

	initUILayout();
}

void EditorScene::update()
{
	auto window = Application::getEngine()->getWindow();
	auto deltaV = window->getRHCursorDeltaV() / _camera.getCameraScale();
	if (window->getMouseButton(GLFW_MOUSE_BUTTON_MIDDLE) == GLFW_PRESS) {
		_camera.move(-deltaV);
	}

	auto cursorWPos = getCursorWorldPos();
	_editShapeObj.setVisible(_mouseDown && _editState != EditState::NONE);
	switch (_editState) {
	case EditState::NONE:
		break;
	case EditState::RECT:
		_editRect = fei::Rect(_mouseDownPos, cursorWPos - _mouseDownPos);
		break;
	case EditState::CIRCLE:
		if (_mouseDown && window->getKey(GLFW_KEY_W)) {
			_editCircle.setRadius(_editCircle.getRadius() + 1.0f);
		}
		if (_mouseDown && window->getKey(GLFW_KEY_S)) {
			_editCircle.setRadius(_editCircle.getRadius() - 1.0f);
		}
		_editCircle.setPosition(cursorWPos);
		break;
	case EditState::POLYGON:
		break;
	}

	if (_needInitUILayout) {
		initUILayout();
		_needInitUILayout = false;
	}
}

void EditorScene::initUILayout()
{
	auto window = Application::getEngine()->getWindow();
	_camera.setCameraSize(window->getFrameSize());
	_uiCamera.setCameraSize(window->getFrameSize());
	_commandLabel.setPosition(_uiCamera.screenToWorld(Vec2(5.0f)));
}

void EditorScene::clearEditState()
{
	_mouseDown = false;
}

void EditorScene::editRect()
{
	clearEditState();
	_editState = EditState::RECT;
	_editShapeObj.setShape(&_editRect);
}

void EditorScene::editCircle()
{
	clearEditState();
	_editState = EditState::CIRCLE;
	_editShapeObj.setShape(&_editCircle);
}

void EditorScene::editPolygon()
{
	clearEditState();
	_editState = EditState::POLYGON;
	_editShapeObj.setShape(&_editPolygon);
}

const Vec2 EditorScene::getCursorWorldPos()
{
	auto window = Application::getEngine()->getWindow();
	return _camera.screenToWorld(window->getRHCursorPos());
}

void EditorScene::charactorCallback(unsigned int codepoint)
{
	_commandLabel.inputChar(static_cast<char>(codepoint));
}

void EditorScene::keyCallback(int key, int scancode, int action, int mods)
{
	auto window = Application::getEngine()->getWindow();
	switch (key) {
	case GLFW_KEY_BACKSPACE:
		if (action == GLFW_PRESS || action == GLFW_REPEAT) {
			_commandLabel.deleteChar();
		}
		break;
	case GLFW_KEY_F11:
		if (action == GLFW_PRESS) {
			window->setFullscreen(!window->isFullscreen());
			_needInitUILayout = true;
		}
		break;
	case GLFW_KEY_ENTER:
		if (action == GLFW_PRESS) {
			_commandLabel.executeCommand();
		}
		break;
	case GLFW_KEY_UP:
		if (action == GLFW_PRESS) {
			_commandLabel.prevCommand();
		}
		break;
	case GLFW_KEY_DOWN:
		if (action == GLFW_PRESS) {
			_commandLabel.nextCommand();
		}
		break;
	case GLFW_KEY_I:
		if (action == GLFW_PRESS && _editState == EditState::POLYGON && _mouseDown) {
			_editPolygon.insertVertexOnClosestSegment(getCursorWorldPos() - _editPolygon.getPosition());
		}
		break;
	case GLFW_KEY_V:
		if (action == GLFW_PRESS && _editState == EditState::POLYGON && _mouseDown) {
			_editPolygon.pushVertex(getCursorWorldPos() - _editPolygon.getPosition());
		}
		break;
	}
}

void EditorScene::scrollCallback(double xoffset, double yoffset)
{
	if (yoffset > 0.0) {
		_camera.zoomCameraScale(1.1f);
	} else if (yoffset < 0.0) {
		_camera.zoomCameraScale(0.9f);
	}
}

void EditorScene::mouseButtonCallback(int button, int action, int mods)
{
	auto bodyType = Body::Type::STATIC;
	auto cursorWPos = getCursorWorldPos();
	if (button == GLFW_MOUSE_BUTTON_LEFT) {
		if (action == GLFW_PRESS) {
			if (_editState != EditState::NONE) {
				_mouseDown = true;
				_mouseDownPos = getCursorWorldPos();
			}
		} else if (action == GLFW_RELEASE) {
			if (_mouseDown) {
				switch (_editState) {
				case EditState::NONE:
					break;
				case EditState::RECT:
					{
						auto body = Physics::getInstance()->createBody(Vec2::ZERO, bodyType);
						body->createFixture(&_editRect);
						_rectList.push_back(_editRect);
						_shapeList.push_back(&_rectList.back());
						_shapeBodyMap[&_rectList.back()] = body;
						break;
					}
				case EditState::CIRCLE:
					{
						auto body = Physics::getInstance()->createBody(Vec2::ZERO, bodyType);
						body->createFixture(&_editCircle);
						_circleList.push_back(_editCircle);
						_shapeList.push_back(&_circleList.back());
						_shapeBodyMap[&_circleList.back()] = body;
						break;
					}
				case EditState::POLYGON:
					{
						if (!_editPolygon.isValid()) {
							_editPolygon.clearVertex();
							break;
						}
						auto body = Physics::getInstance()->createBody(Vec2::ZERO, bodyType);
						body->createFixture(_editPolygon);
						_polygonList.push_back(_editPolygon);
						_shapeList.push_back(&_polygonList.back());
						_shapeBodyMap[&_polygonList.back()] = body;
						_editPolygon.clearVertex();
					}
					break;
				}
				_mouseDown = false;
			}
		}
	}
	if (button == GLFW_MOUSE_BUTTON_RIGHT && action == GLFW_PRESS) {
		for (auto shape = _shapeList.rbegin(); shape != _shapeList.rend(); ++shape) {
			if ((*shape)->collidePoint(cursorWPos)) {
				auto body = _shapeBodyMap[*shape];
				if (body) {
					Physics::getInstance()->destroyBody(body);
				}
				_shapeList.erase((++shape).base());
				break;
			}
		}
	}
}
<commit_msg>update CollisionEditor<commit_after>#include "editor.h"

using namespace fei;

void EditorScene::init()
{
	_editState = EditState::NONE;
	_mouseDown = false;
	_needInitUILayout = false;
	_editCircle.setRadius(64.0f);
	_editPolygon.setSolid(false);

	_editShapeObj.setColorAlpha(0.5f);

	Physics::getInstance()->setDoDebugDraw(true);
	Physics::getInstance()->setDebugDrawCamera(&_camera);
	Physics::getInstance()->setRatio(64.0f);

	setCamera(&_camera);

	_texture.setHasAlpha(true);
	add(&_texture);
	add(&_editShapeObj);
	add(&_uiLayer);

	_uiLayer.setCamera(&_uiCamera);
	_uiLayer.add(&_commandLabel);

	_fontCache.loadFont("res/font/wqy.ttc", 20);
	_commandLabel.setFontCache(&_fontCache);

	auto gravityFunc =
		[](std::vector<std::string> params)
		{
			double a = 0.0;
			double b = 0.0;
			if (params.size() == 2) {
				a = std::atof(params[0].c_str());
				b = std::atof(params[1].c_str());
				Physics::getInstance()->setGravity(Vec2(a, b));
			} else {
				return fut::CommandResult(fut::CommandResult::Type::ERROR, "Param size must be 2!");
			}
			return fut::CommandResult::Ok;
		};
	auto newRectFunc =
		[](std::vector<std::string> params)
		{
			double data[4] = {0.0};
			if (params.size() == 4) {
				for (int i = 0; i < 4; i++) {
					data[i] = std::atof(params[i].c_str());
				}
				auto body = Physics::getInstance()->createBody(Vec2::ZERO, Body::Type::DYNAMIC);
				Rect rect(data[0], data[1], data[2], data[3]);
				body->createFixture(&rect);
			} else {
				return fut::CommandResult(fut::CommandResult::Type::ERROR, "Param size must be 4!");
			}
			return fut::CommandResult::Ok;
		};
	auto newCircleFunc =
		[](std::vector<std::string> params)
		{
			double data[3] = {0.0};
			if (params.size() == 3) {
				for (int i = 0; i < 3; i++) {
					data[i] = std::atof(params[i].c_str());
				}
				auto body = Physics::getInstance()->createBody(Vec2::ZERO, Body::Type::DYNAMIC);
				Circle circle(Vec2(data[0], data[1]), data[2]);
				body->createFixture(&circle);
			} else {
				return fut::CommandResult(fut::CommandResult::Type::ERROR, "Param size must be 4!");
			}
			return fut::CommandResult::Ok;
		};
	auto newPolygonFunc =
		[](std::vector<std::string> params)
		{
			if (params.size() < 6) {
				auto ret = fut::CommandResult::Error;
				ret._result = "Vertices less than 3!";
				return ret;
			}
			Polygon poly;
			poly.setDataVector(fei::strVecToVec2Vec(params));
			auto body = Physics::getInstance()->createBody(Vec2::ZERO, Body::Type::DYNAMIC);
			body->createFixture(poly);
			return fut::CommandResult::Ok;
		};
	auto debugdrawFunc =
		[](std::vector<std::string> params)
		{
			if (params.size() == 1) {
				if (params[0] == "on") {
					Physics::getInstance()->setDoDebugDraw(true);
					return fut::CommandResult::Ok;
				} else if (params[0] == "off") {
					Physics::getInstance()->setDoDebugDraw(false);
					return fut::CommandResult::Ok;
				}
			}
			return fut::CommandResult(fut::CommandResult::Type::ERROR, "Param must be 'on' or 'off'!");
		};
	auto quitFunc =
		[](std::vector<std::string> params)
		{
			Application::getEngine()->exit();
			return fut::CommandResult::Ok;
		};
	auto loadImageFunc =
		[this](std::vector<std::string> params)
		{
			if (params.size() != 1) {
				return fut::CommandResult(fut::CommandResult::Type::ERROR, "Param must be image filename!");
			}
			_texture.load(params[0]);
			return fut::CommandResult::Ok;
		};
	auto editRectFunc =
		[this](std::vector<std::string> params)
		{
			editRect();
			return fut::CommandResult::Ok;
		};
	auto editCircleFunc =
		[this](std::vector<std::string> params)
		{
			editCircle();
			return fut::CommandResult::Ok;
		};
	auto editPolygonFunc =
		[this](std::vector<std::string> params)
		{
			editPolygon();
			return fut::CommandResult::Ok;
		};
	auto saveFunc =
		[this](std::vector<std::string> params)
		{
			if (params.size() >= 1) {
				_saveName = params[0];
			}
			return fut::CommandResult::Ok;
		};

	auto interpreter = _commandLabel.getInterpreter();
	interpreter->registerCommand({":set", "gravity"}, gravityFunc);
	interpreter->registerCommand({":set", "debugdraw"}, debugdrawFunc);
	interpreter->registerCommand({":new", "rect"}, newRectFunc);
	interpreter->registerCommand({":new", "circle"}, newCircleFunc);
	interpreter->registerCommand({":new", "polygon"}, newPolygonFunc);
	interpreter->registerCommand({":load", "img"}, loadImageFunc);
	interpreter->registerCommand({":edit", "rect"}, editRectFunc);
	interpreter->registerCommand({":edit", "circle"}, editCircleFunc);
	interpreter->registerCommand({":edit", "polygon"}, editPolygonFunc);
	interpreter->registerCommand({":w"}, saveFunc);
	interpreter->registerCommand({":q"}, quitFunc);

	initUILayout();
}

void EditorScene::update()
{
	auto window = Application::getEngine()->getWindow();
	auto deltaV = window->getRHCursorDeltaV() / _camera.getCameraScale();
	if (window->getMouseButton(GLFW_MOUSE_BUTTON_MIDDLE) == GLFW_PRESS || window->getKey(GLFW_KEY_SPACE)) {
		_camera.move(-deltaV);
	}

	auto cursorWPos = getCursorWorldPos();
	_editShapeObj.setVisible(_mouseDown && _editState != EditState::NONE);
	switch (_editState) {
	case EditState::NONE:
		break;
	case EditState::RECT:
		_editRect = fei::Rect(_mouseDownPos, cursorWPos - _mouseDownPos);
		break;
	case EditState::CIRCLE:
		if (_mouseDown && window->getKey(GLFW_KEY_W)) {
			_editCircle.setRadius(_editCircle.getRadius() + 1.0f);
		}
		if (_mouseDown && window->getKey(GLFW_KEY_S)) {
			_editCircle.setRadius(_editCircle.getRadius() - 1.0f);
		}
		_editCircle.setPosition(cursorWPos);
		break;
	case EditState::POLYGON:
		break;
	}

	if (_needInitUILayout) {
		initUILayout();
		_needInitUILayout = false;
	}
}

void EditorScene::initUILayout()
{
	auto window = Application::getEngine()->getWindow();
	_camera.setCameraSize(window->getFrameSize());
	_uiCamera.setCameraSize(window->getFrameSize());
	_commandLabel.setPosition(_uiCamera.screenToWorld(Vec2(5.0f)));
}

void EditorScene::clearEditState()
{
	_mouseDown = false;
}

void EditorScene::editRect()
{
	clearEditState();
	_editState = EditState::RECT;
	_editShapeObj.setShape(&_editRect);
}

void EditorScene::editCircle()
{
	clearEditState();
	_editState = EditState::CIRCLE;
	_editShapeObj.setShape(&_editCircle);
}

void EditorScene::editPolygon()
{
	clearEditState();
	_editState = EditState::POLYGON;
	_editShapeObj.setShape(&_editPolygon);
}

const Vec2 EditorScene::getCursorWorldPos()
{
	auto window = Application::getEngine()->getWindow();
	return _camera.screenToWorld(window->getRHCursorPos());
}

void EditorScene::charactorCallback(unsigned int codepoint)
{
	_commandLabel.inputChar(static_cast<char>(codepoint));
}

void EditorScene::keyCallback(int key, int scancode, int action, int mods)
{
	auto window = Application::getEngine()->getWindow();
	switch (key) {
	case GLFW_KEY_BACKSPACE:
		if (action == GLFW_PRESS || action == GLFW_REPEAT) {
			_commandLabel.deleteChar();
		}
		break;
	case GLFW_KEY_F11:
		if (action == GLFW_PRESS) {
			window->setFullscreen(!window->isFullscreen());
			_needInitUILayout = true;
		}
		break;
	case GLFW_KEY_ENTER:
		if (action == GLFW_PRESS) {
			_commandLabel.executeCommand();
		}
		break;
	case GLFW_KEY_UP:
		if (action == GLFW_PRESS) {
			_commandLabel.prevCommand();
		}
		break;
	case GLFW_KEY_DOWN:
		if (action == GLFW_PRESS) {
			_commandLabel.nextCommand();
		}
		break;
	case GLFW_KEY_I:
		if (action == GLFW_PRESS && _editState == EditState::POLYGON && _mouseDown) {
			_editPolygon.insertVertexOnClosestSegment(getCursorWorldPos() - _editPolygon.getPosition());
		}
		break;
	case GLFW_KEY_V:
		if (action == GLFW_PRESS && _editState == EditState::POLYGON && _mouseDown) {
			_editPolygon.pushVertex(getCursorWorldPos() - _editPolygon.getPosition());
		}
		break;
	}
}

void EditorScene::scrollCallback(double xoffset, double yoffset)
{
	if (yoffset > 0.0) {
		_camera.zoomCameraScale(1.1f);
	} else if (yoffset < 0.0) {
		_camera.zoomCameraScale(0.9f);
	}
}

void EditorScene::mouseButtonCallback(int button, int action, int mods)
{
	auto bodyType = Body::Type::STATIC;
	auto cursorWPos = getCursorWorldPos();
	if (button == GLFW_MOUSE_BUTTON_LEFT) {
		if (action == GLFW_PRESS) {
			if (_editState != EditState::NONE) {
				_mouseDown = true;
				_mouseDownPos = getCursorWorldPos();
			}
		} else if (action == GLFW_RELEASE) {
			if (_mouseDown) {
				switch (_editState) {
				case EditState::NONE:
					break;
				case EditState::RECT:
					{
						auto body = Physics::getInstance()->createBody(Vec2::ZERO, bodyType);
						body->createFixture(&_editRect);
						_rectList.push_back(_editRect);
						_shapeList.push_back(&_rectList.back());
						_shapeBodyMap[&_rectList.back()] = body;
						break;
					}
				case EditState::CIRCLE:
					{
						auto body = Physics::getInstance()->createBody(Vec2::ZERO, bodyType);
						body->createFixture(&_editCircle);
						_circleList.push_back(_editCircle);
						_shapeList.push_back(&_circleList.back());
						_shapeBodyMap[&_circleList.back()] = body;
						break;
					}
				case EditState::POLYGON:
					{
						if (!_editPolygon.isValid()) {
							_editPolygon.clearVertex();
							break;
						}
						auto body = Physics::getInstance()->createBody(Vec2::ZERO, bodyType);
						body->createFixture(_editPolygon);
						_polygonList.push_back(_editPolygon);
						_shapeList.push_back(&_polygonList.back());
						_shapeBodyMap[&_polygonList.back()] = body;
						_editPolygon.clearVertex();
					}
					break;
				}
				_mouseDown = false;
			}
		}
	}
	if (button == GLFW_MOUSE_BUTTON_RIGHT && action == GLFW_PRESS) {
		for (auto shape = _shapeList.rbegin(); shape != _shapeList.rend(); ++shape) {
			if ((*shape)->collidePoint(cursorWPos)) {
				auto body = _shapeBodyMap[*shape];
				if (body) {
					Physics::getInstance()->destroyBody(body);
				}
				_shapeList.erase((++shape).base());
				break;
			}
		}
	}
}
<|endoftext|>


<commit_before>// ImGui - standalone example application for SDL2 + OpenGL

#include <imgui.h>
#include "imgui_impl_sdl.h"
#include <stdio.h>
#include <SDL.h>
#include <SDL_opengl.h>

int main(int, char**)
{
    // Setup SDL
	if (SDL_Init(SDL_INIT_EVERYTHING) != 0)
        return -1;

    // Setup window
	SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
	SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 24);
	SDL_GL_SetAttribute(SDL_GL_STENCIL_SIZE, 8);
	SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 2);
	SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 2);
	SDL_DisplayMode current;
	SDL_GetCurrentDisplayMode(0, &current);
	SDL_Window *window = SDL_CreateWindow("ImGui SDL2+OpenGL example", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, 1280, 720, SDL_WINDOW_OPENGL|SDL_WINDOW_RESIZABLE);
	SDL_GLContext glcontext = SDL_GL_CreateContext(window);

    // Setup ImGui binding
    ImGui_ImplSdl_Init(window);

    // Load Fonts
    // (see extra_fonts/README.txt for more details)
    //ImGuiIO& io = ImGui::GetIO();
    //io.Fonts->AddFontDefault();
    //io.Fonts->AddFontFromFileTTF("../../extra_fonts/Cousine-Regular.ttf", 15.0f);
    //io.Fonts->AddFontFromFileTTF("../../extra_fonts/DroidSans.ttf", 16.0f);
    //io.Fonts->AddFontFromFileTTF("../../extra_fonts/ProggyClean.ttf", 13.0f);
    //io.Fonts->AddFontFromFileTTF("../../extra_fonts/ProggyTiny.ttf", 10.0f);
    //io.Fonts->AddFontFromFileTTF("c:\\Windows\\Fonts\\ArialUni.ttf", 18.0f, NULL, io.Fonts->GetGlyphRangesJapanese());

    // Merge glyphs from multiple fonts into one (e.g. combine default font with another with Chinese glyphs, or add icons)
    //ImWchar icons_ranges[] = { 0xf000, 0xf3ff, 0 };
    //ImFontConfig icons_config; icons_config.MergeMode = true; icons_config.PixelSnapH = true;
    //io.Fonts->AddFontFromFileTTF("../../extra_fonts/DroidSans.ttf", 18.0f);
    //io.Fonts->AddFontFromFileTTF("../../extra_fonts/fontawesome-webfont.ttf", 18.0f, &icons_config, icons_ranges);

    bool show_test_window = true;
    bool show_another_window = false;
    ImVec4 clear_color = ImColor(114, 144, 154);

    // Main loop
	bool done = false;
    while (!done)
    {
        SDL_Event event;
        while (SDL_PollEvent(&event))
        {
            ImGui_ImplSdl_ProcessEvent(&event);
            if (event.type == SDL_QUIT)
                done = true;
        }
        ImGui_ImplSdl_NewFrame(window);

        // 1. Show a simple window
        // Tip: if we don't call ImGui::Begin()/ImGui::End() the widgets appears in a window automatically called "Debug"
        {
            static float f = 0.0f;
            ImGui::Text("Hello, world!");
            ImGui::SliderFloat("float", &f, 0.0f, 1.0f);
            ImGui::ColorEdit3("clear color", (float*)&clear_color);
            if (ImGui::Button("Test Window")) show_test_window ^= 1;
            if (ImGui::Button("Another Window")) show_another_window ^= 1;
            ImGui::Text("Application average %.3f ms/frame (%.1f FPS)", 1000.0f / ImGui::GetIO().Framerate, ImGui::GetIO().Framerate);
        }

        // 2. Show another simple window, this time using an explicit Begin/End pair
        if (show_another_window)
        {
            ImGui::SetNextWindowSize(ImVec2(200,100), ImGuiSetCond_FirstUseEver);
            ImGui::Begin("Another Window", &show_another_window);
            ImGui::Text("Hello");
            ImGui::End();
        }

        // 3. Show the ImGui test window. Most of the sample code is in ImGui::ShowTestWindow()
        if (show_test_window)
        {
            ImGui::SetNextWindowPos(ImVec2(650, 20), ImGuiSetCond_FirstUseEver);
            ImGui::ShowTestWindow(&show_test_window);
        }

        // Rendering
        glViewport(0, 0, (int)ImGui::GetIO().DisplaySize.x, (int)ImGui::GetIO().DisplaySize.y);
        glClearColor(clear_color.x, clear_color.y, clear_color.z, clear_color.w);
        glClear(GL_COLOR_BUFFER_BIT);
        ImGui::Render();
        SDL_GL_SwapWindow(window);
    }

    // Cleanup
    ImGui_ImplSdl_Shutdown();
    SDL_GL_DeleteContext(glcontext);
	SDL_DestroyWindow(window);
	SDL_Quit();

    return 0;
}
<commit_msg>Show SDL error message on init failure<commit_after>// ImGui - standalone example application for SDL2 + OpenGL

#include <imgui.h>
#include "imgui_impl_sdl.h"
#include <stdio.h>
#include <SDL.h>
#include <SDL_opengl.h>

int main(int, char**)
{
    // Setup SDL
	if (SDL_Init(SDL_INIT_EVERYTHING) != 0)
	{
        printf("Error: %s", SDL_GetError());
        return -1;
	}

    // Setup window
	SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
	SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 24);
	SDL_GL_SetAttribute(SDL_GL_STENCIL_SIZE, 8);
	SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 2);
	SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 2);
	SDL_DisplayMode current;
	SDL_GetCurrentDisplayMode(0, &current);
	SDL_Window *window = SDL_CreateWindow("ImGui SDL2+OpenGL example", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, 1280, 720, SDL_WINDOW_OPENGL|SDL_WINDOW_RESIZABLE);
	SDL_GLContext glcontext = SDL_GL_CreateContext(window);

    // Setup ImGui binding
    ImGui_ImplSdl_Init(window);

    // Load Fonts
    // (see extra_fonts/README.txt for more details)
    //ImGuiIO& io = ImGui::GetIO();
    //io.Fonts->AddFontDefault();
    //io.Fonts->AddFontFromFileTTF("../../extra_fonts/Cousine-Regular.ttf", 15.0f);
    //io.Fonts->AddFontFromFileTTF("../../extra_fonts/DroidSans.ttf", 16.0f);
    //io.Fonts->AddFontFromFileTTF("../../extra_fonts/ProggyClean.ttf", 13.0f);
    //io.Fonts->AddFontFromFileTTF("../../extra_fonts/ProggyTiny.ttf", 10.0f);
    //io.Fonts->AddFontFromFileTTF("c:\\Windows\\Fonts\\ArialUni.ttf", 18.0f, NULL, io.Fonts->GetGlyphRangesJapanese());

    // Merge glyphs from multiple fonts into one (e.g. combine default font with another with Chinese glyphs, or add icons)
    //ImWchar icons_ranges[] = { 0xf000, 0xf3ff, 0 };
    //ImFontConfig icons_config; icons_config.MergeMode = true; icons_config.PixelSnapH = true;
    //io.Fonts->AddFontFromFileTTF("../../extra_fonts/DroidSans.ttf", 18.0f);
    //io.Fonts->AddFontFromFileTTF("../../extra_fonts/fontawesome-webfont.ttf", 18.0f, &icons_config, icons_ranges);

    bool show_test_window = true;
    bool show_another_window = false;
    ImVec4 clear_color = ImColor(114, 144, 154);

    // Main loop
	bool done = false;
    while (!done)
    {
        SDL_Event event;
        while (SDL_PollEvent(&event))
        {
            ImGui_ImplSdl_ProcessEvent(&event);
            if (event.type == SDL_QUIT)
                done = true;
        }
        ImGui_ImplSdl_NewFrame(window);

        // 1. Show a simple window
        // Tip: if we don't call ImGui::Begin()/ImGui::End() the widgets appears in a window automatically called "Debug"
        {
            static float f = 0.0f;
            ImGui::Text("Hello, world!");
            ImGui::SliderFloat("float", &f, 0.0f, 1.0f);
            ImGui::ColorEdit3("clear color", (float*)&clear_color);
            if (ImGui::Button("Test Window")) show_test_window ^= 1;
            if (ImGui::Button("Another Window")) show_another_window ^= 1;
            ImGui::Text("Application average %.3f ms/frame (%.1f FPS)", 1000.0f / ImGui::GetIO().Framerate, ImGui::GetIO().Framerate);
        }

        // 2. Show another simple window, this time using an explicit Begin/End pair
        if (show_another_window)
        {
            ImGui::SetNextWindowSize(ImVec2(200,100), ImGuiSetCond_FirstUseEver);
            ImGui::Begin("Another Window", &show_another_window);
            ImGui::Text("Hello");
            ImGui::End();
        }

        // 3. Show the ImGui test window. Most of the sample code is in ImGui::ShowTestWindow()
        if (show_test_window)
        {
            ImGui::SetNextWindowPos(ImVec2(650, 20), ImGuiSetCond_FirstUseEver);
            ImGui::ShowTestWindow(&show_test_window);
        }

        // Rendering
        glViewport(0, 0, (int)ImGui::GetIO().DisplaySize.x, (int)ImGui::GetIO().DisplaySize.y);
        glClearColor(clear_color.x, clear_color.y, clear_color.z, clear_color.w);
        glClear(GL_COLOR_BUFFER_BIT);
        ImGui::Render();
        SDL_GL_SwapWindow(window);
    }

    // Cleanup
    ImGui_ImplSdl_Shutdown();
    SDL_GL_DeleteContext(glcontext);
	SDL_DestroyWindow(window);
	SDL_Quit();

    return 0;
}
<|endoftext|>


<commit_before>// Copyright 2014 Duncan Smith
// https://github.com/dusmith1974/osoa
//
// 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.

// Implements the WebSocket class.

#include "osoa_pch.h"
#include "service/comms/web_socket.h"

#include <iostream>

#include "boost/asio.hpp"

#include "Poco/Format.h"
#include "Poco/Net/HTTPRequestHandler.h"
#include "Poco/Net/HTTPRequestHandlerFactory.h"
#include "Poco/Net/HTTPServer.h"
#include "Poco/Net/HTTPServerParams.h"
#include "Poco/Net/HTTPServerRequest.h"
#include "Poco/Net/HTTPServerResponse.h"
#include "Poco/Net/NetException.h"
#include "Poco/Net/ServerSocket.h"
#include "Poco/Net/WebSocket.h"
#include "Poco/Util/ServerApplication.h"

using Poco::Net::ServerSocket;
//using Poco::Net::WebSocket;
using Poco::Net::WebSocketException;
using Poco::Net::HTTPRequestHandler;
using Poco::Net::HTTPRequestHandlerFactory;
using Poco::Net::HTTPServer;
using Poco::Net::HTTPServerRequest;
using Poco::Net::HTTPResponse;
using Poco::Net::HTTPServerResponse;
using Poco::Net::HTTPServerParams;
using Poco::Timestamp;
using Poco::ThreadPool;
using Poco::Util::ServerApplication;
using Poco::Util::Application;

namespace osoa {

void handler(const boost::system::error_code& error, int /*signal_number*/) {
  if (!error) {
    // process signal
  }
}

// Handle a WebSocket connection.
class WebSocketRequestHandler : public HTTPRequestHandler {
 public:
  void handleRequest(HTTPServerRequest& request, HTTPServerResponse& response) {
    try {
      Poco::Net::WebSocket ws(request, response);
      std::cout << std::string("WebSocket connection established.") << std::endl;
      char buffer[1024];
      int flags;
      int n;
      do {
        n = ws.receiveFrame(buffer, sizeof(buffer), flags);
        std::cout << Poco::format("Frame received (length=%d, flags=0x%x).", n, unsigned(flags)) << std::endl; // use boost format?
        ws.sendFrame(buffer, n, flags);
      } while (n > 0 || (flags & Poco::Net::WebSocket::FRAME_OP_BITMASK) != Poco::Net::WebSocket::FRAME_OP_CLOSE);

      std::cout << "WebSocket connection closed." << std::endl;
    }
    catch (WebSocketException& exc) {
      std::cout << exc.what() << std::endl;
      switch (exc.code()) {
       case Poco::Net::WebSocket::WS_ERR_HANDSHAKE_UNSUPPORTED_VERSION:
        response.set("Sec-WebSocket-Version", Poco::Net::WebSocket::WEBSOCKET_VERSION);
        // fallthrough
       case Poco::Net::WebSocket::WS_ERR_NO_HANDSHAKE:
       case Poco::Net::WebSocket::WS_ERR_HANDSHAKE_NO_VERSION:
       case Poco::Net::WebSocket::WS_ERR_HANDSHAKE_NO_KEY:
        response.setStatusAndReason(HTTPResponse::HTTP_BAD_REQUEST);
        response.setContentLength(0);
        response.send();
        break;
      }
    }
  }
};

class RequestHandlerFactory: public HTTPRequestHandlerFactory
{
public:
  HTTPRequestHandler* createRequestHandler(const HTTPServerRequest& request)
  {
    std::string str = "Request from "
      + request.clientAddress().toString()
      + ": "
      + request.getMethod()
      + " "
      + request.getURI()
      + " "
      + request.getVersion();

    std::cout << str << std::endl;

    for (HTTPServerRequest::ConstIterator it = request.begin(); it != request.end(); ++it) {
      str = (it->first + ": " + it->second);
      std::cout << str << std::endl;
    }

    return new WebSocketRequestHandler;
  }
};

WebSocket::WebSocket() {
}

WebSocket::~WebSocket() {
}

void WebSocket::Run() {
    unsigned short port = 9980;

    // set-up a server socket
    ServerSocket svs(port);

    // set-up a HTTPServer instance
    HTTPServer srv(new RequestHandlerFactory, svs, new HTTPServerParams);

    // start the HTTPServer
    srv.start();

    // wait for CTRL-C or kill
    boost::asio::io_service io_service;
    boost::asio::signal_set signals(io_service, SIGINT, SIGTERM);
    signals.async_wait(handler);
    io_service.run();

    // Stop the HTTPServer
    srv.stop();
}

}  // namespcae osoa
<commit_msg>WebSocket<commit_after>// Copyright 2014 Duncan Smith
// https://github.com/dusmith1974/osoa
//
// 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.

// Implements the WebSocket class.

#include "osoa_pch.h"
#include "service/comms/web_socket.h"

#include <iostream>

#include "boost/asio.hpp"

#include "Poco/Format.h"
#include "Poco/Net/HTTPRequestHandler.h"
#include "Poco/Net/HTTPRequestHandlerFactory.h"
#include "Poco/Net/HTTPServer.h"
#include "Poco/Net/HTTPServerParams.h"
#include "Poco/Net/HTTPServerRequest.h"
#include "Poco/Net/HTTPServerResponse.h"
#include "Poco/Net/NetException.h"
#include "Poco/Net/ServerSocket.h"
#include "Poco/Net/WebSocket.h"
#include "Poco/Util/ServerApplication.h"

using Poco::Net::ServerSocket;
using Poco::Net::WebSocketException;
using Poco::Net::HTTPRequestHandler;
using Poco::Net::HTTPRequestHandlerFactory;
using Poco::Net::HTTPServer;
using Poco::Net::HTTPServerRequest;
using Poco::Net::HTTPResponse;
using Poco::Net::HTTPServerResponse;
using Poco::Net::HTTPServerParams;
using Poco::Timestamp;
using Poco::ThreadPool;
using Poco::Util::ServerApplication;
using Poco::Util::Application;

std::unique_ptr<Poco::Net::WebSocket> ws_;
int flags_;

namespace osoa {

void handler(const boost::system::error_code& error, int /*signal_number*/) {
  if (!error) {
    // process signal
  }
}

// Handle a WebSocket connection.
class WebSocketRequestHandler : public HTTPRequestHandler {
 public:
   WebSocketRequestHandler::WebSocketRequestHandler() /*: flags_{0}*/ {
   }

  void handleRequest(HTTPServerRequest& request, HTTPServerResponse& response) {
    try {
      int opcodes = 0;
      //Poco::Net::WebSocket ws(request, response);
      ws_ = std::unique_ptr<Poco::Net::WebSocket>(new Poco::Net::WebSocket(request, response));
      std::cout << std::string("WebSocket connection established.") << std::endl;
      char buffer[1024];
      int n;
      int msg_num = 0;
      do {
        n = ws_->receiveFrame(buffer, sizeof(buffer), flags_);
        opcodes = flags_ & Poco::Net::WebSocket::FRAME_OP_BITMASK;

        std::cout << Poco::format("Frame received (length=%d, flags_=0x%x, msg=%d).", n, unsigned(flags_), ++msg_num) << std::endl;

        //ws_->sendFrame(buffer, n, flags_);
        flags_ &= ~Poco::Net::WebSocket::FRAME_OP_BITMASK;
        flags_ |= Poco::Net::WebSocket::FRAME_OP_PING;
        ws_->sendFrame(buffer, 5, flags_);
        opcodes = flags_ & Poco::Net::WebSocket::FRAME_OP_BITMASK;

        // TODO(DS) Replace sleep with a deadline timer.
        boost::this_thread::sleep(boost::posix_time::seconds(1));

        /*std::string another = "another message";
        ws_->sendFrame(another.data(), another.length(), flags_);
        SendMessage("from call");*/

      } while (n > 0 || opcodes != Poco::Net::WebSocket::FRAME_OP_CLOSE);

      //std::cout << "WebSocket connection closed." << std::endl;
    }
    catch (WebSocketException& exc) {
      std::cout << exc.what() << std::endl;
      switch (exc.code()) {
       case Poco::Net::WebSocket::WS_ERR_HANDSHAKE_UNSUPPORTED_VERSION:
        response.set("Sec-WebSocket-Version", Poco::Net::WebSocket::WEBSOCKET_VERSION);
        // fallthrough
       case Poco::Net::WebSocket::WS_ERR_NO_HANDSHAKE:
       case Poco::Net::WebSocket::WS_ERR_HANDSHAKE_NO_VERSION:
       case Poco::Net::WebSocket::WS_ERR_HANDSHAKE_NO_KEY:
        response.setStatusAndReason(HTTPResponse::HTTP_BAD_REQUEST);
        response.setContentLength(0);
        response.send();
        break;
      }
    }
  }

  void SendMessage(const std::string& message) {
    ws_->sendFrame(message.data(), message.length(), flags_);
  }

 public:
   //std::unique_ptr<Poco::Net::WebSocket> ws_;
   //int flags_;
};

class RequestHandlerFactory: public HTTPRequestHandlerFactory
{
public:
  HTTPRequestHandler* createRequestHandler(const HTTPServerRequest& request)
  {
    std::string str = "Request from "
      + request.clientAddress().toString()
      + ": "
      + request.getMethod()
      + " "
      + request.getURI()
      + " "
      + request.getVersion();

    std::cout << str << std::endl;

    for (HTTPServerRequest::ConstIterator it = request.begin(); it != request.end(); ++it) {
      str = (it->first + ": " + it->second);
      std::cout << str << std::endl;
    }

    return new WebSocketRequestHandler;
  }
};

WebSocket::WebSocket() {
}

WebSocket::~WebSocket() {
}

void WebSocket::Run() {
    unsigned short port = 9980;

    // set-up a server socket
    ServerSocket svs(port);

    // set-up a HTTPServer instance
    HTTPServer srv(new RequestHandlerFactory, svs, new HTTPServerParams);

    // start the HTTPServer
    srv.start();

    //std::string message("hooray!");
    //ws_->sendFrame(message.data(), message.length(), flags_);

    // wait for CTRL-C or kill
    boost::asio::io_service io_service;
    boost::asio::signal_set signals(io_service, SIGINT, SIGTERM);
    signals.async_wait(handler);
    io_service.run();

    // Stop the HTTPServer
    srv.stop();
}

}  // namespcae osoa
<|endoftext|>


<commit_before>/**
 * \file        table_obj_seg.cpp
 * \author      Zhen Zeng (zengzhen@umich.edu)
 */

#include <iostream>
#include <pcl/io/pcd_io.h>
#include "ros_sec/TableObjectSegmentation/table_obj_seg.h"

#include <pcl/surface/convex_hull.h>
#include <pcl/segmentation/extract_polygonal_prism_data.h>

// #include <pcl/common/centroid.h>
#include "ros_sec/util/util.h"

#include <time.h>

bool TIMING = true;

bool compareClusterSize(const pcl::PointIndices& a,const pcl::PointIndices& b)
{
    return a.indices.size() > b.indices.size();
}

namespace TableObject{
    Segmentation::Segmentation()
    :_sceneCloud(),
    _inPlaneCloud(new Cloud),
    _outPlaneCloud (new Cloud),
    _cloud_hull(new Cloud),
    _tableTopCloud(new Cloud),
    _cloud_objects(new Cloud){};

    Segmentation::Segmentation(const std::string& pcd_file)
    :_sceneCloud(pcd_file),
    _inPlaneCloud(new Cloud),
    _outPlaneCloud (new Cloud),
    _cloud_hull(new Cloud),
    _tableTopCloud(new Cloud),
    _cloud_objects(new Cloud){};

    Segmentation::Segmentation(CloudConstPtr cloud)
    :_sceneCloud(cloud),
    _inPlaneCloud(new Cloud),
    _outPlaneCloud (new Cloud),
    _cloud_hull(new Cloud),
    _tableTopCloud(new Cloud),
    _cloud_objects(new Cloud){};

    void Segmentation::resetCloud(const std::string& pcd_file, bool downsample)
    {
        _sceneCloud.resetCloud(pcd_file, downsample);
    }

    void Segmentation::resetCloud(CloudConstPtr cloud)
    {
        _sceneCloud.resetCloud(cloud);
    }

    void Segmentation::setThreshold(int threshold)
    {
        _threshold=threshold;
    }

    void Segmentation::seg_hull(bool view2D)
    {
        if(view2D)
        {
            _viewer2D.viewImage(_sceneCloud.getCloud(), "frame");
            _viewer2D.writeImage("frame.png");
        }

        std::clock_t t;
        if(TIMING) t = clock();
        _sceneCloud.filterValid();
//         _sceneCloud.filterNoise();
        _sceneCloud.findPlane(0.01);
        _sceneCloud.getPlaneCoefficients(_coefficients);
        if(TIMING){
            t = clock() - t;
            std::printf("plane segmentation: %f seconds\n", ((float)t)/CLOCKS_PER_SEC);
        }

        // extract the inliers of the estimated plane
        _sceneCloud.extractPlane(_inPlaneCloud, _outPlaneCloud);
        if(view2D)
        {
            _viewer2D.viewImage(_inPlaneCloud, "plane");
            _viewer2D.writeImage("plane.png");
        }

        // filter small groups of points first before region growing
        pcl::IndicesPtr inliers(new std::vector<int>);
        _sceneCloud.getPlaneInliers(inliers);
        TableObject::pcdCloud inPlanePcdCloud(_inPlaneCloud);
        inPlanePcdCloud.setIndices(inliers);
//         inPlanePcdCloud.filterNoise();

        //region grow
        inPlanePcdCloud.regionGrow(false);

        //get largest cluster as table top
        pcl::PointIndices::Ptr plane_indices(new pcl::PointIndices);
        _tableTopCloud.reset(new Cloud);
        inPlanePcdCloud.getMaxCluster(plane_indices, _tableTopCloud);
        if(view2D)
        {
            _viewer2D.viewImage(_tableTopCloud, "tabletop");
            _viewer2D.writeImage("tabletop.png");
        }

        // Create a Convex Hull representation of the projected inliers
        pcl::ConvexHull<RefPointType> chull;
        chull.setInputCloud (_tableTopCloud);
        chull.setIndices(plane_indices);
        chull.reconstruct (*_cloud_hull);

        if(VERBOSE)
        {
            std::cout << "Convex hull has dimemsion of " << chull.getDimension() << std::endl;
            std::cout << "Convex hull has " << _cloud_hull->points.size () << " valid data points." << std::endl;
        }
    }

    void Segmentation::seg(bool view2D)
    {
        std::clock_t t;
        if(TIMING) t = clock();
        _sceneCloud.filterValid();
//         _sceneCloud.filterNoise();
        _sceneCloud.findPlane(0.01);
        _sceneCloud.getPlaneCoefficients(_coefficients);
        if(TIMING){
        	t = clock() - t;
        	std::printf("plane segmentation: %f seconds\n", ((float)t)/CLOCKS_PER_SEC);
        }

        // extract the inliers of the estimated plane
        _sceneCloud.extractPlane(_inPlaneCloud, _outPlaneCloud);
        if(view2D)
        {
            _viewer2D.viewImage(_sceneCloud.getCloud(), "frame");
            _viewer2D.writeImage("frame.png");
            _viewer2D.viewImage(_inPlaneCloud, "plane");
            _viewer2D.writeImage("plane.png");
            _viewer2D.viewImage(_outPlaneCloud, "out_plane");
            _viewer2D.writeImage("out_plane.png");
        }

        // filter small groups of points first before region growing
        pcl::IndicesPtr inliers(new std::vector<int>);
        _sceneCloud.getPlaneInliers(inliers);
        TableObject::pcdCloud inPlanePcdCloud(_inPlaneCloud);
        inPlanePcdCloud.setIndices(inliers);
//         inPlanePcdCloud.filterNoise();

        //region grow
        inPlanePcdCloud.regionGrow(false);

        //get largest cluster as table top
        pcl::PointIndices::Ptr plane_indices(new pcl::PointIndices);
        _tableTopCloud.reset(new Cloud);
        inPlanePcdCloud.getMaxCluster(plane_indices, _tableTopCloud);
        if(view2D)
        {
            _viewer2D.viewImage(_tableTopCloud, "tabletop");
            _viewer2D.writeImage("tabletop.png");
        }

        // Create a Convex Hull representation of the projected inliers
        pcl::ConvexHull<RefPointType> chull;
        chull.setInputCloud (_tableTopCloud);
        chull.setIndices(plane_indices);
        chull.reconstruct (*_cloud_hull);

        if(VERBOSE)
        {
            std::cout << "Convex hull has dimemsion of " << chull.getDimension() << std::endl;
            std::cout << "Convex hull has " << _cloud_hull->points.size () << " valid data points." << std::endl;
        }

        // get point clouds within planar prism
        pcl::ExtractPolygonalPrismData<RefPointType> prism;
        prism.setInputCloud(_outPlaneCloud);
        prism.setInputPlanarHull(_cloud_hull);
        prism.setHeightLimits(0, 0.5);
        pcl::PointIndices::Ptr output (new pcl::PointIndices);
        prism.segment(*output);

        // extract object clouds
        pcl::ExtractIndices<RefPointType> extract;
        extract.setInputCloud (_outPlaneCloud);
        extract.setIndices (output);
        extract.setKeepOrganized(true);
        extract.setNegative (false);
        extract.filter (*_cloud_objects);

        if(VERBOSE) std::cout << "Objects point cloud has: " << output->indices.size () << " valid data points." << std::endl;

        if(view2D)
        {
            _viewer2D.viewImage(_cloud_objects, "objects");
            _viewer2D.writeImage("objects.png");
        }

        //filter noise in extracted _cloud_objects
        TableObject::pcdCloud objectsPcdCloud(_cloud_objects);
        objectsPcdCloud.setIndices(*output);
//         objectsPcdCloud.filterNoise();
        objectsPcdCloud.regionGrow(false);
        objectsPcdCloud.getThresholdedClusters(_clusters, _threshold);
//         prune();

        std::sort(_clusters.begin(), _clusters.end(), compareClusterSize);

        if(VERBOSE)
        {
            for(int i=0;i<_clusters.size();i++)
                std::cout << "cluster[" << i << "] has " << _clusters[i].indices.size() << " points\n";
        }
    }

    void Segmentation::seg(CloudPtr cloud_hull, bool view2D)
    {
        _cloud_hull=cloud_hull;

        std::clock_t t;
        if(TIMING) t=std::clock();
//         _sceneCloud.filterValid();
//         _sceneCloud.filterNoise();
//         _sceneCloud.findPlane(0.005);
        if(TIMING){
        	t = clock() - t;
        	std::printf("plane segmentation: %f seconds\n", ((float)t)/CLOCKS_PER_SEC);
        }

        if(TIMING) t = std::clock();
        // extract the inliers of the estimated plane
//         _sceneCloud.extractPlane(_inPlaneCloud, _outPlaneCloud);
        if(view2D)
            _viewer2D.viewImage(_inPlaneCloud, "plane");

        // get point clouds within planar prism
        pcl::ExtractPolygonalPrismData<RefPointType> prism;
//         prism.setInputCloud(_outPlaneCloud);
        prism.setInputCloud(_sceneCloud.getCloud());
        prism.setInputPlanarHull(_cloud_hull);
        prism.setHeightLimits(0.005, 0.5);
        pcl::PointIndices::Ptr output (new pcl::PointIndices);
        prism.segment(*output);

        // extract object clouds
        pcl::ExtractIndices<RefPointType> extract;
//         extract.setInputCloud (_outPlaneCloud);
        extract.setInputCloud(_sceneCloud.getCloud());
        extract.setIndices (output);
        extract.setKeepOrganized(true);
        extract.setNegative (false);
        extract.filter (*_cloud_objects);

        if(TIMING){
        	t = clock() - t;
        	std::printf("extracting object points: %f seconds\n", ((float)t)/CLOCKS_PER_SEC);
        }

        if(VERBOSE) std::cout << "Objects point cloud has: " << output->indices.size () << " valid data points." << std::endl;

        if(view2D)
            _viewer2D.viewImage(_cloud_objects, "objects");

        if(TIMING) t = std::clock();
        //filter noise in extracted _cloud_objects
        TableObject::pcdCloud objectsPcdCloud(_cloud_objects);
        objectsPcdCloud.setIndices(*output);
        objectsPcdCloud.filterNoise();
        objectsPcdCloud.regionGrow(true);
        objectsPcdCloud.getThresholdedClusters(_clusters, _threshold);

        std::sort(_clusters.begin(), _clusters.end(), compareClusterSize);

        if(TIMING){
        	t = clock() - t;
        	std::printf("object clustering: %f seconds\n", ((float)t)/CLOCKS_PER_SEC);
        }

        if(VERBOSE)
        {
            for(int i=0;i<_clusters.size();i++)
                std::cout << "cluster[" << i << "] has " << _clusters[i].indices.size() << " points\n";
        }
    }

    void Segmentation::prune()
    {
        std::vector<Eigen::Vector4f,Eigen::aligned_allocator<Eigen::Vector4f> > centroids;
        computeObjCentroid(centroids);

        for(int i=_clusters.size()-1; i>=0; i--)
        {
            double distance;
            pcl::PointXYZ point;
            Eigen::Vector4f centroid = centroids[i];
            pcl::ModelCoefficients coefficients;

            point.x = centroid[1];
            point.y = centroid[2];
            point.z = centroid[3];
            _sceneCloud.getPlaneCoefficients(coefficients);
            distance=pcl::pointToPlaneDistance<pcl::PointXYZ>(point, coefficients.values[0], coefficients.values[1], coefficients.values[2], coefficients.values[3]);
            std::cout << "cluster[" << i << "] has centroid above the tabletop at " << distance << std::endl;

            if(distance<0.01)
            {
                std::cout << "cluster[" << i << "] is pruned\n";
                _clusters.erase(_clusters.begin()+i);
            }
        }
    }

    void Segmentation::getsceneCloud(pcdCloud& sceneCloud)
    {
        sceneCloud = _sceneCloud;
    }

    void Segmentation::getObjects(CloudPtr cloud_objects, std::vector< pcl::PointIndices >& clusters)
    {
        *cloud_objects=*_cloud_objects;
//         _removedIndices->assign(pass.getRemovedIndices()->begin(), pass.getRemovedIndices()->end());
        clusters.assign(_clusters.begin(), _clusters.end());
    }

    void Segmentation::getInPlaneCloud(CloudPtr inPlaneCloud)
    {
        *inPlaneCloud = *_inPlaneCloud;
    }

    void Segmentation::getOutPlaneCloud(CloudPtr outPlaneCloud)
    {
        *outPlaneCloud = *_outPlaneCloud;
    }

    void Segmentation::getCloudHull(CloudPtr cloudHull)
    {
        *cloudHull = *_cloud_hull;
    }

    void Segmentation::getTableTopCloud(CloudPtr tableTopCloud)
    {
        *tableTopCloud = *_tableTopCloud;
    }

	void Segmentation::getPlaneCoefficients(pcl::ModelCoefficients& coefficients)
	{
		coefficients = _coefficients;
	}

    void Segmentation::recordTarget(int cluster_id)
    {
        pcl::PCDWriter writer;
        CloudPtr target (new Cloud);
        pcl::copyPointCloud (*_cloud_objects, _clusters[cluster_id], *target);
        writer.write ("target.pcd", *target, false);
    }

    void Segmentation::computeObjCentroid(std::vector<Eigen::Vector4f,Eigen::aligned_allocator<Eigen::Vector4f> >& centroid)
    {
        TableObject::computeObjCentroid(_cloud_objects, _clusters, centroid);
    }

}
<commit_msg>MODIFY: seg(bool): objectsPcdCloud filterNoise() before regionGrow<commit_after>/**
 * \file        table_obj_seg.cpp
 * \author      Zhen Zeng (zengzhen@umich.edu)
 */

#include <iostream>
#include <pcl/io/pcd_io.h>
#include "ros_sec/TableObjectSegmentation/table_obj_seg.h"

#include <pcl/surface/convex_hull.h>
#include <pcl/segmentation/extract_polygonal_prism_data.h>

// #include <pcl/common/centroid.h>
#include "ros_sec/util/util.h"

#include <time.h>

bool TIMING = true;

bool compareClusterSize(const pcl::PointIndices& a,const pcl::PointIndices& b)
{
    return a.indices.size() > b.indices.size();
}

namespace TableObject{
    Segmentation::Segmentation()
    :_sceneCloud(),
    _inPlaneCloud(new Cloud),
    _outPlaneCloud (new Cloud),
    _cloud_hull(new Cloud),
    _tableTopCloud(new Cloud),
    _cloud_objects(new Cloud){};

    Segmentation::Segmentation(const std::string& pcd_file)
    :_sceneCloud(pcd_file),
    _inPlaneCloud(new Cloud),
    _outPlaneCloud (new Cloud),
    _cloud_hull(new Cloud),
    _tableTopCloud(new Cloud),
    _cloud_objects(new Cloud){};

    Segmentation::Segmentation(CloudConstPtr cloud)
    :_sceneCloud(cloud),
    _inPlaneCloud(new Cloud),
    _outPlaneCloud (new Cloud),
    _cloud_hull(new Cloud),
    _tableTopCloud(new Cloud),
    _cloud_objects(new Cloud){};

    void Segmentation::resetCloud(const std::string& pcd_file, bool downsample)
    {
        _sceneCloud.resetCloud(pcd_file, downsample);
    }

    void Segmentation::resetCloud(CloudConstPtr cloud)
    {
        _sceneCloud.resetCloud(cloud);
    }

    void Segmentation::setThreshold(int threshold)
    {
        _threshold=threshold;
    }

    void Segmentation::seg_hull(bool view2D)
    {
        if(view2D)
        {
            _viewer2D.viewImage(_sceneCloud.getCloud(), "frame");
            _viewer2D.writeImage("frame.png");
        }

        std::clock_t t;
        if(TIMING) t = clock();
        _sceneCloud.filterValid();
//         _sceneCloud.filterNoise();
        _sceneCloud.findPlane(0.01);
        _sceneCloud.getPlaneCoefficients(_coefficients);
        if(TIMING){
            t = clock() - t;
            std::printf("plane segmentation: %f seconds\n", ((float)t)/CLOCKS_PER_SEC);
        }

        // extract the inliers of the estimated plane
        _sceneCloud.extractPlane(_inPlaneCloud, _outPlaneCloud);
        if(view2D)
        {
            _viewer2D.viewImage(_inPlaneCloud, "plane");
            _viewer2D.writeImage("plane.png");
        }

        // filter small groups of points first before region growing
        pcl::IndicesPtr inliers(new std::vector<int>);
        _sceneCloud.getPlaneInliers(inliers);
        TableObject::pcdCloud inPlanePcdCloud(_inPlaneCloud);
        inPlanePcdCloud.setIndices(inliers);
//         inPlanePcdCloud.filterNoise();

        //region grow
        inPlanePcdCloud.regionGrow(false);

        //get largest cluster as table top
        pcl::PointIndices::Ptr plane_indices(new pcl::PointIndices);
        _tableTopCloud.reset(new Cloud);
        inPlanePcdCloud.getMaxCluster(plane_indices, _tableTopCloud);
        if(view2D)
        {
            _viewer2D.viewImage(_tableTopCloud, "tabletop");
            _viewer2D.writeImage("tabletop.png");
        }

        // Create a Convex Hull representation of the projected inliers
        pcl::ConvexHull<RefPointType> chull;
        chull.setInputCloud (_tableTopCloud);
        chull.setIndices(plane_indices);
        chull.reconstruct (*_cloud_hull);

        if(VERBOSE)
        {
            std::cout << "Convex hull has dimemsion of " << chull.getDimension() << std::endl;
            std::cout << "Convex hull has " << _cloud_hull->points.size () << " valid data points." << std::endl;
        }
    }

    void Segmentation::seg(bool view2D)
    {
        std::clock_t t;
        if(TIMING) t = clock();
        _sceneCloud.filterValid();
//         _sceneCloud.filterNoise();
        _sceneCloud.findPlane(0.01);
        _sceneCloud.getPlaneCoefficients(_coefficients);
        if(TIMING){
        	t = clock() - t;
        	std::printf("plane segmentation: %f seconds\n", ((float)t)/CLOCKS_PER_SEC);
        }

        // extract the inliers of the estimated plane
        _sceneCloud.extractPlane(_inPlaneCloud, _outPlaneCloud);
        if(view2D)
        {
            _viewer2D.viewImage(_sceneCloud.getCloud(), "frame");
            _viewer2D.writeImage("frame.png");
            _viewer2D.viewImage(_inPlaneCloud, "plane");
            _viewer2D.writeImage("plane.png");
            _viewer2D.viewImage(_outPlaneCloud, "out_plane");
            _viewer2D.writeImage("out_plane.png");
        }

        // filter small groups of points first before region growing
        pcl::IndicesPtr inliers(new std::vector<int>);
        _sceneCloud.getPlaneInliers(inliers);
        TableObject::pcdCloud inPlanePcdCloud(_inPlaneCloud);
        inPlanePcdCloud.setIndices(inliers);
//         inPlanePcdCloud.filterNoise();

        //region grow
        inPlanePcdCloud.regionGrow(false);

        //get largest cluster as table top
        pcl::PointIndices::Ptr plane_indices(new pcl::PointIndices);
        _tableTopCloud.reset(new Cloud);
        inPlanePcdCloud.getMaxCluster(plane_indices, _tableTopCloud);
        if(view2D)
        {
            _viewer2D.viewImage(_tableTopCloud, "tabletop");
            _viewer2D.writeImage("tabletop.png");
        }

        // Create a Convex Hull representation of the projected inliers
        pcl::ConvexHull<RefPointType> chull;
        chull.setInputCloud (_tableTopCloud);
        chull.setIndices(plane_indices);
        chull.reconstruct (*_cloud_hull);

        if(VERBOSE)
        {
            std::cout << "Convex hull has dimemsion of " << chull.getDimension() << std::endl;
            std::cout << "Convex hull has " << _cloud_hull->points.size () << " valid data points." << std::endl;
        }

        // get point clouds within planar prism
        pcl::ExtractPolygonalPrismData<RefPointType> prism;
        prism.setInputCloud(_outPlaneCloud);
        prism.setInputPlanarHull(_cloud_hull);
        prism.setHeightLimits(0, 0.5);
        pcl::PointIndices::Ptr output (new pcl::PointIndices);
        prism.segment(*output);

        // extract object clouds
        pcl::ExtractIndices<RefPointType> extract;
        extract.setInputCloud (_outPlaneCloud);
        extract.setIndices (output);
        extract.setKeepOrganized(true);
        extract.setNegative (false);
        extract.filter (*_cloud_objects);

        if(VERBOSE) std::cout << "Objects point cloud has: " << output->indices.size () << " valid data points." << std::endl;

        if(view2D)
        {
            _viewer2D.viewImage(_cloud_objects, "objects");
            _viewer2D.writeImage("objects.png");
        }

        //filter noise in extracted _cloud_objects
        TableObject::pcdCloud objectsPcdCloud(_cloud_objects);
        objectsPcdCloud.setIndices(*output);
        objectsPcdCloud.filterNoise();
        objectsPcdCloud.regionGrow(false);
        objectsPcdCloud.getThresholdedClusters(_clusters, _threshold);
//         prune();

        std::sort(_clusters.begin(), _clusters.end(), compareClusterSize);

        if(VERBOSE)
        {
            for(int i=0;i<_clusters.size();i++)
                std::cout << "cluster[" << i << "] has " << _clusters[i].indices.size() << " points\n";
        }
    }

    void Segmentation::seg(CloudPtr cloud_hull, bool view2D)
    {
        _cloud_hull=cloud_hull;

        std::clock_t t;
        if(TIMING) t=std::clock();
//         _sceneCloud.filterValid();
//         _sceneCloud.filterNoise();
//         _sceneCloud.findPlane(0.005);
        if(TIMING){
        	t = clock() - t;
        	std::printf("plane segmentation: %f seconds\n", ((float)t)/CLOCKS_PER_SEC);
        }

        if(TIMING) t = std::clock();
        // extract the inliers of the estimated plane
//         _sceneCloud.extractPlane(_inPlaneCloud, _outPlaneCloud);
        if(view2D)
            _viewer2D.viewImage(_inPlaneCloud, "plane");

        // get point clouds within planar prism
        pcl::ExtractPolygonalPrismData<RefPointType> prism;
//         prism.setInputCloud(_outPlaneCloud);
        prism.setInputCloud(_sceneCloud.getCloud());
        prism.setInputPlanarHull(_cloud_hull);
        prism.setHeightLimits(0.005, 0.5);
        pcl::PointIndices::Ptr output (new pcl::PointIndices);
        prism.segment(*output);

        // extract object clouds
        pcl::ExtractIndices<RefPointType> extract;
//         extract.setInputCloud (_outPlaneCloud);
        extract.setInputCloud(_sceneCloud.getCloud());
        extract.setIndices (output);
        extract.setKeepOrganized(true);
        extract.setNegative (false);
        extract.filter (*_cloud_objects);

        if(TIMING){
        	t = clock() - t;
        	std::printf("extracting object points: %f seconds\n", ((float)t)/CLOCKS_PER_SEC);
        }

        if(VERBOSE) std::cout << "Objects point cloud has: " << output->indices.size () << " valid data points." << std::endl;

        if(view2D)
            _viewer2D.viewImage(_cloud_objects, "objects");

        if(TIMING) t = std::clock();
        //filter noise in extracted _cloud_objects
        TableObject::pcdCloud objectsPcdCloud(_cloud_objects);
        objectsPcdCloud.setIndices(*output);
        objectsPcdCloud.filterNoise();
        objectsPcdCloud.regionGrow(true);
        objectsPcdCloud.getThresholdedClusters(_clusters, _threshold);

        std::sort(_clusters.begin(), _clusters.end(), compareClusterSize);

        if(TIMING){
        	t = clock() - t;
        	std::printf("object clustering: %f seconds\n", ((float)t)/CLOCKS_PER_SEC);
        }

        if(VERBOSE)
        {
            for(int i=0;i<_clusters.size();i++)
                std::cout << "cluster[" << i << "] has " << _clusters[i].indices.size() << " points\n";
        }
    }

    void Segmentation::prune()
    {
        std::vector<Eigen::Vector4f,Eigen::aligned_allocator<Eigen::Vector4f> > centroids;
        computeObjCentroid(centroids);

        for(int i=_clusters.size()-1; i>=0; i--)
        {
            double distance;
            pcl::PointXYZ point;
            Eigen::Vector4f centroid = centroids[i];
            pcl::ModelCoefficients coefficients;

            point.x = centroid[1];
            point.y = centroid[2];
            point.z = centroid[3];
            _sceneCloud.getPlaneCoefficients(coefficients);
            distance=pcl::pointToPlaneDistance<pcl::PointXYZ>(point, coefficients.values[0], coefficients.values[1], coefficients.values[2], coefficients.values[3]);
            std::cout << "cluster[" << i << "] has centroid above the tabletop at " << distance << std::endl;

            if(distance<0.01)
            {
                std::cout << "cluster[" << i << "] is pruned\n";
                _clusters.erase(_clusters.begin()+i);
            }
        }
    }

    void Segmentation::getsceneCloud(pcdCloud& sceneCloud)
    {
        sceneCloud = _sceneCloud;
    }

    void Segmentation::getObjects(CloudPtr cloud_objects, std::vector< pcl::PointIndices >& clusters)
    {
        *cloud_objects=*_cloud_objects;
//         _removedIndices->assign(pass.getRemovedIndices()->begin(), pass.getRemovedIndices()->end());
        clusters.assign(_clusters.begin(), _clusters.end());
    }

    void Segmentation::getInPlaneCloud(CloudPtr inPlaneCloud)
    {
        *inPlaneCloud = *_inPlaneCloud;
    }

    void Segmentation::getOutPlaneCloud(CloudPtr outPlaneCloud)
    {
        *outPlaneCloud = *_outPlaneCloud;
    }

    void Segmentation::getCloudHull(CloudPtr cloudHull)
    {
        *cloudHull = *_cloud_hull;
    }

    void Segmentation::getTableTopCloud(CloudPtr tableTopCloud)
    {
        *tableTopCloud = *_tableTopCloud;
    }

	void Segmentation::getPlaneCoefficients(pcl::ModelCoefficients& coefficients)
	{
		coefficients = _coefficients;
	}

    void Segmentation::recordTarget(int cluster_id)
    {
        pcl::PCDWriter writer;
        CloudPtr target (new Cloud);
        pcl::copyPointCloud (*_cloud_objects, _clusters[cluster_id], *target);
        writer.write ("target.pcd", *target, false);
    }

    void Segmentation::computeObjCentroid(std::vector<Eigen::Vector4f,Eigen::aligned_allocator<Eigen::Vector4f> >& centroid)
    {
        TableObject::computeObjCentroid(_cloud_objects, _clusters, centroid);
    }

}
<|endoftext|>


<commit_before>// @(#)root/cintex:$Id$
// Author: Pere Mato 2005

// Copyright CERN, CH-1211 Geneva 23, 2004-2005, All rights reserved.
//
// Permission to use, copy, modify, and distribute this software for any
// purpose is hereby granted without fee, provided that this copyright and
// permissions notice appear in all copies and derivatives.
//
// This software is provided "as is" without express or implied warranty.

#include "Reflex/Callback.h"
#include "Reflex/Type.h"
#include "Reflex/Member.h"
#include "Reflex/Member.h"
#include "Reflex/Builder/ReflexBuilder.h"

#include "Cintex/Cintex.h"
#include "CINTClassBuilder.h"
#include "CINTFunctionBuilder.h"
#include "CINTVariableBuilder.h"
#include "CINTTypedefBuilder.h"
#include "CINTEnumBuilder.h"
#include "ROOTClassEnhancer.h"
#include "CINTSourceFile.h"
#include <iostream>

using namespace ROOT::Reflex;
using namespace ROOT::Cintex;
using namespace std;

//Build the Cintex dictionary on Reflex and convert it to CINT
namespace {
   struct Cintex_dict_t {
   public:
      Cintex_dict_t() {
         //--Reflex class builder
         //NamespaceBuilder( "ROOT::Cintex" );
         Type t_void = TypeBuilder("void");
         Type t_int  = TypeBuilder("int");
         Type t_bool = TypeBuilder("bool");
         ClassBuilderT< Cintex >("Cintex", PUBLIC)
            .AddFunctionMember(FunctionTypeBuilder(t_void), "Enable", Enable, 0, 0, PUBLIC | STATIC)
            .AddFunctionMember(FunctionTypeBuilder(t_void, t_int), "SetDebug", SetDebug, 0, 0, PUBLIC | STATIC)
            .AddFunctionMember(FunctionTypeBuilder(t_int), "Debug", Debug, 0, 0, PUBLIC | STATIC)
            .AddFunctionMember(FunctionTypeBuilder(t_bool), "PropagateClassTypedefs", PropagateClassTypedefs, 0, 0, PUBLIC | STATIC)
            .AddFunctionMember(FunctionTypeBuilder(t_void, t_bool), "SetPropagateClassTypedefs", SetPropagateClassTypedefs, 0, 0, PUBLIC | STATIC);

         //--CINT class builder
         Type t = Type::ByName("Cintex");
         ROOT::Cintex::CINTClassBuilder::Get(t).Setup();
      }
      static void* Enable(void*, const std::vector<void*>&, void*) {
         Cintex::Enable();
         return 0;
      }
      static void* SetDebug(void*, const std::vector<void*>& arg, void*) {
         Cintex::SetDebug(*(bool*)arg[0]);
         return 0;
      }
      static void* Debug(void*, const std::vector<void*>&, void*) {
         static int b = Cintex::Debug();
         return &b;
      }

      static void* PropagateClassTypedefs(void*, const std::vector<void*>&, void*) {
         static bool b = Cintex::PropagateClassTypedefs();
         return &b;
      }

      static void* SetPropagateClassTypedefs(void*, const std::vector<void*>& arg, void*) {
         Cintex::SetPropagateClassTypedefs(*(bool*)arg[0]);
         return 0;
      }

   };
   static Cintex_dict_t s_dict;

   static const char* btypes[] = { "bool", "char", "unsigned char", "short", "unsigned short", "int", "unsigned int",
     "long", "unsigned long", "float", "double", "string" };

   void Declare_additional_CINT_typedefs() {
      // as the function name says
      char name[256], value[512];
      int autoload = G__set_class_autoloading(0); // To avoid recursive loads
      for ( size_t i = 0; i < sizeof(btypes)/sizeof(char*); i ++ ) {
         //--- vector ---
         sprintf(name,"vector<%s>", btypes[i]);
         sprintf(value,"vector<%s,allocator<%s> >", btypes[i], btypes[i]);
         CINTTypedefBuilder::Set(name, value);
      }
      G__set_class_autoloading(autoload);
   }
}

namespace ROOT {
   namespace Cintex {

      Cintex& Cintex::Instance() {
         static Cintex s_instance;
         return s_instance;
      }

      Cintex::Cintex() {
         fCallback = new Callback();
         fRootcreator = 0;
         fDbglevel = 0;
         fPropagateClassTypedefs = true;
         fPropagateClassEnums = true;
         fEnabled = false;
      }

      Cintex::~Cintex() {
         if( fCallback ) UninstallClassCallback( fCallback );
         delete fCallback;
      }

      void Cintex::Enable() {
         if ( Instance().fEnabled ) return;
         //---Declare some extra typdefs to please CINT
         Declare_additional_CINT_typedefs();
         //---Install the callback to fothcoming classes ----//
         InstallClassCallback( Instance().fCallback );
         //---Convert to CINT all existing classes ---//
         for( size_t i = 0; i < Type::TypeSize(); i++ ) {

            ( * Instance().fCallback)( Type::TypeAt(i) );
         }
         //---Convert to CINT all existing free functions and variables
         for ( size_t n = 0; n < Scope::ScopeSize(); n++ ) {
            Scope ns = Scope::ScopeAt(n);
            if ( ns.IsNamespace() ) {
               for( size_t m = 0; m < ns.MemberSize(); m++ ) {
                  ( * Instance().fCallback)( ns.MemberAt(m) );
               }
            }
         }
         Instance().fEnabled = true;
      }

      void Cintex::SetROOTCreator(ROOTCreator_t c) {
         Instance().fRootcreator = c;
      }

      ROOTCreator_t Cintex::GetROOTCreator() {
         return Instance().fRootcreator;
      }

      int Cintex::Debug() {
         return Instance().fDbglevel;
      }

      void Cintex::SetDebug(int l) {
         Instance().fDbglevel = l;
      }

      bool Cintex::PropagateClassTypedefs() {
         return Instance().fPropagateClassTypedefs;
      }

      void Cintex::SetPropagateClassTypedefs(bool val) {
         Instance().fPropagateClassTypedefs = val;
      }

      bool Cintex::PropagateClassEnums() {
         return Instance().fPropagateClassEnums;
      }

      void Cintex::SetPropagateClassEnums(bool val) {
         Instance().fPropagateClassEnums = val;
      }

      void Callback::operator () ( const Type& t ) {
         ArtificialSourceFile asf;
         int autoload = G__set_class_autoloading(0); // To avoid recursive loads
         if ( t.IsClass() || t.IsStruct() ) {
            ROOTClassEnhancer enhancer(t);
            enhancer.Setup();
            CINTClassBuilder::Get(t).Setup();
            enhancer.CreateInfo();
         }
         else if ( t.IsTypedef() ) {
            CINTTypedefBuilder::Setup(t);
         }
         else if ( t.IsEnum() ) {
            CINTEnumBuilder::Setup(t);
         }
         G__set_class_autoloading(autoload);
      }

      void Callback::operator () ( const Member& m ) {
         ArtificialSourceFile asf;
         int autoload = G__set_class_autoloading(0); // To avoid recursive loads
         if ( m.IsFunctionMember() ) {
            if( Cintex::Debug() ) cout << "Cintex: Building function " << m.Name(SCOPED|QUALIFIED) << endl;
            CINTFunctionBuilder(m).Setup();
         }
         else if ( m.IsDataMember() ) {
            if( Cintex::Debug() ) cout << "Cintex: Building variable " << m.Name(SCOPED|QUALIFIED) << endl;
            CINTVariableBuilder(m).Setup();
         }
         G__set_class_autoloading(autoload);
      }
   }
}
<commit_msg>Increase size of local tables in function Declare_additional_CINT_typedefs. This is a CMS request.<commit_after>// @(#)root/cintex:$Id$
// Author: Pere Mato 2005

// Copyright CERN, CH-1211 Geneva 23, 2004-2005, All rights reserved.
//
// Permission to use, copy, modify, and distribute this software for any
// purpose is hereby granted without fee, provided that this copyright and
// permissions notice appear in all copies and derivatives.
//
// This software is provided "as is" without express or implied warranty.

#include "Reflex/Callback.h"
#include "Reflex/Type.h"
#include "Reflex/Member.h"
#include "Reflex/Member.h"
#include "Reflex/Builder/ReflexBuilder.h"

#include "Cintex/Cintex.h"
#include "CINTClassBuilder.h"
#include "CINTFunctionBuilder.h"
#include "CINTVariableBuilder.h"
#include "CINTTypedefBuilder.h"
#include "CINTEnumBuilder.h"
#include "ROOTClassEnhancer.h"
#include "CINTSourceFile.h"
#include <iostream>

using namespace ROOT::Reflex;
using namespace ROOT::Cintex;
using namespace std;

//Build the Cintex dictionary on Reflex and convert it to CINT
namespace {
   struct Cintex_dict_t {
   public:
      Cintex_dict_t() {
         //--Reflex class builder
         //NamespaceBuilder( "ROOT::Cintex" );
         Type t_void = TypeBuilder("void");
         Type t_int  = TypeBuilder("int");
         Type t_bool = TypeBuilder("bool");
         ClassBuilderT< Cintex >("Cintex", PUBLIC)
            .AddFunctionMember(FunctionTypeBuilder(t_void), "Enable", Enable, 0, 0, PUBLIC | STATIC)
            .AddFunctionMember(FunctionTypeBuilder(t_void, t_int), "SetDebug", SetDebug, 0, 0, PUBLIC | STATIC)
            .AddFunctionMember(FunctionTypeBuilder(t_int), "Debug", Debug, 0, 0, PUBLIC | STATIC)
            .AddFunctionMember(FunctionTypeBuilder(t_bool), "PropagateClassTypedefs", PropagateClassTypedefs, 0, 0, PUBLIC | STATIC)
            .AddFunctionMember(FunctionTypeBuilder(t_void, t_bool), "SetPropagateClassTypedefs", SetPropagateClassTypedefs, 0, 0, PUBLIC | STATIC);

         //--CINT class builder
         Type t = Type::ByName("Cintex");
         ROOT::Cintex::CINTClassBuilder::Get(t).Setup();
      }
      static void* Enable(void*, const std::vector<void*>&, void*) {
         Cintex::Enable();
         return 0;
      }
      static void* SetDebug(void*, const std::vector<void*>& arg, void*) {
         Cintex::SetDebug(*(bool*)arg[0]);
         return 0;
      }
      static void* Debug(void*, const std::vector<void*>&, void*) {
         static int b = Cintex::Debug();
         return &b;
      }

      static void* PropagateClassTypedefs(void*, const std::vector<void*>&, void*) {
         static bool b = Cintex::PropagateClassTypedefs();
         return &b;
      }

      static void* SetPropagateClassTypedefs(void*, const std::vector<void*>& arg, void*) {
         Cintex::SetPropagateClassTypedefs(*(bool*)arg[0]);
         return 0;
      }

   };
   static Cintex_dict_t s_dict;

   static const char* btypes[] = { "bool", "char", "unsigned char", "short", "unsigned short", "int", "unsigned int",
     "long", "unsigned long", "float", "double", "string" };

   void Declare_additional_CINT_typedefs() {
      // as the function name says
      char name[4096], value[8192];
      int autoload = G__set_class_autoloading(0); // To avoid recursive loads
      for ( size_t i = 0; i < sizeof(btypes)/sizeof(char*); i ++ ) {
         //--- vector ---
         sprintf(name,"vector<%s>", btypes[i]);
         sprintf(value,"vector<%s,allocator<%s> >", btypes[i], btypes[i]);
         CINTTypedefBuilder::Set(name, value);
      }
      G__set_class_autoloading(autoload);
   }
}

namespace ROOT {
   namespace Cintex {

      Cintex& Cintex::Instance() {
         static Cintex s_instance;
         return s_instance;
      }

      Cintex::Cintex() {
         fCallback = new Callback();
         fRootcreator = 0;
         fDbglevel = 0;
         fPropagateClassTypedefs = true;
         fPropagateClassEnums = true;
         fEnabled = false;
      }

      Cintex::~Cintex() {
         if( fCallback ) UninstallClassCallback( fCallback );
         delete fCallback;
      }

      void Cintex::Enable() {
         if ( Instance().fEnabled ) return;
         //---Declare some extra typdefs to please CINT
         Declare_additional_CINT_typedefs();
         //---Install the callback to fothcoming classes ----//
         InstallClassCallback( Instance().fCallback );
         //---Convert to CINT all existing classes ---//
         for( size_t i = 0; i < Type::TypeSize(); i++ ) {

            ( * Instance().fCallback)( Type::TypeAt(i) );
         }
         //---Convert to CINT all existing free functions and variables
         for ( size_t n = 0; n < Scope::ScopeSize(); n++ ) {
            Scope ns = Scope::ScopeAt(n);
            if ( ns.IsNamespace() ) {
               for( size_t m = 0; m < ns.MemberSize(); m++ ) {
                  ( * Instance().fCallback)( ns.MemberAt(m) );
               }
            }
         }
         Instance().fEnabled = true;
      }

      void Cintex::SetROOTCreator(ROOTCreator_t c) {
         Instance().fRootcreator = c;
      }

      ROOTCreator_t Cintex::GetROOTCreator() {
         return Instance().fRootcreator;
      }

      int Cintex::Debug() {
         return Instance().fDbglevel;
      }

      void Cintex::SetDebug(int l) {
         Instance().fDbglevel = l;
      }

      bool Cintex::PropagateClassTypedefs() {
         return Instance().fPropagateClassTypedefs;
      }

      void Cintex::SetPropagateClassTypedefs(bool val) {
         Instance().fPropagateClassTypedefs = val;
      }

      bool Cintex::PropagateClassEnums() {
         return Instance().fPropagateClassEnums;
      }

      void Cintex::SetPropagateClassEnums(bool val) {
         Instance().fPropagateClassEnums = val;
      }

      void Callback::operator () ( const Type& t ) {
         ArtificialSourceFile asf;
         int autoload = G__set_class_autoloading(0); // To avoid recursive loads
         if ( t.IsClass() || t.IsStruct() ) {
            ROOTClassEnhancer enhancer(t);
            enhancer.Setup();
            CINTClassBuilder::Get(t).Setup();
            enhancer.CreateInfo();
         }
         else if ( t.IsTypedef() ) {
            CINTTypedefBuilder::Setup(t);
         }
         else if ( t.IsEnum() ) {
            CINTEnumBuilder::Setup(t);
         }
         G__set_class_autoloading(autoload);
      }

      void Callback::operator () ( const Member& m ) {
         ArtificialSourceFile asf;
         int autoload = G__set_class_autoloading(0); // To avoid recursive loads
         if ( m.IsFunctionMember() ) {
            if( Cintex::Debug() ) cout << "Cintex: Building function " << m.Name(SCOPED|QUALIFIED) << endl;
            CINTFunctionBuilder(m).Setup();
         }
         else if ( m.IsDataMember() ) {
            if( Cintex::Debug() ) cout << "Cintex: Building variable " << m.Name(SCOPED|QUALIFIED) << endl;
            CINTVariableBuilder(m).Setup();
         }
         G__set_class_autoloading(autoload);
      }
   }
}
<|endoftext|>


<commit_before>/*
 *  Copyright (c) 2014-present, Facebook, Inc.
 *  All rights reserved.
 *
 *  This source code is licensed under the BSD-style license found in the
 *  LICENSE file in the root directory of this source tree. An additional grant
 *  of patent rights can be found in the PATENTS file in the same directory.
 *
 */

#include <string>
#include <cstring>

#include <zlib.h>

namespace osquery {

#define MOD_GZIP_ZLIB_WINDOWSIZE 15
#define MOD_GZIP_ZLIB_CFACTOR 9

std::string compressString(const std::string& data) {
  z_stream zs;
  memset(&zs, 0, sizeof(zs));

  if (deflateInit2(&zs,
                   Z_BEST_COMPRESSION,
                   Z_DEFLATED,
                   MOD_GZIP_ZLIB_WINDOWSIZE + 16,
                   MOD_GZIP_ZLIB_CFACTOR,
                   Z_DEFAULT_STRATEGY) != Z_OK) {
    return std::string();
  }

  zs.next_in = (Bytef*)data.data();
  zs.avail_in = static_cast<uInt>(data.size());

  int ret = Z_OK;
  std::string output;

  {
    char buffer[16384] = {0};
    while (ret == Z_OK) {
      zs.next_out = reinterpret_cast<Bytef*>(buffer);
      zs.avail_out = sizeof(output);

      ret = deflate(&zs, Z_FINISH);
      if (output.size() < zs.total_out) {
        output.append(buffer, zs.total_out - output.size());
      }
    }
  }

  deflateEnd(&zs);
  if (ret != Z_STREAM_END) {
    return std::string();
  }

  return output;
}
}
<commit_msg>remote: Fix output size for TLS compression (#3133)<commit_after>/*
 *  Copyright (c) 2014-present, Facebook, Inc.
 *  All rights reserved.
 *
 *  This source code is licensed under the BSD-style license found in the
 *  LICENSE file in the root directory of this source tree. An additional grant
 *  of patent rights can be found in the PATENTS file in the same directory.
 *
 */

#include <cstring>
#include <string>

#include <zlib.h>

namespace osquery {

#define MOD_GZIP_ZLIB_WINDOWSIZE 15
#define MOD_GZIP_ZLIB_CFACTOR 9

std::string compressString(const std::string& data) {
  z_stream zs;
  memset(&zs, 0, sizeof(zs));

  if (deflateInit2(&zs,
                   Z_BEST_COMPRESSION,
                   Z_DEFLATED,
                   MOD_GZIP_ZLIB_WINDOWSIZE + 16,
                   MOD_GZIP_ZLIB_CFACTOR,
                   Z_DEFAULT_STRATEGY) != Z_OK) {
    return std::string();
  }

  zs.next_in = (Bytef*)data.data();
  zs.avail_in = static_cast<uInt>(data.size());

  int ret = Z_OK;
  std::string output;

  {
    char buffer[16384] = {0};
    while (ret == Z_OK) {
      zs.next_out = reinterpret_cast<Bytef*>(buffer);
      zs.avail_out = sizeof(buffer);

      ret = deflate(&zs, Z_FINISH);
      if (output.size() < zs.total_out) {
        output.append(buffer, zs.total_out - output.size());
      }
    }
  }

  deflateEnd(&zs);
  if (ret != Z_STREAM_END) {
    return std::string();
  }

  return output;
}
}
<|endoftext|>


<commit_before>// Licensed GNU LGPL v3 or later: http://www.gnu.org/licenses/lgpl.html
// rapicorn-zintern - small C source compression utility
#include <cxxaux.hh>
#include <glib.h>
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <zlib.h>
#include <string>

typedef Rapicorn::uint8 uint8;
typedef std::string String;

namespace {

static void     zintern_error  (const char     *format,
                                ...) RAPICORN_PRINTF (1, 2);

static void
zintern_error  (const char     *format,
                ...)
{
  gchar *buffer;
  va_list args;
  va_start (args, format);
  buffer = g_strdup_vprintf (format, args);
  va_end (args);
  g_printerr ("\nERROR: %s", buffer);
  _exit (1);
  g_free (buffer);
}

static bool use_compression = FALSE;
static bool use_base_name = FALSE;
static bool break_at_newlines = FALSE;
static bool as_resource = false;

typedef struct {
  uint pos;
  bool pad;
} Config;
static Config config_init = { 0, 0 };

static inline void
print_uchar (Config *config,
	     uint8 d)
{
  if (config->pos > 70)
    {
      printf ("\"\n  \"");
      config->pos = 3;
      config->pad = FALSE;
    }
  if (d == '\\')
    {
      printf ("\\\\");
      config->pos += 2;
    }
  else if (d == '\n')
    {
      printf ("\\n");
      config->pos += 2;
      if (break_at_newlines && config->pos > 3)
        config->pos |= 1 << 31;
    }
  else if (d == '"')
    {
      printf ("\\\"");
      config->pos += 2;
    }
  else if (d < 33 || d > 126 || d == '?')
    {
      printf ("\\%o", d);
      config->pos += 1 + 1 + (d > 7) + (d > 63);
      config->pad = d < 64;
      return;
    }
  else if (config->pad && d >= '0' && d <= '9')
    {
      printf ("\"\"");
      printf ("%c", d);
      config->pos += 3;
    }
  else
    {
      printf ("%c", d);
      config->pos += 1;
    }
  config->pad = FALSE;
}

#define to_upper(c)     ((c) >='a' && (c) <='z' ? (c) - 'a' + 'A' : (c))
#define is_alnum(c)     (((c) >='A' && (c) <='Z') || ((c) >='a' && (c) <='z') || ((c) >='0' && (c) <='9'))
static String
to_cupper (const String &str)
{
  String s (str);
  for (uint i = 0; i < s.size(); i++)
    if (is_alnum (s[i]))
      s[i] = to_upper (s[i]);
    else
      s[i] = '_';
  return s;
}

static void
gen_zfile (const char *name,
	   const char *file)
{
  FILE *f = fopen (file, "r");
  uint8 *data = NULL;
  uint i, dlen = 0, mlen = 0;
  Bytef *cdata;
  uLongf clen;
  gchar *basefile = g_path_get_basename (file);
  String fname = use_base_name ? basefile : file;
  g_free (basefile); basefile = NULL;
  Config config;
  if (!f)
    zintern_error ("failed to open \"%s\": %s", file, g_strerror (errno));
  do
    {
      if (mlen <= dlen + 1024)
	{
	  mlen += 8192;
	  data = g_renew (uint8, data, mlen);
	}
      dlen += fread (data + dlen, 1, mlen - dlen, f);
    }
  while (!feof (f));

  if (ferror (f))
    zintern_error ("failed to read from \"%s\": %s", file, g_strerror (errno));

  if (use_compression || as_resource)
    {
      int result;
      const char *err;
      clen = dlen + dlen / 100 + 64;
      cdata = g_new (uint8, clen);
      result = compress2 (cdata, &clen, data, dlen, Z_BEST_COMPRESSION);
      switch (result)
	{
	case Z_OK:
	  err = NULL;
	  break;
	case Z_MEM_ERROR:
	  err = "out of memory";
	  break;
	case Z_BUF_ERROR:
	  err = "insufficient buffer size";
	  break;
	default:
	  err = "unknown error";
	  break;
	}
      if (err)
	zintern_error ("while compressing \"%s\": %s", file, err);
    }
  else
    {
      clen = dlen;
      cdata = data;
    }

  g_print ("/* rapicorn-zintern file dump of %s */\n", file);

  if (as_resource)
    {
      if (name[0] == '/')
        g_error ("invalid absolute resource path (must be relative): %s", name);
      /* two things to consider for using the compressed data:
       * 1) for the reader code, pack_size + 1 must be smaller than data_size to identify compressed data.
       * 2) using compressed data requires runtime unpacking overhead and extra dynamic memory allocation,
       *    so it should provide a *significant* benefit if it's used.
       */
      const bool compress_resource = clen <= 0.75 * dlen && clen + 1 < dlen;
      const size_t rlen = compress_resource ? clen : dlen;
      const uint8 *rdata = rlen == dlen ? data : cdata;
      gchar *ident = g_strcanon (g_strdup (name), "0123456789abcdefghijklmnopqrstuvwxyz_ABCDEFGHIJKLMNOPQRSTUVWXYZ", '_');

      config = config_init;
      printf ("RAPICORN_STATIC_RESOURCE_DATA (%s) =\n  \"", ident);
      for (i = 0; i < rlen; i++)
        print_uchar (&config, rdata[i]);
      printf ("\"; // %lu + 1\n", rlen);

      config = config_init;
      printf ("RAPICORN_STATIC_RESOURCE_ENTRY (%s, \"", ident);
      for (i = 0; i < strlen (name); i++)
        print_uchar (&config, name[i]);
      printf ("\", %u);\n", dlen);
      g_free (ident);
    }
  else
    {
      config = config_init;
      printf ("#define %s_NAME \"", to_cupper (name).c_str());
      for (i = 0; i < fname.size(); i++)
        print_uchar (&config, fname[i]);
      printf ("\"\n");

      printf ("#define %s_SIZE (%u)\n", to_cupper (name).c_str(), dlen);

      config = config_init;
      printf ("static const unsigned char %s_DATA[%lu + 1] =\n", to_cupper (name).c_str(), clen);
      printf ("( \"");
      for (i = 0; i < clen; i++)
        print_uchar (&config, cdata[i]);
      printf ("\");\n");
    }

  fclose (f);
  g_free (data);
  if (cdata != data)
    g_free (cdata);
}

static int
help (char *arg)
{
  g_printerr ("usage: rapicorn-zintern [-h] [-b] [-z] [[name file]...]\n");
  g_printerr ("  -h  Print usage information\n");
  g_printerr ("  -b  Strip directories from file names\n");
  g_printerr ("  -n  Break output lines after newlines raw data\n");
  g_printerr ("  -r  Produce Rapicorn resource declarations\n");
  g_printerr ("  -z  Compress data blocks with libz\n");
  g_printerr ("Parse (name, file) pairs and generate C source\n");
  g_printerr ("containing inlined data blocks of the files given.\n");
  return arg != NULL;
}

extern "C" int
main (int   argc,
      char *argv[])
{
  GSList *plist = NULL;

  for (int i = 1; i < argc; i++)
    {
      if (strcmp ("-z", argv[i]) == 0)
	{
	  use_compression = TRUE;
	}
      else if (strcmp ("-r", argv[i]) == 0)
	{
	  as_resource = true;
	}
      else if (strcmp ("-b", argv[i]) == 0)
	{
	  use_base_name = TRUE;
	}
      else if (strcmp ("-n", argv[i]) == 0)
	{
	  break_at_newlines = TRUE;
	}
      else if (strcmp ("-h", argv[i]) == 0)
	{
	  return help (NULL);
	}
      else
	plist = g_slist_append (plist, argv[i]);
    }

  if (argc <= 1)
    return help (NULL);

  while (plist && plist->next)
    {
      const char *name = (char*) plist->data;
      GSList *tmp = plist;
      plist = tmp->next;
      g_slist_free_1 (tmp);
      const char *file = (char*) plist->data;
      tmp = plist;
      plist = tmp->next;
      g_slist_free_1 (tmp);
      gen_zfile (name, file);
    }

  return 0;
}

} // anon
<commit_msg>RCORE: zintern: fix newlines after error messages missing<commit_after>// Licensed GNU LGPL v3 or later: http://www.gnu.org/licenses/lgpl.html
// rapicorn-zintern - small C source compression utility
#include <cxxaux.hh>
#include <glib.h>
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <zlib.h>
#include <string>

typedef Rapicorn::uint8 uint8;
typedef std::string String;

namespace {

static void     zintern_error  (const char     *format,
                                ...) RAPICORN_PRINTF (1, 2);

static void
zintern_error  (const char     *format,
                ...)
{
  gchar *buffer;
  va_list args;
  va_start (args, format);
  buffer = g_strdup_vprintf (format, args);
  va_end (args);
  g_printerr ("\nERROR: %s\n", buffer);
  _exit (1);
  g_free (buffer);
}

static bool use_compression = FALSE;
static bool use_base_name = FALSE;
static bool break_at_newlines = FALSE;
static bool as_resource = false;

typedef struct {
  uint pos;
  bool pad;
} Config;
static Config config_init = { 0, 0 };

static inline void
print_uchar (Config *config,
	     uint8 d)
{
  if (config->pos > 70)
    {
      printf ("\"\n  \"");
      config->pos = 3;
      config->pad = FALSE;
    }
  if (d == '\\')
    {
      printf ("\\\\");
      config->pos += 2;
    }
  else if (d == '\n')
    {
      printf ("\\n");
      config->pos += 2;
      if (break_at_newlines && config->pos > 3)
        config->pos |= 1 << 31;
    }
  else if (d == '"')
    {
      printf ("\\\"");
      config->pos += 2;
    }
  else if (d < 33 || d > 126 || d == '?')
    {
      printf ("\\%o", d);
      config->pos += 1 + 1 + (d > 7) + (d > 63);
      config->pad = d < 64;
      return;
    }
  else if (config->pad && d >= '0' && d <= '9')
    {
      printf ("\"\"");
      printf ("%c", d);
      config->pos += 3;
    }
  else
    {
      printf ("%c", d);
      config->pos += 1;
    }
  config->pad = FALSE;
}

#define to_upper(c)     ((c) >='a' && (c) <='z' ? (c) - 'a' + 'A' : (c))
#define is_alnum(c)     (((c) >='A' && (c) <='Z') || ((c) >='a' && (c) <='z') || ((c) >='0' && (c) <='9'))
static String
to_cupper (const String &str)
{
  String s (str);
  for (uint i = 0; i < s.size(); i++)
    if (is_alnum (s[i]))
      s[i] = to_upper (s[i]);
    else
      s[i] = '_';
  return s;
}

static void
gen_zfile (const char *name,
	   const char *file)
{
  FILE *f = fopen (file, "r");
  uint8 *data = NULL;
  uint i, dlen = 0, mlen = 0;
  Bytef *cdata;
  uLongf clen;
  gchar *basefile = g_path_get_basename (file);
  String fname = use_base_name ? basefile : file;
  g_free (basefile); basefile = NULL;
  Config config;
  if (!f)
    zintern_error ("failed to open \"%s\": %s", file, g_strerror (errno));
  do
    {
      if (mlen <= dlen + 1024)
	{
	  mlen += 8192;
	  data = g_renew (uint8, data, mlen);
	}
      dlen += fread (data + dlen, 1, mlen - dlen, f);
    }
  while (!feof (f));

  if (ferror (f))
    zintern_error ("failed to read from \"%s\": %s", file, g_strerror (errno));

  if (use_compression || as_resource)
    {
      int result;
      const char *err;
      clen = dlen + dlen / 100 + 64;
      cdata = g_new (uint8, clen);
      result = compress2 (cdata, &clen, data, dlen, Z_BEST_COMPRESSION);
      switch (result)
	{
	case Z_OK:
	  err = NULL;
	  break;
	case Z_MEM_ERROR:
	  err = "out of memory";
	  break;
	case Z_BUF_ERROR:
	  err = "insufficient buffer size";
	  break;
	default:
	  err = "unknown error";
	  break;
	}
      if (err)
	zintern_error ("while compressing \"%s\": %s", file, err);
    }
  else
    {
      clen = dlen;
      cdata = data;
    }

  g_print ("/* rapicorn-zintern file dump of %s */\n", file);

  if (as_resource)
    {
      if (name[0] == '/')
        g_error ("invalid absolute resource path (must be relative): %s", name);
      /* two things to consider for using the compressed data:
       * 1) for the reader code, pack_size + 1 must be smaller than data_size to identify compressed data.
       * 2) using compressed data requires runtime unpacking overhead and extra dynamic memory allocation,
       *    so it should provide a *significant* benefit if it's used.
       */
      const bool compress_resource = clen <= 0.75 * dlen && clen + 1 < dlen;
      const size_t rlen = compress_resource ? clen : dlen;
      const uint8 *rdata = rlen == dlen ? data : cdata;
      gchar *ident = g_strcanon (g_strdup (name), "0123456789abcdefghijklmnopqrstuvwxyz_ABCDEFGHIJKLMNOPQRSTUVWXYZ", '_');

      config = config_init;
      printf ("RAPICORN_STATIC_RESOURCE_DATA (%s) =\n  \"", ident);
      for (i = 0; i < rlen; i++)
        print_uchar (&config, rdata[i]);
      printf ("\"; // %lu + 1\n", rlen);

      config = config_init;
      printf ("RAPICORN_STATIC_RESOURCE_ENTRY (%s, \"", ident);
      for (i = 0; i < strlen (name); i++)
        print_uchar (&config, name[i]);
      printf ("\", %u);\n", dlen);
      g_free (ident);
    }
  else
    {
      config = config_init;
      printf ("#define %s_NAME \"", to_cupper (name).c_str());
      for (i = 0; i < fname.size(); i++)
        print_uchar (&config, fname[i]);
      printf ("\"\n");

      printf ("#define %s_SIZE (%u)\n", to_cupper (name).c_str(), dlen);

      config = config_init;
      printf ("static const unsigned char %s_DATA[%lu + 1] =\n", to_cupper (name).c_str(), clen);
      printf ("( \"");
      for (i = 0; i < clen; i++)
        print_uchar (&config, cdata[i]);
      printf ("\");\n");
    }

  fclose (f);
  g_free (data);
  if (cdata != data)
    g_free (cdata);
}

static int
help (char *arg)
{
  g_printerr ("usage: rapicorn-zintern [-h] [-b] [-z] [[name file]...]\n");
  g_printerr ("  -h  Print usage information\n");
  g_printerr ("  -b  Strip directories from file names\n");
  g_printerr ("  -n  Break output lines after newlines raw data\n");
  g_printerr ("  -r  Produce Rapicorn resource declarations\n");
  g_printerr ("  -z  Compress data blocks with libz\n");
  g_printerr ("Parse (name, file) pairs and generate C source\n");
  g_printerr ("containing inlined data blocks of the files given.\n");
  return arg != NULL;
}

extern "C" int
main (int   argc,
      char *argv[])
{
  GSList *plist = NULL;

  for (int i = 1; i < argc; i++)
    {
      if (strcmp ("-z", argv[i]) == 0)
	{
	  use_compression = TRUE;
	}
      else if (strcmp ("-r", argv[i]) == 0)
	{
	  as_resource = true;
	}
      else if (strcmp ("-b", argv[i]) == 0)
	{
	  use_base_name = TRUE;
	}
      else if (strcmp ("-n", argv[i]) == 0)
	{
	  break_at_newlines = TRUE;
	}
      else if (strcmp ("-h", argv[i]) == 0)
	{
	  return help (NULL);
	}
      else
	plist = g_slist_append (plist, argv[i]);
    }

  if (argc <= 1)
    return help (NULL);

  while (plist && plist->next)
    {
      const char *name = (char*) plist->data;
      GSList *tmp = plist;
      plist = tmp->next;
      g_slist_free_1 (tmp);
      const char *file = (char*) plist->data;
      tmp = plist;
      plist = tmp->next;
      g_slist_free_1 (tmp);
      gen_zfile (name, file);
    }

  return 0;
}

} // anon
<|endoftext|>