<commit_before>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: pe_property.cxx,v $
 *
 *  $Revision: 1.3 $
 *
 *  last change: $Author: rt $ $Date: 2005-09-07 18:49:01 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    This library is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *    Lesser General Public License for more details.
 *
 *    You should have received a copy of the GNU Lesser General Public
 *    License along with this library; if not, write to the Free Software
 *    Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/

#include <precomp.h>
#include <s2_luidl/pe_property.hxx>

// NOT FULLY DEFINED SERVICES
#include <ary/idl/i_gate.hxx>
#include <ary/idl/i_property.hxx>
#include <ary/idl/i_service.hxx>
#include <ary/idl/ip_ce.hxx>
#include <ary_i/codeinf2.hxx>
#include <s2_luidl/pe_vari2.hxx>
#include <s2_luidl/tk_keyw.hxx>
#include <s2_luidl/tk_ident.hxx>
#include <s2_luidl/tk_punct.hxx>

namespace csi
{
namespace uidl
{

PE_Property::PE_Property( const Ce_id & i_rCurOwner )
    :   eState(e_none),
        pCurOwner(&i_rCurOwner),
        pPE_Variable(0),
        nCurParsedType(0),
        sCurParsedName(),
        bIsOptional(false),
        aStereotypes()
{
    pPE_Variable    = new PE_Variable(nCurParsedType, sCurParsedName);
}

void
PE_Property::EstablishContacts( UnoIDL_PE *                io_pParentPE,
                                ary::n22::Repository &      io_rRepository,
                                TokenProcessing_Result &    o_rResult )
{
    UnoIDL_PE::EstablishContacts(io_pParentPE,io_rRepository,o_rResult);
    pPE_Variable->EstablishContacts(this,io_rRepository,o_rResult);
}

PE_Property::~PE_Property()
{
}

void
PE_Property::ProcessToken( const Token & i_rToken )
{
    i_rToken.Trigger(*this);
}

void
PE_Property::Process_Stereotype( const TokStereotype & i_rToken )
{
    switch (i_rToken.Id())
    {
        case TokStereotype::ste_optional:
            bIsOptional = true;
            break;
        case TokStereotype::ste_readonly:
            aStereotypes.Set_Flag(Stereotypes::readonly);
            break;
        case TokStereotype::ste_bound:
            aStereotypes.Set_Flag(Stereotypes::bound);
            break;
        case TokStereotype::ste_constrained:
            aStereotypes.Set_Flag(Stereotypes::constrained);
            break;
        case TokStereotype::ste_maybeambiguous:
            aStereotypes.Set_Flag(Stereotypes::maybeambiguous);
            break;
        case TokStereotype::ste_maybedefault:
            aStereotypes.Set_Flag(Stereotypes::maybedefault);
            break;
        case TokStereotype::ste_maybevoid:
            aStereotypes.Set_Flag(Stereotypes::maybevoid);
            break;
        case TokStereotype::ste_removable:
            aStereotypes.Set_Flag(Stereotypes::removable);
            break;
        case TokStereotype::ste_transient:
            aStereotypes.Set_Flag(Stereotypes::transient);
            break;

        default:
            SetResult(not_done, pop_failure);
            eState = e_none;
            return;
    }

    SetResult(done, stay);
}

void
PE_Property::Process_MetaType( const TokMetaType & i_rToken )
{
    if (eState == e_start)
    {
        if ( i_rToken.Id() == TokMetaType::mt_property )
        {
            SetResult(done, stay);
            eState = expect_variable;
            return;
        }
    }   // endif (eState == e_start)

    SetResult(not_done, pop_failure);
    eState = e_none;
}

void
PE_Property::Process_Punctuation( const TokPunctuation & i_rToken )
{
    switch (eState)
    {
        case e_start:
            SetResult(done, stay);
            break;
        case expect_variable:
            if (i_rToken.Id() == TokPunctuation::Semicolon)
            {
                SetResult(done, pop_success);
                eState = e_none;
            }
            else if (i_rToken.Id() == TokPunctuation::Comma)
                SetResult(done, stay);
            else
                SetResult(not_done, pop_failure);
            break;
        default:
            csv_assert(false);
    }
}

void
PE_Property::Process_Default()
{
    if (eState == expect_variable)
    {
        SetResult(not_done, push_sure, pPE_Variable.Ptr());
        eState = in_variable;
    }
    else
        SetResult(not_done, pop_failure);
}

void
PE_Property::InitData()
{
    eState = e_start;

    nCurParsedType = 0;
    sCurParsedName = "";

    // bIsOptional and
    // aStereotypes
    //   may be preset by the PE_Service-(or PE_Interface-)parent
    //   with PresetOptional() or
    //   PresetStereotype()
    //   - therefore it must not be set here!
}

void
PE_Property::TransferData()
{
    if (bIsOptional)
    {
        SetOptional();
        bIsOptional = false;
    }

    ary::idl::CodeEntity *
        pCe = 0;
    csv_assert(pCurOwner->IsValid());

    pCe = &Gate().Ces().Store_Property( *pCurOwner,
                                        sCurParsedName,
                                        nCurParsedType,
                                        aStereotypes );

    csv_assert(pCe != 0);
    PassDocuAt(*pCe);

    nCurParsedType = 0;
    sCurParsedName.clear();
    aStereotypes = Stereotypes();

    eState = e_none;
}

void
PE_Property::ReceiveData()
{
    eState = expect_variable;
}

UnoIDL_PE &
PE_Property::MyPE()
{
    return *this;
}

}   // namespace uidl
}   // namespace csi

<commit_msg>INTEGRATION: CWS pchfix02 (1.3.30); FILE MERGED 2006/09/01 17:15:48 kaib 1.3.30.1: #i68856# Added header markers and pch files<commit_after>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: pe_property.cxx,v $
 *
 *  $Revision: 1.4 $
 *
 *  last change: $Author: obo $ $Date: 2006-09-16 17:10:26 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    This library is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *    Lesser General Public License for more details.
 *
 *    You should have received a copy of the GNU Lesser General Public
 *    License along with this library; if not, write to the Free Software
 *    Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/

// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_autodoc.hxx"

#include <precomp.h>
#include <s2_luidl/pe_property.hxx>

// NOT FULLY DEFINED SERVICES
#include <ary/idl/i_gate.hxx>
#include <ary/idl/i_property.hxx>
#include <ary/idl/i_service.hxx>
#include <ary/idl/ip_ce.hxx>
#include <ary_i/codeinf2.hxx>
#include <s2_luidl/pe_vari2.hxx>
#include <s2_luidl/tk_keyw.hxx>
#include <s2_luidl/tk_ident.hxx>
#include <s2_luidl/tk_punct.hxx>

namespace csi
{
namespace uidl
{

PE_Property::PE_Property( const Ce_id & i_rCurOwner )
    :   eState(e_none),
        pCurOwner(&i_rCurOwner),
        pPE_Variable(0),
        nCurParsedType(0),
        sCurParsedName(),
        bIsOptional(false),
        aStereotypes()
{
    pPE_Variable    = new PE_Variable(nCurParsedType, sCurParsedName);
}

void
PE_Property::EstablishContacts( UnoIDL_PE *                io_pParentPE,
                                ary::n22::Repository &      io_rRepository,
                                TokenProcessing_Result &    o_rResult )
{
    UnoIDL_PE::EstablishContacts(io_pParentPE,io_rRepository,o_rResult);
    pPE_Variable->EstablishContacts(this,io_rRepository,o_rResult);
}

PE_Property::~PE_Property()
{
}

void
PE_Property::ProcessToken( const Token & i_rToken )
{
    i_rToken.Trigger(*this);
}

void
PE_Property::Process_Stereotype( const TokStereotype & i_rToken )
{
    switch (i_rToken.Id())
    {
        case TokStereotype::ste_optional:
            bIsOptional = true;
            break;
        case TokStereotype::ste_readonly:
            aStereotypes.Set_Flag(Stereotypes::readonly);
            break;
        case TokStereotype::ste_bound:
            aStereotypes.Set_Flag(Stereotypes::bound);
            break;
        case TokStereotype::ste_constrained:
            aStereotypes.Set_Flag(Stereotypes::constrained);
            break;
        case TokStereotype::ste_maybeambiguous:
            aStereotypes.Set_Flag(Stereotypes::maybeambiguous);
            break;
        case TokStereotype::ste_maybedefault:
            aStereotypes.Set_Flag(Stereotypes::maybedefault);
            break;
        case TokStereotype::ste_maybevoid:
            aStereotypes.Set_Flag(Stereotypes::maybevoid);
            break;
        case TokStereotype::ste_removable:
            aStereotypes.Set_Flag(Stereotypes::removable);
            break;
        case TokStereotype::ste_transient:
            aStereotypes.Set_Flag(Stereotypes::transient);
            break;

        default:
            SetResult(not_done, pop_failure);
            eState = e_none;
            return;
    }

    SetResult(done, stay);
}

void
PE_Property::Process_MetaType( const TokMetaType & i_rToken )
{
    if (eState == e_start)
    {
        if ( i_rToken.Id() == TokMetaType::mt_property )
        {
            SetResult(done, stay);
            eState = expect_variable;
            return;
        }
    }   // endif (eState == e_start)

    SetResult(not_done, pop_failure);
    eState = e_none;
}

void
PE_Property::Process_Punctuation( const TokPunctuation & i_rToken )
{
    switch (eState)
    {
        case e_start:
            SetResult(done, stay);
            break;
        case expect_variable:
            if (i_rToken.Id() == TokPunctuation::Semicolon)
            {
                SetResult(done, pop_success);
                eState = e_none;
            }
            else if (i_rToken.Id() == TokPunctuation::Comma)
                SetResult(done, stay);
            else
                SetResult(not_done, pop_failure);
            break;
        default:
            csv_assert(false);
    }
}

void
PE_Property::Process_Default()
{
    if (eState == expect_variable)
    {
        SetResult(not_done, push_sure, pPE_Variable.Ptr());
        eState = in_variable;
    }
    else
        SetResult(not_done, pop_failure);
}

void
PE_Property::InitData()
{
    eState = e_start;

    nCurParsedType = 0;
    sCurParsedName = "";

    // bIsOptional and
    // aStereotypes
    //   may be preset by the PE_Service-(or PE_Interface-)parent
    //   with PresetOptional() or
    //   PresetStereotype()
    //   - therefore it must not be set here!
}

void
PE_Property::TransferData()
{
    if (bIsOptional)
    {
        SetOptional();
        bIsOptional = false;
    }

    ary::idl::CodeEntity *
        pCe = 0;
    csv_assert(pCurOwner->IsValid());

    pCe = &Gate().Ces().Store_Property( *pCurOwner,
                                        sCurParsedName,
                                        nCurParsedType,
                                        aStereotypes );

    csv_assert(pCe != 0);
    PassDocuAt(*pCe);

    nCurParsedType = 0;
    sCurParsedName.clear();
    aStereotypes = Stereotypes();

    eState = e_none;
}

void
PE_Property::ReceiveData()
{
    eState = expect_variable;
}

UnoIDL_PE &
PE_Property::MyPE()
{
    return *this;
}

}   // namespace uidl
}   // namespace csi

<|endoftext|>


<commit_before>//==- DeadStores.cpp - Check for stores to dead variables --------*- C++ -*-==//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
//  This file defines a DeadStores, a flow-sensitive checker that looks for
//  stores to variables that are no longer live.
//
//===----------------------------------------------------------------------===//

#include "clang/Analysis/LocalCheckers.h"
#include "clang/Analysis/Analyses/LiveVariables.h"
#include "clang/Analysis/Visitors/CFGRecStmtVisitor.h"
#include "clang/Analysis/PathSensitive/BugReporter.h"
#include "clang/Analysis/PathSensitive/GRExprEngine.h"
#include "clang/Basic/Diagnostic.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/ParentMap.h"
#include "llvm/Support/Compiler.h"

using namespace clang;

namespace {

class VISIBILITY_HIDDEN DeadStoreObs : public LiveVariables::ObserverTy {
  ASTContext &Ctx;
  BugReporter& BR;
  ParentMap& Parents;

