<commit_before>//===-- ARMTargetMachine.cpp - Define TargetMachine for ARM ---------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
//
//===----------------------------------------------------------------------===//

#include "ARMTargetMachine.h"
#include "ARMTargetAsmInfo.h"
#include "ARMFrameInfo.h"
#include "ARM.h"
#include "llvm/PassManager.h"
#include "llvm/CodeGen/Passes.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/FormattedStream.h"
#include "llvm/Target/TargetOptions.h"
#include "llvm/Target/TargetRegistry.h"
using namespace llvm;

static cl::opt<bool> DisableLdStOpti("disable-arm-loadstore-opti", cl::Hidden,
                              cl::desc("Disable load store optimization pass"));
static cl::opt<bool> DisableIfConversion("disable-arm-if-conversion",cl::Hidden,
                              cl::desc("Disable if-conversion pass"));
extern "C" void LLVMInitializeARMTarget() {
  // Register the target.
  RegisterTargetMachine<ARMTargetMachine> X(TheARMTarget);
  RegisterTargetMachine<ThumbTargetMachine> Y(TheThumbTarget);
}

/// TargetMachine ctor - Create an ARM architecture model.
///
ARMBaseTargetMachine::ARMBaseTargetMachine(const Target &T,
                                           const std::string &TT,
                                           const std::string &FS,
                                           bool isThumb)
  : LLVMTargetMachine(T),
    Subtarget(TT, FS, isThumb),
    FrameInfo(Subtarget),
    JITInfo(),
    InstrItins(Subtarget.getInstrItineraryData()) {
  DefRelocModel = getRelocationModel();
}

ARMTargetMachine::ARMTargetMachine(const Target &T, const std::string &TT,
                                   const std::string &FS)
  : ARMBaseTargetMachine(T, TT, FS, false), InstrInfo(Subtarget),
    DataLayout(Subtarget.isAPCS_ABI() ?
               std::string("e-p:32:32-f64:32:32-i64:32:32") :
               std::string("e-p:32:32-f64:64:64-i64:64:64")),
    TLInfo(*this) {
}

ThumbTargetMachine::ThumbTargetMachine(const Target &T, const std::string &TT,
                                       const std::string &FS)
  : ARMBaseTargetMachine(T, TT, FS, true),
    DataLayout(Subtarget.isAPCS_ABI() ?
               std::string("e-p:32:32-f64:32:32-i64:32:32-"
                           "i16:16:32-i8:8:32-i1:8:32-a:0:32") :
               std::string("e-p:32:32-f64:64:64-i64:64:64-"
                           "i16:16:32-i8:8:32-i1:8:32-a:0:32")),
    TLInfo(*this) {
  // Create the approriate type of Thumb InstrInfo
  if (Subtarget.hasThumb2())
    InstrInfo = new Thumb2InstrInfo(Subtarget);
  else
    InstrInfo = new Thumb1InstrInfo(Subtarget);
}

const TargetAsmInfo *ARMBaseTargetMachine::createTargetAsmInfo() const {
  switch (Subtarget.TargetType) {
  default: llvm_unreachable("Unknown ARM subtarget kind");
  case ARMSubtarget::isDarwin:
    return new ARMDarwinTargetAsmInfo();
  case ARMSubtarget::isELF:
    return new ARMELFTargetAsmInfo();
  }
}

// Pass Pipeline Configuration
bool ARMBaseTargetMachine::addInstSelector(PassManagerBase &PM,
                                           CodeGenOpt::Level OptLevel) {
  PM.add(createARMISelDag(*this));
  return false;
}

bool ARMBaseTargetMachine::addPreRegAlloc(PassManagerBase &PM,
                                          CodeGenOpt::Level OptLevel) {
  if (Subtarget.hasNEON())
    PM.add(createNEONPreAllocPass());

  // FIXME: temporarily disabling load / store optimization pass for Thumb mode.
  if (OptLevel != CodeGenOpt::None && !DisableLdStOpti && !Subtarget.isThumb())
    PM.add(createARMLoadStoreOptimizationPass(true));
  return true;
}

bool ARMBaseTargetMachine::addPreEmitPass(PassManagerBase &PM,
                                          CodeGenOpt::Level OptLevel) {
  // FIXME: temporarily disabling load / store optimization pass for Thumb1 mode.
  if (OptLevel != CodeGenOpt::None && !DisableLdStOpti &&
      !Subtarget.isThumb1Only())
    PM.add(createARMLoadStoreOptimizationPass());

  if (OptLevel != CodeGenOpt::None &&
      !DisableIfConversion && !Subtarget.isThumb())
    PM.add(createIfConverterPass());

  if (Subtarget.isThumb2()) {
    PM.add(createThumb2ITBlockPass());
    PM.add(createThumb2SizeReductionPass());
  }

  PM.add(createARMConstantIslandPass());
  return true;
}

bool ARMBaseTargetMachine::addCodeEmitter(PassManagerBase &PM,
                                          CodeGenOpt::Level OptLevel,
                                          MachineCodeEmitter &MCE) {
  // FIXME: Move this to TargetJITInfo!
  if (DefRelocModel == Reloc::Default)
    setRelocationModel(Reloc::Static);

  // Machine code emitter pass for ARM.
  PM.add(createARMCodeEmitterPass(*this, MCE));
  return false;
}

bool ARMBaseTargetMachine::addCodeEmitter(PassManagerBase &PM,
                                          CodeGenOpt::Level OptLevel,
                                          JITCodeEmitter &JCE) {
  // FIXME: Move this to TargetJITInfo!
  if (DefRelocModel == Reloc::Default)
    setRelocationModel(Reloc::Static);

  // Machine code emitter pass for ARM.
  PM.add(createARMJITCodeEmitterPass(*this, JCE));
  return false;
}

bool ARMBaseTargetMachine::addCodeEmitter(PassManagerBase &PM,
                                          CodeGenOpt::Level OptLevel,
                                          ObjectCodeEmitter &OCE) {
  // FIXME: Move this to TargetJITInfo!
  if (DefRelocModel == Reloc::Default)
    setRelocationModel(Reloc::Static);

  // Machine code emitter pass for ARM.
  PM.add(createARMObjectCodeEmitterPass(*this, OCE));
  return false;
}

bool ARMBaseTargetMachine::addSimpleCodeEmitter(PassManagerBase &PM,
                                                CodeGenOpt::Level OptLevel,
                                                MachineCodeEmitter &MCE) {
  // Machine code emitter pass for ARM.
  PM.add(createARMCodeEmitterPass(*this, MCE));
  return false;
}

bool ARMBaseTargetMachine::addSimpleCodeEmitter(PassManagerBase &PM,
                                                CodeGenOpt::Level OptLevel,
                                                JITCodeEmitter &JCE) {
  // Machine code emitter pass for ARM.
  PM.add(createARMJITCodeEmitterPass(*this, JCE));
  return false;
}

bool ARMBaseTargetMachine::addSimpleCodeEmitter(PassManagerBase &PM,
                                            CodeGenOpt::Level OptLevel,
                                            ObjectCodeEmitter &OCE) {
  // Machine code emitter pass for ARM.
  PM.add(createARMObjectCodeEmitterPass(*this, OCE));
  return false;
}

<commit_msg>Adding a blank line back.<commit_after>//===-- ARMTargetMachine.cpp - Define TargetMachine for ARM ---------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
//
//===----------------------------------------------------------------------===//

#include "ARMTargetMachine.h"
#include "ARMTargetAsmInfo.h"
#include "ARMFrameInfo.h"
#include "ARM.h"
#include "llvm/PassManager.h"
#include "llvm/CodeGen/Passes.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/FormattedStream.h"
#include "llvm/Target/TargetOptions.h"
#include "llvm/Target/TargetRegistry.h"
using namespace llvm;

static cl::opt<bool> DisableLdStOpti("disable-arm-loadstore-opti", cl::Hidden,
                              cl::desc("Disable load store optimization pass"));
static cl::opt<bool> DisableIfConversion("disable-arm-if-conversion",cl::Hidden,
                              cl::desc("Disable if-conversion pass"));

extern "C" void LLVMInitializeARMTarget() {
  // Register the target.
  RegisterTargetMachine<ARMTargetMachine> X(TheARMTarget);
  RegisterTargetMachine<ThumbTargetMachine> Y(TheThumbTarget);
}

/// TargetMachine ctor - Create an ARM architecture model.
///
ARMBaseTargetMachine::ARMBaseTargetMachine(const Target &T,
                                           const std::string &TT,
                                           const std::string &FS,
                                           bool isThumb)
  : LLVMTargetMachine(T),
    Subtarget(TT, FS, isThumb),
    FrameInfo(Subtarget),
    JITInfo(),
    InstrItins(Subtarget.getInstrItineraryData()) {
  DefRelocModel = getRelocationModel();
}

ARMTargetMachine::ARMTargetMachine(const Target &T, const std::string &TT,
                                   const std::string &FS)
  : ARMBaseTargetMachine(T, TT, FS, false), InstrInfo(Subtarget),
    DataLayout(Subtarget.isAPCS_ABI() ?
               std::string("e-p:32:32-f64:32:32-i64:32:32") :
               std::string("e-p:32:32-f64:64:64-i64:64:64")),
    TLInfo(*this) {
}

ThumbTargetMachine::ThumbTargetMachine(const Target &T, const std::string &TT,
                                       const std::string &FS)
  : ARMBaseTargetMachine(T, TT, FS, true),
    DataLayout(Subtarget.isAPCS_ABI() ?
               std::string("e-p:32:32-f64:32:32-i64:32:32-"
                           "i16:16:32-i8:8:32-i1:8:32-a:0:32") :
               std::string("e-p:32:32-f64:64:64-i64:64:64-"
                           "i16:16:32-i8:8:32-i1:8:32-a:0:32")),
    TLInfo(*this) {
  // Create the approriate type of Thumb InstrInfo
  if (Subtarget.hasThumb2())
    InstrInfo = new Thumb2InstrInfo(Subtarget);
  else
    InstrInfo = new Thumb1InstrInfo(Subtarget);
}

const TargetAsmInfo *ARMBaseTargetMachine::createTargetAsmInfo() const {
  switch (Subtarget.TargetType) {
  default: llvm_unreachable("Unknown ARM subtarget kind");
  case ARMSubtarget::isDarwin:
    return new ARMDarwinTargetAsmInfo();
  case ARMSubtarget::isELF:
    return new ARMELFTargetAsmInfo();
  }
}

// Pass Pipeline Configuration
bool ARMBaseTargetMachine::addInstSelector(PassManagerBase &PM,
                                           CodeGenOpt::Level OptLevel) {
  PM.add(createARMISelDag(*this));
  return false;
}

bool ARMBaseTargetMachine::addPreRegAlloc(PassManagerBase &PM,
                                          CodeGenOpt::Level OptLevel) {
  if (Subtarget.hasNEON())
    PM.add(createNEONPreAllocPass());

  // FIXME: temporarily disabling load / store optimization pass for Thumb mode.
  if (OptLevel != CodeGenOpt::None && !DisableLdStOpti && !Subtarget.isThumb())
    PM.add(createARMLoadStoreOptimizationPass(true));
  return true;
}

bool ARMBaseTargetMachine::addPreEmitPass(PassManagerBase &PM,
                                          CodeGenOpt::Level OptLevel) {
  // FIXME: temporarily disabling load / store optimization pass for Thumb1 mode.
  if (OptLevel != CodeGenOpt::None && !DisableLdStOpti &&
      !Subtarget.isThumb1Only())
    PM.add(createARMLoadStoreOptimizationPass());

  if (OptLevel != CodeGenOpt::None &&
      !DisableIfConversion && !Subtarget.isThumb())
    PM.add(createIfConverterPass());

  if (Subtarget.isThumb2()) {
    PM.add(createThumb2ITBlockPass());
    PM.add(createThumb2SizeReductionPass());
  }

  PM.add(createARMConstantIslandPass());
  return true;
}

