<commit_before>#define BOOST_TEST_DYN_LINK
#define BOOST_TEST_MAIN
#define BOOST_TEST_MODULE parse JSON

#include <arpa/inet.h>
#include <boost/test/unit_test.hpp>
#include <sys/uio.h>

#include <cstring>

#include "cJSON.h"
#include "parse.h"
#include "state.h"

static char wrong_json[] =   "{\"id\": 7384,\"method\": add\",\"params\":{\"path\": \"foo/bar/state\",\"value\": 123}}";
static char json_no_method[] = "{\"id\": 7384,\"meth\": \"add\",\"params\":{\"path\": \"foo/bar/state\",\"value\": 123}}";
static char json_no_string_method[] = "{\"id\": 7384,\"method\": 123,\"params\":{\"path\": \"foo/bar/state\",\"value\": 123}}";
static char json_two_method[] = "[{\"id\": 7384,\"method\": \"add\",\"params\":{\"path\": \"foo/bar/state\",\"value\": 123}}, {\"id\": 7384,\"method\": \"add\",\"params\":{\"path\": \"foo/state\",\"value\": 321}}]";
static char json_unsupported_method[] = "{\"id\": 7384,\"method\": \"horst\",\"params\":{\"path\": \"foo/bar/state\",\"value\": 123}}";
static char add_without_path[] = "{\"id\": 7384,\"method\": \"add\",\"params\":{\"value\": 123}}";
static char remove_without_path[] = "{\"id\": 7384,\"method\": \"remove\",\"params\":{\"value\": 123}}";
static char fetch_without_id[] = "{\"id\": 7384,\"method\": \"fetch\",\"params\":{\"path\": {\"startsWith\": \"person\"}}}";
static char correct_fetch[] = "{\"id\": 7384,\"method\": \"fetch\",\"params\":{\"id\": \"123456\",\"path\": {\"startsWith\": \"person\"}}}";
static char path_no_string[] = "{\"id\": 7384,\"method\": \"add\",\"params\":{\"path\": 123,\"value\": 123}}";
static char no_value[] = "{\"id\": 7384,\"method\": \"add\",\"params\":{\"path\": \"foo/bar/state\"}}";
static char no_params[] = "{\"id\": 7384,\"method\": \"add\"}";

static const int ADD_WITHOUT_PATH = 1;
static const int PATH_NO_STRING = 2;
static const int NO_VALUE = 3;
static const int NO_PARAMS = 4;
static const int UNSUPPORTED_METHOD = 5;
static const int REMOVE_WITHOUT_PATH = 6;
static const int FETCH_WITHOUT_ID = 7;
static const int CORRECT_FETCH = 7;

static char readback_buffer[10000];
static char *readback_buffer_ptr = readback_buffer;

extern "C" {

	int fake_read(int fd, void *buf, size_t count)
	{
		return 0;
	}

	int fake_send(int fd, void *buf, size_t count, int flags)
	{
		return 0;
	}

	static int copy_iov(const struct iovec *iov, int iovcnt)
	{
		int count = 0;
		for (int i = 0; i < iovcnt; ++i) {
			memcpy(readback_buffer_ptr, iov[i].iov_base, iov[i].iov_len);
			readback_buffer_ptr += iov[i].iov_len;
			count += iov[i].iov_len;
		}
		return count;
	}

	int fake_writev(int fd, const struct iovec *iov, int iovcnt)
	{
		int count = copy_iov(iov, iovcnt);
		return count;
	}
}

struct F {
	F(int fd)
	{
		create_state_hashtable();
		p = alloc_peer(fd);

		readback_buffer_ptr = readback_buffer;
		std::memset(readback_buffer, 0x00, sizeof(readback_buffer));
	}
	~F()
	{
		free_peer(p);
		delete_state_hashtable();
	}

	struct peer *p;
};

static void check_invalid_message(const char *buffer, int code, const char *message_string)
{
	uint32_t len;
	const char *readback_ptr = buffer;
	memcpy(&len, readback_ptr, sizeof(len));
	len = ntohl(len);
	readback_ptr += sizeof(len);

	const char *end_parse;
	cJSON *root = cJSON_ParseWithOpts(readback_ptr, &end_parse, 0);
	BOOST_CHECK(root != NULL);

	uint32_t parsed_length = end_parse - readback_ptr;
	BOOST_CHECK(parsed_length == len);

	cJSON *error = cJSON_GetObjectItem(root, "error");
	BOOST_REQUIRE(error != NULL);

	cJSON *code_object = cJSON_GetObjectItem(error, "code");
	BOOST_REQUIRE(code_object != NULL);
	BOOST_CHECK(code_object->type == cJSON_Number);
	BOOST_CHECK(code_object->valueint == code);

	cJSON *message = cJSON_GetObjectItem(error, "message");
	BOOST_REQUIRE(message != NULL);
	BOOST_CHECK(message->type == cJSON_String);
	BOOST_CHECK(strcmp(message->valuestring, message_string) == 0);

	cJSON_Delete(root);
}

static void check_invalid_params_message(const char *buffer)
{
	check_invalid_message(buffer, -32602, "Invalid params");
}

static void check_method_not_found_message(const char *buffer)
{
	check_invalid_message(buffer, -32601, "Method not found");
}

static cJSON *create_correct_json()
{
	cJSON *root = cJSON_CreateObject();
	cJSON_AddNumberToObject(root, "id", 7384);
	cJSON_AddStringToObject(root, "method", "add");

	cJSON *params = cJSON_CreateObject();
	cJSON_AddStringToObject(params, "path", "/foo/bar/state/");
	cJSON_AddNumberToObject(params, "value", 123);
	cJSON_AddItemToObject(root, "params", params);
	return root;
}

static void check_invalid_request_message(const char *buffer)
{
	check_invalid_message(buffer, -32600, "Invalid Request");
}

BOOST_AUTO_TEST_CASE(parse_correct_json)
{
	F f(-1);
	cJSON *correct_json = create_correct_json();
	char *unformatted_json = cJSON_PrintUnformatted(correct_json);
	int ret = parse_message(unformatted_json, strlen(unformatted_json), f.p);
	cJSON_free(unformatted_json);
	cJSON_Delete(correct_json);
	BOOST_CHECK(ret == 0);
}

BOOST_AUTO_TEST_CASE(length_too_long)
{
	cJSON *correct_json = create_correct_json();
	char *unformatted_json = cJSON_PrintUnformatted(correct_json);
	int ret = parse_message(unformatted_json, strlen(unformatted_json) + 1, NULL);
	cJSON_free(unformatted_json);
	cJSON_Delete(correct_json);

	BOOST_CHECK(ret == -1);
}

BOOST_AUTO_TEST_CASE(length_too_short)
{
	cJSON *correct_json = create_correct_json();
	char *unformatted_json = cJSON_PrintUnformatted(correct_json);
	int ret = parse_message(unformatted_json, strlen(unformatted_json) -1, NULL);
	cJSON_free(unformatted_json);
	cJSON_Delete(correct_json);

	BOOST_CHECK(ret == -1);
}

BOOST_AUTO_TEST_CASE(two_method)
{
	F f(-1);
	int ret = parse_message(json_two_method, strlen(json_two_method), f.p);
	BOOST_CHECK(ret == 0);
}

BOOST_AUTO_TEST_CASE(wrong_array)
{
	const int numbers[2] = {1,2};
	cJSON *root = cJSON_CreateIntArray(numbers, 2);
	char *unformatted_json = cJSON_PrintUnformatted(root);
	int ret = parse_message(unformatted_json, strlen(unformatted_json), NULL);
	cJSON_free(unformatted_json);
	cJSON_Delete(root);

	BOOST_CHECK(ret == -1);
}

BOOST_AUTO_TEST_CASE(add_without_path_test)
{
	F f(ADD_WITHOUT_PATH);
	int ret = parse_message(add_without_path, strlen(add_without_path), f.p);
	BOOST_CHECK(ret == 0);

	check_invalid_params_message(readback_buffer);
}

BOOST_AUTO_TEST_CASE(path_no_string_test)
{
	F f(PATH_NO_STRING);
	int ret = parse_message(path_no_string, strlen(path_no_string), f.p);
	BOOST_CHECK(ret == 0);

	check_invalid_params_message(readback_buffer);
}

BOOST_AUTO_TEST_CASE(no_value_test)
{
	F f(NO_VALUE);
	int ret = parse_message(no_value, strlen(no_value), f.p);
	BOOST_CHECK(ret == 0);

	check_invalid_params_message(readback_buffer);
}

BOOST_AUTO_TEST_CASE(no_params_test)
{
	F f(NO_PARAMS);
	int ret = parse_message(no_params, strlen(no_params), f.p);
	BOOST_CHECK(ret == 0);

	check_invalid_params_message(readback_buffer);
}

BOOST_AUTO_TEST_CASE(unsupported_method)
{
	F f(UNSUPPORTED_METHOD);
	int ret = parse_message(json_unsupported_method, strlen(json_unsupported_method), f.p);
	BOOST_CHECK(ret == 0);

	check_method_not_found_message(readback_buffer);
}

BOOST_AUTO_TEST_CASE(no_method)
{
	F f(UNSUPPORTED_METHOD);
	int ret = parse_message(json_no_method, strlen(json_no_method), f.p);
	BOOST_CHECK(ret == 0);

	check_invalid_request_message(readback_buffer);
}

BOOST_AUTO_TEST_CASE(no_string_method)
{
	F f(UNSUPPORTED_METHOD);
	int ret = parse_message(json_no_string_method, strlen(json_no_string_method), f.p);
	BOOST_CHECK(ret == 0);

	check_invalid_request_message(readback_buffer);
}

BOOST_AUTO_TEST_CASE(parse_wrong_json)
{
	int ret = parse_message(wrong_json, strlen(wrong_json), NULL);
	BOOST_CHECK(ret == -1);
}

BOOST_AUTO_TEST_CASE(remove_without_path_test)
{
	F f(REMOVE_WITHOUT_PATH);
	int ret = parse_message(remove_without_path, strlen(remove_without_path), f.p);
	BOOST_CHECK(ret == 0);

	check_invalid_params_message(readback_buffer);
}

BOOST_AUTO_TEST_CASE(fetch_without_id_test)
{
	F f(FETCH_WITHOUT_ID);
	int ret = parse_message(fetch_without_id, strlen(fetch_without_id), f.p);
	BOOST_CHECK(ret == 0);

	check_invalid_params_message(readback_buffer);
}

BOOST_AUTO_TEST_CASE(correct_fetch_test)
{
	F f(CORRECT_FETCH);
	int ret = parse_message(correct_fetch, strlen(correct_fetch), f.p);
	BOOST_CHECK(ret == 0);
}
<commit_msg>Fix indentation.<commit_after>#define BOOST_TEST_DYN_LINK
#define BOOST_TEST_MAIN
#define BOOST_TEST_MODULE parse JSON

#include <arpa/inet.h>
#include <boost/test/unit_test.hpp>
#include <sys/uio.h>

#include <cstring>

#include "cJSON.h"
#include "parse.h"
#include "state.h"