  enum DeadStoreKind { Standard, Enclosing, DeadIncrement, DeadInit };

public:
  DeadStoreObs(ASTContext &ctx, BugReporter& br, ParentMap& parents)
    : Ctx(ctx), BR(br), Parents(parents) {}

  virtual ~DeadStoreObs() {}

  void Report(VarDecl* V, DeadStoreKind dsk, SourceLocation L, SourceRange R) {

    std::string name(V->getName());

    const char* BugType = 0;
    std::string msg;

    switch (dsk) {
      default:
        assert(false && "Impossible dead store type.");

      case DeadInit:
        BugType = "dead initialization";
        msg = "Value stored to '" + name +
          "' during its initialization is never read";
        break;

      case DeadIncrement:
        BugType = "dead increment";
      case Standard:
        if (!BugType) BugType = "dead store";
        msg = "Value stored to '" + name + "' is never read";
        break;

      case Enclosing:
        BugType = "dead store";
        msg = "Although the value stored to '" + name +
          "' is used in the enclosing expression, the value is never actually"
          " read from '" + name + "'";
        break;
    }

    BR.EmitBasicReport(BugType, msg.c_str(), L, R);
  }

  void CheckVarDecl(VarDecl* VD, Expr* Ex, Expr* Val,
                    DeadStoreKind dsk,
                    const LiveVariables::AnalysisDataTy& AD,
                    const LiveVariables::ValTy& Live) {

    if (VD->hasLocalStorage() && !Live(VD, AD) && !VD->getAttr<UnusedAttr>())
      Report(VD, dsk, Ex->getSourceRange().getBegin(),
             Val->getSourceRange());
  }

  void CheckDeclRef(DeclRefExpr* DR, Expr* Val, DeadStoreKind dsk,
                    const LiveVariables::AnalysisDataTy& AD,
                    const LiveVariables::ValTy& Live) {

    if (VarDecl* VD = dyn_cast<VarDecl>(DR->getDecl()))
      CheckVarDecl(VD, DR, Val, dsk, AD, Live);
  }

  bool isIncrement(VarDecl* VD, BinaryOperator* B) {
    if (B->isCompoundAssignmentOp())
      return true;

    Expr* RHS = B->getRHS()->IgnoreParenCasts();
    BinaryOperator* BRHS = dyn_cast<BinaryOperator>(RHS);

    if (!BRHS)
      return false;

    DeclRefExpr *DR;

    if ((DR = dyn_cast<DeclRefExpr>(BRHS->getLHS()->IgnoreParenCasts())))
      if (DR->getDecl() == VD)
        return true;

    if ((DR = dyn_cast<DeclRefExpr>(BRHS->getRHS()->IgnoreParenCasts())))
      if (DR->getDecl() == VD)
        return true;

    return false;
  }

  virtual void ObserveStmt(Stmt* S,
                           const LiveVariables::AnalysisDataTy& AD,
                           const LiveVariables::ValTy& Live) {

    // Skip statements in macros.
    if (S->getLocStart().isMacroID())
      return;

    if (BinaryOperator* B = dyn_cast<BinaryOperator>(S)) {
      if (!B->isAssignmentOp()) return; // Skip non-assignments.

      if (DeclRefExpr* DR = dyn_cast<DeclRefExpr>(B->getLHS()))
        if (VarDecl *VD = dyn_cast<VarDecl>(DR->getDecl())) {

          // Special case: check for assigning null to a pointer.  This
          //  is a common form of defensive programming.
          // FIXME: Make this optional?

          Expr* Val = B->getRHS();
          llvm::APSInt Result(Ctx.getTypeSize(Val->getType()));

          if (VD->getType()->isPointerType() &&
              Val->IgnoreParenCasts()->isIntegerConstantExpr(Result, Ctx, 0))
            if (Result == 0)
              return;

          DeadStoreKind dsk =
            Parents.isSubExpr(B)
            ? Enclosing
            : (isIncrement(VD,B) ? DeadIncrement : Standard);

          CheckVarDecl(VD, DR, Val, dsk, AD, Live);
        }
    }
    else if (UnaryOperator* U = dyn_cast<UnaryOperator>(S)) {
      if (!U->isIncrementOp())
        return;

      Expr *Ex = U->getSubExpr()->IgnoreParenCasts();

      if (DeclRefExpr* DR = dyn_cast<DeclRefExpr>(Ex))
        CheckDeclRef(DR, U, DeadIncrement, AD, Live);
    }
    else if (DeclStmt* DS = dyn_cast<DeclStmt>(S))
      // Iterate through the decls.  Warn if any initializers are complex
      // expressions that are not live (never used).
      for (DeclStmt::decl_iterator DI=DS->decl_begin(), DE=DS->decl_end();
           DI != DE; ++DI) {

        VarDecl* V = dyn_cast<VarDecl>(*DI);

        if (!V)
          continue;

        if (V->hasLocalStorage())
          if (Expr* E = V->getInit()) {
            // A dead initialization is a variable that is dead after it
            // is initialized.  We don't flag warnings for those variables
            // marked 'unused'.
            if (!Live(V, AD) && V->getAttr<UnusedAttr>() == 0) {
              // Special case: check for initializations with constants.
              //
              //  e.g. : int x = 0;
              //
              // If x is EVER assigned a new value later, don't issue
              // a warning.  This is because such initialization can be
              // due to defensive programming.
              if (!E->isConstantExpr(Ctx,NULL))
                Report(V, DeadInit, V->getLocation(), E->getSourceRange());
            }
          }
      }
  }
};

} // end anonymous namespace

//===----------------------------------------------------------------------===//
// Driver function to invoke the Dead-Stores checker on a CFG.
//===----------------------------------------------------------------------===//

void clang::CheckDeadStores(LiveVariables& L, BugReporter& BR) {
  DeadStoreObs A(BR.getContext(), BR, BR.getParentMap());
  L.runOnAllBlocks(*BR.getCFG(), &A);
}
<commit_msg>Don't use Expr::isIntegerConstantExpr just to check if a pointer value is initialize to NULL.<commit_after>//==- DeadStores.cpp - Check for stores to dead variables --------*- C++ -*-==//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
//  This file defines a DeadStores, a flow-sensitive checker that looks for
//  stores to variables that are no longer live.
//
//===----------------------------------------------------------------------===//

#include "clang/Analysis/LocalCheckers.h"
#include "clang/Analysis/Analyses/LiveVariables.h"
#include "clang/Analysis/Visitors/CFGRecStmtVisitor.h"
#include "clang/Analysis/PathSensitive/BugReporter.h"
#include "clang/Analysis/PathSensitive/GRExprEngine.h"
#include "clang/Basic/Diagnostic.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/ParentMap.h"
#include "llvm/Support/Compiler.h"

using namespace clang;

namespace {

class VISIBILITY_HIDDEN DeadStoreObs : public LiveVariables::ObserverTy {
  ASTContext &Ctx;
  BugReporter& BR;
  ParentMap& Parents;

  enum DeadStoreKind { Standard, Enclosing, DeadIncrement, DeadInit };

public:
  DeadStoreObs(ASTContext &ctx, BugReporter& br, ParentMap& parents)
    : Ctx(ctx), BR(br), Parents(parents) {}

  virtual ~DeadStoreObs() {}

  void Report(VarDecl* V, DeadStoreKind dsk, SourceLocation L, SourceRange R) {

    std::string name(V->getName());

    const char* BugType = 0;
    std::string msg;

    switch (dsk) {
      default:
        assert(false && "Impossible dead store type.");

      case DeadInit:
        BugType = "dead initialization";
        msg = "Value stored to '" + name +
          "' during its initialization is never read";
        break;

      case DeadIncrement:
        BugType = "dead increment";
      case Standard:
        if (!BugType) BugType = "dead store";
        msg = "Value stored to '" + name + "' is never read";
        break;

      case Enclosing:
        BugType = "dead store";
        msg = "Although the value stored to '" + name +
          "' is used in the enclosing expression, the value is never actually"
          " read from '" + name + "'";
        break;
    }

    BR.EmitBasicReport(BugType, msg.c_str(), L, R);
  }

  void CheckVarDecl(VarDecl* VD, Expr* Ex, Expr* Val,
                    DeadStoreKind dsk,
                    const LiveVariables::AnalysisDataTy& AD,
                    const LiveVariables::ValTy& Live) {

    if (VD->hasLocalStorage() && !Live(VD, AD) && !VD->getAttr<UnusedAttr>())
      Report(VD, dsk, Ex->getSourceRange().getBegin(),
             Val->getSourceRange());
  }

  void CheckDeclRef(DeclRefExpr* DR, Expr* Val, DeadStoreKind dsk,
                    const LiveVariables::AnalysisDataTy& AD,
                    const LiveVariables::ValTy& Live) {

    if (VarDecl* VD = dyn_cast<VarDecl>(DR->getDecl()))
      CheckVarDecl(VD, DR, Val, dsk, AD, Live);
  }

  bool isIncrement(VarDecl* VD, BinaryOperator* B) {
    if (B->isCompoundAssignmentOp())
      return true;

    Expr* RHS = B->getRHS()->IgnoreParenCasts();
    BinaryOperator* BRHS = dyn_cast<BinaryOperator>(RHS);

    if (!BRHS)
      return false;

    DeclRefExpr *DR;

    if ((DR = dyn_cast<DeclRefExpr>(BRHS->getLHS()->IgnoreParenCasts())))
      if (DR->getDecl() == VD)
        return true;

    if ((DR = dyn_cast<DeclRefExpr>(BRHS->getRHS()->IgnoreParenCasts())))
      if (DR->getDecl() == VD)
        return true;

    return false;
  }

  virtual void ObserveStmt(Stmt* S,
                           const LiveVariables::AnalysisDataTy& AD,
                           const LiveVariables::ValTy& Live) {

    // Skip statements in macros.
    if (S->getLocStart().isMacroID())
      return;

    if (BinaryOperator* B = dyn_cast<BinaryOperator>(S)) {
      if (!B->isAssignmentOp()) return; // Skip non-assignments.

      if (DeclRefExpr* DR = dyn_cast<DeclRefExpr>(B->getLHS()))
        if (VarDecl *VD = dyn_cast<VarDecl>(DR->getDecl())) {
          // Special case: check for assigning null to a pointer.
          //  This is a common form of defensive programming.
          if (VD->getType()->isPointerType()) {
            if (IntegerLiteral* L =
                  dyn_cast<IntegerLiteral>(B->getRHS()->IgnoreParenCasts()))
              if (L->getValue() == 0)
                return;
          }

          DeadStoreKind dsk =
            Parents.isSubExpr(B)
            ? Enclosing
            : (isIncrement(VD,B) ? DeadIncrement : Standard);

          CheckVarDecl(VD, DR, B->getRHS(), dsk, AD, Live);
        }
    }
    else if (UnaryOperator* U = dyn_cast<UnaryOperator>(S)) {
      if (!U->isIncrementOp())
        return;

      Expr *Ex = U->getSubExpr()->IgnoreParenCasts();

      if (DeclRefExpr* DR = dyn_cast<DeclRefExpr>(Ex))
        CheckDeclRef(DR, U, DeadIncrement, AD, Live);
    }
    else if (DeclStmt* DS = dyn_cast<DeclStmt>(S))
      // Iterate through the decls.  Warn if any initializers are complex
      // expressions that are not live (never used).
      for (DeclStmt::decl_iterator DI=DS->decl_begin(), DE=DS->decl_end();
           DI != DE; ++DI) {

        VarDecl* V = dyn_cast<VarDecl>(*DI);

        if (!V)
          continue;

        if (V->hasLocalStorage())
          if (Expr* E = V->getInit()) {
            // A dead initialization is a variable that is dead after it
            // is initialized.  We don't flag warnings for those variables
            // marked 'unused'.
            if (!Live(V, AD) && V->getAttr<UnusedAttr>() == 0) {
              // Special case: check for initializations with constants.
              //
              //  e.g. : int x = 0;
              //
              // If x is EVER assigned a new value later, don't issue
              // a warning.  This is because such initialization can be
              // due to defensive programming.
              if (!E->isConstantExpr(Ctx,NULL))
                Report(V, DeadInit, V->getLocation(), E->getSourceRange());
            }
          }
      }
  }
};

} // end anonymous namespace

