<commit_before>/*
 * Copyright (C) 2012 The Android Open Source Project
 *
 * 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.
 */

#include "elf_writer.h"

#include "base/unix_file/fd_file.h"
#include "elf_file.h"
#include "oat.h"
#include "oat_file.h"

#include <llvm/Support/TargetSelect.h>

#include <mcld/Environment.h>
#include <mcld/IRBuilder.h>
#include <mcld/Linker.h>
#include <mcld/LinkerConfig.h>
#include <mcld/Module.h>
#include <mcld/Support/Path.h>
#include <mcld/Support/TargetSelect.h>

namespace art {

bool ElfWriter::Create(File* file, std::vector<uint8_t>& oat_contents, const Compiler& compiler) {
  ElfWriter elf_writer(compiler);
  return elf_writer.Write(oat_contents, file);
}

ElfWriter::ElfWriter(const Compiler& compiler) : compiler_(&compiler) {}

ElfWriter::~ElfWriter() {}

static void InitializeLLVM() {
  // TODO: this is lifted from art's compiler_llvm.cc, should be factored out
#if defined(ART_TARGET)
  llvm::InitializeNativeTarget();
  // TODO: odd that there is no InitializeNativeTargetMC?
#else
  llvm::InitializeAllTargets();
  llvm::InitializeAllTargetMCs();
#endif
}

bool ElfWriter::Write(std::vector<uint8_t>& oat_contents, File* elf_file) {

  std::string target_triple;
  std::string target_cpu;
  std::string target_attr;
  Compiler::InstructionSetToLLVMTarget(compiler_->GetInstructionSet(),
                                       target_triple,
                                       target_cpu,
                                       target_attr);

  {
    // Based on mclinker's llvm-mcld.cpp main() and LinkerTest
    //
    // TODO: LinkerTest uses mcld::Initialize(), but it does an
    // llvm::InitializeAllTargets, which we don't want. Basically we
    // want mcld::InitializeNative, but it doesn't exist yet, so we
    // inline the minimal we need here.
    InitializeLLVM();
    mcld::InitializeAllTargets();
    mcld::InitializeAllLinkers();
    mcld::InitializeAllEmulations();
    mcld::InitializeAllDiagnostics();

    UniquePtr<mcld::LinkerConfig> linker_config(new mcld::LinkerConfig(target_triple));
    CHECK(linker_config.get() != NULL);
    linker_config->setCodeGenType(mcld::LinkerConfig::DynObj);
    linker_config->options().setSOName(elf_file->GetPath());
    // TODO: Wire up mcld DiagnosticEngine to LOG?
    if (false) {
      // enables some tracing of input file processing
      linker_config->options().setTrace(true);
    }

    // Based on alone::Linker::config
    UniquePtr<mcld::Module> module(new mcld::Module(linker_config->options().soname()));
    CHECK(module.get() != NULL);
    UniquePtr<mcld::IRBuilder> ir_builder(new mcld::IRBuilder(*module.get(), *linker_config.get()));
    CHECK(ir_builder.get() != NULL);
    UniquePtr<mcld::Linker> linker(new mcld::Linker());
    CHECK(linker.get() != NULL);
    linker->config(*linker_config.get());

    // Add an artificial memory input. Based on LinkerTest.
    UniquePtr<OatFile> oat_file(OatFile::Open(oat_contents, elf_file->GetPath()));
    CHECK(oat_file.get() != NULL) << elf_file->GetPath();

    const char* oat_data_start = reinterpret_cast<const char*>(&oat_file->GetOatHeader());
    const size_t oat_data_length = oat_file->GetOatHeader().GetExecutableOffset();
    const char* oat_code_start = oat_data_start + oat_data_length;
    const size_t oat_code_length = oat_file->Size() - oat_data_length;

    // TODO: ownership of input?
    mcld::Input* input = ir_builder->CreateInput("oat contents",
                                                 mcld::sys::fs::Path("oat contents path"),
                                                 mcld::Input::Object);
    CHECK(input != NULL);

    // TODO: ownership of null_section?
    mcld::LDSection* null_section = ir_builder->CreateELFHeader(*input,
                                                                "",
                                                                mcld::LDFileFormat::Null,
                                                                llvm::ELF::SHT_NULL,
                                                                0);
    CHECK(null_section != NULL);

    // TODO: we should split readonly data from readonly executable
    // code like .oat does.  We need to control section layout with
    // linker script like functionality to guarantee references
    // between sections maintain relative position which isn't
    // possible right now with the mclinker APIs.
    CHECK(oat_code_start);

    // TODO: ownership of text_section?
    // we need to ensure that oatdata is page aligned so when we
    // fixup the segment load addresses, they remain page aligned.
    mcld::LDSection* text_section = ir_builder->CreateELFHeader(*input,
                                                                ".text",
                                                                llvm::ELF::SHT_PROGBITS,
                                                                llvm::ELF::SHF_EXECINSTR
                                                                | llvm::ELF::SHF_ALLOC,
                                                                kPageSize);
    CHECK(text_section != NULL);

    mcld::SectionData* text_section_data = ir_builder->CreateSectionData(*text_section);
    CHECK(text_section_data != NULL);

    // TODO: why does IRBuilder::CreateRegion take a non-const pointer?
    mcld::Fragment* text_fragment = ir_builder->CreateRegion(const_cast<char*>(oat_data_start),
                                                             oat_file->Size());
    CHECK(text_fragment != NULL);
    ir_builder->AppendFragment(*text_fragment, *text_section_data);

    ir_builder->AddSymbol(*input,
                          "oatdata",
                          mcld::ResolveInfo::Object,
                          mcld::ResolveInfo::Define,
                          mcld::ResolveInfo::Global,
                          oat_data_length,  // size
                          0,                // offset
                          text_section);

    ir_builder->AddSymbol(*input,
                          "oatexec",
                          mcld::ResolveInfo::Function,
                          mcld::ResolveInfo::Define,
                          mcld::ResolveInfo::Global,
                          oat_code_length,  // size
                          oat_data_length,  // offset
                          text_section);

    ir_builder->AddSymbol(*input,
                          "oatlastword",
                          mcld::ResolveInfo::Object,
                          mcld::ResolveInfo::Define,
                          mcld::ResolveInfo::Global,
                          0,                // size
                          // subtract a word so symbol is within section
                          (oat_data_length + oat_code_length) - sizeof(uint32_t),  // offset
                          text_section);

    // link inputs
    if (!linker->link(*module.get(), *ir_builder.get())) {
      LOG(ERROR) << "problem linking " << elf_file->GetPath();
      return false;
    }

    // emited linked output
    if (!linker->emit(elf_file->Fd())) {
      LOG(ERROR) << "problem emitting " << elf_file->GetPath();
      return false;
    }
    // TODO: mcld::Linker::emit closed the file descriptor. It probably shouldn't.
    // For now, close our File to match.
    elf_file->Close();
    mcld::Finalize();
  }
  LOG(INFO) << "ELF file written successfully: " << elf_file->GetPath();
  return true;
}

bool ElfWriter::Fixup(File* file, uintptr_t oat_data_begin) {
  UniquePtr<ElfFile> elf_file(ElfFile::Open(file, true, false));
  CHECK(elf_file.get() != NULL);

  // Lookup "oatdata" symbol address.
  llvm::ELF::Elf32_Addr oatdata_address = elf_file->FindSymbolAddress(llvm::ELF::SHT_DYNSYM,
                                                                      "oatdata");
  CHECK_NE(0U, oatdata_address);
  llvm::ELF::Elf32_Off base_address = oat_data_begin - oatdata_address;

  if (!FixupDynamic(*elf_file.get(), base_address)) {
      LOG(WARNING) << "Failed fo fixup .dynamic in " << file->GetPath();
      return false;
  }
  if (!FixupSectionHeaders(*elf_file.get(), base_address)) {
      LOG(WARNING) << "Failed fo fixup section headers in " << file->GetPath();
      return false;
  }
  if (!FixupProgramHeaders(*elf_file.get(), base_address)) {
      LOG(WARNING) << "Failed fo fixup program headers in " << file->GetPath();
      return false;
  }
  if (!FixupSymbols(*elf_file.get(), base_address, true)) {
      LOG(WARNING) << "Failed fo fixup .dynsym in " << file->GetPath();
      return false;
  }
  if (!FixupSymbols(*elf_file.get(), base_address, false)) {
      LOG(WARNING) << "Failed fo fixup .symtab in " << file->GetPath();
      return false;
  }
  return true;
}

bool ElfWriter::FixupDynamic(ElfFile& elf_file, uintptr_t base_address) {
  // TODO: C++0x auto.
  for (llvm::ELF::Elf32_Word i = 0; i < elf_file.GetDynamicNum(); i++) {
    llvm::ELF::Elf32_Dyn& elf_dyn = elf_file.GetDynamic(i);
    bool elf_dyn_needs_fixup = false;
    // case 1: if Elf32_Dyn.d_tag implies Elf32_Dyn.d_un contains an address in d_ptr
    switch (elf_dyn.d_tag) {
      case llvm::ELF::DT_PLTGOT:
      case llvm::ELF::DT_HASH:
      case llvm::ELF::DT_STRTAB:
      case llvm::ELF::DT_SYMTAB:
      case llvm::ELF::DT_RELA:
      case llvm::ELF::DT_INIT:
      case llvm::ELF::DT_FINI:
      case llvm::ELF::DT_REL:
      case llvm::ELF::DT_DEBUG:
      case llvm::ELF::DT_JMPREL: {
          elf_dyn_needs_fixup = true;
        break;
      }
      default: {
        // case 2: if d_tag is even and greater than  > DT_ENCODING
        if ((elf_dyn.d_tag > llvm::ELF::DT_ENCODING) && ((elf_dyn.d_tag % 2) == 0)) {
          elf_dyn_needs_fixup = true;
        }
        break;
      }
    }
    if (elf_dyn_needs_fixup) {
        uint32_t d_ptr = elf_dyn.d_un.d_ptr;
        d_ptr += base_address;
        elf_dyn.d_un.d_ptr = d_ptr;
    }
  }
  return true;
}

bool ElfWriter::FixupSectionHeaders(ElfFile& elf_file, uintptr_t base_address) {
  for (llvm::ELF::Elf32_Word i = 0; i < elf_file.GetSectionHeaderNum(); i++) {
    llvm::ELF::Elf32_Shdr& sh = elf_file.GetSectionHeader(i);
    // 0 implies that the section will not exist in the memory of the process
    if (sh.sh_addr == 0) {
      continue;
    }
    sh.sh_addr += base_address;
  }
  return true;
}

bool ElfWriter::FixupProgramHeaders(ElfFile& elf_file, uintptr_t base_address) {
  // TODO: ELFObjectFile doesn't have give to Elf32_Phdr, so we do that ourselves for now.
  for (llvm::ELF::Elf32_Word i = 0; i < elf_file.GetProgramHeaderNum(); i++) {
    llvm::ELF::Elf32_Phdr& ph = elf_file.GetProgramHeader(i);
    CHECK_EQ(ph.p_vaddr, ph.p_paddr) << elf_file.GetFile().GetPath() << " i=" << i;
    CHECK((ph.p_align == 0) || (0 == ((ph.p_vaddr - ph.p_offset) & (ph.p_align - 1))));
    ph.p_vaddr += base_address;
    ph.p_paddr += base_address;
    CHECK((ph.p_align == 0) || (0 == ((ph.p_vaddr - ph.p_offset) & (ph.p_align - 1))));
  }
  return true;
}

bool ElfWriter::FixupSymbols(ElfFile& elf_file, uintptr_t base_address, bool dynamic) {
  llvm::ELF::Elf32_Word section_type = dynamic ? llvm::ELF::SHT_DYNSYM : llvm::ELF::SHT_SYMTAB;
  // TODO: Unfortunate ELFObjectFile has protected symbol access, so use ElfFile
  llvm::ELF::Elf32_Shdr* symbol_section = elf_file.FindSectionByType(section_type);
  CHECK(symbol_section != NULL) << elf_file.GetFile().GetPath();
  for (uint32_t i = 0; i < elf_file.GetSymbolNum(*symbol_section); i++) {
    llvm::ELF::Elf32_Sym& symbol = elf_file.GetSymbol(section_type, i);
    if (symbol.st_value != 0) {
      symbol.st_value += base_address;
    }
  }
  return true;
}

void ElfWriter::GetOatElfInformation(File* file,
                                     size_t& oat_loaded_size,
                                     size_t& oat_data_offset) {
  UniquePtr<ElfFile> elf_file(ElfFile::Open(file, false, false));
  CHECK(elf_file.get() != NULL);

  oat_loaded_size = elf_file->GetLoadedSize();
  CHECK_NE(0U, oat_loaded_size);
  oat_data_offset = elf_file->FindSymbolAddress(llvm::ELF::SHT_DYNSYM, "oatdata");
  CHECK_NE(0U, oat_data_offset);
}

}  // namespace art
<commit_msg>Fix MIPS to use standard kPageSize=0x1000 section alignment for ELF sections<commit_after>/*
 * Copyright (C) 2012 The Android Open Source Project
 *
 * 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.
 */

