<commit_before>/* Copyright 2021 The TensorFlow Authors. All Rights Reserved.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
==============================================================================*/

#include "mlir-hlo/Analysis/userange_analysis.h"
#include "mlir-hlo/Dialect/lhlo/IR/lhlo_ops.h"
#include "mlir-hlo/Transforms/PassDetail.h"
#include "mlir-hlo/Transforms/passes.h"
#include "mlir/Dialect/Bufferization/Transforms/BufferUtils.h"
#include "mlir/Interfaces/CopyOpInterface.h"
#include "mlir/Interfaces/SideEffectInterfaces.h"
#include "mlir/Pass/Pass.h"

namespace mlir {

namespace {

class CopyRemoval : bufferization::BufferPlacementTransformationBase {
 public:
  explicit CopyRemoval(Operation *op)
      : BufferPlacementTransformationBase(op),
        userange_(op, allocs, aliases),
        dominators_(op) {}

  void removeCopy() {
    // A vector with the allocation value / copy operation pairs s to process.
    llvm::SmallVector<CopyOpInterface> toProcess;
    fillProcessSetAndResolveAliases(toProcess);

    DenseMap<Value, UseInterval::Vector> updatedUserange;
    DenseMap<Value, UserangeAnalysis::UsePositionList> updatedUsepositions;

    // Lambda expression to update the userange interval.
    auto lambdaUserangeUpdate = [&](Value v,
                                    DenseMap<Value, UseInterval::Vector> &map)
        -> UseInterval::Vector & { return insertUserangeInterval(v, map); };

    // A set containing copy operations that can be erased.
    SmallPtrSet<Operation *, 16> toErase;
    while (!toProcess.empty()) {
      CopyOpInterface copyOp = toProcess.pop_back_val();

      // Cast the Operation and get the Source and Target.
      Value copySource = copyOp.getSource();
      Value copyTarget = copyOp.getTarget();

      // Only remove copies if they do not affect maps.
      if (copySource.getType().cast<MemRefType>().getLayout() !=
          copyTarget.getType().cast<MemRefType>().getLayout())
        continue;

      // Get the UserangeIntervals.
      auto sourceAlloc = alias_to_alloc_map_[copySource];
      UseInterval::Vector sourceInterval =
          getOrInsert(sourceAlloc, updatedUserange, lambdaUserangeUpdate);
      auto targetAlloc = alias_to_alloc_map_[copyTarget];
      UseInterval::Vector targetInterval =
          getOrInsert(targetAlloc, updatedUserange, lambdaUserangeUpdate);

      UseInterval::Vector intersect = sourceInterval;

      // Compute the intersection.
      UseInterval::intervalIntersect(intersect, targetInterval);

      // If the sourceInterval contains more than one UseInterval, there are
      // multiple operations that intersect. The sourceInterval must have at
      // least one UseInterval that contains the copyOp.
      if (intersect.size() != 1) continue;

      // Check if all operations inside the intersection are benign, part of the
      // copyOp or a dealloc.
      if (!usesInIntervalAreSafe(copyOp, copySource, *intersect.begin()))
        continue;

      // Check if the currentOp dominates all uses of the copyTarget.
      if (!checkDominance(copyOp, copyTarget.getUsers(), toErase)) continue;

      // The last op in the intersection of the use ranges needs to be a
      // dealloc, as it ended the original source range. If we do the reuse,
      // we have to remove that dealloc to extend the liferange of the original
      // value.
      auto lastOp = userange_.getOperation(intersect.back().end);
      if (!isDeallocOperationFor(lastOp, copySource)) continue;
      toErase.insert(lastOp);

      // Merge the Useranges.
      UseInterval::intervalMerge(sourceInterval, targetInterval);

      // Replace all uses of the target with the source.
      copyTarget.replaceAllUsesWith(copySource);
      toErase.insert(copyOp);
    }
    // Erase the copy operations.
    for (auto *eraseOp : toErase) eraseOp->erase();

    // Erase all allocs without uses.
    for (const bufferization::BufferPlacementAllocs::AllocEntry &entry :
         allocs) {
      Value alloc = std::get<0>(entry);
      if (alloc.use_empty()) alloc.getDefiningOp()->erase();
    }
  }

 private:
  /// Iterate over all allocs and their aliases and add their uses to the
  /// process set that implement a CopyOpInterface, where the alloc or alias is
  /// the source of the CopyOpInterface.
  void fillProcessSetAndResolveAliases(
      llvm::SmallVectorImpl<CopyOpInterface> &toProcess) {
    // A Set that contains the already processed aliases.
    SmallPtrSet<Value, 16U> processedAliases;

    // Iterate over the allocs.
    for (const bufferization::BufferPlacementAllocs::AllocEntry &entry :
         allocs) {
      Value allocValue = std::get<0>(entry);

      // Resolve the aliases of the current alloc and iterate over them.
      // At the same time, merge the use ranges of aliases into the use range
      // of the corresponding allocation.
      const ValueSetT &aliasSet = aliases.resolve(allocValue);
      for (Value alias : aliasSet) {
        // If the alias is already processed, continue.
        if (!processedAliases.insert(alias).second) continue;
        // Union the use ranges.
        userange_.unionRanges(allocValue, alias);
        // Remember the alias.
        alias_to_alloc_map_.insert({alias, allocValue});
        // If any of the uses are a copy, we have a canidate.
        for (auto user : alias.getUsers()) {
          auto copyOp = dyn_cast<CopyOpInterface>(user);
          if (!copyOp) continue;
          if (copyOp.getSource() != alias) continue;
          toProcess.push_back(copyOp);
        }
      }
    }
  }

  /// Find the given Value in the DenseMap and return the pointer. If the given
  /// Value is not in the Map, insert a copy of the given original to the
  /// DenseMap using the pased update function and return a pointer to that
  /// element.
  template <typename T, typename TFunc>
  T &getOrInsert(Value v, DenseMap<Value, T> &updateMap,
                 const TFunc &updateFunc) {
    auto iter = updateMap.find(v);
    if (iter != updateMap.end()) return iter->second;
    return updateFunc(v, updateMap);
  }

  /// Insert the original userange intervals of the operation in the map.
  UseInterval::Vector &insertUserangeInterval(
      Value v, DenseMap<Value, UseInterval::Vector> &updateMap) {
    const auto *original = userange_.getUserangeInterval(v).getValue();
    auto &entry = updateMap[v];
    entry = *original;
    return entry;
  }

  /// Check if all users in the given range are dominated by given operation.
  /// Note: The target has always at least one use which is the copy operation.
  bool checkDominance(Operation *operation, const Value::user_range &userRange,
                      SmallPtrSet<Operation *, 16> &ignoreSet) {
    // Check if any use of the target is not dominated by the useOp. Erased
    // operations are ignored as uses.
    return llvm::all_of(userRange, [=](Operation *user) {
      return ignoreSet.count(user) || dominators_.dominates(operation, user);
    });
  }

  /// Checks whether op is a dealloction operation for value.
  /// This helper is aware of aliasing via the alias_to_alloc_map_.
  bool isDeallocOperationFor(Operation *op, Value value) {
    auto effect = dyn_cast<MemoryEffectOpInterface>(op);
    Value originalAlloc = alias_to_alloc_map_[value];
    return effect && effect.hasEffect<MemoryEffects::Free>() &&
           llvm::any_of(op->getOperands(), [&](Value operand) {
             Value operandAlloc = alias_to_alloc_map_[operand];
             return operandAlloc == originalAlloc;
           });
  }

  /// Checks whether all uses within the given interval are safe, i.e., there
  /// are no conflicts.
  /// This currently means that the interval may only contain non-sideeffecting
  /// operations or a dealloc of the given source value.
  bool usesInIntervalAreSafe(Operation *op, Value source,
                             UseInterval &interval) {
    // Divide the start and end by two to remove read/write properties.
    for (int id = interval.start / 2, e = interval.end / 2; id <= e; ++id) {
      // Get the operation from the id. Multiply the id by 2, because the
      // userange operates on doubled ids. Return false if the operation is not
      // an ancestor.
      // TODO(herhut): This is a bit of a big hammer. Ideally this should only
      //               look at use positions. Refactor to use those here.
      Operation *op_in_interval = userange_.getOperation(id * 2);
      if (op->isAncestor(op_in_interval)) continue;
      auto effect = dyn_cast<MemoryEffectOpInterface>(op_in_interval);
      // If we do not know about effects, fail.
      if (!effect) return false;
      // If it has no effect we are safe. It is OK if it gets the operand as
      // it does not use it.
      if (effect.hasNoEffect()) continue;
      if (isDeallocOperationFor(op_in_interval, source)) continue;
      return false;
    }
    return true;
  }

  /// The current userange info.
  UserangeAnalysis userange_;

  /// A map from aliases to their allocation value.
  DenseMap<Value, Value> alias_to_alloc_map_;

  /// The current dominance info.
  DominanceInfo dominators_;
};

struct CopyRemovalPass : public CopyRemovalBase<CopyRemovalPass> {
  void runOnOperation() override {
    Operation *funcOp = getOperation();
    CopyRemoval removal(funcOp);
    removal.removeCopy();
  }
};

}  // namespace

std::unique_ptr<OperationPass<func::FuncOp>> createCopyRemovalPass() {
  return std::make_unique<CopyRemovalPass>();
}

}  // namespace mlir
<commit_msg>Apply clang-tidy fixes for llvm-qualified-auto in copy_removal.cc (NFC)<commit_after>/* Copyright 2021 The TensorFlow Authors. All Rights Reserved.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
==============================================================================*/

#include "mlir-hlo/Analysis/userange_analysis.h"
#include "mlir-hlo/Dialect/lhlo/IR/lhlo_ops.h"
#include "mlir-hlo/Transforms/PassDetail.h"
#include "mlir-hlo/Transforms/passes.h"
#include "mlir/Dialect/Bufferization/Transforms/BufferUtils.h"
#include "mlir/Interfaces/CopyOpInterface.h"
#include "mlir/Interfaces/SideEffectInterfaces.h"
#include "mlir/Pass/Pass.h"

namespace mlir {

namespace {

class CopyRemoval : bufferization::BufferPlacementTransformationBase {
 public:
  explicit CopyRemoval(Operation *op)
      : BufferPlacementTransformationBase(op),
        userange_(op, allocs, aliases),
        dominators_(op) {}

  void removeCopy() {
    // A vector with the allocation value / copy operation pairs s to process.
    llvm::SmallVector<CopyOpInterface> toProcess;
    fillProcessSetAndResolveAliases(toProcess);

    DenseMap<Value, UseInterval::Vector> updatedUserange;
    DenseMap<Value, UserangeAnalysis::UsePositionList> updatedUsepositions;

    // Lambda expression to update the userange interval.
    auto lambdaUserangeUpdate = [&](Value v,
                                    DenseMap<Value, UseInterval::Vector> &map)
        -> UseInterval::Vector & { return insertUserangeInterval(v, map); };

    // A set containing copy operations that can be erased.
    SmallPtrSet<Operation *, 16> toErase;
    while (!toProcess.empty()) {
      CopyOpInterface copyOp = toProcess.pop_back_val();

      // Cast the Operation and get the Source and Target.
      Value copySource = copyOp.getSource();
      Value copyTarget = copyOp.getTarget();

      // Only remove copies if they do not affect maps.
      if (copySource.getType().cast<MemRefType>().getLayout() !=
          copyTarget.getType().cast<MemRefType>().getLayout())
        continue;

      // Get the UserangeIntervals.
      auto sourceAlloc = alias_to_alloc_map_[copySource];
      UseInterval::Vector sourceInterval =
          getOrInsert(sourceAlloc, updatedUserange, lambdaUserangeUpdate);
      auto targetAlloc = alias_to_alloc_map_[copyTarget];
      UseInterval::Vector targetInterval =
          getOrInsert(targetAlloc, updatedUserange, lambdaUserangeUpdate);

      UseInterval::Vector intersect = sourceInterval;

      // Compute the intersection.
      UseInterval::intervalIntersect(intersect, targetInterval);

      // If the sourceInterval contains more than one UseInterval, there are
      // multiple operations that intersect. The sourceInterval must have at
      // least one UseInterval that contains the copyOp.
      if (intersect.size() != 1) continue;

      // Check if all operations inside the intersection are benign, part of the
      // copyOp or a dealloc.
      if (!usesInIntervalAreSafe(copyOp, copySource, *intersect.begin()))
        continue;

      // Check if the currentOp dominates all uses of the copyTarget.
      if (!checkDominance(copyOp, copyTarget.getUsers(), toErase)) continue;

      // The last op in the intersection of the use ranges needs to be a
      // dealloc, as it ended the original source range. If we do the reuse,
      // we have to remove that dealloc to extend the liferange of the original
      // value.
      auto *lastOp = userange_.getOperation(intersect.back().end);
      if (!isDeallocOperationFor(lastOp, copySource)) continue;
      toErase.insert(lastOp);

      // Merge the Useranges.
      UseInterval::intervalMerge(sourceInterval, targetInterval);

      // Replace all uses of the target with the source.
      copyTarget.replaceAllUsesWith(copySource);
      toErase.insert(copyOp);
    }
    // Erase the copy operations.
    for (auto *eraseOp : toErase) eraseOp->erase();

    // Erase all allocs without uses.
    for (const bufferization::BufferPlacementAllocs::AllocEntry &entry :
         allocs) {
      Value alloc = std::get<0>(entry);
      if (alloc.use_empty()) alloc.getDefiningOp()->erase();
    }
  }