//===----------------------------------------------------------------------===//
// Driver function to invoke the Dead-Stores checker on a CFG.
//===----------------------------------------------------------------------===//

void clang::CheckDeadStores(LiveVariables& L, BugReporter& BR) {
  DeadStoreObs A(BR.getContext(), BR, BR.getParentMap());
  L.runOnAllBlocks(*BR.getCFG(), &A);
}
<|endoftext|>


<commit_before>/*\file
 *
 * \brief Functionality for getting experimental/empirical atomic data (source)
*/

#include <algorithm>

#include "pulsar/system/AtomicInfo.hpp"
#include "pulsar/system/AtomicInfo_LUT.hpp"
#include "pulsar/exception/Exceptions.hpp"

namespace pulsar{
namespace system {

// global LUT:
// Maps Z to symbol
using lut::atomic_Z_sym_;

// Maps symbol to Z
using lut::atomic_sym_Z_;

// Maps Z to data
using lut::atomic_Z_data_;

int AtomicZNumberFromSym(const std::string & sym)
{
    if(atomic_sym_Z_.count(sym))
        return atomic_sym_Z_.at(sym);
    else
        throw exception::SystemException("No Z number for this atomic symbol",
                                           "symbol", sym);
}

std::string AtomicSymFromZ(int Z)
{
    if(atomic_Z_sym_.count(Z))
        return atomic_Z_sym_.at(Z);
    else
        throw exception::SystemException("No symbol for this Z number",
                                           "Z", Z);
}

const AtomicData & AtomicInfoFromZ(int Z)
{
    if(atomic_Z_data_.count(Z))
        return atomic_Z_data_.at(Z);
    else
        throw exception::SystemException("No atomic data for this Z number",
                                           "Z", Z);
}

const AtomicData & AtomicInfoFromSym(const std::string & sym)
{
    return AtomicInfoFromZ(AtomicZNumberFromSym(sym));
}

const IsotopeData & IsotopeInfoFromZ(int Z, int isonum)
{
    AtomicData ad = AtomicInfoFromZ(Z);

    for(const auto & it : ad.isotopes)
        if(it.isonum == isonum)
            return it;

    throw exception::SystemException("No isotope data for this Z and isotope number",
                                           "Z", Z,
                                           "isotope", isonum);
}

const IsotopeData & IsotopeInfoFromSym(const std::string & sym, int isonum)
{
    return IsotopeInfoFromZ(AtomicZNumberFromSym(sym), isonum);
}

int MostCommonIsotopeFromZ(int Z)
{
    const AtomicData & ad = AtomicInfoFromZ(Z);
    if(ad.isotopes.size() == 0)
        throw exception::SystemException("Developer error: No isotopes for this Z number?",
                                           "Z", Z);

    auto maxit = std::max_element(ad.isotopes.begin(), ad.isotopes.end(),
                                  [](const IsotopeData & idat1, const IsotopeData & idat2)
                                    { return idat1.abund < idat2.abund; }
                                 );

    return maxit->isonum;
}

int MostCommonIsotopeFromSym(const std::string & sym)
{
    return MostCommonIsotopeFromZ(AtomicZNumberFromSym(sym));
}

double AtomicMassFromZ(int Z)
{
    return AtomicInfoFromZ(Z).mass;
}

double AtomicMassFromSym(const std::string & sym)
{
    return AtomicInfoFromSym(sym).mass;
}

double IsotopeMassFromZ(int Z, int isonum)
{
    return IsotopeInfoFromZ(Z, isonum).mass;
}

double IsotopeMassFromSym(const std::string & sym, int isonum)
{
    return IsotopeInfoFromSym(sym, isonum).mass;
}

std::string AtomicNameFromZ(int Z)
{
    return AtomicInfoFromZ(Z).name;
}

std::string AtomicNameFromSym(const std::string & sym)
{
    return AtomicInfoFromSym(sym).name;
}

int AtomicMultiplicityFromZ(int Z)
{
    return AtomicInfoFromZ(Z).multiplicity;
}

int AtomicMultiplicityFromSym(const std::string & sym)
{
    return AtomicInfoFromSym(sym).multiplicity;
}

double CovRadiusFromZ(int Z)
{
    return AtomicInfoFromZ(Z).covradius;
}

double CovRadiusFroSym(const std::string & sym)
{
    return AtomicInfoFromSym(sym).covradius;
}

double VDWRadiusFromZ(int Z)
{
    return AtomicInfoFromZ(Z).vdwradius;
}

double VDWRadiusFroSym(const std::string & sym)
{
    return AtomicInfoFromSym(sym).vdwradius;
}

} // closing namespace system
} // closing namespace pulsar

<commit_msg>Fix returning of local variable<commit_after>/*\file
 *
 * \brief Functionality for getting experimental/empirical atomic data (source)
*/

#include <algorithm>

#include "pulsar/system/AtomicInfo.hpp"
#include "pulsar/system/AtomicInfo_LUT.hpp"
#include "pulsar/exception/Exceptions.hpp"

namespace pulsar{
namespace system {

// global LUT:
// Maps Z to symbol
using lut::atomic_Z_sym_;

// Maps symbol to Z
using lut::atomic_sym_Z_;

// Maps Z to data
using lut::atomic_Z_data_;

int AtomicZNumberFromSym(const std::string & sym)
{
    if(atomic_sym_Z_.count(sym))
        return atomic_sym_Z_.at(sym);
    else
        throw exception::SystemException("No Z number for this atomic symbol",
                                           "symbol", sym);
}

std::string AtomicSymFromZ(int Z)
{
    if(atomic_Z_sym_.count(Z))
        return atomic_Z_sym_.at(Z);
    else
        throw exception::SystemException("No symbol for this Z number",
                                           "Z", Z);
}

const AtomicData & AtomicInfoFromZ(int Z)
{
    if(atomic_Z_data_.count(Z))
        return atomic_Z_data_.at(Z);
    else
        throw exception::SystemException("No atomic data for this Z number",
                                           "Z", Z);
}

const AtomicData & AtomicInfoFromSym(const std::string & sym)
{
    return AtomicInfoFromZ(AtomicZNumberFromSym(sym));
}

const IsotopeData & IsotopeInfoFromZ(int Z, int isonum)
{
    const AtomicData & ad = AtomicInfoFromZ(Z);

    for(const auto & it : ad.isotopes)
        if(it.isonum == isonum)
            return it;

    throw exception::SystemException("No isotope data for this Z and isotope number",
                                           "Z", Z,
                                           "isotope", isonum);
}

const IsotopeData & IsotopeInfoFromSym(const std::string & sym, int isonum)
{
    return IsotopeInfoFromZ(AtomicZNumberFromSym(sym), isonum);
}

int MostCommonIsotopeFromZ(int Z)
{
    const AtomicData & ad = AtomicInfoFromZ(Z);
    if(ad.isotopes.size() == 0)
        throw exception::SystemException("Developer error: No isotopes for this Z number?",
                                           "Z", Z);

    auto maxit = std::max_element(ad.isotopes.begin(), ad.isotopes.end(),
                                  [](const IsotopeData & idat1, const IsotopeData & idat2)
                                    { return idat1.abund < idat2.abund; }
                                 );

    return maxit->isonum;
}

int MostCommonIsotopeFromSym(const std::string & sym)
{
    return MostCommonIsotopeFromZ(AtomicZNumberFromSym(sym));
}

double AtomicMassFromZ(int Z)
{
    return AtomicInfoFromZ(Z).mass;
}

double AtomicMassFromSym(const std::string & sym)
{
    return AtomicInfoFromSym(sym).mass;
}

double IsotopeMassFromZ(int Z, int isonum)
{
    return IsotopeInfoFromZ(Z, isonum).mass;
}

double IsotopeMassFromSym(const std::string & sym, int isonum)
{
    return IsotopeInfoFromSym(sym, isonum).mass;
}

std::string AtomicNameFromZ(int Z)
{
    return AtomicInfoFromZ(Z).name;
}

std::string AtomicNameFromSym(const std::string & sym)
{
    return AtomicInfoFromSym(sym).name;
}

int AtomicMultiplicityFromZ(int Z)
{
    return AtomicInfoFromZ(Z).multiplicity;
}

int AtomicMultiplicityFromSym(const std::string & sym)
{
    return AtomicInfoFromSym(sym).multiplicity;
}

double CovRadiusFromZ(int Z)
{
    return AtomicInfoFromZ(Z).covradius;
}

double CovRadiusFroSym(const std::string & sym)
{
    return AtomicInfoFromSym(sym).covradius;
}

double VDWRadiusFromZ(int Z)
{
    return AtomicInfoFromZ(Z).vdwradius;
}

double VDWRadiusFroSym(const std::string & sym)
{
    return AtomicInfoFromSym(sym).vdwradius;
}

} // closing namespace system
} // closing namespace pulsar

<|endoftext|>


<commit_before>/*********************************************************************************
 *
 * Inviwo - Interactive Visualization Workshop
 *
 * Copyright (c) 2012-2015 Inviwo Foundation
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 * 1. Redistributions of source code must retain the above copyright notice, this
 * list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright notice,
 * this list of conditions and the following disclaimer in the documentation
 * and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 *********************************************************************************/

#include <inviwo/core/network/processornetworkevaluator.h>
#include <inviwo/core/processors/canvasprocessor.h>
#include <inviwo/core/processors/progressbarowner.h>
#include <inviwo/core/util/assertion.h>
#include <inviwo/core/util/canvas.h>
#include <inviwo/core/util/rendercontext.h>

