<commit_before>#include "common.h"
#include "x86_helpers.h"

xed_reg_enum_t GetUnusedRegister(xed_reg_enum_t used_register, int operand_width) {
  switch (operand_width) {
  case 16:
    if (used_register == XED_REG_AX) return XED_REG_CX;
    return XED_REG_AX;
  case 32:
    if (used_register == XED_REG_EAX) return XED_REG_ECX;
    return XED_REG_EAX;
  case 64:
    if (used_register == XED_REG_RAX) return XED_REG_RCX;
    return XED_REG_RAX;
  default:
    FATAL("Unexpected operand width");
  }
}

xed_reg_enum_t GetFullSizeRegister(xed_reg_enum_t r, int child_ptr_size) {
  if (child_ptr_size == 8) {
    return xed_get_largest_enclosing_register(r);
  } else {
    return xed_get_largest_enclosing_register32(r);
  }
}

xed_reg_enum_t Get8BitRegister(xed_reg_enum_t r) {
  switch (r) {
  case XED_REG_AX:
  case XED_REG_EAX:
  case XED_REG_RAX:
    return XED_REG_AL;

  case XED_REG_CX:
  case XED_REG_ECX:
  case XED_REG_RCX:
    return XED_REG_CL;

  case XED_REG_DX:
  case XED_REG_EDX:
  case XED_REG_RDX:
    return XED_REG_DL;

  case XED_REG_BX:
  case XED_REG_EBX:
  case XED_REG_RBX:
    return XED_REG_BL;

  case XED_REG_SP:
  case XED_REG_ESP:
  case XED_REG_RSP:
    return XED_REG_SPL;

  case XED_REG_BP:
  case XED_REG_EBP:
  case XED_REG_RBP:
    return XED_REG_BPL;

  case XED_REG_SI:
  case XED_REG_ESI:
  case XED_REG_RSI:
    return XED_REG_SIL;

  case XED_REG_DI:
  case XED_REG_EDI:
  case XED_REG_RDI:
    return XED_REG_DIL;

  case XED_REG_R8W:
  case XED_REG_R8D:
  case XED_REG_R8:
    return XED_REG_R8B;

  case XED_REG_R9W:
  case XED_REG_R9D:
  case XED_REG_R9:
    return XED_REG_R9B;

  case XED_REG_R10W:
  case XED_REG_R10D:
  case XED_REG_R10:
    return XED_REG_R10B;

  case XED_REG_R11W:
  case XED_REG_R11D:
  case XED_REG_R11:
    return XED_REG_R11B;

  case XED_REG_R12W:
  case XED_REG_R12D:
  case XED_REG_R12:
    return XED_REG_R12B;

  case XED_REG_R13W:
  case XED_REG_R13D:
  case XED_REG_R13:
    return XED_REG_R13B;

  case XED_REG_R14W:
  case XED_REG_R14D:
  case XED_REG_R14:
    return XED_REG_R14B;

  case XED_REG_R15W:
  case XED_REG_R15D:
  case XED_REG_R15:
    return XED_REG_R15B;

  default:
    FATAL("Unknown register");
  }
}

uint32_t Push(xed_state_t *dstate, xed_reg_enum_t r, unsigned char *encoded, size_t encoded_size) {
  uint32_t olen;
  xed_error_enum_t xed_error;

  // push destination register
  xed_encoder_request_t push;
  xed_encoder_request_zero_set_mode(&push, dstate);
  xed_encoder_request_set_iclass(&push, XED_ICLASS_PUSH);

  xed_encoder_request_set_effective_operand_width(&push, dstate->stack_addr_width * 8);
  xed_encoder_request_set_effective_address_size(&push, dstate->stack_addr_width * 8);

  xed_encoder_request_set_reg(&push, XED_OPERAND_REG0, GetFullSizeRegister(r, dstate->stack_addr_width));
  xed_encoder_request_set_operand_order(&push, 0, XED_OPERAND_REG0);

  xed_error = xed_encode(&push, encoded, encoded_size, &olen);
  if (xed_error != XED_ERROR_NONE) {
    FATAL("Error encoding instruction");
  }

  return olen;
}

uint32_t Pop(xed_state_t *dstate, xed_reg_enum_t r, unsigned char *encoded, size_t encoded_size) {
  uint32_t olen;
  xed_error_enum_t xed_error;

  // push destination register
  xed_encoder_request_t pop;
  xed_encoder_request_zero_set_mode(&pop, dstate);
  xed_encoder_request_set_iclass(&pop, XED_ICLASS_POP);

  xed_encoder_request_set_effective_operand_width(&pop, dstate->stack_addr_width * 8);
  xed_encoder_request_set_effective_address_size(&pop, dstate->stack_addr_width * 8);

  xed_encoder_request_set_reg(&pop, XED_OPERAND_REG0, GetFullSizeRegister(r, dstate->stack_addr_width));
  xed_encoder_request_set_operand_order(&pop, 0, XED_OPERAND_REG0);

  xed_error = xed_encode(&pop, encoded, encoded_size, &olen);
  if (xed_error != XED_ERROR_NONE) {
    FATAL("Error encoding instruction");
  }

  return olen;
}

void CopyOperandFromInstruction(xed_decoded_inst_t *src,
                                xed_encoder_request_t *dest,
                                xed_operand_enum_t src_operand_name,
                                xed_operand_enum_t dest_operand_name,
                                int dest_operand_index,
                                size_t stack_offset)
{
  if ((src_operand_name >= XED_OPERAND_REG0) && (src_operand_name <= XED_OPERAND_REG8) &&
      (dest_operand_name >= XED_OPERAND_REG0) && (dest_operand_name <= XED_OPERAND_REG8))
  {
    xed_reg_enum_t r = xed_decoded_inst_get_reg(src, src_operand_name);
    xed_encoder_request_set_reg(dest, dest_operand_name, r);
  } else if (src_operand_name == XED_OPERAND_MEM0 && dest_operand_name == XED_OPERAND_MEM0) {
    xed_encoder_request_set_mem0(dest);
    xed_reg_enum_t base_reg = xed_decoded_inst_get_base_reg(src, 0);
    xed_encoder_request_set_base0(dest, base_reg);
    xed_encoder_request_set_seg0(dest, xed_decoded_inst_get_seg_reg(src, 0));
    xed_encoder_request_set_index(dest, xed_decoded_inst_get_index_reg(src, 0));
    xed_encoder_request_set_scale(dest, xed_decoded_inst_get_scale(src, 0));
    // in case where base is rsp, disp needs fixing
    if ((base_reg == XED_REG_SP) || (base_reg == XED_REG_ESP) || (base_reg == XED_REG_RSP)) {
      int64_t disp = xed_decoded_inst_get_memory_displacement(src, 0) + stack_offset;
      // always use disp width 4 in this case
      xed_encoder_request_set_memory_displacement(dest, disp, 4);
    } else {
      xed_encoder_request_set_memory_displacement(dest,
        xed_decoded_inst_get_memory_displacement(src, 0),
        xed_decoded_inst_get_memory_displacement_width(src, 0));
    }
    // int length = xed_decoded_inst_get_memory_operand_length(xedd, 0);
    xed_encoder_request_set_memory_operand_length(dest,
      xed_decoded_inst_get_memory_operand_length(src, 0));
  } else if (src_operand_name == XED_OPERAND_IMM0 && dest_operand_name == XED_OPERAND_IMM0) {
    uint64_t imm = xed_decoded_inst_get_unsigned_immediate(src);
    uint32_t width = xed_decoded_inst_get_immediate_width(src);
    xed_encoder_request_set_uimm0(dest, imm, width);
  } else if (src_operand_name == XED_OPERAND_IMM0SIGNED && dest_operand_name == XED_OPERAND_IMM0SIGNED) {
    int32_t imm = xed_decoded_inst_get_signed_immediate(src);
    uint32_t width = xed_decoded_inst_get_immediate_width(src);
    xed_encoder_request_set_simm(dest, imm, width);
  } else {
    FATAL("Unsupported param");
  }
  xed_encoder_request_set_operand_order(dest, dest_operand_index, dest_operand_name);
}

uint32_t Mov(xed_state_t *dstate, uint32_t operand_width, xed_reg_enum_t base_reg, int32_t displacement, xed_reg_enum_t r2, unsigned char *encoded, size_t encoded_size) {
  uint32_t olen;
  xed_error_enum_t xed_error;

  xed_encoder_request_t mov;
  xed_encoder_request_zero_set_mode(&mov, dstate);
  xed_encoder_request_set_iclass(&mov, XED_ICLASS_MOV);

  xed_encoder_request_set_effective_operand_width(&mov, operand_width);
  xed_encoder_request_set_effective_address_size(&mov, dstate->stack_addr_width * 8);

  xed_encoder_request_set_mem0(&mov);
  xed_encoder_request_set_base0(&mov, base_reg);
  xed_encoder_request_set_memory_displacement(&mov, displacement, 4);
  // int length = xed_decoded_inst_get_memory_operand_length(xedd, 0);
  xed_encoder_request_set_memory_operand_length(&mov, operand_width / 8);
  xed_encoder_request_set_operand_order(&mov, 0, XED_OPERAND_MEM0);

  xed_encoder_request_set_reg(&mov, XED_OPERAND_REG0, r2);
  xed_encoder_request_set_operand_order(&mov, 1, XED_OPERAND_REG0);

  xed_error = xed_encode(&mov, encoded, encoded_size, &olen);
  if (xed_error != XED_ERROR_NONE) {
    FATAL("Error encoding instruction");
  }

  return olen;
}

uint32_t Lzcnt(xed_state_t *dstate, uint32_t operand_width, xed_reg_enum_t dest_reg, xed_reg_enum_t src_reg, unsigned char *encoded, size_t encoded_size) {
  uint32_t olen;
  xed_error_enum_t xed_error;

  xed_encoder_request_t lzcnt;
  xed_encoder_request_zero_set_mode(&lzcnt, dstate);
  xed_encoder_request_set_iclass(&lzcnt, XED_ICLASS_LZCNT);

  xed_encoder_request_set_effective_operand_width(&lzcnt, operand_width);
  //xed_encoder_request_set_effective_address_size(&lzcnt, operand_width);

  xed_encoder_request_set_reg(&lzcnt, XED_OPERAND_REG0, dest_reg);
  xed_encoder_request_set_operand_order(&lzcnt, 0, XED_OPERAND_REG0);

  xed_encoder_request_set_reg(&lzcnt, XED_OPERAND_REG1, src_reg);
  xed_encoder_request_set_operand_order(&lzcnt, 1, XED_OPERAND_REG1);

  xed_error = xed_encode(&lzcnt, encoded, encoded_size, &olen);
  if (xed_error != XED_ERROR_NONE) {
    FATAL("Error encoding instruction");
  }

  return olen;
}

