<commit_before>#include "libcpu.h"
#include "x86_isa.h"
#include "x86_decode.h"

static unsigned long decode_table[256] = {
	/* 0x00 - 0x07 */
	0, 0, 0, 0, 0, 0, 0, 0,
	/* 0x08 - 0x0F */
	0, 0, 0, 0, 0, 0, 0, 0,
	/* 0x10 - 0x17 */
	0, 0, 0, 0, 0, 0, 0, 0,
	/* 0x18 - 0x1F */
	0, 0, 0, 0, 0, 0, 0, 0,
	/* 0x20 - 0x27 */
	0, 0, 0, 0, 0, 0, 0, 0,
	/* 0x28 - 0x2F */
	0, 0, 0, 0, 0, 0, 0, 0,
	/* 0x30 - 0x37 */
	0, 0, 0, 0, 0, 0, 0, 0,
	/* 0x38 - 0x3F */
	0, 0, 0, 0, 0, 0, 0, 0,
	/* 0x40 - 0x47 */
	0, 0, 0, 0, 0, 0, 0, 0,
	/* 0x48 - 0x4F */
	0, 0, 0, 0, 0, 0, 0, 0,
	/* 0x50 - 0x57 */
	0, 0, 0, 0, 0, 0, 0, 0,
	/* 0x58 - 0x5F */
	0, 0, 0, 0, 0, 0, 0, 0,
	/* 0x60 - 0x67 */
	0, 0, 0, 0, 0, 0, 0, 0,
	/* 0x68 - 0x6F */
	0, 0, 0, 0, 0, 0, 0, 0,
	/* 0x70 - 0x77 */
	0, 0, 0, 0, 0, 0, 0, 0,
	/* 0x78 - 0x7F */
	0, 0, 0, 0, 0, 0, 0, 0,
	/* 0x80 - 0x87 */
	0, 0, 0, 0, 0, 0, 0, 0,
	/* 0x88 - 0x8F */
	0, INSTR_MOV|ModRM|SrcReg, 0, 0, 0, 0, 0, 0,
	/* 0x90 - 0x97 */
	0, 0, 0, 0, 0, 0, 0, 0,
	/* 0x98 - 0x9F */
	0, 0, 0, 0, 0, 0, 0, 0,
	/* 0xA0 - 0xA7 */
	0, 0, 0, 0, 0, 0, 0, 0,
	/* 0xA8 - 0xAF */
	0, 0, 0, 0, 0, 0, 0, 0,
	/* 0xB0 - 0xB7 */
	0, 0, 0, 0, 0, 0, 0, 0,
	/* 0xB8 - 0xBF */
	INSTR_MOV|SrcImm16|DstReg, INSTR_MOV|SrcImm16|DstReg, INSTR_MOV|SrcImm16|DstReg, INSTR_MOV|SrcImm16|DstReg,
	0, 0, 0, 0,
	/* 0xC0 - 0xC7 */
	0, 0, 0, INSTR_RET|SrcNone|DstNone, 0, 0, 0, 0,
	/* 0xC8 - 0xCF */
	0, 0, 0, 0, 0, 0, 0, 0,
	/* 0xD0 - 0xD7 */
	0, 0, 0, 0, 0, 0, 0, 0,
	/* 0xD8 - 0xDF */
	0, 0, 0, 0, 0, 0, 0, 0,
	/* 0xE0 - 0xE7 */
	0, 0, 0, 0, 0, 0, 0, 0,
	/* 0xE8 - 0xEF */
	0, 0, 0, 0, 0, 0, 0, 0,
	/* 0xF0 - 0xF7 */
	0, 0, 0, 0, 0, 0, 0, 0,
	/* 0xF8 - 0xFF */
	0, 0, 0, 0, 0, 0, 0, 0,
};

static void
decode_dst_operand(struct x86_instr *instr)
{
	struct x86_operand *operand = &instr->dst;

	switch (instr->flags & DstMask) {
	case DstNone:
		break;
	case DstReg:
		operand->type	= OP_REG;

		if (instr->flags & ModRM)
			operand->reg	= instr->rm;
		else
			operand->reg	= instr->opcode & 0x03;
		break;
	case DstMem:
		operand->type	= OP_MEM;
		operand->reg	= instr->rm;
		break;
	case DstMemDisp8:
	case DstMemDisp16:
		operand->type	= OP_MEM_DISP;
		operand->reg	= instr->rm;
		operand->disp	= instr->disp;
		break;
	}
}

static void
decode_src_operand(struct x86_instr *instr)
{
	struct x86_operand *operand = &instr->src;

	switch (instr->flags & SrcMask) {
	case SrcNone:
		break;
	case SrcImm16:
		operand->type	= OP_IMM;
		operand->imm	= instr->imm_data;
		break;
	case SrcReg:
		operand->type	= OP_REG;
		operand->reg	= instr->reg_opc;
		break;
	}
}

static void
decode_imm16(struct x86_instr *instr, uint8_t imm_lo, uint8_t imm_hi)
{
	instr->imm_data	= (imm_hi << 8) | imm_lo;

	instr->nr_bytes	+= 2;
}

static void
decode_disp16(struct x86_instr *instr, uint8_t disp_lo, uint8_t disp_hi)
{
	instr->disp	= (int16_t)((disp_hi << 8) | disp_lo);

	instr->nr_bytes	+= 2;
}

static void
decode_disp8(struct x86_instr *instr, uint8_t disp)
{
	instr->disp	= (int8_t)disp;

	instr->nr_bytes	+= 1;
}

static void
decode_modrm_byte(struct x86_instr *instr, uint8_t modrm)
{
	instr->mod	= (modrm & 0xc0) >> 6;
	instr->reg_opc	= (modrm & 0x38) >> 3;
	instr->rm	= (modrm & 0x07);

	switch (instr->mod) {
	case 0x00:
		instr->flags	|= DstMem;
		break;
	case 0x01:
		instr->flags	|= DstMemDisp8;
		break;
	case 0x02:
		instr->flags	|= DstMemDisp16;
		break;
	case 0x03:
		instr->flags	|= DstReg;
		break;
	}
	instr->nr_bytes++;
}

int
arch_8086_decode_instr(struct x86_instr *instr, uint8_t* RAM, addr_t pc)
{
	uint8_t opcode;

	instr->nr_bytes = 1;

	/* Prefixes */
	instr->seg_override	= NO_OVERRIDE;
	for (;;) {
		switch (opcode = RAM[pc++]) {
		case 0x26:
			instr->seg_override	= ES_OVERRIDE;
			break;
		case 0x2e:
			instr->seg_override	= CS_OVERRIDE;
			break;
		case 0x36:
			instr->seg_override	= SS_OVERRIDE;
			break;
		case 0x3e:
			instr->seg_override	= DS_OVERRIDE;
			break;
		case 0xf2:	/* REPNE/REPNZ */
		case 0xf3:	/* REP/REPE/REPZ */
			break;
		default:
			goto done_prefixes;
		}
		instr->nr_bytes++;
	}

done_prefixes:

	/* Opcode byte */
	instr->opcode	= opcode;

	instr->flags	= decode_table[opcode];

	if (instr->flags == 0)	/* Unrecognized? */
		return -1;

	if (instr->flags & ModRM)
		decode_modrm_byte(instr, RAM[pc++]);

	if (instr->flags & DstMemDisp8)
		decode_disp8(instr, RAM[pc+0]);

	if (instr->flags & DstMemDisp16)
		decode_disp16(instr, RAM[pc+0], RAM[pc+1]);

	if (instr->flags & SrcImm16)
		decode_imm16(instr, RAM[pc+0], RAM[pc+1]);

	decode_src_operand(instr);

	decode_dst_operand(instr);

	return 0;
}

int
arch_8086_instr_length(struct x86_instr *instr)
{
	return instr->nr_bytes;
}
<commit_msg>x86: Fix decode_table formatting<commit_after>#include "libcpu.h"
#include "x86_isa.h"
#include "x86_decode.h"

static unsigned long decode_table[256] = {
	/*[0x0]*/	0,
	/*[0x1]*/	0,
	/*[0x2]*/	0,
	/*[0x3]*/	0,
	/*[0x4]*/	0,
	/*[0x5]*/	0,
	/*[0x6]*/	0,
	/*[0x7]*/	0,
	/*[0x8]*/	0,
	/*[0x9]*/	0,
	/*[0xA]*/	0,
	/*[0xB]*/	0,
	/*[0xC]*/	0,
	/*[0xD]*/	0,
	/*[0xE]*/	0,
	/*[0xF]*/	0,
	/*[0x10]*/	0,
	/*[0x11]*/	0,
	/*[0x12]*/	0,
	/*[0x13]*/	0,
	/*[0x14]*/	0,
	/*[0x15]*/	0,
	/*[0x16]*/	0,
	/*[0x17]*/	0,
	/*[0x18]*/	0,
	/*[0x19]*/	0,
	/*[0x1A]*/	0,
	/*[0x1B]*/	0,
	/*[0x1C]*/	0,
	/*[0x1D]*/	0,
	/*[0x1E]*/	0,
	/*[0x1F]*/	0,
	/*[0x20]*/	0,
	/*[0x21]*/	0,
	/*[0x22]*/	0,
	/*[0x23]*/	0,
	/*[0x24]*/	0,
	/*[0x25]*/	0,
	/*[0x26]*/	0,
	/*[0x27]*/	0,
	/*[0x28]*/	0,
	/*[0x29]*/	0,
	/*[0x2A]*/	0,
	/*[0x2B]*/	0,
	/*[0x2C]*/	0,
	/*[0x2D]*/	0,
	/*[0x2E]*/	0,
	/*[0x2F]*/	0,
	/*[0x30]*/	0,
	/*[0x31]*/	0,
	/*[0x32]*/	0,
	/*[0x33]*/	0,
	/*[0x34]*/	0,
	/*[0x35]*/	0,
	/*[0x36]*/	0,
	/*[0x37]*/	0,
	/*[0x38]*/	0,
	/*[0x39]*/	0,
	/*[0x3A]*/	0,
	/*[0x3B]*/	0,
	/*[0x3C]*/	0,
	/*[0x3D]*/	0,
	/*[0x3E]*/	0,
	/*[0x3F]*/	0,
	/*[0x40]*/	0,
	/*[0x41]*/	0,
	/*[0x42]*/	0,
	/*[0x43]*/	0,
	/*[0x44]*/	0,
	/*[0x45]*/	0,
	/*[0x46]*/	0,
	/*[0x47]*/	0,
	/*[0x48]*/	0,
	/*[0x49]*/	0,
	/*[0x4A]*/	0,
	/*[0x4B]*/	0,
	/*[0x4C]*/	0,
	/*[0x4D]*/	0,
	/*[0x4E]*/	0,
	/*[0x4F]*/	0,
	/*[0x50]*/	0,
	/*[0x51]*/	0,
	/*[0x52]*/	0,
	/*[0x53]*/	0,
	/*[0x54]*/	0,
	/*[0x55]*/	0,
	/*[0x56]*/	0,
	/*[0x57]*/	0,
	/*[0x58]*/	0,
	/*[0x59]*/	0,
	/*[0x5A]*/	0,
	/*[0x5B]*/	0,
	/*[0x5C]*/	0,
	/*[0x5D]*/	0,
	/*[0x5E]*/	0,
	/*[0x5F]*/	0,
	/*[0x60]*/	0,
	/*[0x61]*/	0,
	/*[0x62]*/	0,
	/*[0x63]*/	0,
	/*[0x64]*/	0,
	/*[0x65]*/	0,
	/*[0x66]*/	0,
	/*[0x67]*/	0,
	/*[0x68]*/	0,
	/*[0x69]*/	0,
	/*[0x6A]*/	0,
	/*[0x6B]*/	0,
	/*[0x6C]*/	0,
	/*[0x6D]*/	0,
	/*[0x6E]*/	0,
	/*[0x6F]*/	0,
	/*[0x70]*/	0,
	/*[0x71]*/	0,
	/*[0x72]*/	0,
	/*[0x73]*/	0,
	/*[0x74]*/	0,
	/*[0x75]*/	0,
	/*[0x76]*/	0,
	/*[0x77]*/	0,
	/*[0x78]*/	0,
	/*[0x79]*/	0,
	/*[0x7A]*/	0,
	/*[0x7B]*/	0,
	/*[0x7C]*/	0,
	/*[0x7D]*/	0,
	/*[0x7E]*/	0,
	/*[0x7F]*/	0,
	/*[0x80]*/	0,
	/*[0x81]*/	0,
	/*[0x82]*/	0,
	/*[0x83]*/	0,
	/*[0x84]*/	0,
	/*[0x85]*/	0,
	/*[0x86]*/	0,
	/*[0x87]*/	0,
	/*[0x88]*/	0,
	/*[0x89]*/	INSTR_MOV|ModRM|SrcReg,
	/*[0x8A]*/	0,
	/*[0x8B]*/	0,
	/*[0x8C]*/	0,
	/*[0x8D]*/	0,
	/*[0x8E]*/	0,
	/*[0x8F]*/	0,
	/*[0x90]*/	0,
	/*[0x91]*/	0,
	/*[0x92]*/	0,
	/*[0x93]*/	0,
	/*[0x94]*/	0,
	/*[0x95]*/	0,
	/*[0x96]*/	0,
	/*[0x97]*/	0,
	/*[0x98]*/	0,
	/*[0x99]*/	0,
	/*[0x9A]*/	0,
	/*[0x9B]*/	0,
	/*[0x9C]*/	0,
	/*[0x9D]*/	0,
	/*[0x9E]*/	0,
	/*[0x9F]*/	0,
	/*[0xA0]*/	0,
	/*[0xA1]*/	0,
	/*[0xA2]*/	0,
	/*[0xA3]*/	0,
	/*[0xA4]*/	0,
	/*[0xA5]*/	0,
	/*[0xA6]*/	0,
	/*[0xA7]*/	0,
	/*[0xA8]*/	0,
	/*[0xA9]*/	0,
	/*[0xAA]*/	0,
	/*[0xAB]*/	0,
	/*[0xAC]*/	0,
	/*[0xAD]*/	0,
	/*[0xAE]*/	0,
	/*[0xAF]*/	0,
	/*[0xB0]*/	0,
	/*[0xB1]*/	0,
	/*[0xB2]*/	0,
	/*[0xB3]*/	0,
	/*[0xB4]*/	0,
	/*[0xB5]*/	0,
	/*[0xB6]*/	0,
	/*[0xB7]*/	0,
	/*[0xB8]*/	INSTR_MOV|SrcImm16|DstReg,
	/*[0xB9]*/	INSTR_MOV|SrcImm16|DstReg,
	/*[0xBA]*/	INSTR_MOV|SrcImm16|DstReg,
	/*[0xBB]*/	INSTR_MOV|SrcImm16|DstReg,
	/*[0xBC]*/	0,
	/*[0xBD]*/	0,
	/*[0xBE]*/	0,
	/*[0xBF]*/	0,
	/*[0xC0]*/	0,
	/*[0xC1]*/	0,
	/*[0xC2]*/	0,
	/*[0xC3]*/	INSTR_RET|SrcNone|DstNone,
	/*[0xC4]*/	0,
	/*[0xC5]*/	0,
	/*[0xC6]*/	0,
	/*[0xC7]*/	0,
	/*[0xC8]*/	0,
	/*[0xC9]*/	0,
	/*[0xCA]*/	0,
	/*[0xCB]*/	0,
	/*[0xCC]*/	0,
	/*[0xCD]*/	0,
	/*[0xCE]*/	0,
	/*[0xCF]*/	0,
	/*[0xD0]*/	0,
	/*[0xD1]*/	0,
	/*[0xD2]*/	0,
	/*[0xD3]*/	0,
	/*[0xD4]*/	0,
	/*[0xD5]*/	0,
	/*[0xD6]*/	0,
	/*[0xD7]*/	0,
	/*[0xD8]*/	0,
	/*[0xD9]*/	0,
	/*[0xDA]*/	0,
	/*[0xDB]*/	0,
	/*[0xDC]*/	0,
	/*[0xDD]*/	0,
	/*[0xDE]*/	0,
	/*[0xDF]*/	0,
	/*[0xE0]*/	0,
	/*[0xE1]*/	0,
	/*[0xE2]*/	0,
	/*[0xE3]*/	0,
	/*[0xE4]*/	0,
	/*[0xE5]*/	0,
	/*[0xE6]*/	0,
	/*[0xE7]*/	0,
	/*[0xE8]*/	0,
	/*[0xE9]*/	0,
	/*[0xEA]*/	0,
	/*[0xEB]*/	0,
	/*[0xEC]*/	0,
	/*[0xED]*/	0,
	/*[0xEE]*/	0,
	/*[0xEF]*/	0,
	/*[0xF0]*/	0,
	/*[0xF1]*/	0,
	/*[0xF2]*/	0,
	/*[0xF3]*/	0,
	/*[0xF4]*/	0,
	/*[0xF5]*/	0,
	/*[0xF6]*/	0,
	/*[0xF7]*/	0,
	/*[0xF8]*/	0,
	/*[0xF9]*/	0,
	/*[0xFA]*/	0,
	/*[0xFB]*/	0,
	/*[0xFC]*/	0,
	/*[0xFD]*/	0,
	/*[0xFE]*/	0,
	/*[0xFF]*/	0,
};

