<commit_before>#include "memory.h"

#include <cstdint>
#include <string>

namespace dgb {

void Memory::LoadBootloader(const std::string &filename) {
  bootstrap_.reset(new MMapFile(filename));
  bootstrap_is_mapped_ = true;
}

uint8_t Memory::Read8(uint16_t offset) {
  if (bootstrap_is_mapped_ && offset <= 0xff) {  // Bootstrap code.
    return *(reinterpret_cast<uint8_t*>(bootstrap_->memory()) + offset);
  }
  if (offset < 0x8000) return cartridge_->Read8(offset);  // ROM
  if (offset < 0xA000) return display_->Read8(offset - 0x8000);  // VRAM
  if (offset < 0xC000) return cartridge_->Read8(offset);  // Cartridge RAM
  if (0xFE00 <= offset && offset <= 0xFE9F)
    return display_->ReadSprite8(offset - 0xFE00);
  if ((0xFF00 <= offset && offset < 0xFF80) || offset == 0xFFFF) {
    return ReadFromDevice(offset);
  }
  return *GetOffset(offset);
}

// TODO: merge with above
uint8_t *Memory::GetOffset(uint16_t offset) {
  if (bootstrap_is_mapped_ && offset <= 0xff) {  // Bootstrap code.
    return reinterpret_cast<uint8_t*>(bootstrap_->memory()) + offset;
  } else if (offset < 0x8000) {  // ROM

  } else if (offset < 0xA000) {  // Video RAM
    // Fall through (this should never happen)
  } else if (offset < 0xC000) {  // Cartridge RAM

  } else if (offset < 0xE000) {  // Working RAM
    return &wram_[offset - 0xC000];
  } else if (offset < 0xFE00) {  // Echo of working RAM C000-DDFF
    return &wram_[offset - 0xE000];
  } else if (offset < 0xFF80) {
    // Fall through
  } else if (offset < 0xFFFF) {  // High RAM Area.
    return &high_ram_[offset - 0xFF80];
  } else {  // Interrupt enable register.
    // Fall through.
  }

  FATALF("NOT IMPLEMENTED: read from address 0x%04x", 0xffff & offset);
  return nullptr;  // Unreachable.
}

void Memory::Write8(uint16_t offset, uint8_t value) {
  if (offset < 0x8000) return cartridge_->Write8(offset, value);  // ROM
  if (offset < 0xA000) {
    return display_->Write8(offset - 0x8000, value);  // VRAM
  }
  if (offset < 0xC000) return cartridge_->Write8(offset, value);  // Cartridge RAM
  // Sprite Attribute Table
  if (0xFE00 <= offset && offset <= 0xFE9F)
    return display_->WriteSprite8(offset - 0xFE00, value);
  if (0xFEA0 <= offset && offset <= 0xFEFF) {
    WARNINGF("Noop memory write: (0x%04x) <- 0x%02x",
        offset & 0xffff, value & 0xff);
    return;
  }
  if (offset == 0xFF46) return StartDMATransfer(value);
  Write(offset, reinterpret_cast<uint8_t*>(&value), 1);
}

// TODO: merge with above
void Memory::Write(uint16_t offset, uint8_t *value, int length) {
  if (offset < 0x8000) {  // Cartridge ROM

  } else if (offset < 0xA000) {  // Video RAM
    for (int i = 0; i < length; ++i) {
      display_->Write8(offset - 0x8000 + i, *(value + i));
    }
    return;
  } else if (offset < 0xC000) {  // Cartridge RAM
    // Fall through
  } else if (offset < 0xE000) {  // Working RAM
    for (int i = 0; i < length; ++i) {
      wram_[offset - 0xC000 + i] = *(value + i);
    }
    return;
  } else if (offset < 0xFF00) {
    // Fall through
  } else if (offset < 0xFF80) {  // Device registers.
    for (int i = 0; i < length; ++i) {
      WriteToDevice(offset + i, *(value + i));
    }
    return;
  } else if (offset < 0xFFFF) {  // High RAM Area.
    for (int i = 0; i < length; ++i) {
      high_ram_[offset - 0xFF80 + i] = *(value + i);
    }
    return;
  } else {  // Interrupt enable register.
    for (int i = 0; i < length; ++i) {
      WriteToDevice(offset + i, *(value + i));
    }
    return;
  }

  FATALF("NOT IMPLEMENTED: write %d bytes (0x%04x) <- 0x%04x\n",
      length, 0xffff & offset, 0xffff & *reinterpret_cast<uint16_t*>(value));
}

uint8_t Memory::ReadFromDevice(uint16_t offset) {
  if (offset == 0xff00) { return input_->Joypad(); }
  if (offset == 0xff04) { return timers_->Divider(); }
  if (offset == 0xff07) { return timers_->control(); }
  if (offset == 0xff0f) { return interrupt_flag_; }

  // Sound controller registers.
  if (offset == 0xff11) { return sound_controller_->Read8(offset); }
  if (offset == 0xff16) { return sound_controller_->Read8(offset); }
  if (offset == 0xff24) { return sound_controller_->channel_control(); }
  if (offset == 0xff25) { return sound_controller_->output_select(); }
  if (offset == 0xff26) { return sound_controller_->on_off(); }

  // Display registers.
  if (offset == 0xff40) { return display_->Control(); }
  if (offset == 0xff41) { return display_->Status(); }
  if (offset == 0xff42) { return display_->ScrollY(); }
  if (offset == 0xff43) { return display_->ScrollX(); }
  if (offset == 0xff44) { return display_->LCDCY(); }
  if (offset == 0xff45) { return display_->LYC(); }
  if (offset == 0xff48) { return display_->object_palette_0(); }
  if (offset == 0xff49) { return display_->object_palette_1(); }
  if (offset == 0xff4a) { return display_->WindowY(); }
  if (offset == 0xff4b) { return display_->WindowX(); }

  if (offset == 0xffff) { return interrupt_enable_; }

  FATALF("NOT IMPLEMENTED: read from device 0x%04x", offset & 0xffff);
}

void Memory::WriteToDevice(uint16_t offset, uint8_t value) {
  if (offset == 0xff00) {
    input_->SetJoypad(value);
    return;
  }
  if (offset == 0xff01) {  // Serial Transfer Data register.
    //WARNINGF("NOT IMPLEMENTED: write to Serial Transfer Data register "
    //    "(0xff01) <- 0x%02x", value);
    return;
  }
  if (offset == 0xff02) {  // Serial Transfer Control register.
    //WARNINGF("NOT IMPLEMENTED: write to Serial Transfer Control register "
    //    "(0xff02) <- 0x%02x", value);
    return;
  }
  if (offset == 0xff06) {  // Timer Modulo register.
    timers_->set_modulo(value);
    return;
  }
  if (offset == 0xff07) {  // Timer Control register.
    timers_->set_control(value);
    return;
  }
  if (offset == 0xff0f) {  // Interrupt Flag register.
    interrupt_flag_ = value;
    return;
  }
  if (offset == 0xff24) {
    sound_controller_->set_channel_control(value);
    return;
  }
  if (offset == 0xff25) {
    sound_controller_->set_output_select(value);
    return;
  }
  if (offset == 0xff26) {
    sound_controller_->set_on_off(value);
    return;
  }
  if ((0xff10 <= offset && offset <= 0xff23) ||
      (0xff30 <= offset && offset <= 0xff3f)) {  // Sound control registers.
    sound_controller_->Write8(offset, value);
    return;
  }
  if (0xff40 <= offset && offset <= 0xff4b) {  // Display IO registers.
    if (offset == 0xff40) {
      display_->SetControl(value);
    } else if (offset == 0xff41) {
      display_->SetStatus(value);
    } else if (offset == 0xff42) {
      display_->SetScrollY(value);
    } else if (offset == 0xff43) {
      display_->SetScrollX(value);
    } else if (offset == 0xff45) {
      display_->SetLYC(value);
    } else if (offset == 0xff47) {
      display_->SetPalette(value);
    } else if (offset == 0xff48) {
      display_->set_object_palette_0(value);
    } else if (offset == 0xff49) {
      display_->set_object_palette_1(value);
    } else if (offset == 0xff4a) {
      display_->SetWindowY(value);
    } else if (offset == 0xff4b) {
      display_->SetWindowX(value);
    } else {
      FATALF("NOT IMPLEMENTED: write to video device (0x%04x) <- %s",
          offset & 0xffff, ByteBits(value).c_str());
    }
    return;
  }
  if (offset == 0xff50 && value == 1) {  // Unmap the boot rom.
    bootstrap_is_mapped_ = false;
    return;
  }
  if (offset == 0xff7c || offset == 0xff7d || offset == 0xff7e || offset == 0xff7f) {
    // TODO
    ERRORF("NOT IMPLEMENTED: write to device (0x%04x) <- 0x%04x",
        offset & 0xffff, value & 0xff);
    return;
  }
  if (offset == 0xffff) {
    interrupt_enable_ = value;
    return;
  }
  // TODO
  ERRORF("NOT IMPLEMENTED: write to device (0x%04x) <- 0x%04x",
      offset & 0xffff, value & 0xff);
}

void Memory::StartDMATransfer(uint8_t value) {
  // TODO: do this in a separate thread?
  // TODO: restrict CPU access to only HRAM?
  uint16_t src_start = value << 8;
  uint16_t dest_start = 0xFE00;
  for (uint8_t offset = 0; offset < 0xA0; ++offset) {
    // TODO: write directly to sprite attribute table
    Write8(dest_start + offset, Read8(src_start + offset));
  }
}

////////// MockMemoryBus

uint8_t MockMemoryBus::Read8(uint16_t offset) {
  if (expected_ops_.empty()) {
    FATALF("Unexpected Read8(0x%x)", offset);
  }
  ExpectedOp op = expected_ops_.front();
  expected_ops_.pop_front();
  if (op.is_write) {
    FATALF("Unexpected Write8(0x%x), wanted Read8", offset);
  }
  if (op.offset != offset) {
    FATALF("Read8 at unexpected offset: want: 0x%x, got: 0x%x", op.offset, offset);
  }
  return op.value;
}

void MockMemoryBus::Write8(uint16_t offset, uint8_t value) {
  if (expected_ops_.empty()) {
    FATALF("Unexpected Write8(0x%x, 0x%x)", offset, value);
  }
  ExpectedOp op = expected_ops_.front();
  expected_ops_.pop_front();
  if (!op.is_write) {
    FATALF("Unexpected Read8(0x%x), wanted Write8", offset);
  }
  if (op.offset != offset) {
    FATALF("Write at unexpected offset: want: 0x%x, got: 0x%x", op.offset, offset);
  }
  if (op.value != value) {
    FATALF("Write8(0x%x) of unexpected value: want: 0x%x, got: 0x%x", offset, op.value, value);
  }
}

void MockMemoryBus::ExpectRead(uint16_t offset, uint8_t return_value) {
  ExpectedOp op;
  op.offset = offset;
  op.value = return_value;
  expected_ops_.push_back(op);
}

void MockMemoryBus::ExpectWrite(uint16_t offset, uint8_t value) {
  ExpectedOp op;
  op.is_write = true;
  op.offset = offset;
  op.value = value;
  expected_ops_.push_back(op);
}

}  // namespace dgb
<commit_msg>Ignore read/write to CGB speed switch register<commit_after>#include "memory.h"

#include <cstdint>
#include <string>

