<commit_before>//===- Pattern.cpp - Pattern wrapper class --------------------------------===//
//
// Copyright 2019 The MLIR Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//   http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// =============================================================================
//
// Pattern wrapper class to simplify using TableGen Record defining a MLIR
// Pattern.
//
//===----------------------------------------------------------------------===//

#include "mlir/TableGen/Pattern.h"
#include "llvm/ADT/Twine.h"
#include "llvm/Support/FormatVariadic.h"
#include "llvm/TableGen/Error.h"
#include "llvm/TableGen/Record.h"

using namespace mlir;

using llvm::formatv;
using mlir::tblgen::Operator;

//===----------------------------------------------------------------------===//
// DagLeaf
//===----------------------------------------------------------------------===//

bool tblgen::DagLeaf::isUnspecified() const {
  return dyn_cast_or_null<llvm::UnsetInit>(def);
}

bool tblgen::DagLeaf::isOperandMatcher() const {
  // Operand matchers specify a type constraint.
  return isSubClassOf("TypeConstraint");
}

bool tblgen::DagLeaf::isAttrMatcher() const {
  // Attribute matchers specify an attribute constraint.
  return isSubClassOf("AttrConstraint");
}

bool tblgen::DagLeaf::isNativeCodeCall() const {
  return isSubClassOf("NativeCodeCall");
}

bool tblgen::DagLeaf::isConstantAttr() const {
  return isSubClassOf("ConstantAttr");
}

bool tblgen::DagLeaf::isEnumAttrCase() const {
  return isSubClassOf("EnumAttrCaseInfo");
}

tblgen::Constraint tblgen::DagLeaf::getAsConstraint() const {
  assert((isOperandMatcher() || isAttrMatcher()) &&
         "the DAG leaf must be operand or attribute");
  return Constraint(cast<llvm::DefInit>(def)->getDef());
}

tblgen::ConstantAttr tblgen::DagLeaf::getAsConstantAttr() const {
  assert(isConstantAttr() && "the DAG leaf must be constant attribute");
  return ConstantAttr(cast<llvm::DefInit>(def));
}

tblgen::EnumAttrCase tblgen::DagLeaf::getAsEnumAttrCase() const {
  assert(isEnumAttrCase() && "the DAG leaf must be an enum attribute case");
  return EnumAttrCase(cast<llvm::DefInit>(def));
}

std::string tblgen::DagLeaf::getConditionTemplate() const {
  return getAsConstraint().getConditionTemplate();
}

llvm::StringRef tblgen::DagLeaf::getNativeCodeTemplate() const {
  assert(isNativeCodeCall() && "the DAG leaf must be NativeCodeCall");
  return cast<llvm::DefInit>(def)->getDef()->getValueAsString("expression");
}

bool tblgen::DagLeaf::isSubClassOf(StringRef superclass) const {
  if (auto *defInit = dyn_cast_or_null<llvm::DefInit>(def))
    return defInit->getDef()->isSubClassOf(superclass);
  return false;
}

//===----------------------------------------------------------------------===//
// DagNode
//===----------------------------------------------------------------------===//

bool tblgen::DagNode::isNativeCodeCall() const {
  if (auto *defInit = dyn_cast_or_null<llvm::DefInit>(node->getOperator()))
    return defInit->getDef()->isSubClassOf("NativeCodeCall");
  return false;
}

bool tblgen::DagNode::isOperation() const {
  return !(isNativeCodeCall() || isReplaceWithValue());
}

llvm::StringRef tblgen::DagNode::getNativeCodeTemplate() const {
  assert(isNativeCodeCall() && "the DAG leaf must be NativeCodeCall");
  return cast<llvm::DefInit>(node->getOperator())
      ->getDef()
      ->getValueAsString("expression");
}

llvm::StringRef tblgen::DagNode::getSymbol() const {
  return node->getNameStr();
}

Operator &tblgen::DagNode::getDialectOp(RecordOperatorMap *mapper) const {
  llvm::Record *opDef = cast<llvm::DefInit>(node->getOperator())->getDef();
  auto it = mapper->find(opDef);
  if (it != mapper->end())
    return *it->second;
  return *mapper->try_emplace(opDef, llvm::make_unique<Operator>(opDef))
              .first->second;
}

int tblgen::DagNode::getNumOps() const {
  int count = isReplaceWithValue() ? 0 : 1;
  for (int i = 0, e = getNumArgs(); i != e; ++i) {
    if (auto child = getArgAsNestedDag(i))
      count += child.getNumOps();
  }
  return count;
}

int tblgen::DagNode::getNumArgs() const { return node->getNumArgs(); }

bool tblgen::DagNode::isNestedDagArg(unsigned index) const {
  return isa<llvm::DagInit>(node->getArg(index));
}

tblgen::DagNode tblgen::DagNode::getArgAsNestedDag(unsigned index) const {
  return DagNode(dyn_cast_or_null<llvm::DagInit>(node->getArg(index)));
}

tblgen::DagLeaf tblgen::DagNode::getArgAsLeaf(unsigned index) const {
  assert(!isNestedDagArg(index));
  return DagLeaf(node->getArg(index));
}

StringRef tblgen::DagNode::getArgName(unsigned index) const {
  return node->getArgNameStr(index);
}

bool tblgen::DagNode::isReplaceWithValue() const {
  auto *dagOpDef = cast<llvm::DefInit>(node->getOperator())->getDef();
  return dagOpDef->getName() == "replaceWithValue";
}

//===----------------------------------------------------------------------===//
// SymbolInfoMap
//===----------------------------------------------------------------------===//

StringRef tblgen::SymbolInfoMap::getValuePackName(StringRef symbol,
                                                  int *index) {
  StringRef name, indexStr;
  int idx = -1;
  std::tie(name, indexStr) = symbol.rsplit("__");

  if (indexStr.consumeInteger(10, idx)) {
    // The second part is not an index; we return the whole symbol as-is.
    return symbol;
  }
  if (index) {
    *index = idx;
  }
  return name;
}

tblgen::SymbolInfoMap::SymbolInfo::SymbolInfo(const Operator *op,
                                              SymbolInfo::Kind kind,
                                              Optional<int> index)
    : op(op), kind(kind), argIndex(index) {}

int tblgen::SymbolInfoMap::SymbolInfo::getStaticValueCount() const {
  switch (kind) {
  case Kind::Attr:
  case Kind::Operand:
  case Kind::Value:
    return 1;
  case Kind::Result:
    return op->getNumResults();
  }
}

std::string
tblgen::SymbolInfoMap::SymbolInfo::getVarDecl(StringRef name) const {
  switch (kind) {
  case Kind::Attr: {
    auto type =
        op->getArg(*argIndex).get<NamedAttribute *>()->attr.getStorageType();
    return formatv("{0} {1};\n", type, name);
  }
  case Kind::Operand:
  case Kind::Value: {
    return formatv("Value *{0};\n", name);
  }
  case Kind::Result: {
    // Use the op itself for the results.
    return formatv("{0} {1};\n", op->getQualCppClassName(), name);
  }
  }
}

std::string
tblgen::SymbolInfoMap::SymbolInfo::getValueAndRangeUse(StringRef name,
                                                       int index) const {
  switch (kind) {
  case Kind::Attr:
  case Kind::Operand: {
    assert(index < 0 && "only allowed for symbol bound to result");
    return name;
  }
  case Kind::Result: {
    // TODO(b/133341698): The following is incorrect for variadic results. We
    // should use getODSResults().
    if (index >= 0) {
      return formatv("{0}.getOperation()->getResult({1})", name, index);
    }

    // If referencing multiple results, compose a comma-separated list.
    SmallVector<std::string, 4> values;
    for (int i = 0, e = op->getNumResults(); i < e; ++i) {
      values.push_back(formatv("{0}.getOperation()->getResult({1})", name, i));
    }
    return llvm::join(values, ", ");
  }
  case Kind::Value: {
    assert(index < 0 && "only allowed for symbol bound to result");
    assert(op == nullptr);
    return name;
  }
  }
}

bool tblgen::SymbolInfoMap::bindOpArgument(StringRef symbol, const Operator &op,
                                           int argIndex) {
  StringRef name = getValuePackName(symbol);
  if (name != symbol) {
    auto error = formatv(
        "symbol '{0}' with trailing index cannot bind to op argument", symbol);
    PrintFatalError(loc, error);
  }

  auto symInfo = op.getArg(argIndex).is<NamedAttribute *>()
                     ? SymbolInfo::getAttr(&op, argIndex)
                     : SymbolInfo::getOperand(&op, argIndex);

  return symbolInfoMap.insert({symbol, symInfo}).second;
}

bool tblgen::SymbolInfoMap::bindOpResult(StringRef symbol, const Operator &op) {
  StringRef name = getValuePackName(symbol);
  return symbolInfoMap.insert({name, SymbolInfo::getResult(&op)}).second;
}

bool tblgen::SymbolInfoMap::bindValue(StringRef symbol) {
  return symbolInfoMap.insert({symbol, SymbolInfo::getValue()}).second;
}

bool tblgen::SymbolInfoMap::contains(StringRef symbol) const {
  return find(symbol) != symbolInfoMap.end();
}

tblgen::SymbolInfoMap::const_iterator
tblgen::SymbolInfoMap::find(StringRef key) const {
  StringRef name = getValuePackName(key);
  return symbolInfoMap.find(name);
}

int tblgen::SymbolInfoMap::getStaticValueCount(StringRef symbol) const {
  StringRef name = getValuePackName(symbol);
  if (name != symbol) {
    // If there is a trailing index inside symbol, it references just one
    // static value.
    return 1;
  }
  // Otherwise, find how many it represents by querying the symbol's info.
  return find(name)->getValue().getStaticValueCount();
}

std::string tblgen::SymbolInfoMap::getValueAndRangeUse(StringRef symbol) const {
  int index = -1;
  StringRef name = getValuePackName(symbol, &index);

  auto it = symbolInfoMap.find(name);
  if (it == symbolInfoMap.end()) {
    auto error = formatv("referencing unbound symbol '{0}'", symbol);
    PrintFatalError(loc, error);
  }

  return it->getValue().getValueAndRangeUse(name, index);
}

//===----------------------------------------------------------------------===//
// Pattern
//==----------------------------------------------------------------------===//

tblgen::Pattern::Pattern(const llvm::Record *def, RecordOperatorMap *mapper)
    : def(*def), recordOpMap(mapper) {}

tblgen::DagNode tblgen::Pattern::getSourcePattern() const {
  return tblgen::DagNode(def.getValueAsDag("sourcePattern"));
}

int tblgen::Pattern::getNumResultPatterns() const {
  auto *results = def.getValueAsListInit("resultPatterns");
  return results->size();
}

tblgen::DagNode tblgen::Pattern::getResultPattern(unsigned index) const {
  auto *results = def.getValueAsListInit("resultPatterns");
  return tblgen::DagNode(cast<llvm::DagInit>(results->getElement(index)));
}

void tblgen::Pattern::collectSourcePatternBoundSymbols(
    tblgen::SymbolInfoMap &infoMap) {
  collectBoundSymbols(getSourcePattern(), infoMap, /*isSrcPattern=*/true);
}

void tblgen::Pattern::collectResultPatternBoundSymbols(
    tblgen::SymbolInfoMap &infoMap) {
  for (int i = 0, e = getNumResultPatterns(); i < e; ++i) {
    auto pattern = getResultPattern(i);
    collectBoundSymbols(pattern, infoMap, /*isSrcPattern=*/false);
  }
}

const tblgen::Operator &tblgen::Pattern::getSourceRootOp() {
  return getSourcePattern().getDialectOp(recordOpMap);
}