static void
decode_dst_operand(struct x86_instr *instr)
{
	struct x86_operand *operand = &instr->dst;

	switch (instr->flags & DstMask) {
	case DstNone:
		break;
	case DstReg:
		operand->type	= OP_REG;

		if (instr->flags & ModRM)
			operand->reg	= instr->rm;
		else
			operand->reg	= instr->opcode & 0x03;
		break;
	case DstMem:
		operand->type	= OP_MEM;
		operand->reg	= instr->rm;
		break;
	case DstMemDisp8:
	case DstMemDisp16:
		operand->type	= OP_MEM_DISP;
		operand->reg	= instr->rm;
		operand->disp	= instr->disp;
		break;
	}
}

static void
decode_src_operand(struct x86_instr *instr)
{
	struct x86_operand *operand = &instr->src;

	switch (instr->flags & SrcMask) {
	case SrcNone:
		break;
	case SrcImm16:
		operand->type	= OP_IMM;
		operand->imm	= instr->imm_data;
		break;
	case SrcReg:
		operand->type	= OP_REG;
		operand->reg	= instr->reg_opc;
		break;
	}
}

static void
decode_imm16(struct x86_instr *instr, uint8_t imm_lo, uint8_t imm_hi)
{
	instr->imm_data	= (imm_hi << 8) | imm_lo;

	instr->nr_bytes	+= 2;
}

static void
decode_disp16(struct x86_instr *instr, uint8_t disp_lo, uint8_t disp_hi)
{
	instr->disp	= (int16_t)((disp_hi << 8) | disp_lo);

	instr->nr_bytes	+= 2;
}

static void
decode_disp8(struct x86_instr *instr, uint8_t disp)
{
	instr->disp	= (int8_t)disp;

	instr->nr_bytes	+= 1;
}

static void
decode_modrm_byte(struct x86_instr *instr, uint8_t modrm)
{
	instr->mod	= (modrm & 0xc0) >> 6;
	instr->reg_opc	= (modrm & 0x38) >> 3;
	instr->rm	= (modrm & 0x07);

	switch (instr->mod) {
	case 0x00:
		instr->flags	|= DstMem;
		break;
	case 0x01:
		instr->flags	|= DstMemDisp8;
		break;
	case 0x02:
		instr->flags	|= DstMemDisp16;
		break;
	case 0x03:
		instr->flags	|= DstReg;
		break;
	}
	instr->nr_bytes++;
}

int
arch_8086_decode_instr(struct x86_instr *instr, uint8_t* RAM, addr_t pc)
{
	uint8_t opcode;

	instr->nr_bytes = 1;

	/* Prefixes */
	instr->seg_override	= NO_OVERRIDE;
	for (;;) {
		switch (opcode = RAM[pc++]) {
		case 0x26:
			instr->seg_override	= ES_OVERRIDE;
			break;
		case 0x2e:
			instr->seg_override	= CS_OVERRIDE;
			break;
		case 0x36:
			instr->seg_override	= SS_OVERRIDE;
			break;
		case 0x3e:
			instr->seg_override	= DS_OVERRIDE;
			break;
		case 0xf2:	/* REPNE/REPNZ */
		case 0xf3:	/* REP/REPE/REPZ */
			break;
		default:
			goto done_prefixes;
		}
		instr->nr_bytes++;
	}

done_prefixes:

	/* Opcode byte */
	instr->opcode	= opcode;

	instr->flags	= decode_table[opcode];

	if (instr->flags == 0)	/* Unrecognized? */
		return -1;

	if (instr->flags & ModRM)
		decode_modrm_byte(instr, RAM[pc++]);

	if (instr->flags & DstMemDisp8)
		decode_disp8(instr, RAM[pc+0]);

	if (instr->flags & DstMemDisp16)
		decode_disp16(instr, RAM[pc+0], RAM[pc+1]);

	if (instr->flags & SrcImm16)
		decode_imm16(instr, RAM[pc+0], RAM[pc+1]);

	decode_src_operand(instr);

	decode_dst_operand(instr);

	return 0;
}

int
arch_8086_instr_length(struct x86_instr *instr)
{
	return instr->nr_bytes;
}
<|endoftext|>


<commit_before>#include <stdlib.h>
#include <stdio.h>

#include "libcpu.h"
#include "x86_isa.h"
#include "x86_decode.h"

static const char* mnemo[] = {
	/* [INSTR_AAA] */	 "aaa",
	/* [INSTR_AAD] */	 "aad",
	/* [INSTR_AAM] */	 "aam",
	/* [INSTR_AAS] */	 "aas",
	/* [INSTR_ADC] */	 "adc",
	/* [INSTR_ADD] */	 "add",
	/* [INSTR_AND] */	 "and",
	/* [INSTR_CALL] */	 "call",
	/* [INSTR_CBW] */	 "cbw",
	/* [INSTR_CLC] */	 "clc",
	/* [INSTR_CLD] */	 "cld",
	/* [INSTR_CLI] */	 "cli",
	/* [INSTR_CMC] */	 "cmc",
	/* [INSTR_CMP] */	 "cmp",
	/* [INSTR_CMPSB] */	 "cmpsb",
	/* [INSTR_CMPSW] */	 "cmpsw",
	/* [INSTR_CWD] */	 "cwd",
	/* [INSTR_DAA] */	 "daa",
	/* [INSTR_DAS] */	 "das",
	/* [INSTR_DEC] */	 "dec",
	/* [INSTR_DIV] */	 "div",
	/* [INSTR_HLT] */	 "hlt",
	/* [INSTR_IDIV] */	 "idiv",
	/* [INSTR_IMUL] */	 "imul",
	/* [INSTR_IN] */	 "in",
	/* [INSTR_INC] */	 "inc",
	/* [INSTR_INT] */	 "int",
	/* [INSTR_INTO] */	 "into",
	/* [INSTR_IRET] */	 "iret",
	/* [INSTR_JA] */	 "ja",
	/* [INSTR_JAE] */	 "jae",
	/* [INSTR_JB] */	 "jb",
	/* [INSTR_JBE] */	 "jbe",
	/* [INSTR_JC] */	 "jc",
	/* [INSTR_JCXZ] */	 "jcxz",
	/* [INSTR_JE] */	 "je",
	/* [INSTR_JG] */	 "jg",
	/* [INSTR_JGE] */	 "jge",
	/* [INSTR_JL] */	 "jl",
	/* [INSTR_JLE] */	 "jle",
	/* [INSTR_JMP] */	 "jmp",
	/* [INSTR_JNA] */	 "jna",
	/* [INSTR_JNAE] */	 "jnae",
	/* [INSTR_JNB] */	 "jnb",
	/* [INSTR_JNBE] */	 "jnbe",
	/* [INSTR_JNC] */	 "jnc",
	/* [INSTR_JNE] */	 "jne",
	/* [INSTR_JNG] */	 "jng",
	/* [INSTR_JNGE] */	 "jnge",
	/* [INSTR_JNL] */	 "jnl",
	/* [INSTR_JNLE] */	 "jnle",
	/* [INSTR_JNO] */	 "jno",
	/* [INSTR_JNP] */	 "jnp",
	/* [INSTR_JNS] */	 "jns",
	/* [INSTR_JNZ] */	 "jnz",
	/* [INSTR_JO] */	 "jo",
	/* [INSTR_JP] */	 "jp",
	/* [INSTR_JPE] */	 "jpe",
	/* [INSTR_JPO] */	 "jpo",
	/* [INSTR_JS] */	 "js",
	/* [INSTR_JZ] */	 "jz",
	/* [INSTR_LAHF] */	 "lahf",
	/* [INSTR_LDS] */	 "lds",
	/* [INSTR_LEA] */	 "lea",
	/* [INSTR_LES] */	 "les",
	/* [INSTR_LODSB] */	 "lodsb",
	/* [INSTR_LODSW] */	 "lodsw",
	/* [INSTR_LOOP] */	 "loop",
	/* [INSTR_LOOPE] */	 "loope",
	/* [INSTR_LOOPNE] */	 "loopne",
	/* [INSTR_LOOPNZ] */	 "loopnz",
	/* [INSTR_LOOPZ] */	 "loopz",
	/* [INSTR_MOV] */	 "mov",
	/* [INSTR_MOVSB] */	 "movsb",
	/* [INSTR_MOVSW] */	 "movsw",
	/* [INSTR_MUL] */	 "mul",
	/* [INSTR_NEG] */	 "neg",
	/* [INSTR_NOP] */	 "nop",
	/* [INSTR_NOT] */	 "not",
	/* [INSTR_OR] */	 "or",
	/* [INSTR_OUT] */	 "out",
	/* [INSTR_POP] */	 "pop",
	/* [INSTR_POPA] */	 "popa",
	/* [INSTR_POPF] */	 "popf",
	/* [INSTR_PUSH] */	 "push",
	/* [INSTR_PUSHA] */	 "pusha",
	/* [INSTR_PUSHF] */	 "pushf",
	/* [INSTR_RCL] */	 "rcl",
	/* [INSTR_RCR] */	 "rcr",
	/* [INSTR_REP] */	 "rep",
	/* [INSTR_REPE] */	 "repe",
	/* [INSTR_REPNE] */	 "repne",
	/* [INSTR_REPNZ] */	 "repnz",
	/* [INSTR_REPZ] */	 "repz",
	/* [INSTR_RET] */	 "ret",
	/* [INSTR_RETF] */	 "retf",
	/* [INSTR_ROL] */	 "rol",
	/* [INSTR_ROR] */	 "ror",
	/* [INSTR_SAHF] */	 "sahf",
	/* [INSTR_SAL] */	 "sal",
	/* [INSTR_SAR] */	 "sar",
	/* [INSTR_SBB] */	 "sbb",
	/* [INSTR_SCASB] */	 "scasb",
	/* [INSTR_SCASW] */	 "scasw",
	/* [INSTR_SHL] */	 "shl",
	/* [INSTR_SHR] */	 "shr",
	/* [INSTR_STC] */	 "stc",
	/* [INSTR_STD] */	 "std",
	/* [INSTR_STI] */	 "sti",
	/* [INSTR_STOSB] */	 "stosb",
	/* [INSTR_STOSW] */	 "stosw",
	/* [INSTR_SUB] */	 "sub",
	/* [INSTR_TEST] */	 "test",
	/* [INSTR_XCHG] */	 "xchg",
	/* [INSTR_XLATB] */	 "xlatb",
	/* [INSTR_XOR] */	 "xor",
};