static char wrong_json[] =   "{\"id\": 7384,\"method\": add\",\"params\":{\"path\": \"foo/bar/state\",\"value\": 123}}";
static char json_no_method[] = "{\"id\": 7384,\"meth\": \"add\",\"params\":{\"path\": \"foo/bar/state\",\"value\": 123}}";
static char json_no_string_method[] = "{\"id\": 7384,\"method\": 123,\"params\":{\"path\": \"foo/bar/state\",\"value\": 123}}";
static char json_two_method[] = "[{\"id\": 7384,\"method\": \"add\",\"params\":{\"path\": \"foo/bar/state\",\"value\": 123}}, {\"id\": 7384,\"method\": \"add\",\"params\":{\"path\": \"foo/state\",\"value\": 321}}]";
static char json_unsupported_method[] = "{\"id\": 7384,\"method\": \"horst\",\"params\":{\"path\": \"foo/bar/state\",\"value\": 123}}";
static char add_without_path[] = "{\"id\": 7384,\"method\": \"add\",\"params\":{\"value\": 123}}";
static char remove_without_path[] = "{\"id\": 7384,\"method\": \"remove\",\"params\":{\"value\": 123}}";
static char fetch_without_id[] = "{\"id\": 7384,\"method\": \"fetch\",\"params\":{\"path\": {\"startsWith\": \"person\"}}}";
static char correct_fetch[] = "{\"id\": 7384,\"method\": \"fetch\",\"params\":{\"id\": \"123456\",\"path\": {\"startsWith\": \"person\"}}}";
static char path_no_string[] = "{\"id\": 7384,\"method\": \"add\",\"params\":{\"path\": 123,\"value\": 123}}";
static char no_value[] = "{\"id\": 7384,\"method\": \"add\",\"params\":{\"path\": \"foo/bar/state\"}}";
static char no_params[] = "{\"id\": 7384,\"method\": \"add\"}";

static const int ADD_WITHOUT_PATH = 1;
static const int PATH_NO_STRING = 2;
static const int NO_VALUE = 3;
static const int NO_PARAMS = 4;
static const int UNSUPPORTED_METHOD = 5;
static const int REMOVE_WITHOUT_PATH = 6;
static const int FETCH_WITHOUT_ID = 7;
static const int CORRECT_FETCH = 7;

static char readback_buffer[10000];
static char *readback_buffer_ptr = readback_buffer;

extern "C" {

	int fake_read(int fd, void *buf, size_t count)
	{
		return 0;
	}

	int fake_send(int fd, void *buf, size_t count, int flags)
	{
		return 0;
	}

	static int copy_iov(const struct iovec *iov, int iovcnt)
	{
		int count = 0;
		for (int i = 0; i < iovcnt; ++i) {
			memcpy(readback_buffer_ptr, iov[i].iov_base, iov[i].iov_len);
			readback_buffer_ptr += iov[i].iov_len;
			count += iov[i].iov_len;
		}
		return count;
	}

	int fake_writev(int fd, const struct iovec *iov, int iovcnt)
	{
		int count = copy_iov(iov, iovcnt);
		return count;
	}
}

struct F {
	F(int fd)
	{
		create_state_hashtable();
		p = alloc_peer(fd);

		readback_buffer_ptr = readback_buffer;
		std::memset(readback_buffer, 0x00, sizeof(readback_buffer));
	}
	~F()
	{
		free_peer(p);
		delete_state_hashtable();
	}

	struct peer *p;
};

static void check_invalid_message(const char *buffer, int code, const char *message_string)
{
	uint32_t len;
	const char *readback_ptr = buffer;
	memcpy(&len, readback_ptr, sizeof(len));
	len = ntohl(len);
	readback_ptr += sizeof(len);

	const char *end_parse;
	cJSON *root = cJSON_ParseWithOpts(readback_ptr, &end_parse, 0);
	BOOST_CHECK(root != NULL);

	uint32_t parsed_length = end_parse - readback_ptr;
	BOOST_CHECK(parsed_length == len);

	cJSON *error = cJSON_GetObjectItem(root, "error");
	BOOST_REQUIRE(error != NULL);

	cJSON *code_object = cJSON_GetObjectItem(error, "code");
	BOOST_REQUIRE(code_object != NULL);
	BOOST_CHECK(code_object->type == cJSON_Number);
	BOOST_CHECK(code_object->valueint == code);

	cJSON *message = cJSON_GetObjectItem(error, "message");
	BOOST_REQUIRE(message != NULL);
	BOOST_CHECK(message->type == cJSON_String);
	BOOST_CHECK(strcmp(message->valuestring, message_string) == 0);

	cJSON_Delete(root);
}

static void check_invalid_params_message(const char *buffer)
{
	check_invalid_message(buffer, -32602, "Invalid params");
}

static void check_method_not_found_message(const char *buffer)
{
	check_invalid_message(buffer, -32601, "Method not found");
}

static cJSON *create_correct_json()
{
	cJSON *root = cJSON_CreateObject();
	cJSON_AddNumberToObject(root, "id", 7384);
	cJSON_AddStringToObject(root, "method", "add");

	cJSON *params = cJSON_CreateObject();
	cJSON_AddStringToObject(params, "path", "/foo/bar/state/");
	cJSON_AddNumberToObject(params, "value", 123);
	cJSON_AddItemToObject(root, "params", params);
	return root;
}

static void check_invalid_request_message(const char *buffer)
{
	check_invalid_message(buffer, -32600, "Invalid Request");
}

BOOST_AUTO_TEST_CASE(parse_correct_json)
{
	F f(-1);
	cJSON *correct_json = create_correct_json();
	char *unformatted_json = cJSON_PrintUnformatted(correct_json);
	int ret = parse_message(unformatted_json, strlen(unformatted_json), f.p);
	cJSON_free(unformatted_json);
	cJSON_Delete(correct_json);
	BOOST_CHECK(ret == 0);
}

BOOST_AUTO_TEST_CASE(length_too_long)
{
	cJSON *correct_json = create_correct_json();
	char *unformatted_json = cJSON_PrintUnformatted(correct_json);
	int ret = parse_message(unformatted_json, strlen(unformatted_json) + 1, NULL);
	cJSON_free(unformatted_json);
	cJSON_Delete(correct_json);

	BOOST_CHECK(ret == -1);
}

BOOST_AUTO_TEST_CASE(length_too_short)
{
	cJSON *correct_json = create_correct_json();
	char *unformatted_json = cJSON_PrintUnformatted(correct_json);
	int ret = parse_message(unformatted_json, strlen(unformatted_json) - 1, NULL);
	cJSON_free(unformatted_json);
	cJSON_Delete(correct_json);

	BOOST_CHECK(ret == -1);
}

BOOST_AUTO_TEST_CASE(two_method)
{
	F f(-1);
	int ret = parse_message(json_two_method, strlen(json_two_method), f.p);
	BOOST_CHECK(ret == 0);
}

BOOST_AUTO_TEST_CASE(wrong_array)
{
	const int numbers[2] = {1,2};
	cJSON *root = cJSON_CreateIntArray(numbers, 2);
	char *unformatted_json = cJSON_PrintUnformatted(root);
	int ret = parse_message(unformatted_json, strlen(unformatted_json), NULL);
	cJSON_free(unformatted_json);
	cJSON_Delete(root);

	BOOST_CHECK(ret == -1);
}

BOOST_AUTO_TEST_CASE(add_without_path_test)
{
	F f(ADD_WITHOUT_PATH);
	int ret = parse_message(add_without_path, strlen(add_without_path), f.p);
	BOOST_CHECK(ret == 0);

	check_invalid_params_message(readback_buffer);
}

BOOST_AUTO_TEST_CASE(path_no_string_test)
{
	F f(PATH_NO_STRING);
	int ret = parse_message(path_no_string, strlen(path_no_string), f.p);
	BOOST_CHECK(ret == 0);

	check_invalid_params_message(readback_buffer);
}

BOOST_AUTO_TEST_CASE(no_value_test)
{
	F f(NO_VALUE);
	int ret = parse_message(no_value, strlen(no_value), f.p);
	BOOST_CHECK(ret == 0);

	check_invalid_params_message(readback_buffer);
}

BOOST_AUTO_TEST_CASE(no_params_test)
{
	F f(NO_PARAMS);
	int ret = parse_message(no_params, strlen(no_params), f.p);
	BOOST_CHECK(ret == 0);

	check_invalid_params_message(readback_buffer);
}

BOOST_AUTO_TEST_CASE(unsupported_method)
{
	F f(UNSUPPORTED_METHOD);
	int ret = parse_message(json_unsupported_method, strlen(json_unsupported_method), f.p);
	BOOST_CHECK(ret == 0);

	check_method_not_found_message(readback_buffer);
}

BOOST_AUTO_TEST_CASE(no_method)
{
	F f(UNSUPPORTED_METHOD);
	int ret = parse_message(json_no_method, strlen(json_no_method), f.p);
	BOOST_CHECK(ret == 0);

	check_invalid_request_message(readback_buffer);
}

BOOST_AUTO_TEST_CASE(no_string_method)
{
	F f(UNSUPPORTED_METHOD);
	int ret = parse_message(json_no_string_method, strlen(json_no_string_method), f.p);
	BOOST_CHECK(ret == 0);

	check_invalid_request_message(readback_buffer);
}

BOOST_AUTO_TEST_CASE(parse_wrong_json)
{
	int ret = parse_message(wrong_json, strlen(wrong_json), NULL);
	BOOST_CHECK(ret == -1);
}

BOOST_AUTO_TEST_CASE(remove_without_path_test)
{
	F f(REMOVE_WITHOUT_PATH);
	int ret = parse_message(remove_without_path, strlen(remove_without_path), f.p);
	BOOST_CHECK(ret == 0);

	check_invalid_params_message(readback_buffer);
}

BOOST_AUTO_TEST_CASE(fetch_without_id_test)
{
	F f(FETCH_WITHOUT_ID);
	int ret = parse_message(fetch_without_id, strlen(fetch_without_id), f.p);
	BOOST_CHECK(ret == 0);

	check_invalid_params_message(readback_buffer);
}

BOOST_AUTO_TEST_CASE(correct_fetch_test)
{
	F f(CORRECT_FETCH);
	int ret = parse_message(correct_fetch, strlen(correct_fetch), f.p);
	BOOST_CHECK(ret == 0);
}
<|endoftext|>


<commit_before>#pragma once

// pqrs::osx::launchctl v2.0

// (C) Copyright Takayama Fumihiko 2019.
// Distributed under the Boost Software License, Version 1.0.
// (See http://www.boost.org/LICENSE_1_0.txt)

// `pqrs::osx::launchctl` can be used safely in a multi-threaded environment.

#include "launchctl/domain_target.hpp"
#include "launchctl/service_name.hpp"
#include "launchctl/service_path.hpp"
#include "launchctl/service_target.hpp"
#include <type_safe/flag_set.hpp>

namespace pqrs {
namespace osx {
namespace launchctl {
inline void enable(const domain_target& domain_target,
                   const service_name& service_name,
                   const service_path& service_path) {
  auto service_target = make_service_target(domain_target, service_name);

  // If service_path is already bootstrapped and disabled, launchctl bootstrap will fail until it is enabled again.
  // So we should enable it first, and then bootstrap and enable it.

  {
    auto command = (std::stringstream() << "/bin/launchctl enable " << service_target).str();
    system(command.c_str());
  }
  {
    auto command = (std::stringstream() << "/bin/launchctl bootstrap " << domain_target << " " << service_path).str();
    system(command.c_str());
  }
  {
    auto command = (std::stringstream() << "/bin/launchctl enable " << service_target).str();
    system(command.c_str());
  }
}

inline void disable(const domain_target& domain_target,
                    const service_name& service_name,
                    const service_path& service_path) {
  auto service_target = make_service_target(domain_target, service_name);

  {
    auto command = (std::stringstream() << "/bin/launchctl bootout " << domain_target << " " << service_path).str();
    system(command.c_str());
  }
  {
    auto command = (std::stringstream() << "/bin/launchctl disable " << service_target).str();
    system(command.c_str());
  }
}

enum class kickstart_flags {
  kill,
  background,
  _flag_set_size,
};

inline void kickstart(const domain_target& domain_target,
                      const service_name& service_name,
                      type_safe::flag_set<kickstart_flags> flags = type_safe::flag_set<kickstart_flags>()) {
  auto service_target = make_service_target(domain_target, service_name);

  {
    std::stringstream ss;
    ss << "/bin/launchctl kickstart ";
    if (flags & kickstart_flags::kill) {
      ss << " -k ";
    }
    ss << service_target;

    if (flags & kickstart_flags::background) {
      ss << " & ";
    }

    auto command = ss.str();
    system(command.c_str());
  }
}
} // namespace launchctl
} // namespace osx
} // namespace pqrs
<commit_msg>Update vendor/cget<commit_after>#pragma once