bool ARMBaseTargetMachine::addCodeEmitter(PassManagerBase &PM,
                                          CodeGenOpt::Level OptLevel,
                                          MachineCodeEmitter &MCE) {
  // FIXME: Move this to TargetJITInfo!
  if (DefRelocModel == Reloc::Default)
    setRelocationModel(Reloc::Static);

  // Machine code emitter pass for ARM.
  PM.add(createARMCodeEmitterPass(*this, MCE));
  return false;
}

bool ARMBaseTargetMachine::addCodeEmitter(PassManagerBase &PM,
                                          CodeGenOpt::Level OptLevel,
                                          JITCodeEmitter &JCE) {
  // FIXME: Move this to TargetJITInfo!
  if (DefRelocModel == Reloc::Default)
    setRelocationModel(Reloc::Static);

  // Machine code emitter pass for ARM.
  PM.add(createARMJITCodeEmitterPass(*this, JCE));
  return false;
}

bool ARMBaseTargetMachine::addCodeEmitter(PassManagerBase &PM,
                                          CodeGenOpt::Level OptLevel,
                                          ObjectCodeEmitter &OCE) {
  // FIXME: Move this to TargetJITInfo!
  if (DefRelocModel == Reloc::Default)
    setRelocationModel(Reloc::Static);

  // Machine code emitter pass for ARM.
  PM.add(createARMObjectCodeEmitterPass(*this, OCE));
  return false;
}

bool ARMBaseTargetMachine::addSimpleCodeEmitter(PassManagerBase &PM,
                                                CodeGenOpt::Level OptLevel,
                                                MachineCodeEmitter &MCE) {
  // Machine code emitter pass for ARM.
  PM.add(createARMCodeEmitterPass(*this, MCE));
  return false;
}

bool ARMBaseTargetMachine::addSimpleCodeEmitter(PassManagerBase &PM,
                                                CodeGenOpt::Level OptLevel,
                                                JITCodeEmitter &JCE) {
  // Machine code emitter pass for ARM.
  PM.add(createARMJITCodeEmitterPass(*this, JCE));
  return false;
}

bool ARMBaseTargetMachine::addSimpleCodeEmitter(PassManagerBase &PM,
                                            CodeGenOpt::Level OptLevel,
                                            ObjectCodeEmitter &OCE) {
  // Machine code emitter pass for ARM.
  PM.add(createARMObjectCodeEmitterPass(*this, OCE));
  return false;
}

<|endoftext|>


<commit_before>/*
 * Copyright (c) 2013-2014 ARM Limited
 * All rights reserved.
 *
 * The license below extends only to copyright in the software and shall
 * not be construed as granting a license to any other intellectual
 * property including but not limited to intellectual property relating
 * to a hardware implementation of the functionality of the software
 * licensed hereunder.  You may use the software subject to the license
 * terms below provided that you ensure that this notice is replicated
 * unmodified and in its entirety in all distributions of the software,
 * modified or unmodified, in source code or in binary form.
 *
 * Copyright (c) 2005 The Regents of The University of Michigan
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met: redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer;
 * redistributions in binary form must reproduce the above copyright
 * notice, this list of conditions and the following disclaimer in the
 * documentation and/or other materials provided with the distribution;
 * neither the name of the copyright holders nor the names of its
 * contributors may be used to endorse or promote products derived from
 * this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 * Authors: Ron Dreslinski
 *          Mitch Hayenga
 */

/**
 * @file
 * Hardware Prefetcher Definition.
 */

#include <list>

#include "mem/cache/prefetch/base.hh"
#include "mem/cache/base.hh"
#include "sim/system.hh"

BasePrefetcher::BasePrefetcher(const BasePrefetcherParams *p)
    : ClockedObject(p), cache(nullptr), blkSize(0), system(p->sys),
      onMiss(p->on_miss), onRead(p->on_read),
      onWrite(p->on_write), onData(p->on_data), onInst(p->on_inst),
      masterId(system->getMasterId(name())),
      pageBytes(system->getPageBytes())
{
}

void
BasePrefetcher::setCache(BaseCache *_cache)
{
    assert(!cache);
    cache = _cache;
    blkSize = cache->getBlockSize();
}

void
BasePrefetcher::regStats()
{
    pfIssued
        .name(name() + ".num_hwpf_issued")
        .desc("number of hwpf issued")
        ;
}

bool
BasePrefetcher::observeAccess(const PacketPtr &pkt) const
{
    Addr addr = pkt->getAddr();
    bool fetch = pkt->req->isInstFetch();
    bool read= pkt->isRead();
    bool is_secure = pkt->isSecure();

    if (pkt->req->isUncacheable()) return false;
    if (fetch && !onInst) return false;
    if (!fetch && !onData) return false;
    if (!fetch && read && !onRead) return false;
    if (!fetch && !read && !onWrite) return false;

    if (onMiss) {
        return !inCache(addr, is_secure) &&
               !inMissQueue(addr, is_secure);
    }

    return true;
}

bool
BasePrefetcher::inCache(Addr addr, bool is_secure) const
{
    if (cache->inCache(addr, is_secure)) {
        return true;
    }
    return false;
}

bool
BasePrefetcher::inMissQueue(Addr addr, bool is_secure) const
{
    if (cache->inMissQueue(addr, is_secure)) {
        return true;
    }
    return false;
}

bool
BasePrefetcher::samePage(Addr a, Addr b) const
{
    return roundDown(a, pageBytes) == roundDown(b, pageBytes);
}

<commit_msg>mem: Hide WriteInvalidate requests from prefetchers<commit_after>/*
 * Copyright (c) 2013-2014 ARM Limited
 * All rights reserved.
 *
 * The license below extends only to copyright in the software and shall
 * not be construed as granting a license to any other intellectual
 * property including but not limited to intellectual property relating
 * to a hardware implementation of the functionality of the software
 * licensed hereunder.  You may use the software subject to the license
 * terms below provided that you ensure that this notice is replicated
 * unmodified and in its entirety in all distributions of the software,
 * modified or unmodified, in source code or in binary form.
 *
 * Copyright (c) 2005 The Regents of The University of Michigan
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met: redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer;
 * redistributions in binary form must reproduce the above copyright
 * notice, this list of conditions and the following disclaimer in the
 * documentation and/or other materials provided with the distribution;
 * neither the name of the copyright holders nor the names of its
 * contributors may be used to endorse or promote products derived from
 * this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 * Authors: Ron Dreslinski
 *          Mitch Hayenga
 */

/**
 * @file
 * Hardware Prefetcher Definition.
 */

#include <list>

#include "mem/cache/prefetch/base.hh"
#include "mem/cache/base.hh"
#include "sim/system.hh"

BasePrefetcher::BasePrefetcher(const BasePrefetcherParams *p)
    : ClockedObject(p), cache(nullptr), blkSize(0), system(p->sys),
      onMiss(p->on_miss), onRead(p->on_read),
      onWrite(p->on_write), onData(p->on_data), onInst(p->on_inst),
      masterId(system->getMasterId(name())),
      pageBytes(system->getPageBytes())
{
}

void
BasePrefetcher::setCache(BaseCache *_cache)
{
    assert(!cache);
    cache = _cache;
    blkSize = cache->getBlockSize();
}

void
BasePrefetcher::regStats()
{
    pfIssued
        .name(name() + ".num_hwpf_issued")
        .desc("number of hwpf issued")
        ;
}

bool
BasePrefetcher::observeAccess(const PacketPtr &pkt) const
{
    Addr addr = pkt->getAddr();
    bool fetch = pkt->req->isInstFetch();
    bool read = pkt->isRead();
    bool inv = pkt->isInvalidate();
    bool is_secure = pkt->isSecure();

    if (pkt->req->isUncacheable()) return false;
    if (fetch && !onInst) return false;
    if (!fetch && !onData) return false;
    if (!fetch && read && !onRead) return false;
    if (!fetch && !read && !onWrite) return false;
    if (!fetch && !read && inv) return false;

    if (onMiss) {
        return !inCache(addr, is_secure) &&
               !inMissQueue(addr, is_secure);
    }

    return true;
}

bool
BasePrefetcher::inCache(Addr addr, bool is_secure) const
{
    if (cache->inCache(addr, is_secure)) {
        return true;
    }
    return false;
}

bool
BasePrefetcher::inMissQueue(Addr addr, bool is_secure) const
{
    if (cache->inMissQueue(addr, is_secure)) {
        return true;
    }
    return false;
}

bool
BasePrefetcher::samePage(Addr a, Addr b) const
{
    return roundDown(a, pageBytes) == roundDown(b, pageBytes);
}

<|endoftext|>


<commit_before>// ============================================================
// Example:     LCDML: graphic display with u8g
// ============================================================
// Author:      Jomelo
// Last update: 21.01.2018
// License:     MIT
// ============================================================
// Description:
// This example shows how to use the u8glib with the LCDMenuLib
// The menu can placed in a box that can be placed anywhere on
// the screen.
// ============================================================
// *********************************************************************
// special settings
// *********************************************************************
// enable this line when you are not usigng a standard arduino
// for example when your chip is an ESP or a STM or SAM or something else
//#define _LCDML_cfg_use_ram

  // include libs
  #include <LCDMenuLib2.h>

  //extern char* g_LCDML_DISP_lang_lcdml_table[254];   // uncomment if you have got problem with lib compile and undefined g_LCDML_DISP_lang_lcdml_table

  // U8g2lib
  #include <Arduino.h>
  #include <U8g2lib.h>

  #ifdef U8X8_HAVE_HW_SPI
  #include <SPI.h>
  #endif
  #ifdef U8X8_HAVE_HW_I2C
  #include <Wire.h>
  #endif

// *********************************************************************
// U8GLIB
// *********************************************************************
  // U8g2 Constructor List (Frame Buffer)
  // The complete list is available here: https://github.com/olikraus/u8g2/wiki/u8g2setupcpp
  // Please update the pin numbers according to your setup. Use U8X8_PIN_NONE if the reset pin is not connected
  //U8G2_ST7920_128X64_F_HW_SPI u8g2(U8G2_R0, /* CS=*/ 53, /* reset=*/ U8X8_PIN_NONE);     // (MEGA, ...
  //U8G2_ST7920_128X64_F_HW_SPI u8g2(U8G2_R0, /* CS=*/ 12, /* reset=*/ U8X8_PIN_NONE);   // (Uno and co
  U8G2_ST7920_128X64_F_SW_SPI u8g2(U8G2_R0, /* clock=*/ 25, /* data= /R/w */ 33, /* CS=*/ 32, /* reset= */ U8X8_PIN_NONE );  // ESP32

  // settings for u8g lib and LCD
  #define _LCDML_DISP_w                 128            // LCD width
  #define _LCDML_DISP_h                 64             // LCD height
  // font settings
  #define _LCDML_DISP_font              u8g2_font_squeezed_r7_tr   // u8g_font_6x13  // u8glib font (more fonts under u8g.h line 1520 ...)
  #define _LCDML_DISP_font_w            7              // font width
  #define _LCDML_DISP_font_h            8             // font height
  // cursor settings
  #define _LCDML_DISP_cursor_char       ">"            // cursor char
  #define _LCDML_DISP_cur_space_before  2              // cursor space between
  #define _LCDML_DISP_cur_space_behind  4              // cursor space between
  // menu position and size
  #define _LCDML_DISP_box_x0            0              // start point (x0, y0)
  #define _LCDML_DISP_box_y0            0              // start point (x0, y0)
  #define _LCDML_DISP_box_x1            128            // width x  (x0 + width)
  #define _LCDML_DISP_box_y1            64             // hight y  (y0 + height)
  #define _LCDML_DISP_draw_frame        1              // draw a box around the menu
   // scrollbar width
  #define _LCDML_DISP_scrollbar_w       6  // scrollbar width (if this value is < 3, the scrollbar is disabled)

  // nothing change here
  #define _LCDML_DISP_cols_max          ((_LCDML_DISP_box_x1-_LCDML_DISP_box_x0)/_LCDML_DISP_font_w)
  #define _LCDML_DISP_rows_max          ((_LCDML_DISP_box_y1-_LCDML_DISP_box_y0-((_LCDML_DISP_box_y1-_LCDML_DISP_box_y0)/_LCDML_DISP_font_h))/_LCDML_DISP_font_h)

  // rows and cols
  // when you use more rows or cols as allowed change in LCDMenuLib.h the define "_LCDML_DISP_cfg_max_rows" and "_LCDML_DISP_cfg_max_string_length"
  // the program needs more ram with this changes
  #define _LCDML_DISP_rows              _LCDML_DISP_rows_max  // max rows
  #define _LCDML_DISP_cols              20                   // max cols

