<commit_before>//===-- StackProtector.cpp - Stack Protector Insertion --------------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This pass inserts stack protectors into functions which need them. A variable
// with a random value in it is stored onto the stack before the local variables
// are allocated. Upon exiting the block, the stored value is checked. If it's
// changed, then there was some sort of violation and the program aborts.
//
//===----------------------------------------------------------------------===//

#define DEBUG_TYPE "stack-protector"
#include "llvm/CodeGen/Passes.h"
#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/ADT/Statistic.h"
#include "llvm/ADT/Triple.h"
#include "llvm/Analysis/Dominators.h"
#include "llvm/IR/Attributes.h"
#include "llvm/IR/Constants.h"
#include "llvm/IR/DataLayout.h"
#include "llvm/IR/DerivedTypes.h"
#include "llvm/IR/Function.h"
#include "llvm/IR/GlobalValue.h"
#include "llvm/IR/GlobalVariable.h"
#include "llvm/IR/Instructions.h"
#include "llvm/IR/Intrinsics.h"
#include "llvm/IR/Module.h"
#include "llvm/Pass.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Target/TargetLowering.h"
#include <cstdlib>
using namespace llvm;

STATISTIC(NumFunProtected, "Number of functions protected");
STATISTIC(NumAddrTaken, "Number of local variables that have their address"
                        " taken.");

namespace {
  class StackProtector : public FunctionPass {
    const TargetMachine *TM;

    /// TLI - Keep a pointer of a TargetLowering to consult for determining
    /// target type sizes.
    const TargetLoweringBase *TLI;
    const Triple Trip;

    Function *F;
    Module *M;

    DominatorTree *DT;

    /// \brief The minimum size of buffers that will receive stack smashing
    /// protection when -fstack-protection is used.
    unsigned SSPBufferSize;

    /// VisitedPHIs - The set of PHI nodes visited when determining
    /// if a variable's reference has been taken.  This set
    /// is maintained to ensure we don't visit the same PHI node multiple
    /// times.
    SmallPtrSet<const PHINode*, 16> VisitedPHIs;

    /// InsertStackProtectors - Insert code into the prologue and epilogue of
    /// the function.
    ///
    ///  - The prologue code loads and stores the stack guard onto the stack.
    ///  - The epilogue checks the value stored in the prologue against the
    ///    original value. It calls __stack_chk_fail if they differ.
    bool InsertStackProtectors();

    /// CreateFailBB - Create a basic block to jump to when the stack protector
    /// check fails.
    BasicBlock *CreateFailBB();

    /// ContainsProtectableArray - Check whether the type either is an array or
    /// contains an array of sufficient size so that we need stack protectors
    /// for it.
    bool ContainsProtectableArray(Type *Ty, bool Strong = false,
                                  bool InStruct = false) const;

    /// \brief Check whether a stack allocation has its address taken.
    bool HasAddressTaken(const Instruction *AI);

    /// RequiresStackProtector - Check whether or not this function needs a
    /// stack protector based upon the stack protector level.
    bool RequiresStackProtector();
  public:
    static char ID;             // Pass identification, replacement for typeid.
    StackProtector() : FunctionPass(ID), TM(0), TLI(0), SSPBufferSize(0) {
      initializeStackProtectorPass(*PassRegistry::getPassRegistry());
    }
    StackProtector(const TargetMachine *TM)
      : FunctionPass(ID), TM(TM), TLI(0), Trip(TM->getTargetTriple()),
        SSPBufferSize(8) {
      initializeStackProtectorPass(*PassRegistry::getPassRegistry());
    }

    virtual void getAnalysisUsage(AnalysisUsage &AU) const {
      AU.addPreserved<DominatorTree>();
    }

    virtual bool runOnFunction(Function &Fn);
  };
} // end anonymous namespace

char StackProtector::ID = 0;
INITIALIZE_PASS(StackProtector, "stack-protector",
                "Insert stack protectors", false, false)

FunctionPass *llvm::createStackProtectorPass(const TargetMachine *TM) {
  return new StackProtector(TM);
}

bool StackProtector::runOnFunction(Function &Fn) {
  F = &Fn;
  M = F->getParent();
  DT = getAnalysisIfAvailable<DominatorTree>();
  TLI = TM->getTargetLowering();

  if (!RequiresStackProtector()) return false;

  Attribute Attr =
    Fn.getAttributes().getAttribute(AttributeSet::FunctionIndex,
                                    "stack-protector-buffer-size");
  if (Attr.isStringAttribute())
    SSPBufferSize = atoi(Attr.getValueAsString().data());

  ++NumFunProtected;
  return InsertStackProtectors();
}

/// ContainsProtectableArray - Check whether the type either is an array or
/// contains a char array of sufficient size so that we need stack protectors
/// for it.
bool StackProtector::ContainsProtectableArray(Type *Ty, bool Strong,
                                              bool InStruct) const {
  if (!Ty) return false;
  if (ArrayType *AT = dyn_cast<ArrayType>(Ty)) {
    // In strong mode any array, regardless of type and size, triggers a
    // protector
    if (Strong)
      return true;
    if (!AT->getElementType()->isIntegerTy(8)) {
      // If we're on a non-Darwin platform or we're inside of a structure, don't
      // add stack protectors unless the array is a character array.
      if (InStruct || !Trip.isOSDarwin())
          return false;
    }

    // If an array has more than SSPBufferSize bytes of allocated space, then we
    // emit stack protectors.
    if (SSPBufferSize <= TLI->getDataLayout()->getTypeAllocSize(AT))
      return true;
  }

  const StructType *ST = dyn_cast<StructType>(Ty);
  if (!ST) return false;

  for (StructType::element_iterator I = ST->element_begin(),
         E = ST->element_end(); I != E; ++I)
    if (ContainsProtectableArray(*I, Strong, true))
      return true;

  return false;
}

bool StackProtector::HasAddressTaken(const Instruction *AI) {
  for (Value::const_use_iterator UI = AI->use_begin(), UE = AI->use_end();
        UI != UE; ++UI) {
    const User *U = *UI;
    if (const StoreInst *SI = dyn_cast<StoreInst>(U)) {
      if (AI == SI->getValueOperand())
        return true;
    } else if (const PtrToIntInst *SI = dyn_cast<PtrToIntInst>(U)) {
      if (AI == SI->getOperand(0))
        return true;
    } else if (isa<CallInst>(U)) {
      return true;
    } else if (isa<InvokeInst>(U)) {
      return true;
    } else if (const SelectInst *SI = dyn_cast<SelectInst>(U)) {
      if (HasAddressTaken(SI))
        return true;
    } else if (const PHINode *PN = dyn_cast<PHINode>(U)) {
      // Keep track of what PHI nodes we have already visited to ensure
      // they are only visited once.
      if (VisitedPHIs.insert(PN))
        if (HasAddressTaken(PN))
          return true;
    } else if (const GetElementPtrInst *GEP = dyn_cast<GetElementPtrInst>(U)) {
      if (HasAddressTaken(GEP))
        return true;
    } else if (const BitCastInst *BI = dyn_cast<BitCastInst>(U)) {
      if (HasAddressTaken(BI))
        return true;
    }
  }
  return false;
}

/// \brief Check whether or not this function needs a stack protector based
/// upon the stack protector level.
///
/// We use two heuristics: a standard (ssp) and strong (sspstrong).
/// The standard heuristic which will add a guard variable to functions that
/// call alloca with a either a variable size or a size >= SSPBufferSize,
/// functions with character buffers larger than SSPBufferSize, and functions
/// with aggregates containing character buffers larger than SSPBufferSize. The
/// strong heuristic will add a guard variables to functions that call alloca
/// regardless of size, functions with any buffer regardless of type and size,
/// functions with aggregates that contain any buffer regardless of type and
/// size, and functions that contain stack-based variables that have had their
/// address taken.
bool StackProtector::RequiresStackProtector() {
  bool Strong = false;
  if (F->getAttributes().hasAttribute(AttributeSet::FunctionIndex,
                                      Attribute::StackProtectReq))
    return true;
  else if (F->getAttributes().hasAttribute(AttributeSet::FunctionIndex,
                                           Attribute::StackProtectStrong))
    Strong = true;
  else if (!F->getAttributes().hasAttribute(AttributeSet::FunctionIndex,
                                            Attribute::StackProtect))
    return false;

  for (Function::iterator I = F->begin(), E = F->end(); I != E; ++I) {
    BasicBlock *BB = I;

    for (BasicBlock::iterator
           II = BB->begin(), IE = BB->end(); II != IE; ++II) {
      if (AllocaInst *AI = dyn_cast<AllocaInst>(II)) {
        if (AI->isArrayAllocation()) {
          // SSP-Strong: Enable protectors for any call to alloca, regardless
          // of size.
          if (Strong)
            return true;

          if (const ConstantInt *CI =
               dyn_cast<ConstantInt>(AI->getArraySize())) {
            if (CI->getLimitedValue(SSPBufferSize) >= SSPBufferSize)
              // A call to alloca with size >= SSPBufferSize requires
              // stack protectors.
              return true;
          } else {
            // A call to alloca with a variable size requires protectors.
            return true;
          }
        }

        if (ContainsProtectableArray(AI->getAllocatedType(), Strong))
          return true;

        if (Strong && HasAddressTaken(AI)) {
          ++NumAddrTaken;
          return true;
        }
      }
    }
  }

  return false;
}

/// InsertStackProtectors - Insert code into the prologue and epilogue of the
/// function.
///
///  - The prologue code loads and stores the stack guard onto the stack.
///  - The epilogue checks the value stored in the prologue against the original
///    value. It calls __stack_chk_fail if they differ.
bool StackProtector::InsertStackProtectors() {
  BasicBlock *FailBB = 0;       // The basic block to jump to if check fails.
  BasicBlock *FailBBDom = 0;    // FailBB's dominator.
  AllocaInst *AI = 0;           // Place on stack that stores the stack guard.
  Value *StackGuardVar = 0;  // The stack guard variable.

  for (Function::iterator I = F->begin(), E = F->end(); I != E; ) {
    BasicBlock *BB = I++;
    ReturnInst *RI = dyn_cast<ReturnInst>(BB->getTerminator());
    if (!RI) continue;

    if (!FailBB) {
      // Insert code into the entry block that stores the __stack_chk_guard
      // variable onto the stack:
      //
      //   entry:
      //     StackGuardSlot = alloca i8*
      //     StackGuard = load __stack_chk_guard
      //     call void @llvm.stackprotect.create(StackGuard, StackGuardSlot)
      //
      PointerType *PtrTy = Type::getInt8PtrTy(RI->getContext());
      unsigned AddressSpace, Offset;
      if (TLI->getStackCookieLocation(AddressSpace, Offset)) {
        Constant *OffsetVal =
          ConstantInt::get(Type::getInt32Ty(RI->getContext()), Offset);

        StackGuardVar = ConstantExpr::getIntToPtr(OffsetVal,
                                      PointerType::get(PtrTy, AddressSpace));
      } else if (Trip.getOS() == llvm::Triple::OpenBSD) {
        StackGuardVar = M->getOrInsertGlobal("__guard_local", PtrTy);
        cast<GlobalValue>(StackGuardVar)
            ->setVisibility(GlobalValue::HiddenVisibility);
      } else {
        StackGuardVar = M->getOrInsertGlobal("__stack_chk_guard", PtrTy);
      }

      BasicBlock &Entry = F->getEntryBlock();
      Instruction *InsPt = &Entry.front();

      AI = new AllocaInst(PtrTy, "StackGuardSlot", InsPt);
      LoadInst *LI = new LoadInst(StackGuardVar, "StackGuard", false, InsPt);

      Value *Args[] = { LI, AI };
      CallInst::
        Create(Intrinsic::getDeclaration(M, Intrinsic::stackprotector),
               Args, "", InsPt);

      // Create the basic block to jump to when the guard check fails.
      FailBB = CreateFailBB();
    }

    // For each block with a return instruction, convert this:
    //
    //   return:
    //     ...
    //     ret ...
    //
    // into this:
    //
    //   return:
    //     ...
    //     %1 = load __stack_chk_guard
    //     %2 = load StackGuardSlot
    //     %3 = cmp i1 %1, %2
    //     br i1 %3, label %SP_return, label %CallStackCheckFailBlk
    //
    //   SP_return:
    //     ret ...
    //
    //   CallStackCheckFailBlk:
    //     call void @__stack_chk_fail()
    //     unreachable

    // Split the basic block before the return instruction.
    BasicBlock *NewBB = BB->splitBasicBlock(RI, "SP_return");

    if (DT && DT->isReachableFromEntry(BB)) {
      DT->addNewBlock(NewBB, BB);
      FailBBDom = FailBBDom ? DT->findNearestCommonDominator(FailBBDom, BB) :BB;
    }

    // Remove default branch instruction to the new BB.
    BB->getTerminator()->eraseFromParent();

    // Move the newly created basic block to the point right after the old basic
    // block so that it's in the "fall through" position.
    NewBB->moveAfter(BB);

    // Generate the stack protector instructions in the old basic block.
    LoadInst *LI1 = new LoadInst(StackGuardVar, "", false, BB);
    LoadInst *LI2 = new LoadInst(AI, "", true, BB);
    ICmpInst *Cmp = new ICmpInst(*BB, CmpInst::ICMP_EQ, LI1, LI2, "");
    BranchInst::Create(NewBB, FailBB, Cmp, BB);
  }

  // Return if we didn't modify any basic blocks. I.e., there are no return
  // statements in the function.
  if (!FailBB) return false;

  if (DT && FailBBDom)
    DT->addNewBlock(FailBB, FailBBDom);

  return true;
}

