<commit_before>#include <stdio.h>

#ifdef WIN32
#include <winsock2.h>
#else
#include <sys/types.h>
#include <sys/socket.h>
#include <unistd.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#endif

#include "socket.h"

#ifdef WIN32
bool wsaStartupDone = false;
#endif

ClientSocket::ClientSocket()
{
    sockfd = -1;

#ifdef WIN32
    if (!wsaStartupDone)
    {
        WSADATA wsaData = {0};
        //WSAStartup needs to be called on windows before sockets can be used. Request version 1.1, which is supported on windows 98 and higher.
        WSAStartup(MAKEWORD(1, 1), &wsaData);
        wsaStartupDone = true;
    }
#endif
}

void ClientSocket::connectTo(std::string host, int port)
{
    struct sockaddr_in serv_addr;
    sockfd = socket(AF_INET, SOCK_STREAM, 0);

    memset(&serv_addr, '0', sizeof(serv_addr));
    serv_addr.sin_family = AF_INET;
    serv_addr.sin_port = htons(port);
    serv_addr.sin_addr.s_addr = inet_addr(host.c_str());
    if (connect(sockfd, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) < 0)
    {
        printf("Connect to %s:%d failed\n", host.c_str(), port);
        close();
        return;
    }
}

ClientSocket::~ClientSocket()
{
    close();
}

void ClientSocket::sendNr(int nr)
{
    sendAll(&nr, sizeof(int));
}

void ClientSocket::sendAll(const void* data, int length)
{
    if (sockfd == -1)
        return;
    const char* ptr = (const char*)data;
    while(length > 0)
    {
        int n = send(sockfd, ptr, length, 0);
        if (n <= 0)
        {
            close();
            return;
        }
        ptr += length;
        length -= n;
    }
}

int ClientSocket::recvNr()
{
    int ret = 0;
    recvAll(&ret, 4);
    return ret;
}

void ClientSocket::recvAll(void* data, int length)
{
    if (sockfd == -1)
        return;
    char* ptr = (char*)data;
    while(length > 0)
    {
        int n = recv(sockfd, ptr, length, 0);
        if (n <= 0)
        {
            close();
            return;
        }
        ptr += length;
        length -= n;
    }
}

void ClientSocket::close()
{
    if (sockfd == -1)
        return;
#ifdef WIN32
    closesocket(sockfd);
#else
    close(sockfd);
#endif
    sockfd = -1;
}
<commit_msg>Add missing include and proper close call for linux.<commit_after>#include <stdio.h>
#include <string.h>

#ifdef WIN32
#include <winsock2.h>
#else
#include <sys/types.h>
#include <sys/socket.h>
#include <unistd.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#endif

#include "socket.h"

#ifdef WIN32
bool wsaStartupDone = false;
#endif

ClientSocket::ClientSocket()
{
    sockfd = -1;

#ifdef WIN32
    if (!wsaStartupDone)
    {
        WSADATA wsaData = {0};
        //WSAStartup needs to be called on windows before sockets can be used. Request version 1.1, which is supported on windows 98 and higher.
        WSAStartup(MAKEWORD(1, 1), &wsaData);
        wsaStartupDone = true;
    }
#endif
}

void ClientSocket::connectTo(std::string host, int port)
{
    struct sockaddr_in serv_addr;
    sockfd = socket(AF_INET, SOCK_STREAM, 0);

    memset(&serv_addr, '0', sizeof(serv_addr));
    serv_addr.sin_family = AF_INET;
    serv_addr.sin_port = htons(port);
    serv_addr.sin_addr.s_addr = inet_addr(host.c_str());
    if (connect(sockfd, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) < 0)
    {
        printf("Connect to %s:%d failed\n", host.c_str(), port);
        close();
        return;
    }
}

ClientSocket::~ClientSocket()
{
    close();
}

void ClientSocket::sendNr(int nr)
{
    sendAll(&nr, sizeof(int));
}

void ClientSocket::sendAll(const void* data, int length)
{
    if (sockfd == -1)
        return;
    const char* ptr = (const char*)data;
    while(length > 0)
    {
        int n = send(sockfd, ptr, length, 0);
        if (n <= 0)
        {
            close();
            return;
        }
        ptr += length;
        length -= n;
    }
}

int ClientSocket::recvNr()
{
    int ret = 0;
    recvAll(&ret, 4);
    return ret;
}

void ClientSocket::recvAll(void* data, int length)
{
    if (sockfd == -1)
        return;
    char* ptr = (char*)data;
    while(length > 0)
    {
        int n = recv(sockfd, ptr, length, 0);
        if (n <= 0)
        {
            close();
            return;
        }
        ptr += length;
        length -= n;
    }
}

void ClientSocket::close()
{
    if (sockfd == -1)
        return;
#ifdef WIN32
    closesocket(sockfd);
#else
    ::close(sockfd);
#endif
    sockfd = -1;
}
<|endoftext|>


<commit_before>//===- Cloning.cpp - Unit tests for the Cloner ----------------------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//

#include "llvm/Transforms/Utils/Cloning.h"
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/IR/Argument.h"
#include "llvm/IR/Constant.h"
#include "llvm/IR/DIBuilder.h"
#include "llvm/IR/DebugInfo.h"
#include "llvm/IR/Function.h"
#include "llvm/IR/IRBuilder.h"
#include "llvm/IR/InstIterator.h"
#include "llvm/IR/Instructions.h"
#include "llvm/IR/IntrinsicInst.h"
#include "llvm/IR/LLVMContext.h"
#include "llvm/IR/Module.h"
#include "gtest/gtest.h"

using namespace llvm;

namespace {

class CloneInstruction : public ::testing::Test {
protected:
  virtual void SetUp() {
    V = nullptr;
  }

  template <typename T>
  T *clone(T *V1) {
    Value *V2 = V1->clone();
    Orig.insert(V1);
    Clones.insert(V2);
    return cast<T>(V2);
  }

  void eraseClones() {
    DeleteContainerPointers(Clones);
  }

  virtual void TearDown() {
    eraseClones();
    DeleteContainerPointers(Orig);
    delete V;
  }

  SmallPtrSet<Value *, 4> Orig;   // Erase on exit
  SmallPtrSet<Value *, 4> Clones; // Erase in eraseClones

  LLVMContext context;
  Value *V;
};

TEST_F(CloneInstruction, OverflowBits) {
  V = new Argument(Type::getInt32Ty(context));

  BinaryOperator *Add = BinaryOperator::Create(Instruction::Add, V, V);
  BinaryOperator *Sub = BinaryOperator::Create(Instruction::Sub, V, V);
  BinaryOperator *Mul = BinaryOperator::Create(Instruction::Mul, V, V);

  BinaryOperator *AddClone = this->clone(Add);
  BinaryOperator *SubClone = this->clone(Sub);
  BinaryOperator *MulClone = this->clone(Mul);

  EXPECT_FALSE(AddClone->hasNoUnsignedWrap());
  EXPECT_FALSE(AddClone->hasNoSignedWrap());
  EXPECT_FALSE(SubClone->hasNoUnsignedWrap());
  EXPECT_FALSE(SubClone->hasNoSignedWrap());
  EXPECT_FALSE(MulClone->hasNoUnsignedWrap());
  EXPECT_FALSE(MulClone->hasNoSignedWrap());

  eraseClones();

  Add->setHasNoUnsignedWrap();
  Sub->setHasNoUnsignedWrap();
  Mul->setHasNoUnsignedWrap();

  AddClone = this->clone(Add);
  SubClone = this->clone(Sub);
  MulClone = this->clone(Mul);

  EXPECT_TRUE(AddClone->hasNoUnsignedWrap());
  EXPECT_FALSE(AddClone->hasNoSignedWrap());
  EXPECT_TRUE(SubClone->hasNoUnsignedWrap());
  EXPECT_FALSE(SubClone->hasNoSignedWrap());
  EXPECT_TRUE(MulClone->hasNoUnsignedWrap());
  EXPECT_FALSE(MulClone->hasNoSignedWrap());

  eraseClones();

  Add->setHasNoSignedWrap();
  Sub->setHasNoSignedWrap();
  Mul->setHasNoSignedWrap();

  AddClone = this->clone(Add);
  SubClone = this->clone(Sub);
  MulClone = this->clone(Mul);

  EXPECT_TRUE(AddClone->hasNoUnsignedWrap());
  EXPECT_TRUE(AddClone->hasNoSignedWrap());
  EXPECT_TRUE(SubClone->hasNoUnsignedWrap());
  EXPECT_TRUE(SubClone->hasNoSignedWrap());
  EXPECT_TRUE(MulClone->hasNoUnsignedWrap());
  EXPECT_TRUE(MulClone->hasNoSignedWrap());

  eraseClones();

  Add->setHasNoUnsignedWrap(false);
  Sub->setHasNoUnsignedWrap(false);
  Mul->setHasNoUnsignedWrap(false);

  AddClone = this->clone(Add);
  SubClone = this->clone(Sub);
  MulClone = this->clone(Mul);

  EXPECT_FALSE(AddClone->hasNoUnsignedWrap());
  EXPECT_TRUE(AddClone->hasNoSignedWrap());
  EXPECT_FALSE(SubClone->hasNoUnsignedWrap());
  EXPECT_TRUE(SubClone->hasNoSignedWrap());
  EXPECT_FALSE(MulClone->hasNoUnsignedWrap());
  EXPECT_TRUE(MulClone->hasNoSignedWrap());
}

TEST_F(CloneInstruction, Inbounds) {
  V = new Argument(Type::getInt32PtrTy(context));

  Constant *Z = Constant::getNullValue(Type::getInt32Ty(context));
  std::vector<Value *> ops;
  ops.push_back(Z);
  GetElementPtrInst *GEP =
      GetElementPtrInst::Create(Type::getInt32Ty(context), V, ops);
  EXPECT_FALSE(this->clone(GEP)->isInBounds());

  GEP->setIsInBounds();
  EXPECT_TRUE(this->clone(GEP)->isInBounds());
}

TEST_F(CloneInstruction, Exact) {
  V = new Argument(Type::getInt32Ty(context));

  BinaryOperator *SDiv = BinaryOperator::Create(Instruction::SDiv, V, V);
  EXPECT_FALSE(this->clone(SDiv)->isExact());

  SDiv->setIsExact(true);
  EXPECT_TRUE(this->clone(SDiv)->isExact());
}

TEST_F(CloneInstruction, Attributes) {
  Type *ArgTy1[] = { Type::getInt32PtrTy(context) };
  FunctionType *FT1 =  FunctionType::get(Type::getVoidTy(context), ArgTy1, false);

  Function *F1 = Function::Create(FT1, Function::ExternalLinkage);
  BasicBlock *BB = BasicBlock::Create(context, "", F1);
  IRBuilder<> Builder(BB);
  Builder.CreateRetVoid();

  Function *F2 = Function::Create(FT1, Function::ExternalLinkage);

  Attribute::AttrKind AK[] = { Attribute::NoCapture };
  AttributeSet AS = AttributeSet::get(context, 0, AK);
  Argument *A = F1->arg_begin();
  A->addAttr(AS);

  SmallVector<ReturnInst*, 4> Returns;
  ValueToValueMapTy VMap;
  VMap[A] = UndefValue::get(A->getType());

  CloneFunctionInto(F2, F1, VMap, false, Returns);
  EXPECT_FALSE(F2->arg_begin()->hasNoCaptureAttr());

  delete F1;
  delete F2;
}

TEST_F(CloneInstruction, CallingConvention) {
  Type *ArgTy1[] = { Type::getInt32PtrTy(context) };
  FunctionType *FT1 =  FunctionType::get(Type::getVoidTy(context), ArgTy1, false);

  Function *F1 = Function::Create(FT1, Function::ExternalLinkage);
  F1->setCallingConv(CallingConv::Cold);
  BasicBlock *BB = BasicBlock::Create(context, "", F1);
  IRBuilder<> Builder(BB);
  Builder.CreateRetVoid();

  Function *F2 = Function::Create(FT1, Function::ExternalLinkage);

  SmallVector<ReturnInst*, 4> Returns;
  ValueToValueMapTy VMap;
  VMap[F1->arg_begin()] = F2->arg_begin();

  CloneFunctionInto(F2, F1, VMap, false, Returns);
  EXPECT_EQ(CallingConv::Cold, F2->getCallingConv());

  delete F1;
  delete F2;
}

class CloneFunc : public ::testing::Test {
protected:
  virtual void SetUp() {
    SetupModule();
    CreateOldFunc();
    CreateNewFunc();
    SetupFinder();
  }