 private:
  /// Iterate over all allocs and their aliases and add their uses to the
  /// process set that implement a CopyOpInterface, where the alloc or alias is
  /// the source of the CopyOpInterface.
  void fillProcessSetAndResolveAliases(
      llvm::SmallVectorImpl<CopyOpInterface> &toProcess) {
    // A Set that contains the already processed aliases.
    SmallPtrSet<Value, 16U> processedAliases;

    // Iterate over the allocs.
    for (const bufferization::BufferPlacementAllocs::AllocEntry &entry :
         allocs) {
      Value allocValue = std::get<0>(entry);

      // Resolve the aliases of the current alloc and iterate over them.
      // At the same time, merge the use ranges of aliases into the use range
      // of the corresponding allocation.
      const ValueSetT &aliasSet = aliases.resolve(allocValue);
      for (Value alias : aliasSet) {
        // If the alias is already processed, continue.
        if (!processedAliases.insert(alias).second) continue;
        // Union the use ranges.
        userange_.unionRanges(allocValue, alias);
        // Remember the alias.
        alias_to_alloc_map_.insert({alias, allocValue});
        // If any of the uses are a copy, we have a canidate.
        for (auto *user : alias.getUsers()) {
          auto copyOp = dyn_cast<CopyOpInterface>(user);
          if (!copyOp) continue;
          if (copyOp.getSource() != alias) continue;
          toProcess.push_back(copyOp);
        }
      }
    }
  }

  /// Find the given Value in the DenseMap and return the pointer. If the given
  /// Value is not in the Map, insert a copy of the given original to the
  /// DenseMap using the pased update function and return a pointer to that
  /// element.
  template <typename T, typename TFunc>
  T &getOrInsert(Value v, DenseMap<Value, T> &updateMap,
                 const TFunc &updateFunc) {
    auto iter = updateMap.find(v);
    if (iter != updateMap.end()) return iter->second;
    return updateFunc(v, updateMap);
  }

  /// Insert the original userange intervals of the operation in the map.
  UseInterval::Vector &insertUserangeInterval(
      Value v, DenseMap<Value, UseInterval::Vector> &updateMap) {
    const auto *original = userange_.getUserangeInterval(v).getValue();
    auto &entry = updateMap[v];
    entry = *original;
    return entry;
  }

  /// Check if all users in the given range are dominated by given operation.
  /// Note: The target has always at least one use which is the copy operation.
  bool checkDominance(Operation *operation, const Value::user_range &userRange,
                      SmallPtrSet<Operation *, 16> &ignoreSet) {
    // Check if any use of the target is not dominated by the useOp. Erased
    // operations are ignored as uses.
    return llvm::all_of(userRange, [=](Operation *user) {
      return ignoreSet.count(user) || dominators_.dominates(operation, user);
    });
  }

  /// Checks whether op is a dealloction operation for value.
  /// This helper is aware of aliasing via the alias_to_alloc_map_.
  bool isDeallocOperationFor(Operation *op, Value value) {
    auto effect = dyn_cast<MemoryEffectOpInterface>(op);
    Value originalAlloc = alias_to_alloc_map_[value];
    return effect && effect.hasEffect<MemoryEffects::Free>() &&
           llvm::any_of(op->getOperands(), [&](Value operand) {
             Value operandAlloc = alias_to_alloc_map_[operand];
             return operandAlloc == originalAlloc;
           });
  }

  /// Checks whether all uses within the given interval are safe, i.e., there
  /// are no conflicts.
  /// This currently means that the interval may only contain non-sideeffecting
  /// operations or a dealloc of the given source value.
  bool usesInIntervalAreSafe(Operation *op, Value source,
                             UseInterval &interval) {
    // Divide the start and end by two to remove read/write properties.
    for (int id = interval.start / 2, e = interval.end / 2; id <= e; ++id) {
      // Get the operation from the id. Multiply the id by 2, because the
      // userange operates on doubled ids. Return false if the operation is not
      // an ancestor.
      // TODO(herhut): This is a bit of a big hammer. Ideally this should only
      //               look at use positions. Refactor to use those here.
      Operation *op_in_interval = userange_.getOperation(id * 2);
      if (op->isAncestor(op_in_interval)) continue;
      auto effect = dyn_cast<MemoryEffectOpInterface>(op_in_interval);
      // If we do not know about effects, fail.
      if (!effect) return false;
      // If it has no effect we are safe. It is OK if it gets the operand as
      // it does not use it.
      if (effect.hasNoEffect()) continue;
      if (isDeallocOperationFor(op_in_interval, source)) continue;
      return false;
    }
    return true;
  }

  /// The current userange info.
  UserangeAnalysis userange_;

  /// A map from aliases to their allocation value.
  DenseMap<Value, Value> alias_to_alloc_map_;

  /// The current dominance info.
  DominanceInfo dominators_;
};

struct CopyRemovalPass : public CopyRemovalBase<CopyRemovalPass> {
  void runOnOperation() override {
    Operation *funcOp = getOperation();
    CopyRemoval removal(funcOp);
    removal.removeCopy();
  }
};

}  // namespace

std::unique_ptr<OperationPass<func::FuncOp>> createCopyRemovalPass() {
  return std::make_unique<CopyRemovalPass>();
}

}  // namespace mlir
<|endoftext|>


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

#include "tcambin_tcamprop_impl.h"

#include "tcambin_data.h"

#include <algorithm>
#include <gst-helper/gst_gvalue_helper.h>
#include <tcamprop1.0_consumer/tcamprop1_consumer.h>
#include <tcamprop1.0_gobject/tcam_gerror.h>
#include <tcamprop1.0_gobject/tcam_property_provider.h>
#include <tcamprop1.0_gobject/tcam_property_provider_simple_functions.h>

static GSList* gst_tcambin_get_tcam_property_names(TcamPropertyProvider* iface, GError** err)
{
    tcambin_data& self = *GST_TCAMBIN(iface)->data;

    if (self.src == nullptr)
    {
        tcamprop1_gobj::set_gerror(err, tcamprop1::status::device_not_opened);
        return nullptr;
    }

    std::vector<std::string> convert_name_list;
    // if dutils(-cuda) is present then first fetch the names from that
    // tcamconvert does not offer properties
    if (self.tcam_converter && TCAM_IS_PROPERTY_PROVIDER(self.tcam_converter))
    {
        convert_name_list = tcamprop1_consumer::get_property_names_noerror(
            TCAM_PROPERTY_PROVIDER(self.tcam_converter));
    }
    auto src_prop_list_res =
        tcamprop1_consumer::get_property_names(TCAM_PROPERTY_PROVIDER(self.src));
    if (src_prop_list_res.has_error())
    {
        tcamprop1_gobj::set_gerror(err, src_prop_list_res.error());
        return nullptr;
    }

    // merge both list;
    if (convert_name_list.empty())
    {
        return gst_helper::gst_string_vector_to_GSList(src_prop_list_res.value());
    }

    auto& merged_prop_list = src_prop_list_res.value();
    merged_prop_list.insert(
        merged_prop_list.end(), convert_name_list.begin(), convert_name_list.end());

    std::sort(merged_prop_list.begin(), merged_prop_list.end());
    merged_prop_list.erase(std::unique(merged_prop_list.begin(), merged_prop_list.end()),
                           merged_prop_list.end());

    return gst_helper::gst_string_vector_to_GSList(merged_prop_list);
}

static TcamPropertyBase* gst_tcambin_get_tcam_property(TcamPropertyProvider* iface,
                                                       const char* name,
                                                       GError** err)
{
    tcambin_data& self = *GST_TCAMBIN(iface)->data;

    if (name == nullptr)
    {
        tcamprop1_gobj::set_gerror(err, tcamprop1::status::parameter_null);
        return nullptr;
    }

    if (self.src == nullptr)
    {
        tcamprop1_gobj::set_gerror(err, tcamprop1::status::device_not_opened);
        return nullptr;
    }

    if (self.tcam_converter)
    {
        auto res = tcam_property_provider_get_tcam_property(
            TCAM_PROPERTY_PROVIDER(self.tcam_converter), name, nullptr);
        if (res)
        {
            return res;
        }
    }

    return tcam_property_provider_get_tcam_property(TCAM_PROPERTY_PROVIDER(self.src), name, err);
}

void tcam::gst::bin::gst_tcambin_tcamprop_init(TcamPropertyProviderInterface* iface)
{
    iface->get_tcam_property_names = gst_tcambin_get_tcam_property_names;
    iface->get_tcam_property = gst_tcambin_get_tcam_property;

    iface->set_tcam_boolean = tcamprop1_gobj::provider_set_tcam_boolean;
    iface->set_tcam_integer = tcamprop1_gobj::provider_set_tcam_integer;
    iface->set_tcam_float = tcamprop1_gobj::provider_set_tcam_float;
    iface->set_tcam_enumeration = tcamprop1_gobj::provider_set_tcam_enumeration;
    iface->set_tcam_command = tcamprop1_gobj::provider_set_tcam_command;

    iface->get_tcam_boolean = tcamprop1_gobj::provider_get_tcam_boolean;
    iface->get_tcam_integer = tcamprop1_gobj::provider_get_tcam_integer;
    iface->get_tcam_float = tcamprop1_gobj::provider_get_tcam_float;
    iface->get_tcam_enumeration = tcamprop1_gobj::provider_get_tcam_enumeration;
}
<commit_msg>gst/bin: Add security check<commit_after>/*
 * Copyright 2021 The Imaging Source Europe GmbH
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "tcambin_tcamprop_impl.h"

#include "tcambin_data.h"

#include <algorithm>
#include <gst-helper/gst_gvalue_helper.h>
#include <tcamprop1.0_consumer/tcamprop1_consumer.h>
#include <tcamprop1.0_gobject/tcam_gerror.h>
#include <tcamprop1.0_gobject/tcam_property_provider.h>
#include <tcamprop1.0_gobject/tcam_property_provider_simple_functions.h>

static GSList* gst_tcambin_get_tcam_property_names(TcamPropertyProvider* iface, GError** err)
{
    tcambin_data& self = *GST_TCAMBIN(iface)->data;

    if (self.src == nullptr)
    {
        tcamprop1_gobj::set_gerror(err, tcamprop1::status::device_not_opened);
        return nullptr;
    }

    std::vector<std::string> convert_name_list;
    // if dutils(-cuda) is present then first fetch the names from that
    // tcamconvert does not offer properties
    if (self.tcam_converter && TCAM_IS_PROPERTY_PROVIDER(self.tcam_converter))
    {
        convert_name_list = tcamprop1_consumer::get_property_names_noerror(
            TCAM_PROPERTY_PROVIDER(self.tcam_converter));
    }
    auto src_prop_list_res =
        tcamprop1_consumer::get_property_names(TCAM_PROPERTY_PROVIDER(self.src));
    if (src_prop_list_res.has_error())
    {
        tcamprop1_gobj::set_gerror(err, src_prop_list_res.error());
        return nullptr;
    }

    // merge both list;
    if (convert_name_list.empty())
    {
        return gst_helper::gst_string_vector_to_GSList(src_prop_list_res.value());
    }

    auto& merged_prop_list = src_prop_list_res.value();
    merged_prop_list.insert(
        merged_prop_list.end(), convert_name_list.begin(), convert_name_list.end());

    std::sort(merged_prop_list.begin(), merged_prop_list.end());
    merged_prop_list.erase(std::unique(merged_prop_list.begin(), merged_prop_list.end()),
                           merged_prop_list.end());

    return gst_helper::gst_string_vector_to_GSList(merged_prop_list);
}

static TcamPropertyBase* gst_tcambin_get_tcam_property(TcamPropertyProvider* iface,
                                                       const char* name,
                                                       GError** err)
{
    tcambin_data& self = *GST_TCAMBIN(iface)->data;

    if (name == nullptr)
    {
        tcamprop1_gobj::set_gerror(err, tcamprop1::status::parameter_null);
        return nullptr;
    }

    if (self.src == nullptr)
    {
        tcamprop1_gobj::set_gerror(err, tcamprop1::status::device_not_opened);
        return nullptr;
    }

    if (self.tcam_converter && TCAM_IS_PROPERTY_PROVIDER(self.tcam_converter))
    {
        auto res = tcam_property_provider_get_tcam_property(
            TCAM_PROPERTY_PROVIDER(self.tcam_converter), name, nullptr);
        if (res)
        {
            return res;
        }
    }

    return tcam_property_provider_get_tcam_property(TCAM_PROPERTY_PROVIDER(self.src), name, err);
}

void tcam::gst::bin::gst_tcambin_tcamprop_init(TcamPropertyProviderInterface* iface)
{
    iface->get_tcam_property_names = gst_tcambin_get_tcam_property_names;
    iface->get_tcam_property = gst_tcambin_get_tcam_property;

    iface->set_tcam_boolean = tcamprop1_gobj::provider_set_tcam_boolean;
    iface->set_tcam_integer = tcamprop1_gobj::provider_set_tcam_integer;
    iface->set_tcam_float = tcamprop1_gobj::provider_set_tcam_float;
    iface->set_tcam_enumeration = tcamprop1_gobj::provider_set_tcam_enumeration;
    iface->set_tcam_command = tcamprop1_gobj::provider_set_tcam_command;

    iface->get_tcam_boolean = tcamprop1_gobj::provider_get_tcam_boolean;
    iface->get_tcam_integer = tcamprop1_gobj::provider_get_tcam_integer;
    iface->get_tcam_float = tcamprop1_gobj::provider_get_tcam_float;
    iface->get_tcam_enumeration = tcamprop1_gobj::provider_get_tcam_enumeration;
}
<|endoftext|>


<commit_before>/* IBM_PROLOG_BEGIN_TAG                                                   */
/* This is an automatically generated prolog.                             */
/*                                                                        */
/* $Source: src/import/generic/memory/lib/utils/index.H $                 */
/*                                                                        */
/* OpenPOWER HostBoot Project                                             */
/*                                                                        */
/* Contributors Listed Below - COPYRIGHT 2015,2019                        */
/* [+] International Business Machines Corp.                              */
/*                                                                        */
/*                                                                        */
/* Licensed under the Apache License, Version 2.0 (the "License");        */
/* you may not use this file except in compliance with the License.       */
/* You may obtain a copy of the License at                                */
/*                                                                        */
/*     http://www.apache.org/licenses/LICENSE-2.0                         */
/*                                                                        */
/* Unless required by applicable law or agreed to in writing, software    */
/* distributed under the License is distributed on an "AS IS" BASIS,      */
/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or        */
/* implied. See the License for the specific language governing           */
/* permissions and limitations under the License.                         */
/*                                                                        */
/* IBM_PROLOG_END_TAG                                                     */