namespace dgb {

void Memory::LoadBootloader(const std::string &filename) {
  bootstrap_.reset(new MMapFile(filename));
  bootstrap_is_mapped_ = true;
}

uint8_t Memory::Read8(uint16_t offset) {
  if (bootstrap_is_mapped_ && offset <= 0xff) {  // Bootstrap code.
    return *(reinterpret_cast<uint8_t*>(bootstrap_->memory()) + offset);
  }
  if (offset < 0x8000) return cartridge_->Read8(offset);  // ROM
  if (offset < 0xA000) return display_->Read8(offset - 0x8000);  // VRAM
  if (offset < 0xC000) return cartridge_->Read8(offset);  // Cartridge RAM
  if (0xFE00 <= offset && offset <= 0xFE9F)
    return display_->ReadSprite8(offset - 0xFE00);
  if ((0xFF00 <= offset && offset < 0xFF80) || offset == 0xFFFF) {
    return ReadFromDevice(offset);
  }
  return *GetOffset(offset);
}

// TODO: merge with above
uint8_t *Memory::GetOffset(uint16_t offset) {
  if (bootstrap_is_mapped_ && offset <= 0xff) {  // Bootstrap code.
    return reinterpret_cast<uint8_t*>(bootstrap_->memory()) + offset;
  } else if (offset < 0x8000) {  // ROM

  } else if (offset < 0xA000) {  // Video RAM
    // Fall through (this should never happen)
  } else if (offset < 0xC000) {  // Cartridge RAM

  } else if (offset < 0xE000) {  // Working RAM
    return &wram_[offset - 0xC000];
  } else if (offset < 0xFE00) {  // Echo of working RAM C000-DDFF
    return &wram_[offset - 0xE000];
  } else if (offset < 0xFF80) {
    // Fall through
  } else if (offset < 0xFFFF) {  // High RAM Area.
    return &high_ram_[offset - 0xFF80];
  } else {  // Interrupt enable register.
    // Fall through.
  }

  FATALF("NOT IMPLEMENTED: read from address 0x%04x", 0xffff & offset);
  return nullptr;  // Unreachable.
}

void Memory::Write8(uint16_t offset, uint8_t value) {
  if (offset < 0x8000) return cartridge_->Write8(offset, value);  // ROM
  if (offset < 0xA000) {
    return display_->Write8(offset - 0x8000, value);  // VRAM
  }
  if (offset < 0xC000) return cartridge_->Write8(offset, value);  // Cartridge RAM
  // Sprite Attribute Table
  if (0xFE00 <= offset && offset <= 0xFE9F)
    return display_->WriteSprite8(offset - 0xFE00, value);
  if (0xFEA0 <= offset && offset <= 0xFEFF) {
    WARNINGF("Noop memory write: (0x%04x) <- 0x%02x",
        offset & 0xffff, value & 0xff);
    return;
  }
  if (offset == 0xFF46) return StartDMATransfer(value);
  Write(offset, reinterpret_cast<uint8_t*>(&value), 1);
}

// TODO: merge with above
void Memory::Write(uint16_t offset, uint8_t *value, int length) {
  if (offset < 0x8000) {  // Cartridge ROM

  } else if (offset < 0xA000) {  // Video RAM
    for (int i = 0; i < length; ++i) {
      display_->Write8(offset - 0x8000 + i, *(value + i));
    }
    return;
  } else if (offset < 0xC000) {  // Cartridge RAM
    // Fall through
  } else if (offset < 0xE000) {  // Working RAM
    for (int i = 0; i < length; ++i) {
      wram_[offset - 0xC000 + i] = *(value + i);
    }
    return;
  } else if (offset < 0xFF00) {
    // Fall through
  } else if (offset < 0xFF80) {  // Device registers.
    for (int i = 0; i < length; ++i) {
      WriteToDevice(offset + i, *(value + i));
    }
    return;
  } else if (offset < 0xFFFF) {  // High RAM Area.
    for (int i = 0; i < length; ++i) {
      high_ram_[offset - 0xFF80 + i] = *(value + i);
    }
    return;
  } else {  // Interrupt enable register.
    for (int i = 0; i < length; ++i) {
      WriteToDevice(offset + i, *(value + i));
    }
    return;
  }

  FATALF("NOT IMPLEMENTED: write %d bytes (0x%04x) <- 0x%04x\n",
      length, 0xffff & offset, 0xffff & *reinterpret_cast<uint16_t*>(value));
}

uint8_t Memory::ReadFromDevice(uint16_t offset) {
  if (offset == 0xff00) { return input_->Joypad(); }
  if (offset == 0xff04) { return timers_->Divider(); }
  if (offset == 0xff07) { return timers_->control(); }
  if (offset == 0xff0f) { return interrupt_flag_; }

  // Sound controller registers.
  if (offset == 0xff11) { return sound_controller_->Read8(offset); }
  if (offset == 0xff16) { return sound_controller_->Read8(offset); }
  if (offset == 0xff24) { return sound_controller_->channel_control(); }
  if (offset == 0xff25) { return sound_controller_->output_select(); }
  if (offset == 0xff26) { return sound_controller_->on_off(); }

  // Display registers.
  if (offset == 0xff40) { return display_->Control(); }
  if (offset == 0xff41) { return display_->Status(); }
  if (offset == 0xff42) { return display_->ScrollY(); }
  if (offset == 0xff43) { return display_->ScrollX(); }
  if (offset == 0xff44) { return display_->LCDCY(); }
  if (offset == 0xff45) { return display_->LYC(); }
  if (offset == 0xff48) { return display_->object_palette_0(); }
  if (offset == 0xff49) { return display_->object_palette_1(); }
  if (offset == 0xff4a) { return display_->WindowY(); }
  if (offset == 0xff4b) { return display_->WindowX(); }

  if (offset == 0xff4d) {
    INFOF("(CGB only) read from CGB speed switch register 0x%04x", offset & 0xffff);
    return 0x00;
  }

  if (offset == 0xffff) { return interrupt_enable_; }

  FATALF("NOT IMPLEMENTED: read from device 0x%04x", offset & 0xffff);
}

void Memory::WriteToDevice(uint16_t offset, uint8_t value) {
  if (offset == 0xff00) {
    input_->SetJoypad(value);
    return;
  }
  if (offset == 0xff01) {  // Serial Transfer Data register.
    //WARNINGF("NOT IMPLEMENTED: write to Serial Transfer Data register "
    //    "(0xff01) <- 0x%02x", value);
    return;
  }
  if (offset == 0xff02) {  // Serial Transfer Control register.
    //WARNINGF("NOT IMPLEMENTED: write to Serial Transfer Control register "
    //    "(0xff02) <- 0x%02x", value);
    return;
  }
  if (offset == 0xff06) {  // Timer Modulo register.
    timers_->set_modulo(value);
    return;
  }
  if (offset == 0xff07) {  // Timer Control register.
    timers_->set_control(value);
    return;
  }
  if (offset == 0xff0f) {  // Interrupt Flag register.
    interrupt_flag_ = value;
    return;
  }
  if (offset == 0xff24) {
    sound_controller_->set_channel_control(value);
    return;
  }
  if (offset == 0xff25) {
    sound_controller_->set_output_select(value);
    return;
  }
  if (offset == 0xff26) {
    sound_controller_->set_on_off(value);
    return;
  }
  if ((0xff10 <= offset && offset <= 0xff23) ||
      (0xff30 <= offset && offset <= 0xff3f)) {  // Sound control registers.
    sound_controller_->Write8(offset, value);
    return;
  }
  if (0xff40 <= offset && offset <= 0xff4b) {  // Display IO registers.
    if (offset == 0xff40) {
      display_->SetControl(value);
    } else if (offset == 0xff41) {
      display_->SetStatus(value);
    } else if (offset == 0xff42) {
      display_->SetScrollY(value);
    } else if (offset == 0xff43) {
      display_->SetScrollX(value);
    } else if (offset == 0xff45) {
      display_->SetLYC(value);
    } else if (offset == 0xff47) {
      display_->SetPalette(value);
    } else if (offset == 0xff48) {
      display_->set_object_palette_0(value);
    } else if (offset == 0xff49) {
      display_->set_object_palette_1(value);
    } else if (offset == 0xff4a) {
      display_->SetWindowY(value);
    } else if (offset == 0xff4b) {
      display_->SetWindowX(value);
    } else {
      FATALF("NOT IMPLEMENTED: write to video device (0x%04x) <- %s",
          offset & 0xffff, ByteBits(value).c_str());
    }
    return;
  }
  if (offset == 0xff4d) {
    // CGB speed switch register - actual functionality is only relevant for GBColor, so we'll just
    // do nothing.
    INFOF("(not implemented) write to CGB speed switch register (0x%04x) <- %s",
        offset & 0xffff, ByteBits(value).c_str());
  }
  if (offset == 0xff50 && value == 1) {  // Unmap the boot rom.
    bootstrap_is_mapped_ = false;
    return;
  }
  if (offset == 0xff7c || offset == 0xff7d || offset == 0xff7e || offset == 0xff7f) {
    // TODO
    ERRORF("NOT IMPLEMENTED: write to device (0x%04x) <- 0x%04x",
        offset & 0xffff, value & 0xff);
    return;
  }
  if (offset == 0xffff) {
    interrupt_enable_ = value;
    return;
  }
  // TODO
  ERRORF("NOT IMPLEMENTED: write to device (0x%04x) <- 0x%04x",
      offset & 0xffff, value & 0xff);
}

void Memory::StartDMATransfer(uint8_t value) {
  // TODO: do this in a separate thread?
  // TODO: restrict CPU access to only HRAM?
  uint16_t src_start = value << 8;
  uint16_t dest_start = 0xFE00;
  for (uint8_t offset = 0; offset < 0xA0; ++offset) {
    // TODO: write directly to sprite attribute table
    Write8(dest_start + offset, Read8(src_start + offset));
  }
}

////////// MockMemoryBus

uint8_t MockMemoryBus::Read8(uint16_t offset) {
  if (expected_ops_.empty()) {
    FATALF("Unexpected Read8(0x%x)", offset);
  }
  ExpectedOp op = expected_ops_.front();
  expected_ops_.pop_front();
  if (op.is_write) {
    FATALF("Unexpected Write8(0x%x), wanted Read8", offset);
  }
  if (op.offset != offset) {
    FATALF("Read8 at unexpected offset: want: 0x%x, got: 0x%x", op.offset, offset);
  }
  return op.value;
}

void MockMemoryBus::Write8(uint16_t offset, uint8_t value) {
  if (expected_ops_.empty()) {
    FATALF("Unexpected Write8(0x%x, 0x%x)", offset, value);
  }
  ExpectedOp op = expected_ops_.front();
  expected_ops_.pop_front();
  if (!op.is_write) {
    FATALF("Unexpected Read8(0x%x), wanted Write8", offset);
  }
  if (op.offset != offset) {
    FATALF("Write at unexpected offset: want: 0x%x, got: 0x%x", op.offset, offset);
  }
  if (op.value != value) {
    FATALF("Write8(0x%x) of unexpected value: want: 0x%x, got: 0x%x", offset, op.value, value);
  }
}

void MockMemoryBus::ExpectRead(uint16_t offset, uint8_t return_value) {
  ExpectedOp op;
  op.offset = offset;
  op.value = return_value;
  expected_ops_.push_back(op);
}

void MockMemoryBus::ExpectWrite(uint16_t offset, uint8_t value) {
  ExpectedOp op;
  op.is_write = true;
  op.offset = offset;
  op.value = value;
  expected_ops_.push_back(op);
}

}  // namespace dgb
<|endoftext|>


