<commit_before>//-------------------------------------------------------------------------------------------------------
// Copyright (C) Microsoft. All rights reserved.
// Licensed under the MIT license. See LICENSE.txt file in the project root for full license information.
//-------------------------------------------------------------------------------------------------------
#include "RuntimeLibraryPch.h"

#include "Library/ForInObjectEnumerator.h"

namespace Js
{
    ForInObjectEnumerator::ShadowData::ShadowData(
        RecyclableObject * initObject,
        RecyclableObject * firstPrototype,
        Recycler * recycler)
        : currentObject(initObject),
          firstPrototype(firstPrototype),
          propertyIds(recycler)
    {
    }

    ForInObjectEnumerator::ForInObjectEnumerator(RecyclableObject* object, ScriptContext * scriptContext, bool enumSymbols)
    {
        Initialize(object, scriptContext, enumSymbols);
    }

    void ForInObjectEnumerator::Clear()
    {
        // Only clear stuff that are not useful for the next enumerator
        shadowData = nullptr;
    }

    void ForInObjectEnumerator::Initialize(RecyclableObject* initObject, ScriptContext * requestContext, bool enumSymbols, ForInCache * forInCache)
    {
        this->enumeratingPrototype = false;

        if (initObject == nullptr)
        {
            enumerator.Clear(EnumeratorFlags::None, requestContext);
            this->shadowData = nullptr;
            this->canUseJitFastPath = false;
            return;
        }

        Assert(JavascriptOperators::GetTypeId(initObject) != TypeIds_Null
            && JavascriptOperators::GetTypeId(initObject) != TypeIds_Undefined);

        EnumeratorFlags flags;
        RecyclableObject * firstPrototype = nullptr;
        RecyclableObject * firstPrototypeWithEnumerableProperties = GetFirstPrototypeWithEnumerableProperties(initObject, &firstPrototype);
        if (firstPrototypeWithEnumerableProperties != nullptr)
        {
            Recycler *recycler = requestContext->GetRecycler();
            this->shadowData = RecyclerNew(recycler, ShadowData, initObject, firstPrototype, recycler);
            flags = EnumeratorFlags::UseCache | EnumeratorFlags::SnapShotSemantics | EnumeratorFlags::EnumNonEnumerable | (enumSymbols ? EnumeratorFlags::EnumSymbols : EnumeratorFlags::None);
        }
        // no enumerable properties in the prototype chain, no need to search it
        else
        {
            this->shadowData = nullptr;
            flags = EnumeratorFlags::UseCache | EnumeratorFlags::SnapShotSemantics | (enumSymbols ? EnumeratorFlags::EnumSymbols : EnumeratorFlags::None);
        }

        if (InitializeCurrentEnumerator(initObject, flags, requestContext, forInCache))
        {
            canUseJitFastPath = this->enumerator.CanUseJITFastPath();
        }
        else
        {
            // Nothing to enumerate.
            // We keep the shadowData so that it may walk up the prototype chain (e.g. primitive type)
            enumerator.Clear(flags, requestContext);
            canUseJitFastPath = false;
        }
    }

    RecyclableObject* ForInObjectEnumerator::GetFirstPrototypeWithEnumerableProperties(RecyclableObject* object, RecyclableObject** pFirstPrototype)
    {
        RecyclableObject* firstPrototype = nullptr;
        RecyclableObject* firstPrototypeWithEnumerableProperties = nullptr;

        if (JavascriptOperators::GetTypeId(object) != TypeIds_HostDispatch)
        {
            firstPrototypeWithEnumerableProperties = object;
            while (true)
            {
                firstPrototypeWithEnumerableProperties = firstPrototypeWithEnumerableProperties->GetPrototype();

                if (firstPrototypeWithEnumerableProperties == nullptr)
                {
                    break;
                }

                if (JavascriptOperators::GetTypeId(firstPrototypeWithEnumerableProperties) == TypeIds_Null)
                {
                    firstPrototypeWithEnumerableProperties = nullptr;
                    break;
                }

                if (firstPrototype == nullptr)
                {
                    firstPrototype = firstPrototypeWithEnumerableProperties;
                }

                if (!DynamicType::Is(firstPrototypeWithEnumerableProperties->GetTypeId())
                    || !DynamicObject::FromVar(firstPrototypeWithEnumerableProperties)->GetHasNoEnumerableProperties())
                {
                    break;
                }
            }
        }

        if (pFirstPrototype != nullptr)
        {
            *pFirstPrototype = firstPrototype;
        }

        return firstPrototypeWithEnumerableProperties;
    }

    BOOL ForInObjectEnumerator::InitializeCurrentEnumerator(RecyclableObject * object, ForInCache * forInCache)
    {
        EnumeratorFlags flags = enumerator.GetFlags();
        RecyclableObject * prototype = object->GetPrototype();
        if (prototype == nullptr || prototype->GetTypeId() == TypeIds_Null)
        {
            // If this is the last object on the prototype chain, we don't need to get the non-enumerable properties any more to track shadowing
            flags &= ~EnumeratorFlags::EnumNonEnumerable;
        }
        return InitializeCurrentEnumerator(object, flags, GetScriptContext(), forInCache);
    }

    BOOL ForInObjectEnumerator::InitializeCurrentEnumerator(RecyclableObject * object, EnumeratorFlags flags,  ScriptContext * scriptContext, ForInCache * forInCache)
    {
        Assert(object);
        Assert(scriptContext);

        if (VirtualTableInfo<DynamicObject>::HasVirtualTable(object))
        {
            DynamicObject* dynamicObject = (DynamicObject*)object;
            return dynamicObject->DynamicObject::GetEnumerator(&enumerator, flags, scriptContext, forInCache);
        }

        return object->GetEnumerator(&enumerator, flags, scriptContext, forInCache);
    }

    BOOL ForInObjectEnumerator::TestAndSetEnumerated(PropertyId propertyId)
    {
        Assert(this->shadowData != nullptr);
        Assert(!Js::IsInternalPropertyId(propertyId));

        return !(this->shadowData->propertyIds.TestAndSet(propertyId));
    }

    Var ForInObjectEnumerator::MoveAndGetNext(PropertyId& propertyId)
    {
        PropertyRecord const * propRecord;
        PropertyAttributes attributes = PropertyNone;

        while (true)
        {
            propertyId = Constants::NoProperty;
            Var currentIndex = enumerator.MoveAndGetNext(propertyId, &attributes);

            // The object type may have changed and we may not be able to use fast path anymore.
            this->canUseJitFastPath = enumerator.CanUseJITFastPath();

            if (currentIndex)
            {
                if (this->shadowData == nullptr)
                {
                    // There are no prototype that has enumerable properties,
                    // don't need to keep track of the propertyIds we visited.

                    // We have asked for enumerable properties only, so don't need to check the attribute returned.
                    Assert(attributes & PropertyEnumerable);

                    return currentIndex;
                }

                // Property Id does not exist.
                if (propertyId == Constants::NoProperty)
                {
                    if (!JavascriptString::Is(currentIndex)) //This can be undefined
                    {
                        continue;
                    }
                    JavascriptString *pString = JavascriptString::FromVar(currentIndex);
                    if (VirtualTableInfo<Js::PropertyString>::HasVirtualTable(pString))
                    {
                        // If we have a property string, it is assumed that the propertyId is being
                        // kept alive with the object
                        PropertyString * propertyString = (PropertyString *)pString;
                        propertyId = propertyString->GetPropertyRecord()->GetPropertyId();
                    }
                    else
                    {
                        ScriptContext* scriptContext = pString->GetScriptContext();
                        scriptContext->GetOrAddPropertyRecord(pString->GetString(), pString->GetLength(), &propRecord);
                        propertyId = propRecord->GetPropertyId();

                        // We keep the track of what is enumerated using a bit vector of propertyID.
                        // so the propertyId can't be collected until the end of the for in enumerator
                        // Keep a list of the property string.
                        this->shadowData->newPropertyStrings.Prepend(GetScriptContext()->GetRecycler(), propRecord);
                    }
                }

                if (TestAndSetEnumerated(propertyId) //checks if the property is already enumerated or not
                    && (attributes & PropertyEnumerable))
                {
                    return currentIndex;
                }
            }
            else
            {
                if (this->shadowData == nullptr)
                {
                    Assert(!this->enumeratingPrototype);
                    return nullptr;
                }

                RecyclableObject * object;
                if (!this->enumeratingPrototype)
                {
                    this->enumeratingPrototype = true;
                    object = this->shadowData->firstPrototype;
                    this->shadowData->currentObject = object;
                }
                else
                {
                    //walk the prototype chain
                    object = this->shadowData->currentObject->GetPrototype();
                    this->shadowData->currentObject = object;
                    if ((object == nullptr) || (JavascriptOperators::GetTypeId(object) == TypeIds_Null))
                    {
                        return nullptr;
                    }
                }

                do
                {
                    if (!InitializeCurrentEnumerator(object))
                    {
                        return nullptr;
                    }

                    if (!enumerator.IsNullEnumerator())
                    {
                        break;
                    }

                     //walk the prototype chain
                    object = object->GetPrototype();
                    this->shadowData->currentObject = object;
                    if ((object == nullptr) || (JavascriptOperators::GetTypeId(object) == TypeIds_Null))
                    {
                        return nullptr;
                    }
                }
                while (true);
            }
        }
    }
}
<commit_msg>AND canUseJitFastPath with previous value so that if it is already false we don’t call CanUseJITFastPath function<commit_after>//-------------------------------------------------------------------------------------------------------
// Copyright (C) Microsoft. All rights reserved.
// Licensed under the MIT license. See LICENSE.txt file in the project root for full license information.
//-------------------------------------------------------------------------------------------------------
#include "RuntimeLibraryPch.h"

#include "Library/ForInObjectEnumerator.h"

namespace Js
{
    ForInObjectEnumerator::ShadowData::ShadowData(
        RecyclableObject * initObject,
        RecyclableObject * firstPrototype,
        Recycler * recycler)
        : currentObject(initObject),
          firstPrototype(firstPrototype),
          propertyIds(recycler)
    {
    }