namespace inviwo {

std::map<ProcessorNetwork*,ProcessorNetworkEvaluator*> ProcessorNetworkEvaluator::processorNetworkEvaluators_;

ProcessorNetworkEvaluator::ProcessorNetworkEvaluator(ProcessorNetwork* processorNetwork)
    : processorNetwork_(processorNetwork)
    , evaulationQueued_(false)
    , evaluationDisabled_(false)
    , processorStatesDirty_(true) {

    initializeNetwork();

    ivwAssert(processorNetworkEvaluators_.find(processorNetwork) == processorNetworkEvaluators_.end() ,
              "A ProcessorNetworkEvaluator for the given ProcessorNetwork is already created");
    processorNetworkEvaluators_[processorNetwork] = this;
    processorNetwork_->addObserver(this);
}

ProcessorNetworkEvaluator::~ProcessorNetworkEvaluator() {
    std::map<ProcessorNetwork*,ProcessorNetworkEvaluator*>::iterator it = processorNetworkEvaluators_.find(processorNetwork_);

    if (it != processorNetworkEvaluators_.end())
        processorNetworkEvaluators_.erase(it);
}

void ProcessorNetworkEvaluator::topologyUpdated() {
    processorStatesDirty_ = true;
}

void ProcessorNetworkEvaluator::initializeNetwork() {
    ivwAssert(processorNetwork_!=0, "processorNetwork_ not initialized, call setProcessorNetwork()");
    // initialize network
    std::vector<Processor*> processors = processorNetwork_->getProcessors();

    for (size_t i=0; i<processors.size(); i++)
        if (!processors[i]->isInitialized())
            processors[i]->initialize();
}

void ProcessorNetworkEvaluator::saveSnapshotAllCanvases(std::string dir, std::string default_name, std::string ext) {
    std::vector<inviwo::CanvasProcessor*> pv = processorNetwork_->getProcessorsByType<inviwo::CanvasProcessor>();
    int i = 0;

    for (std::vector<inviwo::CanvasProcessor*>::iterator it = pv.begin(); it != pv.end(); it++) {
        std::stringstream ss;

        if (default_name == "" || default_name == "UPN")
            ss << (*it)->getIdentifier();
        else
            ss << default_name << i+1;

        std::string path(dir + ss.str() + ext);
        LogInfo("Saving canvas to: " + path);
        (*it)->saveImageLayer(path);
        ++i;
    }
}

void ProcessorNetworkEvaluator::setProcessorVisited(Processor* processor, bool visited) {
    ProcMapIt it = processorStates_.find(processor);
    if (it != processorStates_.end())
        it->second.visited = visited;
}

bool ProcessorNetworkEvaluator::hasBeenVisited(Processor* processor) const {
    const_ProcMapIt it = processorStates_.find(processor);
    if (it != processorStates_.end())
        return it->second.visited;
    else
        return false;
}

void ProcessorNetworkEvaluator::setPropertyVisited(Property* property, bool visited) {
    PropertyMapIt it = propertiesVisited_.find(property);
    if (it != propertiesVisited_.end())
        it->second.visited = visited;
}

bool ProcessorNetworkEvaluator::hasBeenVisited(Property* property) const {
    const_PropertyMapIt it = propertiesVisited_.find(property);
    if (it != propertiesVisited_.end())
        return it->second.visited;
    else
        return false;
}

const ProcessorNetworkEvaluator::ProcessorList&
ProcessorNetworkEvaluator::getStoredPredecessors(Processor* processor) const {
    const_ProcMapIt it = processorStates_.find(processor);
    if (it != processorStates_.end()) {
        return it->second.pred;
    }
    else {
        // processor not found, return reference to empty list of dummy element
        return processorStates_.find(nullptr)->second.pred;
    }
}

ProcessorNetworkEvaluator::ProcessorList ProcessorNetworkEvaluator::getDirectPredecessors(Processor* processor, Event* event) const {
    ProcessorList predecessors;
    const std::vector<Inport*>& inports = processor->getInports(event);

    for (std::vector<Inport*>::const_iterator portIt = inports.begin(), portItEnd = inports.end(); portIt!=portItEnd; ++portIt) {
        if (!(*portIt)->isConnected())
            continue;

        const std::vector<Outport*>& connectedOutPorts = (*portIt)->getConnectedOutports();

        for (std::vector<Outport*>::const_iterator connectedPortIt = connectedOutPorts.begin(),
             connectedPortItEnd = connectedOutPorts.end();
             connectedPortIt!=connectedPortItEnd; ++connectedPortIt)
            if(*connectedPortIt)
                predecessors.insert((*connectedPortIt)->getProcessor());
    }

    return predecessors;
}

void ProcessorNetworkEvaluator::traversePredecessors(Processor* processor) {
    if (!hasBeenVisited(processor)) {
        setProcessorVisited(processor);

        const ProcessorList &directPredecessors = getStoredPredecessors(processor);
        ProcessorList::const_iterator it = directPredecessors.begin();
        while (it != directPredecessors.end()) {
            traversePredecessors(*it);
            ++it;
        }
        processorsSorted_.push_back(processor);
    }
}

void ProcessorNetworkEvaluator::determineProcessingOrder() {
    std::vector<Processor*> processors = processorNetwork_->getProcessors();
    std::vector<Processor*> endProcessors;

    for (size_t i=0; i<processors.size(); i++)
        if (processors[i]->isEndProcessor())
            endProcessors.push_back(processors[i]);

    // perform topological sorting and store processor order
    // in processorsSorted_
    processorsSorted_.clear();
    resetProcessorVisitedStates();

    for (size_t i=0; i<endProcessors.size(); i++)
        traversePredecessors(endProcessors[i]);
}

void ProcessorNetworkEvaluator::updateProcessorStates() {
    std::vector<Processor*> processors = processorNetwork_->getProcessors();
    std::vector<Processor*> endProcessors;

    processorStates_.clear();
    // insert dummy processor to be able to return a reference to an
    // empty predecessor list, if a processor does not exist (getStoredPredecessors())
    processorStates_.insert(ProcMapPair(nullptr, ProcessorState()));

    // update all processor states, i.e. collecting predecessors
    std::vector<Processor*>::const_iterator it = processors.begin();
    while (it != processors.end()) {
        // register processor in global state map
        if (!processorStates_.insert(ProcMapPair(*it, ProcessorState(getDirectPredecessors(*it)))).second)
            LogError("Processor State was already registered.");

        if ((*it)->isEndProcessor())
            endProcessors.push_back(*it);
        ++it;
    }

    // perform topological sorting and store processor order in processorsSorted_
    processorsSorted_.clear();
    it = endProcessors.begin();
    while (it != endProcessors.end()) {
        traversePredecessors(*it);
        ++it;
    }
}

void ProcessorNetworkEvaluator::resetProcessorVisitedStates() {
    ProcMapIt it = processorStates_.begin();
    while (it != processorStates_.end()) {
        it->second.visited = false;
        ++it;
    }
}

void ProcessorNetworkEvaluator::propagateInteractionEventImpl(Processor* processor,
                                                              InteractionEvent* event) {
    if (!hasBeenVisited(processor)) {
        processor->invokeInteractionEvent(event);
        setProcessorVisited(processor);
        if (event->hasBeenUsed()) return;

        ProcessorList directPredecessors = getDirectPredecessors(processor, event);

        for (ProcessorList::iterator it = directPredecessors.begin(),
             itEnd = directPredecessors.end();
             it != itEnd; ++it) {
            propagateInteractionEventImpl(*it, event);
            if (event->hasBeenUsed()) return;
        }
    }
}

void ProcessorNetworkEvaluator::propagateInteractionEvent(Processor* processor,
                                                          InteractionEvent* event) {
    resetProcessorVisitedStates();
    processorNetwork_->lock();
    propagateInteractionEventImpl(processor, event);
    processorNetwork_->unlock();
}

bool ProcessorNetworkEvaluator::isPortConnectedToProcessor(Port* port, Processor* processor) {
    bool isConnected = false;
    std::vector<PortConnection*> portConnections = processorNetwork_->getConnections();
    std::vector<Outport*> outports = processor->getOutports();

    for (size_t i=0; i<outports.size(); i++) {
        for (size_t j=0; j<portConnections.size(); j++) {
            const Port* curOutport = portConnections[j]->getOutport();

            if (curOutport == outports[i]) {
                const Port* connectedInport = portConnections[j]->getInport();

                if (connectedInport == port) {
                    isConnected = true;
                    break;
                }
            }
        }
    }

    if (isConnected) return isConnected;

    std::vector<Inport*> inports = processor->getInports();

    for (size_t i=0; i<inports.size(); i++) {
        for (size_t j=0; j<portConnections.size(); j++) {
            const Port* curInport = portConnections[j]->getInport();

            if (curInport == inports[i]) {
                const Outport* connectedOutport = portConnections[j]->getOutport();

                if (connectedOutport == port) {
                    isConnected = true;
                    break;
                }
            }
        }
    }

    return isConnected;
}

void ProcessorNetworkEvaluator::onProcessorInvalidationEnd(Processor* p) {
    processorNetwork_->onProcessorInvalidationEnd(p);
    p->ProcessorObservable::removeObserver(this);

    if (evaulationQueued_) {
        evaulationQueued_ = false;
        requestEvaluate();
    }
}

void ProcessorNetworkEvaluator::onProcessorNetworkEvaluateRequest() {
    //Direct request, thus we don't want to queue the evaluation anymore
    if (evaulationQueued_)
        evaulationQueued_ = false;

    requestEvaluate();
}

void ProcessorNetworkEvaluator::onProcessorNetworkUnlocked() {
    // Only evaluate if an evaluation is queued or the network is modified
    if (evaulationQueued_ || processorNetwork_->isModified()) {
        evaulationQueued_ = false;
        requestEvaluate();
    }
}

void ProcessorNetworkEvaluator::disableEvaluation() {
    evaluationDisabled_ = true;
}

void ProcessorNetworkEvaluator::enableEvaluation() {
    evaluationDisabled_ = false;

    if (evaulationQueued_) {
        evaulationQueued_ = false;
        requestEvaluate();
    }
}

ProcessorNetworkEvaluator*
ProcessorNetworkEvaluator::getProcessorNetworkEvaluatorForProcessorNetwork(
    ProcessorNetwork* network) {
    std::map<ProcessorNetwork*, ProcessorNetworkEvaluator*>::iterator it =
        processorNetworkEvaluators_.find(network);

    if (it == processorNetworkEvaluators_.end()) return new ProcessorNetworkEvaluator(network);

    return it->second;
}

void ProcessorNetworkEvaluator::requestEvaluate() {
    // evaluation has been triggered but is currently queued
    // requestEvaluate needs to be called with evaulationQueued_ false to continue.
    if (evaulationQueued_) return;

    // wait for linking to finish
    if (processorNetwork_->isLinking()) {
        evaulationQueued_ = true;
        return;
    }

    // evaluation disabled
    if (processorNetwork_->islocked() || evaluationDisabled_) {
        evaulationQueued_ = true;
        return;
    }

    // wait for invalidation to finish before evaluating
    if (processorNetwork_->isInvalidating()) {
        evaulationQueued_ = true;
        return;
    }

    evaulationQueued_ = false;
    //if we haven't returned yet, perform evaluation of the network
    evaluate();
}

void ProcessorNetworkEvaluator::evaluate() {
    // lock processor network to avoid concurrent evaluation
    processorNetwork_->lock();
    RenderContext::getPtr()->activateDefaultRenderContext();

    // if the processor network has changed determine the new processor order
    if (processorNetwork_->isModified()) {
        initializeNetwork();
        processorNetwork_->setModified(false);
        processorStatesDirty_ = true;
    }

    if (processorStatesDirty_) {
        // network topology has changed, update internal processor states
        updateProcessorStates();
    }

    for (auto processor : processorsSorted_) {
        if (!processor->isValid()) {
            if (processor->isReady()) {
                // re-initialize resources (e.g., shaders) if necessary
                if (processor->getInvalidationLevel() >= INVALID_RESOURCES)
                    processor->initializeResources();

                // call onChange for all invalid inports
                for (auto inport : processor->getInports()) {
                    inport->callOnChangeIfChanged();
                }

                #if IVW_PROFILING
                processor->notifyObserversAboutToProcess(processor);
                #endif

                try {
                    // do the actual processing
                    processor->process();
                } catch (Exception& e) {
                    LogError(e.getMessage());
                }
                // set processor as valid
                processor->setValid();

                #if IVW_PROFILING
                processor->notifyObserversFinishedProcess(processor);
                #endif
            } else {
                processor->doIfNotReady();
            }
        }
    }
    resetProcessorVisitedStates();

    // unlock processor network to allow next evaluation
    processorNetwork_->unlock();
}

} // namespace
<commit_msg>Core: ProcessorNetworkEvaluator, catch exceptions from initializeResources and callOnChangeIfChanged<commit_after>/*********************************************************************************
 *
 * Inviwo - Interactive Visualization Workshop
 *
 * Copyright (c) 2012-2015 Inviwo Foundation
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 * 1. Redistributions of source code must retain the above copyright notice, this
 * list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright notice,
 * this list of conditions and the following disclaimer in the documentation
 * and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 *********************************************************************************/

#include <inviwo/core/network/processornetworkevaluator.h>
#include <inviwo/core/processors/canvasprocessor.h>
#include <inviwo/core/processors/progressbarowner.h>
#include <inviwo/core/util/assertion.h>
#include <inviwo/core/util/canvas.h>
#include <inviwo/core/util/rendercontext.h>