<commit_before>AliAnalysisTask *AddTaskHFECalPbPbSys(int trigtype, int TPCclust, int Nits, double nSigMim, double Mimeop, double Maxeop, int PIDorder, int sysID){
  //get the current analysis manager
  AliAnalysisManager *mgr = AliAnalysisManager::GetAnalysisManager();
  if (!mgr) {
    Error("AddTaskHFE", "No analysis manager found.");
    return NULL;
  }
  if (!mgr->GetInputEventHandler()) {
    ::Error("AddTaskHFE", "This task requires an input event handler");
    return NULL;
  }
  TString type = mgr->GetInputEventHandler()->GetDataType(); // can be "ESD" or "AOD"
  if (type=="AOD"){
    ::Error("AddTaskHFE", "The tasks exits because AODs are in input");
    return NULL;
  }
  Bool_t MCthere=kFALSE;
  AliMCEventHandler *mcH = dynamic_cast<AliMCEventHandler*>(mgr->GetMCtruthEventHandler());
  if(!mcH){
    MCthere=kFALSE;
  }else{
    MCthere=kTRUE;
  }
  cout<<"AddTaskHFE - MC config is: "<<MCthere<<endl;

  //============= Set Task Name ===================
  //TString taskName=("AliAnalysisTaskHFE.cxx+");
  //===============================================

  gROOT->LoadMacro("$ALICE_ROOT/PWGHF/hfe/macros/configs/PbPb/ConfigHFECalSys_PbPb.C");

  AliAnalysisTaskHFE *hfetask = ConfigHFECalSys_PbPb(MCthere,TPCclust,Nits,nSigMim,Mimeop,Maxeop,PIDorder);
  //RequestMemory(hfetask, 250*1024);
  if(trigtype==0)hfetask->SelectCollisionCandidates(AliVEvent::kEMCEGA);
  if(trigtype==1)hfetask->SelectCollisionCandidates(AliVEvent::kCentral);
  if(trigtype==2)hfetask->SelectCollisionCandidates(AliVEvent::kSemiCentral);
  if(trigtype==3)hfetask->SelectCollisionCandidates(AliVEvent::kMB);
  if(trigtype==4)hfetask->SelectCollisionCandidates(AliVEvent::kEMCEJE);
  mgr->AddTask(hfetask);

  int inSig = (int)(nSigMim*10.0);
  int iMimeop = (int)(Mimeop*10.0);
  int iMaxeop = (int)(Maxeop*10.0);

  //find input container
  AliAnalysisDataContainer *cinput  = mgr->GetCommonInputContainer();
  TString containerName = mgr->GetCommonFileName();
  TString appendix(TString::Format(":PWGHF_hfeCalPbPbTrig%dTPC%dITS%dnSig%dMimeop%dMaxeop%dPID%d",trigtype,TPCclust,Nits,inSig,iMimeop,iMaxeop,PIDorder));
  //if(trigtype==1)appendix(TString::Format(":PWGHF_hfeCentTPC%dITS%dnSig%dMimeop%dMaxeop%dPID%d",TPCclust,Nits,inSig,iMimeop,iMaxeop,PIDorder));
  //if(trigtype==2)appendix(TString::Format(":PWGHF_hfeSemiTPC%dITS%dnSig%dMimeop%dMaxeop%dPID%d",TPCclust,Nits,inSig,iMimeop,iMaxeop,PIDorder));
  //if(trigtype==3)appendix(TString::Format(":PWGHF_hfekMBTPC%dITS%dnSig%dMimeop%dMaxeop%dPID%d",TPCclust,Nits,inSig,iMimeop,iMaxeop,PIDorder));
  //containerName += ":PWGHF_hfeCalPbPbEGA";
  containerName += appendix;

  TString Output1(TString::Format("HFE_Results_EMCALSys_SysID%d",sysID));
  TString Output2(TString::Format("HFE_QA_EMCALSYS_SysID%d",sysID));

  hfetask->ConnectOutput(1, mgr->CreateContainer(Output1, TList::Class(),
						 AliAnalysisManager::kOutputContainer, containerName.Data()));
  hfetask->ConnectOutput(2, mgr->CreateContainer(Output2, TList::Class(),
					         AliAnalysisManager::kOutputContainer, containerName.Data()));

  /*
  hfetask->ConnectOutput(1, mgr->CreateContainer("HFE_Results_EMCALSys", TList::Class(),
						 AliAnalysisManager::kOutputContainer, containerName.Data()));
  hfetask->ConnectOutput(2, mgr->CreateContainer("HFE_QA_EMCALSys", TList::Class(),
					      AliAnalysisManager::kOutputContainer, containerName.Data()));
  */
  mgr->ConnectInput  (hfetask,  0, cinput );

  /*
  //<--- task2 for central trigger

  AliAnalysisTaskHFE *hfetask2 = ConfigHFECalstandard_PbPb(MCthere,TPCclust);
  hfetask2->SelectCollisionCandidates(AliVEvent::kCentral);
  mgr->AddTask(hfetask2);

  //find input container
  TString containerName2 = mgr->GetCommonFileName();
  containerName2 += ":PWGHF_hfeCalPbPbCent";

  hfetask2->ConnectOutput(1, mgr->CreateContainer("HFE_Results_EMCALCent", TList::Class(),
						 AliAnalysisManager::kOutputContainer, containerName2.Data()));
  hfetask2->ConnectOutput(2, mgr->CreateContainer("HFE_QA_EMCALCent", TList::Class(),
					      AliAnalysisManager::kOutputContainer, containerName2.Data()));

  mgr->ConnectInput  (hfetask2,  0, cinput );
  */

/*
  AliAnalysisTaskHFE *trdtask = ConfigHFEtrd(MCthere);

  //----------------------
  //create data containers
  //----------------------

  trdtask->ConnectOutput(1, mgr->CreateContainer("HFE_Results", TList::Class(),
					      AliAnalysisManager::kOutputContainer, containerName.Data()));
  trdtask->ConnectOutput(2, mgr->CreateContainer("HFE_QA", TList::Class(),
					      AliAnalysisManager::kOutputContainer, containerName.Data()));
  mgr->ConnectInput  (trdtask,  0, cinput );
*/

  //return hfetask;
  return NULL;
}
<commit_msg>added a cut selection<commit_after>AliAnalysisTask *AddTaskHFECalPbPbSys(int trigtype, int TPCclust, int Nits, int ITSstat,double nSigMim, double Mimeop, double Maxeop, int PIDorder, int sysID){
  //get the current analysis manager
  AliAnalysisManager *mgr = AliAnalysisManager::GetAnalysisManager();
  if (!mgr) {
    Error("AddTaskHFE", "No analysis manager found.");
    return NULL;
  }
  if (!mgr->GetInputEventHandler()) {
    ::Error("AddTaskHFE", "This task requires an input event handler");
    return NULL;
  }
  TString type = mgr->GetInputEventHandler()->GetDataType(); // can be "ESD" or "AOD"
  if (type=="AOD"){
    ::Error("AddTaskHFE", "The tasks exits because AODs are in input");
    return NULL;
  }
  Bool_t MCthere=kFALSE;
  AliMCEventHandler *mcH = dynamic_cast<AliMCEventHandler*>(mgr->GetMCtruthEventHandler());
  if(!mcH){
    MCthere=kFALSE;
  }else{
    MCthere=kTRUE;
  }
  cout<<"AddTaskHFE - MC config is: "<<MCthere<<endl;

  //============= Set Task Name ===================
  //TString taskName=("AliAnalysisTaskHFE.cxx+");
  //===============================================

  gROOT->LoadMacro("$ALICE_ROOT/PWGHF/hfe/macros/configs/PbPb/ConfigHFECalSys_PbPb.C");

  AliAnalysisTaskHFE *hfetask = ConfigHFECalSys_PbPb(MCthere,TPCclust,Nits,ITSstat,nSigMim,Mimeop,Maxeop,PIDorder);
  //RequestMemory(hfetask, 250*1024);
  if(trigtype==0)hfetask->SelectCollisionCandidates(AliVEvent::kEMCEGA);
  if(trigtype==1)hfetask->SelectCollisionCandidates(AliVEvent::kCentral);
  if(trigtype==2)hfetask->SelectCollisionCandidates(AliVEvent::kSemiCentral);
  if(trigtype==3)hfetask->SelectCollisionCandidates(AliVEvent::kMB);
  if(trigtype==4)hfetask->SelectCollisionCandidates(AliVEvent::kEMCEJE);
  mgr->AddTask(hfetask);

  int inSig = (int)(nSigMim*10.0);
  int iMimeop = (int)(Mimeop*10.0);
  int iMaxeop = (int)(Maxeop*10.0);

  //find input container
  AliAnalysisDataContainer *cinput  = mgr->GetCommonInputContainer();
  TString containerName = mgr->GetCommonFileName();
  TString appendix(TString::Format(":PWGHF_hfeCalPbPbTrig%dTPC%dITS%dITSLay%dnSig%dMimeop%dMaxeop%dPID%d",trigtype,TPCclust,Nits,ITSstat,inSig,iMimeop,iMaxeop,PIDorder));
  //if(trigtype==1)appendix(TString::Format(":PWGHF_hfeCentTPC%dITS%dnSig%dMimeop%dMaxeop%dPID%d",TPCclust,Nits,inSig,iMimeop,iMaxeop,PIDorder));
  //if(trigtype==2)appendix(TString::Format(":PWGHF_hfeSemiTPC%dITS%dnSig%dMimeop%dMaxeop%dPID%d",TPCclust,Nits,inSig,iMimeop,iMaxeop,PIDorder));
  //if(trigtype==3)appendix(TString::Format(":PWGHF_hfekMBTPC%dITS%dnSig%dMimeop%dMaxeop%dPID%d",TPCclust,Nits,inSig,iMimeop,iMaxeop,PIDorder));
  //containerName += ":PWGHF_hfeCalPbPbEGA";
  containerName += appendix;

  TString Output1(TString::Format("HFE_Results_EMCALSys_SysID%d",sysID));
  TString Output2(TString::Format("HFE_QA_EMCALSYS_SysID%d",sysID));

  hfetask->ConnectOutput(1, mgr->CreateContainer(Output1, TList::Class(),
						 AliAnalysisManager::kOutputContainer, containerName.Data()));
  hfetask->ConnectOutput(2, mgr->CreateContainer(Output2, TList::Class(),
					         AliAnalysisManager::kOutputContainer, containerName.Data()));

  /*
  hfetask->ConnectOutput(1, mgr->CreateContainer("HFE_Results_EMCALSys", TList::Class(),
						 AliAnalysisManager::kOutputContainer, containerName.Data()));
  hfetask->ConnectOutput(2, mgr->CreateContainer("HFE_QA_EMCALSys", TList::Class(),
					      AliAnalysisManager::kOutputContainer, containerName.Data()));
  */
  mgr->ConnectInput  (hfetask,  0, cinput );

  /*
  //<--- task2 for central trigger

  AliAnalysisTaskHFE *hfetask2 = ConfigHFECalstandard_PbPb(MCthere,TPCclust);
  hfetask2->SelectCollisionCandidates(AliVEvent::kCentral);
  mgr->AddTask(hfetask2);

  //find input container
  TString containerName2 = mgr->GetCommonFileName();
  containerName2 += ":PWGHF_hfeCalPbPbCent";

  hfetask2->ConnectOutput(1, mgr->CreateContainer("HFE_Results_EMCALCent", TList::Class(),
						 AliAnalysisManager::kOutputContainer, containerName2.Data()));
  hfetask2->ConnectOutput(2, mgr->CreateContainer("HFE_QA_EMCALCent", TList::Class(),
					      AliAnalysisManager::kOutputContainer, containerName2.Data()));

  mgr->ConnectInput  (hfetask2,  0, cinput );
  */

/*
  AliAnalysisTaskHFE *trdtask = ConfigHFEtrd(MCthere);

  //----------------------
  //create data containers
  //----------------------

  trdtask->ConnectOutput(1, mgr->CreateContainer("HFE_Results", TList::Class(),
					      AliAnalysisManager::kOutputContainer, containerName.Data()));
  trdtask->ConnectOutput(2, mgr->CreateContainer("HFE_QA", TList::Class(),
					      AliAnalysisManager::kOutputContainer, containerName.Data()));
  mgr->ConnectInput  (trdtask,  0, cinput );
*/

  //return hfetask;
  return NULL;
}
<|endoftext|>


<commit_before>// mfcSimpleView.cpp : implementation of the CSimpleView class
//
// Copyright (c) 2001 Virtual Terrain Project
// Free for all uses, see license.txt for details.
//

#include "stdafx.h"
#include "mfcSimple.h"

#include "mfcSimpleDoc.h"
#include "mfcSimpleView.h"

bool CreateScene();
void CleanupScene();

// Header for the vtlib library
#include "vtlib/vtlib.h"
#include "vtlib/core/Terrain.h"
#include "vtlib/core/TerrainScene.h"
#include "vtlib/core/NavEngines.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

/////////////////////////////////////////////////////////////////////////////
// CSimpleView

IMPLEMENT_DYNCREATE(CSimpleView, CView)

BEGIN_MESSAGE_MAP(CSimpleView, CView)
	//{{AFX_MSG_MAP(CSimpleView)
	ON_WM_DESTROY()
	ON_WM_CREATE()
	ON_WM_SIZE()
	ON_WM_PAINT()
	ON_WM_LBUTTONDOWN()
	ON_WM_LBUTTONUP()
	ON_WM_MOUSEMOVE()
	ON_WM_RBUTTONDOWN()
	ON_WM_RBUTTONUP()
	ON_WM_MBUTTONDOWN()
	ON_WM_MBUTTONUP()
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CSimpleView construction/destruction

CSimpleView::CSimpleView()
{
	m_hGLContext = NULL;
	m_GLPixelIndex = 0;
}

CSimpleView::~CSimpleView()
{
}

BOOL CSimpleView::PreCreateWindow(CREATESTRUCT& cs)
{
	// TODO: Modify the Window class or styles here by modifying
	//  the CREATESTRUCT cs

	return CView::PreCreateWindow(cs);
}

/////////////////////////////////////////////////////////////////////////////
// CSimpleView diagnostics

#ifdef _DEBUG
void CSimpleView::AssertValid() const
{
	CView::AssertValid();
}

void CSimpleView::Dump(CDumpContext& dc) const
{
	CView::Dump(dc);
}

CSimpleDoc* CSimpleView::GetDocument() // non-debug version is inline
{
	ASSERT(m_pDocument->IsKindOf(RUNTIME_CLASS(CSimpleDoc)));
	return (CSimpleDoc*)m_pDocument;
}
#endif //_DEBUG