// *********************************************************************
// Prototypes
// *********************************************************************
  void lcdml_menu_display();
  void lcdml_menu_clear();
  void lcdml_menu_control();

// *********************************************************************
// Objects
// *********************************************************************
  LCDMenuLib2_menu LCDML_0 (255, 0, 0, NULL, NULL); // root menu element (do not change)
  LCDMenuLib2 LCDML(LCDML_0, _LCDML_DISP_rows, _LCDML_DISP_cols, lcdml_menu_display, lcdml_menu_clear, lcdml_menu_control);

// Modification for PlatformIO and similar platforms
  #include <LCDML_display_dynFunction.h>
  #include <LCDML_display_menu.h>
  #include <LCDML_condition.h>
  #include <LCDML_display_menuFunction.h>
  #include <LCDML_control.h>

// *********************************************************************
// LCDML MENU/DISP
// *********************************************************************
  // LCDML_0        => layer 0
  // LCDML_0_X      => layer 1
  // LCDML_0_X_X    => layer 2
  // LCDML_0_X_X_X  => layer 3
  // LCDML_0_...      => layer ...

  // For beginners
  // LCDML_add(id, prev_layer, new_num, lang_char_array, callback_function)
  LCDML_add         (0  , LCDML_0         , 1  , "Information"      , mFunc_information);       // this menu function can be found on "LCDML_display_menuFunction" tab
  LCDML_add         (1  , LCDML_0         , 2  , "Time info"        , mFunc_timer_info);        // this menu function can be found on "LCDML_display_menuFunction" tab
  LCDML_add         (2  , LCDML_0         , 3  , "Program"          , NULL);                    // NULL = no menu function
  LCDML_add         (3  , LCDML_0_3       , 1  , "Program 1"        , NULL);                    // NULL = no menu function
  LCDML_add         (4  , LCDML_0_3_1     , 1  , "P1 dummy"         , NULL);                    // NULL = no menu function
  LCDML_add         (5  , LCDML_0_3_1     , 2  , "P1 Settings"      , NULL);                    // NULL = no menu function
  LCDML_add         (6  , LCDML_0_3_1_2   , 1  , "Warm"             , NULL);                    // NULL = no menu function
  LCDML_add         (7  , LCDML_0_3_1_2   , 2  , "Cold"             , NULL);                    // NULL = no menu function
  LCDML_add         (8  , LCDML_0_3_1_2   , 3  , "Back"             , mFunc_back);              // this menu function can be found on "LCDML_display_menuFunction" tab
  LCDML_add         (9  , LCDML_0_3_1     , 3  , "Back"             , mFunc_back);              // this menu function can be found on "LCDML_display_menuFunction" tab
  LCDML_add         (10 , LCDML_0_3       , 2  , "Program 2"        , mFunc_p2);                // this menu function can be found on "LCDML_display_menuFunction" tab
  LCDML_add         (11 , LCDML_0_3       , 3  , "Back"             , mFunc_back);              // this menu function can be found on "LCDML_display_menuFunction" tab
  LCDML_add         (12 , LCDML_0         , 4  , "Special"          , NULL);                    // NULL = no menu function
  LCDML_add         (13 , LCDML_0_4       , 1  , "Go to Root"       , mFunc_goToRootMenu);      // this menu function can be found on "LCDML_display_menuFunction" tab
  LCDML_add         (14 , LCDML_0_4       , 2  , "Jump to Time info", mFunc_jumpTo_timer_info); // this menu function can be found on "LCDML_display_menuFunction" tab
  LCDML_add         (15 , LCDML_0_4       , 3  , "Back"             , mFunc_back);              // this menu function can be found on "LCDML_display_menuFunction" tab

  // Advanced menu (for profit) part with more settings
  // Example for one function and different parameters
  // It is recommend to use parameters for switching settings like, (small drink, medium drink, big drink) or (200ml, 400ml, 600ml, 800ml) ...
  // the parameter change can also be released with dynParams on the next example
  // LCDMenuLib_addAdvanced(id, prev_layer,     new_num, condition,   lang_char_array, callback_function, parameter (0-255), menu function type  )
  LCDML_addAdvanced (16 , LCDML_0         , 5  , NULL,          "Parameter"      , NULL,                0,            _LCDML_TYPE_default);                    // NULL = no menu function
  LCDML_addAdvanced (17 , LCDML_0_5       , 1  , NULL,          "Parameter 1"      , mFunc_para,       10,            _LCDML_TYPE_default);                    // NULL = no menu function
  LCDML_addAdvanced (18 , LCDML_0_5       , 2  , NULL,          "Parameter 2"      , mFunc_para,       20,            _LCDML_TYPE_default);                    // NULL = no menu function
  LCDML_addAdvanced (19 , LCDML_0_5       , 3  , NULL,          "Parameter 3"      , mFunc_para,       30,            _LCDML_TYPE_default);                    // NULL = no menu function
  LCDML_add         (20 , LCDML_0_5       , 4  , "Back"             , mFunc_back);              // this menu function can be found on "LCDML_display_menuFunction" tab

  // Example for dynamic content
  // 1. set the string to ""
  // 2. use type  _LCDML_TYPE_dynParam   instead of    _LCDML_TYPE_default
  // this function type can not be used in combination with different parameters
  // LCDMenuLib_addAdvanced(id, prev_layer,     new_num, condition,   lang_char_array, callback_function, parameter (0-255), menu function type  )
  LCDML_addAdvanced (21 , LCDML_0         , 6  , NULL,          ""                  , mDyn_para,                0,   _LCDML_TYPE_dynParam);                     // NULL = no menu function

  // Example for conditions (for example for a screensaver)
  // 1. define a condition as a function of a boolean type -> return false = not displayed, return true = displayed
  // 2. set the function name as callback (remove the braces '()' it gives bad errors)
  // LCDMenuLib_addAdvanced(id, prev_layer,     new_num, condition,   lang_char_array, callback_function, parameter (0-255), menu function type  )
  LCDML_addAdvanced (22 , LCDML_0         , 7  , COND_hide,  "screensaver"        , mFunc_screensaver,        0,   _LCDML_TYPE_default);       // this menu function can be found on "LCDML_display_menuFunction" tab

  // ***TIP*** Try to update _LCDML_DISP_cnt when you add a menu element.

  // menu element count - last element id
  // this value must be the same as the last menu element
  #define _LCDML_DISP_cnt    22

  // create menu
  LCDML_createMenu(_LCDML_DISP_cnt);

// *********************************************************************
// SETUP
// *********************************************************************
  void setup()
  {
    u8g2.begin();

    // serial init; only be needed if serial control is used
    Serial.begin(9600);                // start serial
    Serial.println(F(_LCDML_VERSION)); // only for examples

    // LCDMenuLib Setup
    LCDML_setup(_LCDML_DISP_cnt);

    // Enable Menu Rollover
    LCDML.MENU_enRollover();

    // Enable Screensaver (screensaver menu function, time to activate in ms)
    LCDML.SCREEN_enable(mFunc_screensaver, 60000); // set to 60 seconds
    //LCDML.SCREEN_disable();

    // Some needful methods

    // You can jump to a menu function from anywhere with
    //LCDML.OTHER_jumpToFunc(mFunc_p2); // the parameter is the function name
  }

// *********************************************************************
// LOOP
// *********************************************************************
  void loop()
  {
    // this function must called here, do not delete it
    LCDML.loop();
  }

// *********************************************************************
// check some errors - do not change here anything
// *********************************************************************
# if(_LCDML_glcd_tft_box_x1 > _LCDML_glcd_tft_w)
# error _LCDML_glcd_tft_box_x1 is to big
# endif

# if(_LCDML_glcd_tft_box_y1 > _LCDML_glcd_tft_h)
# error _LCDML_glcd_tft_box_y1 is to big
# endif
<commit_msg>v2.2.7<commit_after>// ============================================================
// Example:     LCDML: graphic display with u8g
// ============================================================
// Author:      Jomelo
// Last update: 21.01.2018
// License:     MIT
// ============================================================
// Description:
// This example shows how to use the u8glib with the LCDMenuLib
// The menu can placed in a box that can be placed anywhere on
// the screen.
// ============================================================
// *********************************************************************
// special settings
// *********************************************************************
// enable this line when you are not usigng a standard arduino
// for example when your chip is an ESP or a STM or SAM or something else
//#define _LCDML_cfg_use_ram

  // include libs
  #include <LCDMenuLib2.h>

  //extern char* g_LCDML_DISP_lang_lcdml_table[254];   // uncomment if you have got problem with lib compile and undefined g_LCDML_DISP_lang_lcdml_table

  // U8g2lib
  #include <Arduino.h>
  #include <U8g2lib.h>

  #ifdef U8X8_HAVE_HW_SPI
  #include <SPI.h>
  #endif
  #ifdef U8X8_HAVE_HW_I2C
  #include <Wire.h>
  #endif

// *********************************************************************
// U8GLIB
// *********************************************************************
  // U8g2 Constructor List (Frame Buffer)
  // The complete list is available here: https://github.com/olikraus/u8g2/wiki/u8g2setupcpp
  // Please update the pin numbers according to your setup. Use U8X8_PIN_NONE if the reset pin is not connected
  //U8G2_ST7920_128X64_F_HW_SPI u8g2(U8G2_R0, /* CS=*/ 53, /* reset=*/ U8X8_PIN_NONE);     // (MEGA, ...
  //U8G2_ST7920_128X64_F_HW_SPI u8g2(U8G2_R0, /* CS=*/ 12, /* reset=*/ U8X8_PIN_NONE);   // (Uno and co
  U8G2_ST7920_128X64_F_SW_SPI u8g2(U8G2_R0, /* clock=*/ 25, /* data= /R/w */ 33, /* CS=*/ 32, /* reset= */ U8X8_PIN_NONE );  // ESP32

  // settings for u8g lib and LCD
  #define _LCDML_DISP_w                 128            // LCD width
  #define _LCDML_DISP_h                 64             // LCD height
  // font settings
  #define _LCDML_DISP_font              u8g2_font_squeezed_r7_tr   // u8g_font_6x13  // u8glib font (more fonts under u8g.h line 1520 ...)
  #define _LCDML_DISP_font_w            7              // font width
  #define _LCDML_DISP_font_h            8             // font height
  // cursor settings
  #define _LCDML_DISP_cursor_char       ">"            // cursor char
  #define _LCDML_DISP_cur_space_before  2              // cursor space between
  #define _LCDML_DISP_cur_space_behind  4              // cursor space between
  // menu position and size
  #define _LCDML_DISP_box_x0            0              // start point (x0, y0)
  #define _LCDML_DISP_box_y0            0              // start point (x0, y0)
  #define _LCDML_DISP_box_x1            128            // width x  (x0 + width)
  #define _LCDML_DISP_box_y1            64             // hight y  (y0 + height)
  #define _LCDML_DISP_draw_frame        1              // draw a box around the menu
   // scrollbar width
  #define _LCDML_DISP_scrollbar_w       6  // scrollbar width (if this value is < 3, the scrollbar is disabled)

  // nothing change here
  #define _LCDML_DISP_cols_max          ((_LCDML_DISP_box_x1-_LCDML_DISP_box_x0)/_LCDML_DISP_font_w)
  #define _LCDML_DISP_rows_max          ((_LCDML_DISP_box_y1-_LCDML_DISP_box_y0-((_LCDML_DISP_box_y1-_LCDML_DISP_box_y0)/_LCDML_DISP_font_h))/_LCDML_DISP_font_h)

  // rows and cols
  // when you use more rows or cols as allowed change in LCDMenuLib.h the define "_LCDML_DISP_cfg_max_rows" and "_LCDML_DISP_cfg_max_string_length"
  // the program needs more ram with this changes
  #define _LCDML_DISP_rows              _LCDML_DISP_rows_max  // max rows
  #define _LCDML_DISP_cols              20                   // max cols