#include "elf_writer.h"

#include "base/unix_file/fd_file.h"
#include "elf_file.h"
#include "oat.h"
#include "oat_file.h"

#include <llvm/Support/TargetSelect.h>

#include <mcld/Environment.h>
#include <mcld/IRBuilder.h>
#include <mcld/Linker.h>
#include <mcld/LinkerConfig.h>
#include <mcld/MC/ZOption.h>
#include <mcld/Module.h>
#include <mcld/Support/Path.h>
#include <mcld/Support/TargetSelect.h>

namespace art {

bool ElfWriter::Create(File* file, std::vector<uint8_t>& oat_contents, const Compiler& compiler) {
  ElfWriter elf_writer(compiler);
  return elf_writer.Write(oat_contents, file);
}

ElfWriter::ElfWriter(const Compiler& compiler) : compiler_(&compiler) {}

ElfWriter::~ElfWriter() {}

static void InitializeLLVM() {
  // TODO: this is lifted from art's compiler_llvm.cc, should be factored out
#if defined(ART_TARGET)
  llvm::InitializeNativeTarget();
  // TODO: odd that there is no InitializeNativeTargetMC?
#else
  llvm::InitializeAllTargets();
  llvm::InitializeAllTargetMCs();
#endif
}

bool ElfWriter::Write(std::vector<uint8_t>& oat_contents, File* elf_file) {

  std::string target_triple;
  std::string target_cpu;
  std::string target_attr;
  Compiler::InstructionSetToLLVMTarget(compiler_->GetInstructionSet(),
                                       target_triple,
                                       target_cpu,
                                       target_attr);

  {
    // Based on mclinker's llvm-mcld.cpp main() and LinkerTest
    //
    // TODO: LinkerTest uses mcld::Initialize(), but it does an
    // llvm::InitializeAllTargets, which we don't want. Basically we
    // want mcld::InitializeNative, but it doesn't exist yet, so we
    // inline the minimal we need here.
    InitializeLLVM();
    mcld::InitializeAllTargets();
    mcld::InitializeAllLinkers();
    mcld::InitializeAllEmulations();
    mcld::InitializeAllDiagnostics();

    UniquePtr<mcld::LinkerConfig> linker_config(new mcld::LinkerConfig(target_triple));
    CHECK(linker_config.get() != NULL);
    linker_config->setCodeGenType(mcld::LinkerConfig::DynObj);
    if (compiler_->GetInstructionSet() == kMips) {
      // MCLinker defaults MIPS section alignment to 0x10000, not 0x1000
      mcld::ZOption z_option;
      z_option.setKind(mcld::ZOption::MaxPageSize);
      z_option.setPageSize(kPageSize);
      linker_config->options().addZOption(z_option);
    }
    linker_config->options().setSOName(elf_file->GetPath());
    // TODO: Wire up mcld DiagnosticEngine to LOG?
    if (false) {
      // enables some tracing of input file processing
      linker_config->options().setTrace(true);
    }

    // Based on alone::Linker::config
    UniquePtr<mcld::Module> module(new mcld::Module(linker_config->options().soname()));
    CHECK(module.get() != NULL);
    UniquePtr<mcld::IRBuilder> ir_builder(new mcld::IRBuilder(*module.get(), *linker_config.get()));
    CHECK(ir_builder.get() != NULL);
    UniquePtr<mcld::Linker> linker(new mcld::Linker());
    CHECK(linker.get() != NULL);
    linker->config(*linker_config.get());

    // Add an artificial memory input. Based on LinkerTest.
    UniquePtr<OatFile> oat_file(OatFile::Open(oat_contents, elf_file->GetPath()));
    CHECK(oat_file.get() != NULL) << elf_file->GetPath();

    const char* oat_data_start = reinterpret_cast<const char*>(&oat_file->GetOatHeader());
    const size_t oat_data_length = oat_file->GetOatHeader().GetExecutableOffset();
    const char* oat_code_start = oat_data_start + oat_data_length;
    const size_t oat_code_length = oat_file->Size() - oat_data_length;

    // TODO: ownership of input?
    mcld::Input* input = ir_builder->CreateInput("oat contents",
                                                 mcld::sys::fs::Path("oat contents path"),
                                                 mcld::Input::Object);
    CHECK(input != NULL);

    // TODO: ownership of null_section?
    mcld::LDSection* null_section = ir_builder->CreateELFHeader(*input,
                                                                "",
                                                                mcld::LDFileFormat::Null,
                                                                llvm::ELF::SHT_NULL,
                                                                0);
    CHECK(null_section != NULL);

    // TODO: we should split readonly data from readonly executable
    // code like .oat does.  We need to control section layout with
    // linker script like functionality to guarantee references
    // between sections maintain relative position which isn't
    // possible right now with the mclinker APIs.
    CHECK(oat_code_start);

    // we need to ensure that oatdata is page aligned so when we
    // fixup the segment load addresses, they remain page aligned.
    uint32_t alignment = kPageSize;

    // TODO: ownership of text_section?
    mcld::LDSection* text_section = ir_builder->CreateELFHeader(*input,
                                                                ".text",
                                                                llvm::ELF::SHT_PROGBITS,
                                                                llvm::ELF::SHF_EXECINSTR
                                                                | llvm::ELF::SHF_ALLOC,
                                                                alignment);
    CHECK(text_section != NULL);

    mcld::SectionData* text_section_data = ir_builder->CreateSectionData(*text_section);
    CHECK(text_section_data != NULL);

    // TODO: why does IRBuilder::CreateRegion take a non-const pointer?
    mcld::Fragment* text_fragment = ir_builder->CreateRegion(const_cast<char*>(oat_data_start),
                                                             oat_file->Size());
    CHECK(text_fragment != NULL);
    ir_builder->AppendFragment(*text_fragment, *text_section_data);

    ir_builder->AddSymbol(*input,
                          "oatdata",
                          mcld::ResolveInfo::Object,
                          mcld::ResolveInfo::Define,
                          mcld::ResolveInfo::Global,
                          oat_data_length,  // size
                          0,                // offset
                          text_section);

    ir_builder->AddSymbol(*input,
                          "oatexec",
                          mcld::ResolveInfo::Function,
                          mcld::ResolveInfo::Define,
                          mcld::ResolveInfo::Global,
                          oat_code_length,  // size
                          oat_data_length,  // offset
                          text_section);

    ir_builder->AddSymbol(*input,
                          "oatlastword",
                          mcld::ResolveInfo::Object,
                          mcld::ResolveInfo::Define,
                          mcld::ResolveInfo::Global,
                          0,                // size
                          // subtract a word so symbol is within section
                          (oat_data_length + oat_code_length) - sizeof(uint32_t),  // offset
                          text_section);

    // link inputs
    if (!linker->link(*module.get(), *ir_builder.get())) {
      LOG(ERROR) << "problem linking " << elf_file->GetPath();
      return false;
    }

    // emited linked output
    if (!linker->emit(elf_file->Fd())) {
      LOG(ERROR) << "problem emitting " << elf_file->GetPath();
      return false;
    }
    // TODO: mcld::Linker::emit closed the file descriptor. It probably shouldn't.
    // For now, close our File to match.
    elf_file->Close();
    mcld::Finalize();
  }
  LOG(INFO) << "ELF file written successfully: " << elf_file->GetPath();
  return true;
}

bool ElfWriter::Fixup(File* file, uintptr_t oat_data_begin) {
  UniquePtr<ElfFile> elf_file(ElfFile::Open(file, true, false));
  CHECK(elf_file.get() != NULL);

  // Lookup "oatdata" symbol address.
  llvm::ELF::Elf32_Addr oatdata_address = elf_file->FindSymbolAddress(llvm::ELF::SHT_DYNSYM,
                                                                      "oatdata");
  CHECK_NE(0U, oatdata_address);
  llvm::ELF::Elf32_Off base_address = oat_data_begin - oatdata_address;

  if (!FixupDynamic(*elf_file.get(), base_address)) {
      LOG(WARNING) << "Failed fo fixup .dynamic in " << file->GetPath();
      return false;
  }
  if (!FixupSectionHeaders(*elf_file.get(), base_address)) {
      LOG(WARNING) << "Failed fo fixup section headers in " << file->GetPath();
      return false;
  }
  if (!FixupProgramHeaders(*elf_file.get(), base_address)) {
      LOG(WARNING) << "Failed fo fixup program headers in " << file->GetPath();
      return false;
  }
  if (!FixupSymbols(*elf_file.get(), base_address, true)) {
      LOG(WARNING) << "Failed fo fixup .dynsym in " << file->GetPath();
      return false;
  }
  if (!FixupSymbols(*elf_file.get(), base_address, false)) {
      LOG(WARNING) << "Failed fo fixup .symtab in " << file->GetPath();
      return false;
  }
  return true;
}

bool ElfWriter::FixupDynamic(ElfFile& elf_file, uintptr_t base_address) {
  // TODO: C++0x auto.
  for (llvm::ELF::Elf32_Word i = 0; i < elf_file.GetDynamicNum(); i++) {
    llvm::ELF::Elf32_Dyn& elf_dyn = elf_file.GetDynamic(i);
    bool elf_dyn_needs_fixup = false;
    // case 1: if Elf32_Dyn.d_tag implies Elf32_Dyn.d_un contains an address in d_ptr
    switch (elf_dyn.d_tag) {
      case llvm::ELF::DT_PLTGOT:
      case llvm::ELF::DT_HASH:
      case llvm::ELF::DT_STRTAB:
      case llvm::ELF::DT_SYMTAB:
      case llvm::ELF::DT_RELA:
      case llvm::ELF::DT_INIT:
      case llvm::ELF::DT_FINI:
      case llvm::ELF::DT_REL:
      case llvm::ELF::DT_DEBUG:
      case llvm::ELF::DT_JMPREL: {
          elf_dyn_needs_fixup = true;
        break;
      }
      default: {
        // case 2: if d_tag is even and greater than  > DT_ENCODING
        if ((elf_dyn.d_tag > llvm::ELF::DT_ENCODING) && ((elf_dyn.d_tag % 2) == 0)) {
          elf_dyn_needs_fixup = true;
        }
        break;
      }
    }
    if (elf_dyn_needs_fixup) {
        uint32_t d_ptr = elf_dyn.d_un.d_ptr;
        d_ptr += base_address;
        elf_dyn.d_un.d_ptr = d_ptr;
    }
  }
  return true;
}

bool ElfWriter::FixupSectionHeaders(ElfFile& elf_file, uintptr_t base_address) {
  for (llvm::ELF::Elf32_Word i = 0; i < elf_file.GetSectionHeaderNum(); i++) {
    llvm::ELF::Elf32_Shdr& sh = elf_file.GetSectionHeader(i);
    // 0 implies that the section will not exist in the memory of the process
    if (sh.sh_addr == 0) {
      continue;
    }
    sh.sh_addr += base_address;
  }
  return true;
}

bool ElfWriter::FixupProgramHeaders(ElfFile& elf_file, uintptr_t base_address) {
  // TODO: ELFObjectFile doesn't have give to Elf32_Phdr, so we do that ourselves for now.
  for (llvm::ELF::Elf32_Word i = 0; i < elf_file.GetProgramHeaderNum(); i++) {
    llvm::ELF::Elf32_Phdr& ph = elf_file.GetProgramHeader(i);
    CHECK_EQ(ph.p_vaddr, ph.p_paddr) << elf_file.GetFile().GetPath() << " i=" << i;
    CHECK((ph.p_align == 0) || (0 == ((ph.p_vaddr - ph.p_offset) & (ph.p_align - 1))));
    ph.p_vaddr += base_address;
    ph.p_paddr += base_address;
    CHECK((ph.p_align == 0) || (0 == ((ph.p_vaddr - ph.p_offset) & (ph.p_align - 1))));
  }
  return true;
}

bool ElfWriter::FixupSymbols(ElfFile& elf_file, uintptr_t base_address, bool dynamic) {
  llvm::ELF::Elf32_Word section_type = dynamic ? llvm::ELF::SHT_DYNSYM : llvm::ELF::SHT_SYMTAB;
  // TODO: Unfortunate ELFObjectFile has protected symbol access, so use ElfFile
  llvm::ELF::Elf32_Shdr* symbol_section = elf_file.FindSectionByType(section_type);
  CHECK(symbol_section != NULL) << elf_file.GetFile().GetPath();
  for (uint32_t i = 0; i < elf_file.GetSymbolNum(*symbol_section); i++) {
    llvm::ELF::Elf32_Sym& symbol = elf_file.GetSymbol(section_type, i);
    if (symbol.st_value != 0) {
      symbol.st_value += base_address;
    }
  }
  return true;
}

void ElfWriter::GetOatElfInformation(File* file,
                                     size_t& oat_loaded_size,
                                     size_t& oat_data_offset) {
  UniquePtr<ElfFile> elf_file(ElfFile::Open(file, false, false));
  CHECK(elf_file.get() != NULL);

  oat_loaded_size = elf_file->GetLoadedSize();
  CHECK_NE(0U, oat_loaded_size);
  oat_data_offset = elf_file->FindSymbolAddress(llvm::ELF::SHT_DYNSYM, "oatdata");
  CHECK_NE(0U, oat_data_offset);
}

}  // namespace art
<|endoftext|>


