<commit_before>/****************************************************************************
** mode2.c *****************************************************************
****************************************************************************
*
* mode2 - shows the pulse/space length of a remote button
*
* Copyright (C) 1998 Trent Piepho <xyzzy@u.washington.edu>
* Copyright (C) 1998 Christoph Bartelmus <lirc@bartelmus.de>
*
*/

#ifdef HAVE_CONFIG_H
# include <config.h>
#endif

#ifdef _CYGWIN_
#define __USE_LINUX_IOCTL_DEFS
#endif

#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include <unistd.h>
#include <fcntl.h>
#include <getopt.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/ioctl.h>
#include <limits.h>
#include <errno.h>
#include <syslog.h>
#include <time.h>
#include <pwd.h>

#include "lirc_private.h"

static char* opt_device = NULL;
static int opt_dmode = 0;
static int t_div = 500;
static unsigned int opt_gap = 10000;
static int opt_raw_access = 0;

static const char* const help =
	"Usage: mode2 [options]\n"
	"\t -d --device=device\tread from given device\n"
	"\t -H --driver=driver\tuse given driver\n"
	"\t -U --plugindir=path\tLoad plugins from path.\n"
	"\t -k --keep-root\t\tkeep root privileges\n"
	"\t -m --mode\t\tenable column display mode\n"
	"\t -r --raw\t\taccess device directly\n"
	"\t -g --gap=time\t\ttreat spaces longer than time as the gap\n"
	"\t -s --scope=time\t'scope like display with time us per char.\n"
	"\t -h --help\t\tdisplay usage summary\n"
	"\t -v --version\t\tdisplay version\n"
	"\t -A --driver-options=key:value[|key:value...]\n"
	"\t\t\t\tSet driver options\n";

static const struct option options[] = {
	{"help",           no_argument,       NULL, 'h'},
	{"version",        no_argument,       NULL, 'v'},
	{"device",         required_argument, NULL, 'd'},
	{"driver",         required_argument, NULL, 'H'},
	{"keep-root",      no_argument,       NULL, 'k'},
	{"mode",           no_argument,       NULL, 'm'},
	{"raw",            no_argument,       NULL, 'r'},
	{"gap",            required_argument, NULL, 'g'},
	{"scope",          required_argument, NULL, 's'},
	{"plugindir",      required_argument, NULL, 'U'},
	{"driver-options", required_argument, NULL, 'A'},
	{0,	           0,		      0,    0  }
};

const char* const MSG_NO_GETMODE =
	"Problems: this device is not a LIRC kernel device (it does not\n"
	"support LIRC_GET_REC_MODE ioctl). This is not necessarily a\n"
	"problem, but mode2 will not work.  If you are using the --raw\n"
	"option you might try using without it and select a driver\n"
	"instead. Otherwise, try using lircd + irw to view the decoded\n"
	"data - this might very well work even if mode2 doesn't.";

static void add_defaults(void)
{
	char level[4];

	snprintf(level, sizeof(level), "%d", lirc_log_defaultlevel());

	const char* const defaults[] = {
		"mode2:driver",	    "default",
		"mode2:lircdfile",  LIRCD,
		"lircd:logfile",    "syslog",
		"lircd:debug",	    level,
		"lircd:plugindir",  PLUGINDIR,
		"lircd:configfile", LIRCDCFGFILE,
		(const char*)NULL,  (const char*)NULL
	};
	options_add_defaults(defaults);
}

static void parse_options(int argc, char** argv)
{
	int c;
	static const char* const optstring = "hvd:H:mkrg:s:U:A:";
	char driver[64];

	strcpy(driver, "default");
	add_defaults();
	while ((c = getopt_long(argc, argv, optstring, options, NULL)) != -1) {
		switch (c) {
		case 'h':
			puts(help);
			exit(EXIT_SUCCESS);
		case 'H':
			strncpy(driver, optarg, sizeof(driver) - 1);
			break;
		case 'v':
			printf("%s %s\n", "mode2 ", VERSION);
			exit(EXIT_SUCCESS);
		case 'U':
			options_set_opt("lircd:plugindir", optarg);
			break;
		case 'k':
			unsetenv("SUDO_USER");
			break;
		case 'd':
			opt_device = optarg;
			break;
		case 's':
			opt_dmode = 2;
			t_div = atoi(optarg);
			break;
		case 'm':
			opt_dmode = 1;
			break;
		case 'r':
			opt_raw_access = 1;
			break;
		case 'g':
			opt_gap = atoi(optarg);
			break;
		case 'A':
			options_set_opt("lircd:driver-options", optarg);
			break;
		default:
			printf("Usage: mode2 [options]\n");
			exit(EXIT_FAILURE);
		}
	}
	if (optind < argc) {
		fputs("Too many arguments\n", stderr);
		exit(EXIT_FAILURE);
	}
	if (opt_raw_access && opt_device == NULL) {
		fprintf(stderr, "The --raw option requires a --device\n");
		exit(EXIT_FAILURE);
	}
	if (hw_choose_driver(driver) != 0) {
		fprintf(stderr, "Driver `%s' not found.", driver);
		fputs(" (Missing -U/--plugins option?)\n", stderr);
		fputs("Available drivers:\n", stderr);
		hw_print_drivers(stderr);
		exit(EXIT_FAILURE);
	}
}

/** Open device using curr_driver->open_func() and curr_driver->init_func().*/
int open_device(int opt_raw_access, const char* device)
{
	struct stat s;

	__u32 mode;
	int fd;
	const char* opt;

	if (opt_raw_access) {
		fd = open(device, O_RDONLY);
		if (fd == -1) {
			device = device ? device : "(Null)";
			perrorf("Error while opening device: %s", device);
			exit(EXIT_FAILURE);
		}
		;
		if ((fstat(fd, &s) != -1) && (S_ISFIFO(s.st_mode))) {
			/* can't do ioctls on a pipe */
		} else if ((fstat(fd, &s) != -1) && (!S_ISCHR(s.st_mode))) {
			fprintf(stderr, "%s is not a character device\n",
				device);
			fputs("Use the -d option to specify device\n",
			      stderr);
			close(fd);
			exit(EXIT_FAILURE);
		} else if (ioctl(fd, LIRC_GET_REC_MODE, &mode) == -1) {
			puts(MSG_NO_GETMODE);
			close(fd);
			exit(EXIT_FAILURE);
		}
	} else {
		curr_driver->open_func(device);
		opt = options_getstring("lircd:driver-options");
		if (opt != NULL)
			if (drv_handle_options(opt) != 0) {
				fprintf(stderr,
				"Cannot set driver (%s) options (%s)\n",
				curr_driver->name, opt);
				exit(EXIT_FAILURE);
			}
		if (!curr_driver->init_func || !curr_driver->init_func()) {
			fprintf(stderr, "Cannot initiate device %s\n",
				curr_driver->device);
			exit(EXIT_FAILURE);
		}
		printf("Using device: %s\n", curr_driver->device);
		fd = curr_driver->fd;   /* please compiler */
		mode = curr_driver->rec_mode;
		if (mode != LIRC_MODE_MODE2) {
			if (strcmp(curr_driver->name, "default") == 0) {
				puts("Please use the --raw option to access "
				     "the device directly instead through\n"
				     "the abstraction layer");
				exit(EXIT_FAILURE);
			} else if (mode != LIRC_MODE_LIRCCODE) {
				puts("Internal error: bad receive mode");
				exit(EXIT_FAILURE);
			}
		}
	}
	if (opt_device && strcmp(opt_device, LIRCD) == 0) {
		fputs("Refusing to connect to lircd socket\n", stderr);
		exit(EXIT_FAILURE);
	}
	printf("Using device: %s\n", curr_driver->device);
	return fd;
}

/** Define loglevel and open the log file. */
static void setup_log(void)
{
	char path[128];
	const char* loglevel;

	loglevel = getenv("LIRC_LOGLEVEL");
	if (loglevel == NULL) {
		loglevel = "LIRC_NOTICE";
	} else if (string2loglevel(loglevel) == LIRC_BADLEVEL) {
		fprintf(stderr, "Bad LIRC_LOGLEVEL: %s\n", loglevel);
		loglevel = "LIRC_NOTICE";
	}
	lirc_log_get_clientlog("mode2", path, sizeof(path));
	lirc_log_set_file(path);
	lirc_log_open("mode2", 1, string2loglevel(loglevel));
}

/** Get the codelength (bits per decoded value) for lirccode data. */
unsigned int get_codelength(int fd, int use_raw_access)
{
	unsigned int code_length;
	int r = 1;

	if (use_raw_access) {
		if (ioctl(fd, LIRC_GET_LENGTH, &code_length) == -1) {
			perror("Could not get code length");
			close(fd);
			exit(EXIT_FAILURE);
		}
		return code_length;
	}
	if (curr_driver->drvctl_func) {
		r = curr_driver->drvctl_func(DRVCTL_GET_RAW_CODELENGTH,
					     &code_length);
	}
	if (r != 0)
		code_length = curr_driver->code_length;
	return code_length;
}

/** Print mode2 data as pulse/space durations, one per line. */
void print_mode2_data(unsigned int data)
{
	static int bitno = 1;

	switch (opt_dmode) {
	case 0:
		printf("%s %u\n", (
			       data & PULSE_BIT) ? "pulse" : "space",
		       (__u32)(data & PULSE_MASK));
		break;
	case 1: {
		/* print output like irrecord raw config file data */
		printf(" %8u", (__u32)data & PULSE_MASK);
		++bitno;
		if (data & PULSE_BIT) {
			if ((bitno & 1) == 0)
				/* not in expected order */
				fputs("-pulse", stdout);
		} else {
			if (bitno & 1)
				/* not in expected order */
				fputs("-space", stdout);
			if (((data & PULSE_MASK) > opt_gap) || (bitno >= 6)) {
				/* real long space or more
				 * than 6 codes, start new line */
				puts("");
				if ((data & PULSE_MASK) > opt_gap)
					puts("");
				bitno = 0;
			}
		}
		break;
	}
	case 2:
		if ((data & PULSE_MASK) > opt_gap) {
			fputs("_\n\n_", stdout);
		} else {
			printf("%.*s",
			       ((data & PULSE_MASK) + t_div / 2) / t_div,
			       (data & PULSE_BIT) ?
			       "------------" : "____________");
		}
		break;
	}
	fflush(stdout);
}

/** Print lirccode data as a decoded value (an integer) per line. */
void print_lirccode_data(char* buffer, size_t count)
{
	size_t i;

	fputs("code: 0x", stdout);
	for (i = 0; i < count; i++)
		printf("%02x", (unsigned char)buffer[i]);
	puts("");
	fflush(stdout);
}

/**
 * Process next button press and print a dump, return boolean OK/FAIL.
 */
int next_press(int fd, int mode, int bytes)
{
	char buffspace[bytes];
	int r;
        union {
		char* buffer;
		lirc_t data;
	} input;

	input.buffer = buffspace;
	if (opt_raw_access || mode != LIRC_MODE_MODE2) {
		r = read(fd, input.buffer, bytes);
		if (r == -1)
			perrorf("read() error on %s", opt_device);
		else if (r != (int)bytes)
			fprintf(stderr, "Partial read %d bytes on %s",
				r, opt_device);
		if (r != (int)bytes)
			return 0;
		if (mode == LIRC_MODE_MODE2)
			print_mode2_data(input.data);
		else
			print_lirccode_data(input.buffer, bytes);
	} else {
		input.data = curr_driver->readdata(0);
		if (input.data == 0) {
			fputs("readdata() failed\n", stderr);
			return 0;
		}
		print_mode2_data(input.data);
	}
	return 1;
}