tblgen::Operator &tblgen::Pattern::getDialectOp(DagNode node) {
  return node.getDialectOp(recordOpMap);
}

std::vector<tblgen::AppliedConstraint> tblgen::Pattern::getConstraints() const {
  auto *listInit = def.getValueAsListInit("constraints");
  std::vector<tblgen::AppliedConstraint> ret;
  ret.reserve(listInit->size());

  for (auto it : *listInit) {
    auto *dagInit = dyn_cast<llvm::DagInit>(it);
    if (!dagInit)
      PrintFatalError(def.getLoc(), "all elemements in Pattern multi-entity "
                                    "constraints should be DAG nodes");

    std::vector<std::string> entities;
    entities.reserve(dagInit->arg_size());
    for (auto *argName : dagInit->getArgNames())
      entities.push_back(argName->getValue());

    ret.emplace_back(cast<llvm::DefInit>(dagInit->getOperator())->getDef(),
                     dagInit->getNameStr(), std::move(entities));
  }
  return ret;
}

int tblgen::Pattern::getBenefit() const {
  // The initial benefit value is a heuristic with number of ops in the source
  // pattern.
  int initBenefit = getSourcePattern().getNumOps();
  llvm::DagInit *delta = def.getValueAsDag("benefitDelta");
  if (delta->getNumArgs() != 1 || !isa<llvm::IntInit>(delta->getArg(0))) {
    PrintFatalError(def.getLoc(),
                    "The 'addBenefit' takes and only takes one integer value");
  }
  return initBenefit + dyn_cast<llvm::IntInit>(delta->getArg(0))->getValue();
}

std::vector<tblgen::Pattern::IdentifierLine>
tblgen::Pattern::getLocation() const {
  std::vector<std::pair<StringRef, unsigned>> result;
  result.reserve(def.getLoc().size());
  for (auto loc : def.getLoc()) {
    unsigned buf = llvm::SrcMgr.FindBufferContainingLoc(loc);
    assert(buf && "invalid source location");
    result.emplace_back(
        llvm::SrcMgr.getBufferInfo(buf).Buffer->getBufferIdentifier(),
        llvm::SrcMgr.getLineAndColumn(loc, buf).first);
  }
  return result;
}

void tblgen::Pattern::collectBoundSymbols(DagNode tree, SymbolInfoMap &infoMap,
                                          bool isSrcPattern) {
  auto treeName = tree.getSymbol();
  if (!tree.isOperation()) {
    if (!treeName.empty()) {
      PrintFatalError(
          def.getLoc(),
          formatv("binding symbol '{0}' to non-operation unsupported right now",
                  treeName));
    }
    return;
  }

  auto &op = getDialectOp(tree);
  auto numOpArgs = op.getNumArgs();
  auto numTreeArgs = tree.getNumArgs();

  if (numOpArgs != numTreeArgs) {
    auto err = formatv("op '{0}' argument number mismatch: "
                       "{1} in pattern vs. {2} in definition",
                       op.getOperationName(), numTreeArgs, numOpArgs);
    PrintFatalError(def.getLoc(), err);
  }

  // The name attached to the DAG node's operator is for representing the
  // results generated from this op. It should be remembered as bound results.
  if (!treeName.empty()) {
    if (!infoMap.bindOpResult(treeName, op))
      PrintFatalError(def.getLoc(),
                      formatv("symbol '{0}' bound more than once", treeName));
  }

  for (int i = 0; i != numTreeArgs; ++i) {
    if (auto treeArg = tree.getArgAsNestedDag(i)) {
      // This DAG node argument is a DAG node itself. Go inside recursively.
      collectBoundSymbols(treeArg, infoMap, isSrcPattern);
    } else if (isSrcPattern) {
      // We can only bind symbols to op arguments in source pattern. Those
      // symbols are referenced in result patterns.
      auto treeArgName = tree.getArgName(i);
      if (!treeArgName.empty()) {
        if (!infoMap.bindOpArgument(treeArgName, op, i)) {
          auto err = formatv("symbol '{0}' bound more than once", treeArgName);
          PrintFatalError(def.getLoc(), err);
        }
      }
    }
  }
}
<commit_msg>Add unreachable to avoid GCC -Wreturn-type warning<commit_after>//===- Pattern.cpp - Pattern wrapper class --------------------------------===//
//
// Copyright 2019 The MLIR Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//   http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// =============================================================================
//
// Pattern wrapper class to simplify using TableGen Record defining a MLIR
// Pattern.
//
//===----------------------------------------------------------------------===//

#include "mlir/TableGen/Pattern.h"
#include "llvm/ADT/Twine.h"
#include "llvm/Support/FormatVariadic.h"
#include "llvm/TableGen/Error.h"
#include "llvm/TableGen/Record.h"

using namespace mlir;

using llvm::formatv;
using mlir::tblgen::Operator;

//===----------------------------------------------------------------------===//
// DagLeaf
//===----------------------------------------------------------------------===//

bool tblgen::DagLeaf::isUnspecified() const {
  return dyn_cast_or_null<llvm::UnsetInit>(def);
}

bool tblgen::DagLeaf::isOperandMatcher() const {
  // Operand matchers specify a type constraint.
  return isSubClassOf("TypeConstraint");
}

bool tblgen::DagLeaf::isAttrMatcher() const {
  // Attribute matchers specify an attribute constraint.
  return isSubClassOf("AttrConstraint");
}

bool tblgen::DagLeaf::isNativeCodeCall() const {
  return isSubClassOf("NativeCodeCall");
}

bool tblgen::DagLeaf::isConstantAttr() const {
  return isSubClassOf("ConstantAttr");
}

bool tblgen::DagLeaf::isEnumAttrCase() const {
  return isSubClassOf("EnumAttrCaseInfo");
}

tblgen::Constraint tblgen::DagLeaf::getAsConstraint() const {
  assert((isOperandMatcher() || isAttrMatcher()) &&
         "the DAG leaf must be operand or attribute");
  return Constraint(cast<llvm::DefInit>(def)->getDef());
}

tblgen::ConstantAttr tblgen::DagLeaf::getAsConstantAttr() const {
  assert(isConstantAttr() && "the DAG leaf must be constant attribute");
  return ConstantAttr(cast<llvm::DefInit>(def));
}

tblgen::EnumAttrCase tblgen::DagLeaf::getAsEnumAttrCase() const {
  assert(isEnumAttrCase() && "the DAG leaf must be an enum attribute case");
  return EnumAttrCase(cast<llvm::DefInit>(def));
}

std::string tblgen::DagLeaf::getConditionTemplate() const {
  return getAsConstraint().getConditionTemplate();
}

llvm::StringRef tblgen::DagLeaf::getNativeCodeTemplate() const {
  assert(isNativeCodeCall() && "the DAG leaf must be NativeCodeCall");
  return cast<llvm::DefInit>(def)->getDef()->getValueAsString("expression");
}

bool tblgen::DagLeaf::isSubClassOf(StringRef superclass) const {
  if (auto *defInit = dyn_cast_or_null<llvm::DefInit>(def))
    return defInit->getDef()->isSubClassOf(superclass);
  return false;
}

//===----------------------------------------------------------------------===//
// DagNode
//===----------------------------------------------------------------------===//

bool tblgen::DagNode::isNativeCodeCall() const {
  if (auto *defInit = dyn_cast_or_null<llvm::DefInit>(node->getOperator()))
    return defInit->getDef()->isSubClassOf("NativeCodeCall");
  return false;
}

bool tblgen::DagNode::isOperation() const {
  return !(isNativeCodeCall() || isReplaceWithValue());
}

llvm::StringRef tblgen::DagNode::getNativeCodeTemplate() const {
  assert(isNativeCodeCall() && "the DAG leaf must be NativeCodeCall");
  return cast<llvm::DefInit>(node->getOperator())
      ->getDef()
      ->getValueAsString("expression");
}

llvm::StringRef tblgen::DagNode::getSymbol() const {
  return node->getNameStr();
}

Operator &tblgen::DagNode::getDialectOp(RecordOperatorMap *mapper) const {
  llvm::Record *opDef = cast<llvm::DefInit>(node->getOperator())->getDef();
  auto it = mapper->find(opDef);
  if (it != mapper->end())
    return *it->second;
  return *mapper->try_emplace(opDef, llvm::make_unique<Operator>(opDef))
              .first->second;
}

int tblgen::DagNode::getNumOps() const {
  int count = isReplaceWithValue() ? 0 : 1;
  for (int i = 0, e = getNumArgs(); i != e; ++i) {
    if (auto child = getArgAsNestedDag(i))
      count += child.getNumOps();
  }
  return count;
}

int tblgen::DagNode::getNumArgs() const { return node->getNumArgs(); }

bool tblgen::DagNode::isNestedDagArg(unsigned index) const {
  return isa<llvm::DagInit>(node->getArg(index));
}

tblgen::DagNode tblgen::DagNode::getArgAsNestedDag(unsigned index) const {
  return DagNode(dyn_cast_or_null<llvm::DagInit>(node->getArg(index)));
}

tblgen::DagLeaf tblgen::DagNode::getArgAsLeaf(unsigned index) const {
  assert(!isNestedDagArg(index));
  return DagLeaf(node->getArg(index));
}

StringRef tblgen::DagNode::getArgName(unsigned index) const {
  return node->getArgNameStr(index);
}

bool tblgen::DagNode::isReplaceWithValue() const {
  auto *dagOpDef = cast<llvm::DefInit>(node->getOperator())->getDef();
  return dagOpDef->getName() == "replaceWithValue";
}

//===----------------------------------------------------------------------===//
// SymbolInfoMap
//===----------------------------------------------------------------------===//

StringRef tblgen::SymbolInfoMap::getValuePackName(StringRef symbol,
                                                  int *index) {
  StringRef name, indexStr;
  int idx = -1;
  std::tie(name, indexStr) = symbol.rsplit("__");

  if (indexStr.consumeInteger(10, idx)) {
    // The second part is not an index; we return the whole symbol as-is.
    return symbol;
  }
  if (index) {
    *index = idx;
  }
  return name;
}

tblgen::SymbolInfoMap::SymbolInfo::SymbolInfo(const Operator *op,
                                              SymbolInfo::Kind kind,
                                              Optional<int> index)
    : op(op), kind(kind), argIndex(index) {}

int tblgen::SymbolInfoMap::SymbolInfo::getStaticValueCount() const {
  switch (kind) {
  case Kind::Attr:
  case Kind::Operand:
  case Kind::Value:
    return 1;
  case Kind::Result:
    return op->getNumResults();
  }
  llvm_unreachable("unknown kind");
}

std::string
tblgen::SymbolInfoMap::SymbolInfo::getVarDecl(StringRef name) const {
  switch (kind) {
  case Kind::Attr: {
    auto type =
        op->getArg(*argIndex).get<NamedAttribute *>()->attr.getStorageType();
    return formatv("{0} {1};\n", type, name);
  }
  case Kind::Operand:
  case Kind::Value: {
    return formatv("Value *{0};\n", name);
  }
  case Kind::Result: {
    // Use the op itself for the results.
    return formatv("{0} {1};\n", op->getQualCppClassName(), name);
  }
  }
  llvm_unreachable("unknown kind");
}