uint32_t CmpImm8(xed_state_t *dstate, uint32_t operand_width, xed_reg_enum_t dest_reg, uint64_t imm, unsigned char *encoded, size_t encoded_size) {
  uint32_t olen;
  xed_error_enum_t xed_error;

  xed_encoder_request_t lzcnt;
  xed_encoder_request_zero_set_mode(&lzcnt, dstate);
  xed_encoder_request_set_iclass(&lzcnt, XED_ICLASS_CMP);

  xed_encoder_request_set_effective_operand_width(&lzcnt, operand_width);
  // xed_encoder_request_set_effective_address_size(&lzcnt, operand_width);

  xed_encoder_request_set_reg(&lzcnt, XED_OPERAND_REG0, dest_reg);
  xed_encoder_request_set_operand_order(&lzcnt, 0, XED_OPERAND_REG0);

  xed_encoder_request_set_uimm0_bits(&lzcnt, imm, 8);
  xed_encoder_request_set_operand_order(&lzcnt, 1, XED_OPERAND_IMM0);

  xed_error = xed_encode(&lzcnt, encoded, encoded_size, &olen);
  if (xed_error != XED_ERROR_NONE) {
    FATAL("Error encoding instruction");
  }

  return olen;
}

uint32_t GetInstructionLength(xed_encoder_request_t *inst) {
  unsigned int olen;
  unsigned char tmp[15];
  xed_error_enum_t xed_error;

  xed_error = xed_encode(inst, tmp, sizeof(tmp), &olen);
  if (xed_error != XED_ERROR_NONE) {
    FATAL("Error encoding instruction");
  }

  return olen;

}

void FixRipDisplacement(xed_encoder_request_t *inst, size_t mem_address, size_t fixed_instruction_address) {
  // fake displacement, just to get length
  xed_encoder_request_set_memory_displacement(inst, 0x7777777, 4);
  uint32_t inst_length = GetInstructionLength(inst);

  size_t instruction_end_addr = fixed_instruction_address + inst_length;
  int64_t fixed_disp = (int64_t)(mem_address) - (int64_t)(instruction_end_addr);
  if (llabs(fixed_disp) > 0x7FFFFFFF) FATAL("Offset larger than 2G");

  xed_encoder_request_set_memory_displacement(inst, fixed_disp, 4);
}
<commit_msg>Fix warnings with encoded_size<commit_after>#include "common.h"
#include "x86_helpers.h"

xed_reg_enum_t GetUnusedRegister(xed_reg_enum_t used_register, int operand_width) {
  switch (operand_width) {
  case 16:
    if (used_register == XED_REG_AX) return XED_REG_CX;
    return XED_REG_AX;
  case 32:
    if (used_register == XED_REG_EAX) return XED_REG_ECX;
    return XED_REG_EAX;
  case 64:
    if (used_register == XED_REG_RAX) return XED_REG_RCX;
    return XED_REG_RAX;
  default:
    FATAL("Unexpected operand width");
  }
}

xed_reg_enum_t GetFullSizeRegister(xed_reg_enum_t r, int child_ptr_size) {
  if (child_ptr_size == 8) {
    return xed_get_largest_enclosing_register(r);
  } else {
    return xed_get_largest_enclosing_register32(r);
  }
}

xed_reg_enum_t Get8BitRegister(xed_reg_enum_t r) {
  switch (r) {
  case XED_REG_AX:
  case XED_REG_EAX:
  case XED_REG_RAX:
    return XED_REG_AL;

  case XED_REG_CX:
  case XED_REG_ECX:
  case XED_REG_RCX:
    return XED_REG_CL;

  case XED_REG_DX:
  case XED_REG_EDX:
  case XED_REG_RDX:
    return XED_REG_DL;

  case XED_REG_BX:
  case XED_REG_EBX:
  case XED_REG_RBX:
    return XED_REG_BL;

  case XED_REG_SP:
  case XED_REG_ESP:
  case XED_REG_RSP:
    return XED_REG_SPL;

  case XED_REG_BP:
  case XED_REG_EBP:
  case XED_REG_RBP:
    return XED_REG_BPL;

  case XED_REG_SI:
  case XED_REG_ESI:
  case XED_REG_RSI:
    return XED_REG_SIL;

  case XED_REG_DI:
  case XED_REG_EDI:
  case XED_REG_RDI:
    return XED_REG_DIL;

  case XED_REG_R8W:
  case XED_REG_R8D:
  case XED_REG_R8:
    return XED_REG_R8B;

  case XED_REG_R9W:
  case XED_REG_R9D:
  case XED_REG_R9:
    return XED_REG_R9B;

  case XED_REG_R10W:
  case XED_REG_R10D:
  case XED_REG_R10:
    return XED_REG_R10B;

  case XED_REG_R11W:
  case XED_REG_R11D:
  case XED_REG_R11:
    return XED_REG_R11B;

  case XED_REG_R12W:
  case XED_REG_R12D:
  case XED_REG_R12:
    return XED_REG_R12B;

  case XED_REG_R13W:
  case XED_REG_R13D:
  case XED_REG_R13:
    return XED_REG_R13B;

  case XED_REG_R14W:
  case XED_REG_R14D:
  case XED_REG_R14:
    return XED_REG_R14B;

  case XED_REG_R15W:
  case XED_REG_R15D:
  case XED_REG_R15:
    return XED_REG_R15B;

  default:
    FATAL("Unknown register");
  }
}

uint32_t Push(xed_state_t *dstate, xed_reg_enum_t r, unsigned char *encoded, size_t encoded_size) {
  uint32_t olen;
  xed_error_enum_t xed_error;

  // push destination register
  xed_encoder_request_t push;
  xed_encoder_request_zero_set_mode(&push, dstate);
  xed_encoder_request_set_iclass(&push, XED_ICLASS_PUSH);

  xed_encoder_request_set_effective_operand_width(&push, dstate->stack_addr_width * 8);
  xed_encoder_request_set_effective_address_size(&push, dstate->stack_addr_width * 8);

  xed_encoder_request_set_reg(&push, XED_OPERAND_REG0, GetFullSizeRegister(r, dstate->stack_addr_width));
  xed_encoder_request_set_operand_order(&push, 0, XED_OPERAND_REG0);

  xed_error = xed_encode(&push, encoded, (unsigned int)encoded_size, &olen);
  if (xed_error != XED_ERROR_NONE) {
    FATAL("Error encoding instruction");
  }

  return olen;
}

uint32_t Pop(xed_state_t *dstate, xed_reg_enum_t r, unsigned char *encoded, size_t encoded_size) {
  uint32_t olen;
  xed_error_enum_t xed_error;

  // push destination register
  xed_encoder_request_t pop;
  xed_encoder_request_zero_set_mode(&pop, dstate);
  xed_encoder_request_set_iclass(&pop, XED_ICLASS_POP);

  xed_encoder_request_set_effective_operand_width(&pop, dstate->stack_addr_width * 8);
  xed_encoder_request_set_effective_address_size(&pop, dstate->stack_addr_width * 8);

  xed_encoder_request_set_reg(&pop, XED_OPERAND_REG0, GetFullSizeRegister(r, dstate->stack_addr_width));
  xed_encoder_request_set_operand_order(&pop, 0, XED_OPERAND_REG0);

  xed_error = xed_encode(&pop, encoded, (unsigned int)encoded_size, &olen);
  if (xed_error != XED_ERROR_NONE) {
    FATAL("Error encoding instruction");
  }

  return olen;
}

void CopyOperandFromInstruction(xed_decoded_inst_t *src,
                                xed_encoder_request_t *dest,
                                xed_operand_enum_t src_operand_name,
                                xed_operand_enum_t dest_operand_name,
                                int dest_operand_index,
                                size_t stack_offset)
{
  if ((src_operand_name >= XED_OPERAND_REG0) && (src_operand_name <= XED_OPERAND_REG8) &&
      (dest_operand_name >= XED_OPERAND_REG0) && (dest_operand_name <= XED_OPERAND_REG8))
  {
    xed_reg_enum_t r = xed_decoded_inst_get_reg(src, src_operand_name);
    xed_encoder_request_set_reg(dest, dest_operand_name, r);
  } else if (src_operand_name == XED_OPERAND_MEM0 && dest_operand_name == XED_OPERAND_MEM0) {
    xed_encoder_request_set_mem0(dest);
    xed_reg_enum_t base_reg = xed_decoded_inst_get_base_reg(src, 0);
    xed_encoder_request_set_base0(dest, base_reg);
    xed_encoder_request_set_seg0(dest, xed_decoded_inst_get_seg_reg(src, 0));
    xed_encoder_request_set_index(dest, xed_decoded_inst_get_index_reg(src, 0));
    xed_encoder_request_set_scale(dest, xed_decoded_inst_get_scale(src, 0));
    // in case where base is rsp, disp needs fixing
    if ((base_reg == XED_REG_SP) || (base_reg == XED_REG_ESP) || (base_reg == XED_REG_RSP)) {
      int64_t disp = xed_decoded_inst_get_memory_displacement(src, 0) + stack_offset;
      // always use disp width 4 in this case
      xed_encoder_request_set_memory_displacement(dest, disp, 4);
    } else {
      xed_encoder_request_set_memory_displacement(dest,
        xed_decoded_inst_get_memory_displacement(src, 0),
        xed_decoded_inst_get_memory_displacement_width(src, 0));
    }
    // int length = xed_decoded_inst_get_memory_operand_length(xedd, 0);
    xed_encoder_request_set_memory_operand_length(dest,
      xed_decoded_inst_get_memory_operand_length(src, 0));
  } else if (src_operand_name == XED_OPERAND_IMM0 && dest_operand_name == XED_OPERAND_IMM0) {
    uint64_t imm = xed_decoded_inst_get_unsigned_immediate(src);
    uint32_t width = xed_decoded_inst_get_immediate_width(src);
    xed_encoder_request_set_uimm0(dest, imm, width);
  } else if (src_operand_name == XED_OPERAND_IMM0SIGNED && dest_operand_name == XED_OPERAND_IMM0SIGNED) {
    int32_t imm = xed_decoded_inst_get_signed_immediate(src);
    uint32_t width = xed_decoded_inst_get_immediate_width(src);
    xed_encoder_request_set_simm(dest, imm, width);
  } else {
    FATAL("Unsupported param");
  }
  xed_encoder_request_set_operand_order(dest, dest_operand_index, dest_operand_name);
}