  virtual void TearDown() {
    delete Finder;
  }

  void SetupModule() {
    M = new Module("", C);
  }

  void CreateOldFunc() {
    FunctionType* FuncType = FunctionType::get(Type::getVoidTy(C), false);
    OldFunc = Function::Create(FuncType, GlobalValue::PrivateLinkage, "f", M);
    CreateOldFunctionBodyAndDI();
  }

  void CreateOldFunctionBodyAndDI() {
    DIBuilder DBuilder(*M);
    IRBuilder<> IBuilder(C);

    // Function DI
    DIFile File = DBuilder.createFile("filename.c", "/file/dir/");
    DITypeArray ParamTypes = DBuilder.getOrCreateTypeArray(None);
    DICompositeType FuncType = DBuilder.createSubroutineType(File, ParamTypes);
    DICompileUnit CU = DBuilder.createCompileUnit(dwarf::DW_LANG_C99,
        "filename.c", "/file/dir", "CloneFunc", false, "", 0);

    DISubprogram Subprogram = DBuilder.createFunction(CU, "f", "f", File, 4,
        FuncType, true, true, 3, 0, false, OldFunc);

    // Function body
    BasicBlock* Entry = BasicBlock::Create(C, "", OldFunc);
    IBuilder.SetInsertPoint(Entry);
    DebugLoc Loc = DebugLoc::get(3, 2, Subprogram);
    IBuilder.SetCurrentDebugLocation(Loc);
    AllocaInst* Alloca = IBuilder.CreateAlloca(IntegerType::getInt32Ty(C));
    IBuilder.SetCurrentDebugLocation(DebugLoc::get(4, 2, Subprogram));
    Value* AllocaContent = IBuilder.getInt32(1);
    Instruction* Store = IBuilder.CreateStore(AllocaContent, Alloca);
    IBuilder.SetCurrentDebugLocation(DebugLoc::get(5, 2, Subprogram));
    Instruction* Terminator = IBuilder.CreateRetVoid();

    // Create a local variable around the alloca
    DIType IntType = DBuilder.createBasicType("int", 32, 0,
        dwarf::DW_ATE_signed);
    DIExpression E = DBuilder.createExpression();
    DIVariable Variable = DBuilder.createLocalVariable(
      dwarf::DW_TAG_auto_variable, Subprogram, "x", File, 5, IntType, true);
    DBuilder.insertDeclare(Alloca, Variable, E, Store);
    DBuilder.insertDbgValueIntrinsic(AllocaContent, 0, Variable, E, Terminator);
    // Finalize the debug info
    DBuilder.finalize();

    // Create another, empty, compile unit
    DIBuilder DBuilder2(*M);
    DBuilder2.createCompileUnit(dwarf::DW_LANG_C99,
        "extra.c", "/file/dir", "CloneFunc", false, "", 0);
    DBuilder2.finalize();
  }

  void CreateNewFunc() {
    ValueToValueMapTy VMap;
    NewFunc = CloneFunction(OldFunc, VMap, true, nullptr);
    M->getFunctionList().push_back(NewFunc);
  }

  void SetupFinder() {
    Finder = new DebugInfoFinder();
    Finder->processModule(*M);
  }

  LLVMContext C;
  Function* OldFunc;
  Function* NewFunc;
  Module* M;
  DebugInfoFinder* Finder;
};

// Test that a new, distinct function was created.
TEST_F(CloneFunc, NewFunctionCreated) {
  EXPECT_NE(OldFunc, NewFunc);
}

// Test that a new subprogram entry was added and is pointing to the new
// function, while the original subprogram still points to the old one.
TEST_F(CloneFunc, Subprogram) {
  unsigned SubprogramCount = Finder->subprogram_count();
  EXPECT_EQ(2U, SubprogramCount);

  auto Iter = Finder->subprograms().begin();
  DISubprogram Sub1(*Iter);
  EXPECT_TRUE(Sub1.Verify());
  Iter++;
  DISubprogram Sub2(*Iter);
  EXPECT_TRUE(Sub2.Verify());

  EXPECT_TRUE((Sub1.getFunction() == OldFunc && Sub2.getFunction() == NewFunc)
           || (Sub1.getFunction() == NewFunc && Sub2.getFunction() == OldFunc));
}

// Test that the new subprogram entry was not added to the CU which doesn't
// contain the old subprogram entry.
TEST_F(CloneFunc, SubprogramInRightCU) {
  EXPECT_EQ(2U, Finder->compile_unit_count());

  auto Iter = Finder->compile_units().begin();
  DICompileUnit CU1(*Iter);
  EXPECT_TRUE(CU1.Verify());
  Iter++;
  DICompileUnit CU2(*Iter);
  EXPECT_TRUE(CU2.Verify());
  EXPECT_TRUE(CU1.getSubprograms().getNumElements() == 0
           || CU2.getSubprograms().getNumElements() == 0);
}

// Test that instructions in the old function still belong to it in the
// metadata, while instruction in the new function belong to the new one.
TEST_F(CloneFunc, InstructionOwnership) {
  inst_iterator OldIter = inst_begin(OldFunc);
  inst_iterator OldEnd = inst_end(OldFunc);
  inst_iterator NewIter = inst_begin(NewFunc);
  inst_iterator NewEnd = inst_end(NewFunc);
  while (OldIter != OldEnd && NewIter != NewEnd) {
    Instruction& OldI = *OldIter;
    Instruction& NewI = *NewIter;
    EXPECT_NE(&OldI, &NewI);

    EXPECT_EQ(OldI.hasMetadata(), NewI.hasMetadata());
    if (OldI.hasMetadata()) {
      const DebugLoc& OldDL = OldI.getDebugLoc();
      const DebugLoc& NewDL = NewI.getDebugLoc();

      // Verify that the debug location data is the same
      EXPECT_EQ(OldDL.getLine(), NewDL.getLine());
      EXPECT_EQ(OldDL.getCol(), NewDL.getCol());

      // But that they belong to different functions
      DISubprogram OldSubprogram(OldDL.getScope(C));
      DISubprogram NewSubprogram(NewDL.getScope(C));
      EXPECT_TRUE(OldSubprogram.Verify());
      EXPECT_TRUE(NewSubprogram.Verify());
      EXPECT_EQ(OldFunc, OldSubprogram.getFunction());
      EXPECT_EQ(NewFunc, NewSubprogram.getFunction());
    }

    ++OldIter;
    ++NewIter;
  }
  EXPECT_EQ(OldEnd, OldIter);
  EXPECT_EQ(NewEnd, NewIter);
}

// Test that the arguments for debug intrinsics in the new function were
// properly cloned
TEST_F(CloneFunc, DebugIntrinsics) {
  inst_iterator OldIter = inst_begin(OldFunc);
  inst_iterator OldEnd = inst_end(OldFunc);
  inst_iterator NewIter = inst_begin(NewFunc);
  inst_iterator NewEnd = inst_end(NewFunc);
  while (OldIter != OldEnd && NewIter != NewEnd) {
    Instruction& OldI = *OldIter;
    Instruction& NewI = *NewIter;
    if (DbgDeclareInst* OldIntrin = dyn_cast<DbgDeclareInst>(&OldI)) {
      DbgDeclareInst* NewIntrin = dyn_cast<DbgDeclareInst>(&NewI);
      EXPECT_TRUE(NewIntrin);

      // Old address must belong to the old function
      EXPECT_EQ(OldFunc, cast<AllocaInst>(OldIntrin->getAddress())->
                         getParent()->getParent());
      // New address must belong to the new function
      EXPECT_EQ(NewFunc, cast<AllocaInst>(NewIntrin->getAddress())->
                         getParent()->getParent());

      // Old variable must belong to the old function
      EXPECT_EQ(OldFunc, DISubprogram(DIVariable(OldIntrin->getVariable())
                         .getContext()).getFunction());
      // New variable must belong to the New function
      EXPECT_EQ(NewFunc, DISubprogram(DIVariable(NewIntrin->getVariable())
                         .getContext()).getFunction());
    } else if (DbgValueInst* OldIntrin = dyn_cast<DbgValueInst>(&OldI)) {
      DbgValueInst* NewIntrin = dyn_cast<DbgValueInst>(&NewI);
      EXPECT_TRUE(NewIntrin);

      // Old variable must belong to the old function
      EXPECT_EQ(OldFunc, DISubprogram(DIVariable(OldIntrin->getVariable())
                         .getContext()).getFunction());
      // New variable must belong to the New function
      EXPECT_EQ(NewFunc, DISubprogram(DIVariable(NewIntrin->getVariable())
                         .getContext()).getFunction());
    }

    ++OldIter;
    ++NewIter;
  }
}

}
<commit_msg>Transforms: Fix a use of the old DebugLoc in unittests<commit_after>//===- Cloning.cpp - Unit tests for the Cloner ----------------------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//