std::string
tblgen::SymbolInfoMap::SymbolInfo::getValueAndRangeUse(StringRef name,
                                                       int index) const {
  switch (kind) {
  case Kind::Attr:
  case Kind::Operand: {
    assert(index < 0 && "only allowed for symbol bound to result");
    return name;
  }
  case Kind::Result: {
    // TODO(b/133341698): The following is incorrect for variadic results. We
    // should use getODSResults().
    if (index >= 0) {
      return formatv("{0}.getOperation()->getResult({1})", name, index);
    }

    // If referencing multiple results, compose a comma-separated list.
    SmallVector<std::string, 4> values;
    for (int i = 0, e = op->getNumResults(); i < e; ++i) {
      values.push_back(formatv("{0}.getOperation()->getResult({1})", name, i));
    }
    return llvm::join(values, ", ");
  }
  case Kind::Value: {
    assert(index < 0 && "only allowed for symbol bound to result");
    assert(op == nullptr);
    return name;
  }
  }
  llvm_unreachable("unknown kind");
}

bool tblgen::SymbolInfoMap::bindOpArgument(StringRef symbol, const Operator &op,
                                           int argIndex) {
  StringRef name = getValuePackName(symbol);
  if (name != symbol) {
    auto error = formatv(
        "symbol '{0}' with trailing index cannot bind to op argument", symbol);
    PrintFatalError(loc, error);
  }

  auto symInfo = op.getArg(argIndex).is<NamedAttribute *>()
                     ? SymbolInfo::getAttr(&op, argIndex)
                     : SymbolInfo::getOperand(&op, argIndex);

  return symbolInfoMap.insert({symbol, symInfo}).second;
}

bool tblgen::SymbolInfoMap::bindOpResult(StringRef symbol, const Operator &op) {
  StringRef name = getValuePackName(symbol);
  return symbolInfoMap.insert({name, SymbolInfo::getResult(&op)}).second;
}

bool tblgen::SymbolInfoMap::bindValue(StringRef symbol) {
  return symbolInfoMap.insert({symbol, SymbolInfo::getValue()}).second;
}

bool tblgen::SymbolInfoMap::contains(StringRef symbol) const {
  return find(symbol) != symbolInfoMap.end();
}

tblgen::SymbolInfoMap::const_iterator
tblgen::SymbolInfoMap::find(StringRef key) const {
  StringRef name = getValuePackName(key);
  return symbolInfoMap.find(name);
}

int tblgen::SymbolInfoMap::getStaticValueCount(StringRef symbol) const {
  StringRef name = getValuePackName(symbol);
  if (name != symbol) {
    // If there is a trailing index inside symbol, it references just one
    // static value.
    return 1;
  }
  // Otherwise, find how many it represents by querying the symbol's info.
  return find(name)->getValue().getStaticValueCount();
}

std::string tblgen::SymbolInfoMap::getValueAndRangeUse(StringRef symbol) const {
  int index = -1;
  StringRef name = getValuePackName(symbol, &index);

  auto it = symbolInfoMap.find(name);
  if (it == symbolInfoMap.end()) {
    auto error = formatv("referencing unbound symbol '{0}'", symbol);
    PrintFatalError(loc, error);
  }

  return it->getValue().getValueAndRangeUse(name, index);
}

//===----------------------------------------------------------------------===//
// Pattern
//==----------------------------------------------------------------------===//

tblgen::Pattern::Pattern(const llvm::Record *def, RecordOperatorMap *mapper)
    : def(*def), recordOpMap(mapper) {}

tblgen::DagNode tblgen::Pattern::getSourcePattern() const {
  return tblgen::DagNode(def.getValueAsDag("sourcePattern"));
}

int tblgen::Pattern::getNumResultPatterns() const {
  auto *results = def.getValueAsListInit("resultPatterns");
  return results->size();
}

tblgen::DagNode tblgen::Pattern::getResultPattern(unsigned index) const {
  auto *results = def.getValueAsListInit("resultPatterns");
  return tblgen::DagNode(cast<llvm::DagInit>(results->getElement(index)));
}

void tblgen::Pattern::collectSourcePatternBoundSymbols(
    tblgen::SymbolInfoMap &infoMap) {
  collectBoundSymbols(getSourcePattern(), infoMap, /*isSrcPattern=*/true);
}

void tblgen::Pattern::collectResultPatternBoundSymbols(
    tblgen::SymbolInfoMap &infoMap) {
  for (int i = 0, e = getNumResultPatterns(); i < e; ++i) {
    auto pattern = getResultPattern(i);
    collectBoundSymbols(pattern, infoMap, /*isSrcPattern=*/false);
  }
}

const tblgen::Operator &tblgen::Pattern::getSourceRootOp() {
  return getSourcePattern().getDialectOp(recordOpMap);
}

tblgen::Operator &tblgen::Pattern::getDialectOp(DagNode node) {
  return node.getDialectOp(recordOpMap);
}

std::vector<tblgen::AppliedConstraint> tblgen::Pattern::getConstraints() const {
  auto *listInit = def.getValueAsListInit("constraints");
  std::vector<tblgen::AppliedConstraint> ret;
  ret.reserve(listInit->size());

  for (auto it : *listInit) {
    auto *dagInit = dyn_cast<llvm::DagInit>(it);
    if (!dagInit)
      PrintFatalError(def.getLoc(), "all elemements in Pattern multi-entity "
                                    "constraints should be DAG nodes");

    std::vector<std::string> entities;
    entities.reserve(dagInit->arg_size());
    for (auto *argName : dagInit->getArgNames())
      entities.push_back(argName->getValue());

    ret.emplace_back(cast<llvm::DefInit>(dagInit->getOperator())->getDef(),
                     dagInit->getNameStr(), std::move(entities));
  }
  return ret;
}

int tblgen::Pattern::getBenefit() const {
  // The initial benefit value is a heuristic with number of ops in the source
  // pattern.
  int initBenefit = getSourcePattern().getNumOps();
  llvm::DagInit *delta = def.getValueAsDag("benefitDelta");
  if (delta->getNumArgs() != 1 || !isa<llvm::IntInit>(delta->getArg(0))) {
    PrintFatalError(def.getLoc(),
                    "The 'addBenefit' takes and only takes one integer value");
  }
  return initBenefit + dyn_cast<llvm::IntInit>(delta->getArg(0))->getValue();
}

std::vector<tblgen::Pattern::IdentifierLine>
tblgen::Pattern::getLocation() const {
  std::vector<std::pair<StringRef, unsigned>> result;
  result.reserve(def.getLoc().size());
  for (auto loc : def.getLoc()) {
    unsigned buf = llvm::SrcMgr.FindBufferContainingLoc(loc);
    assert(buf && "invalid source location");
    result.emplace_back(
        llvm::SrcMgr.getBufferInfo(buf).Buffer->getBufferIdentifier(),
        llvm::SrcMgr.getLineAndColumn(loc, buf).first);
  }
  return result;
}

void tblgen::Pattern::collectBoundSymbols(DagNode tree, SymbolInfoMap &infoMap,
                                          bool isSrcPattern) {
  auto treeName = tree.getSymbol();
  if (!tree.isOperation()) {
    if (!treeName.empty()) {
      PrintFatalError(
          def.getLoc(),
          formatv("binding symbol '{0}' to non-operation unsupported right now",
                  treeName));
    }
    return;
  }

  auto &op = getDialectOp(tree);
  auto numOpArgs = op.getNumArgs();
  auto numTreeArgs = tree.getNumArgs();

  if (numOpArgs != numTreeArgs) {
    auto err = formatv("op '{0}' argument number mismatch: "
                       "{1} in pattern vs. {2} in definition",
                       op.getOperationName(), numTreeArgs, numOpArgs);
    PrintFatalError(def.getLoc(), err);
  }

  // The name attached to the DAG node's operator is for representing the
  // results generated from this op. It should be remembered as bound results.
  if (!treeName.empty()) {
    if (!infoMap.bindOpResult(treeName, op))
      PrintFatalError(def.getLoc(),
                      formatv("symbol '{0}' bound more than once", treeName));
  }

  for (int i = 0; i != numTreeArgs; ++i) {
    if (auto treeArg = tree.getArgAsNestedDag(i)) {
      // This DAG node argument is a DAG node itself. Go inside recursively.
      collectBoundSymbols(treeArg, infoMap, isSrcPattern);
    } else if (isSrcPattern) {
      // We can only bind symbols to op arguments in source pattern. Those
      // symbols are referenced in result patterns.
      auto treeArgName = tree.getArgName(i);
      if (!treeArgName.empty()) {
        if (!infoMap.bindOpArgument(treeArgName, op, i)) {
          auto err = formatv("symbol '{0}' bound more than once", treeArgName);
          PrintFatalError(def.getLoc(), err);
        }
      }
    }
  }
}
<|endoftext|>


<commit_before><commit_msg>Use the positions of the root bone in world space, contrarily to the other bones that are in bone space. This does not seem to be defined in the BVH specifications, but seems more commonly used by the different mocap systems.<commit_after><|endoftext|>


<commit_before>/**************************************************************************
 * Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
 *                                                                        *
 * Author: The ALICE Off-line Project.                                    *
 * Contributors are mentioned in the code where appropriate.              *
 *                                                                        *
 * Permission to use, copy, modify and distribute this software and its   *
 * documentation strictly for non-commercial purposes is hereby granted   *
 * without fee, provided that the above copyright notice appears in all   *
 * copies and that both the copyright notice and this permission notice   *
 * appear in the supporting documentation. The authors make no claims     *
 * about the suitability of this software for any purpose. It is          *
 * provided "as is" without express or implied warranty.                  *
 **************************************************************************/

/*
$Log$
Revision 1.2  2000/10/06 16:49:46  cblume
Made Getters const

Revision 1.1.2.2  2000/10/04 16:34:58  cblume
Replace include files by forward declarations

Revision 1.1.2.1  2000/09/22 14:47:52  cblume
Add the tracking code

*/

#include <TObject.h>

#include "AliRun.h"

#include "AliTRD.h"
#include "AliTRDgeometry.h"
#include "AliTRDcluster.h"
#include "AliTRDtimeBin.h"
#include "AliTRDtrackingSector.h"

ClassImp(AliTRDtrackingSector)

//_______________________________________________________

AliTRDtrackingSector::~AliTRDtrackingSector()
{
  //
  // Destructor
  //

  delete[] fTimeBin;

}

//_______________________________________________________
AliTRDtimeBin &AliTRDtrackingSector::operator[](Int_t i)
{
  //
  // Index operator
  //

  return *(fTimeBin+i);

}

//_______________________________________________________

void AliTRDtrackingSector::SetUp()
{

  AliTRD *TRD = (AliTRD*) gAlice->GetDetector("TRD");
  fGeom = TRD->GetGeometry();

  fTimeBinSize = fGeom->GetTimeBinSize();

  fN = AliTRDgeometry::Nplan() * (Int_t(AliTRDgeometry::DrThick()
                                       /fTimeBinSize) + 1);

  fTimeBin = new AliTRDtimeBin[fN];

}

//______________________________________________________

Double_t AliTRDtrackingSector::GetX(Int_t l) const
{
  if( (l<0) || (l>fN-1)) {
    fprintf(stderr,"AliTRDtrackingSector::GetX: TimeBin index is out of range !\n");
    return -99999.;
  }
  else {

    Int_t tb_per_plane = fN/AliTRDgeometry::Nplan();
    Int_t plane = l/tb_per_plane;
    Int_t time_slice = l%(Int_t(AliTRDgeometry::DrThick()
                               /fTimeBinSize) + 1);

    Float_t t0 = fGeom->GetTime0(plane);
    Double_t x = t0 + time_slice * fTimeBinSize;

    //    cerr<<"plane, tb, x = "<<plane<<","<<time_slice<<","<<x<<endl;

    return x;
  }
}

//______________________________________________________