void CSimpleView::OnDraw(CDC* pDC)
{
	CSimpleDoc* pDoc = GetDocument();
	ASSERT_VALID(pDoc);
}

/////////////////////////////////////////////////////////////////////////////
// CSimpleView message handlers
// set Windows Pixel Format
BOOL CSimpleView::SetWindowPixelFormat(HDC hDC)
{
	PIXELFORMATDESCRIPTOR pixelDesc;

	pixelDesc.nSize = sizeof(PIXELFORMATDESCRIPTOR);
	pixelDesc.nVersion = 1;

	pixelDesc.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL |
		PFD_DOUBLEBUFFER | PFD_STEREO_DONTCARE;

	pixelDesc.iPixelType = PFD_TYPE_RGBA;
	pixelDesc.cColorBits = 32;
	pixelDesc.cRedBits = 8;
	pixelDesc.cRedShift = 16;
	pixelDesc.cGreenBits = 8;
	pixelDesc.cGreenShift = 8;
	pixelDesc.cBlueBits = 8;
	pixelDesc.cBlueShift = 0;
	pixelDesc.cAlphaBits = 0;
	pixelDesc.cAlphaShift = 0;
	pixelDesc.cAccumBits = 64;
	pixelDesc.cAccumRedBits = 16;
	pixelDesc.cAccumGreenBits = 16;
	pixelDesc.cAccumBlueBits = 16;
	pixelDesc.cAccumAlphaBits = 0;
	pixelDesc.cDepthBits = 32;
	pixelDesc.cStencilBits = 8;
	pixelDesc.cAuxBuffers = 0;
	pixelDesc.iLayerType = PFD_MAIN_PLANE;
	pixelDesc.bReserved = 0;
	pixelDesc.dwLayerMask = 0;
	pixelDesc.dwVisibleMask = 0;
	pixelDesc.dwDamageMask = 0;

	m_GLPixelIndex = ChoosePixelFormat(hDC,&pixelDesc);
	if (m_GLPixelIndex == 0) // Choose default
	{
		m_GLPixelIndex = 1;
		if (DescribePixelFormat(hDC,m_GLPixelIndex,
			sizeof(PIXELFORMATDESCRIPTOR),&pixelDesc)==0)
			return FALSE;
	}

	if (!SetPixelFormat(hDC,m_GLPixelIndex,&pixelDesc))
		return FALSE;

	return TRUE;
}

//********************************************
// CreateViewGLContext
// Create an OpenGL rendering context
//********************************************
BOOL CSimpleView::CreateViewGLContext(HDC hDC)
{
	m_hGLContext = wglCreateContext(hDC);

	if (m_hGLContext==NULL)
		return FALSE;

	if (wglMakeCurrent(hDC,m_hGLContext)==FALSE)
		return FALSE;

	return TRUE;
}

void CSimpleView::OnDestroy()
{
	CleanupScene();

	if (wglGetCurrentContext() != NULL)
		wglMakeCurrent(NULL,NULL);
	if (m_hGLContext != NULL)
	{
		wglDeleteContext(m_hGLContext);
		m_hGLContext = NULL;
	}
	CView::OnDestroy();
}

int CSimpleView::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
	if (CView::OnCreate(lpCreateStruct) == -1)
		return -1;
	HWND hWnd = GetSafeHwnd();
	HDC hDC = ::GetDC(hWnd);

	if (SetWindowPixelFormat(hDC)==FALSE)
		return 0;

	if (CreateViewGLContext(hDC)==FALSE)
		return 0;
	return CreateScene();
}

void CSimpleView::OnSize(UINT nType, int cx, int cy)
{
	CView::OnSize(nType, cx, cy);
	glViewport(0,0,cx, cy);
	vtGetScene()->SetWindowSize(cx, cy);
}

void CSimpleView::OnPaint()
{
	CPaintDC dc(this); // device context for painting

	// Render the scene
	vtGetScene()->DoUpdate();
	//this would occur, for example, after your call to glClear() and before calling SwapBuffers()
	SwapBuffers(dc.m_ps.hdc);
	InvalidateRect(NULL,FALSE);	//for Continuous Rendering
}

//-----------------------The Following is VTerrain Code-----------------

vtTerrainScene *ts = NULL;

//
// Create the 3d scene
//
bool CreateScene()
{
	// Get a handle to the vtScene - one is already created for you
	vtScene *pScene = vtGetScene();
	pScene->Init();

	// Look up the camera
	vtCamera *pCamera = pScene->GetCamera();
	pCamera->SetHither(10);
	pCamera->SetYon(100000);

	// The  terrain scene will contain all the terrains that are created.
	ts = new vtTerrainScene;

	// Set the global data path
	vtStringArray paths;
	paths.push_back(vtString("Data/"));
	pScene->SetDataPath(paths);

	// Begin creating the scene, including the sun and sky
	vtGroup *pTopGroup = ts->BeginTerrainScene();

	// Tell the scene graph to point to this terrain scene
	pScene->SetRoot(pTopGroup);

	// Create a new vtTerrain, read its paramters from a file
	vtTerrain *pTerr = new vtTerrain;
	pTerr->SetParamFile("Data/Simple.xml");

	// Add the terrain to the scene, and contruct it
	ts->AppendTerrain(pTerr);
	if (!ts->BuildTerrain(pTerr))
	{
		AfxMessageBox("Terrain creation failed.");
		return false;
	}

	ts->SetCurrentTerrain(pTerr);

	// Create a navigation engine to move around on the terrain
	// Get flight speed from terrain parameters
	float fSpeed = pTerr->GetParams().GetValueFloat(STR_NAVSPEED);

	vtTerrainFlyer *pFlyer = new vtTerrainFlyer(fSpeed);
	pFlyer->SetTarget(pCamera);
	pFlyer->SetHeightField(pTerr->GetHeightField());
	pScene->AddEngine(pFlyer);

	// Minimum height over terrain is 100 m
	vtHeightConstrain *pConstrain = new vtHeightConstrain(100);
	pConstrain->SetTarget(pCamera);
	pConstrain->SetHeightField(pTerr->GetHeightField());
	pScene->AddEngine(pConstrain);

	return true;
}

void CleanupScene()
{
	vtGetScene()->SetRoot(NULL);
	if (ts)
	{
		ts->CleanupScene();
		delete ts;
	}
	vtGetScene()->Shutdown();
}

//--------------Mouse EVENTS-----------------

//
// turn MFC events flags in VT flags
//
int MFCFlagsToVT(int nFlags)
{
	int flags = 0;
	if ( (nFlags & MK_CONTROL)!=0 )
		flags |= VT_CONTROL;
	if ( (nFlags & MK_SHIFT)!=0 )
		flags |= VT_SHIFT;
	return flags;
}

//
// turn MFC mouse events into VT mouse events
//
void CSimpleView::OnMouseMove(UINT nFlags, CPoint point)
{
	vtMouseEvent event;

	event.type = VT_MOVE;
	event.button = VT_NONE;
	event.flags = MFCFlagsToVT(nFlags);
	event.pos.Set(point.x,point.y);

	vtGetScene()->OnMouse(event);
}

void CSimpleView::OnLButtonUp(UINT nFlags, CPoint point)
{
	vtMouseEvent event;

	event.type = VT_UP;
	event.button = VT_LEFT;
	event.flags = MFCFlagsToVT(nFlags);
	event.pos.Set(point.x,point.y);

	vtGetScene()->OnMouse(event);
}

void CSimpleView::OnLButtonDown(UINT nFlags, CPoint point)
{
	vtMouseEvent event;

	event.type = VT_DOWN;
	event.button = VT_LEFT;
	event.flags = MFCFlagsToVT(nFlags);
	event.pos.Set(point.x,point.y);

	vtGetScene()->OnMouse(event);
}

void CSimpleView::OnRButtonDown(UINT nFlags, CPoint point)
{
	vtMouseEvent event;

	event.type = VT_DOWN;
	event.button = VT_RIGHT;
	event.flags = MFCFlagsToVT(nFlags);
	event.pos.Set(point.x,point.y);

	vtGetScene()->OnMouse(event);
}

void CSimpleView::OnRButtonUp(UINT nFlags, CPoint point)
{
	vtMouseEvent event;

	event.type = VT_UP;
	event.button = VT_RIGHT;
	event.flags = MFCFlagsToVT(nFlags);
	event.pos.Set(point.x,point.y);

	vtGetScene()->OnMouse(event);
}

void CSimpleView::OnMButtonDown(UINT nFlags, CPoint point)
{
	vtMouseEvent event;

	event.type = VT_DOWN;
	event.button = VT_MIDDLE;
	event.flags = MFCFlagsToVT(nFlags);
	event.pos.Set(point.x,point.y);

	vtGetScene()->OnMouse(event);
}

void CSimpleView::OnMButtonUp(UINT nFlags, CPoint point)
{
	vtMouseEvent event;

	event.type = VT_UP;
	event.button = VT_MIDDLE;
	event.flags = MFCFlagsToVT(nFlags);
	event.pos.Set(point.x,point.y);

	vtGetScene()->OnMouse(event);
}

<commit_msg>use global data path, increase Yon<commit_after>// mfcSimpleView.cpp : implementation of the CSimpleView class
//
// Copyright (c) 2001 Virtual Terrain Project
// Free for all uses, see license.txt for details.
//

#include "stdafx.h"
#include "mfcSimple.h"

#include "mfcSimpleDoc.h"
#include "mfcSimpleView.h"

bool CreateScene();
void CleanupScene();

// Header for the vtlib library
#include "vtlib/vtlib.h"
#include "vtlib/core/Terrain.h"
#include "vtlib/core/TerrainScene.h"
#include "vtlib/core/NavEngines.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

/////////////////////////////////////////////////////////////////////////////
// CSimpleView

IMPLEMENT_DYNCREATE(CSimpleView, CView)

BEGIN_MESSAGE_MAP(CSimpleView, CView)
	//{{AFX_MSG_MAP(CSimpleView)
	ON_WM_DESTROY()
	ON_WM_CREATE()
	ON_WM_SIZE()
	ON_WM_PAINT()
	ON_WM_LBUTTONDOWN()
	ON_WM_LBUTTONUP()
	ON_WM_MOUSEMOVE()
	ON_WM_RBUTTONDOWN()
	ON_WM_RBUTTONUP()
	ON_WM_MBUTTONDOWN()
	ON_WM_MBUTTONUP()
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CSimpleView construction/destruction

CSimpleView::CSimpleView()
{
	m_hGLContext = NULL;
	m_GLPixelIndex = 0;
}

CSimpleView::~CSimpleView()
{
}

BOOL CSimpleView::PreCreateWindow(CREATESTRUCT& cs)
{
	// TODO: Modify the Window class or styles here by modifying
	//  the CREATESTRUCT cs

	return CView::PreCreateWindow(cs);
}

/////////////////////////////////////////////////////////////////////////////
// CSimpleView diagnostics

#ifdef _DEBUG
void CSimpleView::AssertValid() const
{
	CView::AssertValid();
}

void CSimpleView::Dump(CDumpContext& dc) const
{
	CView::Dump(dc);
}

CSimpleDoc* CSimpleView::GetDocument() // non-debug version is inline
{
	ASSERT(m_pDocument->IsKindOf(RUNTIME_CLASS(CSimpleDoc)));
	return (CSimpleDoc*)m_pDocument;
}
#endif //_DEBUG

void CSimpleView::OnDraw(CDC* pDC)
{
	CSimpleDoc* pDoc = GetDocument();
	ASSERT_VALID(pDoc);
}