// *********************************************************************
// Prototypes
// *********************************************************************
  void lcdml_menu_display();
  void lcdml_menu_clear();
  void lcdml_menu_control();

// *********************************************************************
// Objects
// *********************************************************************
  LCDMenuLib2_menu LCDML_0 (255, 0, 0, NULL, NULL); // root menu element (do not change)
  LCDMenuLib2 LCDML(LCDML_0, _LCDML_DISP_rows, _LCDML_DISP_cols, lcdml_menu_display, lcdml_menu_clear, lcdml_menu_control);

// Modification for PlatformIO and similar platforms
  #include <LCDML_display_dynFunction.h>
  #include <LCDML_display_menu.h>
  #include <LCDML_condition.h>
  #include <LCDML_display_menuFunction.h>
  #include <LCDML_control.h>

// *********************************************************************
// LCDML MENU/DISP
// *********************************************************************
  // LCDML_0        => layer 0
  // LCDML_0_X      => layer 1
  // LCDML_0_X_X    => layer 2
  // LCDML_0_X_X_X  => layer 3
  // LCDML_0_...      => layer ...

  // For beginners
  // LCDML_add(id, prev_layer, new_num, lang_char_array, callback_function)
  LCDML_add         (0  , LCDML_0         , 1  , "Information"      , mFunc_information);       // this menu function can be found on "LCDML_display_menuFunction" tab
  LCDML_add         (1  , LCDML_0         , 2  , "Time info"        , mFunc_timer_info);        // this menu function can be found on "LCDML_display_menuFunction" tab
  LCDML_add         (2  , LCDML_0         , 3  , "Program"          , NULL);                    // NULL = no menu function
  LCDML_add         (3  , LCDML_0_3       , 1  , "Program 1"        , NULL);                    // NULL = no menu function
  LCDML_add         (4  , LCDML_0_3_1     , 1  , "P1 dummy"         , NULL);                    // NULL = no menu function
  LCDML_add         (5  , LCDML_0_3_1     , 2  , "P1 Settings"      , NULL);                    // NULL = no menu function
  LCDML_add         (6  , LCDML_0_3_1_2   , 1  , "Warm"             , NULL);                    // NULL = no menu function
  LCDML_add         (7  , LCDML_0_3_1_2   , 2  , "Cold"             , NULL);                    // NULL = no menu function
  LCDML_add         (8  , LCDML_0_3_1_2   , 3  , "Back"             , mFunc_back);              // this menu function can be found on "LCDML_display_menuFunction" tab
  LCDML_add         (9  , LCDML_0_3_1     , 3  , "Back"             , mFunc_back);              // this menu function can be found on "LCDML_display_menuFunction" tab
  LCDML_add         (10 , LCDML_0_3       , 2  , "Program 2"        , mFunc_p2);                // this menu function can be found on "LCDML_display_menuFunction" tab
  LCDML_add         (11 , LCDML_0_3       , 3  , "Back"             , mFunc_back);              // this menu function can be found on "LCDML_display_menuFunction" tab
  LCDML_add         (12 , LCDML_0         , 4  , "Special"          , NULL);                    // NULL = no menu function
  LCDML_add         (13 , LCDML_0_4       , 1  , "Go to Root"       , mFunc_goToRootMenu);      // this menu function can be found on "LCDML_display_menuFunction" tab
  LCDML_add         (14 , LCDML_0_4       , 2  , "Jump to Time info", mFunc_jumpTo_timer_info); // this menu function can be found on "LCDML_display_menuFunction" tab
  LCDML_add         (15 , LCDML_0_4       , 3  , "Back"             , mFunc_back);              // this menu function can be found on "LCDML_display_menuFunction" tab

  // Advanced menu (for profit) part with more settings
  // Example for one function and different parameters
  // It is recommend to use parameters for switching settings like, (small drink, medium drink, big drink) or (200ml, 400ml, 600ml, 800ml) ...
  // the parameter change can also be released with dynParams on the next example
  // LCDMenuLib_addAdvanced(id, prev_layer,     new_num, condition,   lang_char_array, callback_function, parameter (0-255), menu function type  )
  LCDML_addAdvanced (16 , LCDML_0         , 5  , NULL,          "Parameter"      , NULL,                0,            _LCDML_TYPE_default);                    // NULL = no menu function
  LCDML_addAdvanced (17 , LCDML_0_5       , 1  , NULL,          "Parameter 1"      , mFunc_para,       10,            _LCDML_TYPE_default);                    // NULL = no menu function
  LCDML_addAdvanced (18 , LCDML_0_5       , 2  , NULL,          "Parameter 2"      , mFunc_para,       20,            _LCDML_TYPE_default);                    // NULL = no menu function
  LCDML_addAdvanced (19 , LCDML_0_5       , 3  , NULL,          "Parameter 3"      , mFunc_para,       30,            _LCDML_TYPE_default);                    // NULL = no menu function
  LCDML_add         (20 , LCDML_0_5       , 4  , "Back"             , mFunc_back);              // this menu function can be found on "LCDML_display_menuFunction" tab

  // Example for dynamic content
  // 1. set the string to ""
  // 2. use type  _LCDML_TYPE_dynParam   instead of    _LCDML_TYPE_default
  // this function type can not be used in combination with different parameters
  // LCDMenuLib_addAdvanced(id, prev_layer,     new_num, condition,   lang_char_array, callback_function, parameter (0-255), menu function type  )
  LCDML_addAdvanced (21 , LCDML_0         , 6  , NULL,          ""                  , mDyn_para,                0,   _LCDML_TYPE_dynParam);                     // NULL = no menu function

  // Example for conditions (for example for a screensaver)
  // 1. define a condition as a function of a boolean type -> return false = not displayed, return true = displayed
  // 2. set the function name as callback (remove the braces '()' it gives bad errors)
  // LCDMenuLib_addAdvanced(id, prev_layer,     new_num, condition,   lang_char_array, callback_function, parameter (0-255), menu function type  )
  LCDML_addAdvanced (22 , LCDML_0         , 7  , COND_hide,  "screensaver"        , mFunc_screensaver,        0,   _LCDML_TYPE_default);       // this menu function can be found on "LCDML_display_menuFunction" tab

  // ***TIP*** Try to update _LCDML_DISP_cnt when you add a menu element.

  // menu element count - last element id
  // this value must be the same as the last menu element
  #define _LCDML_DISP_cnt    22

  // create menu
  LCDML_createMenu(_LCDML_DISP_cnt);

// *********************************************************************
// SETUP
// *********************************************************************
  void setup()
  {
    u8g2.begin();

    // serial init; only be needed if serial control is used
    Serial.begin(9600);                // start serial
    Serial.println(F(_LCDML_VERSION)); // only for examples

    // LCDMenuLib Setup
    LCDML_setup(_LCDML_DISP_cnt);

    // Enable Menu Rollover
    LCDML.MENU_enRollover();

    // Enable Screensaver (screensaver menu function, time to activate in ms)
    LCDML.SCREEN_enable(mFunc_screensaver, 60000); // set to 60 seconds
    //LCDML.SCREEN_disable();

    // Some needful methods

    // You can jump to a menu function from anywhere with
    //LCDML.OTHER_jumpToFunc(mFunc_p2); // the parameter is the function name
  }

// *********************************************************************
// LOOP
// *********************************************************************
  void loop()
  {
    // this function must called here, do not delete it
    LCDML.loop();
  }

// *********************************************************************
// check some errors - do not change here anything
// *********************************************************************
# if(_LCDML_glcd_tft_box_x1 > _LCDML_glcd_tft_w)
# error _LCDML_glcd_tft_box_x1 is to big
# endif

# if(_LCDML_glcd_tft_box_y1 > _LCDML_glcd_tft_h)
# error _LCDML_glcd_tft_box_y1 is to big
# endif<|endoftext|>


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

The Medical Imaging Interaction Toolkit (MITK)

Copyright (c) German Cancer Research Center,
Division of Medical and Biological Informatics.
All rights reserved.

This software is distributed WITHOUT ANY WARRANTY; without
even the implied warranty of MERCHANTABILITY or FITNESS FOR
A PARTICULAR PURPOSE.

See LICENSE.txt or http://www.mitk.org for details.

===================================================================*/
#include "QmitkOtsuAction.h"

// MITK
#include <itkOtsuMultipleThresholdsImageFilter.h>
#include <mitkRenderingManager.h>
#include <mitkImage.h>
#include <mitkImageCast.h>
#include <mitkITKImageImport.h>
#include <mitkLevelWindowProperty.h>

// ITK
#include <itkMultiplyImageFilter.h>

// Qt
#include <QDialog>
#include <QVBoxLayout>
#include <QApplication>
#include <QList>
#include <QLabel>
#include <QMessageBox>

using namespace berry;
using namespace mitk;
using namespace std;

QmitkOtsuAction::QmitkOtsuAction()
: m_OtsuSegmentationDialog(NULL)
{
}

QmitkOtsuAction::~QmitkOtsuAction()
{
}

void QmitkOtsuAction::Run(const QList<DataNode::Pointer> &selectedNodes)
{
  this->m_DataNode = selectedNodes[0];
  //this->m_selectedNodes = selectedNodes;

  m_OtsuSegmentationDialog = new QDialog(QApplication::activeWindow());

  QVBoxLayout *layout = new QVBoxLayout;
  layout->setContentsMargins(0, 0, 0, 0);

  m_OtsuSpinBox = new QSpinBox;
  m_OtsuSpinBox->setRange(2, 32);
  m_OtsuSpinBox->setValue(2);

  m_OtsuPushButton = new QPushButton("OK");

  connect(m_OtsuPushButton, SIGNAL(clicked()), this, SLOT(OtsuSegmentationDone()));

  QLabel* numberOfThresholdsLabel = new QLabel("Select number of Regions of Interest:");
  //numberOfThresholdsLabel->setAlignment(Qt::AlignmentFlag::AlignHCenter);
  //numberOfThresholdsLabel->setAlignment(Qt::AlignmentFlag::AlignVCenter);
  numberOfThresholdsLabel->setAlignment(Qt::AlignVCenter | Qt::AlignHCenter);
  layout->addWidget(numberOfThresholdsLabel);
  layout->addWidget(m_OtsuSpinBox);
  layout->addWidget(m_OtsuPushButton);

  m_OtsuSegmentationDialog->setLayout(layout);
  m_OtsuSegmentationDialog->setFixedSize(300, 80);

  m_OtsuSegmentationDialog->open();
}