// pqrs::osx::launchctl v2.1

// (C) Copyright Takayama Fumihiko 2019.
// Distributed under the Boost Software License, Version 1.0.
// (See http://www.boost.org/LICENSE_1_0.txt)

// `pqrs::osx::launchctl` can be used safely in a multi-threaded environment.

#include "launchctl/domain_target.hpp"
#include "launchctl/service_name.hpp"
#include "launchctl/service_path.hpp"
#include "launchctl/service_target.hpp"
#include <type_safe/flag_set.hpp>

namespace pqrs {
namespace osx {
namespace launchctl {
inline void bootstrap(const domain_target& domain_target,
                      const service_path& service_path) {
  {
    auto command = (std::stringstream() << "/bin/launchctl bootstrap " << domain_target << " " << service_path).str();
    system(command.c_str());
  }
}

inline void bootout(const domain_target& domain_target,
                    const service_path& service_path) {
  {
    auto command = (std::stringstream() << "/bin/launchctl bootout " << domain_target << " " << service_path).str();
    system(command.c_str());
  }
}

inline void enable(const domain_target& domain_target,
                   const service_name& service_name,
                   const service_path& service_path) {
  auto service_target = make_service_target(domain_target, service_name);

  // If service_path is already bootstrapped and disabled, launchctl bootstrap will fail until it is enabled again.
  // So we should enable it first, and then bootstrap and enable it.

  {
    auto command = (std::stringstream() << "/bin/launchctl enable " << service_target).str();
    system(command.c_str());
  }

  bootstrap(domain_target, service_path);

  {
    auto command = (std::stringstream() << "/bin/launchctl enable " << service_target).str();
    system(command.c_str());
  }
}

inline void disable(const domain_target& domain_target,
                    const service_name& service_name,
                    const service_path& service_path) {
  auto service_target = make_service_target(domain_target, service_name);

  bootout(domain_target, service_path);

  {
    auto command = (std::stringstream() << "/bin/launchctl disable " << service_target).str();
    system(command.c_str());
  }
}

enum class kickstart_flags {
  kill,
  background,
  _flag_set_size,
};

inline void kickstart(const domain_target& domain_target,
                      const service_name& service_name,
                      type_safe::flag_set<kickstart_flags> flags = type_safe::flag_set<kickstart_flags>()) {
  auto service_target = make_service_target(domain_target, service_name);

  {
    std::stringstream ss;
    ss << "/bin/launchctl kickstart ";
    if (flags & kickstart_flags::kill) {
      ss << " -k ";
    }
    ss << service_target;

    if (flags & kickstart_flags::background) {
      ss << " & ";
    }

    auto command = ss.str();
    system(command.c_str());
  }
}
} // namespace launchctl
} // namespace osx
} // namespace pqrs
<|endoftext|>


<commit_before>/*************************************************************************
 *
 *  $RCSfile: XMLTextFrameHyperlinkContext.cxx,v $
 *
 *  $Revision: 1.9 $
 *
 *  last change: $Author: obo $ $Date: 2004-09-09 10:48:27 $
 *
 *  The Contents of this file are made available subject to the terms of
 *  either of the following licenses
 *
 *         - GNU Lesser General Public License Version 2.1
 *         - Sun Industry Standards Source License Version 1.1
 *
 *  Sun Microsystems Inc., October, 2000
 *
 *  GNU Lesser General Public License Version 2.1
 *  =============================================
 *  Copyright 2000 by Sun Microsystems, Inc.
 *  901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public
 *  License version 2.1, as published by the Free Software Foundation.
 *
 *  This library is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *  Lesser General Public License for more details.
 *
 *  You should have received a copy of the GNU Lesser General Public
 *  License along with this library; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *  MA  02111-1307  USA
 *
 *
 *  Sun Industry Standards Source License Version 1.1
 *  =================================================
 *  The contents of this file are subject to the Sun Industry Standards
 *  Source License Version 1.1 (the "License"); You may not use this file
 *  except in compliance with the License. You may obtain a copy of the
 *  License at http://www.openoffice.org/license.html.
 *
 *  Software provided under this License is provided on an "AS IS" basis,
 *  WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
 *  WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
 *  MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
 *  See the License for the specific provisions governing your rights and
 *  obligations concerning the Software.
 *
 *  The Initial Developer of the Original Code is: Sun Microsystems, Inc.
 *
 *  Copyright: 2000 by Sun Microsystems, Inc.
 *
 *  All Rights Reserved.
 *
 *  Contributor(s): _______________________________________
 *
 *
 ************************************************************************/

#ifndef _XMLOFF_XMLIMP_HXX
#include "xmlimp.hxx"
#endif
#ifndef _XMLOFF_NMSPMAP_HXX
#include "nmspmap.hxx"
#endif
#ifndef _XMLOFF_XMLNMSPE_HXX
#include "xmlnmspe.hxx"
#endif
#ifndef _XMLOFF_XMLTOKEN_HXX
#include "xmltoken.hxx"
#endif
#ifndef _XMLOFF_XMLUCONV_HXX
#include "xmluconv.hxx"
#endif
#ifndef _XMLTEXTFRAMECONTEXT_HXX
#include "XMLTextFrameContext.hxx"
#endif
#ifndef _XMLTEXTFRAMEHYPERLINKCONTEXT_HXX
#include "XMLTextFrameHyperlinkContext.hxx"
#endif

// OD 2004-04-21 #i26791#
#ifndef _XMLOFF_TXTPARAIMPHINT_HXX
#include <txtparaimphint.hxx>
#endif

using namespace ::rtl;
using namespace ::com::sun::star::uno;
using namespace ::com::sun::star::text;
using namespace ::com::sun::star::xml::sax;
using namespace ::com::sun::star::beans;
using namespace ::xmloff::token;

TYPEINIT1( XMLTextFrameHyperlinkContext, SvXMLImportContext );

XMLTextFrameHyperlinkContext::XMLTextFrameHyperlinkContext(
        SvXMLImport& rImport,
        sal_uInt16 nPrfx, const OUString& rLName,
        const Reference< XAttributeList > & xAttrList,
        TextContentAnchorType eATyp ) :
    SvXMLImportContext( rImport, nPrfx, rLName ),
    eDefaultAnchorType( eATyp ),
    bMap( sal_False )
{
    OUString sShow;
    const SvXMLTokenMap& rTokenMap =
        GetImport().GetTextImport()->GetTextHyperlinkAttrTokenMap();

    sal_Int16 nAttrCount = xAttrList.is() ? xAttrList->getLength() : 0;
    for( sal_Int16 i=0; i < nAttrCount; i++ )
    {
        const OUString& rAttrName = xAttrList->getNameByIndex( i );
        const OUString& rValue = xAttrList->getValueByIndex( i );

        OUString aLocalName;
        sal_uInt16 nPrefix =
            GetImport().GetNamespaceMap().GetKeyByAttrName( rAttrName,
                                                            &aLocalName );
        switch( rTokenMap.Get( nPrefix, aLocalName ) )
        {
        case XML_TOK_TEXT_HYPERLINK_HREF:
            sHRef = GetImport().GetAbsoluteReference( rValue );
            break;
        case XML_TOK_TEXT_HYPERLINK_NAME:
            sName = rValue;
            break;
        case XML_TOK_TEXT_HYPERLINK_TARGET_FRAME:
            sTargetFrameName = rValue;
            break;
        case XML_TOK_TEXT_HYPERLINK_SHOW:
            sShow = rValue;
            break;
        case XML_TOK_TEXT_HYPERLINK_SERVER_MAP:
            {
                sal_Bool bTmp;
                if( rImport.GetMM100UnitConverter().convertBool( bTmp,
                                                                  rValue ) )
                {
                    bMap = bTmp;
                }
            }
            break;
        }
    }

    if( sShow.getLength() && !sTargetFrameName.getLength() )
    {
        if( IsXMLToken( sShow, XML_NEW ) )
            sTargetFrameName =
                    OUString( RTL_CONSTASCII_USTRINGPARAM("_blank" ) );
        else if( IsXMLToken( sShow, XML_REPLACE ) )
            sTargetFrameName =
                    OUString( RTL_CONSTASCII_USTRINGPARAM("_self" ) );
    }
}

XMLTextFrameHyperlinkContext::~XMLTextFrameHyperlinkContext()
{
}

void XMLTextFrameHyperlinkContext::EndElement()
{
}

SvXMLImportContext *XMLTextFrameHyperlinkContext::CreateChildContext(
        sal_uInt16 nPrefix,
        const OUString& rLocalName,
        const Reference< XAttributeList > & xAttrList )
{
    SvXMLImportContext *pContext = 0;
    XMLTextFrameContext *pTextFrameContext = 0;

    if( XML_NAMESPACE_DRAW == nPrefix )
    {
        if( IsXMLToken( rLocalName, XML_FRAME ) )
            pTextFrameContext = new XMLTextFrameContext( GetImport(), nPrefix,
                                                rLocalName, xAttrList,
                                                eDefaultAnchorType );
    }

    if( pTextFrameContext )
    {
        pTextFrameContext->SetHyperlink( sHRef, sName, sTargetFrameName, bMap );
        pContext = pTextFrameContext;
        xFrameContext = pContext;
    }
    else
        pContext = new SvXMLImportContext( GetImport(), nPrefix, rLocalName );

    return pContext;
}

TextContentAnchorType XMLTextFrameHyperlinkContext::GetAnchorType() const
{
    if( xFrameContext.Is() )
    {
        SvXMLImportContext *pContext = &xFrameContext;
        return PTR_CAST( XMLTextFrameContext, pContext ) ->GetAnchorType();
    }
    else
        return eDefaultAnchorType;

}

Reference < XTextContent > XMLTextFrameHyperlinkContext::GetTextContent() const
{
    Reference <XTextContent > xTxt;
    if( xFrameContext.Is() )
    {
        SvXMLImportContext *pContext = &xFrameContext;
        xTxt = PTR_CAST( XMLTextFrameContext, pContext )->GetTextContent();
    }

    return xTxt;
}

// --> OD 2004-08-24 #33242#
Reference < drawing::XShape > XMLTextFrameHyperlinkContext::GetShape() const
{
    Reference < drawing::XShape > xShape;
    if( xFrameContext.Is() )
    {
        SvXMLImportContext *pContext = &xFrameContext;
        xShape = PTR_CAST( XMLTextFrameContext, pContext )->GetShape();
    }

    return xShape;
}
// <--

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

#ifndef _XMLOFF_XMLIMP_HXX
#include "xmlimp.hxx"
#endif
#ifndef _XMLOFF_NMSPMAP_HXX
#include "nmspmap.hxx"
#endif
#ifndef _XMLOFF_XMLNMSPE_HXX
#include "xmlnmspe.hxx"
#endif
#ifndef _XMLOFF_XMLTOKEN_HXX
#include "xmltoken.hxx"
#endif
#ifndef _XMLOFF_XMLUCONV_HXX
#include "xmluconv.hxx"
#endif
#ifndef _XMLTEXTFRAMECONTEXT_HXX
#include "XMLTextFrameContext.hxx"
#endif
#ifndef _XMLTEXTFRAMEHYPERLINKCONTEXT_HXX
#include "XMLTextFrameHyperlinkContext.hxx"
#endif

// OD 2004-04-21 #i26791#
#ifndef _XMLOFF_TXTPARAIMPHINT_HXX
#include <txtparaimphint.hxx>
#endif

using namespace ::rtl;
using namespace ::com::sun::star::uno;
using namespace ::com::sun::star::text;
using namespace ::com::sun::star::xml::sax;
using namespace ::com::sun::star::beans;
using namespace ::xmloff::token;

TYPEINIT1( XMLTextFrameHyperlinkContext, SvXMLImportContext );