/////////////////////////////////////////////////////////////////////////////
// CSimpleView message handlers
// set Windows Pixel Format
BOOL CSimpleView::SetWindowPixelFormat(HDC hDC)
{
	PIXELFORMATDESCRIPTOR pixelDesc;

	pixelDesc.nSize = sizeof(PIXELFORMATDESCRIPTOR);
	pixelDesc.nVersion = 1;

	pixelDesc.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL |
		PFD_DOUBLEBUFFER | PFD_STEREO_DONTCARE;

	pixelDesc.iPixelType = PFD_TYPE_RGBA;
	pixelDesc.cColorBits = 32;
	pixelDesc.cRedBits = 8;
	pixelDesc.cRedShift = 16;
	pixelDesc.cGreenBits = 8;
	pixelDesc.cGreenShift = 8;
	pixelDesc.cBlueBits = 8;
	pixelDesc.cBlueShift = 0;
	pixelDesc.cAlphaBits = 0;
	pixelDesc.cAlphaShift = 0;
	pixelDesc.cAccumBits = 64;
	pixelDesc.cAccumRedBits = 16;
	pixelDesc.cAccumGreenBits = 16;
	pixelDesc.cAccumBlueBits = 16;
	pixelDesc.cAccumAlphaBits = 0;
	pixelDesc.cDepthBits = 32;
	pixelDesc.cStencilBits = 8;
	pixelDesc.cAuxBuffers = 0;
	pixelDesc.iLayerType = PFD_MAIN_PLANE;
	pixelDesc.bReserved = 0;
	pixelDesc.dwLayerMask = 0;
	pixelDesc.dwVisibleMask = 0;
	pixelDesc.dwDamageMask = 0;

	m_GLPixelIndex = ChoosePixelFormat(hDC,&pixelDesc);
	if (m_GLPixelIndex == 0) // Choose default
	{
		m_GLPixelIndex = 1;
		if (DescribePixelFormat(hDC,m_GLPixelIndex,
			sizeof(PIXELFORMATDESCRIPTOR),&pixelDesc)==0)
			return FALSE;
	}

	if (!SetPixelFormat(hDC,m_GLPixelIndex,&pixelDesc))
		return FALSE;

	return TRUE;
}

//********************************************
// CreateViewGLContext
// Create an OpenGL rendering context
//********************************************
BOOL CSimpleView::CreateViewGLContext(HDC hDC)
{
	m_hGLContext = wglCreateContext(hDC);

	if (m_hGLContext==NULL)
		return FALSE;

	if (wglMakeCurrent(hDC,m_hGLContext)==FALSE)
		return FALSE;

	return TRUE;
}

void CSimpleView::OnDestroy()
{
	CleanupScene();

	if (wglGetCurrentContext() != NULL)
		wglMakeCurrent(NULL,NULL);
	if (m_hGLContext != NULL)
	{
		wglDeleteContext(m_hGLContext);
		m_hGLContext = NULL;
	}
	CView::OnDestroy();
}

int CSimpleView::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
	if (CView::OnCreate(lpCreateStruct) == -1)
		return -1;
	HWND hWnd = GetSafeHwnd();
	HDC hDC = ::GetDC(hWnd);

	if (SetWindowPixelFormat(hDC)==FALSE)
		return 0;

	if (CreateViewGLContext(hDC)==FALSE)
		return 0;
	return CreateScene();
}

void CSimpleView::OnSize(UINT nType, int cx, int cy)
{
	CView::OnSize(nType, cx, cy);
	glViewport(0,0,cx, cy);
	vtGetScene()->SetWindowSize(cx, cy);
}

void CSimpleView::OnPaint()
{
	CPaintDC dc(this); // device context for painting

	// Render the scene
	vtGetScene()->DoUpdate();
	//this would occur, for example, after your call to glClear() and before calling SwapBuffers()
	SwapBuffers(dc.m_ps.hdc);
	InvalidateRect(NULL,FALSE);	//for Continuous Rendering
}

//-----------------------The Following is VTerrain Code-----------------

vtTerrainScene *ts = NULL;

//
// Create the 3d scene
//
bool CreateScene()
{
	// Get a handle to the vtScene - one is already created for you
	vtScene *pScene = vtGetScene();
	pScene->Init();

	// Look up the camera
	vtCamera *pCamera = pScene->GetCamera();
	pCamera->SetHither(10);
	pCamera->SetYon(150000);

	// The  terrain scene will contain all the terrains that are created.
	ts = new vtTerrainScene;

	// Get the global data path
	char user_config_dir[MAX_PATH];
	SHGetFolderPathA(NULL, CSIDL_APPDATA, NULL, SHGFP_TYPE_CURRENT, user_config_dir);
	vtLoadDataPath(user_config_dir, NULL);

	// And look locally too, just in case the global path isn't set yet
	vtGetDataPath().push_back("../Data/");

	// Begin creating the scene, including the sun and sky
	vtGroup *pTopGroup = ts->BeginTerrainScene();

	// Tell the scene graph to point to this terrain scene
	pScene->SetRoot(pTopGroup);

	// Create a new vtTerrain, read its paramters from a file
	vtTerrain *pTerr = new vtTerrain;
	pTerr->SetParamFile("Data/Simple.xml");

	// Add the terrain to the scene, and contruct it
	ts->AppendTerrain(pTerr);
	if (!ts->BuildTerrain(pTerr))
	{
		AfxMessageBox("Terrain creation failed.");
		return false;
	}

	ts->SetCurrentTerrain(pTerr);

	// Create a navigation engine to move around on the terrain
	// Get flight speed from terrain parameters
	float fSpeed = pTerr->GetParams().GetValueFloat(STR_NAVSPEED);

	vtTerrainFlyer *pFlyer = new vtTerrainFlyer(fSpeed);
	pFlyer->SetTarget(pCamera);
	pFlyer->SetHeightField(pTerr->GetHeightField());
	pScene->AddEngine(pFlyer);

	// Minimum height over terrain is 100 m
	vtHeightConstrain *pConstrain = new vtHeightConstrain(100);
	pConstrain->SetTarget(pCamera);
	pConstrain->SetHeightField(pTerr->GetHeightField());
	pScene->AddEngine(pConstrain);

	return true;
}

void CleanupScene()
{
	vtGetScene()->SetRoot(NULL);
	if (ts)
	{
		ts->CleanupScene();
		delete ts;
	}
	vtGetScene()->Shutdown();
}

//--------------Mouse EVENTS-----------------

//
// turn MFC events flags in VT flags
//
int MFCFlagsToVT(int nFlags)
{
	int flags = 0;
	if ( (nFlags & MK_CONTROL)!=0 )
		flags |= VT_CONTROL;
	if ( (nFlags & MK_SHIFT)!=0 )
		flags |= VT_SHIFT;
	return flags;
}

//
// turn MFC mouse events into VT mouse events
//
void CSimpleView::OnMouseMove(UINT nFlags, CPoint point)
{
	vtMouseEvent event;

	event.type = VT_MOVE;
	event.button = VT_NONE;
	event.flags = MFCFlagsToVT(nFlags);
	event.pos.Set(point.x,point.y);

	vtGetScene()->OnMouse(event);
}

void CSimpleView::OnLButtonUp(UINT nFlags, CPoint point)
{
	vtMouseEvent event;

	event.type = VT_UP;
	event.button = VT_LEFT;
	event.flags = MFCFlagsToVT(nFlags);
	event.pos.Set(point.x,point.y);

	vtGetScene()->OnMouse(event);
}

void CSimpleView::OnLButtonDown(UINT nFlags, CPoint point)
{
	vtMouseEvent event;

	event.type = VT_DOWN;
	event.button = VT_LEFT;
	event.flags = MFCFlagsToVT(nFlags);
	event.pos.Set(point.x,point.y);

	vtGetScene()->OnMouse(event);
}

void CSimpleView::OnRButtonDown(UINT nFlags, CPoint point)
{
	vtMouseEvent event;

	event.type = VT_DOWN;
	event.button = VT_RIGHT;
	event.flags = MFCFlagsToVT(nFlags);
	event.pos.Set(point.x,point.y);

	vtGetScene()->OnMouse(event);
}

void CSimpleView::OnRButtonUp(UINT nFlags, CPoint point)
{
	vtMouseEvent event;

	event.type = VT_UP;
	event.button = VT_RIGHT;
	event.flags = MFCFlagsToVT(nFlags);
	event.pos.Set(point.x,point.y);

	vtGetScene()->OnMouse(event);
}

void CSimpleView::OnMButtonDown(UINT nFlags, CPoint point)
{
	vtMouseEvent event;

	event.type = VT_DOWN;
	event.button = VT_MIDDLE;
	event.flags = MFCFlagsToVT(nFlags);
	event.pos.Set(point.x,point.y);

	vtGetScene()->OnMouse(event);
}

void CSimpleView::OnMButtonUp(UINT nFlags, CPoint point)
{
	vtMouseEvent event;

	event.type = VT_UP;
	event.button = VT_MIDDLE;
	event.flags = MFCFlagsToVT(nFlags);
	event.pos.Set(point.x,point.y);

	vtGetScene()->OnMouse(event);
}

<|endoftext|>


<commit_before>#pragma once

#include <cstdint>
#include <functional>
#include <string>
#include <type_traits>

#include <boost/mpl/contains.hpp>
#include <boost/mpl/vector.hpp>

#include "blackhole/cpp17/string_view.hpp"

namespace blackhole {
inline namespace v1 {

/// Trait that describes how to format user defined types provided as attributes.
template<typename T>
struct display_traits;

/// Represents a trait for mapping an owned types to their associated lightweight view types.
///
/// By default all types are transparently mapped to itself, but Blackhole provides some
/// specializations.
///
/// \warning it is undefined behavior to add specializations for this trait.
template<typename T>
struct view_of {
    typedef T type;
};

/// Forward.
class writer_t;

}  // namespace v1
}  // namespace blackhole