/// CreateFailBB - Create a basic block to jump to when the stack protector
/// check fails.
BasicBlock *StackProtector::CreateFailBB() {
  LLVMContext &Context = F->getContext();
  BasicBlock *FailBB = BasicBlock::Create(Context, "CallStackCheckFailBlk", F);
  if (Trip.getOS() == llvm::Triple::OpenBSD) {
    Constant *StackChkFail = M->getOrInsertFunction(
        "__stack_smash_handler", Type::getVoidTy(Context),
        Type::getInt8PtrTy(Context), NULL);

    Constant *NameStr = ConstantDataArray::getString(Context, F->getName());
    Constant *FuncName =
        new GlobalVariable(*M, NameStr->getType(), true,
                           GlobalVariable::PrivateLinkage, NameStr, "SSH");

    SmallVector<Constant *, 2> IdxList;
    IdxList.push_back(ConstantInt::get(Type::getInt8Ty(Context), 0));
    IdxList.push_back(ConstantInt::get(Type::getInt8Ty(Context), 0));

    SmallVector<Value *, 1> Args;
    Args.push_back(ConstantExpr::getGetElementPtr(FuncName, IdxList));

    CallInst::Create(StackChkFail, Args, "", FailBB);
  } else {
    Constant *StackChkFail = M->getOrInsertFunction(
        "__stack_chk_fail", Type::getVoidTy(Context), NULL);
    CallInst::Create(StackChkFail, "", FailBB);
  }
  new UnreachableInst(Context, FailBB);
  return FailBB;
}
<commit_msg>[stackprotector] Refactored ssp prologue creation code into its own helper function.<commit_after>//===-- StackProtector.cpp - Stack Protector Insertion --------------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This pass inserts stack protectors into functions which need them. A variable
// with a random value in it is stored onto the stack before the local variables
// are allocated. Upon exiting the block, the stored value is checked. If it's
// changed, then there was some sort of violation and the program aborts.
//
//===----------------------------------------------------------------------===//

#define DEBUG_TYPE "stack-protector"
#include "llvm/CodeGen/Passes.h"
#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/ADT/Statistic.h"
#include "llvm/ADT/Triple.h"
#include "llvm/Analysis/Dominators.h"
#include "llvm/IR/Attributes.h"
#include "llvm/IR/Constants.h"
#include "llvm/IR/DataLayout.h"
#include "llvm/IR/DerivedTypes.h"
#include "llvm/IR/Function.h"
#include "llvm/IR/GlobalValue.h"
#include "llvm/IR/GlobalVariable.h"
#include "llvm/IR/Instructions.h"
#include "llvm/IR/Intrinsics.h"
#include "llvm/IR/Module.h"
#include "llvm/Pass.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Target/TargetLowering.h"
#include <cstdlib>
using namespace llvm;

STATISTIC(NumFunProtected, "Number of functions protected");
STATISTIC(NumAddrTaken, "Number of local variables that have their address"
                        " taken.");

namespace {
  class StackProtector : public FunctionPass {
    const TargetMachine *TM;

    /// TLI - Keep a pointer of a TargetLowering to consult for determining
    /// target type sizes.
    const TargetLoweringBase *TLI;
    const Triple Trip;

    Function *F;
    Module *M;

    DominatorTree *DT;

    /// \brief The minimum size of buffers that will receive stack smashing
    /// protection when -fstack-protection is used.
    unsigned SSPBufferSize;

    /// VisitedPHIs - The set of PHI nodes visited when determining
    /// if a variable's reference has been taken.  This set
    /// is maintained to ensure we don't visit the same PHI node multiple
    /// times.
    SmallPtrSet<const PHINode*, 16> VisitedPHIs;

    /// InsertStackProtectors - Insert code into the prologue and epilogue of
    /// the function.
    ///
    ///  - The prologue code loads and stores the stack guard onto the stack.
    ///  - The epilogue checks the value stored in the prologue against the
    ///    original value. It calls __stack_chk_fail if they differ.
    bool InsertStackProtectors();

    /// CreateFailBB - Create a basic block to jump to when the stack protector
    /// check fails.
    BasicBlock *CreateFailBB();

    /// ContainsProtectableArray - Check whether the type either is an array or
    /// contains an array of sufficient size so that we need stack protectors
    /// for it.
    bool ContainsProtectableArray(Type *Ty, bool Strong = false,
                                  bool InStruct = false) const;

    /// \brief Check whether a stack allocation has its address taken.
    bool HasAddressTaken(const Instruction *AI);

    /// RequiresStackProtector - Check whether or not this function needs a
    /// stack protector based upon the stack protector level.
    bool RequiresStackProtector();
  public:
    static char ID;             // Pass identification, replacement for typeid.
    StackProtector() : FunctionPass(ID), TM(0), TLI(0), SSPBufferSize(0) {
      initializeStackProtectorPass(*PassRegistry::getPassRegistry());
    }
    StackProtector(const TargetMachine *TM)
      : FunctionPass(ID), TM(TM), TLI(0), Trip(TM->getTargetTriple()),
        SSPBufferSize(8) {
      initializeStackProtectorPass(*PassRegistry::getPassRegistry());
    }

    virtual void getAnalysisUsage(AnalysisUsage &AU) const {
      AU.addPreserved<DominatorTree>();
    }

    virtual bool runOnFunction(Function &Fn);
  };
} // end anonymous namespace

char StackProtector::ID = 0;
INITIALIZE_PASS(StackProtector, "stack-protector",
                "Insert stack protectors", false, false)

FunctionPass *llvm::createStackProtectorPass(const TargetMachine *TM) {
  return new StackProtector(TM);
}

bool StackProtector::runOnFunction(Function &Fn) {
  F = &Fn;
  M = F->getParent();
  DT = getAnalysisIfAvailable<DominatorTree>();
  TLI = TM->getTargetLowering();

  if (!RequiresStackProtector()) return false;

  Attribute Attr =
    Fn.getAttributes().getAttribute(AttributeSet::FunctionIndex,
                                    "stack-protector-buffer-size");
  if (Attr.isStringAttribute())
    SSPBufferSize = atoi(Attr.getValueAsString().data());

  ++NumFunProtected;
  return InsertStackProtectors();
}

/// ContainsProtectableArray - Check whether the type either is an array or
/// contains a char array of sufficient size so that we need stack protectors
/// for it.
bool StackProtector::ContainsProtectableArray(Type *Ty, bool Strong,
                                              bool InStruct) const {
  if (!Ty) return false;
  if (ArrayType *AT = dyn_cast<ArrayType>(Ty)) {
    // In strong mode any array, regardless of type and size, triggers a
    // protector
    if (Strong)
      return true;
    if (!AT->getElementType()->isIntegerTy(8)) {
      // If we're on a non-Darwin platform or we're inside of a structure, don't
      // add stack protectors unless the array is a character array.
      if (InStruct || !Trip.isOSDarwin())
          return false;
    }

    // If an array has more than SSPBufferSize bytes of allocated space, then we
    // emit stack protectors.
    if (SSPBufferSize <= TLI->getDataLayout()->getTypeAllocSize(AT))
      return true;
  }

  const StructType *ST = dyn_cast<StructType>(Ty);
  if (!ST) return false;

  for (StructType::element_iterator I = ST->element_begin(),
         E = ST->element_end(); I != E; ++I)
    if (ContainsProtectableArray(*I, Strong, true))
      return true;

  return false;
}

bool StackProtector::HasAddressTaken(const Instruction *AI) {
  for (Value::const_use_iterator UI = AI->use_begin(), UE = AI->use_end();
        UI != UE; ++UI) {
    const User *U = *UI;
    if (const StoreInst *SI = dyn_cast<StoreInst>(U)) {
      if (AI == SI->getValueOperand())
        return true;
    } else if (const PtrToIntInst *SI = dyn_cast<PtrToIntInst>(U)) {
      if (AI == SI->getOperand(0))
        return true;
    } else if (isa<CallInst>(U)) {
      return true;
    } else if (isa<InvokeInst>(U)) {
      return true;
    } else if (const SelectInst *SI = dyn_cast<SelectInst>(U)) {
      if (HasAddressTaken(SI))
        return true;
    } else if (const PHINode *PN = dyn_cast<PHINode>(U)) {
      // Keep track of what PHI nodes we have already visited to ensure
      // they are only visited once.
      if (VisitedPHIs.insert(PN))
        if (HasAddressTaken(PN))
          return true;
    } else if (const GetElementPtrInst *GEP = dyn_cast<GetElementPtrInst>(U)) {
      if (HasAddressTaken(GEP))
        return true;
    } else if (const BitCastInst *BI = dyn_cast<BitCastInst>(U)) {
      if (HasAddressTaken(BI))
        return true;
    }
  }
  return false;
}

/// \brief Check whether or not this function needs a stack protector based
/// upon the stack protector level.
///
/// We use two heuristics: a standard (ssp) and strong (sspstrong).
/// The standard heuristic which will add a guard variable to functions that
/// call alloca with a either a variable size or a size >= SSPBufferSize,
/// functions with character buffers larger than SSPBufferSize, and functions
/// with aggregates containing character buffers larger than SSPBufferSize. The
/// strong heuristic will add a guard variables to functions that call alloca
/// regardless of size, functions with any buffer regardless of type and size,
/// functions with aggregates that contain any buffer regardless of type and
/// size, and functions that contain stack-based variables that have had their
/// address taken.
bool StackProtector::RequiresStackProtector() {
  bool Strong = false;
  if (F->getAttributes().hasAttribute(AttributeSet::FunctionIndex,
                                      Attribute::StackProtectReq))
    return true;
  else if (F->getAttributes().hasAttribute(AttributeSet::FunctionIndex,
                                           Attribute::StackProtectStrong))
    Strong = true;
  else if (!F->getAttributes().hasAttribute(AttributeSet::FunctionIndex,
                                            Attribute::StackProtect))
    return false;

  for (Function::iterator I = F->begin(), E = F->end(); I != E; ++I) {
    BasicBlock *BB = I;

    for (BasicBlock::iterator
           II = BB->begin(), IE = BB->end(); II != IE; ++II) {
      if (AllocaInst *AI = dyn_cast<AllocaInst>(II)) {
        if (AI->isArrayAllocation()) {
          // SSP-Strong: Enable protectors for any call to alloca, regardless
          // of size.
          if (Strong)
            return true;

          if (const ConstantInt *CI =
               dyn_cast<ConstantInt>(AI->getArraySize())) {
            if (CI->getLimitedValue(SSPBufferSize) >= SSPBufferSize)
              // A call to alloca with size >= SSPBufferSize requires
              // stack protectors.
              return true;
          } else {
            // A call to alloca with a variable size requires protectors.
            return true;
          }
        }

        if (ContainsProtectableArray(AI->getAllocatedType(), Strong))
          return true;

        if (Strong && HasAddressTaken(AI)) {
          ++NumAddrTaken;
          return true;
        }
      }
    }
  }

  return false;
}

/// Insert code into the entry block that stores the __stack_chk_guard
/// variable onto the stack:
///
///   entry:
///     StackGuardSlot = alloca i8*
///     StackGuard = load __stack_chk_guard
///     call void @llvm.stackprotect.create(StackGuard, StackGuardSlot)
///
static void CreatePrologue(Function *F, Module *M, ReturnInst *RI,
                           const TargetLoweringBase *TLI, const Triple &Trip,
                           AllocaInst *&AI, Value *&StackGuardVar) {
  PointerType *PtrTy = Type::getInt8PtrTy(RI->getContext());
  unsigned AddressSpace, Offset;
  if (TLI->getStackCookieLocation(AddressSpace, Offset)) {
    Constant *OffsetVal =
      ConstantInt::get(Type::getInt32Ty(RI->getContext()), Offset);

    StackGuardVar = ConstantExpr::getIntToPtr(OffsetVal,
                                              PointerType::get(PtrTy,
                                                               AddressSpace));
  } else if (Trip.getOS() == llvm::Triple::OpenBSD) {
    StackGuardVar = M->getOrInsertGlobal("__guard_local", PtrTy);
    cast<GlobalValue>(StackGuardVar)
      ->setVisibility(GlobalValue::HiddenVisibility);
  } else {
    StackGuardVar = M->getOrInsertGlobal("__stack_chk_guard", PtrTy);
  }

  BasicBlock &Entry = F->getEntryBlock();
  Instruction *InsPt = &Entry.front();

  AI = new AllocaInst(PtrTy, "StackGuardSlot", InsPt);
  LoadInst *LI = new LoadInst(StackGuardVar, "StackGuard", false, InsPt);

  Value *Args[] = { LI, AI };
  CallInst::
    Create(Intrinsic::getDeclaration(M, Intrinsic::stackprotector),
           Args, "", InsPt);
}

