<commit_before>/*
 * Serve HTTP requests from another HTTP/AJP server.
 *
 * author: Max Kellermann <mk@cm4all.com>
 */

#include "handler.hxx"
#include "request.hxx"
#include "request_forward.hxx"
#include "http_server.hxx"
#include "http_cache.hxx"
#include "http_response.hxx"
#include "http_address.hxx"
#include "cgi_address.hxx"
#include "global.h"
#include "cookie_client.hxx"
#include "uri-extract.h"
#include "strref_pool.hxx"
#include "strmap.hxx"
#include "http_response.hxx"
#include "istream-impl.h"
#include "lhttp_address.hxx"

static void
proxy_collect_cookies(request &request2, const struct strmap *headers)
{
    const struct resource_address &address = *request2.translate.address;

    if (headers == nullptr)
        return;

    auto r = headers->EqualRange("set-cookie2");
    if (r.first == r.second) {
        r = headers->EqualRange("set-cookie");
        if (r.first == r.second)
            return;
    }

    const char *host_and_port = request2.translate.response->cookie_host;
    if (host_and_port == nullptr)
        host_and_port = resource_address_host_and_port(&address);
    if (host_and_port == nullptr)
        return;

    const char *path = resource_address_uri_path(&address);
    if (path == nullptr)
        return;

    struct session *session = request_make_session(request2);
    if (session == nullptr)
        return;

    for (auto i = r.first; i != r.second; ++i)
        cookie_jar_set_cookie2(session->cookies, i->value,
                               host_and_port, path);

    session_put(session);
}

static void
proxy_response(http_status_t status, struct strmap *headers,
               struct istream *body, void *ctx)
{
    request &request2 = *(request *)ctx;

#ifndef NDEBUG
    const struct resource_address &address = *request2.translate.address;
    assert(address.type == RESOURCE_ADDRESS_HTTP ||
           address.type == RESOURCE_ADDRESS_LHTTP ||
           address.type == RESOURCE_ADDRESS_AJP ||
           address.type == RESOURCE_ADDRESS_NFS ||
           resource_address_is_cgi_alike(&address));
#endif

    proxy_collect_cookies(request2, headers);

    response_handler.InvokeResponse(&request2, status, headers, body);
}

static void
proxy_abort(GError *error, void *ctx)
{
    request &request2 = *(request *)ctx;

    response_handler.InvokeAbort(&request2, error);
}

static const struct http_response_handler proxy_response_handler = {
    .response = proxy_response,
    .abort = proxy_abort,
};

void
proxy_handler(request &request2)
{
    struct http_server_request *request = request2.request;
    const TranslateResponse &tr = *request2.translate.response;
    const struct resource_address *address = request2.translate.address;

    assert(address->type == RESOURCE_ADDRESS_HTTP ||
           address->type == RESOURCE_ADDRESS_LHTTP ||
           address->type == RESOURCE_ADDRESS_AJP ||
           address->type == RESOURCE_ADDRESS_NFS ||
           resource_address_is_cgi_alike(address));

    const char *host_and_port = nullptr, *uri_p = nullptr;
    if (address->type == RESOURCE_ADDRESS_HTTP ||
        address->type == RESOURCE_ADDRESS_AJP) {
        host_and_port = address->u.http->host_and_port;
        uri_p = address->u.http->path;
    } else if (address->type == RESOURCE_ADDRESS_LHTTP) {
        host_and_port = address->u.lhttp->host_and_port;
        uri_p = address->u.lhttp->uri;
    }

    struct forward_request forward;
    request_forward(forward, request2,
                    tr.request_header_forward,
                    host_and_port, uri_p,
                    address->type == RESOURCE_ADDRESS_HTTP ||
                    address->type == RESOURCE_ADDRESS_LHTTP);

    if (request2.translate.response->transparent &&
        (!strref_is_empty(&request2.uri.args) ||
         !strref_is_empty(&request2.uri.path_info)))
        address = resource_address_insert_args(*request->pool, address,
                                               request2.uri.args.data,
                                               request2.uri.args.length,
                                               request2.uri.path_info.data,
                                               request2.uri.path_info.length);

    if (!request2.processor_focus)
        /* forward query string */
        address = resource_address_insert_query_string_from(*request->pool,
                                                            address,
                                                            request->uri);

    if (resource_address_is_cgi_alike(address) &&
        address->u.cgi->uri == nullptr) {
        struct resource_address *copy = resource_address_dup(*request->pool,
                                                             address);
        struct cgi_address *cgi = resource_address_get_cgi(copy);

        /* pass the "real" request URI to the CGI (but without the
           "args", unless the request is "transparent") */
        if (request2.translate.response->transparent ||
            strref_is_empty(&request2.uri.args))
            cgi->uri = request->uri;
        else if (strref_is_empty(&request2.uri.query))
            cgi->uri = strref_dup(request->pool, &request2.uri.base);
        else
            cgi->uri = p_strncat(request->pool,
                                 request2.uri.base.data,
                                 request2.uri.base.length,
                                 "?", (size_t)1,
                                 request2.uri.query.data,
                                 request2.uri.query.length,
                                 nullptr);

        address = copy;
    }

#ifdef SPLICE
    if (forward.body != nullptr)
        forward.body = istream_pipe_new(request->pool, forward.body,
                                        global_pipe_stock);
#endif

    for (const auto &i : tr.request_headers)
        forward.headers->Add(i.key, i.value);

    http_cache_request(*global_http_cache, *request->pool,
                       session_id_low(request2.session_id),
                       forward.method, *address,
                       forward.headers, forward.body,
                       proxy_response_handler, &request2,
                       request2.async_ref);
}
<commit_msg>proxy_handler: move code to GetCookieHost()<commit_after>/*
 * Serve HTTP requests from another HTTP/AJP server.
 *
 * author: Max Kellermann <mk@cm4all.com>
 */

#include "handler.hxx"
#include "request.hxx"
#include "request_forward.hxx"
#include "http_server.hxx"
#include "http_cache.hxx"
#include "http_response.hxx"
#include "http_address.hxx"
#include "cgi_address.hxx"
#include "global.h"
#include "cookie_client.hxx"
#include "uri-extract.h"
#include "strref_pool.hxx"
#include "strmap.hxx"
#include "http_response.hxx"
#include "istream-impl.h"
#include "lhttp_address.hxx"

gcc_pure
static const char *
GetCookieHost(const request &r)
{
    const TranslateResponse &t = *r.translate.response;
    if (t.cookie_host != nullptr)
        return t.cookie_host;

    const struct resource_address &address = *r.translate.address;
    return resource_address_host_and_port(&address);
}

static void
proxy_collect_cookies(request &request2, const struct strmap *headers)
{
    const struct resource_address &address = *request2.translate.address;

    if (headers == nullptr)
        return;

    auto r = headers->EqualRange("set-cookie2");
    if (r.first == r.second) {
        r = headers->EqualRange("set-cookie");
        if (r.first == r.second)
            return;
    }

    const char *host_and_port = GetCookieHost(request2);
    if (host_and_port == nullptr)
        return;

    const char *path = resource_address_uri_path(&address);
    if (path == nullptr)
        return;

    struct session *session = request_make_session(request2);
    if (session == nullptr)
        return;

    for (auto i = r.first; i != r.second; ++i)
        cookie_jar_set_cookie2(session->cookies, i->value,
                               host_and_port, path);

    session_put(session);
}

static void
proxy_response(http_status_t status, struct strmap *headers,
               struct istream *body, void *ctx)
{
    request &request2 = *(request *)ctx;

#ifndef NDEBUG
    const struct resource_address &address = *request2.translate.address;
    assert(address.type == RESOURCE_ADDRESS_HTTP ||
           address.type == RESOURCE_ADDRESS_LHTTP ||
           address.type == RESOURCE_ADDRESS_AJP ||
           address.type == RESOURCE_ADDRESS_NFS ||
           resource_address_is_cgi_alike(&address));
#endif

    proxy_collect_cookies(request2, headers);

    response_handler.InvokeResponse(&request2, status, headers, body);
}

static void
proxy_abort(GError *error, void *ctx)
{
    request &request2 = *(request *)ctx;

    response_handler.InvokeAbort(&request2, error);
}

static const struct http_response_handler proxy_response_handler = {
    .response = proxy_response,
    .abort = proxy_abort,
};

void
proxy_handler(request &request2)
{
    struct http_server_request *request = request2.request;
    const TranslateResponse &tr = *request2.translate.response;
    const struct resource_address *address = request2.translate.address;

    assert(address->type == RESOURCE_ADDRESS_HTTP ||
           address->type == RESOURCE_ADDRESS_LHTTP ||
           address->type == RESOURCE_ADDRESS_AJP ||
           address->type == RESOURCE_ADDRESS_NFS ||
           resource_address_is_cgi_alike(address));

    const char *host_and_port = nullptr, *uri_p = nullptr;
    if (address->type == RESOURCE_ADDRESS_HTTP ||
        address->type == RESOURCE_ADDRESS_AJP) {
        host_and_port = address->u.http->host_and_port;
        uri_p = address->u.http->path;
    } else if (address->type == RESOURCE_ADDRESS_LHTTP) {
        host_and_port = address->u.lhttp->host_and_port;
        uri_p = address->u.lhttp->uri;
    }

    struct forward_request forward;
    request_forward(forward, request2,
                    tr.request_header_forward,
                    host_and_port, uri_p,
                    address->type == RESOURCE_ADDRESS_HTTP ||
                    address->type == RESOURCE_ADDRESS_LHTTP);

    if (request2.translate.response->transparent &&
        (!strref_is_empty(&request2.uri.args) ||
         !strref_is_empty(&request2.uri.path_info)))
        address = resource_address_insert_args(*request->pool, address,
                                               request2.uri.args.data,
                                               request2.uri.args.length,
                                               request2.uri.path_info.data,
                                               request2.uri.path_info.length);

    if (!request2.processor_focus)
        /* forward query string */
        address = resource_address_insert_query_string_from(*request->pool,
                                                            address,
                                                            request->uri);

    if (resource_address_is_cgi_alike(address) &&
        address->u.cgi->uri == nullptr) {
        struct resource_address *copy = resource_address_dup(*request->pool,
                                                             address);
        struct cgi_address *cgi = resource_address_get_cgi(copy);

        /* pass the "real" request URI to the CGI (but without the
           "args", unless the request is "transparent") */
        if (request2.translate.response->transparent ||
            strref_is_empty(&request2.uri.args))
            cgi->uri = request->uri;
        else if (strref_is_empty(&request2.uri.query))
            cgi->uri = strref_dup(request->pool, &request2.uri.base);
        else
            cgi->uri = p_strncat(request->pool,
                                 request2.uri.base.data,
                                 request2.uri.base.length,
                                 "?", (size_t)1,
                                 request2.uri.query.data,
                                 request2.uri.query.length,
                                 nullptr);

        address = copy;
    }

#ifdef SPLICE
    if (forward.body != nullptr)
        forward.body = istream_pipe_new(request->pool, forward.body,
                                        global_pipe_stock);
#endif

    for (const auto &i : tr.request_headers)
        forward.headers->Add(i.key, i.value);

    http_cache_request(*global_http_cache, *request->pool,
                       session_id_low(request2.session_id),
                       forward.method, *address,
                       forward.headers, forward.body,
                       proxy_response_handler, &request2,
                       request2.async_ref);
}
<|endoftext|>


<commit_before>#include <array>
#include <cmath>
#include <cstdlib>
#include <iostream>
#include <random>
#include <vector>

#include <SFML/Graphics.hpp>
#include <noise/noise.h>

#include "force.h"
#include "particle.h"

#include "colour.h"
#include "util.h"

using namespace noise;

constexpr int cell_size = 10;