uint32_t Mov(xed_state_t *dstate, uint32_t operand_width, xed_reg_enum_t base_reg, int32_t displacement, xed_reg_enum_t r2, unsigned char *encoded, size_t encoded_size) {
  uint32_t olen;
  xed_error_enum_t xed_error;

  xed_encoder_request_t mov;
  xed_encoder_request_zero_set_mode(&mov, dstate);
  xed_encoder_request_set_iclass(&mov, XED_ICLASS_MOV);

  xed_encoder_request_set_effective_operand_width(&mov, operand_width);
  xed_encoder_request_set_effective_address_size(&mov, dstate->stack_addr_width * 8);

  xed_encoder_request_set_mem0(&mov);
  xed_encoder_request_set_base0(&mov, base_reg);
  xed_encoder_request_set_memory_displacement(&mov, displacement, 4);
  // int length = xed_decoded_inst_get_memory_operand_length(xedd, 0);
  xed_encoder_request_set_memory_operand_length(&mov, operand_width / 8);
  xed_encoder_request_set_operand_order(&mov, 0, XED_OPERAND_MEM0);

  xed_encoder_request_set_reg(&mov, XED_OPERAND_REG0, r2);
  xed_encoder_request_set_operand_order(&mov, 1, XED_OPERAND_REG0);

  xed_error = xed_encode(&mov, encoded, (unsigned int)encoded_size, &olen);
  if (xed_error != XED_ERROR_NONE) {
    FATAL("Error encoding instruction");
  }

  return olen;
}

uint32_t Lzcnt(xed_state_t *dstate, uint32_t operand_width, xed_reg_enum_t dest_reg, xed_reg_enum_t src_reg, unsigned char *encoded, size_t encoded_size) {
  uint32_t olen;
  xed_error_enum_t xed_error;

  xed_encoder_request_t lzcnt;
  xed_encoder_request_zero_set_mode(&lzcnt, dstate);
  xed_encoder_request_set_iclass(&lzcnt, XED_ICLASS_LZCNT);

  xed_encoder_request_set_effective_operand_width(&lzcnt, operand_width);
  //xed_encoder_request_set_effective_address_size(&lzcnt, operand_width);

  xed_encoder_request_set_reg(&lzcnt, XED_OPERAND_REG0, dest_reg);
  xed_encoder_request_set_operand_order(&lzcnt, 0, XED_OPERAND_REG0);

  xed_encoder_request_set_reg(&lzcnt, XED_OPERAND_REG1, src_reg);
  xed_encoder_request_set_operand_order(&lzcnt, 1, XED_OPERAND_REG1);

  xed_error = xed_encode(&lzcnt, encoded, (unsigned int)encoded_size, &olen);
  if (xed_error != XED_ERROR_NONE) {
    FATAL("Error encoding instruction");
  }

  return olen;
}

uint32_t CmpImm8(xed_state_t *dstate, uint32_t operand_width, xed_reg_enum_t dest_reg, uint64_t imm, unsigned char *encoded, size_t encoded_size) {
  uint32_t olen;
  xed_error_enum_t xed_error;

  xed_encoder_request_t lzcnt;
  xed_encoder_request_zero_set_mode(&lzcnt, dstate);
  xed_encoder_request_set_iclass(&lzcnt, XED_ICLASS_CMP);

  xed_encoder_request_set_effective_operand_width(&lzcnt, operand_width);
  // xed_encoder_request_set_effective_address_size(&lzcnt, operand_width);

  xed_encoder_request_set_reg(&lzcnt, XED_OPERAND_REG0, dest_reg);
  xed_encoder_request_set_operand_order(&lzcnt, 0, XED_OPERAND_REG0);

  xed_encoder_request_set_uimm0_bits(&lzcnt, imm, 8);
  xed_encoder_request_set_operand_order(&lzcnt, 1, XED_OPERAND_IMM0);

  xed_error = xed_encode(&lzcnt, encoded, (unsigned int)encoded_size, &olen);
  if (xed_error != XED_ERROR_NONE) {
    FATAL("Error encoding instruction");
  }

  return olen;
}

uint32_t GetInstructionLength(xed_encoder_request_t *inst) {
  unsigned int olen;
  unsigned char tmp[15];
  xed_error_enum_t xed_error;

  xed_error = xed_encode(inst, tmp, sizeof(tmp), &olen);
  if (xed_error != XED_ERROR_NONE) {
    FATAL("Error encoding instruction");
  }

  return olen;

}

void FixRipDisplacement(xed_encoder_request_t *inst, size_t mem_address, size_t fixed_instruction_address) {
  // fake displacement, just to get length
  xed_encoder_request_set_memory_displacement(inst, 0x7777777, 4);
  uint32_t inst_length = GetInstructionLength(inst);

  size_t instruction_end_addr = fixed_instruction_address + inst_length;
  int64_t fixed_disp = (int64_t)(mem_address) - (int64_t)(instruction_end_addr);
  if (llabs(fixed_disp) > 0x7FFFFFFF) FATAL("Offset larger than 2G");

  xed_encoder_request_set_memory_displacement(inst, fixed_disp, 4);
}
<|endoftext|>


<commit_before>// Copyright 2018 Google LLC
//
// 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
//
//     https://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.

#include <array>
#include <utility>

namespace polymorphic {
namespace detail {

template <typename T>
using ptr = T*;
template <typename T, typename Signature>
struct function_entry;

template <typename T, typename Return, typename Method, typename... Parameters>
struct function_entry<T, Return(Method, Parameters...)> {
  static Return poly_call(Method method, void* t, Parameters... parameters) {
    return poly_extend(method, *static_cast<T*>(t), parameters...);
  }
};

template <typename T, typename Return, typename Method, typename... Parameters>
struct function_entry<T, Return(Method, Parameters...)const> {
  static Return poly_call(Method method, const void* t, Parameters... parameters) {
    return poly_extend(method, *static_cast<const T*>(t), parameters...);
  }
};

template <typename T, typename... Signatures>
inline const auto vtable = std::array{
    reinterpret_cast<ptr<void()>>(function_entry<T, Signatures>::poly_call)...};

template <size_t Index, typename Signature>
struct vtable_caller;
template <size_t Index, typename Return, typename Method,
          typename... Parameters>
struct vtable_caller<Index, Return(Method, Parameters...)> {
  static Return call_vtable(Method method, ptr<const ptr<void()>> table,
                            void* t, Parameters... parameters) {
    return reinterpret_cast<ptr<Return(Method, void*, Parameters...)>>(
        table[Index])(method, t, parameters...);
  }
  constexpr static std::size_t get_index(ptr<Return(Method, Parameters...)>) {
    return Index;
  }

  using  is_const = std::false_type;
};

template <size_t Index, typename Signature>
struct vtable_caller;
template <size_t Index, typename Return, typename Method,
          typename... Parameters>
struct vtable_caller<Index, Return(Method, Parameters...)const> {
  static Return call_vtable(Method method, ptr<const ptr<void()>> table,
                            const void* t, Parameters... parameters) {
    return reinterpret_cast<ptr<Return(Method, const void*, Parameters...)>>(
        table[Index])(method, t, parameters...);
  }
  constexpr static std::size_t get_index(ptr<Return(Method, Parameters...)>) {
    return Index;
  }

  using  is_const = std::true_type;
};

template<typename T>
using is_const_t = typename T::is_const;

template <typename... implementations>
struct overload_call_vtable : implementations... {
  using implementations::call_vtable...;
  using implementations::get_index...;
  static constexpr bool all_const = std::conjunction_v<is_const_t<implementations>...>;
};

template <typename IntPack, typename... Signatures>
struct polymorphic_caller_implementation;
template <size_t... I, typename... Signatures>
struct polymorphic_caller_implementation<std::index_sequence<I...>,
                                         Signatures...>
    : overload_call_vtable<vtable_caller<I, Signatures>...> {};

}  // namespace detail
template <typename... Signatures>
class polymorphic_view;

template <typename T>
struct is_polymorphic_view {
  static constexpr bool value = false;
};

template <typename... Signatures>
struct is_polymorphic_view<polymorphic_view<Signatures...>> {
  static constexpr bool value = true;
};

template <typename... Signatures>
class polymorphic_view
    : private detail::polymorphic_caller_implementation<
          std::make_index_sequence<sizeof...(Signatures)>, Signatures...> {
  const std::array<detail::ptr<void()>, sizeof...(Signatures)>* vptr_ = nullptr;
  std::conditional_t<polymorphic_view::all_const,const void*, void*> t_ = nullptr;

  template <typename... OtherSignatures>
  static auto get_vtable(const polymorphic_view<OtherSignatures...>& other) {
    static const std::array<detail::ptr<void()>, sizeof...(Signatures)> vtable{
        other.template get_entry<Signatures>()...};
    return &vtable;
  }
  template <typename Signature>
  detail::ptr<void()> get_entry() const {
    return (*vptr_)[this->get_index(detail::ptr<Signature>{})];
  }

  template <typename... OtherSignatures>
  friend class polymorphic_view;

 public:
  template <typename T, typename = std::enable_if_t<
                            !is_polymorphic_view<std::decay_t<T>>::value>>
  explicit polymorphic_view(T& t)
      : vptr_(&detail::vtable<std::decay_t<T>, Signatures...>), t_(&t) {}

  template <typename... OtherSignatures>
  explicit polymorphic_view(const polymorphic_view<OtherSignatures...>& other)
      : vptr_(get_vtable(other)), t_(other.t_) {}

  explicit operator bool() const { return t_ != nullptr; }

  template <typename Method, typename... Parameters>
  decltype(auto) call(Parameters&&... parameters) {
    return this->call_vtable(Method{}, vptr_->data(), t_,
                             std::forward<Parameters>(parameters)...);
  }
};

}  // namespace polymorphic

#include <iostream>
#include <string>

struct draw {};
struct another {};

template <typename T>
void poly_extend(draw, const T& t) {
  std::cout << t << "\n";
}
template <typename T>
void poly_extend(another, T& t) {
  t = t + t;
}

int main() {
  int i = 5;
  using poly = polymorphic::polymorphic_view<void(draw), void(another)>;
  using poly_const = polymorphic::polymorphic_view<void(draw) const>;
  const int ic = 7;
  poly_const pc1{ ic };
  pc1.call<draw>();
  poly p1{i};
  p1.call<draw>();
  auto p2 = p1;
  p2.call<draw>();
  std::string s("hello world");
  p2 = poly{s};
  p2.call<another>();
  p2.call<draw>();

  polymorphic::polymorphic_view<void(draw)> p3{p2};

  p3.call<draw>();
}
<commit_msg>Add initial polymorphic_object<commit_after>// Copyright 2018 Google LLC
//
// 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
//
//     https://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.

#include <array>
#include <utility>