namespace inviwo {

std::map<ProcessorNetwork*,ProcessorNetworkEvaluator*> ProcessorNetworkEvaluator::processorNetworkEvaluators_;

ProcessorNetworkEvaluator::ProcessorNetworkEvaluator(ProcessorNetwork* processorNetwork)
    : processorNetwork_(processorNetwork)
    , evaulationQueued_(false)
    , evaluationDisabled_(false)
    , processorStatesDirty_(true) {

    initializeNetwork();

    ivwAssert(processorNetworkEvaluators_.find(processorNetwork) == processorNetworkEvaluators_.end() ,
              "A ProcessorNetworkEvaluator for the given ProcessorNetwork is already created");
    processorNetworkEvaluators_[processorNetwork] = this;
    processorNetwork_->addObserver(this);
}

ProcessorNetworkEvaluator::~ProcessorNetworkEvaluator() {
    std::map<ProcessorNetwork*,ProcessorNetworkEvaluator*>::iterator it = processorNetworkEvaluators_.find(processorNetwork_);

    if (it != processorNetworkEvaluators_.end())
        processorNetworkEvaluators_.erase(it);
}

void ProcessorNetworkEvaluator::topologyUpdated() {
    processorStatesDirty_ = true;
}

void ProcessorNetworkEvaluator::initializeNetwork() {
    ivwAssert(processorNetwork_!=0, "processorNetwork_ not initialized, call setProcessorNetwork()");
    // initialize network
    std::vector<Processor*> processors = processorNetwork_->getProcessors();

    for (size_t i=0; i<processors.size(); i++)
        if (!processors[i]->isInitialized())
            processors[i]->initialize();
}

void ProcessorNetworkEvaluator::saveSnapshotAllCanvases(std::string dir, std::string default_name, std::string ext) {
    std::vector<inviwo::CanvasProcessor*> pv = processorNetwork_->getProcessorsByType<inviwo::CanvasProcessor>();
    int i = 0;

    for (std::vector<inviwo::CanvasProcessor*>::iterator it = pv.begin(); it != pv.end(); it++) {
        std::stringstream ss;

        if (default_name == "" || default_name == "UPN")
            ss << (*it)->getIdentifier();
        else
            ss << default_name << i+1;

        std::string path(dir + ss.str() + ext);
        LogInfo("Saving canvas to: " + path);
        (*it)->saveImageLayer(path);
        ++i;
    }
}

void ProcessorNetworkEvaluator::setProcessorVisited(Processor* processor, bool visited) {
    ProcMapIt it = processorStates_.find(processor);
    if (it != processorStates_.end())
        it->second.visited = visited;
}

bool ProcessorNetworkEvaluator::hasBeenVisited(Processor* processor) const {
    const_ProcMapIt it = processorStates_.find(processor);
    if (it != processorStates_.end())
        return it->second.visited;
    else
        return false;
}

void ProcessorNetworkEvaluator::setPropertyVisited(Property* property, bool visited) {
    PropertyMapIt it = propertiesVisited_.find(property);
    if (it != propertiesVisited_.end())
        it->second.visited = visited;
}

bool ProcessorNetworkEvaluator::hasBeenVisited(Property* property) const {
    const_PropertyMapIt it = propertiesVisited_.find(property);
    if (it != propertiesVisited_.end())
        return it->second.visited;
    else
        return false;
}

const ProcessorNetworkEvaluator::ProcessorList&
ProcessorNetworkEvaluator::getStoredPredecessors(Processor* processor) const {
    const_ProcMapIt it = processorStates_.find(processor);
    if (it != processorStates_.end()) {
        return it->second.pred;
    }
    else {
        // processor not found, return reference to empty list of dummy element
        return processorStates_.find(nullptr)->second.pred;
    }
}

ProcessorNetworkEvaluator::ProcessorList ProcessorNetworkEvaluator::getDirectPredecessors(Processor* processor, Event* event) const {
    ProcessorList predecessors;
    const std::vector<Inport*>& inports = processor->getInports(event);

    for (std::vector<Inport*>::const_iterator portIt = inports.begin(), portItEnd = inports.end(); portIt!=portItEnd; ++portIt) {
        if (!(*portIt)->isConnected())
            continue;

        const std::vector<Outport*>& connectedOutPorts = (*portIt)->getConnectedOutports();

        for (std::vector<Outport*>::const_iterator connectedPortIt = connectedOutPorts.begin(),
             connectedPortItEnd = connectedOutPorts.end();
             connectedPortIt!=connectedPortItEnd; ++connectedPortIt)
            if(*connectedPortIt)
                predecessors.insert((*connectedPortIt)->getProcessor());
    }

    return predecessors;
}

void ProcessorNetworkEvaluator::traversePredecessors(Processor* processor) {
    if (!hasBeenVisited(processor)) {
        setProcessorVisited(processor);

        const ProcessorList &directPredecessors = getStoredPredecessors(processor);
        ProcessorList::const_iterator it = directPredecessors.begin();
        while (it != directPredecessors.end()) {
            traversePredecessors(*it);
            ++it;
        }
        processorsSorted_.push_back(processor);
    }
}

void ProcessorNetworkEvaluator::determineProcessingOrder() {
    std::vector<Processor*> processors = processorNetwork_->getProcessors();
    std::vector<Processor*> endProcessors;

    for (size_t i=0; i<processors.size(); i++)
        if (processors[i]->isEndProcessor())
            endProcessors.push_back(processors[i]);

    // perform topological sorting and store processor order
    // in processorsSorted_
    processorsSorted_.clear();
    resetProcessorVisitedStates();

    for (size_t i=0; i<endProcessors.size(); i++)
        traversePredecessors(endProcessors[i]);
}

void ProcessorNetworkEvaluator::updateProcessorStates() {
    std::vector<Processor*> processors = processorNetwork_->getProcessors();
    std::vector<Processor*> endProcessors;

    processorStates_.clear();
    // insert dummy processor to be able to return a reference to an
    // empty predecessor list, if a processor does not exist (getStoredPredecessors())
    processorStates_.insert(ProcMapPair(nullptr, ProcessorState()));

    // update all processor states, i.e. collecting predecessors
    std::vector<Processor*>::const_iterator it = processors.begin();
    while (it != processors.end()) {
        // register processor in global state map
        if (!processorStates_.insert(ProcMapPair(*it, ProcessorState(getDirectPredecessors(*it)))).second)
            LogError("Processor State was already registered.");

        if ((*it)->isEndProcessor())
            endProcessors.push_back(*it);
        ++it;
    }

    // perform topological sorting and store processor order in processorsSorted_
    processorsSorted_.clear();
    it = endProcessors.begin();
    while (it != endProcessors.end()) {
        traversePredecessors(*it);
        ++it;
    }
}

void ProcessorNetworkEvaluator::resetProcessorVisitedStates() {
    ProcMapIt it = processorStates_.begin();
    while (it != processorStates_.end()) {
        it->second.visited = false;
        ++it;
    }
}

void ProcessorNetworkEvaluator::propagateInteractionEventImpl(Processor* processor,
                                                              InteractionEvent* event) {
    if (!hasBeenVisited(processor)) {
        processor->invokeInteractionEvent(event);
        setProcessorVisited(processor);
        if (event->hasBeenUsed()) return;

        ProcessorList directPredecessors = getDirectPredecessors(processor, event);

        for (ProcessorList::iterator it = directPredecessors.begin(),
             itEnd = directPredecessors.end();
             it != itEnd; ++it) {
            propagateInteractionEventImpl(*it, event);
            if (event->hasBeenUsed()) return;
        }
    }
}

void ProcessorNetworkEvaluator::propagateInteractionEvent(Processor* processor,
                                                          InteractionEvent* event) {
    resetProcessorVisitedStates();
    processorNetwork_->lock();
    propagateInteractionEventImpl(processor, event);
    processorNetwork_->unlock();
}

bool ProcessorNetworkEvaluator::isPortConnectedToProcessor(Port* port, Processor* processor) {
    bool isConnected = false;
    std::vector<PortConnection*> portConnections = processorNetwork_->getConnections();
    std::vector<Outport*> outports = processor->getOutports();

    for (size_t i=0; i<outports.size(); i++) {
        for (size_t j=0; j<portConnections.size(); j++) {
            const Port* curOutport = portConnections[j]->getOutport();

            if (curOutport == outports[i]) {
                const Port* connectedInport = portConnections[j]->getInport();

                if (connectedInport == port) {
                    isConnected = true;
                    break;
                }
            }
        }
    }

    if (isConnected) return isConnected;

    std::vector<Inport*> inports = processor->getInports();

    for (size_t i=0; i<inports.size(); i++) {
        for (size_t j=0; j<portConnections.size(); j++) {
            const Port* curInport = portConnections[j]->getInport();

            if (curInport == inports[i]) {
                const Outport* connectedOutport = portConnections[j]->getOutport();

                if (connectedOutport == port) {
                    isConnected = true;
                    break;
                }
            }
        }
    }

    return isConnected;
}

void ProcessorNetworkEvaluator::onProcessorInvalidationEnd(Processor* p) {
    processorNetwork_->onProcessorInvalidationEnd(p);
    p->ProcessorObservable::removeObserver(this);

    if (evaulationQueued_) {
        evaulationQueued_ = false;
        requestEvaluate();
    }
}

void ProcessorNetworkEvaluator::onProcessorNetworkEvaluateRequest() {
    //Direct request, thus we don't want to queue the evaluation anymore
    if (evaulationQueued_)
        evaulationQueued_ = false;

    requestEvaluate();
}

void ProcessorNetworkEvaluator::onProcessorNetworkUnlocked() {
    // Only evaluate if an evaluation is queued or the network is modified
    if (evaulationQueued_ || processorNetwork_->isModified()) {
        evaulationQueued_ = false;
        requestEvaluate();
    }
}

void ProcessorNetworkEvaluator::disableEvaluation() {
    evaluationDisabled_ = true;
}

void ProcessorNetworkEvaluator::enableEvaluation() {
    evaluationDisabled_ = false;

    if (evaulationQueued_) {
        evaulationQueued_ = false;
        requestEvaluate();
    }
}

ProcessorNetworkEvaluator*
ProcessorNetworkEvaluator::getProcessorNetworkEvaluatorForProcessorNetwork(
    ProcessorNetwork* network) {
    std::map<ProcessorNetwork*, ProcessorNetworkEvaluator*>::iterator it =
        processorNetworkEvaluators_.find(network);

    if (it == processorNetworkEvaluators_.end()) return new ProcessorNetworkEvaluator(network);

    return it->second;
}

void ProcessorNetworkEvaluator::requestEvaluate() {
    // evaluation has been triggered but is currently queued
    // requestEvaluate needs to be called with evaulationQueued_ false to continue.
    if (evaulationQueued_) return;

    // wait for linking to finish
    if (processorNetwork_->isLinking()) {
        evaulationQueued_ = true;
        return;
    }

    // evaluation disabled
    if (processorNetwork_->islocked() || evaluationDisabled_) {
        evaulationQueued_ = true;
        return;
    }

    // wait for invalidation to finish before evaluating
    if (processorNetwork_->isInvalidating()) {
        evaulationQueued_ = true;
        return;
    }

    evaulationQueued_ = false;
    //if we haven't returned yet, perform evaluation of the network
    evaluate();
}

void ProcessorNetworkEvaluator::evaluate() {
    // lock processor network to avoid concurrent evaluation
    processorNetwork_->lock();
    RenderContext::getPtr()->activateDefaultRenderContext();

    // if the processor network has changed determine the new processor order
    if (processorNetwork_->isModified()) {
        initializeNetwork();
        processorNetwork_->setModified(false);
        processorStatesDirty_ = true;
    }

    if (processorStatesDirty_) {
        // network topology has changed, update internal processor states
        updateProcessorStates();
    }

    for (auto processor : processorsSorted_) {
        if (!processor->isValid()) {
            if (processor->isReady()) {
                try {
                    // re-initialize resources (e.g., shaders) if necessary
                    if (processor->getInvalidationLevel() >= INVALID_RESOURCES) {
                        processor->initializeResources();
                    }
                    // call onChange for all invalid inports
                    for (auto inport : processor->getInports()) {
                        inport->callOnChangeIfChanged();
                    }
                } catch (Exception& e) {
                    LogError(e.getMessage());
                    processor->setValid();
                    continue;
                }

                #if IVW_PROFILING
                processor->notifyObserversAboutToProcess(processor);
                #endif

                try {
                    // do the actual processing
                    processor->process();
                } catch (Exception& e) {
                    LogError(e.getMessage());
                }
                // set processor as valid
                processor->setValid();

                #if IVW_PROFILING
                processor->notifyObserversFinishedProcess(processor);
                #endif
            } else {
                processor->doIfNotReady();
            }
        }
    }
    resetProcessorVisitedStates();

    // unlock processor network to allow next evaluation
    processorNetwork_->unlock();
}

} // namespace
<|endoftext|>