#include "llvm/Transforms/Utils/Cloning.h"
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/IR/Argument.h"
#include "llvm/IR/Constant.h"
#include "llvm/IR/DIBuilder.h"
#include "llvm/IR/DebugInfo.h"
#include "llvm/IR/Function.h"
#include "llvm/IR/IRBuilder.h"
#include "llvm/IR/InstIterator.h"
#include "llvm/IR/Instructions.h"
#include "llvm/IR/IntrinsicInst.h"
#include "llvm/IR/LLVMContext.h"
#include "llvm/IR/Module.h"
#include "gtest/gtest.h"

using namespace llvm;

namespace {

class CloneInstruction : public ::testing::Test {
protected:
  virtual void SetUp() {
    V = nullptr;
  }

  template <typename T>
  T *clone(T *V1) {
    Value *V2 = V1->clone();
    Orig.insert(V1);
    Clones.insert(V2);
    return cast<T>(V2);
  }

  void eraseClones() {
    DeleteContainerPointers(Clones);
  }

  virtual void TearDown() {
    eraseClones();
    DeleteContainerPointers(Orig);
    delete V;
  }

  SmallPtrSet<Value *, 4> Orig;   // Erase on exit
  SmallPtrSet<Value *, 4> Clones; // Erase in eraseClones

  LLVMContext context;
  Value *V;
};

TEST_F(CloneInstruction, OverflowBits) {
  V = new Argument(Type::getInt32Ty(context));

  BinaryOperator *Add = BinaryOperator::Create(Instruction::Add, V, V);
  BinaryOperator *Sub = BinaryOperator::Create(Instruction::Sub, V, V);
  BinaryOperator *Mul = BinaryOperator::Create(Instruction::Mul, V, V);

  BinaryOperator *AddClone = this->clone(Add);
  BinaryOperator *SubClone = this->clone(Sub);
  BinaryOperator *MulClone = this->clone(Mul);

  EXPECT_FALSE(AddClone->hasNoUnsignedWrap());
  EXPECT_FALSE(AddClone->hasNoSignedWrap());
  EXPECT_FALSE(SubClone->hasNoUnsignedWrap());
  EXPECT_FALSE(SubClone->hasNoSignedWrap());
  EXPECT_FALSE(MulClone->hasNoUnsignedWrap());
  EXPECT_FALSE(MulClone->hasNoSignedWrap());

  eraseClones();

  Add->setHasNoUnsignedWrap();
  Sub->setHasNoUnsignedWrap();
  Mul->setHasNoUnsignedWrap();

  AddClone = this->clone(Add);
  SubClone = this->clone(Sub);
  MulClone = this->clone(Mul);

  EXPECT_TRUE(AddClone->hasNoUnsignedWrap());
  EXPECT_FALSE(AddClone->hasNoSignedWrap());
  EXPECT_TRUE(SubClone->hasNoUnsignedWrap());
  EXPECT_FALSE(SubClone->hasNoSignedWrap());
  EXPECT_TRUE(MulClone->hasNoUnsignedWrap());
  EXPECT_FALSE(MulClone->hasNoSignedWrap());

  eraseClones();

  Add->setHasNoSignedWrap();
  Sub->setHasNoSignedWrap();
  Mul->setHasNoSignedWrap();

  AddClone = this->clone(Add);
  SubClone = this->clone(Sub);
  MulClone = this->clone(Mul);

  EXPECT_TRUE(AddClone->hasNoUnsignedWrap());
  EXPECT_TRUE(AddClone->hasNoSignedWrap());
  EXPECT_TRUE(SubClone->hasNoUnsignedWrap());
  EXPECT_TRUE(SubClone->hasNoSignedWrap());
  EXPECT_TRUE(MulClone->hasNoUnsignedWrap());
  EXPECT_TRUE(MulClone->hasNoSignedWrap());

  eraseClones();

  Add->setHasNoUnsignedWrap(false);
  Sub->setHasNoUnsignedWrap(false);
  Mul->setHasNoUnsignedWrap(false);

  AddClone = this->clone(Add);
  SubClone = this->clone(Sub);
  MulClone = this->clone(Mul);

  EXPECT_FALSE(AddClone->hasNoUnsignedWrap());
  EXPECT_TRUE(AddClone->hasNoSignedWrap());
  EXPECT_FALSE(SubClone->hasNoUnsignedWrap());
  EXPECT_TRUE(SubClone->hasNoSignedWrap());
  EXPECT_FALSE(MulClone->hasNoUnsignedWrap());
  EXPECT_TRUE(MulClone->hasNoSignedWrap());
}

TEST_F(CloneInstruction, Inbounds) {
  V = new Argument(Type::getInt32PtrTy(context));

  Constant *Z = Constant::getNullValue(Type::getInt32Ty(context));
  std::vector<Value *> ops;
  ops.push_back(Z);
  GetElementPtrInst *GEP =
      GetElementPtrInst::Create(Type::getInt32Ty(context), V, ops);
  EXPECT_FALSE(this->clone(GEP)->isInBounds());

  GEP->setIsInBounds();
  EXPECT_TRUE(this->clone(GEP)->isInBounds());
}

TEST_F(CloneInstruction, Exact) {
  V = new Argument(Type::getInt32Ty(context));

  BinaryOperator *SDiv = BinaryOperator::Create(Instruction::SDiv, V, V);
  EXPECT_FALSE(this->clone(SDiv)->isExact());

  SDiv->setIsExact(true);
  EXPECT_TRUE(this->clone(SDiv)->isExact());
}

TEST_F(CloneInstruction, Attributes) {
  Type *ArgTy1[] = { Type::getInt32PtrTy(context) };
  FunctionType *FT1 =  FunctionType::get(Type::getVoidTy(context), ArgTy1, false);

  Function *F1 = Function::Create(FT1, Function::ExternalLinkage);
  BasicBlock *BB = BasicBlock::Create(context, "", F1);
  IRBuilder<> Builder(BB);
  Builder.CreateRetVoid();

  Function *F2 = Function::Create(FT1, Function::ExternalLinkage);

  Attribute::AttrKind AK[] = { Attribute::NoCapture };
  AttributeSet AS = AttributeSet::get(context, 0, AK);
  Argument *A = F1->arg_begin();
  A->addAttr(AS);

  SmallVector<ReturnInst*, 4> Returns;
  ValueToValueMapTy VMap;
  VMap[A] = UndefValue::get(A->getType());

  CloneFunctionInto(F2, F1, VMap, false, Returns);
  EXPECT_FALSE(F2->arg_begin()->hasNoCaptureAttr());

  delete F1;
  delete F2;
}

TEST_F(CloneInstruction, CallingConvention) {
  Type *ArgTy1[] = { Type::getInt32PtrTy(context) };
  FunctionType *FT1 =  FunctionType::get(Type::getVoidTy(context), ArgTy1, false);

  Function *F1 = Function::Create(FT1, Function::ExternalLinkage);
  F1->setCallingConv(CallingConv::Cold);
  BasicBlock *BB = BasicBlock::Create(context, "", F1);
  IRBuilder<> Builder(BB);
  Builder.CreateRetVoid();

  Function *F2 = Function::Create(FT1, Function::ExternalLinkage);

  SmallVector<ReturnInst*, 4> Returns;
  ValueToValueMapTy VMap;
  VMap[F1->arg_begin()] = F2->arg_begin();

  CloneFunctionInto(F2, F1, VMap, false, Returns);
  EXPECT_EQ(CallingConv::Cold, F2->getCallingConv());

  delete F1;
  delete F2;
}

class CloneFunc : public ::testing::Test {
protected:
  virtual void SetUp() {
    SetupModule();
    CreateOldFunc();
    CreateNewFunc();
    SetupFinder();
  }

  virtual void TearDown() {
    delete Finder;
  }

  void SetupModule() {
    M = new Module("", C);
  }

  void CreateOldFunc() {
    FunctionType* FuncType = FunctionType::get(Type::getVoidTy(C), false);
    OldFunc = Function::Create(FuncType, GlobalValue::PrivateLinkage, "f", M);
    CreateOldFunctionBodyAndDI();
  }

  void CreateOldFunctionBodyAndDI() {
    DIBuilder DBuilder(*M);
    IRBuilder<> IBuilder(C);

    // Function DI
    DIFile File = DBuilder.createFile("filename.c", "/file/dir/");
    DITypeArray ParamTypes = DBuilder.getOrCreateTypeArray(None);
    DICompositeType FuncType = DBuilder.createSubroutineType(File, ParamTypes);
    DICompileUnit CU = DBuilder.createCompileUnit(dwarf::DW_LANG_C99,
        "filename.c", "/file/dir", "CloneFunc", false, "", 0);

    DISubprogram Subprogram = DBuilder.createFunction(CU, "f", "f", File, 4,
        FuncType, true, true, 3, 0, false, OldFunc);

    // Function body
    BasicBlock* Entry = BasicBlock::Create(C, "", OldFunc);
    IBuilder.SetInsertPoint(Entry);
    DebugLoc Loc = DebugLoc::get(3, 2, Subprogram);
    IBuilder.SetCurrentDebugLocation(Loc);
    AllocaInst* Alloca = IBuilder.CreateAlloca(IntegerType::getInt32Ty(C));
    IBuilder.SetCurrentDebugLocation(DebugLoc::get(4, 2, Subprogram));
    Value* AllocaContent = IBuilder.getInt32(1);
    Instruction* Store = IBuilder.CreateStore(AllocaContent, Alloca);
    IBuilder.SetCurrentDebugLocation(DebugLoc::get(5, 2, Subprogram));
    Instruction* Terminator = IBuilder.CreateRetVoid();

    // Create a local variable around the alloca
    DIType IntType = DBuilder.createBasicType("int", 32, 0,
        dwarf::DW_ATE_signed);
    DIExpression E = DBuilder.createExpression();
    DIVariable Variable = DBuilder.createLocalVariable(
      dwarf::DW_TAG_auto_variable, Subprogram, "x", File, 5, IntType, true);
    DBuilder.insertDeclare(Alloca, Variable, E, Store);
    DBuilder.insertDbgValueIntrinsic(AllocaContent, 0, Variable, E, Terminator);
    // Finalize the debug info
    DBuilder.finalize();

    // Create another, empty, compile unit
    DIBuilder DBuilder2(*M);
    DBuilder2.createCompileUnit(dwarf::DW_LANG_C99,
        "extra.c", "/file/dir", "CloneFunc", false, "", 0);
    DBuilder2.finalize();
  }

