<commit_before>//===- DataStructureAA.cpp - Data Structure Based Alias Analysis ----------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file was developed by the LLVM research group and is distributed under
// the University of Illinois Open Source License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This pass uses the top-down data structure graphs to implement a simple
// context sensitive alias analysis.
//
//===----------------------------------------------------------------------===//

#include "llvm/Module.h"
#include "llvm/Analysis/AliasAnalysis.h"
#include "llvm/Analysis/Passes.h"
#include "llvm/Analysis/DataStructure/DataStructure.h"
#include "llvm/Analysis/DataStructure/DSGraph.h"
using namespace llvm;

namespace {
  class DSAA : public ModulePass, public AliasAnalysis {
    TDDataStructures *TD;
    BUDataStructures *BU;
  public:
    DSAA() : TD(0) {}

    //------------------------------------------------
    // Implement the Pass API
    //

    // run - Build up the result graph, representing the pointer graph for the
    // program.
    //
    bool runOnModule(Module &M) {
      InitializeAliasAnalysis(this);
      TD = &getAnalysis<TDDataStructures>();
      BU = &getAnalysis<BUDataStructures>();
      return false;
    }

    virtual void getAnalysisUsage(AnalysisUsage &AU) const {
      AliasAnalysis::getAnalysisUsage(AU);
      AU.setPreservesAll();                         // Does not transform code
      AU.addRequiredTransitive<TDDataStructures>(); // Uses TD Datastructures
      AU.addRequiredTransitive<BUDataStructures>(); // Uses BU Datastructures
    }

    //------------------------------------------------
    // Implement the AliasAnalysis API
    //

    AliasResult alias(const Value *V1, unsigned V1Size,
                      const Value *V2, unsigned V2Size);

    void getMustAliases(Value *P, std::vector<Value*> &RetVals);

    ModRefResult getModRefInfo(CallSite CS, Value *P, unsigned Size);
    ModRefResult getModRefInfo(CallSite CS1, CallSite CS2) {
      return AliasAnalysis::getModRefInfo(CS1,CS2);
    }

    virtual void deleteValue(Value *V) {
      BU->deleteValue(V);
      TD->deleteValue(V);
    }

    virtual void copyValue(Value *From, Value *To) {
      if (From == To) return;
      BU->copyValue(From, To);
      TD->copyValue(From, To);
    }

  private:
    DSGraph *getGraphForValue(const Value *V);
  };

  // Register the pass...
  RegisterOpt<DSAA> X("ds-aa", "Data Structure Graph Based Alias Analysis");

  // Register as an implementation of AliasAnalysis
  RegisterAnalysisGroup<AliasAnalysis, DSAA> Y;
}

ModulePass *llvm::createDSAAPass() { return new DSAA(); }

// getGraphForValue - Return the DSGraph to use for queries about the specified
// value...
//
DSGraph *DSAA::getGraphForValue(const Value *V) {
  if (const Instruction *I = dyn_cast<Instruction>(V))
    return &TD->getDSGraph(*I->getParent()->getParent());
  else if (const Argument *A = dyn_cast<Argument>(V))
    return &TD->getDSGraph(*A->getParent());
  else if (const BasicBlock *BB = dyn_cast<BasicBlock>(V))
    return &TD->getDSGraph(*BB->getParent());
  return 0;
}

// isSinglePhysicalObject - For now, the only case that we know that there is
// only one memory object in the node is when there is a single global in the
// node, and the only composition bit set is Global.
//
static bool isSinglePhysicalObject(DSNode *N) {
  assert(N->isComplete() && "Can only tell if this is a complete object!");
  return N->isGlobalNode() && N->getGlobals().size() == 1 &&
         !N->isHeapNode() && !N->isAllocaNode() && !N->isUnknownNode();
}

// alias - This is the only method here that does anything interesting...
AliasAnalysis::AliasResult DSAA::alias(const Value *V1, unsigned V1Size,
                                       const Value *V2, unsigned V2Size) {
  if (V1 == V2) return MustAlias;

  DSGraph *G1 = getGraphForValue(V1);
  DSGraph *G2 = getGraphForValue(V2);
  assert((!G1 || !G2 || G1 == G2) && "Alias query for 2 different functions?");

  // Get the graph to use...
  DSGraph &G = *(G1 ? G1 : (G2 ? G2 : &TD->getGlobalsGraph()));

  const DSGraph::ScalarMapTy &GSM = G.getScalarMap();
  DSGraph::ScalarMapTy::const_iterator I = GSM.find((Value*)V1);
  if (I == GSM.end()) return NoAlias;

  assert(I->second.getNode() && "Scalar map points to null node?");
  DSGraph::ScalarMapTy::const_iterator J = GSM.find((Value*)V2);
  if (J == GSM.end()) return NoAlias;

  assert(J->second.getNode() && "Scalar map points to null node?");

  DSNode  *N1 = I->second.getNode(),  *N2 = J->second.getNode();
  unsigned O1 = I->second.getOffset(), O2 = J->second.getOffset();

  // We can only make a judgment of one of the nodes is complete...
  if (N1->isComplete() || N2->isComplete()) {
    if (N1 != N2)
      return NoAlias;   // Completely different nodes.

#if 0  // This does not correctly handle arrays!
    // Both point to the same node and same offset, and there is only one
    // physical memory object represented in the node, return must alias.
    //
    // FIXME: This isn't correct because we do not handle array indexing
    // correctly.

    if (O1 == O2 && isSinglePhysicalObject(N1))
      return MustAlias; // Exactly the same object & offset
#endif

    // See if they point to different offsets...  if so, we may be able to
    // determine that they do not alias...
    if (O1 != O2) {
      if (O2 < O1) {    // Ensure that O1 <= O2
        std::swap(V1, V2);
        std::swap(O1, O2);
        std::swap(V1Size, V2Size);
      }

      // FIXME: This is not correct because we do not handle array
      // indexing correctly with this check!
      //if (O1+V1Size <= O2) return NoAlias;
    }
  }

  // FIXME: we could improve on this by checking the globals graph for aliased
  // global queries...
  return AliasAnalysis::alias(V1, V1Size, V2, V2Size);
}

/// getModRefInfo - does a callsite modify or reference a value?
///
AliasAnalysis::ModRefResult
DSAA::getModRefInfo(CallSite CS, Value *P, unsigned Size) {
  AliasAnalysis::ModRefResult Result =AliasAnalysis::getModRefInfo(CS, P, Size);
  Function *F = CS.getCalledFunction();

  if (!F || F->isExternal() || Result == NoModRef)
    return Result;

  // Clone the function TD graph, clearing off Mod/Ref flags
  const Function *csParent = CS.getInstruction()->getParent()->getParent();
  DSGraph TDGraph(TD->getDSGraph(*csParent));
  TDGraph.maskNodeTypes(~(DSNode::Modified|DSNode::Read));

  // Insert the callee's BU graph into the TD graph
  const DSGraph &BUGraph = BU->getDSGraph(*F);
  TDGraph.mergeInGraph(TDGraph.getDSCallSiteForCallSite(CS),
                       *F, BUGraph, 0);

  // Report the flags that have been added
  const DSNodeHandle &DSH = TDGraph.getNodeForValue(P);
  if (const DSNode *N = DSH.getNode()) {
    if (!N->isModified())   // We proved it was not modified.
      Result = ModRefResult(Result & ~Mod);
    if (!N->isRead())       // We proved it was not read.
      Result = ModRefResult(Result & ~Ref);
  }
  return Result;
}

/// getMustAliases - If there are any pointers known that must alias this
/// pointer, return them now.  This allows alias-set based alias analyses to
/// perform a form a value numbering (which is exposed by load-vn).  If an alias
/// analysis supports this, it should ADD any must aliased pointers to the
/// specified vector.
///
void DSAA::getMustAliases(Value *P, std::vector<Value*> &RetVals) {
#if 0    // This does not correctly handle arrays!
  // Currently the only must alias information we can provide is to say that
  // something is equal to a global value. If we already have a global value,
  // don't get worked up about it.
  if (!isa<GlobalValue>(P)) {
    DSGraph *G = getGraphForValue(P);
    if (!G) G = &TD->getGlobalsGraph();

    // The only must alias information we can currently determine occurs when
    // the node for P is a global node with only one entry.
    DSGraph::ScalarMapTy::const_iterator I = G->getScalarMap().find(P);
    if (I != G->getScalarMap().end()) {
      DSNode *N = I->second.getNode();
      if (N->isComplete() && isSinglePhysicalObject(N))
        RetVals.push_back(N->getGlobals()[0]);
    }
  }
#endif
  return AliasAnalysis::getMustAliases(P, RetVals);
}

<commit_msg>add some possibly bogus assertions.<commit_after>//===- DataStructureAA.cpp - Data Structure Based Alias Analysis ----------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file was developed by the LLVM research group and is distributed under
// the University of Illinois Open Source License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This pass uses the top-down data structure graphs to implement a simple
// context sensitive alias analysis.
//
//===----------------------------------------------------------------------===//

#include "llvm/Constants.h"
#include "llvm/DerivedTypes.h"
#include "llvm/Module.h"
#include "llvm/Analysis/AliasAnalysis.h"
#include "llvm/Analysis/Passes.h"
#include "llvm/Analysis/DataStructure/DataStructure.h"
#include "llvm/Analysis/DataStructure/DSGraph.h"
using namespace llvm;

namespace {
  class DSAA : public ModulePass, public AliasAnalysis {
    TDDataStructures *TD;
    BUDataStructures *BU;
  public:
    DSAA() : TD(0) {}

    //------------------------------------------------
    // Implement the Pass API
    //

    // run - Build up the result graph, representing the pointer graph for the
    // program.
    //
    bool runOnModule(Module &M) {
      InitializeAliasAnalysis(this);
      TD = &getAnalysis<TDDataStructures>();
      BU = &getAnalysis<BUDataStructures>();
      return false;
    }

    virtual void getAnalysisUsage(AnalysisUsage &AU) const {
      AliasAnalysis::getAnalysisUsage(AU);
      AU.setPreservesAll();                         // Does not transform code
      AU.addRequiredTransitive<TDDataStructures>(); // Uses TD Datastructures
      AU.addRequiredTransitive<BUDataStructures>(); // Uses BU Datastructures
    }

    //------------------------------------------------
    // Implement the AliasAnalysis API
    //

    AliasResult alias(const Value *V1, unsigned V1Size,
                      const Value *V2, unsigned V2Size);

    void getMustAliases(Value *P, std::vector<Value*> &RetVals);

    ModRefResult getModRefInfo(CallSite CS, Value *P, unsigned Size);
    ModRefResult getModRefInfo(CallSite CS1, CallSite CS2) {
      return AliasAnalysis::getModRefInfo(CS1,CS2);
    }

    virtual void deleteValue(Value *V) {
      BU->deleteValue(V);
      TD->deleteValue(V);
    }

    virtual void copyValue(Value *From, Value *To) {
      if (From == To) return;
      BU->copyValue(From, To);
      TD->copyValue(From, To);
    }

  private:
    DSGraph *getGraphForValue(const Value *V);
  };

  // Register the pass...
  RegisterOpt<DSAA> X("ds-aa", "Data Structure Graph Based Alias Analysis");

  // Register as an implementation of AliasAnalysis
  RegisterAnalysisGroup<AliasAnalysis, DSAA> Y;
}

ModulePass *llvm::createDSAAPass() { return new DSAA(); }