int main(int argc, char* argv[])
{
    if (argc != 2) {
        std::cout << "usage: " << argv[0] << " <filename>" << std::endl;
        std::exit(2);
    }

    const std::string img_name = argv[1];
    sf::Image img;
    img.loadFromFile(img_name);

    std::string output_name = "output_cell10_";
    unsigned int output_index = 1;
    float output_interval = 5.f;

    // These values are used to compute perlin noise
    double xn = 0, yn = 0, zn = 0;

    // Some good defaults w/ cell size 10  and flow_strength 3.f
    /*const double xoffset = 0.05;
    const double yoffset = 0.05;
    const double zoffset = 0.01;*/

    const double xoffset = 0.01;
    const double yoffset = 0.01;
    const double zoffset = 0.01;

    constexpr int num_particles = 10000;
    constexpr int alpha = 10;
    constexpr float flow_strength = 3.f;

    // Window size
    int width = img.getSize().x;
    int height = img.getSize().y;

    const unsigned int cols = width / cell_size;
    const unsigned int rows = height / cell_size;

    width = cols * cell_size;
    height = rows * cell_size;

    // Random number generator setup
    std::random_device rd;
    std::default_random_engine gen(rd());
    // distributions for random x and y coordinates
    std::uniform_int_distribution<int> rand_x(0, width-1);
    std::uniform_int_distribution<int> rand_y(0, height-1);

    // Setup noise generator
    module::Perlin noise;
    noise.SetSeed(rand_y(gen));

    // Create and initialize the force vectors on a grid layout
    std::vector< std::vector<Force> > forces(rows, std::vector<Force> (cols, Force()));
    std::vector< std::vector<sf::Color> > colours(rows, std::vector<sf::Color> (cols, sf::Color()));

    for (unsigned int y = 0; y < rows; y++)
    {
        for (unsigned int x = 0; x < cols; x++)
        {
            forces[y][x].setPosition(x * cell_size, y * cell_size);
            forces[y][x].setMagnitude(cell_size);
            forces[y][x].setAngle(0.f);

            std::vector<sf::Color> pixels;

            for (unsigned int j = y*cell_size; j < (y+1)*cell_size; j++)
            {
                for (unsigned int i = x*cell_size; i < (x+1)*cell_size; i++)
                {
                    pixels.push_back(img.getPixel(i, j));
                }
            }
            colours[y][x] = util::avgColor(pixels);
        }
    }

    // Create and initialize the particles
    Particle particles[num_particles];
    for (int i = 0; i < num_particles; i++)
    {
        particles[i].current.position = sf::Vector2f(rand_x(gen), rand_y(gen));
    }

    sf::RenderTexture window;
    window.create(width, height);

    window.clear(sf::Color::Black);

    sf::Clock clock;
    sf::Time time;
    int frames = 0;

    sf::Clock output_clock;
    sf::Time output_time;

    while (true)
    {
        yn = 0;
        for (unsigned int y = 0; y < rows; y++)
        {
            xn = 0;
            for (unsigned int x = 0; x < cols; x++)
            {
                double n = noise.GetValue(xn, yn, zn);
                float dir = util::map(n, -1, 1, 0, 270);

                forces[y][x].setAngle(dir);

                xn += xoffset;
            }
            yn += yoffset;
        }

        sf::VertexArray lines(sf::Lines);

        for (int i = 0; i < num_particles; i++)
        {
            Particle *p = &particles[i];
            int gx, gy;
            gx = p->current.position.x / cell_size;
            gy = p->current.position.y / cell_size;
            p->current.color = colours[gy][gx];
            p->current.color.a = alpha;
            p->acceleration = forces[gy][gx].getVector() / (float)cell_size * flow_strength;
            p->update(window);
            std::array<sf::Vertex, 2> line = p->getLine();
            lines.append(line[0]);
            lines.append(line[1]);
        }

        window.draw(lines);

        //window.display();
        zn += zoffset;

        // Calculate FPS
        frames += 1;
        time += clock.restart();
        if (time.asSeconds() > 1)
        {
            std::cout << 1.f / time.asSeconds() * frames << std::endl;
            time = sf::Time();
            frames = 0;
        }

        // Periodically write the image to disk
        output_time += output_clock.restart();
        if (output_time.asSeconds() >= output_interval) {
            std::cout << "Writing " << output_name << output_index << ".jpg" << std::endl;
            window.display();
            window.getTexture().copyToImage().saveToFile(output_name + std::to_string(output_index) + ".jpg");
            ++output_index;
            output_time = sf::Time();
        }

    }
}
<commit_msg>Add some comments and cleanup a bit<commit_after>#include <array>
#include <cmath>
#include <cstdlib>
#include <iostream>
#include <random>
#include <vector>

#include <SFML/Graphics.hpp>
#include <noise/noise.h>

#include "force.h"
#include "particle.h"

#include "colour.h"
#include "util.h"

using namespace noise;

int main(int argc, char* argv[])
{
    if (argc != 2) {
        std::cout << "usage: " << argv[0] << " <filename>" << std::endl;
        std::exit(2);
    }

    const std::string img_name = argv[1];
    sf::Image img;
    img.loadFromFile(img_name);

    // These values are used to compute perlin noise
    double xn = 0, yn = 0, zn = 0;

    // Some good defaults w/ cell size 10  and flow_strength 3.f
    /*const double xoffset = 0.05;
    const double yoffset = 0.05;
    const double zoffset = 0.01;*/

    // Parameters for image file creation
    std::string output_name = "output_cell10_";
    unsigned int output_index = 1;
    float output_interval = 5.f;

    // Parameters for Perlin noise generation
    const double xoffset = 0.01;
    const double yoffset = 0.01;
    const double zoffset = 0.01;

    // Parameters for particles and grid
    constexpr int cell_size = 10;
    constexpr int num_particles = 10000;
    constexpr int alpha = 10;
    constexpr float flow_strength = 3.f;

    int width = img.getSize().x;
    int height = img.getSize().y;

    const unsigned int cols = width / cell_size;
    const unsigned int rows = height / cell_size;
    width = cols * cell_size;
    height = rows * cell_size;

    // Random number generator setup
    std::random_device rd;
    std::default_random_engine gen(rd());
    // distributions for random x and y coordinates
    std::uniform_int_distribution<int> rand_x(0, width-1);
    std::uniform_int_distribution<int> rand_y(0, height-1);

    // Setup noise generator
    module::Perlin noise;
    noise.SetSeed(rand_y(gen));

    // Create a vector of vectors to hold the Force object for each square
    std::vector< std::vector<Force> > forces(rows, std::vector<Force> (cols, Force()));
    // Create a vector of vectors to hold the average colour of each square
    std::vector< std::vector<sf::Color> > colours(rows, std::vector<sf::Color> (cols, sf::Color()));

    for (unsigned int y = 0; y < rows; y++)
    {
        for (unsigned int x = 0; x < cols; x++)
        {
            forces[y][x].setPosition(x * cell_size, y * cell_size);
            forces[y][x].setMagnitude(cell_size);
            forces[y][x].setAngle(0.f);

            // Get the value of each pixel in the current grid square
            // Then find the average colour of that square
            std::vector<sf::Color> pixels;
            for (unsigned int j = y*cell_size; j < (y+1)*cell_size; j++)
            {
                for (unsigned int i = x*cell_size; i < (x+1)*cell_size; i++)
                {
                    pixels.push_back(img.getPixel(i, j));
                }
            }
            colours[y][x] = util::avgColor(pixels);
        }
    }

    // Create and initialize the particles
    Particle particles[num_particles];
    for (int i = 0; i < num_particles; i++)
    {
        particles[i].current.position = sf::Vector2f(rand_x(gen), rand_y(gen));
    }

    sf::RenderTexture window;
    window.create(width, height);

    window.clear(sf::Color::Black);

    sf::Clock clock;
    sf::Time time;
    int frames = 0;

    sf::Clock output_clock;
    sf::Time output_time;

    while (true)
    {
        yn = 0;
        for (unsigned int y = 0; y < rows; y++)
        {
            xn = 0;
            for (unsigned int x = 0; x < cols; x++)
            {
                double n = noise.GetValue(xn, yn, zn);
                float dir = util::map(n, -1, 1, 0, 270);

                forces[y][x].setAngle(dir);

                xn += xoffset;
            }
            yn += yoffset;
        }

        sf::VertexArray lines(sf::Lines);

        for (int i = 0; i < num_particles; i++)
        {
            Particle *p = &particles[i];
            int gx, gy;
            gx = p->current.position.x / cell_size;
            gy = p->current.position.y / cell_size;
            p->current.color = colours[gy][gx];
            p->current.color.a = alpha;
            p->acceleration = forces[gy][gx].getVector() / (float)cell_size * flow_strength;
            p->update(window);
            std::array<sf::Vertex, 2> line = p->getLine();
            lines.append(line[0]);
            lines.append(line[1]);
        }

        window.draw(lines);

        //window.display();
        zn += zoffset;

        // Calculate FPS
        frames += 1;
        time += clock.restart();
        if (time.asSeconds() > 1)
        {
            std::cout << 1.f / time.asSeconds() * frames << std::endl;
            time = sf::Time();
            frames = 0;
        }

        // Periodically write the image to disk
        output_time += output_clock.restart();
        if (output_time.asSeconds() >= output_interval) {
            std::cout << "Writing " << output_name << output_index << ".jpg" << std::endl;
            window.display();
            window.getTexture().copyToImage().saveToFile(output_name + std::to_string(output_index) + ".jpg");
            ++output_index;
            output_time = sf::Time();
        }

    }
}
<|endoftext|>


<commit_before>#include "GameProcess.h"
#include "Object.h"
#include "Engine.h"
#include "World.h"
#include "App.h"
#include "ToolsCamera.h"
#include "ControlsApp.h"
#include "MathLib.h"
#include "Game.h"
#include "Editor.h"
#include "Input.h"
#include "BlueRayUtils.h"
#include "World.h"

using namespace MathLib;

CGameProcess::CGameProcess(void)
{

}

CGameProcess::~CGameProcess(void)
{

}
int CGameProcess::Init()
{
	g_Engine.pFileSystem->CacheFilesFormExt("char");
	g_Engine.pFileSystem->CacheFilesFormExt("node");
	g_Engine.pFileSystem->CacheFilesFormExt("smesh");
	g_Engine.pFileSystem->CacheFilesFormExt("sanim");

	g_Engine.pWorld->LoadWorld("data/scene/terrain/test/test.world");
	//g_Engine.pWorld->LoadWorld("data/scene/terrain/cj/cj.world");
	g_Engine.pControls->SetKeyPressFunc(KeyPress);
	g_Engine.pControls->SetKeyReleaseFunc(KeyRelease);

	m_pRole = new CFPSRoleLocal();
	m_pRole->Init(10001, "data/role/hero/FpsRole/fps.char");		//ؽɫԴ

	m_pRole->SetActorPosition(vec3(0, 0, 0));	//ýɫʼλáŴΪԭ㣬άϵvec3
	m_pSkillSystem = new CSkillSystem(this);
	m_pCameraBase = new CCameraBase();
	m_pCameraBase->SetEnabled(1);
	g_pSysControl->SetMouseGrab(1);

	m_pStarControl = new CStarControl();
	m_pRayControl = new CRayControl();

	return 1;
}

int CGameProcess::ShutDown()			//رϷ
{
	delete m_pRole;
	delete m_pSkillSystem;
	delete m_pCameraBase;
	delete m_pStarControl;
	delete m_pRayControl;

	DelAllListen();
	return 0;
}