  void CreateNewFunc() {
    ValueToValueMapTy VMap;
    NewFunc = CloneFunction(OldFunc, VMap, true, nullptr);
    M->getFunctionList().push_back(NewFunc);
  }

  void SetupFinder() {
    Finder = new DebugInfoFinder();
    Finder->processModule(*M);
  }

  LLVMContext C;
  Function* OldFunc;
  Function* NewFunc;
  Module* M;
  DebugInfoFinder* Finder;
};

// Test that a new, distinct function was created.
TEST_F(CloneFunc, NewFunctionCreated) {
  EXPECT_NE(OldFunc, NewFunc);
}

// Test that a new subprogram entry was added and is pointing to the new
// function, while the original subprogram still points to the old one.
TEST_F(CloneFunc, Subprogram) {
  unsigned SubprogramCount = Finder->subprogram_count();
  EXPECT_EQ(2U, SubprogramCount);

  auto Iter = Finder->subprograms().begin();
  DISubprogram Sub1(*Iter);
  EXPECT_TRUE(Sub1.Verify());
  Iter++;
  DISubprogram Sub2(*Iter);
  EXPECT_TRUE(Sub2.Verify());

  EXPECT_TRUE((Sub1.getFunction() == OldFunc && Sub2.getFunction() == NewFunc)
           || (Sub1.getFunction() == NewFunc && Sub2.getFunction() == OldFunc));
}

// Test that the new subprogram entry was not added to the CU which doesn't
// contain the old subprogram entry.
TEST_F(CloneFunc, SubprogramInRightCU) {
  EXPECT_EQ(2U, Finder->compile_unit_count());

  auto Iter = Finder->compile_units().begin();
  DICompileUnit CU1(*Iter);
  EXPECT_TRUE(CU1.Verify());
  Iter++;
  DICompileUnit CU2(*Iter);
  EXPECT_TRUE(CU2.Verify());
  EXPECT_TRUE(CU1.getSubprograms().getNumElements() == 0
           || CU2.getSubprograms().getNumElements() == 0);
}

// Test that instructions in the old function still belong to it in the
// metadata, while instruction in the new function belong to the new one.
TEST_F(CloneFunc, InstructionOwnership) {
  inst_iterator OldIter = inst_begin(OldFunc);
  inst_iterator OldEnd = inst_end(OldFunc);
  inst_iterator NewIter = inst_begin(NewFunc);
  inst_iterator NewEnd = inst_end(NewFunc);
  while (OldIter != OldEnd && NewIter != NewEnd) {
    Instruction& OldI = *OldIter;
    Instruction& NewI = *NewIter;
    EXPECT_NE(&OldI, &NewI);

    EXPECT_EQ(OldI.hasMetadata(), NewI.hasMetadata());
    if (OldI.hasMetadata()) {
      const DebugLoc& OldDL = OldI.getDebugLoc();
      const DebugLoc& NewDL = NewI.getDebugLoc();

      // Verify that the debug location data is the same
      EXPECT_EQ(OldDL.getLine(), NewDL.getLine());
      EXPECT_EQ(OldDL.getCol(), NewDL.getCol());

      // But that they belong to different functions
      DISubprogram OldSubprogram(OldDL.getScope());
      DISubprogram NewSubprogram(NewDL.getScope());
      EXPECT_TRUE(OldSubprogram.Verify());
      EXPECT_TRUE(NewSubprogram.Verify());
      EXPECT_EQ(OldFunc, OldSubprogram.getFunction());
      EXPECT_EQ(NewFunc, NewSubprogram.getFunction());
    }

    ++OldIter;
    ++NewIter;
  }
  EXPECT_EQ(OldEnd, OldIter);
  EXPECT_EQ(NewEnd, NewIter);
}

// Test that the arguments for debug intrinsics in the new function were
// properly cloned
TEST_F(CloneFunc, DebugIntrinsics) {
  inst_iterator OldIter = inst_begin(OldFunc);
  inst_iterator OldEnd = inst_end(OldFunc);
  inst_iterator NewIter = inst_begin(NewFunc);
  inst_iterator NewEnd = inst_end(NewFunc);
  while (OldIter != OldEnd && NewIter != NewEnd) {
    Instruction& OldI = *OldIter;
    Instruction& NewI = *NewIter;
    if (DbgDeclareInst* OldIntrin = dyn_cast<DbgDeclareInst>(&OldI)) {
      DbgDeclareInst* NewIntrin = dyn_cast<DbgDeclareInst>(&NewI);
      EXPECT_TRUE(NewIntrin);

      // Old address must belong to the old function
      EXPECT_EQ(OldFunc, cast<AllocaInst>(OldIntrin->getAddress())->
                         getParent()->getParent());
      // New address must belong to the new function
      EXPECT_EQ(NewFunc, cast<AllocaInst>(NewIntrin->getAddress())->
                         getParent()->getParent());

      // Old variable must belong to the old function
      EXPECT_EQ(OldFunc, DISubprogram(DIVariable(OldIntrin->getVariable())
                         .getContext()).getFunction());
      // New variable must belong to the New function
      EXPECT_EQ(NewFunc, DISubprogram(DIVariable(NewIntrin->getVariable())
                         .getContext()).getFunction());
    } else if (DbgValueInst* OldIntrin = dyn_cast<DbgValueInst>(&OldI)) {
      DbgValueInst* NewIntrin = dyn_cast<DbgValueInst>(&NewI);
      EXPECT_TRUE(NewIntrin);

      // Old variable must belong to the old function
      EXPECT_EQ(OldFunc, DISubprogram(DIVariable(OldIntrin->getVariable())
                         .getContext()).getFunction());
      // New variable must belong to the New function
      EXPECT_EQ(NewFunc, DISubprogram(DIVariable(NewIntrin->getVariable())
                         .getContext()).getFunction());
    }

    ++OldIter;
    ++NewIter;
  }
}

}
<|endoftext|>


<commit_before><commit_msg>Blacklist the QPointerBase class.<commit_after><|endoftext|>


<commit_before><commit_msg>Added a place holder test for mobilab signal<commit_after><|endoftext|>


<commit_before><commit_msg>fixed assert<commit_after><|endoftext|>


<commit_before><commit_msg>INTEGRATION: CWS changefileheader (1.5.72); FILE MERGED 2008/04/01 16:02:19 thb 1.5.72.3: #i85898# Stripping all external header guards 2008/04/01 12:58:12 thb 1.5.72.2: #i85898# Stripping all external header guards 2008/03/31 15:30:22 rt 1.5.72.1: #i87441# Change license header to LPGL v3.<commit_after><|endoftext|>


<commit_before>#include "QDisplayDataWidget.h"
#include "ModifyObject.h"
#include "QMonitorTableWidget.h"

#ifdef SOFA_QT4
#include <QHBoxLayout>
#include <QVBoxLayout>
#include <Q3GroupBox>
#include <QLabel>
#include <QValidator>
#else
#include <qlayout.h>
#include <qlabel.h>
#include <qgroupbox.h>
#include <qvalidator.h>
#endif

#define TEXTSIZE_THRESHOLD 45