static const char *to_mnemonic(struct x86_instr *instr)
{
	return mnemo[x86_instr_type(instr)];
}

static const char *reg_names[] = {
	"al",
	"cl",
	"dl",
	"bl",
	"ah",
	"ch",
	"dh",
	"bh",
};

static const char *reg_names_wide[] = {
	"ax",
	"cx",
	"dx",
	"bx",
	"sp",
	"bp",
	"si",
	"di",
};

static const char *mem_reg_names[] = {
	"bx+si",
	"bx+di",
	"bp+si",
	"bp+di",
	"si",
	"di",
	NULL,
	"bx",
};

static const char *seg_override_names[] = {
	"",
	"es:",
	"cs:",
	"ss:",
	"ds:",
};

static const char *to_reg_name(int reg_num, int byte_op)
{
	if (byte_op)
		return reg_names[reg_num];

	return reg_names_wide[reg_num];
}

static int
print_operand(char *operands, size_t size, struct x86_instr *instr, struct x86_operand *operand)
{
	int ret;

	switch (operand->type) {
	case OP_IMM:
		ret = snprintf(operands, size, "$0x%x", operand->imm);
		break;
	case OP_REG:
		ret = snprintf(operands, size, "%s", to_reg_name(operand->reg, instr->flags & ByteOp));
		break;
	case OP_MEM:
		ret = snprintf(operands, size, "%s(%s)", seg_override_names[instr->seg_override], mem_reg_names[operand->reg]);
		break;
	}
	return ret;
}

int
arch_8086_disasm_instr(cpu_t *cpu, addr_t pc, char *line, unsigned int max_line)
{
	struct x86_instr instr;
	char operands[32];
	int len = 0;

	if (arch_8086_decode_instr(&instr, cpu->RAM, pc) != 0) {
		fprintf(stderr, "error: unable to decode opcode %x\n", cpu->RAM[pc]);
		exit(1);
	}

	operands[0] = '\0';

	/* AT&T syntax operands */
	if (!(instr.flags & SrcNone))
		len += print_operand(operands+len, sizeof(operands)-len, &instr, &instr.src);

	if (!(instr.flags & SrcNone) && !(instr.flags & DstNone))
		len += snprintf(operands+len, sizeof(operands)-len, ",");

	if (!(instr.flags & DstNone))
		len += print_operand(operands+len, sizeof(operands)-len, &instr, &instr.dst);

        snprintf(line, max_line, "%s\t%s", to_mnemonic(&instr), operands);

        return arch_8086_instr_length(&instr);
}
<commit_msg>x86: Fix register pretty print<commit_after>#include <stdlib.h>
#include <stdio.h>

#include "libcpu.h"
#include "x86_isa.h"
#include "x86_decode.h"

static const char* mnemo[] = {
	/* [INSTR_AAA] */	 "aaa",
	/* [INSTR_AAD] */	 "aad",
	/* [INSTR_AAM] */	 "aam",
	/* [INSTR_AAS] */	 "aas",
	/* [INSTR_ADC] */	 "adc",
	/* [INSTR_ADD] */	 "add",
	/* [INSTR_AND] */	 "and",
	/* [INSTR_CALL] */	 "call",
	/* [INSTR_CBW] */	 "cbw",
	/* [INSTR_CLC] */	 "clc",
	/* [INSTR_CLD] */	 "cld",
	/* [INSTR_CLI] */	 "cli",
	/* [INSTR_CMC] */	 "cmc",
	/* [INSTR_CMP] */	 "cmp",
	/* [INSTR_CMPSB] */	 "cmpsb",
	/* [INSTR_CMPSW] */	 "cmpsw",
	/* [INSTR_CWD] */	 "cwd",
	/* [INSTR_DAA] */	 "daa",
	/* [INSTR_DAS] */	 "das",
	/* [INSTR_DEC] */	 "dec",
	/* [INSTR_DIV] */	 "div",
	/* [INSTR_HLT] */	 "hlt",
	/* [INSTR_IDIV] */	 "idiv",
	/* [INSTR_IMUL] */	 "imul",
	/* [INSTR_IN] */	 "in",
	/* [INSTR_INC] */	 "inc",
	/* [INSTR_INT] */	 "int",
	/* [INSTR_INTO] */	 "into",
	/* [INSTR_IRET] */	 "iret",
	/* [INSTR_JA] */	 "ja",
	/* [INSTR_JAE] */	 "jae",
	/* [INSTR_JB] */	 "jb",
	/* [INSTR_JBE] */	 "jbe",
	/* [INSTR_JC] */	 "jc",
	/* [INSTR_JCXZ] */	 "jcxz",
	/* [INSTR_JE] */	 "je",
	/* [INSTR_JG] */	 "jg",
	/* [INSTR_JGE] */	 "jge",
	/* [INSTR_JL] */	 "jl",
	/* [INSTR_JLE] */	 "jle",
	/* [INSTR_JMP] */	 "jmp",
	/* [INSTR_JNA] */	 "jna",
	/* [INSTR_JNAE] */	 "jnae",
	/* [INSTR_JNB] */	 "jnb",
	/* [INSTR_JNBE] */	 "jnbe",
	/* [INSTR_JNC] */	 "jnc",
	/* [INSTR_JNE] */	 "jne",
	/* [INSTR_JNG] */	 "jng",
	/* [INSTR_JNGE] */	 "jnge",
	/* [INSTR_JNL] */	 "jnl",
	/* [INSTR_JNLE] */	 "jnle",
	/* [INSTR_JNO] */	 "jno",
	/* [INSTR_JNP] */	 "jnp",
	/* [INSTR_JNS] */	 "jns",
	/* [INSTR_JNZ] */	 "jnz",
	/* [INSTR_JO] */	 "jo",
	/* [INSTR_JP] */	 "jp",
	/* [INSTR_JPE] */	 "jpe",
	/* [INSTR_JPO] */	 "jpo",
	/* [INSTR_JS] */	 "js",
	/* [INSTR_JZ] */	 "jz",
	/* [INSTR_LAHF] */	 "lahf",
	/* [INSTR_LDS] */	 "lds",
	/* [INSTR_LEA] */	 "lea",
	/* [INSTR_LES] */	 "les",
	/* [INSTR_LODSB] */	 "lodsb",
	/* [INSTR_LODSW] */	 "lodsw",
	/* [INSTR_LOOP] */	 "loop",
	/* [INSTR_LOOPE] */	 "loope",
	/* [INSTR_LOOPNE] */	 "loopne",
	/* [INSTR_LOOPNZ] */	 "loopnz",
	/* [INSTR_LOOPZ] */	 "loopz",
	/* [INSTR_MOV] */	 "mov",
	/* [INSTR_MOVSB] */	 "movsb",
	/* [INSTR_MOVSW] */	 "movsw",
	/* [INSTR_MUL] */	 "mul",
	/* [INSTR_NEG] */	 "neg",
	/* [INSTR_NOP] */	 "nop",
	/* [INSTR_NOT] */	 "not",
	/* [INSTR_OR] */	 "or",
	/* [INSTR_OUT] */	 "out",
	/* [INSTR_POP] */	 "pop",
	/* [INSTR_POPA] */	 "popa",
	/* [INSTR_POPF] */	 "popf",
	/* [INSTR_PUSH] */	 "push",
	/* [INSTR_PUSHA] */	 "pusha",
	/* [INSTR_PUSHF] */	 "pushf",
	/* [INSTR_RCL] */	 "rcl",
	/* [INSTR_RCR] */	 "rcr",
	/* [INSTR_REP] */	 "rep",
	/* [INSTR_REPE] */	 "repe",
	/* [INSTR_REPNE] */	 "repne",
	/* [INSTR_REPNZ] */	 "repnz",
	/* [INSTR_REPZ] */	 "repz",
	/* [INSTR_RET] */	 "ret",
	/* [INSTR_RETF] */	 "retf",
	/* [INSTR_ROL] */	 "rol",
	/* [INSTR_ROR] */	 "ror",
	/* [INSTR_SAHF] */	 "sahf",
	/* [INSTR_SAL] */	 "sal",
	/* [INSTR_SAR] */	 "sar",
	/* [INSTR_SBB] */	 "sbb",
	/* [INSTR_SCASB] */	 "scasb",
	/* [INSTR_SCASW] */	 "scasw",
	/* [INSTR_SHL] */	 "shl",
	/* [INSTR_SHR] */	 "shr",
	/* [INSTR_STC] */	 "stc",
	/* [INSTR_STD] */	 "std",
	/* [INSTR_STI] */	 "sti",
	/* [INSTR_STOSB] */	 "stosb",
	/* [INSTR_STOSW] */	 "stosw",
	/* [INSTR_SUB] */	 "sub",
	/* [INSTR_TEST] */	 "test",
	/* [INSTR_XCHG] */	 "xchg",
	/* [INSTR_XLATB] */	 "xlatb",
	/* [INSTR_XOR] */	 "xor",
};

static const char *to_mnemonic(struct x86_instr *instr)
{
	return mnemo[x86_instr_type(instr)];
}

static const char *reg_names[] = {
	"%al",
	"%cl",
	"%dl",
	"%bl",
	"%ah",
	"%ch",
	"%dh",
	"%bh",
};

static const char *reg_names_wide[] = {
	"%ax",
	"%cx",
	"%dx",
	"%bx",
	"%sp",
	"%bp",
	"%si",
	"%di",
};

static const char *mem_reg_names[] = {
	"%bx+si",
	"%bx+di",
	"%bp+si",
	"%bp+di",
	"%si",
	"%di",
	NULL,
	"%bx",
};

static const char *seg_override_names[] = {
	"",
	"%es:",
	"%cs:",
	"%ss:",
	"%ds:",
};

static const char *to_reg_name(int reg_num, int byte_op)
{
	if (byte_op)
		return reg_names[reg_num];

	return reg_names_wide[reg_num];
}

static int
print_operand(char *operands, size_t size, struct x86_instr *instr, struct x86_operand *operand)
{
	int ret;

	switch (operand->type) {
	case OP_IMM:
		ret = snprintf(operands, size, "$0x%x", operand->imm);
		break;
	case OP_REG:
		ret = snprintf(operands, size, "%s", to_reg_name(operand->reg, instr->flags & ByteOp));
		break;
	case OP_MEM:
		ret = snprintf(operands, size, "%s(%s)", seg_override_names[instr->seg_override], mem_reg_names[operand->reg]);
		break;
	}
	return ret;
}

int
arch_8086_disasm_instr(cpu_t *cpu, addr_t pc, char *line, unsigned int max_line)
{
	struct x86_instr instr;
	char operands[32];
	int len = 0;

	if (arch_8086_decode_instr(&instr, cpu->RAM, pc) != 0) {
		fprintf(stderr, "error: unable to decode opcode %x\n", cpu->RAM[pc]);
		exit(1);
	}

	operands[0] = '\0';

	/* AT&T syntax operands */
	if (!(instr.flags & SrcNone))
		len += print_operand(operands+len, sizeof(operands)-len, &instr, &instr.src);

	if (!(instr.flags & SrcNone) && !(instr.flags & DstNone))
		len += snprintf(operands+len, sizeof(operands)-len, ",");

	if (!(instr.flags & DstNone))
		len += print_operand(operands+len, sizeof(operands)-len, &instr, &instr.dst);

        snprintf(line, max_line, "%s\t%s", to_mnemonic(&instr), operands);

        return arch_8086_instr_length(&instr);
}
<|endoftext|>


<commit_before>/**
 * Unit tests for ports
 * @author Denis Los
 */

#include "../module.h"
#include <catch.hpp>
#include <map>

static const int NONE = -1;
static const int DATA_LIMIT = 5;
static const Cycle EXPECTED_MAX_CYCLE = 8_cl;
static const Cycle CLOCK_LIMIT = 10_cl;

enum CheckCode {  MODULE_A, MODULE_B };

static bool check_data( Cycle cycle, CheckCode code, int data)
{
    static std::map<Cycle, std::pair<int, int>> script =
    // | CYCLE |MODULE_A|MODULE_B|
    {
       { 0_cl, { NONE,    NONE }},
       { 1_cl, { NONE,    NONE }},
       { 2_cl, { 1,       NONE }},
       { 3_cl, { NONE,    2    }},
       { 4_cl, { 3,       NONE }},
       { 5_cl, { NONE,    4    }},
       { 6_cl, { 5,       NONE }},
       { 7_cl, { NONE,    6    }},
       { 8_cl, { NONE,    NONE }}
    };

    if ( cycle > EXPECTED_MAX_CYCLE)
        return false;

    switch ( code)
    {
    case MODULE_A: return script[cycle].first  == data;
    case MODULE_B: return script[cycle].second == data;
    default: return false;
    };
}

static bool check_readiness( Cycle cycle, CheckCode code, bool is_ready)
{
    return check_data( cycle, code, NONE) != is_ready;
}

class A : public Module
{
public:
    explicit A( Module* root) : Module( root, "A")
    {
        to_B = make_write_port<int>( "A_to_B", PORT_BW);
        from_B = make_read_port<int>( "B_to_A", PORT_LATENCY);
        init = make_read_port<int>( "init_A", PORT_LATENCY);
        stop = make_write_port<bool>( "stop", PORT_BW);
    }

    void clock( Cycle cycle)
    {
        bool is_init_ready = init->is_ready( cycle);
        bool is_from_B_ready = from_B->is_ready( cycle);

        if ( cycle != 1_cl)
            CHECK( !is_init_ready);
        CHECK( check_readiness( cycle, MODULE_B, is_from_B_ready));

        if ( is_init_ready)
        {
            auto data = init->read( cycle);
            CHECK( cycle == 1_cl );
            CHECK( data == 0 );
            to_B->write( data + 1, cycle);
        }
        else if ( is_from_B_ready)
        {
            auto data = from_B->read( cycle);
            CHECK( check_data( cycle, MODULE_B, data));
            if ( data >= DATA_LIMIT)
                stop->write( true, cycle);
            else
                to_B->write( data + 1, cycle);
        }
    }

private:
    WritePort<int>* to_B;
    ReadPort<int>* from_B;
    ReadPort<int>* init;
    WritePort<bool>* stop;
};

