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

Daemon GPL Source Code
Copyright (C) 1999-2010 id Software LLC, a ZeniMax Media company.

This file is part of the Daemon GPL Source Code (Daemon Source Code).

Daemon Source Code is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.

Daemon Source Code is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with Daemon Source Code.  If not, see <http://www.gnu.org/licenses/>.

In addition, the Daemon Source Code is also subject to certain additional terms.
You should have received a copy of these additional terms immediately following the
terms and conditions of the GNU General Public License which accompanied the Daemon
Source Code.  If not, please request a copy in writing from id Software at the address
below.

If you have questions concerning this license or the applicable additional terms, you
may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville,
Maryland 20850 USA.

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

// sv_bot.c

#include "server.h"

/*
==================
SV_BotAllocateClient
==================
*/
int SV_BotAllocateClient( void )
{
	int      i;
	// Never use the first slot otherwise: if a bot connect before the first client game supposedly won't start
	int      firstSlot = std::max( 1, sv_privateClients->integer );
	client_t *cl;

	// find a free client slot which was occupied by a bot (doesn't matter which)
	for ( i = firstSlot, cl = svs.clients + firstSlot; i < sv_maxclients->integer; i++, cl++ )
	{
		if ( cl->state == CS_FREE && cl->netchan.remoteAddress.type == NA_BOT )
		{
			break;
		}
	}

	// find any free client slot
	if ( i == sv_maxclients->integer )
	{
		for ( i = firstSlot, cl = svs.clients; i < sv_maxclients->integer; i++, cl++ )
		{
			if ( cl->state == CS_FREE )
			{
				break;
			}
		}
	}

	if ( i >= sv_maxclients->integer )
	{
		return -1;
	}

	cl->gentity = SV_GentityNum( i );
	cl->gentity->s.number = i;
	cl->state = CS_ACTIVE;
	cl->lastPacketTime = svs.time;
	cl->netchan.remoteAddress.type = NA_BOT;
	cl->rate = 16384;

	return i;
}

/*
==================
SV_BotFreeClient
==================
*/
void SV_BotFreeClient( int clientNum )
{
	client_t *cl;

	if ( clientNum < 0 || clientNum >= sv_maxclients->integer )
	{
		Com_Error( ERR_DROP, "SV_BotFreeClient: bad clientNum: %i", clientNum );
	}

	cl = &svs.clients[ clientNum ];
	cl->state = CS_FREE;
	cl->name[ 0 ] = 0;
}

/*
==================
SV_IsBot
==================
*/
bool SV_IsBot( const client_t* client )
{
	return client->netchan.remoteAddress.type == NA_BOT && client->state == CS_ACTIVE;
}

//
//  * * * BOT AI CODE IS BELOW THIS POINT * * *
//

/*
==================
SV_BotGetConsoleMessage
==================
*/
int SV_BotGetConsoleMessage( int client, char *buf, int size )
{
	client_t *cl;
	int      index;

	cl = &svs.clients[ client ];
	cl->lastPacketTime = svs.time;

	if ( cl->reliableAcknowledge == cl->reliableSequence )
	{
		return qfalse;
	}

	cl->reliableAcknowledge++;
	index = cl->reliableAcknowledge & ( MAX_RELIABLE_COMMANDS - 1 );

	if ( !cl->reliableCommands[ index ][ 0 ] )
	{
		return qfalse;
	}

	//Q_strncpyz( buf, cl->reliableCommands[index], size );
	return qtrue;
}

<commit_msg>Simplify the bot client allocation logic<commit_after>/*
===========================================================================

Daemon GPL Source Code
Copyright (C) 1999-2010 id Software LLC, a ZeniMax Media company.

This file is part of the Daemon GPL Source Code (Daemon Source Code).

Daemon Source Code is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.

Daemon Source Code is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with Daemon Source Code.  If not, see <http://www.gnu.org/licenses/>.

In addition, the Daemon Source Code is also subject to certain additional terms.
You should have received a copy of these additional terms immediately following the
terms and conditions of the GNU General Public License which accompanied the Daemon
Source Code.  If not, please request a copy in writing from id Software at the address
below.

If you have questions concerning this license or the applicable additional terms, you
may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville,
Maryland 20850 USA.

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

// sv_bot.c

#include "server.h"

/*
==================
SV_BotAllocateClient
==================
*/
int SV_BotAllocateClient( void )
{
	int i;
	for (i = std::max(1, sv_privateClients->integer); i < sv_maxclients->integer; i++) {
		if (svs.clients[i].state == CS_FREE) {
			break;
		}
	}

	if (i >= sv_maxclients->integer) {
		return -1;
	}

	client_t* cl = svs.clients + i;
	cl->gentity = SV_GentityNum(i);
	cl->gentity->s.number = i;
	cl->state = CS_ACTIVE;
	cl->lastPacketTime = svs.time;
	cl->netchan.remoteAddress.type = NA_BOT;
	cl->rate = 16384;

	return i;
}

/*
==================
SV_BotFreeClient
==================
*/
void SV_BotFreeClient( int clientNum )
{
	client_t *cl;

	if ( clientNum < 0 || clientNum >= sv_maxclients->integer )
	{
		Com_Error( ERR_DROP, "SV_BotFreeClient: bad clientNum: %i", clientNum );
	}

	cl = &svs.clients[ clientNum ];
	cl->state = CS_FREE;
	cl->name[ 0 ] = 0;
}

/*
==================
SV_IsBot
==================
*/
bool SV_IsBot( const client_t* client )
{
	return client->netchan.remoteAddress.type == NA_BOT && client->state == CS_ACTIVE;
}

//
//  * * * BOT AI CODE IS BELOW THIS POINT * * *
//

/*
==================
SV_BotGetConsoleMessage
==================
*/
int SV_BotGetConsoleMessage( int client, char *buf, int size )
{
	client_t *cl;
	int      index;

	cl = &svs.clients[ client ];
	cl->lastPacketTime = svs.time;

	if ( cl->reliableAcknowledge == cl->reliableSequence )
	{
		return qfalse;
	}

	cl->reliableAcknowledge++;
	index = cl->reliableAcknowledge & ( MAX_RELIABLE_COMMANDS - 1 );

	if ( !cl->reliableCommands[ index ][ 0 ] )
	{
		return qfalse;
	}

	//Q_strncpyz( buf, cl->reliableCommands[index], size );
	return qtrue;
}

<|endoftext|>


<commit_before>#include <rcc/rcc.h>
#include <gpio/gpio.h>
#include <interrupt/interrupt.h>
#include <timer/timer.h>
#include <os/time.h>
#include <usb/usb.h>
#include <usb/descriptor.h>

#include "report_desc.h"
#include "usb_strings.h"
#include "configloader.h"
#include "config.h"

static uint32_t& reset_reason = *(uint32_t*)0x10000000;

static bool do_reset_bootloader;
static bool do_reset;

void reset() {
	SCB.AIRCR = (0x5fa << 16) | (1 << 2); // SYSRESETREQ
}

void reset_bootloader() {
	reset_reason = 0xb007;
	reset();
}

Configloader configloader(0x801f800);

config_t config;

auto dev_desc = device_desc(0x200, 0, 0, 0, 64, 0x1d50, 0x6080, 0x110, 1, 2, 3, 1);
auto conf_desc = configuration_desc(1, 1, 0, 0xc0, 0,
	// HID interface.
	interface_desc(0, 0, 1, 0x03, 0x00, 0x00, 0,
		hid_desc(0x111, 0, 1, 0x22, sizeof(report_desc)),
		endpoint_desc(0x81, 0x03, 16, 1)
	)
);

desc_t dev_desc_p = {sizeof(dev_desc), (void*)&dev_desc};
desc_t conf_desc_p = {sizeof(conf_desc), (void*)&conf_desc};
desc_t report_desc_p = {sizeof(report_desc), (void*)&report_desc};

static Pin usb_dm = GPIOA[11];
static Pin usb_dp = GPIOA[12];
static Pin usb_pu = GPIOA[15];

static PinArray button_inputs = GPIOB.array(0, 10);
static PinArray button_leds = GPIOC.array(0, 10);

static Pin qe1a = GPIOA[0];
static Pin qe1b = GPIOA[1];
static Pin qe2a = GPIOA[6];
static Pin qe2b = GPIOA[7];

static Pin led1 = GPIOA[8];
static Pin led2 = GPIOA[9];

USB_f1 usb(USB, dev_desc_p, conf_desc_p);

uint32_t last_led_time;

class HID_arcin : public USB_HID {
	private:
		bool set_feature_bootloader(bootloader_report_t* report) {
			switch(report->func) {
				case 0:
					return true;

				case 0x10: // Reset to bootloader
					do_reset_bootloader = true;
					return true;

				case 0x20: // Reset to runtime
					do_reset = true;
					return true;

				default:
					return false;
			}
		}

		bool set_feature_config(config_report_t* report) {
			if(report->segment != 0) {
				return false;
			}

			configloader.write(report->size, report->data);

			return true;
		}

		bool get_feature_config() {
			config_report_t report = {0xc0, 0, sizeof(config)};

			memcpy(report.data, &config, sizeof(config));

			usb.write(0, (uint32_t*)&report, sizeof(report));

			return true;
		}

	public:
		HID_arcin(USB_generic& usbd, desc_t rdesc) : USB_HID(usbd, rdesc, 0, 1, 64) {}

	protected:
		virtual bool set_output_report(uint32_t* buf, uint32_t len) {
			if(len != sizeof(output_report_t)) {
				return false;
			}

			output_report_t* report = (output_report_t*)buf;

			last_led_time = Time::time();
			button_leds.set(report->leds);
			return true;
		}

		virtual bool set_feature_report(uint32_t* buf, uint32_t len) {
			switch(*buf & 0xff) {
				case 0xb0:
					if(len != sizeof(bootloader_report_t)) {
						return false;
					}

					return set_feature_bootloader((bootloader_report_t*)buf);

				case 0xc0:
					if(len != sizeof(config_report_t)) {
						return false;
					}

					return set_feature_config((config_report_t*)buf);

				default:
					return false;
			}
		}

		virtual bool get_feature_report(uint8_t report_id) {
			switch(report_id) {
				case 0xc0:
					return get_feature_config();

				default:
					return false;
			}
		}
};

HID_arcin usb_hid(usb, report_desc_p);

USB_strings usb_strings(usb, config.label);