    ForInObjectEnumerator::ForInObjectEnumerator(RecyclableObject* object, ScriptContext * scriptContext, bool enumSymbols)
    {
        Initialize(object, scriptContext, enumSymbols);
    }

    void ForInObjectEnumerator::Clear()
    {
        // Only clear stuff that are not useful for the next enumerator
        shadowData = nullptr;
    }

    void ForInObjectEnumerator::Initialize(RecyclableObject* initObject, ScriptContext * requestContext, bool enumSymbols, ForInCache * forInCache)
    {
        this->enumeratingPrototype = false;

        if (initObject == nullptr)
        {
            enumerator.Clear(EnumeratorFlags::None, requestContext);
            this->shadowData = nullptr;
            this->canUseJitFastPath = false;
            return;
        }

        Assert(JavascriptOperators::GetTypeId(initObject) != TypeIds_Null
            && JavascriptOperators::GetTypeId(initObject) != TypeIds_Undefined);

        EnumeratorFlags flags;
        RecyclableObject * firstPrototype = nullptr;
        RecyclableObject * firstPrototypeWithEnumerableProperties = GetFirstPrototypeWithEnumerableProperties(initObject, &firstPrototype);
        if (firstPrototypeWithEnumerableProperties != nullptr)
        {
            Recycler *recycler = requestContext->GetRecycler();
            this->shadowData = RecyclerNew(recycler, ShadowData, initObject, firstPrototype, recycler);
            flags = EnumeratorFlags::UseCache | EnumeratorFlags::SnapShotSemantics | EnumeratorFlags::EnumNonEnumerable | (enumSymbols ? EnumeratorFlags::EnumSymbols : EnumeratorFlags::None);
        }
        // no enumerable properties in the prototype chain, no need to search it
        else
        {
            this->shadowData = nullptr;
            flags = EnumeratorFlags::UseCache | EnumeratorFlags::SnapShotSemantics | (enumSymbols ? EnumeratorFlags::EnumSymbols : EnumeratorFlags::None);
        }

        if (InitializeCurrentEnumerator(initObject, flags, requestContext, forInCache))
        {
            canUseJitFastPath = this->enumerator.CanUseJITFastPath();
        }
        else
        {
            // Nothing to enumerate.
            // We keep the shadowData so that it may walk up the prototype chain (e.g. primitive type)
            enumerator.Clear(flags, requestContext);
            canUseJitFastPath = false;
        }
    }

    RecyclableObject* ForInObjectEnumerator::GetFirstPrototypeWithEnumerableProperties(RecyclableObject* object, RecyclableObject** pFirstPrototype)
    {
        RecyclableObject* firstPrototype = nullptr;
        RecyclableObject* firstPrototypeWithEnumerableProperties = nullptr;

        if (JavascriptOperators::GetTypeId(object) != TypeIds_HostDispatch)
        {
            firstPrototypeWithEnumerableProperties = object;
            while (true)
            {
                firstPrototypeWithEnumerableProperties = firstPrototypeWithEnumerableProperties->GetPrototype();

                if (firstPrototypeWithEnumerableProperties == nullptr)
                {
                    break;
                }

                if (JavascriptOperators::GetTypeId(firstPrototypeWithEnumerableProperties) == TypeIds_Null)
                {
                    firstPrototypeWithEnumerableProperties = nullptr;
                    break;
                }

                if (firstPrototype == nullptr)
                {
                    firstPrototype = firstPrototypeWithEnumerableProperties;
                }

                if (!DynamicType::Is(firstPrototypeWithEnumerableProperties->GetTypeId())
                    || !DynamicObject::FromVar(firstPrototypeWithEnumerableProperties)->GetHasNoEnumerableProperties())
                {
                    break;
                }
            }
        }

        if (pFirstPrototype != nullptr)
        {
            *pFirstPrototype = firstPrototype;
        }

        return firstPrototypeWithEnumerableProperties;
    }

    BOOL ForInObjectEnumerator::InitializeCurrentEnumerator(RecyclableObject * object, ForInCache * forInCache)
    {
        EnumeratorFlags flags = enumerator.GetFlags();
        RecyclableObject * prototype = object->GetPrototype();
        if (prototype == nullptr || prototype->GetTypeId() == TypeIds_Null)
        {
            // If this is the last object on the prototype chain, we don't need to get the non-enumerable properties any more to track shadowing
            flags &= ~EnumeratorFlags::EnumNonEnumerable;
        }
        return InitializeCurrentEnumerator(object, flags, GetScriptContext(), forInCache);
    }

    BOOL ForInObjectEnumerator::InitializeCurrentEnumerator(RecyclableObject * object, EnumeratorFlags flags,  ScriptContext * scriptContext, ForInCache * forInCache)
    {
        Assert(object);
        Assert(scriptContext);

        if (VirtualTableInfo<DynamicObject>::HasVirtualTable(object))
        {
            DynamicObject* dynamicObject = (DynamicObject*)object;
            return dynamicObject->DynamicObject::GetEnumerator(&enumerator, flags, scriptContext, forInCache);
        }

        return object->GetEnumerator(&enumerator, flags, scriptContext, forInCache);
    }

    BOOL ForInObjectEnumerator::TestAndSetEnumerated(PropertyId propertyId)
    {
        Assert(this->shadowData != nullptr);
        Assert(!Js::IsInternalPropertyId(propertyId));

        return !(this->shadowData->propertyIds.TestAndSet(propertyId));
    }

    Var ForInObjectEnumerator::MoveAndGetNext(PropertyId& propertyId)
    {
        PropertyRecord const * propRecord;
        PropertyAttributes attributes = PropertyNone;

        while (true)
        {
            propertyId = Constants::NoProperty;
            Var currentIndex = enumerator.MoveAndGetNext(propertyId, &attributes);

            // The object type may have changed and we may not be able to use Jit fast path anymore.
            // canUseJitFastPath is determined in ForInObjectEnumerator::Initialize, once we decide we can't use
            // Jit fast path we will never go back to use fast path so && with current value  - if it's already
            // false we don't call CanUseJITFastPath()

            this->canUseJitFastPath = this->canUseJitFastPath && enumerator.CanUseJITFastPath();

            if (currentIndex)
            {
                if (this->shadowData == nullptr)
                {
                    // There are no prototype that has enumerable properties,
                    // don't need to keep track of the propertyIds we visited.

                    // We have asked for enumerable properties only, so don't need to check the attribute returned.
                    Assert(attributes & PropertyEnumerable);

                    return currentIndex;
                }

                // Property Id does not exist.
                if (propertyId == Constants::NoProperty)
                {
                    if (!JavascriptString::Is(currentIndex)) //This can be undefined
                    {
                        continue;
                    }
                    JavascriptString *pString = JavascriptString::FromVar(currentIndex);
                    if (VirtualTableInfo<Js::PropertyString>::HasVirtualTable(pString))
                    {
                        // If we have a property string, it is assumed that the propertyId is being
                        // kept alive with the object
                        PropertyString * propertyString = (PropertyString *)pString;
                        propertyId = propertyString->GetPropertyRecord()->GetPropertyId();
                    }
                    else
                    {
                        ScriptContext* scriptContext = pString->GetScriptContext();
                        scriptContext->GetOrAddPropertyRecord(pString->GetString(), pString->GetLength(), &propRecord);
                        propertyId = propRecord->GetPropertyId();

                        // We keep the track of what is enumerated using a bit vector of propertyID.
                        // so the propertyId can't be collected until the end of the for in enumerator
                        // Keep a list of the property string.
                        this->shadowData->newPropertyStrings.Prepend(GetScriptContext()->GetRecycler(), propRecord);
                    }
                }

                if (TestAndSetEnumerated(propertyId) //checks if the property is already enumerated or not
                    && (attributes & PropertyEnumerable))
                {
                    return currentIndex;
                }
            }
            else
            {
                if (this->shadowData == nullptr)
                {
                    Assert(!this->enumeratingPrototype);
                    return nullptr;
                }

                RecyclableObject * object;
                if (!this->enumeratingPrototype)
                {
                    this->enumeratingPrototype = true;
                    object = this->shadowData->firstPrototype;
                    this->shadowData->currentObject = object;
                }
                else
                {
                    //walk the prototype chain
                    object = this->shadowData->currentObject->GetPrototype();
                    this->shadowData->currentObject = object;
                    if ((object == nullptr) || (JavascriptOperators::GetTypeId(object) == TypeIds_Null))
                    {
                        return nullptr;
                    }
                }

                do
                {
                    if (!InitializeCurrentEnumerator(object))
                    {
                        return nullptr;
                    }

                    if (!enumerator.IsNullEnumerator())
                    {
                        break;
                    }

                     //walk the prototype chain
                    object = object->GetPrototype();
                    this->shadowData->currentObject = object;
                    if ((object == nullptr) || (JavascriptOperators::GetTypeId(object) == TypeIds_Null))
                    {
                        return nullptr;
                    }
                }
                while (true);
            }
        }
    }
}
<|endoftext|>


<commit_before>//==- DebugCheckers.cpp - Debugging Checkers ---------------------*- 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 checkers that display debugging information.
//
//===----------------------------------------------------------------------===//

#include "ClangSACheckers.h"
#include "clang/Analysis/Analyses/Dominators.h"
#include "clang/Analysis/Analyses/LiveVariables.h"
#include "clang/Analysis/CallGraph.h"
#include "clang/StaticAnalyzer/Core/Checker.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/AnalysisManager.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/ExplodedGraph.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h"
#include "llvm/Support/Process.h"

using namespace clang;
using namespace ento;

//===----------------------------------------------------------------------===//
// DominatorsTreeDumper
//===----------------------------------------------------------------------===//

namespace {
class DominatorsTreeDumper : public Checker<check::ASTCodeBody> {
public:
  void checkASTCodeBody(const Decl *D, AnalysisManager& mgr,
                        BugReporter &BR) const {
    if (AnalysisDeclContext *AC = mgr.getAnalysisDeclContext(D)) {
      DominatorTree dom;
      dom.buildDominatorTree(*AC);
      dom.dump();
    }
  }
};
}