void QmitkOtsuAction::OtsuSegmentationDone()
{

  /*
  if (result == QDialog::Rejected)
  m_ThresholdingToolManager->ActivateTool(-1);*/

  this->PerformOtsuSegmentation();

  m_OtsuSegmentationDialog->deleteLater();
  m_OtsuSegmentationDialog = NULL;

  //m_ThresholdingToolManager->SetReferenceData(NULL);
  //m_ThresholdingToolManager->SetWorkingData(NULL);

  RenderingManager::GetInstance()->RequestUpdateAll();
}

void QmitkOtsuAction::SetDataStorage(DataStorage *dataStorage)
{
  m_DataStorage = dataStorage;
}

void QmitkOtsuAction::SetFunctionality(QtViewPart* /*functionality*/)
{
}

void QmitkOtsuAction::PerformOtsuSegmentation()
{
  int numberOfThresholds = this->m_OtsuSpinBox->value() - 1;
  int proceed;

  QMessageBox* messageBox = new QMessageBox(QMessageBox::Question, NULL, "The otsu segmentation computation may take several minutes depending on the number of Regions you selected. Proceed anyway?", QMessageBox::Ok | QMessageBox::Cancel);
  if (numberOfThresholds >= 5)
  {
    proceed = messageBox->exec();
    if (proceed != QMessageBox::Ok) return;
  }

  mitk::Image::Pointer mitkImage = 0;

  mitkImage = dynamic_cast<mitk::Image*>( this->m_DataNode->GetData() );

  try
  {
    // get selected mitk image
    const unsigned short dim = 3;
    typedef short InputPixelType;
    typedef unsigned char OutputPixelType;

    typedef itk::Image< InputPixelType, dim > InputImageType;
    typedef itk::Image< OutputPixelType, dim > OutputImageType;

    //typedef itk::OtsuThresholdImageFilter< InputImageType, OutputImageType > FilterType;
    typedef itk::OtsuMultipleThresholdsImageFilter< InputImageType, OutputImageType > FilterType;
    //typedef itk::MultiplyImageFilter< OutputImageType, OutputImageType, OutputImageType> MultiplyFilterType;
    //typedef itk::RandomImageSource< OutputImageType> RandomImageSourceType;
    //typedef itk::ImageRegionIterator< OutputImageType > ImageIteratorType;

    FilterType::Pointer filter = FilterType::New();
    //MultiplyFilterType::Pointer multiplyImageFilter = MultiplyFilterType::New();
    //RandomImageSourceType::Pointer randomImageSource = RandomImageSourceType::New();

    filter->SetNumberOfThresholds(numberOfThresholds);
    //filter->SetLabelOffset(0);
    /*
    filter->SetOutsideValue( 1 );
    filter->SetInsideValue( 0 );*/

    InputImageType::Pointer itkImage;
    mitk::CastToItkImage(mitkImage, itkImage);

    filter->SetInput( itkImage );
//    filter->UpdateOutputInformation();

    //multiplyImageFilter->SetInput1(filter->GetOutput());
    //OutputImageType::Pointer constantImage = OutputImageType::New();
    //constantImage->SetLargestPossibleRegion(filter->GetOutput()->GetLargestPossibleRegion());
    //constantImage->SetBufferedRegion(filter->GetOutput()->GetLargestPossibleRegion());
    //constantImage->Allocate();
    //ImageIteratorType it(constantImage, constantImage->GetLargestPossibleRegion());
    //while (!it.IsAtEnd())
    //{
    //  it.Set(1);
    //  ++it;
    //}

    ////randomImageSource->SetSize(filter->GetOutput()->GetLargestPossibleRegion().GetSize());
    ////multiplyImageFilter->SetInput2(randomImageSource->GetOutput());
    //multiplyImageFilter->SetInput2(constantImage);

    filter->Update();
    //multiplyImageFilter->Update();

    mitk::DataNode::Pointer resultNode = mitk::DataNode::New();
    std::string nameOfResultImage = this->m_DataNode->GetName();
    nameOfResultImage.append("Otsu");
    resultNode->SetProperty("name", mitk::StringProperty::New(nameOfResultImage) );
    resultNode->SetProperty("binary", mitk::BoolProperty::New(false) );
    resultNode->SetProperty("use color", mitk::BoolProperty::New(false) );

    mitk::LevelWindowProperty::Pointer levWinProp = mitk::LevelWindowProperty::New();
    mitk::LevelWindow levelwindow;
    levelwindow.SetRangeMinMax(0, numberOfThresholds);
    levWinProp->SetLevelWindow( levelwindow );
    resultNode->SetProperty( "levelwindow", levWinProp );

    //resultNode->SetData( mitk::ImportItkImage ( filter->GetOutput() ) );
    resultNode->SetData( mitk::ImportItkImage ( filter->GetOutput() ) );

    this->m_DataStorage->Add(resultNode, this->m_DataNode);

  }
  catch( std::exception& err )
  {
    MITK_ERROR(this->GetClassName()) << err.what();
  }
  }<commit_msg>COMP: added a cancel button to the Otsu Segmentation Dialog.<commit_after>/*===================================================================

The Medical Imaging Interaction Toolkit (MITK)

Copyright (c) German Cancer Research Center,
Division of Medical and Biological Informatics.
All rights reserved.

This software is distributed WITHOUT ANY WARRANTY; without
even the implied warranty of MERCHANTABILITY or FITNESS FOR
A PARTICULAR PURPOSE.

See LICENSE.txt or http://www.mitk.org for details.

===================================================================*/
#include "QmitkOtsuAction.h"

// MITK
#include <itkOtsuMultipleThresholdsImageFilter.h>
#include <mitkRenderingManager.h>
#include <mitkImage.h>
#include <mitkImageCast.h>
#include <mitkITKImageImport.h>
#include <mitkLevelWindowProperty.h>

// ITK
#include <itkMultiplyImageFilter.h>

// Qt
#include <QDialog>
#include <QVBoxLayout>
#include <QApplication>
#include <QList>
#include <QLabel>
#include <QMessageBox>

using namespace berry;
using namespace mitk;
using namespace std;

QmitkOtsuAction::QmitkOtsuAction()
: m_OtsuSegmentationDialog(NULL)
{
}

QmitkOtsuAction::~QmitkOtsuAction()
{
}

void QmitkOtsuAction::Run(const QList<DataNode::Pointer> &selectedNodes)
{
  this->m_DataNode = selectedNodes[0];
  //this->m_selectedNodes = selectedNodes;

  m_OtsuSegmentationDialog = new QDialog(QApplication::activeWindow());

  QVBoxLayout *layout = new QVBoxLayout;
  layout->setContentsMargins(0, 0, 0, 0);
  QHBoxLayout* spinBoxLayout = new QHBoxLayout;
  QHBoxLayout* buttonLayout = new QHBoxLayout;

  m_OtsuSpinBox = new QSpinBox;
  m_OtsuSpinBox->setRange(2, 32);
  m_OtsuSpinBox->setValue(2);

  m_OtsuPushButton = new QPushButton("OK");
  QPushButton* CancelButton = new QPushButton("Cancel");

  connect(m_OtsuPushButton, SIGNAL(clicked()), this, SLOT(OtsuSegmentationDone()));
  connect(CancelButton, SIGNAL(clicked()), m_OtsuSegmentationDialog, SLOT(reject()));

  QLabel* numberOfThresholdsLabel = new QLabel("Select number of Regions of Interest:");
  numberOfThresholdsLabel->setAlignment(Qt::AlignVCenter | Qt::AlignHCenter);
  layout->addWidget(numberOfThresholdsLabel);
  layout->addLayout(spinBoxLayout);
  spinBoxLayout->addSpacing(50);
  spinBoxLayout->addWidget(m_OtsuSpinBox);
  spinBoxLayout->addSpacing(50);
  layout->addLayout(buttonLayout);
  buttonLayout->addWidget(m_OtsuPushButton);
  buttonLayout->addWidget(CancelButton);

  m_OtsuSegmentationDialog->setLayout(layout);
  m_OtsuSegmentationDialog->setFixedSize(300, 80);

  m_OtsuSegmentationDialog->open();
}

void QmitkOtsuAction::OtsuSegmentationDone()
{

  /*
  if (result == QDialog::Rejected)
  m_ThresholdingToolManager->ActivateTool(-1);*/

  this->PerformOtsuSegmentation();

  m_OtsuSegmentationDialog->deleteLater();
  m_OtsuSegmentationDialog = NULL;

  //m_ThresholdingToolManager->SetReferenceData(NULL);
  //m_ThresholdingToolManager->SetWorkingData(NULL);

  RenderingManager::GetInstance()->RequestUpdateAll();
}

void QmitkOtsuAction::SetDataStorage(DataStorage *dataStorage)
{
  m_DataStorage = dataStorage;
}

void QmitkOtsuAction::SetFunctionality(QtViewPart* /*functionality*/)
{
}

void QmitkOtsuAction::PerformOtsuSegmentation()
{
  int numberOfThresholds = this->m_OtsuSpinBox->value() - 1;
  int proceed;

  QMessageBox* messageBox = new QMessageBox(QMessageBox::Question, NULL, "The otsu segmentation computation may take several minutes depending on the number of Regions you selected. Proceed anyway?", QMessageBox::Ok | QMessageBox::Cancel);
  if (numberOfThresholds >= 5)
  {
    proceed = messageBox->exec();
    if (proceed != QMessageBox::Ok) return;
  }

  mitk::Image::Pointer mitkImage = 0;

  mitkImage = dynamic_cast<mitk::Image*>( this->m_DataNode->GetData() );

  try
  {
    // get selected mitk image
    const unsigned short dim = 3;
    typedef short InputPixelType;
    typedef unsigned char OutputPixelType;

    typedef itk::Image< InputPixelType, dim > InputImageType;
    typedef itk::Image< OutputPixelType, dim > OutputImageType;

    //typedef itk::OtsuThresholdImageFilter< InputImageType, OutputImageType > FilterType;
    typedef itk::OtsuMultipleThresholdsImageFilter< InputImageType, OutputImageType > FilterType;
    //typedef itk::MultiplyImageFilter< OutputImageType, OutputImageType, OutputImageType> MultiplyFilterType;
    //typedef itk::RandomImageSource< OutputImageType> RandomImageSourceType;
    //typedef itk::ImageRegionIterator< OutputImageType > ImageIteratorType;

    FilterType::Pointer filter = FilterType::New();
    //MultiplyFilterType::Pointer multiplyImageFilter = MultiplyFilterType::New();
    //RandomImageSourceType::Pointer randomImageSource = RandomImageSourceType::New();

    filter->SetNumberOfThresholds(numberOfThresholds);
    //filter->SetLabelOffset(0);
    /*
    filter->SetOutsideValue( 1 );
    filter->SetInsideValue( 0 );*/

    InputImageType::Pointer itkImage;
    mitk::CastToItkImage(mitkImage, itkImage);

    filter->SetInput( itkImage );
//    filter->UpdateOutputInformation();

    //multiplyImageFilter->SetInput1(filter->GetOutput());
    //OutputImageType::Pointer constantImage = OutputImageType::New();
    //constantImage->SetLargestPossibleRegion(filter->GetOutput()->GetLargestPossibleRegion());
    //constantImage->SetBufferedRegion(filter->GetOutput()->GetLargestPossibleRegion());
    //constantImage->Allocate();
    //ImageIteratorType it(constantImage, constantImage->GetLargestPossibleRegion());
    //while (!it.IsAtEnd())
    //{
    //  it.Set(1);
    //  ++it;
    //}

    ////randomImageSource->SetSize(filter->GetOutput()->GetLargestPossibleRegion().GetSize());
    ////multiplyImageFilter->SetInput2(randomImageSource->GetOutput());
    //multiplyImageFilter->SetInput2(constantImage);

    filter->Update();
    //multiplyImageFilter->Update();

    mitk::DataNode::Pointer resultNode = mitk::DataNode::New();
    std::string nameOfResultImage = this->m_DataNode->GetName();
    nameOfResultImage.append("Otsu");
    resultNode->SetProperty("name", mitk::StringProperty::New(nameOfResultImage) );
    resultNode->SetProperty("binary", mitk::BoolProperty::New(false) );
    resultNode->SetProperty("use color", mitk::BoolProperty::New(false) );

    mitk::LevelWindowProperty::Pointer levWinProp = mitk::LevelWindowProperty::New();
    mitk::LevelWindow levelwindow;
    levelwindow.SetRangeMinMax(0, numberOfThresholds);
    levWinProp->SetLevelWindow( levelwindow );
    resultNode->SetProperty( "levelwindow", levWinProp );

    //resultNode->SetData( mitk::ImportItkImage ( filter->GetOutput() ) );
    resultNode->SetData( mitk::ImportItkImage ( filter->GetOutput() ) );

    this->m_DataStorage->Add(resultNode, this->m_DataNode);

  }
  catch( std::exception& err )
  {
    MITK_ERROR(this->GetClassName()) << err.what();
  }
  }<|endoftext|>