int main() {
	rcc_init();

	// Initialize system timer.
	STK.LOAD = 72000000 / 8 / 1000; // 1000 Hz.
	STK.CTRL = 0x03;

	// Load config.
	configloader.read(sizeof(config), &config);

	RCC.enable(RCC.GPIOA);
	RCC.enable(RCC.GPIOB);
	RCC.enable(RCC.GPIOC);

	usb_dm.set_mode(Pin::AF);
	usb_dm.set_af(14);
	usb_dp.set_mode(Pin::AF);
	usb_dp.set_af(14);

	RCC.enable(RCC.USB);

	usb.init();

	usb_pu.set_mode(Pin::Output);
	usb_pu.on();

	button_inputs.set_mode(Pin::Input);
	button_inputs.set_pull(Pin::PullUp);

	button_leds.set_mode(Pin::Output);

	led1.set_mode(Pin::Output);
	led1.on();

	led2.set_mode(Pin::Output);
	led2.on();

	RCC.enable(RCC.TIM2);
	RCC.enable(RCC.TIM3);

	if(!(config.flags & (1 << 1))) {
		TIM2.CCER = 1 << 1;
	}

	TIM2.CCMR1 = (1 << 8) | (1 << 0);
	TIM2.SMCR = 3;
	TIM2.CR1 = 1;

	if(config.qe1_sens < 0) {
		TIM2.ARR = 256 * -config.qe1_sens - 1;
	} else {
		TIM2.ARR = 256 - 1;
	}

	if(!(config.flags & (1 << 2))) {
		TIM3.CCER = 1 << 1;
	}

	TIM3.CCMR1 = (1 << 8) | (1 << 0);
	TIM3.SMCR = 3;
	TIM3.CR1 = 1;

	if(config.qe2_sens < 0) {
		TIM3.ARR = 256 * -config.qe2_sens - 1;
	} else {
		TIM3.ARR = 256 - 1;
	}

	qe1a.set_af(1);
	qe1b.set_af(1);
	qe1a.set_mode(Pin::AF);
	qe1b.set_mode(Pin::AF);

	qe2a.set_af(2);
	qe2b.set_af(2);
	qe2a.set_mode(Pin::AF);
	qe2b.set_mode(Pin::AF);

	uint8_t last_x = 0;
	uint8_t last_y = 0;

	int8_t state_x = 0;
	int8_t state_y = 0;

	while(1) {
		usb.process();

		uint16_t buttons = button_inputs.get() ^ 0x7ff;

		if(do_reset_bootloader) {
			Time::sleep(10);
			reset_bootloader();
		}

		if(do_reset) {
			Time::sleep(10);
			reset();
		}

		if(Time::time() - last_led_time > 1000) {
			button_leds.set(buttons);
		}

		if(usb.ep_ready(1)) {
			uint32_t qe1_count = TIM2.CNT;
			uint32_t qe2_count = TIM3.CNT;

			int8_t rx = qe1_count - last_x;
			int8_t ry = qe2_count - last_y;

			if(rx > 1) {
				state_x = 100;
				last_x = qe1_count;
			} else if(rx < -1) {
				state_x = -100;
				last_x = qe1_count;
			} else if(state_x > 0) {
				state_x--;
				last_x = qe1_count;
			} else if(state_x < 0) {
				state_x++;
				last_x = qe1_count;
			}

			if(ry > 1) {
				state_y = 100;
				last_y = qe2_count;
			} else if(ry < -1) {
				state_y = -100;
				last_y = qe2_count;
			} else if(state_y > 0) {
				state_y--;
				last_y = qe2_count;
			} else if(state_y < 0) {
				state_y++;
				last_y = qe2_count;
			}

			if(state_x > 0) {
				buttons |= 1 << 11;
			} else if(state_x < 0) {
				buttons |= 1 << 12;
			}

			if(state_y > 0) {
				buttons |= 1 << 13;
			} else if(state_y < 0) {
				buttons |= 1 << 14;
			}

			if(config.qe1_sens < 0) {
				qe1_count /= -config.qe1_sens;
			} else if(config.qe1_sens > 0) {
				qe1_count *= config.qe1_sens;
			}

			if(config.qe2_sens < 0) {
				qe2_count /= -config.qe2_sens;
			} else if(config.qe2_sens > 0) {
				qe2_count *= config.qe2_sens;
			}

			input_report_t report = {1, buttons, uint8_t(qe1_count), uint8_t(qe2_count)};

			usb.write(1, (uint32_t*)&report, sizeof(report));
		}
	}
}
<commit_msg>Added common axis interface to allow switching between QE/analog.<commit_after>#include <rcc/rcc.h>
#include <gpio/gpio.h>
#include <interrupt/interrupt.h>
#include <timer/timer.h>
#include <os/time.h>
#include <usb/usb.h>
#include <usb/descriptor.h>

#include "report_desc.h"
#include "usb_strings.h"
#include "configloader.h"
#include "config.h"

static uint32_t& reset_reason = *(uint32_t*)0x10000000;

static bool do_reset_bootloader;
static bool do_reset;

void reset() {
	SCB.AIRCR = (0x5fa << 16) | (1 << 2); // SYSRESETREQ
}

void reset_bootloader() {
	reset_reason = 0xb007;
	reset();
}

Configloader configloader(0x801f800);

config_t config;

auto dev_desc = device_desc(0x200, 0, 0, 0, 64, 0x1d50, 0x6080, 0x110, 1, 2, 3, 1);
auto conf_desc = configuration_desc(1, 1, 0, 0xc0, 0,
	// HID interface.
	interface_desc(0, 0, 1, 0x03, 0x00, 0x00, 0,
		hid_desc(0x111, 0, 1, 0x22, sizeof(report_desc)),
		endpoint_desc(0x81, 0x03, 16, 1)
	)
);

desc_t dev_desc_p = {sizeof(dev_desc), (void*)&dev_desc};
desc_t conf_desc_p = {sizeof(conf_desc), (void*)&conf_desc};
desc_t report_desc_p = {sizeof(report_desc), (void*)&report_desc};

static Pin usb_dm = GPIOA[11];
static Pin usb_dp = GPIOA[12];
static Pin usb_pu = GPIOA[15];

static PinArray button_inputs = GPIOB.array(0, 10);
static PinArray button_leds = GPIOC.array(0, 10);

static Pin qe1a = GPIOA[0];
static Pin qe1b = GPIOA[1];
static Pin qe2a = GPIOA[6];
static Pin qe2b = GPIOA[7];

static Pin led1 = GPIOA[8];
static Pin led2 = GPIOA[9];

USB_f1 usb(USB, dev_desc_p, conf_desc_p);

uint32_t last_led_time;

class HID_arcin : public USB_HID {
	private:
		bool set_feature_bootloader(bootloader_report_t* report) {
			switch(report->func) {
				case 0:
					return true;

				case 0x10: // Reset to bootloader
					do_reset_bootloader = true;
					return true;

				case 0x20: // Reset to runtime
					do_reset = true;
					return true;

				default:
					return false;
			}
		}

		bool set_feature_config(config_report_t* report) {
			if(report->segment != 0) {
				return false;
			}

			configloader.write(report->size, report->data);

			return true;
		}

		bool get_feature_config() {
			config_report_t report = {0xc0, 0, sizeof(config)};

			memcpy(report.data, &config, sizeof(config));

			usb.write(0, (uint32_t*)&report, sizeof(report));

			return true;
		}

	public:
		HID_arcin(USB_generic& usbd, desc_t rdesc) : USB_HID(usbd, rdesc, 0, 1, 64) {}

	protected:
		virtual bool set_output_report(uint32_t* buf, uint32_t len) {
			if(len != sizeof(output_report_t)) {
				return false;
			}

			output_report_t* report = (output_report_t*)buf;

			last_led_time = Time::time();
			button_leds.set(report->leds);
			return true;
		}

		virtual bool set_feature_report(uint32_t* buf, uint32_t len) {
			switch(*buf & 0xff) {
				case 0xb0:
					if(len != sizeof(bootloader_report_t)) {
						return false;
					}

					return set_feature_bootloader((bootloader_report_t*)buf);

				case 0xc0:
					if(len != sizeof(config_report_t)) {
						return false;
					}

					return set_feature_config((config_report_t*)buf);

				default:
					return false;
			}
		}

		virtual bool get_feature_report(uint8_t report_id) {
			switch(report_id) {
				case 0xc0:
					return get_feature_config();

				default:
					return false;
			}
		}
};

HID_arcin usb_hid(usb, report_desc_p);

USB_strings usb_strings(usb, config.label);

class Axis {
	public:
		virtual uint32_t get() = 0;
};

class QEAxis : public Axis {
	private:
		TIM_t& tim;

	public:
		QEAxis(TIM_t& t) : tim(t) {}

		void enable(bool invert, int8_t sens) {
			if(!invert) {
				tim.CCER = 1 << 1;
			}

			tim.CCMR1 = (1 << 8) | (1 << 0);
			tim.SMCR = 3;
			tim.CR1 = 1;

			if(sens < 0) {
				tim.ARR = 256 * -sens - 1;
			} else {
				tim.ARR = 256 - 1;
			}
		}

		virtual uint32_t get() final {
			return tim.CNT;
		}
};

QEAxis axis_qe1(TIM2);
QEAxis axis_qe2(TIM3);

int main() {
	rcc_init();

	// Initialize system timer.
	STK.LOAD = 72000000 / 8 / 1000; // 1000 Hz.
	STK.CTRL = 0x03;

	// Load config.
	configloader.read(sizeof(config), &config);

	RCC.enable(RCC.GPIOA);
	RCC.enable(RCC.GPIOB);
	RCC.enable(RCC.GPIOC);

	usb_dm.set_mode(Pin::AF);
	usb_dm.set_af(14);
	usb_dp.set_mode(Pin::AF);
	usb_dp.set_af(14);

	RCC.enable(RCC.USB);

	usb.init();

	usb_pu.set_mode(Pin::Output);
	usb_pu.on();

	button_inputs.set_mode(Pin::Input);
	button_inputs.set_pull(Pin::PullUp);

	button_leds.set_mode(Pin::Output);

	led1.set_mode(Pin::Output);
	led1.on();

	led2.set_mode(Pin::Output);
	led2.on();

	Axis* axis_1;

	if(0) {
		// TODO: Analog mode.

		//axis_1 = &ana_1;
	} else {
		RCC.enable(RCC.TIM2);

		axis_qe1.enable(config.flags & (1 << 1), config.qe1_sens);

		qe1a.set_af(1);
		qe1b.set_af(1);
		qe1a.set_mode(Pin::AF);
		qe1b.set_mode(Pin::AF);

		axis_1 = &axis_qe1;
	}

	Axis* axis_2;

	if(0) {
		// TODO: Analog mode.

		//axis_2 = &ana_2;
	} else {
		RCC.enable(RCC.TIM3);

		axis_qe2.enable(config.flags & (1 << 2), config.qe2_sens);

		qe2a.set_af(1);
		qe2b.set_af(1);
		qe2a.set_mode(Pin::AF);
		qe2b.set_mode(Pin::AF);

		axis_2 = &axis_qe2;
	}

	uint8_t last_x = 0;
	uint8_t last_y = 0;

	int8_t state_x = 0;
	int8_t state_y = 0;

	while(1) {
		usb.process();

		uint16_t buttons = button_inputs.get() ^ 0x7ff;

		if(do_reset_bootloader) {
			Time::sleep(10);
			reset_bootloader();
		}

		if(do_reset) {
			Time::sleep(10);
			reset();
		}

		if(Time::time() - last_led_time > 1000) {
			button_leds.set(buttons);
		}

		if(usb.ep_ready(1)) {
			uint32_t qe1_count = axis_1->get();
			uint32_t qe2_count = axis_2->get();

			int8_t rx = qe1_count - last_x;
			int8_t ry = qe2_count - last_y;

			if(rx > 1) {
				state_x = 100;
				last_x = qe1_count;
			} else if(rx < -1) {
				state_x = -100;
				last_x = qe1_count;
			} else if(state_x > 0) {
				state_x--;
				last_x = qe1_count;
			} else if(state_x < 0) {
				state_x++;
				last_x = qe1_count;
			}

			if(ry > 1) {
				state_y = 100;
				last_y = qe2_count;
			} else if(ry < -1) {
				state_y = -100;
				last_y = qe2_count;
			} else if(state_y > 0) {
				state_y--;
				last_y = qe2_count;
			} else if(state_y < 0) {
				state_y++;
				last_y = qe2_count;
			}

			if(state_x > 0) {
				buttons |= 1 << 11;
			} else if(state_x < 0) {
				buttons |= 1 << 12;
			}

			if(state_y > 0) {
				buttons |= 1 << 13;
			} else if(state_y < 0) {
				buttons |= 1 << 14;
			}

			if(config.qe1_sens < 0) {
				qe1_count /= -config.qe1_sens;
			} else if(config.qe1_sens > 0) {
				qe1_count *= config.qe1_sens;
			}

			if(config.qe2_sens < 0) {
				qe2_count /= -config.qe2_sens;
			} else if(config.qe2_sens > 0) {
				qe2_count *= config.qe2_sens;
			}

			input_report_t report = {1, buttons, uint8_t(qe1_count), uint8_t(qe2_count)};

			usb.write(1, (uint32_t*)&report, sizeof(report));
		}
	}
}
<|endoftext|>


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