namespace blackhole {
inline namespace v1 {
namespace attribute {

class value_t;
class view_t;

/// Represents an attribute value holder.
///
/// Attribute value is an algebraic data type that can be initialized with one of the following
/// predefined primitive types:
///     - none marker;
///     - boolean type (true or false);
///     - signed integer types up to 64-bit size;
///     - unsigned integer types up to 64-bit size;
///     - floating point type;
///     - owned string type;
///     - and a function type, which can fill the specified writer with the value lazily.
///
/// The underlying value can be obtained through `blackhole::attribute::get` function with providing
/// the desired result type. For example:
///     blackhole::attribute::value_t value(42);
///     const auto actual = blackhole::attribute::get<std::int64_t>(value);
///
///     assert(42 == actual);
///
/// As an alternative a visitor pattern is provided for enabling underlying value visitation. To
/// enable this feature, implement the `value_t::visitor_t` interface and provide an instance of
/// this implementation to the `apply` method.
class value_t {
public:
    /// Available types.
    typedef std::nullptr_t null_type;
    typedef bool           bool_type;
    typedef std::int64_t   sint64_type;
    typedef std::uint64_t  uint64_type;
    typedef double         double_type;
    typedef std::string    string_type;
    typedef std::function<auto(writer_t& writer) -> void> function_type;

    /// The type sequence of all available types.
    typedef boost::mpl::vector<
        null_type,
        bool_type,
        sint64_type,
        uint64_type,
        double_type,
        string_type,
        function_type
    > types;

    /// Visitor interface.
    class visitor_t {
    public:
        virtual ~visitor_t() = 0;
        virtual auto operator()(const null_type&) -> void = 0;
        virtual auto operator()(const bool_type&) -> void = 0;
        virtual auto operator()(const sint64_type&) -> void = 0;
        virtual auto operator()(const uint64_type&) -> void = 0;
        virtual auto operator()(const double_type&) -> void = 0;
        virtual auto operator()(const string_type&) -> void = 0;
        virtual auto operator()(const function_type&) -> void = 0;
    };

    struct inner_t;

private:
    typedef std::aligned_storage<sizeof(function_type) + sizeof(int)>::type storage_type;

    /// The underlying type.
    storage_type storage;

public:
    /// Constructs a null value containing tagged nullptr value.
    value_t();

    value_t(std::nullptr_t);

    /// Constructs a value initialized with the given boolean value.
    value_t(bool value);

    /// Constructs a value initialized with the given signed integer.
    value_t(char value);
    value_t(short value);
    value_t(int value);
    value_t(long value);
    value_t(long long value);

    /// Constructs a value initialized with the given unsigned integer.
    value_t(unsigned char value);
    value_t(unsigned short value);
    value_t(unsigned int value);
    value_t(unsigned long value);
    value_t(unsigned long long value);

    value_t(double value);

    /// Constructs a value from the given string literal not including the terminating null
    /// character.
    ///
    /// \note this overload is required to prevent implicit conversion literal values to bool.
    template<std::size_t N>
    value_t(const char(&value)[N]) { construct(string_type{value, N - 1}); }

    value_t(std::string value);

    value_t(const value_t& other);
    value_t(value_t&& other);

    ~value_t();

    auto operator=(const value_t& other) -> value_t&;
    auto operator=(value_t&& other) -> value_t&;

    /// Applies the given visitor to perform pattern matching.
    auto apply(visitor_t& visitor) const -> void;

    /// Returns the internal underlying value.
    auto inner() noexcept -> inner_t&;
    auto inner() const noexcept -> const inner_t&;

private:
    template<typename T>
    auto construct(T&& value) -> void;
};

/// Represents an attribute value holder view, containing only lightweight views of the actual
/// values.
///
/// If an owned value is small enough to keep its copy - this class does it, otherwise keeping only
/// view proxy values. For example for `std::string` values there is a lightweight mapping that
/// holds only two members: a pointer to constant char and a size.
///
/// The underlying value can also be obtained through `blackhole::attribute::get` function with
/// providing the desired result type. For example:
///     blackhole::attribute::view_t value("le vinegret");
///     const auto actual = blackhole::attribute::get<std::int64_t>(value);
///
///     assert("le vinegret" == actual);
///
class view_t {
public:
    /// Available types.
    typedef std::nullptr_t null_type;
    typedef bool           bool_type;
    typedef std::int64_t   sint64_type;
    typedef std::uint64_t  uint64_type;
    typedef double         double_type;
    typedef string_view    string_type;

    struct function_type {
        const void* value;
        std::reference_wrapper<auto(const void* value, writer_t& writer) -> void> fn;

        auto operator()(writer_t& wr) const -> void {
            fn(value, wr);
        }

        auto operator==(const function_type& other) const noexcept -> bool {
            return value == other.value && fn.get() == other.fn.get();
        }
    };

    /// The type sequence of all available types.
    typedef boost::mpl::vector<
        null_type,
        bool_type,
        sint64_type,
        uint64_type,
        double_type,
        string_type,
        function_type
    > types;

    /// Visitor interface.
    class visitor_t {
    public:
        virtual ~visitor_t() = 0;
        virtual auto operator()(const null_type&) -> void = 0;
        virtual auto operator()(const bool_type&) -> void = 0;
        virtual auto operator()(const sint64_type&) -> void = 0;
        virtual auto operator()(const uint64_type&) -> void = 0;
        virtual auto operator()(const double_type&) -> void = 0;
        virtual auto operator()(const string_type&) -> void = 0;
        virtual auto operator()(const function_type&) -> void = 0;
    };

    struct inner_t;

private:
    typedef std::aligned_storage<2 * sizeof(void*) + sizeof(int)>::type storage_type;

    /// The underlying type.
    storage_type storage;

public:
    /// Constructs a null value view containing tagged nullptr value.
    view_t();

    view_t(std::nullptr_t);

    /// Constructs a value view initialized with the given boolean value.
    view_t(bool value);

    /// Constructs a value view initialized with the given signed integer.
    view_t(char value);
    view_t(short value);
    view_t(int value);
    view_t(long value);
    view_t(long long value);

    /// Constructs a value view initialized with the given unsigned integer.
    view_t(unsigned char value);
    view_t(unsigned short value);
    view_t(unsigned int value);
    view_t(unsigned long value);
    view_t(unsigned long long value);

    /// Constructs a value view from the given floating point value.
    view_t(float value);
    view_t(double value);

    /// Constructs a value view from the given string literal not including the terminating null
    /// character.
    ///
    /// \note this overload is required to prevent implicit conversion literal values to bool.
    template<std::size_t N>
    view_t(const char(&value)[N]) { construct(string_type{value, N - 1}); }

    /// Constructs a value view from the given string view.
    view_t(const string_type& value);

    /// Constructs a value view from the given string.
    view_t(const std::string& value);

    /// Constructs a value view from the given owned attribute value.
    view_t(const value_t& value);

    /// Constructs a value view from a custom type that implements `display_traits` trait.
    ///
    /// \sa display_traits for more information.
    template<typename T>
    view_t(const T& value, decltype(&display_traits<T>::apply)* = nullptr) {
        construct(function_type{static_cast<const void*>(&value), std::ref(display<T>)});
    }

    view_t(const view_t& other) = default;
    view_t(view_t&& other) = default;

    ~view_t() = default;

    auto operator=(const view_t& other) -> view_t& = default;
    auto operator=(view_t&& other) -> view_t& = default;

    /// Applies the given visitor to perform pattern matching.
    auto apply(visitor_t& visitor) const -> void;

    auto operator==(const view_t& other) const -> bool;
    auto operator!=(const view_t& other) const -> bool;

    /// Returns the internal underlying value.
    auto inner() noexcept -> inner_t&;
    auto inner() const noexcept -> const inner_t&;

private:
    template<typename T>
    auto construct(T&& value) -> void;

    template<typename T>
    static auto display(const void* value, writer_t& wr) -> void {
        display_traits<T>::apply(*static_cast<const T*>(value), wr);
    }
};

/// Retrieves a value of a specified, but yet restricted type, from a given attribute value.
///
/// \throws std::bad_cast if the content is not of the specified type T.
template<typename T>
auto get(const value_t& value) ->
    typename std::enable_if<boost::mpl::contains<value_t::types, T>::value, const T&>::type;

/// Retrieves a value of a specified, but yet restricted type, from a given attribute value view.
///
/// \throws std::bad_cast if the content is not of the specified type T.
template<typename T>
auto get(const view_t& value) ->
    typename std::enable_if<boost::mpl::contains<view_t::types, T>::value, const T&>::type;

}  // namespace attribute
}  // namespace v1
}  // namespace blackhole
<commit_msg>docs: add comments<commit_after>#pragma once

#include <cstdint>
#include <functional>
#include <string>
#include <type_traits>

#include <boost/mpl/contains.hpp>
#include <boost/mpl/vector.hpp>

#include "blackhole/cpp17/string_view.hpp"

namespace blackhole {
inline namespace v1 {

/// Trait that describes how to format user defined types provided as attributes.
///
/// The trait must implement `apply` function that matches attribute function type signature.
template<typename T>
struct display_traits;

/// Represents a trait for mapping an owned types to their associated lightweight view types.
///
/// By default all types are transparently mapped to itself, but Blackhole provides some
/// specializations.
///
/// \warning it is undefined behavior to add specializations for this trait.
template<typename T>
struct view_of {
    typedef T type;
};

/// Forward.
class writer_t;

}  // namespace v1
}  // namespace blackhole

namespace blackhole {
inline namespace v1 {
namespace attribute {

class value_t;
class view_t;

/// Represents an attribute value holder.
///
/// Attribute value is an algebraic data type that can be initialized with one of the following
/// predefined primitive types:
///     - none marker;
///     - boolean type (true or false);
///     - signed integer types up to 64-bit size;
///     - unsigned integer types up to 64-bit size;
///     - floating point type;
///     - owned string type;
///     - and a function type, which can fill the specified writer with the value lazily.
///
/// The underlying value can be obtained through `blackhole::attribute::get` function with providing
/// the desired result type. For example:
///     blackhole::attribute::value_t value(42);
///     const auto actual = blackhole::attribute::get<std::int64_t>(value);
///
///     assert(42 == actual);
///
/// As an alternative a visitor pattern is provided for enabling underlying value visitation. To
/// enable this feature, implement the `value_t::visitor_t` interface and provide an instance of
/// this implementation to the `apply` method.
class value_t {
public:
    /// Available types.
    typedef std::nullptr_t null_type;
    typedef bool           bool_type;
    typedef std::int64_t   sint64_type;
    typedef std::uint64_t  uint64_type;
    typedef double         double_type;
    typedef std::string    string_type;
    typedef std::function<auto(writer_t& writer) -> void> function_type;

    /// The type sequence of all available types.
    typedef boost::mpl::vector<
        null_type,
        bool_type,
        sint64_type,
        uint64_type,
        double_type,
        string_type,
        function_type
    > types;

    /// Visitor interface.
    class visitor_t {
    public:
        virtual ~visitor_t() = 0;
        virtual auto operator()(const null_type&) -> void = 0;
        virtual auto operator()(const bool_type&) -> void = 0;
        virtual auto operator()(const sint64_type&) -> void = 0;
        virtual auto operator()(const uint64_type&) -> void = 0;
        virtual auto operator()(const double_type&) -> void = 0;
        virtual auto operator()(const string_type&) -> void = 0;
        virtual auto operator()(const function_type&) -> void = 0;
    };

    struct inner_t;

private:
    typedef std::aligned_storage<sizeof(function_type) + sizeof(int)>::type storage_type;

    /// The underlying type.
    storage_type storage;

public:
    /// Constructs a null value containing tagged nullptr value.
    value_t();

    value_t(std::nullptr_t);

    /// Constructs a value initialized with the given boolean value.
    value_t(bool value);

    /// Constructs a value initialized with the given signed integer.
    value_t(char value);
    value_t(short value);
    value_t(int value);
    value_t(long value);
    value_t(long long value);

    /// Constructs a value initialized with the given unsigned integer.
    value_t(unsigned char value);
    value_t(unsigned short value);
    value_t(unsigned int value);
    value_t(unsigned long value);
    value_t(unsigned long long value);

    value_t(double value);

    /// Constructs a value from the given string literal not including the terminating null
    /// character.
    ///
    /// \note this overload is required to prevent implicit conversion literal values to bool.
    template<std::size_t N>
    value_t(const char(&value)[N]) { construct(string_type{value, N - 1}); }

    value_t(std::string value);

    value_t(const value_t& other);
    value_t(value_t&& other);

    ~value_t();

    auto operator=(const value_t& other) -> value_t&;
    auto operator=(value_t&& other) -> value_t&;

    /// Applies the given visitor to perform pattern matching.
    auto apply(visitor_t& visitor) const -> void;

    /// Returns the internal underlying value.
    auto inner() noexcept -> inner_t&;
    auto inner() const noexcept -> const inner_t&;

private:
    template<typename T>
    auto construct(T&& value) -> void;
};

/// Represents an attribute value holder view, containing only lightweight views of the actual
/// values.
///
/// If an owned value is small enough to keep its copy - this class does it, otherwise keeping only
/// view proxy values. For example for `std::string` values there is a lightweight mapping that
/// holds only two members: a pointer to constant char and a size.
///
/// The underlying value can also be obtained through `blackhole::attribute::get` function with
/// providing the desired result type. For example:
///     blackhole::attribute::view_t value("le vinegret");
///     const auto actual = blackhole::attribute::get<std::int64_t>(value);
///
///     assert("le vinegret" == actual);
///
class view_t {
public:
    /// Available types.
    typedef std::nullptr_t null_type;
    typedef bool           bool_type;
    typedef std::int64_t   sint64_type;
    typedef std::uint64_t  uint64_type;
    typedef double         double_type;
    typedef string_view    string_type;

    struct function_type {
        const void* value;
        std::reference_wrapper<auto(const void* value, writer_t& writer) -> void> fn;

        auto operator()(writer_t& wr) const -> void {
            fn(value, wr);
        }

        auto operator==(const function_type& other) const noexcept -> bool {
            return value == other.value && fn.get() == other.fn.get();
        }
    };

    /// The type sequence of all available types.
    typedef boost::mpl::vector<
        null_type,
        bool_type,
        sint64_type,
        uint64_type,
        double_type,
        string_type,
        function_type
    > types;

    /// Visitor interface.
    class visitor_t {
    public:
        virtual ~visitor_t() = 0;
        virtual auto operator()(const null_type&) -> void = 0;
        virtual auto operator()(const bool_type&) -> void = 0;
        virtual auto operator()(const sint64_type&) -> void = 0;
        virtual auto operator()(const uint64_type&) -> void = 0;
        virtual auto operator()(const double_type&) -> void = 0;
        virtual auto operator()(const string_type&) -> void = 0;
        virtual auto operator()(const function_type&) -> void = 0;
    };

    struct inner_t;

private:
    typedef std::aligned_storage<2 * sizeof(void*) + sizeof(int)>::type storage_type;

    /// The underlying type.
    storage_type storage;

public:
    /// Constructs a null value view containing tagged nullptr value.
    view_t();

    view_t(std::nullptr_t);

    /// Constructs a value view initialized with the given boolean value.
    view_t(bool value);

    /// Constructs a value view initialized with the given signed integer.
    view_t(char value);
    view_t(short value);
    view_t(int value);
    view_t(long value);
    view_t(long long value);

    /// Constructs a value view initialized with the given unsigned integer.
    view_t(unsigned char value);
    view_t(unsigned short value);
    view_t(unsigned int value);
    view_t(unsigned long value);
    view_t(unsigned long long value);

    /// Constructs a value view from the given floating point value.
    view_t(float value);
    view_t(double value);

    /// Constructs a value view from the given string literal not including the terminating null
    /// character.
    ///
    /// \note this overload is required to prevent implicit conversion literal values to bool.
    template<std::size_t N>
    view_t(const char(&value)[N]) { construct(string_type{value, N - 1}); }

    /// Constructs a value view from the given string view.
    view_t(const string_type& value);

    /// Constructs a value view from the given string.
    view_t(const std::string& value);

    /// Constructs a value view from the given owned attribute value.
    view_t(const value_t& value);

    /// Constructs a value view from a custom type that implements `display_traits` trait.
    ///
    /// \sa display_traits for more information.
    template<typename T>
    view_t(const T& value, decltype(&display_traits<T>::apply)* = nullptr) {
        construct(function_type{static_cast<const void*>(&value), std::ref(display<T>)});
    }

    view_t(const view_t& other) = default;
    view_t(view_t&& other) = default;

    ~view_t() = default;

    auto operator=(const view_t& other) -> view_t& = default;
    auto operator=(view_t&& other) -> view_t& = default;

    /// Applies the given visitor to perform pattern matching.
    auto apply(visitor_t& visitor) const -> void;

    auto operator==(const view_t& other) const -> bool;
    auto operator!=(const view_t& other) const -> bool;

    /// Returns the internal underlying value.
    auto inner() noexcept -> inner_t&;
    auto inner() const noexcept -> const inner_t&;

private:
    template<typename T>
    auto construct(T&& value) -> void;

    template<typename T>
    static auto display(const void* value, writer_t& wr) -> void {
        display_traits<T>::apply(*static_cast<const T*>(value), wr);
    }
};

/// Retrieves a value of a specified, but yet restricted type, from a given attribute value.
///
/// \throws std::bad_cast if the content is not of the specified type T.
template<typename T>
auto get(const value_t& value) ->
    typename std::enable_if<boost::mpl::contains<value_t::types, T>::value, const T&>::type;

/// Retrieves a value of a specified, but yet restricted type, from a given attribute value view.
///
/// \throws std::bad_cast if the content is not of the specified type T.
template<typename T>
auto get(const view_t& value) ->
    typename std::enable_if<boost::mpl::contains<view_t::types, T>::value, const T&>::type;

}  // namespace attribute
}  // namespace v1
}  // namespace blackhole
<|endoftext|>


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