Double_t AliTRDtrackingSector::GetMaxY(Int_t l) const
{

  if((l<(fN-1)) && (l>-1)) {
    Int_t tb_per_plane = fN/AliTRDgeometry::Nplan();
    Int_t plane = l/tb_per_plane;
    return fGeom->GetChamberWidth(plane);
  }
  else {
    fprintf(stderr,
    "AliTRDtrackingSector::GetMaxY: TimeBin index is out of range !\n");
    if(l<0) return fGeom->GetChamberWidth(0);
    else return fGeom->GetChamberWidth(AliTRDgeometry::Nplan()-1);
  }
}

//______________________________________________________

Int_t AliTRDtrackingSector::GetTimeBinNumber(Double_t x) const
{
  Float_t r_out = fGeom->GetTime0(AliTRDgeometry::Nplan()-1)
                + AliTRDgeometry::DrThick();
  Float_t r_in = fGeom->GetTime0(0);
  //  cerr<<"GetTimeBinNumber: r_in,r_out = "<<r_in<<","<<r_out<<endl;

  if(x >= r_out) return fN-1;
  if(x <= r_in) return 0;

  Float_t gap = fGeom->GetTime0(1) - fGeom->GetTime0(0);
  //  cerr<<"GetTimeBinNumber: gap = "<<gap<<endl;

  Int_t plane = Int_t((x - r_in + fTimeBinSize/2)/gap);
  //  cerr<<"GetTimeBinNumber: plane="<<plane<<endl;

  Int_t local_tb = Int_t((x-fGeom->GetTime0(plane))/fTimeBinSize + 0.5);
  //  cerr<<"GetTimeBinNumber: local_tb="<<local_tb<<endl;

  Int_t time_bin = plane * (Int_t(AliTRDgeometry::DrThick()
                                 /fTimeBinSize) + 1) + local_tb;
  //  cerr<<"GetTimeBinNumber: time_bin = "<<time_bin<<endl;

  return time_bin;
}

//______________________________________________________

Int_t AliTRDtrackingSector::GetTimeBin(Int_t det, Int_t local_tb) const
{
  Int_t plane = fGeom->GetPlane(det);

  Int_t time_bin = plane * (Int_t(AliTRDgeometry::DrThick()
                                 /fTimeBinSize) + 1) + local_tb;
  return time_bin;
}

<commit_msg>Changed timebin 0 to be the one closest to the readout<commit_after>/**************************************************************************
 * Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
 *                                                                        *
 * Author: The ALICE Off-line Project.                                    *
 * Contributors are mentioned in the code where appropriate.              *
 *                                                                        *
 * Permission to use, copy, modify and distribute this software and its   *
 * documentation strictly for non-commercial purposes is hereby granted   *
 * without fee, provided that the above copyright notice appears in all   *
 * copies and that both the copyright notice and this permission notice   *
 * appear in the supporting documentation. The authors make no claims     *
 * about the suitability of this software for any purpose. It is          *
 * provided "as is" without express or implied warranty.                  *
 **************************************************************************/

/*
$Log$
Revision 1.3  2000/10/15 23:40:01  cblume
Remove AliTRDconst

Revision 1.2  2000/10/06 16:49:46  cblume
Made Getters const

Revision 1.1.2.2  2000/10/04 16:34:58  cblume
Replace include files by forward declarations

Revision 1.1.2.1  2000/09/22 14:47:52  cblume
Add the tracking code

*/

#include <TObject.h>

#include "AliRun.h"

#include "AliTRD.h"
#include "AliTRDgeometry.h"
#include "AliTRDcluster.h"
#include "AliTRDtimeBin.h"
#include "AliTRDtrackingSector.h"

ClassImp(AliTRDtrackingSector)

//_______________________________________________________

AliTRDtrackingSector::~AliTRDtrackingSector()
{
  //
  // Destructor
  //

  delete[] fTimeBin;

}

//_______________________________________________________
AliTRDtimeBin &AliTRDtrackingSector::operator[](Int_t i)
{
  //
  // Index operator
  //

  return *(fTimeBin+i);

}

//_______________________________________________________

void AliTRDtrackingSector::SetUp()
{

  AliTRD *TRD = (AliTRD*) gAlice->GetDetector("TRD");
  fGeom = TRD->GetGeometry();

  fTimeBinSize = fGeom->GetTimeBinSize();

  fN = AliTRDgeometry::Nplan() * (Int_t(AliTRDgeometry::DrThick()
                                       /fTimeBinSize) + 1);

  fTimeBin = new AliTRDtimeBin[fN];

}

//______________________________________________________

Double_t AliTRDtrackingSector::GetX(Int_t l) const
{
  if( (l<0) || (l>fN-1)) {
    fprintf(stderr,"AliTRDtrackingSector::GetX: TimeBin index is out of range !\n");
    return -99999.;
  }
  else {

    Int_t tb_per_plane = fN/AliTRDgeometry::Nplan();
    Int_t plane = l/tb_per_plane;
    Int_t time_slice = l%(Int_t(AliTRDgeometry::DrThick()
                               /fTimeBinSize) + 1);

    Float_t t0 = fGeom->GetTime0(plane);
    Double_t x = t0 + time_slice * fTimeBinSize;

    //    cerr<<"plane, tb, x = "<<plane<<","<<time_slice<<","<<x<<endl;

    return x;
  }
}

//______________________________________________________

Double_t AliTRDtrackingSector::GetMaxY(Int_t l) const
{

  if((l<(fN-1)) && (l>-1)) {
    Int_t tb_per_plane = fN/AliTRDgeometry::Nplan();
    Int_t plane = l/tb_per_plane;
    return fGeom->GetChamberWidth(plane);
  }
  else {
    fprintf(stderr,
    "AliTRDtrackingSector::GetMaxY: TimeBin index is out of range !\n");
    if(l<0) return fGeom->GetChamberWidth(0);
    else return fGeom->GetChamberWidth(AliTRDgeometry::Nplan()-1);
  }
}

//______________________________________________________

Int_t AliTRDtrackingSector::GetTimeBinNumber(Double_t x) const
{
  //Float_t r_out = fGeom->GetTime0(AliTRDgeometry::Nplan()-1)
  //              + AliTRDgeometry::DrThick();
  // Changed to new time0 (CBL)
  Float_t r_out = fGeom->GetTime0(AliTRDgeometry::Nplan()-1);
  Float_t r_in = fGeom->GetTime0(0);
  //  cerr<<"GetTimeBinNumber: r_in,r_out = "<<r_in<<","<<r_out<<endl;

  if(x >= r_out) return fN-1;
  if(x <= r_in) return 0;

  Float_t gap = fGeom->GetTime0(1) - fGeom->GetTime0(0);
  //  cerr<<"GetTimeBinNumber: gap = "<<gap<<endl;

  Int_t plane = Int_t((x - r_in + fTimeBinSize/2)/gap);
  //  cerr<<"GetTimeBinNumber: plane="<<plane<<endl;

  Int_t local_tb = Int_t((x-fGeom->GetTime0(plane))/fTimeBinSize + 0.5);
  //  cerr<<"GetTimeBinNumber: local_tb="<<local_tb<<endl;

  Int_t time_bin = plane * (Int_t(AliTRDgeometry::DrThick()
                                 /fTimeBinSize) + 1) + local_tb;
  //  cerr<<"GetTimeBinNumber: time_bin = "<<time_bin<<endl;

  return time_bin;
}

//______________________________________________________

Int_t AliTRDtrackingSector::GetTimeBin(Int_t det, Int_t local_tb) const
{
  Int_t plane = fGeom->GetPlane(det);

  Int_t time_bin = plane * (Int_t(AliTRDgeometry::DrThick()
                                 /fTimeBinSize) + 1) + local_tb;
  return time_bin;
}

<|endoftext|>


<commit_before>/******************************************************************************
 *                    _   _____   __________                                  *
 *                   | | / / _ | / __/_  __/     Visibility                   *
 *                   | |/ / __ |_\ \  / /          Across                     *
 *                   |___/_/ |_/___/ /_/       Space and Time                 *
 *                                                                            *
 * This file is part of VAST. It is subject to the license terms in the       *
 * LICENSE file found in the top-level directory of this distribution and at  *
 * http://vast.io/license. No part of VAST, including this file, may be       *
 * copied, modified, propagated, or distributed except according to the terms *
 * contained in the LICENSE file.                                             *
 ******************************************************************************/

#include "vast/system/indexer.hpp"

#include <new>

#include <caf/all.hpp>

#include "vast/concept/printable/stream.hpp"
#include "vast/concept/printable/vast/expression.hpp"
#include "vast/const_table_slice_handle.hpp"
#include "vast/detail/assert.hpp"
#include "vast/expression.hpp"
#include "vast/filesystem.hpp"
#include "vast/logger.hpp"

#include "vast/system/atoms.hpp"
#include "vast/system/indexer.hpp"

using namespace caf;

namespace vast::system {

indexer_state::indexer_state() : initialized(false) {
  // nop
}

indexer_state::~indexer_state() {
  if (initialized)
    tbl.~table_index();
}

void indexer_state::init(table_index&& from) {
  VAST_ASSERT(!initialized);
  new (&tbl) table_index(std::move(from));
  initialized = true;
}

behavior indexer(stateful_actor<indexer_state>* self, path dir,
                 record_type layout) {
  auto maybe_tbl = make_table_index(std::move(dir), layout);
  if (!maybe_tbl) {
    VAST_ERROR(self, "unable to generate table layout for", layout);
    return {};
  }
  self->state.init(std::move(*maybe_tbl));
  VAST_DEBUG(self, "operates for layout", layout);
  return {
    [=](const predicate& pred) {
      VAST_DEBUG(self, "got predicate:", pred);
      return self->state.tbl.lookup(pred);
    },
    [=](const expression& expr) {
      VAST_DEBUG(self, "got expression:", expr);
      return self->state.tbl.lookup(expr);
    },
    [=](persist_atom) -> result<void> {
      if (auto err = self->state.tbl.flush_to_disk(); err != caf::none)
        return err;
      return caf::unit;
    },
    [=](stream<const_table_slice_handle> in) {
      self->make_sink(
        in,
        [](unit_t&) {
          // nop
        },
        [=](unit_t&, const std::vector<const_table_slice_handle>& xs) {
          for (auto& x : xs)
            self->state.tbl.add(x);
        },
        [=](unit_t&, const error& err) {
          if (err) {
            VAST_ERROR(self, "got a stream error:", self->system().render(err));
          }
        }
      );
    },
    [=](shutdown_atom) { self->quit(exit_reason::user_shutdown); },
  };
}

} // namespace vast::system
<commit_msg>Suppress error log entry for ordinary shutdown<commit_after>/******************************************************************************
 *                    _   _____   __________                                  *
 *                   | | / / _ | / __/_  __/     Visibility                   *
 *                   | |/ / __ |_\ \  / /          Across                     *
 *                   |___/_/ |_/___/ /_/       Space and Time                 *
 *                                                                            *
 * This file is part of VAST. It is subject to the license terms in the       *
 * LICENSE file found in the top-level directory of this distribution and at  *
 * http://vast.io/license. No part of VAST, including this file, may be       *
 * copied, modified, propagated, or distributed except according to the terms *
 * contained in the LICENSE file.                                             *
 ******************************************************************************/

#include "vast/system/indexer.hpp"

#include <new>

#include <caf/all.hpp>

#include "vast/concept/printable/stream.hpp"
#include "vast/concept/printable/vast/expression.hpp"
#include "vast/const_table_slice_handle.hpp"
#include "vast/detail/assert.hpp"
#include "vast/expression.hpp"
#include "vast/filesystem.hpp"
#include "vast/logger.hpp"

#include "vast/system/atoms.hpp"
#include "vast/system/indexer.hpp"

using namespace caf;