#ifndef EXTENSIONS_CONFIG_LDAP_LDAPUSERPROFILE_HXX_
#include "ldapuserprofilebe.hxx"
#endif //CONFIGMGR_BACKEND_LDAPUSERPROFILE_HXX_
#ifndef _COM_SUN_STAR_REGISTRY_XREGISTRYKEY_HPP_
#include <com/sun/star/registry/XRegistryKey.hpp>
#endif
#ifndef _CPPUHELPER_IMPLEMENTATIONENTRY_HXX_
#include <cppuhelper/implementationentry.hxx>
#endif // _CPPUHELPER_IMPLEMENTATIONENTRY_HXX_

#ifndef _RTL_USTRBUF_HXX_
#include <rtl/ustrbuf.hxx>
#endif // _RTL_USTRBUF_HXX_

using namespace extensions::config::ldap ;

//==============================================================================

static uno::Reference<uno::XInterface> SAL_CALL createLdapUserProfileBe(
                   const uno::Reference<uno::XComponentContext>& aContext) {
    return * new LdapUserProfileBe(aContext) ;
}
//------------------------------------------------------------------------------

static const cppu::ImplementationEntry kImplementations_entries[] =
{
    {
        createLdapUserProfileBe,
        LdapUserProfileBe::getLdapUserProfileBeName,
        LdapUserProfileBe::getLdapUserProfileBeServiceNames,
        cppu::createSingleComponentFactory,
        NULL,
        0
    },
    { NULL }
} ;
//------------------------------------------------------------------------------

extern "C" void SAL_CALL component_getImplementationEnvironment(
                                            const sal_Char **aEnvTypeName,
                                            uno_Environment **aEnvironment) {
    *aEnvTypeName = CPPU_CURRENT_LANGUAGE_BINDING_NAME ;
}
//------------------------------------------------------------------------------

extern "C" sal_Bool SAL_CALL component_writeInfo(void *aServiceManager,
                                                 void *aRegistryKey) {
    using namespace ::com::sun::star::registry;
    if (aRegistryKey)
    {

        /** Service factory */
        uno::Reference<lang::XMultiServiceFactory> xFactory
            (reinterpret_cast<lang::XMultiServiceFactory*> (aServiceManager),
             uno::UNO_QUERY);

        rtl::OUStringBuffer aImplKeyName;
        aImplKeyName.appendAscii("/");
        aImplKeyName.append(LdapUserProfileBe::getLdapUserProfileBeName());

        rtl::OUString aMainKeyName(RTL_CONSTASCII_USTRINGPARAM("/UNO/SERVICES"));

        uno::Reference<XRegistryKey> xNewImplKey(
            reinterpret_cast<XRegistryKey*>
            (aRegistryKey)->createKey(aImplKeyName.makeStringAndClear()));

        uno::Reference<XRegistryKey> xNewKey(
            xNewImplKey->createKey(aMainKeyName));

        //Now register associated service names
        uno::Sequence<rtl::OUString> sServiceNames =
            LdapUserProfileBe::getLdapUserProfileBeServiceNames();
        for (sal_Int32 i = 0 ; i < sServiceNames.getLength() ; ++ i)
        {
            xNewKey->createKey(sServiceNames[i]);
        }
        //Now register associated org.openoffice.UserProfile component
        //that this backend supports under xNewImplKey
        uno::Reference<XRegistryKey> xComponentKey(
            xNewImplKey->createKey(rtl::OUString::createFromAscii
            ("/DATA/SupportedComponents")));

        uno::Sequence<rtl::OUString> aComponentList(1);
        aComponentList[0]= rtl::OUString::createFromAscii
            ("org.openoffice.UserProfile");

        xComponentKey->setAsciiListValue(aComponentList);
        return sal_True;
    }
    return sal_False;
}
//------------------------------------------------------------------------------

extern "C" void *component_getFactory(const sal_Char *aImplementationName,
                                      void *aServiceManager,
                                      void *aRegistryKey) {
    return cppu::component_getFactoryHelper(aImplementationName,
                                            aServiceManager,
                                            aRegistryKey,
                                            kImplementations_entries) ;
}
//------------------------------------------------------------------------------
<commit_msg>INTEGRATION: CWS ooo19126 (1.2.222); FILE MERGED 2005/09/05 12:58:51 rt 1.2.222.1: #i54170# Change license header: remove SISSL<commit_after>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: componentdef.cxx,v $
 *
 *  $Revision: 1.3 $
 *
 *  last change: $Author: rt $ $Date: 2005-09-08 19:22:12 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    This library is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *    Lesser General Public License for more details.
 *
 *    You should have received a copy of the GNU Lesser General Public
 *    License along with this library; if not, write to the Free Software
 *    Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/

#ifndef EXTENSIONS_CONFIG_LDAP_LDAPUSERPROFILE_HXX_
#include "ldapuserprofilebe.hxx"
#endif //CONFIGMGR_BACKEND_LDAPUSERPROFILE_HXX_
#ifndef _COM_SUN_STAR_REGISTRY_XREGISTRYKEY_HPP_
#include <com/sun/star/registry/XRegistryKey.hpp>
#endif
#ifndef _CPPUHELPER_IMPLEMENTATIONENTRY_HXX_
#include <cppuhelper/implementationentry.hxx>
#endif // _CPPUHELPER_IMPLEMENTATIONENTRY_HXX_

#ifndef _RTL_USTRBUF_HXX_
#include <rtl/ustrbuf.hxx>
#endif // _RTL_USTRBUF_HXX_

using namespace extensions::config::ldap ;

//==============================================================================

static uno::Reference<uno::XInterface> SAL_CALL createLdapUserProfileBe(
                   const uno::Reference<uno::XComponentContext>& aContext) {
    return * new LdapUserProfileBe(aContext) ;
}
//------------------------------------------------------------------------------

static const cppu::ImplementationEntry kImplementations_entries[] =
{
    {
        createLdapUserProfileBe,
        LdapUserProfileBe::getLdapUserProfileBeName,
        LdapUserProfileBe::getLdapUserProfileBeServiceNames,
        cppu::createSingleComponentFactory,
        NULL,
        0
    },
    { NULL }
} ;
//------------------------------------------------------------------------------

extern "C" void SAL_CALL component_getImplementationEnvironment(
                                            const sal_Char **aEnvTypeName,
                                            uno_Environment **aEnvironment) {
    *aEnvTypeName = CPPU_CURRENT_LANGUAGE_BINDING_NAME ;
}
//------------------------------------------------------------------------------

extern "C" sal_Bool SAL_CALL component_writeInfo(void *aServiceManager,
                                                 void *aRegistryKey) {
    using namespace ::com::sun::star::registry;
    if (aRegistryKey)
    {

        /** Service factory */
        uno::Reference<lang::XMultiServiceFactory> xFactory
            (reinterpret_cast<lang::XMultiServiceFactory*> (aServiceManager),
             uno::UNO_QUERY);

        rtl::OUStringBuffer aImplKeyName;
        aImplKeyName.appendAscii("/");
        aImplKeyName.append(LdapUserProfileBe::getLdapUserProfileBeName());

        rtl::OUString aMainKeyName(RTL_CONSTASCII_USTRINGPARAM("/UNO/SERVICES"));

        uno::Reference<XRegistryKey> xNewImplKey(
            reinterpret_cast<XRegistryKey*>
            (aRegistryKey)->createKey(aImplKeyName.makeStringAndClear()));

        uno::Reference<XRegistryKey> xNewKey(
            xNewImplKey->createKey(aMainKeyName));

        //Now register associated service names
        uno::Sequence<rtl::OUString> sServiceNames =
            LdapUserProfileBe::getLdapUserProfileBeServiceNames();
        for (sal_Int32 i = 0 ; i < sServiceNames.getLength() ; ++ i)
        {
            xNewKey->createKey(sServiceNames[i]);
        }
        //Now register associated org.openoffice.UserProfile component
        //that this backend supports under xNewImplKey
        uno::Reference<XRegistryKey> xComponentKey(
            xNewImplKey->createKey(rtl::OUString::createFromAscii
            ("/DATA/SupportedComponents")));

        uno::Sequence<rtl::OUString> aComponentList(1);
        aComponentList[0]= rtl::OUString::createFromAscii
            ("org.openoffice.UserProfile");

        xComponentKey->setAsciiListValue(aComponentList);
        return sal_True;
    }
    return sal_False;
}
//------------------------------------------------------------------------------

extern "C" void *component_getFactory(const sal_Char *aImplementationName,
                                      void *aServiceManager,
                                      void *aRegistryKey) {
    return cppu::component_getFactoryHelper(aImplementationName,
                                            aServiceManager,
                                            aRegistryKey,
                                            kImplementations_entries) ;
}
//------------------------------------------------------------------------------
<|endoftext|>


<commit_before>#include <iomanip>
#include <stdexcept>
#include "performance.h"

using namespace std;
using namespace cv;

void TestSystem::setWorkingDir(const string& val)
{
    working_dir_ = val;
}

void TestSystem::setTestFilter(const string& val)
{
    test_filter_ = val;
}

void TestSystem::run()
{
    // Run test initializers
    vector<Runnable*>::iterator it = inits_.begin();
    for (; it != inits_.end(); ++it)
    {
        if ((*it)->name().find(test_filter_, 0) != string::npos)
            (*it)->run();
    }

    printHeading();

    // Run tests
    it = tests_.begin();
    for (; it != tests_.end(); ++it)
    {
        try
        {
            if ((*it)->name().find(test_filter_, 0) != string::npos)
            {
                cout << endl << (*it)->name() << ":\n";
                (*it)->run();
                finishCurrentSubtest();
            }
        }
        catch (const Exception&)
        {
            // Message is printed via callback
            resetCurrentSubtest();
        }
        catch (const runtime_error& e)
        {
            printError(e.what());
            resetCurrentSubtest();
        }
    }

    printSummary();
}

void TestSystem::finishCurrentSubtest()
{
    if (cur_subtest_is_empty_)
        // There is no need to print subtest statistics
        return;

    int cpu_time = static_cast<int>(cpu_elapsed_ / getTickFrequency() * 1000.0);
    int gpu_time = static_cast<int>(gpu_elapsed_ / getTickFrequency() * 1000.0);

    double speedup = static_cast<double>(cpu_elapsed_) /
                     std::max((int64)1, gpu_elapsed_);
    speedup_total_ += speedup;

    printMetrics(cpu_time, gpu_time, speedup);

    num_subtests_called_++;
    resetCurrentSubtest();
}