XMLTextFrameHyperlinkContext::XMLTextFrameHyperlinkContext(
        SvXMLImport& rImport,
        sal_uInt16 nPrfx, const OUString& rLName,
        const Reference< XAttributeList > & xAttrList,
        TextContentAnchorType eATyp ) :
    SvXMLImportContext( rImport, nPrfx, rLName ),
    eDefaultAnchorType( eATyp ),
    bMap( sal_False )
{
    OUString sShow;
    const SvXMLTokenMap& rTokenMap =
        GetImport().GetTextImport()->GetTextHyperlinkAttrTokenMap();

    sal_Int16 nAttrCount = xAttrList.is() ? xAttrList->getLength() : 0;
    for( sal_Int16 i=0; i < nAttrCount; i++ )
    {
        const OUString& rAttrName = xAttrList->getNameByIndex( i );
        const OUString& rValue = xAttrList->getValueByIndex( i );

        OUString aLocalName;
        sal_uInt16 nPrefix =
            GetImport().GetNamespaceMap().GetKeyByAttrName( rAttrName,
                                                            &aLocalName );
        switch( rTokenMap.Get( nPrefix, aLocalName ) )
        {
        case XML_TOK_TEXT_HYPERLINK_HREF:
            sHRef = GetImport().GetAbsoluteReference( rValue );
            break;
        case XML_TOK_TEXT_HYPERLINK_NAME:
            sName = rValue;
            break;
        case XML_TOK_TEXT_HYPERLINK_TARGET_FRAME:
            sTargetFrameName = rValue;
            break;
        case XML_TOK_TEXT_HYPERLINK_SHOW:
            sShow = rValue;
            break;
        case XML_TOK_TEXT_HYPERLINK_SERVER_MAP:
            {
                sal_Bool bTmp;
                if( rImport.GetMM100UnitConverter().convertBool( bTmp,
                                                                  rValue ) )
                {
                    bMap = bTmp;
                }
            }
            break;
        }
    }

    if( sShow.getLength() && !sTargetFrameName.getLength() )
    {
        if( IsXMLToken( sShow, XML_NEW ) )
            sTargetFrameName =
                    OUString( RTL_CONSTASCII_USTRINGPARAM("_blank" ) );
        else if( IsXMLToken( sShow, XML_REPLACE ) )
            sTargetFrameName =
                    OUString( RTL_CONSTASCII_USTRINGPARAM("_self" ) );
    }
}

XMLTextFrameHyperlinkContext::~XMLTextFrameHyperlinkContext()
{
}

void XMLTextFrameHyperlinkContext::EndElement()
{
}

SvXMLImportContext *XMLTextFrameHyperlinkContext::CreateChildContext(
        sal_uInt16 nPrefix,
        const OUString& rLocalName,
        const Reference< XAttributeList > & xAttrList )
{
    SvXMLImportContext *pContext = 0;
    XMLTextFrameContext *pTextFrameContext = 0;

    if( XML_NAMESPACE_DRAW == nPrefix )
    {
        if( IsXMLToken( rLocalName, XML_FRAME ) )
            pTextFrameContext = new XMLTextFrameContext( GetImport(), nPrefix,
                                                rLocalName, xAttrList,
                                                eDefaultAnchorType );
    }

    if( pTextFrameContext )
    {
        pTextFrameContext->SetHyperlink( sHRef, sName, sTargetFrameName, bMap );
        pContext = pTextFrameContext;
        xFrameContext = pContext;
    }
    else
        pContext = new SvXMLImportContext( GetImport(), nPrefix, rLocalName );

    return pContext;
}

TextContentAnchorType XMLTextFrameHyperlinkContext::GetAnchorType() const
{
    if( xFrameContext.Is() )
    {
        SvXMLImportContext *pContext = &xFrameContext;
        return PTR_CAST( XMLTextFrameContext, pContext ) ->GetAnchorType();
    }
    else
        return eDefaultAnchorType;

}

Reference < XTextContent > XMLTextFrameHyperlinkContext::GetTextContent() const
{
    Reference <XTextContent > xTxt;
    if( xFrameContext.Is() )
    {
        SvXMLImportContext *pContext = &xFrameContext;
        xTxt = PTR_CAST( XMLTextFrameContext, pContext )->GetTextContent();
    }

    return xTxt;
}

// --> OD 2004-08-24 #33242#
Reference < drawing::XShape > XMLTextFrameHyperlinkContext::GetShape() const
{
    Reference < drawing::XShape > xShape;
    if( xFrameContext.Is() )
    {
        SvXMLImportContext *pContext = &xFrameContext;
        xShape = PTR_CAST( XMLTextFrameContext, pContext )->GetShape();
    }

    return xShape;
}
// <--

<|endoftext|>


<commit_before>#ifndef RPGSS_CORE_VEC2_HPP_INCLUDED
#define RPGSS_CORE_VEC2_HPP_INCLUDED

#include <cmath>

#include "../common/types.hpp"

namespace rpgss {
    namespace core {

        template<typename T>
        struct Vec2 {
            T x;
            T y;

            Vec2() : x(0), y(0) { }

            template<typename U>
            Vec2(U x_, U y_) : x(x_), y(y_) { }

            template<typename U>
            Vec2(const U vec[2]) : x(vec[0]), y(vec[1]) { }

            Vec2(const Vec2& that) : x(that.x), y(that.y) { }

            Vec2& operator=(const Vec2& that) {
                x = that.x;
                y = that.y;
                return *this;
            }

            bool operator==(const Vec2& rhs) const {
                return (x == rhs.x && y == rhs.y);
            }

            bool operator!=(const Vec2& rhs) const {
                return !(*this == rhs);
            }

            Vec2 operator+(const Vec2& rhs) {
                return Vec2(x + rhs.x, y + rhs.y);
            }

            Vec2 operator-(const Vec2& rhs) {
                return Vec2(x - rhs.x, y - rhs.y);
            }

            template<typename U>
            Vec2 operator*(U scalar) {
                return Vec2(x * scalar, y * scalar);
            }

            Vec2& operator+=(const Vec2& rhs) {
                x += rhs.x;
                y += rhs.y;
                return *this;
            }

            Vec2& operator-=(const Vec2& rhs) {
                x -= rhs.x;
                y -= rhs.y;
                return *this;
            }

            template<typename U>
            Vec2& operator*=(U scalar) {
                x = (T)(x * scalar);
                y = (T)(y * scalar);
                return *this;
            }

            float len() const {
                return std::sqrt((float)(x * x + y * y));
            }

            T lenSQ() const {
                return x * x + y * y;
            }

            T dot(const Vec2& rhs) const {
                return x * rhs.x + y * rhs.y;
            }

            Vec2& null() {
                x = 0;
                y = 0;
                return *this;
            }

            Vec2& unit() {
                float l = len();
                x = (T)(x / l);
                y = (T)(y / l);
                return *this;
            }

            float distFrom(const Vec2& that) const {
                return Vec2(x - that.x, y - that.y).len();
            }

            T distFromSQ(const Vec2& that) const {
                return Vec2(x - that.x, y - that.y).lenSQ();
            }

            Vec2& rotateBy(float degrees, const Vec2& center = Vec2()) {
                degrees *= 3.14159f / 180.0f;
                float cs = std::cos(degrees);
                float sn = std::sin(degrees);
                T tx = x - center.x;
                T ty = y - center.y;
                x = (T)(tx * cs - ty * sn) + center.x;
                y = (T)(tx * sn + ty * cs) + center.y;
                return *this;
            }

            float getAngle() const {
                if (y == 0) {
                    return x < 0.0f ? 180.0f : 0.0f;
                } else if (x == 0.0f) {
                    return y < 0.0f ? 270.0f : 90.0f;
                }
                if ( y > 0.0f) {
                    if (x > 0.0f) {
                        return (float)(std::atan((float)(y / x)) * (180.0f / 3.14159f));
                    } else {
                        return (float)(180.0f - std::atan((float)(y / -x)) * (180.0f / 3.14159f));
                    }
                } else {
                    if (x > 0.0f) {
                        return (float)(360.0f - std::atan((float)(-y / x)) * (180.0f / 3.14159f));
                    } else {
                        return (float)(180.0f + std::atan((float)(-y / -x)) * (180.0f / 3.14159f));
                    }
                }
            }

            float getAngleWith(const Vec2& that) const {
                float tmp = (float)(x*that.x + y*that.y);
                if (tmp == 0.0f) {
                    return 90.0f;
                }
                tmp = tmp / std::sqrt((float)((x*x + y*y) * (that.x*that.x + that.y*that.y)));
                if (tmp < 0.0f) {
                    tmp = -tmp;
                }
                return (float)(std::atan(std::sqrt(1 - tmp*tmp) / tmp) * (180.0f / 3.14159f));
            }

            bool isBetween(const Vec2& begin, const Vec2& end) const {
                if (begin.x != end.x) {
                    return ((begin.x <= x && x <= end.x) ||
                        (begin.x >= x && x >= end.x));
                } else {
                    return ((begin.y <= y && y <= end.y) ||
                        (begin.y >= y && y >= end.y));
                }
            }

            Vec2 getInterpolated(const Vec2& that, float d) const {
                float inv = 1.0f - d;
                return Vec2((T)(that.x*inv + x*d), (T)(that.y*inv + y*d));
            }

            Vec2& interpolate(const Vec2& a, const Vec2& b, float d)
            {
                x = (T)((float)b.x + ( ( a.x - b.x ) * d ));
                y = (T)((float)b.y + ( ( a.y - b.y ) * d ));
                return *this;
            }

        };

        typedef Vec2<i32> Vec2i;
        typedef Vec2<f32> Vec2f;

    } // namespace core
} // namespace rpgss

#endif // RPGSS_CORE_VEC2_HPP_INCLUDED
<commit_msg>Respect that out y-axis goes down in rotation code.<commit_after>#ifndef RPGSS_CORE_VEC2_HPP_INCLUDED
#define RPGSS_CORE_VEC2_HPP_INCLUDED

#include <cmath>

#include "../common/types.hpp"

namespace rpgss {
    namespace core {

        template<typename T>
        struct Vec2 {
            T x;
            T y;

            Vec2() : x(0), y(0) { }

            template<typename U>
            Vec2(U x_, U y_) : x(x_), y(y_) { }

            template<typename U>
            Vec2(const U vec[2]) : x(vec[0]), y(vec[1]) { }

            Vec2(const Vec2& that) : x(that.x), y(that.y) { }

            Vec2& operator=(const Vec2& that) {
                x = that.x;
                y = that.y;
                return *this;
            }

            bool operator==(const Vec2& rhs) const {
                return (x == rhs.x && y == rhs.y);
            }

            bool operator!=(const Vec2& rhs) const {
                return !(*this == rhs);
            }

            Vec2 operator+(const Vec2& rhs) {
                return Vec2(x + rhs.x, y + rhs.y);
            }

            Vec2 operator-(const Vec2& rhs) {
                return Vec2(x - rhs.x, y - rhs.y);
            }

            template<typename U>
            Vec2 operator*(U scalar) {
                return Vec2(x * scalar, y * scalar);
            }

            Vec2& operator+=(const Vec2& rhs) {
                x += rhs.x;
                y += rhs.y;
                return *this;
            }

            Vec2& operator-=(const Vec2& rhs) {
                x -= rhs.x;
                y -= rhs.y;
                return *this;
            }

            template<typename U>
            Vec2& operator*=(U scalar) {
                x = (T)(x * scalar);
                y = (T)(y * scalar);
                return *this;
            }

            float len() const {
                return std::sqrt((float)(x * x + y * y));
            }

            T lenSQ() const {
                return x * x + y * y;
            }

            T dot(const Vec2& rhs) const {
                return x * rhs.x + y * rhs.y;
            }

            Vec2& null() {
                x = 0;
                y = 0;
                return *this;
            }

            Vec2& unit() {
                float l = len();
                x = (T)(x / l);
                y = (T)(y / l);
                return *this;
            }