#include "chrome/browser/chromeos/cros/language_library.h"

#include "base/basictypes.h"
#include "base/message_loop.h"
#include "base/string_util.h"
#include "chrome/browser/chrome_thread.h"
#include "chrome/browser/chromeos/cros/cros_library.h"
#include "third_party/cros/chromeos_keyboard.h"
#include "third_party/icu/public/common/unicode/uloc.h"

// Allows InvokeLater without adding refcounting. This class is a Singleton and
// won't be deleted until it's last InvokeLater is run.
template <>
struct RunnableMethodTraits<chromeos::LanguageLibraryImpl> {
  void RetainCallee(chromeos::LanguageLibraryImpl* obj) {}
  void ReleaseCallee(chromeos::LanguageLibraryImpl* obj) {}
};

namespace {

// Finds a property which has |new_prop.key| from |prop_list|, and replaces the
// property with |new_prop|. Returns true if such a property is found.
bool FindAndUpdateProperty(const chromeos::ImeProperty& new_prop,
                           chromeos::ImePropertyList* prop_list) {
  for (size_t i = 0; i < prop_list->size(); ++i) {
    chromeos::ImeProperty& prop = prop_list->at(i);
    if (prop.key == new_prop.key) {
      const int saved_id = prop.selection_item_id;
      // Update the list except the radio id. As written in chromeos_language.h,
      // |prop.selection_item_id| is dummy.
      prop = new_prop;
      prop.selection_item_id = saved_id;
      return true;
    }
  }
  return false;
}

// There are some differences between ISO 639-2 (T) and ISO 639-2 B, and
// some language codes are not recognized by ICU (i.e. ICU cannot convert
// these codes to display names). Hence we convert these codes to ones
// that ICU recognize.
//
// See http://en.wikipedia.org/wiki/List_of_ISO_639-1_codes for details.
const char* kIso639VariantMapping[][2] = {
  {"cze", "ces"},
  {"ger", "deu"},
  {"gre", "ell"},
  // "scr" is not a ISO 639 code. For some reason, evdev.xml uses "scr" as
  // the language code for Croatian.
  {"scr", "hrv"},
  {"rum", "ron"},
  {"slo", "slk"},
};

}  // namespace

namespace chromeos {

std::string LanguageLibrary::NormalizeLanguageCode(
    const std::string& language_code) {
  // Convert some language codes. See comments at kIso639VariantMapping.
  if (language_code.size() == 3) {
    for (size_t i = 0; i < arraysize(kIso639VariantMapping); ++i) {
      if (language_code == kIso639VariantMapping[i][0]) {
        return kIso639VariantMapping[i][1];
      }
    }
  }
  // We only handle two-letter codes from here.
  // Some ibus engines return locale codes like "zh_CN" as language codes,
  // and we don't want to rewrite this to "zho".
  if (language_code.size() != 2) {
    return language_code;
  }
  const char* three_letter_code = uloc_getISO3Language(
      language_code.c_str());
  if (three_letter_code && strlen(three_letter_code) > 0) {
    return three_letter_code;
  }
  return language_code;
}

bool LanguageLibrary::IsKeyboardLayout(
    const std::string& input_method_id) {
  const bool case_insensitive = false;
  return StartsWithASCII(input_method_id, "xkb:", case_insensitive);
}

LanguageLibraryImpl::LanguageLibraryImpl()
    : language_status_connection_(NULL),
      current_input_method_("", "", "") {
}

LanguageLibraryImpl::~LanguageLibraryImpl() {
  if (language_status_connection_) {
    chromeos::DisconnectLanguageStatus(language_status_connection_);
  }
}

LanguageLibraryImpl::Observer::~Observer() {
}

void LanguageLibraryImpl::AddObserver(Observer* observer) {
  observers_.AddObserver(observer);
}

void LanguageLibraryImpl::RemoveObserver(Observer* observer) {
  observers_.RemoveObserver(observer);
}

namespace {

// Removes "US" input method. Older (v18 and earlier) cros might add the dummy
// input method to |input_methods|, but we don't need it anymore.
// TODO(yusukes): Remove this function when we finish migrating to v20.
void RemoveDummyInputMethod(chromeos::InputMethodDescriptors* input_methods) {
  chromeos::InputMethodDescriptors::iterator iter;
  for (iter = input_methods->begin(); iter != input_methods->end(); ++iter) {
    if ((iter->id == "USA") && (input_methods->size() > 1)) {
      input_methods->erase(iter);
      return;
    }
  }
}

}  // namespace

chromeos::InputMethodDescriptors* LanguageLibraryImpl::GetActiveInputMethods() {
  chromeos::InputMethodDescriptors* result = NULL;
  if (EnsureLoadedAndStarted()) {
    result = chromeos::GetActiveInputMethods(language_status_connection_);
  }
  if (!result || result->empty()) {
    result = CreateFallbackInputMethodDescriptors();
  }
  // TODO(yusukes): Remove this hack.
  RemoveDummyInputMethod(result);
  return result;
}

chromeos::InputMethodDescriptors*
LanguageLibraryImpl::GetSupportedInputMethods() {
  chromeos::InputMethodDescriptors* result = NULL;
  if (EnsureLoadedAndStarted()) {
    result = chromeos::GetSupportedInputMethods(language_status_connection_);
  }
  if (!result || result->empty()) {
    result = CreateFallbackInputMethodDescriptors();
  }
  // TODO(yusukes): Remove this hack.
  RemoveDummyInputMethod(result);
  return result;
}

void LanguageLibraryImpl::ChangeInputMethod(
    const std::string& input_method_id) {
  if (EnsureLoadedAndStarted()) {
    chromeos::ChangeInputMethod(
        language_status_connection_, input_method_id.c_str());
  }
}

void LanguageLibraryImpl::SetImePropertyActivated(const std::string& key,
                                                  bool activated) {
  DCHECK(!key.empty());
  if (EnsureLoadedAndStarted()) {
    chromeos::SetImePropertyActivated(
        language_status_connection_, key.c_str(), activated);
  }
}

bool LanguageLibraryImpl::SetInputMethodActivated(
    const std::string& input_method_id, bool activated) {
  bool success = false;
  if (EnsureLoadedAndStarted()) {
    success = chromeos::SetInputMethodActivated(language_status_connection_,
                                                input_method_id.c_str(),
                                                activated);
  }
  return success;
}

bool LanguageLibraryImpl::InputMethodIsActivated(
    const std::string& input_method_id) {
  scoped_ptr<InputMethodDescriptors> active_input_method_descriptors(
      CrosLibrary::Get()->GetLanguageLibrary()->GetActiveInputMethods());
  for (size_t i = 0; i < active_input_method_descriptors->size(); ++i) {
    if (active_input_method_descriptors->at(i).id == input_method_id) {
      return true;
    }
  }
  return false;
}

bool LanguageLibraryImpl::GetImeConfig(
    const char* section, const char* config_name, ImeConfigValue* out_value) {
  bool success = false;
  if (EnsureLoadedAndStarted()) {
    success = chromeos::GetImeConfig(
        language_status_connection_, section, config_name, out_value);
  }
  return success;
}

bool LanguageLibraryImpl::SetImeConfig(
    const char* section, const char* config_name, const ImeConfigValue& value) {
  bool success = false;
  if (EnsureLoadedAndStarted()) {
    success = chromeos::SetImeConfig(
        language_status_connection_, section, config_name, value);
  }
  return success;
}

// static
void LanguageLibraryImpl::InputMethodChangedHandler(
    void* object, const chromeos::InputMethodDescriptor& current_input_method) {
  LanguageLibraryImpl* language_library =
      static_cast<LanguageLibraryImpl*>(object);
  language_library->UpdateCurrentInputMethod(current_input_method);
}

// static
void LanguageLibraryImpl::RegisterPropertiesHandler(
    void* object, const ImePropertyList& prop_list) {
  LanguageLibraryImpl* language_library =
      static_cast<LanguageLibraryImpl*>(object);
  language_library->RegisterProperties(prop_list);
}

// static
void LanguageLibraryImpl::UpdatePropertyHandler(
    void* object, const ImePropertyList& prop_list) {
  LanguageLibraryImpl* language_library =
      static_cast<LanguageLibraryImpl*>(object);
  language_library->UpdateProperty(prop_list);
}

bool LanguageLibraryImpl::EnsureStarted() {
  if (language_status_connection_) {
    if (chromeos::LanguageStatusConnectionIsAlive(
            language_status_connection_)) {
      return true;
    }
    DLOG(WARNING) << "IBus/XKB connection is closed. Trying to reconnect...";
    chromeos::DisconnectLanguageStatus(language_status_connection_);
  }
  chromeos::LanguageStatusMonitorFunctions monitor_functions;
  monitor_functions.current_language = &InputMethodChangedHandler;
  monitor_functions.register_ime_properties = &RegisterPropertiesHandler;
  monitor_functions.update_ime_property = &UpdatePropertyHandler;
  language_status_connection_
      = chromeos::MonitorLanguageStatus(monitor_functions, this);
  return language_status_connection_ != NULL;
}

bool LanguageLibraryImpl::EnsureLoadedAndStarted() {
  return CrosLibrary::Get()->EnsureLoaded() &&
         EnsureStarted();
}

void LanguageLibraryImpl::UpdateCurrentInputMethod(
    const chromeos::InputMethodDescriptor& current_input_method) {
  // Make sure we run on UI thread.
  if (!ChromeThread::CurrentlyOn(ChromeThread::UI)) {
    DLOG(INFO) << "UpdateCurrentInputMethod (Background thread)";
    ChromeThread::PostTask(
        ChromeThread::UI, FROM_HERE,
        // NewRunnableMethod() copies |current_input_method| by value.
        NewRunnableMethod(
            this, &LanguageLibraryImpl::UpdateCurrentInputMethod,
            current_input_method));
    return;
  }

  DLOG(INFO) << "UpdateCurrentInputMethod (UI thread)";
  const char kDefaultLayout[] = "us";
  if (IsKeyboardLayout(current_input_method.id)) {
    // If the new input method is a keyboard layout, switch the keyboard.
    std::vector<std::string> portions;
    SplitString(current_input_method.id, ':', &portions);
    const std::string keyboard_layout =
        (portions.size() > 1 && !portions[1].empty() ?
         portions[1] : kDefaultLayout);
    chromeos::SetCurrentKeyboardLayoutByName(keyboard_layout);
  } else {
    // If the new input method is an IME, change the keyboard back to the
    // default layout (US).  TODO(satorux): What if the user is using a non-US
    // keyboard, such as a Japanese keyboard? We need to rework this.
    chromeos::SetCurrentKeyboardLayoutByName(kDefaultLayout);
  }

  current_input_method_ = current_input_method;
  FOR_EACH_OBSERVER(Observer, observers_, InputMethodChanged(this));
}

void LanguageLibraryImpl::RegisterProperties(const ImePropertyList& prop_list) {
  if (!ChromeThread::CurrentlyOn(ChromeThread::UI)) {
    ChromeThread::PostTask(
        ChromeThread::UI, FROM_HERE,
        NewRunnableMethod(
            this, &LanguageLibraryImpl::RegisterProperties, prop_list));
    return;
  }

  // |prop_list| might be empty. This means "clear all properties."
  current_ime_properties_ = prop_list;
  FOR_EACH_OBSERVER(Observer, observers_, ImePropertiesChanged(this));
}

void LanguageLibraryImpl::UpdateProperty(const ImePropertyList& prop_list) {
  if (!ChromeThread::CurrentlyOn(ChromeThread::UI)) {
    ChromeThread::PostTask(
        ChromeThread::UI, FROM_HERE,
        NewRunnableMethod(
            this, &LanguageLibraryImpl::UpdateProperty, prop_list));
    return;
  }

  for (size_t i = 0; i < prop_list.size(); ++i) {
    FindAndUpdateProperty(prop_list[i], &current_ime_properties_);
  }
  FOR_EACH_OBSERVER(Observer, observers_, ImePropertiesChanged(this));
}

}  // namespace chromeos
<commit_msg>Remove the obsolete function, RemoveDummyInputMethod. Depends on http://codereview.chromium.org/1523019.<commit_after>// Copyright (c) 2009 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "chrome/browser/chromeos/cros/language_library.h"