namespace sofa
{

using namespace core::objectmodel;
using namespace sofa::component::misc;

namespace gui
{
namespace qt
{
QDisplayDataWidget::QDisplayDataWidget(QWidget* parent,
        BaseData* data,
        const ModifyObjectFlags& flags):Q3GroupBox(parent),
    data_(data),
    datainfowidget_(NULL),
    datawidget_(NULL),
    numWidgets_(0)

{
    if(data_ == NULL)
    {
        return;
    }

    setTitle(data_->getName().c_str());
    setInsideMargin(4);
    setInsideSpacing(2);

    const std::string label_text = data_->getHelp();

    if (label_text != "TODO")
    {
        datainfowidget_ = new QDisplayDataInfoWidget(this,label_text,data_,flags.LINKPATH_MODIFIABLE_FLAG);
        numWidgets_ += datainfowidget_->getNumLines()/3;

    }

    DataWidget::CreatorArgument dwarg;
    dwarg.name =  data_->getName();
    dwarg.data = data_;
    dwarg.parent = this;
    dwarg.readOnly = (data_->isReadOnly() && flags.READONLY_FLAG);

    std::string widget = data_->getWidget();

    if (widget.empty())
        datawidget_ = DataWidgetFactory::CreateAnyObject(dwarg);
    else
        datawidget_ = DataWidgetFactory::CreateObject(dwarg.data->getWidget(), dwarg);
    if (datawidget_ == NULL)
    {
        datawidget_ = new QDataSimpleEdit(this,data_->getName().c_str(), data_);
        datawidget_->createWidgets();
        datawidget_->setEnabled( !(data_->isReadOnly() && flags.READONLY_FLAG) );
        assert(datawidget_ != NULL);
    }

    setColumns(datawidget_->numColumnWidget());
    //std::cout << "WIDGET created for data " << dwarg.data << " : " << dwarg.name << " : " << dwarg.data->getValueTypeString() << std::endl;
    numWidgets_+=datawidget_->sizeWidget();
    connect(datawidget_,SIGNAL(WidgetDirty(bool)), this, SIGNAL ( WidgetDirty(bool) ) );
    connect(this, SIGNAL( WidgetUpdate() ), datawidget_, SLOT( updateWidgetValue() ) );
    connect(this, SIGNAL( DataUpdate() ), datawidget_, SLOT(updateDataValue() ) );
    connect(datawidget_,SIGNAL(DataOwnerDirty(bool)),this,SIGNAL(DataOwnerDirty(bool)) );

}

void QDisplayDataWidget::UpdateData()
{
    emit DataUpdate();
}

void QDisplayDataWidget::UpdateWidgets()
{
    emit WidgetUpdate();
}

QDataSimpleEdit::QDataSimpleEdit(QWidget* parent, const char* name, BaseData* data):
    DataWidget(parent,name,data)
{
}
bool QDataSimpleEdit::createWidgets()
{
    QString str  = QString( getBaseData()->getValueString().c_str() );
    if( str.length() > TEXTSIZE_THRESHOLD )
    {
        innerWidget_.type = TEXTEDIT;
        innerWidget_.widget.textEdit = new QTextEdit(this->parentWidget());
        connect(innerWidget_.widget.textEdit , SIGNAL( textChanged() ), this, SLOT ( setWidgetDirty() ) );
        innerWidget_.widget.textEdit->setText(str);
    }
    else
    {
        innerWidget_.type = LINEEDIT;
        innerWidget_.widget.lineEdit  = new QLineEdit(this->parentWidget());
        connect( innerWidget_.widget.lineEdit, SIGNAL(textChanged(const QString&)), this, SLOT( setWidgetDirty() ) );
        innerWidget_.widget.lineEdit->setText(str);
    }

    return true;
}

void QDataSimpleEdit::readFromData()
{
    QString str = QString( getBaseData()->getValueString().c_str() );
    if(innerWidget_.type == TEXTEDIT)
    {
        innerWidget_.widget.textEdit->setText(str);
    }
    else if(innerWidget_.type == LINEEDIT)
    {
        innerWidget_.widget.lineEdit->setText(str);
    }

}

void QDataSimpleEdit::writeToData()
{
    if(getBaseData())
    {
        std::string value;
        if( innerWidget_.type == TEXTEDIT)
        {
            value = innerWidget_.widget.textEdit->text().ascii();
        }
        else if( innerWidget_.type == LINEEDIT)
        {
            value = innerWidget_.widget.lineEdit->text().ascii();
        }
        getBaseData()->read(value);
    }
}

/* QPoissonRatioWidget */

QPoissonRatioWidget::QPoissonRatioWidget(QWidget * parent, const char * name, sofa::core::objectmodel::TData<double> *data)
    :TDataWidget<double>(parent,name,data)
{

}

bool QPoissonRatioWidget::createWidgets()
{
    QGridLayout* layout = new QGridLayout(this,2,3);

    lineEdit = new QLineEdit(this);
    lineEdit->setText(QString("-1.0"));
    lineEdit->setMaximumSize(lineEdit->size());
    lineEdit->setAlignment(Qt::AlignHCenter);

    lineEdit->setValidator(new QDoubleValidator(0.0,0.5,2,this));

    layout->addWidget(lineEdit,0,1,Qt::AlignHCenter);
    QLabel* min = new QLabel(this);
    min->setText(QString("0.0"));
    min->setMaximumSize( min->sizeHint() );
    layout->addWidget(min,1,0,Qt::AlignHCenter);

    slider = new QSlider(Qt::Horizontal, this);
    slider->setRange(0,50); //max times 10 at the power 2 (2 digits after ".")
    slider->setTickmarks(QSlider::Below);
    slider->setTickInterval(5);
    layout->addWidget(slider,1,1,Qt::AlignHCenter);

    QLabel* max = new QLabel(this);
    max->setText(QString("0.5"));
    max->setMaximumSize ( max->sizeHint() );

    layout->addWidget(max,1,2,Qt::AlignHCenter);

    // synchronization between qslider and qlineedit
    connect(slider, SIGNAL( valueChanged(int) ), this, SLOT ( changeLineEditValue() ) );
    connect(slider, SIGNAL( sliderReleased()   ), this, SLOT ( changeLineEditValue() ) );
    connect(lineEdit, SIGNAL( textChanged(const QString&) ), this, SLOT (changeSliderValue() ) );

    // synchronization between the widgets and the modify object dialog box
    connect(lineEdit, SIGNAL( textChanged(const QString&) ), this, SLOT( setWidgetDirty() ) );
    connect(slider, SIGNAL( sliderReleased()  ), this, SLOT ( setWidgetDirty() ) );
    connect(slider, SIGNAL( valueChanged(int) ), this, SLOT ( setWidgetDirty() ) );

    return true;
}

void QPoissonRatioWidget::readFromData()
{
    double value = this->getData()->virtualGetValue();
    QString str;
    str.setNum(value);
    lineEdit->setText(str);
    changeSliderValue();
}

void QPoissonRatioWidget::writeToData()
{
    bool ok;
    double d = lineEdit->text().toDouble(&ok);
    if(ok)
    {
        this->getData()->virtualSetValue(d);
    }
}

void QPoissonRatioWidget::changeLineEditValue()
{
    int v = slider->value();
    double db = (double)v / 100.;
    QString str;
    str.setNum(db);
    lineEdit->setText(str);
}

void QPoissonRatioWidget::changeSliderValue()
{
    bool ok;
    double v = lineEdit->text().toDouble(&ok);
    if(ok)
    {
        slider->setValue( (int)(v*100.) );
    }
}

helper::Creator<DataWidgetFactory, QPoissonRatioWidget> DWClass_Poissonratio("poissonRatio",false);

} // qt
} //gui
} //sofa

<commit_msg>r7010/sofa-dev : FIX: compilation <commit_after>#include "QDisplayDataWidget.h"
#include "ModifyObject.h"

#ifdef SOFA_QT4
#include <QHBoxLayout>
#include <QVBoxLayout>
#include <Q3GroupBox>
#include <QLabel>
#include <QValidator>
#else
#include <qlayout.h>
#include <qlabel.h>
#include <qgroupbox.h>
#include <qvalidator.h>
#endif

#define TEXTSIZE_THRESHOLD 45

namespace sofa
{

using namespace core::objectmodel;
using namespace sofa::component::misc;

namespace gui
{
namespace qt
{
QDisplayDataWidget::QDisplayDataWidget(QWidget* parent,
        BaseData* data,
        const ModifyObjectFlags& flags):Q3GroupBox(parent),
    data_(data),
    datainfowidget_(NULL),
    datawidget_(NULL),
    numWidgets_(0)

{
    if(data_ == NULL)
    {
        return;
    }

    setTitle(data_->getName().c_str());
    setInsideMargin(4);
    setInsideSpacing(2);

    const std::string label_text = data_->getHelp();

    if (label_text != "TODO")
    {
        datainfowidget_ = new QDisplayDataInfoWidget(this,label_text,data_,flags.LINKPATH_MODIFIABLE_FLAG);
        numWidgets_ += datainfowidget_->getNumLines()/3;

    }

    DataWidget::CreatorArgument dwarg;
    dwarg.name =  data_->getName();
    dwarg.data = data_;
    dwarg.parent = this;
    dwarg.readOnly = (data_->isReadOnly() && flags.READONLY_FLAG);

    std::string widget = data_->getWidget();

    if (widget.empty())
        datawidget_ = DataWidgetFactory::CreateAnyObject(dwarg);
    else
        datawidget_ = DataWidgetFactory::CreateObject(dwarg.data->getWidget(), dwarg);
    if (datawidget_ == NULL)
    {
        datawidget_ = new QDataSimpleEdit(this,data_->getName().c_str(), data_);
        datawidget_->createWidgets();
        datawidget_->setEnabled( !(data_->isReadOnly() && flags.READONLY_FLAG) );
        assert(datawidget_ != NULL);
    }

    setColumns(datawidget_->numColumnWidget());
    //std::cout << "WIDGET created for data " << dwarg.data << " : " << dwarg.name << " : " << dwarg.data->getValueTypeString() << std::endl;
    numWidgets_+=datawidget_->sizeWidget();
    connect(datawidget_,SIGNAL(WidgetDirty(bool)), this, SIGNAL ( WidgetDirty(bool) ) );
    connect(this, SIGNAL( WidgetUpdate() ), datawidget_, SLOT( updateWidgetValue() ) );
    connect(this, SIGNAL( DataUpdate() ), datawidget_, SLOT(updateDataValue() ) );
    connect(datawidget_,SIGNAL(DataOwnerDirty(bool)),this,SIGNAL(DataOwnerDirty(bool)) );

}

void QDisplayDataWidget::UpdateData()
{
    emit DataUpdate();
}

void QDisplayDataWidget::UpdateWidgets()
{
    emit WidgetUpdate();
}

QDataSimpleEdit::QDataSimpleEdit(QWidget* parent, const char* name, BaseData* data):
    DataWidget(parent,name,data)
{
}
bool QDataSimpleEdit::createWidgets()
{
    QString str  = QString( getBaseData()->getValueString().c_str() );
    if( str.length() > TEXTSIZE_THRESHOLD )
    {
        innerWidget_.type = TEXTEDIT;
        innerWidget_.widget.textEdit = new QTextEdit(this->parentWidget());
        connect(innerWidget_.widget.textEdit , SIGNAL( textChanged() ), this, SLOT ( setWidgetDirty() ) );
        innerWidget_.widget.textEdit->setText(str);
    }
    else
    {
        innerWidget_.type = LINEEDIT;
        innerWidget_.widget.lineEdit  = new QLineEdit(this->parentWidget());
        connect( innerWidget_.widget.lineEdit, SIGNAL(textChanged(const QString&)), this, SLOT( setWidgetDirty() ) );
        innerWidget_.widget.lineEdit->setText(str);
    }

    return true;
}

void QDataSimpleEdit::readFromData()
{
    QString str = QString( getBaseData()->getValueString().c_str() );
    if(innerWidget_.type == TEXTEDIT)
    {
        innerWidget_.widget.textEdit->setText(str);
    }
    else if(innerWidget_.type == LINEEDIT)
    {
        innerWidget_.widget.lineEdit->setText(str);
    }

}

void QDataSimpleEdit::writeToData()
{
    if(getBaseData())
    {
        std::string value;
        if( innerWidget_.type == TEXTEDIT)
        {
            value = innerWidget_.widget.textEdit->text().ascii();
        }
        else if( innerWidget_.type == LINEEDIT)
        {
            value = innerWidget_.widget.lineEdit->text().ascii();
        }
        getBaseData()->read(value);
    }
}

/* QPoissonRatioWidget */

QPoissonRatioWidget::QPoissonRatioWidget(QWidget * parent, const char * name, sofa::core::objectmodel::TData<double> *data)
    :TDataWidget<double>(parent,name,data)
{

}

bool QPoissonRatioWidget::createWidgets()
{
    QGridLayout* layout = new QGridLayout(this,2,3);

    lineEdit = new QLineEdit(this);
    lineEdit->setText(QString("-1.0"));
    lineEdit->setMaximumSize(lineEdit->size());
    lineEdit->setAlignment(Qt::AlignHCenter);

    lineEdit->setValidator(new QDoubleValidator(0.0,0.5,2,this));

    layout->addWidget(lineEdit,0,1,Qt::AlignHCenter);
    QLabel* min = new QLabel(this);
    min->setText(QString("0.0"));
    min->setMaximumSize( min->sizeHint() );
    layout->addWidget(min,1,0,Qt::AlignHCenter);

    slider = new QSlider(Qt::Horizontal, this);
    slider->setRange(0,50); //max times 10 at the power 2 (2 digits after ".")
    slider->setTickmarks(QSlider::Below);
    slider->setTickInterval(5);
    layout->addWidget(slider,1,1,Qt::AlignHCenter);

    QLabel* max = new QLabel(this);
    max->setText(QString("0.5"));
    max->setMaximumSize ( max->sizeHint() );

    layout->addWidget(max,1,2,Qt::AlignHCenter);

    // synchronization between qslider and qlineedit
    connect(slider, SIGNAL( valueChanged(int) ), this, SLOT ( changeLineEditValue() ) );
    connect(slider, SIGNAL( sliderReleased()   ), this, SLOT ( changeLineEditValue() ) );
    connect(lineEdit, SIGNAL( textChanged(const QString&) ), this, SLOT (changeSliderValue() ) );

    // synchronization between the widgets and the modify object dialog box
    connect(lineEdit, SIGNAL( textChanged(const QString&) ), this, SLOT( setWidgetDirty() ) );
    connect(slider, SIGNAL( sliderReleased()  ), this, SLOT ( setWidgetDirty() ) );
    connect(slider, SIGNAL( valueChanged(int) ), this, SLOT ( setWidgetDirty() ) );

    return true;
}

void QPoissonRatioWidget::readFromData()
{
    double value = this->getData()->virtualGetValue();
    QString str;
    str.setNum(value);
    lineEdit->setText(str);
    changeSliderValue();
}

void QPoissonRatioWidget::writeToData()
{
    bool ok;
    double d = lineEdit->text().toDouble(&ok);
    if(ok)
    {
        this->getData()->virtualSetValue(d);
    }
}

void QPoissonRatioWidget::changeLineEditValue()
{
    int v = slider->value();
    double db = (double)v / 100.;
    QString str;
    str.setNum(db);
    lineEdit->setText(str);
}

void QPoissonRatioWidget::changeSliderValue()
{
    bool ok;
    double v = lineEdit->text().toDouble(&ok);
    if(ok)
    {
        slider->setValue( (int)(v*100.) );
    }
}

helper::Creator<DataWidgetFactory, QPoissonRatioWidget> DWClass_Poissonratio("poissonRatio",false);

} // qt
} //gui
} //sofa