void ento::registerDominatorsTreeDumper(CheckerManager &mgr) {
  mgr.registerChecker<DominatorsTreeDumper>();
}

//===----------------------------------------------------------------------===//
// LiveVariablesDumper
//===----------------------------------------------------------------------===//

namespace {
class LiveVariablesDumper : public Checker<check::ASTCodeBody> {
public:
  void checkASTCodeBody(const Decl *D, AnalysisManager& mgr,
                        BugReporter &BR) const {
    if (LiveVariables* L = mgr.getAnalysis<LiveVariables>(D)) {
      L->dumpBlockLiveness(mgr.getSourceManager());
    }
  }
};
}

void ento::registerLiveVariablesDumper(CheckerManager &mgr) {
  mgr.registerChecker<LiveVariablesDumper>();
}

//===----------------------------------------------------------------------===//
// CFGViewer
//===----------------------------------------------------------------------===//

namespace {
class CFGViewer : public Checker<check::ASTCodeBody> {
public:
  void checkASTCodeBody(const Decl *D, AnalysisManager& mgr,
                        BugReporter &BR) const {
    if (CFG *cfg = mgr.getCFG(D)) {
      cfg->viewCFG(mgr.getLangOpts());
    }
  }
};
}

void ento::registerCFGViewer(CheckerManager &mgr) {
  mgr.registerChecker<CFGViewer>();
}

//===----------------------------------------------------------------------===//
// CFGDumper
//===----------------------------------------------------------------------===//

namespace {
class CFGDumper : public Checker<check::ASTCodeBody> {
public:
  void checkASTCodeBody(const Decl *D, AnalysisManager& mgr,
                        BugReporter &BR) const {
    if (CFG *cfg = mgr.getCFG(D)) {
      cfg->dump(mgr.getLangOpts(),
                llvm::sys::Process::StandardErrHasColors());
    }
  }
};
}

void ento::registerCFGDumper(CheckerManager &mgr) {
  mgr.registerChecker<CFGDumper>();
}

//===----------------------------------------------------------------------===//
// CallGraphViewer
//===----------------------------------------------------------------------===//

namespace {
class CallGraphViewer : public Checker< check::ASTDecl<TranslationUnitDecl> > {
public:
  void checkASTDecl(const TranslationUnitDecl *TU, AnalysisManager& mgr,
                    BugReporter &BR) const {
    CallGraph CG;
    CG.addToCallGraph(const_cast<TranslationUnitDecl*>(TU));
    CG.viewGraph();
  }
};
}

void ento::registerCallGraphViewer(CheckerManager &mgr) {
  mgr.registerChecker<CallGraphViewer>();
}

//===----------------------------------------------------------------------===//
// CallGraphDumper
//===----------------------------------------------------------------------===//

namespace {
class CallGraphDumper : public Checker< check::ASTDecl<TranslationUnitDecl> > {
public:
  void checkASTDecl(const TranslationUnitDecl *TU, AnalysisManager& mgr,
                    BugReporter &BR) const {
    CallGraph CG;
    CG.addToCallGraph(const_cast<TranslationUnitDecl*>(TU));
    CG.dump();
  }
};
}

void ento::registerCallGraphDumper(CheckerManager &mgr) {
  mgr.registerChecker<CallGraphDumper>();
}

//===----------------------------------------------------------------------===//
// ConfigDumper
//===----------------------------------------------------------------------===//

namespace {
class ConfigDumper : public Checker< check::EndOfTranslationUnit > {
  typedef AnalyzerOptions::ConfigTable Table;

  static int compareEntry(const void *LHS, const void *RHS) {
    return ((const Table::MapEntryTy *)LHS)->getKey().compare(
           ((const Table::MapEntryTy *)RHS)->getKey());
  }

public:
  void checkEndOfTranslationUnit(const TranslationUnitDecl *TU,
                                 AnalysisManager& mgr,
                                 BugReporter &BR) const {
    const Table &Config = mgr.options.Config;

    SmallVector<const Table::MapEntryTy *, 32> Keys;
    for (Table::const_iterator I = Config.begin(), E = Config.end(); I != E;
         ++I)
      Keys.push_back(&*I);
    llvm::array_pod_sort(Keys.begin(), Keys.end(), compareEntry);

    llvm::errs() << "[config]\n";
    for (unsigned I = 0, E = Keys.size(); I != E; ++I)
      llvm::errs() << Keys[I]->getKey() << " = " << Keys[I]->second << '\n';

    llvm::errs() << "[stats]\n" << "num-entries = " << Keys.size() << '\n';
  }
};
}

void ento::registerConfigDumper(CheckerManager &mgr) {
  mgr.registerChecker<ConfigDumper>();
}

//===----------------------------------------------------------------------===//
// ExplodedGraph Viewer
//===----------------------------------------------------------------------===//

namespace {
class ExplodedGraphViewer : public Checker< check::EndAnalysis > {
public:
  ExplodedGraphViewer() {}
  void checkEndAnalysis(ExplodedGraph &G, BugReporter &B,ExprEngine &Eng) const {
    Eng.ViewGraph(0);
  }
};

}

void ento::registerExplodedGraphViewer(CheckerManager &mgr) {
  mgr.registerChecker<ExplodedGraphViewer>();
}
<commit_msg>array_pod_sort loses some type safety, better use the right types.<commit_after>//==- DebugCheckers.cpp - Debugging Checkers ---------------------*- 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 checkers that display debugging information.
//
//===----------------------------------------------------------------------===//

#include "ClangSACheckers.h"
#include "clang/Analysis/Analyses/Dominators.h"
#include "clang/Analysis/Analyses/LiveVariables.h"
#include "clang/Analysis/CallGraph.h"
#include "clang/StaticAnalyzer/Core/Checker.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/AnalysisManager.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/ExplodedGraph.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h"
#include "llvm/Support/Process.h"

using namespace clang;
using namespace ento;

//===----------------------------------------------------------------------===//
// DominatorsTreeDumper
//===----------------------------------------------------------------------===//

namespace {
class DominatorsTreeDumper : public Checker<check::ASTCodeBody> {
public:
  void checkASTCodeBody(const Decl *D, AnalysisManager& mgr,
                        BugReporter &BR) const {
    if (AnalysisDeclContext *AC = mgr.getAnalysisDeclContext(D)) {
      DominatorTree dom;
      dom.buildDominatorTree(*AC);
      dom.dump();
    }
  }
};
}

void ento::registerDominatorsTreeDumper(CheckerManager &mgr) {
  mgr.registerChecker<DominatorsTreeDumper>();
}

//===----------------------------------------------------------------------===//
// LiveVariablesDumper
//===----------------------------------------------------------------------===//

namespace {
class LiveVariablesDumper : public Checker<check::ASTCodeBody> {
public:
  void checkASTCodeBody(const Decl *D, AnalysisManager& mgr,
                        BugReporter &BR) const {
    if (LiveVariables* L = mgr.getAnalysis<LiveVariables>(D)) {
      L->dumpBlockLiveness(mgr.getSourceManager());
    }
  }
};
}

void ento::registerLiveVariablesDumper(CheckerManager &mgr) {
  mgr.registerChecker<LiveVariablesDumper>();
}

//===----------------------------------------------------------------------===//
// CFGViewer
//===----------------------------------------------------------------------===//

namespace {
class CFGViewer : public Checker<check::ASTCodeBody> {
public:
  void checkASTCodeBody(const Decl *D, AnalysisManager& mgr,
                        BugReporter &BR) const {
    if (CFG *cfg = mgr.getCFG(D)) {
      cfg->viewCFG(mgr.getLangOpts());
    }
  }
};
}

void ento::registerCFGViewer(CheckerManager &mgr) {
  mgr.registerChecker<CFGViewer>();
}

//===----------------------------------------------------------------------===//
// CFGDumper
//===----------------------------------------------------------------------===//

namespace {
class CFGDumper : public Checker<check::ASTCodeBody> {
public:
  void checkASTCodeBody(const Decl *D, AnalysisManager& mgr,
                        BugReporter &BR) const {
    if (CFG *cfg = mgr.getCFG(D)) {
      cfg->dump(mgr.getLangOpts(),
                llvm::sys::Process::StandardErrHasColors());
    }
  }
};
}

void ento::registerCFGDumper(CheckerManager &mgr) {
  mgr.registerChecker<CFGDumper>();
}

//===----------------------------------------------------------------------===//
// CallGraphViewer
//===----------------------------------------------------------------------===//

namespace {
class CallGraphViewer : public Checker< check::ASTDecl<TranslationUnitDecl> > {
public:
  void checkASTDecl(const TranslationUnitDecl *TU, AnalysisManager& mgr,
                    BugReporter &BR) const {
    CallGraph CG;
    CG.addToCallGraph(const_cast<TranslationUnitDecl*>(TU));
    CG.viewGraph();
  }
};
}

void ento::registerCallGraphViewer(CheckerManager &mgr) {
  mgr.registerChecker<CallGraphViewer>();
}

//===----------------------------------------------------------------------===//
// CallGraphDumper
//===----------------------------------------------------------------------===//

namespace {
class CallGraphDumper : public Checker< check::ASTDecl<TranslationUnitDecl> > {
public:
  void checkASTDecl(const TranslationUnitDecl *TU, AnalysisManager& mgr,
                    BugReporter &BR) const {
    CallGraph CG;
    CG.addToCallGraph(const_cast<TranslationUnitDecl*>(TU));
    CG.dump();
  }
};
}

void ento::registerCallGraphDumper(CheckerManager &mgr) {
  mgr.registerChecker<CallGraphDumper>();
}

//===----------------------------------------------------------------------===//
// ConfigDumper
//===----------------------------------------------------------------------===//

namespace {
class ConfigDumper : public Checker< check::EndOfTranslationUnit > {
  typedef AnalyzerOptions::ConfigTable Table;