class B : public Module
{
public:
    explicit B(  Module* root) : Module( root, "B")
    {
        to_A = make_write_port<int>( "B_to_A", PORT_BW);
        from_A = make_read_port<int>( "A_to_B", PORT_LATENCY);
    };

    void clock( Cycle cycle)
    {
        bool is_from_A_ready = from_A->is_ready( cycle);
        CHECK( check_readiness( cycle, MODULE_A, is_from_A_ready));
        if ( is_from_A_ready)
        {
            auto data = from_A->read( cycle);
            CHECK( check_data( cycle, MODULE_A, data));
            to_A->write( data + 1, cycle);
        }
    }

private:
    WritePort<int>* to_A;
    ReadPort<int>* from_A;
};

class TestRoot : public Root
{
public:
    TestRoot() : Root( "test-root"), a( this), b( this)
    {
        init = make_write_port<int>( "init_A", PORT_BW);
        stop = make_read_port<bool>( "stop", PORT_LATENCY);
        init_portmap();
        CHECK( init->get_fanout() == 1);

        // init object A by value 0
        init->write( 0, 0_cl);
    }

    bool clock( Cycle cycle)
    {
        if ( stop->is_ready( cycle))
        {
            CHECK( cycle == EXPECTED_MAX_CYCLE);
            stop->read( cycle);
            return true;
        }

        CHECK( cycle < EXPECTED_MAX_CYCLE);
        a.clock( cycle);
        b.clock( cycle);
        return false;
    }
private:
    A a;
    B b;

    WritePort<int>* init;
    ReadPort<bool>* stop;
};