// getGraphForValue - Return the DSGraph to use for queries about the specified
// value...
//
DSGraph *DSAA::getGraphForValue(const Value *V) {
  if (const Instruction *I = dyn_cast<Instruction>(V))
    return &TD->getDSGraph(*I->getParent()->getParent());
  else if (const Argument *A = dyn_cast<Argument>(V))
    return &TD->getDSGraph(*A->getParent());
  else if (const BasicBlock *BB = dyn_cast<BasicBlock>(V))
    return &TD->getDSGraph(*BB->getParent());
  return 0;
}

// isSinglePhysicalObject - For now, the only case that we know that there is
// only one memory object in the node is when there is a single global in the
// node, and the only composition bit set is Global.
//
static bool isSinglePhysicalObject(DSNode *N) {
  assert(N->isComplete() && "Can only tell if this is a complete object!");
  return N->isGlobalNode() && N->getGlobals().size() == 1 &&
         !N->isHeapNode() && !N->isAllocaNode() && !N->isUnknownNode();
}

// alias - This is the only method here that does anything interesting...
AliasAnalysis::AliasResult DSAA::alias(const Value *V1, unsigned V1Size,
                                       const Value *V2, unsigned V2Size) {
  if (V1 == V2) return MustAlias;

  DSGraph *G1 = getGraphForValue(V1);
  DSGraph *G2 = getGraphForValue(V2);
  assert((!G1 || !G2 || G1 == G2) && "Alias query for 2 different functions?");

  // Get the graph to use...
  DSGraph &G = *(G1 ? G1 : (G2 ? G2 : &TD->getGlobalsGraph()));

  const DSGraph::ScalarMapTy &GSM = G.getScalarMap();
  DSGraph::ScalarMapTy::const_iterator I = GSM.find((Value*)V1);
  if (I == GSM.end()) return NoAlias;

  assert(I->second.getNode() && "Scalar map points to null node?");
  DSGraph::ScalarMapTy::const_iterator J = GSM.find((Value*)V2);
  if (J == GSM.end()) return NoAlias;

  assert(J->second.getNode() && "Scalar map points to null node?");

  DSNode  *N1 = I->second.getNode(),  *N2 = J->second.getNode();
  unsigned O1 = I->second.getOffset(), O2 = J->second.getOffset();

  // We can only make a judgment of one of the nodes is complete...
  if (N1->isComplete() || N2->isComplete()) {
    if (N1 != N2)
      return NoAlias;   // Completely different nodes.

#if 0  // This does not correctly handle arrays!
    // Both point to the same node and same offset, and there is only one
    // physical memory object represented in the node, return must alias.
    //
    // FIXME: This isn't correct because we do not handle array indexing
    // correctly.

    if (O1 == O2 && isSinglePhysicalObject(N1))
      return MustAlias; // Exactly the same object & offset
#endif

    // See if they point to different offsets...  if so, we may be able to
    // determine that they do not alias...
    if (O1 != O2) {
      if (O2 < O1) {    // Ensure that O1 <= O2
        std::swap(V1, V2);
        std::swap(O1, O2);
        std::swap(V1Size, V2Size);
      }

      // FIXME: This is not correct because we do not handle array
      // indexing correctly with this check!
      //if (O1+V1Size <= O2) return NoAlias;
    }
  }

  // FIXME: we could improve on this by checking the globals graph for aliased
  // global queries...
  return AliasAnalysis::alias(V1, V1Size, V2, V2Size);
}

/// getModRefInfo - does a callsite modify or reference a value?
///
AliasAnalysis::ModRefResult
DSAA::getModRefInfo(CallSite CS, Value *P, unsigned Size) {
  AliasAnalysis::ModRefResult Result =AliasAnalysis::getModRefInfo(CS, P, Size);
  Function *F = CS.getCalledFunction();

  if (!F || F->isExternal() || Result == NoModRef)
    return Result;

  // Clone the function TD graph, clearing off Mod/Ref flags
  const Function *csParent = CS.getInstruction()->getParent()->getParent();
  DSGraph TDGraph(TD->getDSGraph(*csParent));
  TDGraph.maskNodeTypes(~(DSNode::Modified|DSNode::Read));

  // Insert the callee's BU graph into the TD graph
  const DSGraph &BUGraph = BU->getDSGraph(*F);
  TDGraph.mergeInGraph(TDGraph.getDSCallSiteForCallSite(CS),
                       *F, BUGraph, 0);

  // Report the flags that have been added
  const DSNodeHandle &DSH = TDGraph.getNodeForValue(P);
  if (const DSNode *N = DSH.getNode()) {
    if (!N->isModified())   // We proved it was not modified.
      Result = ModRefResult(Result & ~Mod);
    if (!N->isRead())       // We proved it was not read.
      Result = ModRefResult(Result & ~Ref);
  } else {
    if (isa<ConstantPointerNull>(P))
      Result = NoModRef;
    else
      assert(isa<GlobalVariable>(P) &&
    cast<GlobalVariable>(P)->getType()->getElementType()->isFirstClassType() &&
             "This isn't a global that DSA inconsiderately dropped "
             "from the graph?");
  }
  return Result;
}

/// getMustAliases - If there are any pointers known that must alias this
/// pointer, return them now.  This allows alias-set based alias analyses to
/// perform a form a value numbering (which is exposed by load-vn).  If an alias
/// analysis supports this, it should ADD any must aliased pointers to the
/// specified vector.
///
void DSAA::getMustAliases(Value *P, std::vector<Value*> &RetVals) {
#if 0    // This does not correctly handle arrays!
  // Currently the only must alias information we can provide is to say that
  // something is equal to a global value. If we already have a global value,
  // don't get worked up about it.
  if (!isa<GlobalValue>(P)) {
    DSGraph *G = getGraphForValue(P);
    if (!G) G = &TD->getGlobalsGraph();

    // The only must alias information we can currently determine occurs when
    // the node for P is a global node with only one entry.
    DSGraph::ScalarMapTy::const_iterator I = G->getScalarMap().find(P);
    if (I != G->getScalarMap().end()) {
      DSNode *N = I->second.getNode();
      if (N->isComplete() && isSinglePhysicalObject(N))
        RetVals.push_back(N->getGlobals()[0]);
    }
  }
#endif
  return AliasAnalysis::getMustAliases(P, RetVals);
}

<|endoftext|>


<commit_before>/*
 * SPDX-License-Identifier: Apache-2.0
 */

// ATTENTION: The code in this file is highly EXPERIMENTAL.
// Adventurous users should note that the APIs will probably change.

#include "onnx/common/assertions.h"
#include <cstdarg>
#include <cstdio>
#include "onnx/common/common.h"