            float distFrom(const Vec2& that) const {
                return Vec2(x - that.x, y - that.y).len();
            }

            T distFromSQ(const Vec2& that) const {
                return Vec2(x - that.x, y - that.y).lenSQ();
            }

            Vec2& rotateBy(float degrees, const Vec2& center = Vec2()) {
                degrees *= 3.14159f / 180.0f;

                float cs = std::cos(degrees);
                float sn = std::sin(degrees);

                T tx = x - center.x;
                T ty = y - center.y;

                // this code respects that our y-axis goes down
                // to make it work the other way (y-axis goes up),
                // simply swap the signs inside the parentheses
                x = (T)(tx * cs + ty * sn) + center.x;
                y = (T)(ty * cs - tx * sn) + center.y;

                return *this;
            }

            float getAngle() const {
                if (y == 0) {
                    return x < 0.0f ? 180.0f : 0.0f;
                } else if (x == 0.0f) {
                    return y < 0.0f ? 270.0f : 90.0f;
                }
                if ( y > 0.0f) {
                    if (x > 0.0f) {
                        return (float)(std::atan((float)(y / x)) * (180.0f / 3.14159f));
                    } else {
                        return (float)(180.0f - std::atan((float)(y / -x)) * (180.0f / 3.14159f));
                    }
                } else {
                    if (x > 0.0f) {
                        return (float)(360.0f - std::atan((float)(-y / x)) * (180.0f / 3.14159f));
                    } else {
                        return (float)(180.0f + std::atan((float)(-y / -x)) * (180.0f / 3.14159f));
                    }
                }
            }

            float getAngleWith(const Vec2& that) const {
                float tmp = (float)(x*that.x + y*that.y);
                if (tmp == 0.0f) {
                    return 90.0f;
                }
                tmp = tmp / std::sqrt((float)((x*x + y*y) * (that.x*that.x + that.y*that.y)));
                if (tmp < 0.0f) {
                    tmp = -tmp;
                }
                return (float)(std::atan(std::sqrt(1 - tmp*tmp) / tmp) * (180.0f / 3.14159f));
            }

            bool isBetween(const Vec2& begin, const Vec2& end) const {
                if (begin.x != end.x) {
                    return ((begin.x <= x && x <= end.x) ||
                        (begin.x >= x && x >= end.x));
                } else {
                    return ((begin.y <= y && y <= end.y) ||
                        (begin.y >= y && y >= end.y));
                }
            }

            Vec2 getInterpolated(const Vec2& that, float d) const {
                float inv = 1.0f - d;
                return Vec2((T)(that.x*inv + x*d), (T)(that.y*inv + y*d));
            }

            Vec2& interpolate(const Vec2& a, const Vec2& b, float d)
            {
                x = (T)((float)b.x + ( ( a.x - b.x ) * d ));
                y = (T)((float)b.y + ( ( a.y - b.y ) * d ));
                return *this;
            }

        };

        typedef Vec2<i32> Vec2i;
        typedef Vec2<f32> Vec2f;

    } // namespace core
} // namespace rpgss

#endif // RPGSS_CORE_VEC2_HPP_INCLUDED
<|endoftext|>


<commit_before>// [WriteFile Name=ConfigureSubnetworkTrace, Category=Analysis]
// [Legal]
// Copyright 2020 Esri.

// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
// http://www.apache.org/licenses/LICENSE-2.0

// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// [Legal]

#ifdef PCH_BUILD
#include "pch.hpp"
#endif // PCH_BUILD

#include "ConfigureSubnetworkTrace.h"

#include "CodedValueDomain.h"
#include "TaskWatcher.h"
#include "UtilityAssetGroup.h"
#include "UtilityAssetType.h"
#include "UtilityCategory.h"
#include "UtilityCategoryComparison.h"
#include "UtilityDomainNetwork.h"
#include "UtilityElement.h"
#include "UtilityElementTraceResult.h"
#include "UtilityNetwork.h"
#include "UtilityNetworkDefinition.h"
#include "UtilityNetworkSource.h"
#include "UtilityNetworkTypes.h"
#include "UtilityTerminal.h"
#include "UtilityTerminalConfiguration.h"
#include "UtilityTier.h"
#include "UtilityTraceAndCondition.h"
#include "UtilityTraceConfiguration.h"
#include "UtilityTraceOrCondition.h"
#include "UtilityTraceParameters.h"
#include "UtilityTraceResultListModel.h"
#include "UtilityTraversability.h"

#include <QQmlEngine>
#include <algorithm>

using namespace Esri::ArcGISRuntime;

ConfigureSubnetworkTrace::ConfigureSubnetworkTrace(QObject* parent /* = nullptr */):
  QObject(parent)
{
  m_utilityNetwork = new UtilityNetwork(m_featureLayerUrl, this);

  connect(m_utilityNetwork, &UtilityNetwork::doneLoading, this, &ConfigureSubnetworkTrace::onUtilityNetworkLoaded);

  connect(m_utilityNetwork, &UtilityNetwork::traceCompleted, this, &ConfigureSubnetworkTrace::onTraceCompleted);

  m_utilityNetwork->load();
}

QString ConfigureSubnetworkTrace::expressionToString(UtilityTraceConditionalExpression* expression)
{
  switch (expression->traceConditionType())
  {
    case UtilityTraceConditionType::UtilityNetworkAttributeComparison:
    {
      const UtilityNetworkAttributeComparison* attributeExpression = static_cast<UtilityNetworkAttributeComparison*>(expression);
      const UtilityNetworkAttribute* networkAttribute = attributeExpression->networkAttribute();
      const UtilityNetworkAttribute* otherNetworkAttribute = attributeExpression->otherNetworkAttribute();
      const Domain networkDomain = networkAttribute->domain();
      const QString operatorAsString = comparisonOperatorToString(attributeExpression->comparisonOperator());

      // check if attribute domain is a coded value domain.
      if (!networkDomain.isEmpty() && (networkDomain.domainType() == DomainType::CodedValueDomain))
      {
        const CodedValueDomain codedValueDomain = static_cast<CodedValueDomain>(networkDomain);
        const QList<CodedValue> codedValues = codedValueDomain.codedValues();

        // get the coded value using the value as the index for the list of coded values
        const QString codedValueName = codedValues[attributeExpression->value().toInt()].name();

        return QString("`%1` %2 `%3`").arg(networkAttribute->name(), operatorAsString, codedValueName);
      }
      else
      {
        if (otherNetworkAttribute)
        {
          return QString("`%1` %2 `%3`").arg(networkAttribute->name(), operatorAsString, otherNetworkAttribute->name());
        }
        return QString("`%1` %2 `%3`").arg(networkAttribute->name(), operatorAsString, attributeExpression->value().toString());
      }
    }
    case UtilityTraceConditionType::UtilityCategoryComparison:
    {
      const UtilityCategoryComparison* comparisonExpression = static_cast<UtilityCategoryComparison*>(expression);

      return QString("`%1` %2").arg(comparisonExpression->category()->name(), (comparisonExpression->comparisonOperator() == UtilityCategoryComparisonOperator::Exists) ? "Exists" : "DoesNotExist");
    }
    case UtilityTraceConditionType::UtilityTraceAndCondition:
    {
      const UtilityTraceAndCondition* andExpression = static_cast<UtilityTraceAndCondition*>(expression);

      return QString("(%1) AND\n (%2)").arg(expressionToString(andExpression->leftExpression()), expressionToString(andExpression->rightExpression()));
    }
    case UtilityTraceConditionType::UtilityTraceOrCondition:
    {
      const UtilityTraceOrCondition* orExpression = static_cast<UtilityTraceOrCondition*>(expression);
      return QString("(%1) OR\n (%2)").arg(expressionToString(orExpression->leftExpression()), expressionToString(orExpression->rightExpression()));
    }
    default:
      return QString("Unknown trace conditional expression");
  }
}

QString ConfigureSubnetworkTrace::comparisonOperatorToString(const UtilityAttributeComparisonOperator& comparisonOperator)
{
  switch (comparisonOperator)
  {
    case UtilityAttributeComparisonOperator::Equal:
      return QString("Equal");
    case UtilityAttributeComparisonOperator::NotEqual:
      return QString("NotEqual");
    case UtilityAttributeComparisonOperator::GreaterThan:
      return QString("GreaterThan");
    case UtilityAttributeComparisonOperator::GreaterThanEqual:
      return QString("GreaterThanEqual");
    case UtilityAttributeComparisonOperator::LessThan:
      return QString("LessThan");
    case UtilityAttributeComparisonOperator::LessThanEqual:
      return QString("LessThanEqual");
    case UtilityAttributeComparisonOperator::IncludesTheValues:
      return QString("IncludesTheValues");
    case UtilityAttributeComparisonOperator::DoesNotIncludeTheValues:
      return QString("DoesNotIncludeTheValues");
    case UtilityAttributeComparisonOperator::IncludesAny:
      return QString("IncludesAny");
    case UtilityAttributeComparisonOperator::DoesNotIncludeAny:
      return QString("DoesNotIncludeAny");
    default:
      return QString("Unknown comparison operator");
  }
}

QVariant ConfigureSubnetworkTrace::convertToDataType(const QVariant& value, const Esri::ArcGISRuntime::UtilityNetworkAttributeDataType& dataType)
{
  switch (dataType)
  {
    case UtilityNetworkAttributeDataType::Integer:
    {
      return static_cast<int>(value.toDouble());
    }
    case UtilityNetworkAttributeDataType::Float:
    {
      return value.toFloat();
    }
    case UtilityNetworkAttributeDataType::Double:
    {
      return value.toDouble();
    }
    case UtilityNetworkAttributeDataType::Boolean:
    {
      return value.toBool();
    }
    default:
      return QVariant();
  }
}

void ConfigureSubnetworkTrace::codedValueOrInputText(const QString& currentText)
{
  // Update the UI to show the correct value entry for the attribute.
  if (m_networkDefinition)
  {
    const Domain domain = m_networkDefinition->networkAttribute(currentText)->domain();
    if (!domain.isEmpty() && (domain.domainType() == DomainType::CodedValueDomain))
    {
      m_valueSelectionListModel.clear();
      const CodedValueDomain codedValueDomain = static_cast<CodedValueDomain>(domain);

      for (CodedValue codedValue: codedValueDomain.codedValues())
        m_valueSelectionListModel.append(codedValue.name());

      m_textFieldVisible = false;
    }
    else
    {
      m_textFieldVisible = true;
    }
    emit valueSelectionListModelChanged();
    emit textFieldVisibleChanged();
  }
}

void ConfigureSubnetworkTrace::addCondition(const QString& selectedAttribute, int selectedOperator, const QVariant& selectedValue)
{
  // NOTE: You may also create a UtilityCategoryComparison with UtilityNetworkDefinition.Categories and UtilityCategoryComparisonOperator.

  UtilityNetworkAttribute* selectedNetworkAttribute = m_networkDefinition->networkAttribute(selectedAttribute);
  const QVariant convertedSelectedValue = convertToDataType(selectedValue, selectedNetworkAttribute->dataType());

  if (convertedSelectedValue.isNull())
  {
    m_dialogText = "Unknow network attribute data type";
    emit dialogTextChanged();
    emit showDialog();
    return;
  }

  const UtilityAttributeComparisonOperator selectedOperatorEnum = static_cast<UtilityAttributeComparisonOperator>(selectedOperator);

  // NOTE: You may also create a UtilityNetworkAttributeComparison with another NetworkAttribute.
  UtilityTraceConditionalExpression* expression = new UtilityNetworkAttributeComparison(selectedNetworkAttribute, selectedOperatorEnum, convertedSelectedValue, this);

  UtilityTraceConditionalExpression* otherExpression = static_cast<UtilityTraceConditionalExpression*>(m_traceConfiguration->traversability()->barriers());

  // NOTE: You may also combine expressions with UtilityTraceAndCondition
  UtilityTraceConditionalExpression* combineExpressions = new UtilityTraceOrCondition(otherExpression, expression, this);

  m_expressionBuilder = expressionToString(combineExpressions);
  emit expressionBuilderChanged();

  m_traceConfiguration->traversability()->setBarriers(combineExpressions);
}