namespace polymorphic {
namespace detail {

template <typename T>
using ptr = T*;
template <typename T, typename Signature>
struct function_entry;

template <typename T, typename Return, typename Method, typename... Parameters>
struct function_entry<T, Return(Method, Parameters...)> {
  static Return poly_call(Method method, void* t, Parameters... parameters) {
    return poly_extend(method, *static_cast<T*>(t), parameters...);
  }
};

template <typename T, typename Return, typename Method, typename... Parameters>
struct function_entry<T, Return(Method, Parameters...) const> {
  static Return poly_call(Method method, const void* t,
                          Parameters... parameters) {
    return poly_extend(method, *static_cast<const T*>(t), parameters...);
  }
};

template <typename T>
struct type {};

template <typename T, typename... Signatures>
inline const auto vtable = std::array{
    reinterpret_cast<ptr<void()>>(function_entry<T, Signatures>::poly_call)...};

template <size_t Index, typename Signature>
struct vtable_caller;
template <size_t Index, typename Return, typename Method,
          typename... Parameters>
struct vtable_caller<Index, Return(Method, Parameters...)> {
  static Return call_vtable(Method method, ptr<const ptr<void()>> table,
                            void* t, Parameters... parameters) {
    return reinterpret_cast<ptr<Return(Method, void*, Parameters...)>>(
        table[Index])(method, t, parameters...);
  }
  constexpr static std::size_t get_index(type<Return(Method, Parameters...)>) {
    return Index;
  }

  constexpr static bool is_const = false;
};

template <size_t Index, typename Signature>
struct vtable_caller;
template <size_t Index, typename Return, typename Method,
          typename... Parameters>
struct vtable_caller<Index, Return(Method, Parameters...) const> {
  static Return call_vtable(Method method, ptr<const ptr<void()>> table,
                            const void* t, Parameters... parameters) {
    return reinterpret_cast<ptr<Return(Method, const void*, Parameters...)>>(
        table[Index])(method, t, parameters...);
  }
  constexpr static std::size_t get_index(
      type<Return(Method, Parameters...) const>) {
    return Index;
  }

  constexpr static bool is_const = true;
};

template <typename T>
using is_const_t = typename T::is_const;

template <typename... implementations>
struct overload_call_vtable : implementations... {
  using implementations::call_vtable...;
  using implementations::get_index...;
  static constexpr bool all_const = (implementations::is_const && ...);
};

template <typename IntPack, typename... Signatures>
struct polymorphic_caller_implementation;
template <size_t... I, typename... Signatures>
struct polymorphic_caller_implementation<std::index_sequence<I...>,
                                         Signatures...>
    : overload_call_vtable<vtable_caller<I, Signatures>...> {};

}  // namespace detail
template <typename... Signatures>
class polymorphic_view;

template <typename... Signatures>
class polymorphic_object;

template <typename T>
struct is_polymorphic{
  static constexpr bool value = false;
};

template <typename... Signatures>
struct is_polymorphic<polymorphic_view<Signatures...>> {
  static constexpr bool value = true;
};

template <typename... Signatures>
struct is_polymorphic<polymorphic_object<Signatures...>> {
  static constexpr bool value = true;
};

using object_ptr = std::unique_ptr<void, detail::ptr<void(void*)>>;

template <typename T>
object_ptr make_object_ptr(const T& t) {
  return object_ptr(new T(t), +[](void* v) { delete static_cast<T*>(v); });
}

namespace detail {
struct clone {};

template <typename T>
object_ptr poly_extend(clone, const T& t) {
  return make_object_ptr(t);
}

template<typename T>
auto get_ptr(T* t){return t;}

template<typename T>
auto get_ptr(T& t){return t.get();}

}  // namespace detail

template <typename... Signatures>
class polymorphic_object
    : private detail::polymorphic_caller_implementation<
          std::make_index_sequence<sizeof...(Signatures) + 1>, Signatures...,
          object_ptr(detail::clone) const> {
  const std::array<detail::ptr<void()>, sizeof...(Signatures) + 1>* vptr_ =
      nullptr;
  object_ptr t_;

  template <typename Signature>
  detail::ptr<void()> get_entry() const {
    return (*vptr_)[this->get_index(detail::type<Signature>{})];
  }

  template <typename... OtherSignatures>
  friend class polymorphic_view;

 public: template <typename T, typename = std::enable_if_t< !is_polymorphic<std::decay_t<T>>::value>>
  explicit polymorphic_object(T& t)
      : vptr_(&detail::vtable<std::decay_t<T>, Signatures...,
                              object_ptr(detail::clone)>),
        t_(make_object_ptr(t)) {}

  polymorphic_object(const polymorphic_object& other)
      : vptr_(other.vptr_), t_(other.call<detail::clone>()) {}

  polymorphic_object(polymorphic_object&&) = default;

  polymorphic_object& operator=(polymorphic_object&&) = default;

  polymorphic_object& operator=(const polymorphic_object& other) {
    (*this) = polymorphic_view(other);
  }

  explicit operator bool() const { return t_ != nullptr; }

  template <typename Method, typename... Parameters>
  decltype(auto) call(Parameters&&... parameters) {
    return this->call_vtable(Method{}, vptr_->data(), t_.get(),
                             std::forward<Parameters>(parameters)...);
  }

  template <typename Method, typename... Parameters>
  decltype(auto) call(Parameters&&... parameters) const {
    return this->call_vtable(Method{}, vptr_->data(), t_.get(),
                             std::forward<Parameters>(parameters)...);
  }
};

template <typename... Signatures>
class polymorphic_view
    : private detail::polymorphic_caller_implementation<
          std::make_index_sequence<sizeof...(Signatures)>, Signatures...> {
  const std::array<detail::ptr<void()>, sizeof...(Signatures)>* vptr_ = nullptr;
  std::conditional_t<polymorphic_view::all_const, const void*, void*> t_ =
      nullptr;

  template <typename Poly>
  static auto get_vtable(const Poly& other) {
    static const std::array<detail::ptr<void()>, sizeof...(Signatures)> vtable{
        other.template get_entry<Signatures>()...};
    return &vtable;
  }

  template <typename Signature>
  detail::ptr<void()> get_entry() const {
    return (*vptr_)[this->get_index(detail::type<Signature>{})];
  }

  template <typename... OtherSignatures>
  friend class polymorphic_view;

 public:
  template <typename T, typename = std::enable_if_t<
                            !is_polymorphic<std::decay_t<T>>::value>>
  explicit polymorphic_view(T& t)
      : vptr_(&detail::vtable<std::decay_t<T>, Signatures...>), t_(&t) {}

  template <typename Poly, typename = std::enable_if_t<
                            is_polymorphic<std::decay_t<Poly>>::value>>
  explicit polymorphic_view(const Poly& other)
      : vptr_(get_vtable(other)), t_(detail::get_ptr(other.t_)) {}

  explicit operator bool() const { return t_ != nullptr; }

  template <typename Method, typename... Parameters>
  decltype(auto) call(Parameters&&... parameters) {
    return this->call_vtable(Method{}, vptr_->data(), t_,
                             std::forward<Parameters>(parameters)...);
  }
};

}  // namespace polymorphic

#include <iostream>
#include <string>

struct draw {};
struct another {};

template <typename T>
void poly_extend(draw, const T& t) {
  std::cout << t << "\n";
}
template <typename T>
void poly_extend(another, T& t) {
  t = t + t;
}

int main() {
  int i = 5;

  using poly = polymorphic::polymorphic_view<void(draw) const, void(another)>;
  using poly_object =
      polymorphic::polymorphic_object<void(draw) const, void(another)>;
  poly_object po{i};
  auto po1 = po;
  po.call<another>();
  po1.call<draw>();
  po.call<draw>();

  poly a{po};
  a.call<draw>();

  using poly_const = polymorphic::polymorphic_view<void(draw) const>;
  const int ic = 7;
  poly_const pc1{ic};
  pc1.call<draw>();
  poly p1{i};
  p1.call<draw>();
  auto p2 = p1;
  p2.call<draw>();
  std::string s("hello world");
  p2 = poly{s};
  p2.call<another>();
  p2.call<draw>();

  polymorphic::polymorphic_view<void(draw) const> p3{p2};

  p3.call<draw>();
}<|endoftext|>


<commit_before>//
// PROJECT CHRONO - http://projectchrono.org
//
// Copyright (c) 2010, 2012 Alessandro Tasora
// Copyright (c) 2013 Project Chrono
// All rights reserved.
//
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file at the top level of the distribution
// and at http://projectchrono.org/license-chrono.txt.
//

///////////////////////////////////////////////////
//
//   ChShaftsBody.cpp
//
// ------------------------------------------------
//             www.deltaknowledge.com
// ------------------------------------------------
///////////////////////////////////////////////////

#include "physics/ChShaftsBody.h"
#include "physics/ChGlobal.h"

#include "core/ChMemory.h" // must be last include (memory leak debugger). In .cpp only.

namespace chrono
{

// Register into the object factory, to enable run-time
// dynamic creation and persistence
ChClassRegister<ChShaftsBody> a_registration_ChShaftsBody;

//////////////////////////////////////
//////////////////////////////////////

ChShaftsBody::ChShaftsBody ()
{

	this->torque_react= 0;
	this->cache_li_speed =0.f;
	this->cache_li_pos = 0.f;

	this->shaft = 0;
	this->body = 0;
	this->shaft_dir = VECT_Z;

	SetIdentifier(CHGLOBALS().GetUniqueIntID()); // mark with unique ID
}

ChShaftsBody::~ChShaftsBody ()
{

}

void ChShaftsBody::Copy(ChShaftsBody* source)
{
		// copy the parent class data...
	ChPhysicsItem::Copy(source);

		// copy class data

	torque_react = source->torque_react;
	cache_li_speed = source->cache_li_speed;
	cache_li_pos = source->cache_li_pos;
	this->shaft_dir = source->shaft_dir;
	this->shaft = 0;
	this->body = 0;
}

int ChShaftsBody::Initialize(ChSharedPtr<ChShaft> mshaft, ChSharedPtr<ChBodyFrame> mbody, ChVector<>& mdir)
{
	ChShaft* mm1 = mshaft.get_ptr();
	ChBodyFrame* mm2 = mbody.get_ptr();
	assert(mm1 && mm2);
	assert(mm1->GetSystem() == mm2->GetSystem());

	this->shaft = mm1;
	this->body = mm2;
	this->shaft_dir = Vnorm(mdir);

	this->constraint.SetVariables(&mm1->Variables(), &mm2->Variables());

	this->SetSystem(this->shaft->GetSystem());
	return true;
}

void ChShaftsBody::Update (double mytime)
{
		// Inherit time changes of parent class
	ChPhysicsItem::Update(mytime);

		// update class data
	// ...
}

////////// LCP INTERFACES ////

void ChShaftsBody::InjectConstraints(ChLcpSystemDescriptor& mdescriptor)
{
	//if (!this->IsActive())
	//	return;

	mdescriptor.InsertConstraint(&constraint);
}

void ChShaftsBody::ConstraintsBiReset()
{
	constraint.Set_b_i(0.);
}

void ChShaftsBody::ConstraintsBiLoad_C(double factor, double recovery_clamp, bool do_clamp)
{
	//if (!this->IsActive())
	//	return;

	double res = 0; // no residual

	constraint.Set_b_i(constraint.Get_b_i() +  factor * res);
}

void ChShaftsBody::ConstraintsBiLoad_Ct(double factor)
{
	//if (!this->IsActive())
	//	return;

	// nothing
}

void ChShaftsBody::ConstraintsLoadJacobians()
{
		// compute jacobians
	//ChVector<> jacw = this->body->TrasformDirectionParentToLocal(shaft_dir);
	ChVector<> jacw = shaft_dir;

	this->constraint.Get_Cq_a()->ElementN(0)=-1;

	this->constraint.Get_Cq_b()->ElementN(0)=0;
	this->constraint.Get_Cq_b()->ElementN(1)=0;
	this->constraint.Get_Cq_b()->ElementN(2)=0;
	this->constraint.Get_Cq_b()->ElementN(3)=(float)jacw.x;
	this->constraint.Get_Cq_b()->ElementN(4)=(float)jacw.y;
	this->constraint.Get_Cq_b()->ElementN(5)=(float)jacw.z;
}

void ChShaftsBody::ConstraintsFetch_react(double factor)
{
	// From constraints to react vector:
	this->torque_react = constraint.Get_l_i() * factor;
}

// Following functions are for exploiting the contact persistence

void  ChShaftsBody::ConstraintsLiLoadSuggestedSpeedSolution()
{
	constraint.Set_l_i(this->cache_li_speed);
}

void  ChShaftsBody::ConstraintsLiLoadSuggestedPositionSolution()
{
	constraint.Set_l_i(this->cache_li_pos);
}

void  ChShaftsBody::ConstraintsLiFetchSuggestedSpeedSolution()
{
	this->cache_li_speed = (float)constraint.Get_l_i();
}

void  ChShaftsBody::ConstraintsLiFetchSuggestedPositionSolution()
{
	this->cache_li_pos =  (float)constraint.Get_l_i();
}

//////// FILE I/O

void ChShaftsBody::StreamOUT(ChStreamOutBinary& mstream)
{
			// class version number
	mstream.VersionWrite(1);

		// serialize parent class too
	ChPhysicsItem::StreamOUT(mstream);

		// stream out all member data
	mstream << this->shaft_dir;

}

void ChShaftsBody::StreamIN(ChStreamInBinary& mstream)
{
		// class version number
	int version = mstream.VersionRead();

		// deserialize parent class too
	ChPhysicsItem::StreamIN(mstream);

		// deserialize class
	mstream >> this->shaft_dir;
}

} // END_OF_NAMESPACE____