///
/// @file index.H
/// @brief Tools to return attribute array index from a fapi2 target
///
// *HWP HWP Owner: Andre Marin <aamarin@us.ibm.com>
// *HWP HWP Backup: Jacob Harvey <jlharvey@us.ibm.com>
// *HWP Team: Memory
// *HWP Level: 2
// *HWP Consumed by: HB:FSP

#ifndef _MSS_INDEX_H_
#define _MSS_INDEX_H_

#include <fapi2.H>
#include <generic/memory/lib/utils/pos.H>

///
/// @brief Trait classes for the mss::index functions
///
template<fapi2::TargetType T>
class indexTraits
{
    public:
        enum
        {
            MCS_PER_MC = 2,
            PORTS_PER_MCBIST = 4,
            PORTS_PER_MCS = 2,
            DIMMS_PER_PORT = 2,
            MBA_PER_MC = 2,
        };
};

namespace mss
{

///
/// @brief Return an attribute array index from a fapi2 target
/// @tparam T the fapi2::TargetType - derived
/// @param[in] i_target a fapi2 target
/// @return size_t the attribute array index.
///
template< fapi2::TargetType T >
inline size_t index(const fapi2::Target<T>& i_target);

///
/// @brief Return an attribute array index from a DIMM target
/// @param[in] i_target a DIMM target representing the DIMM in question
/// @return size_t the attribute array index.
///
template<>
inline size_t index(const fapi2::Target<fapi2::TARGET_TYPE_DIMM>& i_target)
{
    typedef indexTraits<fapi2::TARGET_TYPE_DIMM> TT;
    return mss::pos(i_target) % TT::DIMMS_PER_PORT;
}

///
///@brief Return an attribute array index from a MCA target
/// @param[in] i_target a MCA target representing the MCA in question
/// @return size_t the attribute array index.
///
template<>
inline size_t index(const fapi2::Target<fapi2::TARGET_TYPE_MCA>& i_target)
{
    typedef indexTraits<fapi2::TARGET_TYPE_MCA> TT;
    return mss::pos(i_target) % TT::PORTS_PER_MCS;
}

///
/// @brief Return an attribute array index from a MCS target
/// @param[in] i_target a MCS target representing the MCS in question
/// @return size_t the attribute array index.
///
template<>
inline size_t index(const fapi2::Target<fapi2::TARGET_TYPE_MCS>& i_target)
{
    typedef indexTraits<fapi2::TARGET_TYPE_MCS> TT;
    return mss::pos(i_target) % TT::MCS_PER_MC;
}

///
/// @brief Return an attribute array index from a rank number
/// @param[in] i_rank uint64_t a rank number DIMM0 {0, 1, 2, 3} DIMM1 {0, 1, 2, 3}
/// @return size_t the attribute array index.
///
inline size_t index(const uint64_t i_rank)
{
    constexpr size_t RANK_MID_POINT = 4;
    return i_rank % RANK_MID_POINT;
}

}
#endif
<commit_msg>L3 work for mss xmls<commit_after>/* IBM_PROLOG_BEGIN_TAG                                                   */
/* This is an automatically generated prolog.                             */
/*                                                                        */
/* $Source: src/import/generic/memory/lib/utils/index.H $                 */
/*                                                                        */
/* OpenPOWER HostBoot Project                                             */
/*                                                                        */
/* Contributors Listed Below - COPYRIGHT 2015,2019                        */
/* [+] International Business Machines Corp.                              */
/*                                                                        */
/*                                                                        */
/* Licensed under the Apache License, Version 2.0 (the "License");        */
/* you may not use this file except in compliance with the License.       */
/* You may obtain a copy of the License at                                */
/*                                                                        */
/*     http://www.apache.org/licenses/LICENSE-2.0                         */
/*                                                                        */
/* Unless required by applicable law or agreed to in writing, software    */
/* distributed under the License is distributed on an "AS IS" BASIS,      */
/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or        */
/* implied. See the License for the specific language governing           */
/* permissions and limitations under the License.                         */
/*                                                                        */
/* IBM_PROLOG_END_TAG                                                     */

///
/// @file index.H
/// @brief Tools to return attribute array index from a fapi2 target
///
// *HWP HWP Owner: Andre Marin <aamarin@us.ibm.com>
// *HWP HWP Backup: Jacob Harvey <jlharvey@us.ibm.com>
// *HWP Team: Memory
// *HWP Level: 3
// *HWP Consumed by: HB:FSP

#ifndef _MSS_INDEX_H_
#define _MSS_INDEX_H_

#include <fapi2.H>
#include <generic/memory/lib/utils/pos.H>

///
/// @brief Trait classes for the mss::index functions
///
template<fapi2::TargetType T>
class indexTraits
{
    public:
        enum
        {
            MCS_PER_MC = 2,
            PORTS_PER_MCBIST = 4,
            PORTS_PER_MCS = 2,
            DIMMS_PER_PORT = 2,
            MBA_PER_MC = 2,
        };
};

namespace mss
{

///
/// @brief Return an attribute array index from a fapi2 target
/// @tparam T the fapi2::TargetType - derived
/// @param[in] i_target a fapi2 target
/// @return size_t the attribute array index.
///
template< fapi2::TargetType T >
inline size_t index(const fapi2::Target<T>& i_target);

///
/// @brief Return an attribute array index from a DIMM target
/// @param[in] i_target a DIMM target representing the DIMM in question
/// @return size_t the attribute array index.
///
template<>
inline size_t index(const fapi2::Target<fapi2::TARGET_TYPE_DIMM>& i_target)
{
    typedef indexTraits<fapi2::TARGET_TYPE_DIMM> TT;
    return mss::pos(i_target) % TT::DIMMS_PER_PORT;
}

///
///@brief Return an attribute array index from a MCA target
/// @param[in] i_target a MCA target representing the MCA in question
/// @return size_t the attribute array index.
///
template<>
inline size_t index(const fapi2::Target<fapi2::TARGET_TYPE_MCA>& i_target)
{
    typedef indexTraits<fapi2::TARGET_TYPE_MCA> TT;
    return mss::pos(i_target) % TT::PORTS_PER_MCS;
}

///
/// @brief Return an attribute array index from a MCS target
/// @param[in] i_target a MCS target representing the MCS in question
/// @return size_t the attribute array index.
///
template<>
inline size_t index(const fapi2::Target<fapi2::TARGET_TYPE_MCS>& i_target)
{
    typedef indexTraits<fapi2::TARGET_TYPE_MCS> TT;
    return mss::pos(i_target) % TT::MCS_PER_MC;
}

///
/// @brief Return an attribute array index from a rank number
/// @param[in] i_rank uint64_t a rank number DIMM0 {0, 1, 2, 3} DIMM1 {0, 1, 2, 3}
/// @return size_t the attribute array index.
///
inline size_t index(const uint64_t i_rank)
{
    constexpr size_t RANK_MID_POINT = 4;
    return i_rank % RANK_MID_POINT;
}

}
#endif
<|endoftext|>


<commit_before>// Virvo - Virtual Reality Volume Rendering
// Copyright (C) 1999-2003 University of Stuttgart, 2004-2005 Brown University
// Contact: Jurgen P. Schulze, jschulze@ucsd.edu
//
// This file is part of Virvo.
//
// Virvo is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2.1 of the License, or (at your option) any later version.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library (see license.txt); if not, write to the
// Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA

#define GLX_GLXEXT_LEGACY

#include <iostream>
#include <errno.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>

#undef USE_NEXTSTEP

#ifdef USE_NEXTSTEP
#  include <mach-o/dyld.h>
#elif defined(__linux__) || defined(LINUX) || defined(__hpux) || defined(__APPLE__) || defined(__sun)
#include <dlfcn.h>
#endif

#include "vvopengl.h"
#include <GL/glx.h>

#include "vvdynlib.h"

using namespace std;

int vvDynLib::close(VV_SHLIB_HANDLE handle)
{
#ifdef _WIN32
  FreeLibrary (handle);
  return 1;

#elif __hpux
  // HP-UX 10.x and 32-bit 11.00 do not pay attention to the ref count when
  // unloading a dynamic lib.  So, if the ref count is more than 1, do not
  // unload the lib.  This will cause a library loaded more than once to
  // not be unloaded until the process runs down, but that's life.  It's
  // better than unloading a library that's in use.
  // So far as I know, there's no way to decrement the refcnt that the kernel
  // is looking at - the shl_descriptor is a copy of what the kernel has, not
  // the actual struct.
  // On 64-bit HP-UX using dlopen, this problem has been fixed.
  struct shl_descriptor  desc;
  if (shl_gethandle_r(handle, &desc) == -1)
    return -1;
  if (desc.ref_count > 1)
    return 1;
#if defined(__GNUC__) || __cplusplus >= 199707L
  shl_unload(handle);
#else
  cxxshl_unload(handle);
#endif                                          /* aC++ vs. Hp C++ */
  return 1;

#else

#ifdef __sun4
  // SunOS4 does not automatically call _fini()!
  void *ptr;
  ptr = sym(handle, "_fini");

  if (ptr != 0)
    (*((int (*)(void)) ptr)) ();                  // Call _fini hook explicitly.
#endif

  dlclose(handle);
  return 1;
#endif
}

char* vvDynLib::error()
{
#ifdef __hpux
  return strerror(errno);
#elif _WIN32
  static char buf[128];
  FormatMessageA (FORMAT_MESSAGE_FROM_SYSTEM,
    NULL,
    GetLastError (),
    0,
    buf,
    sizeof buf,
    NULL);
  return buf;
#else
  return dlerror();
#endif
}