  static int compareEntry(const void *LHS, const void *RHS) {
    return (*(const Table::MapEntryTy **)LHS)->getKey().compare(
           (*(const Table::MapEntryTy **)RHS)->getKey());
  }

public:
  void checkEndOfTranslationUnit(const TranslationUnitDecl *TU,
                                 AnalysisManager& mgr,
                                 BugReporter &BR) const {
    const Table &Config = mgr.options.Config;

    SmallVector<const Table::MapEntryTy *, 32> Keys;
    for (Table::const_iterator I = Config.begin(), E = Config.end(); I != E;
         ++I)
      Keys.push_back(&*I);
    llvm::array_pod_sort(Keys.begin(), Keys.end(), compareEntry);

    llvm::errs() << "[config]\n";
    for (unsigned I = 0, E = Keys.size(); I != E; ++I)
      llvm::errs() << Keys[I]->getKey() << " = " << Keys[I]->second << '\n';

    llvm::errs() << "[stats]\n" << "num-entries = " << Keys.size() << '\n';
  }
};
}

void ento::registerConfigDumper(CheckerManager &mgr) {
  mgr.registerChecker<ConfigDumper>();
}

//===----------------------------------------------------------------------===//
// ExplodedGraph Viewer
//===----------------------------------------------------------------------===//

namespace {
class ExplodedGraphViewer : public Checker< check::EndAnalysis > {
public:
  ExplodedGraphViewer() {}
  void checkEndAnalysis(ExplodedGraph &G, BugReporter &B,ExprEngine &Eng) const {
    Eng.ViewGraph(0);
  }
};

}

void ento::registerExplodedGraphViewer(CheckerManager &mgr) {
  mgr.registerChecker<ExplodedGraphViewer>();
}
<|endoftext|>


<commit_before>// $Id$
/**
 * @file recraw-local.C
 * @brief Run reconstruction of raw data locally
 *
 *

 * Usage: aliroot -b -q -l \
 *     recraw-local.C'("file", "cdb", minEvent, maxEvent, modules)'
 *
 * Examples:
 *     recraw-local.C'("alien:///alice/data/2009/.../....root")'
 *     recraw-local.C'("raw://run12345")'
 *     recraw-local.C'("raw://run12345", minEvent, MaxEvent)'
 *     recraw-local.C'("raw.root", "local://$PWD", minEvent, MaxEvent)'
 *
 * Defaults
 *     cdb="raw://"  -> take OCDB from GRID
 *     minEvent=-1   -> no lower event selection
 *     maxEvent=-1   -> no upper event selection
 *     modules="ALL" -> all modules
 *     hltOption="loglevel=0x7c" -> logging level info and above
 *
 *

 *
 * The input file can be a file on the grid, indicated by the tag
 * 'alien://' indicates. By default also the OCDB is set to the GRID.
 * If either the file or the OCDB is taken from the GRID, the macros
 * connects to the Grid in the beginning.
 *
 * Input files can be specified via te run number when using the tag
 * 'raw://' followed by the string 'run12345' where the number needs
 * to be adjusted.
 *
 * As for the OCDB it is always a good idea to use the OCDB from the
 * Grid as this will contain all the necessary objects and the latest
 * calibration. The special URI 'raw://' is most advisable as it selects
 * the storage automatically from the run number. Other options are e.g.
 * - "alien://folder=/alice/data/2010/OCDB"
 * - "local://$ALICE_ROOT/OCDB"
 *
 * Re-running the HLT reconstruction
 * By specifying the hlt options, the HLT chain can be re-run instead
 * of just extracting the online result. E.g. the following options
 * specify to ignore the HLTOUT payload and run the two chains defined
 * in the agents. The translation of the online configuration into
 * an HLT offline chain is under development.
 *

 *   ignore-hltout chains=GLOBAL-esd-converter,TPC-clusters
 *

 *
 * Note: You need a valid GRID token, use 'alien-token-init' of your
 * alien installation.
 *
 * @author Matthias.Richter@ift.uib.no
 * @ingroup alihlt_qa
 */
void recraw_local(const char *filename,
		  const char *cdbURI,
		  int minEvent=-1,
		  int maxEvent=-1,
		  const char *modules="ALL",
		  const char *hltOptions="loglevel=0x7c")
{
  // connect to the GRID if we use a file or OCDB from the GRID
  TString struri=cdbURI;
  TString strfile=filename;
  if (struri.BeginsWith("raw://") ||
      strfile.Contains("://") && !strfile.Contains("local://")) {
    TGrid::Connect("alien");
  }

  // Set the CDB storage location
  AliCDBManager * man = AliCDBManager::Instance();
  man->SetDefaultStorage(cdbURI);

  // Reconstruction settings
  AliReconstruction rec;

  if (minEvent>=0 || maxEvent>minEvent) {
    if (minEvent<0) minEvent=0;
    if (maxEvent<minEvent) maxEvent=minEvent;
    rec.SetEventRange(minEvent,maxEvent);
  }

  TString strModules=modules;
  if (modules)
    rec.SetRunReconstruction(modules);
  else
    rec.SetRunReconstruction("ALL");

  // QA options
  TString qaOptions="HLT TPC";
  if (!strModules.Contains("TPC")) qaOptions.ReplaceAll("TPC", "");
  qaOptions+=":ALL";
  rec.SetRunQA(qaOptions) ;
  //rec.SetQARefDefaultStorage("local://$ALICE_ROOT/QAref") ;

  // AliReconstruction settings
  rec.SetWriteESDfriend(kTRUE);
  rec.SetRunVertexFinder(strModules.Contains("ITS"));
  rec.SetInput(filename);
  rec.SetOption("HLT", hltOptions);

  rec.SetRunPlaneEff(kFALSE);

  // switch off cleanESD
  rec.SetCleanESD(kFALSE);

  AliLog::Flush();
  rec.Run();

}

void recraw_local(const char *filename,
		  int minEvent=-1,
		  int maxEvent=-1,
		  const char *modules="ALL",
		  const char *hltOptions="loglevel=0x7f")
{
  recraw_local(filename, "raw://", minEvent, maxEvent, modules, hltOptions);
}

void recraw_local()
{
  cout << "recraw-local: Run AliRoot reconstruction locally" << endl;
  cout << " Usage: aliroot -b -q -l \\" << endl;
  cout << "     recraw-local.C'(\"file\", \"cdb\", minEvent, maxEvent, modules, hltOptions)'" << endl;
  cout << "" << endl;
  cout << " Examples:" << endl;
  cout << "     recraw-local.C'(\"alien:///alice/data/2009/.../....root\")' " << endl;
  cout << "     recraw-local.C'(\"raw://run12345\")'" << endl;
  cout << "     recraw-local.C'(\"raw://run12345\", minEvent, MaxEvent)'" << endl;
  cout << "     recraw-local.C'(\"raw.root\", \"local://$PWD\", minEvent, MaxEvent)'" << endl;
  cout << "" << endl;
  cout << " Defaults" << endl;
  cout << "     cdb=\"raw://\"  -> take OCDB from GRID" << endl;
  cout << "     minEvent=-1   -> no lower event selection" << endl;
  cout << "     maxEvent=-1   -> no upper event selection" << endl;
  cout << "     modules=\"ALL\" -> all modules" << endl;
  cout << "     hltOption=\"loglevel=0x7c\" -> logging level info and above" << endl;
}
<commit_msg>handle the case of simulated raw data by checking for the GRP in the working directory when using a local OCDB<commit_after>// $Id$
/**
 * @file recraw-local.C
 * @brief Run reconstruction of raw data locally
 *
 *

 * Usage: aliroot -b -q -l \
 *     recraw-local.C'("file", "cdb", minEvent, maxEvent, modules)'
 *
 * Examples:
 *     recraw-local.C'("alien:///alice/data/2009/.../....root")'
 *     recraw-local.C'("raw://run12345")'
 *     recraw-local.C'("raw://run12345", minEvent, MaxEvent)'
 *     recraw-local.C'("raw.root", "local://$PWD", minEvent, MaxEvent)'
 *
 * Defaults
 *     cdb="raw://"  -> take OCDB from GRID
 *     minEvent=-1   -> no lower event selection
 *     maxEvent=-1   -> no upper event selection
 *     modules="ALL" -> all modules
 *     hltOption="loglevel=0x7c" -> logging level info and above
 *
 *

 *
 * The input file can be a file on the grid, indicated by the tag
 * 'alien://' indicates. By default also the OCDB is set to the GRID.
 * If either the file or the OCDB is taken from the GRID, the macros
 * connects to the Grid in the beginning.
 *
 * Input files can be specified via te run number when using the tag
 * 'raw://' followed by the string 'run12345' where the number needs
 * to be adjusted.
 *
 * As for the OCDB it is always a good idea to use the OCDB from the
 * Grid as this will contain all the necessary objects and the latest
 * calibration. The special URI 'raw://' is most advisable as it selects
 * the storage automatically from the run number. Other options are e.g.
 * - "alien://folder=/alice/data/2010/OCDB"
 * - "local://$ALICE_ROOT/OCDB"
 *
 * Re-running the HLT reconstruction
 * By specifying the hlt options, the HLT chain can be re-run instead
 * of just extracting the online result. E.g. the following options
 * specify to ignore the HLTOUT payload and run the two chains defined
 * in the agents. The translation of the online configuration into
 * an HLT offline chain is under development.
 *

 *   ignore-hltout chains=GLOBAL-esd-converter,TPC-clusters
 *

 *
 * Note: You need a valid GRID token, use 'alien-token-init' of your
 * alien installation.
 *
 * @author Matthias.Richter@ift.uib.no
 * @ingroup alihlt_qa
 */