<commit_before>// Copyright (c) 2013 GitHub, Inc.
// Use of this source code is governed by the MIT license that can be
// found in the LICENSE file.

#include "shell/common/platform_util.h"

#include <windows.h>  // windows.h must be included first

#include <atlbase.h>
#include <comdef.h>
#include <commdlg.h>
#include <dwmapi.h>
#include <objbase.h>
#include <shellapi.h>
#include <shlobj.h>
#include <wrl/client.h>

#include "base/bind.h"
#include "base/bind_helpers.h"
#include "base/files/file_path.h"
#include "base/files/file_util.h"
#include "base/logging.h"
#include "base/stl_util.h"
#include "base/strings/string_util.h"
#include "base/strings/utf_string_conversions.h"
#include "base/task/post_task.h"
#include "base/task/thread_pool.h"
#include "base/threading/scoped_blocking_call.h"
#include "base/win/registry.h"
#include "base/win/scoped_co_mem.h"
#include "base/win/scoped_com_initializer.h"
#include "base/win/windows_version.h"
#include "content/public/browser/browser_task_traits.h"
#include "content/public/browser/browser_thread.h"
#include "ui/base/win/shell.h"
#include "url/gurl.h"

namespace {

// Required COM implementation of IFileOperationProgressSink so we can
// precheck files before deletion to make sure they can be move to the
// Recycle Bin.
class DeleteFileProgressSink : public IFileOperationProgressSink {
 public:
  DeleteFileProgressSink();
  virtual ~DeleteFileProgressSink() = default;

 private:
  ULONG STDMETHODCALLTYPE AddRef(void) override;
  ULONG STDMETHODCALLTYPE Release(void) override;
  HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid,
                                           LPVOID* ppvObj) override;
  HRESULT STDMETHODCALLTYPE StartOperations(void) override;
  HRESULT STDMETHODCALLTYPE FinishOperations(HRESULT) override;
  HRESULT STDMETHODCALLTYPE PreRenameItem(DWORD, IShellItem*, LPCWSTR) override;
  HRESULT STDMETHODCALLTYPE
  PostRenameItem(DWORD, IShellItem*, LPCWSTR, HRESULT, IShellItem*) override;
  HRESULT STDMETHODCALLTYPE PreMoveItem(DWORD,
                                        IShellItem*,
                                        IShellItem*,
                                        LPCWSTR) override;
  HRESULT STDMETHODCALLTYPE PostMoveItem(DWORD,
                                         IShellItem*,
                                         IShellItem*,
                                         LPCWSTR,
                                         HRESULT,
                                         IShellItem*) override;
  HRESULT STDMETHODCALLTYPE PreCopyItem(DWORD,
                                        IShellItem*,
                                        IShellItem*,
                                        LPCWSTR) override;
  HRESULT STDMETHODCALLTYPE PostCopyItem(DWORD,
                                         IShellItem*,
                                         IShellItem*,
                                         LPCWSTR,
                                         HRESULT,
                                         IShellItem*) override;
  HRESULT STDMETHODCALLTYPE PreDeleteItem(DWORD, IShellItem*) override;
  HRESULT STDMETHODCALLTYPE PostDeleteItem(DWORD,
                                           IShellItem*,
                                           HRESULT,
                                           IShellItem*) override;
  HRESULT STDMETHODCALLTYPE PreNewItem(DWORD, IShellItem*, LPCWSTR) override;
  HRESULT STDMETHODCALLTYPE PostNewItem(DWORD,
                                        IShellItem*,
                                        LPCWSTR,
                                        LPCWSTR,
                                        DWORD,
                                        HRESULT,
                                        IShellItem*) override;
  HRESULT STDMETHODCALLTYPE UpdateProgress(UINT, UINT) override;
  HRESULT STDMETHODCALLTYPE ResetTimer(void) override;
  HRESULT STDMETHODCALLTYPE PauseTimer(void) override;
  HRESULT STDMETHODCALLTYPE ResumeTimer(void) override;

  ULONG m_cRef;
};

DeleteFileProgressSink::DeleteFileProgressSink() {
  m_cRef = 0;
}

HRESULT DeleteFileProgressSink::PreDeleteItem(DWORD dwFlags, IShellItem*) {
  if (!(dwFlags & TSF_DELETE_RECYCLE_IF_POSSIBLE)) {
    // TSF_DELETE_RECYCLE_IF_POSSIBLE will not be set for items that cannot be
    // recycled.  In this case, we abort the delete operation.  This bubbles
    // up and stops the Delete in IFileOperation.
    return E_ABORT;
  }
  // Returns S_OK if successful, or an error value otherwise. In the case of an
  // error value, the delete operation and all subsequent operations pending
  // from the call to IFileOperation are canceled.
  return S_OK;
}

HRESULT DeleteFileProgressSink::QueryInterface(REFIID riid, LPVOID* ppvObj) {
  // Always set out parameter to NULL, validating it first.
  if (!ppvObj)
    return E_INVALIDARG;
  *ppvObj = nullptr;
  if (riid == IID_IUnknown || riid == IID_IFileOperationProgressSink) {
    // Increment the reference count and return the pointer.
    *ppvObj = reinterpret_cast<IUnknown*>(this);
    AddRef();
    return NOERROR;
  }
  return E_NOINTERFACE;
}

ULONG DeleteFileProgressSink::AddRef() {
  InterlockedIncrement(&m_cRef);
  return m_cRef;
}

ULONG DeleteFileProgressSink::Release() {
  // Decrement the object's internal counter.
  ULONG ulRefCount = InterlockedDecrement(&m_cRef);
  if (0 == m_cRef) {
    delete this;
  }
  return ulRefCount;
}

HRESULT DeleteFileProgressSink::StartOperations() {
  return S_OK;
}

HRESULT DeleteFileProgressSink::FinishOperations(HRESULT) {
  return S_OK;
}

HRESULT DeleteFileProgressSink::PreRenameItem(DWORD, IShellItem*, LPCWSTR) {
  return S_OK;
}

HRESULT DeleteFileProgressSink::PostRenameItem(DWORD,
                                               IShellItem*,
                                               __RPC__in_string LPCWSTR,
                                               HRESULT,
                                               IShellItem*) {
  return E_NOTIMPL;
}

HRESULT DeleteFileProgressSink::PreMoveItem(DWORD,
                                            IShellItem*,
                                            IShellItem*,
                                            LPCWSTR) {
  return E_NOTIMPL;
}

HRESULT DeleteFileProgressSink::PostMoveItem(DWORD,
                                             IShellItem*,
                                             IShellItem*,
                                             LPCWSTR,
                                             HRESULT,
                                             IShellItem*) {
  return E_NOTIMPL;
}

HRESULT DeleteFileProgressSink::PreCopyItem(DWORD,
                                            IShellItem*,
                                            IShellItem*,
                                            LPCWSTR) {
  return E_NOTIMPL;
}

HRESULT DeleteFileProgressSink::PostCopyItem(DWORD,
                                             IShellItem*,
                                             IShellItem*,
                                             LPCWSTR,
                                             HRESULT,
                                             IShellItem*) {
  return E_NOTIMPL;
}

HRESULT DeleteFileProgressSink::PostDeleteItem(DWORD,
                                               IShellItem*,
                                               HRESULT,
                                               IShellItem*) {
  return S_OK;
}

HRESULT DeleteFileProgressSink::PreNewItem(DWORD dwFlags,
                                           IShellItem*,
                                           LPCWSTR) {
  return E_NOTIMPL;
}

HRESULT DeleteFileProgressSink::PostNewItem(DWORD,
                                            IShellItem*,
                                            LPCWSTR,
                                            LPCWSTR,
                                            DWORD,
                                            HRESULT,
                                            IShellItem*) {
  return E_NOTIMPL;
}

HRESULT DeleteFileProgressSink::UpdateProgress(UINT, UINT) {
  return S_OK;
}

HRESULT DeleteFileProgressSink::ResetTimer() {
  return S_OK;
}

HRESULT DeleteFileProgressSink::PauseTimer() {
  return S_OK;
}

HRESULT DeleteFileProgressSink::ResumeTimer() {
  return S_OK;
}

std::string OpenExternalOnWorkerThread(
    const GURL& url,
    const platform_util::OpenExternalOptions& options) {
  base::ScopedBlockingCall scoped_blocking_call(FROM_HERE,
                                                base::BlockingType::MAY_BLOCK);
  // Quote the input scheme to be sure that the command does not have
  // parameters unexpected by the external program. This url should already
  // have been escaped.
  base::string16 escaped_url = L"\"" + base::UTF8ToUTF16(url.spec()) + L"\"";
  base::string16 working_dir = options.working_dir.value();

  if (reinterpret_cast<ULONG_PTR>(
          ShellExecuteW(nullptr, L"open", escaped_url.c_str(), nullptr,
                        working_dir.empty() ? nullptr : working_dir.c_str(),
                        SW_SHOWNORMAL)) <= 32) {
    return "Failed to open";
  }
  return "";
}

void ShowItemInFolderOnWorkerThread(const base::FilePath& full_path) {
  base::ScopedBlockingCall scoped_blocking_call(FROM_HERE,
                                                base::BlockingType::MAY_BLOCK);
  base::win::ScopedCOMInitializer com_initializer;
  if (!com_initializer.Succeeded())
    return;

  base::FilePath dir = full_path.DirName().AsEndingWithSeparator();
  // ParseDisplayName will fail if the directory is "C:", it must be "C:\\".
  if (dir.empty())
    return;

  Microsoft::WRL::ComPtr<IShellFolder> desktop;
  HRESULT hr = SHGetDesktopFolder(desktop.GetAddressOf());
  if (FAILED(hr))
    return;

  base::win::ScopedCoMem<ITEMIDLIST> dir_item;
  hr = desktop->ParseDisplayName(NULL, NULL,
                                 const_cast<wchar_t*>(dir.value().c_str()),
                                 NULL, &dir_item, NULL);
  if (FAILED(hr))
    return;

  base::win::ScopedCoMem<ITEMIDLIST> file_item;
  hr = desktop->ParseDisplayName(
      NULL, NULL, const_cast<wchar_t*>(full_path.value().c_str()), NULL,
      &file_item, NULL);
  if (FAILED(hr))
    return;

  const ITEMIDLIST* highlight[] = {file_item};
  hr = SHOpenFolderAndSelectItems(dir_item, base::size(highlight), highlight,
                                  NULL);
  if (FAILED(hr)) {
    // On some systems, the above call mysteriously fails with "file not
    // found" even though the file is there.  In these cases, ShellExecute()
    // seems to work as a fallback (although it won't select the file).
    if (hr == ERROR_FILE_NOT_FOUND) {
      ShellExecute(NULL, L"open", dir.value().c_str(), NULL, NULL, SW_SHOW);
    } else {
      LOG(WARNING) << " " << __func__ << "(): Can't open full_path = \""
                   << full_path.value() << "\""
                   << " hr = " << logging::SystemErrorCodeToString(hr);
    }
  }
}

std::string OpenPathOnThread(const base::FilePath& full_path) {
  // May result in an interactive dialog.
  base::ScopedBlockingCall scoped_blocking_call(FROM_HERE,
                                                base::BlockingType::MAY_BLOCK);
  bool success;
  if (base::DirectoryExists(full_path))
    success = ui::win::OpenFolderViaShell(full_path);
  else
    success = ui::win::OpenFileViaShell(full_path);

  return success ? "" : "Failed to open path";
}

}  // namespace

namespace platform_util {

void ShowItemInFolder(const base::FilePath& full_path) {
  base::ThreadPool::CreateSingleThreadTaskRunner(
      {base::MayBlock(), base::TaskPriority::USER_BLOCKING})
      ->PostTask(FROM_HERE,
                 base::BindOnce(&ShowItemInFolderOnWorkerThread, full_path));
}

void OpenPath(const base::FilePath& full_path, OpenCallback callback) {
  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);