/////////////////////
<commit_msg>Another assert trouble - removed<commit_after>//
// PROJECT CHRONO - http://projectchrono.org
//
// Copyright (c) 2010, 2012 Alessandro Tasora
// Copyright (c) 2013 Project Chrono
// All rights reserved.
//
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file at the top level of the distribution
// and at http://projectchrono.org/license-chrono.txt.
//

///////////////////////////////////////////////////
//
//   ChShaftsBody.cpp
//
// ------------------------------------------------
//             www.deltaknowledge.com
// ------------------------------------------------
///////////////////////////////////////////////////

#include "physics/ChShaftsBody.h"
#include "physics/ChGlobal.h"

#include "core/ChMemory.h" // must be last include (memory leak debugger). In .cpp only.

namespace chrono
{

// Register into the object factory, to enable run-time
// dynamic creation and persistence
ChClassRegister<ChShaftsBody> a_registration_ChShaftsBody;

//////////////////////////////////////
//////////////////////////////////////

ChShaftsBody::ChShaftsBody ()
{

	this->torque_react= 0;
	this->cache_li_speed =0.f;
	this->cache_li_pos = 0.f;

	this->shaft = 0;
	this->body = 0;
	this->shaft_dir = VECT_Z;

	SetIdentifier(CHGLOBALS().GetUniqueIntID()); // mark with unique ID
}

ChShaftsBody::~ChShaftsBody ()
{

}

void ChShaftsBody::Copy(ChShaftsBody* source)
{
		// copy the parent class data...
	ChPhysicsItem::Copy(source);

		// copy class data

	torque_react = source->torque_react;
	cache_li_speed = source->cache_li_speed;
	cache_li_pos = source->cache_li_pos;
	this->shaft_dir = source->shaft_dir;
	this->shaft = 0;
	this->body = 0;
}

int ChShaftsBody::Initialize(ChSharedPtr<ChShaft> mshaft, ChSharedPtr<ChBodyFrame> mbody, ChVector<>& mdir)
{
	ChShaft* mm1 = mshaft.get_ptr();
	ChBodyFrame* mm2 = mbody.get_ptr();
	assert(mm1 && mm2);

	this->shaft = mm1;
	this->body = mm2;
	this->shaft_dir = Vnorm(mdir);

	this->constraint.SetVariables(&mm1->Variables(), &mm2->Variables());

	this->SetSystem(this->shaft->GetSystem());
	return true;
}

void ChShaftsBody::Update (double mytime)
{
		// Inherit time changes of parent class
	ChPhysicsItem::Update(mytime);

		// update class data
	// ...
}

////////// LCP INTERFACES ////

void ChShaftsBody::InjectConstraints(ChLcpSystemDescriptor& mdescriptor)
{
	//if (!this->IsActive())
	//	return;

	mdescriptor.InsertConstraint(&constraint);
}

void ChShaftsBody::ConstraintsBiReset()
{
	constraint.Set_b_i(0.);
}

void ChShaftsBody::ConstraintsBiLoad_C(double factor, double recovery_clamp, bool do_clamp)
{
	//if (!this->IsActive())
	//	return;

	double res = 0; // no residual

	constraint.Set_b_i(constraint.Get_b_i() +  factor * res);
}

void ChShaftsBody::ConstraintsBiLoad_Ct(double factor)
{
	//if (!this->IsActive())
	//	return;

	// nothing
}

void ChShaftsBody::ConstraintsLoadJacobians()
{
		// compute jacobians
	//ChVector<> jacw = this->body->TrasformDirectionParentToLocal(shaft_dir);
	ChVector<> jacw = shaft_dir;

	this->constraint.Get_Cq_a()->ElementN(0)=-1;

	this->constraint.Get_Cq_b()->ElementN(0)=0;
	this->constraint.Get_Cq_b()->ElementN(1)=0;
	this->constraint.Get_Cq_b()->ElementN(2)=0;
	this->constraint.Get_Cq_b()->ElementN(3)=(float)jacw.x;
	this->constraint.Get_Cq_b()->ElementN(4)=(float)jacw.y;
	this->constraint.Get_Cq_b()->ElementN(5)=(float)jacw.z;
}

void ChShaftsBody::ConstraintsFetch_react(double factor)
{
	// From constraints to react vector:
	this->torque_react = constraint.Get_l_i() * factor;
}

// Following functions are for exploiting the contact persistence

void  ChShaftsBody::ConstraintsLiLoadSuggestedSpeedSolution()
{
	constraint.Set_l_i(this->cache_li_speed);
}

void  ChShaftsBody::ConstraintsLiLoadSuggestedPositionSolution()
{
	constraint.Set_l_i(this->cache_li_pos);
}

void  ChShaftsBody::ConstraintsLiFetchSuggestedSpeedSolution()
{
	this->cache_li_speed = (float)constraint.Get_l_i();
}

void  ChShaftsBody::ConstraintsLiFetchSuggestedPositionSolution()
{
	this->cache_li_pos =  (float)constraint.Get_l_i();
}

//////// FILE I/O

void ChShaftsBody::StreamOUT(ChStreamOutBinary& mstream)
{
			// class version number
	mstream.VersionWrite(1);

		// serialize parent class too
	ChPhysicsItem::StreamOUT(mstream);

		// stream out all member data
	mstream << this->shaft_dir;

}

void ChShaftsBody::StreamIN(ChStreamInBinary& mstream)
{
		// class version number
	int version = mstream.VersionRead();

		// deserialize parent class too
	ChPhysicsItem::StreamIN(mstream);

		// deserialize class
	mstream >> this->shaft_dir;
}

} // END_OF_NAMESPACE____

/////////////////////
<|endoftext|>


<commit_before>#include<iostream>
#include<string.h>
#include<string>
#include<vector>
#include<sys/types.h>
#include<sys/wait.h>
#include<sys/stat.h>
#include<stdio.h>
#include<unistd.h>
#include<stdlib.h>
#include<cstring>
#include<algorithm>
#include<iterator>
#include<sstream>

using namespace std;

bool run_test(char command[]);
bool run_word_test(char command[]);
bool test_word(const char command[]);
bool test_check_brackets(const char command[]);
void parse_line(char c_line[], char *command_line[]);
void run_line(char *command_line[]);

 int main()
{
	string str;
	string arg = "";
	 while(1)
	{
		str = "";
		char userName[100] = "";
		if(getlogin_r(userName, sizeof(userName)-1) != 0) //Getting username, and returns null if cant be found
		{
			perror("Error getting username");
		}
		cout << '['  << userName << '@';
		char hostName[100] = "";
		if(gethostname(hostName, sizeof(hostName)-1) != 0) // Getting host name, returns numm if it cannot be found
		{
			perror("Error getting hostname");
		}
		cout << hostName << ']';
		cout << "$";
		getline(cin,str);  //Gets a command
		if(str == "exit")  //If the command is exit the program stops
		{
			 break;
		}
		if(str.size() != 0 && str.at(0) == '#')
		{
			str = "";
		}
		if(str != "")
		{
			for(unsigned i = 0; i < str.size(); i++)
			{
				if(str.at(i) == '#')  //Removes all part of the command after the comment
				{
					str = str.substr(0,i);
				}
			}
			while(str.at(0) == ' ')
			{
				str = str.substr(1,str.size()-1);
			}
			if(str.at(str.size() - 1 ) == ' ')
			{
				str = str.substr(0,str.size()-2);
			}
			bool testBool_brac = false;
			bool testBool = false;
			char c_line[100];
			char *command_line[64];
			strcpy(c_line,str.c_str());
			c_line[str.size()] = '\0';
			testBool_brac = test_check_brackets(c_line);

			if(testBool_brac)
			{
				run_test(c_line);
			}
			else if(!testBool_brac)
			{
				cout << "Checking test\n";
				testBool = test_word(c_line);
				if(testBool)
				{
					cout << "Running test\n";
					run_word_test(c_line);
				}
				else
				{
					parse_line(c_line, command_line);
					run_line(command_line);
				}
			}
		}

	}
	  return 0;
}

void parse_line(char c_line[], char *command_line[])
{
	while(*c_line != '\0')
	{
		while(*c_line == ' ' || *c_line == '\n' || *c_line == '\t')
		{
			*c_line++ = '\0';
		}
		*command_line++ = c_line;
		while(*c_line != '\0' && *c_line != ' ' && *c_line != '\n' && *c_line != '\t')
		{
			c_line++;
		}
		*command_line = NULL;
	}
	return;
}

bool test_word(const char command[])
{
	int i = 0;
	if(command[i] == 't' && command[i + 1] == 'e')
	{
		if(command[i + 3] == 't')
		{
			return true;
		}
	}
	return false;
}