void recraw_local(const char *filename,
		  const char *cdbURI,
		  int minEvent=-1,
		  int maxEvent=-1,
		  const char *modules="ALL",
		  const char *hltOptions="loglevel=0x7c")
{
  // connect to the GRID if we use a file or OCDB from the GRID
  TString struri=cdbURI;
  TString strfile=filename;
  if (struri.BeginsWith("raw://") ||
      strfile.Contains("://") && !strfile.Contains("local://")) {
    TGrid::Connect("alien");
  }

  // Set the CDB storage location
  AliCDBManager * man = AliCDBManager::Instance();
  man->SetDefaultStorage(cdbURI);
  if (struri.BeginsWith("local://")) {
    // set specific storage for GRP entry
    // search in the working directory and one level above, the latter
    // follows the standard simulation setup like e.g. in test/ppbench
    if (!gSystem->AccessPathName("GRP/GRP/Data")) {
      man->SetSpecificStorage("GRP/GRP/Data", "local://$PWD");
    } else if (!gSystem->AccessPathName("../GRP/GRP/Data")) {
      man->SetSpecificStorage("GRP/GRP/Data", "local://$PWD/..");
    }
  }

  // Reconstruction settings
  AliReconstruction rec;

  if (minEvent>=0 || maxEvent>minEvent) {
    if (minEvent<0) minEvent=0;
    if (maxEvent<minEvent) maxEvent=minEvent;
    rec.SetEventRange(minEvent,maxEvent);
  }

  TString strModules=modules;
  if (modules)
    rec.SetRunReconstruction(modules);
  else
    rec.SetRunReconstruction("ALL");

  // QA options
  TString qaOptions="HLT TPC";
  if (!strModules.Contains("TPC")) qaOptions.ReplaceAll("TPC", "");
  qaOptions+=":ALL";
  rec.SetRunQA(qaOptions) ;
  //rec.SetQARefDefaultStorage("local://$ALICE_ROOT/QAref") ;

  // AliReconstruction settings
  rec.SetWriteESDfriend(kTRUE);
  rec.SetRunVertexFinder(strModules.Contains("ITS"));
  rec.SetInput(filename);
  rec.SetOption("HLT", hltOptions);

  rec.SetRunPlaneEff(kFALSE);

  // switch off cleanESD
  rec.SetCleanESD(kFALSE);

  AliLog::Flush();
  rec.Run();

}

void recraw_local(const char *filename,
		  int minEvent=-1,
		  int maxEvent=-1,
		  const char *modules="ALL",
		  const char *hltOptions="loglevel=0x7f")
{
  recraw_local(filename, "raw://", minEvent, maxEvent, modules, hltOptions);
}

void recraw_local()
{
  cout << "recraw-local: Run AliRoot reconstruction locally" << endl;
  cout << " Usage: aliroot -b -q -l \\" << endl;
  cout << "     recraw-local.C'(\"file\", \"cdb\", minEvent, maxEvent, modules, hltOptions)'" << endl;
  cout << "" << endl;
  cout << " Examples:" << endl;
  cout << "     recraw-local.C'(\"alien:///alice/data/2009/.../....root\")' " << endl;
  cout << "     recraw-local.C'(\"raw://run12345\")'" << endl;
  cout << "     recraw-local.C'(\"raw://run12345\", minEvent, MaxEvent)'" << endl;
  cout << "     recraw-local.C'(\"raw.root\", \"local://$PWD\", minEvent, MaxEvent)'" << endl;
  cout << "" << endl;
  cout << " Defaults" << endl;
  cout << "     cdb=\"raw://\"  -> take OCDB from GRID" << endl;
  cout << "     minEvent=-1   -> no lower event selection" << endl;
  cout << "     maxEvent=-1   -> no upper event selection" << endl;
  cout << "     modules=\"ALL\" -> all modules" << endl;
  cout << "     hltOption=\"loglevel=0x7c\" -> logging level info and above" << endl;
}
<|endoftext|>


<commit_before>/*
 * Copyright (c) 2011-2014, Intel Corporation
 * 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.
 *
 * 3. Neither the name of the copyright holder nor the names of its contributors
 * may be used to endorse or promote products derived from this software without
 * specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER 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 "XmlStringDocSink.h"
#include <libxml/parser.h>

#define base CXmlDocSink

CXmlStringDocSink::CXmlStringDocSink(std::string& strResult):
      _strResult(strResult)
{
}

bool CXmlStringDocSink::doProcess(CXmlDocSource& xmlDocSource,
                                  CXmlSerializingContext& serializingContext)
{
    (void)serializingContext;

    xmlChar* pcDumpedDoc = NULL;

    int iSize;
    xmlDocDumpFormatMemoryEnc(xmlDocSource.getDoc(), &pcDumpedDoc, &iSize, "UTF-8", 1);

    if (!pcDumpedDoc) {

        return false;
    }

    _strResult.append((const char*)pcDumpedDoc);

    xmlFree(pcDumpedDoc);

    return true;
}
<commit_msg>Missing error reporting statement in XML Export feature<commit_after>/*
 * Copyright (c) 2011-2014, Intel Corporation
 * 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.
 *
 * 3. Neither the name of the copyright holder nor the names of its contributors
 * may be used to endorse or promote products derived from this software without
 * specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER 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 "XmlStringDocSink.h"
#include <libxml/parser.h>

#define base CXmlDocSink

CXmlStringDocSink::CXmlStringDocSink(std::string& strResult):
      _strResult(strResult)
{
}

bool CXmlStringDocSink::doProcess(CXmlDocSource& xmlDocSource,
                                  CXmlSerializingContext& serializingContext)
{
    (void)serializingContext;

    xmlChar* pcDumpedDoc = NULL;

    int iSize;
    xmlDocDumpFormatMemoryEnc(xmlDocSource.getDoc(), &pcDumpedDoc, &iSize, "UTF-8", 1);

    if (!pcDumpedDoc) {

        serializingContext.setError("Unable to encode XML document in memory");

        return false;
    }

    _strResult.append((const char*)pcDumpedDoc);

    xmlFree(pcDumpedDoc);

    return true;
}
<|endoftext|>


<commit_before>#include <cstdlib>
#include <jwt.h>

#include <Poco/Error.h>
#include <Poco/Exception.h>
#include <Poco/Logger.h>
#include <Poco/JSON/Array.h>
#include <Poco/JSON/Parser.h>

#include "di/Injectable.h"
#include "jwt/JWTDecoder.h"
#include "model/TokenID.h"
#include "util/JsonUtil.h"

using namespace BeeeOn;
using namespace std;
using namespace Poco;
using namespace Poco::JSON;

BEEEON_OBJECT_BEGIN(BeeeOn, JWTDecoder)
BEEEON_OBJECT_TEXT("secret", &JWTDecoder::setSecret)
BEEEON_OBJECT_END(BeeeOn, JWTDecoder)

JWTDecoder::JWTDecoder()
{
}

JWTDecoder::~JWTDecoder()
{
}

static vector<string> deserializeArray(const string &arr)
{
	vector<string> deserialized;
	Parser parser;

	Array::Ptr array = parser.parse(arr).extract<Array::Ptr>();

	for (size_t i = 0; i < array->size(); i++)
		deserialized.push_back(array->getElement<string>(i));

	return deserialized;
}

static void fillTokenWithData(JWToken &token, jwt_t *tokenData)
{
	const char *claim = ::jwt_get_grant(tokenData, "iss");
	if (claim != NULL)
		token.setIssuer(string(claim));
	else
		token.setIssuer("");

	claim = ::jwt_get_grant(tokenData, "sub");
	if (claim != NULL)
		token.setSubject(string(claim));
	else
		token.setSubject("");

	char *jsonClaim = ::jwt_get_grants_json(tokenData, "aud");
	if (jsonClaim != NULL) {
		try {
			token.setAudience(deserializeArray(jsonClaim));
		} catch (...) {
			::free(jsonClaim);
			throw;
		}

		::free(jsonClaim);
	}

	claim = ::jwt_get_grant(tokenData, "locale");
	if (claim != NULL)
		token.setLocale(string(claim));
	else
		token.setLocale("");

	long timeRaw = ::jwt_get_grant_int(tokenData, "exp");
	if (Error::last() != ENOENT)
		token.setExpirationTime(Timestamp::fromEpochTime(timeRaw));
	else
		token.setExpirationTime(Nullable<Timestamp>());

	timeRaw = ::jwt_get_grant_int(tokenData, "iat");
	if (Error::last() != ENOENT)
		token.setIssuedAt(Timestamp::fromEpochTime(timeRaw));
	else
		token.setIssuedAt(Nullable<Timestamp>());

	timeRaw = ::jwt_get_grant_int(tokenData, "nbf");
	if (Error::last() != ENOENT)
		token.setNotBefore(Timestamp::fromEpochTime(timeRaw));
	else
		token.setNotBefore(Nullable<Timestamp>());
}

JWToken JWTDecoder::decode(const TokenID &tokenId) const
{
	JWToken token;
	const string &tokenID = tokenId.toString();

	const unsigned char *secret;

	if (m_secret.empty())
		secret = NULL;
	else
		secret = reinterpret_cast<const unsigned char *>(m_secret.c_str());

	const size_t secretLen = m_secret.length();

	jwt_t *tokenData;
	const int err = ::jwt_decode(&tokenData, tokenID.c_str(), secret, secretLen);
	if (err != 0)
		throw InvalidArgumentException("jwt decode: " + Error::getMessage(err));

	try {
		fillTokenWithData(token, tokenData);
	} catch (...) {
		::jwt_free(tokenData);
		throw;
	}

	::jwt_free(tokenData);

	return token;
}

void JWTDecoder::setSecret(const string &secret)
{
	m_secret = secret;
}
<commit_msg>JWTDecoder: convert JSONException to SyntaxException<commit_after>#include <cstdlib>
#include <jwt.h>

#include <Poco/Error.h>
#include <Poco/Exception.h>
#include <Poco/Logger.h>
#include <Poco/JSON/Array.h>
#include <Poco/JSON/JSONException.h>
#include <Poco/JSON/Parser.h>

#include "di/Injectable.h"
#include "jwt/JWTDecoder.h"
#include "model/TokenID.h"
#include "util/JsonUtil.h"

using namespace BeeeOn;
using namespace std;
using namespace Poco;
using namespace Poco::JSON;

BEEEON_OBJECT_BEGIN(BeeeOn, JWTDecoder)
BEEEON_OBJECT_TEXT("secret", &JWTDecoder::setSecret)
BEEEON_OBJECT_END(BeeeOn, JWTDecoder)

JWTDecoder::JWTDecoder()
{
}

JWTDecoder::~JWTDecoder()
{
}

static vector<string> deserializeArray(const string &arr)
{
	vector<string> deserialized;
	Parser parser;

	try {
		Array::Ptr array = parser.parse(arr).extract<Array::Ptr>();

		for (size_t i = 0; i < array->size(); i++)
			deserialized.push_back(array->getElement<string>(i));

		return deserialized;
	}
	catch (const JSONException &e) {
		throw SyntaxException("failed to parse array", e);
	}
}

static void fillTokenWithData(JWToken &token, jwt_t *tokenData)
{
	const char *claim = ::jwt_get_grant(tokenData, "iss");
	if (claim != NULL)
		token.setIssuer(string(claim));
	else
		token.setIssuer("");

	claim = ::jwt_get_grant(tokenData, "sub");
	if (claim != NULL)
		token.setSubject(string(claim));
	else
		token.setSubject("");

	char *jsonClaim = ::jwt_get_grants_json(tokenData, "aud");
	if (jsonClaim != NULL) {
		try {
			token.setAudience(deserializeArray(jsonClaim));
		} catch (...) {
			::free(jsonClaim);
			throw;
		}

		::free(jsonClaim);
	}

	claim = ::jwt_get_grant(tokenData, "locale");
	if (claim != NULL)
		token.setLocale(string(claim));
	else
		token.setLocale("");

	long timeRaw = ::jwt_get_grant_int(tokenData, "exp");
	if (Error::last() != ENOENT)
		token.setExpirationTime(Timestamp::fromEpochTime(timeRaw));
	else
		token.setExpirationTime(Nullable<Timestamp>());

	timeRaw = ::jwt_get_grant_int(tokenData, "iat");
	if (Error::last() != ENOENT)
		token.setIssuedAt(Timestamp::fromEpochTime(timeRaw));
	else
		token.setIssuedAt(Nullable<Timestamp>());

	timeRaw = ::jwt_get_grant_int(tokenData, "nbf");
	if (Error::last() != ENOENT)
		token.setNotBefore(Timestamp::fromEpochTime(timeRaw));
	else
		token.setNotBefore(Nullable<Timestamp>());
}

JWToken JWTDecoder::decode(const TokenID &tokenId) const
{
	JWToken token;
	const string &tokenID = tokenId.toString();

	const unsigned char *secret;

	if (m_secret.empty())
		secret = NULL;
	else
		secret = reinterpret_cast<const unsigned char *>(m_secret.c_str());

	const size_t secretLen = m_secret.length();

	jwt_t *tokenData;
	const int err = ::jwt_decode(&tokenData, tokenID.c_str(), secret, secretLen);
	if (err != 0)
		throw InvalidArgumentException("jwt decode: " + Error::getMessage(err));

	try {
		fillTokenWithData(token, tokenData);
	} catch (...) {
		::jwt_free(tokenData);
		throw;
	}

	::jwt_free(tokenData);

	return token;
}

void JWTDecoder::setSecret(const string &secret)
{
	m_secret = secret;
}
<|endoftext|>


<commit_before>/*******************************
Copyright (c) 2016-2017 Grégoire Angerand

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
**********************************/