<commit_before>//===- PowerPCSubtarget.cpp - PPC Subtarget Information ---------*- C++ -*-===//
//
//                     The LLVM Compiler Infrastructure
//
// This file was developed by Nate Begeman and is distributed under the
// University of Illinois Open Source License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file implements the PPC specific subclass of TargetSubtarget.
//
//===----------------------------------------------------------------------===//

#include "PPCSubtarget.h"
#include "PPC.h"
#include "llvm/Module.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Target/SubtargetFeature.h"
#include "PPCGenSubtarget.inc"

using namespace llvm;
PPCTargetEnum llvm::PPCTarget = TargetDefault;

namespace llvm {
  cl::opt<PPCTargetEnum, true>
  PPCTargetArg(cl::desc("Force generation of code for a specific PPC target:"),
               cl::values(
                          clEnumValN(TargetAIX,  "aix", "  Enable AIX codegen"),
                          clEnumValN(TargetDarwin,"darwin",
                                     "  Enable Darwin codegen"),
                          clEnumValEnd),
               cl::location(PPCTarget), cl::init(TargetDefault));
}

/// Length of FeatureKV.
static const unsigned FeatureKVSize = sizeof(FeatureKV)
                                          / sizeof(SubtargetFeatureKV);
/// Length of SubTypeKV.
static const unsigned SubTypeKVSize = sizeof(SubTypeKV)
                                             / sizeof(SubtargetFeatureKV);

#if defined(__APPLE__)
#include <mach/mach.h>
#include <mach/mach_host.h>
#include <mach/host_info.h>
#include <mach/machine.h>

/// GetCurrentPowerPCFeatures - Returns the current CPUs features.
static const char *GetCurrentPowerPCCPU() {
  host_basic_info_data_t hostInfo;
  mach_msg_type_number_t infoCount;

  infoCount = HOST_BASIC_INFO_COUNT;
  host_info(mach_host_self(), HOST_BASIC_INFO, (host_info_t)&hostInfo,
            &infoCount);

  if (hostInfo.cpu_type != CPU_TYPE_POWERPC) return "generic";

  switch(hostInfo.cpu_subtype) {
  case CPU_SUBTYPE_POWERPC_601:   return "601";
  case CPU_SUBTYPE_POWERPC_602:   return "602";
  case CPU_SUBTYPE_POWERPC_603:   return "603";
  case CPU_SUBTYPE_POWERPC_603e:  return "603e";
  case CPU_SUBTYPE_POWERPC_603ev: return "603ev";
  case CPU_SUBTYPE_POWERPC_604:   return "604";
  case CPU_SUBTYPE_POWERPC_604e:  return "604e";
  case CPU_SUBTYPE_POWERPC_620:   return "620";
  case CPU_SUBTYPE_POWERPC_750:   return "750";
  case CPU_SUBTYPE_POWERPC_7400:  return "7400";
  case CPU_SUBTYPE_POWERPC_7450:  return "7450";
  case CPU_SUBTYPE_POWERPC_970:   return "970";
  default: ;
  }

  return "generic";
}
#endif

PPCSubtarget::PPCSubtarget(const Module &M, const std::string &FS)
  : StackAlignment(16), IsGigaProcessor(false), IsAIX(false), IsDarwin(false) {

  // Determine default and user specified characteristics
  std::string CPU = "generic";
#if defined(__APPLE__)
  CPU = GetCurrentPowerPCCPU();
#endif
  uint32_t Bits =
  SubtargetFeatures::Parse(FS, CPU,
                           SubTypeKV, SubTypeKVSize, FeatureKV, FeatureKVSize);
  IsGigaProcessor = (Bits & FeatureGPUL ) != 0;
  Is64Bit         = (Bits & Feature64Bit) != 0;
  HasFSQRT        = (Bits & FeatureFSqrt) != 0;
  Has64BitRegs    = (Bits & Feature64BitRegs) != 0;

  // Set the boolean corresponding to the current target triple, or the default
  // if one cannot be determined, to true.
  const std::string& TT = M.getTargetTriple();
  if (TT.length() > 5) {
    IsDarwin = TT.find("darwin") != std::string::npos;
  } else if (TT.empty()) {
#if defined(_POWER)
    IsAIX = true;
#elif defined(__APPLE__)
    IsDarwin = true;
#endif
  }
}
<commit_msg>Simplify this, matching changes in the tblgen emitter<commit_after>//===- PowerPCSubtarget.cpp - PPC Subtarget Information ---------*- C++ -*-===//
//
//                     The LLVM Compiler Infrastructure
//
// This file was developed by Nate Begeman and is distributed under the
// University of Illinois Open Source License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file implements the PPC specific subclass of TargetSubtarget.
//
//===----------------------------------------------------------------------===//

#include "PPCSubtarget.h"
#include "PPC.h"
#include "llvm/Module.h"
#include "llvm/Support/CommandLine.h"
#include "PPCGenSubtarget.inc"

using namespace llvm;
PPCTargetEnum llvm::PPCTarget = TargetDefault;

namespace llvm {
  cl::opt<PPCTargetEnum, true>
  PPCTargetArg(cl::desc("Force generation of code for a specific PPC target:"),
               cl::values(
                          clEnumValN(TargetAIX,  "aix", "  Enable AIX codegen"),
                          clEnumValN(TargetDarwin,"darwin",
                                     "  Enable Darwin codegen"),
                          clEnumValEnd),
               cl::location(PPCTarget), cl::init(TargetDefault));
}

#if defined(__APPLE__)
#include <mach/mach.h>
#include <mach/mach_host.h>
#include <mach/host_info.h>
#include <mach/machine.h>

/// GetCurrentPowerPCFeatures - Returns the current CPUs features.
static const char *GetCurrentPowerPCCPU() {
  host_basic_info_data_t hostInfo;
  mach_msg_type_number_t infoCount;

  infoCount = HOST_BASIC_INFO_COUNT;
  host_info(mach_host_self(), HOST_BASIC_INFO, (host_info_t)&hostInfo,
            &infoCount);

  if (hostInfo.cpu_type != CPU_TYPE_POWERPC) return "generic";

  switch(hostInfo.cpu_subtype) {
  case CPU_SUBTYPE_POWERPC_601:   return "601";
  case CPU_SUBTYPE_POWERPC_602:   return "602";
  case CPU_SUBTYPE_POWERPC_603:   return "603";
  case CPU_SUBTYPE_POWERPC_603e:  return "603e";
  case CPU_SUBTYPE_POWERPC_603ev: return "603ev";
  case CPU_SUBTYPE_POWERPC_604:   return "604";
  case CPU_SUBTYPE_POWERPC_604e:  return "604e";
  case CPU_SUBTYPE_POWERPC_620:   return "620";
  case CPU_SUBTYPE_POWERPC_750:   return "750";
  case CPU_SUBTYPE_POWERPC_7400:  return "7400";
  case CPU_SUBTYPE_POWERPC_7450:  return "7450";
  case CPU_SUBTYPE_POWERPC_970:   return "970";
  default: ;
  }

  return "generic";
}
#endif

PPCSubtarget::PPCSubtarget(const Module &M, const std::string &FS)
  : StackAlignment(16), IsGigaProcessor(false), IsAIX(false), IsDarwin(false) {

  // Determine default and user specified characteristics
  std::string CPU = "generic";
#if defined(__APPLE__)
  CPU = GetCurrentPowerPCCPU();
#endif
  uint32_t Bits =
  SubtargetFeatures::Parse(FS, CPU,
                           SubTypeKV, SubTypeKVSize, FeatureKV, FeatureKVSize);
  IsGigaProcessor = (Bits & FeatureGPUL ) != 0;
  Is64Bit         = (Bits & Feature64Bit) != 0;
  HasFSQRT        = (Bits & FeatureFSqrt) != 0;
  Has64BitRegs    = (Bits & Feature64BitRegs) != 0;

  // Set the boolean corresponding to the current target triple, or the default
  // if one cannot be determined, to true.
  const std::string& TT = M.getTargetTriple();
  if (TT.length() > 5) {
    IsDarwin = TT.find("darwin") != std::string::npos;
  } else if (TT.empty()) {
#if defined(_POWER)
    IsAIX = true;
#elif defined(__APPLE__)
    IsDarwin = true;
#endif
  }
}
<|endoftext|>