#include "base/basictypes.h"
#include "base/message_loop.h"
#include "base/string_util.h"
#include "chrome/browser/chrome_thread.h"
#include "chrome/browser/chromeos/cros/cros_library.h"
#include "third_party/cros/chromeos_keyboard.h"
#include "third_party/icu/public/common/unicode/uloc.h"

// Allows InvokeLater without adding refcounting. This class is a Singleton and
// won't be deleted until it's last InvokeLater is run.
template <>
struct RunnableMethodTraits<chromeos::LanguageLibraryImpl> {
  void RetainCallee(chromeos::LanguageLibraryImpl* obj) {}
  void ReleaseCallee(chromeos::LanguageLibraryImpl* obj) {}
};

namespace {

// Finds a property which has |new_prop.key| from |prop_list|, and replaces the
// property with |new_prop|. Returns true if such a property is found.
bool FindAndUpdateProperty(const chromeos::ImeProperty& new_prop,
                           chromeos::ImePropertyList* prop_list) {
  for (size_t i = 0; i < prop_list->size(); ++i) {
    chromeos::ImeProperty& prop = prop_list->at(i);
    if (prop.key == new_prop.key) {
      const int saved_id = prop.selection_item_id;
      // Update the list except the radio id. As written in chromeos_language.h,
      // |prop.selection_item_id| is dummy.
      prop = new_prop;
      prop.selection_item_id = saved_id;
      return true;
    }
  }
  return false;
}

// There are some differences between ISO 639-2 (T) and ISO 639-2 B, and
// some language codes are not recognized by ICU (i.e. ICU cannot convert
// these codes to display names). Hence we convert these codes to ones
// that ICU recognize.
//
// See http://en.wikipedia.org/wiki/List_of_ISO_639-1_codes for details.
const char* kIso639VariantMapping[][2] = {
  {"cze", "ces"},
  {"ger", "deu"},
  {"gre", "ell"},
  // "scr" is not a ISO 639 code. For some reason, evdev.xml uses "scr" as
  // the language code for Croatian.
  {"scr", "hrv"},
  {"rum", "ron"},
  {"slo", "slk"},
};

}  // namespace

namespace chromeos {

std::string LanguageLibrary::NormalizeLanguageCode(
    const std::string& language_code) {
  // Convert some language codes. See comments at kIso639VariantMapping.
  if (language_code.size() == 3) {
    for (size_t i = 0; i < arraysize(kIso639VariantMapping); ++i) {
      if (language_code == kIso639VariantMapping[i][0]) {
        return kIso639VariantMapping[i][1];
      }
    }
  }
  // We only handle two-letter codes from here.
  // Some ibus engines return locale codes like "zh_CN" as language codes,
  // and we don't want to rewrite this to "zho".
  if (language_code.size() != 2) {
    return language_code;
  }
  const char* three_letter_code = uloc_getISO3Language(
      language_code.c_str());
  if (three_letter_code && strlen(three_letter_code) > 0) {
    return three_letter_code;
  }
  return language_code;
}

bool LanguageLibrary::IsKeyboardLayout(
    const std::string& input_method_id) {
  const bool case_insensitive = false;
  return StartsWithASCII(input_method_id, "xkb:", case_insensitive);
}

LanguageLibraryImpl::LanguageLibraryImpl()
    : language_status_connection_(NULL),
      current_input_method_("", "", "") {
}

LanguageLibraryImpl::~LanguageLibraryImpl() {
  if (language_status_connection_) {
    chromeos::DisconnectLanguageStatus(language_status_connection_);
  }
}

LanguageLibraryImpl::Observer::~Observer() {
}

void LanguageLibraryImpl::AddObserver(Observer* observer) {
  observers_.AddObserver(observer);
}

void LanguageLibraryImpl::RemoveObserver(Observer* observer) {
  observers_.RemoveObserver(observer);
}

chromeos::InputMethodDescriptors* LanguageLibraryImpl::GetActiveInputMethods() {
  chromeos::InputMethodDescriptors* result = NULL;
  if (EnsureLoadedAndStarted()) {
    result = chromeos::GetActiveInputMethods(language_status_connection_);
  }
  if (!result || result->empty()) {
    result = CreateFallbackInputMethodDescriptors();
  }
  return result;
}

chromeos::InputMethodDescriptors*
LanguageLibraryImpl::GetSupportedInputMethods() {
  chromeos::InputMethodDescriptors* result = NULL;
  if (EnsureLoadedAndStarted()) {
    result = chromeos::GetSupportedInputMethods(language_status_connection_);
  }
  if (!result || result->empty()) {
    result = CreateFallbackInputMethodDescriptors();
  }
  return result;
}

void LanguageLibraryImpl::ChangeInputMethod(
    const std::string& input_method_id) {
  if (EnsureLoadedAndStarted()) {
    chromeos::ChangeInputMethod(
        language_status_connection_, input_method_id.c_str());
  }
}

void LanguageLibraryImpl::SetImePropertyActivated(const std::string& key,
                                                  bool activated) {
  DCHECK(!key.empty());
  if (EnsureLoadedAndStarted()) {
    chromeos::SetImePropertyActivated(
        language_status_connection_, key.c_str(), activated);
  }
}

bool LanguageLibraryImpl::SetInputMethodActivated(
    const std::string& input_method_id, bool activated) {
  bool success = false;
  if (EnsureLoadedAndStarted()) {
    success = chromeos::SetInputMethodActivated(language_status_connection_,
                                                input_method_id.c_str(),
                                                activated);
  }
  return success;
}

bool LanguageLibraryImpl::InputMethodIsActivated(
    const std::string& input_method_id) {
  scoped_ptr<InputMethodDescriptors> active_input_method_descriptors(
      CrosLibrary::Get()->GetLanguageLibrary()->GetActiveInputMethods());
  for (size_t i = 0; i < active_input_method_descriptors->size(); ++i) {
    if (active_input_method_descriptors->at(i).id == input_method_id) {
      return true;
    }
  }
  return false;
}

bool LanguageLibraryImpl::GetImeConfig(
    const char* section, const char* config_name, ImeConfigValue* out_value) {
  bool success = false;
  if (EnsureLoadedAndStarted()) {
    success = chromeos::GetImeConfig(
        language_status_connection_, section, config_name, out_value);
  }
  return success;
}

bool LanguageLibraryImpl::SetImeConfig(
    const char* section, const char* config_name, const ImeConfigValue& value) {
  bool success = false;
  if (EnsureLoadedAndStarted()) {
    success = chromeos::SetImeConfig(
        language_status_connection_, section, config_name, value);
  }
  return success;
}

// static
void LanguageLibraryImpl::InputMethodChangedHandler(
    void* object, const chromeos::InputMethodDescriptor& current_input_method) {
  LanguageLibraryImpl* language_library =
      static_cast<LanguageLibraryImpl*>(object);
  language_library->UpdateCurrentInputMethod(current_input_method);
}

// static
void LanguageLibraryImpl::RegisterPropertiesHandler(
    void* object, const ImePropertyList& prop_list) {
  LanguageLibraryImpl* language_library =
      static_cast<LanguageLibraryImpl*>(object);
  language_library->RegisterProperties(prop_list);
}

// static
void LanguageLibraryImpl::UpdatePropertyHandler(
    void* object, const ImePropertyList& prop_list) {
  LanguageLibraryImpl* language_library =
      static_cast<LanguageLibraryImpl*>(object);
  language_library->UpdateProperty(prop_list);
}

bool LanguageLibraryImpl::EnsureStarted() {
  if (language_status_connection_) {
    if (chromeos::LanguageStatusConnectionIsAlive(
            language_status_connection_)) {
      return true;
    }
    DLOG(WARNING) << "IBus connection is closed. Trying to reconnect...";
    chromeos::DisconnectLanguageStatus(language_status_connection_);
  }
  chromeos::LanguageStatusMonitorFunctions monitor_functions;
  monitor_functions.current_language = &InputMethodChangedHandler;
  monitor_functions.register_ime_properties = &RegisterPropertiesHandler;
  monitor_functions.update_ime_property = &UpdatePropertyHandler;
  language_status_connection_
      = chromeos::MonitorLanguageStatus(monitor_functions, this);
  return language_status_connection_ != NULL;
}

bool LanguageLibraryImpl::EnsureLoadedAndStarted() {
  return CrosLibrary::Get()->EnsureLoaded() &&
         EnsureStarted();
}

void LanguageLibraryImpl::UpdateCurrentInputMethod(
    const chromeos::InputMethodDescriptor& current_input_method) {
  // Make sure we run on UI thread.
  if (!ChromeThread::CurrentlyOn(ChromeThread::UI)) {
    DLOG(INFO) << "UpdateCurrentInputMethod (Background thread)";
    ChromeThread::PostTask(
        ChromeThread::UI, FROM_HERE,
        // NewRunnableMethod() copies |current_input_method| by value.
        NewRunnableMethod(
            this, &LanguageLibraryImpl::UpdateCurrentInputMethod,
            current_input_method));
    return;
  }

  DLOG(INFO) << "UpdateCurrentInputMethod (UI thread)";
  const char kDefaultLayout[] = "us";
  if (IsKeyboardLayout(current_input_method.id)) {
    // If the new input method is a keyboard layout, switch the keyboard.
    std::vector<std::string> portions;
    SplitString(current_input_method.id, ':', &portions);
    const std::string keyboard_layout =
        (portions.size() > 1 && !portions[1].empty() ?
         portions[1] : kDefaultLayout);
    chromeos::SetCurrentKeyboardLayoutByName(keyboard_layout);
  } else {
    // If the new input method is an IME, change the keyboard back to the
    // default layout (US).  TODO(satorux): What if the user is using a non-US
    // keyboard, such as a Japanese keyboard? We need to rework this.
    chromeos::SetCurrentKeyboardLayoutByName(kDefaultLayout);
  }

  current_input_method_ = current_input_method;
  FOR_EACH_OBSERVER(Observer, observers_, InputMethodChanged(this));
}

void LanguageLibraryImpl::RegisterProperties(const ImePropertyList& prop_list) {
  if (!ChromeThread::CurrentlyOn(ChromeThread::UI)) {
    ChromeThread::PostTask(
        ChromeThread::UI, FROM_HERE,
        NewRunnableMethod(
            this, &LanguageLibraryImpl::RegisterProperties, prop_list));
    return;
  }

  // |prop_list| might be empty. This means "clear all properties."
  current_ime_properties_ = prop_list;
  FOR_EACH_OBSERVER(Observer, observers_, ImePropertiesChanged(this));
}

void LanguageLibraryImpl::UpdateProperty(const ImePropertyList& prop_list) {
  if (!ChromeThread::CurrentlyOn(ChromeThread::UI)) {
    ChromeThread::PostTask(
        ChromeThread::UI, FROM_HERE,
        NewRunnableMethod(
            this, &LanguageLibraryImpl::UpdateProperty, prop_list));
    return;
  }

  for (size_t i = 0; i < prop_list.size(); ++i) {
    FindAndUpdateProperty(prop_list[i], &current_ime_properties_);
  }
  FOR_EACH_OBSERVER(Observer, observers_, ImePropertiesChanged(this));
}

}  // namespace chromeos
<|endoftext|>