void TestSystem::printHeading()
{
    cout << setiosflags(ios_base::left);
    cout << TAB << setw(10) << "CPU, ms" << setw(10) << "GPU, ms"
        << setw(14) << "SPEEDUP"
        << "DESCRIPTION\n";
    cout << resetiosflags(ios_base::left);
}

void TestSystem::printSummary()
{
    cout << setiosflags(ios_base::fixed);
    cout << "\naverage GPU speedup: x"
        << setprecision(3) << speedup_total_ / std::max(1, num_subtests_called_)
        << endl;
    cout << resetiosflags(ios_base::fixed);
}

void TestSystem::printMetrics(double cpu_time, double gpu_time, double speedup)
{
    cout << TAB << setiosflags(ios_base::left);
    stringstream stream;

    stream << cpu_time;
    cout << setw(10) << stream.str();

    stream.str("");
    stream << gpu_time;
    cout << setw(10) << stream.str();

    stream.str("");
    stream << "x" << setprecision(3) << speedup;
    cout << setw(14) << stream.str();

    cout << cur_subtest_description_.str();
    cout << resetiosflags(ios_base::left) << endl;
}

void TestSystem::printError(const std::string& msg)
{
    cout << TAB << "[error: " << msg << "] " << cur_subtest_description_.str() << endl;
}

void gen(Mat& mat, int rows, int cols, int type, Scalar low, Scalar high)
{
    mat.create(rows, cols, type);
    RNG rng(0);
    rng.fill(mat, RNG::UNIFORM, low, high);
}

string abspath(const string& relpath)
{
    return TestSystem::instance().workingDir() + relpath;
}

int CV_CDECL cvErrorCallback(int /*status*/, const char* /*func_name*/,
                             const char* err_msg, const char* /*file_name*/,
                             int /*line*/, void* /*userdata*/)
{
    TestSystem::instance().printError(err_msg);
    return 0;
}

int main(int argc, char** argv)
{
    if (argc < 3)
        cout << "Usage: performance_gpu <test_filter> <working_dir_with_slash>\n\n";
    if (argc >= 2)
        TestSystem::instance().setTestFilter(argv[1]);
    if (argc >= 3)
        TestSystem::instance().setWorkingDir(argv[2]);

    redirectError(cvErrorCallback);
    TestSystem::instance().run();

    return 0;
}
<commit_msg>added command line args parsing into gpu performance sample<commit_after>#include <iomanip>
#include <stdexcept>
#include <string>
#include "performance.h"

using namespace std;
using namespace cv;

void TestSystem::setWorkingDir(const string& val)
{
    working_dir_ = val;
}

void TestSystem::setTestFilter(const string& val)
{
    test_filter_ = val;
}

void TestSystem::run()
{
    // Run test initializers
    vector<Runnable*>::iterator it = inits_.begin();
    for (; it != inits_.end(); ++it)
    {
        if ((*it)->name().find(test_filter_, 0) != string::npos)
            (*it)->run();
    }

    printHeading();

    // Run tests
    it = tests_.begin();
    for (; it != tests_.end(); ++it)
    {
        try
        {
            if ((*it)->name().find(test_filter_, 0) != string::npos)
            {
                cout << endl << (*it)->name() << ":\n";
                (*it)->run();
                finishCurrentSubtest();
            }
        }
        catch (const Exception&)
        {
            // Message is printed via callback
            resetCurrentSubtest();
        }
        catch (const runtime_error& e)
        {
            printError(e.what());
            resetCurrentSubtest();
        }
    }

    printSummary();
}

void TestSystem::finishCurrentSubtest()
{
    if (cur_subtest_is_empty_)
        // There is no need to print subtest statistics
        return;

    int cpu_time = static_cast<int>(cpu_elapsed_ / getTickFrequency() * 1000.0);
    int gpu_time = static_cast<int>(gpu_elapsed_ / getTickFrequency() * 1000.0);

    double speedup = static_cast<double>(cpu_elapsed_) /
                     std::max((int64)1, gpu_elapsed_);
    speedup_total_ += speedup;

    printMetrics(cpu_time, gpu_time, speedup);

    num_subtests_called_++;
    resetCurrentSubtest();
}

void TestSystem::printHeading()
{
    cout << setiosflags(ios_base::left);
    cout << TAB << setw(10) << "CPU, ms" << setw(10) << "GPU, ms"
        << setw(14) << "SPEEDUP"
        << "DESCRIPTION\n";
    cout << resetiosflags(ios_base::left);
}

void TestSystem::printSummary()
{
    cout << setiosflags(ios_base::fixed);
    cout << "\naverage GPU speedup: x"
        << setprecision(3) << speedup_total_ / std::max(1, num_subtests_called_)
        << endl;
    cout << resetiosflags(ios_base::fixed);
}

void TestSystem::printMetrics(double cpu_time, double gpu_time, double speedup)
{
    cout << TAB << setiosflags(ios_base::left);
    stringstream stream;

    stream << cpu_time;
    cout << setw(10) << stream.str();

    stream.str("");
    stream << gpu_time;
    cout << setw(10) << stream.str();

    stream.str("");
    stream << "x" << setprecision(3) << speedup;
    cout << setw(14) << stream.str();

    cout << cur_subtest_description_.str();
    cout << resetiosflags(ios_base::left) << endl;
}

void TestSystem::printError(const std::string& msg)
{
    cout << TAB << "[error: " << msg << "] " << cur_subtest_description_.str() << endl;
}

void gen(Mat& mat, int rows, int cols, int type, Scalar low, Scalar high)
{
    mat.create(rows, cols, type);
    RNG rng(0);
    rng.fill(mat, RNG::UNIFORM, low, high);
}

string abspath(const string& relpath)
{
    return TestSystem::instance().workingDir() + relpath;
}

int CV_CDECL cvErrorCallback(int /*status*/, const char* /*func_name*/,
                             const char* err_msg, const char* /*file_name*/,
                             int /*line*/, void* /*userdata*/)
{
    TestSystem::instance().printError(err_msg);
    return 0;
}

int main(int argc, char** argv)
{
    // Parse command line arguments
    for (int i = 1; i < argc; ++i)
    {
        string key = argv[i];
        if (key == "--help")
        {
            cout << "Usage: performance_gpu [--filter <test_filter>] [--working-dir <working_dir_with_slash>]\n";
            return 0;
        }
        if (key == "--filter" && i + 1 < argc)
            TestSystem::instance().setTestFilter(argv[++i]);
        else if (key == "--working-dir" && i + 1 < argc)
            TestSystem::instance().setWorkingDir(argv[++i]);
        else
        {
            cout << "Unknown parameter: '" << key << "'" << endl;
            return -1;
        }
    }

    redirectError(cvErrorCallback);
    TestSystem::instance().run();

    return 0;
}
<|endoftext|>


<commit_before>// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.

#include "resultconfig.h"
#include <vespa/vespalib/util/exceptions.h>
#include <vespa/vespalib/stllike/hash_map.hpp>

#include <vespa/log/log.h>
LOG_SETUP(".searchlib.docsummary.resultconfig");

namespace search::docsummary {

void
ResultConfig::Clean()
{
    _classLookup.clear();
    _nameLookup.clear();
}

void
ResultConfig::Init()
{
}

ResultConfig::ResultConfig()
    : _defaultSummaryId(-1),
      _classLookup(),
      _nameLookup()
{
    Init();
}

ResultConfig::~ResultConfig()
{
    Clean();
}

const char *
ResultConfig::GetResTypeName(ResType type)
{
    switch (type) {
    case RES_INT:         return "integer";
    case RES_SHORT:       return "short";
    case RES_BYTE:        return "byte";
    case RES_BOOL:        return "bool";
    case RES_FLOAT:       return "float";
    case RES_DOUBLE:      return "double";
    case RES_INT64:       return "int64";
    case RES_STRING:      return "string";
    case RES_DATA:        return "data";
    case RES_LONG_STRING: return "longstring";
    case RES_LONG_DATA:   return "longdata";
    case RES_XMLSTRING:   return "xmlstring";
    case RES_JSONSTRING:  return "jsonstring";
    case RES_TENSOR:  return "tensor";
    case RES_FEATUREDATA: return "featuredata";
    }
    return "unknown-type";
}

void
ResultConfig::Reset()
{
    if (! _classLookup.empty() || _fieldEnum.GetNumEntries() > 0) {
        Clean();
        Init();
    }
}

ResultClass *
ResultConfig::AddResultClass(const char *name, uint32_t id)
{
    ResultClass *ret = nullptr;

    if (id != NoClassID() && (_classLookup.find(id) == _classLookup.end())) {
        ResultClass::UP rc(new ResultClass(name, id, _fieldEnum));
        ret = rc.get();
        _classLookup[id] = std::move(rc);
        if (_nameLookup.find(name) != _nameLookup.end()) {
            LOG(warning, "Duplicate result class name: %s (now maps to class id %u)", name, id);
        }
        _nameLookup[name] = id;
    }
    return ret;
}

const ResultClass*
ResultConfig::LookupResultClass(uint32_t id) const
{
    IdMap::const_iterator it(_classLookup.find(id));
    return (it != _classLookup.end()) ? it->second.get() : nullptr;
}

uint32_t
ResultConfig::LookupResultClassId(const vespalib::string &name, uint32_t def) const
{
    NameMap::const_iterator found(_nameLookup.find(name));
    return (found != _nameLookup.end()) ? found->second : def;
}

uint32_t
ResultConfig::LookupResultClassId(const vespalib::string &name) const
{
    return LookupResultClassId(name, (name.empty() || (name == "default")) ? _defaultSummaryId : NoClassID());
}

void
ResultConfig::CreateEnumMaps()
{
    for (auto & entry : _classLookup) {
       entry.second->CreateEnumMap();
    }
}

bool
ResultConfig::ReadConfig(const vespa::config::search::SummaryConfig &cfg, const char *configId)
{
    bool rc = true;
    Reset();
    int    maxclassID = 0x7fffffff; // avoid negative classids
    _defaultSummaryId = cfg.defaultsummaryid;
    for (uint32_t i = 0; rc && i < cfg.classes.size(); i++) {
        if (cfg.classes[i].name.empty()) {
            LOG(warning, "%s classes[%d]: empty name", configId, i);
        }
        int classID = cfg.classes[i].id;
        if (classID < 0 || classID > maxclassID) {
            LOG(error, "%s classes[%d]: bad id %d", configId, i, classID);
            rc = false;
            break;
        }
        ResultClass *resClass = AddResultClass(cfg.classes[i].name.c_str(), classID);
        if (resClass == nullptr) {
            LOG(error,"%s: unable to add classes[%d] name %s", configId, i, cfg.classes[i].name.c_str());
            rc = false;
            break;
        }
        for (unsigned int j = 0; rc && (j < cfg.classes[i].fields.size()); j++) {
            const char *fieldtype = cfg.classes[i].fields[j].type.c_str();
            const char *fieldname = cfg.classes[i].fields[j].name.c_str();
            LOG(debug, "Reconfiguring class '%s' field '%s' of type '%s'", cfg.classes[i].name.c_str(), fieldname, fieldtype);
            if (strcmp(fieldtype, "integer") == 0) {
                rc = resClass->AddConfigEntry(fieldname, RES_INT);
            } else if (strcmp(fieldtype, "short") == 0) {
                rc = resClass->AddConfigEntry(fieldname, RES_SHORT);
            } else if (strcmp(fieldtype, "bool") == 0) {
                rc = resClass->AddConfigEntry(fieldname, RES_BOOL);
            } else if (strcmp(fieldtype, "byte") == 0) {
                rc = resClass->AddConfigEntry(fieldname, RES_BYTE);
            } else if (strcmp(fieldtype, "float") == 0) {
                rc = resClass->AddConfigEntry(fieldname, RES_FLOAT);
            } else if (strcmp(fieldtype, "double") == 0) {
                rc = resClass->AddConfigEntry(fieldname, RES_DOUBLE);
            } else if (strcmp(fieldtype, "int64") == 0) {
                rc = resClass->AddConfigEntry(fieldname, RES_INT64);
            } else if (strcmp(fieldtype, "string") == 0) {
                rc = resClass->AddConfigEntry(fieldname, RES_STRING);
            } else if (strcmp(fieldtype, "data") == 0) {
                rc = resClass->AddConfigEntry(fieldname, RES_DATA);
            } else if (strcmp(fieldtype, "longstring") == 0) {
                rc = resClass->AddConfigEntry(fieldname, RES_LONG_STRING);
            } else if (strcmp(fieldtype, "longdata") == 0) {
                rc = resClass->AddConfigEntry(fieldname, RES_LONG_DATA);
            } else if (strcmp(fieldtype, "xmlstring") == 0) {
                rc = resClass->AddConfigEntry(fieldname, RES_XMLSTRING);
            } else if (strcmp(fieldtype, "jsonstring") == 0) {
                rc = resClass->AddConfigEntry(fieldname, RES_JSONSTRING);
            } else if (strcmp(fieldtype, "tensor") == 0) {
                rc = resClass->AddConfigEntry(fieldname, RES_TENSOR);
            } else if (strcmp(fieldtype, "featuredata") == 0) {
                rc = resClass->AddConfigEntry(fieldname, RES_FEATUREDATA);
            } else {
                LOG(error, "%s %s.fields[%d]: unknown type '%s'", configId, cfg.classes[i].name.c_str(), j, fieldtype);
                rc = false;
                break;
            }
            if (!rc) {
                LOG(error, "%s %s.fields[%d]: duplicate name '%s'", configId, cfg.classes[i].name.c_str(), j, fieldname);
                break;
            }
        }
    }
    if (rc) {
        CreateEnumMaps(); // create mappings needed by TVM
    } else {
        Reset();          // FAIL, discard all config
    }
    return rc;
}

uint32_t
ResultConfig::GetClassID(const char *buf, uint32_t buflen)
{
    uint32_t ret = NoClassID();
    uint32_t tmp32;

    if (buflen >= sizeof(tmp32)) {
        memcpy(&tmp32, buf, sizeof(tmp32));
        ret = tmp32;
    }
    return ret;
}

}
<commit_msg>Handle raw type<commit_after>// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.