  base::PostTaskAndReplyWithResult(
      base::ThreadPool::CreateCOMSTATaskRunner(
          {base::MayBlock(), base::TaskPriority::USER_BLOCKING})
          .get(),
      FROM_HERE, base::BindOnce(&OpenPathOnThread, full_path),
      std::move(callback));
}

void OpenExternal(const GURL& url,
                  const OpenExternalOptions& options,
                  OpenCallback callback) {
  base::PostTaskAndReplyWithResult(
      base::ThreadPool::CreateCOMSTATaskRunner(
          {base::MayBlock(), base::TaskPriority::USER_BLOCKING})
          .get(),
      FROM_HERE, base::BindOnce(&OpenExternalOnWorkerThread, url, options),
      std::move(callback));
}

bool MoveItemToTrash(const base::FilePath& path, bool delete_on_fail) {
  base::win::ScopedCOMInitializer com_initializer;
  if (!com_initializer.Succeeded())
    return false;

  Microsoft::WRL::ComPtr<IFileOperation> pfo;
  if (FAILED(::CoCreateInstance(CLSID_FileOperation, nullptr, CLSCTX_ALL,
                                IID_PPV_ARGS(&pfo))))
    return false;

  // Elevation prompt enabled for UAC protected files.  This overrides the
  // SILENT, NO_UI and NOERRORUI flags.

  if (base::win::GetVersion() >= base::win::Version::WIN8) {
    // Windows 8 introduces the flag RECYCLEONDELETE and deprecates the
    // ALLOWUNDO in favor of ADDUNDORECORD.
    if (FAILED(pfo->SetOperationFlags(
            FOF_NO_UI | FOFX_ADDUNDORECORD | FOF_NOERRORUI | FOF_SILENT |
            FOFX_SHOWELEVATIONPROMPT | FOFX_RECYCLEONDELETE)))
      return false;
  } else {
    // For Windows 7 and Vista, RecycleOnDelete is the default behavior.
    if (FAILED(pfo->SetOperationFlags(FOF_NO_UI | FOF_ALLOWUNDO |
                                      FOF_NOERRORUI | FOF_SILENT |
                                      FOFX_SHOWELEVATIONPROMPT)))
      return false;
  }

  // Create an IShellItem from the supplied source path.
  Microsoft::WRL::ComPtr<IShellItem> delete_item;
  if (FAILED(SHCreateItemFromParsingName(
          path.value().c_str(), NULL,
          IID_PPV_ARGS(delete_item.GetAddressOf()))))
    return false;

  Microsoft::WRL::ComPtr<IFileOperationProgressSink> delete_sink(
      new DeleteFileProgressSink);
  if (!delete_sink)
    return false;

  // Processes the queued command DeleteItem. This will trigger
  // the DeleteFileProgressSink to check for Recycle Bin.
  return SUCCEEDED(pfo->DeleteItem(delete_item.Get(), delete_sink.Get())) &&
         SUCCEEDED(pfo->PerformOperations());
}

void Beep() {
  MessageBeep(MB_OK);
}

}  // namespace platform_util
<commit_msg>chore: ShowItemInFolder should use COMSTA (#22614)<commit_after>// Copyright (c) 2013 GitHub, Inc.
// Use of this source code is governed by the MIT license that can be
// found in the LICENSE file.

#include "shell/common/platform_util.h"

#include <windows.h>  // windows.h must be included first

#include <atlbase.h>
#include <comdef.h>
#include <commdlg.h>
#include <dwmapi.h>
#include <objbase.h>
#include <shellapi.h>
#include <shlobj.h>
#include <wrl/client.h>

#include "base/bind.h"
#include "base/bind_helpers.h"
#include "base/files/file_path.h"
#include "base/files/file_util.h"
#include "base/logging.h"
#include "base/stl_util.h"
#include "base/strings/string_util.h"
#include "base/strings/utf_string_conversions.h"
#include "base/task/post_task.h"
#include "base/task/thread_pool.h"
#include "base/threading/scoped_blocking_call.h"
#include "base/win/registry.h"
#include "base/win/scoped_co_mem.h"
#include "base/win/scoped_com_initializer.h"
#include "base/win/windows_version.h"
#include "content/public/browser/browser_task_traits.h"
#include "content/public/browser/browser_thread.h"
#include "ui/base/win/shell.h"
#include "url/gurl.h"

namespace {

// Required COM implementation of IFileOperationProgressSink so we can
// precheck files before deletion to make sure they can be move to the
// Recycle Bin.
class DeleteFileProgressSink : public IFileOperationProgressSink {
 public:
  DeleteFileProgressSink();
  virtual ~DeleteFileProgressSink() = default;

 private:
  ULONG STDMETHODCALLTYPE AddRef(void) override;
  ULONG STDMETHODCALLTYPE Release(void) override;
  HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid,
                                           LPVOID* ppvObj) override;
  HRESULT STDMETHODCALLTYPE StartOperations(void) override;
  HRESULT STDMETHODCALLTYPE FinishOperations(HRESULT) override;
  HRESULT STDMETHODCALLTYPE PreRenameItem(DWORD, IShellItem*, LPCWSTR) override;
  HRESULT STDMETHODCALLTYPE
  PostRenameItem(DWORD, IShellItem*, LPCWSTR, HRESULT, IShellItem*) override;
  HRESULT STDMETHODCALLTYPE PreMoveItem(DWORD,
                                        IShellItem*,
                                        IShellItem*,
                                        LPCWSTR) override;
  HRESULT STDMETHODCALLTYPE PostMoveItem(DWORD,
                                         IShellItem*,
                                         IShellItem*,
                                         LPCWSTR,
                                         HRESULT,
                                         IShellItem*) override;
  HRESULT STDMETHODCALLTYPE PreCopyItem(DWORD,
                                        IShellItem*,
                                        IShellItem*,
                                        LPCWSTR) override;
  HRESULT STDMETHODCALLTYPE PostCopyItem(DWORD,
                                         IShellItem*,
                                         IShellItem*,
                                         LPCWSTR,
                                         HRESULT,
                                         IShellItem*) override;
  HRESULT STDMETHODCALLTYPE PreDeleteItem(DWORD, IShellItem*) override;
  HRESULT STDMETHODCALLTYPE PostDeleteItem(DWORD,
                                           IShellItem*,
                                           HRESULT,
                                           IShellItem*) override;
  HRESULT STDMETHODCALLTYPE PreNewItem(DWORD, IShellItem*, LPCWSTR) override;
  HRESULT STDMETHODCALLTYPE PostNewItem(DWORD,
                                        IShellItem*,
                                        LPCWSTR,
                                        LPCWSTR,
                                        DWORD,
                                        HRESULT,
                                        IShellItem*) override;
  HRESULT STDMETHODCALLTYPE UpdateProgress(UINT, UINT) override;
  HRESULT STDMETHODCALLTYPE ResetTimer(void) override;
  HRESULT STDMETHODCALLTYPE PauseTimer(void) override;
  HRESULT STDMETHODCALLTYPE ResumeTimer(void) override;

  ULONG m_cRef;
};

DeleteFileProgressSink::DeleteFileProgressSink() {
  m_cRef = 0;
}

HRESULT DeleteFileProgressSink::PreDeleteItem(DWORD dwFlags, IShellItem*) {
  if (!(dwFlags & TSF_DELETE_RECYCLE_IF_POSSIBLE)) {
    // TSF_DELETE_RECYCLE_IF_POSSIBLE will not be set for items that cannot be
    // recycled.  In this case, we abort the delete operation.  This bubbles
    // up and stops the Delete in IFileOperation.
    return E_ABORT;
  }
  // Returns S_OK if successful, or an error value otherwise. In the case of an
  // error value, the delete operation and all subsequent operations pending
  // from the call to IFileOperation are canceled.
  return S_OK;
}

HRESULT DeleteFileProgressSink::QueryInterface(REFIID riid, LPVOID* ppvObj) {
  // Always set out parameter to NULL, validating it first.
  if (!ppvObj)
    return E_INVALIDARG;
  *ppvObj = nullptr;
  if (riid == IID_IUnknown || riid == IID_IFileOperationProgressSink) {
    // Increment the reference count and return the pointer.
    *ppvObj = reinterpret_cast<IUnknown*>(this);
    AddRef();
    return NOERROR;
  }
  return E_NOINTERFACE;
}

ULONG DeleteFileProgressSink::AddRef() {
  InterlockedIncrement(&m_cRef);
  return m_cRef;
}

ULONG DeleteFileProgressSink::Release() {
  // Decrement the object's internal counter.
  ULONG ulRefCount = InterlockedDecrement(&m_cRef);
  if (0 == m_cRef) {
    delete this;
  }
  return ulRefCount;
}

HRESULT DeleteFileProgressSink::StartOperations() {
  return S_OK;
}

HRESULT DeleteFileProgressSink::FinishOperations(HRESULT) {
  return S_OK;
}

HRESULT DeleteFileProgressSink::PreRenameItem(DWORD, IShellItem*, LPCWSTR) {
  return S_OK;
}

HRESULT DeleteFileProgressSink::PostRenameItem(DWORD,
                                               IShellItem*,
                                               __RPC__in_string LPCWSTR,
                                               HRESULT,
                                               IShellItem*) {
  return E_NOTIMPL;
}

HRESULT DeleteFileProgressSink::PreMoveItem(DWORD,
                                            IShellItem*,
                                            IShellItem*,
                                            LPCWSTR) {
  return E_NOTIMPL;
}

HRESULT DeleteFileProgressSink::PostMoveItem(DWORD,
                                             IShellItem*,
                                             IShellItem*,
                                             LPCWSTR,
                                             HRESULT,
                                             IShellItem*) {
  return E_NOTIMPL;
}

HRESULT DeleteFileProgressSink::PreCopyItem(DWORD,
                                            IShellItem*,
                                            IShellItem*,
                                            LPCWSTR) {
  return E_NOTIMPL;
}

HRESULT DeleteFileProgressSink::PostCopyItem(DWORD,
                                             IShellItem*,
                                             IShellItem*,
                                             LPCWSTR,
                                             HRESULT,
                                             IShellItem*) {
  return E_NOTIMPL;
}

HRESULT DeleteFileProgressSink::PostDeleteItem(DWORD,
                                               IShellItem*,
                                               HRESULT,
                                               IShellItem*) {
  return S_OK;
}

HRESULT DeleteFileProgressSink::PreNewItem(DWORD dwFlags,
                                           IShellItem*,
                                           LPCWSTR) {
  return E_NOTIMPL;
}

HRESULT DeleteFileProgressSink::PostNewItem(DWORD,
                                            IShellItem*,
                                            LPCWSTR,
                                            LPCWSTR,
                                            DWORD,
                                            HRESULT,
                                            IShellItem*) {
  return E_NOTIMPL;
}

HRESULT DeleteFileProgressSink::UpdateProgress(UINT, UINT) {
  return S_OK;
}

HRESULT DeleteFileProgressSink::ResetTimer() {
  return S_OK;
}

HRESULT DeleteFileProgressSink::PauseTimer() {
  return S_OK;
}

HRESULT DeleteFileProgressSink::ResumeTimer() {
  return S_OK;
}

std::string OpenExternalOnWorkerThread(
    const GURL& url,
    const platform_util::OpenExternalOptions& options) {
  base::ScopedBlockingCall scoped_blocking_call(FROM_HERE,
                                                base::BlockingType::MAY_BLOCK);
  // Quote the input scheme to be sure that the command does not have
  // parameters unexpected by the external program. This url should already
  // have been escaped.
  base::string16 escaped_url = L"\"" + base::UTF8ToUTF16(url.spec()) + L"\"";
  base::string16 working_dir = options.working_dir.value();

  if (reinterpret_cast<ULONG_PTR>(
          ShellExecuteW(nullptr, L"open", escaped_url.c_str(), nullptr,
                        working_dir.empty() ? nullptr : working_dir.c_str(),
                        SW_SHOWNORMAL)) <= 32) {
    return "Failed to open";
  }
  return "";
}

void ShowItemInFolderOnWorkerThread(const base::FilePath& full_path) {
  base::ScopedBlockingCall scoped_blocking_call(FROM_HERE,
                                                base::BlockingType::MAY_BLOCK);
  base::win::ScopedCOMInitializer com_initializer;
  if (!com_initializer.Succeeded())
    return;

  base::FilePath dir = full_path.DirName().AsEndingWithSeparator();
  // ParseDisplayName will fail if the directory is "C:", it must be "C:\\".
  if (dir.empty())
    return;

  Microsoft::WRL::ComPtr<IShellFolder> desktop;
  HRESULT hr = SHGetDesktopFolder(desktop.GetAddressOf());
  if (FAILED(hr))
    return;

  base::win::ScopedCoMem<ITEMIDLIST> dir_item;
  hr = desktop->ParseDisplayName(NULL, NULL,
                                 const_cast<wchar_t*>(dir.value().c_str()),
                                 NULL, &dir_item, NULL);
  if (FAILED(hr))
    return;

  base::win::ScopedCoMem<ITEMIDLIST> file_item;
  hr = desktop->ParseDisplayName(
      NULL, NULL, const_cast<wchar_t*>(full_path.value().c_str()), NULL,
      &file_item, NULL);
  if (FAILED(hr))
    return;

  const ITEMIDLIST* highlight[] = {file_item};
  hr = SHOpenFolderAndSelectItems(dir_item, base::size(highlight), highlight,
                                  NULL);
  if (FAILED(hr)) {
    // On some systems, the above call mysteriously fails with "file not
    // found" even though the file is there.  In these cases, ShellExecute()
    // seems to work as a fallback (although it won't select the file).
    if (hr == ERROR_FILE_NOT_FOUND) {
      ShellExecute(NULL, L"open", dir.value().c_str(), NULL, NULL, SW_SHOW);
    } else {
      LOG(WARNING) << " " << __func__ << "(): Can't open full_path = \""
                   << full_path.value() << "\""
                   << " hr = " << logging::SystemErrorCodeToString(hr);
    }
  }
}

std::string OpenPathOnThread(const base::FilePath& full_path) {
  // May result in an interactive dialog.
  base::ScopedBlockingCall scoped_blocking_call(FROM_HERE,
                                                base::BlockingType::MAY_BLOCK);
  bool success;
  if (base::DirectoryExists(full_path))
    success = ui::win::OpenFolderViaShell(full_path);
  else
    success = ui::win::OpenFileViaShell(full_path);

  return success ? "" : "Failed to open path";
}

}  // namespace