<commit_before>#include "medDatabaseDataSource.h"

#include <medDataManager.h>

#include <medDatabaseSearchPanel.h>
#include <medDatabaseView.h>
#include <medDatabasePreview.h>

#include <medDatabaseProxyModel.h>
#include <medDatabaseModel.h>
#include <medDatabaseExporter.h>

#include <medToolBoxActions.h>

class medDatabaseDataSourcePrivate
{
public:
    QWidget* database_widget;
    medDatabasePreview *preview;
    medDatabaseModel *model;
    medDatabaseView *view;
    medDatabaseProxyModel *proxy;

    QList<medToolBox*> toolboxes;
    medDatabaseSearchPanel *searchPanel;
    medToolBoxActions* actionsTb;

};

medDatabaseDataSource::medDatabaseDataSource( QWidget* parent /*= 0*/ ): medAbstractDataSource(parent), d(new medDatabaseDataSourcePrivate)
{
    d->database_widget = new QWidget(parent);

    d->model = new medDatabaseModel (this);
    d->proxy = new medDatabaseProxyModel(this);

    d->proxy->setSourceModel(d->model);

    d->preview = new medDatabasePreview(d->database_widget);
    d->view    = new medDatabaseView(d->database_widget);
    d->view->setModel(d->proxy);

    QVBoxLayout *database_layout = new QVBoxLayout(d->database_widget);
    database_layout->setContentsMargins(0, 0, 0, 0);
    database_layout->setSpacing(0);
    database_layout->addWidget(d->view);
    database_layout->addWidget(d->preview);

    d->actionsTb = new medToolBoxActions(parent);
    d->toolboxes.push_back(d->actionsTb);

    d->searchPanel = new medDatabaseSearchPanel(parent);
    d->searchPanel->setColumnNames(d->model->columnNames());
    d->toolboxes.push_back(d->searchPanel);

    connect(d->view, SIGNAL(patientClicked(const medDataIndex&)), d->preview, SLOT(onPatientClicked(const medDataIndex&)));
    connect(d->view, SIGNAL(seriesClicked(const medDataIndex&)), d->preview, SLOT(onSeriesClicked(const medDataIndex&)));
    connect(d->view, SIGNAL(patientClicked(const medDataIndex&)), d->actionsTb, SLOT(patientSelected(const medDataIndex&)));
    connect(d->view, SIGNAL(seriesClicked(const medDataIndex&)), d->actionsTb, SLOT(seriesSelected(const medDataIndex&)));
    connect(d->view, SIGNAL(noPatientOrSeriesSelected()), d->actionsTb, SLOT(noPatientOrSeriesSelected()));
    connect(d->view, SIGNAL(open(const medDataIndex&)), this, SIGNAL(open(const medDataIndex&)));
    connect(d->view, SIGNAL(exportData(const medDataIndex&)), this, SIGNAL(exportData(const medDataIndex&)));
    connect(d->view, SIGNAL(dataRemoved(const medDataIndex&)), this, SIGNAL(dataRemoved(const medDataIndex&)));

    connect (medDataManager::instance(), SIGNAL(dataRemoved()), this, SLOT(update()));
    connect (medDataManager::instance(), SIGNAL(dataAdded()), this, SLOT(update()));

    connect(d->searchPanel, SIGNAL(filter(const QString &, int)),this, SLOT(onFilter(const QString &, int)));

    connect(d->actionsTb, SIGNAL(removeClicked()), d->view, SLOT(onRemoveSelectedItemRequested()));
    connect(d->actionsTb, SIGNAL(exportClicked()), d->view, SLOT(onExportSelectedItemRequested()));
    connect(d->actionsTb, SIGNAL(viewClicked()), d->view, SLOT(onViewSelectedItemRequested()));
    connect(d->actionsTb, SIGNAL(saveClicked()), d->view, SLOT(onSaveSelectedItemRequested()));
}

medDatabaseDataSource::~medDatabaseDataSource()
{
    delete d;
    d = NULL;
}

QWidget* medDatabaseDataSource::mainViewWidget()
{
    return d->database_widget;
}

QWidget* medDatabaseDataSource::sourceSelectorWidget()
{
    return new QWidget();
}

QString medDatabaseDataSource::tabName()
{
    return tr("Database");
}

QList<medToolBox*> medDatabaseDataSource::getToolboxes()
{
    return d->toolboxes;
}

QString medDatabaseDataSource::description(void) const
{
	return tr("Browse the medInria Database");
}

void medDatabaseDataSource::update(const medDataIndex &index)
{
    Q_UNUSED(index);
    d->preview->reset();
    d->preview->init();
    d->preview->update();
}

void medDatabaseDataSource::onFilter( const QString &text, int column )
{
    // adding or overriding filter on column
    d->proxy->setFilterRegExpWithColumn(QRegExp(text, Qt::CaseInsensitive, QRegExp::Wildcard), column);
}

void medDatabaseDataSource::onOpeningFailed(const medDataIndex& index)
{
    d->view->onOpeningFailed(index);
}
<commit_msg>Remove useless connections in medDataSourceDataBase<commit_after>#include "medDatabaseDataSource.h"

#include <medDataManager.h>

#include <medDatabaseSearchPanel.h>
#include <medDatabaseView.h>
#include <medDatabasePreview.h>

#include <medDatabaseProxyModel.h>
#include <medDatabaseModel.h>
#include <medDatabaseExporter.h>

#include <medToolBoxActions.h>

class medDatabaseDataSourcePrivate
{
public:
    QWidget* database_widget;
    medDatabasePreview *preview;
    medDatabaseModel *model;
    medDatabaseView *view;
    medDatabaseProxyModel *proxy;

    QList<medToolBox*> toolboxes;
    medDatabaseSearchPanel *searchPanel;
    medToolBoxActions* actionsTb;

};

medDatabaseDataSource::medDatabaseDataSource( QWidget* parent /*= 0*/ ): medAbstractDataSource(parent), d(new medDatabaseDataSourcePrivate)
{
    d->database_widget = new QWidget(parent);

    d->model = new medDatabaseModel (this);
    d->proxy = new medDatabaseProxyModel(this);

    d->proxy->setSourceModel(d->model);

    d->preview = new medDatabasePreview(d->database_widget);
    d->view    = new medDatabaseView(d->database_widget);
    d->view->setModel(d->proxy);

    QVBoxLayout *database_layout = new QVBoxLayout(d->database_widget);
    database_layout->setContentsMargins(0, 0, 0, 0);
    database_layout->setSpacing(0);
    database_layout->addWidget(d->view);
    database_layout->addWidget(d->preview);

    d->actionsTb = new medToolBoxActions(parent);
    d->toolboxes.push_back(d->actionsTb);

    d->searchPanel = new medDatabaseSearchPanel(parent);
    d->searchPanel->setColumnNames(d->model->columnNames());
    d->toolboxes.push_back(d->searchPanel);

    connect(d->view, SIGNAL(patientClicked(const medDataIndex&)), d->preview, SLOT(onPatientClicked(const medDataIndex&)));
    connect(d->view, SIGNAL(seriesClicked(const medDataIndex&)), d->preview, SLOT(onSeriesClicked(const medDataIndex&)));
    connect(d->view, SIGNAL(patientClicked(const medDataIndex&)), d->actionsTb, SLOT(patientSelected(const medDataIndex&)));
    connect(d->view, SIGNAL(seriesClicked(const medDataIndex&)), d->actionsTb, SLOT(seriesSelected(const medDataIndex&)));
    connect(d->view, SIGNAL(noPatientOrSeriesSelected()), d->actionsTb, SLOT(noPatientOrSeriesSelected()));
    connect(d->view, SIGNAL(open(const medDataIndex&)), this, SIGNAL(open(const medDataIndex&)));
    connect(d->view, SIGNAL(exportData(const medDataIndex&)), this, SIGNAL(exportData(const medDataIndex&)));
    connect(d->view, SIGNAL(dataRemoved(const medDataIndex&)), this, SIGNAL(dataRemoved(const medDataIndex&)));

    connect(d->searchPanel, SIGNAL(filter(const QString &, int)),this, SLOT(onFilter(const QString &, int)));

    connect(d->actionsTb, SIGNAL(removeClicked()), d->view, SLOT(onRemoveSelectedItemRequested()));
    connect(d->actionsTb, SIGNAL(exportClicked()), d->view, SLOT(onExportSelectedItemRequested()));
    connect(d->actionsTb, SIGNAL(viewClicked()), d->view, SLOT(onViewSelectedItemRequested()));
    connect(d->actionsTb, SIGNAL(saveClicked()), d->view, SLOT(onSaveSelectedItemRequested()));
}

medDatabaseDataSource::~medDatabaseDataSource()
{
    delete d;
    d = NULL;
}

QWidget* medDatabaseDataSource::mainViewWidget()
{
    return d->database_widget;
}

QWidget* medDatabaseDataSource::sourceSelectorWidget()
{
    return new QWidget();
}

QString medDatabaseDataSource::tabName()
{
    return tr("Database");
}

QList<medToolBox*> medDatabaseDataSource::getToolboxes()
{
    return d->toolboxes;
}

QString medDatabaseDataSource::description(void) const
{
	return tr("Browse the medInria Database");
}

void medDatabaseDataSource::update(const medDataIndex &index)
{
    Q_UNUSED(index);
    d->preview->reset();
    d->preview->init();
    d->preview->update();
}

void medDatabaseDataSource::onFilter( const QString &text, int column )
{
    // adding or overriding filter on column
    d->proxy->setFilterRegExpWithColumn(QRegExp(text, Qt::CaseInsensitive, QRegExp::Wildcard), column);
}

void medDatabaseDataSource::onOpeningFailed(const medDataIndex& index)
{
    d->view->onOpeningFailed(index);
}
<|endoftext|>


<commit_before>#include "fanfoukit.h"
#include "httprequest.h"

#include <QPair>
#include <QNetworkAccessManager>
#include <QNetworkReply>
#include <QRegExp>
#include <QStringList>
#include <QFile>
#include <QDir>
#include <QDateTime>
#include <QSettings>
#include <QCryptographicHash>
#include <QUuid>
#include <QtFeedback/QFeedbackHapticsEffect>
#include <QtFeedback/QFeedbackActuator>
#include <QFileInfo>
#include <QTextDocument>
#include <QDeclarativeItem>
#include <QPainter>
#include <QDesktopServices>
#include <QCoreApplication>
#include <QDebug>

#define ACCESS_TOKEN_URL "http://fanfou.com/oauth/access_token"
#define SPLASH_URL "http://api.zccrs.com/splash/meefan/n9/"
#define SPLASH_PATH QDesktopServices::storageLocation(QDesktopServices::CacheLocation) + QDir::separator() +  "splash" + QDir::separator()

FanfouKit::FanfouKit(QObject *parent)
    : OAuth(parent)
    , m_accessManager(new QNetworkAccessManager(this))
    , m_httpRequest(new HttpRequest(m_accessManager, this))
    , m_settings(new QSettings(this))
    , m_rumble(0)
{
    updateSplash();
}

FanfouKit::FanfouKit(QNetworkAccessManager *manager, QObject *parent)
    : OAuth(parent)
    , m_accessManager(manager)
    , m_httpRequest(new HttpRequest(m_accessManager, this))
    , m_settings(new QSettings(this))
    , m_rumble(0)
{
    updateSplash();
}