TEST_CASE( "test_ports: Test_Ports_A_B")
{
    TestRoot tr;

    for ( auto cycle = 0_cl; cycle < CLOCK_LIMIT; cycle.inc())
        if ( tr.clock( cycle))
            break;
}
<commit_msg>Delete dead code from ports example test (#1209)<commit_after>/**
 * Unit tests for ports
 * @author Denis Los
 */

#include "../module.h"
#include <catch.hpp>

#include <cassert>
#include <map>

static const constexpr int NONE = -1;
static const constexpr int DATA_LIMIT = 5;

enum CheckCode {  MODULE_A, MODULE_B };

static bool check_data( Cycle cycle, CheckCode code, int data)
{
    static std::map<Cycle, std::pair<int, int>> script =
    // | CYCLE |MODULE_A|MODULE_B|
    {
       { 0_cl, { NONE,    NONE }},
       { 1_cl, { NONE,    NONE }},
       { 2_cl, { 1,       NONE }},
       { 3_cl, { NONE,    2    }},
       { 4_cl, { 3,       NONE }},
       { 5_cl, { NONE,    4    }},
       { 6_cl, { 5,       NONE }},
       { 7_cl, { NONE,    6    }},
       { 8_cl, { NONE,    NONE }}
    };

    return ( code == MODULE_A ? script.at( cycle).first : script.at( cycle).second) == data;
}

static bool check_readiness( Cycle cycle, CheckCode code, bool is_ready)
{
    return check_data( cycle, code, NONE) != is_ready;
}

class A : public Module
{
public:
    explicit A( Module* root) : Module( root, "A")
    {
        to_B = make_write_port<int>( "A_to_B", PORT_BW);
        from_B = make_read_port<int>( "B_to_A", PORT_LATENCY);
        init = make_read_port<int>( "init_A", PORT_LATENCY);
        stop = make_write_port<bool>( "stop", PORT_BW);
    }

    void clock( Cycle cycle)
    {
        bool is_init_ready = init->is_ready( cycle);
        bool is_from_B_ready = from_B->is_ready( cycle);

        if ( cycle != 1_cl)
            CHECK( !is_init_ready);
        CHECK( check_readiness( cycle, MODULE_B, is_from_B_ready));

        if ( is_init_ready)
        {
            auto data = init->read( cycle);
            CHECK( cycle == 1_cl );
            CHECK( data == 0 );
            to_B->write( data + 1, cycle);
        }
        else if ( is_from_B_ready)
        {
            auto data = from_B->read( cycle);
            CHECK( check_data( cycle, MODULE_B, data));
            if ( data >= DATA_LIMIT)
                stop->write( true, cycle);
            else
                to_B->write( data + 1, cycle);
        }
    }

private:
    WritePort<int>* to_B;
    ReadPort<int>* from_B;
    ReadPort<int>* init;
    WritePort<bool>* stop;
};

class B : public Module
{
public:
    explicit B(  Module* root) : Module( root, "B")
    {
        to_A = make_write_port<int>( "B_to_A", PORT_BW);
        from_A = make_read_port<int>( "A_to_B", PORT_LATENCY);
    };

    void clock( Cycle cycle)
    {
        bool is_from_A_ready = from_A->is_ready( cycle);
        CHECK( check_readiness( cycle, MODULE_A, is_from_A_ready));
        if ( is_from_A_ready)
        {
            auto data = from_A->read( cycle);
            CHECK( check_data( cycle, MODULE_A, data));
            to_A->write( data + 1, cycle);
        }
    }

private:
    WritePort<int>* to_A;
    ReadPort<int>* from_A;
};

class TestRoot : public Root
{
public:
    TestRoot() : Root( "test-root"), a( this), b( this)
    {
        init = make_write_port<int>( "init_A", PORT_BW);
        stop = make_read_port<bool>( "stop", PORT_LATENCY);
        init_portmap();
        CHECK( init->get_fanout() == 1);

        // init object A by value 0
        init->write( 0, 0_cl);
    }

    bool clock( Cycle cycle)
    {
        if ( stop->is_ready( cycle))
        {
            stop->read( cycle);
            return true;
        }

        a.clock( cycle);
        b.clock( cycle);
        return false;
    }
private:
    A a;
    B b;

    WritePort<int>* init;
    ReadPort<bool>* stop;
};

TEST_CASE( "test_ports: Test_Ports_A_B")
{
    static const constexpr Cycle CLOCK_LIMIT = 10_cl;
    TestRoot tr;

    for ( auto cycle = 0_cl; cycle < CLOCK_LIMIT; cycle.inc())
        if ( tr.clock( cycle))
            break;
}
<|endoftext|>


<commit_before>////////////////////////////////////////////////////////////////////////////////
/// @brief V8 Traverser
///
/// @file
///
/// DISCLAIMER
///
/// Copyright 2014-2015 ArangoDB GmbH, Cologne, Germany
/// Copyright 2004-2014 triAGENS GmbH, Cologne, Germany
///
/// Licensed under the Apache License, Version 2.0 (the "License");
/// you may not use this file except in compliance with the License.
/// You may obtain a copy of the License at
///
///     http://www.apache.org/licenses/LICENSE-2.0
///
/// Unless required by applicable law or agreed to in writing, software
/// distributed under the License is distributed on an "AS IS" BASIS,
/// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
/// See the License for the specific language governing permissions and
/// limitations under the License.
///
/// Copyright holder is ArangoDB GmbH, Cologne, Germany
///
/// @author Michael Hackstein
/// @author Copyright 2014-2015, ArangoDB GmbH, Cologne, Germany
/// @author Copyright 2012-2013, triAGENS GmbH, Cologne, Germany
////////////////////////////////////////////////////////////////////////////////

#include "v8.h"
#include "V8/v8-conv.h"
#include "V8/v8-utils.h"
#include "V8Server/v8-vocbaseprivate.h"
#include "V8Server/v8-wrapshapedjson.h"
#include "V8Server/v8-vocindex.h"
#include "V8Server/v8-collection.h"
#include "Utils/transactions.h"
#include "Utils/V8ResolverGuard.h"
#include "Utils/CollectionNameResolver.h"
#include "VocBase/document-collection.h"
#include "Traverser.h"
#include "VocBase/key-generator.h"

using namespace std;
using namespace triagens::basics;
using namespace triagens::arango;

class SimpleEdgeExpander {

  private:
////////////////////////////////////////////////////////////////////////////////
/// @brief direction of expansion
////////////////////////////////////////////////////////////////////////////////

    TRI_edge_direction_e direction;

////////////////////////////////////////////////////////////////////////////////
/// @brief edge collection
////////////////////////////////////////////////////////////////////////////////

    TRI_document_collection_t* edgeCollection;

////////////////////////////////////////////////////////////////////////////////
/// @brief collection name and /
////////////////////////////////////////////////////////////////////////////////

    string edgeIdPrefix;

////////////////////////////////////////////////////////////////////////////////
/// @brief the collection name resolver
////////////////////////////////////////////////////////////////////////////////

    CollectionNameResolver* resolver;

////////////////////////////////////////////////////////////////////////////////
/// @brief this indicates whether or not a distance attribute is used or
/// whether all edges are considered to have weight 1
////////////////////////////////////////////////////////////////////////////////

    bool usesDist;

////////////////////////////////////////////////////////////////////////////////
/// @brief an ID for the expander, just for debuggin
////////////////////////////////////////////////////////////////////////////////

    string id;

  public:

    SimpleEdgeExpander(TRI_edge_direction_e direction,
                       TRI_document_collection_t* edgeCollection,
                       string edgeCollectionName,
                       CollectionNameResolver* resolver,
                       string id)
      : direction(direction), edgeCollection(edgeCollection),
        resolver(resolver), usesDist(false), id(id)
    {
      edgeIdPrefix = edgeCollectionName + "/";
    };

    Traverser::VertexId extractFromId(TRI_doc_mptr_copy_t& ptr) {
      char const* key = TRI_EXTRACT_MARKER_FROM_KEY(&ptr);
      TRI_voc_cid_t cid = TRI_EXTRACT_MARKER_FROM_CID(&ptr);
      string col = resolver->getCollectionName(cid);
      col.append("/");
      col.append(key);
      return col;
    };

    Traverser::VertexId extractToId(TRI_doc_mptr_copy_t& ptr) {
      char const* key = TRI_EXTRACT_MARKER_TO_KEY(&ptr);
      TRI_voc_cid_t cid = TRI_EXTRACT_MARKER_TO_CID(&ptr);
      string col = resolver->getCollectionName(cid);
      col.append("/");
      col.append(key);
      return col;
    };

    Traverser::EdgeId extractEdgeId(TRI_doc_mptr_copy_t ptr) {
      char const* key = TRI_EXTRACT_MARKER_KEY(ptr);
      // AppendAndCopy
      return edgeIdPrefix.append(key);
    };

    void operator() (Traverser::VertexId source,
                     vector<Traverser::Step>& result) {
      std::vector<TRI_doc_mptr_copy_t> edges;
      TransactionBase fake(true); // Fake a transaction to please checks.
                                  // This is due to multi-threading

      // Process Vertex Id!
      size_t split;
      char const* str = source.c_str();
      if (!TRI_ValidateDocumentIdKeyGenerator(str, &split)) {
        // TODO Error Handling
        return;
      }
      string collectionName = source.substr(0, split);

      auto col = resolver->getCollectionStruct(collectionName);
      if (col == nullptr) {
        // collection not found
        throw TRI_ERROR_ARANGO_COLLECTION_NOT_FOUND;
      }
      auto collectionCId = col->_cid;
      edges = TRI_LookupEdgesDocumentCollection(edgeCollection, direction, collectionCId, const_cast<char*>(str + split + 1));

      unordered_map<Traverser::VertexId, size_t> candidates;
      Traverser::VertexId from;
      Traverser::VertexId to;
      if (usesDist) {
        for (size_t j = 0;  j < edges.size(); ++j) {
          from = extractFromId(edges[j]);
          to = extractToId(edges[j]);
          if (from != source) {
            auto cand = candidates.find(from);
            if (cand == candidates.end()) {
              // Add weight
              result.emplace_back(to, from, 1, extractEdgeId(edges[j]));
              candidates.emplace(from, result.size()-1);
            } else {
              // Compare weight
              // use result[cand->seconde].weight() and .setWeight()
            }
          }
          else if (to != source) {
            auto cand = candidates.find(to);
            if (cand == candidates.end()) {
              // Add weight
              result.emplace_back(to, from, 1, extractEdgeId(edges[j]));
              candidates.emplace(to, result.size()-1);
            } else {
              // Compare weight
              // use result[cand->seconde].weight() and .setWeight()
            }
          }
        }
      }
      else {
        for (size_t j = 0;  j < edges.size();  ++j) {
          from = extractFromId(edges[j]);
          to = extractFromId(edges[j]);
          if (from != source) {
            auto cand = candidates.find(from);
            if (cand == candidates.end()) {
              result.emplace_back(from, to, 1, extractEdgeId(edges[j]));
              candidates.emplace(from, result.size()-1);
            }
          }
          else if (to != source) {
            auto cand = candidates.find(to);
            if (cand == candidates.end()) {
              result.emplace_back(to, from, 1, extractEdgeId(edges[j]));
              candidates.emplace(to, result.size()-1);
            }
          }
        }
      }
    }
};

static v8::Handle<v8::Value> pathIdsToV8(v8::Isolate* isolate, Traverser::Path& p) {
  v8::EscapableHandleScope scope(isolate);
  TRI_GET_GLOBALS();
  v8::Handle<v8::Object> result = v8::Object::New(isolate);

  uint32_t const vn = static_cast<uint32_t>(p.vertices.size());
  v8::Handle<v8::Array> vertices = v8::Array::New(isolate, static_cast<int>(vn));

  for (size_t j = 0;  j < vn;  ++j) {
    vertices->Set(static_cast<uint32_t>(j), TRI_V8_ASCII_STRING(p.vertices[j]));
  }
  result->Set("vertices", vertices);

  uint32_t const en = static_cast<uint32_t>(p.edges.size());
  v8::Handle<v8::Array> edges = v8::Array::New(isolate, static_cast<int>(en));

  for (size_t j = 0;  j < en;  ++j) {
    edges->Set(static_cast<uint32_t>(j), TRI_V8_ASCII_STRING(p.edges[j]));
  }
  result->Set(TRI_V8_STRING("edges"), edges);
  result->Set(TRI_V8_STRING("distance"), v8::Number::New(isolate, p.weight));

  return result;
};

struct LocalCollectionGuard {
  LocalCollectionGuard (TRI_vocbase_col_t* collection)
    : _collection(collection) {
  }

  ~LocalCollectionGuard () {
    if (_collection != nullptr && ! _collection->_isLocal) {
      FreeCoordinatorCollection(_collection);
    }
  }

  TRI_vocbase_col_t* _collection;
};

void TRI_RunDijkstraSearch (const v8::FunctionCallbackInfo<v8::Value>& args) {
  v8::Isolate* isolate = args.GetIsolate();
  v8::HandleScope scope(isolate);

  if (args.Length() < 4 || args.Length() > 5) {
    TRI_V8_THROW_EXCEPTION_USAGE("AQL_SHORTEST_PATH(<vertexcollection>, <edgecollection>, <start>, <end>, <options>)");
  }

  std::unique_ptr<char[]> key;
  TRI_vocbase_t* vocbase;
  TRI_vocbase_col_t const* col = nullptr;

  vocbase = GetContextVocBase(isolate);

  vector<string> readCollections;
  vector<string> writeCollections;
  TRI_voc_cid_t vertexCollectionCId;
  TRI_voc_cid_t edgeCollectionCId;
  TRI_voc_rid_t rid;

  double lockTimeout = (double) (TRI_TRANSACTION_DEFAULT_LOCK_TIMEOUT / 1000000ULL);
  bool embed = false;
  bool waitForSync = false;

  // get the vertex collection
  if (! args[0]->IsString()) {
    TRI_V8_THROW_TYPE_ERROR("expecting string for <vertexcollection>");
  }
  string vertexCollectionName = TRI_ObjectToString(args[0]);

  // get the edge collection
  if (! args[1]->IsString()) {
    TRI_V8_THROW_TYPE_ERROR("expecting string for <edgecollection>");
  }
  string const edgeCollectionName = TRI_ObjectToString(args[1]);

  vocbase = GetContextVocBase(isolate);

  if (vocbase == nullptr) {
    TRI_V8_THROW_EXCEPTION(TRI_ERROR_ARANGO_DATABASE_NOT_FOUND);
  }
  V8ResolverGuard resolver(vocbase);

  readCollections.push_back(vertexCollectionName);
  readCollections.push_back(edgeCollectionName);

  if (! args[2]->IsString()) {
    TRI_V8_THROW_TYPE_ERROR("expecting string for <startVertex>");
  }

  std::string vertexColName;

  if (! ExtractDocumentHandle(isolate, args[2], vertexColName, key, rid)) {
    TRI_V8_THROW_EXCEPTION(TRI_ERROR_ARANGO_DOCUMENT_HANDLE_BAD);
  }

  if (key.get() == nullptr) {
    TRI_V8_THROW_EXCEPTION(TRI_ERROR_ARANGO_DOCUMENT_HANDLE_BAD);
  }

  TRI_ASSERT(key.get() != nullptr);

  // IHHF isCoordinator

  // Start Transaction to collect all parts of the path
  ExplicitTransaction trx(
    vocbase,
    readCollections,
    writeCollections,
    lockTimeout,
    waitForSync,
    embed
  );

  int res = trx.begin();

  if (res != TRI_ERROR_NO_ERROR) {
    TRI_V8_THROW_EXCEPTION(res);
  }

  col = resolver.getResolver()->getCollectionStruct(vertexCollectionName);
  if (col == nullptr) {
    // collection not found
    TRI_V8_THROW_EXCEPTION(TRI_ERROR_ARANGO_COLLECTION_NOT_FOUND);
  }
  vertexCollectionCId = col->_cid;
  if (trx.orderBarrier(trx.trxCollection(col->_cid)) == nullptr) {
    TRI_V8_THROW_EXCEPTION_MEMORY();
  }

  col = resolver.getResolver()->getCollectionStruct(edgeCollectionName);
  if (col == nullptr) {
    // collection not found
    TRI_V8_THROW_EXCEPTION(TRI_ERROR_ARANGO_COLLECTION_NOT_FOUND);
  }
  edgeCollectionCId = col->_cid;
  if (trx.orderBarrier(trx.trxCollection(col->_cid)) == nullptr) {
    TRI_V8_THROW_EXCEPTION_MEMORY();
  }

  TRI_document_collection_t* ecol = trx.trxCollection(col->_cid)->_collection->_collection;
  CollectionNameResolver resolver1(vocbase);
  CollectionNameResolver resolver2(vocbase);
  SimpleEdgeExpander forwardExpander(TRI_EDGE_OUT, ecol, edgeCollectionName, &resolver1, "A");
  SimpleEdgeExpander backwardExpander(TRI_EDGE_IN, ecol, edgeCollectionName, &resolver2, "B");

  Traverser traverser(forwardExpander, backwardExpander);
  unique_ptr<Traverser::Path> path(traverser.shortestPath(startVertex, targetVertex));
  if (path.get() == nullptr) {
    res = trx.finish(res);
    v8::EscapableHandleScope scope(isolate);
    TRI_V8_RETURN(scope.Escape<v8::Value>(v8::Object::New(isolate)));
  }
  auto result = pathIdsToV8(isolate, *path);
  res = trx.finish(res);

  // This is how to get the data out of the collections!
  // Vertices
  TRI_doc_mptr_copy_t document;
  res = trx.readSingle(trx.trxCollection(vertexCollectionCId), &document, key.get());

  // Edges TRI_EDGE_OUT is hardcoded
  TRI_document_collection_t* ecol = trx.trxCollection(edgeCollectionCId)->_collection->_collection;
  std::vector<TRI_doc_mptr_copy_t>&& edges = TRI_LookupEdgesDocumentCollection(ecol, TRI_EDGE_OUT, vertexCollectionCId, key.get());

  // Add Dijkstra here

  // Now build up the result use Subtransactions for each used collection
  if (res == TRI_ERROR_NO_ERROR) {
    {
      // Collect all vertices
      SingleCollectionReadOnlyTransaction subtrx(new V8TransactionContext(true), vocbase, vertexCollectionCId);

      res = subtrx.begin();

      if (res != TRI_ERROR_NO_ERROR) {
        TRI_V8_THROW_EXCEPTION(res);
      }

      result = TRI_WrapShapedJson(isolate, subtrx, vertexCollectionCId, document.getDataPtr());

      if (document.getDataPtr() == nullptr) {
        res = TRI_ERROR_ARANGO_DOCUMENT_NOT_FOUND;
        TRI_V8_THROW_EXCEPTION(res);
      }

      res = subtrx.finish(res);
    }

    {
      // Collect all edges
      SingleCollectionReadOnlyTransaction subtrx2(new V8TransactionContext(true), vocbase, edgeCollectionCId);

      res = subtrx2.begin();

      if (res != TRI_ERROR_NO_ERROR) {
        TRI_V8_THROW_EXCEPTION(res);
      }

      bool error = false;

      uint32_t const n = static_cast<uint32_t>(edges.size());
      documents = v8::Array::New(isolate, static_cast<int>(n));
      for (size_t j = 0;  j < n;  ++j) {
        v8::Handle<v8::Value> doc = TRI_WrapShapedJson(isolate, subtrx2, edgeCollectionCId, edges[j].getDataPtr());

        if (doc.IsEmpty()) {
          error = true;
          break;
        }
        else {
          documents->Set(static_cast<uint32_t>(j), doc);
        }
      }
      if (error) {
        TRI_V8_THROW_EXCEPTION_MEMORY();
      }

      res = subtrx2.finish(res);
    }
  }
  res = trx.finish(res);

  // Not yet correct. Needs to build an object first.
  // TRI_V8_RETURN(result);
  TRI_V8_RETURN(documents);
}
<commit_msg>Add some more couts.<commit_after>////////////////////////////////////////////////////////////////////////////////
/// @brief V8 Traverser
///
/// @file
///
/// DISCLAIMER
///
/// Copyright 2014-2015 ArangoDB GmbH, Cologne, Germany
/// Copyright 2004-2014 triAGENS GmbH, Cologne, Germany
///
/// Licensed under the Apache License, Version 2.0 (the "License");
/// you may not use this file except in compliance with the License.
/// You may obtain a copy of the License at
///
///     http://www.apache.org/licenses/LICENSE-2.0
///
/// Unless required by applicable law or agreed to in writing, software
/// distributed under the License is distributed on an "AS IS" BASIS,
/// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
/// See the License for the specific language governing permissions and
/// limitations under the License.
///
/// Copyright holder is ArangoDB GmbH, Cologne, Germany
///
/// @author Michael Hackstein
/// @author Copyright 2014-2015, ArangoDB GmbH, Cologne, Germany
/// @author Copyright 2012-2013, triAGENS GmbH, Cologne, Germany
////////////////////////////////////////////////////////////////////////////////

#include "v8.h"
#include "V8/v8-conv.h"
#include "V8/v8-utils.h"
#include "V8Server/v8-vocbaseprivate.h"
#include "V8Server/v8-wrapshapedjson.h"
#include "V8Server/v8-vocindex.h"
#include "V8Server/v8-collection.h"
#include "Utils/transactions.h"
#include "Utils/V8ResolverGuard.h"
#include "Utils/CollectionNameResolver.h"
#include "VocBase/document-collection.h"
#include "Traverser.h"
#include "VocBase/key-generator.h"

using namespace std;
using namespace triagens::basics;
using namespace triagens::arango;

class SimpleEdgeExpander {

  private:
////////////////////////////////////////////////////////////////////////////////
/// @brief direction of expansion
////////////////////////////////////////////////////////////////////////////////

    TRI_edge_direction_e direction;

////////////////////////////////////////////////////////////////////////////////
/// @brief edge collection
////////////////////////////////////////////////////////////////////////////////

    TRI_document_collection_t* edgeCollection;

////////////////////////////////////////////////////////////////////////////////
/// @brief collection name and /
////////////////////////////////////////////////////////////////////////////////

    string edgeIdPrefix;

////////////////////////////////////////////////////////////////////////////////
/// @brief the collection name resolver
////////////////////////////////////////////////////////////////////////////////

    CollectionNameResolver* resolver;

////////////////////////////////////////////////////////////////////////////////
/// @brief this indicates whether or not a distance attribute is used or
/// whether all edges are considered to have weight 1
////////////////////////////////////////////////////////////////////////////////

    bool usesDist;

////////////////////////////////////////////////////////////////////////////////
/// @brief an ID for the expander, just for debuggin
////////////////////////////////////////////////////////////////////////////////

    string id;

  public:

    SimpleEdgeExpander(TRI_edge_direction_e direction,
                       TRI_document_collection_t* edgeCollection,
                       string edgeCollectionName,
                       CollectionNameResolver* resolver,
                       string id)
      : direction(direction), edgeCollection(edgeCollection),
        resolver(resolver), usesDist(false), id(id)
    {
      edgeIdPrefix = edgeCollectionName + "/";
    };

    Traverser::VertexId extractFromId(TRI_doc_mptr_copy_t& ptr) {
      char const* key = TRI_EXTRACT_MARKER_FROM_KEY(&ptr);
      TRI_voc_cid_t cid = TRI_EXTRACT_MARKER_FROM_CID(&ptr);
      string col = resolver->getCollectionName(cid);
      col.append("/");
      col.append(key);
      return col;
    };

    Traverser::VertexId extractToId(TRI_doc_mptr_copy_t& ptr) {
      char const* key = TRI_EXTRACT_MARKER_TO_KEY(&ptr);
      TRI_voc_cid_t cid = TRI_EXTRACT_MARKER_TO_CID(&ptr);
      string col = resolver->getCollectionName(cid);
      col.append("/");
      col.append(key);
      return col;
    };

    Traverser::EdgeId extractEdgeId(TRI_doc_mptr_copy_t ptr) {
      char const* key = TRI_EXTRACT_MARKER_KEY(ptr);
      // AppendAndCopy
      return edgeIdPrefix.append(key);
    };

    void operator() (Traverser::VertexId source,
                     vector<Traverser::Step>& result) {
      std::cout << "Expander " << id << " called." << std::endl;
      std::vector<TRI_doc_mptr_copy_t> edges;
      TransactionBase fake(true); // Fake a transaction to please checks.
                                  // This is due to multi-threading

      // Process Vertex Id!
      size_t split;
      char const* str = source.c_str();
      if (!TRI_ValidateDocumentIdKeyGenerator(str, &split)) {
        // TODO Error Handling
        return;
      }
      string collectionName = source.substr(0, split);

      auto col = resolver->getCollectionStruct(collectionName);
      if (col == nullptr) {
        // collection not found
        throw TRI_ERROR_ARANGO_COLLECTION_NOT_FOUND;
      }
      auto collectionCId = col->_cid;
      edges = TRI_LookupEdgesDocumentCollection(edgeCollection, direction, collectionCId, const_cast<char*>(str + split + 1));
      std::cout << "Expander " << id << " got edges." << std::endl;

      unordered_map<Traverser::VertexId, size_t> candidates;
      Traverser::VertexId from;
      Traverser::VertexId to;
      if (usesDist) {
        for (size_t j = 0;  j < edges.size(); ++j) {
          from = extractFromId(edges[j]);
          to = extractToId(edges[j]);
          if (from != source) {
            auto cand = candidates.find(from);
            if (cand == candidates.end()) {
              // Add weight
              result.emplace_back(to, from, 1, extractEdgeId(edges[j]));
              candidates.emplace(from, result.size()-1);
            } else {
              // Compare weight
              // use result[cand->seconde].weight() and .setWeight()
            }
          }
          else if (to != source) {
            auto cand = candidates.find(to);
            if (cand == candidates.end()) {
              // Add weight
              result.emplace_back(to, from, 1, extractEdgeId(edges[j]));
              candidates.emplace(to, result.size()-1);
            } else {
              // Compare weight
              // use result[cand->seconde].weight() and .setWeight()
            }
          }
        }
      }
      else {
        for (size_t j = 0;  j < edges.size();  ++j) {
          from = extractFromId(edges[j]);
          to = extractFromId(edges[j]);
          if (from != source) {
            auto cand = candidates.find(from);
            if (cand == candidates.end()) {
              result.emplace_back(from, to, 1, extractEdgeId(edges[j]));
              candidates.emplace(from, result.size()-1);
            }
          }
          else if (to != source) {
            auto cand = candidates.find(to);
            if (cand == candidates.end()) {
              result.emplace_back(to, from, 1, extractEdgeId(edges[j]));
              candidates.emplace(to, result.size()-1);
            }
          }
        }
      }
      std::cout << "Expander " << id << " done." << std::endl;
    }
};

static v8::Handle<v8::Value> pathIdsToV8(v8::Isolate* isolate, Traverser::Path& p) {
  v8::EscapableHandleScope scope(isolate);
  TRI_GET_GLOBALS();
  v8::Handle<v8::Object> result = v8::Object::New(isolate);

  uint32_t const vn = static_cast<uint32_t>(p.vertices.size());
  v8::Handle<v8::Array> vertices = v8::Array::New(isolate, static_cast<int>(vn));

  for (size_t j = 0;  j < vn;  ++j) {
    vertices->Set(static_cast<uint32_t>(j), TRI_V8_ASCII_STRING(p.vertices[j]));
  }
  result->Set("vertices", vertices);

  uint32_t const en = static_cast<uint32_t>(p.edges.size());
  v8::Handle<v8::Array> edges = v8::Array::New(isolate, static_cast<int>(en));

  for (size_t j = 0;  j < en;  ++j) {
    edges->Set(static_cast<uint32_t>(j), TRI_V8_ASCII_STRING(p.edges[j]));
  }
  result->Set(TRI_V8_STRING("edges"), edges);
  result->Set(TRI_V8_STRING("distance"), v8::Number::New(isolate, p.weight));

  return result;
};

struct LocalCollectionGuard {
  LocalCollectionGuard (TRI_vocbase_col_t* collection)
    : _collection(collection) {
  }

  ~LocalCollectionGuard () {
    if (_collection != nullptr && ! _collection->_isLocal) {
      FreeCoordinatorCollection(_collection);
    }
  }

  TRI_vocbase_col_t* _collection;
};

void TRI_RunDijkstraSearch (const v8::FunctionCallbackInfo<v8::Value>& args) {
  v8::Isolate* isolate = args.GetIsolate();
  v8::HandleScope scope(isolate);

  if (args.Length() < 4 || args.Length() > 5) {
    TRI_V8_THROW_EXCEPTION_USAGE("AQL_SHORTEST_PATH(<vertexcollection>, <edgecollection>, <start>, <end>, <options>)");
  }

  std::unique_ptr<char[]> key;
  TRI_vocbase_t* vocbase;
  TRI_vocbase_col_t const* col = nullptr;

  vocbase = GetContextVocBase(isolate);

  vector<string> readCollections;
  vector<string> writeCollections;
  TRI_voc_cid_t vertexCollectionCId;
  TRI_voc_cid_t edgeCollectionCId;
  TRI_voc_rid_t rid;

  double lockTimeout = (double) (TRI_TRANSACTION_DEFAULT_LOCK_TIMEOUT / 1000000ULL);
  bool embed = false;
  bool waitForSync = false;

  // get the vertex collection
  if (! args[0]->IsString()) {
    TRI_V8_THROW_TYPE_ERROR("expecting string for <vertexcollection>");
  }
  string vertexCollectionName = TRI_ObjectToString(args[0]);

  // get the edge collection
  if (! args[1]->IsString()) {
    TRI_V8_THROW_TYPE_ERROR("expecting string for <edgecollection>");
  }
  string const edgeCollectionName = TRI_ObjectToString(args[1]);

  vocbase = GetContextVocBase(isolate);

  if (vocbase == nullptr) {
    TRI_V8_THROW_EXCEPTION(TRI_ERROR_ARANGO_DATABASE_NOT_FOUND);
  }
  V8ResolverGuard resolver(vocbase);

  readCollections.push_back(vertexCollectionName);
  readCollections.push_back(edgeCollectionName);

  if (! args[2]->IsString()) {
    TRI_V8_THROW_TYPE_ERROR("expecting string for <startVertex>");
  }

  std::string vertexColName;

  if (! ExtractDocumentHandle(isolate, args[2], vertexColName, key, rid)) {
    TRI_V8_THROW_EXCEPTION(TRI_ERROR_ARANGO_DOCUMENT_HANDLE_BAD);
  }

  if (key.get() == nullptr) {
    TRI_V8_THROW_EXCEPTION(TRI_ERROR_ARANGO_DOCUMENT_HANDLE_BAD);
  }

  TRI_ASSERT(key.get() != nullptr);

  // IHHF isCoordinator

  // Start Transaction to collect all parts of the path
  ExplicitTransaction trx(
    vocbase,
    readCollections,
    writeCollections,
    lockTimeout,
    waitForSync,
    embed
  );

  int res = trx.begin();

  if (res != TRI_ERROR_NO_ERROR) {
    TRI_V8_THROW_EXCEPTION(res);
  }

  col = resolver.getResolver()->getCollectionStruct(vertexCollectionName);
  if (col == nullptr) {
    // collection not found
    TRI_V8_THROW_EXCEPTION(TRI_ERROR_ARANGO_COLLECTION_NOT_FOUND);
  }
  vertexCollectionCId = col->_cid;
  if (trx.orderBarrier(trx.trxCollection(col->_cid)) == nullptr) {
    TRI_V8_THROW_EXCEPTION_MEMORY();
  }

  col = resolver.getResolver()->getCollectionStruct(edgeCollectionName);
  if (col == nullptr) {
    // collection not found
    TRI_V8_THROW_EXCEPTION(TRI_ERROR_ARANGO_COLLECTION_NOT_FOUND);
  }
  edgeCollectionCId = col->_cid;
  if (trx.orderBarrier(trx.trxCollection(col->_cid)) == nullptr) {
    TRI_V8_THROW_EXCEPTION_MEMORY();
  }

  TRI_document_collection_t* ecol = trx.trxCollection(col->_cid)->_collection->_collection;
  CollectionNameResolver resolver1(vocbase);
  CollectionNameResolver resolver2(vocbase);
  SimpleEdgeExpander forwardExpander(TRI_EDGE_OUT, ecol, edgeCollectionName, &resolver1, "A");
  SimpleEdgeExpander backwardExpander(TRI_EDGE_IN, ecol, edgeCollectionName, &resolver2, "B");

  Traverser traverser(forwardExpander, backwardExpander);
  unique_ptr<Traverser::Path> path(traverser.shortestPath(startVertex, targetVertex));
  if (path.get() == nullptr) {
    res = trx.finish(res);
    v8::EscapableHandleScope scope(isolate);
    TRI_V8_RETURN(scope.Escape<v8::Value>(v8::Object::New(isolate)));
  }
  auto result = pathIdsToV8(isolate, *path);
  res = trx.finish(res);

  // This is how to get the data out of the collections!
  // Vertices
  TRI_doc_mptr_copy_t document;
  res = trx.readSingle(trx.trxCollection(vertexCollectionCId), &document, key.get());

  // Edges TRI_EDGE_OUT is hardcoded
  TRI_document_collection_t* ecol = trx.trxCollection(edgeCollectionCId)->_collection->_collection;
  std::vector<TRI_doc_mptr_copy_t>&& edges = TRI_LookupEdgesDocumentCollection(ecol, TRI_EDGE_OUT, vertexCollectionCId, key.get());

  // Add Dijkstra here

  // Now build up the result use Subtransactions for each used collection
  if (res == TRI_ERROR_NO_ERROR) {
    {
      // Collect all vertices
      SingleCollectionReadOnlyTransaction subtrx(new V8TransactionContext(true), vocbase, vertexCollectionCId);

      res = subtrx.begin();

      if (res != TRI_ERROR_NO_ERROR) {
        TRI_V8_THROW_EXCEPTION(res);
      }

      result = TRI_WrapShapedJson(isolate, subtrx, vertexCollectionCId, document.getDataPtr());

      if (document.getDataPtr() == nullptr) {
        res = TRI_ERROR_ARANGO_DOCUMENT_NOT_FOUND;
        TRI_V8_THROW_EXCEPTION(res);
      }

      res = subtrx.finish(res);
    }

    {
      // Collect all edges
      SingleCollectionReadOnlyTransaction subtrx2(new V8TransactionContext(true), vocbase, edgeCollectionCId);

      res = subtrx2.begin();

      if (res != TRI_ERROR_NO_ERROR) {
        TRI_V8_THROW_EXCEPTION(res);
      }

      bool error = false;

      uint32_t const n = static_cast<uint32_t>(edges.size());
      documents = v8::Array::New(isolate, static_cast<int>(n));
      for (size_t j = 0;  j < n;  ++j) {
        v8::Handle<v8::Value> doc = TRI_WrapShapedJson(isolate, subtrx2, edgeCollectionCId, edges[j].getDataPtr());

        if (doc.IsEmpty()) {
          error = true;
          break;
        }
        else {
          documents->Set(static_cast<uint32_t>(j), doc);
        }
      }
      if (error) {
        TRI_V8_THROW_EXCEPTION_MEMORY();
      }

      res = subtrx2.finish(res);
    }
  }
  res = trx.finish(res);

  // Not yet correct. Needs to build an object first.
  // TRI_V8_RETURN(result);
  TRI_V8_RETURN(documents);
}
<|endoftext|>


<commit_before>// Copyright (c) 2006-2008 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 "base/shared_memory.h"

#include <fcntl.h>
#include <sys/mman.h>

#include "base/logging.h"
#include "base/string_util.h"

namespace {
// Paranoia. Semaphores and shared memory segments should live in different
// namespaces, but who knows what's out there.
const char kSemaphoreSuffix[] = "-sem";
}

SharedMemory::SharedMemory()
    : mapped_file_(-1),
      memory_(NULL),
      read_only_(false),
      max_size_(0),
      lock_(NULL) {
}

SharedMemory::SharedMemory(SharedMemoryHandle handle, bool read_only)
    : mapped_file_(handle),
      memory_(NULL),
      read_only_(read_only),
      max_size_(0),
      lock_(NULL) {
}

SharedMemory::SharedMemory(SharedMemoryHandle handle, bool read_only,
                           ProcessHandle process)
    : mapped_file_(handle),
      memory_(NULL),
      read_only_(read_only),
      max_size_(0),
      lock_(NULL) {
  // We don't handle this case yet (note the ignored parameter); let's die if
  // someone comes calling.
  NOTREACHED();
}

SharedMemory::~SharedMemory() {
  Close();
  if (lock_ != NULL)
    sem_close(lock_);
}

bool SharedMemory::Create(const std::wstring &name, bool read_only,
                          bool open_existing, size_t size) {
  read_only_ = read_only;

  int posix_flags = 0;
  posix_flags |= read_only ? O_RDONLY : O_RDWR;
  if (!open_existing)
    posix_flags |= O_CREAT;

  if (CreateOrOpen(name, posix_flags)) {
    ftruncate(mapped_file_, size);
    max_size_ = size;
    return true;
  }

  return false;
}

bool SharedMemory::Open(const std::wstring &name, bool read_only) {
  read_only_ = read_only;

  int posix_flags = 0;
  posix_flags |= read_only ? O_RDONLY : O_RDWR;

  return CreateOrOpen(name, posix_flags);
}

bool SharedMemory::CreateOrOpen(const std::wstring &name, int posix_flags) {
  DCHECK(mapped_file_ == -1);

  name_ = L"/" + name;

  int posix_mode = 0600;  // owner read/write
  std::string posix_name(WideToUTF8(name_));
  mapped_file_ = shm_open(posix_name.c_str(), posix_flags, posix_mode);
  if (mapped_file_ < 0)
    return false;

  posix_name += kSemaphoreSuffix;
  lock_ = sem_open(posix_name.c_str(), O_CREAT, posix_mode, 1);
  if (lock_ == SEM_FAILED) {
    close(mapped_file_);
    mapped_file_ = -1;
    shm_unlink(posix_name.c_str());
    lock_ = NULL;
    return false;
  }

  return true;
}

bool SharedMemory::Map(size_t bytes) {
  if (mapped_file_ == -1)
    return false;

  memory_ = mmap(NULL, bytes, PROT_READ | (read_only_ ? 0 : PROT_WRITE),
                 MAP_SHARED, mapped_file_, 0);

  if (memory_)
    max_size_ = bytes;

  return (memory_ != NULL);
}

bool SharedMemory::Unmap() {
  if (memory_ == NULL)
    return false;

  munmap(memory_, max_size_);
  memory_ = NULL;
  max_size_ = 0;
  return true;
}

bool SharedMemory::ShareToProcessCommon(ProcessHandle process,
                                        SharedMemoryHandle *new_handle,
                                        bool close_self) {
  *new_handle = 0;
  // TODO(awalker): figure out if we need this, and do the appropriate
  // VM magic if so.
  return false;
}

void SharedMemory::Close() {
  if (memory_ != NULL) {
    munmap(memory_, max_size_);

    memory_ = NULL;
    max_size_ = 0;
  }

  std::string posix_name(WideToUTF8(name_));
  if (mapped_file_) {
    close(mapped_file_);
    shm_unlink(posix_name.c_str());
    mapped_file_ = -1;
  }

  if (lock_) {
    posix_name += kSemaphoreSuffix;
    sem_unlink(posix_name.c_str());
    lock_ = NULL;
  }
}

void SharedMemory::Lock() {
  DCHECK(lock_ != NULL);
  sem_wait(lock_);
}

void SharedMemory::Unlock() {
  DCHECK(lock_ != NULL);
  sem_post(lock_);
}

<commit_msg>ensure that the shared memory has actually been created before trying to re-use it when the |open_existing| flag is passed to Create(). Review URL: http://codereview.chromium.org/4039<commit_after>// Copyright (c) 2006-2008 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 "base/shared_memory.h"

#include <fcntl.h>
#include <sys/mman.h>

#include "base/logging.h"
#include "base/string_util.h"

namespace {
// Paranoia. Semaphores and shared memory segments should live in different
// namespaces, but who knows what's out there.
const char kSemaphoreSuffix[] = "-sem";
}

SharedMemory::SharedMemory()
    : mapped_file_(-1),
      memory_(NULL),
      read_only_(false),
      max_size_(0),
      lock_(NULL) {
}

SharedMemory::SharedMemory(SharedMemoryHandle handle, bool read_only)
    : mapped_file_(handle),
      memory_(NULL),
      read_only_(read_only),
      max_size_(0),
      lock_(NULL) {
}

SharedMemory::SharedMemory(SharedMemoryHandle handle, bool read_only,
                           ProcessHandle process)
    : mapped_file_(handle),
      memory_(NULL),
      read_only_(read_only),
      max_size_(0),
      lock_(NULL) {
  // We don't handle this case yet (note the ignored parameter); let's die if
  // someone comes calling.
  NOTREACHED();
}

SharedMemory::~SharedMemory() {
  Close();
  if (lock_ != NULL)
    sem_close(lock_);
}

bool SharedMemory::Create(const std::wstring &name, bool read_only,
                          bool open_existing, size_t size) {
  read_only_ = read_only;

  int posix_flags = 0;
  posix_flags |= read_only ? O_RDONLY : O_RDWR;
  if (!open_existing || mapped_file_ <= 0)
    posix_flags |= O_CREAT;

  if (CreateOrOpen(name, posix_flags)) {
    ftruncate(mapped_file_, size);
    max_size_ = size;
    return true;
  }

  return false;
}

bool SharedMemory::Open(const std::wstring &name, bool read_only) {
  read_only_ = read_only;

  int posix_flags = 0;
  posix_flags |= read_only ? O_RDONLY : O_RDWR;

  return CreateOrOpen(name, posix_flags);
}

bool SharedMemory::CreateOrOpen(const std::wstring &name, int posix_flags) {
  DCHECK(mapped_file_ == -1);

  name_ = L"/" + name;

  int posix_mode = 0600;  // owner read/write
  std::string posix_name(WideToUTF8(name_));
  mapped_file_ = shm_open(posix_name.c_str(), posix_flags, posix_mode);
  if (mapped_file_ < 0)
    return false;

  posix_name += kSemaphoreSuffix;
  lock_ = sem_open(posix_name.c_str(), O_CREAT, posix_mode, 1);
  if (lock_ == SEM_FAILED) {
    close(mapped_file_);
    mapped_file_ = -1;
    shm_unlink(posix_name.c_str());
    lock_ = NULL;
    return false;
  }

  return true;
}

bool SharedMemory::Map(size_t bytes) {
  if (mapped_file_ == -1)
    return false;

  memory_ = mmap(NULL, bytes, PROT_READ | (read_only_ ? 0 : PROT_WRITE),
                 MAP_SHARED, mapped_file_, 0);

  if (memory_)
    max_size_ = bytes;

  return (memory_ != NULL);
}

bool SharedMemory::Unmap() {
  if (memory_ == NULL)
    return false;

  munmap(memory_, max_size_);
  memory_ = NULL;
  max_size_ = 0;
  return true;
}

bool SharedMemory::ShareToProcessCommon(ProcessHandle process,
                                        SharedMemoryHandle *new_handle,
                                        bool close_self) {
  *new_handle = 0;
  // TODO(awalker): figure out if we need this, and do the appropriate
  // VM magic if so.
  return false;
}

void SharedMemory::Close() {
  if (memory_ != NULL) {
    munmap(memory_, max_size_);

    memory_ = NULL;
    max_size_ = 0;
  }

  std::string posix_name(WideToUTF8(name_));
  if (mapped_file_) {
    close(mapped_file_);
    shm_unlink(posix_name.c_str());
    mapped_file_ = -1;
  }

  if (lock_) {
    posix_name += kSemaphoreSuffix;
    sem_unlink(posix_name.c_str());
    lock_ = NULL;
  }
}

void SharedMemory::Lock() {
  DCHECK(lock_ != NULL);
  sem_wait(lock_);
}

void SharedMemory::Unlock() {
  DCHECK(lock_ != NULL);
  sem_post(lock_);
}

<|endoftext|>


<commit_before>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: desktopcontext.cxx,v $
 *
 *  $Revision: 1.4 $
 *
 *  last change: $Author: rt $ $Date: 2005-09-08 17:07:10 $
 *
 *  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 _DESKTOP_DESKTOPCONTEXT_HXX_
#include "desktopcontext.hxx"
#endif

#include <vcl/svapp.hxx>
#include <svtools/javainteractionhandler.hxx>

using namespace rtl;
using namespace com::sun::star::uno;
using namespace com::sun::star::task;

namespace desktop
{

DesktopContext::DesktopContext( const Reference< XCurrentContext > & ctx )
    : m_xNextContext( ctx )
{
}

Any SAL_CALL DesktopContext::getValueByName( const OUString& Name) throw (RuntimeException)
{
    Any retVal;

    if ( 0 == Name.compareToAscii( DESKTOP_ENVIRONMENT_NAME ) )
    {
        retVal = makeAny( Application::GetDesktopEnvironment() );
    }
    else if ( 0 == Name.compareToAscii( JAVA_INTERACTION_HANDLER_NAME ))
    {
        retVal = makeAny( Reference< XInteractionHandler >( new svt::JavaInteractionHandler()) );
    }
    else if( m_xNextContext.is() )
    {
        // Call next context in chain if found
        retVal = m_xNextContext->getValueByName( Name );
    }
    return retVal;
}

}
<commit_msg>INTEGRATION: CWS kdesettings3 (1.4.206); FILE MERGED 2006/07/21 12:53:52 kendy 1.4.206.1: #i66204# Don't link with KDE libraries in Gnome (and v.v.)<commit_after>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: desktopcontext.cxx,v $
 *
 *  $Revision: 1.5 $
 *
 *  last change: $Author: ihi $ $Date: 2006-08-04 12:32:13 $
 *
 *  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 _DESKTOP_DESKTOPCONTEXT_HXX_
#include "desktopcontext.hxx"
#endif

#include <vcl/svapp.hxx>
#include <svtools/javainteractionhandler.hxx>

using namespace rtl;
using namespace com::sun::star::uno;
using namespace com::sun::star::task;

namespace desktop
{

DesktopContext::DesktopContext( const Reference< XCurrentContext > & ctx )
    : m_xNextContext( ctx )
{
}

Any SAL_CALL DesktopContext::getValueByName( const OUString& Name) throw (RuntimeException)
{
    Any retVal;

    if ( 0 == Name.compareToAscii( JAVA_INTERACTION_HANDLER_NAME ))
    {
        retVal = makeAny( Reference< XInteractionHandler >( new svt::JavaInteractionHandler()) );
    }
    else if( m_xNextContext.is() )
    {
        // Call next context in chain if found
        retVal = m_xNextContext->getValueByName( Name );
    }
    return retVal;
}

}
<|endoftext|>


<commit_before>/* Copyright © 2001-2014, Canal TP and/or its affiliates. All rights reserved.

This file is part of Navitia,
    the software to build cool stuff with public transport.

Hope you'll enjoy and contribute to this project,
    powered by Canal TP (www.canaltp.fr).
Help us simplify mobility and open public transport:
    a non ending quest to the responsive locomotion way of traveling!

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

This program 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 Affero General Public License for more details.

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

Stay tuned using
twitter @navitia
IRC #navitia on freenode
https://groups.google.com/d/forum/navitia
www.navitia.io
*/

#include "osm_tags_reader.h"
#include "utils/functions.h"
#include <iostream>
#include <algorithm>

namespace ed { namespace connectors{

static void update_if_unknown(int& target, const int& source) {
    if (target == -1) {
        target = source;
    }
}

std::bitset<8> parse_way_tags(const std::map<std::string, std::string> & tags){
    constexpr int unknown = -1;
    constexpr int foot_forbiden = 0;
    constexpr int foot_allowed = 1;

    constexpr int car_forbiden = 0;
    constexpr int car_residential = 1;
    constexpr int car_tertiary = 2;
    constexpr int car_secondary = 3;
    constexpr int car_primary = 4;
    constexpr int car_trunk = 5;
    constexpr int car_motorway = 6;

    constexpr int bike_forbiden = 0;
    constexpr int bike_allowed = 2;
    constexpr int bike_lane = 3;
    constexpr int bike_busway = 4;
    constexpr int bike_track = 5;

    int car_direct = unknown;
    int car_reverse = unknown;
    int bike_direct = unknown;
    int bike_reverse = unknown;
    int foot = unknown;

    for(std::pair<std::string, std::string> pair : tags){
        std::string key = pair.first, val = pair.second;
        std::transform(key.begin(), key.end(), key.begin(), ::tolower);
        std::transform(val.begin(), val.end(), val.begin(), ::tolower);

        if (key == "highway") {
            if (in(val, {"footway", "pedestrian"})) {
                update_if_unknown(foot, foot_allowed);
            } else if (val == "cycleway") {
                update_if_unknown(bike_direct, bike_track);
                update_if_unknown(foot, foot_allowed);
            } else if (val == "path") {
                //http://www.cyclestreets.net/journey/help/osmconversion/#toc6
                //highway = path => might mean lots of different things, so we allow bike and foot
                update_if_unknown(bike_direct, bike_track);
                update_if_unknown(foot, foot_allowed);
            } else if (val == "steps") {
                update_if_unknown(foot, foot_allowed);
            } else if (in(val, {"primary", "primary_link"})) {
                update_if_unknown(car_direct, car_primary);
                update_if_unknown(foot, foot_allowed);
                update_if_unknown(bike_direct, bike_allowed);
            } else if (in(val, {"secondary", "secondary_link"})) {
                update_if_unknown(car_direct, car_secondary);
                update_if_unknown(foot, foot_allowed);
                update_if_unknown(bike_direct, bike_allowed);
            } else if (in(val, {"tertiary", "tertiary_link"})) {
                update_if_unknown(car_direct, car_tertiary);
                update_if_unknown(foot, foot_allowed);
                update_if_unknown(bike_direct, bike_allowed);
            } else if (in(val, {"unclassified", "residential", "living_street",
                            "road", "service", "track"})) {
                update_if_unknown(car_direct, car_residential);
                update_if_unknown(foot, foot_allowed);
                update_if_unknown(bike_direct, bike_allowed);
            } else if (in(val, {"motorway", "motorway_link"})) {
                update_if_unknown(car_direct, car_motorway);
                update_if_unknown(foot, foot_forbiden);
                update_if_unknown(bike_direct, bike_forbiden);
            } else if (in(val, {"trunk", "trunk_link"})) {
                update_if_unknown(car_direct, car_trunk);
                update_if_unknown(foot, foot_forbiden);
                update_if_unknown(bike_direct, bike_forbiden);
            }
        }

        else if (in(key, {"pedestrian", "foot"})) {
            if (in(val, {"yes", "designated", "permissive", "lane", "official",
                            "allowed", "destination"})) {
                foot = foot_allowed;
            } else if (in(val, {"no", "private"})) {
                foot = foot_forbiden;
            } else {
                std::cerr << "I don't know what to do with: " << key << "=" << val << std::endl;
            }
        }

        // http://wiki.openstreetmap.org/wiki/Cycleway
        // http://wiki.openstreetmap.org/wiki/Map_Features#Cycleway
        else if(key == "cycleway") {
            if(val == "lane" || val == "yes" || val == "true" || val == "lane_in_the_middle")
                bike_direct = bike_lane;
            else if(val == "track")
                bike_direct = bike_track;
            else if(val == "opposite_lane")
                bike_reverse = bike_lane;
            else if(val == "opposite_track")
                bike_reverse = bike_track;
            else if(val == "opposite")
                bike_reverse = bike_allowed;
            else if(val == "share_busway")
                bike_direct = bike_busway;
            else if(val == "lane_left")
                bike_reverse = bike_lane;
            else
                bike_direct = bike_lane;
        }
        else if(key == "bicycle") {
            if(val == "yes" || val == "permissive" || val == "destination" || val == "designated"
                    || val == "private" || val == "true" || val == "allowed"
                    || val == "official" || val == "destination")
                bike_direct = bike_allowed;
            else if(val == "no" || val == "dismount" || val == "VTT")
                bike_direct = bike_forbiden;
            else if(val == "share_busway")
                bike_direct = bike_busway;
            else if(val == "opposite_lane" || val == "opposite")
                bike_reverse = bike_allowed;
            else
                std::cerr << "I don't know what to do with: " << key << "=" << val << std::endl;
        }

        else if (key == "busway") {
            if (in(val, {"yes", "track", "lane"})) {
                update_if_unknown(bike_direct, bike_busway);
            } else if (in(val, {"opposite_lane", "opposite_track"})) {
                update_if_unknown(bike_reverse, bike_busway);
            } else {
                update_if_unknown(bike_direct, bike_busway);
            }
        }

        else if(key == "oneway") {
            if(val == "yes" || val == "true" || val == "1") {
                car_reverse = car_forbiden;
                update_if_unknown(bike_reverse, bike_forbiden);
            }
        }

        else if(key == "junction") {
            if(val == "roundabout") {
                car_reverse = car_forbiden;
                update_if_unknown(bike_reverse, bike_forbiden);
            }
        }

        else if(key == "access"){
            if(val == "yes"){
                foot = foot_allowed;
            } else if(val == "no"){
                foot = foot_forbiden;
            }
        }

        else if(key == "public_transport"){
            if(val == "platform"){
                foot = foot_allowed;
            }
        }

        else if(key == "railway"){
            if(val == "platform"){
                foot = foot_allowed;
            }
        }
    }

    update_if_unknown(car_reverse, car_direct);
    update_if_unknown(bike_reverse, bike_direct);
    update_if_unknown(car_direct, car_forbiden);
    update_if_unknown(bike_direct, bike_forbiden);
    update_if_unknown(car_reverse, car_forbiden);
    update_if_unknown(bike_reverse, bike_forbiden);
    update_if_unknown(foot, foot_forbiden);

    std::bitset<8> result;
    result[CYCLE_FWD] = (bike_direct != bike_forbiden);
    result[CYCLE_BWD] = (bike_reverse != bike_forbiden);
    result[CAR_FWD] = (car_direct != car_forbiden);
    result[CAR_BWD] = (car_reverse != car_forbiden);
    result[FOOT_FWD] = (foot != foot_forbiden);
    result[FOOT_BWD] = (foot != foot_forbiden);
    return result;
}

}} //namespace navitia::OSM
<commit_msg>osm2ed: use only highway for routing<commit_after>/* Copyright © 2001-2014, Canal TP and/or its affiliates. All rights reserved.

This file is part of Navitia,
    the software to build cool stuff with public transport.

Hope you'll enjoy and contribute to this project,
    powered by Canal TP (www.canaltp.fr).
Help us simplify mobility and open public transport:
    a non ending quest to the responsive locomotion way of traveling!

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

This program 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 Affero General Public License for more details.

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

Stay tuned using
twitter @navitia
IRC #navitia on freenode
https://groups.google.com/d/forum/navitia
www.navitia.io
*/

#include "osm_tags_reader.h"
#include "utils/functions.h"
#include <iostream>
#include <algorithm>

namespace ed { namespace connectors{

static void update_if_unknown(int& target, const int& source) {
    if (target == -1) {
        target = source;
    }
}

std::bitset<8> parse_way_tags(const std::map<std::string, std::string> & tags){
    // if no highway tag, we can do nothing on it
    if (! tags.count("highway")) { return {}; }

    constexpr int unknown = -1;
    constexpr int foot_forbiden = 0;
    constexpr int foot_allowed = 1;

    constexpr int car_forbiden = 0;
    constexpr int car_residential = 1;
    constexpr int car_tertiary = 2;
    constexpr int car_secondary = 3;
    constexpr int car_primary = 4;
    constexpr int car_trunk = 5;
    constexpr int car_motorway = 6;

    constexpr int bike_forbiden = 0;
    constexpr int bike_allowed = 2;
    constexpr int bike_lane = 3;
    constexpr int bike_busway = 4;
    constexpr int bike_track = 5;

    int car_direct = unknown;
    int car_reverse = unknown;
    int bike_direct = unknown;
    int bike_reverse = unknown;
    int foot = unknown;

    for(std::pair<std::string, std::string> pair : tags){
        std::string key = pair.first, val = pair.second;
        std::transform(key.begin(), key.end(), key.begin(), ::tolower);
        std::transform(val.begin(), val.end(), val.begin(), ::tolower);

        if (key == "highway") {
            if (in(val, {"footway", "pedestrian"})) {
                update_if_unknown(foot, foot_allowed);
            } else if (val == "cycleway") {
                update_if_unknown(bike_direct, bike_track);
                update_if_unknown(foot, foot_allowed);
            } else if (val == "path") {
                //http://www.cyclestreets.net/journey/help/osmconversion/#toc6
                //highway = path => might mean lots of different things, so we allow bike and foot
                update_if_unknown(bike_direct, bike_track);
                update_if_unknown(foot, foot_allowed);
            } else if (val == "steps") {
                update_if_unknown(foot, foot_allowed);
            } else if (in(val, {"primary", "primary_link"})) {
                update_if_unknown(car_direct, car_primary);
                update_if_unknown(foot, foot_allowed);
                update_if_unknown(bike_direct, bike_allowed);
            } else if (in(val, {"secondary", "secondary_link"})) {
                update_if_unknown(car_direct, car_secondary);
                update_if_unknown(foot, foot_allowed);
                update_if_unknown(bike_direct, bike_allowed);
            } else if (in(val, {"tertiary", "tertiary_link"})) {
                update_if_unknown(car_direct, car_tertiary);
                update_if_unknown(foot, foot_allowed);
                update_if_unknown(bike_direct, bike_allowed);
            } else if (in(val, {"unclassified", "residential", "living_street",
                            "road", "service", "track"})) {
                update_if_unknown(car_direct, car_residential);
                update_if_unknown(foot, foot_allowed);
                update_if_unknown(bike_direct, bike_allowed);
            } else if (in(val, {"motorway", "motorway_link"})) {
                update_if_unknown(car_direct, car_motorway);
                update_if_unknown(foot, foot_forbiden);
                update_if_unknown(bike_direct, bike_forbiden);
            } else if (in(val, {"trunk", "trunk_link"})) {
                update_if_unknown(car_direct, car_trunk);
                update_if_unknown(foot, foot_forbiden);
                update_if_unknown(bike_direct, bike_forbiden);
            }
        }

        else if (in(key, {"pedestrian", "foot"})) {
            if (in(val, {"yes", "designated", "permissive", "lane", "official",
                            "allowed", "destination"})) {
                foot = foot_allowed;
            } else if (in(val, {"no", "private"})) {
                foot = foot_forbiden;
            } else {
                std::cerr << "I don't know what to do with: " << key << "=" << val << std::endl;
            }
        }

        // http://wiki.openstreetmap.org/wiki/Cycleway
        // http://wiki.openstreetmap.org/wiki/Map_Features#Cycleway
        else if(key == "cycleway") {
            if(val == "lane" || val == "yes" || val == "true" || val == "lane_in_the_middle")
                bike_direct = bike_lane;
            else if(val == "track")
                bike_direct = bike_track;
            else if(val == "opposite_lane")
                bike_reverse = bike_lane;
            else if(val == "opposite_track")
                bike_reverse = bike_track;
            else if(val == "opposite")
                bike_reverse = bike_allowed;
            else if(val == "share_busway")
                bike_direct = bike_busway;
            else if(val == "lane_left")
                bike_reverse = bike_lane;
            else
                bike_direct = bike_lane;
        }
        else if(key == "bicycle") {
            if(val == "yes" || val == "permissive" || val == "destination" || val == "designated"
                    || val == "private" || val == "true" || val == "allowed"
                    || val == "official" || val == "destination")
                bike_direct = bike_allowed;
            else if(val == "no" || val == "dismount" || val == "VTT")
                bike_direct = bike_forbiden;
            else if(val == "share_busway")
                bike_direct = bike_busway;
            else if(val == "opposite_lane" || val == "opposite")
                bike_reverse = bike_allowed;
            else
                std::cerr << "I don't know what to do with: " << key << "=" << val << std::endl;
        }

        else if (key == "busway") {
            if (in(val, {"yes", "track", "lane"})) {
                update_if_unknown(bike_direct, bike_busway);
            } else if (in(val, {"opposite_lane", "opposite_track"})) {
                update_if_unknown(bike_reverse, bike_busway);
            } else {
                update_if_unknown(bike_direct, bike_busway);
            }
        }

        else if(key == "oneway") {
            if(val == "yes" || val == "true" || val == "1") {
                car_reverse = car_forbiden;
                update_if_unknown(bike_reverse, bike_forbiden);
            }
        }

        else if(key == "junction") {
            if(val == "roundabout") {
                car_reverse = car_forbiden;
                update_if_unknown(bike_reverse, bike_forbiden);
            }
        }

        else if(key == "access"){
            if(val == "yes"){
                foot = foot_allowed;
            } else if(val == "no"){
                foot = foot_forbiden;
            }
        }

        else if(key == "public_transport"){
            if(val == "platform"){
                foot = foot_allowed;
            }
        }

        else if(key == "railway"){
            if(val == "platform"){
                foot = foot_allowed;
            }
        }
    }

    update_if_unknown(car_reverse, car_direct);
    update_if_unknown(bike_reverse, bike_direct);
    update_if_unknown(car_direct, car_forbiden);
    update_if_unknown(bike_direct, bike_forbiden);
    update_if_unknown(car_reverse, car_forbiden);
    update_if_unknown(bike_reverse, bike_forbiden);
    update_if_unknown(foot, foot_forbiden);

    std::bitset<8> result;
    result[CYCLE_FWD] = (bike_direct != bike_forbiden);
    result[CYCLE_BWD] = (bike_reverse != bike_forbiden);
    result[CAR_FWD] = (car_direct != car_forbiden);
    result[CAR_BWD] = (car_reverse != car_forbiden);
    result[FOOT_FWD] = (foot != foot_forbiden);
    result[FOOT_BWD] = (foot != foot_forbiden);
    return result;
}

}} //namespace navitia::OSM
<|endoftext|>


<commit_before>#include <string.h>
#include <math.h>
#include "ev3api.h"
#include "SerialData.h"
#include "SerialSendTask.h"
#include "SelfPositionManager.h"

SelfPositionManager* SelfPositionManager::GetInstance(){
	static SelfPositionManager manager;
	return &manager;
}

void SelfPositionManager::UpdatePosition(int8_t leftMotorCount, int8_t rightMotorCount)
{
	// 車輪直径(mm)
	double TireDiameter = 81.6;

	// 左右車輪間の距離(mm)
	double d = 128;

	// 左車輪の移動距離
	double Tl = TireDiameter * M_PI * leftMotorCount / 360.0;

	// 右車輪の移動距離
	double Tr = TireDiameter * M_PI * rightMotorCount / 360.0;

	// モータエンコーダ値の変化量
	double D = (Tl + Tr) / 2.0;

	// 角度の変化量
	double theta = (Tr - Tl) / d;
	//
	// 計算用にラジアンに変換した前回までの角度
	double theta0 = Angle * M_PI / 180.0;

	double X = (D * cos(theta0 + (theta / 2.0)));
	double Y = (D * sin(theta0 + (theta / 2.0)));

	PositionX += X;
	PositionY -= Y;

	// 0 - 360度の範囲に変更
	if(Angle + (theta / M_PI * 180.0) > 360) {
		Angle = Angle + (theta / M_PI * 180.0) - 360;
	}else if(Angle + (theta / M_PI * 180.0) < 0) {
		Angle = 360 - Angle +(theta / M_PI * 180.0);
	}else {
		Angle += (theta / M_PI * 180.0);
	}

	SelfPositionData p;
	p.PositionX = (uint)PositionX;
	p.PositionY = (uint)PositionY;
	p.Angle = (ushort)Angle;

	// 自己位置情報と同様のサイズを持つ配列にコピー
	memcpy(buff_self_position, &p, sizeof(SelfPositionData));
}

void SelfPositionManager::ResetPosition(SelfPositionData p)
{
	PositionX = p.PositionX;
	PositionY = p.PositionY;
	Angle = p.Angle;
	Distance = p.Distance;
}

// ある座標との距離を求める
double SelfPositionManager::GetDistance(Point* p)
{
	return hypot(p->X - PositionX, p->Y - PositionY);
}<commit_msg>総走行距離の算出機能を追加<commit_after>#include <string.h>
#include <math.h>
#include "ev3api.h"
#include "SerialData.h"
#include "SerialSendTask.h"
#include "SelfPositionManager.h"

SelfPositionManager* SelfPositionManager::GetInstance(){
	static SelfPositionManager manager;
	return &manager;
}

void SelfPositionManager::UpdatePosition(int8_t leftMotorCount, int8_t rightMotorCount)
{
	// 車輪直径(mm)
	double TireDiameter = 81.6;

	// 左右車輪間の距離(mm)
	double d = 128;

	// 左車輪の移動距離
	double Tl = TireDiameter * M_PI * leftMotorCount / 360.0;

	// 右車輪の移動距離
	double Tr = TireDiameter * M_PI * rightMotorCount / 360.0;

	// モータエンコーダ値の変化量
	double D = (Tl + Tr) / 2.0;

	// 角度の変化量
	double theta = (Tr - Tl) / d;
	//
	// 計算用にラジアンに変換した前回までの角度
	double theta0 = Angle * M_PI / 180.0;

	double X = (D * cos(theta0 + (theta / 2.0)));
	double Y = (D * sin(theta0 + (theta / 2.0)));

	PositionX += X;
	PositionY -= Y;
	Distance += D;

	// 0 - 360度の範囲に変更
	if(Angle + (theta / M_PI * 180.0) > 360) {
		Angle = Angle + (theta / M_PI * 180.0) - 360;
	}else if(Angle + (theta / M_PI * 180.0) < 0) {
		Angle = 360 - Angle +(theta / M_PI * 180.0);
	}else {
		Angle += (theta / M_PI * 180.0);
	}

	SelfPositionData p;
	p.PositionX = (uint)PositionX;
	p.PositionY = (uint)PositionY;
	p.Angle = (ushort)Angle;
	p.Distance = (uint)Distance;

	// 自己位置情報と同様のサイズを持つ配列にコピー
	memcpy(buff_self_position, &p, sizeof(SelfPositionData));
}

void SelfPositionManager::ResetPosition(SelfPositionData p)
{
	PositionX = p.PositionX;
	PositionY = p.PositionY;
	Angle = p.Angle;
	Distance = p.Distance;
}

// ある座標との距離を求める
double SelfPositionManager::GetDistance(Point* p)
{
	return hypot(p->X - PositionX, p->Y - PositionY);
}<|endoftext|>