<commit_before>/*
 * Copyright 2015-2017 Two Pore Guys, Inc.
 * All rights reserved
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted providing that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 *
 */

#include <stdio.h>
#include <stdbool.h>
#include <glib.h>
#include <rpc/object.h>
#include <rpc/connection.h>
#include <rpc/client.h>
#include <rpc/service.h>
#include <rpc/serializer.h>

static int cmd_tree(int argc, const char *argv[]);
static int cmd_inspect(int argc, const char *argv[]);
static int cmd_call(int argc, const char *argv[]);
static int cmd_get(int argc, const char *argv[]);
static int cmd_set(int argc, const char *argv[]);

static const char *server;
static char **args;
static bool json;
static bool yaml;

static struct {
	const char *name;
	int (*fn)(int argc, const char *argv[]);
} commands[] = {
    { "tree", cmd_tree },
    { "inspect", cmd_inspect },
    { "call", cmd_call },
    { "get", cmd_get },
    { "set", cmd_set },
    { NULL}
};

static GOptionEntry options[] = {
    { "server", 's', 0, G_OPTION_ARG_STRING, &server, "Server URI", NULL },
    { "json", 'j', 0, G_OPTION_ARG_NONE, &json, "JSON output", NULL },
    { "yaml", 'y', 0, G_OPTION_ARG_NONE, &yaml, "YAML output", NULL },
    { G_OPTION_REMAINING, 0, 0, G_OPTION_ARG_STRING_ARRAY, &args, "Command...", NULL },
    { NULL }
};

static rpc_connection_t
connect(void)
{
	rpc_client_t client;

	client = rpc_client_create(server, NULL);
	return (rpc_client_get_connection(client));
}

static int
cmd_tree(int argc, const char *argv[])
{
	rpc_call_t call;
	rpc_object_t tree;
	rpc_connection_t conn;
	int ret = 0;

	tree = rpc_array_create();
	conn = connect();
	call = rpc_connection_call(conn, "/", RPC_DISCOVERABLE_INTERFACE,
	    "get_instances", NULL, NULL);

	for (;;) {
		rpc_call_wait(call);

		switch (rpc_call_status(call)) {
		case RPC_CALL_MORE_AVAILABLE:
			rpc_array_append_stolen_value(tree, rpc_call_result(call));
			rpc_call_continue(call, false);
			break;

		case RPC_CALL_DONE:
			goto done;

		case RPC_CALL_ERROR:
			ret = 1;
			goto error;

		default:
			g_assert_not_reached();
		}
	}

done:
	rpc_array_sort(tree, ^(rpc_object_t o1, rpc_object_t o2) {
		return (g_strcmp0(
		    rpc_dictionary_get_string(o1, "path"),
		    rpc_dictionary_get_string(o2, "path")));
	});

	rpc_array_apply(tree, ^(size_t idx, rpc_object_t i) {
		const char *path;
		const char *descr;

		rpc_object_unpack(i, "{s,s}",
		    "path", &path,
		    "description", &descr);

		printf("%s (%s)\n", path, descr != NULL ? descr : "<none>");
		return ((bool)true);
	});

error:
	rpc_release(tree);
	rpc_call_free(call);
	return (ret);
}

static int
cmd_inspect(int argc, const char *argv[])
{

}

static int
cmd_call(int argc, const char *argv[])
{

}<commit_msg>Implement "rpctool tree" and "rpctool call".<commit_after>/*
 * Copyright 2015-2017 <NAME>, Inc.
 * All rights reserved
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted providing that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 *
 */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdbool.h>
#include <glib.h>
#include <rpc/object.h>
#include <rpc/connection.h>
#include <rpc/client.h>
#include <rpc/service.h>
#include <rpc/serializer.h>

static int cmd_tree(int argc, const char *argv[]);
static int cmd_inspect(int argc, const char *argv[]);
static int cmd_call(int argc, const char *argv[]);
static int cmd_get(int argc, const char *argv[]);
static int cmd_set(int argc, const char *argv[]);

static const char *server;
static char **args;
static bool json;
static bool yaml;

static struct {
	const char *name;
	int (*fn)(int argc, const char *argv[]);
} commands[] = {
	{ "tree", cmd_tree },
	{ "inspect", cmd_inspect },
	{ "call", cmd_call },
	{ "get", cmd_get },
	{ "set", cmd_set },
	{ NULL}
};