FanfouKit::FanfouKit(const QByteArray &consumerKey, const QByteArray &consumerSecret, QObject *parent)
    : OAuth(consumerKey, consumerSecret, parent)
    , m_accessManager(new QNetworkAccessManager(this))
    , m_httpRequest(new HttpRequest(m_accessManager, this))
    , m_settings(new QSettings(this))
    , m_rumble(0)
{
    updateSplash();
}

HttpRequest *FanfouKit::httpRequest() const
{
    return m_httpRequest;
}

QByteArray FanfouKit::readFile(const QString &filePath) const
{
    QFile file(filePath);

    if (file.open(QIODevice::ReadOnly)) {
        return file.readAll();
    }

    return QByteArray();
}

QString FanfouKit::fileName(const QString &filePath) const
{
    QFileInfo info(filePath);

    return info.fileName();
}

QString FanfouKit::fromUtf8(const QByteArray &data) const
{
    return QString::fromUtf8(data);
}

QByteArray FanfouKit::toUtf8(const QString &string) const
{
    return string.toUtf8();
}

QString FanfouKit::datetimeFormatFromISO(const QString &dt) const
{
    return QDateTime::fromString(dt, Qt::ISODate).toLocalTime().toString("yyyy-MM-dd hh:mm");
}

void FanfouKit::setSettingValue(const QString &name, const QVariant &value)
{
    m_settings->setValue(name, value);
}

QVariant FanfouKit::settingValue(const QString &name, const QVariant &defaultValue) const
{
    return m_settings->value(name, defaultValue);
}

void FanfouKit::clearSettings()
{
    m_settings->clear();
}

QByteArray FanfouKit::objectClassName(QObject *object) const
{
    return object->metaObject()->className();
}

QString FanfouKit::createUuid() const
{
    return QUuid::createUuid().toString();
}

void FanfouKit::vibrationDevice(qreal intensity, int duration)
{
    ensureVibraRumble();

    m_rumble->setIntensity(intensity);
    m_rumble->setDuration(duration);
    m_rumble->start();
}

QString FanfouKit::stringSimplified(const QString &string) const
{
    return string.simplified();
}

QByteArray FanfouKit::byteArrayJoin(const QByteArray &a1, const QByteArray &a2,
                                    const QByteArray &a3, const QByteArray &a4,
                                    const QByteArray &a5, const QByteArray &a6) const
{
    return a1 + a2 + a3 + a4 + a5 + a6;
}

int FanfouKit::byteArraySize(const QByteArray &data) const
{
    return data.size();
}

QString FanfouKit::toPlainText(const QString &text) const
{
    QTextDocument document;

    document.setHtml(text);

    return document.toPlainText();
}

bool FanfouKit::saveImage(const QScriptValue object, const QString &toPath) const
{
    if (QDeclarativeItem *item = qobject_cast<QDeclarativeItem*>(object.toQObject())) {
        QImage image(item->implicitWidth(), item->implicitHeight(), QImage::Format_ARGB32_Premultiplied);
        QPainter p(&image);

        item->paint(&p, 0, 0);

        if (image.isNull()) {
            qWarning("FanfouKit::saveImage: Image data is null");

            return false;
        }

        return image.save(toPath);
    }

    qWarning("FanfouKit::saveImage: Image object is null");

    return false;
}

QString FanfouKit::picturesStorageLocation() const
{
    return QDesktopServices::storageLocation(QDesktopServices::PicturesLocation);
}

QString FanfouKit::applicationVersion() const
{
    return qApp->applicationVersion();
}

QByteArray FanfouKit::generateXAuthorizationHeader(const QString &username, const QString &password)
{
    QUrl url(ACCESS_TOKEN_URL);

    url.addEncodedQueryItem("x_auth_username", username.toUtf8().toPercentEncoding());
    url.addEncodedQueryItem("x_auth_password", password.toUtf8().toPercentEncoding());
    url.addQueryItem("x_auth_mode", "client_auth");

    QByteArray oauthHeader = OAuth::generateAuthorizationHeader(url, OAuth::POST);
    const QList<QPair<QByteArray, QByteArray> > urlItems = url.encodedQueryItems();

    for (int i = 0; i < urlItems.count(); ++i) {
        const QPair<QByteArray, QByteArray> &item = urlItems.at(i);
        oauthHeader.append("," + item.first + "=\"" + item.second + "\"");
    }

    return oauthHeader;
}

void FanfouKit::requestAccessToken(const QString &username, const QString &password)
{
    QNetworkRequest request;
    request.setUrl(QUrl(ACCESS_TOKEN_URL));
    request.setRawHeader("Authorization", generateXAuthorizationHeader(username, password));
    request.setHeader(QNetworkRequest::ContentTypeHeader, "application/x-www-form-urlencoded");

    QNetworkReply *reply = m_accessManager->post(request, QByteArray());
    connect(reply, SIGNAL(finished()), this, SLOT(onRequestAccessToken()));
}

QString FanfouKit::stringEncrypt(const QString &content, QString key)
{
    if (content.isEmpty() || key.isEmpty())
        return content;

   key = QString::fromUtf8(QCryptographicHash::hash(key.toUtf8(), QCryptographicHash::Md5));

   QString request;

   for (int i = 0; i < content.count(); ++i) {
       request.append(QChar(content.at(i).unicode() ^ key.at(i % key.size()).unicode()));
   }

   return request;
}

QString FanfouKit::stringUncrypt(const QString &content, QString key)
{
    return stringEncrypt(content, key);
}

void FanfouKit::onRequestAccessToken()
{
    QNetworkReply *reply = qobject_cast<QNetworkReply*>(sender());

    if (!reply)
        return;

    const QByteArray &data = reply->readAll();

    /// network error
    if (reply->error() != QNetworkReply::NoError) {
        /// login failed
        if (data.contains("<error>")) {
            QString error = QString::fromUtf8(data);
            QRegExp regExp("<error>(.+)</error>", Qt::CaseInsensitive, QRegExp::RegExp2);

            if (regExp.indexIn(error) >= 0) {
                emit requestAccessTokenError(regExp.cap(1));
            } else {
                emit requestAccessTokenError(regExp.errorString() + "\n" + error);
            }
        } else {
            emit requestAccessTokenError(reply->errorString());
        }
        return;
    }

    const QList<QByteArray> &data_list = data.split('&');

    if (data_list.count() < 2) {
        emit requestAccessTokenError("Parse reply data error, data: " + QString::fromUtf8(data));
        return;
    }

    const QList<QByteArray> &token_list = data_list.first().split('=');
    const QList<QByteArray> &secret_list = data_list.last().split('=');

    if (token_list.count() < 2 || secret_list.count() < 2) {
        emit requestAccessTokenError("Parse reply data error, data: " + QString::fromUtf8(data));
        return;
    }

    if (token_list.first().contains("secret")) {
        setOAuthToken(secret_list.last());
        setOAuthTokenSecret(token_list.last());
    } else {
        setOAuthToken(token_list.last());
        setOAuthTokenSecret(secret_list.last());
    }

    emit requestAccessTokenFinished();
}

void FanfouKit::onGetSplashLateshFinished()
{
    QNetworkReply *reply = qobject_cast<QNetworkReply*>(sender());

    if (!reply)
        return;

    const QList<QByteArray> dataList = reply->readAll().split(',');

    if (dataList.count() < 2)
        return;

    const QString splashPath = SPLASH_PATH;
    QByteArray splashFileName = dataList.last().split('"').at(3);

    if (!splashFileName.isEmpty()) {
        if (!QFile::exists(splashPath + splashFileName)) {
            QNetworkRequest request;

            request.setUrl(QUrl(SPLASH_URL + splashFileName));

            QNetworkReply *reply = m_accessManager->get(request);
            connect(reply, SIGNAL(finished()), this, SLOT(onGetSplashImageFinished()));
        }
    }
}

void FanfouKit::onGetSplashImageFinished()
{
    QNetworkReply *reply = qobject_cast<QNetworkReply*>(sender());

    if (!reply)
        return;

    const QString &splashPath = SPLASH_PATH;

    QFile file(splashPath + QFileInfo(reply->url().path()).fileName());

    if (!QDir().mkpath(QFileInfo(file.fileName()).absolutePath()))
        return;

    if (file.open(QIODevice::WriteOnly)) {
        file.write(reply->readAll());
        file.close();
    }
}

void FanfouKit::ensureVibraRumble()
{
    if (m_rumble)
        return;

    m_rumble = new QTM_NAMESPACE::QFeedbackHapticsEffect(this);

    foreach (QTM_NAMESPACE::QFeedbackActuator *actuator, QTM_NAMESPACE::QFeedbackActuator::actuators()) {
        if (actuator->name() == "Vibra") {
            m_rumble->setActuator(actuator);
            break;
        }
    }
}

void FanfouKit::updateSplash()
{
    QNetworkRequest request;

    request.setUrl(QUrl(SPLASH_URL + QLatin1String("latesh")));

    QNetworkReply *reply = m_accessManager->get(request);
    connect(reply, SIGNAL(finished()), this, SLOT(onGetSplashLateshFinished()));

    int today = QDate::currentDate().toString("yyyyMMdd").toInt();
    QDir splashDir(SPLASH_PATH);

    //clear old splash
    foreach (const QString &fileName, splashDir.entryList(QStringList() << "*.jpg", QDir::Files, QDir::Name)) {
        if (fileName.size() != 12)
            continue;

        bool ok = false;
        int file_date = fileName.left(8).toInt(&ok);

        if (ok && file_date < today) {
            splashDir.remove(fileName);
        }
    }
}
<commit_msg>更正latest拼写错误<commit_after>#include "fanfoukit.h"
#include "httprequest.h"

#include <QPair>
#include <QNetworkAccessManager>
#include <QNetworkReply>
#include <QRegExp>
#include <QStringList>
#include <QFile>
#include <QDir>
#include <QDateTime>
#include <QSettings>
#include <QCryptographicHash>
#include <QUuid>
#include <QtFeedback/QFeedbackHapticsEffect>
#include <QtFeedback/QFeedbackActuator>
#include <QFileInfo>
#include <QTextDocument>
#include <QDeclarativeItem>
#include <QPainter>
#include <QDesktopServices>
#include <QCoreApplication>
#include <QDebug>

#define ACCESS_TOKEN_URL "http://fanfou.com/oauth/access_token"
#define SPLASH_URL "http://api.zccrs.com/splash/meefan/n9/"
#define SPLASH_PATH QDesktopServices::storageLocation(QDesktopServices::CacheLocation) + QDir::separator() +  "splash" + QDir::separator()

FanfouKit::FanfouKit(QObject *parent)
    : OAuth(parent)
    , m_accessManager(new QNetworkAccessManager(this))
    , m_httpRequest(new HttpRequest(m_accessManager, this))
    , m_settings(new QSettings(this))
    , m_rumble(0)
{
    updateSplash();
}

FanfouKit::FanfouKit(QNetworkAccessManager *manager, QObject *parent)
    : OAuth(parent)
    , m_accessManager(manager)
    , m_httpRequest(new HttpRequest(m_accessManager, this))
    , m_settings(new QSettings(this))
    , m_rumble(0)
{
    updateSplash();
}

FanfouKit::FanfouKit(const QByteArray &consumerKey, const QByteArray &consumerSecret, QObject *parent)
    : OAuth(consumerKey, consumerSecret, parent)
    , m_accessManager(new QNetworkAccessManager(this))
    , m_httpRequest(new HttpRequest(m_accessManager, this))
    , m_settings(new QSettings(this))
    , m_rumble(0)
{
    updateSplash();
}

HttpRequest *FanfouKit::httpRequest() const
{
    return m_httpRequest;
}

QByteArray FanfouKit::readFile(const QString &filePath) const
{
    QFile file(filePath);

    if (file.open(QIODevice::ReadOnly)) {
        return file.readAll();
    }

    return QByteArray();
}

QString FanfouKit::fileName(const QString &filePath) const
{
    QFileInfo info(filePath);

    return info.fileName();
}

QString FanfouKit::fromUtf8(const QByteArray &data) const
{
    return QString::fromUtf8(data);
}

QByteArray FanfouKit::toUtf8(const QString &string) const
{
    return string.toUtf8();
}

QString FanfouKit::datetimeFormatFromISO(const QString &dt) const
{
    return QDateTime::fromString(dt, Qt::ISODate).toLocalTime().toString("yyyy-MM-dd hh:mm");
}

void FanfouKit::setSettingValue(const QString &name, const QVariant &value)
{
    m_settings->setValue(name, value);
}

QVariant FanfouKit::settingValue(const QString &name, const QVariant &defaultValue) const
{
    return m_settings->value(name, defaultValue);
}