#include "resultconfig.h"
#include <vespa/vespalib/util/exceptions.h>
#include <vespa/vespalib/stllike/hash_map.hpp>

#include <vespa/log/log.h>
LOG_SETUP(".searchlib.docsummary.resultconfig");

namespace search::docsummary {

void
ResultConfig::Clean()
{
    _classLookup.clear();
    _nameLookup.clear();
}

void
ResultConfig::Init()
{
}

ResultConfig::ResultConfig()
    : _defaultSummaryId(-1),
      _classLookup(),
      _nameLookup()
{
    Init();
}

ResultConfig::~ResultConfig()
{
    Clean();
}

const char *
ResultConfig::GetResTypeName(ResType type)
{
    switch (type) {
    case RES_INT:         return "integer";
    case RES_SHORT:       return "short";
    case RES_BYTE:        return "byte";
    case RES_BOOL:        return "bool";
    case RES_FLOAT:       return "float";
    case RES_DOUBLE:      return "double";
    case RES_INT64:       return "int64";
    case RES_STRING:      return "string";
    case RES_DATA:        return "data";
    case RES_LONG_STRING: return "longstring";
    case RES_LONG_DATA:   return "longdata";
    case RES_XMLSTRING:   return "xmlstring";
    case RES_JSONSTRING:  return "jsonstring";
    case RES_TENSOR:  return "tensor";
    case RES_FEATUREDATA: return "featuredata";
    }
    return "unknown-type";
}

void
ResultConfig::Reset()
{
    if (! _classLookup.empty() || _fieldEnum.GetNumEntries() > 0) {
        Clean();
        Init();
    }
}

ResultClass *
ResultConfig::AddResultClass(const char *name, uint32_t id)
{
    ResultClass *ret = nullptr;

    if (id != NoClassID() && (_classLookup.find(id) == _classLookup.end())) {
        ResultClass::UP rc(new ResultClass(name, id, _fieldEnum));
        ret = rc.get();
        _classLookup[id] = std::move(rc);
        if (_nameLookup.find(name) != _nameLookup.end()) {
            LOG(warning, "Duplicate result class name: %s (now maps to class id %u)", name, id);
        }
        _nameLookup[name] = id;
    }
    return ret;
}

const ResultClass*
ResultConfig::LookupResultClass(uint32_t id) const
{
    IdMap::const_iterator it(_classLookup.find(id));
    return (it != _classLookup.end()) ? it->second.get() : nullptr;
}

uint32_t
ResultConfig::LookupResultClassId(const vespalib::string &name, uint32_t def) const
{
    NameMap::const_iterator found(_nameLookup.find(name));
    return (found != _nameLookup.end()) ? found->second : def;
}

uint32_t
ResultConfig::LookupResultClassId(const vespalib::string &name) const
{
    return LookupResultClassId(name, (name.empty() || (name == "default")) ? _defaultSummaryId : NoClassID());
}

void
ResultConfig::CreateEnumMaps()
{
    for (auto & entry : _classLookup) {
       entry.second->CreateEnumMap();
    }
}

bool
ResultConfig::ReadConfig(const vespa::config::search::SummaryConfig &cfg, const char *configId)
{
    bool rc = true;
    Reset();
    int    maxclassID = 0x7fffffff; // avoid negative classids
    _defaultSummaryId = cfg.defaultsummaryid;
    for (uint32_t i = 0; rc && i < cfg.classes.size(); i++) {
        if (cfg.classes[i].name.empty()) {
            LOG(warning, "%s classes[%d]: empty name", configId, i);
        }
        int classID = cfg.classes[i].id;
        if (classID < 0 || classID > maxclassID) {
            LOG(error, "%s classes[%d]: bad id %d", configId, i, classID);
            rc = false;
            break;
        }
        ResultClass *resClass = AddResultClass(cfg.classes[i].name.c_str(), classID);
        if (resClass == nullptr) {
            LOG(error,"%s: unable to add classes[%d] name %s", configId, i, cfg.classes[i].name.c_str());
            rc = false;
            break;
        }
        for (unsigned int j = 0; rc && (j < cfg.classes[i].fields.size()); j++) {
            const char *fieldtype = cfg.classes[i].fields[j].type.c_str();
            const char *fieldname = cfg.classes[i].fields[j].name.c_str();
            LOG(debug, "Reconfiguring class '%s' field '%s' of type '%s'", cfg.classes[i].name.c_str(), fieldname, fieldtype);
            if (strcmp(fieldtype, "integer") == 0) {
                rc = resClass->AddConfigEntry(fieldname, RES_INT);
            } else if (strcmp(fieldtype, "short") == 0) {
                rc = resClass->AddConfigEntry(fieldname, RES_SHORT);
            } else if (strcmp(fieldtype, "bool") == 0) {
                rc = resClass->AddConfigEntry(fieldname, RES_BOOL);
            } else if (strcmp(fieldtype, "byte") == 0) {
                rc = resClass->AddConfigEntry(fieldname, RES_BYTE);
            } else if (strcmp(fieldtype, "float") == 0) {
                rc = resClass->AddConfigEntry(fieldname, RES_FLOAT);
            } else if (strcmp(fieldtype, "double") == 0) {
                rc = resClass->AddConfigEntry(fieldname, RES_DOUBLE);
            } else if (strcmp(fieldtype, "int64") == 0) {
                rc = resClass->AddConfigEntry(fieldname, RES_INT64);
            } else if (strcmp(fieldtype, "string") == 0) {
                rc = resClass->AddConfigEntry(fieldname, RES_STRING);
            } else if (strcmp(fieldtype, "data") == 0) {
                rc = resClass->AddConfigEntry(fieldname, RES_DATA);
            } else if (strcmp(fieldtype, "raw") == 0) {
                rc = resClass->AddConfigEntry(fieldname, RES_DATA);
            } else if (strcmp(fieldtype, "longstring") == 0) {
                rc = resClass->AddConfigEntry(fieldname, RES_LONG_STRING);
            } else if (strcmp(fieldtype, "longdata") == 0) {
                rc = resClass->AddConfigEntry(fieldname, RES_LONG_DATA);
            } else if (strcmp(fieldtype, "xmlstring") == 0) {
                rc = resClass->AddConfigEntry(fieldname, RES_XMLSTRING);
            } else if (strcmp(fieldtype, "jsonstring") == 0) {
                rc = resClass->AddConfigEntry(fieldname, RES_JSONSTRING);
            } else if (strcmp(fieldtype, "tensor") == 0) {
                rc = resClass->AddConfigEntry(fieldname, RES_TENSOR);
            } else if (strcmp(fieldtype, "featuredata") == 0) {
                rc = resClass->AddConfigEntry(fieldname, RES_FEATUREDATA);
            } else {
                LOG(error, "%s %s.fields[%d]: unknown type '%s'", configId, cfg.classes[i].name.c_str(), j, fieldtype);
                rc = false;
                break;
            }
            if (!rc) {
                LOG(error, "%s %s.fields[%d]: duplicate name '%s'", configId, cfg.classes[i].name.c_str(), j, fieldname);
                break;
            }
        }
    }
    if (rc) {
        CreateEnumMaps(); // create mappings needed by TVM
    } else {
        Reset();          // FAIL, discard all config
    }
    return rc;
}

uint32_t
ResultConfig::GetClassID(const char *buf, uint32_t buflen)
{
    uint32_t ret = NoClassID();
    uint32_t tmp32;

    if (buflen >= sizeof(tmp32)) {
        memcpy(&tmp32, buf, sizeof(tmp32));
        ret = tmp32;
    }
    return ret;
}

}
<|endoftext|>


<commit_before>/**
 * File    : F.cpp
 * Author  : Kazune Takahashi
 * Created : 2018-4-15 23:25:04
 * Powered by Visual Studio Code
 */

#include <iostream>
#include <iomanip>   // << fixed << setprecision(xxx)
#include <algorithm> // do { } while ( next_permutation(A, A+xxx) ) ;
#include <vector>
#include <string> // to_string(nnn) // substr(m, n) // stoi(nnn)
#include <complex>
#include <tuple>
#include <queue>
#include <stack>
#include <map> // if (M.find(key) != M.end()) { }
#include <set>
#include <random> // random_device rd; mt19937 mt(rd());
#include <cctype>
#include <cassert>
#include <cmath>
#include <cstdio>
#include <cstdlib>
using namespace std;

#define DEBUG 0 // change 0 -> 1 if we need debug.

typedef long long ll;

// const int dx[4] = {1, 0, -1, 0};
// const int dy[4] = {0, 1, 0, -1};

// const int C = 1e6+10;
// const ll M = 1000000007;

int N, M, Q;
int a[50];
int l[50];
int r[50];
bool used[50];