VV_SHLIB_HANDLE vvDynLib::open(const char* filename, int mode)
{
  void* handle;

#ifdef _WIN32
  handle = LoadLibraryA (filename);
#elif __hpux
#if defined(__GNUC__) || __cplusplus >= 199707L
  handle = shl_load(filename, mode, 0L);
#else
  handle = cxxshl_load(filename, mode, 0L);
#endif
#else
  handle = dlopen(filename, mode);
#endif

  if(handle == NULL)
  {
    cerr << error() << endl;
  }

#ifdef __sun4
  if (handle != 0)
  {
    void *ptr;
    // Some systems (e.g., SunOS4) do not automatically call _init(), so
    // we'll have to call it manually.

    ptr = sym(handle, "_init");

                                                  // Call _init hook explicitly.
    if (ptr != 0 && (*((int (*)(void)) ptr)) () == -1)
    {
      // Close down the handle to prevent leaks.
      close(handle);
      return 0;
    }
  }
#endif

#ifdef _WIN32
  mode = mode;                                    // prevent warning
#endif

  return (VV_SHLIB_HANDLE)handle;
}

void* vvDynLib::sym(VV_SHLIB_HANDLE handle, const char* symbolname)
{
#ifdef _WIN32
  return (void *)GetProcAddress(handle, symbolname);
#elif __hpux
  void *value;
  int status;
  shl_t _handle = handle;
  status = shl_findsym(&_handle, symbolname, TYPE_UNDEFINED, &value);
  return status == 0 ? value : NULL;
#else
  return dlsym (handle, symbolname);
#endif
}

// #define USE_DYNLIB_FOR_GL // this has problems
void (*vvDynLib::glSym(const char *symbolname))(void)
{
#if defined(_WIN32)
  return (void (*)()) wglGetProcAddress(symbolname);
#elif defined(USE_DYNLIB_FOR_GL) || defined(__sgi)
  VV_SHLIB_HANDLE dynLib = open("libGL.so", RTLD_NOW);
  void (*func)() = (void (*)()) sym(dynLib, symbolname);
  close(dynLib);
  return func;
#elif defined(__APPLE__)
#ifndef USE_NEXTSTEP
  VV_SHLIB_HANDLE dynLib = open(NULL, RTLD_NOW);
  void (*func)() = (void (*)()) sym(dynLib, symbolname);
  close(dynLib);
  return func;
#else
  NSSymbol symbol;
  // Prepend a '_' for the Unix C symbol mangling convention
  char *mangledSymbolName = new char[strlen(symbolname) + 2];
  strcpy(mangledSymbolName + 1, symbolname);
  mangledSymbolName[0] = '_';
  symbol = NULL;
  if (NSIsSymbolNameDefined (mangledSymbolName))
    symbol = NSLookupAndBindSymbol (mangledSymbolName);
  delete[] (mangledSymbolName);
  return symbol ? (void (*)(void))NSAddressOfSymbol (symbol) : NULL;
#endif
#elif defined(GLX_ARB_get_proc_address)
  return (void (*)())  glXGetProcAddressARB((const GLubyte *)symbolname);
#else
  return (void (*)()) glXGetProcAddress((const GLubyte *)symbolname);
#endif
}
// vim: sw=2:expandtab:softtabstop=2:ts=2:cino=\:0g0t0
<commit_msg>compile fix<commit_after>// Virvo - Virtual Reality Volume Rendering
// Copyright (C) 1999-2003 University of Stuttgart, 2004-2005 Brown University
// Contact: Jurgen P. Schulze, jschulze@ucsd.edu
//
// This file is part of Virvo.
//
// Virvo is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2.1 of the License, or (at your option) any later version.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library (see license.txt); if not, write to the
// Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA

#define GLX_GLXEXT_LEGACY

#include <iostream>
#include <errno.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>

#undef USE_NEXTSTEP

#ifdef USE_NEXTSTEP
#  include <mach-o/dyld.h>
#elif defined(__linux__) || defined(LINUX) || defined(__hpux) || defined(__APPLE__) || defined(__sun)
#include <dlfcn.h>
#endif

#include "vvopengl.h"
#if defined(HAVE_X11) && defined(USE_X11)
#include <GL/glx.h>
#endif

#include "vvdynlib.h"

using namespace std;

int vvDynLib::close(VV_SHLIB_HANDLE handle)
{
#ifdef _WIN32
  FreeLibrary (handle);
  return 1;

#elif __hpux
  // HP-UX 10.x and 32-bit 11.00 do not pay attention to the ref count when
  // unloading a dynamic lib.  So, if the ref count is more than 1, do not
  // unload the lib.  This will cause a library loaded more than once to
  // not be unloaded until the process runs down, but that's life.  It's
  // better than unloading a library that's in use.
  // So far as I know, there's no way to decrement the refcnt that the kernel
  // is looking at - the shl_descriptor is a copy of what the kernel has, not
  // the actual struct.
  // On 64-bit HP-UX using dlopen, this problem has been fixed.
  struct shl_descriptor  desc;
  if (shl_gethandle_r(handle, &desc) == -1)
    return -1;
  if (desc.ref_count > 1)
    return 1;
#if defined(__GNUC__) || __cplusplus >= 199707L
  shl_unload(handle);
#else
  cxxshl_unload(handle);
#endif                                          /* aC++ vs. Hp C++ */
  return 1;

#else

#ifdef __sun4
  // SunOS4 does not automatically call _fini()!
  void *ptr;
  ptr = sym(handle, "_fini");

  if (ptr != 0)
    (*((int (*)(void)) ptr)) ();                  // Call _fini hook explicitly.
#endif

  dlclose(handle);
  return 1;
#endif
}

char* vvDynLib::error()
{
#ifdef __hpux
  return strerror(errno);
#elif _WIN32
  static char buf[128];
  FormatMessageA (FORMAT_MESSAGE_FROM_SYSTEM,
    NULL,
    GetLastError (),
    0,
    buf,
    sizeof buf,
    NULL);
  return buf;
#else
  return dlerror();
#endif
}

VV_SHLIB_HANDLE vvDynLib::open(const char* filename, int mode)
{
  void* handle;

#ifdef _WIN32
  handle = LoadLibraryA (filename);
#elif __hpux
#if defined(__GNUC__) || __cplusplus >= 199707L
  handle = shl_load(filename, mode, 0L);
#else
  handle = cxxshl_load(filename, mode, 0L);
#endif
#else
  handle = dlopen(filename, mode);
#endif

  if(handle == NULL)
  {
    cerr << error() << endl;
  }

#ifdef __sun4
  if (handle != 0)
  {
    void *ptr;
    // Some systems (e.g., SunOS4) do not automatically call _init(), so
    // we'll have to call it manually.

    ptr = sym(handle, "_init");

                                                  // Call _init hook explicitly.
    if (ptr != 0 && (*((int (*)(void)) ptr)) () == -1)
    {
      // Close down the handle to prevent leaks.
      close(handle);
      return 0;
    }
  }
#endif

#ifdef _WIN32
  mode = mode;                                    // prevent warning
#endif

  return (VV_SHLIB_HANDLE)handle;
}

void* vvDynLib::sym(VV_SHLIB_HANDLE handle, const char* symbolname)
{
#ifdef _WIN32
  return (void *)GetProcAddress(handle, symbolname);
#elif __hpux
  void *value;
  int status;
  shl_t _handle = handle;
  status = shl_findsym(&_handle, symbolname, TYPE_UNDEFINED, &value);
  return status == 0 ? value : NULL;
#else
  return dlsym (handle, symbolname);
#endif
}

// #define USE_DYNLIB_FOR_GL // this has problems
void (*vvDynLib::glSym(const char *symbolname))(void)
{
#if defined(_WIN32)
  return (void (*)()) wglGetProcAddress(symbolname);
#elif defined(USE_DYNLIB_FOR_GL) || defined(__sgi)
  VV_SHLIB_HANDLE dynLib = open("libGL.so", RTLD_NOW);
  void (*func)() = (void (*)()) sym(dynLib, symbolname);
  close(dynLib);
  return func;
#elif defined(__APPLE__)
#ifndef USE_NEXTSTEP
  VV_SHLIB_HANDLE dynLib = open(NULL, RTLD_NOW);
  void (*func)() = (void (*)()) sym(dynLib, symbolname);
  close(dynLib);
  return func;
#else
  NSSymbol symbol;
  // Prepend a '_' for the Unix C symbol mangling convention
  char *mangledSymbolName = new char[strlen(symbolname) + 2];
  strcpy(mangledSymbolName + 1, symbolname);
  mangledSymbolName[0] = '_';
  symbol = NULL;
  if (NSIsSymbolNameDefined (mangledSymbolName))
    symbol = NSLookupAndBindSymbol (mangledSymbolName);
  delete[] (mangledSymbolName);
  return symbol ? (void (*)(void))NSAddressOfSymbol (symbol) : NULL;
#endif
#elif defined(GLX_ARB_get_proc_address)
  return (void (*)())  glXGetProcAddressARB((const GLubyte *)symbolname);
#else
  return (void (*)()) glXGetProcAddress((const GLubyte *)symbolname);
#endif
}
// vim: sw=2:expandtab:softtabstop=2:ts=2:cino=\:0g0t0
<|endoftext|>


<commit_before>#include <iostream>
#include <fstream>
#include <map>
#include <sstream>

using namespace std;

struct Node {
    string vert;
    int weight;
    Node *next;
};

struct List {
    struct Node *head;
};

class Graph {
    int vertices;
    int edges;
    struct List *vertexArray;
    int count = 0;
    map<string, int> vertList;

public:

    Graph(int vertices) {
        this->vertices = vertices;
        vertexArray = new List[vertices];
        for (int i = 0; i < vertices; i++) {
            vertexArray[i].head = NULL;
        }
    }

    Node *nextNode(string vert) {
        Node *newNode = new Node;
        newNode->vert = vert;
        newNode->weight = 0;
        newNode->next = NULL;
        return newNode;
    }

    void addVertex(string vert) {
        vertList[vert] = count; //maps Vertex to an integer in the order the Vertex is added
        count++;
    }

    void addEdge(string head, string vert, int weight) {
        Node *newNode = nextNode(vert);
        newNode->weight = weight;
        newNode->next = vertexArray[vertList.at(head)].head;
        vertexArray[vertList.at(head)].head = newNode;
        /*the result of the adjacency graph will look something like this
         * example:
         *
         * inputVertices: a,b,c,d
         * inputEdges: (a,b), (a,d), (b,c) (d,b)]
         *
         * mapping:
         * a<->0, b<->1, c<->2, d<->3
         *
         * adjacency list:
         * arr elements| linked lists connected to elements
         *      0      |->b->d
         *      1      |->c
         *      2      |
         *      3      |->b
         *
         *      the nodes in the linked list should carry the weight of the edge
        */

    }

    bool readGraph(ifstream &inputFile) {
        if (!inputFile.is_open()) {
            cout << "Error opening file " << endl;
        } else {
            string str;
            string str2;
            string str3;
            getline(inputFile, str);
            vertices = stoi(str);
            new Graph(vertices);
            while (!inputFile.eof()) {
                getline(inputFile, str);
                if (atoi(str.c_str())!= 0) {
                    edges = stoi(str);
                    break;
                } else {
                    addVertex(str);
                }
            }
            while (!inputFile.eof()) {
                getline(inputFile, str);
                stringstream line(str);
                line >> str >> str2 >> str3;
                addEdge(str, str2, stoi(str3));
            }
        }
    }

    void TopologicalSort() {}

    void ShortestPath() {}

    void MinimumSpanningTree() {}
};

int main() {
    Graph *graph = new Graph(5); //int parameter shouldn't matter since graph will be recreated in the readGraph function
    string path;
    cout << "Please enter a file path: ";
    cin >> path;
    ifstream inputFile(path);
    graph->readGraph(inputFile);

    return 0;
}
<commit_msg>Merging Branches... readGraph seems to be working, I also added comments explaining code and adjacency list<commit_after>#include <iostream>
#include <fstream>
#include <map>
#include <sstream>

using namespace std;

struct Node {
    string vert;
    int weight;
    Node *next;
};

struct List {
    struct Node *head;
};

class Graph {
    int vertices;
    int edges;
    struct List *vertexArray;
    int count = 0;
    map<string, int> vertList;

public:

    Graph(int vertices) {
        this->vertices = vertices;
        vertexArray = new List[vertices];
        for (int i = 0; i < vertices; i++) {
            vertexArray[i].head = NULL;
        }
    }