namespace vast::system {

indexer_state::indexer_state() : initialized(false) {
  // nop
}

indexer_state::~indexer_state() {
  if (initialized)
    tbl.~table_index();
}

void indexer_state::init(table_index&& from) {
  VAST_ASSERT(!initialized);
  new (&tbl) table_index(std::move(from));
  initialized = true;
}

behavior indexer(stateful_actor<indexer_state>* self, path dir,
                 record_type layout) {
  auto maybe_tbl = make_table_index(std::move(dir), layout);
  if (!maybe_tbl) {
    VAST_ERROR(self, "unable to generate table layout for", layout);
    return {};
  }
  self->state.init(std::move(*maybe_tbl));
  VAST_DEBUG(self, "operates for layout", layout);
  return {
    [=](const predicate& pred) {
      VAST_DEBUG(self, "got predicate:", pred);
      return self->state.tbl.lookup(pred);
    },
    [=](const expression& expr) {
      VAST_DEBUG(self, "got expression:", expr);
      return self->state.tbl.lookup(expr);
    },
    [=](persist_atom) -> result<void> {
      if (auto err = self->state.tbl.flush_to_disk(); err != caf::none)
        return err;
      return caf::unit;
    },
    [=](stream<const_table_slice_handle> in) {
      self->make_sink(
        in,
        [](unit_t&) {
          // nop
        },
        [=](unit_t&, const std::vector<const_table_slice_handle>& xs) {
          for (auto& x : xs)
            self->state.tbl.add(x);
        },
        [=](unit_t&, const error& err) {
          if (err && err != caf::exit_reason::user_shutdown) {
            VAST_ERROR(self, "got a stream error:", self->system().render(err));
          }
        }
      );
    },
    [=](shutdown_atom) { self->quit(exit_reason::user_shutdown); },
  };
}

} // namespace vast::system
<|endoftext|>


<commit_before>/* -*- mode: C++; c-basic-offset: 4; indent-tabs-mode: nil -*- */

#pragma once

#include <string>

#include <db.h>

#include "cursor.hpp"
#include "db_env.hpp"
#include "db_txn.hpp"
#include "exceptions.hpp"
#include "slice.hpp"
#include "stats.hpp"

namespace ftcxx {

    template<class Comparator, class Handler>
    class CallbackCursor;
    template<class Comparator, class Predicate>
    class BufferedCursor;
    template<class Comparator>
    class SimpleCursor;

    class DB {
    public:
        DB()
            : _db(nullptr)
        {}

        explicit DB(::DB *d)
            : _db(d)
        {}

        ~DB() {
            if (_db) {
                close();
            }
        }

        DB(const DB &) = delete;
        DB& operator=(const DB &) = delete;

        DB(DB &&o)
            : _db(nullptr)
        {
            std::swap(_db, o._db);
        }

        DB& operator=(DB &&o) {
            std::swap(_db, o._db);
            return *this;
        }

        ::DB *db() const { return _db; }

        Slice descriptor() const {
            return Slice(_db->cmp_descriptor->dbt);
        }

        template<typename Callback>
        int getf_set(const DBTxn &txn, const Slice &key, int flags, Callback cb) const {
            class WrappedCallback {
                Callback &_cb;
            public:
                WrappedCallback(Callback &cb_)
                    : _cb(cb_)
                {}

                static int call(const DBT *key_, const DBT *val_, void *extra) {
                    WrappedCallback *wc = static_cast<WrappedCallback *>(extra);
                    return wc->call(key_, val_);
                }

                int call(const DBT *key_, const DBT *val_) {
                    return _cb(Slice(*key_), Slice(*val_));
                }
            } wc(cb);

            DBT kdbt = key.dbt();
            return _db->getf_set(_db, txn.txn(), flags, &kdbt, &WrappedCallback::call, &wc);
        }

        int put(const DBTxn &txn, DBT *key, DBT *val, int flags=0) const {
            return _db->put(_db, txn.txn(), key, val, flags);
        }

        int put(const DBTxn &txn, const Slice &key, const Slice &val, int flags=0) const {
            DBT kdbt = key.dbt();
            DBT vdbt = val.dbt();
            return put(txn, &kdbt, &vdbt, flags);
        }

        int del(const DBTxn &txn, DBT *key, int flags=0) const {
            return _db->del(_db, txn.txn(), key, flags);
        }

        int del(const DBTxn &txn, const Slice &key, int flags=0) const {
            DBT kdbt = key.dbt();
            return _db->del(_db, txn.txn(), &kdbt, flags);
        }

        Stats get_stats() const {
            Stats stats;
            DB_BTREE_STAT64 s = {0, 0, 0};
            int r = _db->stat64(_db, NULL, &s);
            handle_ft_retval(r);
            stats.dataSize = s.bt_dsize;
            stats.fileSize = s.bt_fsize;
            stats.numberOfKeys = s.bt_nkeys;
            return stats;
        }

        struct NullFilter {
            bool operator()(const Slice &, const Slice &) {
                return true;
            }
        };

        /**
         * Constructs a Cursor over this DB, over the range from left to
         * right (or right to left if !forward).
         */
        template<class Comparator, class Handler>
        CallbackCursor<Comparator, Handler> cursor(const DBTxn &txn, DBT *left, DBT *right,
                                                   Comparator &&cmp, Handler &&handler, int flags=0,
                                                   bool forward=true, bool end_exclusive=false, bool prelock=true) const;

        template<class Comparator, class Handler>
        CallbackCursor<Comparator, Handler> cursor(const DBTxn &txn, const Slice &left, const Slice &right,
                                                   Comparator &&cmp, Handler &&handler, int flags=0,
                                                   bool forward=true, bool end_exclusive=false, bool prelock=true) const;

        template<class Comparator, class Handler>
        CallbackCursor<Comparator, Handler> cursor(const DBTxn &txn, Comparator &&cmp, Handler &&handler,
                                                   int flags=0, bool forward=true, bool prelock=true) const;

        template<class Comparator, class Predicate>
        BufferedCursor<Comparator, Predicate> buffered_cursor(const DBTxn &txn, DBT *left, DBT *right,
                                                              Comparator &&cmp, Predicate &&filter, int flags=0,
                                                              bool forward=true, bool end_exclusive=false, bool prelock=true) const;

        template<class Comparator, class Predicate>
        BufferedCursor<Comparator, Predicate> buffered_cursor(const DBTxn &txn, const Slice &left, const Slice &right,
                                                              Comparator &&cmp, Predicate &&filter, int flags=0,
                                                              bool forward=true, bool end_exclusive=false, bool prelock=true) const;

        template<class Comparator, class Predicate>
        BufferedCursor<Comparator, Predicate> buffered_cursor(const DBTxn &txn, Comparator &&cmp, Predicate &&filter,
                                                              int flags=0, bool forward=true, bool prelock=true) const;

        template<class Comparator>
        SimpleCursor<Comparator> simple_cursor(const DBTxn &txn, DBT *left, DBT *right,
                                               Comparator &&cmp, Slice &key, Slice &val, int flags=0,
                                               bool forward=true, bool end_exclusive=false, bool prelock=true) const;

        template<class Comparator>
        SimpleCursor<Comparator> simple_cursor(const DBTxn &txn, const Slice &left, const Slice &right,
                                               Comparator &&cmp, Slice &key, Slice &val, int flags=0,
                                               bool forward=true, bool end_exclusive=false, bool prelock=true) const;

        template<class Comparator>
        SimpleCursor<Comparator> simple_cursor(const DBTxn &txn, Comparator &&cmp, Slice &key, Slice &val,
                                               int flags=0, bool forward=true, bool prelock=true) const;

        void close() {
            int r = _db->close(_db, 0);
            handle_ft_retval(r);
            _db = nullptr;
        }

    private:
        ::DB *_db;
    };

    class DBBuilder {
        uint32_t _readpagesize;
        TOKU_COMPRESSION_METHOD _compression_method;
        uint32_t _fanout;
        uint8_t _memcmp_magic;
        uint32_t _pagesize;
        Slice _descriptor;

    public:
        DBBuilder()
            : _readpagesize(0),
              _compression_method(TOKU_COMPRESSION_METHOD(0)),
              _fanout(0),
              _memcmp_magic(0),
              _pagesize(0),
              _descriptor()
        {}

        DB open(const DBEnv &env, const DBTxn &txn, const char *fname, const char *dbname, DBTYPE dbtype, uint32_t flags, int mode) const {
            ::DB *db;
            int r = db_create(&db, env.env(), 0);
            handle_ft_retval(r);

            if (_readpagesize) {
                r = db->set_readpagesize(db, _readpagesize);
                handle_ft_retval(r);
            }

            if (_compression_method) {
                r = db->set_compression_method(db, _compression_method);
                handle_ft_retval(r);
            }

            if (_fanout) {
                r = db->set_fanout(db, _fanout);
                handle_ft_retval(r);
            }

            if (_memcmp_magic) {
                r = db->set_memcmp_magic(db, _memcmp_magic);
                handle_ft_retval(r);
            }

            if (_pagesize) {
                r = db->set_pagesize(db, _pagesize);
                handle_ft_retval(r);
            }

            r = db->open(db, txn.txn(), fname, dbname, dbtype, flags, mode);
            handle_ft_retval(r);

            if (!_descriptor.empty()) {
                DBT desc = _descriptor.dbt();
                r = db->change_descriptor(db, txn.txn(), &desc, DB_UPDATE_CMP_DESCRIPTOR);
                handle_ft_retval(r);
            }

            return DB(db);
        }

        DBBuilder& set_readpagesize(uint32_t readpagesize) {
            _readpagesize = readpagesize;
            return *this;
        }

        DBBuilder& set_compression_method(TOKU_COMPRESSION_METHOD _compressionmethod) {
            _compression_method = _compressionmethod;
            return *this;
        }

        DBBuilder& set_fanout(uint32_t fanout) {
            _fanout = fanout;
            return *this;
        }

        DBBuilder& set_memcmp_magic(uint8_t _memcmpmagic) {
            _memcmp_magic = _memcmpmagic;
            return *this;
        }

        DBBuilder& set_pagesize(uint32_t pagesize) {
            _pagesize = pagesize;
            return *this;
        }

        DBBuilder& set_descriptor(const Slice &desc) {
            _descriptor = desc;
            return *this;
        }
    };

} // namespace ftcxx
<commit_msg>allow temporary construction of ftcxx::DB<commit_after>/* -*- mode: C++; c-basic-offset: 4; indent-tabs-mode: nil -*- */

#pragma once

#include <string>

#include <db.h>

#include "cursor.hpp"
#include "db_env.hpp"
#include "db_txn.hpp"
#include "exceptions.hpp"
#include "slice.hpp"
#include "stats.hpp"

namespace ftcxx {

    template<class Comparator, class Handler>
    class CallbackCursor;
    template<class Comparator, class Predicate>
    class BufferedCursor;
    template<class Comparator>
    class SimpleCursor;

    class DB {
    public:
        DB()
            : _db(nullptr),
              _close_on_destroy(false)
        {}

        explicit DB(::DB *d, bool close_on_destroy=false)
            : _db(d),
              _close_on_destroy(close_on_destroy)
        {}

        ~DB() {
            if (_db && _close_on_destroy) {
                close();
            }
        }

        DB(const DB &) = delete;
        DB& operator=(const DB &) = delete;

        DB(DB &&o)
            : _db(nullptr),
              _close_on_destroy(false)
        {
            std::swap(_db, o._db);
            std::swap(_close_on_destroy, o._close_on_destroy);
        }

        DB& operator=(DB &&o) {
            std::swap(_db, o._db);
            std::swap(_close_on_destroy, o._close_on_destroy);
            return *this;
        }

        ::DB *db() const { return _db; }

        Slice descriptor() const {
            return Slice(_db->cmp_descriptor->dbt);
        }