int CGameProcess::Update()
{
	float ifps = g_Engine.pGame->GetIFps();

	if (g_Engine.pInput->IsKeyDown('1'))
	{
		CAction* pAction = m_pRole->OrceAction("attack02");
		if (pAction)
		{
			pAction->SetupSkillThrow(vec3_zero, -1.0f, 2.0f);
			m_pRole->StopMove();
		}
	}
	else if (g_Engine.pInput->IsKeyDown('2'))
	{
		CAction* pAction = m_pRole->OrceAction("skill01");
		if (pAction)
		{
			m_pRole->StopMove();
		}
	}
	else if (g_Engine.pInput->IsKeyDown('3'))
	{
		CAction* pAction = m_pRole->OrceAction("skill02");
		if (pAction)
		{
			m_pRole->StopMove();
			CRoleBase* pTarget = NULL;
			for (int i = 0; i < 20; i++)
			{
				float l = (m_vAIList[i]->GetPosition() - m_pRole->GetPosition()).length();
				if (l > 5.0f && l < 15.0f)
				{
					pTarget = m_vAIList[i];
					break;
				}
			}
			if (pTarget)
			{
				CVector<int> vTarget;
				vTarget.Append(pTarget->GetRoleID());
				pAction->SetupSkillBulletTarget(vTarget);
				m_pRole->SetDirection((pTarget->GetPosition() - m_pRole->GetPosition()).normalize(), 1);
			}
		}
	}
	else if (g_Engine.pInput->IsKeyDown('4'))//෢ӵ
	{
		CAction* pAction = m_pRole->OrceAction("skill02");
		if (pAction)
		{
			m_pRole->StopMove();
			CVector<int> vTarget;
			for (int i = 0; i < 20; i++)
			{
				float l = (m_vAIList[i]->GetPosition() - m_pRole->GetPosition()).length();
				if (l > 5.0f && l < 20.0f)
				{
					vTarget.Append(m_vAIList[i]->GetRoleID());
				}
			}
			if (!vTarget.Empty())
			{
				pAction->SetupSkillBulletTarget(vTarget);
			}
		}
	}
	else if (g_Engine.pInput->IsKeyDown('5'))
	{
		CAction* pAction = m_pRole->OrceAction("skill03");
		if (pAction)
		{
			m_pRole->StopMove();
			CVector<vec3> vPos;
			pAction->SetupSkillTargetPoint(vPos);
		}
	}
	else if (g_Engine.pInput->IsKeyDown('6'))
	{
		CAction* pAction = m_pRole->OrceAction("skill06");
		if (pAction)
		{
			m_pRole->StopMove();
			CVector<vec3> vPos;
			for (int i = 0; i < 20; i++)
			{
				float l = (m_vAIList[i]->GetPosition() - m_pRole->GetPosition()).length();
				if (l > 5.0f && l < 20.0f)
					vPos.Append(m_vAIList[i]->GetPosition());

			}
		}
	}
	return 0;
}

<commit_msg>Signed-off-by: mrlitong <litongtongxue@gmail.com><commit_after>#include "GameProcess.h"
#include "Object.h"
#include "Engine.h"
#include "World.h"
#include "App.h"
#include "ToolsCamera.h"
#include "ControlsApp.h"
#include "MathLib.h"
#include "Game.h"
#include "Editor.h"
#include "Input.h"
#include "BlueRayUtils.h"
#include "World.h"
#include "Action.h"
#include "FPSRoleLocal.h"

using namespace MathLib;

CGameProcess::CGameProcess(void)
{

}

CGameProcess::~CGameProcess(void)
{

}
int CGameProcess::Init()
{
	g_Engine.pFileSystem->CacheFilesFormExt("char");
	g_Engine.pFileSystem->CacheFilesFormExt("node");
	g_Engine.pFileSystem->CacheFilesFormExt("smesh");
	g_Engine.pFileSystem->CacheFilesFormExt("sanim");

	g_Engine.pWorld->LoadWorld("data/scene/terrain/test/test.world");
	//g_Engine.pWorld->LoadWorld("data/scene/terrain/cj/cj.world");
	g_Engine.pControls->SetKeyPressFunc(KeyPress);
	g_Engine.pControls->SetKeyReleaseFunc(KeyRelease);

	m_pRole = new CFPSRoleLocal();
	m_pRole->Init(10001, "data/role/hero/FpsRole/fps.char");		//ؽɫԴ

	m_pRole->SetActorPosition(vec3(0, 0, 0));	//ýɫʼλáŴΪԭ㣬άϵvec3
	m_pSkillSystem = new CSkillSystem(this);
	m_pCameraBase = new CCameraBase();
	m_pCameraBase->SetEnabled(1);
	g_pSysControl->SetMouseGrab(1);

	m_pStarControl = new CStarControl();
	m_pRayControl = new CRayControl();

	return 1;
}

int CGameProcess::ShutDown()			//رϷ
{
	delete m_pRole;
	delete m_pSkillSystem;
	delete m_pCameraBase;
	delete m_pStarControl;
	delete m_pRayControl;

	DelAllListen();
	return 0;
}

int CGameProcess::Update()
{
	float ifps = g_Engine.pGame->GetIFps();

	if (g_Engine.pInput->IsKeyDown('1'))
	{
		CAction* pAction = m_pRole->OrceAction("attack02");
		if (pAction)
		{
			pAction->SetupSkillThrow(vec3_zero, -1.0f, 2.0f);
			m_pRole->StopMove();
		}
	}
	else if (g_Engine.pInput->IsKeyDown('2'))
	{
		CAction* pAction = m_pRole->OrceAction("skill01");
		if (pAction)
		{
			m_pRole->StopMove();
		}
	}
	else if (g_Engine.pInput->IsKeyDown('3'))
	{
		CAction* pAction = m_pRole->OrceAction("skill02");
		if (pAction)
		{
			m_pRole->StopMove();
			CRoleBase* pTarget = NULL;
			for (int i = 0; i < 20; i++)
			{
				float l = (m_vAIList[i]->GetPosition() - m_pRole->GetPosition()).length();
				if (l > 5.0f && l < 15.0f)
				{
					pTarget = m_vAIList[i];
					break;
				}
			}
			if (pTarget)
			{
				CVector<int> vTarget;
				vTarget.Append(pTarget->GetRoleID());
				pAction->SetupSkillBulletTarget(vTarget);
				m_pRole->SetDirection((pTarget->GetPosition() - m_pRole->GetPosition()).normalize(), 1);
			}
		}
	}
	else if (g_Engine.pInput->IsKeyDown('4'))//෢ӵ
	{
		CAction* pAction = m_pRole->OrceAction("skill02");
		if (pAction)
		{
			m_pRole->StopMove();
			CVector<int> vTarget;
			for (int i = 0; i < 20; i++)
			{
				float l = (m_vAIList[i]->GetPosition() - m_pRole->GetPosition()).length();
				if (l > 5.0f && l < 20.0f)
				{
					vTarget.Append(m_vAIList[i]->GetRoleID());
				}
			}
			if (!vTarget.Empty())
			{
				pAction->SetupSkillBulletTarget(vTarget);
			}
		}
	}
	else if (g_Engine.pInput->IsKeyDown('5'))
	{
		CAction* pAction = m_pRole->OrceAction("skill03");
		if (pAction)
		{
			m_pRole->StopMove();
			CVector<vec3> vPos;
			pAction->SetupSkillTargetPoint(vPos);
		}
	}
	else if (g_Engine.pInput->IsKeyDown('6'))
	{
		CAction* pAction = m_pRole->OrceAction("skill06");
		if (pAction)
		{
			m_pRole->StopMove();
			CVector<vec3> vPos;
			for (int i = 0; i < 20; i++)
			{
				float l = (m_vAIList[i]->GetPosition() - m_pRole->GetPosition()).length();
				if (l > 5.0f && l < 20.0f)
					vPos.Append(m_vAIList[i]->GetPosition());

			}
			pAction->SetupSkillTargetPoint(vPos);
		}
	}
	else if ()
	{

	}
	return 0;
}

<|endoftext|>


<commit_before>/*=========================================================================

  Program:   Visualization Toolkit
  Module:    vtkFollower.cxx

  Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
  All rights reserved.
  See Copyright.txt or http://www.kitware.com/Copyright.htm for details.

     This software is distributed WITHOUT ANY WARRANTY; without even
     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
     PURPOSE.  See the above copyright notice for more information.

=========================================================================*/

#include "vtkFollower.h"

#include "vtkCamera.h"
#include "vtkMath.h"
#include "vtkMatrix4x4.h"
#include "vtkObjectFactory.h"
#include "vtkProperty.h"
#include "vtkRenderer.h"
#include "vtkTexture.h"
#include "vtkTransform.h"

#include <math.h>

vtkStandardNewMacro(vtkFollower);

vtkCxxSetObjectMacro(vtkFollower,Camera,vtkCamera);

//----------------------------------------------------------------------
// Creates a follower with no camera set
vtkFollower::vtkFollower()
{
  this->Camera = NULL;
  this->Device = vtkActor::New();

  this->InternalMatrix = vtkMatrix4x4::New();
}

//----------------------------------------------------------------------
vtkFollower::~vtkFollower()
{
  if (this->Camera)
    {
    this->Camera->UnRegister(this);
    }

  this->Device->Delete();

  this->InternalMatrix->Delete();
}

//----------------------------------------------------------------------------
void vtkFollower::ComputeMatrix()
{
  // check whether or not need to rebuild the matrix
  if ( this->GetMTime() > this->MatrixMTime ||
       (this->Camera && this->Camera->GetMTime() > this->MatrixMTime) )
    {
    this->GetOrientation();
    this->Transform->Push();
    this->Transform->Identity();
    this->Transform->PostMultiply();

    this->Transform->Translate(-this->Origin[0],
                               -this->Origin[1],
                               -this->Origin[2]);
    // scale
    this->Transform->Scale(this->Scale[0],
                           this->Scale[1],
                           this->Scale[2]);

    // rotate
    this->Transform->RotateY(this->Orientation[1]);
    this->Transform->RotateX(this->Orientation[0]);
    this->Transform->RotateZ(this->Orientation[2]);

    if (this->Camera)
      {
      double *pos, *vup, distance;
      double Rx[3], Ry[3], Rz[3];

      vtkMatrix4x4 *matrix = this->InternalMatrix;
      matrix->Identity();

      // do the rotation
      // first rotate y
      pos = this->Camera->GetPosition();
      vup = this->Camera->GetViewUp();

      if (this->Camera->GetParallelProjection())
        {
        this->Camera->GetDirectionOfProjection(Rz);
        Rz[0] = -Rz[0];
        Rz[1] = -Rz[1];
        Rz[2] = -Rz[2];
        }
      else
        {
        distance = sqrt(
          (pos[0] - this->Position[0])*(pos[0] - this->Position[0]) +
          (pos[1] - this->Position[1])*(pos[1] - this->Position[1]) +
          (pos[2] - this->Position[2])*(pos[2] - this->Position[2]));
        for (int i = 0; i < 3; i++)
          {
          Rz[i] = (pos[i] - this->Position[i])/distance;
          }
        }

      // We cannot directly use the vup angle since it can be aligned with Rz:
      //vtkMath::Cross(vup,Rz,Rx);
      //vtkMath::Normalize(Rx);
      //vtkMath::Cross(Rz,Rx,Ry);

      //instead use the view right angle:
      double dop[3], vur[3];
      this->Camera->GetDirectionOfProjection(dop);

      vtkMath::Cross(dop,vup,vur);
      vtkMath::Normalize(vur);

      vtkMath::Cross(Rz, vur, Ry);
      vtkMath::Normalize(Ry);
      vtkMath::Cross(Ry,Rz,Rx);

      matrix->Element[0][0] = Rx[0];
      matrix->Element[1][0] = Rx[1];
      matrix->Element[2][0] = Rx[2];
      matrix->Element[0][1] = Ry[0];
      matrix->Element[1][1] = Ry[1];
      matrix->Element[2][1] = Ry[2];
      matrix->Element[0][2] = Rz[0];
      matrix->Element[1][2] = Rz[1];
      matrix->Element[2][2] = Rz[2];

      this->Transform->Concatenate(matrix);
      }

    // translate to projection reference point PRP
    // this is the camera's position blasted through
    // the current matrix
    this->Transform->Translate(this->Origin[0] + this->Position[0],
                               this->Origin[1] + this->Position[1],
                               this->Origin[2] + this->Position[2]);

    // apply user defined matrix last if there is one
    if (this->UserMatrix)
      {
      this->Transform->Concatenate(this->UserMatrix);
      }

    this->Transform->PreMultiply();
    this->Transform->GetMatrix(this->Matrix);
    this->MatrixMTime.Modified();
    this->Transform->Pop();
    }
}