namespace ONNX_NAMESPACE {

std::string barf(const char* fmt, ...) {
  char msg[2048];
  va_list args;

  va_start(args, fmt);
  vsnprintf(msg, 2048, fmt, args);
  va_end(args);

  return std::string(msg);
}

void throw_assert_error(std::string& msg) {
  ONNX_THROW_EX(assert_error(msg));
}

void throw_tensor_error(std::string& msg) {
  ONNX_THROW_EX(tensor_error(msg));
}

} // namespace ONNX_NAMESPACE
<commit_msg>Add an assert to make sure the quantity is reasonable for vsnprintf (#4413)<commit_after>/*
 * SPDX-License-Identifier: Apache-2.0
 */

// ATTENTION: The code in this file is highly EXPERIMENTAL.
// Adventurous users should note that the APIs will probably change.

#include "onnx/common/assertions.h"
#include <cstdarg>
#include <cstdio>
#include "onnx/common/common.h"

namespace ONNX_NAMESPACE {

std::string barf(const char* fmt, ...) {
  char msg[2048];
  va_list args;

  va_start(args, fmt);
  // Although vsnprintf might have vulnerability issue while using format string with overflowed length,
  // it should be safe here to use fixed length for buffer "msg". No further checking is needed.
  vsnprintf(msg, 2048, fmt, args);
  va_end(args);

  return std::string(msg);
}

void throw_assert_error(std::string& msg) {
  ONNX_THROW_EX(assert_error(msg));
}

void throw_tensor_error(std::string& msg) {
  ONNX_THROW_EX(tensor_error(msg));
}

} // namespace ONNX_NAMESPACE
<|endoftext|>


<commit_before>/*
 * This file is open source software, licensed to you under the terms
 * of the Apache License, Version 2.0 (the "License").  See the NOTICE file
 * distributed with this work for additional information regarding copyright
 * ownership.  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.
 */
/*
 * Copyright (C) 2017 ScyllaDB Ltd.
 */

#pragma once

#include <utility>
#include <type_traits>
#include <functional>

namespace seastar {

template <typename Signature>
class noncopyable_function;

/// A clone of \c std::function, but only invokes the move constructor
/// of the contained function.
template <typename Ret, typename... Args>
class noncopyable_function<Ret (Args...)> {
    static constexpr size_t nr_direct = 32;
    union [[gnu::may_alias]] storage {
        char direct[nr_direct];
        void* indirect;
    };
    using call_type = Ret (*)(const noncopyable_function* func, Args...);
    using move_type = void (*)(noncopyable_function* from, noncopyable_function* to);
    using destroy_type = void (*)(noncopyable_function* func);
    struct vtable {
        const call_type call;
        const move_type move;
        const destroy_type destroy;
    };
private:
    const vtable* _vtable;
    storage _storage;
private:
    static Ret empty_call(const noncopyable_function* func, Args... args) {
        throw std::bad_function_call();
    }
    static void empty_move(noncopyable_function* from, noncopyable_function* to) {}
    static void empty_destroy(noncopyable_function* func) {}
    static constexpr vtable _s_empty_vtable = {empty_call, empty_move, empty_destroy};

    static void indirect_move(noncopyable_function* from, noncopyable_function* to) {
        using void_ptr = void*;
        new (&to->_storage.indirect) void_ptr(from->_storage.indirect);
    }

    template <typename Func>
    struct direct_vtable_for {
        static Func* access(noncopyable_function* func) { return reinterpret_cast<Func*>(func->_storage.direct); }
        static const Func* access(const noncopyable_function* func) { return reinterpret_cast<const Func*>(func->_storage.direct); }
        static Ret call(const noncopyable_function* func, Args... args) {
            return (*access(const_cast<noncopyable_function*>(func)))(std::forward<Args>(args)...);
        }
        static void move(noncopyable_function* from, noncopyable_function* to) {
            new (access(to)) Func(std::move(*access(from)));
            destroy(from);
        }
        static void destroy(noncopyable_function* func) {
            access(func)->~Func();
        }
        static void initialize(Func&& from, noncopyable_function* to) {
            new (access(to)) Func(std::move(from));
        }
        static constexpr vtable make_vtable() { return { call, move, destroy }; }
        static const vtable s_vtable;
    };
    template <typename Func>
    struct indirect_vtable_for {
        static Func* access(noncopyable_function* func) { return reinterpret_cast<Func*>(func->_storage.indirect); }
        static const Func* access(const noncopyable_function* func) { return reinterpret_cast<const Func*>(func->_storage.indirect); }
        static Ret call(const noncopyable_function* func, Args... args) {
            return (*access(const_cast<noncopyable_function*>(func)))(std::forward<Args>(args)...);
        }
        static void destroy(noncopyable_function* func) {
            delete access(func);
        }
        static void initialize(Func&& from, noncopyable_function* to) {
            to->_storage.indirect = new Func(std::move(from));
        }
        static constexpr vtable make_vtable() { return { call, indirect_move, destroy }; }
        static const vtable s_vtable;
    };
    template <typename Func, bool Direct = true>
    struct select_vtable_for : direct_vtable_for<Func> {};
    template <typename Func>
    struct select_vtable_for<Func, false> : indirect_vtable_for<Func> {};
    template <typename Func>
    static constexpr bool is_direct() {
        return sizeof(Func) <= nr_direct && alignof(Func) <= alignof(storage)
                && std::is_nothrow_move_constructible<Func>::value;
    }
    template <typename Func>
    struct vtable_for : select_vtable_for<Func, is_direct<Func>()> {};
public:
    noncopyable_function() noexcept : _vtable(&_s_empty_vtable) {}
    template <typename Func>
    noncopyable_function(Func func) {
        vtable_for<Func>::initialize(std::move(func), this);
        _vtable = &vtable_for<Func>::s_vtable;
    }
    template <typename Object, typename... AllButFirstArg>
    noncopyable_function(Ret (Object::*member)(AllButFirstArg...)) : noncopyable_function(std::mem_fn(member)) {}
    template <typename Object, typename... AllButFirstArg>
    noncopyable_function(Ret (Object::*member)(AllButFirstArg...) const) : noncopyable_function(std::mem_fn(member)) {}

    ~noncopyable_function() {
        _vtable->destroy(this);
    }

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

    noncopyable_function(noncopyable_function&& x) noexcept : _vtable(std::exchange(x._vtable, &_s_empty_vtable)) {
        _vtable->move(&x, this);
    }

    noncopyable_function& operator=(noncopyable_function&& x) noexcept {
        if (this != &x) {
            this->~noncopyable_function();
            new (this) noncopyable_function(std::move(x));
        }
        return *this;
    }

    Ret operator()(Args... args) const {
        return _vtable->call(this, std::forward<Args>(args)...);
    }

    explicit operator bool() const {
        return _vtable != &_s_empty_vtable;
    }
};

template <typename Ret, typename... Args>
constexpr typename noncopyable_function<Ret (Args...)>::vtable noncopyable_function<Ret (Args...)>::_s_empty_vtable;

template <typename Ret, typename... Args>
template <typename Func>
const typename noncopyable_function<Ret (Args...)>::vtable noncopyable_function<Ret (Args...)>::direct_vtable_for<Func>::s_vtable
        = noncopyable_function<Ret (Args...)>::direct_vtable_for<Func>::make_vtable();

template <typename Ret, typename... Args>
template <typename Func>
const typename noncopyable_function<Ret (Args...)>::vtable noncopyable_function<Ret (Args...)>::indirect_vtable_for<Func>::s_vtable
        = noncopyable_function<Ret (Args...)>::indirect_vtable_for<Func>::make_vtable();

}

<commit_msg>noncopyable_function: share some thunks among noncopyable_functions of different signatures<commit_after>/*
 * This file is open source software, licensed to you under the terms
 * of the Apache License, Version 2.0 (the "License").  See the NOTICE file
 * distributed with this work for additional information regarding copyright
 * ownership.  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.
 */
/*
 * Copyright (C) 2017 ScyllaDB Ltd.
 */

#pragma once

#include <utility>
#include <type_traits>
#include <functional>

namespace seastar {

template <typename Signature>
class noncopyable_function;

namespace internal {

class noncopyable_function_base {
private:
    noncopyable_function_base() = default;
    static constexpr size_t nr_direct = 32;
    union [[gnu::may_alias]] storage {
        char direct[nr_direct];
        void* indirect;
    };
    using move_type = void (*)(noncopyable_function_base* from, noncopyable_function_base* to);
    using destroy_type = void (*)(noncopyable_function_base* func);

    static void empty_move(noncopyable_function_base* from, noncopyable_function_base* to) {}
    static void empty_destroy(noncopyable_function_base* func) {}

    static void indirect_move(noncopyable_function_base* from, noncopyable_function_base* to) {
        using void_ptr = void*;
        new (&to->_storage.indirect) void_ptr(from->_storage.indirect);
    }

private:
    storage _storage;

    template <typename Signature>
    friend class seastar::noncopyable_function;
};

}

/// A clone of \c std::function, but only invokes the move constructor
/// of the contained function.
template <typename Ret, typename... Args>
class noncopyable_function<Ret (Args...)> : private internal::noncopyable_function_base {
    using call_type = Ret (*)(const noncopyable_function* func, Args...);
    struct vtable {
        const call_type call;
        const move_type move;
        const destroy_type destroy;
    };
private:
    const vtable* _vtable;
private:
    static Ret empty_call(const noncopyable_function* func, Args... args) {
        throw std::bad_function_call();
    }

    static constexpr vtable _s_empty_vtable = {empty_call, empty_move, empty_destroy};

    template <typename Func>
    struct direct_vtable_for {
        static Func* access(noncopyable_function* func) { return reinterpret_cast<Func*>(func->_storage.direct); }
        static const Func* access(const noncopyable_function* func) { return reinterpret_cast<const Func*>(func->_storage.direct); }
        static Func* access(noncopyable_function_base* func) { return access(static_cast<noncopyable_function*>(func)); }
        static Ret call(const noncopyable_function* func, Args... args) {
            return (*access(const_cast<noncopyable_function*>(func)))(std::forward<Args>(args)...);
        }
        static void move(noncopyable_function_base* from, noncopyable_function_base* to) {
            new (access(to)) Func(std::move(*access(from)));
            destroy(from);
        }
        static void destroy(noncopyable_function_base* func) {
            access(func)->~Func();
        }
        static void initialize(Func&& from, noncopyable_function* to) {
            new (access(to)) Func(std::move(from));
        }
        static constexpr vtable make_vtable() { return { call, move, destroy }; }
        static const vtable s_vtable;
    };
    template <typename Func>
    struct indirect_vtable_for {
        static Func* access(noncopyable_function* func) { return reinterpret_cast<Func*>(func->_storage.indirect); }
        static const Func* access(const noncopyable_function* func) { return reinterpret_cast<const Func*>(func->_storage.indirect); }
        static Func* access(noncopyable_function_base* func) { return access(static_cast<noncopyable_function*>(func)); }
        static Ret call(const noncopyable_function* func, Args... args) {
            return (*access(const_cast<noncopyable_function*>(func)))(std::forward<Args>(args)...);
        }
        static void destroy(noncopyable_function_base* func) {
            delete access(func);
        }
        static void initialize(Func&& from, noncopyable_function* to) {
            to->_storage.indirect = new Func(std::move(from));
        }
        static constexpr vtable make_vtable() { return { call, indirect_move, destroy }; }
        static const vtable s_vtable;
    };
    template <typename Func, bool Direct = true>
    struct select_vtable_for : direct_vtable_for<Func> {};
    template <typename Func>
    struct select_vtable_for<Func, false> : indirect_vtable_for<Func> {};
    template <typename Func>
    static constexpr bool is_direct() {
        return sizeof(Func) <= nr_direct && alignof(Func) <= alignof(storage)
                && std::is_nothrow_move_constructible<Func>::value;
    }
    template <typename Func>
    struct vtable_for : select_vtable_for<Func, is_direct<Func>()> {};
public:
    noncopyable_function() noexcept : _vtable(&_s_empty_vtable) {}
    template <typename Func>
    noncopyable_function(Func func) {
        vtable_for<Func>::initialize(std::move(func), this);
        _vtable = &vtable_for<Func>::s_vtable;
    }
    template <typename Object, typename... AllButFirstArg>
    noncopyable_function(Ret (Object::*member)(AllButFirstArg...)) : noncopyable_function(std::mem_fn(member)) {}
    template <typename Object, typename... AllButFirstArg>
    noncopyable_function(Ret (Object::*member)(AllButFirstArg...) const) : noncopyable_function(std::mem_fn(member)) {}

    ~noncopyable_function() {
        _vtable->destroy(this);
    }

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

    noncopyable_function(noncopyable_function&& x) noexcept : _vtable(std::exchange(x._vtable, &_s_empty_vtable)) {
        _vtable->move(&x, this);
    }

    noncopyable_function& operator=(noncopyable_function&& x) noexcept {
        if (this != &x) {
            this->~noncopyable_function();
            new (this) noncopyable_function(std::move(x));
        }
        return *this;
    }

    Ret operator()(Args... args) const {
        return _vtable->call(this, std::forward<Args>(args)...);
    }

    explicit operator bool() const {
        return _vtable != &_s_empty_vtable;
    }
};

template <typename Ret, typename... Args>
constexpr typename noncopyable_function<Ret (Args...)>::vtable noncopyable_function<Ret (Args...)>::_s_empty_vtable;

template <typename Ret, typename... Args>
template <typename Func>
const typename noncopyable_function<Ret (Args...)>::vtable noncopyable_function<Ret (Args...)>::direct_vtable_for<Func>::s_vtable
        = noncopyable_function<Ret (Args...)>::direct_vtable_for<Func>::make_vtable();

template <typename Ret, typename... Args>
template <typename Func>
const typename noncopyable_function<Ret (Args...)>::vtable noncopyable_function<Ret (Args...)>::indirect_vtable_for<Func>::s_vtable
        = noncopyable_function<Ret (Args...)>::indirect_vtable_for<Func>::make_vtable();

}

<|endoftext|>


<commit_before>/*************************************************************************
 *
 *  $RCSfile: localfilelayer.hxx,v $
 *
 *  $Revision: 1.8 $
 *
 *  last change: $Author: rt $ $Date: 2003-04-17 13:29:29 $
 *
 *  The Contents of this file are made available subject to the terms of
 *  either of the following licenses
 *
 *         - GNU Lesser General Public License Version 2.1
 *         - Sun Industry Standards Source License Version 1.1
 *
 *  Sun Microsystems Inc., October, 2000
 *
 *  GNU Lesser General Public License Version 2.1
 *  =============================================
 *  Copyright 2000 by Sun Microsystems, Inc.
 *  901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public
 *  License version 2.1, as published by the Free Software Foundation.
 *
 *  This library is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *  Lesser General Public License for more details.
 *
 *  You should have received a copy of the GNU Lesser General Public
 *  License along with this library; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *  MA  02111-1307  USA
 *
 *
 *  Sun Industry Standards Source License Version 1.1
 *  =================================================
 *  The contents of this file are subject to the Sun Industry Standards
 *  Source License Version 1.1 (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.openoffice.org/license.html.
 *
 *  Software provided under this License is provided on an "AS IS" basis,
 *  WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
 *  WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
 *  MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
 *  See the License for the specific provisions governing your rights and
 *  obligations concerning the Software.
 *
 *  The Initial Developer of the Original Code is: Sun Microsystems, Inc.
 *
 *  Copyright: 2000 by Sun Microsystems, Inc.
 *
 *  All Rights Reserved.
 *
 *  Contributor(s): _______________________________________
 *
 *
 ************************************************************************/

#ifndef CONFIGMGR_LOCALBE_LOCALFILELAYER_HXX_
#define CONFIGMGR_LOCALBE_LOCALFILELAYER_HXX_

#ifndef _COM_SUN_STAR_CONFIGURATION_BACKEND_XUPDATABLELAYER_HPP_
#include <com/sun/star/configuration/backend/XUpdatableLayer.hpp>
#endif // _COM_SUN_STAR_CONFIGURATION_BACKEND_XUPDATABLELAYER_HPP_

#ifndef _COM_SUN_STAR_CONFIGURATION_BACKEND_XCOMPOSITELAYER_HPP_
#include <com/sun/star/configuration/backend/XCompositeLayer.hpp>
#endif // _COM_SUN_STAR_CONFIGURATION_BACKEND_XCOMPOSITELAYER_HPP_

#ifndef _COM_SUN_STAR_UTIL_XTIMESTAMPED_HPP_
#include <com/sun/star/util/XTimeStamped.hpp>
#endif

#ifndef _COM_SUN_STAR_LANG_XMULTISERVICEFACTORY_HPP_
#include <com/sun/star/lang/XMultiServiceFactory.hpp>
#endif // _COM_SUN_STAR_LANG_XMULTISERVICEFACTORY_HPP_

#ifndef _CPPUHELPER_IMPLBASE3_HXX_
#include <cppuhelper/implbase3.hxx>
#endif
#ifndef _CPPUHELPER_IMPLBASE2_HXX_
#include <cppuhelper/implbase2.hxx>
#endif
#ifndef _CPPUHELPER_IMPLBASE1_HXX_
#include <cppuhelper/implbase1.hxx>
#endif

#ifndef VECTOR_INCLUDED_
#define VECTOR_INCLUDED_
#include <vector>
#endif // VECTOR_INCLUDED_

namespace configmgr { namespace localbe {

namespace css = com::sun::star ;
namespace uno = css::uno ;
namespace lang = css::lang ;
namespace util = css::util ;
namespace backend = css::configuration::backend ;

/**
  Basic Implementation of the readonly XLayer interfaces for a local file access.
  The read data is accessible through a canned implementation of an XML parser.
  The layer is defined by the URL of the file containing its contents.
  */
class BasicLocalFileLayer
{
protected :
    /**
      Constructor providing the base directory and the
      file subpath describing the file to access.
      An optional resource directory provides the location
      of sublayers of the component.

      @param xFactory   service factory used to access canned services
      @param aBaseDir   base directory
      @param aComponent subpath describing the component file
      */
    BasicLocalFileLayer(
            const uno::Reference<lang::XMultiServiceFactory>& xFactory,
            const rtl::OUString& aComponentFile) ;
    /** Destructor */
    ~BasicLocalFileLayer() ;

protected :
    /**
      Describes the contents of a particular file to a handler.

      @param xHandler   handler to describe the data to
      @param aFileUrl   URL of the file
      @throws com::sun::star::configuration::backend::MalformedDataException
              if the file contains invalid data.
      @throws com::sun::star::lang::NullPointerException
              if pContext is NULL.
      @throws com::sun::star::lang::WrappedTargetException
              if an error occurs while accessing the data.
      */
    void readData(backend::XLayer * pContext,
                  const uno::Reference<backend::XLayerHandler>& xHandler,
                  const rtl::OUString& aFileUrl)
        throw (backend::MalformedDataException, lang::NullPointerException,
               lang::WrappedTargetException, uno::RuntimeException);

    /**
      Returns an object that can be used to write a layer.
      */
    uno::Reference<backend::XLayerHandler> createLayerWriter();

public:
    /**
      Returns a timestamp associated to a file defined by its URL.

      @param aFileUrl   URL of the file
      @return   timestamp
      */
    static rtl::OUString getTimestamp(const rtl::OUString& aFileUrl) ;

    rtl::OUString const & getFileUrl() const { return mFileUrl; };

private :
    /** Service factory */
    uno::Reference<lang::XMultiServiceFactory> const mFactory ;
    /** URL of the file being accessed */
    rtl::OUString const mFileUrl ;
    /** XLayer implementation used for readData */
    uno::Reference<backend::XLayer> mLayerReader ;

} ;
/**
  Implementation of the readonly XLayer interfaces for a local file access.
  The read data is accessible through a canned implementation of
  an XML parser.
  The layer is defined by the URL of the file containing its
  contents.
  */
class SimpleLocalFileLayer  : public BasicLocalFileLayer
                            , public cppu::WeakImplHelper1<backend::XLayer>
{
public :
    /**
      Constructor providing the base directory and the
      file subpath describing the file to access.
      An optional resource directory provides the location
      of sublayers of the component.

      @param xFactory   service factory used to access canned services
      @param aComponentFile URL describing the component file
      */
    SimpleLocalFileLayer(
            const uno::Reference<lang::XMultiServiceFactory>& xFactory,
            const rtl::OUString& aComponentFile) ;
    /**
      Constructor providing the base directory and the
      file subpath describing the file to access.
      An optional resource directory provides the location
      of sublayers of the component.

      @param xFactory   service factory used to access canned services
      @param aBaseDir   base directory
      @param aComponent subpath describing the component file
      */
    SimpleLocalFileLayer(
            const uno::Reference<lang::XMultiServiceFactory>& xFactory,
            const rtl::OUString& aBaseDir,
            const rtl::OUString& aComponent) ;

    /** Destructor */
    ~SimpleLocalFileLayer() ;

    // XLayer
    virtual void SAL_CALL readData(
            const uno::Reference<backend::XLayerHandler>& xHandler)
        throw (backend::MalformedDataException, lang::NullPointerException,
               lang::WrappedTargetException, uno::RuntimeException);

} ;
/**
  Implementation of the XUpdatableLayer
  interface for a local file access.
  The read data is accessible through a canned implementation of
  an XML parser, and the write data is defined through a canned
  implementation of an XML writer.
  The layer is defined by the URL of the file containing its
  contents, and that file will be either read or updated by
  the access to the handlers.
  The timestamp is refreshed on each read operation only.
  */
class FlatLocalFileLayer : public BasicLocalFileLayer
                     , public cppu::WeakImplHelper2<backend::XUpdatableLayer,
                                                    util::XTimeStamped>
{
public :
    /**
      Constructor providing the base directory and the
      file subpath describing the file to access.

      @param xFactory   service factory used to access canned services
      @param aBaseDir   base directory
      @param aComponent subpath describing the component file
      */
    FlatLocalFileLayer(
            const uno::Reference<lang::XMultiServiceFactory>& xFactory,
            const rtl::OUString& aBaseDir,
            const rtl::OUString& aComponent) ;
    /** Destructor */
    ~FlatLocalFileLayer(void) ;

    // XLayer
    virtual void SAL_CALL readData(
            const uno::Reference<backend::XLayerHandler>& xHandler)
        throw (backend::MalformedDataException, lang::NullPointerException,
               lang::WrappedTargetException, uno::RuntimeException);

    // XUpdatableLayer
    virtual void SAL_CALL replaceWith(
            const uno::Reference<backend::XLayer>& aNewLayer)
        throw (backend::MalformedDataException, lang::NullPointerException,
               lang::WrappedTargetException, uno::RuntimeException);

    // XTimeStamped
    virtual rtl::OUString SAL_CALL getTimestamp()
        throw (uno::RuntimeException);

private :
    /** XLayerHandler implementation for getWriteHandler */
    uno::Reference<backend::XLayerHandler> mLayerWriter ;

} ;

/**
  Implementation of the XUpdatableLayer and XCompositeLayer
  interfaces for a local file access.
  The read data is accessible through a canned implementation of
  an XML parser, and the write data is defined through a canned
  implementation of an XML writer.
  The layer is defined by the URL of the file containing its
  contents, and that file will be either read or updated by
  the access to the handlers.
  The timestamp is refreshed on each read operation only.
  */
class CompositeLocalFileLayer : public BasicLocalFileLayer
                     , public cppu::WeakImplHelper3<backend::XUpdatableLayer,
                                                    backend::XCompositeLayer,
                                                    util::XTimeStamped>
{
public :
    typedef std::vector<rtl::OUString> SubLayerFiles;
    /**
      Constructor providing the base directory and the
      file subpath describing the file to access.
      An resource directory provides the location
      of sublayers of the component.

      @param xFactory   service factory used to access canned services
      @param aBaseDir   base directory
      @param aComponent subpath describing the component file
      @param aResDir    resource directory, if empty it is
                        assumed the layer does not have sublayers.
      */
    CompositeLocalFileLayer(
            const uno::Reference<lang::XMultiServiceFactory>& xFactory,
            const rtl::OUString& aBaseDir,
            const rtl::OUString& aComponent,
            const SubLayerFiles& aSublayerDirectories) ;
    /** Destructor */
    ~CompositeLocalFileLayer(void) ;
    // XLayer
    virtual void SAL_CALL readData(
            const uno::Reference<backend::XLayerHandler>& xHandler)
        throw (backend::MalformedDataException, lang::NullPointerException,
               lang::WrappedTargetException, uno::RuntimeException);

    // XUpdatableLayer
    virtual void SAL_CALL replaceWith(
            const uno::Reference<backend::XLayer>& aNewLayer)
        throw (backend::MalformedDataException, lang::NullPointerException,
               lang::WrappedTargetException, uno::RuntimeException);

    // XCompositeLayer
    virtual uno::Sequence<rtl::OUString> SAL_CALL listSubLayerIds()
        throw (lang::WrappedTargetException, uno::RuntimeException)
    { return mSubLayers ; }

    virtual void SAL_CALL readSubLayerData(
            const uno::Reference<backend::XLayerHandler>& xHandler,
            const rtl::OUString& aSubLayerId)
        throw (backend::MalformedDataException, lang::NullPointerException,
               lang::WrappedTargetException, lang::IllegalArgumentException,
               uno::RuntimeException);

    // XTimeStamped
    virtual rtl::OUString SAL_CALL getTimestamp()
        throw (uno::RuntimeException);

private :
    /** XLayerHandler implementation for getWriteHandler */
    uno::Reference<backend::XLayerHandler> mLayerWriter ;
    /** List of available sublayers... */
    uno::Sequence<rtl::OUString> mSubLayers ;
    /** .. and the corresponding file URLs. */
    SubLayerFiles mSubLayerFiles ;

    /**
      Fills the list of available sublayers.

      @param aResDir    resource directory containing potential sublayers
      @param aComponent component subpath
      */
    void fillSubLayerLists(const SubLayerFiles& aSublayerDirectories,
                           const rtl::OUString& aComponent) ;
} ;
/**
  Factory function to create the appropriate Flat- or Composite-
  LocalFileLayer for a set of parameters.

  Arguments provide the base directory and the
  file subpath describing the file to access.
  An optional resource directory provides the location
  of sublayers of the component.

  @param xFactory   service factory used to access canned services
  @param aBaseDir   base directory
  @param aComponent subpath describing the component file
  @param aResDir    resource directory, if empty it is
                    assumed the layer does not have sublayers.
  */
uno::Reference<backend::XUpdatableLayer> createLocalFileLayer(
        const uno::Reference<lang::XMultiServiceFactory>& xFactory,
        const rtl::OUString& aBaseDir,
        const rtl::OUString& aComponent,
        const rtl::OUString& aResDir) ;

} } // configmgr.localbe

#endif // CONFIGMGR_LOCALBE_LOCALFILELAYER_HXX_
<commit_msg>INTEGRATION: CWS scp2officecfg (1.8.90); FILE MERGED 2004/06/08 14:31:55 jb 1.8.90.1: #i25937# Reorganize local backends to separate fixed default data from localizations, so that module configuration can be installed<commit_after>/*************************************************************************
 *
 *  $RCSfile: localfilelayer.hxx,v $
 *
 *  $Revision: 1.9 $
 *
 *  last change: $Author: obo $ $Date: 2004-07-05 13:23:38 $
 *
 *  The Contents of this file are made available subject to the terms of
 *  either of the following licenses
 *
 *         - GNU Lesser General Public License Version 2.1
 *         - Sun Industry Standards Source License Version 1.1
 *
 *  Sun Microsystems Inc., October, 2000
 *
 *  GNU Lesser General Public License Version 2.1
 *  =============================================
 *  Copyright 2000 by Sun Microsystems, Inc.
 *  901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public
 *  License version 2.1, as published by the Free Software Foundation.
 *
 *  This library is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *  Lesser General Public License for more details.
 *
 *  You should have received a copy of the GNU Lesser General Public
 *  License along with this library; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *  MA  02111-1307  USA
 *
 *
 *  Sun Industry Standards Source License Version 1.1
 *  =================================================
 *  The contents of this file are subject to the Sun Industry Standards
 *  Source License Version 1.1 (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.openoffice.org/license.html.
 *
 *  Software provided under this License is provided on an "AS IS" basis,
 *  WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
 *  WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
 *  MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
 *  See the License for the specific provisions governing your rights and
 *  obligations concerning the Software.
 *
 *  The Initial Developer of the Original Code is: Sun Microsystems, Inc.
 *
 *  Copyright: 2000 by Sun Microsystems, Inc.
 *
 *  All Rights Reserved.
 *
 *  Contributor(s): _______________________________________
 *
 *
 ************************************************************************/

#ifndef CONFIGMGR_LOCALBE_LOCALFILELAYER_HXX_
#define CONFIGMGR_LOCALBE_LOCALFILELAYER_HXX_

#ifndef _COM_SUN_STAR_CONFIGURATION_BACKEND_XUPDATABLELAYER_HPP_
#include <com/sun/star/configuration/backend/XUpdatableLayer.hpp>
#endif // _COM_SUN_STAR_CONFIGURATION_BACKEND_XUPDATABLELAYER_HPP_

#ifndef _COM_SUN_STAR_CONFIGURATION_BACKEND_XCOMPOSITELAYER_HPP_
#include <com/sun/star/configuration/backend/XCompositeLayer.hpp>
#endif // _COM_SUN_STAR_CONFIGURATION_BACKEND_XCOMPOSITELAYER_HPP_

#ifndef _COM_SUN_STAR_UTIL_XTIMESTAMPED_HPP_
#include <com/sun/star/util/XTimeStamped.hpp>
#endif

#ifndef _COM_SUN_STAR_LANG_XMULTISERVICEFACTORY_HPP_
#include <com/sun/star/lang/XMultiServiceFactory.hpp>
#endif // _COM_SUN_STAR_LANG_XMULTISERVICEFACTORY_HPP_

#ifndef _CPPUHELPER_IMPLBASE3_HXX_
#include <cppuhelper/implbase3.hxx>
#endif
#ifndef _CPPUHELPER_IMPLBASE2_HXX_
#include <cppuhelper/implbase2.hxx>
#endif
#ifndef _CPPUHELPER_IMPLBASE1_HXX_
#include <cppuhelper/implbase1.hxx>
#endif

#ifndef VECTOR_INCLUDED_
#define VECTOR_INCLUDED_
#include <vector>
#endif // VECTOR_INCLUDED_

namespace configmgr { namespace localbe {

namespace css = com::sun::star ;
namespace uno = css::uno ;
namespace lang = css::lang ;
namespace util = css::util ;
namespace backend = css::configuration::backend ;

/**
  Basic Implementation of the readonly XLayer interfaces for a local file access.
  The read data is accessible through a canned implementation of an XML parser.
  The layer is defined by the URL of the file containing its contents.
  */
class BasicLocalFileLayer
{
protected :
    /**
      Constructor providing the base directory and the
      file subpath describing the file to access.
      An optional resource directory provides the location
      of sublayers of the component.

      @param xFactory   service factory used to access canned services
      @param aComponentFile path describing the component file
      */
    BasicLocalFileLayer(
            const uno::Reference<lang::XMultiServiceFactory>& xFactory,
            const rtl::OUString& aComponentFile) ;
    /** Destructor */
    ~BasicLocalFileLayer() ;

protected :
    /**
      Describes the contents of a particular file to a handler.

      @param xHandler   handler to describe the data to
      @param aFileUrl   URL of the file
      @throws com::sun::star::configuration::backend::MalformedDataException
              if the file contains invalid data.
      @throws com::sun::star::lang::NullPointerException
              if pContext is NULL.
      @throws com::sun::star::lang::WrappedTargetException
              if an error occurs while accessing the data.
      */
    void readData(backend::XLayer * pContext,
                  const uno::Reference<backend::XLayerHandler>& xHandler,
                  const rtl::OUString& aFileUrl)
        throw (backend::MalformedDataException, lang::NullPointerException,
               lang::WrappedTargetException, uno::RuntimeException);

    /**
      Returns an object that can be used to write a layer.
      */
    uno::Reference<backend::XLayerHandler> createLayerWriter();

public:
    /**
      Returns a timestamp associated to a file defined by its URL.

      @param aFileUrl   URL of the file
      @return   timestamp
      */
    static rtl::OUString getTimestamp(const rtl::OUString& aFileUrl) ;

    rtl::OUString const & getFileUrl() const { return mFileUrl; };

private :
    /** Service factory */
    uno::Reference<lang::XMultiServiceFactory> const mFactory ;
    /** URL of the file being accessed */
    rtl::OUString const mFileUrl ;
    /** XLayer implementation used for readData */
    uno::Reference<backend::XLayer> mLayerReader ;

} ;
/**
  Implementation of the readonly XLayer interfaces for a local file access.
  The read data is accessible through a canned implementation of
  an XML parser.
  The layer is defined by the URL of the file containing its
  contents.
  */
class SimpleLocalFileLayer  : public BasicLocalFileLayer
                             , public cppu::WeakImplHelper2<backend::XLayer,
                                                            util::XTimeStamped>
{
public :
    /**
      Constructor providing the base directory and the
      file subpath describing the file to access.
      An optional resource directory provides the location
      of sublayers of the component.

      @param xFactory   service factory used to access canned services
      @param aComponentFile URL describing the component file
      */
    SimpleLocalFileLayer(
            const uno::Reference<lang::XMultiServiceFactory>& xFactory,
            const rtl::OUString& aComponentFile) ;
    /**
      Constructor providing the base directory and the
      file subpath describing the file to access.
      An optional resource directory provides the location
      of sublayers of the component.

      @param xFactory   service factory used to access canned services
      @param aBaseDir   base directory
      @param aComponent subpath describing the component file
      */
    SimpleLocalFileLayer(
            const uno::Reference<lang::XMultiServiceFactory>& xFactory,
            const rtl::OUString& aBaseDir,
            const rtl::OUString& aComponent) ;

    /** Destructor */
    ~SimpleLocalFileLayer() ;

    // XLayer
    virtual void SAL_CALL readData(
            const uno::Reference<backend::XLayerHandler>& xHandler)
        throw (backend::MalformedDataException, lang::NullPointerException,
               lang::WrappedTargetException, uno::RuntimeException);

    // XTimeStamped
    virtual rtl::OUString SAL_CALL getTimestamp()
        throw (uno::RuntimeException);

} ;
/**
  Implementation of the XUpdatableLayer
  interface for a local file access.
  The read data is accessible through a canned implementation of
  an XML parser, and the write data is defined through a canned
  implementation of an XML writer.
  The layer is defined by the URL of the file containing its
  contents, and that file will be either read or updated by
  the access to the handlers.
  The timestamp is refreshed on each read operation only.
  */
class FlatLocalFileLayer : public BasicLocalFileLayer
                     , public cppu::WeakImplHelper2<backend::XUpdatableLayer,
                                                    util::XTimeStamped>
{
public :
    /**
      Constructor providing the base directory and the
      file subpath describing the file to access.

      @param xFactory   service factory used to access canned services
      @param aBaseDir   base directory
      @param aComponent subpath describing the component file
      */
    FlatLocalFileLayer(
            const uno::Reference<lang::XMultiServiceFactory>& xFactory,
            const rtl::OUString& aBaseDir,
            const rtl::OUString& aComponent) ;
    /** Destructor */
    ~FlatLocalFileLayer(void) ;

    // XLayer
    virtual void SAL_CALL readData(
            const uno::Reference<backend::XLayerHandler>& xHandler)
        throw (backend::MalformedDataException, lang::NullPointerException,
               lang::WrappedTargetException, uno::RuntimeException);

    // XUpdatableLayer
    virtual void SAL_CALL replaceWith(
            const uno::Reference<backend::XLayer>& aNewLayer)
        throw (backend::MalformedDataException, lang::NullPointerException,
               lang::WrappedTargetException, uno::RuntimeException);

    // XTimeStamped
    virtual rtl::OUString SAL_CALL getTimestamp()
        throw (uno::RuntimeException);

private :
    /** XLayerHandler implementation for getWriteHandler */
    uno::Reference<backend::XLayerHandler> mLayerWriter ;

} ;

/**
  Implementation of the XCompositeLayer
  interface for a local file access.
  The read data is accessible through a canned implementation of
  an XML parser.
  The layer is defined by the URL of the file containing its
  contents, and that file will be either read or updated by
  the access to the handlers.
  The timestamp is refreshed on each read operation only.
  */
class BasicCompositeLocalFileLayer : public BasicLocalFileLayer
{
public:
    typedef std::vector<rtl::OUString> SubLayerFiles;
protected:
    /**
      Constructor providing the base directory and the
      file subpath describing the file to access.
      An resource directory provides the location
      of sublayers of the component.

      @param xFactory   service factory used to access canned services
      @param aComponent path describing the component file
      */
    BasicCompositeLocalFileLayer(
            const uno::Reference<lang::XMultiServiceFactory>& xFactory,
            const rtl::OUString& aComponent) ;

    // XCompositeLayer helpers
    uno::Sequence<rtl::OUString> SAL_CALL listSubLayerIds()
        throw (lang::WrappedTargetException, uno::RuntimeException)
    { return mSubLayers ; }

    void SAL_CALL readSubLayerData(
            backend::XCompositeLayer * context,
            const uno::Reference<backend::XLayerHandler>& xHandler,
            const rtl::OUString& aSubLayerId)
        throw (backend::MalformedDataException, lang::NullPointerException,
               lang::WrappedTargetException, lang::IllegalArgumentException,
               uno::RuntimeException);

    /**
      Fills the list of available sublayers.

      @param aResDir    resource directory containing potential sublayers
      @param aComponent component subpath
      */
    void fillSubLayerLists(const SubLayerFiles& aSublayerDirectories,
                           const rtl::OUString& aComponent) ;
private :
    /** List of available sublayers... */
    uno::Sequence<rtl::OUString> mSubLayers ;
    /** .. and the corresponding file URLs. */
    SubLayerFiles mSubLayerFiles ;

};

/**
  Implementation of the XCompositeLayer
  interface for a local file access.
  The read data is accessible through a canned implementation of
  an XML parser.
  The layer is defined by the URL of the file containing its
  contents, and that file will be either read or updated by
  the access to the handlers.
  The timestamp is refreshed on each read operation only.
  */
class CompositeLocalFileLayer : public BasicCompositeLocalFileLayer
                     , public cppu::WeakImplHelper1< backend::XCompositeLayer>
{
public :
    /**
      Constructor providing the base directory and the
      file subpath describing the file to access.
      An resource directory provides the location
      of sublayers of the component.

      @param xFactory   service factory used to access canned services
      @param aBaseDir   base directory
      @param aComponent subpath describing the component file
      @param aResDir    resource directory, if empty it is
                        assumed the layer does not have sublayers.
      */
    CompositeLocalFileLayer(
            const uno::Reference<lang::XMultiServiceFactory>& xFactory,
            const rtl::OUString& aComponent,
            const SubLayerFiles& aSublayerDirectories) ;
    /** Destructor */
    ~CompositeLocalFileLayer(void) ;
    // XLayer
    virtual void SAL_CALL readData(
            const uno::Reference<backend::XLayerHandler>& xHandler)
        throw (backend::MalformedDataException, lang::NullPointerException,
               lang::WrappedTargetException, uno::RuntimeException);

    // XCompositeLayer
    virtual uno::Sequence<rtl::OUString> SAL_CALL listSubLayerIds()
        throw (lang::WrappedTargetException, uno::RuntimeException)
    { return BasicCompositeLocalFileLayer::listSubLayerIds() ; }

    virtual void SAL_CALL readSubLayerData(
            const uno::Reference<backend::XLayerHandler>& xHandler,
            const rtl::OUString& aSubLayerId)
        throw (backend::MalformedDataException, lang::NullPointerException,
               lang::WrappedTargetException, lang::IllegalArgumentException,
               uno::RuntimeException);

private :
    // not implemented: warn of attempts to use this here
    void getFileUrl();
} ;
/**
  Implementation of the XUpdatableLayer and XCompositeLayer
  interfaces for a local file access.
  The read data is accessible through a canned implementation of
  an XML parser, and the write data is defined through a canned
  implementation of an XML writer.
  The layer is defined by the URL of the file containing its
  contents, and that file will be either read or updated by
  the access to the handlers.
  The timestamp is refreshed on each read operation only.
  */
class FullCompositeLocalFileLayer : public BasicCompositeLocalFileLayer
                     , public cppu::WeakImplHelper3<backend::XUpdatableLayer,
                                                    backend::XCompositeLayer,
                                                    util::XTimeStamped>
{
public :
    /**
      Constructor providing the base directory and the
      file subpath describing the file to access.
      An resource directory provides the location
      of sublayers of the component.

      @param xFactory   service factory used to access canned services
      @param aBaseDir   base directory
      @param aComponent subpath describing the component file
      @param aResDir    resource directory, if empty it is
                        assumed the layer does not have sublayers.
      */
    FullCompositeLocalFileLayer(
            const uno::Reference<lang::XMultiServiceFactory>& xFactory,
            const rtl::OUString& aBaseDir,
            const rtl::OUString& aComponent,
            const SubLayerFiles& aSublayerDirectories) ;
    /** Destructor */
    ~FullCompositeLocalFileLayer(void) ;
    // XLayer
    virtual void SAL_CALL readData(
            const uno::Reference<backend::XLayerHandler>& xHandler)
        throw (backend::MalformedDataException, lang::NullPointerException,
               lang::WrappedTargetException, uno::RuntimeException);

    // XUpdatableLayer
    virtual void SAL_CALL replaceWith(
            const uno::Reference<backend::XLayer>& aNewLayer)
        throw (backend::MalformedDataException, lang::NullPointerException,
               lang::WrappedTargetException, uno::RuntimeException);

    // XCompositeLayer
    virtual uno::Sequence<rtl::OUString> SAL_CALL listSubLayerIds()
        throw (lang::WrappedTargetException, uno::RuntimeException)
    { return BasicCompositeLocalFileLayer::listSubLayerIds() ; }

    virtual void SAL_CALL readSubLayerData(
            const uno::Reference<backend::XLayerHandler>& xHandler,
            const rtl::OUString& aSubLayerId)
        throw (backend::MalformedDataException, lang::NullPointerException,
               lang::WrappedTargetException, lang::IllegalArgumentException,
               uno::RuntimeException);

    // XTimeStamped
    virtual rtl::OUString SAL_CALL getTimestamp()
        throw (uno::RuntimeException);

private :
    /** XLayerHandler implementation for getWriteHandler */
    uno::Reference<backend::XLayerHandler> mLayerWriter ;
} ;
/**
  Factory function to create the appropriate Flat- or Composite-
  LocalFileLayer for a set of parameters.

  Arguments provide the base directory and the
  file subpath describing the file to access.
  An optional resource directory provides the location
  of sublayers of the component.

  @param xFactory   service factory used to access canned services
  @param aBaseDir   base directory
  @param aComponent subpath describing the component file
  @param aResDir    resource directory, if empty it is
                    assumed the layer does not have sublayers.
  */
uno::Reference<backend::XLayer> createReadonlyLocalFileLayer(
        const uno::Reference<lang::XMultiServiceFactory>& xFactory,
        const rtl::OUString& aBaseDir,
        const rtl::OUString& aComponent,
        const rtl::OUString& aResDir) ;

/**
  Factory function to create the appropriate Flat- or Composite-
  LocalFileLayer for a set of parameters.

  Arguments provide the base directory and the
  file subpath describing the file to access.
  An optional resource directory provides the location
  of sublayers of the component.

  @param xFactory   service factory used to access canned services
  @param aBaseDir   base directory
  @param aComponent subpath describing the component file
  @param aResDir    resource directory, if empty it is
                    assumed the layer does not have sublayers.
  */
uno::Reference<backend::XUpdatableLayer> createUpdatableLocalFileLayer(
        const uno::Reference<lang::XMultiServiceFactory>& xFactory,
        const rtl::OUString& aBaseDir,
        const rtl::OUString& aComponent,
        const rtl::OUString& aResDir) ;

} } // configmgr.localbe

#endif // CONFIGMGR_LOCALBE_LOCALFILELAYER_HXX_
<|endoftext|>


<commit_before><commit_msg>Fix conversion from double to int warning. BUG=none TEST=none TBR=jleyba<commit_after><|endoftext|>


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

  Program:   Visualization Toolkit
  Module:    vtkImage2dGradientFilter.cxx
  Language:  C++
  Date:      $Date$
  Version:   $Revision$

Copyright (c) 1993-1995 Ken Martin, Will Schroeder, Bill Lorensen.

This software is copyrighted by Ken Martin, Will Schroeder and Bill Lorensen.
The following terms apply to all files associated with the software unless
explicitly disclaimed in individual files. This copyright specifically does
not apply to the related textbook "The Visualization Toolkit" ISBN
013199837-4 published by Prentice Hall which is covered by its own copyright.

The authors hereby grant permission to use, copy, and distribute this
software and its documentation for any purpose, provided that existing
copyright notices are retained in all copies and that this notice is included
verbatim in any distributions. Additionally, the authors grant permission to
modify this software and its documentation for any purpose, provided that
such modifications are not distributed without the explicit consent of the
authors and that existing copyright notices are retained in all copies. Some
of the algorithms implemented by this software are patented, observe all
applicable patent law.

IN NO EVENT SHALL THE AUTHORS OR DISTRIBUTORS BE LIABLE TO ANY PARTY FOR
DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
OF THE USE OF THIS SOFTWARE, ITS DOCUMENTATION, OR ANY DERIVATIVES THEREOF,
EVEN IF THE AUTHORS HAVE BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

THE AUTHORS AND DISTRIBUTORS SPECIFICALLY DISCLAIM ANY WARRANTIES, INCLUDING,
BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
PARTICULAR PURPOSE, AND NON-INFRINGEMENT.  THIS SOFTWARE IS PROVIDED ON AN
"AS IS" BASIS, AND THE AUTHORS AND DISTRIBUTORS HAVE NO OBLIGATION TO PROVIDE
MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.

=========================================================================*/
#include <math.h>
#include "vtkImage2dGradientFilter.h"

//----------------------------------------------------------------------------
// Description:
// Construct an instance of vtkImage2dGradientFilter fitler.
vtkImage2dGradientFilter::vtkImage2dGradientFilter()
{
  this->KernelSize[0] = 3;
  this->KernelSize[1] = 3;

  this->KernelMiddle[0] = 1;
  this->KernelMiddle[1] = 1;

  this->SetAxes3d(VTK_IMAGE_X_AXIS,VTK_IMAGE_Y_AXIS, VTK_IMAGE_COMPONENT_AXIS);
  this->SetOutputDataType(VTK_IMAGE_FLOAT);
}

//----------------------------------------------------------------------------
void vtkImage2dGradientFilter::PrintSelf(ostream& os, vtkIndent indent)
{
  this->vtkImageSpatialFilter::PrintSelf(os, indent);
}

//----------------------------------------------------------------------------
// Description:
// Add Component as the third axis.
void vtkImage2dGradientFilter::SetAxes2d(int axis0, int axis1)
{
  if (axis0 == VTK_IMAGE_COMPONENT_AXIS || axis1 == VTK_IMAGE_COMPONENT_AXIS)
    {
    vtkErrorMacro(<< "SetAxes2d: Cannot use Component as an axis");
    return;
    }
  this->SetAxes3d(axis0, axis0, VTK_IMAGE_COMPONENT_AXIS);
}

//----------------------------------------------------------------------------
// Description:
// All components will be generated.
void vtkImage2dGradientFilter::InterceptCacheUpdate(vtkImageRegion *region)
{
  int bounds[6];

  region->GetBounds3d(bounds);
  bounds[4] = 0;
  bounds[5] = 2;
  region->SetBounds3d(bounds);
}

//----------------------------------------------------------------------------
// Description:
// This method is passed a region that holds the image bounds of this filters
// input, and changes the region to hold the image bounds of this filters
// output.
void vtkImage2dGradientFilter::ComputeOutputImageInformation(
		    vtkImageRegion *inRegion, vtkImageRegion *outRegion)
{
  int bounds[8];
  int idx;

  inRegion->GetImageBounds4d(bounds);
  if ( ! this->HandleBoundaries)
    {
    // shrink output image bounds.
    for (idx = 0; idx < 4; ++idx)
      {
      bounds[idx*2] += this->KernelMiddle[idx];
      bounds[idx*2+1] -= (this->KernelSize[idx] - 1) - this->KernelMiddle[idx];
      }
    }

  // from 0 to 2 components
  bounds[4] = 0;
  bounds[5] = 2;

  outRegion->SetImageBounds4d(bounds);
}

//----------------------------------------------------------------------------
// Description:
// This method executes the filter for the postion of the image which
// is not affected by boundaries.  Component axis is axis2.  Gradient
// is performed over axis0 and axis1.
template <class T>
void vtkImage2dGradientFilterExecuteCenter(vtkImage2dGradientFilter *self,
				     vtkImageRegion *inRegion, T *inPtr,
				     vtkImageRegion *outRegion, float *outPtr)
{
  double d0, d1, temp;
  float r0, r1;
  // For looping though output (and input) pixels.
  int outMin0, outMax0, outMin1, outMax1;
  int outIdx0, outIdx1;
  int outInc0, outInc1, outInc2;
  float *outPtr0, *outPtr1, *outPtr2;
  int inInc0, inInc1;
  T *inPtr0, *inPtr1;

  self = self;
  // Get information to march through data
  inRegion->GetIncrements2d(inInc0, inInc1);
  outRegion->GetIncrements3d(outInc0, outInc1, outInc2);
  outRegion->GetBounds2d(outMin0, outMax0, outMin1, outMax1);

  // We want the input pixel to correspond to output
  inPtr = (T *)(inRegion->GetVoidPointer2d(outMin0, outMin1));

  // The aspect ratio is important for computing the gradient.
  inRegion->GetAspectRatio2d(r0, r1);
  r0 = 1.0 / r0;
  r1 = 1.0 / r1;

  // loop through pixels of output
  outPtr1 = outPtr;
  inPtr1 = inPtr;
  for (outIdx1 = outMin1; outIdx1 <= outMax1; ++outIdx1)
    {
    outPtr0 = outPtr1;
    inPtr0 = inPtr1;
    for (outIdx0 = outMin0; outIdx0 <= outMax0; ++outIdx0)
      {

      // Compute gradient using central differences.
      d0 = (inPtr0[inInc0] - inPtr0[-inInc0]) * r0;
      d1 = (inPtr0[inInc1] - inPtr0[-inInc1]) * r1;

      // Set the magnitude
      outPtr2 = outPtr0;
      *outPtr2 = (float)(hypot(d0, d1));
      temp = 1.0 / *outPtr2;
      // Set the vector
      outPtr2 += outInc2;
      *outPtr2 = d0 / temp;
      outPtr2 += outInc2;
      *outPtr2 = d1 / temp;

      outPtr0 += outInc0;
      inPtr0 += inInc0;
      }
    outPtr1 += outInc1;
    inPtr1 += inInc1;
    }
}

//----------------------------------------------------------------------------
// Description:
// This method behaves just like "vtkImage2dGradientFilterExecute" but
// it handles boundaries. Pixels are just replicated to get values
// out of bounds.
template <class T>
void vtkImage2dGradientFilterExecuteBoundary(vtkImage2dGradientFilter *self,
				     vtkImageRegion *inRegion, T *inPtr,
				     vtkImageRegion *outRegion, float *outPtr)
{
  float d0, d1;
  float r0, r1;
  float temp;
  // For looping though output (and input) pixels.
  int outMin0, outMax0, outMin1, outMax1;
  int outIdx0, outIdx1;
  int outInc0, outInc1, outInc2;
  float *outPtr0, *outPtr1, *outPtr2;
  int inInc0, inInc1;
  T *inPtr0, *inPtr1;
  // Boundary of input image
  int inImageMin0, inImageMax0, inImageMin1, inImageMax1;

  self = self;
  // Get boundary information
  inRegion->GetImageBounds2d(inImageMin0,inImageMax0, inImageMin1,inImageMax1);

  // Get information to march through data
  inRegion->GetIncrements2d(inInc0, inInc1);
  outRegion->GetIncrements3d(outInc0, outInc1, outInc2);
  outRegion->GetBounds2d(outMin0, outMax0, outMin1, outMax1);

  // We want the input pixel to correspond to output
  inPtr = (T *)(inRegion->GetVoidPointer2d(outMin0, outMin1));

  // The aspect ratio is important for computing the gradient.
  inRegion->GetAspectRatio2d(r0, r1);
  r0 = 1.0 / r0;
  r1 = 1.0 / r1;

  // loop through pixels of output
  outPtr1 = outPtr;
  inPtr1 = inPtr;
  for (outIdx1 = outMin1; outIdx1 <= outMax1; ++outIdx1)
    {
    outPtr0 = outPtr1;
    inPtr0 = inPtr1;
    for (outIdx0 = outMin0; outIdx0 <= outMax0; ++outIdx0)
      {

      // Compute gradient using central differences (if in bounds).
      d0 = ((outIdx0 + 1) > inImageMax0) ? *inPtr0 : inPtr0[inInc0];
      d1 = ((outIdx1 + 1) > inImageMax1) ? *inPtr0 : inPtr0[inInc1];
      d0 -= ((outIdx0 - 1) < inImageMin0) ? *inPtr0 : inPtr0[-inInc0];
      d1 -= ((outIdx1 - 1) < inImageMin1) ? *inPtr0 : inPtr0[-inInc1];
      d0 *= r0;
      d1 *= r1;

      // Set the magnitude
      outPtr2 = outPtr0;
      *outPtr2 = (float)(hypot(d0, d1));
      temp = 1.0 / *outPtr2;
      // Set the vector
      outPtr2 += outInc2;
      *outPtr2 = d0 / temp;
      outPtr2 += outInc2;
      *outPtr2 = d1 / temp;

      outPtr0 += outInc0;
      inPtr0 += inInc0;
      }
    outPtr1 += outInc1;
    inPtr1 += inInc1;
    }
}

//----------------------------------------------------------------------------
// Description:
// This method contains a switch statement that calls the correct
// templated function for the input region type.  The output region
// must be of type float.  This methode only execute the filter
// without handling image boundary conditions.
// The third axis is the component axis for the output.
void vtkImage2dGradientFilter::ExecuteCenter3d(vtkImageRegion *inRegion,
					       vtkImageRegion *outRegion)
{
  void *inPtr = inRegion->GetVoidPointer3d();
  void *outPtr = outRegion->GetVoidPointer3d();

  // this filter expects that output is type float.
  if (outRegion->GetDataType() != VTK_IMAGE_FLOAT)
    {
    vtkErrorMacro(<< "Execute: output DataType, "
                  << vtkImageDataTypeNameMacro(outRegion->GetDataType())
                  << ", must be float");
    return;
    }

  switch (inRegion->GetDataType())
    {
    case VTK_IMAGE_FLOAT:
      vtkImage2dGradientFilterExecuteCenter(this,
			  inRegion, (float *)(inPtr),
			  outRegion, (float *)(outPtr));
      break;
    case VTK_IMAGE_INT:
      vtkImage2dGradientFilterExecuteCenter(this,
			  inRegion, (int *)(inPtr),
			  outRegion, (float *)(outPtr));
      break;
    case VTK_IMAGE_SHORT:
      vtkImage2dGradientFilterExecuteCenter(this,
			  inRegion, (short *)(inPtr),
			  outRegion, (float *)(outPtr));
      break;
    case VTK_IMAGE_UNSIGNED_SHORT:
      vtkImage2dGradientFilterExecuteCenter(this,
			  inRegion, (unsigned short *)(inPtr),
			  outRegion, (float *)(outPtr));
      break;
    case VTK_IMAGE_UNSIGNED_CHAR:
      vtkImage2dGradientFilterExecuteCenter(this,
			  inRegion, (unsigned char *)(inPtr),
			  outRegion, (float *)(outPtr));
      break;
    default:
      vtkErrorMacro(<< "ExecuteCenter: Unknown DataType");
      return;
    }
}

//----------------------------------------------------------------------------
// Description:
// This method contains a switch statement that calls the correct
// templated function for the input region type.  The output region
// must be of type float.  This method does handle boundary conditions.
// The third axis is the component axis for the output.
void vtkImage2dGradientFilter::ExecuteBoundary3d(vtkImageRegion *inRegion,
						 vtkImageRegion *outRegion)
{
  void *inPtr = inRegion->GetVoidPointer3d();
  void *outPtr = outRegion->GetVoidPointer3d();

  // this filter expects that output is type float.
  if (outRegion->GetDataType() != VTK_IMAGE_FLOAT)
    {
    vtkErrorMacro(<< "Execute: output DataType, "
                  << vtkImageDataTypeNameMacro(outRegion->GetDataType())
                  << ", must be float");
    return;
    }

  switch (inRegion->GetDataType())
    {
    case VTK_IMAGE_FLOAT:
      vtkImage2dGradientFilterExecuteBoundary(this,
			  inRegion, (float *)(inPtr),
			  outRegion, (float *)(outPtr));
      break;
    case VTK_IMAGE_INT:
      vtkImage2dGradientFilterExecuteBoundary(this,
			  inRegion, (int *)(inPtr),
			  outRegion, (float *)(outPtr));
      break;
    case VTK_IMAGE_SHORT:
      vtkImage2dGradientFilterExecuteBoundary(this,
			  inRegion, (short *)(inPtr),
			  outRegion, (float *)(outPtr));
      break;
    case VTK_IMAGE_UNSIGNED_SHORT:
      vtkImage2dGradientFilterExecuteBoundary(this,
			  inRegion, (unsigned short *)(inPtr),
			  outRegion, (float *)(outPtr));
      break;
    case VTK_IMAGE_UNSIGNED_CHAR:
      vtkImage2dGradientFilterExecuteBoundary(this,
			  inRegion, (unsigned char *)(inPtr),
			  outRegion, (float *)(outPtr));
      break;
    default:
      vtkErrorMacro(<< "ExecuteBoundary: Unknown DataType");
      return;
    }
}

<commit_msg>Normalize bug<commit_after>/*=========================================================================

  Program:   Visualization Toolkit
  Module:    vtkImage2dGradientFilter.cxx
  Language:  C++
  Date:      $Date$
  Version:   $Revision$

Copyright (c) 1993-1995 Ken Martin, Will Schroeder, Bill Lorensen.

This software is copyrighted by Ken Martin, Will Schroeder and Bill Lorensen.
The following terms apply to all files associated with the software unless
explicitly disclaimed in individual files. This copyright specifically does
not apply to the related textbook "The Visualization Toolkit" ISBN
013199837-4 published by Prentice Hall which is covered by its own copyright.

The authors hereby grant permission to use, copy, and distribute this
software and its documentation for any purpose, provided that existing
copyright notices are retained in all copies and that this notice is included
verbatim in any distributions. Additionally, the authors grant permission to
modify this software and its documentation for any purpose, provided that
such modifications are not distributed without the explicit consent of the
authors and that existing copyright notices are retained in all copies. Some
of the algorithms implemented by this software are patented, observe all
applicable patent law.

IN NO EVENT SHALL THE AUTHORS OR DISTRIBUTORS BE LIABLE TO ANY PARTY FOR
DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
OF THE USE OF THIS SOFTWARE, ITS DOCUMENTATION, OR ANY DERIVATIVES THEREOF,
EVEN IF THE AUTHORS HAVE BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

THE AUTHORS AND DISTRIBUTORS SPECIFICALLY DISCLAIM ANY WARRANTIES, INCLUDING,
BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
PARTICULAR PURPOSE, AND NON-INFRINGEMENT.  THIS SOFTWARE IS PROVIDED ON AN
"AS IS" BASIS, AND THE AUTHORS AND DISTRIBUTORS HAVE NO OBLIGATION TO PROVIDE
MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.

=========================================================================*/
#include <math.h>
#include "vtkImage2dGradientFilter.h"

//----------------------------------------------------------------------------
// Description:
// Construct an instance of vtkImage2dGradientFilter fitler.
vtkImage2dGradientFilter::vtkImage2dGradientFilter()
{
  this->KernelSize[0] = 3;
  this->KernelSize[1] = 3;

  this->KernelMiddle[0] = 1;
  this->KernelMiddle[1] = 1;

  this->SetAxes3d(VTK_IMAGE_X_AXIS,VTK_IMAGE_Y_AXIS, VTK_IMAGE_COMPONENT_AXIS);
  this->SetOutputDataType(VTK_IMAGE_FLOAT);
}

//----------------------------------------------------------------------------
void vtkImage2dGradientFilter::PrintSelf(ostream& os, vtkIndent indent)
{
  this->vtkImageSpatialFilter::PrintSelf(os, indent);
}

//----------------------------------------------------------------------------
// Description:
// Add Component as the third axis.
void vtkImage2dGradientFilter::SetAxes2d(int axis0, int axis1)
{
  if (axis0 == VTK_IMAGE_COMPONENT_AXIS || axis1 == VTK_IMAGE_COMPONENT_AXIS)
    {
    vtkErrorMacro(<< "SetAxes2d: Cannot use Component as an axis");
    return;
    }
  this->SetAxes3d(axis0, axis0, VTK_IMAGE_COMPONENT_AXIS);
}

//----------------------------------------------------------------------------
// Description:
// All components will be generated.
void vtkImage2dGradientFilter::InterceptCacheUpdate(vtkImageRegion *region)
{
  int bounds[6];

  region->GetBounds3d(bounds);
  bounds[4] = 0;
  bounds[5] = 2;
  region->SetBounds3d(bounds);
}

//----------------------------------------------------------------------------
// Description:
// This method is passed a region that holds the image bounds of this filters
// input, and changes the region to hold the image bounds of this filters
// output.
void vtkImage2dGradientFilter::ComputeOutputImageInformation(
		    vtkImageRegion *inRegion, vtkImageRegion *outRegion)
{
  int bounds[8];
  int idx;

  inRegion->GetImageBounds4d(bounds);
  if ( ! this->HandleBoundaries)
    {
    // shrink output image bounds.
    for (idx = 0; idx < 4; ++idx)
      {
      bounds[idx*2] += this->KernelMiddle[idx];
      bounds[idx*2+1] -= (this->KernelSize[idx] - 1) - this->KernelMiddle[idx];
      }
    }

  // from 0 to 2 components
  bounds[4] = 0;
  bounds[5] = 2;

  outRegion->SetImageBounds4d(bounds);
}

//----------------------------------------------------------------------------
// Description:
// This execute method handles boundaries.
// it handles boundaries. Pixels are just replicated to get values
// out of bounds.
template <class T>
void vtkImage2dGradientFilterExecute(vtkImage2dGradientFilter *self,
				     vtkImageRegion *inRegion, T *inPtr,
				     vtkImageRegion *outRegion, float *outPtr)
{
  float d0, d1;
  float r0, r1;
  float temp;
  // For looping though output (and input) pixels.
  int outMin0, outMax0, outMin1, outMax1;
  int outIdx0, outIdx1;
  int outInc0, outInc1, outInc2;
  float *outPtr0, *outPtr1, *outPtr2;
  int inInc0, inInc1;
  T *inPtr0, *inPtr1;
  // Boundary of input image
  int inImageMin0, inImageMax0, inImageMin1, inImageMax1;

  self = self;
  // Get boundary information
  inRegion->GetImageBounds2d(inImageMin0,inImageMax0, inImageMin1,inImageMax1);

  // Get information to march through data
  inRegion->GetIncrements2d(inInc0, inInc1);
  outRegion->GetIncrements3d(outInc0, outInc1, outInc2);
  outRegion->GetBounds2d(outMin0, outMax0, outMin1, outMax1);

  // We want the input pixel to correspond to output
  inPtr = (T *)(inRegion->GetVoidPointer2d(outMin0, outMin1));

  // The aspect ratio is important for computing the gradient.
  inRegion->GetAspectRatio2d(r0, r1);
  r0 = 1.0 / r0;
  r1 = 1.0 / r1;

  // loop through pixels of output
  outPtr1 = outPtr;
  inPtr1 = inPtr;
  for (outIdx1 = outMin1; outIdx1 <= outMax1; ++outIdx1)
    {
    outPtr0 = outPtr1;
    inPtr0 = inPtr1;
    for (outIdx0 = outMin0; outIdx0 <= outMax0; ++outIdx0)
      {

      // Compute gradient using central differences (if in bounds).
      d0 = ((outIdx0 + 1) > inImageMax0) ? *inPtr0 : inPtr0[inInc0];
      d1 = ((outIdx1 + 1) > inImageMax1) ? *inPtr0 : inPtr0[inInc1];
      d0 -= ((outIdx0 - 1) < inImageMin0) ? *inPtr0 : inPtr0[-inInc0];
      d1 -= ((outIdx1 - 1) < inImageMin1) ? *inPtr0 : inPtr0[-inInc1];
      d0 *= r0;
      d1 *= r1;

      // Set the magnitude
      outPtr2 = outPtr0;
      *outPtr2 = (float)(hypot(d0, d1));
      temp = 1.0 / *outPtr2;
      // Set the vector
      outPtr2 += outInc2;
      *outPtr2 = d0 * temp;
      outPtr2 += outInc2;
      *outPtr2 = d1 * temp;

      outPtr0 += outInc0;
      inPtr0 += inInc0;
      }
    outPtr1 += outInc1;
    inPtr1 += inInc1;
    }
}

//----------------------------------------------------------------------------
// Description:
// This method contains a switch statement that calls the correct
// templated function for the input region type.  The output region
// must be of type float.  This methode only execute the filter
// without handling image boundary conditions.
// The third axis is the component axis for the output.
void vtkImage2dGradientFilter::ExecuteCenter3d(vtkImageRegion *inRegion,
					       vtkImageRegion *outRegion)
{
  void *inPtr = inRegion->GetVoidPointer3d();
  void *outPtr = outRegion->GetVoidPointer3d();

  // this filter expects that output is type float.
  if (outRegion->GetDataType() != VTK_IMAGE_FLOAT)
    {
    vtkErrorMacro(<< "Execute: output DataType, "
                  << vtkImageDataTypeNameMacro(outRegion->GetDataType())
                  << ", must be float");
    return;
    }

  switch (inRegion->GetDataType())
    {
    case VTK_IMAGE_FLOAT:
      vtkImage2dGradientFilterExecute(this,
			  inRegion, (float *)(inPtr),
			  outRegion, (float *)(outPtr));
      break;
    case VTK_IMAGE_INT:
      vtkImage2dGradientFilterExecute(this,
			  inRegion, (int *)(inPtr),
			  outRegion, (float *)(outPtr));
      break;
    case VTK_IMAGE_SHORT:
      vtkImage2dGradientFilterExecute(this,
			  inRegion, (short *)(inPtr),
			  outRegion, (float *)(outPtr));
      break;
    case VTK_IMAGE_UNSIGNED_SHORT:
      vtkImage2dGradientFilterExecute(this,
			  inRegion, (unsigned short *)(inPtr),
			  outRegion, (float *)(outPtr));
      break;
    case VTK_IMAGE_UNSIGNED_CHAR:
      vtkImage2dGradientFilterExecute(this,
			  inRegion, (unsigned char *)(inPtr),
			  outRegion, (float *)(outPtr));
      break;
    default:
      vtkErrorMacro(<< "ExecuteCenter: Unknown DataType");
      return;
    }
}

//----------------------------------------------------------------------------
// Description:
// This method contains a switch statement that calls the correct
// templated function for the input region type.  The output region
// must be of type float.  This method does handle boundary conditions.
// The third axis is the component axis for the output.
void vtkImage2dGradientFilter::ExecuteBoundary3d(vtkImageRegion *inRegion,
						 vtkImageRegion *outRegion)
{
  void *inPtr = inRegion->GetVoidPointer3d();
  void *outPtr = outRegion->GetVoidPointer3d();

  // this filter expects that output is type float.
  if (outRegion->GetDataType() != VTK_IMAGE_FLOAT)
    {
    vtkErrorMacro(<< "Execute: output DataType, "
                  << vtkImageDataTypeNameMacro(outRegion->GetDataType())
                  << ", must be float");
    return;
    }

  switch (inRegion->GetDataType())
    {
    case VTK_IMAGE_FLOAT:
      vtkImage2dGradientFilterExecute(this,
			  inRegion, (float *)(inPtr),
			  outRegion, (float *)(outPtr));
      break;
    case VTK_IMAGE_INT:
      vtkImage2dGradientFilterExecute(this,
			  inRegion, (int *)(inPtr),
			  outRegion, (float *)(outPtr));
      break;
    case VTK_IMAGE_SHORT:
      vtkImage2dGradientFilterExecute(this,
			  inRegion, (short *)(inPtr),
			  outRegion, (float *)(outPtr));
      break;
    case VTK_IMAGE_UNSIGNED_SHORT:
      vtkImage2dGradientFilterExecute(this,
			  inRegion, (unsigned short *)(inPtr),
			  outRegion, (float *)(outPtr));
      break;
    case VTK_IMAGE_UNSIGNED_CHAR:
      vtkImage2dGradientFilterExecute(this,
			  inRegion, (unsigned char *)(inPtr),
			  outRegion, (float *)(outPtr));
      break;
    default:
      vtkErrorMacro(<< "ExecuteBoundary: Unknown DataType");
      return;
    }
}

<|endoftext|>


<commit_before>/*
-----------------------------------------------------------------------------
This source file is part of OGRE
    (Object-oriented Graphics Rendering Engine)
For the latest info, see http://www.ogre3d.org/

Copyright (c) 2000-2014 Torus Knot Software Ltd

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 "OgreStableHeaders.h"
#include "OgreException.h"
#include "OgreLogManager.h"

#ifdef __BORLANDC__
    #include <stdio.h>
#endif

namespace Ogre {

    Exception::Exception(int num, const String& desc, const String& src) :
        line( 0 ),
        number( num ),
        description( desc ),
        source( src )
    {
        // Log this error - not any more, allow catchers to do it
        //LogManager::getSingleton().logMessage(this->getFullDescription());
    }

    Exception::Exception(int num, const String& desc, const String& src,
        const char* typ, const char* fil, long lin) :
        line( lin ),
        number( num ),
        typeName(typ),
        description( desc ),
        source( src ),
        file( fil )
    {
        // Log this error, mask it from debug though since it may be caught and ignored
        if(LogManager::getSingletonPtr())
        {
            LogManager::getSingleton().logMessage(
                this->getFullDescription(),
                LML_CRITICAL, true);
        }

    }

    Exception::Exception(const Exception& rhs)
        : line( rhs.line ),
        number( rhs.number ),
        typeName( rhs.typeName ),
        description( rhs.description ),
        source( rhs.source ),
        file( rhs.file )
    {
    }

    Exception& Exception::operator = ( const Exception& rhs )
    {
        description = rhs.description;
        number = rhs.number;
        source = rhs.source;
        file = rhs.file;
        line = rhs.line;
        typeName = rhs.typeName;

        return *this;
    }

    const String& Exception::getFullDescription(void) const
    {
        if (fullDesc.empty())
        {

            StringStream desc;

            desc <<  "OGRE EXCEPTION(" << number << ":" << typeName << "): "
                << description
                << " in " << source;

            if( line > 0 )
            {
                desc << " at " << file << " (line " << line << ")";
            }

            fullDesc = desc.str();
        }

        return fullDesc;
    }

    int Exception::getNumber(void) const throw()
    {
        return number;
    }

}

<commit_msg>OgreException: beatify getFullDescription()<commit_after>/*
-----------------------------------------------------------------------------
This source file is part of OGRE
    (Object-oriented Graphics Rendering Engine)
For the latest info, see http://www.ogre3d.org/

Copyright (c) 2000-2014 Torus Knot Software Ltd

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 "OgreStableHeaders.h"
#include "OgreException.h"
#include "OgreLogManager.h"

#ifdef __BORLANDC__
    #include <stdio.h>
#endif

namespace Ogre {

    Exception::Exception(int num, const String& desc, const String& src) :
        line( 0 ),
        number( num ),
        description( desc ),
        source( src )
    {
        // Log this error - not any more, allow catchers to do it
        //LogManager::getSingleton().logMessage(this->getFullDescription());
    }

    Exception::Exception(int num, const String& desc, const String& src,
        const char* typ, const char* fil, long lin) :
        line( lin ),
        number( num ),
        typeName(typ),
        description( desc ),
        source( src ),
        file( fil )
    {
        // Log this error, mask it from debug though since it may be caught and ignored
        if(LogManager::getSingletonPtr())
        {
            LogManager::getSingleton().logMessage(
                this->getFullDescription(),
                LML_CRITICAL, true);
        }

    }

    Exception::Exception(const Exception& rhs)
        : line( rhs.line ),
        number( rhs.number ),
        typeName( rhs.typeName ),
        description( rhs.description ),
        source( rhs.source ),
        file( rhs.file )
    {
    }

    Exception& Exception::operator = ( const Exception& rhs )
    {
        description = rhs.description;
        number = rhs.number;
        source = rhs.source;
        file = rhs.file;
        line = rhs.line;
        typeName = rhs.typeName;

        return *this;
    }

    const String& Exception::getFullDescription(void) const
    {
        if (fullDesc.empty())
        {

            StringStream desc;

            desc << typeName << ": "
                << description
                << " in " << source;

            if( line > 0 )
            {
                desc << " at " << file << " (line " << line << ")";
            }

            fullDesc = desc.str();
        }

        return fullDesc;
    }

    int Exception::getNumber(void) const throw()
    {
        return number;
    }

}

<|endoftext|>