<|endoftext|>


<commit_before>/*
    Copyright (C) 2012  Lasath Fernando <kde@lasath.org>

    This library is free software; you can redistribute it and/or
    modify it under the terms of the GNU Lesser General Public
    License as published by the Free Software Foundation; either
    version 2.1 of the License, or (at your option) any later version.

    This library is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    Lesser General Public License for more details.

    You should have received a copy of the GNU Lesser General Public
    License along with this library; if not, write to the Free Software
    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
*/

#include "message.h"

#include <KDebug>
#include <QSharedData>

#include <TelepathyQt/ContactManager>
#include <TelepathyQt/Connection>

#include <TelepathyLoggerQt4/Entity>

using namespace KTp;

class Message::Private : public QSharedData {

  public:
    Private() :
        isHistory(false)
    {};
    QDateTime   sentTime;
    QString     token;
    Tp::ChannelTextMessageType messageType;
    QVariantMap properties;
    QString     mainPart;
    QStringList parts;
    QStringList scripts;
    bool isHistory;
    MessageDirection direction;
};

Message::Message(const Tp::Message &original, const KTp::MessageContext &context) :
    d(new Private)
{
    Q_UNUSED(context)
    d->sentTime = original.sent();
    d->token = original.messageToken();
    d->messageType = original.messageType();
    d->isHistory = false;
    d->direction = KTp::Message::LocalToRemote;
    setMainMessagePart(original.text());
}

Message::Message(const Tp::ReceivedMessage &original, const KTp::MessageContext &context) :
    d(new Private)
{
    Q_UNUSED(context)
    d->sentTime = original.sent();
    d->token = original.messageToken();
    d->messageType = original.messageType();
    d->isHistory = original.isScrollback();
    d->direction = KTp::Message::RemoteToLocal;

    setMainMessagePart(original.text());
}

Message::Message(const Tpl::TextEventPtr &original, const KTp::MessageContext &context) :
    d(new Private)
{
    d->sentTime = original->timestamp();
    d->token = original->messageToken();
    d->messageType = original->messageType();
    d->isHistory = true;

    if (original->sender()->identifier() == context.account()->normalizedName()) {
        d->direction = KTp::Message::LocalToRemote;
    } else {
        d->direction = KTp::Message::RemoteToLocal;
    }

    setMainMessagePart(original->message());
}

Message::Message(const Message& other):
    d(other.d)
{
}

Message::~Message()
{
}

QString Message::mainMessagePart() const
{
    return d->mainPart;
}

void Message::setMainMessagePart(const QString& message)
{
    d->mainPart = message;
}

void Message::appendMessagePart(const QString& part)
{
    d->parts << part;
}

void Message::appendScript(const QString& script)
{
    // Append the script only if it is not already appended to avoid multiple
    // execution of the scripts.
    if (!d->scripts.contains(script)) {
        d->scripts << script;
    }
}

QString Message::finalizedMessage() const
{
    QString msg = d->mainPart + QLatin1String("\n") +
        d->parts.join(QLatin1String("\n"));

//     kDebug() << msg;
    return msg;
}

QString Message::finalizedScript() const
{
    if (d->scripts.empty()) {
        return QString();
    }

    QString finalScript = d->scripts.join(QLatin1String(""));

    if (!finalScript.isEmpty()) {
        finalScript.append(QLatin1String("false;"));
    }

//    kDebug() << finalScript;
    return finalScript;
}

QVariant Message::property(const char *name) const
{
    return d->properties[QLatin1String(name)];
}

void Message::setProperty(const char *name, const QVariant& value)
{
    d->properties[QLatin1String(name)] = value;
}

QDateTime Message::time() const
{
    return d->sentTime;
}

QString Message::token() const
{
    return d->token;
}

Tp::ChannelTextMessageType Message::type() const
{
    return d->messageType;
}

int Message::partsSize() const
{
    return d->parts.size();
}

bool Message::isHistory() const
{
    return d->isHistory;
}

KTp::Message::MessageDirection Message::direction() const
{
    return d->direction;
}
<commit_msg>Make message store sender<commit_after>/*
    Copyright (C) 2012  Lasath Fernando <kde@lasath.org>

    This library is free software; you can redistribute it and/or
    modify it under the terms of the GNU Lesser General Public
    License as published by the Free Software Foundation; either
    version 2.1 of the License, or (at your option) any later version.

    This library is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    Lesser General Public License for more details.

    You should have received a copy of the GNU Lesser General Public
    License along with this library; if not, write to the Free Software
    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
*/

#include "message.h"

#include <KDebug>
#include <QSharedData>

#include <TelepathyQt/ContactManager>
#include <TelepathyQt/Connection>

#include <TelepathyLoggerQt4/Entity>

using namespace KTp;

class Message::Private : public QSharedData {

  public:
    Private() :
        isHistory(false)
    {};
    QDateTime   sentTime;
    QString     token;
    Tp::ChannelTextMessageType messageType;
    QVariantMap properties;
    QString     mainPart;
    QStringList parts;
    QStringList scripts;
    bool isHistory;
    MessageDirection direction;
};

Message::Message(const Tp::Message &original, const KTp::MessageContext &context) :
    d(new Private)
{
    Q_UNUSED(context)
    d->sentTime = original.sent();
    d->token = original.messageToken();
    d->messageType = original.messageType();
    d->isHistory = false;
    d->direction = KTp::Message::LocalToRemote;

    setMainMessagePart(original.text());

    setProperty("sender", context.account()->nickname());
    setProperty("sender-avatar", context.account()->avatar().avatarData);
}

Message::Message(const Tp::ReceivedMessage &original, const KTp::MessageContext &context) :
    d(new Private)
{
    Q_UNUSED(context)
    d->sentTime = original.sent();
    d->token = original.messageToken();
    d->messageType = original.messageType();
    d->isHistory = original.isScrollback();
    d->direction = KTp::Message::RemoteToLocal;

    setMainMessagePart(original.text());

    if (!original.sender().isNull()) {
        setProperty("sender", original.sender()->alias());
        setProperty("sender-avatar", original.sender()->avatarData().fileName);
    } else {
        setProperty("sender", original.senderNickname());
    }
}

Message::Message(const Tpl::TextEventPtr &original, const KTp::MessageContext &context) :
    d(new Private)
{
    d->sentTime = original->timestamp();
    d->token = original->messageToken();
    d->messageType = original->messageType();
    d->isHistory = true;

    if (original->sender()->identifier() == context.account()->normalizedName()) {
        d->direction = KTp::Message::LocalToRemote;
    } else {
        d->direction = KTp::Message::RemoteToLocal;
    }

    setMainMessagePart(original->message());

    setProperty("sender", original->sender()->alias());
    setProperty("sender-avatar", original->sender()->avatarToken());
}

Message::Message(const Message& other):
    d(other.d)
{
}

Message::~Message()
{
}

QString Message::mainMessagePart() const
{
    return d->mainPart;
}

void Message::setMainMessagePart(const QString& message)
{
    d->mainPart = message;
}

void Message::appendMessagePart(const QString& part)
{
    d->parts << part;
}