//----------------------------------------------------------------------
void vtkFollower::PrintSelf(ostream& os, vtkIndent indent)
{
  this->Superclass::PrintSelf(os,indent);

  if ( this->Camera )
    {
    os << indent << "Camera:\n";
    this->Camera->PrintSelf(os,indent.GetNextIndent());
    }
  else
    {
    os << indent << "Camera: (none)\n";
    }
}

//----------------------------------------------------------------------
int vtkFollower::RenderOpaqueGeometry(vtkViewport *vp)
{
  if ( ! this->Mapper )
    {
    return 0;
    }

  if (!this->Property)
    {
    // force creation of a property
    this->GetProperty();
    }

  if (this->GetIsOpaque())
    {
    vtkRenderer *ren = static_cast<vtkRenderer *>(vp);
    this->Render(ren);
    return 1;
    }
  return 0;
}

//-----------------------------------------------------------------------------
int vtkFollower::RenderTranslucentPolygonalGeometry(vtkViewport *vp)
{
  if ( ! this->Mapper )
    {
    return 0;
    }

  if (!this->Property)
    {
    // force creation of a property
    this->GetProperty();
    }

  if (!this->GetIsOpaque())
    {
    vtkRenderer *ren = static_cast<vtkRenderer *>(vp);
    this->Render(ren);
    return 1;
    }
  return 0;
}

//-----------------------------------------------------------------------------
void vtkFollower::ReleaseGraphicsResources(vtkWindow *w)
{
  this->Device->ReleaseGraphicsResources(w);
}

//-----------------------------------------------------------------------------
// Description:
// Does this prop have some translucent polygonal geometry?
int vtkFollower::HasTranslucentPolygonalGeometry()
{
  if ( ! this->Mapper )
    {
    return 0;
    }
  // make sure we have a property
  if (!this->Property)
    {
    // force creation of a property
    this->GetProperty();
    }

  // is this actor opaque ?
  return !this->GetIsOpaque();
}

//-----------------------------------------------------------------------------
// This causes the actor to be rendered. It, in turn, will render the actor's
// property and then mapper.
void vtkFollower::Render(vtkRenderer *ren)
{
  this->Property->Render(this, ren);

  this->Device->SetProperty (this->Property);
  this->Property->Render(this, ren);
  if (this->BackfaceProperty)
    {
    this->BackfaceProperty->BackfaceRender(this, ren);
    this->Device->SetBackfaceProperty(this->BackfaceProperty);
    }

  /* render the texture */
  if (this->Texture)
    {
    this->Texture->Render(ren);
    }

  // make sure the device has the same matrix
  this->ComputeMatrix();
  this->Device->SetUserMatrix(this->Matrix);

  this->Device->Render(ren,this->Mapper);
}

//----------------------------------------------------------------------
void vtkFollower::ShallowCopy(vtkProp *prop)
{
  vtkFollower *f = vtkFollower::SafeDownCast(prop);
  if ( f != NULL )
    {
    this->SetCamera(f->GetCamera());
    }

  // Now do superclass
  this->vtkActor::ShallowCopy(prop);
}

<commit_msg>Added missing ReleaseGraphicsResources.<commit_after>/*=========================================================================

  Program:   Visualization Toolkit
  Module:    vtkFollower.cxx

  Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
  All rights reserved.
  See Copyright.txt or http://www.kitware.com/Copyright.htm for details.

     This software is distributed WITHOUT ANY WARRANTY; without even
     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
     PURPOSE.  See the above copyright notice for more information.

=========================================================================*/

#include "vtkFollower.h"

#include "vtkCamera.h"
#include "vtkMath.h"
#include "vtkMatrix4x4.h"
#include "vtkObjectFactory.h"
#include "vtkProperty.h"
#include "vtkRenderer.h"
#include "vtkTexture.h"
#include "vtkTransform.h"

#include <math.h>

vtkStandardNewMacro(vtkFollower);

vtkCxxSetObjectMacro(vtkFollower,Camera,vtkCamera);

//----------------------------------------------------------------------
// Creates a follower with no camera set
vtkFollower::vtkFollower()
{
  this->Camera = NULL;
  this->Device = vtkActor::New();

  this->InternalMatrix = vtkMatrix4x4::New();
}

//----------------------------------------------------------------------
vtkFollower::~vtkFollower()
{
  if (this->Camera)
    {
    this->Camera->UnRegister(this);
    }

  this->Device->Delete();

  this->InternalMatrix->Delete();
}

//----------------------------------------------------------------------------
void vtkFollower::ComputeMatrix()
{
  // check whether or not need to rebuild the matrix
  if ( this->GetMTime() > this->MatrixMTime ||
       (this->Camera && this->Camera->GetMTime() > this->MatrixMTime) )
    {
    this->GetOrientation();
    this->Transform->Push();
    this->Transform->Identity();
    this->Transform->PostMultiply();

    this->Transform->Translate(-this->Origin[0],
                               -this->Origin[1],
                               -this->Origin[2]);
    // scale
    this->Transform->Scale(this->Scale[0],
                           this->Scale[1],
                           this->Scale[2]);

    // rotate
    this->Transform->RotateY(this->Orientation[1]);
    this->Transform->RotateX(this->Orientation[0]);
    this->Transform->RotateZ(this->Orientation[2]);

    if (this->Camera)
      {
      double *pos, *vup, distance;
      double Rx[3], Ry[3], Rz[3];

      vtkMatrix4x4 *matrix = this->InternalMatrix;
      matrix->Identity();

      // do the rotation
      // first rotate y
      pos = this->Camera->GetPosition();
      vup = this->Camera->GetViewUp();

      if (this->Camera->GetParallelProjection())
        {
        this->Camera->GetDirectionOfProjection(Rz);
        Rz[0] = -Rz[0];
        Rz[1] = -Rz[1];
        Rz[2] = -Rz[2];
        }
      else
        {
        distance = sqrt(
          (pos[0] - this->Position[0])*(pos[0] - this->Position[0]) +
          (pos[1] - this->Position[1])*(pos[1] - this->Position[1]) +
          (pos[2] - this->Position[2])*(pos[2] - this->Position[2]));
        for (int i = 0; i < 3; i++)
          {
          Rz[i] = (pos[i] - this->Position[i])/distance;
          }
        }

      // We cannot directly use the vup angle since it can be aligned with Rz:
      //vtkMath::Cross(vup,Rz,Rx);
      //vtkMath::Normalize(Rx);
      //vtkMath::Cross(Rz,Rx,Ry);

      //instead use the view right angle:
      double dop[3], vur[3];
      this->Camera->GetDirectionOfProjection(dop);

      vtkMath::Cross(dop,vup,vur);
      vtkMath::Normalize(vur);

      vtkMath::Cross(Rz, vur, Ry);
      vtkMath::Normalize(Ry);
      vtkMath::Cross(Ry,Rz,Rx);

      matrix->Element[0][0] = Rx[0];
      matrix->Element[1][0] = Rx[1];
      matrix->Element[2][0] = Rx[2];
      matrix->Element[0][1] = Ry[0];
      matrix->Element[1][1] = Ry[1];
      matrix->Element[2][1] = Ry[2];
      matrix->Element[0][2] = Rz[0];
      matrix->Element[1][2] = Rz[1];
      matrix->Element[2][2] = Rz[2];

      this->Transform->Concatenate(matrix);
      }

    // translate to projection reference point PRP
    // this is the camera's position blasted through
    // the current matrix
    this->Transform->Translate(this->Origin[0] + this->Position[0],
                               this->Origin[1] + this->Position[1],
                               this->Origin[2] + this->Position[2]);

    // apply user defined matrix last if there is one
    if (this->UserMatrix)
      {
      this->Transform->Concatenate(this->UserMatrix);
      }

    this->Transform->PreMultiply();
    this->Transform->GetMatrix(this->Matrix);
    this->MatrixMTime.Modified();
    this->Transform->Pop();
    }
}

//----------------------------------------------------------------------
void vtkFollower::PrintSelf(ostream& os, vtkIndent indent)
{
  this->Superclass::PrintSelf(os,indent);

  if ( this->Camera )
    {
    os << indent << "Camera:\n";
    this->Camera->PrintSelf(os,indent.GetNextIndent());
    }
  else
    {
    os << indent << "Camera: (none)\n";
    }
}

//----------------------------------------------------------------------
int vtkFollower::RenderOpaqueGeometry(vtkViewport *vp)
{
  if ( ! this->Mapper )
    {
    return 0;
    }

  if (!this->Property)
    {
    // force creation of a property
    this->GetProperty();
    }

  if (this->GetIsOpaque())
    {
    vtkRenderer *ren = static_cast<vtkRenderer *>(vp);
    this->Render(ren);
    return 1;
    }
  return 0;
}

//-----------------------------------------------------------------------------
int vtkFollower::RenderTranslucentPolygonalGeometry(vtkViewport *vp)
{
  if ( ! this->Mapper )
    {
    return 0;
    }

  if (!this->Property)
    {
    // force creation of a property
    this->GetProperty();
    }

  if (!this->GetIsOpaque())
    {
    vtkRenderer *ren = static_cast<vtkRenderer *>(vp);
    this->Render(ren);
    return 1;
    }
  return 0;
}

//-----------------------------------------------------------------------------
void vtkFollower::ReleaseGraphicsResources(vtkWindow *w)
{
  this->Device->ReleaseGraphicsResources(w);
  this->Superclass::ReleaseGraphicsResources(w);
}

//-----------------------------------------------------------------------------
// Description:
// Does this prop have some translucent polygonal geometry?
int vtkFollower::HasTranslucentPolygonalGeometry()
{
  if ( ! this->Mapper )
    {
    return 0;
    }
  // make sure we have a property
  if (!this->Property)
    {
    // force creation of a property
    this->GetProperty();
    }

  // is this actor opaque ?
  return !this->GetIsOpaque();
}

//-----------------------------------------------------------------------------
// This causes the actor to be rendered. It, in turn, will render the actor's
// property and then mapper.
void vtkFollower::Render(vtkRenderer *ren)
{
  this->Property->Render(this, ren);

  this->Device->SetProperty (this->Property);
  this->Property->Render(this, ren);
  if (this->BackfaceProperty)
    {
    this->BackfaceProperty->BackfaceRender(this, ren);
    this->Device->SetBackfaceProperty(this->BackfaceProperty);
    }

  /* render the texture */
  if (this->Texture)
    {
    this->Texture->Render(ren);
    }

  // make sure the device has the same matrix
  this->ComputeMatrix();
  this->Device->SetUserMatrix(this->Matrix);

  this->Device->Render(ren,this->Mapper);
}

//----------------------------------------------------------------------
void vtkFollower::ShallowCopy(vtkProp *prop)
{
  vtkFollower *f = vtkFollower::SafeDownCast(prop);
  if ( f != NULL )
    {
    this->SetCamera(f->GetCamera());
    }

  // Now do superclass
  this->vtkActor::ShallowCopy(prop);
}