/// InsertStackProtectors - Insert code into the prologue and epilogue of the
/// function.
///
///  - The prologue code loads and stores the stack guard onto the stack.
///  - The epilogue checks the value stored in the prologue against the original
///    value. It calls __stack_chk_fail if they differ.
bool StackProtector::InsertStackProtectors() {
  BasicBlock *FailBB = 0;       // The basic block to jump to if check fails.
  BasicBlock *FailBBDom = 0;    // FailBB's dominator.
  AllocaInst *AI = 0;           // Place on stack that stores the stack guard.
  Value *StackGuardVar = 0;  // The stack guard variable.

  for (Function::iterator I = F->begin(), E = F->end(); I != E; ) {
    BasicBlock *BB = I++;
    ReturnInst *RI = dyn_cast<ReturnInst>(BB->getTerminator());
    if (!RI) continue;

    if (!FailBB) {
      CreatePrologue(F, M, RI, TLI, Trip, AI, StackGuardVar);
      // Create the basic block to jump to when the guard check fails.
      FailBB = CreateFailBB();
    }

    // For each block with a return instruction, convert this:
    //
    //   return:
    //     ...
    //     ret ...
    //
    // into this:
    //
    //   return:
    //     ...
    //     %1 = load __stack_chk_guard
    //     %2 = load StackGuardSlot
    //     %3 = cmp i1 %1, %2
    //     br i1 %3, label %SP_return, label %CallStackCheckFailBlk
    //
    //   SP_return:
    //     ret ...
    //
    //   CallStackCheckFailBlk:
    //     call void @__stack_chk_fail()
    //     unreachable

    // Split the basic block before the return instruction.
    BasicBlock *NewBB = BB->splitBasicBlock(RI, "SP_return");

    if (DT && DT->isReachableFromEntry(BB)) {
      DT->addNewBlock(NewBB, BB);
      FailBBDom = FailBBDom ? DT->findNearestCommonDominator(FailBBDom, BB) :BB;
    }

    // Remove default branch instruction to the new BB.
    BB->getTerminator()->eraseFromParent();

    // Move the newly created basic block to the point right after the old basic
    // block so that it's in the "fall through" position.
    NewBB->moveAfter(BB);

    // Generate the stack protector instructions in the old basic block.
    LoadInst *LI1 = new LoadInst(StackGuardVar, "", false, BB);
    LoadInst *LI2 = new LoadInst(AI, "", true, BB);
    ICmpInst *Cmp = new ICmpInst(*BB, CmpInst::ICMP_EQ, LI1, LI2, "");
    BranchInst::Create(NewBB, FailBB, Cmp, BB);
  }

  // Return if we didn't modify any basic blocks. I.e., there are no return
  // statements in the function.
  if (!FailBB) return false;

  if (DT && FailBBDom)
    DT->addNewBlock(FailBB, FailBBDom);

  return true;
}

/// CreateFailBB - Create a basic block to jump to when the stack protector
/// check fails.
BasicBlock *StackProtector::CreateFailBB() {
  LLVMContext &Context = F->getContext();
  BasicBlock *FailBB = BasicBlock::Create(Context, "CallStackCheckFailBlk", F);
  if (Trip.getOS() == llvm::Triple::OpenBSD) {
    Constant *StackChkFail = M->getOrInsertFunction(
        "__stack_smash_handler", Type::getVoidTy(Context),
        Type::getInt8PtrTy(Context), NULL);

    Constant *NameStr = ConstantDataArray::getString(Context, F->getName());
    Constant *FuncName =
        new GlobalVariable(*M, NameStr->getType(), true,
                           GlobalVariable::PrivateLinkage, NameStr, "SSH");

    SmallVector<Constant *, 2> IdxList;
    IdxList.push_back(ConstantInt::get(Type::getInt8Ty(Context), 0));
    IdxList.push_back(ConstantInt::get(Type::getInt8Ty(Context), 0));

    SmallVector<Value *, 1> Args;
    Args.push_back(ConstantExpr::getGetElementPtr(FuncName, IdxList));

    CallInst::Create(StackChkFail, Args, "", FailBB);
  } else {
    Constant *StackChkFail = M->getOrInsertFunction(
        "__stack_chk_fail", Type::getVoidTy(Context), NULL);
    CallInst::Create(StackChkFail, "", FailBB);
  }
  new UnreachableInst(Context, FailBB);
  return FailBB;
}
<|endoftext|>