bool run_word_test(char command[])
{
	bool file = false;
	bool dir = false;
	bool exist = false;
	int i = 3;
	char fix_command[100];
	i++;
	for(; command[i] == ' '; ++i){} // to skip all the spaces between test and the flag
	if(command[i] == '-' && command[i + 1] == 'f')
	{
		file = true;
		i++;
		i++;
	}
	else if(command[i] == '-' && command[i + 1] == 'd')
	{
		dir = true;
		i++;
		i++;
	}
	else if(command[i] == '-')
	{
		exist = true;
		i++;
		i++;
	}
	for(; command[i] == ' '; ++i){} // skip all spaces between flag and argument

	if(command[i] != '\0')
	{
		int j = 0;
		for(; command[i] != '\0' && command[i] != ' '; ++i)
		{
			fix_command[j] = command[i];
			j++;
		}
		fix_command[j] = '\0';
	}
	if(exist)
	{
		struct stat exist;
		if(stat(fix_command, &exist) == 0)
		{
			cout << "(TRUE)\n";
			return true;
		}
		else
		{
			cout << "(FALSE)\n";
			return false;
		}
	}
	else if(file)
	{
		struct stat file;
		stat(fix_command, &file);
		if(S_ISREG(file.st_mode) != 0)
		{
			cout << "(TRUE)\n";
			return true;
		}
		else
		{
			cout << "(FALSE)\n";
			return false;
		}
	}
	else if(dir)
	{
		struct stat dir;
		stat(fix_command, &dir);
		if(S_ISDIR(dir.st_mode) != 0)
		{
			cout << "(TRUE)\n";
			return true;
		}
		else
		{
			cout << "(FALSE)\n";
		}
	}
	return false;
}

bool test_check_brackets(const char command[])
{
	cout << "Checking brackets\n";
	unsigned i = 0;
	if(command[i] == '[')
	{
		i++;
		if(command[i] == ' ')
		{
			for(; command[i] != '\0'; i++)
			{
				if(command[i] == ']')
				{
					if(command[i - 1] == ' ')
					{
					return true;
					}
					else
					{
						cout << "Need a space before ]\n";
						return false;
					}
				}
				++i;
			}
		}
	}
	return false;
}

bool run_test(char command[])
{

}
void run_line(char *command_line[])
{
	pid_t pid;
	int status;
	if((pid = fork()) < 0)
	{
		perror("forking failed");
	}
	else if(pid == 0)
	{
		if(execvp(*command_line,command_line) < 0)
		{
			perror("execvp failed");
			exit(1);
		}
	}
	else
	{
		while(wait(&status) != pid)
		;
	}
	return;
}
<commit_msg>finished test for rshell.cpp<commit_after>#include<iostream>
#include<string.h>
#include<string>
#include<vector>
#include<sys/types.h>
#include<sys/wait.h>
#include<sys/stat.h>
#include<stdio.h>
#include<unistd.h>
#include<stdlib.h>
#include<cstring>
#include<algorithm>
#include<iterator>
#include<sstream>

using namespace std;

bool run_test(char command[]);
bool run_word_test(char command[]);
bool test_word(const char command[]);
bool test_check_brackets(const char command[], bool &brackets);
void parse_line(char c_line[], char *command_line[]);
void run_line(char *command_line[]);

 int main()
{
	string str;
	string arg = "";
	 while(1)
	{
		str = "";
		char userName[100] = "";
		if(getlogin_r(userName, sizeof(userName)-1) != 0) //Getting username, and returns null if cant be found
		{
			perror("Error getting username");
		}
		cout << '['  << userName << '@';
		char hostName[100] = "";
		if(gethostname(hostName, sizeof(hostName)-1) != 0) // Getting host name, returns numm if it cannot be found
		{
			perror("Error getting hostname");
		}
		cout << hostName << ']';
		cout << "$";
		getline(cin,str);  //Gets a command
		if(str == "exit")  //If the command is exit the program stops
		{
			 break;
		}
		if(str.size() != 0 && str.at(0) == '#')
		{
			str = "";
		}
		if(str != "")
		{
			for(unsigned i = 0; i < str.size(); i++)
			{
				if(str.at(i) == '#')  //Removes all part of the command after the comment
				{
					str = str.substr(0,i);
				}
			}
			while(str.at(0) == ' ')
			{
				str = str.substr(1,str.size()-1);
			}
			if(str.at(str.size() - 1 ) == ' ')
			{
				str = str.substr(0,str.size()- 1);
			}
			bool extra_brac = false;
			bool testBool_brac = false;
			bool testBool = false;
			char c_line[100];
			char *command_line[64];
			strcpy(c_line,str.c_str());
			c_line[str.size()] = '\0';
			testBool_brac = test_check_brackets(c_line, extra_brac);

			if(testBool_brac && extra_brac)
			{
				run_test(c_line);
			}
			else if(!testBool_brac && !extra_brac)
			{
				testBool = test_word(c_line);
				if(testBool)
				{
					run_word_test(c_line);
				}
				else
				{
					parse_line(c_line, command_line);
					run_line(command_line);
				}
			}
		}

	}
	  return 0;
}

void parse_line(char c_line[], char *command_line[])
{
	while(*c_line != '\0')
	{
		while(*c_line == ' ' || *c_line == '\n' || *c_line == '\t')
		{
			*c_line++ = '\0';
		}
		*command_line++ = c_line;
		while(*c_line != '\0' && *c_line != ' ' && *c_line != '\n' && *c_line != '\t')
		{
			c_line++;
		}
		*command_line = NULL;
	}
	return;
}

bool test_word(const char command[])
{
	int i = 0;
	if(command[i] == 't' && command[i + 1] == 'e')
	{
		if(command[i + 3] == 't')
		{
			return true;
		}
	}
	return false;
}

bool run_word_test(char command[])
{
	bool file = false;
	bool dir = false;
	bool exist = false;
	int i = 3;
	char fix_command[100];
	i++;
	for(; command[i] == ' '; ++i){} // to skip all the spaces between test and the flag
	if(command[i] == '-' && command[i + 1] == 'f')
	{
		file = true;
		i++;
		i++;
	}
	else if(command[i] == '-' && command[i + 1] == 'd')
	{
		dir = true;
		i++;
		i++;
	}
	else if(command[i] == '-' && (command[i + 1] != 'e' && command[i + 1] != ' '))
	{
		cout << "Invalid Flag\n";
		return false;
	}
	else if(command[i] == '-' && (command[i + 1] == 'e' || command[i + 1] == ' '))
	{
		exist = true;
		i++;
		i++;
	}
	else
	{
		cout << "Error missing Flag\n";
		return false;
	}
	for(; command[i] == ' '; ++i){} // skip all spaces between flag and argument

	if(command[i] != '\0')
	{
		int j = 0;
		for(; command[i] != '\0' && command[i] != ' '; ++i)
		{
			fix_command[j] = command[i];
			j++;
		}
		fix_command[j] = '\0';
	}
	if(exist)
	{
		struct stat exist;
		if(stat(fix_command, &exist) == 0)
		{
			cout << "(True)\n";
			return true;
		}
		else
		{
			cout << "(False)\n";
			return false;
		}
	}
	else if(file)
	{
		struct stat file;
		stat(fix_command, &file);
		if(S_ISREG(file.st_mode) != 0)
		{
			cout << "(True)\n";
			return true;
		}
		else
		{
			cout << "(False)\n";
			return false;
		}
	}
	else if(dir)
	{
		struct stat dir;
		stat(fix_command, &dir);
		if(S_ISDIR(dir.st_mode) != 0)
		{
			cout << "(True)\n";
			return true;
		}
		else
		{
			cout << "(False)\n";
			return false;
		}
	}
	return false;
}

bool test_check_brackets(const char command[], bool &brackets)
{
	bool endBracket = true;
	int i = 0;
	if(command[i] == '[')
	{
		i++;
		if(command[i] == ' ')
		{
			for(; command[i] != '\0'; i++)
			{
				if(command[i] == ']')
				{
					endBracket = false;
					if(command[i - 1] == ' ')
					{
						brackets = true;
						return true;
					}
					else
					{
						brackets = true;
						cout << "Need a space before ]\n";
						return false;
					}
				}
			}
			if(endBracket)
			{
				cout << "Missing ]\n";
				brackets = true;
				return false;
			}

		}
		else
		{
			brackets = true;
			cout << "Need a space after [\n";
			return false;
		}
	}
	return false;
}

bool run_test(char command[])
{
	bool file = false;
	bool dir = false;
	bool exist = false;

	int i = 1;
	for(; command[i] == ' '; i++){} // gets rid of spaces between [ and flag

	if(command[i] == '-')
	{
		i++;
		if(command[i] == 'f')
		{
			file = true;
			i++;
		}
		else if(command[i] == 'd')
		{
			dir = true;
			i++;
		}
		else if(command[i] == 'e' || command[i] == ' ')
		{
			exist = true;
			i++;
		}
		else
		{
			cout << "Error, invalid flag\n";
			return false;
		}
	}
	else if(command[i] != '-')
	{
		cout << "Error, missing flag\n";
		return false;
	}

	char fix_command[100];
	for(; command[i] == ' '; i++){} // to skip all the spaces between the flag and the argument
	if(command[i] != '\0')
	{
		int j = 0;
		for(; command[i] != '\0' && command[i] != ' '; i++)
		{
			fix_command[j] = command[i];
			j++;
		}
		fix_command[j] = '\0';

	}
	else
	{
		cout << "Invalid argument with flag\n";
		return false;
	}
	if(exist)
	{
		struct stat exist;
		if(stat(fix_command, &exist) == 0)
		{
			cout << "(True)\n";
			return true;
		}
		else
		{
			cout << "(False)\n";
			return false;
		}
	}
	else if(file)
	{
		struct stat file;
		stat(fix_command, &file);
		if(S_ISREG(file.st_mode) != 0)
		{
			cout << "(True)\n";
			return true;
		}
		else
		{
			cout << "(False)\n";
			return false;
		}
	}
	else if(dir)
	{
		struct stat dir;
		stat(fix_command, &dir);
		if(S_ISDIR(dir.st_mode) != 0)
		{
			cout << "(True)\n";
			return true;
		}
		else
		{
			cout << "(False)\n";
			return false;
		}
	}
	return false;
}
void run_line(char *command_line[])
{
	pid_t pid;
	int status;
	if((pid = fork()) < 0)
	{
		perror("forking failed");
	}
	else if(pid == 0)
	{
		if(execvp(*command_line,command_line) < 0)
		{
			perror("execvp failed");
			exit(1);
		}
	}
	else
	{
		while(wait(&status) != pid)
		;
	}
	return;
}
<|endoftext|>


<commit_before>#include <iostream>
#include <vector>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <string>
#include <string.h>
#include <sys/wait.h>
#include <sys/types.h>
#include <limits>

using namespace std;