#include "Barrier.h"

namespace yave {

#if 0
static VkAccessFlags vk_layout_access_flags(VkImageLayout layout) {
    switch(layout) {
        case VK_IMAGE_LAYOUT_UNDEFINED:
            return 0;

        case VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL:
            return VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;

        case VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL:
            return VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT | VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT;

        case VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL:
            return VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT;

        case VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL:
            return VK_ACCESS_SHADER_READ_BIT;

        case VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL:
            return VK_ACCESS_TRANSFER_READ_BIT;

        case VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL:
            return VK_ACCESS_TRANSFER_WRITE_BIT;

        case VK_IMAGE_LAYOUT_PRESENT_SRC_KHR:
            return VK_ACCESS_MEMORY_READ_BIT;

        case VK_IMAGE_LAYOUT_GENERAL:
            // assume storage image
            return //VK_ACCESS_MEMORY_READ_BIT | VK_ACCESS_MEMORY_WRITE_BIT |
                   VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT;

        default:
            break;
    }

    y_fatal("Unsupported layout transition");
}

static VkAccessFlags vk_dst_access_flags(PipelineStage dst) {
    if((dst & PipelineStage::AllShadersBit) != PipelineStage::None) {
        return VK_ACCESS_SHADER_READ_BIT;
    }
    switch(dst) {
        case PipelineStage::TransferBit:
            return VK_ACCESS_TRANSFER_READ_BIT;

        case PipelineStage::HostBit:
            return VK_ACCESS_HOST_READ_BIT;

        case PipelineStage::BeginOfPipe:
        case PipelineStage::EndOfPipe:
            return VK_ACCESS_MEMORY_READ_BIT;

        default:
            break;
    }

    y_fatal("Unsuported pipeline stage");
}

static VkAccessFlags vk_src_access_flags(PipelineStage src) {
    if((src & PipelineStage::AllShadersBit) != PipelineStage::None) {
        return VK_ACCESS_SHADER_WRITE_BIT;
    }
    switch(src) {
        case PipelineStage::TransferBit:
            return VK_ACCESS_TRANSFER_WRITE_BIT;

        case PipelineStage::HostBit:
            return VK_ACCESS_HOST_WRITE_BIT;

        case PipelineStage::ColorAttachmentOutBit:
            return VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;

        case PipelineStage::BeginOfPipe:
        case PipelineStage::EndOfPipe:
            return VK_ACCESS_MEMORY_WRITE_BIT;

        default:
            break;
    }

    y_fatal("Unsuported pipeline stage");
}

static VkPipelineStageFlags vk_barrier_stage(VkAccessFlags access) {
    if(access == 0 || access == VK_ACCESS_MEMORY_READ_BIT) {
        return VK_PIPELINE_STAGE_HOST_BIT;
    }
    if(access & (VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT | VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT)) {
        return VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT |
               VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT;
    }
    if(access & (VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT)) {
        return VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
    }
    if(access & (VK_ACCESS_TRANSFER_READ_BIT | VK_ACCESS_TRANSFER_WRITE_BIT)) {
        return VK_PIPELINE_STAGE_TRANSFER_BIT;
    }
    if(access & (VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT)) {
        return VK_PIPELINE_STAGE_VERTEX_SHADER_BIT |
               VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT |
               VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT;
    }

    y_fatal("Unknown access flags");
}
#else
static VkAccessFlags vk_layout_access_flags(VkImageLayout) {
    return VK_ACCESS_MEMORY_READ_BIT | VK_ACCESS_MEMORY_WRITE_BIT;
}

static VkAccessFlags vk_dst_access_flags(PipelineStage) {
    return VK_ACCESS_MEMORY_READ_BIT;
}

static VkAccessFlags vk_src_access_flags(PipelineStage) {
    return VK_ACCESS_MEMORY_WRITE_BIT;
}

static PipelineStage vk_src_barrier_stage(VkAccessFlags) {
    return PipelineStage::EndOfPipe;
}

static PipelineStage vk_dst_barrier_stage(VkAccessFlags) {
    return PipelineStage::EndOfPipe;
}
#endif

static VkImageMemoryBarrier create_barrier(VkImage image, ImageFormat format, usize layers, usize mips, VkImageLayout old_layout, VkImageLayout new_layout) {
    VkImageMemoryBarrier barrier = vk_struct();
    {
        barrier.oldLayout = old_layout;
        barrier.newLayout = new_layout;
        barrier.srcAccessMask = vk_layout_access_flags(old_layout);
        barrier.dstAccessMask = vk_layout_access_flags(new_layout);
        barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
        barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
        barrier.image = image;

        barrier.subresourceRange.aspectMask = format.vk_aspect();
        barrier.subresourceRange.layerCount = layers;
        barrier.subresourceRange.levelCount = mips;
    }
    return barrier;
}

static VkImageMemoryBarrier create_barrier(VkImage image, ImageFormat format, usize layers, usize mips, ImageUsage usage, PipelineStage src, PipelineStage dst) {
    VkImageMemoryBarrier barrier = vk_struct();
    {
        const VkImageLayout layout = vk_image_layout(usage);

        barrier.oldLayout = layout;
        barrier.newLayout = layout;
        barrier.srcAccessMask = vk_src_access_flags(src);
        barrier.dstAccessMask = vk_dst_access_flags(dst);
        barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
        barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
        barrier.image = image;

        barrier.subresourceRange.aspectMask = format.vk_aspect();
        barrier.subresourceRange.layerCount = layers;
        barrier.subresourceRange.levelCount = mips;
    }
    return barrier;
}

static VkBufferMemoryBarrier create_barrier(VkBuffer buffer, usize size, usize offset, PipelineStage src, PipelineStage dst) {
    VkBufferMemoryBarrier barrier = vk_struct();
    {
        Y_TODO(uniform buffers needs to use VK_ACCESS_UNIFORM_READ_BIT)
        barrier.srcAccessMask = vk_src_access_flags(src);
        barrier.dstAccessMask = vk_dst_access_flags(dst);
        barrier.buffer = buffer;
        barrier.size = size;
        barrier.offset = offset;
        barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
        barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
    }
    return barrier;
}

ImageBarrier::ImageBarrier(const ImageBase& image, PipelineStage src, PipelineStage dst) :
        _barrier(create_barrier(image.vk_image(), image.format(), image.layers(), image.mipmaps(), image.usage(), src, dst)),
        _src(src), _dst(dst) {
}

ImageBarrier ImageBarrier::transition_barrier(const ImageBase& image, VkImageLayout src_layout, VkImageLayout dst_layout) {
    ImageBarrier barrier;
    barrier._barrier = create_barrier(image.vk_image(), image.format(), image.layers(), image.mipmaps(), src_layout, dst_layout);
    barrier._src = vk_src_barrier_stage(barrier._barrier.srcAccessMask);
    barrier._dst = vk_dst_barrier_stage(barrier._barrier.dstAccessMask);

    return barrier;
}

ImageBarrier ImageBarrier::transition_to_barrier(const ImageBase& image, VkImageLayout dst_layout) {
    return transition_barrier(image, vk_image_layout(image.usage()), dst_layout);
}

ImageBarrier ImageBarrier::transition_from_barrier(const ImageBase& image, VkImageLayout src_layout) {
    return transition_barrier(image, src_layout, vk_image_layout(image.usage()));
}

VkImageMemoryBarrier ImageBarrier::vk_barrier() const {
    return _barrier;
}

PipelineStage ImageBarrier::dst_stage() const {
    return _dst;
}

PipelineStage ImageBarrier::src_stage() const {
    return _src;
}

BufferBarrier::BufferBarrier(const BufferBase& buffer, PipelineStage src, PipelineStage dst) :
        _barrier(create_barrier(buffer.vk_buffer(), buffer.byte_size(), 0, src, dst)),
        _src(src), _dst(dst) {
}

BufferBarrier::BufferBarrier(const SubBufferBase& buffer, PipelineStage src, PipelineStage dst) :
        _barrier(create_barrier(buffer.vk_buffer(), buffer.byte_size(), buffer.byte_offset(), src, dst)),
        _src(src), _dst(dst) {
}

VkBufferMemoryBarrier BufferBarrier::vk_barrier() const {
    return _barrier;
}

PipelineStage BufferBarrier::dst_stage() const {
    return _dst;
}

PipelineStage BufferBarrier::src_stage() const {
    return _src;
}

}