void Message::appendScript(const QString& script)
{
    // Append the script only if it is not already appended to avoid multiple
    // execution of the scripts.
    if (!d->scripts.contains(script)) {
        d->scripts << script;
    }
}

QString Message::finalizedMessage() const
{
    QString msg = d->mainPart + QLatin1String("\n") +
        d->parts.join(QLatin1String("\n"));

//     kDebug() << msg;
    return msg;
}

QString Message::finalizedScript() const
{
    if (d->scripts.empty()) {
        return QString();
    }

    QString finalScript = d->scripts.join(QLatin1String(""));

    if (!finalScript.isEmpty()) {
        finalScript.append(QLatin1String("false;"));
    }

//    kDebug() << finalScript;
    return finalScript;
}

QVariant Message::property(const char *name) const
{
    return d->properties[QLatin1String(name)];
}

void Message::setProperty(const char *name, const QVariant& value)
{
    d->properties[QLatin1String(name)] = value;
}

QDateTime Message::time() const
{
    return d->sentTime;
}

QString Message::token() const
{
    return d->token;
}

Tp::ChannelTextMessageType Message::type() const
{
    return d->messageType;
}

int Message::partsSize() const
{
    return d->parts.size();
}

bool Message::isHistory() const
{
    return d->isHistory;
}

KTp::Message::MessageDirection Message::direction() const
{
    return d->direction;
}
<|endoftext|>


<commit_before>#include "filename/filename-execution-visitor.h"
#include <QDateTime>
#include <QJSEngine>
#include <QJSValue>
#include <QSet>
#include <QSettings>
#include <QSharedPointer>
#include <QStringList>
#include <QTimeZone>
#include <QVariant>
#include <algorithm>
#include "filename/ast/filename-node-condition-ignore.h"
#include "filename/ast/filename-node-condition-tag.h"
#include "filename/ast/filename-node-condition-token.h"
#include "filename/ast/filename-node-conditional.h"
#include "filename/ast/filename-node-javascript.h"
#include "filename/ast/filename-node-root.h"
#include "filename/ast/filename-node-text.h"
#include "filename/ast/filename-node-variable.h"
#include "filename/filename-condition-visitor.h"
#include "loader/token.h"
#include "logger.h"
#include "models/image.h"

FilenameExecutionVisitor::FilenameExecutionVisitor(const QMap<QString, Token> &tokens, QSettings *settings)
	: FilenameVisitorJavaScript(settings), m_tokens(tokens), m_settings(settings)
{}

void FilenameExecutionVisitor::setEscapeMethod(QString (*escapeMethod)(const QVariant &))
{
	m_escapeMethod = escapeMethod;
}

void FilenameExecutionVisitor::setKeepInvalidTokens(bool keepInvalidTokens)
{
	m_keepInvalidTokens = keepInvalidTokens;
}

QString FilenameExecutionVisitor::run(const FilenameNodeRoot &node)
{
	m_result.clear();

	node.accept(*this);

	return m_result;
}

void FilenameExecutionVisitor::visit(const FilenameNodeConditional &node)
{
	FilenameConditionVisitor conditionVisitor(m_tokens, m_settings);
	bool valid = conditionVisitor.run(*node.condition);

	if (valid && node.ifTrue != nullptr) {
		node.ifTrue->accept(*this);
	} else if (!valid && node.ifFalse != nullptr) {
		node.ifFalse->accept(*this);
	}
}

void FilenameExecutionVisitor::visit(const FilenameNodeConditionIgnore &node)
{
	Q_UNUSED(node);

	// No-op
}

void FilenameExecutionVisitor::visit(const FilenameNodeConditionTag &node)
{
	m_result += cleanVariable(node.tag.text());
}

void FilenameExecutionVisitor::visit(const FilenameNodeConditionToken &node)
{
	visitVariable(node.token);
}