void displayPrompt(){
    char *user = getlogin(); //I assign the login name to a user pointer
    if(user == NULL){
        perror("getlogin");
        exit(1);
    }

    char hostname[100]; //I allocate space for the hostname
    if(gethostname(hostname, sizeof(hostname)) == -1){ //checking for errors withostname
        perror("gethostname");
        exit(1);
    }

    cout << user << '@' << hostname << '$' << ' '; //here I output the user and hostanme to the screen.

}

int extractCommands(string &commandLine, char **cmds){
    const char* args = commandLine.c_str(); //the user input is converted to a const char* as we need it for execvp
    char* args_Mutatable = const_cast<char*>(args); //it needs to be mutable for us to tokenize it
    char *single_command;
    single_command = strtok(args_Mutatable, " ;&|"); //execute strtok with delimeters

    int numOfArgs = 0; //when you add one --> argv[1]

    while(single_command != NULL){
        //cout << single_command << endl;
        cmds[numOfArgs] = strdup(single_command); //this processes each command into the command array for execution
        cout << "at position " << numOfArgs << ": " << cmds[numOfArgs];
        cout << endl;
        single_command = strtok(NULL, " ;&|");
        numOfArgs++;
    }

    cmds[numOfArgs] = NULL;
    return numOfArgs;
}

int executeCommand(char **args){
    int pid = fork();

    if(pid == -1){
        perror("There was some error with fork()");
        exit(1);
    }
    else if(pid == 0){
        if(-1 == execvp(/*args[0]*/ *args, args)){
            perror("There was an error with execvp");
            exit(1);
        }
    }
    else if(pid > 0){
        if(-1 == wait(0)){
            perror("There was an error with wait()");
        }
    }

    return 0; //if everything goes well, return 0
}

void extractConnectors(string commandLine, char **cmds){
    vector<string> connectors;
    for(unsigned int i = 0; i < commandLine.size(); ++i){
        if(commandLine.at(i)  == ';'){
            connectors.push_back(";");
        }
        if((commandLine.at(i) == '&' && commandLine.at(i+1) == '&')){
            connectors.push_back("&&");
        }
        if((commandLine.at(i) == '|' && commandLine.at(i+1) == '|')){
            connectors.push_back("||");
        }
    }

    for(unsigned int i = 0; i < connectors.size(); ++i){
        if(connectors.at(i) == ";"){
            if(executeCommand(cmds) != 0){
                cout << "Error in parsing arguments" << endl;
            }
        }
    }

}

int main(){
    string userInput; //command line in string format
    char *cmds[10000];
    do{
        displayPrompt(); //displays current user and hostname

        getline(cin, userInput); //get's input from user and stores it in a string

        //cout << userInput << endl; //NEED TO DELETE UPON COMPLETETION

        int numArgs = extractCommands(userInput, cmds); //retrieve number of arguments by parsing the string

        if(numArgs <= 0){continue;} //if there are no arguments, simply continue to the next iteration

        /*checks if first argument is exit and quits iff it's the only argument*/
        if( (strcmp(cmds[0], "exit") == 0) && (numArgs == 1) ) { break; }

        //extractConnectors(userInput, cmds);

        if(executeCommand(cmds) != 0){
            cout << "Error in executing commands" << endl;
        }

    }while(1);

    return 0;
}

<commit_msg>hope i'm making progress..<commit_after>#include <iostream>
#include <vector>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <string>
#include <string.h>
#include <sys/wait.h>
#include <sys/types.h>
#include <limits>

using namespace std;

void displayPrompt(){
    char *user = getlogin(); //I assign the login name to a user pointer
    if(user == NULL){
        perror("getlogin");
        exit(1);
    }

    char hostname[100]; //I allocate space for the hostname
    if(gethostname(hostname, sizeof(hostname)) == -1){ //checking for errors withostname
        perror("gethostname");
        exit(1);
    }

    cout << user << '@' << hostname << '$' << ' '; //here I output the user and hostanme to the screen.

}

int extractCommands(string &commandLine, char **cmds){
    const char* args = commandLine.c_str(); //the user input is converted to a const char* as we need it for execvp
    char* args_Mutatable = const_cast<char*>(args); //it needs to be mutable for us to tokenize it
    char *single_command;
    single_command = strtok(args_Mutatable, " ;&|"); //execute strtok with delimeters

    int numOfArgs = 0; //when you add one --> argv[1]

    while(single_command != NULL){
        //cout << single_command << endl;
        cmds[numOfArgs] = strdup(single_command); //this processes each command into the command array for execution
        cout << "at position " << numOfArgs << ": " << cmds[numOfArgs];
        cout << endl;
        single_command = strtok(NULL, " ;&|");
        numOfArgs++;
    }

    cmds[numOfArgs] = NULL;
    return numOfArgs;
}

int executeCommand(int pos, char **args){
    int pid = fork();

    if(pid == -1){
        perror("There was some error with fork()");
        exit(1);
    }
    else if(pid == 0){
        if(-1 == execvp(/*args[0]*/ args[pos], args)){
            perror("There was an error with execvp");
            exit(1);
        }
    }
    else if(pid > 0){
        if(-1 == wait(0)){
            perror("There was an error with wait()");
        }
    }

    return 0; //if everything goes well, return 0
}

vector<string>  extractConnectors(string inputLine){
    vector<string> cnctors;
    for(unsigned int i = 0; i < inputLine.size(); ++i){
        if(inputLine.at(i)  == ';'){
            cnctors.push_back(";");
        }
        if((inputLine.at(i) == '&' && inputLine.at(i+1) == '&')){
            cnctors.push_back("&&");
        }
        if((inputLine.at(i) == '|' && inputLine.at(i+1) == '|')){
            cnctors.push_back("||");
        }
    }
    return cnctors;
}

int main(){
    string userInput; //command line in string format
    char *cmds[10000];
    do{
        displayPrompt(); //displays current user and hostname

        getline(cin, userInput); //get's input from user and stores it in a string

        /*gets all the delimeters and stores into a vector*/
        vector<string> connectors = extractConnectors(userInput);
        cout << "CONNECTORS: ";
        for(unsigned i = 0; i < connectors.size(); ++i){
            cout << connectors.at(i) << ' ';
        }
        cout << endl;

        //cout << userInput << endl; //NEED TO DELETE UPON COMPLETETION

        int numArgs = extractCommands(userInput, cmds); //retrieve number of arguments by parsing the string

        if(numArgs <= 0){continue;} //if there are no arguments, simply continue to the next iteration

        /*checks if first argument is exit and quits iff it's the only argument*/
        if( (strcmp(cmds[0], "exit") == 0) && (numArgs == 1) ) { break; }

        /*if(executeCommand(cmds) != 0){
            cout << "Error in executing commands" << endl;
        }*/

    }while(1);

    return 0;
}

<|endoftext|>


<commit_before>#include <silicium/async_process.hpp>
#include <silicium/http/generate_response.hpp>
#include <silicium/http/receive_request.hpp>
#include <silicium/asio/tcp_acceptor.hpp>
#include <silicium/asio/writing_observable.hpp>
#include <silicium/sink/iterator_sink.hpp>
#include <silicium/observable/spawn_coroutine.hpp>
#include <silicium/absolute_path.hpp>
#include <iostream>
#include <array>
#include <boost/program_options.hpp>

namespace
{
	void respond(boost::asio::ip::tcp::socket &client, Si::memory_range status, Si::memory_range status_text, Si::memory_range content, Si::spawn_context &yield)
	{
		std::vector<char> response;
		auto const response_sink = Si::make_container_sink(response);
		Si::http::generate_status_line(response_sink, "HTTP/1.1", status, status_text);
		Si::http::generate_header(response_sink, "Content-Length", boost::lexical_cast<Si::noexcept_string>(content.size()));
		Si::http::generate_header(response_sink, "Content-Type", "text/html");
		Si::http::finish_headers(response_sink);
		Si::append(response_sink, content);
		boost::system::error_code error = Si::asio::write(client, Si::make_memory_range(response), yield);
		if (!!error)
		{
			std::cerr << "Could not respond to " << client.remote_endpoint() << ": " << error << '\n';
		}
		else
		{
			client.shutdown(boost::asio::ip::tcp::socket::shutdown_both, error);
			if (!!error)
			{
				std::cerr << "Could not shutdown connection to " << client.remote_endpoint() << ": " << error << '\n';
			}
		}
	}

	bool handle_error(boost::system::error_code error, char const *message)
	{
		if (error)
		{
			std::cerr << message << ": " << error << '\n';
			return true;
		}
		return false;
	}

	void clone(
		std::string const &repository,
		Si::absolute_path const &repository_cache)
	{
		Si::async_process_parameters parameters;
		parameters.executable = *Si::absolute_path::create("/usr/bin/git");
		parameters.arguments.emplace_back("clone");
		parameters.arguments.emplace_back(repository.c_str());
		parameters.arguments.emplace_back(repository_cache.c_str());
		parameters.current_path = repository_cache;
		auto output = Si::make_pipe().get();
		auto input = Si::make_pipe().get();
		Si::error_or<Si::async_process> maybe_process = Si::launch_process(parameters, input.read.handle, output.write.handle, output.write.handle);
		if (handle_error(maybe_process.error(), "Could not create git process"))
		{
			return;
		}
		input.read.close();
		output.write.close();
		Si::async_process &process = maybe_process.get();
		for (;;)
		{
			std::array<char, 8192> read_buffer;
			ssize_t const read_result = read(output.read.handle, read_buffer.data(), read_buffer.size());
			if (read_result < 0)
			{
				int errno_ = errno;
				boost::system::error_code error(errno_, boost::system::get_system_category());
				std::cerr << "Reading the output of the process failed with " << error << '\n';
				break;
			}
			if (read_result == 0)
			{
				//end of output
				break;
			}
			std::cerr.write(read_buffer.data(), read_result);
		}
		int const result = process.wait_for_exit().get();
		if (result != 0)
		{
			std::cerr << "Git clone failed\n";
			return;
		}
	}

	void trigger_build(
		std::string const &repository,
		Si::absolute_path const &repository_cache)
	{
		if (handle_error(Si::create_directories(repository_cache), "Could not create repository cache directory"))
		{
			return;
		}

		if (!Si::file_exists(repository_cache / Si::relative_path(".git")))
		{
			std::cerr << "The cache does not exist. Doing an initial clone of " << repository << "\n";
			clone(repository, repository_cache);
			std::cerr << "Created initial clone of the repository\n";
		}
	}
}