        template<typename Callback>
        int getf_set(const DBTxn &txn, const Slice &key, int flags, Callback cb) const {
            class WrappedCallback {
                Callback &_cb;
            public:
                WrappedCallback(Callback &cb_)
                    : _cb(cb_)
                {}

                static int call(const DBT *key_, const DBT *val_, void *extra) {
                    WrappedCallback *wc = static_cast<WrappedCallback *>(extra);
                    return wc->call(key_, val_);
                }

                int call(const DBT *key_, const DBT *val_) {
                    return _cb(Slice(*key_), Slice(*val_));
                }
            } wc(cb);

            DBT kdbt = key.dbt();
            return _db->getf_set(_db, txn.txn(), flags, &kdbt, &WrappedCallback::call, &wc);
        }

        int put(const DBTxn &txn, DBT *key, DBT *val, int flags=0) const {
            return _db->put(_db, txn.txn(), key, val, flags);
        }

        int put(const DBTxn &txn, const Slice &key, const Slice &val, int flags=0) const {
            DBT kdbt = key.dbt();
            DBT vdbt = val.dbt();
            return put(txn, &kdbt, &vdbt, flags);
        }

        int del(const DBTxn &txn, DBT *key, int flags=0) const {
            return _db->del(_db, txn.txn(), key, flags);
        }

        int del(const DBTxn &txn, const Slice &key, int flags=0) const {
            DBT kdbt = key.dbt();
            return _db->del(_db, txn.txn(), &kdbt, flags);
        }

        Stats get_stats() const {
            Stats stats;
            DB_BTREE_STAT64 s = {0, 0, 0};
            int r = _db->stat64(_db, NULL, &s);
            handle_ft_retval(r);
            stats.dataSize = s.bt_dsize;
            stats.fileSize = s.bt_fsize;
            stats.numberOfKeys = s.bt_nkeys;
            return stats;
        }

        struct NullFilter {
            bool operator()(const Slice &, const Slice &) {
                return true;
            }
        };

        /**
         * Constructs a Cursor over this DB, over the range from left to
         * right (or right to left if !forward).
         */
        template<class Comparator, class Handler>
        CallbackCursor<Comparator, Handler> cursor(const DBTxn &txn, DBT *left, DBT *right,
                                                   Comparator &&cmp, Handler &&handler, int flags=0,
                                                   bool forward=true, bool end_exclusive=false, bool prelock=true) const;

        template<class Comparator, class Handler>
        CallbackCursor<Comparator, Handler> cursor(const DBTxn &txn, const Slice &left, const Slice &right,
                                                   Comparator &&cmp, Handler &&handler, int flags=0,
                                                   bool forward=true, bool end_exclusive=false, bool prelock=true) const;

        template<class Comparator, class Handler>
        CallbackCursor<Comparator, Handler> cursor(const DBTxn &txn, Comparator &&cmp, Handler &&handler,
                                                   int flags=0, bool forward=true, bool prelock=true) const;

        template<class Comparator, class Predicate>
        BufferedCursor<Comparator, Predicate> buffered_cursor(const DBTxn &txn, DBT *left, DBT *right,
                                                              Comparator &&cmp, Predicate &&filter, int flags=0,
                                                              bool forward=true, bool end_exclusive=false, bool prelock=true) const;

        template<class Comparator, class Predicate>
        BufferedCursor<Comparator, Predicate> buffered_cursor(const DBTxn &txn, const Slice &left, const Slice &right,
                                                              Comparator &&cmp, Predicate &&filter, int flags=0,
                                                              bool forward=true, bool end_exclusive=false, bool prelock=true) const;

        template<class Comparator, class Predicate>
        BufferedCursor<Comparator, Predicate> buffered_cursor(const DBTxn &txn, Comparator &&cmp, Predicate &&filter,
                                                              int flags=0, bool forward=true, bool prelock=true) const;

        template<class Comparator>
        SimpleCursor<Comparator> simple_cursor(const DBTxn &txn, DBT *left, DBT *right,
                                               Comparator &&cmp, Slice &key, Slice &val, int flags=0,
                                               bool forward=true, bool end_exclusive=false, bool prelock=true) const;

        template<class Comparator>
        SimpleCursor<Comparator> simple_cursor(const DBTxn &txn, const Slice &left, const Slice &right,
                                               Comparator &&cmp, Slice &key, Slice &val, int flags=0,
                                               bool forward=true, bool end_exclusive=false, bool prelock=true) const;

        template<class Comparator>
        SimpleCursor<Comparator> simple_cursor(const DBTxn &txn, Comparator &&cmp, Slice &key, Slice &val,
                                               int flags=0, bool forward=true, bool prelock=true) const;

        void close() {
            int r = _db->close(_db, 0);
            handle_ft_retval(r);
            _db = nullptr;
        }

    private:
        ::DB *_db;
        bool _close_on_destroy;
    };

    class DBBuilder {
        uint32_t _readpagesize;
        TOKU_COMPRESSION_METHOD _compression_method;
        uint32_t _fanout;
        uint8_t _memcmp_magic;
        uint32_t _pagesize;
        Slice _descriptor;

    public:
        DBBuilder()
            : _readpagesize(0),
              _compression_method(TOKU_COMPRESSION_METHOD(0)),
              _fanout(0),
              _memcmp_magic(0),
              _pagesize(0),
              _descriptor()
        {}

        DB open(const DBEnv &env, const DBTxn &txn, const char *fname, const char *dbname, DBTYPE dbtype, uint32_t flags, int mode) const {
            ::DB *db;
            int r = db_create(&db, env.env(), 0);
            handle_ft_retval(r);

            if (_readpagesize) {
                r = db->set_readpagesize(db, _readpagesize);
                handle_ft_retval(r);
            }

            if (_compression_method) {
                r = db->set_compression_method(db, _compression_method);
                handle_ft_retval(r);
            }

            if (_fanout) {
                r = db->set_fanout(db, _fanout);
                handle_ft_retval(r);
            }

            if (_memcmp_magic) {
                r = db->set_memcmp_magic(db, _memcmp_magic);
                handle_ft_retval(r);
            }

            if (_pagesize) {
                r = db->set_pagesize(db, _pagesize);
                handle_ft_retval(r);
            }

            r = db->open(db, txn.txn(), fname, dbname, dbtype, flags, mode);
            handle_ft_retval(r);

            if (!_descriptor.empty()) {
                DBT desc = _descriptor.dbt();
                r = db->change_descriptor(db, txn.txn(), &desc, DB_UPDATE_CMP_DESCRIPTOR);
                handle_ft_retval(r);
            }

            return DB(db, true);
        }

        DBBuilder& set_readpagesize(uint32_t readpagesize) {
            _readpagesize = readpagesize;
            return *this;
        }

        DBBuilder& set_compression_method(TOKU_COMPRESSION_METHOD _compressionmethod) {
            _compression_method = _compressionmethod;
            return *this;
        }

        DBBuilder& set_fanout(uint32_t fanout) {
            _fanout = fanout;
            return *this;
        }

        DBBuilder& set_memcmp_magic(uint8_t _memcmpmagic) {
            _memcmp_magic = _memcmpmagic;
            return *this;
        }

        DBBuilder& set_pagesize(uint32_t pagesize) {
            _pagesize = pagesize;
            return *this;
        }

        DBBuilder& set_descriptor(const Slice &desc) {
            _descriptor = desc;
            return *this;
        }
    };

} // namespace ftcxx
<|endoftext|>


<commit_before>// #include <stdexcept>
// #include <string>

#include "function.hxx"

function::operator double () const
{
  return _fptr(_args);
}

void function::replace(const unsigned idx, const fnbase_ptr arg)
{
  // if (idx >= _args.size())
  //   throw std::out_of_range("Index out of range, " + std::to_string(idx)
  // 			    + " >= " + std::to_string(_args.size()) + "\n");
  _args.at(idx) = arg;
}

auto function::components() -> fnbase_vec &
{
  return _args;
}
<commit_msg>Handle range checking myself<commit_after>#include <stdexcept>
#include <string>

#include "function.hxx"

function::operator double () const
{
  return _fptr(_args);
}

void function::replace(const unsigned idx, const fnbase_ptr arg)
{
  if (idx >= _args.size())
    throw std::out_of_range("Index out of range: "
			    + std::to_string(_args.size()) + "(size) <= "
			    + std::to_string(idx) + "(index)");
  _args.at(idx) = arg;
}

auto function::components() -> fnbase_vec &
{
  return _args;
}
<|endoftext|>


<commit_before>//
// PROJECT:         Aspia Remote Desktop
// FILE:            host/file_transfer_session_client.cc
// LICENSE:         Mozilla Public License Version 2.0
// PROGRAMMERS:     Dmitry Chapyshev (dmitry@aspia.ru)
//

#include "host/file_transfer_session_client.h"
#include "base/files/file_helpers.h"
#include "base/strings/unicode.h"
#include "protocol/message_serialization.h"
#include "protocol/filesystem.h"
#include "proto/auth_session.pb.h"