void FanfouKit::clearSettings()
{
    m_settings->clear();
}

QByteArray FanfouKit::objectClassName(QObject *object) const
{
    return object->metaObject()->className();
}

QString FanfouKit::createUuid() const
{
    return QUuid::createUuid().toString();
}

void FanfouKit::vibrationDevice(qreal intensity, int duration)
{
    ensureVibraRumble();

    m_rumble->setIntensity(intensity);
    m_rumble->setDuration(duration);
    m_rumble->start();
}

QString FanfouKit::stringSimplified(const QString &string) const
{
    return string.simplified();
}

QByteArray FanfouKit::byteArrayJoin(const QByteArray &a1, const QByteArray &a2,
                                    const QByteArray &a3, const QByteArray &a4,
                                    const QByteArray &a5, const QByteArray &a6) const
{
    return a1 + a2 + a3 + a4 + a5 + a6;
}

int FanfouKit::byteArraySize(const QByteArray &data) const
{
    return data.size();
}

QString FanfouKit::toPlainText(const QString &text) const
{
    QTextDocument document;

    document.setHtml(text);

    return document.toPlainText();
}

bool FanfouKit::saveImage(const QScriptValue object, const QString &toPath) const
{
    if (QDeclarativeItem *item = qobject_cast<QDeclarativeItem*>(object.toQObject())) {
        QImage image(item->implicitWidth(), item->implicitHeight(), QImage::Format_ARGB32_Premultiplied);
        QPainter p(&image);

        item->paint(&p, 0, 0);

        if (image.isNull()) {
            qWarning("FanfouKit::saveImage: Image data is null");

            return false;
        }

        return image.save(toPath);
    }

    qWarning("FanfouKit::saveImage: Image object is null");

    return false;
}

QString FanfouKit::picturesStorageLocation() const
{
    return QDesktopServices::storageLocation(QDesktopServices::PicturesLocation);
}

QString FanfouKit::applicationVersion() const
{
    return qApp->applicationVersion();
}

QByteArray FanfouKit::generateXAuthorizationHeader(const QString &username, const QString &password)
{
    QUrl url(ACCESS_TOKEN_URL);

    url.addEncodedQueryItem("x_auth_username", username.toUtf8().toPercentEncoding());
    url.addEncodedQueryItem("x_auth_password", password.toUtf8().toPercentEncoding());
    url.addQueryItem("x_auth_mode", "client_auth");

    QByteArray oauthHeader = OAuth::generateAuthorizationHeader(url, OAuth::POST);
    const QList<QPair<QByteArray, QByteArray> > urlItems = url.encodedQueryItems();

    for (int i = 0; i < urlItems.count(); ++i) {
        const QPair<QByteArray, QByteArray> &item = urlItems.at(i);
        oauthHeader.append("," + item.first + "=\"" + item.second + "\"");
    }

    return oauthHeader;
}

void FanfouKit::requestAccessToken(const QString &username, const QString &password)
{
    QNetworkRequest request;
    request.setUrl(QUrl(ACCESS_TOKEN_URL));
    request.setRawHeader("Authorization", generateXAuthorizationHeader(username, password));
    request.setHeader(QNetworkRequest::ContentTypeHeader, "application/x-www-form-urlencoded");

    QNetworkReply *reply = m_accessManager->post(request, QByteArray());
    connect(reply, SIGNAL(finished()), this, SLOT(onRequestAccessToken()));
}

QString FanfouKit::stringEncrypt(const QString &content, QString key)
{
    if (content.isEmpty() || key.isEmpty())
        return content;

   key = QString::fromUtf8(QCryptographicHash::hash(key.toUtf8(), QCryptographicHash::Md5));

   QString request;

   for (int i = 0; i < content.count(); ++i) {
       request.append(QChar(content.at(i).unicode() ^ key.at(i % key.size()).unicode()));
   }

   return request;
}

QString FanfouKit::stringUncrypt(const QString &content, QString key)
{
    return stringEncrypt(content, key);
}

void FanfouKit::onRequestAccessToken()
{
    QNetworkReply *reply = qobject_cast<QNetworkReply*>(sender());

    if (!reply)
        return;

    const QByteArray &data = reply->readAll();

    /// network error
    if (reply->error() != QNetworkReply::NoError) {
        /// login failed
        if (data.contains("<error>")) {
            QString error = QString::fromUtf8(data);
            QRegExp regExp("<error>(.+)</error>", Qt::CaseInsensitive, QRegExp::RegExp2);

            if (regExp.indexIn(error) >= 0) {
                emit requestAccessTokenError(regExp.cap(1));
            } else {
                emit requestAccessTokenError(regExp.errorString() + "\n" + error);
            }
        } else {
            emit requestAccessTokenError(reply->errorString());
        }
        return;
    }

    const QList<QByteArray> &data_list = data.split('&');

    if (data_list.count() < 2) {
        emit requestAccessTokenError("Parse reply data error, data: " + QString::fromUtf8(data));
        return;
    }

    const QList<QByteArray> &token_list = data_list.first().split('=');
    const QList<QByteArray> &secret_list = data_list.last().split('=');

    if (token_list.count() < 2 || secret_list.count() < 2) {
        emit requestAccessTokenError("Parse reply data error, data: " + QString::fromUtf8(data));
        return;
    }

    if (token_list.first().contains("secret")) {
        setOAuthToken(secret_list.last());
        setOAuthTokenSecret(token_list.last());
    } else {
        setOAuthToken(token_list.last());
        setOAuthTokenSecret(secret_list.last());
    }

    emit requestAccessTokenFinished();
}

void FanfouKit::onGetSplashLateshFinished()
{
    QNetworkReply *reply = qobject_cast<QNetworkReply*>(sender());

    if (!reply)
        return;

    const QList<QByteArray> dataList = reply->readAll().split(',');

    if (dataList.count() < 2)
        return;

    const QString splashPath = SPLASH_PATH;
    QByteArray splashFileName = dataList.last().split('"').at(3);

    if (!splashFileName.isEmpty()) {
        if (!QFile::exists(splashPath + splashFileName)) {
            QNetworkRequest request;

            request.setUrl(QUrl(SPLASH_URL + splashFileName));

            QNetworkReply *reply = m_accessManager->get(request);
            connect(reply, SIGNAL(finished()), this, SLOT(onGetSplashImageFinished()));
        }
    }
}

void FanfouKit::onGetSplashImageFinished()
{
    QNetworkReply *reply = qobject_cast<QNetworkReply*>(sender());

    if (!reply)
        return;

    const QString &splashPath = SPLASH_PATH;

    QFile file(splashPath + QFileInfo(reply->url().path()).fileName());

    if (!QDir().mkpath(QFileInfo(file.fileName()).absolutePath()))
        return;

    if (file.open(QIODevice::WriteOnly)) {
        file.write(reply->readAll());
        file.close();
    }
}

void FanfouKit::ensureVibraRumble()
{
    if (m_rumble)
        return;

    m_rumble = new QTM_NAMESPACE::QFeedbackHapticsEffect(this);

    foreach (QTM_NAMESPACE::QFeedbackActuator *actuator, QTM_NAMESPACE::QFeedbackActuator::actuators()) {
        if (actuator->name() == "Vibra") {
            m_rumble->setActuator(actuator);
            break;
        }
    }
}

void FanfouKit::updateSplash()
{
    QNetworkRequest request;

    request.setUrl(QUrl(SPLASH_URL + QLatin1String("latest")));

    QNetworkReply *reply = m_accessManager->get(request);
    connect(reply, SIGNAL(finished()), this, SLOT(onGetSplashLateshFinished()));

    int today = QDate::currentDate().toString("yyyyMMdd").toInt();
    QDir splashDir(SPLASH_PATH);

    //clear old splash
    foreach (const QString &fileName, splashDir.entryList(QStringList() << "*.jpg", QDir::Files, QDir::Name)) {
        if (fileName.size() != 12)
            continue;

        bool ok = false;
        int file_date = fileName.left(8).toInt(&ok);

        if (ok && file_date < today) {
            splashDir.remove(fileName);
        }
    }
}
<|endoftext|>


<commit_before>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: dp_gui_updatedialog.hxx,v $
 *
 *  $Revision: 1.3 $
 *
 *  last change: $Author: rt $ $Date: 2007-07-06 12:35:42 $
 *
 *  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 2006 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 INCLUDED_DESKTOP_SOURCE_DEPLOYMENT_GUI_DP_GUI_UPDATEDIALOG_HXX
#define INCLUDED_DESKTOP_SOURCE_DEPLOYMENT_GUI_DP_GUI_UPDATEDIALOG_HXX

#ifndef _SAL_CONFIG_H_
#include "sal/config.h"
#endif

#include <memory>
#include <vector>

#ifndef _COM_SUN_STAR_UNO_REFERENCE_HXX_
#include "com/sun/star/uno/Reference.hxx"
#endif
#ifndef _COM_SUN_STAR_UNO_SEQUENCE_HXX_
#include "com/sun/star/uno/Sequence.hxx"
#endif
#ifndef _RTL_REF_HXX_
#include "rtl/ref.hxx"
#endif
#ifndef _RTL_USTRING_HXX_
#include "rtl/ustring.hxx"
#endif
#ifndef _SVLBOXITM_HXX
#include "svtools/svlbitm.hxx"
#endif
#ifndef _SVEDIT_HXX
#include "svtools/svmedit.hxx"
#endif
#ifndef _SVX_CHECKLBX_HXX
#include "svx/checklbx.hxx"
#endif
#ifndef _LINK_HXX
#include "tools/link.hxx"
#endif
#ifndef _SOLAR_H
#include "tools/solar.h"
#endif
#ifndef _SV_BUTTON_HXX
#include "vcl/button.hxx"
#endif
#ifndef _SV_DIALOG_HXX
#include "vcl/dialog.hxx"
#endif
#ifndef _SV_FIXED_HXX
#include "vcl/fixed.hxx"
#endif

/// @HTML

class Image;
class KeyEvent;
class MouseEvent;
class ResId;
class Window;
namespace com { namespace sun { namespace star {
    namespace awt { class XThrobber; }
    namespace deployment { class XPackageManager; }
    namespace uno { class XComponentContext; }
} } }
namespace dp_gui {
    class SelectedPackageIterator;
    struct UpdateData;
}

namespace dp_gui {

/**
   The modal “Check for Updates” dialog.
*/
class UpdateDialog: public ModalDialog {
public:
    /**
       Create an instance.

Exactly one of selectedPackages and
       packageManagers must be non-null.

       @param context
       a non-null component context

       @param parent
       the parent window, may be null

       @param selectedPackages
       if non-null, only check for updates for the selected packages

       @param packageManagers
       if non-null, check for updates for all managed packages
    */
    UpdateDialog(
        com::sun::star::uno::Reference< com::sun::star::uno::XComponentContext >
            const & context,
        Window * parent,
        rtl::Reference< dp_gui::SelectedPackageIterator > const &
            selectedPackages,
        com::sun::star::uno::Sequence< com::sun::star::uno::Reference<
            com::sun::star::deployment::XPackageManager > > const &
            packageManagers,
        std::vector< dp_gui::UpdateData > * updateData);

    ~UpdateDialog();

    virtual BOOL Close();

    virtual short Execute();

private:
    UpdateDialog(UpdateDialog &); // not defined
    void operator =(UpdateDialog &); // not defined

    struct DisabledUpdate;
    struct SpecificError;
    union IndexUnion;
    friend union IndexUnion;
    struct Index;
    friend struct Index;
    class Thread;
    friend class Thread;

    class CheckListBox: public SvxCheckListBox {
    public:
        CheckListBox(
            UpdateDialog & dialog, ResId const & resource,
            Image const & normalStaticImage,
            Image const & highContrastStaticImage);

        virtual ~CheckListBox();

        USHORT getItemCount() const;

    private:
        CheckListBox(UpdateDialog::CheckListBox &); // not defined
        void operator =(UpdateDialog::CheckListBox &); // not defined

        virtual void MouseButtonDown(MouseEvent const & event);

        virtual void MouseButtonUp(MouseEvent const & event);

        virtual void KeyInput(KeyEvent const & event);

        UpdateDialog & m_dialog;
    };

    friend class CheckListBox;

    void insertItem(
        rtl::OUString const & name, USHORT position,
        std::auto_ptr< UpdateDialog::Index const > index,
        SvLBoxButtonKind kind);

    void addAdditional(
        rtl::OUString const & name, USHORT position,
        std::auto_ptr< UpdateDialog::Index const > index,
        SvLBoxButtonKind kind);

    void addEnabledUpdate(
        rtl::OUString const & name, dp_gui::UpdateData const & data);