void ConfigureSubnetworkTrace::changeIncludeBarriersState(bool includeBarriers)
{
  m_traceConfiguration->setIncludeBarriers(includeBarriers);
}

void ConfigureSubnetworkTrace::changeIncludeContainersState(bool includeContainers)
{
  m_traceConfiguration->setIncludeContainers(includeContainers);
}

void ConfigureSubnetworkTrace::reset()
{
  // Reset the barrier condition to the initial value.
  m_traceConfiguration->traversability()->setBarriers(m_initialExpression);
  m_expressionBuilder.clear();
  m_expressionBuilder = expressionToString(static_cast<UtilityTraceConditionalExpression*>(m_initialExpression));
  emit expressionBuilderChanged();
}

void ConfigureSubnetworkTrace::trace()
{
  if (!m_utilityNetwork || !m_utilityElementStartingLocation)
  {
    return;
  }

  m_busy = true;
  emit busyChanged();
  const QList<UtilityElement*> startingLocations {m_utilityElementStartingLocation};
  // Create utility trace parameters for the starting location.
  m_traceParams = new UtilityTraceParameters(UtilityTraceType::Subnetwork, startingLocations, this);
  m_traceParams->setTraceConfiguration(m_traceConfiguration);

  // trace the network
  m_utilityNetwork->trace(m_traceParams);
}

void ConfigureSubnetworkTrace::onTraceCompleted()
{
  if (m_utilityNetwork->traceResult()->isEmpty())
  {
    m_dialogText = "No results returned";
    emit dialogTextChanged();
    emit showDialog();
  }
  // Get the first result.
  UtilityTraceResult* result = m_utilityNetwork->traceResult()->at(0);

  const QList<UtilityElement*> elements = static_cast<UtilityElementTraceResult*>(result)->elements(this);

  // Display the number of elements found by the trace.
  m_dialogText = QString("%1 elements found.").arg(elements.length());
  m_busy = false;
  emit dialogTextChanged();
  emit showDialog();
  emit busyChanged();
}

void ConfigureSubnetworkTrace::onUtilityNetworkLoaded(const Error& e)
{
  if (!e.isEmpty())
  {
    m_dialogText = QString("%1 - %2").arg(e.message(), e.additionalMessage());
    m_busy = false;
    emit dialogTextChanged();
    emit showDialog();
    emit busyChanged();
    return;
  }

  m_busy = false;
  emit busyChanged();
  m_networkDefinition = m_utilityNetwork->definition();

  // Build the choice lists for network attribute comparison.
  for (UtilityNetworkAttribute* networkAttribute : m_networkDefinition->networkAttributes())
  {
    if (!networkAttribute->isSystemDefined())
      m_attributeListModel.append(networkAttribute->name());
  }
  emit attributeListModelChanged();

  // Create a default starting location.
  const UtilityNetworkSource* networkSource = m_networkDefinition->networkSource(m_deviceTableName);
  const UtilityAssetGroup* assetGroup = networkSource->assetGroup(m_assetGroupName);
  UtilityAssetType* assetType = assetGroup->assetType(m_assetTypeName);
  m_utilityElementStartingLocation = m_utilityNetwork->createElementWithAssetType(assetType, m_gloabId);

  QList<UtilityTerminal*> terminals = m_utilityElementStartingLocation->assetType()->terminalConfiguration()->terminals();

  // Set the terminal for this location. (For our case, we use the 'Load' terminal.)
  auto terminal = std::find_if(terminals.begin(), terminals.end(), [](UtilityTerminal* terminal)
  {
      return terminal->name() == "Load";
  });

  m_utilityElementStartingLocation->setTerminal(static_cast<UtilityTerminal*>(*terminal));

  // Get a default trace configuration from a tier to update the UI.
  const UtilityDomainNetwork* domainNetwork = m_networkDefinition->domainNetwork(m_domainNetworkName);
  const UtilityTier* utilityTierSource = domainNetwork->tier(m_tierName);

  // Set the trace configuration.
  m_traceConfiguration = utilityTierSource->traceConfiguration();

  m_initialExpression = m_traceConfiguration->traversability()->barriers();

  if (m_initialExpression)
  {
    m_expressionBuilder = expressionToString(static_cast<UtilityTraceConditionalExpression*>(m_initialExpression));
    emit expressionBuilderChanged();
  }

  // Set the traversability scope.
  utilityTierSource->traceConfiguration()->traversability()->setScope(UtilityTraversabilityScope::Junctions);
}

ConfigureSubnetworkTrace::~ConfigureSubnetworkTrace() = default;

void ConfigureSubnetworkTrace::init()
{
  qmlRegisterType<ConfigureSubnetworkTrace>("Esri.Samples", 1, 0, "ConfigureSubnetworkTraceSample");
}
<commit_msg>added a comment on why Integer dataType deviated from the other cases.<commit_after>// [WriteFile Name=ConfigureSubnetworkTrace, Category=Analysis]
// [Legal]
// Copyright 2020 Esri.

// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
// http://www.apache.org/licenses/LICENSE-2.0

// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// [Legal]

#ifdef PCH_BUILD
#include "pch.hpp"
#endif // PCH_BUILD

#include "ConfigureSubnetworkTrace.h"

#include "CodedValueDomain.h"
#include "TaskWatcher.h"
#include "UtilityAssetGroup.h"
#include "UtilityAssetType.h"
#include "UtilityCategory.h"
#include "UtilityCategoryComparison.h"
#include "UtilityDomainNetwork.h"
#include "UtilityElement.h"
#include "UtilityElementTraceResult.h"
#include "UtilityNetwork.h"
#include "UtilityNetworkDefinition.h"
#include "UtilityNetworkSource.h"
#include "UtilityNetworkTypes.h"
#include "UtilityTerminal.h"
#include "UtilityTerminalConfiguration.h"
#include "UtilityTier.h"
#include "UtilityTraceAndCondition.h"
#include "UtilityTraceConfiguration.h"
#include "UtilityTraceOrCondition.h"
#include "UtilityTraceParameters.h"
#include "UtilityTraceResultListModel.h"
#include "UtilityTraversability.h"

#include <QQmlEngine>
#include <algorithm>

using namespace Esri::ArcGISRuntime;

ConfigureSubnetworkTrace::ConfigureSubnetworkTrace(QObject* parent /* = nullptr */):
  QObject(parent)
{
  m_utilityNetwork = new UtilityNetwork(m_featureLayerUrl, this);

  connect(m_utilityNetwork, &UtilityNetwork::doneLoading, this, &ConfigureSubnetworkTrace::onUtilityNetworkLoaded);

  connect(m_utilityNetwork, &UtilityNetwork::traceCompleted, this, &ConfigureSubnetworkTrace::onTraceCompleted);

  m_utilityNetwork->load();
}

QString ConfigureSubnetworkTrace::expressionToString(UtilityTraceConditionalExpression* expression)
{
  switch (expression->traceConditionType())
  {
    case UtilityTraceConditionType::UtilityNetworkAttributeComparison:
    {
      const UtilityNetworkAttributeComparison* attributeExpression = static_cast<UtilityNetworkAttributeComparison*>(expression);
      const UtilityNetworkAttribute* networkAttribute = attributeExpression->networkAttribute();
      const UtilityNetworkAttribute* otherNetworkAttribute = attributeExpression->otherNetworkAttribute();
      const Domain networkDomain = networkAttribute->domain();
      const QString operatorAsString = comparisonOperatorToString(attributeExpression->comparisonOperator());

      // check if attribute domain is a coded value domain.
      if (!networkDomain.isEmpty() && (networkDomain.domainType() == DomainType::CodedValueDomain))
      {
        const CodedValueDomain codedValueDomain = static_cast<CodedValueDomain>(networkDomain);
        const QList<CodedValue> codedValues = codedValueDomain.codedValues();

        // get the coded value using the value as the index for the list of coded values
        const QString codedValueName = codedValues[attributeExpression->value().toInt()].name();

        return QString("`%1` %2 `%3`").arg(networkAttribute->name(), operatorAsString, codedValueName);
      }
      else
      {
        if (otherNetworkAttribute)
        {
          return QString("`%1` %2 `%3`").arg(networkAttribute->name(), operatorAsString, otherNetworkAttribute->name());
        }
        return QString("`%1` %2 `%3`").arg(networkAttribute->name(), operatorAsString, attributeExpression->value().toString());
      }
    }
    case UtilityTraceConditionType::UtilityCategoryComparison:
    {
      const UtilityCategoryComparison* comparisonExpression = static_cast<UtilityCategoryComparison*>(expression);

      return QString("`%1` %2").arg(comparisonExpression->category()->name(), (comparisonExpression->comparisonOperator() == UtilityCategoryComparisonOperator::Exists) ? "Exists" : "DoesNotExist");
    }
    case UtilityTraceConditionType::UtilityTraceAndCondition:
    {
      const UtilityTraceAndCondition* andExpression = static_cast<UtilityTraceAndCondition*>(expression);

      return QString("(%1) AND\n (%2)").arg(expressionToString(andExpression->leftExpression()), expressionToString(andExpression->rightExpression()));
    }
    case UtilityTraceConditionType::UtilityTraceOrCondition:
    {
      const UtilityTraceOrCondition* orExpression = static_cast<UtilityTraceOrCondition*>(expression);
      return QString("(%1) OR\n (%2)").arg(expressionToString(orExpression->leftExpression()), expressionToString(orExpression->rightExpression()));
    }
    default:
      return QString("Unknown trace conditional expression");
  }
}

QString ConfigureSubnetworkTrace::comparisonOperatorToString(const UtilityAttributeComparisonOperator& comparisonOperator)
{
  switch (comparisonOperator)
  {
    case UtilityAttributeComparisonOperator::Equal:
      return QString("Equal");
    case UtilityAttributeComparisonOperator::NotEqual:
      return QString("NotEqual");
    case UtilityAttributeComparisonOperator::GreaterThan:
      return QString("GreaterThan");
    case UtilityAttributeComparisonOperator::GreaterThanEqual:
      return QString("GreaterThanEqual");
    case UtilityAttributeComparisonOperator::LessThan:
      return QString("LessThan");
    case UtilityAttributeComparisonOperator::LessThanEqual:
      return QString("LessThanEqual");
    case UtilityAttributeComparisonOperator::IncludesTheValues:
      return QString("IncludesTheValues");
    case UtilityAttributeComparisonOperator::DoesNotIncludeTheValues:
      return QString("DoesNotIncludeTheValues");
    case UtilityAttributeComparisonOperator::IncludesAny:
      return QString("IncludesAny");
    case UtilityAttributeComparisonOperator::DoesNotIncludeAny:
      return QString("DoesNotIncludeAny");
    default:
      return QString("Unknown comparison operator");
  }
}

QVariant ConfigureSubnetworkTrace::convertToDataType(const QVariant& value, const Esri::ArcGISRuntime::UtilityNetworkAttributeDataType& dataType)
{
  switch (dataType)
  {
    case UtilityNetworkAttributeDataType::Integer:
    {
      // inconsistent results when using QVariant.toInt() on a
      // QString that doesn't contain an Integer dataType.
      // e.g. QVariant(QString("123.321")).toInt();
      return static_cast<int>(value.toDouble());
    }
    case UtilityNetworkAttributeDataType::Float:
    {
      return value.toFloat();
    }
    case UtilityNetworkAttributeDataType::Double:
    {
      return value.toDouble();
    }
    case UtilityNetworkAttributeDataType::Boolean:
    {
      return value.toBool();
    }
    default:
      return QVariant();
  }
}