    Node *nextNode(string vert) {
        Node *newNode = new Node;
        newNode->vert = vert;
        newNode->weight = 0;
        newNode->next = NULL;
        return newNode;
    }

    void addVertex(string vert) {
        vertList[vert] = count; //maps Vertex to an integer in the order the Vertex is added
        count++;
    }

    void addEdge(string head, string vert, int weight) {
        Node *newNode = nextNode(vert);
        newNode->weight = weight;
        newNode->next = vertexArray[vertList.at(head)].head;
        vertexArray[vertList.at(head)].head = newNode;
        /*the result of the adjacency graph will look something like this
         * example:
         *
         * inputVertices: a,b,c,d
         * inputEdges: (a,b), (a,d), (b,c) (d,b)]
         *
         * mapping:
         * a<->0, b<->1, c<->2, d<->3
         *
         * adjacency list:
         * arr elements| linked lists connected to elements
         *      0      |->b->d
         *      1      |->c
         *      2      |
         *      3      |->b
         *
         *      the nodes in the linked list should carry the weight of the edge
        */

    }

    bool readGraph(ifstream &inputFile) {
        if (!inputFile.is_open()) {
            cout << "Error opening file " << endl;
        } else {
            string str;
            string str2;
            string str3;
            getline(inputFile, str);
            vertices = stoi(str);
            new Graph(vertices);
            while (!inputFile.eof()) {
                getline(inputFile, str);
                if (atoi(str.c_str()) != 0) {
                    edges = stoi(str);
                    break;
                } else {
                    addVertex(str);
                }
            }
            while (!inputFile.eof()) {
                getline(inputFile, str);
                stringstream line(str);
                line >> str >> str2 >> str3;
                addEdge(str, str2, stoi(str3));
            }
        }
    }

    void TopologicalSort() {}

    void ShortestPath() {}

    void MinimumSpanningTree() {}
};

int main() {
    Graph *graph = new Graph(
            5); //int parameter shouldn't matter since graph will be recreated in the readGraph function
    string path;
    cout << "Please enter a file path: ";
    cin >> path;
    ifstream inputFile(path);
    graph->readGraph(inputFile);

    return 0;
}
<|endoftext|>


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

#include "Rule.h"
#include "Html.h"

#include <hext/ParseHext.h>

#include <utility>

Nan::Persistent<v8::Function> Rule::constructor;

NAN_MODULE_INIT(Rule::Init)
{
  v8::Local<v8::FunctionTemplate> tpl = Nan::New<v8::FunctionTemplate>(New);
  tpl->SetClassName(Nan::New("Rule").ToLocalChecked());
  tpl->InstanceTemplate()->SetInternalFieldCount(1);

  Nan::SetPrototypeMethod(tpl, "extract", extract);

  constructor.Reset(Nan::GetFunction(tpl).ToLocalChecked());
  Nan::Set(target,
           Nan::New("Rule").ToLocalChecked(),
           Nan::GetFunction(tpl).ToLocalChecked());
}

Rule::Rule(hext::Rule rule)
: rule_(std::move(rule))
{
}

NAN_METHOD(Rule::New)
{
  if( info.IsConstructCall() )
  {
    Rule * obj = nullptr;
    if( info[0]->IsUndefined() )
    {
      obj = new Rule(hext::ParseHext(""));
    }
    else
    {
      Nan::Utf8String arg(info[0]);
      obj = new Rule(hext::ParseHext(*arg == nullptr ? "" : *arg));
    }

    obj->Wrap(info.This());
    info.GetReturnValue().Set(info.This());
  }
  else
  {
    const int argc = 1;
    v8::Local<v8::Value> argv[argc] = {info[0]};
    v8::Local<v8::Function> cons = Nan::New(constructor);
    info.GetReturnValue().Set(cons->NewInstance(argc, argv));
  }
}

NAN_METHOD(Rule::extract) {
  Rule * obj = Nan::ObjectWrap::Unwrap<Rule>(info.This());
  Nan::MaybeLocal<v8::Object> maybe_arg = Nan::To<v8::Object>(info[0]);
  if( maybe_arg.IsEmpty() )
    return;

  Html * arg = Nan::ObjectWrap::Unwrap<Html>(maybe_arg.ToLocalChecked());
  auto result = obj->rule_.extract(arg->root());
  v8::Local<v8::Array> ret = Nan::New<v8::Array>();
  for(const auto& group : result)
  {
    v8::Local<v8::Array> map = Nan::New<v8::Array>();
    auto it = group.cbegin();
    while( it != group.cend() )
    {
      if( group.count(it->first) < 2 )
      {
        map->Set(
          Nan::New<v8::String>(it->first).ToLocalChecked(),
          Nan::New<v8::String>(it->second).ToLocalChecked()
        );
        ++it;
      }
      else
      {
        // Pack values of non-unique keys into an indexed array
        v8::Local<v8::Array> array = Nan::New<v8::Array>();
        auto lower = group.lower_bound(it->first);
        auto upper = group.upper_bound(it->first);
        for(; lower != upper; ++lower)
          array->Set(
              array->Length(),
              Nan::New<v8::String>(lower->second).ToLocalChecked());
        map->Set(
          Nan::New<v8::String>(it->first).ToLocalChecked(),
          array
        );
        it = upper;
      }
    }

    ret->Set(ret->Length(), map);
  }
  info.GetReturnValue().Set(ret);
}

<commit_msg>libhext/binding/nodejs: hext.Rule.extract: convert ResultMap to v8::Object<commit_after>// Copyright 2016 Thomas Trapp
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include "Rule.h"
#include "Html.h"

#include <hext/ParseHext.h>

#include <utility>

Nan::Persistent<v8::Function> Rule::constructor;

NAN_MODULE_INIT(Rule::Init)
{
  v8::Local<v8::FunctionTemplate> tpl = Nan::New<v8::FunctionTemplate>(New);
  tpl->SetClassName(Nan::New("Rule").ToLocalChecked());
  tpl->InstanceTemplate()->SetInternalFieldCount(1);

  Nan::SetPrototypeMethod(tpl, "extract", extract);

  constructor.Reset(Nan::GetFunction(tpl).ToLocalChecked());
  Nan::Set(target,
           Nan::New("Rule").ToLocalChecked(),
           Nan::GetFunction(tpl).ToLocalChecked());
}

Rule::Rule(hext::Rule rule)
: rule_(std::move(rule))
{
}

NAN_METHOD(Rule::New)
{
  if( info.IsConstructCall() )
  {
    Rule * obj = nullptr;
    if( info[0]->IsUndefined() )
    {
      obj = new Rule(hext::ParseHext(""));
    }
    else
    {
      Nan::Utf8String arg(info[0]);
      obj = new Rule(hext::ParseHext(*arg == nullptr ? "" : *arg));
    }

    obj->Wrap(info.This());
    info.GetReturnValue().Set(info.This());
  }
  else
  {
    const int argc = 1;
    v8::Local<v8::Value> argv[argc] = {info[0]};
    v8::Local<v8::Function> cons = Nan::New(constructor);
    info.GetReturnValue().Set(cons->NewInstance(argc, argv));
  }
}

NAN_METHOD(Rule::extract) {
  Rule * obj = Nan::ObjectWrap::Unwrap<Rule>(info.This());
  Nan::MaybeLocal<v8::Object> maybe_arg = Nan::To<v8::Object>(info[0]);
  if( maybe_arg.IsEmpty() )
    return;

  Html * arg = Nan::ObjectWrap::Unwrap<Html>(maybe_arg.ToLocalChecked());
  auto result = obj->rule_.extract(arg->root());
  v8::Local<v8::Array> ret = Nan::New<v8::Array>();
  for(const auto& group : result)
  {
    v8::Local<v8::Object> map = Nan::New<v8::Object>();
    auto it = group.cbegin();
    while( it != group.cend() )
    {
      if( group.count(it->first) < 2 )
      {
        map->Set(
          Nan::New<v8::String>(it->first).ToLocalChecked(),
          Nan::New<v8::String>(it->second).ToLocalChecked()
        );
        ++it;
      }
      else
      {
        // Pack values of non-unique keys into an indexed array
        v8::Local<v8::Array> array = Nan::New<v8::Array>();
        auto lower = group.lower_bound(it->first);
        auto upper = group.upper_bound(it->first);
        for(; lower != upper; ++lower)
          array->Set(
              array->Length(),
              Nan::New<v8::String>(lower->second).ToLocalChecked());
        map->Set(
          Nan::New<v8::String>(it->first).ToLocalChecked(),
          array
        );
        it = upper;
      }
    }

    ret->Set(ret->Length(), map);
  }
  info.GetReturnValue().Set(ret);
}

<|endoftext|>


<commit_before>#include <string.h>
#include <stdlib.h>
#include <gtk/gtk.h>
#include <getopt.h>
#include <iostream>

#include <bot_vis/bot_vis.h>
#include <lcm/lcm.h>
#include <bot_core/bot_core.h>
#include <path_util/path_util.h>
#include <ConciseArgs>

#include <bot_frames/bot_frames_renderers.h>

//imported renderers
#include <bot_lcmgl_render/lcmgl_bot_renderer.h>
#include <laser_utils/renderer_laser.h>
#include <image_utils/renderer_cam_thumb.h>
#include <visualization/collections_renderer.hpp>
#include <octomap_utils/renderer_octomap.h>
#include <renderer_heightmap/renderer_heightmap.hpp>
#include <renderer_maps/renderer_maps.hpp>

// Individual Renderers:
#include <renderer_drc/renderer_scrollingplots.h>
#include <renderer_drc/renderer_driving.hpp>
#include <renderer_drc/renderer_manipulation.hpp>
#include <renderer_drc/renderer_walking.hpp>

// block of renderers
#include <renderer_robot_state/renderer_robot_state.hpp>
#include <renderer_robot_plan/renderer_robot_plan.hpp>
#include <renderer_affordances/renderer_affordances.hpp>
#include <renderer_end_effector_goal/renderer_end_effector_goal.hpp>

#include "udp_util.h"

using namespace std;

static int
logplayer_remote_on_key_press(BotViewer *viewer, BotEventHandler *ehandler,
        const GdkEventKey *event)
{
    int keyval = event->keyval;

    switch (keyval)
    {
    case 'P':
    case 'p':
        udp_send_string("127.0.0.1", 53261, "PLAYPAUSETOGGLE");
        break;
    case 'N':
    case 'n':
        udp_send_string("127.0.0.1", 53261, "STEP");
        break;
    case '=':
    case '+':
        udp_send_string("127.0.0.1", 53261, "FASTER");
        break;
    case '_':
    case '-':
        udp_send_string("127.0.0.1", 53261, "SLOWER");
        break;
    case '[':
        udp_send_string("127.0.0.1", 53261, "BACK5");
        break;
    case ']':
        udp_send_string("127.0.0.1", 53261, "FORWARD5");
        break;
    default:
        return 0;
    }

    return 1;
}

// TBD - correct location for this code?
static void on_top_view_clicked(GtkToggleToolButton *tb, void *user_data)
{
  BotViewer *self = (BotViewer*) user_data;

  double eye[3];
  double look[3];
  double up[3];
  self->view_handler->get_eye_look(self->view_handler, eye, look, up);
  eye[0] = 0;
  eye[1] = 0;
  eye[2] = 10;
  look[0] = 0;
  look[1] = 0;
  look[2] = 0;
  up[0] = 0;
  up[1] = 10;
  up[2] = 0;
  self->view_handler->set_look_at(self->view_handler, eye, look, up);

  bot_viewer_request_redraw(self);
}