ll solve()
{
  ll ans = 0;
  for (auto i = 0; i < Q; i++)
  {
    int maxi = -1;
    int ind = 0;
    for (auto j = 0; j < N; j++)
    {
      if (!used[j] && l[i] <= a[j] && a[j] <= r[i] && a[j] > maxi)
      {
        maxi = a[j];
        ind = j;
      }
    }
    if (maxi >= 0)
    {
      ans += maxi;
      used[ind] = true;
    }
  }
  cerr << "ans = " << ans << endl;
  return ans;
}

void solveA()
{
  ll ans = 0;
  for (auto i = 0; i < (1 << N); i++)
  {
    int cnt = 0;
    for (auto j = 0; j < N; j++)
    {
      if ((i >> j) & 1)
      {
        cnt++;
      }
    }
    if (cnt == M)
    {
      for (auto j = 0; j < N; j++)
      {
        used[j] = (i >> j) & 1;
      }
      ans = min(ans, solve());
    }
  }
  cout << ans << endl;
}

void solveB()
{
  fill(used, used + N, false);
  for (auto i = 0; i < M; i++)
  {
    used[i] = false;
  }
  cout << solve() << endl;
}

int main()
{
  cin >> N >> M >> Q;
  for (auto i = 0; i < N; i++)
  {
    cin >> a[i];
  }
  for (auto i = 0; i < Q; i++)
  {
    cin >> l[i] >> r[i];
  }
  if (N <= 15)
  {
    solveA();
  }
  else
  {
    solveB();
  }
}<commit_msg>tried F.cpp to 'F'<commit_after>/**
 * File    : F.cpp
 * Author  : Kazune Takahashi
 * Created : 2018-4-15 23:25:04
 * Powered by Visual Studio Code
 */

#include <iostream>
#include <iomanip>   // << fixed << setprecision(xxx)
#include <algorithm> // do { } while ( next_permutation(A, A+xxx) ) ;
#include <vector>
#include <string> // to_string(nnn) // substr(m, n) // stoi(nnn)
#include <complex>
#include <tuple>
#include <queue>
#include <stack>
#include <map> // if (M.find(key) != M.end()) { }
#include <set>
#include <random> // random_device rd; mt19937 mt(rd());
#include <cctype>
#include <cassert>
#include <cmath>
#include <cstdio>
#include <cstdlib>
using namespace std;

#define DEBUG 0 // change 0 -> 1 if we need debug.

typedef long long ll;

// const int dx[4] = {1, 0, -1, 0};
// const int dy[4] = {0, 1, 0, -1};

// const int C = 1e6+10;
// const ll M = 1000000007;

int N, M, Q;
int a[50];
int l[50];
int r[50];
bool used[50];

ll solve()
{
  ll ans = 0;
  for (auto i = 0; i < Q; i++)
  {
    int maxi = -1;
    int ind = 0;
    for (auto j = 0; j < N; j++)
    {
      if (!used[j] && l[i] <= a[j] && a[j] <= r[i] && a[j] > maxi)
      {
        maxi = a[j];
        ind = j;
      }
    }
    if (maxi >= 0)
    {
      ans += maxi;
    }
  }
  // cerr << "ans = " << ans << endl;
  return ans;
}

void solveA()
{
  ll ans = 0;
  for (auto i = 0; i < (1 << N); i++)
  {
    int cnt = 0;
    for (auto j = 0; j < N; j++)
    {
      if ((i >> j) & 1)
      {
        cnt++;
      }
    }
    if (cnt == M)
    {
      for (auto j = 0; j < N; j++)
      {
        used[j] = (i >> j) & 1;
      }
      ans = min(ans, solve());
    }
  }
  cout << ans << endl;
}

void solveB()
{
  fill(used, used + N, false);
  for (auto i = 0; i < M; i++)
  {
    used[i] = false;
  }
  cout << solve() << endl;
}

int main()
{
  cin >> N >> M >> Q;
  for (auto i = 0; i < N; i++)
  {
    cin >> a[i];
  }
  for (auto i = 0; i < Q; i++)
  {
    cin >> l[i] >> r[i];
  }
  if (N <= 15)
  {
    solveA();
  }
  else
  {
    solveB();
  }
}<|endoftext|>


<commit_before>// Copyright (c) 2009 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include <gtk/gtk.h>

#include "app/l10n_util.h"
#include "base/message_loop.h"
#include "base/gfx/gtk_util.h"
#include "chrome/browser/gtk/options/url_picker_dialog_gtk.h"
#include "chrome/browser/net/url_fixer_upper.h"
#include "chrome/browser/possible_url_model.h"
#include "chrome/browser/profile.h"
#include "chrome/common/gtk_util.h"
#include "chrome/common/pref_names.h"
#include "googleurl/src/gurl.h"
#include "grit/chromium_strings.h"
#include "grit/generated_resources.h"
#include "net/base/net_util.h"

namespace {

// Initial size for dialog.
const int kDialogDefaultWidth = 450;
const int kDialogDefaultHeight = 450;

// Initial width of the first column.
const int kTitleColumnInitialSize = 200;

// Style for recent history label.
const char kHistoryLabelMarkup[] = "%s";

// Column ids for |history_list_store_|.
enum {
  COL_FAVICON,
  COL_TITLE,
  COL_DISPLAY_URL,
  COL_COUNT,
};

// Get the row number corresponding to |path|.
gint GetRowNumForPath(GtkTreePath* path) {
  gint* indices = gtk_tree_path_get_indices(path);
  if (!indices) {
    NOTREACHED();
    return -1;
  }
  return indices[0];
}

// Get the row number corresponding to |iter|.
gint GetRowNumForIter(GtkTreeModel* model, GtkTreeIter* iter) {
  GtkTreePath* path = gtk_tree_model_get_path(model, iter);
  int row = GetRowNumForPath(path);
  gtk_tree_path_free(path);
  return row;
}

// Get the row number in the child tree model corresponding to |sort_path| in
// the parent tree model.
gint GetTreeSortChildRowNumForPath(GtkTreeModel* sort_model,
                                   GtkTreePath* sort_path) {
  GtkTreePath *child_path = gtk_tree_model_sort_convert_path_to_child_path(
      GTK_TREE_MODEL_SORT(sort_model), sort_path);
  int row = GetRowNumForPath(child_path);
  gtk_tree_path_free(child_path);
  return row;
}

}  // anonymous namespace

UrlPickerDialogGtk::UrlPickerDialogGtk(UrlPickerCallback* callback,
                                       Profile* profile,
                                       GtkWindow* parent)
    : profile_(profile),
      callback_(callback) {
  dialog_ = gtk_dialog_new_with_buttons(
      l10n_util::GetStringUTF8(IDS_ASI_ADD_TITLE).c_str(),
      parent,
      static_cast<GtkDialogFlags>(GTK_DIALOG_MODAL | GTK_DIALOG_NO_SEPARATOR),
      GTK_STOCK_CANCEL,
      GTK_RESPONSE_CANCEL,
      NULL);

  add_button_ = gtk_dialog_add_button(GTK_DIALOG(dialog_),
                                      GTK_STOCK_ADD, GTK_RESPONSE_OK);
  gtk_dialog_set_default_response(GTK_DIALOG(dialog_), GTK_RESPONSE_OK);
  gtk_window_set_default_size(GTK_WINDOW(dialog_), kDialogDefaultWidth,
                              kDialogDefaultHeight);
  gtk_box_set_spacing(GTK_BOX(GTK_DIALOG(dialog_)->vbox),
                      gtk_util::kContentAreaSpacing);

  // URL entry.
  GtkWidget* url_hbox = gtk_hbox_new(FALSE, gtk_util::kLabelSpacing);
  GtkWidget* url_label = gtk_label_new(
      l10n_util::GetStringUTF8(IDS_ASI_URL).c_str());
  gtk_box_pack_start(GTK_BOX(url_hbox), url_label,
                     FALSE, FALSE, 0);
  url_entry_ = gtk_entry_new();
  gtk_entry_set_activates_default(GTK_ENTRY(url_entry_), TRUE);
  g_signal_connect(G_OBJECT(url_entry_), "changed",
                   G_CALLBACK(OnUrlEntryChanged), this);
  gtk_box_pack_start(GTK_BOX(url_hbox), url_entry_,
                     TRUE, TRUE, 0);
  gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog_)->vbox), url_hbox,
                     FALSE, FALSE, 0);

  // Recent history description label.
  GtkWidget* history_vbox = gtk_vbox_new(FALSE, gtk_util::kLabelSpacing);
  gtk_container_add(GTK_CONTAINER(GTK_DIALOG(dialog_)->vbox), history_vbox);
  GtkWidget* history_label = gtk_label_new(NULL);
  char* markup = g_markup_printf_escaped(kHistoryLabelMarkup,
      l10n_util::GetStringUTF8(IDS_ASI_DESCRIPTION).c_str());
  gtk_label_set_markup(GTK_LABEL(history_label), markup);
  g_free(markup);
  GtkWidget* history_label_alignment = gtk_alignment_new(0.0, 0.5, 0.0, 0.0);
  gtk_container_add(GTK_CONTAINER(history_label_alignment), history_label);
  gtk_box_pack_start(GTK_BOX(history_vbox), history_label_alignment,
                     FALSE, FALSE, 0);

  // Recent history list.
  GtkWidget* scroll_window = gtk_scrolled_window_new(NULL, NULL);
  gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scroll_window),
                                 GTK_POLICY_AUTOMATIC,
                                 GTK_POLICY_AUTOMATIC);
  gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(scroll_window),
                                      GTK_SHADOW_ETCHED_IN);
  gtk_container_add(GTK_CONTAINER(history_vbox), scroll_window);

  history_list_store_ = gtk_list_store_new(COL_COUNT,
                                           GDK_TYPE_PIXBUF,
                                           G_TYPE_STRING,
                                           G_TYPE_STRING);
  history_list_sort_ = gtk_tree_model_sort_new_with_model(
      GTK_TREE_MODEL(history_list_store_));
  gtk_tree_sortable_set_sort_func(GTK_TREE_SORTABLE(history_list_sort_),
                                  COL_TITLE, CompareTitle, this, NULL);
  gtk_tree_sortable_set_sort_func(GTK_TREE_SORTABLE(history_list_sort_),
                                  COL_DISPLAY_URL, CompareURL, this, NULL);
  history_tree_ = gtk_tree_view_new_with_model(history_list_sort_);
  gtk_container_add(GTK_CONTAINER(scroll_window), history_tree_);
  gtk_tree_view_set_headers_visible(GTK_TREE_VIEW(history_tree_),
                                    TRUE);
  g_signal_connect(G_OBJECT(history_tree_), "row-activated",
                   G_CALLBACK(OnHistoryRowActivated), this);

  history_selection_ = gtk_tree_view_get_selection(
      GTK_TREE_VIEW(history_tree_));
  gtk_tree_selection_set_mode(history_selection_,
                              GTK_SELECTION_SINGLE);
  g_signal_connect(G_OBJECT(history_selection_), "changed",
                   G_CALLBACK(OnHistorySelectionChanged), this);

  // History list columns.
  GtkTreeViewColumn* column = gtk_tree_view_column_new();
  GtkCellRenderer* renderer = gtk_cell_renderer_pixbuf_new();
  gtk_tree_view_column_pack_start(column, renderer, FALSE);
  gtk_tree_view_column_add_attribute(column, renderer, "pixbuf", COL_FAVICON);
  renderer = gtk_cell_renderer_text_new();
  gtk_tree_view_column_pack_start(column, renderer, TRUE);
  gtk_tree_view_column_add_attribute(column, renderer, "text", COL_TITLE);
  gtk_tree_view_append_column(GTK_TREE_VIEW(history_tree_),
                              column);
  gtk_tree_view_column_set_title(
      column, l10n_util::GetStringUTF8(IDS_ASI_PAGE_COLUMN).c_str());
  gtk_tree_view_column_set_sizing(column, GTK_TREE_VIEW_COLUMN_FIXED);
  gtk_tree_view_column_set_resizable(column, TRUE);
  gtk_tree_view_column_set_fixed_width(column, kTitleColumnInitialSize);
  gtk_tree_view_column_set_sort_column_id(column, COL_TITLE);

  GtkTreeViewColumn* url_column = gtk_tree_view_column_new_with_attributes(
      l10n_util::GetStringUTF8(IDS_ASI_URL_COLUMN).c_str(),
      gtk_cell_renderer_text_new(),
      "text", COL_DISPLAY_URL,
      NULL);
  gtk_tree_view_append_column(GTK_TREE_VIEW(history_tree_), url_column);
  gtk_tree_view_column_set_sort_column_id(url_column, COL_DISPLAY_URL);

  // Loading data, showing dialog.
  url_table_model_.reset(new PossibleURLModel());
  url_table_model_->SetObserver(this);
  url_table_model_->Reload(profile_);

  EnableControls();

  gtk_widget_show_all(dialog_);

  g_signal_connect(dialog_, "response", G_CALLBACK(OnResponse), this);
  g_signal_connect(dialog_, "destroy", G_CALLBACK(OnWindowDestroy), this);
}