<commit_msg>Fixed over conservatives pipelines barriers<commit_after>/*******************************
Copyright (c) 2016-2017 Grégoire Angerand

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
**********************************/

#include "Barrier.h"

namespace yave {

static VkAccessFlags vk_layout_access_flags(VkImageLayout layout) {
    switch(layout) {
        case VK_IMAGE_LAYOUT_UNDEFINED:
            return 0;

        case VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL:
            return VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;

        case VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL:
            return VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT | VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT;

        case VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL:
            return VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT;

        case VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL:
            return VK_ACCESS_SHADER_READ_BIT;

        case VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL:
            return VK_ACCESS_TRANSFER_READ_BIT;

        case VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL:
            return VK_ACCESS_TRANSFER_WRITE_BIT;

        case VK_IMAGE_LAYOUT_PRESENT_SRC_KHR:
            return VK_ACCESS_MEMORY_READ_BIT;

        case VK_IMAGE_LAYOUT_GENERAL:
            // assume storage image
            return //VK_ACCESS_MEMORY_READ_BIT | VK_ACCESS_MEMORY_WRITE_BIT |
                   VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT;

        default:
            break;
    }

    y_fatal("Unsupported layout transition");
}

static VkAccessFlags vk_dst_access_flags(PipelineStage dst) {
    if((dst & PipelineStage::AllShadersBit) != PipelineStage::None) {
        return VK_ACCESS_SHADER_READ_BIT;
    }
    switch(dst) {
        case PipelineStage::TransferBit:
            return VK_ACCESS_TRANSFER_READ_BIT;

        case PipelineStage::HostBit:
            return VK_ACCESS_HOST_READ_BIT;

        case PipelineStage::BeginOfPipe:
        case PipelineStage::EndOfPipe:
            return VK_ACCESS_MEMORY_READ_BIT;

        default:
            break;
    }

    y_fatal("Unsuported pipeline stage");
}

static VkAccessFlags vk_src_access_flags(PipelineStage src) {
    if((src & PipelineStage::AllShadersBit) != PipelineStage::None) {
        return VK_ACCESS_SHADER_WRITE_BIT;
    }
    switch(src) {
        case PipelineStage::TransferBit:
            return VK_ACCESS_TRANSFER_WRITE_BIT;

        case PipelineStage::HostBit:
            return VK_ACCESS_HOST_WRITE_BIT;

        case PipelineStage::ColorAttachmentOutBit:
            return VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;

        case PipelineStage::BeginOfPipe:
        case PipelineStage::EndOfPipe:
            return VK_ACCESS_MEMORY_WRITE_BIT;

        default:
            break;
    }

    y_fatal("Unsuported pipeline stage");
}

static VkPipelineStageFlags vk_barrier_stage(VkAccessFlags access) {
    if(access == 0 || access == VK_ACCESS_MEMORY_READ_BIT) {
        return VK_PIPELINE_STAGE_HOST_BIT;
    }
    if(access & (VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT | VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT)) {
        return VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT |
               VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT;
    }
    if(access & (VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT)) {
        return VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
    }
    if(access & (VK_ACCESS_TRANSFER_READ_BIT | VK_ACCESS_TRANSFER_WRITE_BIT)) {
        return VK_PIPELINE_STAGE_TRANSFER_BIT;
    }
    if(access & (VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT)) {
        return VK_PIPELINE_STAGE_VERTEX_SHADER_BIT |
               VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT |
               VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT;
    }

    y_fatal("Unknown access flags");
}

static PipelineStage vk_src_barrier_stage(VkAccessFlags access) {
    return PipelineStage(vk_barrier_stage(access));
}

static PipelineStage vk_dst_barrier_stage(VkAccessFlags access) {
    return PipelineStage(vk_barrier_stage(access));
}

static VkImageMemoryBarrier create_barrier(VkImage image, ImageFormat format, usize layers, usize mips, VkImageLayout old_layout, VkImageLayout new_layout) {
    VkImageMemoryBarrier barrier = vk_struct();
    {
        barrier.oldLayout = old_layout;
        barrier.newLayout = new_layout;
        barrier.srcAccessMask = vk_layout_access_flags(old_layout);
        barrier.dstAccessMask = vk_layout_access_flags(new_layout);
        barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
        barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
        barrier.image = image;

        barrier.subresourceRange.aspectMask = format.vk_aspect();
        barrier.subresourceRange.layerCount = layers;
        barrier.subresourceRange.levelCount = mips;
    }
    return barrier;
}

static VkImageMemoryBarrier create_barrier(VkImage image, ImageFormat format, usize layers, usize mips, ImageUsage usage, PipelineStage src, PipelineStage dst) {
    VkImageMemoryBarrier barrier = vk_struct();
    {
        const VkImageLayout layout = vk_image_layout(usage);

        barrier.oldLayout = layout;
        barrier.newLayout = layout;
        barrier.srcAccessMask = vk_src_access_flags(src);
        barrier.dstAccessMask = vk_dst_access_flags(dst);
        barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
        barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
        barrier.image = image;

        barrier.subresourceRange.aspectMask = format.vk_aspect();
        barrier.subresourceRange.layerCount = layers;
        barrier.subresourceRange.levelCount = mips;
    }
    return barrier;
}

static VkBufferMemoryBarrier create_barrier(VkBuffer buffer, usize size, usize offset, PipelineStage src, PipelineStage dst) {
    VkBufferMemoryBarrier barrier = vk_struct();
    {
        Y_TODO(uniform buffers needs to use VK_ACCESS_UNIFORM_READ_BIT)
        barrier.srcAccessMask = vk_src_access_flags(src);
        barrier.dstAccessMask = vk_dst_access_flags(dst);
        barrier.buffer = buffer;
        barrier.size = size;
        barrier.offset = offset;
        barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
        barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
    }
    return barrier;
}

ImageBarrier::ImageBarrier(const ImageBase& image, PipelineStage src, PipelineStage dst) :
        _barrier(create_barrier(image.vk_image(), image.format(), image.layers(), image.mipmaps(), image.usage(), src, dst)),
        _src(src), _dst(dst) {
}

ImageBarrier ImageBarrier::transition_barrier(const ImageBase& image, VkImageLayout src_layout, VkImageLayout dst_layout) {
    ImageBarrier barrier;
    barrier._barrier = create_barrier(image.vk_image(), image.format(), image.layers(), image.mipmaps(), src_layout, dst_layout);
    barrier._src = vk_src_barrier_stage(barrier._barrier.srcAccessMask);
    barrier._dst = vk_dst_barrier_stage(barrier._barrier.dstAccessMask);

    return barrier;
}

ImageBarrier ImageBarrier::transition_to_barrier(const ImageBase& image, VkImageLayout dst_layout) {
    return transition_barrier(image, vk_image_layout(image.usage()), dst_layout);
}

ImageBarrier ImageBarrier::transition_from_barrier(const ImageBase& image, VkImageLayout src_layout) {
    return transition_barrier(image, src_layout, vk_image_layout(image.usage()));
}

VkImageMemoryBarrier ImageBarrier::vk_barrier() const {
    return _barrier;
}

PipelineStage ImageBarrier::dst_stage() const {
    return _dst;
}

PipelineStage ImageBarrier::src_stage() const {
    return _src;
}

BufferBarrier::BufferBarrier(const BufferBase& buffer, PipelineStage src, PipelineStage dst) :
        _barrier(create_barrier(buffer.vk_buffer(), buffer.byte_size(), 0, src, dst)),
        _src(src), _dst(dst) {
}

BufferBarrier::BufferBarrier(const SubBufferBase& buffer, PipelineStage src, PipelineStage dst) :
        _barrier(create_barrier(buffer.vk_buffer(), buffer.byte_size(), buffer.byte_offset(), src, dst)),
        _src(src), _dst(dst) {
}

VkBufferMemoryBarrier BufferBarrier::vk_barrier() const {
    return _barrier;
}

PipelineStage BufferBarrier::dst_stage() const {
    return _dst;
}

PipelineStage BufferBarrier::src_stage() const {
    return _src;
}

}

<|endoftext|>


<commit_before>/*
** Copyright 2011-2012 Merethis
**
** This file is part of Centreon Broker.
**
** Centreon Broker is free software: you can redistribute it and/or
** modify it under the terms of the GNU General Public License version 2
** as published by the Free Software Foundation.
**
** Centreon Broker 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
** General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with Centreon Broker. If not, see
** <http://www.gnu.org/licenses/>.
*/