int main(int argc, char *argv[])
{
  setlinebuf(stdout);

  string config_file = "";
  string role = "robot";
  ConciseArgs opt(argc, (char**)argv);
  opt.add(config_file, "c", "config_file","Robot cfg file");
  opt.add(role, "r", "role","Role - robot or base");
  opt.parse();
  std::cout << "config_file: " << config_file << "\n";
  std::cout << "role: " << role << "\n";

  //todo: comment this section
  gtk_init(&argc, &argv);
  glutInit(&argc, argv);
  g_thread_init(NULL);

  lcm_t * lcm;
  string viewer_title="";
  if(role.compare("robot") == 0){
     lcm= bot_lcm_get_global(NULL);
     viewer_title = "(Robot) MIT DRC Viewer";
  }else if(role.compare("base") == 0){
     string lcm_url = "udpm://239.255.12.68:1268?ttl=1";
     lcm= lcm_create(lcm_url.c_str());// bot_lcm_get_global(lcm_url.c_str());
     viewer_title = "(Base) MIT DRC Viewer";
  }else{
    std::cout << "DRC Viewer role not understood, choose: robot or base\n";
    return 1;
  }

  bot_glib_mainloop_attach_lcm(lcm);
  BotParam * bot_param;
  if(config_file.size()) {
    fprintf(stderr,"Reading config from file\n");
    std::string config_path = std::string(getConfigPath()) +'/' + std::string(config_file);
    bot_param = bot_param_new_from_file(config_path.c_str());
    if (bot_param == NULL) {
      std::cerr << "Couldn't get bot param from file %s\n" << config_path << std::endl;
      exit(-1);
    }
  }else {
    bot_param = bot_param_new_from_server(lcm, 0);
    if (bot_param == NULL) {
      fprintf(stderr, "Couldn't get bot param from server.\n");
      return 1;
    }
  }

  BotFrames* bot_frames = bot_frames_new(lcm, bot_param);
  BotViewer* viewer = bot_viewer_new(viewer_title.c_str());

  //die cleanly for control-c etc :-)
  bot_gtk_quit_on_interrupt();

  // logplayer controls
  BotEventHandler *ehandler = (BotEventHandler*) calloc(1, sizeof(BotEventHandler));
  ehandler->name = "LogPlayer Remote";
  ehandler->enabled = 1;
  ehandler->key_press = logplayer_remote_on_key_press;
  bot_viewer_add_event_handler(viewer, ehandler, 0);

  // core renderers
  bot_viewer_add_stock_renderer(viewer, BOT_VIEWER_STOCK_RENDERER_GRID, 1);
  bot_lcmgl_add_renderer_to_viewer(viewer, lcm, 1);
  laser_util_add_renderer_to_viewer(viewer, 1, lcm, bot_param, bot_frames);
  bot_frames_add_renderer_to_viewer(viewer, 1, bot_frames );
  collections_add_renderer_to_viewer(viewer, 1, lcm);

  // Block of Renderers:
  setup_renderer_robot_state(viewer, 0, lcm);
  setup_renderer_robot_plan(viewer, 0, lcm);
  setup_renderer_affordances(viewer, 0, lcm);
  setup_renderer_end_effector_goal(viewer, 0, lcm);

  // Individual Renderers:
  add_octomap_renderer_to_viewer(viewer, 1, lcm);
  heightmap_add_renderer_to_viewer(viewer, 0, lcm, bot_param, bot_frames);
  maps_add_renderer_to_viewer(viewer, 0, lcm, bot_param, bot_frames);
  scrollingplots_add_renderer_to_viewer(viewer, 0, lcm);
  setup_renderer_manipulation(viewer, 0,lcm);
  setup_renderer_driving(viewer, 0, lcm, bot_param, bot_frames);
  setup_renderer_walking(viewer, 0,lcm);

  add_cam_thumb_renderer_to_viewer(viewer, 0, lcm, bot_param, bot_frames);

  // add custon TOP VIEW button
  GtkWidget *top_view_button;
  top_view_button = (GtkWidget *) gtk_tool_button_new_from_stock(GTK_STOCK_ZOOM_FIT);
  gtk_tool_button_set_label(GTK_TOOL_BUTTON(top_view_button), "Top View");
  gtk_tool_item_set_tooltip(GTK_TOOL_ITEM(top_view_button), viewer->tips, "Switch to Top View", NULL);
  gtk_toolbar_insert(GTK_TOOLBAR(viewer->toolbar), GTK_TOOL_ITEM(top_view_button), 4);
  gtk_widget_show(top_view_button);
  g_signal_connect(G_OBJECT(top_view_button), "clicked", G_CALLBACK(on_top_view_clicked), viewer);

  on_top_view_clicked(NULL, (void *) viewer);

  // load the renderer params from the config file.
  char *fname = g_build_filename(g_get_user_config_dir(), ".bot-plugin-drc-viewer", NULL);
  bot_viewer_load_preferences(viewer, fname);

  gtk_main();

  //save the renderer params to the config file.
  bot_viewer_save_preferences(viewer, fname);
  bot_viewer_unref(viewer);
}
<commit_msg>added config writer<commit_after>#include <string.h>
#include <stdlib.h>
#include <gtk/gtk.h>
#include <getopt.h>
#include <iostream>

#include <bot_vis/bot_vis.h>
#include <lcm/lcm.h>
#include <bot_core/bot_core.h>
#include <path_util/path_util.h>
#include <ConciseArgs>

#include <bot_frames/bot_frames_renderers.h>

//imported renderers
#include <bot_lcmgl_render/lcmgl_bot_renderer.h>
#include <laser_utils/renderer_laser.h>
#include <image_utils/renderer_cam_thumb.h>
#include <visualization/collections_renderer.hpp>
#include <octomap_utils/renderer_octomap.h>
#include <renderer_heightmap/renderer_heightmap.hpp>
#include <renderer_maps/renderer_maps.hpp>

// Individual Renderers:
#include <renderer_drc/renderer_scrollingplots.h>
#include <renderer_drc/renderer_driving.hpp>
#include <renderer_drc/renderer_manipulation.hpp>
#include <renderer_drc/renderer_walking.hpp>

// block of renderers
#include <renderer_robot_state/renderer_robot_state.hpp>
#include <renderer_robot_plan/renderer_robot_plan.hpp>
#include <renderer_affordances/renderer_affordances.hpp>
#include <renderer_end_effector_goal/renderer_end_effector_goal.hpp>

#include "udp_util.h"

using namespace std;

static int
logplayer_remote_on_key_press(BotViewer *viewer, BotEventHandler *ehandler,
        const GdkEventKey *event)
{
    int keyval = event->keyval;

    switch (keyval)
    {
    case 'P':
    case 'p':
        udp_send_string("127.0.0.1", 53261, "PLAYPAUSETOGGLE");
        break;
    case 'N':
    case 'n':
        udp_send_string("127.0.0.1", 53261, "STEP");
        break;
    case '=':
    case '+':
        udp_send_string("127.0.0.1", 53261, "FASTER");
        break;
    case '_':
    case '-':
        udp_send_string("127.0.0.1", 53261, "SLOWER");
        break;
    case '[':
        udp_send_string("127.0.0.1", 53261, "BACK5");
        break;
    case ']':
        udp_send_string("127.0.0.1", 53261, "FORWARD5");
        break;
    default:
        return 0;
    }

    return 1;
}

// TBD - correct location for this code?
static void on_top_view_clicked(GtkToggleToolButton *tb, void *user_data)
{
  BotViewer *self = (BotViewer*) user_data;

  double eye[3];
  double look[3];
  double up[3];
  self->view_handler->get_eye_look(self->view_handler, eye, look, up);
  eye[0] = 0;
  eye[1] = 0;
  eye[2] = 10;
  look[0] = 0;
  look[1] = 0;
  look[2] = 0;
  up[0] = 0;
  up[1] = 10;
  up[2] = 0;
  self->view_handler->set_look_at(self->view_handler, eye, look, up);

  bot_viewer_request_redraw(self);
}

int main(int argc, char *argv[])
{
  setlinebuf(stdout);

  string config_file = "";
  string role = "robot";
  ConciseArgs opt(argc, (char**)argv);
  opt.add(config_file, "c", "config_file","Robot cfg file");
  opt.add(role, "r", "role","Role - robot or base");
  opt.parse();
  std::cout << "config_file: " << config_file << "\n";
  std::cout << "role: " << role << "\n";

  //todo: comment this section
  gtk_init(&argc, &argv);
  glutInit(&argc, argv);
  g_thread_init(NULL);

  lcm_t * lcm;
  string viewer_title="";
  string vis_config_file="";
  if(role.compare("robot") == 0){
     lcm= bot_lcm_get_global(NULL);
     viewer_title = "(Robot) MIT DRC Viewer";
     vis_config_file = ".bot-plugin-robot-drc-viewer";
  }else if(role.compare("base") == 0){
     string lcm_url = "udpm://239.255.12.68:1268?ttl=1";
     lcm= lcm_create(lcm_url.c_str());// bot_lcm_get_global(lcm_url.c_str());
     viewer_title = "(Base) MIT DRC Viewer";
     vis_config_file = ".bot-plugin-base-drc-viewer";
  }else{
    std::cout << "DRC Viewer role not understood, choose: robot or base\n";
    return 1;
  }

  bot_glib_mainloop_attach_lcm(lcm);
  BotParam * bot_param;
  if(config_file.size()) {
    fprintf(stderr,"Reading config from file\n");
    std::string config_path = std::string(getConfigPath()) +'/' + std::string(config_file);
    bot_param = bot_param_new_from_file(config_path.c_str());
    if (bot_param == NULL) {
      std::cerr << "Couldn't get bot param from file %s\n" << config_path << std::endl;
      exit(-1);
    }
  }else {
    bot_param = bot_param_new_from_server(lcm, 0);
    if (bot_param == NULL) {
      fprintf(stderr, "Couldn't get bot param from server.\n");
      return 1;
    }
  }

  BotFrames* bot_frames = bot_frames_new(lcm, bot_param);
  BotViewer* viewer = bot_viewer_new(viewer_title.c_str());

  //die cleanly for control-c etc :-)
  bot_gtk_quit_on_interrupt();

  // logplayer controls
  BotEventHandler *ehandler = (BotEventHandler*) calloc(1, sizeof(BotEventHandler));
  ehandler->name = "LogPlayer Remote";
  ehandler->enabled = 1;
  ehandler->key_press = logplayer_remote_on_key_press;
  bot_viewer_add_event_handler(viewer, ehandler, 0);

  // core renderers
  bot_viewer_add_stock_renderer(viewer, BOT_VIEWER_STOCK_RENDERER_GRID, 1);
  bot_lcmgl_add_renderer_to_viewer(viewer, lcm, 1);
  laser_util_add_renderer_to_viewer(viewer, 1, lcm, bot_param, bot_frames);
  bot_frames_add_renderer_to_viewer(viewer, 1, bot_frames );
  collections_add_renderer_to_viewer(viewer, 1, lcm);

  // Block of Renderers:
  setup_renderer_robot_state(viewer, 0, lcm);
  setup_renderer_robot_plan(viewer, 0, lcm);
  setup_renderer_affordances(viewer, 0, lcm);
  setup_renderer_end_effector_goal(viewer, 0, lcm);

  // Individual Renderers:
  add_octomap_renderer_to_viewer(viewer, 1, lcm);
  heightmap_add_renderer_to_viewer(viewer, 0, lcm, bot_param, bot_frames);
  maps_add_renderer_to_viewer(viewer, 0, lcm, bot_param, bot_frames);
  scrollingplots_add_renderer_to_viewer(viewer, 0, lcm);
  setup_renderer_manipulation(viewer, 0,lcm);
  setup_renderer_driving(viewer, 0, lcm, bot_param, bot_frames);
  setup_renderer_walking(viewer, 0,lcm);

  add_cam_thumb_renderer_to_viewer(viewer, 0, lcm, bot_param, bot_frames);

  // add custon TOP VIEW button
  GtkWidget *top_view_button;
  top_view_button = (GtkWidget *) gtk_tool_button_new_from_stock(GTK_STOCK_ZOOM_FIT);
  gtk_tool_button_set_label(GTK_TOOL_BUTTON(top_view_button), "Top View");
  gtk_tool_item_set_tooltip(GTK_TOOL_ITEM(top_view_button), viewer->tips, "Switch to Top View", NULL);
  gtk_toolbar_insert(GTK_TOOLBAR(viewer->toolbar), GTK_TOOL_ITEM(top_view_button), 4);
  gtk_widget_show(top_view_button);
  g_signal_connect(G_OBJECT(top_view_button), "clicked", G_CALLBACK(on_top_view_clicked), viewer);

  on_top_view_clicked(NULL, (void *) viewer);

  // load the renderer params from the config file.
  char *fname = g_build_filename(g_get_user_config_dir(), ".bot-plugin-drc-viewer", NULL);
  bot_viewer_load_preferences(viewer, fname);

  gtk_main();

  //save the renderer params to the config file.
  bot_viewer_save_preferences(viewer, fname);
  bot_viewer_unref(viewer);
}
<|endoftext|>


<commit_before>// -*- Mode: C++; tab-width: 2; -*-
// vi: set ts=2:
//

// order of includes is important: first qapplication, then BALL includes
#include <QtWidgets/QApplication>
#include <QtWidgets/QMessageBox>
#include <QtCore/QTranslator>

#include "mainframe.h"
#include <BALL/SYSTEM/path.h>
#include <BALL/SYSTEM/directory.h>