<commit_before>/*
 *  Copyright (c) 2011 James Peach
 *
 *  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 <ts/ts.h>
#include <stdlib.h>
#include <spdy/spdy.h>
#include <base/logging.h>

#include "io.h"
#include "protocol.h"

static int spdy_vconn_io(TSCont, TSEvent, void *);

static void
recv_rst_stream(
        const spdy::message_header& header,
        spdy_io_control *           io,
        const uint8_t __restrict *  ptr)
{
    spdy::rst_stream_message rst;

    rst = spdy::rst_stream_message::parse(ptr, header.datalen);

    debug_protocol("[%p/%u] received %s frame stream=%u status_code=%s (%u)",
            io, rst.stream_id,
            cstringof(header.control.type), rst.stream_id,
            cstringof((spdy::error)rst.status_code), rst.status_code);

    io->destroy_stream(rst.stream_id);
}

static void
recv_syn_stream(
        const spdy::message_header& header,
        spdy_io_control *           io,
        const uint8_t __restrict *  ptr)
{
    spdy::syn_stream_message    syn;
    spdy_io_stream *            stream;

    syn = spdy::syn_stream_message::parse(ptr, header.datalen);

    debug_protocol(
            "[%p/%u] received %s frame stream=%u associated=%u priority=%u",
            io, syn.stream_id,
            cstringof(header.control.type), syn.stream_id,
            syn.associated_id, syn.priority);

    if (!io->valid_client_stream_id(syn.stream_id)) {
        debug_protocol("[%p/%u] invalid stream-id %u",
                io, syn.stream_id, syn.stream_id);
        spdy_send_reset_stream(io, syn.stream_id, spdy::PROTOCOL_ERROR);
        return;
    }

    switch (header.control.version) {
    case spdy::PROTOCOL_VERSION_2: // fallthru
    case spdy::PROTOCOL_VERSION_3: break;
    default:
        debug_protocol("[%p/%u] bad protocol version %d",
                io, syn.stream_id, header.control.version);
        spdy_send_reset_stream(io, syn.stream_id, spdy::PROTOCOL_ERROR);
        return;
    }

    spdy::key_value_block kvblock(
            spdy::key_value_block::parse(
                    (spdy::protocol_version)header.control.version,
                    io->decompressor,
                    ptr + spdy::syn_stream_message::size,
                    header.datalen - spdy::syn_stream_message::size)
    );

    if (!kvblock.url().is_complete()) {
        debug_protocol("[%p/%u] incomplete URL", io, syn.stream_id);
        // XXX missing URL, protocol error
        // 3.2.1 400 Bad Request
        spdy_send_reset_stream(io, syn.stream_id, spdy::INVALID_STREAM);
        // XXX send_http_txn_result()
        return;
    }

    if ((stream = io->create_stream(syn.stream_id)) == 0) {
        debug_protocol("[%p/%u] failed to create stream %u",
                io, syn.stream_id, syn.stream_id);
        spdy_send_reset_stream(io, syn.stream_id, spdy::INVALID_STREAM);
        return;
    }

    stream->io = io;
    stream->version = (spdy::protocol_version)header.control.version;
    stream->open(kvblock);
}

static void
recv_ping(
        const spdy::message_header& header,
        spdy_io_control *           io,
        const uint8_t __restrict *  ptr)
{
    spdy::ping_message ping;

    ping = spdy::ping_message::parse(ptr, header.datalen);

    debug_protocol("[%p] received PING id=%u", io, ping.ping_id);

    // Client must send even ping-ids. Ignore the odd ones since
    // we never send them.
    if ((ping.ping_id % 2) == 0) {
        return;
    }

    spdy_send_ping(io, (spdy::protocol_version)header.control.version, ping.ping_id);
}

static void
dispatch_spdy_control_frame(
        const spdy::message_header& header,
        spdy_io_control *           io,
        const uint8_t __restrict *  ptr)
{
    switch (header.control.type) {
    case spdy::CONTROL_SYN_STREAM:
        recv_syn_stream(header, io, ptr);
        break;
    case spdy::CONTROL_SYN_REPLY:
    case spdy::CONTROL_RST_STREAM:
        recv_rst_stream(header, io, ptr);
        break;
    case spdy::CONTROL_PING:
        recv_ping(header, io, ptr);
        break;
    case spdy::CONTROL_SETTINGS:
    case spdy::CONTROL_GOAWAY:
    case spdy::CONTROL_HEADERS:
    case spdy::CONTROL_WINDOW_UPDATE:
        debug_protocol(
            "[%p] SPDY control frame, version=%u type=%s flags=0x%x, %u bytes",
            io, header.control.version, cstringof(header.control.type),
            header.flags, header.datalen);
        break;
    default:
        // SPDY 2.2.1 - MUST ignore unrecognized control frames
        TSError("[spdy] ignoring invalid control frame type %u", header.control.type);
    }

    io->reenable();
}

static void
consume_spdy_frame(spdy_io_control * io)
{
    spdy::message_header    header;
    TSIOBufferBlock         blk;
    const uint8_t *         ptr;
    int64_t                 nbytes;

next_frame:

    blk = TSIOBufferStart(io->input.buffer);
    ptr = (const uint8_t *)TSIOBufferBlockReadStart(blk, io->input.reader, &nbytes);
    TSReleaseAssert(nbytes >= spdy::message_header::size);

    header = spdy::message_header::parse(ptr, (size_t)nbytes);
    TSAssert(header.datalen > 0); // XXX

    if (header.is_control) {
        if (header.control.version != spdy::PROTOCOL_VERSION) {
            TSError("[spdy] client is version %u, but we implement version %u",
                header.control.version, spdy::PROTOCOL_VERSION);
        }
    } else {
        debug_protocol("[%p] SPDY data frame, stream=%u flags=0x%x, %zu bytes",
            io, header.data.stream_id, header.flags, header.datalen);
    }

    if (header.datalen >= spdy::MAX_FRAME_LENGTH) {
        // XXX puke
    }

    if (header.datalen <= (nbytes - spdy::message_header::size)) {
        // We have all the data in-hand ... parse it.
        io->input.consume(spdy::message_header::size);
        io->input.consume(header.datalen);

        ptr += spdy::message_header::size;

        if (header.is_control) {
            dispatch_spdy_control_frame(header, io, ptr);
        } else {
            TSError("[spdy] no data frame support yet");
        }

        if (TSIOBufferReaderAvail(io->input.reader) >= spdy::message_header::size) {
            goto next_frame;
        }
    }

    // Push the high water mark to the end of the frame so that we don't get
    // called back until we have the whole thing.
    io->input.watermark(spdy::message_header::size + header.datalen);
}

static int
spdy_vconn_io(TSCont contp, TSEvent ev, void * edata)
{
    TSVIO               vio = (TSVIO)edata;
    int                 nbytes;
    spdy_io_control *   io;

    (void)vio;

    // Experimentally, we recieve the read or write TSVIO pointer as the
    // callback data.
    //debug_plugin("received IO event %s, VIO=%p", cstringof(ev), vio);

    switch (ev) {
    case TS_EVENT_VCONN_READ_READY:
    case TS_EVENT_VCONN_READ_COMPLETE:
        io = spdy_io_control::get(contp);
        nbytes = TSIOBufferReaderAvail(io->input.reader);
        debug_plugin("received %d bytes", nbytes);
        if ((unsigned)nbytes >= spdy::message_header::size) {
            consume_spdy_frame(io);
        }

        // XXX frame parsing can throw. If it does, best to catch it, log it
        // and drop the connection.
        break;
    case TS_EVENT_VCONN_WRITE_READY:
    case TS_EVENT_VCONN_WRITE_COMPLETE:
        // No need to handle write events. We have already pushed all the data
        // we have into the write buffer.
        break;
    case TS_EVENT_VCONN_EOS: // fallthru
    default:
        if (ev != TS_EVENT_VCONN_EOS) {
            debug_plugin("unexpected accept event %s", cstringof(ev));
        }
        io = spdy_io_control::get(contp);
        TSVConnClose(io->vconn);
        release(io);
    }

    return TS_EVENT_NONE;
}

static int
spdy_accept_io(TSCont contp, TSEvent ev, void * edata)
{
    TSVConn             vconn = (TSVConn)edata;;
    spdy_io_control *   io = nullptr;

    TSVIO read_vio, write_vio;

    switch (ev) {
    case TS_EVENT_NET_ACCEPT:
        io = retain(new spdy_io_control(vconn));
        io->input.watermark(spdy::message_header::size);
        io->output.watermark(spdy::message_header::size);
        // XXX is contp leaked here?
        contp = TSContCreate(spdy_vconn_io, TSMutexCreate());
        TSContDataSet(contp, io);
        read_vio = TSVConnRead(vconn, contp, io->input.buffer, INT64_MAX);
        write_vio = TSVConnWrite(vconn, contp, io->output.reader, INT64_MAX);
        debug_protocol("accepted new SPDY session %p", io);
        break;
    default:
        debug_plugin("unexpected accept event %s", cstringof(ev));
    }

    return TS_EVENT_NONE;
}

static void
spdy_initialize(uint16_t port)
{
    TSCont    contp;
    TSAction  action;

    contp = TSContCreate(spdy_accept_io, TSMutexCreate());
    action = TSNetAccept(contp, port, -1 /* domain */, 1 /* accept threads */);
    if (TSActionDone(action)) {
        debug_plugin("accept action done?");
    }
}

void
TSPluginInit(int argc, const char *argv[])
{
    int port;
    TSPluginRegistrationInfo info;

    info.plugin_name = (char *)"spdy";
    info.vendor_name = (char *)"James Peach";
    info.support_email = (char *)"jamespeach@me.com";

    if (TSPluginRegister(TS_SDK_VERSION_3_0, &info) != TS_SUCCESS) {
        TSError("[%s] Plugin registration failed", __func__);
    }

    debug_plugin("initializing");

    if (argc != 2) {
        TSError("[%s] Usage: spdy.so PORT", __func__);
        return;
    }

    port = atoi(argv[1]);
    if (port <= 1 || port > UINT16_MAX) {
        TSError("[%s] invalid port number: %s", __func__, argv[1]);
        return;
    }

    spdy_initialize((uint16_t)port);
}