int main(int argc, char **argv)
{
	std::string repository;
	std::string cache;
	boost::uint16_t listen_port = 8080;

	boost::program_options::options_description options("options");
	options.add_options()
		("help,h", "produce help message")
		("repository,r", boost::program_options::value(&repository), "the Git URI to clone from")
		("cache,c", boost::program_options::value(&cache), "the directory to use as a cache for the repository")
		("port,p", boost::program_options::value(&listen_port), "the port to listen on for HTTP requests")
		;
	boost::program_options::positional_options_description positional;
	positional.add("repository", 1);
	positional.add("cache", 1);
	boost::program_options::variables_map variables;
	try
	{
		boost::program_options::store(boost::program_options::command_line_parser(argc, argv).options(options).positional(positional).run(), variables);
		boost::program_options::notify(variables);
	}
	catch (boost::program_options::error const &ex)
	{
		std::cerr << options << '\n';
		std::cerr << ex.what() << '\n';
		return 1;
	}

	if (variables.count("help"))
	{
		std::cerr << options << '\n';
		return 0;
	}

	if (repository.empty() || cache.empty())
	{
		std::cerr << options << '\n';
		std::cerr << "Missing option\n";
		return 1;
	}

	Si::absolute_path const absolute_cache = *Si::absolute_path::create(boost::filesystem::absolute(cache));

	boost::asio::io_service io;
	Si::spawn_coroutine([&io, listen_port, &repository, &absolute_cache](Si::spawn_context yield)
	{
		auto acceptor = Si::asio::make_tcp_acceptor(io, boost::asio::ip::tcp::endpoint(boost::asio::ip::address_v4(), listen_port));
		for (;;)
		{
			std::shared_ptr<boost::asio::ip::tcp::socket> client = (*yield.get_one(Si::ref(acceptor))).get();
			assert(client);
			Si::spawn_coroutine([client = std::move(client), &repository, &absolute_cache](Si::spawn_context yield)
			{
				Si::error_or<Si::optional<Si::http::request>> const received = Si::http::receive_request(*client, yield);
				if (received.is_error())
				{
					std::cerr << "Error when receiving request from " << client->remote_endpoint() << ": " << received.error() << '\n';
					return;
				}

				Si::optional<Si::http::request> const &maybe_request = received.get();
				if (!maybe_request)
				{
					return respond(*client, Si::make_c_str_range("400"), Si::make_c_str_range("Bad Request"), Si::make_c_str_range("the server could not parse the request"), yield);
				}

				Si::http::request const &request = *maybe_request;
				if (request.method != "POST" && request.method != "GET")
				{
					return respond(*client, Si::make_c_str_range("405"), Si::make_c_str_range("Method Not Allowed"), Si::make_c_str_range("this HTTP method is not supported by this server"), yield);
				}

				if (request.path != "/")
				{
					return respond(*client, Si::make_c_str_range("404"), Si::make_c_str_range("Not Found"), Si::make_c_str_range("unknown path"), yield);
				}

				if (request.method == "POST")
				{
					trigger_build(repository, absolute_cache);
				}

				char const * const page =
					""
						""
							"<form action=\"/\" method=\"POST\">"
								"<input type=\"submit\" value=\"Trigger build\"/>"
							"</form>"
						""
					"";
				return respond(*client, Si::make_c_str_range("200"), Si::make_c_str_range("OK"), Si::make_c_str_range(page), yield);
			});
		}
	});
	io.run();
}
<commit_msg>split functions and reduce nesting<commit_after>#include <silicium/async_process.hpp>
#include <silicium/http/generate_response.hpp>
#include <silicium/http/receive_request.hpp>
#include <silicium/asio/tcp_acceptor.hpp>
#include <silicium/asio/writing_observable.hpp>
#include <silicium/sink/iterator_sink.hpp>
#include <silicium/observable/spawn_coroutine.hpp>
#include <silicium/absolute_path.hpp>
#include <iostream>
#include <array>
#include <boost/program_options.hpp>

namespace
{
	void respond(boost::asio::ip::tcp::socket &client, Si::memory_range status, Si::memory_range status_text, Si::memory_range content, Si::spawn_context &yield)
	{
		std::vector<char> response;
		auto const response_sink = Si::make_container_sink(response);
		Si::http::generate_status_line(response_sink, "HTTP/1.1", status, status_text);
		Si::http::generate_header(response_sink, "Content-Length", boost::lexical_cast<Si::noexcept_string>(content.size()));
		Si::http::generate_header(response_sink, "Content-Type", "text/html");
		Si::http::finish_headers(response_sink);
		Si::append(response_sink, content);
		boost::system::error_code error = Si::asio::write(client, Si::make_memory_range(response), yield);
		if (!!error)
		{
			std::cerr << "Could not respond to " << client.remote_endpoint() << ": " << error << '\n';
			return;
		}
		client.shutdown(boost::asio::ip::tcp::socket::shutdown_both, error);
		if (!!error)
		{
			std::cerr << "Could not shutdown connection to " << client.remote_endpoint() << ": " << error << '\n';
		}
	}

	bool handle_error(boost::system::error_code error, char const *message)
	{
		if (error)
		{
			std::cerr << message << ": " << error << '\n';
			return true;
		}
		return false;
	}

	enum class output_chunk_result
	{
		more,
		finished
	};

	output_chunk_result handle_output_chunk(Si::native_file_descriptor readable_output)
	{
		std::array<char, 8192> read_buffer;
		ssize_t const read_result = read(readable_output, read_buffer.data(), read_buffer.size());
		if (read_result < 0)
		{
			int errno_ = errno;
			boost::system::error_code error(errno_, boost::system::get_system_category());
			std::cerr << "Reading the output of the process failed with " << error << '\n';
			return output_chunk_result::finished;
		}
		if (read_result == 0)
		{
			//end of output
			return output_chunk_result::finished;
		}
		std::cerr.write(read_buffer.data(), read_result);
		return output_chunk_result::more;
	}

	void clone(
		std::string const &repository,
		Si::absolute_path const &repository_cache)
	{
		Si::async_process_parameters parameters;
		parameters.executable = *Si::absolute_path::create("/usr/bin/git");
		parameters.arguments.emplace_back("clone");
		parameters.arguments.emplace_back(repository.c_str());
		parameters.arguments.emplace_back(repository_cache.c_str());
		parameters.current_path = repository_cache;
		auto output = Si::make_pipe().get();
		auto input = Si::make_pipe().get();
		Si::error_or<Si::async_process> maybe_process = Si::launch_process(parameters, input.read.handle, output.write.handle, output.write.handle);
		if (handle_error(maybe_process.error(), "Could not create git process"))
		{
			return;
		}
		input.read.close();
		output.write.close();
		Si::async_process &process = maybe_process.get();
		for (bool more = true; more;)
		{
			switch (handle_output_chunk(output.read.handle))
			{
			case output_chunk_result::more:
				break;

			case output_chunk_result::finished:
				more = false;
				break;
			}
		}
		int const result = process.wait_for_exit().get();
		if (result != 0)
		{
			std::cerr << "Git clone failed\n";
			return;
		}
	}

	void trigger_build(
		std::string const &repository,
		Si::absolute_path const &repository_cache)
	{
		if (handle_error(Si::create_directories(repository_cache), "Could not create repository cache directory"))
		{
			return;
		}

		if (!Si::file_exists(repository_cache / Si::relative_path(".git")))
		{
			std::cerr << "The cache does not exist. Doing an initial clone of " << repository << "\n";
			clone(repository, repository_cache);
			std::cerr << "Created initial clone of the repository\n";
		}
	}

	void serve_web_client(
		boost::asio::ip::tcp::socket &client,
		std::string const &repository,
		Si::absolute_path const &repository_cache,
		Si::spawn_context &yield)
	{
		Si::error_or<Si::optional<Si::http::request>> const received = Si::http::receive_request(client, yield);
		if (received.is_error())
		{
			std::cerr << "Error when receiving request from " << client.remote_endpoint() << ": " << received.error() << '\n';
			return;
		}

		Si::optional<Si::http::request> const &maybe_request = received.get();
		if (!maybe_request)
		{
			return respond(client, Si::make_c_str_range("400"), Si::make_c_str_range("Bad Request"), Si::make_c_str_range("the server could not parse the request"), yield);
		}

		Si::http::request const &request = *maybe_request;
		if (request.method != "POST" && request.method != "GET")
		{
			return respond(client, Si::make_c_str_range("405"), Si::make_c_str_range("Method Not Allowed"), Si::make_c_str_range("this HTTP method is not supported by this server"), yield);
		}

		if (request.path != "/")
		{
			return respond(client, Si::make_c_str_range("404"), Si::make_c_str_range("Not Found"), Si::make_c_str_range("unknown path"), yield);
		}

		if (request.method == "POST")
		{
			trigger_build(repository, repository_cache);
		}

		char const * const page =
			""
				""
					"<form action=\"/\" method=\"POST\">"
						"<input type=\"submit\" value=\"Trigger build\"/>"
					"</form>"
				""
			"";
		return respond(client, Si::make_c_str_range("200"), Si::make_c_str_range("OK"), Si::make_c_str_range(page), yield);
	}

	void handle_client(
		std::shared_ptr<boost::asio::ip::tcp::socket> client,
		std::string const &repository,
		Si::absolute_path const &repository_cache)
	{
		assert(client);
		Si::spawn_coroutine([client = std::move(client), &repository, &repository_cache](Si::spawn_context yield)
		{
			serve_web_client(*client, repository, repository_cache, yield);
		});
	}
}

int main(int argc, char **argv)
{
	std::string repository;
	std::string cache;
	boost::uint16_t listen_port = 8080;

	boost::program_options::options_description options("options");
	options.add_options()
		("help,h", "produce help message")
		("repository,r", boost::program_options::value(&repository), "the Git URI to clone from")
		("cache,c", boost::program_options::value(&cache), "the directory to use as a cache for the repository")
		("port,p", boost::program_options::value(&listen_port), "the port to listen on for HTTP requests")
		;
	boost::program_options::positional_options_description positional;
	positional.add("repository", 1);
	positional.add("cache", 1);
	boost::program_options::variables_map variables;
	try
	{
		boost::program_options::store(boost::program_options::command_line_parser(argc, argv).options(options).positional(positional).run(), variables);
		boost::program_options::notify(variables);
	}
	catch (boost::program_options::error const &ex)
	{
		std::cerr << options << '\n';
		std::cerr << ex.what() << '\n';
		return 1;
	}

	if (variables.count("help"))
	{
		std::cerr << options << '\n';
		return 0;
	}

	if (repository.empty() || cache.empty())
	{
		std::cerr << options << '\n';
		std::cerr << "Missing option\n";
		return 1;
	}

	Si::absolute_path const absolute_cache = *Si::absolute_path::create(boost::filesystem::absolute(cache));

	boost::asio::io_service io;
	Si::spawn_coroutine([&io, listen_port, &repository, &absolute_cache](Si::spawn_context yield)
	{
		auto acceptor = Si::asio::make_tcp_acceptor(io, boost::asio::ip::tcp::endpoint(boost::asio::ip::address_v4(), listen_port));
		for (;;)
		{
			std::shared_ptr<boost::asio::ip::tcp::socket> client = (*yield.get_one(Si::ref(acceptor))).get();
			handle_client(std::move(client), repository, absolute_cache);
		}
	});
	io.run();
}
<|endoftext|>