    void addDisabledUpdate(UpdateDialog::DisabledUpdate const & data);

    void addGeneralError(rtl::OUString const & message);

    void addSpecificError(UpdateDialog::SpecificError const & data);

    void checkingDone();

    void enableOk();

    DECL_LINK(selectionHandler, void *);

    DECL_LINK(allHandler, void *);

    DECL_LINK(okHandler, void *);

    DECL_LINK(cancelHandler, void *);

    com::sun::star::uno::Reference< com::sun::star::uno::XComponentContext >
        m_context;
    FixedText m_checking;
    com::sun::star::uno::Reference< com::sun::star::awt::XThrobber > m_throbber;
    FixedText m_update;
    UpdateDialog::CheckListBox m_updates;
    CheckBox m_all;
    FixedText m_description;
    MultiLineEdit m_descriptions;
    FixedLine m_line;
    HelpButton m_help;
    PushButton m_ok;
    CancelButton m_cancel;
    rtl::OUString m_error;
    rtl::OUString m_none;
    rtl::OUString m_noInstallable;
    rtl::OUString m_failure;
    rtl::OUString m_unknownError;
    rtl::OUString m_noDescription;
    rtl::OUString m_noInstall;
    rtl::OUString m_noDependency;
    rtl::OUString m_noPermission;
    rtl::OUString m_noPermissionVista;
    rtl::OUString m_noUpdate;
    std::vector< dp_gui::UpdateData > m_enabledUpdates;
    std::vector< UpdateDialog::DisabledUpdate > m_disabledUpdates;
    std::vector< rtl::OUString > m_generalErrors;
    std::vector< UpdateDialog::SpecificError > m_specificErrors;
    std::vector< dp_gui::UpdateData > & m_updateData;
    rtl::Reference< UpdateDialog::Thread > m_thread;
};

}

#endif
<commit_msg>INTEGRATION: CWS updchk10 (1.3.44); FILE MERGED 2007/10/31 14:26:04 dv 1.3.44.2: #i82851# Check if there are still pending updates after removing an extension 2007/10/29 13:27:44 dv 1.3.44.1: #i82851# Extension manager notifies update check about found updates<commit_after>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: dp_gui_updatedialog.hxx,v $
 *
 *  $Revision: 1.4 $
 *
 *  last change: $Author: ihi $ $Date: 2007-11-19 16:52:59 $
 *
 *  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 2006 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 INCLUDED_DESKTOP_SOURCE_DEPLOYMENT_GUI_DP_GUI_UPDATEDIALOG_HXX
#define INCLUDED_DESKTOP_SOURCE_DEPLOYMENT_GUI_DP_GUI_UPDATEDIALOG_HXX

#ifndef _SAL_CONFIG_H_
#include "sal/config.h"
#endif

#include <memory>
#include <vector>

#ifndef _COM_SUN_STAR_UNO_REFERENCE_HXX_
#include "com/sun/star/uno/Reference.hxx"
#endif
#ifndef _COM_SUN_STAR_UNO_SEQUENCE_HXX_
#include "com/sun/star/uno/Sequence.hxx"
#endif
#ifndef _RTL_REF_HXX_
#include "rtl/ref.hxx"
#endif
#ifndef _RTL_USTRING_HXX_
#include "rtl/ustring.hxx"
#endif
#ifndef _SVLBOXITM_HXX
#include "svtools/svlbitm.hxx"
#endif
#ifndef _SVEDIT_HXX
#include "svtools/svmedit.hxx"
#endif
#ifndef _SVX_CHECKLBX_HXX
#include "svx/checklbx.hxx"
#endif
#ifndef _LINK_HXX
#include "tools/link.hxx"
#endif
#ifndef _SOLAR_H
#include "tools/solar.h"
#endif
#ifndef _SV_BUTTON_HXX
#include "vcl/button.hxx"
#endif
#ifndef _SV_DIALOG_HXX
#include "vcl/dialog.hxx"
#endif
#ifndef _SV_FIXED_HXX
#include "vcl/fixed.hxx"
#endif

/// @HTML

class Image;
class KeyEvent;
class MouseEvent;
class ResId;
class Window;
namespace com { namespace sun { namespace star {
    namespace awt { class XThrobber; }
    namespace deployment { class XPackageManager; }
    namespace uno { class XComponentContext; }
} } }
namespace dp_gui {
    class SelectedPackageIterator;
    struct UpdateData;
}

namespace dp_gui {

/**
   The modal “Check for Updates” dialog.
*/
class UpdateDialog: public ModalDialog {
public:
    /**
       Create an instance.

Exactly one of selectedPackages and
       packageManagers must be non-null.

       @param context
       a non-null component context

       @param parent
       the parent window, may be null

       @param selectedPackages
       if non-null, only check for updates for the selected packages

       @param packageManagers
       if non-null, check for updates for all managed packages
    */
    UpdateDialog(
        com::sun::star::uno::Reference< com::sun::star::uno::XComponentContext >
            const & context,
        Window * parent,
        rtl::Reference< dp_gui::SelectedPackageIterator > const &
            selectedPackages,
        com::sun::star::uno::Sequence< com::sun::star::uno::Reference<
            com::sun::star::deployment::XPackageManager > > const &
            packageManagers,
        std::vector< dp_gui::UpdateData > * updateData);

    ~UpdateDialog();

    virtual BOOL Close();

    virtual short Execute();

    void notifyMenubar( bool bPrepareOnly, bool bRecheckOnly );
    static void createNotifyJob( bool bPrepareOnly,
        com::sun::star::uno::Sequence< com::sun::star::uno::Sequence< rtl::OUString > > &rItemList );

private:
    UpdateDialog(UpdateDialog &); // not defined
    void operator =(UpdateDialog &); // not defined

    struct DisabledUpdate;
    struct SpecificError;
    union IndexUnion;
    friend union IndexUnion;
    struct Index;
    friend struct Index;
    class Thread;
    friend class Thread;

    class CheckListBox: public SvxCheckListBox {
    public:
        CheckListBox(
            UpdateDialog & dialog, ResId const & resource,
            Image const & normalStaticImage,
            Image const & highContrastStaticImage);

        virtual ~CheckListBox();

        USHORT getItemCount() const;

    private:
        CheckListBox(UpdateDialog::CheckListBox &); // not defined
        void operator =(UpdateDialog::CheckListBox &); // not defined

        virtual void MouseButtonDown(MouseEvent const & event);

        virtual void MouseButtonUp(MouseEvent const & event);

        virtual void KeyInput(KeyEvent const & event);

        UpdateDialog & m_dialog;
    };

    friend class CheckListBox;

    void insertItem(
        rtl::OUString const & name, USHORT position,
        std::auto_ptr< UpdateDialog::Index const > index,
        SvLBoxButtonKind kind);

    void addAdditional(
        rtl::OUString const & name, USHORT position,
        std::auto_ptr< UpdateDialog::Index const > index,
        SvLBoxButtonKind kind);

    void addEnabledUpdate(
        rtl::OUString const & name, dp_gui::UpdateData const & data);

    void addDisabledUpdate(UpdateDialog::DisabledUpdate const & data);

    void addGeneralError(rtl::OUString const & message);

    void addSpecificError(UpdateDialog::SpecificError const & data);

    void checkingDone();

    void enableOk();

    DECL_LINK(selectionHandler, void *);

    DECL_LINK(allHandler, void *);

    DECL_LINK(okHandler, void *);

    DECL_LINK(cancelHandler, void *);

    com::sun::star::uno::Reference< com::sun::star::uno::XComponentContext >
        m_context;
    FixedText m_checking;
    com::sun::star::uno::Reference< com::sun::star::awt::XThrobber > m_throbber;
    FixedText m_update;
    UpdateDialog::CheckListBox m_updates;
    CheckBox m_all;
    FixedText m_description;
    MultiLineEdit m_descriptions;
    FixedLine m_line;
    HelpButton m_help;
    PushButton m_ok;
    CancelButton m_cancel;
    rtl::OUString m_error;
    rtl::OUString m_none;
    rtl::OUString m_noInstallable;
    rtl::OUString m_failure;
    rtl::OUString m_unknownError;
    rtl::OUString m_noDescription;
    rtl::OUString m_noInstall;
    rtl::OUString m_noDependency;
    rtl::OUString m_noPermission;
    rtl::OUString m_noPermissionVista;
    rtl::OUString m_noUpdate;
    std::vector< dp_gui::UpdateData > m_enabledUpdates;
    std::vector< UpdateDialog::DisabledUpdate > m_disabledUpdates;
    std::vector< rtl::OUString > m_generalErrors;
    std::vector< UpdateDialog::SpecificError > m_specificErrors;
    std::vector< dp_gui::UpdateData > & m_updateData;
    rtl::Reference< UpdateDialog::Thread > m_thread;
};

}

#endif
<|endoftext|>


<commit_before>#include "osl/state/numEffectState.h"
#include "osl/effect_util/effectUtil.h"
#include "osl/container/moveVector.h"
#include "osl/record/csa.h"
#include "osl/record/csaIOError.h"
#include "osl/move_generator/legalMoves.h"
#include <boost/random/mersenne_twister.hpp>
#include <string>
#include <sys/time.h>

namespace osl {
  void
  showState(const NumEffectState& state)
  {
    std::cout << state << std::endl;
  }

  Move
  selectMove(const NumEffectState& state, const MoveVector& moves)
  {
    static boost::mt11213b generator(random());
    return moves[generator() % moves.size()];
  }

  bool
  isMated(const NumEffectState& state)
  {
    return state.inCheck(alt(state.turn()));
  }

  bool
  computerOperate(NumEffectState& state)
  {
    MoveVector moves;
    LegalMoves::generate(state, moves);
    if (moves.empty()) {
      std::cerr << "make masita\n";
      return true;
    }
    const Move my_move = selectMove(state, moves);
    assert(state.isValidMove(my_move));
    state.makeMove(my_move);

    showState(state);
    csaShow(std::cout, my_move);
    std::cout << "\n";

    if (isMated(state)) {
      std::cerr << "checkmate!";
      return true;
    }

    return false;
  }

  bool
  playerOperate(NumEffectState& state, std::string line)
  {
    Move op_move;
    try {
      op_move = record::csa::strToMove(line, state);
    } catch (const std::runtime_error& e) {
      std::cout << e.what() << std::endl;
      return true;
    }

    if (! state.isValidMove(op_move)) {
      return true;
    }

    state.makeMove(op_move);

    showState(state);
    csaShow(std::cout, op_move);
    std::cout << "\n";

    return false;
  }

  std::string
  inputLine(void)
  {
    std::string line;
    if (! std::getline(std::cin, line)) {
      return NULL;
    }
    return line;
  }
}

int
main()
{
  using namespace osl;

  srandom(time(0));

  NumEffectState state((SimpleState(HIRATE)));
  while (true) {
    bool ended = computerOperate(state);
    if (ended) {
      break;
    }

    std::string line = inputLine();
    bool failed = playerOperate(state, line);
    if (failed) {
      break;
    }
  }
}
<commit_msg>Improve result messages<commit_after>#include "osl/state/numEffectState.h"
#include "osl/effect_util/effectUtil.h"
#include "osl/container/moveVector.h"
#include "osl/record/csa.h"
#include "osl/record/csaIOError.h"
#include "osl/move_generator/legalMoves.h"
#include <boost/random/mersenne_twister.hpp>
#include <string>
#include <sys/time.h>

namespace osl {
  void
  showState(const NumEffectState& state)
  {
    std::cout << state << std::endl;
  }

  Move
  selectMove(const NumEffectState& state, const MoveVector& moves)
  {
    static boost::mt11213b generator(random());
    return moves[generator() % moves.size()];
  }

  bool
  isMated(const NumEffectState& state)
  {
    return state.inCheck(alt(state.turn()));
  }

  bool
  computerOperate(NumEffectState& state)
  {
    MoveVector moves;
    LegalMoves::generate(state, moves);
    if (moves.empty()) {
      std::cerr << "You Win!\n";
      return true;
    }
    const Move my_move = selectMove(state, moves);
    assert(state.isValidMove(my_move));
    state.makeMove(my_move);

    showState(state);
    csaShow(std::cout, my_move);
    std::cout << "\n";

    if (isMated(state)) {
      std::cerr << "You Lose...";
      return true;
    }

    return false;
  }

  bool
  playerOperate(NumEffectState& state, std::string line)
  {
    Move op_move;
    try {
      op_move = record::csa::strToMove(line, state);
    } catch (const std::runtime_error& e) {
      std::cout << e.what() << std::endl;
      return true;
    }

    if (! state.isValidMove(op_move)) {
      return true;
    }

    state.makeMove(op_move);

    showState(state);
    csaShow(std::cout, op_move);
    std::cout << "\n";

    return false;
  }