void ConfigureSubnetworkTrace::codedValueOrInputText(const QString& currentText)
{
  // Update the UI to show the correct value entry for the attribute.
  if (m_networkDefinition)
  {
    const Domain domain = m_networkDefinition->networkAttribute(currentText)->domain();
    if (!domain.isEmpty() && (domain.domainType() == DomainType::CodedValueDomain))
    {
      m_valueSelectionListModel.clear();
      const CodedValueDomain codedValueDomain = static_cast<CodedValueDomain>(domain);

      for (CodedValue codedValue: codedValueDomain.codedValues())
        m_valueSelectionListModel.append(codedValue.name());

      m_textFieldVisible = false;
    }
    else
    {
      m_textFieldVisible = true;
    }
    emit valueSelectionListModelChanged();
    emit textFieldVisibleChanged();
  }
}

void ConfigureSubnetworkTrace::addCondition(const QString& selectedAttribute, int selectedOperator, const QVariant& selectedValue)
{
  // NOTE: You may also create a UtilityCategoryComparison with UtilityNetworkDefinition.Categories and UtilityCategoryComparisonOperator.

  UtilityNetworkAttribute* selectedNetworkAttribute = m_networkDefinition->networkAttribute(selectedAttribute);
  const QVariant convertedSelectedValue = convertToDataType(selectedValue, selectedNetworkAttribute->dataType());

  if (convertedSelectedValue.isNull())
  {
    m_dialogText = "Unknow network attribute data type";
    emit dialogTextChanged();
    emit showDialog();
    return;
  }

  const UtilityAttributeComparisonOperator selectedOperatorEnum = static_cast<UtilityAttributeComparisonOperator>(selectedOperator);

  // NOTE: You may also create a UtilityNetworkAttributeComparison with another NetworkAttribute.
  UtilityTraceConditionalExpression* expression = new UtilityNetworkAttributeComparison(selectedNetworkAttribute, selectedOperatorEnum, convertedSelectedValue, this);

  UtilityTraceConditionalExpression* otherExpression = static_cast<UtilityTraceConditionalExpression*>(m_traceConfiguration->traversability()->barriers());

  // NOTE: You may also combine expressions with UtilityTraceAndCondition
  UtilityTraceConditionalExpression* combineExpressions = new UtilityTraceOrCondition(otherExpression, expression, this);

  m_expressionBuilder = expressionToString(combineExpressions);
  emit expressionBuilderChanged();

  m_traceConfiguration->traversability()->setBarriers(combineExpressions);
}

void ConfigureSubnetworkTrace::changeIncludeBarriersState(bool includeBarriers)
{
  m_traceConfiguration->setIncludeBarriers(includeBarriers);
}

void ConfigureSubnetworkTrace::changeIncludeContainersState(bool includeContainers)
{
  m_traceConfiguration->setIncludeContainers(includeContainers);
}

void ConfigureSubnetworkTrace::reset()
{
  // Reset the barrier condition to the initial value.
  m_traceConfiguration->traversability()->setBarriers(m_initialExpression);
  m_expressionBuilder.clear();
  m_expressionBuilder = expressionToString(static_cast<UtilityTraceConditionalExpression*>(m_initialExpression));
  emit expressionBuilderChanged();
}

void ConfigureSubnetworkTrace::trace()
{
  if (!m_utilityNetwork || !m_utilityElementStartingLocation)
  {
    return;
  }

  m_busy = true;
  emit busyChanged();
  const QList<UtilityElement*> startingLocations {m_utilityElementStartingLocation};
  // Create utility trace parameters for the starting location.
  m_traceParams = new UtilityTraceParameters(UtilityTraceType::Subnetwork, startingLocations, this);
  m_traceParams->setTraceConfiguration(m_traceConfiguration);

  // trace the network
  m_utilityNetwork->trace(m_traceParams);
}

void ConfigureSubnetworkTrace::onTraceCompleted()
{
  if (m_utilityNetwork->traceResult()->isEmpty())
  {
    m_dialogText = "No results returned";
    emit dialogTextChanged();
    emit showDialog();
  }
  // Get the first result.
  UtilityTraceResult* result = m_utilityNetwork->traceResult()->at(0);

  const QList<UtilityElement*> elements = static_cast<UtilityElementTraceResult*>(result)->elements(this);

  // Display the number of elements found by the trace.
  m_dialogText = QString("%1 elements found.").arg(elements.length());
  m_busy = false;
  emit dialogTextChanged();
  emit showDialog();
  emit busyChanged();
}

void ConfigureSubnetworkTrace::onUtilityNetworkLoaded(const Error& e)
{
  if (!e.isEmpty())
  {
    m_dialogText = QString("%1 - %2").arg(e.message(), e.additionalMessage());
    m_busy = false;
    emit dialogTextChanged();
    emit showDialog();
    emit busyChanged();
    return;
  }

  m_busy = false;
  emit busyChanged();
  m_networkDefinition = m_utilityNetwork->definition();

  // Build the choice lists for network attribute comparison.
  for (UtilityNetworkAttribute* networkAttribute : m_networkDefinition->networkAttributes())
  {
    if (!networkAttribute->isSystemDefined())
      m_attributeListModel.append(networkAttribute->name());
  }
  emit attributeListModelChanged();

  // Create a default starting location.
  const UtilityNetworkSource* networkSource = m_networkDefinition->networkSource(m_deviceTableName);
  const UtilityAssetGroup* assetGroup = networkSource->assetGroup(m_assetGroupName);
  UtilityAssetType* assetType = assetGroup->assetType(m_assetTypeName);
  m_utilityElementStartingLocation = m_utilityNetwork->createElementWithAssetType(assetType, m_gloabId);

  QList<UtilityTerminal*> terminals = m_utilityElementStartingLocation->assetType()->terminalConfiguration()->terminals();

  // Set the terminal for this location. (For our case, we use the 'Load' terminal.)
  auto terminal = std::find_if(terminals.begin(), terminals.end(), [](UtilityTerminal* terminal)
  {
      return terminal->name() == "Load";
  });

  m_utilityElementStartingLocation->setTerminal(static_cast<UtilityTerminal*>(*terminal));

  // Get a default trace configuration from a tier to update the UI.
  const UtilityDomainNetwork* domainNetwork = m_networkDefinition->domainNetwork(m_domainNetworkName);
  const UtilityTier* utilityTierSource = domainNetwork->tier(m_tierName);

  // Set the trace configuration.
  m_traceConfiguration = utilityTierSource->traceConfiguration();

  m_initialExpression = m_traceConfiguration->traversability()->barriers();

  if (m_initialExpression)
  {
    m_expressionBuilder = expressionToString(static_cast<UtilityTraceConditionalExpression*>(m_initialExpression));
    emit expressionBuilderChanged();
  }

  // Set the traversability scope.
  utilityTierSource->traceConfiguration()->traversability()->setScope(UtilityTraversabilityScope::Junctions);
}

ConfigureSubnetworkTrace::~ConfigureSubnetworkTrace() = default;

void ConfigureSubnetworkTrace::init()
{
  qmlRegisterType<ConfigureSubnetworkTrace>("Esri.Samples", 1, 0, "ConfigureSubnetworkTraceSample");
}
<|endoftext|>


<commit_before>#pragma once
/*
**  Copyright (C) 2012 Aldebaran Robotics
**  See COPYING for the license
*/

#ifndef _QIMESSAGING_DETAILS_TYPE_HXX_
#define _QIMESSAGING_DETAILS_TYPE_HXX_

#include <qi/types.hpp>
#include <cstring>
#include <map>
#include <vector>
#include <list>
#include <boost/mpl/for_each.hpp>
#include <boost/mpl/transform_view.hpp>
#include <boost/type_traits/remove_reference.hpp>
#include <boost/type_traits/add_pointer.hpp>
#include <boost/function_types/parameter_types.hpp>
#include <boost/function_types/result_type.hpp>
#include <boost/function_types/function_type.hpp>
#include <boost/function_types/is_member_pointer.hpp>

#include <qimessaging/typespecialized.hpp>

/* This file contains the default-provided Type specialisations
 *
 */

namespace qi {
  // void
  template<> class TypeImpl<void>: public Type
  {
  public:
    TypeInfo info()
    {
      return typeid(void);
    }
    void* initializeStorage(void*) { return 0;}
    void* ptrFromStorage(void** ) { return 0;}
    void* clone(void*)                       { return 0;}
    void destroy(void* ptr)                  {}
    Kind kind() const { return Void;}
  };

  //reference

  template<typename T> class TypeImpl<T&>
      : public TypeImpl<T> {};

}

namespace qi  {

  namespace detail {
    template<typename T> inline Type* typeOfBackend()
    {
      Type* result = getType(typeid(T));
      if (!result)
      {

        static Type* defaultResult = 0;
        // Is this realy a problem?
        if (!defaultResult)
        qiLogVerbose("qi.meta") << "typeOf request for unregistered type "
          << typeid(T).name();
        if (!defaultResult)
          defaultResult = new TypeImpl<T>();
        result = defaultResult;
      }
      if (typeid(T).name() != result->infoString() && typeid(T)!= typeid(bool))
        qiLogWarning("qi.meta") << "typeOfBackend: type mismatch " << typeid(T).name() << " "
       << result <<" " << result->infoString();
      return result;
    }

    template<typename T> struct TypeOfAdapter
    {
      typedef T type;
    };
    template<typename T> struct TypeOfAdapter<T&>
    {
      typedef typename TypeOfAdapter<T>::type type;
    };
    template<typename T> struct TypeOfAdapter<const T>
    {
      typedef typename TypeOfAdapter<T>::type type;
    };
    template<typename T> struct TypeOfAdapter<T*>
    {
      typedef typename boost::add_pointer<typename boost::remove_const<typename TypeOfAdapter<T>::type>::type>::type type;
    };
  }

  template<typename T> Type* typeOf()
  {
    return detail::typeOfBackend<typename detail::TypeOfAdapter<T>::type>();
  }

  inline Type::Kind Type::kind() const
  {
    return Unknown;
  }

  namespace detail {
    struct signature_function_arg_apply {
      signature_function_arg_apply(std::ostream* val)
        : val(*val)
      {}

      template<typename T> void operator()(T *x) {
        val << qi::typeOf<T>()->signature();
      }

      std::ostream &val;
    };

    template<typename T> struct RawFunctionSignature
    {
      static std::string makeSigreturn()
      {
        typedef typename boost::function_types::result_type<T>::type     ResultType;
        return typeOf<ResultType>()->signature();
      }
      static std::string makeSignature()
      {
        std::stringstream   signature;
        signature << '(';
        typedef typename boost::function_types::parameter_types<T>::type ArgsType;
        boost::mpl::for_each<
          boost::mpl::transform_view<ArgsType,
            boost::add_pointer<
              boost::remove_const<
                boost::remove_reference<boost::mpl::_1>
              >
            >
          >
        >
        (qi::detail::signature_function_arg_apply(&signature));
        signature << ')';
        return signature.str();
      }
    };
    template<typename T> struct MemberFunctionSignature
    {
      static std::string makeSigreturn()
      {
        typedef typename boost::function_types::result_type<T>::type     ResultType;
        return typeOf<ResultType>()->signature();
      }
      static std::string makeSignature()
      {
        // Reconstruct the boost::bind(instance, _1, _2...) signature
        typedef typename boost::function_types::result_type<T>::type     RetType;
        typedef typename boost::function_types::parameter_types<T>::type MemArgsType;
        typedef typename boost::mpl::pop_front< MemArgsType >::type                ArgsType;
        typedef typename boost::mpl::push_front<ArgsType, RetType>::type EffectiveType;
        typedef typename boost::function_types::function_type<EffectiveType>::type type;
        return RawFunctionSignature<type>::makeSignature();
      }
    };
    template<typename T> struct FunctionSignature
    {
      typedef typename  boost::mpl::if_<
        typename boost::function_types::is_member_pointer<T>,
        MemberFunctionSignature<T>,
        RawFunctionSignature<T>
        >::type Backend;
      static std::string signature()
      {
        static std::string result = Backend::makeSignature();
        return result;
      }
      static std::string sigreturn()
      {
        static std::string result = Backend::makeSigreturn();
        return result;
      }
    };
    template<typename T> struct FunctionSignature<boost::function<T> >
    : public FunctionSignature<T> {};