/* vim: set sw=4 tw=79 ts=4 et ai : */
<commit_msg>Switch to TSIOBufferReaderStart<commit_after>/*
 *  Copyright (c) 2011 James Peach
 *
 *  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 <ts/ts.h>
#include <stdlib.h>
#include <spdy/spdy.h>
#include <base/logging.h>

#include "io.h"
#include "protocol.h"

static int spdy_vconn_io(TSCont, TSEvent, void *);

static void
recv_rst_stream(
        const spdy::message_header& header,
        spdy_io_control *           io,
        const uint8_t __restrict *  ptr)
{
    spdy::rst_stream_message rst;

    rst = spdy::rst_stream_message::parse(ptr, header.datalen);

    debug_protocol("[%p/%u] received %s frame stream=%u status_code=%s (%u)",
            io, rst.stream_id,
            cstringof(header.control.type), rst.stream_id,
            cstringof((spdy::error)rst.status_code), rst.status_code);

    io->destroy_stream(rst.stream_id);
}

static void
recv_syn_stream(
        const spdy::message_header& header,
        spdy_io_control *           io,
        const uint8_t __restrict *  ptr)
{
    spdy::syn_stream_message    syn;
    spdy_io_stream *            stream;

    syn = spdy::syn_stream_message::parse(ptr, header.datalen);

    debug_protocol(
            "[%p/%u] received %s frame stream=%u associated=%u priority=%u",
            io, syn.stream_id,
            cstringof(header.control.type), syn.stream_id,
            syn.associated_id, syn.priority);

    if (!io->valid_client_stream_id(syn.stream_id)) {
        debug_protocol("[%p/%u] invalid stream-id %u",
                io, syn.stream_id, syn.stream_id);
        spdy_send_reset_stream(io, syn.stream_id, spdy::PROTOCOL_ERROR);
        return;
    }

    switch (header.control.version) {
    case spdy::PROTOCOL_VERSION_2: // fallthru
    case spdy::PROTOCOL_VERSION_3: break;
    default:
        debug_protocol("[%p/%u] bad protocol version %d",
                io, syn.stream_id, header.control.version);
        spdy_send_reset_stream(io, syn.stream_id, spdy::PROTOCOL_ERROR);
        return;
    }

    spdy::key_value_block kvblock(
            spdy::key_value_block::parse(
                    (spdy::protocol_version)header.control.version,
                    io->decompressor,
                    ptr + spdy::syn_stream_message::size,
                    header.datalen - spdy::syn_stream_message::size)
    );

    if (!kvblock.url().is_complete()) {
        debug_protocol("[%p/%u] incomplete URL", io, syn.stream_id);
        // XXX missing URL, protocol error
        // 3.2.1 400 Bad Request
        spdy_send_reset_stream(io, syn.stream_id, spdy::INVALID_STREAM);
        // XXX send_http_txn_result()
        return;
    }

    if ((stream = io->create_stream(syn.stream_id)) == 0) {
        debug_protocol("[%p/%u] failed to create stream %u",
                io, syn.stream_id, syn.stream_id);
        spdy_send_reset_stream(io, syn.stream_id, spdy::INVALID_STREAM);
        return;
    }

    stream->io = io;
    stream->version = (spdy::protocol_version)header.control.version;
    stream->open(kvblock);
}

static void
recv_ping(
        const spdy::message_header& header,
        spdy_io_control *           io,
        const uint8_t __restrict *  ptr)
{
    spdy::ping_message ping;

    ping = spdy::ping_message::parse(ptr, header.datalen);

    debug_protocol("[%p] received PING id=%u", io, ping.ping_id);

    // Client must send even ping-ids. Ignore the odd ones since
    // we never send them.
    if ((ping.ping_id % 2) == 0) {
        return;
    }

    spdy_send_ping(io, (spdy::protocol_version)header.control.version, ping.ping_id);
}

static void
dispatch_spdy_control_frame(
        const spdy::message_header& header,
        spdy_io_control *           io,
        const uint8_t __restrict *  ptr)
{
    switch (header.control.type) {
    case spdy::CONTROL_SYN_STREAM:
        recv_syn_stream(header, io, ptr);
        break;
    case spdy::CONTROL_SYN_REPLY:
    case spdy::CONTROL_RST_STREAM:
        recv_rst_stream(header, io, ptr);
        break;
    case spdy::CONTROL_PING:
        recv_ping(header, io, ptr);
        break;
    case spdy::CONTROL_SETTINGS:
    case spdy::CONTROL_GOAWAY:
    case spdy::CONTROL_HEADERS:
    case spdy::CONTROL_WINDOW_UPDATE:
        debug_protocol(
            "[%p] SPDY control frame, version=%u type=%s flags=0x%x, %u bytes",
            io, header.control.version, cstringof(header.control.type),
            header.flags, header.datalen);
        break;
    default:
        // SPDY 2.2.1 - MUST ignore unrecognized control frames
        TSError("[spdy] ignoring invalid control frame type %u", header.control.type);
    }

    io->reenable();
}

static size_t
count_bytes_available(
        TSIOBuffer          buffer,
        TSIOBufferReader    reader)
{
    TSIOBufferBlock block;
    size_t count = 0;

    block = TSIOBufferStart(buffer);
    while (block) {
        const char * ptr;
        int64_t nbytes;

        ptr = TSIOBufferBlockReadStart(block, reader, &nbytes);
        if (ptr && nbytes) {
            count += nbytes;
        }

        block = TSIOBufferBlockNext(block);
    }

    return count;
}

static void
consume_spdy_frame(spdy_io_control * io)
{
    spdy::message_header    header;
    TSIOBufferBlock         blk;
    const uint8_t *         ptr;
    int64_t                 nbytes;

next_frame:

    blk = TSIOBufferReaderStart(io->input.reader);
    ptr = (const uint8_t *)TSIOBufferBlockReadStart(blk, io->input.reader, &nbytes);
    if (!ptr) {
        // This should not fail because we only try to consume the header when
        // there are enough bytes to read the header. Experimentally, however,
        // it does fail. I wonder why.
        TSError("TSIOBufferBlockReadStart failed unexpectedly");
        return;
    }

    if (nbytes < spdy::message_header::size) {
        // We should never get here, because we check for space before
        // entering. Unfortunately this does happen :(
        debug_plugin("short read %lld bytes, expected at least %u, real count %zu",
                nbytes, spdy::message_header::size,
                count_bytes_available(io->input.buffer, io->input.reader));
        return;
    }

    header = spdy::message_header::parse(ptr, (size_t)nbytes);
    TSAssert(header.datalen > 0); // XXX

    if (header.is_control) {
        if (header.control.version != spdy::PROTOCOL_VERSION) {
            TSError("[spdy] client is version %u, but we implement version %u",
                header.control.version, spdy::PROTOCOL_VERSION);
        }
    } else {
        debug_protocol("[%p] SPDY data frame, stream=%u flags=0x%x, %zu bytes",
            io, header.data.stream_id, header.flags, header.datalen);
    }

    if (header.datalen >= spdy::MAX_FRAME_LENGTH) {
        // XXX puke
    }

    if (header.datalen <= (nbytes - spdy::message_header::size)) {
        // We have all the data in-hand ... parse it.
        io->input.consume(spdy::message_header::size);
        io->input.consume(header.datalen);

        ptr += spdy::message_header::size;

        if (header.is_control) {
            dispatch_spdy_control_frame(header, io, ptr);
        } else {
            TSError("[spdy] no data frame support yet");
        }

        if (TSIOBufferReaderAvail(io->input.reader) >= spdy::message_header::size) {
            goto next_frame;
        }
    }

    // Push the high water mark to the end of the frame so that we don't get
    // called back until we have the whole thing.
    io->input.watermark(spdy::message_header::size + header.datalen);
}

static int
spdy_vconn_io(TSCont contp, TSEvent ev, void * edata)
{
    TSVIO               vio = (TSVIO)edata;
    int                 nbytes;
    spdy_io_control *   io;

    (void)vio;

    // Experimentally, we recieve the read or write TSVIO pointer as the
    // callback data.
    //debug_plugin("received IO event %s, VIO=%p", cstringof(ev), vio);

    switch (ev) {
    case TS_EVENT_VCONN_READ_READY:
    case TS_EVENT_VCONN_READ_COMPLETE:
        io = spdy_io_control::get(contp);
        nbytes = TSIOBufferReaderAvail(io->input.reader);
        debug_plugin("received %d bytes", nbytes);
        if ((unsigned)nbytes >= spdy::message_header::size) {
            consume_spdy_frame(io);
        }

        // XXX frame parsing can throw. If it does, best to catch it, log it
        // and drop the connection.
        break;
    case TS_EVENT_VCONN_WRITE_READY:
    case TS_EVENT_VCONN_WRITE_COMPLETE:
        // No need to handle write events. We have already pushed all the data
        // we have into the write buffer.
        break;
    case TS_EVENT_VCONN_EOS: // fallthru
    default:
        if (ev != TS_EVENT_VCONN_EOS) {
            debug_plugin("unexpected accept event %s", cstringof(ev));
        }
        io = spdy_io_control::get(contp);
        TSVConnClose(io->vconn);
        release(io);
    }

    return TS_EVENT_NONE;
}

static int
spdy_accept_io(TSCont contp, TSEvent ev, void * edata)
{
    TSVConn             vconn = (TSVConn)edata;;
    spdy_io_control *   io = nullptr;

    TSVIO read_vio, write_vio;

    switch (ev) {
    case TS_EVENT_NET_ACCEPT:
        io = retain(new spdy_io_control(vconn));
        io->input.watermark(spdy::message_header::size);
        io->output.watermark(spdy::message_header::size);
        // XXX is contp leaked here?
        contp = TSContCreate(spdy_vconn_io, TSMutexCreate());
        TSContDataSet(contp, io);
        read_vio = TSVConnRead(vconn, contp, io->input.buffer, INT64_MAX);
        write_vio = TSVConnWrite(vconn, contp, io->output.reader, INT64_MAX);
        debug_protocol("accepted new SPDY session %p", io);
        break;
    default:
        debug_plugin("unexpected accept event %s", cstringof(ev));
    }

    return TS_EVENT_NONE;
}

static void
spdy_initialize(uint16_t port)
{
    TSCont    contp;
    TSAction  action;

    contp = TSContCreate(spdy_accept_io, TSMutexCreate());
    action = TSNetAccept(contp, port, -1 /* domain */, 1 /* accept threads */);
    if (TSActionDone(action)) {
        debug_plugin("accept action done?");
    }
}

void
TSPluginInit(int argc, const char *argv[])
{
    int port;
    TSPluginRegistrationInfo info;

    info.plugin_name = (char *)"spdy";
    info.vendor_name = (char *)"James Peach";
    info.support_email = (char *)"jamespeach@me.com";

    if (TSPluginRegister(TS_SDK_VERSION_3_0, &info) != TS_SUCCESS) {
        TSError("[%s] Plugin registration failed", __func__);
    }

    debug_plugin("initializing");

    if (argc != 2) {
        TSError("[%s] Usage: spdy.so PORT", __func__);
        return;
    }

    port = atoi(argv[1]);
    if (port <= 1 || port > UINT16_MAX) {
        TSError("[%s] invalid port number: %s", __func__, argv[1]);
        return;
    }

    spdy_initialize((uint16_t)port);
}

/* vim: set sw=4 tw=79 ts=4 et ai : */
<|endoftext|>


<commit_before>#pragma once

#include <charconv>
#include <cstdint>
#include <optional>
#include <string>

namespace fly::detail {

/**
 * Helper struct to convert a std::string to a plain-old-data type, e.g. int or float.
 *
 * Ideally, this entire helper can be removed when the STL supports floating point types with
 * std::from_chars. However, only integral types are currently supported. Thus, integral types will
 * use std::from_chars, and floating point types will use the std::stof family of functions.
 *
 * https://en.cppreference.com/w/cpp/compiler_support
 *
 * @author Timothy Flynn (trflynn89@pm.me)
 * @version March 21, 2019
 */
template <typename T>
struct Converter
{
    static std::optional<T> convert(const std::string &value)
    {
        const auto *begin = value.data();
        const auto *end = begin + value.size();

        T converted {};
        auto result = std::from_chars(begin, end, converted);

        if ((result.ptr != end) || (result.ec != std::errc()))
        {
            return std::nullopt;
        }

        return converted;
    }
};

//==================================================================================================
template <>
struct Converter<float>
{
    static std::optional<float> convert(const std::string &value)
    {
        std::size_t index = 0;
        float result {};

        try
        {
            result = std::stof(value, &index);
        }
        catch (...)
        {
            return std::nullopt;
        }

        if (index != value.length())
        {
            return std::nullopt;
        }

        return result;
    }
};

//==================================================================================================
template <>
struct Converter<double>
{
    static std::optional<double> convert(const std::string &value)
    {
        std::size_t index = 0;
        double result {};

        try
        {
            result = std::stod(value, &index);
        }
        catch (...)
        {
            return std::nullopt;
        }

        if (index != value.length())
        {
            return std::nullopt;
        }

        return result;
    }
};

//==================================================================================================
template <>
struct Converter<long double>
{
    static std::optional<long double> convert(const std::string &value)
    {
        std::size_t index = 0;
        long double result {};

        try
        {
            result = std::stold(value, &index);
        }
        catch (...)
        {
            return std::nullopt;
        }

        if (index != value.length())
        {
            return std::nullopt;
        }

        return result;
    }
};

} // namespace fly::detail
<commit_msg>Use std::to_chars for converting floating-point values where available<commit_after>#pragma once

#include "fly/fly.hpp"

#include <charconv>
#include <cstdint>
#include <optional>
#include <string>

namespace fly::detail {

/**
 * Helper struct to convert a std::string to a plain-old-data type, e.g. int or float.
 *
 * Ideally, this entire helper can be removed when the STL supports floating point types with
 * std::from_chars. However, only integral types are currently supported. Thus, integral types will
 * use std::from_chars, and floating point types will use the std::stof family of functions.
 *
 * https://en.cppreference.com/w/cpp/compiler_support
 *
 * @author Timothy Flynn (trflynn89@pm.me)
 * @version March 21, 2019
 */
template <typename T>
struct Converter
{
    static std::optional<T> convert(const std::string &value)
    {
        const char *begin = value.data();
        const char *end = begin + value.size();

        T converted {};
        auto result = std::from_chars(begin, end, converted);

        if ((result.ptr != end) || (result.ec != std::errc {}))
        {
            return std::nullopt;
        }

        return converted;
    }
};

#if !defined(FLY_COMPILER_SUPPORTS_FP_CHARCONV)

//==================================================================================================
template <>
struct Converter<float>
{
    static std::optional<float> convert(const std::string &value)
    {
        std::size_t index = 0;
        float result {};

        try
        {
            result = std::stof(value, &index);
        }
        catch (...)
        {
            return std::nullopt;
        }

        if (index != value.length())
        {
            return std::nullopt;
        }

        return result;
    }
};

//==================================================================================================
template <>
struct Converter<double>
{
    static std::optional<double> convert(const std::string &value)
    {
        std::size_t index = 0;
        double result {};

        try
        {
            result = std::stod(value, &index);
        }
        catch (...)
        {
            return std::nullopt;
        }

        if (index != value.length())
        {
            return std::nullopt;
        }

        return result;
    }
};

//==================================================================================================
template <>
struct Converter<long double>
{
    static std::optional<long double> convert(const std::string &value)
    {
        std::size_t index = 0;
        long double result {};

        try
        {
            result = std::stold(value, &index);
        }
        catch (...)
        {
            return std::nullopt;
        }

        if (index != value.length())
        {
            return std::nullopt;
        }

        return result;
    }
};

#endif

} // namespace fly::detail
<|endoftext|>