int main(int argc, char** argv)
{
	int fd;
	__u32 mode;
	size_t bytes = sizeof(lirc_t);
	/**
	 * Was hard coded to 50000 but this is too long, the shortest gap in the
	 * supplied .conf files is 10826, the longest space defined for any one,
	 * zero or header is 7590
	 */
	__u32 code_length;

	hw_choose_driver(NULL);
	options_load(argc, argv, NULL, parse_options);
	setup_log();
	fd = open_device(opt_raw_access, opt_device);
	if (geteuid() == 0)
		drop_root_cli(setuid);
	mode = curr_driver->rec_mode;
	if (mode == LIRC_MODE_LIRCCODE) {
		code_length = get_codelength(fd, opt_raw_access);
		bytes = (code_length + CHAR_BIT - 1) / CHAR_BIT;
	}
	while (next_press(fd, mode, bytes))
		;
	return EXIT_SUCCESS;
}
<commit_msg>mode2: Clean up stdout/stderr output(#142).<commit_after>/****************************************************************************
** mode2.c *****************************************************************
****************************************************************************
*
* mode2 - shows the pulse/space length or decoded values of remote buttons.
*
*
* Copyright (C) 1998 Trent Piepho <xyzzy@u.washington.edu>
* Copyright (C) 1998 Christoph Bartelmus <lirc@bartelmus.de>
*
*/

/*
 * TODO: Close stuff (call curr_driver->close_func(), closing logs)
 * when a terminating signal arrives.
 */

#ifdef HAVE_CONFIG_H
# include <config.h>
#endif

#ifdef _CYGWIN_
#define __USE_LINUX_IOCTL_DEFS
#endif

#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include <unistd.h>
#include <fcntl.h>
#include <getopt.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/ioctl.h>
#include <limits.h>
#include <errno.h>
#include <syslog.h>
#include <time.h>
#include <pwd.h>

#include "lirc_private.h"

static char* opt_device = NULL;
static int opt_dmode = 0;
static int t_div = 500;
static unsigned int opt_gap = 10000;
static int opt_raw_access = 0;

static const char* const help =
	"Usage: mode2 [options]\n"
	"\t -d --device=device\tread from given device\n"
	"\t -H --driver=driver\tuse given driver\n"
	"\t -U --plugindir=path\tLoad plugins from path.\n"
	"\t -k --keep-root\t\tkeep root privileges\n"
	"\t -m --mode\t\tenable column display mode\n"
	"\t -r --raw\t\taccess device directly\n"
	"\t -g --gap=time\t\ttreat spaces longer than time as the gap\n"
	"\t -s --scope=time\t'scope like display with time us per char.\n"
	"\t -h --help\t\tdisplay usage summary\n"
	"\t -v --version\t\tdisplay version\n"
	"\t -A --driver-options=key:value[|key:value...]\n"
	"\t\t\t\tSet driver options\n";

static const struct option options[] = {
	{"help",           no_argument,       NULL, 'h'},
	{"version",        no_argument,       NULL, 'v'},
	{"device",         required_argument, NULL, 'd'},
	{"driver",         required_argument, NULL, 'H'},
	{"keep-root",      no_argument,       NULL, 'k'},
	{"mode",           no_argument,       NULL, 'm'},
	{"raw",            no_argument,       NULL, 'r'},
	{"gap",            required_argument, NULL, 'g'},
	{"scope",          required_argument, NULL, 's'},
	{"plugindir",      required_argument, NULL, 'U'},
	{"driver-options", required_argument, NULL, 'A'},
	{0,	           0,		      0,    0  }
};

const char* const MSG_NO_GETMODE =
"Problems: this device is not a LIRC kernel device (it does not\n"
"support LIRC_GET_REC_MODE ioctl). This is not necessarily a\n"
"problem, but mode2 will not work.  If you are using the --raw\n"
"option you might try using without it and select a driver\n"
"instead. Otherwise, try using lircd + irw to view the decoded\n"
"data - this might very well work even if mode2 doesn't.\n";

const char* const USE_RAW_MSG =
"Please use the --raw option to access the device directly instead"
" through the abstraction layer\n";

static void add_defaults(void)
{
	char level[4];

	snprintf(level, sizeof(level), "%d", lirc_log_defaultlevel());

	const char* const defaults[] = {
		"mode2:driver",	    "default",
		"mode2:lircdfile",  LIRCD,
		"lircd:logfile",    "syslog",
		"lircd:debug",	    level,
		"lircd:plugindir",  PLUGINDIR,
		"lircd:configfile", LIRCDCFGFILE,
		(const char*)NULL,  (const char*)NULL
	};
	options_add_defaults(defaults);
}

static void parse_options(int argc, char** argv)
{
	int c;
	static const char* const optstring = "hvd:H:mkrg:s:U:A:";
	char driver[64];

	strcpy(driver, "default");
	add_defaults();
	while ((c = getopt_long(argc, argv, optstring, options, NULL)) != -1) {
		switch (c) {
		case 'h':
			puts(help);
			exit(EXIT_SUCCESS);
		case 'H':
			strncpy(driver, optarg, sizeof(driver) - 1);
			break;
		case 'v':
			printf("%s %s\n", "mode2 ", VERSION);
			exit(EXIT_SUCCESS);
		case 'U':
			options_set_opt("lircd:plugindir", optarg);
			break;
		case 'k':
			unsetenv("SUDO_USER");
			break;
		case 'd':
			opt_device = optarg;
			break;
		case 's':
			opt_dmode = 2;
			t_div = atoi(optarg);
			break;
		case 'm':
			opt_dmode = 1;
			break;
		case 'r':
			opt_raw_access = 1;
			break;
		case 'g':
			opt_gap = atoi(optarg);
			break;
		case 'A':
			options_set_opt("lircd:driver-options", optarg);
			break;
		default:
			fprintf(stderr, "Usage: mode2 [options]\n");
			exit(EXIT_FAILURE);
		}
	}
	if (optind < argc) {
		fputs("Too many arguments\n", stderr);
		exit(EXIT_FAILURE);
	}
	if (opt_raw_access && opt_device == NULL) {
		fprintf(stderr, "The --raw option requires a --device\n");
		exit(EXIT_FAILURE);
	}
	if (hw_choose_driver(driver) != 0) {
		fprintf(stderr, "Driver `%s' not found.", driver);
		fputs(" (Missing -U/--plugins option?)\n", stderr);
		fputs("Available drivers:\n", stderr);
		hw_print_drivers(stderr);
		exit(EXIT_FAILURE);
	}
}

/** Open device using curr_driver->open_func() and curr_driver->init_func().*/
int open_device(int opt_raw_access, const char* device)
{
	struct stat s;

	__u32 mode;
	int fd;
	const char* opt;

	if (opt_raw_access) {
		fd = open(device, O_RDONLY);
		if (fd == -1) {
			device = device ? device : "(Null)";
			perrorf("Error while opening device: %s", device);
			exit(EXIT_FAILURE);
		}
		;
		if ((fstat(fd, &s) != -1) && (S_ISFIFO(s.st_mode))) {
			/* can't do ioctls on a pipe */
		} else if ((fstat(fd, &s) != -1) && (!S_ISCHR(s.st_mode))) {
			fprintf(stderr, "%s is not a character device\n",
				device);
			fputs("Use the -d option to specify device\n",
			      stderr);
			close(fd);
			exit(EXIT_FAILURE);
		} else if (ioctl(fd, LIRC_GET_REC_MODE, &mode) == -1) {
			fputs(MSG_NO_GETMODE, stderr);
			close(fd);
			exit(EXIT_FAILURE);
		}
	} else {
		curr_driver->open_func(device);
		opt = options_getstring("lircd:driver-options");
		if (opt != NULL)
			if (drv_handle_options(opt) != 0) {
				fprintf(stderr,
				"Cannot set driver (%s) options (%s)\n",
				curr_driver->name, opt);
				exit(EXIT_FAILURE);
			}
		if (!curr_driver->init_func || !curr_driver->init_func()) {
			fprintf(stderr, "Cannot initiate device %s\n",
				curr_driver->device);
			exit(EXIT_FAILURE);
		}
		fprintf(stderr, "Trying device: %s\n", curr_driver->device);
		fd = curr_driver->fd;   /* please compiler */
		mode = curr_driver->rec_mode;
		if (mode != LIRC_MODE_MODE2) {
			if (strcmp(curr_driver->name, "default") == 0) {
				fputs(USE_RAW_MSG, stderr);
				exit(EXIT_FAILURE);
			} else if (mode != LIRC_MODE_LIRCCODE) {
				fputs("Internal error: bad receive mode\n",
				      stderr);
				exit(EXIT_FAILURE);
			}
		}
	}
	if (opt_device && strcmp(opt_device, LIRCD) == 0) {
		fputs("Refusing to connect to lircd socket\n", stderr);
		exit(EXIT_FAILURE);
	}
	fprintf(stderr, "Using device: %s\n", curr_driver->device);
	return fd;
}

/** Define loglevel and open the log file. */
static void setup_log(void)
{
	char path[128];
	const char* loglevel;

	loglevel = getenv("LIRC_LOGLEVEL");
	if (loglevel == NULL) {
		loglevel = "DEBUG";
	} else if (string2loglevel(loglevel) == LIRC_BADLEVEL) {
		fprintf(stderr, "Bad LIRC_LOGLEVEL: %s\n", loglevel);
		loglevel = "DEBUG";
	}
	lirc_log_get_clientlog("mode2", path, sizeof(path));
	lirc_log_set_file(path);
	lirc_log_open("mode2", 1, string2loglevel(loglevel));
}

/** Get the codelength (bits per decoded value) for lirccode data. */
unsigned int get_codelength(int fd, int use_raw_access)
{
	unsigned int code_length;
	int r = 1;

	if (use_raw_access) {
		if (ioctl(fd, LIRC_GET_LENGTH, &code_length) == -1) {
			perror("Could not get code length");
			close(fd);
			exit(EXIT_FAILURE);
		}
		return code_length;
	}
	if (curr_driver->drvctl_func) {
		r = curr_driver->drvctl_func(DRVCTL_GET_RAW_CODELENGTH,
					     &code_length);
	}
	if (r != 0)
		code_length = curr_driver->code_length;
	return code_length;
}

/** Print mode2 data as pulse/space durations, one per line. */
void print_mode2_data(unsigned int data)
{
	static int bitno = 1;

	switch (opt_dmode) {
	case 0:
		printf("%s %u\n", (
			       data & PULSE_BIT) ? "pulse" : "space",
		       (__u32)(data & PULSE_MASK));
		break;
	case 1: {
		/* print output like irrecord raw config file data */
		printf(" %8u", (__u32)data & PULSE_MASK);
		++bitno;
		if (data & PULSE_BIT) {
			if ((bitno & 1) == 0)
				/* not in expected order */
				fputs("-pulse", stdout);
		} else {
			if (bitno & 1)
				/* not in expected order */
				fputs("-space", stdout);
			if (((data & PULSE_MASK) > opt_gap) || (bitno >= 6)) {
				/* real long space or more
				 * than 6 codes, start new line */
				puts("");
				if ((data & PULSE_MASK) > opt_gap)
					puts("");
				bitno = 0;
			}
		}
		break;
	}
	case 2:
		if ((data & PULSE_MASK) > opt_gap) {
			fputs("_\n\n_", stdout);
		} else {
			printf("%.*s",
			       ((data & PULSE_MASK) + t_div / 2) / t_div,
			       (data & PULSE_BIT) ?
			       "------------" : "____________");
		}
		break;
	}
	fflush(stdout);
}

/** Print lirccode data as a decoded value (an integer) per line. */
void print_lirccode_data(char* buffer, size_t count)
{
	size_t i;

	fputs("code: 0x", stdout);
	for (i = 0; i < count; i++)
		printf("%02x", (unsigned char)buffer[i]);
	puts("");
	fflush(stdout);
}

/**
 * Process next button press and print a dump, return boolean OK/FAIL.
 */
int next_press(int fd, int mode, int bytes)
{
	char buffspace[bytes];
	int r;
        union {
		char* buffer;
		lirc_t data;
	} input;

	input.buffer = buffspace;
	if (opt_raw_access || mode != LIRC_MODE_MODE2) {
		r = read(fd, input.buffer, bytes);
		if (r == -1)
			perrorf("read() error on %s", opt_device);
		else if (r != (int)bytes)
			fprintf(stderr, "Partial read %d bytes on %s",
				r, opt_device);
		if (r != (int)bytes)
			return 0;
		if (mode == LIRC_MODE_MODE2)
			print_mode2_data(input.data);
		else
			print_lirccode_data(input.buffer, bytes);
	} else {
		input.data = curr_driver->readdata(0);
		if (input.data == 0) {
			fputs("readdata() failed\n", stderr);
			return 0;
		}
		print_mode2_data(input.data);
	}
	return 1;
}

int main(int argc, char** argv)
{
	int fd;
	__u32 mode;
	size_t bytes = sizeof(lirc_t);
	/**
	 * Was hard coded to 50000 but this is too long, the shortest gap in the
	 * supplied .conf files is 10826, the longest space defined for any one,
	 * zero or header is 7590
	 */
	__u32 code_length;

	hw_choose_driver(NULL);
	options_load(argc, argv, NULL, parse_options);
	setup_log();
	fd = open_device(opt_raw_access, opt_device);
	if (geteuid() == 0)
		drop_root_cli(setuid);
	mode = curr_driver->rec_mode;
	if (mode == LIRC_MODE_LIRCCODE) {
		code_length = get_codelength(fd, opt_raw_access);
		bytes = (code_length + CHAR_BIT - 1) / CHAR_BIT;
	}
	while (next_press(fd, mode, bytes))
		;
	return EXIT_SUCCESS;
}
<|endoftext|>


<commit_before>// Copyright (c) 2008, Google Inc.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
//     * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
//     * 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.
//     * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "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 COPYRIGHT
// OWNER OR CONTRIBUTORS 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 "config.h"

#include "v8_helpers.h"
#include "v8_npobject.h"
#include "v8_np_utils.h"
#include "np_v8object.h"
#include "npruntime_priv.h"
#include "v8_proxy.h"
#include "dom_wrapper_map.h"
#include "HTMLPlugInElement.h"
#include "V8HTMLAppletElement.h"
#include "V8HTMLEmbedElement.h"
#include "V8HTMLObjectElement.h"

using namespace WebCore;

enum InvokeFunctionType {
  INVOKE_METHOD = 1,
  INVOKE_DEFAULT = 2
};

// TODO(mbelshe): need comments.
// Params: holder could be HTMLEmbedElement or NPObject
static v8::Handle<v8::Value> NPObjectInvokeImpl(
    const v8::Arguments& args, InvokeFunctionType func_id) {
  NPObject* npobject;

  // These three types are subtypes of HTMLPlugInElement.
  if (V8HTMLAppletElement::HasInstance(args.Holder()) ||
    V8HTMLEmbedElement::HasInstance(args.Holder()) ||
    V8HTMLObjectElement::HasInstance(args.Holder())) {
    // The holder object is a subtype of HTMLPlugInElement.
    HTMLPlugInElement* imp =
        V8Proxy::DOMWrapperToNode<HTMLPlugInElement>(args.Holder());
    v8::Handle<v8::Object> instance = imp->getInstance();
    npobject = V8Proxy::ToNativeObject<NPObject>(
        V8ClassIndex::NPOBJECT, instance);

  } else {
    // The holder object is not a subtype of HTMLPlugInElement, it
    // must be an NPObject which has three internal fields.
    ASSERT(args.Holder()->InternalFieldCount() == 3);
    npobject = V8Proxy::ToNativeObject<NPObject>(
        V8ClassIndex::NPOBJECT, args.Holder());
  }

  // Verify that our wrapper wasn't using a NPObject which
  // has already been deleted.
  if (!npobject || !_NPN_IsAlive(npobject)) {
    V8Proxy::ThrowError(V8Proxy::REFERENCE_ERROR, "NPObject deleted");
    return v8::Undefined();
  }

  // wrap up parameters
  int argc = args.Length();
  NPVariant* np_args = new NPVariant[argc];

  for (int i = 0; i < argc; i++) {
    ConvertV8ObjectToNPVariant(args[i], npobject, &np_args[i]);
  }

  NPVariant result;
  VOID_TO_NPVARIANT(result);

  switch (func_id) {
    case INVOKE_METHOD:
      if (npobject->_class->invoke) {
        v8::Handle<v8::String> function_name(v8::String::Cast(*args.Data()));
        NPIdentifier ident = GetStringIdentifier(function_name);
        npobject->_class->invoke(npobject, ident, np_args, argc, &result);
      }
      break;
    case INVOKE_DEFAULT:
      if (npobject->_class->invokeDefault) {
        npobject->_class->invokeDefault(npobject, np_args, argc, &result);
      }
      break;
    default:
      break;
  }

  for (int i=0; i < argc; i++) {
    NPN_ReleaseVariantValue(&np_args[i]);
  }
  delete[] np_args;

  // unwrap return values
  v8::Handle<v8::Value> rv = ConvertNPVariantToV8Object(&result, npobject);
  NPN_ReleaseVariantValue(&result);

  return rv;
}

v8::Handle<v8::Value> NPObjectMethodHandler(const v8::Arguments& args) {
  return NPObjectInvokeImpl(args, INVOKE_METHOD);
}

v8::Handle<v8::Value> NPObjectInvokeDefaultHandler(const v8::Arguments& args) {
  return NPObjectInvokeImpl(args, INVOKE_DEFAULT);
}

static void WeakTemplateCallback(v8::Persistent<v8::Value> obj, void* param);

// NPIdentifier is PrivateIdentifier*.
static WeakReferenceMap<PrivateIdentifier, v8::FunctionTemplate> \
    static_template_map(&WeakTemplateCallback);

static void WeakTemplateCallback(v8::Persistent<v8::Value> obj,
                                 void* param) {
  PrivateIdentifier* iden = static_cast<PrivateIdentifier*>(param);
  ASSERT(iden != NULL);
  ASSERT(static_template_map.contains(iden));

  static_template_map.forget(iden);
}

static v8::Handle<v8::Value> NPObjectGetProperty(v8::Local<v8::Object> self,
                                                 NPIdentifier ident,
                                                 v8::Local<v8::Value> key) {
  NPObject* npobject = V8Proxy::ToNativeObject<NPObject>(V8ClassIndex::NPOBJECT,
                                                         self);

  // Verify that our wrapper wasn't using a NPObject which
  // has already been deleted.
  if (!npobject || !_NPN_IsAlive(npobject)) {
    V8Proxy::ThrowError(V8Proxy::REFERENCE_ERROR, "NPObject deleted");
    return v8::Handle<v8::Value>();
  }

  if (npobject->_class->hasProperty &&
      npobject->_class->hasProperty(npobject, ident) &&
      npobject->_class->getProperty) {
    NPVariant result;
    VOID_TO_NPVARIANT(result);
    if (!npobject->_class->getProperty(npobject, ident, &result)) {
      return v8::Handle<v8::Value>();
    }

    v8::Handle<v8::Value> rv = ConvertNPVariantToV8Object(&result, npobject);
    NPN_ReleaseVariantValue(&result);
    return rv;

  } else if (key->IsString() &&
             npobject->_class->hasMethod &&
             npobject->_class->hasMethod(npobject, ident)) {
    PrivateIdentifier* id = static_cast<PrivateIdentifier*>(ident);
    v8::Persistent<v8::FunctionTemplate> desc = static_template_map.get(id);
    // Cache templates using identifier as the key.
    if (desc.IsEmpty()) {
      // Create a new template
      v8::Local<v8::FunctionTemplate> temp = v8::FunctionTemplate::New();
      temp->SetCallHandler(NPObjectMethodHandler, key);
      desc = v8::Persistent<v8::FunctionTemplate>::New(temp);
      static_template_map.set(id, desc);
    }

    // FunctionTemplate caches function for each context.
    v8::Local<v8::Function> func = desc->GetFunction();
    func->SetName(v8::Handle<v8::String>::Cast(key));
    return func;
  }

  return v8::Handle<v8::Value>();
}

v8::Handle<v8::Value> NPObjectNamedPropertyGetter(v8::Local<v8::String> name,
                                                  const v8::AccessorInfo& info) {
  NPIdentifier ident = GetStringIdentifier(name);
  return NPObjectGetProperty(info.Holder(), ident, name);
}

v8::Handle<v8::Value> NPObjectIndexedPropertyGetter(uint32_t index,
                                                    const v8::AccessorInfo& info) {
  NPIdentifier ident = NPN_GetIntIdentifier(index);
  return NPObjectGetProperty(info.Holder(), ident, v8::Number::New(index));
}

v8::Handle<v8::Value> NPObjectGetNamedProperty(v8::Local<v8::Object> self,
                                               v8::Local<v8::String> name) {
  NPIdentifier ident = GetStringIdentifier(name);
  return NPObjectGetProperty(self, ident, name);
}

v8::Handle<v8::Value> NPObjectGetIndexedProperty(v8::Local<v8::Object> self,
                                                 uint32_t index) {
  NPIdentifier ident = NPN_GetIntIdentifier(index);
  return NPObjectGetProperty(self, ident, v8::Number::New(index));
}

static v8::Handle<v8::Value> NPObjectSetProperty(v8::Local<v8::Object> self,
                                                 NPIdentifier ident,
                                                 v8::Local<v8::Value> value) {
  NPObject* npobject =
    V8Proxy::ToNativeObject<NPObject>(V8ClassIndex::NPOBJECT, self);

  // Verify that our wrapper wasn't using a NPObject which
  // has already been deleted.
  if (!npobject || !_NPN_IsAlive(npobject)) {
    V8Proxy::ThrowError(V8Proxy::REFERENCE_ERROR, "NPObject deleted");
    return value;  // intercepted, but an exception was thrown
  }

  if (npobject->_class->hasProperty &&
      npobject->_class->hasProperty(npobject, ident) &&
      npobject->_class->setProperty) {
    NPVariant npvalue;
    VOID_TO_NPVARIANT(npvalue);
    ConvertV8ObjectToNPVariant(value, npobject, &npvalue);
    bool succ = npobject->_class->setProperty(npobject, ident, &npvalue);
    NPN_ReleaseVariantValue(&npvalue);
    if (succ) return value;  // intercept the call
  }
  return v8::Local<v8::Value>();  // do not intercept the call
}

v8::Handle<v8::Value> NPObjectNamedPropertySetter(v8::Local<v8::String> name,
                                                  v8::Local<v8::Value> value,
                                                  const v8::AccessorInfo& info) {
  NPIdentifier ident = GetStringIdentifier(name);
  return NPObjectSetProperty(info.Holder(), ident, value);
}

v8::Handle<v8::Value> NPObjectIndexedPropertySetter(uint32_t index,
                                                    v8::Local<v8::Value> value,
                                                    const v8::AccessorInfo& info) {
  NPIdentifier ident = NPN_GetIntIdentifier(index);
  return NPObjectSetProperty(info.Holder(), ident, value);
}

v8::Handle<v8::Value> NPObjectSetNamedProperty(v8::Local<v8::Object> self,
                                               v8::Local<v8::String> name,
                                               v8::Local<v8::Value> value) {
  NPIdentifier ident = GetStringIdentifier(name);
  return NPObjectSetProperty(self, ident, value);
}

v8::Handle<v8::Value> NPObjectSetIndexedProperty(v8::Local<v8::Object> self,
                                                 uint32_t index,
                                                 v8::Local<v8::Value> value) {
  NPIdentifier ident = NPN_GetIntIdentifier(index);
  return NPObjectSetProperty(self, ident, value);
}

static void WeakNPObjectCallback(v8::Persistent<v8::Value> obj, void* param);

static DOMWrapperMap<NPObject> static_npobject_map(&WeakNPObjectCallback);

static void WeakNPObjectCallback(v8::Persistent<v8::Value> obj,
                                 void* param) {
  NPObject* npobject = static_cast<NPObject*>(param);
  ASSERT(static_npobject_map.contains(npobject));
  ASSERT(npobject != NULL);

  // Must remove from our map before calling NPN_ReleaseObject().
  // NPN_ReleaseObject can call ForgetV8ObjectForNPObject, which
  // uses the table as well.
  static_npobject_map.forget(npobject);

  if (_NPN_IsAlive(npobject))
    NPN_ReleaseObject(npobject);
}

v8::Local<v8::Object> CreateV8ObjectForNPObject(NPObject* object,
                                                NPObject* root) {
  static v8::Persistent<v8::FunctionTemplate> np_object_desc;

  ASSERT(v8::Context::InContext());

  // If this is a v8 object, just return it.
  if (object->_class == NPScriptObjectClass) {
    V8NPObject* v8npobject = reinterpret_cast<V8NPObject*>(object);
    return v8::Local<v8::Object>::New(v8npobject->v8_object);
  }

  // If we've already wrapped this object, just return it.
  if (static_npobject_map.contains(object))
    return v8::Local<v8::Object>::New(static_npobject_map.get(object));

  // TODO: we should create a Wrapper type as a subclass of JSObject.
  // It has two internal fields, field 0 is the wrapped pointer,
  // and field 1 is the type. There should be an api function that
  // returns unused type id.
  // The same Wrapper type can be used by DOM bindings.
  if (np_object_desc.IsEmpty()) {
    np_object_desc =
        v8::Persistent<v8::FunctionTemplate>::New(v8::FunctionTemplate::New());
    np_object_desc->InstanceTemplate()->SetInternalFieldCount(3);
    np_object_desc->InstanceTemplate()->SetNamedPropertyHandler(
        NPObjectNamedPropertyGetter, NPObjectNamedPropertySetter);
    np_object_desc->InstanceTemplate()->SetIndexedPropertyHandler(
        NPObjectIndexedPropertyGetter, NPObjectIndexedPropertySetter);
    np_object_desc->InstanceTemplate()->SetCallAsFunctionHandler(
        NPObjectInvokeDefaultHandler);
  }

  v8::Handle<v8::Function> func = np_object_desc->GetFunction();
  v8::Local<v8::Object> value = SafeAllocation::NewInstance(func);

  // If we were unable to allocate the instance we avoid wrapping
  // and registering the NP object.
  if (value.IsEmpty())
      return value;

  WrapNPObject(value, object);

  // KJS retains the object as part of its wrapper (see Bindings::CInstance)
  NPN_RetainObject(object);

  _NPN_RegisterObject(object, root);

  // Maintain a weak pointer for v8 so we can cleanup the object.
  v8::Persistent<v8::Object> weak_ref = v8::Persistent<v8::Object>::New(value);
  static_npobject_map.set(object, weak_ref);

  return value;
}

void ForgetV8ObjectForNPObject(NPObject* object) {
  if (static_npobject_map.contains(object)) {
    v8::HandleScope scope;
    v8::Persistent<v8::Object> handle(static_npobject_map.get(object));
    WebCore::V8Proxy::SetDOMWrapper(handle,
        WebCore::V8ClassIndex::NPOBJECT, NULL);
    static_npobject_map.forget(object);
    NPN_ReleaseObject(object);
  }
}
<commit_msg>Fix a renderer crashing bug with NPObject method references. http://www.corp.google.com/~michaeln/flash_crash/crash.html<commit_after>// Copyright (c) 2008, Google Inc.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
//     * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
//     * 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.
//     * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "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 COPYRIGHT
// OWNER OR CONTRIBUTORS 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 "config.h"

#include "v8_helpers.h"
#include "v8_npobject.h"
#include "v8_np_utils.h"
#include "np_v8object.h"
#include "npruntime_priv.h"
#include "v8_proxy.h"
#include "dom_wrapper_map.h"
#include "HTMLPlugInElement.h"
#include "V8HTMLAppletElement.h"
#include "V8HTMLEmbedElement.h"
#include "V8HTMLObjectElement.h"

using namespace WebCore;

enum InvokeFunctionType {
  INVOKE_METHOD = 1,
  INVOKE_DEFAULT = 2
};

// TODO(mbelshe): need comments.
// Params: holder could be HTMLEmbedElement or NPObject
static v8::Handle<v8::Value> NPObjectInvokeImpl(
    const v8::Arguments& args, InvokeFunctionType func_id) {
  NPObject* npobject;

  // These three types are subtypes of HTMLPlugInElement.
  if (V8HTMLAppletElement::HasInstance(args.Holder()) ||
      V8HTMLEmbedElement::HasInstance(args.Holder()) ||
      V8HTMLObjectElement::HasInstance(args.Holder())) {
    // The holder object is a subtype of HTMLPlugInElement.
    HTMLPlugInElement* imp =
        V8Proxy::DOMWrapperToNode<HTMLPlugInElement>(args.Holder());
    v8::Handle<v8::Object> instance = imp->getInstance();
    npobject = V8Proxy::ToNativeObject<NPObject>(
        V8ClassIndex::NPOBJECT, instance);

  } else {
    // The holder object is not a subtype of HTMLPlugInElement, it
    // must be an NPObject which has three internal fields.
    if (args.Holder()->InternalFieldCount() != 3) {
      V8Proxy::ThrowError(V8Proxy::REFERENCE_ERROR,
                          "NPMethod called on non-NPObject");
      return v8::Undefined();
    }
    npobject = V8Proxy::ToNativeObject<NPObject>(
        V8ClassIndex::NPOBJECT, args.Holder());
  }

  // Verify that our wrapper wasn't using a NPObject which
  // has already been deleted.
  if (!npobject || !_NPN_IsAlive(npobject)) {
    V8Proxy::ThrowError(V8Proxy::REFERENCE_ERROR, "NPObject deleted");
    return v8::Undefined();
  }

  // wrap up parameters
  int argc = args.Length();
  NPVariant* np_args = new NPVariant[argc];

  for (int i = 0; i < argc; i++) {
    ConvertV8ObjectToNPVariant(args[i], npobject, &np_args[i]);
  }

  NPVariant result;
  VOID_TO_NPVARIANT(result);

  switch (func_id) {
    case INVOKE_METHOD:
      if (npobject->_class->invoke) {
        v8::Handle<v8::String> function_name(v8::String::Cast(*args.Data()));
        NPIdentifier ident = GetStringIdentifier(function_name);
        npobject->_class->invoke(npobject, ident, np_args, argc, &result);
      }
      break;
    case INVOKE_DEFAULT:
      if (npobject->_class->invokeDefault) {
        npobject->_class->invokeDefault(npobject, np_args, argc, &result);
      }
      break;
    default:
      break;
  }

  for (int i=0; i < argc; i++) {
    NPN_ReleaseVariantValue(&np_args[i]);
  }
  delete[] np_args;

  // unwrap return values
  v8::Handle<v8::Value> rv = ConvertNPVariantToV8Object(&result, npobject);
  NPN_ReleaseVariantValue(&result);

  return rv;
}

v8::Handle<v8::Value> NPObjectMethodHandler(const v8::Arguments& args) {
  return NPObjectInvokeImpl(args, INVOKE_METHOD);
}

v8::Handle<v8::Value> NPObjectInvokeDefaultHandler(const v8::Arguments& args) {
  return NPObjectInvokeImpl(args, INVOKE_DEFAULT);
}

static void WeakTemplateCallback(v8::Persistent<v8::Value> obj, void* param);

// NPIdentifier is PrivateIdentifier*.
static WeakReferenceMap<PrivateIdentifier, v8::FunctionTemplate> \
    static_template_map(&WeakTemplateCallback);

static void WeakTemplateCallback(v8::Persistent<v8::Value> obj,
                                 void* param) {
  PrivateIdentifier* iden = static_cast<PrivateIdentifier*>(param);
  ASSERT(iden != NULL);
  ASSERT(static_template_map.contains(iden));

  static_template_map.forget(iden);
}

static v8::Handle<v8::Value> NPObjectGetProperty(v8::Local<v8::Object> self,
                                                 NPIdentifier ident,
                                                 v8::Local<v8::Value> key) {
  NPObject* npobject = V8Proxy::ToNativeObject<NPObject>(V8ClassIndex::NPOBJECT,
                                                         self);

  // Verify that our wrapper wasn't using a NPObject which
  // has already been deleted.
  if (!npobject || !_NPN_IsAlive(npobject)) {
    V8Proxy::ThrowError(V8Proxy::REFERENCE_ERROR, "NPObject deleted");
    return v8::Handle<v8::Value>();
  }

  if (npobject->_class->hasProperty &&
      npobject->_class->hasProperty(npobject, ident) &&
      npobject->_class->getProperty) {
    NPVariant result;
    VOID_TO_NPVARIANT(result);
    if (!npobject->_class->getProperty(npobject, ident, &result)) {
      return v8::Handle<v8::Value>();
    }

    v8::Handle<v8::Value> rv = ConvertNPVariantToV8Object(&result, npobject);
    NPN_ReleaseVariantValue(&result);
    return rv;

  } else if (key->IsString() &&
             npobject->_class->hasMethod &&
             npobject->_class->hasMethod(npobject, ident)) {
    PrivateIdentifier* id = static_cast<PrivateIdentifier*>(ident);
    v8::Persistent<v8::FunctionTemplate> desc = static_template_map.get(id);
    // Cache templates using identifier as the key.
    if (desc.IsEmpty()) {
      // Create a new template
      v8::Local<v8::FunctionTemplate> temp = v8::FunctionTemplate::New();
      temp->SetCallHandler(NPObjectMethodHandler, key);
      desc = v8::Persistent<v8::FunctionTemplate>::New(temp);
      static_template_map.set(id, desc);
    }

    // FunctionTemplate caches function for each context.
    v8::Local<v8::Function> func = desc->GetFunction();
    func->SetName(v8::Handle<v8::String>::Cast(key));
    return func;
  }

  return v8::Handle<v8::Value>();
}

v8::Handle<v8::Value> NPObjectNamedPropertyGetter(v8::Local<v8::String> name,
                                                  const v8::AccessorInfo& info) {
  NPIdentifier ident = GetStringIdentifier(name);
  return NPObjectGetProperty(info.Holder(), ident, name);
}

v8::Handle<v8::Value> NPObjectIndexedPropertyGetter(uint32_t index,
                                                    const v8::AccessorInfo& info) {
  NPIdentifier ident = NPN_GetIntIdentifier(index);
  return NPObjectGetProperty(info.Holder(), ident, v8::Number::New(index));
}

v8::Handle<v8::Value> NPObjectGetNamedProperty(v8::Local<v8::Object> self,
                                               v8::Local<v8::String> name) {
  NPIdentifier ident = GetStringIdentifier(name);
  return NPObjectGetProperty(self, ident, name);
}

v8::Handle<v8::Value> NPObjectGetIndexedProperty(v8::Local<v8::Object> self,
                                                 uint32_t index) {
  NPIdentifier ident = NPN_GetIntIdentifier(index);
  return NPObjectGetProperty(self, ident, v8::Number::New(index));
}

static v8::Handle<v8::Value> NPObjectSetProperty(v8::Local<v8::Object> self,
                                                 NPIdentifier ident,
                                                 v8::Local<v8::Value> value) {
  NPObject* npobject =
    V8Proxy::ToNativeObject<NPObject>(V8ClassIndex::NPOBJECT, self);

  // Verify that our wrapper wasn't using a NPObject which
  // has already been deleted.
  if (!npobject || !_NPN_IsAlive(npobject)) {
    V8Proxy::ThrowError(V8Proxy::REFERENCE_ERROR, "NPObject deleted");
    return value;  // intercepted, but an exception was thrown
  }

  if (npobject->_class->hasProperty &&
      npobject->_class->hasProperty(npobject, ident) &&
      npobject->_class->setProperty) {
    NPVariant npvalue;
    VOID_TO_NPVARIANT(npvalue);
    ConvertV8ObjectToNPVariant(value, npobject, &npvalue);
    bool succ = npobject->_class->setProperty(npobject, ident, &npvalue);
    NPN_ReleaseVariantValue(&npvalue);
    if (succ) return value;  // intercept the call
  }
  return v8::Local<v8::Value>();  // do not intercept the call
}

v8::Handle<v8::Value> NPObjectNamedPropertySetter(v8::Local<v8::String> name,
                                                  v8::Local<v8::Value> value,
                                                  const v8::AccessorInfo& info) {
  NPIdentifier ident = GetStringIdentifier(name);
  return NPObjectSetProperty(info.Holder(), ident, value);
}

v8::Handle<v8::Value> NPObjectIndexedPropertySetter(uint32_t index,
                                                    v8::Local<v8::Value> value,
                                                    const v8::AccessorInfo& info) {
  NPIdentifier ident = NPN_GetIntIdentifier(index);
  return NPObjectSetProperty(info.Holder(), ident, value);
}

v8::Handle<v8::Value> NPObjectSetNamedProperty(v8::Local<v8::Object> self,
                                               v8::Local<v8::String> name,
                                               v8::Local<v8::Value> value) {
  NPIdentifier ident = GetStringIdentifier(name);
  return NPObjectSetProperty(self, ident, value);
}

v8::Handle<v8::Value> NPObjectSetIndexedProperty(v8::Local<v8::Object> self,
                                                 uint32_t index,
                                                 v8::Local<v8::Value> value) {
  NPIdentifier ident = NPN_GetIntIdentifier(index);
  return NPObjectSetProperty(self, ident, value);
}

static void WeakNPObjectCallback(v8::Persistent<v8::Value> obj, void* param);

static DOMWrapperMap<NPObject> static_npobject_map(&WeakNPObjectCallback);

static void WeakNPObjectCallback(v8::Persistent<v8::Value> obj,
                                 void* param) {
  NPObject* npobject = static_cast<NPObject*>(param);
  ASSERT(static_npobject_map.contains(npobject));
  ASSERT(npobject != NULL);

  // Must remove from our map before calling NPN_ReleaseObject().
  // NPN_ReleaseObject can call ForgetV8ObjectForNPObject, which
  // uses the table as well.
  static_npobject_map.forget(npobject);

  if (_NPN_IsAlive(npobject))
    NPN_ReleaseObject(npobject);
}

v8::Local<v8::Object> CreateV8ObjectForNPObject(NPObject* object,
                                                NPObject* root) {
  static v8::Persistent<v8::FunctionTemplate> np_object_desc;

  ASSERT(v8::Context::InContext());

  // If this is a v8 object, just return it.
  if (object->_class == NPScriptObjectClass) {
    V8NPObject* v8npobject = reinterpret_cast<V8NPObject*>(object);
    return v8::Local<v8::Object>::New(v8npobject->v8_object);
  }

  // If we've already wrapped this object, just return it.
  if (static_npobject_map.contains(object))
    return v8::Local<v8::Object>::New(static_npobject_map.get(object));

  // TODO: we should create a Wrapper type as a subclass of JSObject.
  // It has two internal fields, field 0 is the wrapped pointer,
  // and field 1 is the type. There should be an api function that
  // returns unused type id.
  // The same Wrapper type can be used by DOM bindings.
  if (np_object_desc.IsEmpty()) {
    np_object_desc =
        v8::Persistent<v8::FunctionTemplate>::New(v8::FunctionTemplate::New());
    np_object_desc->InstanceTemplate()->SetInternalFieldCount(3);
    np_object_desc->InstanceTemplate()->SetNamedPropertyHandler(
        NPObjectNamedPropertyGetter, NPObjectNamedPropertySetter);
    np_object_desc->InstanceTemplate()->SetIndexedPropertyHandler(
        NPObjectIndexedPropertyGetter, NPObjectIndexedPropertySetter);
    np_object_desc->InstanceTemplate()->SetCallAsFunctionHandler(
        NPObjectInvokeDefaultHandler);
  }

  v8::Handle<v8::Function> func = np_object_desc->GetFunction();
  v8::Local<v8::Object> value = SafeAllocation::NewInstance(func);

  // If we were unable to allocate the instance we avoid wrapping
  // and registering the NP object.
  if (value.IsEmpty())
      return value;

  WrapNPObject(value, object);

  // KJS retains the object as part of its wrapper (see Bindings::CInstance)
  NPN_RetainObject(object);

  _NPN_RegisterObject(object, root);

  // Maintain a weak pointer for v8 so we can cleanup the object.
  v8::Persistent<v8::Object> weak_ref = v8::Persistent<v8::Object>::New(value);
  static_npobject_map.set(object, weak_ref);

  return value;
}

void ForgetV8ObjectForNPObject(NPObject* object) {
  if (static_npobject_map.contains(object)) {
    v8::HandleScope scope;
    v8::Persistent<v8::Object> handle(static_npobject_map.get(object));
    WebCore::V8Proxy::SetDOMWrapper(handle,
        WebCore::V8ClassIndex::NPOBJECT, NULL);
    static_npobject_map.forget(object);
    NPN_ReleaseObject(object);
  }
}
<|endoftext|>


<commit_before>#include "pch.h"
#include "WASAPIEngine.h"

using namespace concurrency;

WASAPIEngine::WASAPIEngine()
{
	m_deviceList = std::vector<WASAPIDevice^>();
	m_collector = nullptr;
	m_consumer = nullptr;
	HRESULT hr = MFStartup(MF_VERSION, MFSTARTUP_LITE);
}

WASAPIEngine::~WASAPIEngine()
{
}

IAsyncAction^ WASAPIEngine::InitializeCaptureAsync(UIDelegate1^ func, AudioDevices^ devParams, AudioParameters^ params)
{
	return InitializeCaptureAsync(func, nullptr, devParams, params);
}

[Windows::Foundation::Metadata::DefaultOverloadAttribute]
IAsyncAction^ WASAPIEngine::InitializeCaptureAsync(UIDelegate2^ func, AudioDevices^ devParams, AudioParameters^ params)
{
	return InitializeCaptureAsync(nullptr, func, devParams, params);
}

IAsyncAction^ WASAPIEngine::InitializeCaptureAsync(UIDelegate1^ func1, UIDelegate2^ func2, AudioDevices^ devParams, AudioParameters^ params)
{
	return create_async([this ,func1, func2, devParams, params]
	{
		// Get the string identifier of the audio renderer
		auto AudioSelector = MediaDevice::GetAudioCaptureSelector();

		// Add custom properties to the query
		auto PropertyList = ref new Platform::Collections::Vector<String^>();
		PropertyList->Append(PKEY_AudioEndpoint_Supports_EventDriven_Mode);

		// Setup the asynchronous callback
		Concurrency::task<DeviceInformationCollection^> enumOperation(DeviceInformation::FindAllAsync(AudioSelector, PropertyList));
		enumOperation.then([this](DeviceInformationCollection^ DeviceInfoCollection)
		{
			if ((DeviceInfoCollection == nullptr) || (DeviceInfoCollection->Size == 0))
			{
				OutputDebugString(L"No Devices Found.\n");
			}
			else
			{
				try
				{
					// Enumerate through the devices and the custom properties
					for (unsigned int i = 0; i < DeviceInfoCollection->Size; i++)
					{
						auto deviceInfo = DeviceInfoCollection->GetAt(i);
						auto DeviceInfoString = deviceInfo->Name;
						auto DeviceIdString = deviceInfo->Id;

						if (deviceInfo->Properties->Size > 0)
						{
							auto device = ref new WASAPIDevice();
							device->Name = DeviceInfoString;
							device->ID = DeviceIdString;
							m_deviceList.push_back(device);
							OutputDebugString(device->Name->Data());
							OutputDebugString(device->ID->Data());
							OutputDebugString(L"\n");
						}
					}
				}
				catch (Platform::Exception^) {}
			}
		})
		.then([this, func1, func2, devParams, params]()
		{
			if (m_deviceList.size() >= devParams->Devices())
			{
				m_collector = ref new DataCollector(devParams->Devices());
				for (size_t i = 0; i < m_deviceList.size(); i++)
				{
					auto index = devParams->GetIndex(m_deviceList[i]->ID, i);
					if (index != -1)
					{
						m_deviceList[i]->InitCaptureDevice(index, m_collector);
					}
				}
				m_consumer = ref new DataConsumer(devParams->Devices(), m_collector, func1, func2, devParams, params);
				m_consumer->Start();
			}
			else
			{
				if (func1 == nullptr)
				{
					func2(LibAudio::HeartBeatType::NODEVICE, 0, 0, 0, 0, nullptr, nullptr, nullptr, nullptr);
				}
				else
				{
					func1(LibAudio::HeartBeatType::NODEVICE, nullptr, nullptr, nullptr);
				}
			}
		});
	});
}

IAsyncAction^ WASAPIEngine::InitializeRendererAsync(AudioDevices^ devParams, AudioParameters^ params)
{
	return create_async([this, devParams, params]
	{
		// Get the string identifier of the audio renderer
		auto AudioSelector = MediaDevice::GetAudioRenderSelector();

		// Add custom properties to the query
		auto PropertyList = ref new Platform::Collections::Vector<String^>();
		PropertyList->Append(PKEY_AudioEndpoint_Supports_EventDriven_Mode);

		// Setup the asynchronous callback
		Concurrency::task<DeviceInformationCollection^> enumOperation(DeviceInformation::FindAllAsync(AudioSelector, PropertyList));
		enumOperation.then([this](DeviceInformationCollection^ DeviceInfoCollection)
		{
			if ((DeviceInfoCollection == nullptr) || (DeviceInfoCollection->Size == 0))
			{
				OutputDebugString(L"No Devices Found.\n");
			}
			else
			{
				try
				{
					// Enumerate through the devices and the custom properties
					for (unsigned int i = 0; i < DeviceInfoCollection->Size; i++)
					{
						auto deviceInfo = DeviceInfoCollection->GetAt(i);
						auto DeviceInfoString = deviceInfo->Name;
						auto DeviceIdString = deviceInfo->Id;

						if (deviceInfo->Properties->Size > 0)
						{
							auto device = ref new WASAPIDevice();
							device->Name = DeviceInfoString;
							device->ID = DeviceIdString;
							m_deviceList.push_back(device);
							OutputDebugString(device->Name->Data());
							OutputDebugString(device->ID->Data());
							OutputDebugString(L"\n");
						}
					}
				}
				catch (Platform::Exception^) {}
			}
		})
		.then([this, devParams, params]()
		{
			if (m_deviceList.size() >= devParams->Devices())
			{
				m_collector = ref new DataCollector(devParams->Devices());
				for (size_t i = 0; i < m_deviceList.size(); i++)
				{
					auto index = devParams->GetIndex(m_deviceList[i]->ID, i);
					if (index != -1)
					{
						m_deviceList[i]->InitRendererDevice(index, nullptr);
					}
				}
			}
		});
	});
}

IAsyncAction^ WASAPIEngine::GetCaptureDevicesAsync(UIDelegate3^ func)
{
	return create_async([this, func]
	{
		// Get the string identifier of the audio renderer
		auto AudioSelector = MediaDevice::GetAudioCaptureSelector();

		// Add custom properties to the query
		auto PropertyList = ref new Platform::Collections::Vector<String^>();
		PropertyList->Append(PKEY_AudioEndpoint_Supports_EventDriven_Mode);

		// Setup the asynchronous callback
		Concurrency::task<DeviceInformationCollection^> enumOperation(DeviceInformation::FindAllAsync(AudioSelector, PropertyList));
		enumOperation.then([this, func](DeviceInformationCollection^ DeviceInfoCollection)
		{
			if ((DeviceInfoCollection == nullptr) || (DeviceInfoCollection->Size == 0))
			{
				func(L"No Devices Found.\n");
			}
			else
			{
				try
				{
					// Enumerate through the devices and the custom properties
					for (unsigned int i = 0; i < DeviceInfoCollection->Size; i++)
					{
						auto deviceInfo = DeviceInfoCollection->GetAt(i);
						func(deviceInfo->Id);
					}
				}
				catch (Platform::Exception^) {}
			}
		});
	});
}

IAsyncAction^ WASAPIEngine::GetRendererDevicesAsync(UIDelegate3^ func)
{
	return create_async([this, func]
	{
		// Get the string identifier of the audio renderer
		auto AudioSelector = MediaDevice::GetAudioRenderSelector();

		// Add custom properties to the query
		auto PropertyList = ref new Platform::Collections::Vector<String^>();
		PropertyList->Append(PKEY_AudioEndpoint_Supports_EventDriven_Mode);

		// Setup the asynchronous callback
		Concurrency::task<DeviceInformationCollection^> enumOperation(DeviceInformation::FindAllAsync(AudioSelector, PropertyList));
		enumOperation.then([this, func](DeviceInformationCollection^ DeviceInfoCollection)
		{
			if ((DeviceInfoCollection == nullptr) || (DeviceInfoCollection->Size == 0))
			{
				func(L"No Devices Found.\n");
			}
			else
			{
				try
				{
					// Enumerate through the devices and the custom properties
					for (unsigned int i = 0; i < DeviceInfoCollection->Size; i++)
					{
						auto deviceInfo = DeviceInfoCollection->GetAt(i);
						func(deviceInfo->Id);
					}
				}
				catch (Platform::Exception^) {}
			}
		});
	});
}

void WASAPIEngine::Finish()
{
	if (m_consumer != nullptr)
	{
		m_consumer->Finish();
		m_consumer = nullptr;
	}

	for (size_t i = 0; i < m_deviceList.size(); i++)
	{
		if (m_deviceList[i]->Initialized())
		{
			m_deviceList[i]->StopAsync();
		}
		m_deviceList[i] = nullptr;
	}

	if (m_collector != nullptr)
	{
		m_collector->Finish();
		m_collector = nullptr;
	}
}

void WASAPIEngine::Continue()
{
	if (m_consumer != nullptr)
	{
		m_consumer->Continue();
	}
}
<commit_msg>12052016 - 14:49<commit_after>#include "pch.h"
#include "WASAPIEngine.h"

using namespace concurrency;

WASAPIEngine::WASAPIEngine()
{
	m_deviceList = std::vector<WASAPIDevice^>();
	m_collector = nullptr;
	m_consumer = nullptr;
	HRESULT hr = MFStartup(MF_VERSION, MFSTARTUP_LITE);
}

WASAPIEngine::~WASAPIEngine()
{
}

IAsyncAction^ WASAPIEngine::InitializeCaptureAsync(UIDelegate1^ func, AudioDevices^ devParams, AudioParameters^ params)
{
	return InitializeCaptureAsync(func, nullptr, devParams, params);
}

[Windows::Foundation::Metadata::DefaultOverloadAttribute]
IAsyncAction^ WASAPIEngine::InitializeCaptureAsync(UIDelegate2^ func, AudioDevices^ devParams, AudioParameters^ params)
{
	return InitializeCaptureAsync(nullptr, func, devParams, params);
}

IAsyncAction^ WASAPIEngine::InitializeCaptureAsync(UIDelegate1^ func1, UIDelegate2^ func2, AudioDevices^ devParams, AudioParameters^ params)
{
	return create_async([this ,func1, func2, devParams, params]
	{
		// Get the string identifier of the audio renderer
		auto AudioSelector = MediaDevice::GetAudioCaptureSelector();

		// Add custom properties to the query
		auto PropertyList = ref new Platform::Collections::Vector<String^>();
		PropertyList->Append(PKEY_AudioEndpoint_Supports_EventDriven_Mode);

		// Setup the asynchronous callback
		Concurrency::task<DeviceInformationCollection^> enumOperation(DeviceInformation::FindAllAsync(AudioSelector, PropertyList));
		enumOperation.then([this](DeviceInformationCollection^ DeviceInfoCollection)
		{
			if ((DeviceInfoCollection == nullptr) || (DeviceInfoCollection->Size == 0))
			{
				OutputDebugString(L"No Devices Found.\n");
			}
			else
			{
				try
				{
					// Enumerate through the devices and the custom properties
					for (unsigned int i = 0; i < DeviceInfoCollection->Size; i++)
					{
						auto deviceInfo = DeviceInfoCollection->GetAt(i);
						auto DeviceInfoString = deviceInfo->Name;
						auto DeviceIdString = deviceInfo->Id;

						if (deviceInfo->Properties->Size > 0)
						{
							auto device = ref new WASAPIDevice();
							device->Name = DeviceInfoString;
							device->ID = DeviceIdString;
							m_deviceList.push_back(device);
							OutputDebugString(device->Name->Data());
							OutputDebugString(device->ID->Data());
							OutputDebugString(L"\n");
						}
					}
				}
				catch (Platform::Exception^) {}
			}
		})
		.then([this, func1, func2, devParams, params]()
		{
			if (m_deviceList.size() >= devParams->Devices())
			{
				m_collector = ref new DataCollector(devParams->Devices());
				for (size_t i = 0; i < m_deviceList.size(); i++)
				{
					auto index = devParams->GetIndex(m_deviceList[i]->ID, i);
					if (index != -1)
					{
						m_deviceList[i]->InitCaptureDevice(index, m_collector);
					}
				}
				m_consumer = ref new DataConsumer(devParams->Devices(), m_collector, func1, func2, devParams, params);
				m_consumer->Start();
			}
			else
			{
				if (func1 == nullptr)
				{
					func2(LibAudio::HeartBeatType::NODEVICE, 0, 0, 0, 0, nullptr, nullptr, nullptr, nullptr);
				}
				else
				{
					func1(LibAudio::HeartBeatType::NODEVICE, nullptr, nullptr, nullptr);
				}
			}
		});
	});
}

IAsyncAction^ WASAPIEngine::InitializeRendererAsync(AudioDevices^ devParams, AudioParameters^ params)
{
	return create_async([this, devParams, params]
	{
		// Get the string identifier of the audio renderer
		auto AudioSelector = MediaDevice::GetAudioRenderSelector();

		// Add custom properties to the query
		auto PropertyList = ref new Platform::Collections::Vector<String^>();
		PropertyList->Append(PKEY_AudioEndpoint_Supports_EventDriven_Mode);

		// Setup the asynchronous callback
		Concurrency::task<DeviceInformationCollection^> enumOperation(DeviceInformation::FindAllAsync(AudioSelector, PropertyList));
		enumOperation.then([this](DeviceInformationCollection^ DeviceInfoCollection)
		{
			if ((DeviceInfoCollection == nullptr) || (DeviceInfoCollection->Size == 0))
			{
				OutputDebugString(L"No Devices Found.\n");
			}
			else
			{
				try
				{
					// Enumerate through the devices and the custom properties
					for (unsigned int i = 0; i < DeviceInfoCollection->Size; i++)
					{
						auto deviceInfo = DeviceInfoCollection->GetAt(i);
						auto DeviceInfoString = deviceInfo->Name;
						auto DeviceIdString = deviceInfo->Id;

						if (deviceInfo->Properties->Size > 0)
						{
							auto device = ref new WASAPIDevice();
							device->Name = DeviceInfoString;
							device->ID = DeviceIdString;
							m_deviceList.push_back(device);
							OutputDebugString(device->Name->Data());
							OutputDebugString(device->ID->Data());
							OutputDebugString(L"\n");
						}
					}
				}
				catch (Platform::Exception^) {}
			}
		})
		.then([this, devParams, params]()
		{
			if (m_deviceList.size() >= devParams->Devices())
			{
				m_collector = ref new DataCollector(devParams->Devices());
				for (size_t i = 0; i < m_deviceList.size(); i++)
				{
					auto index = devParams->GetIndex(m_deviceList[i]->ID, i);
					if (index != -1)
					{
						m_deviceList[i]->InitRendererDevice(index, nullptr);
					}
				}
			}
		});
	});
}

IAsyncAction^ WASAPIEngine::GetCaptureDevicesAsync(UIDelegate3^ func)
{
	return create_async([this, func]
	{
		// Get the string identifier of the audio renderer
		auto AudioSelector = MediaDevice::GetAudioCaptureSelector();

		// Add custom properties to the query
		auto PropertyList = ref new Platform::Collections::Vector<String^>();
		PropertyList->Append(PKEY_AudioEndpoint_Supports_EventDriven_Mode);

		// Setup the asynchronous callback
		Concurrency::task<DeviceInformationCollection^> enumOperation(DeviceInformation::FindAllAsync(AudioSelector, PropertyList));
		enumOperation.then([this, func](DeviceInformationCollection^ DeviceInfoCollection)
		{
			if ((DeviceInfoCollection == nullptr) || (DeviceInfoCollection->Size == 0))
			{
				func(L"No Devices Found.\n");
			}
			else
			{
				try
				{
					// Enumerate through the devices and the custom properties
					for (unsigned int i = 0; i < DeviceInfoCollection->Size; i++)
					{
						auto deviceInfo = DeviceInfoCollection->GetAt(i);
						func("C - " + deviceInfo->Id + deviceInfo->IsDefault ? "*" : "");
					}
				}
				catch (Platform::Exception^) {}
			}
		});
	});
}

IAsyncAction^ WASAPIEngine::GetRendererDevicesAsync(UIDelegate3^ func)
{
	return create_async([this, func]
	{
		// Get the string identifier of the audio renderer
		auto AudioSelector = MediaDevice::GetAudioRenderSelector();

		// Add custom properties to the query
		auto PropertyList = ref new Platform::Collections::Vector<String^>();
		PropertyList->Append(PKEY_AudioEndpoint_Supports_EventDriven_Mode);

		// Setup the asynchronous callback
		Concurrency::task<DeviceInformationCollection^> enumOperation(DeviceInformation::FindAllAsync(AudioSelector, PropertyList));
		enumOperation.then([this, func](DeviceInformationCollection^ DeviceInfoCollection)
		{
			if ((DeviceInfoCollection == nullptr) || (DeviceInfoCollection->Size == 0))
			{
				func(L"No Devices Found.\n");
			}
			else
			{
				try
				{
					// Enumerate through the devices and the custom properties
					for (unsigned int i = 0; i < DeviceInfoCollection->Size; i++)
					{
						auto deviceInfo = DeviceInfoCollection->GetAt(i);
						func("R - " + deviceInfo->Id + deviceInfo->IsDefault ? "*" : "");
					}
				}
				catch (Platform::Exception^) {}
			}
		});
	});
}

void WASAPIEngine::Finish()
{
	if (m_consumer != nullptr)
	{
		m_consumer->Finish();
		m_consumer = nullptr;
	}

	for (size_t i = 0; i < m_deviceList.size(); i++)
	{
		if (m_deviceList[i]->Initialized())
		{
			m_deviceList[i]->StopAsync();
		}
		m_deviceList[i] = nullptr;
	}

	if (m_collector != nullptr)
	{
		m_collector->Finish();
		m_collector = nullptr;
	}
}

void WASAPIEngine::Continue()
{
	if (m_consumer != nullptr)
	{
		m_consumer->Continue();
	}
}
<|endoftext|>


<commit_before>#define DEBUG 1
/**
 * File    : E2.cpp
 * Author  : Kazune Takahashi
 * Created : 7/6/2020, 8:25:26 PM
 * Powered by Visual Studio Code
 */
#include <algorithm>
#include <bitset>
#include <cassert>
#include <cctype>
#include <chrono>
#include <climits>
#include <cmath>
#include <complex>
#include <cstdint>
#include <cstdio>
#include <cstdlib>
#include <functional>
#include <iomanip>
#include <iostream>
#include <limits>
#include <map>
#include <queue>
#include <random>
#include <set>
#include <stack>
#include <string>
#include <tuple>
#include <unordered_map>
#include <unordered_set>
#include <vector>
// ----- boost -----
#include <boost/integer/common_factor_rt.hpp>
#include <boost/multiprecision/cpp_int.hpp>
#include <boost/rational.hpp>
// ----- using directives and manipulations -----
using namespace std;
using boost::rational;
using boost::integer::gcd; // for C++14 or for cpp_int
using boost::integer::lcm; // for C++14 or for cpp_int
using boost::multiprecision::cpp_int;
using ll = long long;
using ld = long double;
template <typename T>
using max_heap = priority_queue<T>;
template <typename T>
using min_heap = priority_queue<T, vector<T>, greater<T>>;
// ----- constexpr for Mint and Combination -----
constexpr ll MOD{1'000'000'007LL};
// constexpr ll MOD{998'244'353LL}; // be careful
constexpr ll MAX_SIZE{3'000'010LL};
// constexpr ll MAX_SIZE{30'000'010LL}; // if 10^7 is needed
// ----- ch_max and ch_min -----
template <typename T>
bool ch_max(T &left, T right)
{
  if (left < right)
  {
    left = right;
    return true;
  }
  return false;
}
template <typename T>
bool ch_min(T &left, T right)
{
  if (left > right)
  {
    left = right;
    return true;
  }
  return false;
}
// ----- Mint -----
template <ll MOD = MOD>
class Mint
{
public:
  ll x;
  Mint() : x{0LL} {}
  Mint(ll x) : x{(x % MOD + MOD) % MOD} {}
  Mint operator-() const { return x ? MOD - x : 0; }
  Mint &operator+=(Mint const &a)
  {
    if ((x += a.x) >= MOD)
    {
      x -= MOD;
    }
    return *this;
  }
  Mint &operator-=(Mint const &a) { return *this += -a; }
  Mint &operator++() { return *this += 1; }
  Mint operator++(int)
  {
    Mint tmp{*this};
    ++*this;
    return tmp;
  }
  Mint &operator--() { return *this -= 1; }
  Mint operator--(int)
  {
    Mint tmp{*this};
    --*this;
    return tmp;
  }
  Mint &operator*=(Mint const &a)
  {
    (x *= a.x) %= MOD;
    return *this;
  }
  Mint &operator/=(Mint const &a)
  {
    Mint b{a};
    return *this *= b.power(MOD - 2);
  }
  Mint operator+(Mint const &a) const { return Mint(*this) += a; }
  Mint operator-(Mint const &a) const { return Mint(*this) -= a; }
  Mint operator*(Mint const &a) const { return Mint(*this) *= a; }
  Mint operator/(Mint const &a) const { return Mint(*this) /= a; }
  bool operator<(Mint const &a) const { return x < a.x; }
  bool operator<=(Mint const &a) const { return x <= a.x; }
  bool operator>(Mint const &a) const { return x > a.x; }
  bool operator>=(Mint const &a) const { return x >= a.x; }
  bool operator==(Mint const &a) const { return x == a.x; }
  bool operator!=(Mint const &a) const { return !(*this == a); }
  Mint power(ll N) const
  {
    if (N == 0)
    {
      return 1;
    }
    else if (N % 2 == 1)
    {
      return *this * power(N - 1);
    }
    else
    {
      Mint half = power(N / 2);
      return half * half;
    }
  }
};
template <ll MOD>
Mint<MOD> operator+(ll lhs, Mint<MOD> const &rhs) { return rhs + lhs; }
template <ll MOD>
Mint<MOD> operator-(ll lhs, Mint<MOD> const &rhs) { return -rhs + lhs; }
template <ll MOD>
Mint<MOD> operator*(ll lhs, Mint<MOD> const &rhs) { return rhs * lhs; }
template <ll MOD>
Mint<MOD> operator/(ll lhs, Mint<MOD> const &rhs) { return Mint<MOD>{lhs} / rhs; }
template <ll MOD>
istream &operator>>(istream &stream, Mint<MOD> &a) { return stream >> a.x; }
template <ll MOD>
ostream &operator<<(ostream &stream, Mint<MOD> const &a) { return stream << a.x; }
// ----- Combination -----
template <ll MOD = MOD, ll MAX_SIZE = MAX_SIZE>
class Combination
{
public:
  vector<Mint<MOD>> inv, fact, factinv;
  Combination() : inv(MAX_SIZE), fact(MAX_SIZE), factinv(MAX_SIZE)
  {
    inv[1] = 1;
    for (auto i{2LL}; i < MAX_SIZE; i++)
    {
      inv[i] = (-inv[MOD % i]) * (MOD / i);
    }
    fact[0] = factinv[0] = 1;
    for (auto i{1LL}; i < MAX_SIZE; i++)
    {
      fact[i] = Mint<MOD>(i) * fact[i - 1];
      factinv[i] = inv[i] * factinv[i - 1];
    }
  }
  Mint<MOD> operator()(int n, int k)
  {
    if (n >= 0 && k >= 0 && n - k >= 0)
    {
      return fact[n] * factinv[k] * factinv[n - k];
    }
    return 0;
  }
  Mint<MOD> catalan(int x, int y)
  {
    return (*this)(x + y, y) - (*this)(x + y, y - 1);
  }
};
// ----- for C++14 -----
using mint = Mint<MOD>;
using combination = Combination<MOD, MAX_SIZE>;
// ----- for C++17 -----
template <typename T, typename enable_if<is_integral<T>::value>::type * = nullptr>
size_t popcount(T x) { return bitset<64>(x).count(); }
size_t popcount(string const &S) { return bitset<200010>{S}.count(); }
// ----- Infty -----
template <typename T>
constexpr T Infty() { return numeric_limits<T>::max(); }
template <typename T>
constexpr T mInfty() { return numeric_limits<T>::min(); }
// ----- frequently used constexpr -----
// constexpr double epsilon{1e-10};
// constexpr ll infty{1'000'000'000'000'010LL}; // or
// constexpr int infty{1'000'000'010};
// constexpr int dx[4] = {1, 0, -1, 0};
// constexpr int dy[4] = {0, 1, 0, -1};
// ----- Yes() and No() -----
void Yes()
{
  cout << "Yes" << endl;
  exit(0);
}
void No()
{
  cout << "No" << endl;
  exit(0);
}

// ----- Solve -----

class Solve
{

public:
  Solve()
  {
  }

  void flush()
  {
  }

private:
};

// ----- main() -----

/*
int main()
{
  Solve solve;
  solve.flush();
}
*/

int main()
{
  int n, k;
  cin >> n >> k;
  vector<ll> a(n);
  for (auto i{0}; i < n; ++i)
  {
    cin >> a[i];
  }
  sort(a.rbegin(), a.rend());
  if (a[0] < 0)
  {
    cout << accumulate(a.begin(), a.begin() + k, mint{1}, multiplies()) << endl;
    return 0;
  }
  auto l{0}, r{n - 1};
  mint ans{1};
  if (k & 1)
  {
    ans *= a[l++];
  }
  for (auto t{0}; t < k / 2; ++t)
  {
    if (auto left{a[l] * a[l + 1]}, right{a[r] * a[r - 1]}; left >= right)
    {
      ans *= left;
      l += 2;
    }
    else
    {
      ans *= right;
      r -= 2;
    }
  }
  if (ans == 0)
  {
    sleep(1000);
  }
  cout << ans << endl;
}
<commit_msg>submit E2.cpp to 'E - Multiplication 4' (abc173) [C++ (GCC 9.2.1)]<commit_after>#define DEBUG 1
/**
 * File    : E2.cpp
 * Author  : Kazune Takahashi
 * Created : 7/6/2020, 8:25:26 PM
 * Powered by Visual Studio Code
 */
#include <algorithm>
#include <bitset>
#include <cassert>
#include <cctype>
#include <chrono>
#include <climits>
#include <cmath>
#include <complex>
#include <cstdint>
#include <cstdio>
#include <cstdlib>
#include <functional>
#include <iomanip>
#include <iostream>
#include <limits>
#include <map>
#include <queue>
#include <random>
#include <set>
#include <stack>
#include <string>
#include <tuple>
#include <unordered_map>
#include <unordered_set>
#include <vector>
// ----- boost -----
#include <boost/integer/common_factor_rt.hpp>
#include <boost/multiprecision/cpp_int.hpp>
#include <boost/rational.hpp>
// ----- using directives and manipulations -----
using namespace std;
using boost::rational;
using boost::integer::gcd; // for C++14 or for cpp_int
using boost::integer::lcm; // for C++14 or for cpp_int
using boost::multiprecision::cpp_int;
using ll = long long;
using ld = long double;
template <typename T>
using max_heap = priority_queue<T>;
template <typename T>
using min_heap = priority_queue<T, vector<T>, greater<T>>;
// ----- constexpr for Mint and Combination -----
constexpr ll MOD{1'000'000'007LL};
// constexpr ll MOD{998'244'353LL}; // be careful
constexpr ll MAX_SIZE{3'000'010LL};
// constexpr ll MAX_SIZE{30'000'010LL}; // if 10^7 is needed
// ----- ch_max and ch_min -----
template <typename T>
bool ch_max(T &left, T right)
{
  if (left < right)
  {
    left = right;
    return true;
  }
  return false;
}
template <typename T>
bool ch_min(T &left, T right)
{
  if (left > right)
  {
    left = right;
    return true;
  }
  return false;
}
// ----- Mint -----
template <ll MOD = MOD>
class Mint
{
public:
  ll x;
  Mint() : x{0LL} {}
  Mint(ll x) : x{(x % MOD + MOD) % MOD} {}
  Mint operator-() const { return x ? MOD - x : 0; }
  Mint &operator+=(Mint const &a)
  {
    if ((x += a.x) >= MOD)
    {
      x -= MOD;
    }
    return *this;
  }
  Mint &operator-=(Mint const &a) { return *this += -a; }
  Mint &operator++() { return *this += 1; }
  Mint operator++(int)
  {
    Mint tmp{*this};
    ++*this;
    return tmp;
  }
  Mint &operator--() { return *this -= 1; }
  Mint operator--(int)
  {
    Mint tmp{*this};
    --*this;
    return tmp;
  }
  Mint &operator*=(Mint const &a)
  {
    (x *= a.x) %= MOD;
    return *this;
  }
  Mint &operator/=(Mint const &a)
  {
    Mint b{a};
    return *this *= b.power(MOD - 2);
  }
  Mint operator+(Mint const &a) const { return Mint(*this) += a; }
  Mint operator-(Mint const &a) const { return Mint(*this) -= a; }
  Mint operator*(Mint const &a) const { return Mint(*this) *= a; }
  Mint operator/(Mint const &a) const { return Mint(*this) /= a; }
  bool operator<(Mint const &a) const { return x < a.x; }
  bool operator<=(Mint const &a) const { return x <= a.x; }
  bool operator>(Mint const &a) const { return x > a.x; }
  bool operator>=(Mint const &a) const { return x >= a.x; }
  bool operator==(Mint const &a) const { return x == a.x; }
  bool operator!=(Mint const &a) const { return !(*this == a); }
  Mint power(ll N) const
  {
    if (N == 0)
    {
      return 1;
    }
    else if (N % 2 == 1)
    {
      return *this * power(N - 1);
    }
    else
    {
      Mint half = power(N / 2);
      return half * half;
    }
  }
};
template <ll MOD>
Mint<MOD> operator+(ll lhs, Mint<MOD> const &rhs) { return rhs + lhs; }
template <ll MOD>
Mint<MOD> operator-(ll lhs, Mint<MOD> const &rhs) { return -rhs + lhs; }
template <ll MOD>
Mint<MOD> operator*(ll lhs, Mint<MOD> const &rhs) { return rhs * lhs; }
template <ll MOD>
Mint<MOD> operator/(ll lhs, Mint<MOD> const &rhs) { return Mint<MOD>{lhs} / rhs; }
template <ll MOD>
istream &operator>>(istream &stream, Mint<MOD> &a) { return stream >> a.x; }
template <ll MOD>
ostream &operator<<(ostream &stream, Mint<MOD> const &a) { return stream << a.x; }
// ----- Combination -----
template <ll MOD = MOD, ll MAX_SIZE = MAX_SIZE>
class Combination
{
public:
  vector<Mint<MOD>> inv, fact, factinv;
  Combination() : inv(MAX_SIZE), fact(MAX_SIZE), factinv(MAX_SIZE)
  {
    inv[1] = 1;
    for (auto i{2LL}; i < MAX_SIZE; i++)
    {
      inv[i] = (-inv[MOD % i]) * (MOD / i);
    }
    fact[0] = factinv[0] = 1;
    for (auto i{1LL}; i < MAX_SIZE; i++)
    {
      fact[i] = Mint<MOD>(i) * fact[i - 1];
      factinv[i] = inv[i] * factinv[i - 1];
    }
  }
  Mint<MOD> operator()(int n, int k)
  {
    if (n >= 0 && k >= 0 && n - k >= 0)
    {
      return fact[n] * factinv[k] * factinv[n - k];
    }
    return 0;
  }
  Mint<MOD> catalan(int x, int y)
  {
    return (*this)(x + y, y) - (*this)(x + y, y - 1);
  }
};
// ----- for C++14 -----
using mint = Mint<MOD>;
using combination = Combination<MOD, MAX_SIZE>;
// ----- for C++17 -----
template <typename T, typename enable_if<is_integral<T>::value>::type * = nullptr>
size_t popcount(T x) { return bitset<64>(x).count(); }
size_t popcount(string const &S) { return bitset<200010>{S}.count(); }
// ----- Infty -----
template <typename T>
constexpr T Infty() { return numeric_limits<T>::max(); }
template <typename T>
constexpr T mInfty() { return numeric_limits<T>::min(); }
// ----- frequently used constexpr -----
// constexpr double epsilon{1e-10};
// constexpr ll infty{1'000'000'000'000'010LL}; // or
// constexpr int infty{1'000'000'010};
// constexpr int dx[4] = {1, 0, -1, 0};
// constexpr int dy[4] = {0, 1, 0, -1};
// ----- Yes() and No() -----
void Yes()
{
  cout << "Yes" << endl;
  exit(0);
}
void No()
{
  cout << "No" << endl;
  exit(0);
}

// ----- Solve -----

class Solve
{

public:
  Solve()
  {
  }

  void flush()
  {
  }

private:
};

// ----- main() -----

/*
int main()
{
  Solve solve;
  solve.flush();
}
*/

int main()
{
  int n, k;
  cin >> n >> k;
  vector<ll> a(n);
  for (auto i{0}; i < n; ++i)
  {
    cin >> a[i];
  }
  sort(a.rbegin(), a.rend());
  if (a[0] < 0)
  {
    cout << accumulate(a.begin(), a.begin() + k, mint{1}, multiplies()) << endl;
    return 0;
  }
  auto l{0}, r{n - 1};
  mint ans{1};
  if (k & 1)
  {
    ans *= a[l++];
  }
  for (auto t{0}; t < k / 2; ++t)
  {
    if (auto left{a[l] * a[l + 1]}, right{a[r] * a[r - 1]}; left >= right)
    {
      ans *= left;
      l += 2;
    }
    else
    {
      ans *= right;
      r -= 2;
    }
  }
  if (ans == 0)
  {
    assert(false);
  }
  cout << ans << endl;
}
<|endoftext|>


<commit_before>#include "catch.hpp"

#include <lua.hpp>
#include <luwra.hpp>

#include <cstring>
#include <string>
#include <utility>
#include <type_traits>

template <typename I>
struct NumericTest {
	static
	void test(lua_State* state) {
		const I max_value = std::numeric_limits<I>::max();
		const I min_value = std::numeric_limits<I>::lowest();
		const I avg_value = (max_value + min_value) / 2;

		// Largest value
		REQUIRE(luwra::Value<I>::push(state, max_value) == 1);
		REQUIRE(luwra::Value<I>::read(state, -1) == max_value);

		// Lowest value
		REQUIRE(luwra::Value<I>::push(state, min_value) == 1);
		REQUIRE(luwra::Value<I>::read(state, -1) == min_value);

		// Average value
		REQUIRE(luwra::Value<I>::push(state, avg_value) == 1);
		REQUIRE(luwra::Value<I>::read(state, -1) == avg_value);
	}
};

struct TautologyTest {
	static
	void test(lua_State*) {}
};

template <typename B, typename I>
using SelectNumericTest =
	typename std::conditional<
		luwra::internal::NumericContainedValueBase<I, B>::qualifies,
		NumericTest<I>,
		TautologyTest
	>::type;

TEST_CASE("Test Value specialization for numeric C types", "types_numeric") {
	lua_State* state = luaL_newstate();

	// Integer-based types
	SelectNumericTest<lua_Integer, signed short>::test(state);
	SelectNumericTest<lua_Integer, unsigned short>::test(state);
	SelectNumericTest<lua_Integer, signed int>::test(state);
	SelectNumericTest<lua_Integer, unsigned int>::test(state);
	SelectNumericTest<lua_Integer, signed long int>::test(state);
	SelectNumericTest<lua_Integer, unsigned long int>::test(state);
	SelectNumericTest<lua_Integer, signed long long int>::test(state);
	SelectNumericTest<lua_Integer, unsigned long long int>::test(state);

	// Number-based types
	SelectNumericTest<lua_Number, float>::test(state);
	SelectNumericTest<lua_Number, double>::test(state);
	SelectNumericTest<lua_Number, long double>::test(state);

	lua_close(state);
}

TEST_CASE("Test Value specialization for string types", "types_string") {
	lua_State* state = luaL_newstate();

	const char* test_cstr = "Luwra Test String";
	std::string test_str(test_cstr);

	// Safety first
	REQUIRE(test_str == test_cstr);

	// Push both strings
	REQUIRE(luwra::Value<const char*>::push(state, test_cstr) == 1);
	REQUIRE(luwra::Value<std::string>::push(state, test_str) == 1);

	// They must be equal to Lua
	REQUIRE(lua_compare(state, -1, -2, LUA_OPEQ));

	// Extraction as C string must not change the string's value
	const char* l_cstr1 = luwra::Value<const char*>::read(state, -1);
	const char* l_cstr2 = luwra::Value<const char*>::read(state, -2);

	REQUIRE(std::strcmp(test_cstr,        l_cstr1) == 0);
	REQUIRE(std::strcmp(test_cstr,        l_cstr2) == 0);
	REQUIRE(std::strcmp(test_str.c_str(), l_cstr1) == 0);
	REQUIRE(std::strcmp(test_str.c_str(), l_cstr2) == 0);
	REQUIRE(std::strcmp(l_cstr1,          l_cstr2) == 0);

	// Extraction as C++ string must not change the string's value
	std::string l_str1 = luwra::Value<std::string>::read(state, -1);
	std::string l_str2 = luwra::Value<std::string>::read(state, -2);

	REQUIRE(l_str1   == test_cstr);
	REQUIRE(l_str2   == test_cstr);
	REQUIRE(test_str == l_str1);
	REQUIRE(test_str == l_str2);
	REQUIRE(l_str1   == l_str2);

	lua_close(state);
}

TEST_CASE("Test Value specialization for tuples", "types_tuple") {
	lua_State* state = luaL_newstate();

	int a = 13;
	std::string b("Hello");
	float c = 0.37;

	// Push normal tuple
	auto tuple = std::make_tuple(a, b, c);
	REQUIRE(luwra::Value<decltype(tuple)>::push(state, tuple) == 3);

	// Push nested tuple
	auto tuple_nested = std::make_tuple(a, b, c, tuple);
	REQUIRE(luwra::Value<decltype(tuple_nested)>::push(state, tuple_nested) == 6);

	lua_close(state);
}
<commit_msg>Add test case for booleans<commit_after>#include "catch.hpp"

#include <lua.hpp>
#include <luwra.hpp>

#include <cstring>
#include <string>
#include <utility>
#include <type_traits>

template <typename I>
struct NumericTest {
	static
	void test(lua_State* state) {
		const I max_value = std::numeric_limits<I>::max();
		const I min_value = std::numeric_limits<I>::lowest();
		const I avg_value = (max_value + min_value) / 2;

		// Largest value
		REQUIRE(luwra::Value<I>::push(state, max_value) == 1);
		REQUIRE(luwra::Value<I>::read(state, -1) == max_value);

		// Lowest value
		REQUIRE(luwra::Value<I>::push(state, min_value) == 1);
		REQUIRE(luwra::Value<I>::read(state, -1) == min_value);

		// Average value
		REQUIRE(luwra::Value<I>::push(state, avg_value) == 1);
		REQUIRE(luwra::Value<I>::read(state, -1) == avg_value);
	}
};

struct TautologyTest {
	static
	void test(lua_State*) {}
};

template <typename B, typename I>
using SelectNumericTest =
	typename std::conditional<
		luwra::internal::NumericContainedValueBase<I, B>::qualifies,
		NumericTest<I>,
		TautologyTest
	>::type;

TEST_CASE("Test Value specialization for numeric C types", "types_numeric") {
	lua_State* state = luaL_newstate();

	// Integer-based types
	SelectNumericTest<lua_Integer, signed short>::test(state);
	SelectNumericTest<lua_Integer, unsigned short>::test(state);
	SelectNumericTest<lua_Integer, signed int>::test(state);
	SelectNumericTest<lua_Integer, unsigned int>::test(state);
	SelectNumericTest<lua_Integer, signed long int>::test(state);
	SelectNumericTest<lua_Integer, unsigned long int>::test(state);
	SelectNumericTest<lua_Integer, signed long long int>::test(state);
	SelectNumericTest<lua_Integer, unsigned long long int>::test(state);

	// Number-based types
	SelectNumericTest<lua_Number, float>::test(state);
	SelectNumericTest<lua_Number, double>::test(state);
	SelectNumericTest<lua_Number, long double>::test(state);

	lua_close(state);
}

TEST_CASE("Test Value specialization for string types", "types_string") {
	lua_State* state = luaL_newstate();

	const char* test_cstr = "Luwra Test String";
	std::string test_str(test_cstr);

	// Safety first
	REQUIRE(test_str == test_cstr);

	// Push both strings
	REQUIRE(luwra::Value<const char*>::push(state, test_cstr) == 1);
	REQUIRE(luwra::Value<std::string>::push(state, test_str) == 1);

	// They must be equal to Lua
	REQUIRE(lua_compare(state, -1, -2, LUA_OPEQ));

	// Extraction as C string must not change the string's value
	const char* l_cstr1 = luwra::Value<const char*>::read(state, -1);
	const char* l_cstr2 = luwra::Value<const char*>::read(state, -2);

	REQUIRE(std::strcmp(test_cstr,        l_cstr1) == 0);
	REQUIRE(std::strcmp(test_cstr,        l_cstr2) == 0);
	REQUIRE(std::strcmp(test_str.c_str(), l_cstr1) == 0);
	REQUIRE(std::strcmp(test_str.c_str(), l_cstr2) == 0);
	REQUIRE(std::strcmp(l_cstr1,          l_cstr2) == 0);

	// Extraction as C++ string must not change the string's value
	std::string l_str1 = luwra::Value<std::string>::read(state, -1);
	std::string l_str2 = luwra::Value<std::string>::read(state, -2);

	REQUIRE(l_str1   == test_cstr);
	REQUIRE(l_str2   == test_cstr);
	REQUIRE(test_str == l_str1);
	REQUIRE(test_str == l_str2);
	REQUIRE(l_str1   == l_str2);

	lua_close(state);
}

TEST_CASE("Test Value specialization for tuples", "types_tuple") {
	lua_State* state = luaL_newstate();

	int a = 13;
	std::string b("Hello");
	float c = 0.37;

	// Push normal tuple
	auto tuple = std::make_tuple(a, b, c);
	REQUIRE(luwra::Value<decltype(tuple)>::push(state, tuple) == 3);

	// Push nested tuple
	auto tuple_nested = std::make_tuple(a, b, c, tuple);
	REQUIRE(luwra::Value<decltype(tuple_nested)>::push(state, tuple_nested) == 6);

	lua_close(state);
}

TEST_CASE("Test Value specialization for bool") {
	lua_State* state = luaL_newstate();

	bool value = true;

	REQUIRE(luwra::Value<bool>::push(state, value) == 1);
	REQUIRE(luwra::Value<bool>::read(state, -1) == value);

	lua_close(state);
}
<|endoftext|>


<commit_before>#include <image_cloud/common/small_helpers.hpp>
#include <image_cloud/common/type.hpp>
#include <image_cloud/common/calibration/multi_score.hpp>
#include <image_cloud/common/calibration/structs.hpp>

#include <deque>

#include <opencv2/core/core.hpp>
#include <math.h>

#ifndef SEARCH_GRID_6D_H_
#define SEARCH_GRID_6D_H_

namespace search
{
	void grid_setup(Search_setup setup, std::vector<Search_value>& results){
		for(int x=0; x < setup.x.steps_max; ++x)
		{
			for(int y=0; y < setup.y.steps_max; ++y)
			{
				for(int z=0; z < setup.z.steps_max; ++z)
				{
					for(int roll=0; roll < setup.roll.steps_max; ++roll)
					{
						for(int pitch=0; pitch < setup.pitch.steps_max; ++pitch)
						{
							for(int yaw=0; yaw < setup.yaw.steps_max; ++yaw)
							{
								results.push_back(Search_value(setup.x.at(x), setup.y.at(y), setup.z.at(z), setup.roll.at(roll), setup.pitch.at(pitch), setup.yaw.at(yaw)));
							}
						}
					}
				}
			}
		}
	}

	template <typename PointT, typename ImageT>
	void get_best_tf(	tf::Transform in,
						tf::Transform &out,
						const image_geometry::PinholeCameraModel &camera_model,
						const std::deque<pcl::PointCloud<PointT> > &pointclouds,
						const std::deque<cv::Mat> &images,
						float range = 0.5,
						int steps = 3)
	{
		Search_setup search_range;
		std::vector<Search_value> results;

		double r,p,y;
		in.getBasis().getRPY(r, p, y, 1);
		search_range.x.init_range(in.getOrigin()[0], range, steps);
		search_range.y.init_range(in.getOrigin()[1], range, steps);
		search_range.z.init_range(in.getOrigin()[2], range, steps);
		search_range.roll.init_range(r, range, steps);
		search_range.pitch.init_range(p, range, steps);
		search_range.yaw.init_range(y, range, steps);

		grid_setup(search_range, results);

		calculate( camera_model, pointclouds, images, results );

		int best_result_idx = 0;
		long unsigned int best_result = 0;
		for(int i=0; i< results.size(); ++i){
			if(results.at(i).result > best_result){
				best_result_idx = i;
				best_result = results.at(i).result;
			}
		}
		//printf("%d: \t%s\n", best_result_idx, results.at(best_result_idx).to_string().c_str());

		out.setOrigin( tf::Vector3(results.at(best_result_idx).x, results.at(best_result_idx).y, results.at(best_result_idx).z ) );

		tf::Quaternion q;
		q.setRPY(results.at(best_result_idx).roll, results.at(best_result_idx).pitch, results.at(best_result_idx).yaw );
		out.setRotation( q);
	}

	template <typename PointT, typename ImageT>
	inline void calculate(const image_geometry::PinholeCameraModel &camera_model, const std::vector<pcl::PointCloud<PointT> > &pointclouds, const std::vector<cv::Mat> &edge_images, std::vector<Search_value>& results){
		for(int i=0; i < results.size(); ++i){
			score::multi_score<PointT, ImageT>(camera_model, pointclouds, edge_images, results.at(i));
		}
	}
}

#endif
<commit_msg>inlined functions, use new tf helper function<commit_after>#include <image_cloud/common/small_helpers.hpp>
#include <image_cloud/common/type.hpp>
#include <image_cloud/common/calibration/multi_score.hpp>
#include <image_cloud/common/calibration/structs.hpp>

#include <deque>

#include <opencv2/core/core.hpp>
#include <math.h>

#ifndef SEARCH_GRID_6D_H_
#define SEARCH_GRID_6D_H_

namespace search
{
	inline void grid_setup(Search_setup setup, std::vector<Search_value>& results){
		for(int x=0; x < setup.x.steps_max; ++x)
		{
			for(int y=0; y < setup.y.steps_max; ++y)
			{
				for(int z=0; z < setup.z.steps_max; ++z)
				{
					for(int roll=0; roll < setup.roll.steps_max; ++roll)
					{
						for(int pitch=0; pitch < setup.pitch.steps_max; ++pitch)
						{
							for(int yaw=0; yaw < setup.yaw.steps_max; ++yaw)
							{
								results.push_back(Search_value(setup.x.at(x), setup.y.at(y), setup.z.at(z), setup.roll.at(roll), setup.pitch.at(pitch), setup.yaw.at(yaw)));
							}
						}
					}
				}
			}
		}
	}

	template <typename PointT, typename ImageT>
	inline void get_best_tf(	tf::Transform in,
						tf::Transform &out,
						const image_geometry::PinholeCameraModel &camera_model,
						const std::deque<pcl::PointCloud<PointT> > &pointclouds,
						const std::deque<cv::Mat> &images,
						float range = 0.5,
						int steps = 3)
	{
		Search_setup search_range;
		std::vector<Search_value> results;

		double r,p,y;
		in.getBasis().getRPY(r, p, y, 1);
		search_range.x.init_range(in.getOrigin()[0], range, steps);
		search_range.y.init_range(in.getOrigin()[1], range, steps);
		search_range.z.init_range(in.getOrigin()[2], range, steps);
		search_range.roll.init_range(r, range, steps);
		search_range.pitch.init_range(p, range, steps);
		search_range.yaw.init_range(y, range, steps);

		grid_setup(search_range, results);

		calculate( camera_model, pointclouds, images, results );

		int best_result_idx = 0;
		long unsigned int best_result = 0;
		for(int i=0; i< results.size(); ++i){
			if(results.at(i).result > best_result){
				best_result_idx = i;
				best_result = results.at(i).result;
			}
		}
		//printf("%d: \t%s\n", best_result_idx, results.at(best_result_idx).to_string().c_str());

		results.at(best_result_idx).get_transform(out);
	}

	template <typename PointT, typename ImageT>
	inline void calculate(const image_geometry::PinholeCameraModel &camera_model, const std::vector<pcl::PointCloud<PointT> > &pointclouds, const std::vector<cv::Mat> &edge_images, std::vector<Search_value>& results){
		for(int i=0; i < results.size(); ++i){
			score::multi_score<PointT, ImageT>(camera_model, pointclouds, edge_images, results.at(i));
		}
	}
}

#endif
<|endoftext|>