UrlPickerDialogGtk::~UrlPickerDialogGtk() {
  delete callback_;
}

void UrlPickerDialogGtk::AddURL() {
  GURL url(URLFixerUpper::FixupURL(
      gtk_entry_get_text(GTK_ENTRY(url_entry_)), ""));
  callback_->Run(url);
}

void UrlPickerDialogGtk::EnableControls() {
  const gchar* text = gtk_entry_get_text(GTK_ENTRY(url_entry_));
  gtk_widget_set_sensitive(add_button_, text && *text);
}

std::string UrlPickerDialogGtk::GetURLForPath(GtkTreePath* path) const {
  gint row = GetTreeSortChildRowNumForPath(history_list_sort_, path);
  if (row < 0) {
    NOTREACHED();
    return std::string();
  }
  std::wstring languages =
      profile_->GetPrefs()->GetString(prefs::kAcceptLanguages);
  // Because the url_field_ is user-editable, we set the URL with
  // username:password and escaped path and query.
  std::wstring formatted = net::FormatUrl(
      url_table_model_->GetURL(row), languages,
      false, UnescapeRule::NONE, NULL, NULL);
  return WideToUTF8(formatted);
}

void UrlPickerDialogGtk::SetColumnValues(int row, GtkTreeIter* iter) {
  SkBitmap bitmap = url_table_model_->GetIcon(row);
  GdkPixbuf* pixbuf = gfx::GdkPixbufFromSkBitmap(&bitmap);
  std::wstring title = url_table_model_->GetText(row, IDS_ASI_PAGE_COLUMN);
  std::wstring url = url_table_model_->GetText(row, IDS_ASI_URL_COLUMN);
  gtk_list_store_set(history_list_store_, iter,
                     COL_FAVICON, pixbuf,
                     COL_TITLE, WideToUTF8(title).c_str(),
                     COL_DISPLAY_URL, WideToUTF8(url).c_str(),
                     -1);
  g_object_unref(pixbuf);
}

void UrlPickerDialogGtk::AddNodeToList(int row) {
  GtkTreeIter iter;
  if (row == 0) {
    gtk_list_store_prepend(history_list_store_, &iter);
  } else {
    GtkTreeIter sibling;
    gtk_tree_model_iter_nth_child(GTK_TREE_MODEL(history_list_store_), &sibling,
                                  NULL, row - 1);
    gtk_list_store_insert_after(history_list_store_, &iter, &sibling);
  }

  SetColumnValues(row, &iter);
}

void UrlPickerDialogGtk::OnModelChanged() {
  gtk_list_store_clear(history_list_store_);
  for (int i = 0; i < url_table_model_->RowCount(); ++i)
    AddNodeToList(i);
}

void UrlPickerDialogGtk::OnItemsChanged(int start, int length) {
  GtkTreeIter iter;
  bool rv = gtk_tree_model_iter_nth_child(GTK_TREE_MODEL(history_list_store_),
                                          &iter, NULL, start);
  for (int i = 0; i < length; ++i) {
    if (!rv) {
      NOTREACHED();
      return;
    }
    SetColumnValues(start + i, &iter);
    rv = gtk_tree_model_iter_next(GTK_TREE_MODEL(history_list_store_), &iter);
  }
}

void UrlPickerDialogGtk::OnItemsAdded(int start, int length) {
  NOTREACHED();
}

void UrlPickerDialogGtk::OnItemsRemoved(int start, int length) {
  NOTREACHED();
}

// static
gint UrlPickerDialogGtk::CompareTitle(GtkTreeModel* model,
                                      GtkTreeIter* a,
                                      GtkTreeIter* b,
                                      gpointer window) {
  int row1 = GetRowNumForIter(model, a);
  int row2 = GetRowNumForIter(model, b);
  return reinterpret_cast<UrlPickerDialogGtk*>(window)->url_table_model_->
      CompareValues(row1, row2, IDS_ASI_PAGE_COLUMN);
}

// static
gint UrlPickerDialogGtk::CompareURL(GtkTreeModel* model,
                                    GtkTreeIter* a,
                                    GtkTreeIter* b,
                                    gpointer window) {
  int row1 = GetRowNumForIter(model, a);
  int row2 = GetRowNumForIter(model, b);
  return reinterpret_cast<UrlPickerDialogGtk*>(window)->url_table_model_->
      CompareValues(row1, row2, IDS_ASI_URL_COLUMN);
}

// static
void UrlPickerDialogGtk::OnUrlEntryChanged(GtkEditable* editable,
                                           UrlPickerDialogGtk* window) {
  window->EnableControls();
}

// static
void UrlPickerDialogGtk::OnHistorySelectionChanged(
    GtkTreeSelection *selection, UrlPickerDialogGtk* window) {
  GtkTreeIter iter;
  if (!gtk_tree_selection_get_selected(selection, NULL, &iter)) {
    NOTREACHED();
    return;
  }
  GtkTreePath* path = gtk_tree_model_get_path(
      GTK_TREE_MODEL(window->history_list_sort_), &iter);
  gtk_entry_set_text(GTK_ENTRY(window->url_entry_),
                     window->GetURLForPath(path).c_str());
  gtk_tree_path_free(path);
}

void UrlPickerDialogGtk::OnHistoryRowActivated(GtkTreeView* tree_view,
                                               GtkTreePath* path,
                                               GtkTreeViewColumn* column,
                                               UrlPickerDialogGtk* window) {
  GURL url(URLFixerUpper::FixupURL(window->GetURLForPath(path), ""));
  window->callback_->Run(url);
  gtk_widget_destroy(window->dialog_);
}

// static
void UrlPickerDialogGtk::OnResponse(GtkDialog* dialog, int response_id,
                                    UrlPickerDialogGtk* window) {
  if (response_id == GTK_RESPONSE_OK) {
    window->AddURL();
  }
  gtk_widget_destroy(window->dialog_);
}

// static
void UrlPickerDialogGtk::OnWindowDestroy(GtkWidget* widget,
                                         UrlPickerDialogGtk* window) {
  MessageLoop::current()->DeleteSoon(FROM_HERE, window);
}
<commit_msg>Linux: it's not actually a bug to have the selection become empty in the URL picker. BUG=none TEST=in a debug build, go to wrench->options->basics, select "open the following pages", click "add", select something from the list, and then deselect it by holding ctrl and clicking it again; chromium should not crash<commit_after>// Copyright (c) 2009 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include <gtk/gtk.h>

#include "app/l10n_util.h"
#include "base/message_loop.h"
#include "base/gfx/gtk_util.h"
#include "chrome/browser/gtk/options/url_picker_dialog_gtk.h"
#include "chrome/browser/net/url_fixer_upper.h"
#include "chrome/browser/possible_url_model.h"
#include "chrome/browser/profile.h"
#include "chrome/common/gtk_util.h"
#include "chrome/common/pref_names.h"
#include "googleurl/src/gurl.h"
#include "grit/chromium_strings.h"
#include "grit/generated_resources.h"
#include "net/base/net_util.h"

namespace {

// Initial size for dialog.
const int kDialogDefaultWidth = 450;
const int kDialogDefaultHeight = 450;

// Initial width of the first column.
const int kTitleColumnInitialSize = 200;

// Style for recent history label.
const char kHistoryLabelMarkup[] = "%s";

// Column ids for |history_list_store_|.
enum {
  COL_FAVICON,
  COL_TITLE,
  COL_DISPLAY_URL,
  COL_COUNT,
};

// Get the row number corresponding to |path|.
gint GetRowNumForPath(GtkTreePath* path) {
  gint* indices = gtk_tree_path_get_indices(path);
  if (!indices) {
    NOTREACHED();
    return -1;
  }
  return indices[0];
}

// Get the row number corresponding to |iter|.
gint GetRowNumForIter(GtkTreeModel* model, GtkTreeIter* iter) {
  GtkTreePath* path = gtk_tree_model_get_path(model, iter);
  int row = GetRowNumForPath(path);
  gtk_tree_path_free(path);
  return row;
}

// Get the row number in the child tree model corresponding to |sort_path| in
// the parent tree model.
gint GetTreeSortChildRowNumForPath(GtkTreeModel* sort_model,
                                   GtkTreePath* sort_path) {
  GtkTreePath *child_path = gtk_tree_model_sort_convert_path_to_child_path(
      GTK_TREE_MODEL_SORT(sort_model), sort_path);
  int row = GetRowNumForPath(child_path);
  gtk_tree_path_free(child_path);
  return row;
}

}  // anonymous namespace