<commit_before>/*=========================================================================
*
*  Copyright Insight Software Consortium
*
*  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.txt
*
*  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 "sitkImageFileWriter.h"
#include "sitkImageIOUtilities.h"

#include <itkImageIOBase.h>
#include <itkImageFileWriter.h>
#include <itkImageRegionIterator.h>
#include <itkGDCMImageIO.h>

namespace itk {
namespace simple {

void WriteImage ( const Image& image, const std::string &inFileName, bool useCompression )
  {
    ImageFileWriter writer;
    writer.Execute ( image, inFileName, useCompression );
  }

ImageFileWriter::~ImageFileWriter()
{
}

ImageFileWriter::ImageFileWriter()
  {
  this->m_UseCompression = false;
  this->m_KeepOriginalImageUID = false;

  this->m_MemberFactory.reset( new detail::MemberFunctionFactory<MemberFunctionType>( this ) );

  this->m_MemberFactory->RegisterMemberFunctions< PixelIDTypeList, 4 > ();
  this->m_MemberFactory->RegisterMemberFunctions< PixelIDTypeList, 3 > ();
  this->m_MemberFactory->RegisterMemberFunctions< PixelIDTypeList, 2 > ();

  }

std::string ImageFileWriter::ToString() const
  {
  std::ostringstream out;
  out << "itk::simple::ImageFileWriter";
  out << std::endl;

  out << "  UseCompression: ";
  this->ToStringHelper(out, this->m_UseCompression);
  out << std::endl;

  out << "  KeepOriginalImageUID: ";
  this->ToStringHelper(out, this->m_KeepOriginalImageUID);
  out << std::endl;

  out << "  FileName: \"";
  this->ToStringHelper(out, this->m_FileName);
  out << "  Registered ImageIO:" << std::endl;
  ioutils::PrintRegisteredImageIOs(out);
  out << "\"" << std::endl;

  out << ProcessObject::ToString();
  return out.str();
  }

  std::vector<std::string>
  ImageFileWriter::GetRegisteredImageIOs() const
  {
    return ioutils::GetRegisteredImageIOs();
  }

  ImageFileWriter::Self&
  ImageFileWriter::SetUseCompression( bool UseCompression )
  {
    this->m_UseCompression = UseCompression;
    return *this;
  }

  bool ImageFileWriter::GetUseCompression( void ) const
  {
    return this->m_UseCompression;
  }

  ImageFileWriter::Self&
  ImageFileWriter::SetKeepOriginalImageUID( bool KeepOriginalImageUID )
  {
    this->m_KeepOriginalImageUID = KeepOriginalImageUID;
    return *this;
  }

  bool ImageFileWriter::GetKeepOriginalImageUID( void ) const
  {
    return this->m_KeepOriginalImageUID;
  }

ImageFileWriter& ImageFileWriter::SetFileName ( const std::string &fn )
  {
  this->m_FileName = fn;
  return *this;
  }

std::string ImageFileWriter::GetFileName() const
  {
  return this->m_FileName;
  }

  ImageFileWriter& ImageFileWriter::Execute ( const Image& image, const std::string &inFileName, bool useCompression )
  {
    this->SetFileName( inFileName );
    this->SetUseCompression( useCompression );
    return this->Execute( image );
  }

ImageFileWriter& ImageFileWriter::Execute ( const Image& image )
  {
    PixelIDValueType type = image.GetPixelIDValue();
    unsigned int dimension = image.GetDimension();

    return this->m_MemberFactory->GetMemberFunction( type, dimension )( image );
  }

itk::SmartPointer<ImageIOBase>
ImageFileWriter
::GetImageIOBase(const std::string &fileName)
{
  itk::ImageIOBase::Pointer iobase =
    itk::ImageIOFactory::CreateImageIO( fileName.c_str(), itk::ImageIOFactory::WriteMode);

  if ( iobase.IsNull() )
     {
     sitkExceptionMacro( "Unable to determine ImageIO writer for \"" << fileName << "\"" );
    }

  // Try additional parameters
  GDCMImageIO *ioGDCMImage = dynamic_cast<GDCMImageIO*>(iobase.GetPointer());
  if (ioGDCMImage)
    {
    ioGDCMImage->SetKeepOriginalUID(this->m_KeepOriginalImageUID);
    }
  return iobase;
}

//-----------------------------------------------------------------------------
template <class InputImageType>
ImageFileWriter& ImageFileWriter::ExecuteInternal( const Image& inImage )
  {
    typename InputImageType::ConstPointer image =
      dynamic_cast <const InputImageType*> ( inImage.GetITKBase() );

    typedef itk::ImageFileWriter<InputImageType> Writer;
    typename Writer::Pointer writer = Writer::New();
    writer->SetUseCompression( this->m_UseCompression );
    writer->SetFileName ( this->m_FileName.c_str() );
    writer->SetInput ( image );

    itk::ImageIOBase::Pointer imageio = this->GetImageIOBase( this->m_FileName );

    sitkDebugMacro( "ImageIO: " << imageio->GetNameOfClass() );

    writer->SetImageIO( imageio );

    this->PreUpdate( writer.GetPointer() );

    writer->Update();

    return *this;
  }

} // end namespace simple
} // end namespace itk
<commit_msg>Fix indentation in ImageFileWriter<commit_after>/*=========================================================================
*
*  Copyright Insight Software Consortium
*
*  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.txt
*
*  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 "sitkImageFileWriter.h"
#include "sitkImageIOUtilities.h"

#include <itkImageIOBase.h>
#include <itkImageFileWriter.h>
#include <itkImageRegionIterator.h>
#include <itkGDCMImageIO.h>

namespace itk {
namespace simple {

void WriteImage ( const Image& image, const std::string &inFileName, bool useCompression )
{
  ImageFileWriter writer;
  writer.Execute ( image, inFileName, useCompression );
}

ImageFileWriter::~ImageFileWriter()
{
}

ImageFileWriter::ImageFileWriter()
{
  this->m_UseCompression = false;
  this->m_KeepOriginalImageUID = false;

  this->m_MemberFactory.reset( new detail::MemberFunctionFactory<MemberFunctionType>( this ) );

  this->m_MemberFactory->RegisterMemberFunctions< PixelIDTypeList, 4 > ();
  this->m_MemberFactory->RegisterMemberFunctions< PixelIDTypeList, 3 > ();
  this->m_MemberFactory->RegisterMemberFunctions< PixelIDTypeList, 2 > ();

}

std::string ImageFileWriter::ToString() const
{
  std::ostringstream out;
  out << "itk::simple::ImageFileWriter";
  out << std::endl;

  out << "  UseCompression: ";
  this->ToStringHelper(out, this->m_UseCompression);
  out << std::endl;

  out << "  KeepOriginalImageUID: ";
  this->ToStringHelper(out, this->m_KeepOriginalImageUID);
  out << std::endl;

  out << "  FileName: \"";
  this->ToStringHelper(out, this->m_FileName);
  out << "  Registered ImageIO:" << std::endl;
  ioutils::PrintRegisteredImageIOs(out);
  out << "\"" << std::endl;

  out << ProcessObject::ToString();
  return out.str();
}

std::vector<std::string>
ImageFileWriter::GetRegisteredImageIOs() const
{
  return ioutils::GetRegisteredImageIOs();
}

ImageFileWriter::Self&
ImageFileWriter::SetUseCompression( bool UseCompression )
{
  this->m_UseCompression = UseCompression;
  return *this;
}

bool ImageFileWriter::GetUseCompression( void ) const
{
  return this->m_UseCompression;
}

ImageFileWriter::Self&
ImageFileWriter::SetKeepOriginalImageUID( bool KeepOriginalImageUID )
{
  this->m_KeepOriginalImageUID = KeepOriginalImageUID;
  return *this;
}

bool ImageFileWriter::GetKeepOriginalImageUID( void ) const
{
  return this->m_KeepOriginalImageUID;
}

ImageFileWriter& ImageFileWriter::SetFileName ( const std::string &fn )
{
  this->m_FileName = fn;
  return *this;
}

std::string ImageFileWriter::GetFileName() const
{
  return this->m_FileName;
}

ImageFileWriter& ImageFileWriter::Execute ( const Image& image, const std::string &inFileName, bool useCompression )
{
  this->SetFileName( inFileName );
  this->SetUseCompression( useCompression );
  return this->Execute( image );
}

ImageFileWriter& ImageFileWriter::Execute ( const Image& image )
{
  PixelIDValueType type = image.GetPixelIDValue();
  unsigned int dimension = image.GetDimension();

  return this->m_MemberFactory->GetMemberFunction( type, dimension )( image );
}

itk::SmartPointer<ImageIOBase>
ImageFileWriter
::GetImageIOBase(const std::string &fileName)
{
  itk::ImageIOBase::Pointer iobase =
    itk::ImageIOFactory::CreateImageIO( fileName.c_str(), itk::ImageIOFactory::WriteMode);

  if ( iobase.IsNull() )
    {
    sitkExceptionMacro( "Unable to determine ImageIO writer for \"" << fileName << "\"" );
    }

  // Try additional parameters
  GDCMImageIO *ioGDCMImage = dynamic_cast<GDCMImageIO*>(iobase.GetPointer());
  if (ioGDCMImage)
    {
    ioGDCMImage->SetKeepOriginalUID(this->m_KeepOriginalImageUID);
    }
  return iobase;
}

//-----------------------------------------------------------------------------
template <class InputImageType>
ImageFileWriter& ImageFileWriter::ExecuteInternal( const Image& inImage )
{
  typename InputImageType::ConstPointer image =
    dynamic_cast <const InputImageType*> ( inImage.GetITKBase() );

  typedef itk::ImageFileWriter<InputImageType> Writer;
  typename Writer::Pointer writer = Writer::New();
  writer->SetUseCompression( this->m_UseCompression );
  writer->SetFileName ( this->m_FileName.c_str() );
  writer->SetInput ( image );

  itk::ImageIOBase::Pointer imageio = this->GetImageIOBase( this->m_FileName );

  sitkDebugMacro( "ImageIO: " << imageio->GetNameOfClass() );

  writer->SetImageIO( imageio );

  this->PreUpdate( writer.GetPointer() );

  writer->Update();

  return *this;
}

} // end namespace simple
} // end namespace itk
<|endoftext|>


<commit_before>//===--- CompletionInstance.cpp -------------------------------------------===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2019 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See https://swift.org/LICENSE.txt for license information
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===----------------------------------------------------------------------===//

#include "swift/IDE/CompletionInstance.h"

#include "swift/AST/ASTContext.h"
#include "swift/AST/DiagnosticEngine.h"
#include "swift/AST/DiagnosticsFrontend.h"
#include "swift/AST/Module.h"
#include "swift/AST/SourceFile.h"
#include "swift/Basic/LangOptions.h"
#include "swift/Basic/SourceManager.h"
#include "swift/Driver/FrontendUtil.h"
#include "swift/Frontend/Frontend.h"
#include "swift/Parse/Lexer.h"
#include "swift/Parse/PersistentParserState.h"
#include "swift/Subsystems.h"
#include "llvm/ADT/Hashing.h"
#include "llvm/Support/MemoryBuffer.h"

using namespace swift;
using namespace ide;

std::unique_ptr<llvm::MemoryBuffer>
swift::ide::makeCodeCompletionMemoryBuffer(const llvm::MemoryBuffer *origBuf,
                                           unsigned &Offset,
                                           StringRef bufferIdentifier) {

  auto origBuffSize = origBuf->getBufferSize();
  if (Offset > origBuffSize)
    Offset = origBuffSize;

  auto newBuffer = llvm::WritableMemoryBuffer::getNewUninitMemBuffer(
      origBuffSize + 1, bufferIdentifier);
  auto *pos = origBuf->getBufferStart() + Offset;
  auto *newPos =
      std::copy(origBuf->getBufferStart(), pos, newBuffer->getBufferStart());
  *newPos = '\0';
  std::copy(pos, origBuf->getBufferEnd(), newPos + 1);

  return std::unique_ptr<llvm::MemoryBuffer>(newBuffer.release());
}

namespace {
/// Returns index number of \p D in \p Decls . If it's not found, returns ~0.
template <typename Range>
unsigned findIndexInRange(Decl *D, const Range &Decls) {
  unsigned N = 0;
  for (auto I = Decls.begin(), E = Decls.end(); I != E; ++I) {
    if (*I == D)
      return N;
    ++N;
  }
  return ~0U;
}

/// Return the element at \p N in \p Decls .
template <typename Range> Decl *getElementAt(const Range &Decls, unsigned N) {
  assert(std::distance(Decls.begin(), Decls.end()) > N);
  auto I = Decls.begin();
  std::advance(I, N);
  return *I;
}

/// Find the equivalent \c DeclContext with \p DC from \p SF AST.
/// This assumes the AST which contains \p DC has exact the same structure with
/// \p SF.
/// FIXME: This doesn't support IfConfigDecl blocks. If \p DC is in an inactive
///        config block, this function returns \c false.
static DeclContext *getEquivalentDeclContextFromSourceFile(DeclContext *DC,
                                                           SourceFile *SF) {
  auto *newDC = DC;
  // NOTE: Shortcut for DC->getParentSourceFile() == SF case is not needed
  // because they should be always different.

  // Get the index path in the current AST.
  SmallVector<unsigned, 4> IndexStack;
  do {
    auto *D = newDC->getAsDecl();
    auto *parentDC = newDC->getParent();
    unsigned N;
    if (auto parentSF = dyn_cast<SourceFile>(parentDC))
      N = findIndexInRange(D, parentSF->Decls);
    else if (auto parentIDC =
                 dyn_cast<IterableDeclContext>(parentDC->getAsDecl()))
      N = findIndexInRange(D, parentIDC->getMembers());
    else
      llvm_unreachable("invalid DC kind for finding equivalent DC (indexpath)");

    // Not found in the decl context tree.
    // FIXME: Probably DC is in an inactive #if block.
    if (N == ~0U) {
      return nullptr;
    }

    IndexStack.push_back(N);
    newDC = parentDC;
  } while (!newDC->isModuleScopeContext());

  assert(isa<SourceFile>(newDC) && "DC should be in a SourceFile");

  // Query the equivalent decl context from the base SourceFile using the index
  // path.
  newDC = SF;
  do {
    auto N = IndexStack.pop_back_val();
    Decl *D;
    if (auto parentSF = dyn_cast<SourceFile>(newDC))
      D = getElementAt(parentSF->Decls, N);
    else if (auto parentIDC = dyn_cast<IterableDeclContext>(newDC->getAsDecl()))
      D = getElementAt(parentIDC->getMembers(), N);
    else
      llvm_unreachable("invalid DC kind for finding equivalent DC (query)");
    newDC = dyn_cast<DeclContext>(D);
  } while (!IndexStack.empty());

  assert(newDC->getContextKind() == DC->getContextKind());

  return newDC;
}

} // namespace

bool CompletionInstance::performCachedOperaitonIfPossible(
    const swift::CompilerInvocation &Invocation, llvm::hash_code ArgsHash,
    llvm::MemoryBuffer *completionBuffer, unsigned int Offset,
    DiagnosticConsumer *DiagC,
    llvm::function_ref<void(CompilerInstance &)> Callback) {

  if (!CachedCI)
    return false;
  if (CachedReuseCount >= MaxASTReuseCount)
    return false;
  if (CachedArgHash != ArgsHash)
    return false;

  auto &CI = *CachedCI;

  auto &oldState = CI.getPersistentParserState();
  if (!oldState.hasCodeCompletionDelayedDeclState())
    return false;

  auto &SM = CI.getSourceMgr();
  if (SM.getIdentifierForBuffer(SM.getCodeCompletionBufferID()) !=
      completionBuffer->getBufferIdentifier())
    return false;

  auto &oldInfo = oldState.getCodeCompletionDelayedDeclState();

  // Currently, only completions within a function body is supported.
  if (oldInfo.Kind != CodeCompletionDelayedDeclKind::FunctionBody)
    return false;

  // Parse the new buffer into temporary SourceFile.
  SourceManager tmpSM;
  auto tmpBufferID = tmpSM.addMemBufferCopy(completionBuffer);
  tmpSM.setCodeCompletionPoint(tmpBufferID, Offset);

  LangOptions langOpts;
  langOpts.DisableParserLookup = true;
  TypeCheckerOptions typeckOpts;
  SearchPathOptions searchPathOpts;
  DiagnosticEngine tmpDiags(tmpSM);
  std::unique_ptr<ASTContext> Ctx(
      ASTContext::get(langOpts, typeckOpts, searchPathOpts, tmpSM, tmpDiags));
  registerIDERequestFunctions(Ctx->evaluator);
  registerTypeCheckerRequestFunctions(Ctx->evaluator);
  ModuleDecl *M = ModuleDecl::create(Identifier(), *Ctx);
  PersistentParserState newState;
  SourceFile *newSF =
      new (*Ctx) SourceFile(*M, SourceFileKind::Library, tmpBufferID,
                            SourceFile::ImplicitModuleImportKind::None);
  newSF->enableInterfaceHash();
  parseIntoSourceFileFull(*newSF, tmpBufferID, &newState);
  // Couldn't find any completion token?
  if (!newState.hasCodeCompletionDelayedDeclState())
    return false;

  auto &newInfo = newState.getCodeCompletionDelayedDeclState();

  // The new completion must happens in function body too.
  if (newInfo.Kind != CodeCompletionDelayedDeclKind::FunctionBody)
    return false;

  auto *oldSF = oldInfo.ParentContext->getParentSourceFile();

  // If the interface has changed, AST must be refreshed.
  llvm::SmallString<32> oldInterfaceHash{};
  llvm::SmallString<32> newInterfaceHash{};
  oldSF->getInterfaceHash(oldInterfaceHash);
  newSF->getInterfaceHash(newInterfaceHash);
  if (oldInterfaceHash != newInterfaceHash)
    return false;

  DeclContext *DC =
      getEquivalentDeclContextFromSourceFile(newInfo.ParentContext, oldSF);
  if (!DC)
    return false;

  // OK, we can perform fast completion for this. Update the orignal delayed
  // decl state.

  // Fast completion keeps the buffer in memory for multiple completions.
  // To reduce the consumption, slice the source buffer so it only holds
  // the portion that is needed for the second pass.
  auto startOffset = newInfo.StartOffset;
  if (newInfo.PrevOffset != ~0u)
    startOffset = newInfo.PrevOffset;
  auto startLoc = tmpSM.getLocForOffset(tmpBufferID, startOffset);
  startLoc = Lexer::getLocForStartOfLine(tmpSM, startLoc);
  startOffset = tmpSM.getLocOffsetInBuffer(startLoc, tmpBufferID);

  auto endOffset = newInfo.EndOffset;
  auto endLoc = tmpSM.getLocForOffset(tmpBufferID, endOffset);
  endLoc = Lexer::getLocForEndOfToken(tmpSM, endLoc);
  endOffset = tmpSM.getLocOffsetInBuffer(endLoc, tmpBufferID);

  newInfo.StartOffset -= startOffset;
  newInfo.EndOffset -= startOffset;
  if (newInfo.PrevOffset != ~0u)
    newInfo.PrevOffset -= startOffset;

  auto sourceText = completionBuffer->getBuffer().slice(startOffset, endOffset);
  auto newOffset = Offset - startOffset;

  auto newBufferID =
      SM.addMemBufferCopy(sourceText, completionBuffer->getBufferIdentifier());
  SM.setCodeCompletionPoint(newBufferID, newOffset);

  // Construct dummy scopes. We don't need to restore the original scope
  // because they are probably not 'isResolvable()' anyway.
  auto &SI = oldState.getScopeInfo();
  assert(SI.getCurrentScope() == nullptr);
  Scope Top(SI, ScopeKind::TopLevel);
  Scope Body(SI, ScopeKind::FunctionBody);

  oldInfo.ParentContext = DC;
  oldInfo.StartOffset = newInfo.StartOffset;
  oldInfo.EndOffset = newInfo.EndOffset;
  oldInfo.PrevOffset = newInfo.PrevOffset;
  oldState.restoreCodeCompletionDelayedDeclState(oldInfo);

  auto *AFD = cast<AbstractFunctionDecl>(DC);
  if (AFD->isBodySkipped())
    AFD->setBodyDelayed(AFD->getBodySourceRange());
  if (DiagC)
    CI.addDiagnosticConsumer(DiagC);

  CI.getDiags().diagnose(SM.getLocForOffset(newBufferID, newInfo.StartOffset),
                         diag::completion_reusing_astcontext);

  Callback(CI);

  if (DiagC)
    CI.removeDiagnosticConsumer(DiagC);

  CachedReuseCount += 1;

  return true;
}

bool CompletionInstance::performNewOperation(
    Optional<llvm::hash_code> ArgsHash, swift::CompilerInvocation &Invocation,
    llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> FileSystem,
    llvm::MemoryBuffer *completionBuffer, unsigned int Offset,
    std::string &Error, DiagnosticConsumer *DiagC,
    llvm::function_ref<void(CompilerInstance &)> Callback) {

  auto TheInstance = std::make_unique<CompilerInstance>();
  auto &CI = *TheInstance;
  if (DiagC)
    CI.addDiagnosticConsumer(DiagC);

  if (FileSystem != llvm::vfs::getRealFileSystem())
    CI.getSourceMgr().setFileSystem(FileSystem);

  Invocation.setCodeCompletionPoint(completionBuffer, Offset);

  if (CI.setup(Invocation)) {
    Error = "failed to setup compiler instance";
    return false;
  }
  registerIDERequestFunctions(CI.getASTContext().evaluator);

  CI.performParseAndResolveImportsOnly();
  Callback(CI);

  if (DiagC)
    CI.removeDiagnosticConsumer(DiagC);

  if (ArgsHash.hasValue()) {
    CachedCI = std::move(TheInstance);
    CachedArgHash = *ArgsHash;
    CachedReuseCount = 0;
  }

  return true;
}

bool swift::ide::CompletionInstance::performOperation(
    swift::CompilerInvocation &Invocation, llvm::ArrayRef<const char *> Args,
    llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> FileSystem,
    llvm::MemoryBuffer *completionBuffer, unsigned int Offset,
    bool EnableASTCaching, std::string &Error, DiagnosticConsumer *DiagC,
    llvm::function_ref<void(CompilerInstance &)> Callback) {

  // Always disable source location resolutions from .swiftsourceinfo file
  // because they're somewhat heavy operations and aren't needed for completion.
  Invocation.getFrontendOptions().IgnoreSwiftSourceInfo = true;

  // Disable to build syntax tree because code-completion skips some portion of
  // source text. That breaks an invariant of syntax tree building.
  Invocation.getLangOptions().BuildSyntaxTree = false;

  // FIXME: ASTScopeLookup doesn't support code completion yet.
  Invocation.disableASTScopeLookup();

  if (EnableASTCaching) {
    // Compute the signature of the invocation.
    llvm::hash_code ArgsHash(0);
    for (auto arg : Args)
      ArgsHash = llvm::hash_combine(ArgsHash, StringRef(arg));

    // Concurrent completions will block so that they have higher chance to use
    // the cached completion instance.
    std::lock_guard<std::mutex> lock(mtx);

    if (performCachedOperaitonIfPossible(Invocation, ArgsHash, completionBuffer,
                                         Offset, DiagC, Callback))
      return true;

    if (performNewOperation(ArgsHash, Invocation, FileSystem, completionBuffer,
                            Offset, Error, DiagC, Callback))
      return true;
  } else {
    // Concurrent completions may happen in parallel when caching is disabled.
    if (performNewOperation(None, Invocation, FileSystem, completionBuffer,
                            Offset, Error, DiagC, Callback))
      return true;
  }

  assert(!Error.empty());
  return false;
}
<commit_msg>[CodeCompletion] Open virtual file for fast completion buffers<commit_after>//===--- CompletionInstance.cpp -------------------------------------------===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2019 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See https://swift.org/LICENSE.txt for license information
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===----------------------------------------------------------------------===//

#include "swift/IDE/CompletionInstance.h"

#include "swift/AST/ASTContext.h"
#include "swift/AST/DiagnosticEngine.h"
#include "swift/AST/DiagnosticsFrontend.h"
#include "swift/AST/Module.h"
#include "swift/AST/SourceFile.h"
#include "swift/Basic/LangOptions.h"
#include "swift/Basic/SourceManager.h"
#include "swift/Driver/FrontendUtil.h"
#include "swift/Frontend/Frontend.h"
#include "swift/Parse/Lexer.h"
#include "swift/Parse/PersistentParserState.h"
#include "swift/Subsystems.h"
#include "llvm/ADT/Hashing.h"
#include "llvm/Support/MemoryBuffer.h"

using namespace swift;
using namespace ide;

std::unique_ptr<llvm::MemoryBuffer>
swift::ide::makeCodeCompletionMemoryBuffer(const llvm::MemoryBuffer *origBuf,
                                           unsigned &Offset,
                                           StringRef bufferIdentifier) {

  auto origBuffSize = origBuf->getBufferSize();
  if (Offset > origBuffSize)
    Offset = origBuffSize;

  auto newBuffer = llvm::WritableMemoryBuffer::getNewUninitMemBuffer(
      origBuffSize + 1, bufferIdentifier);
  auto *pos = origBuf->getBufferStart() + Offset;
  auto *newPos =
      std::copy(origBuf->getBufferStart(), pos, newBuffer->getBufferStart());
  *newPos = '\0';
  std::copy(pos, origBuf->getBufferEnd(), newPos + 1);

  return std::unique_ptr<llvm::MemoryBuffer>(newBuffer.release());
}

namespace {
/// Returns index number of \p D in \p Decls . If it's not found, returns ~0.
template <typename Range>
unsigned findIndexInRange(Decl *D, const Range &Decls) {
  unsigned N = 0;
  for (auto I = Decls.begin(), E = Decls.end(); I != E; ++I) {
    if (*I == D)
      return N;
    ++N;
  }
  return ~0U;
}

/// Return the element at \p N in \p Decls .
template <typename Range> Decl *getElementAt(const Range &Decls, unsigned N) {
  assert(std::distance(Decls.begin(), Decls.end()) > N);
  auto I = Decls.begin();
  std::advance(I, N);
  return *I;
}

/// Find the equivalent \c DeclContext with \p DC from \p SF AST.
/// This assumes the AST which contains \p DC has exact the same structure with
/// \p SF.
/// FIXME: This doesn't support IfConfigDecl blocks. If \p DC is in an inactive
///        config block, this function returns \c false.
static DeclContext *getEquivalentDeclContextFromSourceFile(DeclContext *DC,
                                                           SourceFile *SF) {
  auto *newDC = DC;
  // NOTE: Shortcut for DC->getParentSourceFile() == SF case is not needed
  // because they should be always different.

  // Get the index path in the current AST.
  SmallVector<unsigned, 4> IndexStack;
  do {
    auto *D = newDC->getAsDecl();
    auto *parentDC = newDC->getParent();
    unsigned N;
    if (auto parentSF = dyn_cast<SourceFile>(parentDC))
      N = findIndexInRange(D, parentSF->Decls);
    else if (auto parentIDC =
                 dyn_cast<IterableDeclContext>(parentDC->getAsDecl()))
      N = findIndexInRange(D, parentIDC->getMembers());
    else
      llvm_unreachable("invalid DC kind for finding equivalent DC (indexpath)");

    // Not found in the decl context tree.
    // FIXME: Probably DC is in an inactive #if block.
    if (N == ~0U) {
      return nullptr;
    }

    IndexStack.push_back(N);
    newDC = parentDC;
  } while (!newDC->isModuleScopeContext());

  assert(isa<SourceFile>(newDC) && "DC should be in a SourceFile");

  // Query the equivalent decl context from the base SourceFile using the index
  // path.
  newDC = SF;
  do {
    auto N = IndexStack.pop_back_val();
    Decl *D;
    if (auto parentSF = dyn_cast<SourceFile>(newDC))
      D = getElementAt(parentSF->Decls, N);
    else if (auto parentIDC = dyn_cast<IterableDeclContext>(newDC->getAsDecl()))
      D = getElementAt(parentIDC->getMembers(), N);
    else
      llvm_unreachable("invalid DC kind for finding equivalent DC (query)");
    newDC = dyn_cast<DeclContext>(D);
  } while (!IndexStack.empty());

  assert(newDC->getContextKind() == DC->getContextKind());

  return newDC;
}

} // namespace

bool CompletionInstance::performCachedOperaitonIfPossible(
    const swift::CompilerInvocation &Invocation, llvm::hash_code ArgsHash,
    llvm::MemoryBuffer *completionBuffer, unsigned int Offset,
    DiagnosticConsumer *DiagC,
    llvm::function_ref<void(CompilerInstance &)> Callback) {

  if (!CachedCI)
    return false;
  if (CachedReuseCount >= MaxASTReuseCount)
    return false;
  if (CachedArgHash != ArgsHash)
    return false;

  auto &CI = *CachedCI;

  auto &oldState = CI.getPersistentParserState();
  if (!oldState.hasCodeCompletionDelayedDeclState())
    return false;

  auto &SM = CI.getSourceMgr();
  if (SM.getIdentifierForBuffer(SM.getCodeCompletionBufferID()) !=
      completionBuffer->getBufferIdentifier())
    return false;

  auto &oldInfo = oldState.getCodeCompletionDelayedDeclState();

  // Currently, only completions within a function body is supported.
  if (oldInfo.Kind != CodeCompletionDelayedDeclKind::FunctionBody)
    return false;

  // Parse the new buffer into temporary SourceFile.
  SourceManager tmpSM;
  auto tmpBufferID = tmpSM.addMemBufferCopy(completionBuffer);
  tmpSM.setCodeCompletionPoint(tmpBufferID, Offset);

  LangOptions langOpts;
  langOpts.DisableParserLookup = true;
  TypeCheckerOptions typeckOpts;
  SearchPathOptions searchPathOpts;
  DiagnosticEngine tmpDiags(tmpSM);
  std::unique_ptr<ASTContext> Ctx(
      ASTContext::get(langOpts, typeckOpts, searchPathOpts, tmpSM, tmpDiags));
  registerIDERequestFunctions(Ctx->evaluator);
  registerTypeCheckerRequestFunctions(Ctx->evaluator);
  ModuleDecl *M = ModuleDecl::create(Identifier(), *Ctx);
  PersistentParserState newState;
  SourceFile *newSF =
      new (*Ctx) SourceFile(*M, SourceFileKind::Library, tmpBufferID,
                            SourceFile::ImplicitModuleImportKind::None);
  newSF->enableInterfaceHash();
  parseIntoSourceFileFull(*newSF, tmpBufferID, &newState);
  // Couldn't find any completion token?
  if (!newState.hasCodeCompletionDelayedDeclState())
    return false;

  auto &newInfo = newState.getCodeCompletionDelayedDeclState();

  // The new completion must happens in function body too.
  if (newInfo.Kind != CodeCompletionDelayedDeclKind::FunctionBody)
    return false;

  auto *oldSF = oldInfo.ParentContext->getParentSourceFile();

  // If the interface has changed, AST must be refreshed.
  llvm::SmallString<32> oldInterfaceHash{};
  llvm::SmallString<32> newInterfaceHash{};
  oldSF->getInterfaceHash(oldInterfaceHash);
  newSF->getInterfaceHash(newInterfaceHash);
  if (oldInterfaceHash != newInterfaceHash)
    return false;

  DeclContext *DC =
      getEquivalentDeclContextFromSourceFile(newInfo.ParentContext, oldSF);
  if (!DC)
    return false;

  // OK, we can perform fast completion for this. Update the orignal delayed
  // decl state.

  // Fast completion keeps the buffer in memory for multiple completions.
  // To reduce the consumption, slice the source buffer so it only holds
  // the portion that is needed for the second pass.
  auto startOffset = newInfo.StartOffset;
  if (newInfo.PrevOffset != ~0u)
    startOffset = newInfo.PrevOffset;
  auto startLoc = tmpSM.getLocForOffset(tmpBufferID, startOffset);
  startLoc = Lexer::getLocForStartOfLine(tmpSM, startLoc);
  startOffset = tmpSM.getLocOffsetInBuffer(startLoc, tmpBufferID);

  auto endOffset = newInfo.EndOffset;
  auto endLoc = tmpSM.getLocForOffset(tmpBufferID, endOffset);
  endLoc = Lexer::getLocForEndOfToken(tmpSM, endLoc);
  endOffset = tmpSM.getLocOffsetInBuffer(endLoc, tmpBufferID);

  newInfo.StartOffset -= startOffset;
  newInfo.EndOffset -= startOffset;
  if (newInfo.PrevOffset != ~0u)
    newInfo.PrevOffset -= startOffset;

  auto sourceText = completionBuffer->getBuffer().slice(startOffset, endOffset);
  auto newOffset = Offset - startOffset;

  auto newBufferID =
      SM.addMemBufferCopy(sourceText, completionBuffer->getBufferIdentifier());
  SM.openVirtualFile(SM.getLocForBufferStart(newBufferID),
                     tmpSM.getDisplayNameForLoc(startLoc),
                     tmpSM.getLineAndColumn(startLoc).first - 1);
  SM.setCodeCompletionPoint(newBufferID, newOffset);

  // Construct dummy scopes. We don't need to restore the original scope
  // because they are probably not 'isResolvable()' anyway.
  auto &SI = oldState.getScopeInfo();
  assert(SI.getCurrentScope() == nullptr);
  Scope Top(SI, ScopeKind::TopLevel);
  Scope Body(SI, ScopeKind::FunctionBody);

  oldInfo.ParentContext = DC;
  oldInfo.StartOffset = newInfo.StartOffset;
  oldInfo.EndOffset = newInfo.EndOffset;
  oldInfo.PrevOffset = newInfo.PrevOffset;
  oldState.restoreCodeCompletionDelayedDeclState(oldInfo);

  auto *AFD = cast<AbstractFunctionDecl>(DC);
  if (AFD->isBodySkipped())
    AFD->setBodyDelayed(AFD->getBodySourceRange());
  if (DiagC)
    CI.addDiagnosticConsumer(DiagC);

  CI.getDiags().diagnose(SM.getLocForOffset(newBufferID, newInfo.StartOffset),
                         diag::completion_reusing_astcontext);

  Callback(CI);

  if (DiagC)
    CI.removeDiagnosticConsumer(DiagC);

  CachedReuseCount += 1;

  return true;
}

bool CompletionInstance::performNewOperation(
    Optional<llvm::hash_code> ArgsHash, swift::CompilerInvocation &Invocation,
    llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> FileSystem,
    llvm::MemoryBuffer *completionBuffer, unsigned int Offset,
    std::string &Error, DiagnosticConsumer *DiagC,
    llvm::function_ref<void(CompilerInstance &)> Callback) {

  auto TheInstance = std::make_unique<CompilerInstance>();
  auto &CI = *TheInstance;
  if (DiagC)
    CI.addDiagnosticConsumer(DiagC);

  if (FileSystem != llvm::vfs::getRealFileSystem())
    CI.getSourceMgr().setFileSystem(FileSystem);

  Invocation.setCodeCompletionPoint(completionBuffer, Offset);

  if (CI.setup(Invocation)) {
    Error = "failed to setup compiler instance";
    return false;
  }
  registerIDERequestFunctions(CI.getASTContext().evaluator);

  CI.performParseAndResolveImportsOnly();
  Callback(CI);

  if (DiagC)
    CI.removeDiagnosticConsumer(DiagC);

  if (ArgsHash.hasValue()) {
    CachedCI = std::move(TheInstance);
    CachedArgHash = *ArgsHash;
    CachedReuseCount = 0;
  }

  return true;
}

bool swift::ide::CompletionInstance::performOperation(
    swift::CompilerInvocation &Invocation, llvm::ArrayRef<const char *> Args,
    llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> FileSystem,
    llvm::MemoryBuffer *completionBuffer, unsigned int Offset,
    bool EnableASTCaching, std::string &Error, DiagnosticConsumer *DiagC,
    llvm::function_ref<void(CompilerInstance &)> Callback) {

  // Always disable source location resolutions from .swiftsourceinfo file
  // because they're somewhat heavy operations and aren't needed for completion.
  Invocation.getFrontendOptions().IgnoreSwiftSourceInfo = true;

  // Disable to build syntax tree because code-completion skips some portion of
  // source text. That breaks an invariant of syntax tree building.
  Invocation.getLangOptions().BuildSyntaxTree = false;

  // FIXME: ASTScopeLookup doesn't support code completion yet.
  Invocation.disableASTScopeLookup();

  if (EnableASTCaching) {
    // Compute the signature of the invocation.
    llvm::hash_code ArgsHash(0);
    for (auto arg : Args)
      ArgsHash = llvm::hash_combine(ArgsHash, StringRef(arg));

    // Concurrent completions will block so that they have higher chance to use
    // the cached completion instance.
    std::lock_guard<std::mutex> lock(mtx);

    if (performCachedOperaitonIfPossible(Invocation, ArgsHash, completionBuffer,
                                         Offset, DiagC, Callback))
      return true;

    if (performNewOperation(ArgsHash, Invocation, FileSystem, completionBuffer,
                            Offset, Error, DiagC, Callback))
      return true;
  } else {
    // Concurrent completions may happen in parallel when caching is disabled.
    if (performNewOperation(None, Invocation, FileSystem, completionBuffer,
                            Offset, Error, DiagC, Callback))
      return true;
  }

  assert(!Error.empty());
  return false;
}
<|endoftext|>


<commit_before>#include "mainwindow.h"
#include "ui_mainwindow.h"
#include "QDebug"
#include <QTimer>
#include <cmath>
#include <collisionoutput.h>

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    ui->displaywidget->installEventFilter(this);
    ui->displaywidget->setFocusPolicy(Qt::WheelFocus);
    LinkMode();
    ui->radioButton->setChecked(1);

}

void MainWindow::Initialize(int argc,const char** argv)
{
  manager = make_shared<ResourceManager>();
  backend = make_shared<RobotPoseBackend>(&world,manager.get());
  if(!backend->LoadCommandLine(argc,argv)){
    exit(1);
  }

  gui=make_shared<QRobotPoseGUI>(ui->displaywidget,backend.get());
    backend->Start();

    gui->resource_frame=ui->frame_resources;

    ui->frame_resources->gui = gui.get();
    ui->frame_resources->SetManager(manager.get());

    //Receive info from the GUI
    connect(gui.get(),SIGNAL(UpdateDriverValue()),this,SLOT(UpdateDriverValue()));
    connect(gui.get(),SIGNAL(UpdateDriverParameters()),this,SLOT(UpdateDriverParameters()));

    connect(gui.get(),SIGNAL(UpdateLinkValue()),this,SLOT(UpdateLinkValue()));
    connect(gui.get(),SIGNAL(UpdateLinkParameters()),this,SLOT(UpdateLinkParameters()));

    //Send GUI events
    connect(ui->spn_driver,SIGNAL(valueChanged(double)),gui.get(),SLOT(SetDriverValue(double)));
    connect(ui->spn_link,SIGNAL(valueChanged(double)),gui.get(),SLOT(SetLinkValue(double)));

    if(!world.robots.empty()) {
      Robot* rob=world.robots[0].get();

      //fill GUI info
      for(int i=0;i<rob->linkNames.size();i++)
          ui->cb_link->addItem(QString::fromStdString(rob->linkNames[i]))
                  ;
      for(int i=0;i<rob->drivers.size();i++)
          ui->cb_driver->addItem(QString::fromStdString(rob->driverNames[i]));

      ui->spn_driver_index->setMaximum(rob->drivers.size() - 1);
      ui->spn_link_index->setMaximum(rob->links.size() - 1);
    }

    ui->displaywidget->installEventFilter(this);
    ui->displaywidget->setFocusPolicy(Qt::WheelFocus);

    SetFree();
}

void MainWindow::SetGeometry(bool status){
  gui->SendButtonToggle("draw_geom",status);
}

void MainWindow::SetPoser(bool status){
  gui->SendButtonToggle("draw_poser",status);
}

void MainWindow::SetBboxes(bool status){
  gui->SendButtonToggle("draw_bbs",status);
}

void MainWindow::SetCOM(bool status){
  gui->SendButtonToggle("draw_com",status);
}

void MainWindow::SetFrame(bool status){
  gui->SendButtonToggle("draw_frame",status);
}

void MainWindow::SetSensors(bool status){
  gui->SendButtonToggle("draw_sensors",status);
}

void MainWindow::SetFree() {
  gui->SendCommand("pose_mode");
  ui->btn_free->setChecked(true);
  ui->btn_ik->setChecked(false);
  ui->lbl_ik->setVisible(false);
  ui->line_ik->setVisible(false);
  ui->btn_delete->setVisible(false);
  ui->btn_constrain->setVisible(false);
  ui->btn_constrain_point->setVisible(false);
  ui->btn_constrain_point->setChecked(false);
  ui->btn_constrain->setChecked(0);
  ui->btn_delete->setChecked(0);
  ui->displaywidget->setStatusTip("Pose Mode: Right-click to pose joints");
}

void MainWindow::SetIK(){
  gui->SendCommand("constrain_point_mode");
  ui->btn_free->setChecked(false);
  ui->btn_ik->setChecked(true);
  ui->lbl_ik->setVisible(true);
  ui->line_ik->setVisible(true);
  ui->btn_delete->setVisible(true);
  ui->btn_constrain->setVisible(true);
  ui->btn_constrain_point->setVisible(true);
  ui->btn_constrain_point->setChecked(true);
  ui->btn_constrain->setChecked(0);
  ui->btn_delete->setChecked(0);
  ui->displaywidget->setStatusTip("IK Mode: right drag to pose by IK, c=constrain, d=delete");
}

void MainWindow::IKConstrain(){
  gui->SendCommand("constrain_link_mode");
  blockSignals(true);
  ui->btn_constrain_point->setChecked(0);
  ui->btn_constrain->setChecked(1);
  ui->btn_delete->setChecked(0);
  blockSignals(false);
}

void MainWindow::IKConstrainPoint(){
  gui->SendCommand("constrain_point_mode");
  blockSignals(true);
  ui->btn_constrain_point->setChecked(1);
  ui->btn_constrain->setChecked(0);
  ui->btn_delete->setChecked(0);
  blockSignals(false);
}

void MainWindow::IKDelete(){
  gui->SendCommand("delete_constraint_mode");
  blockSignals(true);
  ui->btn_constrain_point->setChecked(0);
  ui->btn_constrain->setChecked(0);
  ui->btn_delete->setChecked(1);
  blockSignals(false);
}

void MainWindow::SetDriver(int index){
    gui->SetDriver(index);
}

//this information is shared via pointer, not message passing
void MainWindow::UpdateDriverParameters(){
    if(world.robots.empty()) return;
    Robot* rob=world.robots[0].get();
    bool oldState = ui->spn_driver->blockSignals(true);
#define NUM(x) QString::number(x)
  RobotJointDriver dr=rob->drivers[gui->driver_index];
  QString driver_info=QString("V [%1 %2], T [%3,%4], PID %5,%6,%7").arg( \
        NUM(dr.vmin),NUM(dr.vmax),NUM(dr.tmin),NUM(dr.tmax),NUM(dr.servoP),NUM(dr.servoI),NUM(dr.servoD));
  ui->lbl_driver_info->setText(driver_info);
  Vector2 limits = rob->GetDriverLimits(gui->driver_index);
  ui->spn_driver->setMinimum(limits.x);
  ui->spn_driver->setMaximum(limits.y);
#undef NUM(x)
     if(IsInf(ui->spn_driver->minimum()) || IsInf(ui->spn_driver->minimum()))
         ui->sld_driver->setEnabled(false);
     else ui->sld_driver->setEnabled(true);
  ui->spn_driver->blockSignals((oldState));
}

void MainWindow::SetLink(int index){
    gui->SetLink(index);
}

void MainWindow::UpdateLinkValue(){
    if(world.robots.empty()) return;
    Robot* rob=world.robots[0].get();
    bool oldState = ui->spn_link->blockSignals(true);
    ui->spn_link->setValue(rob->q[gui->link_index]);
    UpdateLinkSlider(rob->q[gui->link_index]);
    ui->spn_link->blockSignals(oldState);
}

void MainWindow::UpdateDriverValue(){
    if(world.robots.empty()) return;
    Robot* rob=world.robots[0].get();
    bool oldState = ui->spn_driver->blockSignals(true);
    ui->spn_driver->setValue(rob->GetDriverValue(gui->driver_index));
    UpdateDriverSlider(rob->GetDriverValue(gui->driver_index));
    ui->spn_driver->blockSignals((oldState));
}

void MainWindow::UpdateLinkSlider(double value){
    bool oldState=ui->sld_link->blockSignals(true);
    float range=ui->spn_link->maximum()-ui->spn_link->minimum();
    float relative=value-ui->spn_link->minimum();
    ui->sld_link->setValue(relative/range*1000);
    ui->sld_link->blockSignals(oldState);
}

void MainWindow::UpdateDriverSlider(double value){
    bool oldState=ui->sld_driver->blockSignals(true);
    float range=ui->spn_driver->maximum()-ui->spn_driver->minimum();
    float relative=value-ui->spn_driver->minimum();
    ui->sld_driver->setValue(relative/range*1000);
    ui->sld_driver->blockSignals(oldState);
}

//this information is shared via pointer, not message passing
void MainWindow::UpdateLinkParameters(){
    if(world.robots.empty()) return;
    Robot* rob=world.robots[0].get();
#define NUM(x) QString::number(x)
  QString link_info=QString("[%1 %2], T [%3,%4]").arg(NUM(rob->velMin(gui->link_index)),NUM(rob->velMax(gui->link_index)),NUM(-rob->torqueMax(gui->link_index)),NUM(rob->torqueMax(gui->link_index)));
  ui->lbl_link_info->setText(link_info);
  ui->spn_link->setMinimum(rob->qMin(gui->link_index));
  ui->spn_link->setMaximum(rob->qMax(gui->link_index));
  if(IsInf(ui->spn_link->minimum()) || IsInf(ui->spn_link->minimum()))
      ui->sld_link->setEnabled(false);
  else ui->sld_link->setEnabled(true);

#undef NUM(x)
}

void MainWindow::LinkMode(){
    ui->lbl_mode->setText("Link");
    ui->spn_driver->hide();
    ui->cb_driver->hide();
    ui->lbl_driver_info->hide();
    ui->spn_driver->hide();
    ui->spn_driver_index->hide();
    ui->sld_driver->hide();

    ui->spn_link->show();
    ui->cb_link->show();
    ui->lbl_link_info->show();
    ui->spn_link->show();
    ui->spn_link_index->show();
    ui->sld_link->show();

}

void MainWindow::DriverMode(){
    ui->lbl_mode->setText("Driver");

    ui->spn_link->hide();
    ui->cb_link->hide();
    ui->lbl_link_info->hide();
    ui->spn_link->hide();
    ui->spn_link_index->hide();
    ui->sld_link->hide();

    ui->spn_driver->show();
    ui->cb_driver->show();
    ui->lbl_driver_info->show();
    ui->spn_driver->show();
    ui->spn_driver_index->show();
    ui->sld_driver->show();
}

void MainWindow::SliderLinkAngle(int ticks){
    float inc=(ui->spn_link->maximum()-ui->spn_link->minimum())/1000;
    float value=ui->spn_link->minimum()+inc*ticks;
    ui->spn_link->setValue(value);
}

void MainWindow::SliderDriverAngle(int ticks){
    float inc=(ui->spn_driver->maximum()-ui->spn_driver->minimum())/1000;
    float value=ui->spn_driver->minimum()+inc*ticks;
    ui->spn_driver->setValue(value);
}

void MainWindow::PrintCollisions(){
    gui->SendButtonPress("request_self_collisions");
}

void MainWindow::LoadFile(){
    gui->LoadFilePrompt("last_resource_location");
}

void MainWindow::SaveFile() {
  gui->SaveFilePrompt("last_resource_location");
}

MainWindow::~MainWindow()
{
    delete ui;
}
<commit_msg>fixed crash when robots have no drivers<commit_after>#include "mainwindow.h"
#include "ui_mainwindow.h"
#include "QDebug"
#include <QTimer>
#include <cmath>
#include <collisionoutput.h>

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    ui->displaywidget->installEventFilter(this);
    ui->displaywidget->setFocusPolicy(Qt::WheelFocus);
    LinkMode();
    ui->radioButton->setChecked(1);

}

void MainWindow::Initialize(int argc,const char** argv)
{
  manager = make_shared<ResourceManager>();
  backend = make_shared<RobotPoseBackend>(&world,manager.get());
  if(!backend->LoadCommandLine(argc,argv)){
    exit(1);
  }

  gui=make_shared<QRobotPoseGUI>(ui->displaywidget,backend.get());
    backend->Start();

    gui->resource_frame=ui->frame_resources;

    ui->frame_resources->gui = gui.get();
    ui->frame_resources->SetManager(manager.get());

    //Receive info from the GUI
    connect(gui.get(),SIGNAL(UpdateDriverValue()),this,SLOT(UpdateDriverValue()));
    connect(gui.get(),SIGNAL(UpdateDriverParameters()),this,SLOT(UpdateDriverParameters()));

    connect(gui.get(),SIGNAL(UpdateLinkValue()),this,SLOT(UpdateLinkValue()));
    connect(gui.get(),SIGNAL(UpdateLinkParameters()),this,SLOT(UpdateLinkParameters()));

    //Send GUI events
    connect(ui->spn_driver,SIGNAL(valueChanged(double)),gui.get(),SLOT(SetDriverValue(double)));
    connect(ui->spn_link,SIGNAL(valueChanged(double)),gui.get(),SLOT(SetLinkValue(double)));

    if(!world.robots.empty()) {
      Robot* rob=world.robots[0].get();

      //fill GUI info
      for(int i=0;i<rob->linkNames.size();i++)
          ui->cb_link->addItem(QString::fromStdString(rob->linkNames[i]))
                  ;
      for(int i=0;i<rob->drivers.size();i++)
          ui->cb_driver->addItem(QString::fromStdString(rob->driverNames[i]));

      ui->spn_driver_index->setMaximum(rob->drivers.size() - 1);
      ui->spn_link_index->setMaximum(rob->links.size() - 1);
    }

    ui->displaywidget->installEventFilter(this);
    ui->displaywidget->setFocusPolicy(Qt::WheelFocus);

    SetFree();
}

void MainWindow::SetGeometry(bool status){
  gui->SendButtonToggle("draw_geom",status);
}

void MainWindow::SetPoser(bool status){
  gui->SendButtonToggle("draw_poser",status);
}

void MainWindow::SetBboxes(bool status){
  gui->SendButtonToggle("draw_bbs",status);
}

void MainWindow::SetCOM(bool status){
  gui->SendButtonToggle("draw_com",status);
}

void MainWindow::SetFrame(bool status){
  gui->SendButtonToggle("draw_frame",status);
}

void MainWindow::SetSensors(bool status){
  gui->SendButtonToggle("draw_sensors",status);
}

void MainWindow::SetFree() {
  gui->SendCommand("pose_mode");
  ui->btn_free->setChecked(true);
  ui->btn_ik->setChecked(false);
  ui->lbl_ik->setVisible(false);
  ui->line_ik->setVisible(false);
  ui->btn_delete->setVisible(false);
  ui->btn_constrain->setVisible(false);
  ui->btn_constrain_point->setVisible(false);
  ui->btn_constrain_point->setChecked(false);
  ui->btn_constrain->setChecked(0);
  ui->btn_delete->setChecked(0);
  ui->displaywidget->setStatusTip("Pose Mode: Right-click to pose joints");
}

void MainWindow::SetIK(){
  gui->SendCommand("constrain_point_mode");
  ui->btn_free->setChecked(false);
  ui->btn_ik->setChecked(true);
  ui->lbl_ik->setVisible(true);
  ui->line_ik->setVisible(true);
  ui->btn_delete->setVisible(true);
  ui->btn_constrain->setVisible(true);
  ui->btn_constrain_point->setVisible(true);
  ui->btn_constrain_point->setChecked(true);
  ui->btn_constrain->setChecked(0);
  ui->btn_delete->setChecked(0);
  ui->displaywidget->setStatusTip("IK Mode: right drag to pose by IK, c=constrain, d=delete");
}

void MainWindow::IKConstrain(){
  gui->SendCommand("constrain_link_mode");
  blockSignals(true);
  ui->btn_constrain_point->setChecked(0);
  ui->btn_constrain->setChecked(1);
  ui->btn_delete->setChecked(0);
  blockSignals(false);
}

void MainWindow::IKConstrainPoint(){
  gui->SendCommand("constrain_point_mode");
  blockSignals(true);
  ui->btn_constrain_point->setChecked(1);
  ui->btn_constrain->setChecked(0);
  ui->btn_delete->setChecked(0);
  blockSignals(false);
}

void MainWindow::IKDelete(){
  gui->SendCommand("delete_constraint_mode");
  blockSignals(true);
  ui->btn_constrain_point->setChecked(0);
  ui->btn_constrain->setChecked(0);
  ui->btn_delete->setChecked(1);
  blockSignals(false);
}

void MainWindow::SetDriver(int index){
    gui->SetDriver(index);
}

//this information is shared via pointer, not message passing
void MainWindow::UpdateDriverParameters(){
    if(world.robots.empty()) return;
    if(gui->driver_index < 0) return;
    Robot* rob=world.robots[0].get();
    bool oldState = ui->spn_driver->blockSignals(true);
#define NUM(x) QString::number(x)
  RobotJointDriver dr=rob->drivers[gui->driver_index];
  QString driver_info=QString("V [%1 %2], T [%3,%4], PID %5,%6,%7").arg( \
        NUM(dr.vmin),NUM(dr.vmax),NUM(dr.tmin),NUM(dr.tmax),NUM(dr.servoP),NUM(dr.servoI),NUM(dr.servoD));
  ui->lbl_driver_info->setText(driver_info);
  Vector2 limits = rob->GetDriverLimits(gui->driver_index);
  ui->spn_driver->setMinimum(limits.x);
  ui->spn_driver->setMaximum(limits.y);
#undef NUM(x)
     if(IsInf(ui->spn_driver->minimum()) || IsInf(ui->spn_driver->minimum()))
         ui->sld_driver->setEnabled(false);
     else ui->sld_driver->setEnabled(true);
  ui->spn_driver->blockSignals((oldState));
}

void MainWindow::SetLink(int index){
    gui->SetLink(index);
}

void MainWindow::UpdateLinkValue(){
    if(world.robots.empty()) return;
    if(gui->link_index < 0) return;
    Robot* rob=world.robots[0].get();
    bool oldState = ui->spn_link->blockSignals(true);
    ui->spn_link->setValue(rob->q[gui->link_index]);
    UpdateLinkSlider(rob->q[gui->link_index]);
    ui->spn_link->blockSignals(oldState);
}

void MainWindow::UpdateDriverValue(){
    if(world.robots.empty()) return;
    if(gui->driver_index < 0) return;
    Robot* rob=world.robots[0].get();
    bool oldState = ui->spn_driver->blockSignals(true);
    ui->spn_driver->setValue(rob->GetDriverValue(gui->driver_index));
    UpdateDriverSlider(rob->GetDriverValue(gui->driver_index));
    ui->spn_driver->blockSignals((oldState));
}

void MainWindow::UpdateLinkSlider(double value){
    bool oldState=ui->sld_link->blockSignals(true);
    float range=ui->spn_link->maximum()-ui->spn_link->minimum();
    float relative=value-ui->spn_link->minimum();
    ui->sld_link->setValue(relative/range*1000);
    ui->sld_link->blockSignals(oldState);
}

void MainWindow::UpdateDriverSlider(double value){
    bool oldState=ui->sld_driver->blockSignals(true);
    float range=ui->spn_driver->maximum()-ui->spn_driver->minimum();
    float relative=value-ui->spn_driver->minimum();
    ui->sld_driver->setValue(relative/range*1000);
    ui->sld_driver->blockSignals(oldState);
}

//this information is shared via pointer, not message passing
void MainWindow::UpdateLinkParameters(){
    if(world.robots.empty()) return;
    if(gui->link_index < 0) return;
    Robot* rob=world.robots[0].get();
#define NUM(x) QString::number(x)
  QString link_info=QString("[%1 %2], T [%3,%4]").arg(NUM(rob->velMin(gui->link_index)),NUM(rob->velMax(gui->link_index)),NUM(-rob->torqueMax(gui->link_index)),NUM(rob->torqueMax(gui->link_index)));
  ui->lbl_link_info->setText(link_info);
  ui->spn_link->setMinimum(rob->qMin(gui->link_index));
  ui->spn_link->setMaximum(rob->qMax(gui->link_index));
  if(IsInf(ui->spn_link->minimum()) || IsInf(ui->spn_link->minimum()))
      ui->sld_link->setEnabled(false);
  else ui->sld_link->setEnabled(true);

#undef NUM(x)
}

void MainWindow::LinkMode(){
    ui->lbl_mode->setText("Link");
    ui->spn_driver->hide();
    ui->cb_driver->hide();
    ui->lbl_driver_info->hide();
    ui->spn_driver->hide();
    ui->spn_driver_index->hide();
    ui->sld_driver->hide();

    ui->spn_link->show();
    ui->cb_link->show();
    ui->lbl_link_info->show();
    ui->spn_link->show();
    ui->spn_link_index->show();
    ui->sld_link->show();

}

void MainWindow::DriverMode(){
    ui->lbl_mode->setText("Driver");

    ui->spn_link->hide();
    ui->cb_link->hide();
    ui->lbl_link_info->hide();
    ui->spn_link->hide();
    ui->spn_link_index->hide();
    ui->sld_link->hide();

    ui->spn_driver->show();
    ui->cb_driver->show();
    ui->lbl_driver_info->show();
    ui->spn_driver->show();
    ui->spn_driver_index->show();
    ui->sld_driver->show();
}

void MainWindow::SliderLinkAngle(int ticks){
    float inc=(ui->spn_link->maximum()-ui->spn_link->minimum())/1000;
    float value=ui->spn_link->minimum()+inc*ticks;
    ui->spn_link->setValue(value);
}

void MainWindow::SliderDriverAngle(int ticks){
    float inc=(ui->spn_driver->maximum()-ui->spn_driver->minimum())/1000;
    float value=ui->spn_driver->minimum()+inc*ticks;
    ui->spn_driver->setValue(value);
}

void MainWindow::PrintCollisions(){
    gui->SendButtonPress("request_self_collisions");
}

void MainWindow::LoadFile(){
    gui->LoadFilePrompt("last_resource_location");
}

void MainWindow::SaveFile() {
  gui->SaveFilePrompt("last_resource_location");
}

MainWindow::~MainWindow()
{
    delete ui;
}
<|endoftext|>


<commit_before>/*
 * 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 <iostream>
#include <fstream>
#include <string>
#include <set>
using namespace std;
#include <netinet/in.h>
#include <stdint.h>

#include "../../include/data/constructs/Key.h"
#include "../../include/data/constructs/KeyExtent.h"
#include "../../include/data/constructs/IterInfo.h"
#include "../../include/data/constructs/value.h"
#include "../../include/data/constructs/KeyValue.h"
#include "../../include/data/constructs/rkey.h"
#include <sys/time.h>
//#include <snappy.h>

#define CATCH_CONFIG_MAIN

#include <hdfs/hdfs.h>

#include "../../include/data/constructs/column.h"
#include "../../include/data/constructs/security/Authorizations.h"
#include "../../include/data/constructs/security/AuthInfo.h"

using namespace cclient::data::security;
using namespace cclient::data;
using namespace cclient::data::streams;

#define NUMBER 50000
#include "../catch.hpp"

TEST_CASE("Test Key", "[createAndSetParameters]") {

	char testVal[3] = { 0x01, 0x02, 0x03 };

	Key key;

	// test reuse
	for (int i = 0; i < 1000; i++) {

		REQUIRE(false == key.isDeleted());

		key.setRow(testVal, 3);
		std::pair<char*, size_t> rowRet = key.getRow();

		REQUIRE(memcmp(testVal, rowRet.first, 3) == 0);
		REQUIRE(3 == rowRet.second);

		key.setColFamily(testVal, 3);
		std::pair<char*, size_t> colFamRet = key.getColFamily();

		REQUIRE(memcmp(testVal, colFamRet.first, 3) == 0);
		REQUIRE(3 == colFamRet.second);

	}

}

TEST_CASE("Test KeyExtent", "[createAndSetParameters]") {

	char testVal[3] = { 0x01, 0x02, 0x03 };

	KeyExtent *newExtent = new KeyExtent("tableId","row");
	REQUIRE("tableId" == newExtent->getTableId());

	delete newExtent;

}

TEST_CASE("Test Key -- testStreamInterface", "[testStreamInterface]") {

	StreamInterface **kv = new StreamInterface*[25];
	for (int i = 0; i < 25; i++) {
		kv[i] = new KeyValue();
		delete kv[i];
	}

	delete[] kv;

	KeyValue *kvList = new KeyValue[200];

	char tst[400];
	memset(tst, 0x01, 400);

	for (int i = 0; i < 200; i++) {
		REQUIRE(kvList[i].getValue() != NULL);

		kvList[i].getValue()->setValue((uint8_t*) tst, 400);

		REQUIRE(0 ==
				memcmp(tst, kvList[i].getValue()->getValue().first,
						kvList[i].getValue()->getValue().second));

		REQUIRE(dynamic_cast<Key*>(kvList[i].getKey()) != NULL);
		REQUIRE(dynamic_cast<Key*>(kvList[i].getStream()) != NULL);

	}

	delete []kvList;

}

TEST_CASE("Test Authorizations", "[createAndSetParameters]") {

	vector<string> auths;
	auths.push_back("one");
	auths.push_back("two");

	Authorizations *authorizations = new Authorizations(&auths);

	REQUIRE(2 == authorizations->getAuthorizations().size());

	delete authorizations;
}

TEST_CASE("Test Authorizations -- createAuthInfoNoNulls", "[createAuthInfoNoNulls]") {
	AuthInfo *auth = new AuthInfo("testuser", "testpassword", "instance");

	REQUIRE("instance"== auth->getInstanceId());

	REQUIRE("testpassword"== auth->getPassword());

	REQUIRE("testuser"== auth->getUserName());

	delete auth;
}

TEST_CASE("Test Column", "[createAndSet]") {

	Column *column = new Column("family", "qualifier", "viz");

	REQUIRE(string(column->getColFamily().first).compare("family") == 0);

	REQUIRE(
			string(column->getColQualifier().first).compare(0,
					column->getColQualifier().second, "qualifier") == 0);

	REQUIRE(
			string(column->getColVisibility().first).compare(0,
					column->getColVisibility().second, "viz") == 0);

	REQUIRE(column->getColFamily().second == strlen("family"));

	REQUIRE(column->getColQualifier().second == strlen("qualifier"));

	REQUIRE(column->getColVisibility().second == strlen("viz"));

	delete column;
}

TEST_CASE("Test IterInfo", "[createAndSet]") {

	IterInfo info("name","class",10000);

	REQUIRE(info.getName() == "name");
	REQUIRE(info.getClass()== "class");

	REQUIRE(info.getPriority() == 10000);

}
<commit_msg>Update test to remove hdfs dep<commit_after>/*
 * 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 <iostream>
#include <fstream>
#include <string>
#include <set>
using namespace std;
#include <netinet/in.h>
#include <stdint.h>

#include "../../include/data/constructs/Key.h"
#include "../../include/data/constructs/KeyExtent.h"
#include "../../include/data/constructs/IterInfo.h"
#include "../../include/data/constructs/value.h"
#include "../../include/data/constructs/KeyValue.h"
#include "../../include/data/constructs/rkey.h"
#include <sys/time.h>
//#include <snappy.h>

#define CATCH_CONFIG_MAIN

#include "../../include/data/constructs/column.h"
#include "../../include/data/constructs/security/Authorizations.h"
#include "../../include/data/constructs/security/AuthInfo.h"

using namespace cclient::data::security;
using namespace cclient::data;
using namespace cclient::data::streams;

#define NUMBER 50000
#include "../catch.hpp"

TEST_CASE("Test Key", "[createAndSetParameters]") {

	char testVal[3] = { 0x01, 0x02, 0x03 };

	Key key;

	// test reuse
	for (int i = 0; i < 1000; i++) {

		REQUIRE(false == key.isDeleted());

		key.setRow(testVal, 3);
		std::pair<char*, size_t> rowRet = key.getRow();

		REQUIRE(memcmp(testVal, rowRet.first, 3) == 0);
		REQUIRE(3 == rowRet.second);

		key.setColFamily(testVal, 3);
		std::pair<char*, size_t> colFamRet = key.getColFamily();

		REQUIRE(memcmp(testVal, colFamRet.first, 3) == 0);
		REQUIRE(3 == colFamRet.second);

	}

}

TEST_CASE("Test KeyExtent", "[createAndSetParameters]") {

	char testVal[3] = { 0x01, 0x02, 0x03 };

	KeyExtent *newExtent = new KeyExtent("tableId","row");
	REQUIRE("tableId" == newExtent->getTableId());

	delete newExtent;

}

TEST_CASE("Test Key -- testStreamInterface", "[testStreamInterface]") {

	StreamInterface **kv = new StreamInterface*[25];
	for (int i = 0; i < 25; i++) {
		kv[i] = new KeyValue();
		delete kv[i];
	}

	delete[] kv;

	KeyValue *kvList = new KeyValue[200];

	char tst[400];
	memset(tst, 0x01, 400);

	for (int i = 0; i < 200; i++) {
		REQUIRE(kvList[i].getValue() != NULL);

		kvList[i].getValue()->setValue((uint8_t*) tst, 400);

		REQUIRE(0 ==
				memcmp(tst, kvList[i].getValue()->getValue().first,
						kvList[i].getValue()->getValue().second));

		REQUIRE(dynamic_cast<Key*>(kvList[i].getKey()) != NULL);
		REQUIRE(dynamic_cast<Key*>(kvList[i].getStream()) != NULL);

	}

	delete []kvList;

}

TEST_CASE("Test Authorizations", "[createAndSetParameters]") {

	vector<string> auths;
	auths.push_back("one");
	auths.push_back("two");

	Authorizations *authorizations = new Authorizations(&auths);

	REQUIRE(2 == authorizations->getAuthorizations().size());

	delete authorizations;
}

TEST_CASE("Test Authorizations -- createAuthInfoNoNulls", "[createAuthInfoNoNulls]") {
	AuthInfo *auth = new AuthInfo("testuser", "testpassword", "instance");

	REQUIRE("instance"== auth->getInstanceId());

	REQUIRE("testpassword"== auth->getPassword());

	REQUIRE("testuser"== auth->getUserName());

	delete auth;
}

TEST_CASE("Test Column", "[createAndSet]") {

	Column *column = new Column("family", "qualifier", "viz");

	REQUIRE(string(column->getColFamily().first).compare("family") == 0);

	REQUIRE(
			string(column->getColQualifier().first).compare(0,
					column->getColQualifier().second, "qualifier") == 0);

	REQUIRE(
			string(column->getColVisibility().first).compare(0,
					column->getColVisibility().second, "viz") == 0);

	REQUIRE(column->getColFamily().second == strlen("family"));

	REQUIRE(column->getColQualifier().second == strlen("qualifier"));

	REQUIRE(column->getColVisibility().second == strlen("viz"));

	delete column;
}

TEST_CASE("Test IterInfo", "[createAndSet]") {

	IterInfo info("name","class",10000);

	REQUIRE(info.getName() == "name");
	REQUIRE(info.getClass()== "class");

	REQUIRE(info.getPriority() == 10000);

}
<|endoftext|>


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

  Program:   Visualization Toolkit
  Module:    TestMergeTables.cxx

  Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
  All rights reserved.
  See Copyright.txt or http://www.kitware.com/Copyright.htm for details.

     This software is distributed WITHOUT ANY WARRANTY; without even
     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
     PURPOSE.  See the above copyright notice for more information.

=========================================================================*/
/*-------------------------------------------------------------------------
  Copyright 2008 Sandia Corporation.
  Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
  the U.S. Government retains certain rights in this software.
-------------------------------------------------------------------------*/