  std::string
  inputLine(void)
  {
    std::string line;
    if (! std::getline(std::cin, line)) {
      return NULL;
    }
    return line;
  }
}

int
main()
{
  using namespace osl;

  srandom(time(0));

  NumEffectState state((SimpleState(HIRATE)));
  while (true) {
    bool ended = computerOperate(state);
    if (ended) {
      break;
    }

    std::string line = inputLine();
    bool failed = playerOperate(state, line);
    if (failed) {
      break;
    }
  }
}
<|endoftext|>


<commit_before>/*
* Copyright (c) 2013-2016, The PurpleI2P Project
*
* This file is part of Purple i2pd project and licensed under BSD3
*
* See full license text in LICENSE file at top of project tree
*/

#include <cstdlib>
#include <iostream>
#include <fstream>
#include <map>
#include <string>
#include <boost/program_options/cmdline.hpp>
#include <boost/program_options/options_description.hpp>
#include <boost/program_options/parsers.hpp>
#include <boost/program_options/variables_map.hpp>

#include "Config.h"
#include "version.h"

using namespace boost::program_options;

namespace i2p {
namespace config {
  options_description m_OptionsDesc;
  variables_map       m_Options;

  /* list of renamed options */
  std::map<std::string, std::string> remapped_options = {
    { "tunnelscfg",          "tunconf" },
    { "v6",                  "ipv6" },
    { "httpaddress",         "http.address" },
    { "httpport",            "http.port"    },
    { "httpproxyaddress",    "httpproxy.address"  },
    { "httpproxyport",       "httpproxy.port"     },
    { "socksproxyaddress",   "socksproxy.address" },
    { "socksproxyport",      "socksproxy.port"    },
    { "samaddress",          "sam.address" },
    { "samport",             "sam.port"    },
    { "bobaddress",          "bob.address" },
    { "bobport",             "bob.port"    },
    { "i2pcontroladdress",   "i2pcontrol.address" },
    { "i2pcontroladdress",   "i2pcontrol.port"    },
    { "proxykeys",           "httpproxy.keys" },
  };
  /* list of options, that loose their argument and become simple switch */
  std::set<std::string> boolean_options = {
    "daemon", "floodfill", "notransit", "service", "ipv6"
  };

  /* this function is a solid piece of shit, remove it after 2.6.0 */
  std::pair<std::string, std::string> old_syntax_parser(const std::string& s) {
    std::string name  = "";
    std::string value = "";
    std::size_t pos = 0;
    /* shortcuts -- -h */
    if (s.length() == 2 && s.at(0) == '-' && s.at(1) != '-')
      return make_pair(s.substr(1), "");
    /* old-style -- -log, /log, etc */
    if (s.at(0) == '/' || (s.at(0) == '-' && s.at(1) != '-')) {
      if ((pos = s.find_first_of("= ")) != std::string::npos) {
        name  = s.substr(1, pos - 1);
        value = s.substr(pos + 1);
      } else {
        name  = s.substr(1, pos);
        value = "";
      }
      if (boolean_options.count(name) > 0 && value != "")
        std::cerr << "args: don't give an argument to switch option: " << s << std::endl;
      if (m_OptionsDesc.find_nothrow(name, false)) {
        std::cerr << "args: option " << s << " style is DEPRECATED, use --" << name << " instead" << std::endl;
        return std::make_pair(name, value);
      }
      if (remapped_options.count(name) > 0) {
        name = remapped_options[name];
        std::cerr << "args: option " << s << " is DEPRECATED, use --" << name << " instead" << std::endl;
        return std::make_pair(name, value);
      } /* else */
    }
    /* long options -- --help */
    if (s.substr(0, 2) == "--") {
      if ((pos = s.find_first_of("= ")) != std::string::npos) {
        name  = s.substr(2, pos - 2);
        value = s.substr(pos + 1);
      } else {
        name  = s.substr(2, pos);
        value = "";
      }
      if (boolean_options.count(name) > 0 && value != "") {
        std::cerr << "args: don't give an argument to switch option: " << s << std::endl;
        value = "";
      }
      if (m_OptionsDesc.find_nothrow(name, false))
        return std::make_pair(name, value);
      if (remapped_options.count(name) > 0) {
        name = remapped_options[name];
        std::cerr << "args: option " << s << " is DEPRECATED, use --" << name << " instead" << std::endl;
        return std::make_pair(name, value);
      } /* else */
    }
    std::cerr << "args: unknown option -- " << s << std::endl;
    return std::make_pair("", "");
  }

  void Init() {
    options_description general("General options");
    general.add_options()
      ("help",     "Show this message")
      ("conf",      value<std::string>()->default_value(""),     "Path to main i2pd config file (default: try ~/.i2pd/i2pd.conf or /var/lib/i2pd/i2pd.conf)")
      ("tunconf",   value<std::string>()->default_value(""),     "Path to config with tunnels list and options (default: try ~/.i2pd/tunnels.conf or /var/lib/i2pd/tunnels.conf)")
      ("pidfile",   value<std::string>()->default_value(""),     "Path to pidfile (default: ~/i2pd/i2pd.pid or /var/lib/i2pd/i2pd.pid)")
      ("log",       value<std::string>()->default_value(""),     "Logs destination: stdout, file, syslog (stdout if not set)")
      ("logfile",   value<std::string>()->default_value(""),     "Path to logfile (stdout if not set, autodetect if daemon)")
      ("loglevel",  value<std::string>()->default_value("info"), "Set the minimal level of log messages (debug, info, warn, error)")
	  ("family",    value<std::string>()->default_value(""),     "Specify a family, router belongs to")
	  ("datadir",   value<std::string>()->default_value(""),     "Path to storage of i2pd data (RI, keys, peer profiles, ...)")
      ("host",      value<std::string>()->default_value("0.0.0.0"),     "External IP")
      ("port",      value<uint16_t>()->default_value(0),                "Port to listen for incoming connections (default: auto)")
      ("ipv4",      value<bool>()->zero_tokens()->default_value(true),  "Enable communication through ipv4")
      ("ipv6",      value<bool>()->zero_tokens()->default_value(false), "Enable communication through ipv6")
      ("daemon",    value<bool>()->zero_tokens()->default_value(false), "Router will go to background after start")
      ("service",   value<bool>()->zero_tokens()->default_value(false), "Router will use system folders like '/var/lib/i2pd'")
      ("notransit", value<bool>()->zero_tokens()->default_value(false), "Router will not accept transit tunnels at startup")
      ("floodfill", value<bool>()->zero_tokens()->default_value(false), "Router will be floodfill")
      ("bandwidth", value<std::string>()->default_value(""), "Bandwidth limit: integer in kbps or letters: L (32), O (256), P (2048), X (>9000)")
#ifdef _WIN32
      ("svcctl",    value<std::string>()->default_value(""),     "Windows service management ('install' or 'remove')")
      ("insomnia", value<bool>()->zero_tokens()->default_value(false), "Prevent system from sleeping")
      ("close", value<std::string>()->default_value("ask"), "Action on close: minimize, exit, ask") // TODO: add custom validator or something
#endif
      ;
    options_description limits("Limits options");
    limits.add_options()
      ("limits.transit",   value<uint16_t>()->default_value(2500), "Maximum active transit sessions (default:2500)")
      ("limits.router",    value<uint16_t>()->default_value(4096), "Maximum active router sessions (default:4096)")
      ("limits.client",    value<uint16_t>()->default_value(1024), "Maximum active client sessions (default:1024)")
      ("limits.floodfill", value<uint16_t>()->default_value(1024), "Maximum active floodfill sessions (default:1024)")
      ;

    options_description httpserver("HTTP Server options");
    httpserver.add_options()
      ("http.enabled",        value<bool>()->default_value(true),               "Enable or disable webconsole")
      ("http.address",        value<std::string>()->default_value("127.0.0.1"), "Webconsole listen address")
      ("http.port",           value<uint16_t>()->default_value(7070),           "Webconsole listen port")
      ;

    options_description httpproxy("HTTP Proxy options");
    httpproxy.add_options()
      ("httpproxy.enabled",   value<bool>()->default_value(true),                         "Enable or disable HTTP Proxy")
      ("httpproxy.address",   value<std::string>()->default_value("127.0.0.1"),           "HTTP Proxy listen address")
      ("httpproxy.port",      value<uint16_t>()->default_value(4444),                     "HTTP Proxy listen port")
      ("httpproxy.keys",      value<std::string>()->default_value(""),  "File to persist HTTP Proxy keys")
      ;

    options_description socksproxy("SOCKS Proxy options");
    socksproxy.add_options()
      ("socksproxy.enabled",  value<bool>()->default_value(true),                         "Enable or disable SOCKS Proxy")
      ("socksproxy.address",  value<std::string>()->default_value("127.0.0.1"),           "SOCKS Proxy listen address")
      ("socksproxy.port",     value<uint16_t>()->default_value(4447),                     "SOCKS Proxy listen port")
      ("socksproxy.keys",     value<std::string>()->default_value(""), "File to persist SOCKS Proxy keys")
      ("socksproxy.outproxy", value<std::string>()->default_value("127.0.0.1"), "Upstream outproxy address for SOCKS Proxy")
      ("socksproxy.outproxyport", value<uint16_t>()->default_value(9050), "Upstream outproxy port for SOCKS Proxy")
      ;

    options_description sam("SAM bridge options");
    sam.add_options()
      ("sam.enabled",         value<bool>()->default_value(false),                        "Enable or disable SAM Application bridge")
      ("sam.address",         value<std::string>()->default_value("127.0.0.1"),           "SAM listen address")
      ("sam.port",            value<uint16_t>()->default_value(7656),                     "SAM listen port")
      ;

    options_description bob("BOB options");
    bob.add_options()
      ("bob.enabled",         value<bool>()->default_value(false),                        "Enable or disable BOB command channel")
      ("bob.address",         value<std::string>()->default_value("127.0.0.1"),           "BOB listen address")
      ("bob.port",            value<uint16_t>()->default_value(2827),                     "BOB listen port")
      ;

    options_description i2pcontrol("I2PControl options");
    i2pcontrol.add_options()
      ("i2pcontrol.enabled",  value<bool>()->default_value(false),                        "Enable or disable I2P Control Protocol")
      ("i2pcontrol.address",  value<std::string>()->default_value("127.0.0.1"),           "I2PCP listen address")
      ("i2pcontrol.port",     value<uint16_t>()->default_value(7650),                     "I2PCP listen port")
      ("i2pcontrol.password", value<std::string>()->default_value("itoopie"),             "I2PCP access password")
      ("i2pcontrol.cert",     value<std::string>()->default_value("i2pcontrol.crt.pem"),  "I2PCP connection cerificate")
      ("i2pcontrol.key",      value<std::string>()->default_value("i2pcontrol.key.pem"),  "I2PCP connection cerificate key")
      ;

	options_description precomputation("Precomputation options");
	precomputation.add_options()
	  ("precomputation.elgamal",
#if defined(__x86_64__)
	   value<bool>()->default_value(false),
#else
	   value<bool>()->default_value(true),
#endif
	   "Enable or disable elgamal precomputation table")
	  ;

    m_OptionsDesc
      .add(general)
      .add(httpserver)
      .add(httpproxy)
      .add(socksproxy)
      .add(sam)
      .add(bob)
      .add(i2pcontrol)
	  .add(precomputation)
      ;
  }

  void ParseCmdline(int argc, char* argv[]) {
    try {
      auto style = boost::program_options::command_line_style::unix_style
                 | boost::program_options::command_line_style::allow_long_disguise;
      style &=   ~ boost::program_options::command_line_style::allow_guessing;
      store(parse_command_line(argc, argv, m_OptionsDesc, style, old_syntax_parser), m_Options);
    } catch (boost::program_options::error& e) {
      std::cerr << "args: " << e.what() << std::endl;
      exit(EXIT_FAILURE);
    }

    if (m_Options.count("help") || m_Options.count("h")) {
      std::cout << "i2pd version " << I2PD_VERSION << " (" << I2P_VERSION << ")" << std::endl;
      std::cout << m_OptionsDesc;
      exit(EXIT_SUCCESS);
    }
  }

  void ParseConfig(const std::string& path) {
    if (path == "") return;

    std::ifstream config(path, std::ios::in);

    if (!config.is_open())
	{
      std::cerr << "missing/unreadable config file: " << path << std::endl;
      exit(EXIT_FAILURE);
    }

    try
	{
		store(boost::program_options::parse_config_file(config, m_OptionsDesc), m_Options);
    }
	catch (boost::program_options::error& e)
	{
      std::cerr << e.what() << std::endl;
      exit(EXIT_FAILURE);
    };
  }