namespace platform_util {

void ShowItemInFolder(const base::FilePath& full_path) {
  base::ThreadPool::CreateCOMSTATaskRunner(
      {base::MayBlock(), base::TaskPriority::USER_BLOCKING})
      ->PostTask(FROM_HERE,
                 base::BindOnce(&ShowItemInFolderOnWorkerThread, full_path));
}

void OpenPath(const base::FilePath& full_path, OpenCallback callback) {
  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);

  base::PostTaskAndReplyWithResult(
      base::ThreadPool::CreateCOMSTATaskRunner(
          {base::MayBlock(), base::TaskPriority::USER_BLOCKING})
          .get(),
      FROM_HERE, base::BindOnce(&OpenPathOnThread, full_path),
      std::move(callback));
}

void OpenExternal(const GURL& url,
                  const OpenExternalOptions& options,
                  OpenCallback callback) {
  base::PostTaskAndReplyWithResult(
      base::ThreadPool::CreateCOMSTATaskRunner(
          {base::MayBlock(), base::TaskPriority::USER_BLOCKING})
          .get(),
      FROM_HERE, base::BindOnce(&OpenExternalOnWorkerThread, url, options),
      std::move(callback));
}

bool MoveItemToTrash(const base::FilePath& path, bool delete_on_fail) {
  base::win::ScopedCOMInitializer com_initializer;
  if (!com_initializer.Succeeded())
    return false;

  Microsoft::WRL::ComPtr<IFileOperation> pfo;
  if (FAILED(::CoCreateInstance(CLSID_FileOperation, nullptr, CLSCTX_ALL,
                                IID_PPV_ARGS(&pfo))))
    return false;

  // Elevation prompt enabled for UAC protected files.  This overrides the
  // SILENT, NO_UI and NOERRORUI flags.

  if (base::win::GetVersion() >= base::win::Version::WIN8) {
    // Windows 8 introduces the flag RECYCLEONDELETE and deprecates the
    // ALLOWUNDO in favor of ADDUNDORECORD.
    if (FAILED(pfo->SetOperationFlags(
            FOF_NO_UI | FOFX_ADDUNDORECORD | FOF_NOERRORUI | FOF_SILENT |
            FOFX_SHOWELEVATIONPROMPT | FOFX_RECYCLEONDELETE)))
      return false;
  } else {
    // For Windows 7 and Vista, RecycleOnDelete is the default behavior.
    if (FAILED(pfo->SetOperationFlags(FOF_NO_UI | FOF_ALLOWUNDO |
                                      FOF_NOERRORUI | FOF_SILENT |
                                      FOFX_SHOWELEVATIONPROMPT)))
      return false;
  }

  // Create an IShellItem from the supplied source path.
  Microsoft::WRL::ComPtr<IShellItem> delete_item;
  if (FAILED(SHCreateItemFromParsingName(
          path.value().c_str(), NULL,
          IID_PPV_ARGS(delete_item.GetAddressOf()))))
    return false;

  Microsoft::WRL::ComPtr<IFileOperationProgressSink> delete_sink(
      new DeleteFileProgressSink);
  if (!delete_sink)
    return false;

  // Processes the queued command DeleteItem. This will trigger
  // the DeleteFileProgressSink to check for Recycle Bin.
  return SUCCEEDED(pfo->DeleteItem(delete_item.Get(), delete_sink.Get())) &&
         SUCCEEDED(pfo->PerformOperations());
}

void Beep() {
  MessageBeep(MB_OK);
}

}  // namespace platform_util
<|endoftext|>


<commit_before>#include "graphicitemblock.h"

#include <QBrush>
#include <QColor>
#include <QFontMetrics>
#include <QDebug>

bd::GraphicItemBlock::GraphicItemBlock(Block *block, QGraphicsItem *parent) : QGraphicsItem(parent)
{
    this->block = block;
    this->currentBoundingRect = QRectF();

    this->giBlockHead = Q_NULLPTR;
    this->giParamsPublic = QList<GraphicItemTextBox *>();
    this->updateBlockData();
}

QRectF bd::GraphicItemBlock::boundingRect() const
{
    return this->currentBoundingRect;
}

void bd::GraphicItemBlock::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
{
    Q_UNUSED(option);
    Q_UNUSED(widget);
    Q_UNUSED(painter);

    painter->setPen(Qt::red);
    painter->drawLine(-200, 0, 200, 0);
    painter->drawLine(0, -200, 0, 200);
}

void bd::GraphicItemBlock::updateBlockData()
{
    int widthMaximum = 0;
    int heightMaximum = 0;
    GraphicItemTextBox *gitb;

    // ------------------------------------------------------------------------
    //                           Create Sub GraphicIterms
    // ------------------------------------------------------------------------

    // creeate new header
    if (this->giBlockHead != Q_NULLPTR) {
        delete this->giBlockHead;
    }
    this->giBlockHead = new GraphicItemBlockHeader(this->block, this);
    if (this->giBlockHead->getUsedWidth() > widthMaximum) widthMaximum = this->giBlockHead->getUsedWidth();
    heightMaximum += this->giBlockHead->getUsedHeight();
    this->giBlockHead->setY(this->giBlockHead->getUsedHeight()/2);

    // create public parameters
    while (this->giParamsPublic.size() > 0) { // clear current list
        GraphicItemTextBox *tb = this->giParamsPublic.takeLast();
        delete tb;
    }
    for (int i=0; i < this->block->getParameters().size(); ++i) { // create new list
        Parameter *param = this->block->getParameters().at(i);
        if (param->isPublic()) {
            gitb = new GraphicItemTextBox(this);
            this->giParamsPublic.append(gitb);

            // update
            gitb->setText(param->name(), GraphicItemTextBox::Align::Center);

            // update height
            gitb->setY(gitb->y() + gitb->getUsedHeight()/2);
            gitb->setY(gitb->y() + heightMaximum);
            heightMaximum += gitb->getUsedHeight();

            // update maximum width
            if (gitb->getUsedWidth() > widthMaximum) widthMaximum = gitb->getUsedWidth();
        }
    }

    // ------------------------------------------------------------------------
    //                             Update Positon
    // ------------------------------------------------------------------------

    // update header
    this->giBlockHead->setY(this->giBlockHead->y() - heightMaximum/2);

    // update public parameters
    for (int i=0; i < this->giParamsPublic.size(); ++i) {
        gitb = this->giParamsPublic.at(i);
        gitb->minWidth = widthMaximum;
        gitb->setY(gitb->y() - heightMaximum/2);
    }
}
<commit_msg>typo in comments<commit_after>#include "graphicitemblock.h"

#include <QBrush>
#include <QColor>
#include <QFontMetrics>
#include <QDebug>

bd::GraphicItemBlock::GraphicItemBlock(Block *block, QGraphicsItem *parent) : QGraphicsItem(parent)
{
    this->block = block;
    this->currentBoundingRect = QRectF();

    this->giBlockHead = Q_NULLPTR;
    this->giParamsPublic = QList<GraphicItemTextBox *>();
    this->updateBlockData();
}

QRectF bd::GraphicItemBlock::boundingRect() const
{
    return this->currentBoundingRect;
}

void bd::GraphicItemBlock::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
{
    Q_UNUSED(option);
    Q_UNUSED(widget);
    Q_UNUSED(painter);

    painter->setPen(Qt::red);
    painter->drawLine(-200, 0, 200, 0);
    painter->drawLine(0, -200, 0, 200);
}

void bd::GraphicItemBlock::updateBlockData()
{
    int widthMaximum = 0;
    int heightMaximum = 0;
    GraphicItemTextBox *gitb;

    // ------------------------------------------------------------------------
    //                           Create Sub GraphicItems
    // ------------------------------------------------------------------------

    // create new header
    if (this->giBlockHead != Q_NULLPTR) {
        delete this->giBlockHead;
    }
    this->giBlockHead = new GraphicItemBlockHeader(this->block, this);
    if (this->giBlockHead->getUsedWidth() > widthMaximum) widthMaximum = this->giBlockHead->getUsedWidth();
    heightMaximum += this->giBlockHead->getUsedHeight();
    this->giBlockHead->setY(this->giBlockHead->getUsedHeight()/2);

    // create public parameters
    while (this->giParamsPublic.size() > 0) { // clear current list
        GraphicItemTextBox *tb = this->giParamsPublic.takeLast();
        delete tb;
    }
    for (int i=0; i < this->block->getParameters().size(); ++i) { // create new list
        Parameter *param = this->block->getParameters().at(i);
        if (param->isPublic()) {
            gitb = new GraphicItemTextBox(this);
            this->giParamsPublic.append(gitb);

            // update
            gitb->setText(param->name(), GraphicItemTextBox::Align::Center);

            // update height
            gitb->setY(gitb->y() + gitb->getUsedHeight()/2);
            gitb->setY(gitb->y() + heightMaximum);
            heightMaximum += gitb->getUsedHeight();

            // update maximum width
            if (gitb->getUsedWidth() > widthMaximum) widthMaximum = gitb->getUsedWidth();
        }
    }

    // ------------------------------------------------------------------------
    //                             Update Positon
    // ------------------------------------------------------------------------

    // update header
    this->giBlockHead->setY(this->giBlockHead->y() - heightMaximum/2);

    // update public parameters
    for (int i=0; i < this->giParamsPublic.size(); ++i) {
        gitb = this->giParamsPublic.at(i);
        gitb->minWidth = widthMaximum;
        gitb->setY(gitb->y() - heightMaximum/2);
    }
}
<|endoftext|>