#include <cassert>
#include <cstdlib>
#include <QMutexLocker>
#include <QWaitCondition>
#include "com/centreon/broker/exceptions/msg.hh"
#include "com/centreon/broker/io/exceptions/shutdown.hh"
#include "com/centreon/broker/io/raw.hh"
#include "com/centreon/broker/tcp/stream.hh"

using namespace com::centreon::broker;
using namespace com::centreon::broker::tcp;

/**************************************
*                                     *
*           Public Methods            *
*                                     *
**************************************/

/**
 *  Constructor.
 *
 *  @param[in] sock Socket used by this stream.
 */
stream::stream(misc::shared_ptr<QTcpSocket> sock)
  : _mutex(new QMutex),
    _process_in(true),
    _process_out(true),
    _socket(sock),
    _timeout(-1) {}

/**
 *  Constructor.
 *
 *  @param[in] sock  Socket used by this stream.
 *  @param[in] mutex Mutex used by this stream.
 */
stream::stream(
          misc::shared_ptr<QTcpSocket> sock,
          misc::shared_ptr<QMutex> mutex)
  : _mutex(mutex),
    _process_in(true),
    _process_out(true),
    _socket(sock),
    _timeout(-1) {}

/**
 *  Destructor.
 */
stream::~stream() {
  QMutexLocker lock(&*_mutex);
  if (!_socket.isNull())
    _socket->close();
}

/**
 *  Enable or disable event processing.
 *
 *  @param[in] in  Set to true to enable input event processing.
 *  @param[in] out Set to true to enable output event processing.
 */
void stream::process(bool in, bool out) {
  _process_in = in;
  _process_out = out;
  return ;
}

/**
 *  Read data from the socket.
 *
 *  @param[out] d Data read.
 */
void stream::read(misc::shared_ptr<io::data>& d) {
  d.clear();
  QMutexLocker lock(&*_mutex);
  bool ret;
  while (1) {
    if (!_process_in
        || (!(ret = _socket->waitForReadyRead(
                (_timeout == -1)
                ? 200
                : _timeout))
                // Standalone socket.
            && ((_timeout != -1)
                // Disconnected socket with no data.
                || ((_socket->state()
                     == QAbstractSocket::UnconnectedState)
                    && (_socket->bytesAvailable() <= 0)))))
      throw (io::exceptions::shutdown(!_process_in, !_process_out)
               << "TCP stream is shutdown");
    if (ret
        || (_socket->error() != QAbstractSocket::SocketTimeoutError)
        || (_socket->bytesAvailable() > 0))
      break ;
    else {
      QWaitCondition cv;
      cv.wait(&*_mutex, 1);
    }
  }

  char buffer[2048];
  qint64 rb(_socket->read(buffer, sizeof(buffer)));
  if (rb < 0)
    throw (exceptions::msg() << "TCP: error while reading: "
             << _socket->errorString());
  misc::shared_ptr<io::raw> data(new io::raw);
#if QT_VERSION >= 0x040500
  data->append(buffer, rb);
#else
  data->append(QByteArray(buffer, rb));
#endif // Qt version
  d = data.staticCast<io::data>();
  return ;
}

/**
 *  Set connection timeout.
 *
 *  @param[in] msecs Timeout in ms.
 */
void stream::set_timeout(int msecs) {
  _timeout = msecs;
  return ;
}

/**
 *  Write data to the socket.
 *
 *  @param[in] d Data to write.
 */
void stream::write(misc::shared_ptr<io::data> const& d) {
  // Raw type.
  static QString const raw_type("com::centreon::broker::io::raw");

  // Check that data exists and should be processed.
  if (!_process_out)
    throw (io::exceptions::shutdown(!_process_in, !_process_out)
             << "TCP stream is shutdown");
  if (d.isNull())
    return ;

  if (d->type() == raw_type) {
    misc::shared_ptr<io::raw> r(d.staticCast<io::raw>());
    QMutexLocker lock(&*_mutex);
    qint64 wb(_socket->write(static_cast<char*>(r->QByteArray::data()),
                             r->size()));
    if (wb < 0)
      throw (exceptions::msg() << "TCP: error while writing: "
               << _socket->errorString());
    _socket->waitForBytesWritten(-1);
  }
  return ;
}

/**************************************
*                                     *
*           Private Methods           *
*                                     *
**************************************/

/**
 *  @brief Copy constructor.
 *
 *  Any call to this constructor will result in a call to abort().
 *
 *  @param[in] s Object to copy.
 */
stream::stream(stream const& s) : io::stream(s) {
  assert(!"TCP stream is not copyable");
  abort();
}

/**
 *  @brief Assignment operator.
 *
 *  Any call to this method will result in a call to abort().
 *
 *  @param[in] s Object to copy.
 *
 *  @return This object.
 */
stream& stream::operator=(stream const& s) {
  (void)s;
  assert(!"TCP stream is not copyable");
  abort();
  return (*this);
}
<commit_msg>Improved TCP stream.<commit_after>/*
** Copyright 2011-2012 Merethis
**
** This file is part of Centreon Broker.
**
** Centreon Broker is free software: you can redistribute it and/or
** modify it under the terms of the GNU General Public License version 2
** as published by the Free Software Foundation.
**
** Centreon Broker 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
** General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with Centreon Broker. If not, see
** <http://www.gnu.org/licenses/>.
*/

#include <cassert>
#include <cstdlib>
#include <QMutexLocker>
#include <QWaitCondition>
#include "com/centreon/broker/exceptions/msg.hh"
#include "com/centreon/broker/io/exceptions/shutdown.hh"
#include "com/centreon/broker/io/raw.hh"
#include "com/centreon/broker/tcp/stream.hh"

using namespace com::centreon::broker;
using namespace com::centreon::broker::tcp;

/**************************************
*                                     *
*           Public Methods            *
*                                     *
**************************************/

/**
 *  Constructor.
 *
 *  @param[in] sock Socket used by this stream.
 */
stream::stream(misc::shared_ptr<QTcpSocket> sock)
  : _mutex(new QMutex),
    _process_in(true),
    _process_out(true),
    _socket(sock),
    _timeout(-1) {}

/**
 *  Constructor.
 *
 *  @param[in] sock  Socket used by this stream.
 *  @param[in] mutex Mutex used by this stream.
 */
stream::stream(
          misc::shared_ptr<QTcpSocket> sock,
          misc::shared_ptr<QMutex> mutex)
  : _mutex(mutex),
    _process_in(true),
    _process_out(true),
    _socket(sock),
    _timeout(-1) {}

/**
 *  Destructor.
 */
stream::~stream() {
  QMutexLocker lock(&*_mutex);
  if (!_socket.isNull())
    _socket->close();
}

/**
 *  Enable or disable event processing.
 *
 *  @param[in] in  Set to true to enable input event processing.
 *  @param[in] out Set to true to enable output event processing.
 */
void stream::process(bool in, bool out) {
  _process_in = in;
  _process_out = out;
  return ;
}

/**
 *  Read data from the socket.
 *
 *  @param[out] d Data read.
 */
void stream::read(misc::shared_ptr<io::data>& d) {
  d.clear();
  QMutexLocker lock(&*_mutex);
  bool ret;
  while (1) {
    if (!_process_in)
      throw (io::exceptions::shutdown(!_process_in, !_process_out)
               << "TCP stream is shutdown");
    if (!(ret = _socket->waitForReadyRead(
                  (_timeout == -1)
                  ? 200
                  : _timeout))
            // Standalone socket.
        && ((_timeout != -1)
            // Disconnected socket with no data.
            || ((_socket->state()
                 == QAbstractSocket::UnconnectedState)
                && (_socket->bytesAvailable() <= 0))))
      throw (exceptions::msg() << "TCP stream is disconnected");
    if (ret
        || (_socket->error() != QAbstractSocket::SocketTimeoutError)
        || (_socket->bytesAvailable() > 0))
      break ;
    else {
      QWaitCondition cv;
      cv.wait(&*_mutex, 1);
    }
  }

  char buffer[2048];
  qint64 rb(_socket->read(buffer, sizeof(buffer)));
  if (rb < 0)
    throw (exceptions::msg() << "TCP: error while reading: "
             << _socket->errorString());
  misc::shared_ptr<io::raw> data(new io::raw);
#if QT_VERSION >= 0x040500
  data->append(buffer, rb);
#else
  data->append(QByteArray(buffer, rb));
#endif // Qt version
  d = data.staticCast<io::data>();
  return ;
}

/**
 *  Set connection timeout.
 *
 *  @param[in] msecs Timeout in ms.
 */
void stream::set_timeout(int msecs) {
  _timeout = msecs;
  return ;
}

/**
 *  Write data to the socket.
 *
 *  @param[in] d Data to write.
 */
void stream::write(misc::shared_ptr<io::data> const& d) {
  // Raw type.
  static QString const raw_type("com::centreon::broker::io::raw");

  // Check that data exists and should be processed.
  if (!_process_out)
    throw (io::exceptions::shutdown(!_process_in, !_process_out)
             << "TCP stream is shutdown");
  if (d.isNull())
    return ;

  if (d->type() == raw_type) {
    misc::shared_ptr<io::raw> r(d.staticCast<io::raw>());
    QMutexLocker lock(&*_mutex);
    qint64 wb(_socket->write(static_cast<char*>(r->QByteArray::data()),
                             r->size()));
    if (wb < 0)
      throw (exceptions::msg() << "TCP: error while writing: "
               << _socket->errorString());
    _socket->waitForBytesWritten(-1);
  }
  return ;
}

/**************************************
*                                     *
*           Private Methods           *
*                                     *
**************************************/

/**
 *  @brief Copy constructor.
 *
 *  Any call to this constructor will result in a call to abort().
 *
 *  @param[in] s Object to copy.
 */
stream::stream(stream const& s) : io::stream(s) {
  assert(!"TCP stream is not copyable");
  abort();
}

/**
 *  @brief Assignment operator.
 *
 *  Any call to this method will result in a call to abort().
 *
 *  @param[in] s Object to copy.
 *
 *  @return This object.
 */
stream& stream::operator=(stream const& s) {
  (void)s;
  assert(!"TCP stream is not copyable");
  abort();
  return (*this);
}
<|endoftext|>