<|endoftext|>


<commit_before>#include "rpcconsole.h"
#include "ui_rpcconsole.h"

#include "clientmodel.h"
#include "bitcoinrpc.h"
#include "guiutil.h"

#include <QTime>
#include <QTimer>
#include <QThread>
#include <QTextEdit>
#include <QKeyEvent>
#include <QUrl>
#include <QScrollBar>

#include <openssl/crypto.h>

// TODO: make it possible to filter out categories (esp debug messages when implemented)
// TODO: receive errors and debug messages through ClientModel

const int CONSOLE_SCROLLBACK = 50;
const int CONSOLE_HISTORY = 50;

const QSize ICON_SIZE(24, 24);

const struct {
    const char *url;
    const char *source;
} ICON_MAPPING[] = {
    {"cmd-request", ":/icons/tx_input"},
    {"cmd-reply", ":/icons/tx_output"},
    {"cmd-error", ":/icons/tx_output"},
    {"misc", ":/icons/tx_inout"},
    {NULL, NULL}
};

/* Object for executing console RPC commands in a separate thread.
*/
class RPCExecutor: public QObject
{
    Q_OBJECT
public slots:
    void start();
    void request(const QString &command);
signals:
    void reply(int category, const QString &command);
};

#include "rpcconsole.moc"

void RPCExecutor::start()
{
   // Nothing to do
}

/**
 * Split shell command line into a list of arguments. Aims to emulate \c bash and friends.
 *
 * - Arguments are delimited with whitespace
 * - Extra whitespace at the beginning and end and between arguments will be ignored
 * - Arguments can be "double" or 'single' quoted. Those are treated the same.
 * - The backslash '\' is used as escape character
 *   - Outside quotes, any character can be escaped
 *   - Within double quotes, only escape double quotes with \" and backslashes with \\
 *   - Within single quotes, only escape single quotes with \' and backslashes with \\
 *
 * @param[out]   args        Parsed arguments will be appended to this list
 * @param[in]    strCommand  Command line to split
 */
bool parseCommandLine(std::vector<std::string> &args, const std::string &strCommand)
{
    enum CmdParseState
    {
        STATE_EATING_SPACES,
        STATE_ARGUMENT,
        STATE_SINGLEQUOTED,
        STATE_DOUBLEQUOTED,
        STATE_ESCAPE_OUTER,
        STATE_ESCAPE_SINGLEQUOTED,
        STATE_ESCAPE_DOUBLEQUOTED
    } state = STATE_EATING_SPACES;
    std::string curarg;
    foreach(char ch, strCommand)
    {
        switch(state)
        {
        case STATE_ARGUMENT: // After argument
        case STATE_EATING_SPACES: // Handle runs of spaces
            switch(ch)
            {
            case '"': state = STATE_DOUBLEQUOTED; break;
            case '\'': state = STATE_SINGLEQUOTED; break;
            case '\\': state = STATE_ESCAPE_OUTER; break;
            case ' ': case '\n': case '\t':
                if(state == STATE_ARGUMENT) // Space ends argument
                {
                    args.push_back(curarg);
                    curarg.clear();
                }
                state = STATE_EATING_SPACES;
                break;
            default: curarg += ch; state = STATE_ARGUMENT;
            }
            break;
        case STATE_SINGLEQUOTED: // Single-quoted string
            switch(ch)
            {
            case '\'': state = STATE_ARGUMENT; break;
            case '\\': state = STATE_ESCAPE_SINGLEQUOTED; break;
            default: curarg += ch;
            }
            break;
        case STATE_DOUBLEQUOTED: // Double-quoted string
            switch(ch)
            {
            case '"': state = STATE_ARGUMENT; break;
            case '\\': state = STATE_ESCAPE_DOUBLEQUOTED; break;
            default: curarg += ch;
            }
            break;
        case STATE_ESCAPE_OUTER: // '\' outside quotes
            curarg += ch; state = STATE_ARGUMENT;
            break;
        case STATE_ESCAPE_SINGLEQUOTED: // '\' in single-quoted text
            if(ch != '\'') curarg += '\\'; // keep '\' for everything but the quote
            curarg += ch; state = STATE_SINGLEQUOTED;
            break;
        case STATE_ESCAPE_DOUBLEQUOTED: // '\' in double-quoted text
            if(ch != '"') curarg += '\\'; // keep '\' for everything but the quote
            curarg += ch; state = STATE_DOUBLEQUOTED;
            break;
        }
    }
    switch(state) // final state
    {
    case STATE_EATING_SPACES:
        return true;
    case STATE_ARGUMENT:
        args.push_back(curarg);
        return true;
    default: // ERROR to end in one of the other states
        return false;
    }
}

void RPCExecutor::request(const QString &command)
{
    std::vector<std::string> args;
    if(!parseCommandLine(args, command.toStdString()))
    {
        emit reply(RPCConsole::CMD_ERROR, QString("Parse error: unbalanced ' or \""));
        return;
    }
    if(args.empty())
        return; // Nothing to do
    try {
        std::string strPrint;
        // Convert argument list to JSON objects in method-dependent way,
        // and pass it along with the method name to the dispatcher.
        json_spirit::Value result = tableRPC.execute(
            args[0],
            RPCConvertValues(args[0], std::vector<std::string>(args.begin() + 1, args.end())));

        // Format result reply
        if (result.type() == json_spirit::null_type)
            strPrint = "";
        else if (result.type() == json_spirit::str_type)
            strPrint = result.get_str();
        else
            strPrint = write_string(result, true);

        emit reply(RPCConsole::CMD_REPLY, QString::fromStdString(strPrint));
    }
    catch (json_spirit::Object& objError)
    {
        emit reply(RPCConsole::CMD_ERROR, QString::fromStdString(write_string(json_spirit::Value(objError), false)));
    }
    catch (std::exception& e)
    {
        emit reply(RPCConsole::CMD_ERROR, QString("Error: ") + QString::fromStdString(e.what()));
    }
}

RPCConsole::RPCConsole(QWidget *parent) :
    QDialog(parent),
    ui(new Ui::RPCConsole),
    historyPtr(0)
{
    ui->setupUi(this);

#ifndef Q_WS_MAC
    ui->openDebugLogfileButton->setIcon(QIcon(":/icons/export"));
    ui->showCLOptionsButton->setIcon(QIcon(":/icons/options"));
#endif

    // Install event filter for up and down arrow
    ui->lineEdit->installEventFilter(this);

    connect(ui->clearButton, SIGNAL(clicked()), this, SLOT(clear()));

    // set OpenSSL version label
    ui->openSSLVersion->setText(SSLeay_version(SSLEAY_VERSION));

    startExecutor();

    clear();
}

RPCConsole::~RPCConsole()
{
    emit stopExecutor();
    delete ui;
}

bool RPCConsole::eventFilter(QObject* obj, QEvent *event)
{
    if(obj == ui->lineEdit)
    {
        if(event->type() == QEvent::KeyPress)
        {
            QKeyEvent *key = static_cast<QKeyEvent*>(event);
            switch(key->key())
            {
            case Qt::Key_Up: browseHistory(-1); return true;
            case Qt::Key_Down: browseHistory(1); return true;
            }
        }
    }
    return QDialog::eventFilter(obj, event);
}

void RPCConsole::setClientModel(ClientModel *model)
{
    this->clientModel = model;
    if(model)
    {
        // Subscribe to information, replies, messages, errors
        connect(model, SIGNAL(numConnectionsChanged(int)), this, SLOT(setNumConnections(int)));
        connect(model, SIGNAL(numBlocksChanged(int,int)), this, SLOT(setNumBlocks(int,int)));

        // Provide initial values
        ui->clientVersion->setText(model->formatFullVersion());
        ui->clientName->setText(model->clientName());
        ui->buildDate->setText(model->formatBuildDate());
        ui->startupTime->setText(model->formatClientStartupTime());

        setNumConnections(model->getNumConnections());
        ui->isTestNet->setChecked(model->isTestNet());

        setNumBlocks(model->getNumBlocks(), model->getNumBlocksOfPeers());
    }
}

static QString categoryClass(int category)
{
    switch(category)
    {
    case RPCConsole::CMD_REQUEST:  return "cmd-request"; break;
    case RPCConsole::CMD_REPLY:    return "cmd-reply"; break;
    case RPCConsole::CMD_ERROR:    return "cmd-error"; break;
    default:                       return "misc";
    }
}

void RPCConsole::clear()
{
    ui->messagesWidget->clear();
    ui->lineEdit->clear();
    ui->lineEdit->setFocus();

    // Add smoothly scaled icon images.
    // (when using width/height on an img, Qt uses nearest instead of linear interpolation)
    for(int i=0; ICON_MAPPING[i].url; ++i)
    {
        ui->messagesWidget->document()->addResource(
                    QTextDocument::ImageResource,
                    QUrl(ICON_MAPPING[i].url),
                    QImage(ICON_MAPPING[i].source).scaled(ICON_SIZE, Qt::IgnoreAspectRatio, Qt::SmoothTransformation));
    }

    // Set default style sheet
    ui->messagesWidget->document()->setDefaultStyleSheet(
                "table { }"
                "td.time { color: #808080; padding-top: 3px; } "
                "td.message { font-family: Monospace; font-size: 12px; } "
                "td.cmd-request { color: #006060; } "
                "td.cmd-error { color: red; } "
                "b { color: #006060; } "
                );

    message(CMD_REPLY, (tr("Welcome to the Bitcoin RPC console.") + "
" +
                        tr("Use up and down arrows to navigate history, and Ctrl-L to clear screen.") + "
" +
                        tr("Type help for an overview of available commands.")), true);
}

void RPCConsole::message(int category, const QString &message, bool html)
{
    QTime time = QTime::currentTime();
    QString timeString = time.toString();
    QString out;
    out += "

" + timeString + "	";
    out += "	";
    out += "";
    if(html)
        out += message;
    else
        out += GUIUtil::HtmlEscape(message, true);
    out += "

";
    ui->messagesWidget->append(out);
}

void RPCConsole::setNumConnections(int count)
{
    ui->numberOfConnections->setText(QString::number(count));
}

void RPCConsole::setNumBlocks(int count, int countOfPeers)
{
    ui->numberOfBlocks->setText(QString::number(count));
    ui->totalBlocks->setText(QString::number(countOfPeers));
    if(clientModel)
    {
        // If there is no current number available display N/A instead of 0, which can't ever be true
        ui->totalBlocks->setText(clientModel->getNumBlocksOfPeers() == 0 ? tr("N/A") : QString::number(clientModel->getNumBlocksOfPeers()));
        ui->lastBlockTime->setText(clientModel->getLastBlockDate().toString());
    }
}

void RPCConsole::on_lineEdit_returnPressed()
{
    QString cmd = ui->lineEdit->text();
    ui->lineEdit->clear();

    if(!cmd.isEmpty())
    {
        message(CMD_REQUEST, cmd);
        emit cmdRequest(cmd);
        // Truncate history from current position
        history.erase(history.begin() + historyPtr, history.end());
        // Append command to history
        history.append(cmd);
        // Enforce maximum history size
        while(history.size() > CONSOLE_HISTORY)
            history.removeFirst();
        // Set pointer to end of history
        historyPtr = history.size();
        // Scroll console view to end
        scrollToEnd();
    }
}

void RPCConsole::browseHistory(int offset)
{
    historyPtr += offset;
    if(historyPtr < 0)
        historyPtr = 0;
    if(historyPtr > history.size())
        historyPtr = history.size();
    QString cmd;
    if(historyPtr < history.size())
        cmd = history.at(historyPtr);
    ui->lineEdit->setText(cmd);
}