namespace aspia {

namespace fs = std::experimental::filesystem;

void FileTransferSessionClient::Run(const std::wstring& input_channel_name,
                                    const std::wstring& output_channel_name)
{
    status_dialog_ = std::make_unique<UiFileStatusDialog>();

    ipc_channel_ = PipeChannel::CreateClient(input_channel_name,
                                             output_channel_name);
    if (ipc_channel_)
    {
        if (ipc_channel_->Connect(GetCurrentProcessId(), this))
        {
            status_dialog_->WaitForClose();
        }

        ipc_channel_.reset();
    }

    status_dialog_.reset();
}

void FileTransferSessionClient::OnPipeChannelConnect(uint32_t user_data)
{
    // The server sends the session type in user_data.
    proto::SessionType session_type = static_cast<proto::SessionType>(user_data);

    if (session_type != proto::SessionType::SESSION_TYPE_FILE_TRANSFER)
    {
        LOG(FATAL) << "Invalid session type passed: " << session_type;
        return;
    }

    status_dialog_->SetSessionStartedStatus();
}

void FileTransferSessionClient::OnPipeChannelDisconnect()
{
    status_dialog_->SetSessionTerminatedStatus();
}

void FileTransferSessionClient::OnPipeChannelMessage(const IOBuffer& buffer)
{
    proto::file_transfer::ClientToHost message;

    if (!ParseMessage(buffer, message))
    {
        ipc_channel_->Close();
        return;
    }

    switch (message.type())
    {
        case proto::RequestType::REQUEST_TYPE_DRIVE_LIST:
            ReadDriveListRequest();
            break;

        case proto::RequestType::REQUEST_TYPE_FILE_LIST:
            ReadFileListRequest(message.file_list_request());
            break;

        case proto::RequestType::REQUEST_TYPE_DIRECTORY_SIZE:
            ReadDirectorySizeRequest(message.directory_size_request());
            break;

        case proto::RequestType::REQUEST_TYPE_CREATE_DIRECTORY:
            ReadCreateDirectoryRequest(message.create_directory_request());
            break;

        case proto::RequestType::REQUEST_TYPE_RENAME:
            ReadRenameRequest(message.rename_request());
            break;

        case proto::RequestType::REQUEST_TYPE_REMOVE:
            ReadRemoveRequest(message.remove_request());
            break;

        case proto::RequestType::REQUEST_TYPE_FILE_UPLOAD:
            ReadFileUploadRequest(message.file_upload_request());
            break;

        case proto::RequestType::REQUEST_TYPE_FILE_UPLOAD_DATA:
        {
            if (!ReadFileUploadDataRequest(message.file_packet()))
                ipc_channel_->Close();
        }
        break;

        case proto::RequestType::REQUEST_TYPE_FILE_DOWNLOAD:
            ReadFileDownloadRequest(message.file_download_request());
            break;

        case proto::RequestType::REQUEST_TYPE_FILE_DOWNLOAD_DATA:
        {
            if (!ReadFileDownloadDataRequest())
                ipc_channel_->Close();
        }
        break;

        default:
            LOG(ERROR) << "Unknown message from client: " << message.type();
            ipc_channel_->Close();
            break;
    }
}

void FileTransferSessionClient::SendReply(
    const proto::file_transfer::HostToClient& reply)
{
    IOBuffer buffer(SerializeMessage<IOBuffer>(reply));
    std::lock_guard<std::mutex> lock(outgoing_lock_);
    ipc_channel_->Send(buffer);
}

void FileTransferSessionClient::ReadDriveListRequest()
{
    proto::file_transfer::HostToClient reply;
    reply.set_type(proto::RequestType::REQUEST_TYPE_DRIVE_LIST);
    reply.set_status(ExecuteDriveListRequest(reply.mutable_drive_list()));

    status_dialog_->SetDriveListRequestStatus(reply.status());
    SendReply(reply);
}

void FileTransferSessionClient::ReadFileListRequest(
    const proto::FileListRequest& request)
{
    proto::file_transfer::HostToClient reply;

    FilePath path = fs::u8path(request.path());

    reply.set_type(proto::RequestType::REQUEST_TYPE_FILE_LIST);
    reply.set_status(ExecuteFileListRequest(path, reply.mutable_file_list()));

    status_dialog_->SetFileListRequestStatus(path, reply.status());
    SendReply(reply);
}

void FileTransferSessionClient::ReadCreateDirectoryRequest(
    const proto::CreateDirectoryRequest& request)
{
    proto::file_transfer::HostToClient reply;

    FilePath path = fs::u8path(request.path());

    reply.set_type(proto::RequestType::REQUEST_TYPE_CREATE_DIRECTORY);
    reply.set_status(ExecuteCreateDirectoryRequest(path));

    status_dialog_->SetCreateDirectoryRequestStatus(path, reply.status());
    SendReply(reply);
}

void FileTransferSessionClient::ReadDirectorySizeRequest(
    const proto::DirectorySizeRequest& request)
{
    proto::file_transfer::HostToClient reply;

    FilePath path = fs::u8path(request.path());

    reply.set_type(proto::RequestType::REQUEST_TYPE_DIRECTORY_SIZE);

    uint64_t directory_size = 0;

    reply.set_status(ExecuteDirectorySizeRequest(path, directory_size));
    reply.mutable_directory_size()->set_size(directory_size);

    SendReply(reply);
}

void FileTransferSessionClient::ReadRenameRequest(
    const proto::RenameRequest& request)
{
    proto::file_transfer::HostToClient reply;

    FilePath old_name = fs::u8path(request.old_name());
    FilePath new_name = fs::u8path(request.new_name());

    reply.set_type(proto::RequestType::REQUEST_TYPE_RENAME);
    reply.set_status(ExecuteRenameRequest(old_name, new_name));

    status_dialog_->SetRenameRequestStatus(old_name, new_name, reply.status());
    SendReply(reply);
}

void FileTransferSessionClient::ReadRemoveRequest(
    const proto::RemoveRequest& request)
{
    proto::file_transfer::HostToClient reply;

    FilePath path = fs::u8path(request.path());

    reply.set_type(proto::RequestType::REQUEST_TYPE_REMOVE);
    reply.set_status(ExecuteRemoveRequest(path));

    status_dialog_->SetRemoveRequestStatus(path, reply.status());
    SendReply(reply);
}

void FileTransferSessionClient::ReadFileUploadRequest(
    const proto::FileUploadRequest& request)
{
    proto::file_transfer::HostToClient reply;
    reply.set_type(proto::RequestType::REQUEST_TYPE_FILE_UPLOAD);

    FilePath file_path = fs::u8path(request.file_path());

    if (!IsValidPathName(file_path))
    {
        reply.set_status(proto::RequestStatus::REQUEST_STATUS_INVALID_PATH_NAME);
    }
    else
    {
        file_depacketizer_ = FileDepacketizer::Create(file_path);
        if (!file_depacketizer_)
        {
            reply.set_status(proto::RequestStatus::REQUEST_STATUS_FILE_CREATE_ERROR);
        }
    }

    status_dialog_->SetFileUploadRequestStatus(file_path, reply.status());

    SendReply(reply);
}

bool FileTransferSessionClient::ReadFileUploadDataRequest(
    const proto::FilePacket& file_packet)
{
    if (!file_depacketizer_)
    {
        LOG(ERROR) << "Unexpected upload data request";
        return false;
    }

    proto::file_transfer::HostToClient reply;
    reply.set_type(proto::RequestType::REQUEST_TYPE_FILE_UPLOAD_DATA);

    if (!file_depacketizer_->ReadNextPacket(file_packet))
    {
        reply.set_status(proto::RequestStatus::REQUEST_STATUS_FILE_WRITE_ERROR);
    }

    if (file_packet.flags() & proto::FilePacket::LAST_PACKET)
    {
        file_depacketizer_.reset();
    }

    SendReply(reply);
    return true;
}

void FileTransferSessionClient::ReadFileDownloadRequest(
    const proto::FileDownloadRequest& request)
{
    proto::file_transfer::HostToClient reply;
    reply.set_type(proto::RequestType::REQUEST_TYPE_FILE_DOWNLOAD);

    FilePath file_path = fs::u8path(request.file_path());

    if (!IsValidPathName(file_path))
    {
        reply.set_status(proto::RequestStatus::REQUEST_STATUS_INVALID_PATH_NAME);
    }
    else
    {
        file_packetizer_ = FilePacketizer::Create(file_path);
        if (!file_packetizer_)
        {
            reply.set_status(proto::RequestStatus::REQUEST_STATUS_FILE_OPEN_ERROR);
        }
    }

    SendReply(reply);
}

bool FileTransferSessionClient::ReadFileDownloadDataRequest()
{
    if (!file_packetizer_)
    {
        LOG(ERROR) << "Unexpected download data request";
        return false;
    }

    proto::file_transfer::HostToClient reply;
    reply.set_type(proto::RequestType::REQUEST_TYPE_FILE_DOWNLOAD_DATA);

    std::unique_ptr<proto::FilePacket> packet =
        file_packetizer_->CreateNextPacket();

    if (!packet)
    {
        reply.set_status(proto::RequestStatus::REQUEST_STATUS_FILE_READ_ERROR);
    }
    else
    {
        if (packet->flags() & proto::FilePacket::LAST_PACKET)
        {
            file_packetizer_.reset();
        }

        reply.set_allocated_file_packet(packet.release());
    }

    SendReply(reply);
    return true;
}

} // namespace aspia
<commit_msg>Added file existence check<commit_after>//
// PROJECT:         Aspia Remote Desktop
// FILE:            host/file_transfer_session_client.cc
// LICENSE:         Mozilla Public License Version 2.0
// PROGRAMMERS:     Dmitry Chapyshev (dmitry@aspia.ru)
//

#include "host/file_transfer_session_client.h"
#include "base/files/file_helpers.h"
#include "base/strings/unicode.h"
#include "protocol/message_serialization.h"
#include "protocol/filesystem.h"
#include "proto/auth_session.pb.h"