  void Finalize() {
    notify(m_Options);
  }

  bool IsDefault(const char *name) {
    if (!m_Options.count(name))
      throw "try to check non-existent option";

    if (m_Options[name].defaulted())
      return true;
    return false;
  }
} // namespace config
} // namespace i2p
<commit_msg>limits options<commit_after>/*
* Copyright (c) 2013-2016, The PurpleI2P Project
*
* This file is part of Purple i2pd project and licensed under BSD3
*
* See full license text in LICENSE file at top of project tree
*/

#include <cstdlib>
#include <iostream>
#include <fstream>
#include <map>
#include <string>
#include <boost/program_options/cmdline.hpp>
#include <boost/program_options/options_description.hpp>
#include <boost/program_options/parsers.hpp>
#include <boost/program_options/variables_map.hpp>

#include "Config.h"
#include "version.h"

using namespace boost::program_options;

namespace i2p {
namespace config {
  options_description m_OptionsDesc;
  variables_map       m_Options;

  /* list of renamed options */
  std::map<std::string, std::string> remapped_options = {
    { "tunnelscfg",          "tunconf" },
    { "v6",                  "ipv6" },
    { "httpaddress",         "http.address" },
    { "httpport",            "http.port"    },
    { "httpproxyaddress",    "httpproxy.address"  },
    { "httpproxyport",       "httpproxy.port"     },
    { "socksproxyaddress",   "socksproxy.address" },
    { "socksproxyport",      "socksproxy.port"    },
    { "samaddress",          "sam.address" },
    { "samport",             "sam.port"    },
    { "bobaddress",          "bob.address" },
    { "bobport",             "bob.port"    },
    { "i2pcontroladdress",   "i2pcontrol.address" },
    { "i2pcontroladdress",   "i2pcontrol.port"    },
    { "proxykeys",           "httpproxy.keys" },
  };
  /* list of options, that loose their argument and become simple switch */
  std::set<std::string> boolean_options = {
    "daemon", "floodfill", "notransit", "service", "ipv6"
  };

  /* this function is a solid piece of shit, remove it after 2.6.0 */
  std::pair<std::string, std::string> old_syntax_parser(const std::string& s) {
    std::string name  = "";
    std::string value = "";
    std::size_t pos = 0;
    /* shortcuts -- -h */
    if (s.length() == 2 && s.at(0) == '-' && s.at(1) != '-')
      return make_pair(s.substr(1), "");
    /* old-style -- -log, /log, etc */
    if (s.at(0) == '/' || (s.at(0) == '-' && s.at(1) != '-')) {
      if ((pos = s.find_first_of("= ")) != std::string::npos) {
        name  = s.substr(1, pos - 1);
        value = s.substr(pos + 1);
      } else {
        name  = s.substr(1, pos);
        value = "";
      }
      if (boolean_options.count(name) > 0 && value != "")
        std::cerr << "args: don't give an argument to switch option: " << s << std::endl;
      if (m_OptionsDesc.find_nothrow(name, false)) {
        std::cerr << "args: option " << s << " style is DEPRECATED, use --" << name << " instead" << std::endl;
        return std::make_pair(name, value);
      }
      if (remapped_options.count(name) > 0) {
        name = remapped_options[name];
        std::cerr << "args: option " << s << " is DEPRECATED, use --" << name << " instead" << std::endl;
        return std::make_pair(name, value);
      } /* else */
    }
    /* long options -- --help */
    if (s.substr(0, 2) == "--") {
      if ((pos = s.find_first_of("= ")) != std::string::npos) {
        name  = s.substr(2, pos - 2);
        value = s.substr(pos + 1);
      } else {
        name  = s.substr(2, pos);
        value = "";
      }
      if (boolean_options.count(name) > 0 && value != "") {
        std::cerr << "args: don't give an argument to switch option: " << s << std::endl;
        value = "";
      }
      if (m_OptionsDesc.find_nothrow(name, false))
        return std::make_pair(name, value);
      if (remapped_options.count(name) > 0) {
        name = remapped_options[name];
        std::cerr << "args: option " << s << " is DEPRECATED, use --" << name << " instead" << std::endl;
        return std::make_pair(name, value);
      } /* else */
    }
    std::cerr << "args: unknown option -- " << s << std::endl;
    return std::make_pair("", "");
  }

  void Init() {
    options_description general("General options");
    general.add_options()
      ("help",     "Show this message")
      ("conf",      value<std::string>()->default_value(""),     "Path to main i2pd config file (default: try ~/.i2pd/i2pd.conf or /var/lib/i2pd/i2pd.conf)")
      ("tunconf",   value<std::string>()->default_value(""),     "Path to config with tunnels list and options (default: try ~/.i2pd/tunnels.conf or /var/lib/i2pd/tunnels.conf)")
      ("pidfile",   value<std::string>()->default_value(""),     "Path to pidfile (default: ~/i2pd/i2pd.pid or /var/lib/i2pd/i2pd.pid)")
      ("log",       value<std::string>()->default_value(""),     "Logs destination: stdout, file, syslog (stdout if not set)")
      ("logfile",   value<std::string>()->default_value(""),     "Path to logfile (stdout if not set, autodetect if daemon)")
      ("loglevel",  value<std::string>()->default_value("info"), "Set the minimal level of log messages (debug, info, warn, error)")
	  ("family",    value<std::string>()->default_value(""),     "Specify a family, router belongs to")
	  ("datadir",   value<std::string>()->default_value(""),     "Path to storage of i2pd data (RI, keys, peer profiles, ...)")
      ("host",      value<std::string>()->default_value("0.0.0.0"),     "External IP")
      ("port",      value<uint16_t>()->default_value(0),                "Port to listen for incoming connections (default: auto)")
      ("ipv4",      value<bool>()->zero_tokens()->default_value(true),  "Enable communication through ipv4")
      ("ipv6",      value<bool>()->zero_tokens()->default_value(false), "Enable communication through ipv6")
      ("daemon",    value<bool>()->zero_tokens()->default_value(false), "Router will go to background after start")
      ("service",   value<bool>()->zero_tokens()->default_value(false), "Router will use system folders like '/var/lib/i2pd'")
      ("notransit", value<bool>()->zero_tokens()->default_value(false), "Router will not accept transit tunnels at startup")
      ("floodfill", value<bool>()->zero_tokens()->default_value(false), "Router will be floodfill")
      ("bandwidth", value<std::string>()->default_value(""), "Bandwidth limit: integer in kbps or letters: L (32), O (256), P (2048), X (>9000)")
#ifdef _WIN32
      ("svcctl",    value<std::string>()->default_value(""),     "Windows service management ('install' or 'remove')")
      ("insomnia", value<bool>()->zero_tokens()->default_value(false), "Prevent system from sleeping")
      ("close", value<std::string>()->default_value("ask"), "Action on close: minimize, exit, ask") // TODO: add custom validator or something
#endif
      ;
    options_description limits("Limits options");
    limits.add_options()
      ("limits.transit",   value<uint16_t>()->default_value(2500), "Maximum active transit sessions (default:2500)")
      ;

    options_description httpserver("HTTP Server options");
    httpserver.add_options()
      ("http.enabled",        value<bool>()->default_value(true),               "Enable or disable webconsole")
      ("http.address",        value<std::string>()->default_value("127.0.0.1"), "Webconsole listen address")
      ("http.port",           value<uint16_t>()->default_value(7070),           "Webconsole listen port")
      ;

    options_description httpproxy("HTTP Proxy options");
    httpproxy.add_options()
      ("httpproxy.enabled",   value<bool>()->default_value(true),                         "Enable or disable HTTP Proxy")
      ("httpproxy.address",   value<std::string>()->default_value("127.0.0.1"),           "HTTP Proxy listen address")
      ("httpproxy.port",      value<uint16_t>()->default_value(4444),                     "HTTP Proxy listen port")
      ("httpproxy.keys",      value<std::string>()->default_value(""),  "File to persist HTTP Proxy keys")
      ;

    options_description socksproxy("SOCKS Proxy options");
    socksproxy.add_options()
      ("socksproxy.enabled",  value<bool>()->default_value(true),                         "Enable or disable SOCKS Proxy")
      ("socksproxy.address",  value<std::string>()->default_value("127.0.0.1"),           "SOCKS Proxy listen address")
      ("socksproxy.port",     value<uint16_t>()->default_value(4447),                     "SOCKS Proxy listen port")
      ("socksproxy.keys",     value<std::string>()->default_value(""), "File to persist SOCKS Proxy keys")
      ("socksproxy.outproxy", value<std::string>()->default_value("127.0.0.1"), "Upstream outproxy address for SOCKS Proxy")
      ("socksproxy.outproxyport", value<uint16_t>()->default_value(9050), "Upstream outproxy port for SOCKS Proxy")
      ;

    options_description sam("SAM bridge options");
    sam.add_options()
      ("sam.enabled",         value<bool>()->default_value(false),                        "Enable or disable SAM Application bridge")
      ("sam.address",         value<std::string>()->default_value("127.0.0.1"),           "SAM listen address")
      ("sam.port",            value<uint16_t>()->default_value(7656),                     "SAM listen port")
      ;

    options_description bob("BOB options");
    bob.add_options()
      ("bob.enabled",         value<bool>()->default_value(false),                        "Enable or disable BOB command channel")
      ("bob.address",         value<std::string>()->default_value("127.0.0.1"),           "BOB listen address")
      ("bob.port",            value<uint16_t>()->default_value(2827),                     "BOB listen port")
      ;

    options_description i2pcontrol("I2PControl options");
    i2pcontrol.add_options()
      ("i2pcontrol.enabled",  value<bool>()->default_value(false),                        "Enable or disable I2P Control Protocol")
      ("i2pcontrol.address",  value<std::string>()->default_value("127.0.0.1"),           "I2PCP listen address")
      ("i2pcontrol.port",     value<uint16_t>()->default_value(7650),                     "I2PCP listen port")
      ("i2pcontrol.password", value<std::string>()->default_value("itoopie"),             "I2PCP access password")
      ("i2pcontrol.cert",     value<std::string>()->default_value("i2pcontrol.crt.pem"),  "I2PCP connection cerificate")
      ("i2pcontrol.key",      value<std::string>()->default_value("i2pcontrol.key.pem"),  "I2PCP connection cerificate key")
      ;

	options_description precomputation("Precomputation options");
	precomputation.add_options()
	  ("precomputation.elgamal",
#if defined(__x86_64__)
	   value<bool>()->default_value(false),
#else
	   value<bool>()->default_value(true),
#endif
	   "Enable or disable elgamal precomputation table")
	  ;

    m_OptionsDesc
      .add(general)
      .add(httpserver)
      .add(httpproxy)
      .add(socksproxy)
      .add(sam)
      .add(bob)
      .add(i2pcontrol)
	  .add(precomputation)
      ;
  }

  void ParseCmdline(int argc, char* argv[]) {
    try {
      auto style = boost::program_options::command_line_style::unix_style
                 | boost::program_options::command_line_style::allow_long_disguise;
      style &=   ~ boost::program_options::command_line_style::allow_guessing;
      store(parse_command_line(argc, argv, m_OptionsDesc, style, old_syntax_parser), m_Options);
    } catch (boost::program_options::error& e) {
      std::cerr << "args: " << e.what() << std::endl;
      exit(EXIT_FAILURE);
    }

    if (m_Options.count("help") || m_Options.count("h")) {
      std::cout << "i2pd version " << I2PD_VERSION << " (" << I2P_VERSION << ")" << std::endl;
      std::cout << m_OptionsDesc;
      exit(EXIT_SUCCESS);
    }
  }

  void ParseConfig(const std::string& path) {
    if (path == "") return;

    std::ifstream config(path, std::ios::in);

    if (!config.is_open())
	{
      std::cerr << "missing/unreadable config file: " << path << std::endl;
      exit(EXIT_FAILURE);
    }

    try
	{
		store(boost::program_options::parse_config_file(config, m_OptionsDesc), m_Options);
    }
	catch (boost::program_options::error& e)
	{
      std::cerr << e.what() << std::endl;
      exit(EXIT_FAILURE);
    };
  }

  void Finalize() {
    notify(m_Options);
  }

  bool IsDefault(const char *name) {
    if (!m_Options.count(name))
      throw "try to check non-existent option";

    if (m_Options[name].defaulted())
      return true;
    return false;
  }
} // namespace config
} // namespace i2p
<|endoftext|>