    template<typename T> inline
    std::string functionArgumentsSignature()
    {
      std::stringstream sigs;
      sigs << "(";
      typedef typename boost::function_types::parameter_types<T>::type ArgsType;
      boost::mpl::for_each<
      boost::mpl::transform_view<ArgsType,
      boost::add_pointer<
        boost::remove_const<
        boost::remove_reference<boost::mpl::_1> > > > > (qi::detail::signature_function_arg_apply(&sigs));
      sigs << ")";
      return sigs.str();
    }

    // Bouncer to DefaultAccess or DirectAccess based on type size
    template<typename T>
    class TypeImplMethodsBySize
    {
    public:
      typedef typename boost::mpl::if_c<
        sizeof(T) <= sizeof(void*),
        DefaultTypeImplMethods<T,
                        TypeByValue<T>
                        >,
        DefaultTypeImplMethods<T,
                        TypeByPointer<T>
                        >
                        >::type type;
    };
  }

  template<typename TypeDispatcher> TypeDispatcher& Type::dispatch(const TypeDispatcher & vv, void**storage)
  {
    TypeDispatcher& v = const_cast<TypeDispatcher&>(vv);
    switch(kind())
    {
    case Void:
      v.visitVoid(this);
      break;
    case Unknown:
      v.visitUnknown(this, storage);
      break;
    case Int:
      {
        TypeInt* tint = static_cast<TypeInt*>(this);
        /* Here we assume that '0' is represented by storage=0 in the byValue case.
        */
        v.visitInt(tint, (storage&&*storage)?tint->get(*storage):0, tint->isSigned(), tint->size());
        break;
      }
    case Float:
      {
        TypeFloat* tfloat = static_cast<TypeFloat*>(this);
        v.visitFloat(tfloat, (storage&&*storage)?tfloat->get(*storage):0, tfloat->size());
        break;
      }
    case String:
      {
        TypeString* tstring = static_cast<TypeString*>(this);
        v.visitString(tstring, *storage);
        break;
      }
    case List:
      {
        TypeList* tlist = static_cast<TypeList*>(this);
        v.visitList(GenericList(tlist, *storage));
        break;
      }
    case Map:
      {
        TypeMap * tlist = static_cast<TypeMap *>(this);
        v.visitMap(GenericMap(tlist, *storage));
        break;
      }
    case Object:
      {
        v.visitObject(GenericObject(static_cast<ObjectType*>(this), *storage));
        break;
      }
    case Pointer:
      {
        TypePointer* tpointer = static_cast<TypePointer*>(this);
        v.visitPointer(tpointer, *storage, (storage&&*storage)?tpointer->dereference(*storage):GenericValue());
        break;
      }
    case Tuple:
      {
      TypeTuple* ttuple = static_cast<TypeTuple*>(this);
      v.visitTuple(ttuple, *storage);
      break;
      }
    case Dynamic:
      {
      GenericValue gv;
      if (storage && *storage)
        gv = *(GenericValue*)ptrFromStorage(storage);
      v.visitDynamic(this, gv);
      }
    }
    return v;
  }
}

#include <qimessaging/details/typestring.hxx>
#include <qimessaging/details/typetuple.hxx>

#endif  // _QIMESSAGING_DETAILS_TYPE_HXX_
<commit_msg>FunctionSignature, functionArgumentsSignature: use string not stream, cache result.<commit_after>#pragma once
/*
**  Copyright (C) 2012 Aldebaran Robotics
**  See COPYING for the license
*/

#ifndef _QIMESSAGING_DETAILS_TYPE_HXX_
#define _QIMESSAGING_DETAILS_TYPE_HXX_

#include <qi/types.hpp>
#include <cstring>
#include <map>
#include <vector>
#include <list>
#include <boost/mpl/for_each.hpp>
#include <boost/mpl/transform_view.hpp>
#include <boost/type_traits/remove_reference.hpp>
#include <boost/type_traits/add_pointer.hpp>
#include <boost/function_types/parameter_types.hpp>
#include <boost/function_types/result_type.hpp>
#include <boost/function_types/function_type.hpp>
#include <boost/function_types/is_member_pointer.hpp>

#include <qimessaging/typespecialized.hpp>

/* This file contains the default-provided Type specialisations
 *
 */

namespace qi {
  // void
  template<> class TypeImpl<void>: public Type
  {
  public:
    TypeInfo info()
    {
      return typeid(void);
    }
    void* initializeStorage(void*) { return 0;}
    void* ptrFromStorage(void** ) { return 0;}
    void* clone(void*)                       { return 0;}
    void destroy(void* ptr)                  {}
    Kind kind() const { return Void;}
  };

  //reference

  template<typename T> class TypeImpl<T&>
      : public TypeImpl<T> {};

}

namespace qi  {

  namespace detail {
    template<typename T> inline Type* typeOfBackend()
    {
      Type* result = getType(typeid(T));
      if (!result)
      {

        static Type* defaultResult = 0;
        // Is this realy a problem?
        if (!defaultResult)
        qiLogVerbose("qi.meta") << "typeOf request for unregistered type "
          << typeid(T).name();
        if (!defaultResult)
          defaultResult = new TypeImpl<T>();
        result = defaultResult;
      }
      if (typeid(T).name() != result->infoString() && typeid(T)!= typeid(bool))
        qiLogWarning("qi.meta") << "typeOfBackend: type mismatch " << typeid(T).name() << " "
       << result <<" " << result->infoString();
      return result;
    }

    template<typename T> struct TypeOfAdapter
    {
      typedef T type;
    };
    template<typename T> struct TypeOfAdapter<T&>
    {
      typedef typename TypeOfAdapter<T>::type type;
    };
    template<typename T> struct TypeOfAdapter<const T>
    {
      typedef typename TypeOfAdapter<T>::type type;
    };
    template<typename T> struct TypeOfAdapter<T*>
    {
      typedef typename boost::add_pointer<typename boost::remove_const<typename TypeOfAdapter<T>::type>::type>::type type;
    };
  }

  template<typename T> Type* typeOf()
  {
    return detail::typeOfBackend<typename detail::TypeOfAdapter<T>::type>();
  }

  inline Type::Kind Type::kind() const
  {
    return Unknown;
  }

  namespace detail {
    struct signature_function_arg_apply {
      signature_function_arg_apply(std::string* val)
        : val(*val)
      {}

      template<typename T> void operator()(T *x) {
        val += qi::typeOf<T>()->signature();
      }

      std::string &val;
    };

    template<typename T> struct RawFunctionSignature
    {
      static std::string makeSigreturn()
      {
        typedef typename boost::function_types::result_type<T>::type     ResultType;
        return typeOf<ResultType>()->signature();
      }
      static std::string makeSignature()
      {
        std::string   signature;
        signature += '(';
        typedef typename boost::function_types::parameter_types<T>::type ArgsType;
        boost::mpl::for_each<
          boost::mpl::transform_view<ArgsType,
            boost::add_pointer<
              boost::remove_const<
                boost::remove_reference<boost::mpl::_1>
              >
            >
          >
        >
        (qi::detail::signature_function_arg_apply(&signature));
        signature += ')';
        return signature;
      }
    };
    template<typename T> struct MemberFunctionSignature
    {
      static std::string makeSigreturn()
      {
        typedef typename boost::function_types::result_type<T>::type     ResultType;
        return typeOf<ResultType>()->signature();
      }
      static std::string makeSignature()
      {
        // Reconstruct the boost::bind(instance, _1, _2...) signature
        typedef typename boost::function_types::result_type<T>::type     RetType;
        typedef typename boost::function_types::parameter_types<T>::type MemArgsType;
        typedef typename boost::mpl::pop_front< MemArgsType >::type                ArgsType;
        typedef typename boost::mpl::push_front<ArgsType, RetType>::type EffectiveType;
        typedef typename boost::function_types::function_type<EffectiveType>::type type;
        return RawFunctionSignature<type>::makeSignature();
      }
    };
    template<typename T> struct FunctionSignature
    {
      typedef typename  boost::mpl::if_<
        typename boost::function_types::is_member_pointer<T>,
        MemberFunctionSignature<T>,
        RawFunctionSignature<T>
        >::type Backend;
      static std::string signature()
      {
        static std::string result = Backend::makeSignature();
        return result;
      }
      static std::string sigreturn()
      {
        static std::string result = Backend::makeSigreturn();
        return result;
      }
    };
    template<typename T> struct FunctionSignature<boost::function<T> >
    : public FunctionSignature<T> {};

    template<typename T> inline
    std::string functionArgumentsSignature()
    {
      static bool done = false;
      static std::string sigs;
      if (!done)
      {
        sigs += '(';
        typedef typename boost::function_types::parameter_types<T>::type ArgsType;
        boost::mpl::for_each<
        boost::mpl::transform_view<ArgsType,
        boost::add_pointer<
        boost::remove_const<
        boost::remove_reference<boost::mpl::_1> > > > > (qi::detail::signature_function_arg_apply(&sigs));
        sigs += ')';
        done = true;
      }
      return sigs;
    }

    // Bouncer to DefaultAccess or DirectAccess based on type size
    template<typename T>
    class TypeImplMethodsBySize
    {
    public:
      typedef typename boost::mpl::if_c<
        sizeof(T) <= sizeof(void*),
        DefaultTypeImplMethods<T,
                        TypeByValue<T>
                        >,
        DefaultTypeImplMethods<T,
                        TypeByPointer<T>
                        >
                        >::type type;
    };
  }

  template<typename TypeDispatcher> TypeDispatcher& Type::dispatch(const TypeDispatcher & vv, void**storage)
  {
    TypeDispatcher& v = const_cast<TypeDispatcher&>(vv);
    switch(kind())
    {
    case Void:
      v.visitVoid(this);
      break;
    case Unknown:
      v.visitUnknown(this, storage);
      break;
    case Int:
      {
        TypeInt* tint = static_cast<TypeInt*>(this);
        /* Here we assume that '0' is represented by storage=0 in the byValue case.
        */
        v.visitInt(tint, (storage&&*storage)?tint->get(*storage):0, tint->isSigned(), tint->size());
        break;
      }
    case Float:
      {
        TypeFloat* tfloat = static_cast<TypeFloat*>(this);
        v.visitFloat(tfloat, (storage&&*storage)?tfloat->get(*storage):0, tfloat->size());
        break;
      }
    case String:
      {
        TypeString* tstring = static_cast<TypeString*>(this);
        v.visitString(tstring, *storage);
        break;
      }
    case List:
      {
        TypeList* tlist = static_cast<TypeList*>(this);
        v.visitList(GenericList(tlist, *storage));
        break;
      }
    case Map:
      {
        TypeMap * tlist = static_cast<TypeMap *>(this);
        v.visitMap(GenericMap(tlist, *storage));
        break;
      }
    case Object:
      {
        v.visitObject(GenericObject(static_cast<ObjectType*>(this), *storage));
        break;
      }
    case Pointer:
      {
        TypePointer* tpointer = static_cast<TypePointer*>(this);
        v.visitPointer(tpointer, *storage, (storage&&*storage)?tpointer->dereference(*storage):GenericValue());
        break;
      }
    case Tuple:
      {
      TypeTuple* ttuple = static_cast<TypeTuple*>(this);
      v.visitTuple(ttuple, *storage);
      break;
      }
    case Dynamic:
      {
      GenericValue gv;
      if (storage && *storage)
        gv = *(GenericValue*)ptrFromStorage(storage);
      v.visitDynamic(this, gv);
      }
    }
    return v;
  }
}

#include <qimessaging/details/typestring.hxx>
#include <qimessaging/details/typetuple.hxx>

#endif  // _QIMESSAGING_DETAILS_TYPE_HXX_
<|endoftext|>