#include <vtkDelimitedTextReader.h>
#include <vtkMergeTables.h>
#include <vtkStringArray.h>
#include <vtkTable.h>
#include <vtkVariant.h>
#include <vtkVariantArray.h>
#include <vtkTestUtilities.h>
#include <vtkIOStream.h>

int
TestMergeTables(int argc, char* argv[])
{
  char * filename1 = vtkTestUtilities::ExpandDataFileName(argc,argv,
                                                  "Data/Infovis/merge1.csv");
  char * filename2 = vtkTestUtilities::ExpandDataFileName(argc,argv,
                                                  "Data/Infovis/merge2.csv");

  vtkDelimitedTextReader * reader1 = vtkDelimitedTextReader::New();
  reader1->SetFieldDelimiterCharacters(",");
  reader1->SetFileName(filename1);
  reader1->SetHaveHeaders(true);
  reader1->Update();

  vtkTable * table1 = reader1->GetOutput();

  vtkDelimitedTextReader * reader2 = vtkDelimitedTextReader::New();
  reader2->SetFieldDelimiterCharacters(",");
  reader2->SetFileName(filename2);
  reader2->SetHaveHeaders(true);
  reader2->Update();

  vtkTable * table2 = reader2->GetOutput();

  cout << "Table 1:" << endl;
  table1->Dump(10);

  cout << "Table 2:" << endl;
  table2->Dump(10);

  vtkMergeTables * merge = vtkMergeTables::New();
  merge->SetInput(0, table1);
  merge->SetInput(1, table2);
  merge->SetMergeColumnsByName(true);
  merge->Update();

  vtkTable * mergedTable = merge->GetOutput();

  cout << "Merged Table:" << endl;
  mergedTable->Dump(10);

  // Test # of columns
  // - There should be 3: Col1, Col2, Col3
  if(mergedTable->GetNumberOfColumns() != 3)
    {
    cout << "ERROR: Wrong number of columns!" << endl
         << "       Expected 3, got " << mergedTable->GetNumberOfColumns()
         << endl;
    return 1;
    }

  return 0;
}
<commit_msg>BUG: Clean up (literally and figuratively) the merge tables test, the vtk classes were not being deleted causing a memory leak.<commit_after>/*=========================================================================

  Program:   Visualization Toolkit
  Module:    TestMergeTables.cxx

  Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
  All rights reserved.
  See Copyright.txt or http://www.kitware.com/Copyright.htm for details.

     This software is distributed WITHOUT ANY WARRANTY; without even
     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
     PURPOSE.  See the above copyright notice for more information.

=========================================================================*/
/*-------------------------------------------------------------------------
  Copyright 2008 Sandia Corporation.
  Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
  the U.S. Government retains certain rights in this software.
-------------------------------------------------------------------------*/