void FilenameExecutionVisitor::visit(const FilenameNodeJavaScript &node)
{
	QJSEngine engine;
	setJavaScriptVariables(engine, m_tokens, engine.globalObject());

	QJSValue result = engine.evaluate(node.script);
	if (result.isError()) {
		log("Error in Javascript evaluation:
" + result.toString());
		return;
	}

	m_result += result.toString();
}

void FilenameExecutionVisitor::visit(const FilenameNodeText &node)
{
	m_result += node.text;
}

void FilenameExecutionVisitor::visit(const FilenameNodeVariable &node)
{
	visitVariable(node.name, node.opts);
}

void FilenameExecutionVisitor::visitVariable(const QString &fullName, const QMap<QString, QString> &options)
{
	// Contexts "obj.var"
	bool found = true;
	QStringList var = fullName.split('.');
	QString name = var.takeFirst();
	QMap<QString, Token> context = m_tokens;
	while (found && !var.isEmpty()) {
		if (context.contains(name)) {
			const QVariant &val = context[name].value();
			if (val.canConvert<QMap<QString, Token>>()) {
				context = val.value<QMap<QString, Token>>();
				name = var.takeFirst();
				continue;
			}
			break;
		}
		found = false;
	}

	// Variable not found
	if (!found || !context.contains(name)) {
		static const QSet<QString> keptTokens { "path", "num" };
		if (m_keepInvalidTokens || keptTokens.contains(name)) {
			QString strOpts;
			for (auto it = options.constBegin(); it != options.constEnd(); ++it) {
				strOpts += it.key();
				if (!it.value().isEmpty()) {
					strOpts += "=" + it.value();
				}
			}
			m_result += "%" + name + (!strOpts.isEmpty() ? ":" + strOpts : "") + "%"; // FIXME: get original value/proper toString()
		}
		return;
	}

	QVariant val = context[name].value();
	QString res;
	bool clean = false;

	// Convert value to a basic string using the given options
	if (val.type() == QVariant::DateTime) {
		res = variableToString(name, val.toDateTime(), options);
	} else if (val.type() == QVariant::ULongLong) {
		res = variableToString(name, val.toULongLong(), options);
	} else if (val.type() == QVariant::LongLong) {
		res = variableToString(name, val.toLongLong(), options);
	} else if (val.type() == QVariant::UInt) {
		res = variableToString(name, val.toUInt(), options);
	} else if (val.type() == QVariant::Int) {
		res = variableToString(name, val.toInt(), options);
	} else if (val.type() == QVariant::StringList) {
		res = variableToString(name, val.toStringList(), options);
		clean = true;
	} else {
		res = val.toString();
	}

	// String options
	if (options.contains("maxlength")) {
		res = res.left(options["maxlength"].toInt());
	}
	if (options.contains("htmlescape")) {
		res = res.toHtmlEscaped();
	}

	// Forbidden characters and spaces replacement settings
	if (name != "allo" && !name.startsWith("url_") && name != "filename" && name != "directory" && name != "old_filename" && name != "old_directory" && !clean) {
		res = cleanVariable(res, options);
	}

	// Escape if necessary
	if (m_escapeMethod != nullptr && options.contains("escape")) {
		res = m_escapeMethod(res);
	}

	m_result += res;
}

QString FilenameExecutionVisitor::variableToString(const QString &name, QDateTime val, const QMap<QString, QString> &options)
{
	Q_UNUSED(name);

	const QString timeZone = options.value("timezone", "");
	if (!timeZone.isEmpty() && timeZone != QLatin1String("server")) {
		if (timeZone == QLatin1String("local")) {
			val = val.toLocalTime();
		} else {
			QTimeZone tz(timeZone.toLatin1());
			if (tz.isValid()) {
				val = val.toTimeZone(tz);
			} else {
				log(QString("Unknown timeZone '%1'").arg(timeZone), Logger::Error);
			}
		}
	}

	const QString format = options.value("format", "MM-dd-yyyy HH.mm");
	return val.toString(format);
}

template <typename T>
QString FilenameExecutionVisitor::variableToString(const QString &name, T val, const QMap<QString, QString> &options)
{
	Q_UNUSED(name);

	return options.contains("length")
		? QString("%1").arg(val, options["length"].toInt(), 10, QChar('0'))
		: QString::number(val);
}

QString FilenameExecutionVisitor::variableToString(const QString &name, QStringList val, const QMap<QString, QString> &options)
{
	// Count
	if (options.contains("count")) {
		return variableToString(name, val.count(), options);
	}

	// Namespaces
	bool ignoreNamespace = options.contains("ignorenamespace");
	bool includeNamespace = options.contains("includenamespace");
	if (ignoreNamespace || includeNamespace) {
		QStringList namespaces = m_tokens["all_namespaces"].value().toStringList();

		if (options.contains("ignorenamespace")) {
			QStringList ignored = options["ignorenamespace"].split(' ');
			QStringList filtered, filteredNamespaces;
			for (int i = 0; i < val.count(); ++i) {
				const QString &nspace = name == "all" ? namespaces[i] : name;
				if (!ignored.contains(nspace)) {
					filtered.append(val[i]);
					filteredNamespaces.append(namespaces[i]);
				}
			}
			val = filtered;
			namespaces = filteredNamespaces;
		}
		if (options.contains("includenamespace")) {
			QStringList excluded;
			if (options.contains("excludenamespace")) {
				excluded = options["excludenamespace"].split(' ');
			}

			QStringList namespaced;
			for (int i = 0; i < val.count(); ++i) {
				const QString nspace = name == "all" ? namespaces[i] : name;
				namespaced.append((!excluded.contains(nspace) ? nspace + ":" : QString()) + val[i]);
			}
			val = namespaced;
		}
	}

	if (options.contains("sort")) {
		std::sort(val.begin(), val.end());
	}

	// Clean each value separately
	if (!name.startsWith("source")) {
		for (QString &t : val) {
			t = cleanVariable(t, options);
		}
	}

	// Separator
	QString mainSeparator = m_settings->value("Save/separator", " ").toString();
	QString tagSeparator = m_settings->value("Save/" + name + "_sep", mainSeparator).toString();
	QString separator = options.value("separator", tagSeparator);
	separator.replace("\\n", "\n").replace("\\r", "\r");

	return val.join(separator);
}

QString FilenameExecutionVisitor::cleanVariable(QString res, const QMap<QString, QString> &options) const
{
	// Forbidden characters
	if (!options.contains("unsafe")) {
		res = res.replace("\\", "_").replace("%", "_").replace("/", "_").replace(":", "_").replace("|", "_").replace("*", "_").replace("?", "_").replace("\"", "_").replace("<", "_").replace(">", "_").replace("__", "_").replace("__", "_").replace("__", "_").trimmed();
	}

	// Replace underscores by spaces
	if (!options.contains("underscores") && (!m_settings->value("Save/replaceblanks", false).toBool() || options.contains("spaces"))) {
		res = res.replace("_", " ");
	}

	return res;
}
<commit_msg>Add explicit template instantiation for variableToString<T><commit_after>#include "filename/filename-execution-visitor.h"
#include <QDateTime>
#include <QJSEngine>
#include <QJSValue>
#include <QSet>
#include <QSettings>
#include <QSharedPointer>
#include <QStringList>
#include <QTimeZone>
#include <QVariant>
#include <algorithm>
#include "filename/ast/filename-node-condition-ignore.h"
#include "filename/ast/filename-node-condition-tag.h"
#include "filename/ast/filename-node-condition-token.h"
#include "filename/ast/filename-node-conditional.h"
#include "filename/ast/filename-node-javascript.h"
#include "filename/ast/filename-node-root.h"
#include "filename/ast/filename-node-text.h"
#include "filename/ast/filename-node-variable.h"
#include "filename/filename-condition-visitor.h"
#include "loader/token.h"
#include "logger.h"
#include "models/image.h"

FilenameExecutionVisitor::FilenameExecutionVisitor(const QMap<QString, Token> &tokens, QSettings *settings)
	: FilenameVisitorJavaScript(settings), m_tokens(tokens), m_settings(settings)
{}

void FilenameExecutionVisitor::setEscapeMethod(QString (*escapeMethod)(const QVariant &))
{
	m_escapeMethod = escapeMethod;
}

void FilenameExecutionVisitor::setKeepInvalidTokens(bool keepInvalidTokens)
{
	m_keepInvalidTokens = keepInvalidTokens;
}

QString FilenameExecutionVisitor::run(const FilenameNodeRoot &node)
{
	m_result.clear();

	node.accept(*this);

	return m_result;
}

void FilenameExecutionVisitor::visit(const FilenameNodeConditional &node)
{
	FilenameConditionVisitor conditionVisitor(m_tokens, m_settings);
	bool valid = conditionVisitor.run(*node.condition);

	if (valid && node.ifTrue != nullptr) {
		node.ifTrue->accept(*this);
	} else if (!valid && node.ifFalse != nullptr) {
		node.ifFalse->accept(*this);
	}
}

void FilenameExecutionVisitor::visit(const FilenameNodeConditionIgnore &node)
{
	Q_UNUSED(node);

	// No-op
}

void FilenameExecutionVisitor::visit(const FilenameNodeConditionTag &node)
{
	m_result += cleanVariable(node.tag.text());
}

void FilenameExecutionVisitor::visit(const FilenameNodeConditionToken &node)
{
	visitVariable(node.token);
}

void FilenameExecutionVisitor::visit(const FilenameNodeJavaScript &node)
{
	QJSEngine engine;
	setJavaScriptVariables(engine, m_tokens, engine.globalObject());

	QJSValue result = engine.evaluate(node.script);
	if (result.isError()) {
		log("Error in Javascript evaluation:
" + result.toString());
		return;
	}

	m_result += result.toString();
}

void FilenameExecutionVisitor::visit(const FilenameNodeText &node)
{
	m_result += node.text;
}

void FilenameExecutionVisitor::visit(const FilenameNodeVariable &node)
{
	visitVariable(node.name, node.opts);
}

void FilenameExecutionVisitor::visitVariable(const QString &fullName, const QMap<QString, QString> &options)
{
	// Contexts "obj.var"
	bool found = true;
	QStringList var = fullName.split('.');
	QString name = var.takeFirst();
	QMap<QString, Token> context = m_tokens;
	while (found && !var.isEmpty()) {
		if (context.contains(name)) {
			const QVariant &val = context[name].value();
			if (val.canConvert<QMap<QString, Token>>()) {
				context = val.value<QMap<QString, Token>>();
				name = var.takeFirst();
				continue;
			}
			break;
		}
		found = false;
	}

	// Variable not found
	if (!found || !context.contains(name)) {
		static const QSet<QString> keptTokens { "path", "num" };
		if (m_keepInvalidTokens || keptTokens.contains(name)) {
			QString strOpts;
			for (auto it = options.constBegin(); it != options.constEnd(); ++it) {
				strOpts += it.key();
				if (!it.value().isEmpty()) {
					strOpts += "=" + it.value();
				}
			}
			m_result += "%" + name + (!strOpts.isEmpty() ? ":" + strOpts : "") + "%"; // FIXME: get original value/proper toString()
		}
		return;
	}

	QVariant val = context[name].value();
	QString res;
	bool clean = false;

	// Convert value to a basic string using the given options
	if (val.type() == QVariant::DateTime) {
		res = variableToString(name, val.toDateTime(), options);
	} else if (val.type() == QVariant::ULongLong) {
		res = variableToString(name, val.toULongLong(), options);
	} else if (val.type() == QVariant::LongLong) {
		res = variableToString(name, val.toLongLong(), options);
	} else if (val.type() == QVariant::UInt) {
		res = variableToString(name, val.toUInt(), options);
	} else if (val.type() == QVariant::Int) {
		res = variableToString(name, val.toInt(), options);
	} else if (val.type() == QVariant::StringList) {
		res = variableToString(name, val.toStringList(), options);
		clean = true;
	} else {
		res = val.toString();
	}

	// String options
	if (options.contains("maxlength")) {
		res = res.left(options["maxlength"].toInt());
	}
	if (options.contains("htmlescape")) {
		res = res.toHtmlEscaped();
	}

	// Forbidden characters and spaces replacement settings
	if (name != "allo" && !name.startsWith("url_") && name != "filename" && name != "directory" && name != "old_filename" && name != "old_directory" && !clean) {
		res = cleanVariable(res, options);
	}

	// Escape if necessary
	if (m_escapeMethod != nullptr && options.contains("escape")) {
		res = m_escapeMethod(res);
	}

	m_result += res;
}

QString FilenameExecutionVisitor::variableToString(const QString &name, QDateTime val, const QMap<QString, QString> &options)
{
	Q_UNUSED(name);

	const QString timeZone = options.value("timezone", "");
	if (!timeZone.isEmpty() && timeZone != QLatin1String("server")) {
		if (timeZone == QLatin1String("local")) {
			val = val.toLocalTime();
		} else {
			QTimeZone tz(timeZone.toLatin1());
			if (tz.isValid()) {
				val = val.toTimeZone(tz);
			} else {
				log(QString("Unknown timeZone '%1'").arg(timeZone), Logger::Error);
			}
		}
	}

	const QString format = options.value("format", "MM-dd-yyyy HH.mm");
	return val.toString(format);
}

template <typename T>
QString FilenameExecutionVisitor::variableToString(const QString &name, T val, const QMap<QString, QString> &options)
{
	Q_UNUSED(name);

	return options.contains("length")
		? QString("%1").arg(val, options["length"].toInt(), 10, QChar('0'))
		: QString::number(val);
}
template QString FilenameExecutionVisitor::variableToString<int>(const QString &name, int val, const QMap<QString, QString> &options);
template QString FilenameExecutionVisitor::variableToString<uint>(const QString &name, uint val, const QMap<QString, QString> &options);
template QString FilenameExecutionVisitor::variableToString<qlonglong>(const QString &name, qlonglong val, const QMap<QString, QString> &options);
template QString FilenameExecutionVisitor::variableToString<qulonglong>(const QString &name, qulonglong val, const QMap<QString, QString> &options);

QString FilenameExecutionVisitor::variableToString(const QString &name, QStringList val, const QMap<QString, QString> &options)
{
	// Count
	if (options.contains("count")) {
		return variableToString(name, val.count(), options);
	}

	// Namespaces
	bool ignoreNamespace = options.contains("ignorenamespace");
	bool includeNamespace = options.contains("includenamespace");
	if (ignoreNamespace || includeNamespace) {
		QStringList namespaces = m_tokens["all_namespaces"].value().toStringList();

		if (options.contains("ignorenamespace")) {
			QStringList ignored = options["ignorenamespace"].split(' ');
			QStringList filtered, filteredNamespaces;
			for (int i = 0; i < val.count(); ++i) {
				const QString &nspace = name == "all" ? namespaces[i] : name;
				if (!ignored.contains(nspace)) {
					filtered.append(val[i]);
					filteredNamespaces.append(namespaces[i]);
				}
			}
			val = filtered;
			namespaces = filteredNamespaces;
		}
		if (options.contains("includenamespace")) {
			QStringList excluded;
			if (options.contains("excludenamespace")) {
				excluded = options["excludenamespace"].split(' ');
			}

			QStringList namespaced;
			for (int i = 0; i < val.count(); ++i) {
				const QString nspace = name == "all" ? namespaces[i] : name;
				namespaced.append((!excluded.contains(nspace) ? nspace + ":" : QString()) + val[i]);
			}
			val = namespaced;
		}
	}

	if (options.contains("sort")) {
		std::sort(val.begin(), val.end());
	}

	// Clean each value separately
	if (!name.startsWith("source")) {
		for (QString &t : val) {
			t = cleanVariable(t, options);
		}
	}

	// Separator
	QString mainSeparator = m_settings->value("Save/separator", " ").toString();
	QString tagSeparator = m_settings->value("Save/" + name + "_sep", mainSeparator).toString();
	QString separator = options.value("separator", tagSeparator);
	separator.replace("\\n", "\n").replace("\\r", "\r");

	return val.join(separator);
}

QString FilenameExecutionVisitor::cleanVariable(QString res, const QMap<QString, QString> &options) const
{
	// Forbidden characters
	if (!options.contains("unsafe")) {
		res = res.replace("\\", "_").replace("%", "_").replace("/", "_").replace(":", "_").replace("|", "_").replace("*", "_").replace("?", "_").replace("\"", "_").replace("<", "_").replace(">", "_").replace("__", "_").replace("__", "_").replace("__", "_").trimmed();
	}

	// Replace underscores by spaces
	if (!options.contains("underscores") && (!m_settings->value("Save/replaceblanks", false).toBool() || options.contains("spaces"))) {
		res = res.replace("_", " ");
	}

	return res;
}
<|endoftext|>