void RPCConsole::startExecutor()
{
    QThread* thread = new QThread;
    RPCExecutor *executor = new RPCExecutor();
    executor->moveToThread(thread);

    // Notify executor when thread started (in executor thread)
    connect(thread, SIGNAL(started()), executor, SLOT(start()));
    // Replies from executor object must go to this object
    connect(executor, SIGNAL(reply(int,QString)), this, SLOT(message(int,QString)));
    // Requests from this object must go to executor
    connect(this, SIGNAL(cmdRequest(QString)), executor, SLOT(request(QString)));
    // On stopExecutor signal
    // - queue executor for deletion (in execution thread)
    // - quit the Qt event loop in the execution thread
    connect(this, SIGNAL(stopExecutor()), executor, SLOT(deleteLater()));
    connect(this, SIGNAL(stopExecutor()), thread, SLOT(quit()));
    // Queue the thread for deletion (in this thread) when it is finished
    connect(thread, SIGNAL(finished()), thread, SLOT(deleteLater()));

    // Default implementation of QThread::run() simply spins up an event loop in the thread,
    // which is what we want.
    thread->start();
}

void RPCConsole::on_tabWidget_currentChanged(int index)
{
    if(ui->tabWidget->widget(index) == ui->tab_console)
    {
        ui->lineEdit->setFocus();
    }
}

void RPCConsole::on_openDebugLogfileButton_clicked()
{
    GUIUtil::openDebugLogfile();
}

void RPCConsole::scrollToEnd()
{
    QScrollBar *scrollbar = ui->messagesWidget->verticalScrollBar();
    scrollbar->setValue(scrollbar->maximum());
}

void RPCConsole::on_showCLOptionsButton_clicked()
{
    GUIUtil::HelpMessageBox help;
    help.exec();
}
<commit_msg>In RPC console, attempt to format errors<commit_after>#include "rpcconsole.h"
#include "ui_rpcconsole.h"

#include "clientmodel.h"
#include "bitcoinrpc.h"
#include "guiutil.h"

#include <QTime>
#include <QTimer>
#include <QThread>
#include <QTextEdit>
#include <QKeyEvent>
#include <QUrl>
#include <QScrollBar>

#include <openssl/crypto.h>

// TODO: make it possible to filter out categories (esp debug messages when implemented)
// TODO: receive errors and debug messages through ClientModel

const int CONSOLE_SCROLLBACK = 50;
const int CONSOLE_HISTORY = 50;

const QSize ICON_SIZE(24, 24);

const struct {
    const char *url;
    const char *source;
} ICON_MAPPING[] = {
    {"cmd-request", ":/icons/tx_input"},
    {"cmd-reply", ":/icons/tx_output"},
    {"cmd-error", ":/icons/tx_output"},
    {"misc", ":/icons/tx_inout"},
    {NULL, NULL}
};

/* Object for executing console RPC commands in a separate thread.
*/
class RPCExecutor: public QObject
{
    Q_OBJECT
public slots:
    void start();
    void request(const QString &command);
signals:
    void reply(int category, const QString &command);
};

#include "rpcconsole.moc"

void RPCExecutor::start()
{
   // Nothing to do
}

/**
 * Split shell command line into a list of arguments. Aims to emulate \c bash and friends.
 *
 * - Arguments are delimited with whitespace
 * - Extra whitespace at the beginning and end and between arguments will be ignored
 * - Arguments can be "double" or 'single' quoted. Those are treated the same.
 * - The backslash '\' is used as escape character
 *   - Outside quotes, any character can be escaped
 *   - Within double quotes, only escape double quotes with \" and backslashes with \\
 *   - Within single quotes, only escape single quotes with \' and backslashes with \\
 *
 * @param[out]   args        Parsed arguments will be appended to this list
 * @param[in]    strCommand  Command line to split
 */
bool parseCommandLine(std::vector<std::string> &args, const std::string &strCommand)
{
    enum CmdParseState
    {
        STATE_EATING_SPACES,
        STATE_ARGUMENT,
        STATE_SINGLEQUOTED,
        STATE_DOUBLEQUOTED,
        STATE_ESCAPE_OUTER,
        STATE_ESCAPE_SINGLEQUOTED,
        STATE_ESCAPE_DOUBLEQUOTED
    } state = STATE_EATING_SPACES;
    std::string curarg;
    foreach(char ch, strCommand)
    {
        switch(state)
        {
        case STATE_ARGUMENT: // After argument
        case STATE_EATING_SPACES: // Handle runs of spaces
            switch(ch)
            {
            case '"': state = STATE_DOUBLEQUOTED; break;
            case '\'': state = STATE_SINGLEQUOTED; break;
            case '\\': state = STATE_ESCAPE_OUTER; break;
            case ' ': case '\n': case '\t':
                if(state == STATE_ARGUMENT) // Space ends argument
                {
                    args.push_back(curarg);
                    curarg.clear();
                }
                state = STATE_EATING_SPACES;
                break;
            default: curarg += ch; state = STATE_ARGUMENT;
            }
            break;
        case STATE_SINGLEQUOTED: // Single-quoted string
            switch(ch)
            {
            case '\'': state = STATE_ARGUMENT; break;
            case '\\': state = STATE_ESCAPE_SINGLEQUOTED; break;
            default: curarg += ch;
            }
            break;
        case STATE_DOUBLEQUOTED: // Double-quoted string
            switch(ch)
            {
            case '"': state = STATE_ARGUMENT; break;
            case '\\': state = STATE_ESCAPE_DOUBLEQUOTED; break;
            default: curarg += ch;
            }
            break;
        case STATE_ESCAPE_OUTER: // '\' outside quotes
            curarg += ch; state = STATE_ARGUMENT;
            break;
        case STATE_ESCAPE_SINGLEQUOTED: // '\' in single-quoted text
            if(ch != '\'') curarg += '\\'; // keep '\' for everything but the quote
            curarg += ch; state = STATE_SINGLEQUOTED;
            break;
        case STATE_ESCAPE_DOUBLEQUOTED: // '\' in double-quoted text
            if(ch != '"') curarg += '\\'; // keep '\' for everything but the quote
            curarg += ch; state = STATE_DOUBLEQUOTED;
            break;
        }
    }
    switch(state) // final state
    {
    case STATE_EATING_SPACES:
        return true;
    case STATE_ARGUMENT:
        args.push_back(curarg);
        return true;
    default: // ERROR to end in one of the other states
        return false;
    }
}

void RPCExecutor::request(const QString &command)
{
    std::vector<std::string> args;
    if(!parseCommandLine(args, command.toStdString()))
    {
        emit reply(RPCConsole::CMD_ERROR, QString("Parse error: unbalanced ' or \""));
        return;
    }
    if(args.empty())
        return; // Nothing to do
    try
    {
        std::string strPrint;
        // Convert argument list to JSON objects in method-dependent way,
        // and pass it along with the method name to the dispatcher.
        json_spirit::Value result = tableRPC.execute(
            args[0],
            RPCConvertValues(args[0], std::vector<std::string>(args.begin() + 1, args.end())));

        // Format result reply
        if (result.type() == json_spirit::null_type)
            strPrint = "";
        else if (result.type() == json_spirit::str_type)
            strPrint = result.get_str();
        else
            strPrint = write_string(result, true);

        emit reply(RPCConsole::CMD_REPLY, QString::fromStdString(strPrint));
    }
    catch (json_spirit::Object& objError)
    {
        try // Nice formatting for standard-format error
        {
            int code = find_value(objError, "code").get_int();
            std::string message = find_value(objError, "message").get_str();
            emit reply(RPCConsole::CMD_ERROR, QString::fromStdString(message) + " (code " + QString::number(code) + ")");
        }
        catch(std::runtime_error &) // raised when converting to invalid type, i.e. missing code or message
        {
            // Show raw JSON object
            emit reply(RPCConsole::CMD_ERROR, QString::fromStdString(write_string(json_spirit::Value(objError), false)));
        }
    }
    catch (std::exception& e)
    {
        emit reply(RPCConsole::CMD_ERROR, QString("Error: ") + QString::fromStdString(e.what()));
    }
}

RPCConsole::RPCConsole(QWidget *parent) :
    QDialog(parent),
    ui(new Ui::RPCConsole),
    historyPtr(0)
{
    ui->setupUi(this);

#ifndef Q_WS_MAC
    ui->openDebugLogfileButton->setIcon(QIcon(":/icons/export"));
    ui->showCLOptionsButton->setIcon(QIcon(":/icons/options"));
#endif

    // Install event filter for up and down arrow
    ui->lineEdit->installEventFilter(this);

    connect(ui->clearButton, SIGNAL(clicked()), this, SLOT(clear()));

    // set OpenSSL version label
    ui->openSSLVersion->setText(SSLeay_version(SSLEAY_VERSION));

    startExecutor();

    clear();
}

RPCConsole::~RPCConsole()
{
    emit stopExecutor();
    delete ui;
}

bool RPCConsole::eventFilter(QObject* obj, QEvent *event)
{
    if(obj == ui->lineEdit)
    {
        if(event->type() == QEvent::KeyPress)
        {
            QKeyEvent *key = static_cast<QKeyEvent*>(event);
            switch(key->key())
            {
            case Qt::Key_Up: browseHistory(-1); return true;
            case Qt::Key_Down: browseHistory(1); return true;
            }
        }
    }
    return QDialog::eventFilter(obj, event);
}

void RPCConsole::setClientModel(ClientModel *model)
{
    this->clientModel = model;
    if(model)
    {
        // Subscribe to information, replies, messages, errors
        connect(model, SIGNAL(numConnectionsChanged(int)), this, SLOT(setNumConnections(int)));
        connect(model, SIGNAL(numBlocksChanged(int,int)), this, SLOT(setNumBlocks(int,int)));

        // Provide initial values
        ui->clientVersion->setText(model->formatFullVersion());
        ui->clientName->setText(model->clientName());
        ui->buildDate->setText(model->formatBuildDate());
        ui->startupTime->setText(model->formatClientStartupTime());

        setNumConnections(model->getNumConnections());
        ui->isTestNet->setChecked(model->isTestNet());

        setNumBlocks(model->getNumBlocks(), model->getNumBlocksOfPeers());
    }
}

static QString categoryClass(int category)
{
    switch(category)
    {
    case RPCConsole::CMD_REQUEST:  return "cmd-request"; break;
    case RPCConsole::CMD_REPLY:    return "cmd-reply"; break;
    case RPCConsole::CMD_ERROR:    return "cmd-error"; break;
    default:                       return "misc";
    }
}

void RPCConsole::clear()
{
    ui->messagesWidget->clear();
    ui->lineEdit->clear();
    ui->lineEdit->setFocus();

    // Add smoothly scaled icon images.
    // (when using width/height on an img, Qt uses nearest instead of linear interpolation)
    for(int i=0; ICON_MAPPING[i].url; ++i)
    {
        ui->messagesWidget->document()->addResource(
                    QTextDocument::ImageResource,
                    QUrl(ICON_MAPPING[i].url),
                    QImage(ICON_MAPPING[i].source).scaled(ICON_SIZE, Qt::IgnoreAspectRatio, Qt::SmoothTransformation));
    }

    // Set default style sheet
    ui->messagesWidget->document()->setDefaultStyleSheet(
                "table { }"
                "td.time { color: #808080; padding-top: 3px; } "
                "td.message { font-family: Monospace; font-size: 12px; } "
                "td.cmd-request { color: #006060; } "
                "td.cmd-error { color: red; } "
                "b { color: #006060; } "
                );

    message(CMD_REPLY, (tr("Welcome to the Bitcoin RPC console.") + "
" +
                        tr("Use up and down arrows to navigate history, and Ctrl-L to clear screen.") + "
" +
                        tr("Type help for an overview of available commands.")), true);
}