#include <vtkDelimitedTextReader.h>
#include <vtkMergeTables.h>
#include <vtkSmartPointer.h>
#include <vtkStringArray.h>
#include <vtkTable.h>
#include <vtkVariant.h>
#include <vtkVariantArray.h>
#include <vtkTestUtilities.h>
#include <vtkIOStream.h>

#define VTK_CREATE(type,name) \
  vtkSmartPointer<type> name = vtkSmartPointer<type>::New()

int
TestMergeTables(int argc, char* argv[])
{
  char * filename1 = vtkTestUtilities::ExpandDataFileName(argc,argv,
                                                  "Data/Infovis/merge1.csv");
  char * filename2 = vtkTestUtilities::ExpandDataFileName(argc,argv,
                                                  "Data/Infovis/merge2.csv");

  VTK_CREATE(vtkDelimitedTextReader,reader1);
  reader1->SetFieldDelimiterCharacters(",");
  reader1->SetFileName(filename1);
  reader1->SetHaveHeaders(true);
  reader1->Update();

  vtkTable * table1 = reader1->GetOutput();

  VTK_CREATE(vtkDelimitedTextReader,reader2);
  reader2->SetFieldDelimiterCharacters(",");
  reader2->SetFileName(filename2);
  reader2->SetHaveHeaders(true);
  reader2->Update();

  vtkTable * table2 = reader2->GetOutput();

  cout << "Table 1:" << endl;
  table1->Dump(10);

  cout << "Table 2:" << endl;
  table2->Dump(10);

  VTK_CREATE(vtkMergeTables,merge);
  merge->SetInput(0, table1);
  merge->SetInput(1, table2);
  merge->SetMergeColumnsByName(true);
  merge->Update();

  vtkTable * mergedTable = merge->GetOutput();

  cout << "Merged Table:" << endl;
  mergedTable->Dump(10);

  // Test # of columns
  // - There should be 3: Col1, Col2, Col3
  if(mergedTable->GetNumberOfColumns() != 3)
    {
    cout << "ERROR: Wrong number of columns!" << endl
         << "       Expected 3, got " << mergedTable->GetNumberOfColumns()
         << endl;
    return 1;
    }

  return 0;
}
<|endoftext|>