namespace aspia {

namespace fs = std::experimental::filesystem;

void FileTransferSessionClient::Run(const std::wstring& input_channel_name,
                                    const std::wstring& output_channel_name)
{
    status_dialog_ = std::make_unique<UiFileStatusDialog>();

    ipc_channel_ = PipeChannel::CreateClient(input_channel_name,
                                             output_channel_name);
    if (ipc_channel_)
    {
        if (ipc_channel_->Connect(GetCurrentProcessId(), this))
        {
            status_dialog_->WaitForClose();
        }

        ipc_channel_.reset();
    }

    status_dialog_.reset();
}

void FileTransferSessionClient::OnPipeChannelConnect(uint32_t user_data)
{
    // The server sends the session type in user_data.
    proto::SessionType session_type = static_cast<proto::SessionType>(user_data);

    if (session_type != proto::SESSION_TYPE_FILE_TRANSFER)
    {
        LOG(FATAL) << "Invalid session type passed: " << session_type;
        return;
    }

    status_dialog_->SetSessionStartedStatus();
}

void FileTransferSessionClient::OnPipeChannelDisconnect()
{
    status_dialog_->SetSessionTerminatedStatus();
}

void FileTransferSessionClient::OnPipeChannelMessage(const IOBuffer& buffer)
{
    proto::file_transfer::ClientToHost message;

    if (!ParseMessage(buffer, message))
    {
        ipc_channel_->Close();
        return;
    }

    switch (message.type())
    {
        case proto::REQUEST_TYPE_DRIVE_LIST:
            ReadDriveListRequest();
            break;

        case proto::REQUEST_TYPE_FILE_LIST:
            ReadFileListRequest(message.file_list_request());
            break;

        case proto::REQUEST_TYPE_DIRECTORY_SIZE:
            ReadDirectorySizeRequest(message.directory_size_request());
            break;

        case proto::REQUEST_TYPE_CREATE_DIRECTORY:
            ReadCreateDirectoryRequest(message.create_directory_request());
            break;

        case proto::REQUEST_TYPE_RENAME:
            ReadRenameRequest(message.rename_request());
            break;

        case proto::REQUEST_TYPE_REMOVE:
            ReadRemoveRequest(message.remove_request());
            break;

        case proto::REQUEST_TYPE_FILE_UPLOAD:
            ReadFileUploadRequest(message.file_upload_request());
            break;

        case proto::REQUEST_TYPE_FILE_UPLOAD_DATA:
        {
            if (!ReadFileUploadDataRequest(message.file_packet()))
                ipc_channel_->Close();
        }
        break;

        case proto::REQUEST_TYPE_FILE_DOWNLOAD:
            ReadFileDownloadRequest(message.file_download_request());
            break;

        case proto::REQUEST_TYPE_FILE_DOWNLOAD_DATA:
        {
            if (!ReadFileDownloadDataRequest())
                ipc_channel_->Close();
        }
        break;

        default:
            LOG(ERROR) << "Unknown message from client: " << message.type();
            ipc_channel_->Close();
            break;
    }
}

void FileTransferSessionClient::SendReply(
    const proto::file_transfer::HostToClient& reply)
{
    IOBuffer buffer(SerializeMessage<IOBuffer>(reply));
    std::lock_guard<std::mutex> lock(outgoing_lock_);
    ipc_channel_->Send(buffer);
}

void FileTransferSessionClient::ReadDriveListRequest()
{
    proto::file_transfer::HostToClient reply;
    reply.set_type(proto::REQUEST_TYPE_DRIVE_LIST);
    reply.set_status(ExecuteDriveListRequest(reply.mutable_drive_list()));

    status_dialog_->SetDriveListRequestStatus(reply.status());
    SendReply(reply);
}

void FileTransferSessionClient::ReadFileListRequest(
    const proto::FileListRequest& request)
{
    proto::file_transfer::HostToClient reply;

    FilePath path = fs::u8path(request.path());

    reply.set_type(proto::REQUEST_TYPE_FILE_LIST);
    reply.set_status(ExecuteFileListRequest(path, reply.mutable_file_list()));

    status_dialog_->SetFileListRequestStatus(path, reply.status());
    SendReply(reply);
}

void FileTransferSessionClient::ReadCreateDirectoryRequest(
    const proto::CreateDirectoryRequest& request)
{
    proto::file_transfer::HostToClient reply;

    FilePath path = fs::u8path(request.path());

    reply.set_type(proto::REQUEST_TYPE_CREATE_DIRECTORY);
    reply.set_status(ExecuteCreateDirectoryRequest(path));

    status_dialog_->SetCreateDirectoryRequestStatus(path, reply.status());
    SendReply(reply);
}

void FileTransferSessionClient::ReadDirectorySizeRequest(
    const proto::DirectorySizeRequest& request)
{
    proto::file_transfer::HostToClient reply;

    FilePath path = fs::u8path(request.path());

    reply.set_type(proto::REQUEST_TYPE_DIRECTORY_SIZE);

    uint64_t directory_size = 0;

    reply.set_status(ExecuteDirectorySizeRequest(path, directory_size));
    reply.mutable_directory_size()->set_size(directory_size);

    SendReply(reply);
}

void FileTransferSessionClient::ReadRenameRequest(
    const proto::RenameRequest& request)
{
    proto::file_transfer::HostToClient reply;

    FilePath old_name = fs::u8path(request.old_name());
    FilePath new_name = fs::u8path(request.new_name());

    reply.set_type(proto::REQUEST_TYPE_RENAME);
    reply.set_status(ExecuteRenameRequest(old_name, new_name));

    status_dialog_->SetRenameRequestStatus(old_name, new_name, reply.status());
    SendReply(reply);
}

void FileTransferSessionClient::ReadRemoveRequest(
    const proto::RemoveRequest& request)
{
    proto::file_transfer::HostToClient reply;

    FilePath path = fs::u8path(request.path());

    reply.set_type(proto::REQUEST_TYPE_REMOVE);
    reply.set_status(ExecuteRemoveRequest(path));

    status_dialog_->SetRemoveRequestStatus(path, reply.status());
    SendReply(reply);
}

void FileTransferSessionClient::ReadFileUploadRequest(
    const proto::FileUploadRequest& request)
{
    proto::file_transfer::HostToClient reply;
    reply.set_type(proto::REQUEST_TYPE_FILE_UPLOAD);

    FilePath file_path = fs::u8path(request.file_path());

    if (!IsValidPathName(file_path))
    {
        reply.set_status(proto::REQUEST_STATUS_INVALID_PATH_NAME);
    }
    else
    {
        std::error_code code;

        if (fs::exists(file_path, code))
        {
            reply.set_status(proto::REQUEST_STATUS_PATH_ALREADY_EXISTS);
        }
        else
        {
            file_depacketizer_ = FileDepacketizer::Create(file_path);
            if (!file_depacketizer_)
            {
                reply.set_status(proto::REQUEST_STATUS_FILE_CREATE_ERROR);
            }
        }
    }

    status_dialog_->SetFileUploadRequestStatus(file_path, reply.status());

    SendReply(reply);
}

bool FileTransferSessionClient::ReadFileUploadDataRequest(
    const proto::FilePacket& file_packet)
{
    if (!file_depacketizer_)
    {
        LOG(ERROR) << "Unexpected upload data request";
        return false;
    }

    proto::file_transfer::HostToClient reply;
    reply.set_type(proto::REQUEST_TYPE_FILE_UPLOAD_DATA);

    if (!file_depacketizer_->ReadNextPacket(file_packet))
    {
        reply.set_status(proto::REQUEST_STATUS_FILE_WRITE_ERROR);
    }

    if (file_packet.flags() & proto::FilePacket::LAST_PACKET)
    {
        file_depacketizer_.reset();
    }

    SendReply(reply);
    return true;
}

void FileTransferSessionClient::ReadFileDownloadRequest(
    const proto::FileDownloadRequest& request)
{
    proto::file_transfer::HostToClient reply;
    reply.set_type(proto::REQUEST_TYPE_FILE_DOWNLOAD);

    FilePath file_path = fs::u8path(request.file_path());

    if (!IsValidPathName(file_path))
    {
        reply.set_status(proto::REQUEST_STATUS_INVALID_PATH_NAME);
    }
    else
    {
        file_packetizer_ = FilePacketizer::Create(file_path);
        if (!file_packetizer_)
        {
            reply.set_status(proto::REQUEST_STATUS_FILE_OPEN_ERROR);
        }
    }

    SendReply(reply);
}

bool FileTransferSessionClient::ReadFileDownloadDataRequest()
{
    if (!file_packetizer_)
    {
        LOG(ERROR) << "Unexpected download data request";
        return false;
    }

    proto::file_transfer::HostToClient reply;
    reply.set_type(proto::REQUEST_TYPE_FILE_DOWNLOAD_DATA);

    std::unique_ptr<proto::FilePacket> packet =
        file_packetizer_->CreateNextPacket();

    if (!packet)
    {
        reply.set_status(proto::REQUEST_STATUS_FILE_READ_ERROR);
    }
    else
    {
        if (packet->flags() & proto::FilePacket::LAST_PACKET)
        {
            file_packetizer_.reset();
        }

        reply.set_allocated_file_packet(packet.release());
    }

    SendReply(reply);
    return true;
}

} // namespace aspia
<|endoftext|>


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

Program:   Medical Imaging & Interaction Toolkit
Language:  C++
Date:      $Date$
Version:   $Revision$

Copyright (c) German Cancer Research Center, Division of Medical and
Biological Informatics. All rights reserved.
See MITKCopyright.txt or http://www.mitk.org/copyright.html for details.

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

=========================================================================*/

#include "QmitkViewInitialization.h"
#include "QmitkViewInitializationControls.h"
#include "icon.xpm"

#include <qaction.h>
#include <qbuttongroup.h>
#include <qcheckbox.h>

#include <QmitkStdMultiWidget.h>
#include <QmitkSelectableGLWidget.h>
#include <QmitkRenderWindowSelector.h>

#include <mitkSliceNavigationController.h>

QmitkViewInitialization::QmitkViewInitialization(QObject *parent, const char *name, QmitkStdMultiWidget *mitkStdMultiWidget, mitk::DataTreeIteratorBase* it)
  : QmitkFunctionality(parent, name, it), m_MultiWidget(mitkStdMultiWidget), m_Controls(NULL)
{
  SetAvailability(true);
}

QmitkViewInitialization::~QmitkViewInitialization()
{
}

QWidget * QmitkViewInitialization::CreateMainWidget(QWidget * /*parent*/)
{
  return NULL;
}

QWidget * QmitkViewInitialization::CreateControlWidget(QWidget *parent)
{
  if (m_Controls == NULL)
  {
    m_Controls = new QmitkViewInitializationControls(parent);
  }
  return m_Controls;
}

void QmitkViewInitialization::CreateConnections()
{
  if ( m_Controls )
  {
    connect( (QObject*)(m_Controls->pbApply), SIGNAL(clicked()),(QObject*) this, SLOT(Apply()) );
    connect( (QObject*)(m_Controls->pbReset), SIGNAL(clicked()),(QObject*) this, SLOT(ResetAll()) );
  }
}

QAction * QmitkViewInitialization::CreateAction(QActionGroup *parent)
{
  QAction* action;
  action = new QAction( tr( "change view initialization" ), QPixmap((const char**)icon_xpm), tr( "&View Initialization" ), 0, parent, "ViewInitialization" );
  return action;
}

void QmitkViewInitialization::Activated()
{
  QmitkFunctionality::Activated();
}

void QmitkViewInitialization::Apply()
{
  mitk::SliceNavigationController::ViewDirection viewDirection;
  switch ( m_Controls->bgOrientation->selectedId() )
  {
    default:
    case 0:
      viewDirection = mitk::SliceNavigationController::Transversal;
      break;
    case 1:
      viewDirection = mitk::SliceNavigationController::Frontal;
      break;
    case 2:
      viewDirection = mitk::SliceNavigationController::Sagittal;
      break;
  }

  mitk::RenderWindow* renderwindow = m_Controls->m_RenderWindowSelector->GetSelectedRenderWindow();
  if(renderwindow != NULL)
  {
    renderwindow->GetSliceNavigationController()->Update(viewDirection,
      m_Controls->cbTop->isChecked(),
      m_Controls->cbFrontSide->isChecked(),
      m_Controls->cbRotated->isChecked()
    );
    renderwindow->GetRenderer()->GetDisplayGeometry()->Fit();
  }
}

void QmitkViewInitialization::ResetAll()
{
  m_MultiWidget->ReInitializeStandardViews();
}
<commit_msg>COMP: adapt to Qt-Vtk render mechanism<commit_after>/*=========================================================================

Program:   Medical Imaging & Interaction Toolkit
Language:  C++
Date:      $Date$
Version:   $Revision$

Copyright (c) German Cancer Research Center, Division of Medical and
Biological Informatics. All rights reserved.
See MITKCopyright.txt or http://www.mitk.org/copyright.html for details.

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

=========================================================================*/

#include "QmitkViewInitialization.h"
#include "QmitkViewInitializationControls.h"
#include "icon.xpm"

#include <qaction.h>
#include <qbuttongroup.h>
#include <qcheckbox.h>

#include <QmitkStdMultiWidget.h>
#include <QmitkSelectableGLWidget.h>
#include <QmitkRenderWindowSelector.h>

#include <mitkSliceNavigationController.h>

QmitkViewInitialization::QmitkViewInitialization(QObject *parent, const char *name, QmitkStdMultiWidget *mitkStdMultiWidget, mitk::DataTreeIteratorBase* it)
  : QmitkFunctionality(parent, name, it), m_MultiWidget(mitkStdMultiWidget), m_Controls(NULL)
{
  SetAvailability(true);
}

QmitkViewInitialization::~QmitkViewInitialization()
{
}

QWidget * QmitkViewInitialization::CreateMainWidget(QWidget * /*parent*/)
{
  return NULL;
}

QWidget * QmitkViewInitialization::CreateControlWidget(QWidget *parent)
{
  if (m_Controls == NULL)
  {
    m_Controls = new QmitkViewInitializationControls(parent);
  }
  return m_Controls;
}

void QmitkViewInitialization::CreateConnections()
{
  if ( m_Controls )
  {
    connect( (QObject*)(m_Controls->pbApply), SIGNAL(clicked()),(QObject*) this, SLOT(Apply()) );
    connect( (QObject*)(m_Controls->pbReset), SIGNAL(clicked()),(QObject*) this, SLOT(ResetAll()) );
  }
}

QAction * QmitkViewInitialization::CreateAction(QActionGroup *parent)
{
  QAction* action;
  action = new QAction( tr( "change view initialization" ), QPixmap((const char**)icon_xpm), tr( "&View Initialization" ), 0, parent, "ViewInitialization" );
  return action;
}

void QmitkViewInitialization::Activated()
{
  QmitkFunctionality::Activated();
}

void QmitkViewInitialization::Apply()
{
  mitk::SliceNavigationController::ViewDirection viewDirection;
  switch ( m_Controls->bgOrientation->selectedId() )
  {
    default:
    case 0:
      viewDirection = mitk::SliceNavigationController::Transversal;
      break;
    case 1:
      viewDirection = mitk::SliceNavigationController::Frontal;
      break;
    case 2:
      viewDirection = mitk::SliceNavigationController::Sagittal;
      break;
  }

  vtkRenderWindow* renderwindow = m_Controls->m_RenderWindowSelector->GetSelectedRenderWindow();
  if(renderwindow != NULL)
  {
    mitk::BaseRenderer::GetInstance(renderwindow)->GetSliceNavigationController()->Update(viewDirection,
      m_Controls->cbTop->isChecked(),
      m_Controls->cbFrontSide->isChecked(),
      m_Controls->cbRotated->isChecked()
    );
    mitk::BaseRenderer::GetInstance(renderwindow)->GetDisplayGeometry()->Fit();
  }
}

void QmitkViewInitialization::ResetAll()
{
  m_MultiWidget->ReInitializeStandardViews();
}
<|endoftext|>