void logMessages(QtMsgType type, const QMessageLogContext& context, const QString& message)
{
	BALL::String s(message.toStdString());
	if (s.hasPrefix("QTextBrowser")) return;

	switch ( type ) {
		case QtDebugMsg:
            BALL::Log.info() << message.toStdString() << " " << (context.file ? context.file : "(unknown context)")
                                                      << " " << context.line
                                                      << " " << (context.function ? context.function : "(unknown function)") << std::endl;
				break;
		case QtWarningMsg:
            BALL::Log.warn() << message.toStdString() << " " << (context.file ? context.file : "(unknown context)")
                                                      << " " << context.line
                                                      << " " << (context.function ? context.function : "(unknown function)") << std::endl;
				break;
		case QtFatalMsg:
				fprintf( stderr, "Fatal: %s\n", message.toLatin1().constData() );
				abort();                    // deliberately core dump
		case QtCriticalMsg:
				fprintf( stderr, "Critical: %s\n", message.toLatin1().constData() );
				abort();                    // deliberately core dump
	}
}

// uncomment this to use debugging to std::cout!
//#undef BALL_OS_WINDOWS

#ifndef BALL_OS_WINDOWS
int main(int argc, char **argv)
{
#else
int WINAPI WinMain(HINSTANCE, HINSTANCE, PSTR cmd_line, int)
{
	int argc = __argc;
	char** argv = __argv;
#endif

	qInstallMessageHandler(logMessages);

	// *sigh* this is required as long as Qt does not correctly paint on OpenGL 2 contexts
	//QGL::setPreferredPaintEngine(QPaintEngine::OpenGL);

	QApplication application(argc, argv);

	QStringList arguments = application.arguments();
	QStringList::const_iterator arg_it;

	bool kiosk_mode = false;
	for (arg_it = arguments.constBegin(); arg_it != arguments.constEnd(); ++arg_it)
	{
		if (arg_it->toLocal8Bit() == "-kiosk")
		{
			kiosk_mode = true;
		}
	}

	if (kiosk_mode)
	{
		BALL::VIEW::UIOperationMode::instance().setMode(BALL::VIEW::UIOperationMode::MODE_KIOSK);
	}

	// =============== testing for opengl support ======================================
	if (!QGLFormat::hasOpenGL())
	{
		QMessageBox::critical(0, "Error while starting BALLView",
				"Your computer has no OpenGL support, please install the correct drivers. Aborting for now...",
				QMessageBox::Ok, Qt::NoButton, Qt::NoButton);
		return -1;
	}

	BALL::String home_dir = BALL::Directory::getUserHomeDir();

	// =============== load translations =====================
	BALL::INIFile f(home_dir + BALL::FileSystem::PATH_SEPARATOR + ".BALLView");
	f.read();

	if (f.hasEntry("GENERAL", "language"))
	{
		QString str = f.getValue("GENERAL", "language").c_str();

		if (str != "en_US")
		{
			QString loc = "BALLView-" + str;

			BALL::Path p;
			QStringList dpaths = QString(p.getDataPath().c_str()).split("\n");

			QTranslator* translator = new QTranslator(&application);
			foreach(QString str, dpaths)
			{
				translator->load(loc, str + "BALLView/translations");
				if (!translator->isEmpty())
				{
					QCoreApplication::installTranslator(translator);
					break;
				}
			}
		}
	}

	// =============== testing if we can write in current directory =====================
	if (home_dir == "")
	{
		try
		{
			BALL::String temp_file_name;
			BALL::File::createTemporaryFilename(temp_file_name);
			BALL::File out(temp_file_name, std::ios::out);
			out << "test" << std::endl;
			out.remove();
		}
		catch(...)
		{
			QMessageBox::warning(0, "Error while starting BALLView",
					QString("You dont have write access to the current working directory\n") +
					"and BALLView can not find your home directory. This can cause\n" +
					"unexpected behaviour. Please start BALLView from your homedir with\n" +
					"absolute path (e.g. C:\\Programs\\BALLView\\BALLView).\n");
		}
	}

	// =============== initialize Mainframe ============================================
	// Create the mainframe.
	BALL::Mainframe mainframe(0, "Mainframe");

	// can we use the users homedir as working dir?
	if (home_dir != "")
	{
		mainframe.setWorkingDir(home_dir);
	}

	// Register the mainfram (required for Python support).
	mainframe.setIdentifier("Mainframe");
	mainframe.registerThis();

	// Show the main window.
	mainframe.show();

	// =============== parsing command line arguments ==================================
	// If there are additional command line arguments, interpret them as files to open or logging flag.
	for (BALL::Index i = 1; i < argc; ++i)
	{
		BALL::String argument(argv[i]);
		if (argument == "-l")
		{
			mainframe.enableLoggingToFile();
			continue;
		}
		else if (argument == "-kiosk")
		{
			// the kiosk mode has already been handled
			continue;
		}

		mainframe.openFile(argument);
	}

	// enable ending of program from python script
	if (mainframe.isAboutToQuit())
	{
		mainframe.aboutToExit();
		return 0;
	}

	// Hand over control to the application.
	return application.exec();
}
<commit_msg>[BALLView] Fix: Var redefinition warning<commit_after>// -*- Mode: C++; tab-width: 2; -*-
// vi: set ts=2:
//

// order of includes is important: first qapplication, then BALL includes
#include <QtWidgets/QApplication>
#include <QtWidgets/QMessageBox>
#include <QtCore/QTranslator>

#include "mainframe.h"
#include <BALL/SYSTEM/path.h>
#include <BALL/SYSTEM/directory.h>

void logMessages(QtMsgType type, const QMessageLogContext& context, const QString& message)
{
	BALL::String s(message.toStdString());
	if (s.hasPrefix("QTextBrowser")) return;

	switch ( type ) {
		case QtDebugMsg:
            BALL::Log.info() << message.toStdString() << " " << (context.file ? context.file : "(unknown context)")
                                                      << " " << context.line
                                                      << " " << (context.function ? context.function : "(unknown function)") << std::endl;
				break;
		case QtWarningMsg:
            BALL::Log.warn() << message.toStdString() << " " << (context.file ? context.file : "(unknown context)")
                                                      << " " << context.line
                                                      << " " << (context.function ? context.function : "(unknown function)") << std::endl;
				break;
		case QtFatalMsg:
				fprintf( stderr, "Fatal: %s\n", message.toLatin1().constData() );
				abort();                    // deliberately core dump
		case QtCriticalMsg:
				fprintf( stderr, "Critical: %s\n", message.toLatin1().constData() );
				abort();                    // deliberately core dump
	}
}

// uncomment this to use debugging to std::cout!
//#undef BALL_OS_WINDOWS

#ifndef BALL_OS_WINDOWS
int main(int argc, char **argv)
{
#else
int WINAPI WinMain(HINSTANCE, HINSTANCE, PSTR cmd_line, int)
{
	int argc = __argc;
	char** argv = __argv;
#endif

	qInstallMessageHandler(logMessages);

	// *sigh* this is required as long as Qt does not correctly paint on OpenGL 2 contexts
	//QGL::setPreferredPaintEngine(QPaintEngine::OpenGL);

	QApplication application(argc, argv);

	QStringList arguments = application.arguments();
	QStringList::const_iterator arg_it;

	bool kiosk_mode = false;
	for (arg_it = arguments.constBegin(); arg_it != arguments.constEnd(); ++arg_it)
	{
		if (arg_it->toLocal8Bit() == "-kiosk")
		{
			kiosk_mode = true;
		}
	}

	if (kiosk_mode)
	{
		BALL::VIEW::UIOperationMode::instance().setMode(BALL::VIEW::UIOperationMode::MODE_KIOSK);
	}

	// =============== testing for opengl support ======================================
	if (!QGLFormat::hasOpenGL())
	{
		QMessageBox::critical(0, "Error while starting BALLView",
				"Your computer has no OpenGL support, please install the correct drivers. Aborting for now...",
				QMessageBox::Ok, Qt::NoButton, Qt::NoButton);
		return -1;
	}

	BALL::String home_dir = BALL::Directory::getUserHomeDir();

	// =============== load translations =====================
	BALL::INIFile f(home_dir + BALL::FileSystem::PATH_SEPARATOR + ".BALLView");
	f.read();

	if (f.hasEntry("GENERAL", "language"))
	{
		QString str = f.getValue("GENERAL", "language").c_str();

		if (str != "en_US")
		{
			QString loc = "BALLView-" + str;

			BALL::Path p;
			QStringList dpaths = QString(p.getDataPath().c_str()).split("\n");

			QTranslator* translator = new QTranslator(&application);
			foreach(QString s, dpaths)
			{
				translator->load(loc, s + "BALLView/translations");
				if (!translator->isEmpty())
				{
					QCoreApplication::installTranslator(translator);
					break;
				}
			}
		}
	}

	// =============== testing if we can write in current directory =====================
	if (home_dir == "")
	{
		try
		{
			BALL::String temp_file_name;
			BALL::File::createTemporaryFilename(temp_file_name);
			BALL::File out(temp_file_name, std::ios::out);
			out << "test" << std::endl;
			out.remove();
		}
		catch(...)
		{
			QMessageBox::warning(0, "Error while starting BALLView",
					QString("You dont have write access to the current working directory\n") +
					"and BALLView can not find your home directory. This can cause\n" +
					"unexpected behaviour. Please start BALLView from your homedir with\n" +
					"absolute path (e.g. C:\\Programs\\BALLView\\BALLView).\n");
		}
	}

	// =============== initialize Mainframe ============================================
	// Create the mainframe.
	BALL::Mainframe mainframe(0, "Mainframe");

	// can we use the users homedir as working dir?
	if (home_dir != "")
	{
		mainframe.setWorkingDir(home_dir);
	}

	// Register the mainfram (required for Python support).
	mainframe.setIdentifier("Mainframe");
	mainframe.registerThis();

	// Show the main window.
	mainframe.show();

	// =============== parsing command line arguments ==================================
	// If there are additional command line arguments, interpret them as files to open or logging flag.
	for (BALL::Index i = 1; i < argc; ++i)
	{
		BALL::String argument(argv[i]);
		if (argument == "-l")
		{
			mainframe.enableLoggingToFile();
			continue;
		}
		else if (argument == "-kiosk")
		{
			// the kiosk mode has already been handled
			continue;
		}

		mainframe.openFile(argument);
	}

	// enable ending of program from python script
	if (mainframe.isAboutToQuit())
	{
		mainframe.aboutToExit();
		return 0;
	}

	// Hand over control to the application.
	return application.exec();
}
<|endoftext|>


<commit_before>// $Id: persistenceManager.C,v 1.6 2000/03/16 12:43:53 oliver Exp $

#include <BALL/CONCEPT/persistenceManager.h>
#include <BALL/KERNEL/system.h>
#include <BALL/KERNEL/protein.h>
#include <BALL/KERNEL/nucleicAcid.h>
#include <BALL/KERNEL/bond.h>

// #define DEBUG_PERSISTENCE

using namespace std;

namespace BALL
{

	PersistenceManager::PersistenceManager()
	{
		// register all kernel classes
		registerKernelClasses_();
	}

	PersistenceManager::PersistenceManager(istream& is)
	{
		// register all kernel classes
		registerKernelClasses_();
		setIstream(is);
	}

	PersistenceManager::PersistenceManager(ostream& os)
	{
		// register all kernel classes
		registerKernelClasses_();
		setOstream(os);
	}

	PersistenceManager::PersistenceManager(istream& is, ostream& os)
	{
		// register all kernel classes
		registerKernelClasses_();
		setIstream(is);
		setOstream(os);
	}

	PersistenceManager::~PersistenceManager()
	{
	}

	void PersistenceManager::registerKernelClasses_()
	{
		// register all kernel classes, their base classes,
		// and the classes used in kernel classes

		registerDefault<BaseFragment>();
		registerDefault<NamedProperty>();
		registerDefault<Vector3>();
		registerDefault<Composite>();
		registerDefault<Atom>();
		registerDefault<Bond>();
		registerDefault<Fragment>();
		registerDefault<System>();
		registerDefault<Molecule>();
		registerDefault<PDBAtom>();
		registerDefault<Residue>();
		registerDefault<Chain>();
		registerDefault<Protein>();
		registerDefault<SecondaryStructure>();
		registerDefault<NucleicAcid>();
		registerDefault<Nucleotide>();
	}

	PersistenceManager& PersistentObject::operator >> (PersistenceManager& pm) const
	{
		pm.startOutput();
		persistentWrite(pm, "");
		pm.endOutput();
		return pm;
	}

	void PersistentObject::persistentWrite(PersistenceManager& /* pm */, const char* /* name */) const
	{
	}

	void PersistentObject::persistentRead(PersistenceManager& /* pm */)
	{
	}

	void PersistenceManager::registerClass(String signature, const CreateMethod	m)
	{
		create_methods_.insert(signature, m);
	}

	void* PersistenceManager::createObject(String signature) const
	{
		if (create_methods_.has(signature))
		{
			CreateMethod method = create_methods_[signature];

#			ifdef DEBUG_PERSISTENCE
				Log.info() << "PersistenceManager: created object of type" << signature << endl;
#			endif

			return method();

		} else {
			return 0;
		}
	}

	Size PersistenceManager::getNumberOfClasses() const
	{
		return create_methods_.size();
	}

	void PersistenceManager::setOstream(ostream& s)
	{
		ostr_ = &s;

		object_out_.clear();
		object_out_needed_.clear();
	}

	void PersistenceManager::setIstream(istream& s)
	{
		istr_ = &s;

		pointer_list_.clear();
		pointer_map_.clear();
	}

	void PersistenceManager::startOutput()
	{
		object_out_.clear();
		object_out_needed_.clear();
		writeStreamHeader();
	}

	void PersistenceManager::endOutput()
	{
		writeStreamTrailer();
		addNeededObjects_();
		writeStreamTrailer();
	}

	PersistenceManager& PersistenceManager::operator << (const PersistentObject& object)
	{
		object >> *this;
		return *this;
	}

	PersistenceManager& PersistenceManager::operator >> (PersistentObject*& object_ptr)
	{
		object_ptr = readObject();
		return *this;
	}

	PersistentObject*	PersistenceManager::readObject()
	{
		if (istr_ == 0)
		{
			return 0;
		}

		PersistentObject*	first_object = 0;
		PersistentObject*	obj = 0;

		pointer_map_.clear();
		pointer_list_.clear();
		object_in_.clear();

		String						type_name;
		LongPointerType		ptr;

		// if an error happened, just exit the loop
		// to clean up the mess
		bool error = false;

		// loop while the stream is not empty,
		// we did not read the END mark and
		// an error did not occur
		while (*istr_ && checkStreamHeader() && !error)
		{
			// retrieve the first object signature
			getObjectHeader(type_name, ptr);

			if (!create_methods_.has(type_name))
			{
				// something bad happend - abort everything and clean up!
				Log.level(LogStream::ERROR) << "Cannot create object of unregistered class " << type_name << "!" << endl;
				error = true;
				break;
			}

			// Create an instance of type_name

			CreateMethod	m = create_methods_[type_name];
			obj = (PersistentObject*)m();

			// check whether the creation was successful
			if (obj == 0)
			{
				Log.level(LogStream::ERROR) << "Could not create object of typ " << type_name << "!" << endl;
				error = false;
				break;
			}

			// remember the this pointer of the new object
			object_in_.push_back(obj);

			// check
			if (ptr == 0)
			{
				Log.level(LogStream::ERROR) << "Read invalid object pointer!" << endl;
				error = true;
				break;
			}

			// store the old pointer and the new pointer
			addPointerPair_(ptr, (void*)obj);

			// make the new object read itself
			(*obj).persistentRead(*this);

			if (!checkObjectTrailer("") || !checkStreamTrailer())
			{
				error = false;
				break;
			}

			// remember the first object created to -
			// this is our return valued
			if (first_object == 0)
			{
				first_object = obj;
			}
		}

		if (error)
		{
			return 0;
		}

		// update the pointers: replace all old object addresses with the
		// new ones
		if (!updatePointers_())
		{
			return 0;
		}

		// finalize all objects
		ObjectList::iterator object_it = object_in_.begin();
		for (; object_it != object_in_.end(); object_it++)
		{
			const_cast<PersistentObject*>(*object_it)->finalize();
		}

		// return the first object read
		return first_object;
	}

	void PersistenceManager::addPointerPair_(LongPointerType old_ptr, void* new_ptr)
	{
#		ifdef DEBUG_PERSISTENCE
			Log.info() << "PersistenceManager: pointer pair (" << old_ptr << "/" << new_ptr << ")" << endl;
#		endif

		pointer_map_.insert(pair<LongPointerType, void*>(old_ptr, new_ptr));
	}

	void PersistenceManager::addNeededObjects_()
	{
		while (object_out_needed_.size() > 0)
		{
			const PersistentObject*	obj = object_out_needed_.back();
			object_out_needed_.pop_back();

			if (!object_out_.has(obj))
			{
				writeStreamHeader();
				(*obj).persistentWrite(*this);
				writeStreamTrailer();
			}

		}
	}

	bool PersistenceManager::updatePointers_()
	{
		// assume everything will go smoothly
		bool result = true;

		PointerList::iterator it = pointer_list_.begin();
		for (; it != pointer_list_.end(); ++it)
		{
			if (pointer_map_.has((*it).second))
			{
				// OK. We know the correct value for the pointer
				(*(*it).first) = pointer_map_[(*it).second];
			} else {
				Log.level(LogStream::ERROR) << "PersistenceManager: Could not assign object for pointer to "
					<< (*it).second << endl;
				result = false;
			}
		}

		return result;
	}

} // namespace BALL
<commit_msg>fixed: WS60ea CC did not understand the template method syntax - reverted to old method<commit_after>// $Id: persistenceManager.C,v 1.7 2000/03/17 11:17:53 oliver Exp $

#include <BALL/CONCEPT/persistenceManager.h>
#include <BALL/KERNEL/system.h>
#include <BALL/KERNEL/protein.h>
#include <BALL/KERNEL/nucleicAcid.h>
#include <BALL/KERNEL/bond.h>

// #define DEBUG_PERSISTENCE

using namespace std;

namespace BALL
{

	PersistenceManager::PersistenceManager()
	{
		// register all kernel classes
		registerKernelClasses_();
	}

	PersistenceManager::PersistenceManager(istream& is)
	{
		// register all kernel classes
		registerKernelClasses_();
		setIstream(is);
	}

	PersistenceManager::PersistenceManager(ostream& os)
	{
		// register all kernel classes
		registerKernelClasses_();
		setOstream(os);
	}

	PersistenceManager::PersistenceManager(istream& is, ostream& os)
	{
		// register all kernel classes
		registerKernelClasses_();
		setIstream(is);
		setOstream(os);
	}

	PersistenceManager::~PersistenceManager()
	{
	}

	void PersistenceManager::registerKernelClasses_()
	{
		// register all kernel classes, their base classes,
		// and the classes used in kernel classes

		#define REGISTER_CLASS(T) registerClass(RTTI::getStreamName<T>(), T::createDefault);
		REGISTER_CLASS(BaseFragment)
		REGISTER_CLASS(NamedProperty)
		REGISTER_CLASS(Vector3)
		REGISTER_CLASS(Composite)
		REGISTER_CLASS(Atom)
		REGISTER_CLASS(Bond)
		REGISTER_CLASS(Fragment)
		REGISTER_CLASS(System)
		REGISTER_CLASS(Molecule)
		REGISTER_CLASS(PDBAtom)
		REGISTER_CLASS(Residue)
		REGISTER_CLASS(Chain)
		REGISTER_CLASS(Protein)
		REGISTER_CLASS(SecondaryStructure)
		REGISTER_CLASS(NucleicAcid)
		REGISTER_CLASS(Nucleotide)
		#undef REGISTER_CLASS
	}

	PersistenceManager& PersistentObject::operator >> (PersistenceManager& pm) const
	{
		pm.startOutput();
		persistentWrite(pm, "");
		pm.endOutput();
		return pm;
	}

	void PersistentObject::persistentWrite(PersistenceManager& /* pm */, const char* /* name */) const
	{
	}

	void PersistentObject::persistentRead(PersistenceManager& /* pm */)
	{
	}

	void PersistenceManager::registerClass(String signature, const CreateMethod	m)
	{
		create_methods_.insert(signature, m);
	}

	void* PersistenceManager::createObject(String signature) const
	{
		if (create_methods_.has(signature))
		{
			CreateMethod method = create_methods_[signature];

#			ifdef DEBUG_PERSISTENCE
				Log.info() << "PersistenceManager: created object of type" << signature << endl;
#			endif

			return method();

		} else {
			return 0;
		}
	}

	Size PersistenceManager::getNumberOfClasses() const
	{
		return create_methods_.size();
	}

	void PersistenceManager::setOstream(ostream& s)
	{
		ostr_ = &s;

		object_out_.clear();
		object_out_needed_.clear();
	}

	void PersistenceManager::setIstream(istream& s)
	{
		istr_ = &s;

		pointer_list_.clear();
		pointer_map_.clear();
	}

	void PersistenceManager::startOutput()
	{
		object_out_.clear();
		object_out_needed_.clear();
		writeStreamHeader();
	}

	void PersistenceManager::endOutput()
	{
		writeStreamTrailer();
		addNeededObjects_();
		writeStreamTrailer();
	}

	PersistenceManager& PersistenceManager::operator << (const PersistentObject& object)
	{
		object >> *this;
		return *this;
	}

	PersistenceManager& PersistenceManager::operator >> (PersistentObject*& object_ptr)
	{
		object_ptr = readObject();
		return *this;
	}

	PersistentObject*	PersistenceManager::readObject()
	{
		if (istr_ == 0)
		{
			return 0;
		}

		PersistentObject*	first_object = 0;
		PersistentObject*	obj = 0;

		pointer_map_.clear();
		pointer_list_.clear();
		object_in_.clear();

		String						type_name;
		LongPointerType		ptr;

		// if an error happened, just exit the loop
		// to clean up the mess
		bool error = false;

		// loop while the stream is not empty,
		// we did not read the END mark and
		// an error did not occur
		while (*istr_ && checkStreamHeader() && !error)
		{
			// retrieve the first object signature
			getObjectHeader(type_name, ptr);

			if (!create_methods_.has(type_name))
			{
				// something bad happend - abort everything and clean up!
				Log.level(LogStream::ERROR) << "Cannot create object of unregistered class " << type_name << "!" << endl;
				error = true;
				break;
			}

			// Create an instance of type_name

			CreateMethod	m = create_methods_[type_name];
			obj = (PersistentObject*)m();

			// check whether the creation was successful
			if (obj == 0)
			{
				Log.level(LogStream::ERROR) << "Could not create object of typ " << type_name << "!" << endl;
				error = false;
				break;
			}

			// remember the this pointer of the new object
			object_in_.push_back(obj);

			// check
			if (ptr == 0)
			{
				Log.level(LogStream::ERROR) << "Read invalid object pointer!" << endl;
				error = true;
				break;
			}

			// store the old pointer and the new pointer
			addPointerPair_(ptr, (void*)obj);

			// make the new object read itself
			(*obj).persistentRead(*this);

			if (!checkObjectTrailer("") || !checkStreamTrailer())
			{
				error = false;
				break;
			}

			// remember the first object created to -
			// this is our return valued
			if (first_object == 0)
			{
				first_object = obj;
			}
		}

		if (error)
		{
			return 0;
		}

		// update the pointers: replace all old object addresses with the
		// new ones
		if (!updatePointers_())
		{
			return 0;
		}

		// finalize all objects
		ObjectList::iterator object_it = object_in_.begin();
		for (; object_it != object_in_.end(); object_it++)
		{
			const_cast<PersistentObject*>(*object_it)->finalize();
		}

		// return the first object read
		return first_object;
	}

	void PersistenceManager::addPointerPair_(LongPointerType old_ptr, void* new_ptr)
	{
#		ifdef DEBUG_PERSISTENCE
			Log.info() << "PersistenceManager: pointer pair (" << old_ptr << "/" << new_ptr << ")" << endl;
#		endif

		pointer_map_.insert(pair<LongPointerType, void*>(old_ptr, new_ptr));
	}

	void PersistenceManager::addNeededObjects_()
	{
		while (object_out_needed_.size() > 0)
		{
			const PersistentObject*	obj = object_out_needed_.back();
			object_out_needed_.pop_back();

			if (!object_out_.has(obj))
			{
				writeStreamHeader();
				(*obj).persistentWrite(*this);
				writeStreamTrailer();
			}

		}
	}

	bool PersistenceManager::updatePointers_()
	{
		// assume everything will go smoothly
		bool result = true;

		PointerList::iterator it = pointer_list_.begin();
		for (; it != pointer_list_.end(); ++it)
		{
			if (pointer_map_.has((*it).second))
			{
				// OK. We know the correct value for the pointer
				(*(*it).first) = pointer_map_[(*it).second];
			} else {
				Log.level(LogStream::ERROR) << "PersistenceManager: Could not assign object for pointer to "
					<< (*it).second << endl;
				result = false;
			}
		}

		return result;
	}

} // namespace BALL
<|endoftext|>