void RPCConsole::message(int category, const QString &message, bool html)
{
    QTime time = QTime::currentTime();
    QString timeString = time.toString();
    QString out;
    out += "

" + timeString + "	";
    out += "	";
    out += "";
    if(html)
        out += message;
    else
        out += GUIUtil::HtmlEscape(message, true);
    out += "

";
    ui->messagesWidget->append(out);
}

void RPCConsole::setNumConnections(int count)
{
    ui->numberOfConnections->setText(QString::number(count));
}

void RPCConsole::setNumBlocks(int count, int countOfPeers)
{
    ui->numberOfBlocks->setText(QString::number(count));
    ui->totalBlocks->setText(QString::number(countOfPeers));
    if(clientModel)
    {
        // If there is no current number available display N/A instead of 0, which can't ever be true
        ui->totalBlocks->setText(clientModel->getNumBlocksOfPeers() == 0 ? tr("N/A") : QString::number(clientModel->getNumBlocksOfPeers()));
        ui->lastBlockTime->setText(clientModel->getLastBlockDate().toString());
    }
}

void RPCConsole::on_lineEdit_returnPressed()
{
    QString cmd = ui->lineEdit->text();
    ui->lineEdit->clear();

    if(!cmd.isEmpty())
    {
        message(CMD_REQUEST, cmd);
        emit cmdRequest(cmd);
        // Truncate history from current position
        history.erase(history.begin() + historyPtr, history.end());
        // Append command to history
        history.append(cmd);
        // Enforce maximum history size
        while(history.size() > CONSOLE_HISTORY)
            history.removeFirst();
        // Set pointer to end of history
        historyPtr = history.size();
        // Scroll console view to end
        scrollToEnd();
    }
}

void RPCConsole::browseHistory(int offset)
{
    historyPtr += offset;
    if(historyPtr < 0)
        historyPtr = 0;
    if(historyPtr > history.size())
        historyPtr = history.size();
    QString cmd;
    if(historyPtr < history.size())
        cmd = history.at(historyPtr);
    ui->lineEdit->setText(cmd);
}

void RPCConsole::startExecutor()
{
    QThread* thread = new QThread;
    RPCExecutor *executor = new RPCExecutor();
    executor->moveToThread(thread);

    // Notify executor when thread started (in executor thread)
    connect(thread, SIGNAL(started()), executor, SLOT(start()));
    // Replies from executor object must go to this object
    connect(executor, SIGNAL(reply(int,QString)), this, SLOT(message(int,QString)));
    // Requests from this object must go to executor
    connect(this, SIGNAL(cmdRequest(QString)), executor, SLOT(request(QString)));
    // On stopExecutor signal
    // - queue executor for deletion (in execution thread)
    // - quit the Qt event loop in the execution thread
    connect(this, SIGNAL(stopExecutor()), executor, SLOT(deleteLater()));
    connect(this, SIGNAL(stopExecutor()), thread, SLOT(quit()));
    // Queue the thread for deletion (in this thread) when it is finished
    connect(thread, SIGNAL(finished()), thread, SLOT(deleteLater()));

    // Default implementation of QThread::run() simply spins up an event loop in the thread,
    // which is what we want.
    thread->start();
}

void RPCConsole::on_tabWidget_currentChanged(int index)
{
    if(ui->tabWidget->widget(index) == ui->tab_console)
    {
        ui->lineEdit->setFocus();
    }
}

void RPCConsole::on_openDebugLogfileButton_clicked()
{
    GUIUtil::openDebugLogfile();
}

void RPCConsole::scrollToEnd()
{
    QScrollBar *scrollbar = ui->messagesWidget->verticalScrollBar();
    scrollbar->setValue(scrollbar->maximum());
}

void RPCConsole::on_showCLOptionsButton_clicked()
{
    GUIUtil::HelpMessageBox help;
    help.exec();
}
<|endoftext|>


<commit_before>/******************************************************************************
 * Copyright (C) 2018 Kitsune Ral <kitsune-ral@users.sf.net>
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 */

#include "util.h"

#include <QtCore/QRegularExpression>
#include <QtCore/QStandardPaths>
#include <QtCore/QDir>
#include <QtCore/QStringBuilder>

static const auto RegExpOptions =
    QRegularExpression::CaseInsensitiveOption
    | QRegularExpression::OptimizeOnFirstUsageOption
    | QRegularExpression::UseUnicodePropertiesOption;

// Converts all that looks like a URL into HTML links
static void linkifyUrls(QString& htmlEscapedText)
{
    // regexp is originally taken from Konsole (https://github.com/KDE/konsole)
    // full url:
    // protocolname:// or www. followed by anything other than whitespaces,
    // <, >, ' or ", and ends before whitespaces, <, >, ', ", ], !, ), :,
    // comma or dot
    // Note: outer parentheses are a part of C++ raw string delimiters, not of
    // the regex (see http://en.cppreference.com/w/cpp/language/string_literal).
    static const QRegularExpression FullUrlRegExp(QStringLiteral(
            R"(((www\.(?!\.)|[a-z][a-z0-9+.-]*://)(&(?![lg]t;)|[^&\s<>'"])+(&(?![lg]t;)|[^&!,.\s<>'"\]):])))"
        ), RegExpOptions);
    // email address:
    // [word chars, dots or dashes]@[word chars, dots or dashes].[word chars]
    static const QRegularExpression EmailAddressRegExp(QStringLiteral(
            R"((mailto:)?(\b(\w|\.|-)+@(\w|\.|-)+\.\w+\b))"
        ), RegExpOptions);

    // NOTE: htmlEscapedText is already HTML-escaped! No literal <,>,&

    htmlEscapedText.replace(EmailAddressRegExp,
                 QStringLiteral(R"(\1\2)"));
    htmlEscapedText.replace(FullUrlRegExp,
                 QStringLiteral(R"(\1)"));
}