static GOptionEntry options[] = {
	{ "server", 's', 0, G_OPTION_ARG_STRING, &server, "Server URI", NULL },
	{ "json", 'j', 0, G_OPTION_ARG_NONE, &json, "JSON output", NULL },
	{ "yaml", 'y', 0, G_OPTION_ARG_NONE, &yaml, "YAML output", NULL },
	{ G_OPTION_REMAINING, 0, 0, G_OPTION_ARG_STRING_ARRAY, &args, "", NULL },
	{ NULL }
};

static rpc_connection_t
connect(void)
{
	rpc_client_t client;
	rpc_object_t error;

	client = rpc_client_create(server, NULL);
	if (client == NULL) {
		error = rpc_get_last_error();
		fprintf(stderr, "Cannot connect: %s\n",
		    rpc_error_get_message(error));
		exit(1);
	}

	return (rpc_client_get_connection(client));
}

static void
output(rpc_object_t obj)
{
	char *str;
	void *frame;
	size_t len;

	if (obj == NULL)
		return;

	if (json) {
		if (rpc_serializer_dump("json", obj, &frame, &len) != 0)
			abort();

		printf("%s\n", (char *)frame);
		g_free(frame);
		return;
	}

	if (yaml) {
		if (rpc_serializer_dump("yaml", obj, &frame, &len) != 0)
			abort();

		printf("%s\n", (char *)frame);
		g_free(frame);
		return;
	}

	str = rpc_copy_description(obj);
	printf("%s\n", str);
	g_free(str);
}

static int
cmd_tree(int argc, const char *argv[])
{
	rpc_call_t call;
	rpc_object_t tree;
	rpc_connection_t conn;
	int ret = 0;

	tree = rpc_array_create();
	conn = connect();
	call = rpc_connection_call(conn, "/", RPC_DISCOVERABLE_INTERFACE,
	    "get_instances", NULL, NULL);

	for (;;) {
		rpc_call_wait(call);

		switch (rpc_call_status(call)) {
		case RPC_CALL_MORE_AVAILABLE:
			rpc_array_append_stolen_value(tree, rpc_call_result(call));
			rpc_call_continue(call, false);
			break;

		case RPC_CALL_DONE:
			goto done;

		case RPC_CALL_ERROR:
			ret = 1;
			goto error;

		default:
			g_assert_not_reached();
		}
	}

done:
	rpc_array_sort(tree, ^(rpc_object_t o1, rpc_object_t o2) {
		return (g_strcmp0(
		    rpc_dictionary_get_string(o1, "path"),
		    rpc_dictionary_get_string(o2, "path")));
	});

	rpc_array_apply(tree, ^(size_t idx, rpc_object_t i) {
		const char *path;
		const char *descr;

		rpc_object_unpack(i, "{s,s}",
		    "path", &path,
		    "description", &descr);

		printf("%s (%s)\n", path, descr != NULL ? descr : "<none>");
		return ((bool)true);
	});

error:
	rpc_release(tree);
	rpc_call_free(call);
	return (ret);
}

static int
cmd_inspect(int argc, const char *argv[])
{

}

static int
cmd_call(int argc, const char *argv[])
{
	rpc_connection_t conn;
	rpc_call_t call;
	rpc_object_t args;
	rpc_object_t error;
	int ret = 0;

	if (argc < 4) {
		fprintf(stderr, "Not enough arguments provided\n");
		return (1);
	}

	args = rpc_serializer_load("json", argv[3], strlen(argv[3]));
	if (args == NULL) {
		error = rpc_get_last_error();
		fprintf(stderr, "Cannot read input: %s\n",
		    rpc_error_get_message(error));
		return (1);
	}

	conn = connect();
	call = rpc_connection_call(conn, argv[0], argv[1], argv[2],
	    NULL, NULL);

	for (;;) {
		rpc_call_wait(call);

		switch (rpc_call_status(call)) {
			case RPC_CALL_MORE_AVAILABLE:
				output(rpc_call_result(call));
				rpc_call_continue(call, false);
				break;

			case RPC_CALL_DONE:
				output(rpc_call_result(call));
				goto done;

			case RPC_CALL_ERROR:
				ret = 1;
				goto error;

			default:
				g_assert_not_reached();
		}
	}

error:
	output(rpc_call_result(call));
done:
	rpc_call_free(call);
	return (0);
}
{'fraction_non_alphanumeric': 0.12884737847590744, 'fraction_numerical': 0.006155805561451921, 'mean_word_length': 4.317720090293454, 'pattern_counts': {'":': 0, '<': 25, '<?xml version=': 0, '>': 24, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '737024', 'n_tokens_mistral': 3557, 'n_tokens_neox': 3263, 'n_words': 998}