UrlPickerDialogGtk::UrlPickerDialogGtk(UrlPickerCallback* callback,
                                       Profile* profile,
                                       GtkWindow* parent)
    : profile_(profile),
      callback_(callback) {
  dialog_ = gtk_dialog_new_with_buttons(
      l10n_util::GetStringUTF8(IDS_ASI_ADD_TITLE).c_str(),
      parent,
      static_cast<GtkDialogFlags>(GTK_DIALOG_MODAL | GTK_DIALOG_NO_SEPARATOR),
      GTK_STOCK_CANCEL,
      GTK_RESPONSE_CANCEL,
      NULL);

  add_button_ = gtk_dialog_add_button(GTK_DIALOG(dialog_),
                                      GTK_STOCK_ADD, GTK_RESPONSE_OK);
  gtk_dialog_set_default_response(GTK_DIALOG(dialog_), GTK_RESPONSE_OK);
  gtk_window_set_default_size(GTK_WINDOW(dialog_), kDialogDefaultWidth,
                              kDialogDefaultHeight);
  gtk_box_set_spacing(GTK_BOX(GTK_DIALOG(dialog_)->vbox),
                      gtk_util::kContentAreaSpacing);

  // URL entry.
  GtkWidget* url_hbox = gtk_hbox_new(FALSE, gtk_util::kLabelSpacing);
  GtkWidget* url_label = gtk_label_new(
      l10n_util::GetStringUTF8(IDS_ASI_URL).c_str());
  gtk_box_pack_start(GTK_BOX(url_hbox), url_label,
                     FALSE, FALSE, 0);
  url_entry_ = gtk_entry_new();
  gtk_entry_set_activates_default(GTK_ENTRY(url_entry_), TRUE);
  g_signal_connect(G_OBJECT(url_entry_), "changed",
                   G_CALLBACK(OnUrlEntryChanged), this);
  gtk_box_pack_start(GTK_BOX(url_hbox), url_entry_,
                     TRUE, TRUE, 0);
  gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog_)->vbox), url_hbox,
                     FALSE, FALSE, 0);

  // Recent history description label.
  GtkWidget* history_vbox = gtk_vbox_new(FALSE, gtk_util::kLabelSpacing);
  gtk_container_add(GTK_CONTAINER(GTK_DIALOG(dialog_)->vbox), history_vbox);
  GtkWidget* history_label = gtk_label_new(NULL);
  char* markup = g_markup_printf_escaped(kHistoryLabelMarkup,
      l10n_util::GetStringUTF8(IDS_ASI_DESCRIPTION).c_str());
  gtk_label_set_markup(GTK_LABEL(history_label), markup);
  g_free(markup);
  GtkWidget* history_label_alignment = gtk_alignment_new(0.0, 0.5, 0.0, 0.0);
  gtk_container_add(GTK_CONTAINER(history_label_alignment), history_label);
  gtk_box_pack_start(GTK_BOX(history_vbox), history_label_alignment,
                     FALSE, FALSE, 0);

  // Recent history list.
  GtkWidget* scroll_window = gtk_scrolled_window_new(NULL, NULL);
  gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scroll_window),
                                 GTK_POLICY_AUTOMATIC,
                                 GTK_POLICY_AUTOMATIC);
  gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(scroll_window),
                                      GTK_SHADOW_ETCHED_IN);
  gtk_container_add(GTK_CONTAINER(history_vbox), scroll_window);

  history_list_store_ = gtk_list_store_new(COL_COUNT,
                                           GDK_TYPE_PIXBUF,
                                           G_TYPE_STRING,
                                           G_TYPE_STRING);
  history_list_sort_ = gtk_tree_model_sort_new_with_model(
      GTK_TREE_MODEL(history_list_store_));
  gtk_tree_sortable_set_sort_func(GTK_TREE_SORTABLE(history_list_sort_),
                                  COL_TITLE, CompareTitle, this, NULL);
  gtk_tree_sortable_set_sort_func(GTK_TREE_SORTABLE(history_list_sort_),
                                  COL_DISPLAY_URL, CompareURL, this, NULL);
  history_tree_ = gtk_tree_view_new_with_model(history_list_sort_);
  gtk_container_add(GTK_CONTAINER(scroll_window), history_tree_);
  gtk_tree_view_set_headers_visible(GTK_TREE_VIEW(history_tree_),
                                    TRUE);
  g_signal_connect(G_OBJECT(history_tree_), "row-activated",
                   G_CALLBACK(OnHistoryRowActivated), this);

  history_selection_ = gtk_tree_view_get_selection(
      GTK_TREE_VIEW(history_tree_));
  gtk_tree_selection_set_mode(history_selection_,
                              GTK_SELECTION_SINGLE);
  g_signal_connect(G_OBJECT(history_selection_), "changed",
                   G_CALLBACK(OnHistorySelectionChanged), this);

  // History list columns.
  GtkTreeViewColumn* column = gtk_tree_view_column_new();
  GtkCellRenderer* renderer = gtk_cell_renderer_pixbuf_new();
  gtk_tree_view_column_pack_start(column, renderer, FALSE);
  gtk_tree_view_column_add_attribute(column, renderer, "pixbuf", COL_FAVICON);
  renderer = gtk_cell_renderer_text_new();
  gtk_tree_view_column_pack_start(column, renderer, TRUE);
  gtk_tree_view_column_add_attribute(column, renderer, "text", COL_TITLE);
  gtk_tree_view_append_column(GTK_TREE_VIEW(history_tree_),
                              column);
  gtk_tree_view_column_set_title(
      column, l10n_util::GetStringUTF8(IDS_ASI_PAGE_COLUMN).c_str());
  gtk_tree_view_column_set_sizing(column, GTK_TREE_VIEW_COLUMN_FIXED);
  gtk_tree_view_column_set_resizable(column, TRUE);
  gtk_tree_view_column_set_fixed_width(column, kTitleColumnInitialSize);
  gtk_tree_view_column_set_sort_column_id(column, COL_TITLE);

  GtkTreeViewColumn* url_column = gtk_tree_view_column_new_with_attributes(
      l10n_util::GetStringUTF8(IDS_ASI_URL_COLUMN).c_str(),
      gtk_cell_renderer_text_new(),
      "text", COL_DISPLAY_URL,
      NULL);
  gtk_tree_view_append_column(GTK_TREE_VIEW(history_tree_), url_column);
  gtk_tree_view_column_set_sort_column_id(url_column, COL_DISPLAY_URL);

  // Loading data, showing dialog.
  url_table_model_.reset(new PossibleURLModel());
  url_table_model_->SetObserver(this);
  url_table_model_->Reload(profile_);

  EnableControls();

  gtk_widget_show_all(dialog_);

  g_signal_connect(dialog_, "response", G_CALLBACK(OnResponse), this);
  g_signal_connect(dialog_, "destroy", G_CALLBACK(OnWindowDestroy), this);
}

UrlPickerDialogGtk::~UrlPickerDialogGtk() {
  delete callback_;
}

void UrlPickerDialogGtk::AddURL() {
  GURL url(URLFixerUpper::FixupURL(
      gtk_entry_get_text(GTK_ENTRY(url_entry_)), ""));
  callback_->Run(url);
}

void UrlPickerDialogGtk::EnableControls() {
  const gchar* text = gtk_entry_get_text(GTK_ENTRY(url_entry_));
  gtk_widget_set_sensitive(add_button_, text && *text);
}

std::string UrlPickerDialogGtk::GetURLForPath(GtkTreePath* path) const {
  gint row = GetTreeSortChildRowNumForPath(history_list_sort_, path);
  if (row < 0) {
    NOTREACHED();
    return std::string();
  }
  std::wstring languages =
      profile_->GetPrefs()->GetString(prefs::kAcceptLanguages);
  // Because the url_field_ is user-editable, we set the URL with
  // username:password and escaped path and query.
  std::wstring formatted = net::FormatUrl(
      url_table_model_->GetURL(row), languages,
      false, UnescapeRule::NONE, NULL, NULL);
  return WideToUTF8(formatted);
}

void UrlPickerDialogGtk::SetColumnValues(int row, GtkTreeIter* iter) {
  SkBitmap bitmap = url_table_model_->GetIcon(row);
  GdkPixbuf* pixbuf = gfx::GdkPixbufFromSkBitmap(&bitmap);
  std::wstring title = url_table_model_->GetText(row, IDS_ASI_PAGE_COLUMN);
  std::wstring url = url_table_model_->GetText(row, IDS_ASI_URL_COLUMN);
  gtk_list_store_set(history_list_store_, iter,
                     COL_FAVICON, pixbuf,
                     COL_TITLE, WideToUTF8(title).c_str(),
                     COL_DISPLAY_URL, WideToUTF8(url).c_str(),
                     -1);
  g_object_unref(pixbuf);
}

void UrlPickerDialogGtk::AddNodeToList(int row) {
  GtkTreeIter iter;
  if (row == 0) {
    gtk_list_store_prepend(history_list_store_, &iter);
  } else {
    GtkTreeIter sibling;
    gtk_tree_model_iter_nth_child(GTK_TREE_MODEL(history_list_store_), &sibling,
                                  NULL, row - 1);
    gtk_list_store_insert_after(history_list_store_, &iter, &sibling);
  }

  SetColumnValues(row, &iter);
}

void UrlPickerDialogGtk::OnModelChanged() {
  gtk_list_store_clear(history_list_store_);
  for (int i = 0; i < url_table_model_->RowCount(); ++i)
    AddNodeToList(i);
}

void UrlPickerDialogGtk::OnItemsChanged(int start, int length) {
  GtkTreeIter iter;
  bool rv = gtk_tree_model_iter_nth_child(GTK_TREE_MODEL(history_list_store_),
                                          &iter, NULL, start);
  for (int i = 0; i < length; ++i) {
    if (!rv) {
      NOTREACHED();
      return;
    }
    SetColumnValues(start + i, &iter);
    rv = gtk_tree_model_iter_next(GTK_TREE_MODEL(history_list_store_), &iter);
  }
}

void UrlPickerDialogGtk::OnItemsAdded(int start, int length) {
  NOTREACHED();
}

void UrlPickerDialogGtk::OnItemsRemoved(int start, int length) {
  NOTREACHED();
}

// static
gint UrlPickerDialogGtk::CompareTitle(GtkTreeModel* model,
                                      GtkTreeIter* a,
                                      GtkTreeIter* b,
                                      gpointer window) {
  int row1 = GetRowNumForIter(model, a);
  int row2 = GetRowNumForIter(model, b);
  return reinterpret_cast<UrlPickerDialogGtk*>(window)->url_table_model_->
      CompareValues(row1, row2, IDS_ASI_PAGE_COLUMN);
}

// static
gint UrlPickerDialogGtk::CompareURL(GtkTreeModel* model,
                                    GtkTreeIter* a,
                                    GtkTreeIter* b,
                                    gpointer window) {
  int row1 = GetRowNumForIter(model, a);
  int row2 = GetRowNumForIter(model, b);
  return reinterpret_cast<UrlPickerDialogGtk*>(window)->url_table_model_->
      CompareValues(row1, row2, IDS_ASI_URL_COLUMN);
}

// static
void UrlPickerDialogGtk::OnUrlEntryChanged(GtkEditable* editable,
                                           UrlPickerDialogGtk* window) {
  window->EnableControls();
}

// static
void UrlPickerDialogGtk::OnHistorySelectionChanged(
    GtkTreeSelection *selection, UrlPickerDialogGtk* window) {
  GtkTreeIter iter;
  if (!gtk_tree_selection_get_selected(selection, NULL, &iter)) {
    // The user has unselected the history element, nothing to do.
    return;
  }
  GtkTreePath* path = gtk_tree_model_get_path(
      GTK_TREE_MODEL(window->history_list_sort_), &iter);
  gtk_entry_set_text(GTK_ENTRY(window->url_entry_),
                     window->GetURLForPath(path).c_str());
  gtk_tree_path_free(path);
}

void UrlPickerDialogGtk::OnHistoryRowActivated(GtkTreeView* tree_view,
                                               GtkTreePath* path,
                                               GtkTreeViewColumn* column,
                                               UrlPickerDialogGtk* window) {
  GURL url(URLFixerUpper::FixupURL(window->GetURLForPath(path), ""));
  window->callback_->Run(url);
  gtk_widget_destroy(window->dialog_);
}

// static
void UrlPickerDialogGtk::OnResponse(GtkDialog* dialog, int response_id,
                                    UrlPickerDialogGtk* window) {
  if (response_id == GTK_RESPONSE_OK) {
    window->AddURL();
  }
  gtk_widget_destroy(window->dialog_);
}

// static
void UrlPickerDialogGtk::OnWindowDestroy(GtkWidget* widget,
                                         UrlPickerDialogGtk* window) {
  MessageLoop::current()->DeleteSoon(FROM_HERE, window);
}
<|endoftext|>