QString QMatrixClient::prettyPrint(const QString& plainText)
{
    auto pt = QStringLiteral("") +
            plainText.toHtmlEscaped() + QStringLiteral("");
    pt.replace('\n', QStringLiteral("
"));

    linkifyUrls(pt);
    return pt;
}

QString QMatrixClient::cacheLocation(const QString& dirName)
{
    const QString cachePath =
        QStandardPaths::writableLocation(QStandardPaths::CacheLocation)
            % '/' % dirName % '/';
    QDir dir;
    if (!dir.exists(cachePath))
        dir.mkpath(cachePath);
    return cachePath;
}

// Tests for function_traits<>

#ifdef Q_CC_CLANG
#pragma clang diagnostic push
#pragma ide diagnostic ignored "OCSimplifyInspection"
#endif
using namespace QMatrixClient;

int f();
static_assert(std::is_same<fn_return_t<decltype(f)>, int>::value,
              "Test fn_return_t<>");

void f1(int);
static_assert(function_traits<decltype(f1)>::arg_number == 1,
              "Test fn_arg_number");

void f2(int, QString);
static_assert(std::is_same<fn_arg_t<decltype(f2), 1>, QString>::value,
              "Test fn_arg_t<>");

struct S { int mf(); };
static_assert(is_callable_v<decltype(&S::mf)>, "Test member function");
static_assert(returns<int, decltype(&S::mf)>(), "Test returns<> with member function");

struct Fo { int operator()(); };
static_assert(is_callable_v<Fo>, "Test is_callable<> with function object");
static_assert(function_traits<Fo>::arg_number == 0, "Test function object");
static_assert(std::is_same<fn_return_t<Fo>, int>::value,
              "Test return type of function object");

struct Fo1 { void operator()(int); };
static_assert(function_traits<Fo1>::arg_number == 1, "Test function object 1");
static_assert(is_callable_v<Fo1>, "Test is_callable<> with function object 1");
static_assert(std::is_same<fn_arg_t<Fo1>, int>(),
              "Test fn_arg_t defaulting to first argument");

static auto l = [] { return 1; };
static_assert(is_callable_v<decltype(l)>, "Test is_callable_v<> with lambda");
static_assert(std::is_same<fn_return_t<decltype(l)>, int>::value,
              "Test fn_return_t<> with lambda");

template <typename T>
struct fn_object
{
    static int smf(double) { return 0; }
};
template <>
struct fn_object<QString>
{
    void operator()(QString);
};
static_assert(is_callable_v<fn_object<QString>>, "Test function object");
static_assert(returns<void, fn_object<QString>>(),
              "Test returns<> with function object");
static_assert(!is_callable_v<fn_object<int>>, "Test non-function object");
// FIXME: These two don't work
//static_assert(is_callable_v<decltype(&fn_object<int>::smf)>,
//              "Test static member function");
//static_assert(returns<int, decltype(&fn_object<int>::smf)>(),
//              "Test returns<> with static member function");

template <typename T>
QString ft(T&&);
static_assert(std::is_same<fn_arg_t<decltype(ft<QString>)>, QString&&>(),
              "Test function templates");

#ifdef Q_CC_CLANG
#pragma clang diagnostic pop
#endif
<commit_msg>Suppress a function_traits<> test with lambdas on MSVC2015<commit_after>/******************************************************************************
 * Copyright (C) 2018 Kitsune Ral <kitsune-ral@users.sf.net>
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 */

#include "util.h"

#include <QtCore/QRegularExpression>
#include <QtCore/QStandardPaths>
#include <QtCore/QDir>
#include <QtCore/QStringBuilder>

static const auto RegExpOptions =
    QRegularExpression::CaseInsensitiveOption
    | QRegularExpression::OptimizeOnFirstUsageOption
    | QRegularExpression::UseUnicodePropertiesOption;

// Converts all that looks like a URL into HTML links
static void linkifyUrls(QString& htmlEscapedText)
{
    // regexp is originally taken from Konsole (https://github.com/KDE/konsole)
    // full url:
    // protocolname:// or www. followed by anything other than whitespaces,
    // <, >, ' or ", and ends before whitespaces, <, >, ', ", ], !, ), :,
    // comma or dot
    // Note: outer parentheses are a part of C++ raw string delimiters, not of
    // the regex (see http://en.cppreference.com/w/cpp/language/string_literal).
    static const QRegularExpression FullUrlRegExp(QStringLiteral(
            R"(((www\.(?!\.)|[a-z][a-z0-9+.-]*://)(&(?![lg]t;)|[^&\s<>'"])+(&(?![lg]t;)|[^&!,.\s<>'"\]):])))"
        ), RegExpOptions);
    // email address:
    // [word chars, dots or dashes]@[word chars, dots or dashes].[word chars]
    static const QRegularExpression EmailAddressRegExp(QStringLiteral(
            R"((mailto:)?(\b(\w|\.|-)+@(\w|\.|-)+\.\w+\b))"
        ), RegExpOptions);

    // NOTE: htmlEscapedText is already HTML-escaped! No literal <,>,&

    htmlEscapedText.replace(EmailAddressRegExp,
                 QStringLiteral(R"(\1\2)"));
    htmlEscapedText.replace(FullUrlRegExp,
                 QStringLiteral(R"(\1)"));
}

QString QMatrixClient::prettyPrint(const QString& plainText)
{
    auto pt = QStringLiteral("") +
            plainText.toHtmlEscaped() + QStringLiteral("");
    pt.replace('\n', QStringLiteral("
"));

    linkifyUrls(pt);
    return pt;
}

QString QMatrixClient::cacheLocation(const QString& dirName)
{
    const QString cachePath =
        QStandardPaths::writableLocation(QStandardPaths::CacheLocation)
            % '/' % dirName % '/';
    QDir dir;
    if (!dir.exists(cachePath))
        dir.mkpath(cachePath);
    return cachePath;
}

// Tests for function_traits<>

#ifdef Q_CC_CLANG
#pragma clang diagnostic push
#pragma ide diagnostic ignored "OCSimplifyInspection"
#endif
using namespace QMatrixClient;

int f();
static_assert(std::is_same<fn_return_t<decltype(f)>, int>::value,
              "Test fn_return_t<>");

void f1(int);
static_assert(function_traits<decltype(f1)>::arg_number == 1,
              "Test fn_arg_number");

void f2(int, QString);
static_assert(std::is_same<fn_arg_t<decltype(f2), 1>, QString>::value,
              "Test fn_arg_t<>");

struct S { int mf(); };
static_assert(is_callable_v<decltype(&S::mf)>, "Test member function");
static_assert(returns<int, decltype(&S::mf)>(), "Test returns<> with member function");

struct Fo { int operator()(); };
static_assert(is_callable_v<Fo>, "Test is_callable<> with function object");
static_assert(function_traits<Fo>::arg_number == 0, "Test function object");
static_assert(std::is_same<fn_return_t<Fo>, int>::value,
              "Test return type of function object");

struct Fo1 { void operator()(int); };
static_assert(function_traits<Fo1>::arg_number == 1, "Test function object 1");
static_assert(is_callable_v<Fo1>, "Test is_callable<> with function object 1");
static_assert(std::is_same<fn_arg_t<Fo1>, int>(),
              "Test fn_arg_t defaulting to first argument");

#if (!defined(_MSC_VER) || _MSC_VER >= 1910)
static auto l = [] { return 1; };
static_assert(is_callable_v<decltype(l)>, "Test is_callable_v<> with lambda");
static_assert(std::is_same<fn_return_t<decltype(l)>, int>::value,
              "Test fn_return_t<> with lambda");
#endif

template <typename T>
struct fn_object
{
    static int smf(double) { return 0; }
};
template <>
struct fn_object<QString>
{
    void operator()(QString);
};
static_assert(is_callable_v<fn_object<QString>>, "Test function object");
static_assert(returns<void, fn_object<QString>>(),
              "Test returns<> with function object");
static_assert(!is_callable_v<fn_object<int>>, "Test non-function object");
// FIXME: These two don't work
//static_assert(is_callable_v<decltype(&fn_object<int>::smf)>,
//              "Test static member function");
//static_assert(returns<int, decltype(&fn_object<int>::smf)>(),
//              "Test returns<> with static member function");

template <typename T>
QString ft(T&&);
static_assert(std::is_same<fn_arg_t<decltype(ft<QString>)>, QString&&>(),
              "Test function templates");

#ifdef Q_CC_CLANG
#pragma clang diagnostic pop
#endif
<|endoftext|>


<commit_before><commit_msg>coverity#708898 Unused pointer value<commit_after><|endoftext|>


<commit_before>/*
 *  Copyright (C) 2007 Austin Robot Technology, Patrick Beeson
 *  Copyright (C) 2009-2012 Austin Robot Technology, Jack O'Quin
 *
 *  License: Modified BSD Software License Agreement
 *
 *  $Id$
 */

/** \file
 *
 *  ROS driver implementation for the Velodyne 3D LIDARs
 */

#include <string>
#include <cmath>

#include <ros/ros.h>
#include <tf/transform_listener.h>
#include <velodyne_msgs/VelodyneScan.h>

#include "driver.h"

namespace velodyne_driver
{

VelodyneDriver::VelodyneDriver(ros::NodeHandle node,
                               ros::NodeHandle private_nh)
{
  // use private node handle to get parameters
  private_nh.param("frame_id", config_.frame_id, std::string("velodyne"));
  std::string tf_prefix = tf::getPrefixParam(private_nh);
  ROS_DEBUG_STREAM("tf_prefix: " << tf_prefix);
  config_.frame_id = tf::resolve(tf_prefix, config_.frame_id);

  // get model name, validate string, determine packet rate
  private_nh.param("model", config_.model, std::string("64E"));
  double packet_rate;                   // packet frequency (Hz)
  if ((config_.model == "64E_S2") ||
      (config_.model == "64E_S2.1"))    // generates 1333312 points per second
    {                                   // 1 packet holds 384 points
      packet_rate = 3472.17;            // 1333312 / 384
    }
  else if (config_.model == "64E")
    {
      packet_rate = 2600.0;
    }
  else if (config_.model == "32E")
    {
      packet_rate = 1808.0;
    }
  else
    {
      ROS_ERROR_STREAM("unknown Velodyne LIDAR model: " << config_.model);
      packet_rate = 2600.0;
    }
  std::string deviceName("Velodyne HDL-" + config_.model);

  private_nh.param("rpm", config_.rpm, 600.0);
  ROS_INFO_STREAM(deviceName << " rotating at " << config_.rpm << " RPM");
  double frequency = (config_.rpm / 60.0);     // expected Hz rate

  // default number of packets for each scan is a single revolution
  // (fractions rounded up)
  config_.npackets = (int) ceil(packet_rate / frequency);
  private_nh.getParam("npackets", config_.npackets);
  ROS_INFO_STREAM("publishing " << config_.npackets << " packets per scan");

  std::string dump_file;
  private_nh.param("pcap", dump_file, std::string(""));

  // initialize diagnostics
  diagnostics_.setHardwareID(deviceName);
  diag_max_freq_ = frequency;
  diag_min_freq_ = frequency;
  ROS_INFO("expected frequency: %.3f (Hz)", frequency);

  using namespace diagnostic_updater;
  diag_topic_.reset(new TopicDiagnostic("velodyne_packets", diagnostics_,
                                        FrequencyStatusParam(&diag_min_freq_,
                                                             &diag_max_freq_,
                                                             0.1, 10),
                                        TimeStampStatusParam()));

  // open Velodyne input device or file
  if (dump_file != "")
    {
      input_.reset(new velodyne_driver::InputPCAP(private_nh,
                                                  packet_rate,
                                                  dump_file));
    }
  else
    {
      input_.reset(new velodyne_driver::InputSocket(private_nh));
    }

  // raw data output topic
  output_ = node.advertise<velodyne_msgs::VelodyneScan>("velodyne_packets", 10);
}

/** poll the device
 *
 *  @returns true unless end of file reached
 */
bool VelodyneDriver::poll(void)
{
  // Allocate a new shared pointer for zero-copy sharing with other nodelets.
  velodyne_msgs::VelodyneScanPtr scan(new velodyne_msgs::VelodyneScan);
  scan->packets.resize(config_.npackets);

  // Since the velodyne delivers data at a very high rate, keep
  // reading and publishing scans as fast as possible.
  for (int i = 0; i < config_.npackets; ++i)
    {
      while (true)
        {
          // keep reading until full packet received
          int rc = input_->getPacket(&scan->packets[i]);
          if (rc == 0) break;       // got a full packet?
          if (rc < 0) return false; // end of file reached?
        }
    }

  // publish message using time of last packet read
  ROS_DEBUG("Publishing a full Velodyne scan.");
  scan->header.stamp = ros::Time(scan->packets[config_.npackets - 1].stamp);
  scan->header.frame_id = config_.frame_id;
  output_.publish(scan);

  // notify diagnostics that a message has been published, updating
  // its status
  diag_topic_->tick(scan->header.stamp);
  diagnostics_.update();

  return true;
}

} // namespace velodyne_driver
<commit_msg>fixed #16 (diagnostic rate for driver)<commit_after>/*
 *  Copyright (C) 2007 Austin Robot Technology, Patrick Beeson
 *  Copyright (C) 2009-2012 Austin Robot Technology, Jack O'Quin
 *
 *  License: Modified BSD Software License Agreement
 *
 *  $Id$
 */

/** \file
 *
 *  ROS driver implementation for the Velodyne 3D LIDARs
 */

#include <string>
#include <cmath>

#include <ros/ros.h>
#include <tf/transform_listener.h>
#include <velodyne_msgs/VelodyneScan.h>

#include "driver.h"

namespace velodyne_driver
{

VelodyneDriver::VelodyneDriver(ros::NodeHandle node,
                               ros::NodeHandle private_nh)
{
  // use private node handle to get parameters
  private_nh.param("frame_id", config_.frame_id, std::string("velodyne"));
  std::string tf_prefix = tf::getPrefixParam(private_nh);
  ROS_DEBUG_STREAM("tf_prefix: " << tf_prefix);
  config_.frame_id = tf::resolve(tf_prefix, config_.frame_id);

  // get model name, validate string, determine packet rate
  private_nh.param("model", config_.model, std::string("64E"));
  double packet_rate;                   // packet frequency (Hz)
  if ((config_.model == "64E_S2") ||
      (config_.model == "64E_S2.1"))    // generates 1333312 points per second
    {                                   // 1 packet holds 384 points
      packet_rate = 3472.17;            // 1333312 / 384
    }
  else if (config_.model == "64E")
    {
      packet_rate = 2600.0;
    }
  else if (config_.model == "32E")
    {
      packet_rate = 1808.0;
    }
  else
    {
      ROS_ERROR_STREAM("unknown Velodyne LIDAR model: " << config_.model);
      packet_rate = 2600.0;
    }
  std::string deviceName("Velodyne HDL-" + config_.model);

  private_nh.param("rpm", config_.rpm, 600.0);
  ROS_INFO_STREAM(deviceName << " rotating at " << config_.rpm << " RPM");
  double frequency = (config_.rpm / 60.0);     // expected Hz rate

  // default number of packets for each scan is a single revolution
  // (fractions rounded up)
  config_.npackets = (int) ceil(packet_rate / frequency);
  private_nh.getParam("npackets", config_.npackets);
  ROS_INFO_STREAM("publishing " << config_.npackets << " packets per scan");

  std::string dump_file;
  private_nh.param("pcap", dump_file, std::string(""));

  // initialize diagnostics
  diagnostics_.setHardwareID(deviceName);
  const double diag_freq = packet_rate/config_.npackets;
  diag_max_freq_ = diag_freq;
  diag_min_freq_ = diag_freq;
  ROS_INFO("expected frequency: %.3f (Hz)", diag_freq);

  using namespace diagnostic_updater;
  diag_topic_.reset(new TopicDiagnostic("velodyne_packets", diagnostics_,
                                        FrequencyStatusParam(&diag_min_freq_,
                                                             &diag_max_freq_,
                                                             0.1, 10),
                                        TimeStampStatusParam()));

  // open Velodyne input device or file
  if (dump_file != "")
    {
      input_.reset(new velodyne_driver::InputPCAP(private_nh,
                                                  packet_rate,
                                                  dump_file));
    }
  else
    {
      input_.reset(new velodyne_driver::InputSocket(private_nh));
    }

  // raw data output topic
  output_ = node.advertise<velodyne_msgs::VelodyneScan>("velodyne_packets", 10);
}

/** poll the device
 *
 *  @returns true unless end of file reached
 */
bool VelodyneDriver::poll(void)
{
  // Allocate a new shared pointer for zero-copy sharing with other nodelets.
  velodyne_msgs::VelodyneScanPtr scan(new velodyne_msgs::VelodyneScan);
  scan->packets.resize(config_.npackets);

  // Since the velodyne delivers data at a very high rate, keep
  // reading and publishing scans as fast as possible.
  for (int i = 0; i < config_.npackets; ++i)
    {
      while (true)
        {
          // keep reading until full packet received
          int rc = input_->getPacket(&scan->packets[i]);
          if (rc == 0) break;       // got a full packet?
          if (rc < 0) return false; // end of file reached?
        }
    }

  // publish message using time of last packet read
  ROS_DEBUG("Publishing a full Velodyne scan.");
  scan->header.stamp = ros::Time(scan->packets[config_.npackets - 1].stamp);
  scan->header.frame_id = config_.frame_id;
  output_.publish(scan);

  // notify diagnostics that a message has been published, updating
  // its status
  diag_topic_->tick(scan->header.stamp);
  diagnostics_.update();

  return true;
}

} // namespace velodyne_driver
<|endoftext|>