<commit_before>#ifndef MJOLNIR_INPUT_READ_INPUT_FILE_HPP
#define MJOLNIR_INPUT_READ_INPUT_FILE_HPP
#include <extlib/toml/toml.hpp>
#include <mjolnir/core/BoundaryCondition.hpp>
#include <mjolnir/core/SimulatorBase.hpp>
#include <mjolnir/core/SimulatorTraits.hpp>
#include <mjolnir/core/Unit.hpp>
#include <mjolnir/util/logger.hpp>
#include <mjolnir/input/utility.hpp>
#include <mjolnir/input/read_units.hpp>
#include <mjolnir/input/read_path.hpp>

#ifdef MJOLNIR_WITH_OPENMP
#include <mjolnir/omp/omp.hpp>
#endif

#include <memory>

namespace mjolnir
{

template<typename realT, template<typename, typename> class boundaryT>
std::unique_ptr<SimulatorBase>
read_parallelism(const toml::value& root, const toml::value& simulator)
{
    MJOLNIR_GET_DEFAULT_LOGGER();
    MJOLNIR_LOG_FUNCTION();

    if(simulator.as_table().count("parallelism") == 0)
    {
        MJOLNIR_LOG_NOTICE("execute on single core");
        return read_units<SimulatorTraits<realT, boundaryT>>(root, simulator);
    }

    const auto parallelism = toml::find(simulator, "parallelism");
    if(parallelism.is_string() && parallelism.as_string() == "sequencial")
    {
        MJOLNIR_LOG_NOTICE("execute on single core");
        return read_units<SimulatorTraits<realT, boundaryT>>(root, simulator);
    }
    else if(parallelism.is_string() &&
           (parallelism.as_string() == "openmp" ||
            parallelism.as_string() == "OpenMP"))
    {
#ifdef MJOLNIR_WITH_OPENMP
        MJOLNIR_LOG_NOTICE("execute on ", omp_get_max_threads() ," cores with openmp");
        return read_units<OpenMPSimulatorTraits<realT, boundaryT>>(root, simulator);
#else
        MJOLNIR_LOG_WARN("OpenMP flag is set, but OpenMP is not enabled when building.");
        MJOLNIR_LOG_WARN("Cannot use OpenMP, running with single core.");
        return read_units<SimulatorTraits<realT, boundaryT>>(root, simulator);
#endif
    }
    else
    {
        throw_exception<std::runtime_error>(toml::format_error("[error] "
            "mjolnir::read_parallelism: invalid variable ",
            toml::find(simulator, "parallelism"), "here", {
            "- \"sequencial\": run with only 1 core (default)",
            "- \"openmp\"    : use openmp to parallelize."
            }));
    }
}

template<typename realT>
std::unique_ptr<SimulatorBase>
read_boundary(const toml::value& root, const toml::value& simulator)
{
    MJOLNIR_GET_DEFAULT_LOGGER();
    MJOLNIR_LOG_FUNCTION();

    const auto boundary = toml::find<std::string>(simulator, "boundary_type");
    if(boundary == "Unlimited")
    {
        MJOLNIR_LOG_NOTICE("Boundary Condition is Unlimited");
        return read_parallelism<realT, UnlimitedBoundary>(root, simulator);
    }
    else if(boundary == "Periodic")
    {
        MJOLNIR_LOG_NOTICE("Boundary Condition is Periodic. "
                           "The shape is cuboid.");
        return read_parallelism<realT, CuboidalPeriodicBoundary>(root, simulator);
    }
    else if(boundary == "PeriodicCuboid")
    {
        MJOLNIR_LOG_NOTICE("Boundary Condition is PeriodicCuboid");
        return read_parallelism<realT, CuboidalPeriodicBoundary>(root, simulator);
    }
    else
    {
        throw_exception<std::runtime_error>(toml::format_error("[error] "
            "mjolnir::read_boundary: invalid boundary",
            toml::find(simulator, "boundary_type"), "here", {
            "- \"Unlimited\"     : no boundary condition. infinite space",
            "- \"Periodic\"      : periodic boundary. Assuming cuboidal shape.",
            "- \"PeriodicCuboid\": periodic boundary with cuboidal shape"
            }));
    }
}

inline std::unique_ptr<SimulatorBase>
read_precision(const toml::value& root, const toml::value& simulator)
{
    MJOLNIR_GET_DEFAULT_LOGGER();
    MJOLNIR_LOG_FUNCTION();

    const auto prec = toml::find<std::string>(simulator, "precision");
    if(prec == "double")
    {
        MJOLNIR_LOG_NOTICE("precision is double");
        return read_boundary<double>(root, simulator);
    }
    else if(prec == "float")
    {
        MJOLNIR_LOG_NOTICE("precision is float");
        return read_boundary<float>(root, simulator);
    }
    else
    {
        throw_exception<std::runtime_error>(toml::format_error("[error] "
            "mjolnir::read_precision: invalid precision",
            toml::find(simulator, "precition"), "here", {
            "expected value is one of the following.",
            "- \"double\": 64 bit floating-point",
            "- \"float\" : 32 bit floating-point"
            }));
    }
}

inline std::unique_ptr<SimulatorBase>
read_input_file(const std::string& filename)
{
    // here, logger name is not given yet. output status directory on console.
    std::cerr << "-- reading and parsing toml file `" << filename << "` ... ";
    auto root = toml::parse(filename);
    std::cerr << " successfully parsed." << std::endl;

    // initializing logger by using output_path and output_prefix ...
    const auto& output   = toml::find(root, "files", "output");
    const auto  out_path = read_output_path(root);

    // XXX:  Here, this code assumes POSIX. it does not support windows.
    // TODO: Consider using Boost.filesystem to manage path and files
    //       in more elegant and powerful way? After switching C++17,
    //       we can re-write that with <filesystem>.
    const auto logger_name = out_path +
        toml::find<std::string>(output, "prefix") + ".log";

    MJOLNIR_SET_DEFAULT_LOGGER(logger_name);
    MJOLNIR_GET_DEFAULT_LOGGER();
    MJOLNIR_LOG_FUNCTION();
    MJOLNIR_LOG_NOTICE("the log file is `", logger_name, '`');

    // Check top-level toml-values. Since it uses logger to warn,
    // we need to call it after `MJOLNIR_SET_DEFAULT_LOGGER(logger_name)`.
    check_keys_available(root, {"files"_s, "units"_s, "simulator"_s,
                                "systems"_s, "forcefields"_s});

    // load the input path in the [files] table and set it globally
    read_input_path(root);

    MJOLNIR_LOG_NOTICE("expanding include files ...");
    expand_include(root);
    MJOLNIR_LOG_NOTICE("done.");

    // the most of important flags are defined in [simulator], like
    // `precision = "float"`, `boundary_type = "Unlimited"`.
    // Those values should be read before others.
    const auto simulator = read_table_from_file(
            toml::find(root, "simulator"), "simulator");

    return read_precision(root, simulator);
}

#ifdef MJOLNIR_SEPARATE_BUILD
extern template std::unique_ptr<SimulatorBase> read_parallelism<double, UnlimitedBoundary       >(const toml::value& root, const toml::value& simulator);
extern template std::unique_ptr<SimulatorBase> read_parallelism<float , UnlimitedBoundary       >(const toml::value& root, const toml::value& simulator);
extern template std::unique_ptr<SimulatorBase> read_parallelism<double, CuboidalPeriodicBoundary>(const toml::value& root, const toml::value& simulator);
extern template std::unique_ptr<SimulatorBase> read_parallelism<float , CuboidalPeriodicBoundary>(const toml::value& root, const toml::value& simulator);

extern template std::unique_ptr<SimulatorBase> read_boundary<double>(const toml::value& root, const toml::value& simulator);
extern template std::unique_ptr<SimulatorBase> read_boundary<float >(const toml::value& root, const toml::value& simulator);
#endif

}// mjolnir
#endif// MJOLNIR_READ_INPUT_FILE
<commit_msg>feat: output version and compiler to log<commit_after>#ifndef MJOLNIR_INPUT_READ_INPUT_FILE_HPP
#define MJOLNIR_INPUT_READ_INPUT_FILE_HPP
#include <extlib/toml/toml.hpp>
#include <mjolnir/core/BoundaryCondition.hpp>
#include <mjolnir/core/SimulatorBase.hpp>
#include <mjolnir/core/SimulatorTraits.hpp>
#include <mjolnir/core/Unit.hpp>
#include <mjolnir/util/logger.hpp>
#include <mjolnir/input/utility.hpp>
#include <mjolnir/input/read_units.hpp>
#include <mjolnir/input/read_path.hpp>

#ifdef MJOLNIR_WITH_OPENMP
#include <mjolnir/omp/omp.hpp>
#endif

#include <memory>

namespace mjolnir
{

template<typename realT, template<typename, typename> class boundaryT>
std::unique_ptr<SimulatorBase>
read_parallelism(const toml::value& root, const toml::value& simulator)
{
    MJOLNIR_GET_DEFAULT_LOGGER();
    MJOLNIR_LOG_FUNCTION();

    if(simulator.as_table().count("parallelism") == 0)
    {
        MJOLNIR_LOG_NOTICE("execute on single core");
        return read_units<SimulatorTraits<realT, boundaryT>>(root, simulator);
    }

    const auto parallelism = toml::find(simulator, "parallelism");
    if(parallelism.is_string() && parallelism.as_string() == "sequencial")
    {
        MJOLNIR_LOG_NOTICE("execute on single core");
        return read_units<SimulatorTraits<realT, boundaryT>>(root, simulator);
    }
    else if(parallelism.is_string() &&
           (parallelism.as_string() == "openmp" ||
            parallelism.as_string() == "OpenMP"))
    {
#ifdef MJOLNIR_WITH_OPENMP
        MJOLNIR_LOG_NOTICE("execute on ", omp_get_max_threads() ," cores with openmp");
        return read_units<OpenMPSimulatorTraits<realT, boundaryT>>(root, simulator);
#else
        MJOLNIR_LOG_WARN("OpenMP flag is set, but OpenMP is not enabled when building.");
        MJOLNIR_LOG_WARN("Cannot use OpenMP, running with single core.");
        return read_units<SimulatorTraits<realT, boundaryT>>(root, simulator);
#endif
    }
    else
    {
        throw_exception<std::runtime_error>(toml::format_error("[error] "
            "mjolnir::read_parallelism: invalid variable ",
            toml::find(simulator, "parallelism"), "here", {
            "- \"sequencial\": run with only 1 core (default)",
            "- \"openmp\"    : use openmp to parallelize."
            }));
    }
}

template<typename realT>
std::unique_ptr<SimulatorBase>
read_boundary(const toml::value& root, const toml::value& simulator)
{
    MJOLNIR_GET_DEFAULT_LOGGER();
    MJOLNIR_LOG_FUNCTION();

    const auto boundary = toml::find<std::string>(simulator, "boundary_type");
    if(boundary == "Unlimited")
    {
        MJOLNIR_LOG_NOTICE("Boundary Condition is Unlimited");
        return read_parallelism<realT, UnlimitedBoundary>(root, simulator);
    }
    else if(boundary == "Periodic")
    {
        MJOLNIR_LOG_NOTICE("Boundary Condition is Periodic. "
                           "The shape is cuboid.");
        return read_parallelism<realT, CuboidalPeriodicBoundary>(root, simulator);
    }
    else if(boundary == "PeriodicCuboid")
    {
        MJOLNIR_LOG_NOTICE("Boundary Condition is PeriodicCuboid");
        return read_parallelism<realT, CuboidalPeriodicBoundary>(root, simulator);
    }
    else
    {
        throw_exception<std::runtime_error>(toml::format_error("[error] "
            "mjolnir::read_boundary: invalid boundary",
            toml::find(simulator, "boundary_type"), "here", {
            "- \"Unlimited\"     : no boundary condition. infinite space",
            "- \"Periodic\"      : periodic boundary. Assuming cuboidal shape.",
            "- \"PeriodicCuboid\": periodic boundary with cuboidal shape"
            }));
    }
}

inline std::unique_ptr<SimulatorBase>
read_precision(const toml::value& root, const toml::value& simulator)
{
    MJOLNIR_GET_DEFAULT_LOGGER();
    MJOLNIR_LOG_FUNCTION();

    const auto prec = toml::find<std::string>(simulator, "precision");
    if(prec == "double")
    {
        MJOLNIR_LOG_NOTICE("precision is double");
        return read_boundary<double>(root, simulator);
    }
    else if(prec == "float")
    {
        MJOLNIR_LOG_NOTICE("precision is float");
        return read_boundary<float>(root, simulator);
    }
    else
    {
        throw_exception<std::runtime_error>(toml::format_error("[error] "
            "mjolnir::read_precision: invalid precision",
            toml::find(simulator, "precition"), "here", {
            "expected value is one of the following.",
            "- \"double\": 64 bit floating-point",
            "- \"float\" : 32 bit floating-point"
            }));
    }
}

inline std::unique_ptr<SimulatorBase>
read_input_file(const std::string& filename)
{
    // here, logger name is not given yet. output status directory on console.
    std::cerr << "-- reading and parsing toml file `" << filename << "` ... ";
    auto root = toml::parse(filename);
    std::cerr << " successfully parsed." << std::endl;

    // initializing logger by using output_path and output_prefix ...
    const auto& output   = toml::find(root, "files", "output");
    const auto  out_path = read_output_path(root);

    // XXX:  Here, this code assumes POSIX. it does not support windows.
    // TODO: Consider using Boost.filesystem to manage path and files
    //       in more elegant and powerful way? After switching C++17,
    //       we can re-write that with <filesystem>.
    const auto logger_name = out_path +
        toml::find<std::string>(output, "prefix") + ".log";

    MJOLNIR_SET_DEFAULT_LOGGER(logger_name);
    MJOLNIR_GET_DEFAULT_LOGGER();
    MJOLNIR_LOG_FUNCTION();
    MJOLNIR_LOG_NOTICE("the log file is `", logger_name, '`');

    MJOLNIR_LOG_NOTICE("mjolnir version ", MJOLNIR_VERSION);
    MJOLNIR_LOG_NOTICE("compiled using ",  MJOLNIR_COMPILER_VERSION);

    // Check top-level toml-values. Since it uses logger to warn,
    // we need to call it after `MJOLNIR_SET_DEFAULT_LOGGER(logger_name)`.
    check_keys_available(root, {"files"_s, "units"_s, "simulator"_s,
                                "systems"_s, "forcefields"_s});

    // load the input path in the [files] table and set it globally
    read_input_path(root);

    MJOLNIR_LOG_NOTICE("expanding include files ...");
    expand_include(root);
    MJOLNIR_LOG_NOTICE("done.");

    // the most of important flags are defined in [simulator], like
    // `precision = "float"`, `boundary_type = "Unlimited"`.
    // Those values should be read before others.
    const auto simulator = read_table_from_file(
            toml::find(root, "simulator"), "simulator");

    return read_precision(root, simulator);
}

#ifdef MJOLNIR_SEPARATE_BUILD
extern template std::unique_ptr<SimulatorBase> read_parallelism<double, UnlimitedBoundary       >(const toml::value& root, const toml::value& simulator);
extern template std::unique_ptr<SimulatorBase> read_parallelism<float , UnlimitedBoundary       >(const toml::value& root, const toml::value& simulator);
extern template std::unique_ptr<SimulatorBase> read_parallelism<double, CuboidalPeriodicBoundary>(const toml::value& root, const toml::value& simulator);
extern template std::unique_ptr<SimulatorBase> read_parallelism<float , CuboidalPeriodicBoundary>(const toml::value& root, const toml::value& simulator);

extern template std::unique_ptr<SimulatorBase> read_boundary<double>(const toml::value& root, const toml::value& simulator);
extern template std::unique_ptr<SimulatorBase> read_boundary<float >(const toml::value& root, const toml::value& simulator);
#endif

}// mjolnir
#endif// MJOLNIR_READ_INPUT_FILE
<|endoftext|>


<commit_before>/*!
 *  Copyright (c) 2018 by Contributors
 * \file type_functor.cc
 * \brief Implementations of type functors.
 */
#include "type_functor.h"

namespace tvm {
namespace relay {

void TypeVisitor::VisitType_(const TypeVarNode* op) {
}

void TypeVisitor::VisitType_(const TensorTypeNode* op) {
}

void TypeVisitor::VisitType_(const IncompleteTypeNode* op) {
}

void TypeVisitor::VisitType_(const FuncTypeNode* op) {
  for (auto type_param : op->type_params) {
    this->VisitType(type_param);
  }

  for (auto type_cs : op->type_constraints) {
    this->VisitType(type_cs);
  }

  for (auto arg_type : op->arg_types) {
    this->VisitType(arg_type);
  }
  this->VisitType(op->ret_type);
}

void TypeVisitor::VisitType_(const TupleTypeNode* op) {
  for (const Type& t : op->fields) {
    this->VisitType(t);
  }
}

void TypeVisitor::VisitType_(const TypeRelationNode* op) {
  for (const Type& t : op->args) {
    this->VisitType(t);
  }
}

// Type Mutator.
Array<Type> TypeMutator::MutateArray(Array<Type> arr) {
  // The array will do copy on write
  // If no changes are made, the original array will be returned.
  for (size_t i = 0; i < arr.size(); ++i) {
    Type ty = arr[i];
    Type new_ty = VisitType(ty);
    if (!ty.same_as(new_ty)) {
      arr.Set(i, new_ty);
    }
  }
  return arr;
}

Type TypeMutator::VisitType_(const TypeVarNode* op) {
  return GetRef<TypeVar>(op);
}

Type TypeMutator::VisitType_(const TensorTypeNode* op) {
  // TODO(tvm-team) recursively visit to replace Var
  return GetRef<Type>(op);
}

Type TypeMutator::VisitType_(const IncompleteTypeNode* op) {
  return GetRef<Type>(op);
}

Type TypeMutator::VisitType_(const FuncTypeNode* op) {
  bool changed = false;
  Array<TypeVar> type_params;
  for (auto type_param : op->type_params) {
    auto new_type_param = VisitType(type_param);
    changed = changed || !new_type_param.same_as(type_param);
    if (const TypeVarNode* tin = new_type_param.as<TypeVarNode>()) {
      type_params.push_back(GetRef<TypeVar>(tin));
    } else {
      LOG(FATAL) << new_type_param << std::endl;
    }
  }

  Array<TypeConstraint> type_constraints;
  for (auto type_cs : op->type_constraints) {
    auto new_type_cs = VisitType(type_cs);
    changed = changed || !new_type_cs.same_as(type_cs);
    if (const TypeConstraintNode* tin =
        new_type_cs.as_derived<TypeConstraintNode>()) {
      type_constraints.push_back(GetRef<TypeConstraint>(tin));
    } else {
      LOG(FATAL) << new_type_cs << std::endl;
    }
  }

  Array<Type> new_args = MutateArray(op->arg_types);
  changed = changed || new_args.same_as(op->arg_types);

  Type new_ret_type = VisitType(op->ret_type);
  changed = changed || new_ret_type.same_as(op->ret_type);

  if (!changed) return GetRef<Type>(op);
  return FuncTypeNode::make(new_args,
                            new_ret_type,
                            type_params,
                            type_constraints);
}

Type TypeMutator::VisitType_(const TupleTypeNode* op) {
  Array<Type> new_fields = MutateArray(op->fields);
  if (new_fields.same_as(op->fields)) {
    return GetRef<Type>(op);
  } else {
    return TupleTypeNode::make(new_fields);
  }
}

Type TypeMutator::VisitType_(const TypeRelationNode* type_rel) {
  Array<Type> new_args = MutateArray(type_rel->args);
  if (new_args.same_as(type_rel->args)) {
    return GetRef<Type>(type_rel);
  } else {
    return TypeRelationNode::make(type_rel->func,
                                  new_args,
                                  type_rel->num_inputs,
                                  type_rel->attrs);
  }
}

// Implements bind.
class TypeBinder : public TypeMutator {
 public:
  explicit TypeBinder(const tvm::Map<TypeVar, Type>& args_map)
    : args_map_(args_map) {}

  Type VisitType_(const TypeVarNode* op) override {
    auto id = GetRef<TypeVar>(op);
    auto it = args_map_.find(id);
    if (it != args_map_.end()) {
      return (*it).second;
    } else {
      return id;
    }
  }

 private:
  const tvm::Map<TypeVar, Type>& args_map_;
};

Type Bind(const Type& type, const tvm::Map<TypeVar, Type>& args_map) {
  return TypeBinder(args_map).VisitType(type);
}

}  // namespace relay
}  // namespace tvm
<commit_msg>[RELAY] bugfix type functor caching (#2113)<commit_after>/*!
 *  Copyright (c) 2018 by Contributors
 * \file type_functor.cc
 * \brief Implementations of type functors.
 */
#include "type_functor.h"

namespace tvm {
namespace relay {

void TypeVisitor::VisitType_(const TypeVarNode* op) {
}

void TypeVisitor::VisitType_(const TensorTypeNode* op) {
}

void TypeVisitor::VisitType_(const IncompleteTypeNode* op) {
}

void TypeVisitor::VisitType_(const FuncTypeNode* op) {
  for (auto type_param : op->type_params) {
    this->VisitType(type_param);
  }

  for (auto type_cs : op->type_constraints) {
    this->VisitType(type_cs);
  }

  for (auto arg_type : op->arg_types) {
    this->VisitType(arg_type);
  }
  this->VisitType(op->ret_type);
}

void TypeVisitor::VisitType_(const TupleTypeNode* op) {
  for (const Type& t : op->fields) {
    this->VisitType(t);
  }
}

void TypeVisitor::VisitType_(const TypeRelationNode* op) {
  for (const Type& t : op->args) {
    this->VisitType(t);
  }
}

// Type Mutator.
Array<Type> TypeMutator::MutateArray(Array<Type> arr) {
  // The array will do copy on write
  // If no changes are made, the original array will be returned.
  for (size_t i = 0; i < arr.size(); ++i) {
    Type ty = arr[i];
    Type new_ty = VisitType(ty);
    if (!ty.same_as(new_ty)) {
      arr.Set(i, new_ty);
    }
  }
  return arr;
}

Type TypeMutator::VisitType_(const TypeVarNode* op) {
  return GetRef<TypeVar>(op);
}

Type TypeMutator::VisitType_(const TensorTypeNode* op) {
  // TODO(tvm-team) recursively visit to replace Var
  return GetRef<Type>(op);
}

Type TypeMutator::VisitType_(const IncompleteTypeNode* op) {
  return GetRef<Type>(op);
}

Type TypeMutator::VisitType_(const FuncTypeNode* op) {
  bool changed = false;
  Array<TypeVar> type_params;
  for (auto type_param : op->type_params) {
    auto new_type_param = VisitType(type_param);
    changed = changed || !new_type_param.same_as(type_param);
    if (const TypeVarNode* tin = new_type_param.as<TypeVarNode>()) {
      type_params.push_back(GetRef<TypeVar>(tin));
    } else {
      LOG(FATAL) << new_type_param << std::endl;
    }
  }

  Array<TypeConstraint> type_constraints;
  for (auto type_cs : op->type_constraints) {
    auto new_type_cs = VisitType(type_cs);
    changed = changed || !new_type_cs.same_as(type_cs);
    if (const TypeConstraintNode* tin =
        new_type_cs.as_derived<TypeConstraintNode>()) {
      type_constraints.push_back(GetRef<TypeConstraint>(tin));
    } else {
      LOG(FATAL) << new_type_cs << std::endl;
    }
  }

  Array<Type> new_args = MutateArray(op->arg_types);
  changed = changed || !new_args.same_as(op->arg_types);

  Type new_ret_type = VisitType(op->ret_type);
  changed = changed || !new_ret_type.same_as(op->ret_type);

  if (!changed) return GetRef<Type>(op);
  return FuncTypeNode::make(new_args,
                            new_ret_type,
                            type_params,
                            type_constraints);
}

Type TypeMutator::VisitType_(const TupleTypeNode* op) {
  Array<Type> new_fields = MutateArray(op->fields);
  if (new_fields.same_as(op->fields)) {
    return GetRef<Type>(op);
  } else {
    return TupleTypeNode::make(new_fields);
  }
}

Type TypeMutator::VisitType_(const TypeRelationNode* type_rel) {
  Array<Type> new_args = MutateArray(type_rel->args);
  if (new_args.same_as(type_rel->args)) {
    return GetRef<Type>(type_rel);
  } else {
    return TypeRelationNode::make(type_rel->func,
                                  new_args,
                                  type_rel->num_inputs,
                                  type_rel->attrs);
  }
}

// Implements bind.
class TypeBinder : public TypeMutator {
 public:
  explicit TypeBinder(const tvm::Map<TypeVar, Type>& args_map)
    : args_map_(args_map) {}

  Type VisitType_(const TypeVarNode* op) override {
    auto id = GetRef<TypeVar>(op);
    auto it = args_map_.find(id);
    if (it != args_map_.end()) {
      return (*it).second;
    } else {
      return id;
    }
  }

 private:
  const tvm::Map<TypeVar, Type>& args_map_;
};

Type Bind(const Type& type, const tvm::Map<TypeVar, Type>& args_map) {
  return TypeBinder(args_map).VisitType(type);
}

}  // namespace relay
}  // namespace tvm
<|endoftext|>


<commit_before>#include "vec2.h"

namespace fd {
namespace core {
namespace math {

vec2i::vec2i() : x(0), y(0) {}

vec2i::vec2i(int32 x, int32 y) : x(x), y(y) {}

//int32
vec2i& vec2i::Add(const vec2i& v) {
	__m128i vxmm = _mm_set_epi32(0, 0, v.y, v.x);
	__m128i xmm = _mm_set_epi32(0, 0, y, x);
	xmm = _mm_add_epi32(xmm, vxmm);

	x = xmm.m128i_i32[0];
	y = xmm.m128i_i32[1];

	return *this;
}

//int32
vec2i& vec2i::Sub(const vec2i& v) {
	__m128i vxmm = _mm_set_epi32(0, 0, v.y, v.x);
	__m128i xmm = _mm_set_epi32(0, 0, y, x);
	xmm = _mm_sub_epi32(xmm, vxmm);

	x = xmm.m128i_i32[0];
	y = xmm.m128i_i32[1];

	return *this;
}

//int32
vec2i& vec2i::Mul(const vec2i& v) {
	__m128i vxmm = _mm_set_epi32(0, v.y, 0, v.x);
	__m128i xmm = _mm_set_epi32(0, y, 0, x);
	xmm = _mm_mul_epi32(xmm, vxmm);

	x = xmm.m128i_i32[0];
	y = xmm.m128i_i32[2];

	return *this;
}

//int32
vec2i& vec2i::Div(const vec2i& v) {
	x /= v.x;
	y /= v.y;
	return *this;
}

//int32
vec2i& vec2i::Add(int32 v) {
	__m128i vxmm = _mm_set_epi32(0, 0, v, v);
	__m128i xmm = _mm_set_epi32(0, 0, y, x);
	xmm = _mm_add_epi32(xmm, vxmm);

	x = xmm.m128i_i32[0];
	y = xmm.m128i_i32[1];

	return *this;
}

//int32
vec2i& vec2i::Sub(int32 v) {
	__m128i vxmm = _mm_set_epi32(0, 0, v, v);
	__m128i xmm = _mm_set_epi32(0, 0, y, x);
	xmm = _mm_sub_epi32(xmm, vxmm);

	x = xmm.m128i_i32[0];
	y = xmm.m128i_i32[1];

	return *this;
}

//int32
vec2i& vec2i::Mul(int32 v) {
	__m128i vxmm = _mm_set_epi32(0, v, 0, v);
	__m128i xmm = _mm_set_epi32(0, y, 0, x);
	xmm = _mm_mul_epi32(xmm, vxmm);

	x = xmm.m128i_i32[0];
	y = xmm.m128i_i32[2];

	return *this;
}

//int32
vec2i& vec2i::Div(int32 v) {
	x /= v;
	y /= v;

	return *this;
}

}
}
}<commit_msg>LNX: vec2i<commit_after>#include "vec2.h"

namespace fd {
namespace core {
namespace math {

vec2i::vec2i() : x(0), y(0) {}

vec2i::vec2i(int32 x, int32 y) : x(x), y(y) {}

//int32
vec2i& vec2i::Add(const vec2i& v) {
	__m128i vxmm = _mm_set_epi32(0, 0, v.y, v.x);
	__m128i xmm = _mm_set_epi32(0, 0, y, x);
	xmm = _mm_add_epi32(xmm, vxmm);

	x = M128I(xmm, 0);
	y = M128I(xmm, 1);

	return *this;
}

//int32
vec2i& vec2i::Sub(const vec2i& v) {
	__m128i vxmm = _mm_set_epi32(0, 0, v.y, v.x);
	__m128i xmm = _mm_set_epi32(0, 0, y, x);
	xmm = _mm_sub_epi32(xmm, vxmm);

	x = M128I(xmm, 0);
	y = M128I(xmm, 1);

	return *this;
}

//int32
vec2i& vec2i::Mul(const vec2i& v) {
	__m128i vxmm = _mm_set_epi32(0, v.y, 0, v.x);
	__m128i xmm = _mm_set_epi32(0, y, 0, x);
	xmm = _mm_mul_epi32(xmm, vxmm);

	x = M128I(xmm, 0);
	y = M128I(xmm, 1);

	return *this;
}

//int32
vec2i& vec2i::Div(const vec2i& v) {
	x /= v.x;
	y /= v.y;
	return *this;
}

//int32
vec2i& vec2i::Add(int32 v) {
	__m128i vxmm = _mm_set_epi32(0, 0, v, v);
	__m128i xmm = _mm_set_epi32(0, 0, y, x);
	xmm = _mm_add_epi32(xmm, vxmm);

	x = M128I(xmm, 0);
	y = M128I(xmm, 1);

	return *this;
}

//int32
vec2i& vec2i::Sub(int32 v) {
	__m128i vxmm = _mm_set_epi32(0, 0, v, v);
	__m128i xmm = _mm_set_epi32(0, 0, y, x);
	xmm = _mm_sub_epi32(xmm, vxmm);

	x = M128I(xmm, 0);
	y = M128I(xmm, 1);

	return *this;
}

//int32
vec2i& vec2i::Mul(int32 v) {
	__m128i vxmm = _mm_set_epi32(0, v, 0, v);
	__m128i xmm = _mm_set_epi32(0, y, 0, x);
	xmm = _mm_mul_epi32(xmm, vxmm);

	x = M128I(xmm, 0);
	y = M128I(xmm, 1);

	return *this;
}

//int32
vec2i& vec2i::Div(int32 v) {
	x /= v;
	y /= v;

	return *this;
}

}
}
}<|endoftext|>


<commit_before>#include "Genes/Freedom_To_Move_Gene.h"

#include <memory>
#include <string>
#include <array>
#include <bitset>

#include "Genes/Gene.h"
#include "Game/Board.h"
#include "Game/Color.h"
#include "Game/Piece.h"

double Freedom_To_Move_Gene::score_board(const Board& board, Color perspective, size_t) const
{
    static auto initial_score = double(attack_count(Board(), WHITE));

    return attack_count(board, perspective)/initial_score;
}

std::unique_ptr<Gene> Freedom_To_Move_Gene::duplicate() const
{
    return std::make_unique<Freedom_To_Move_Gene>(*this);
}

std::string Freedom_To_Move_Gene::name() const
{
    return "Freedom to Move Gene";
}

size_t Freedom_To_Move_Gene::attack_count(const Board& board, Color perspective) const
{
    size_t count = 0;
    for(char file = 'a'; file <= 'h'; ++file)
    {
        for(int rank = 1; rank <= 8; ++rank)
        {
            auto piece = board.piece_on_square(file, rank);
            if( ! piece ||  piece->color() != perspective)
            {
                count += board.moves_attacking_square(file, rank, perspective).count();
            }
        }
    }

    return count;
}
<commit_msg>Speedup to Freedom to Move Gene<commit_after>#include "Genes/Freedom_To_Move_Gene.h"

#include <memory>
#include <string>
#include <array>
#include <bitset>

#include "Genes/Gene.h"
#include "Game/Board.h"
#include "Game/Color.h"
#include "Game/Piece.h"

double Freedom_To_Move_Gene::score_board(const Board& board, Color perspective, size_t) const
{
    static auto initial_score = double(attack_count(Board(), WHITE));

    return attack_count(board, perspective)/initial_score;
}

std::unique_ptr<Gene> Freedom_To_Move_Gene::duplicate() const
{
    return std::make_unique<Freedom_To_Move_Gene>(*this);
}

std::string Freedom_To_Move_Gene::name() const
{
    return "Freedom to Move Gene";
}

size_t Freedom_To_Move_Gene::attack_count(const Board& board, Color perspective) const
{
    size_t count = 0;
    for(char file = 'a'; file <= 'h'; ++file)
    {
        for(int rank = 1; rank <= 8; ++rank)
        {
            if(board.moves_attacking_square(file, rank, perspective).any())
            {
                auto piece = board.piece_on_square(file, rank);
                if( ! piece ||  piece->color() != perspective)
                {
                    count += board.moves_attacking_square(file, rank, perspective).count();
                }
            }
        }
    }

    return count;
}
<|endoftext|>


<commit_before>// Copyright (c) 2016 Stefan Krüger
// released under MIT (see LICENSE for details)

// based on example from
// http://docs.openlighting.org/ola/doc/latest/dmx_cpp_client_tutorial.html

// build for local:
// g++ -std=c++11 olamapper.cpp -o olamapper.out $(pkg-config --cflags --libs libola)

#include <ola/DmxBuffer.h>
#include <ola/Logging.h>
#include <ola/client/ClientWrapper.h>
#include <ola/io/SelectServer.h>

#include <unistd.h>
#include <string>
#include <iostream>
#include <fstream>

uint16_t universe_in = 1;
uint16_t universe_in_start_address = 1;
uint16_t universe_out = 2;
uint16_t universe_channel_count = 240;
uint16_t universe_rescale_max = 60000;
static const uint16_t channel_count_MAX = 512;

ola::client::OlaClientWrapper wrapper(false);
ola::client::OlaClient *client;
ola::DmxBuffer channels_out;

int my_map[channel_count_MAX];

enum ola_state_t {
  state_undefined,
  state_standby,
  state_waiting,
  state_connected,
  state_running,
};

ola_state_t system_state = state_undefined;

bool flag_run = true;

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// configuration things

void parse_config_channels(std::string raw_channels) {
  // get part between []
  size_t start = raw_channels.find('[');
  size_t end = raw_channels.find(']');
  raw_channels = raw_channels.substr(start+1, (end-1)-start);
  // std::cout << "raw_channels: '" << raw_channels << "'" << std::endl;
  // split at every ', '
  start = 0;
  end = 0;
  size_t map_index = 0;
  while ( (end = raw_channels.find(", ", start)) != std::string::npos ) {
    std::string element = raw_channels.substr(start, end - start);
    start = end + 1;
    // std::cout << element << std::endl;
    // now we can convert the element string to a int
    int value;
    value = std::stoi(element);
    my_map[map_index] = value;
    map_index += 1;
    // std::cout << value << std::endl;
  }
  // handle last element
  std::string element = raw_channels.substr(start);
  int value;
  value = std::stoi(element);
  my_map[map_index] = value;
  map_index += 1;
  // std::cout << value << std::endl;
  // std::cout << map_index << std::endl;
  // std::cout << my_map << std::endl;
}

void parse_config_map(std::string raw_input) {
  // find "map": { "channels": [....]}
  size_t start = std::string::npos;
  start = raw_input.find("\"map\"");
  // std::cout << "map start: '" << start << "'" << std::endl;
  if (start != std::string::npos) {
    // std::cout << "map found." << std::endl;
    size_t start_channels = raw_input.find("\"channels\"", start);
    // std::cout << "channels start: '" << start_channels << "'" << std::endl;
    if (start_channels != std::string::npos) {
      // std::cout << "channels found." << std::endl;
      size_t end = raw_input.find('}', start_channels);
      if (end != std::string::npos) {
        // std::cout << "channels end found." << std::endl;
        std::string channels_list = raw_input.substr(start+1, (end-1)-start);
        // std::cout << "channels_list: '" << channels_list << "'" << std::endl;
        parse_config_channels(channels_list);
      } else {
        std::cout
          << "Error in Config Format: 'channels' section end not found."
          << std::endl;
      }
    } else {
      std::cout
        << "Error in Config Format: 'channels' section not found."
        << std::endl;
    }
  } else {
    std::cout
      << "Error in Config Format: 'map' section not found."
      << std::endl;
  }
}

int parse_value(std::string raw_input, std::string key_name) {
  size_t start = std::string::npos;
  size_t end = std::string::npos;
  std::string value_raw;
  int value = -1;

  start = raw_input.find("\"" + key_name + "\"");
  // std::cout << "start: '" << start << "'" << std::endl;
  if (start != std::string::npos) {
    end = raw_input.find_first_of(",}", start);
    if (end != std::string::npos) {
      // start + " + key_name + " + :
      size_t value_content_start = start + 1 + key_name.length() + 1 + 1;
      value_raw = raw_input.substr(
        value_content_start,
        (end)-value_content_start);
      // std::cout << "value_raw: '" << value_raw << "'" << std::endl;
      // now we can convert the element string to a int
      value = std::stoi(value_raw);
    } else {
      std::cout
        << "Error in Config Format: '"
        << key_name
        << "' value end not found."
        << std::endl;
    }
  } else {
    std::cout
      << "Error in Config Format: '"
      << key_name
      << "' value not found."
      << std::endl;
  }

  return value;
}

void parse_config_universe(std::string raw_input) {
  // find "universe": { }
  // std::cout << "raw_input: '" << raw_input << "'" << std::endl;
  std::string key_name = "universe";
  size_t start_section = raw_input.find("\""+key_name+"\"");
  // std::cout << "start_section: '" << start_section << "'" << std::endl;
  if (start_section != std::string::npos) {
    size_t section_content_start = start_section + 1 + key_name.length();
    std::string section_content = raw_input.substr(
      section_content_start);
    // find 'start_address'
    uint16_t u_start_address = parse_value(section_content, "start_address");
    // find 'channel_count'
    uint16_t u_channel_count = parse_value(section_content, "channel_count");
    // find 'input'
    uint16_t u_input = parse_value(section_content, "input");
    // find 'output'
    uint16_t u_output = parse_value(section_content, "output");
    // find 'rescale_max'
    uint16_t u_rescale_max = parse_value(section_content, "rescale_max");
    // done
    std::cout << "start_address: " << u_start_address << std::endl;
    std::cout << "input: " << u_input << std::endl;
    std::cout << "output: " << u_output << std::endl;
    std::cout << "channel_count: " << u_channel_count << std::endl;
    std::cout << "rescale_max: " << u_rescale_max << std::endl;
    universe_in_start_address = u_start_address;
    universe_in = u_input;
    universe_out = u_output;
    universe_channel_count = u_channel_count;
    universe_rescale_max = u_rescale_max;
    std::cout << "universe_in_start_address: " << universe_in_start_address << std::endl;
    std::cout << "universe_in: " << universe_in << std::endl;
    std::cout << "universe_out: " << universe_out << std::endl;
    std::cout << "universe_channel_count: " << universe_channel_count << std::endl;
    std::cout << "universe_rescale_max: " << universe_rescale_max << std::endl;

  } else {
    std::cout
      << "Error in Config Format: 'universe' section not found."
      << std::endl;
  }
}

// void read_config_from_file(std::string filename) {
void read_config_from_file() {
  // std::string filename = "my_map.config";
  std::ifstream myfile("./map.json");
  if (myfile.is_open()) {
    std::string line;
    std::string raw_input;
    // read in all lines and combine theme.
    while ( std::getline(myfile, line) ) {
      std::cout << line << std::endl;
      raw_input += line;
    }
    myfile.close();
    std::cout << std::endl;
    std::cout << std::endl;

    // ------------------------------------------
    // now we can parse the input
    // std::cout << "raw_input: '" << raw_input << "'" << std::endl;

    // search and extract map
    std::cout << "parse_config_map.."<< std::endl;
    parse_config_map(raw_input);

    // search and extract universe information
    std::cout << "parse_config_universe.."<< std::endl;
    parse_config_universe(raw_input);

    std::cout << "parsing done."<< std::endl;

  } else {
    std::cout << "Unable to open file."<< std::endl;
  }
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// helper

void rescale_channels() {
  for (
    size_t channel_output_index = 0;
    channel_output_index < universe_channel_count;
    channel_output_index = channel_output_index +2
  ) {
      uint8_t value_h = 0;
      uint8_t value_l = 0;
      uint16_t value = 0;

      // get channel values
      value_h = channels_out.Get(channel_output_index);
      value_l = channels_out.Get(channel_output_index+1);

      // combine to 16bit value
      value = (value_h << 8) | value_l;

      // rescale:
      uint32_t value_calc = value * universe_rescale_max;
      value = value_calc / 65535;

      // splitt to 8itt values
      value_h = value >> 8;
      value_l = value;

      // set channel values
      channels_out.SetChannel(
        channel_output_index,
        value_h
      );
      channels_out.SetChannel(
        channel_output_index+1,
        value_l
      );
  }
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// mapping

// map data to new channels and send frame
void map_channels(const ola::DmxBuffer &data) {
  for (
    size_t channel_output_index = 0;
    channel_output_index < universe_channel_count;
    channel_output_index++
  ) {
    int map_value = my_map[channel_output_index];
    // check if map_value is
    if (map_value > -1) {
        // check if map_value is in range of input channels
        if (map_value < (int)data.Size()) {
          channels_out.SetChannel(
            channel_output_index,
            data.Get(map_value));
        }
    }
  }
  rescale_channels();
  // std::cout << "Send frame: " << std::endl << channels_out << std::endl;
  wrapper.GetClient()->SendDMX(
    universe_out,
    channels_out,
    ola::client::SendDMXArgs());
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// ola things

// Called when universe registration completes.
void RegisterComplete(const ola::client::Result& result) {
  if (!result.Success()) {
    OLA_WARN << "Failed to register universe: " << result.Error();
  }
}

// Called when new DMX data arrives.
void dmx_receive_frame(const ola::client::DMXMetadata &metadata,
  const ola::DmxBuffer &data) {
  // std::cout << "Received " << data.Size()
  // << " channels for universe " << metadata.universe
  // << ", priority " << static_cast<int>(metadata.priority)
  // << std::endl;
  map_channels(data);
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// ola state helper

void ola_connection_closed(ola::io::SelectServer *ss) {
  std::cerr << "Connection to olad was closed" << std::endl;
  ss->Terminate();
  system_state = state_waiting;
}

void ola_waiting_for_connection() {
  bool flag_connected = false;
  try {
    std::cout << "try wrapper.Setup() " << std::endl;
    bool available  = wrapper.Setup();
    std::cout << "available: " << available << std::endl;
    if (available) {
      flag_connected = true;
    }
  }
  // catch (const std::exception &exc) {
  //   // catch anything thrown that derives from std::exception
  //   std::cerr << exc.what();
  //   std::cout << "error!!: " << exc.what() << std::endl;
  // }
  catch (...) {
    // catch all
    // sleep microseconds
    // usleep(500000);
    std::cout << "error!!: " << std::endl;
  }
  // }

  if (flag_connected) {
    client = wrapper.GetClient();
    system_state = state_connected;
  }
}

void ola_setup() {
  client->SetCloseHandler(
    ola::NewSingleCallback(
      ola_connection_closed,
      wrapper.GetSelectServer() ));

  // clean channels_out buffer
  channels_out.Blackout();

  // Set the callback and register our interest in this universe
  client->SetDMXCallback(ola::NewCallback(&dmx_receive_frame));
  client->RegisterUniverse(
    universe_in,
    ola::client::REGISTER,
    ola::NewSingleCallback(&RegisterComplete));
  std::cout << "map incoming channels." << std::endl;

  system_state = state_running;
}

void ola_run() {
  // this call blocks:
  wrapper.GetSelectServer()->Run();
  // if this exits we switch back to waiting state:
  std::cout << "map incoming channels." << std::endl;
  system_state = state_waiting;
}

void ola_statemaschine() {
  switch (system_state) {
    case state_undefined : {
      system_state = state_waiting;
    } break;
    case state_standby : {
      system_state = state_waiting;
    } break;
    case state_waiting : {
      ola_waiting_for_connection();
    } break;
    case state_connected : {
      ola_setup();
    } break;
    case state_running : {
      // attention! blocks untill error..
      ola_run();
    } break;
  }  // end switch
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// main

int main() {
  ola::InitLogging(ola::OLA_LOG_INFO, ola::OLA_LOG_STDERR);
  // read map from file:
  // read_config_from_file("my_map.config");
  read_config_from_file();

  // while (flag_run) {
  //     ola_statemaschine()
  // }

  // manual cycle
  std::cout << "ola_waiting_for_connection()" << std::endl;
  ola_waiting_for_connection();
  std::cout << "ola_setup()" << std::endl;
  ola_setup();
  std::cout << "ola_run()" << std::endl;
  ola_run();

}
<commit_msg>initial wait works. now get the rewaiting to work...<commit_after>// Copyright (c) 2016 Stefan Krüger
// released under MIT (see LICENSE for details)

// based on example from
// http://docs.openlighting.org/ola/doc/latest/dmx_cpp_client_tutorial.html

// build for local:
// g++ -std=c++11 olamapper.cpp -o olamapper.out $(pkg-config --cflags --libs libola)

#include <ola/DmxBuffer.h>
#include <ola/Logging.h>
#include <ola/client/ClientWrapper.h>
#include <ola/io/SelectServer.h>

#include <unistd.h>
#include <string>
#include <iostream>
#include <fstream>

uint16_t universe_in = 1;
uint16_t universe_in_start_address = 1;
uint16_t universe_out = 2;
uint16_t universe_channel_count = 240;
uint16_t universe_rescale_max = 60000;
static const uint16_t channel_count_MAX = 512;

ola::client::OlaClientWrapper wrapper(false);
ola::client::OlaClient *client;
ola::DmxBuffer channels_out;

int my_map[channel_count_MAX];

enum ola_state_t {
  state_undefined,
  state_standby,
  state_waiting,
  state_connected,
  state_running,
};

ola_state_t system_state = state_undefined;

bool flag_run = true;

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// configuration things

void parse_config_channels(std::string raw_channels) {
  // get part between []
  size_t start = raw_channels.find('[');
  size_t end = raw_channels.find(']');
  raw_channels = raw_channels.substr(start+1, (end-1)-start);
  // std::cout << "raw_channels: '" << raw_channels << "'" << std::endl;
  // split at every ', '
  start = 0;
  end = 0;
  size_t map_index = 0;
  while ( (end = raw_channels.find(", ", start)) != std::string::npos ) {
    std::string element = raw_channels.substr(start, end - start);
    start = end + 1;
    // std::cout << element << std::endl;
    // now we can convert the element string to a int
    int value;
    value = std::stoi(element);
    my_map[map_index] = value;
    map_index += 1;
    // std::cout << value << std::endl;
  }
  // handle last element
  std::string element = raw_channels.substr(start);
  int value;
  value = std::stoi(element);
  my_map[map_index] = value;
  map_index += 1;
  // std::cout << value << std::endl;
  // std::cout << map_index << std::endl;
  // std::cout << my_map << std::endl;
}

void parse_config_map(std::string raw_input) {
  // find "map": { "channels": [....]}
  size_t start = std::string::npos;
  start = raw_input.find("\"map\"");
  // std::cout << "map start: '" << start << "'" << std::endl;
  if (start != std::string::npos) {
    // std::cout << "map found." << std::endl;
    size_t start_channels = raw_input.find("\"channels\"", start);
    // std::cout << "channels start: '" << start_channels << "'" << std::endl;
    if (start_channels != std::string::npos) {
      // std::cout << "channels found." << std::endl;
      size_t end = raw_input.find('}', start_channels);
      if (end != std::string::npos) {
        // std::cout << "channels end found." << std::endl;
        std::string channels_list = raw_input.substr(start+1, (end-1)-start);
        // std::cout << "channels_list: '" << channels_list << "'" << std::endl;
        parse_config_channels(channels_list);
      } else {
        std::cout
          << "Error in Config Format: 'channels' section end not found."
          << std::endl;
      }
    } else {
      std::cout
        << "Error in Config Format: 'channels' section not found."
        << std::endl;
    }
  } else {
    std::cout
      << "Error in Config Format: 'map' section not found."
      << std::endl;
  }
}

int parse_value(std::string raw_input, std::string key_name) {
  size_t start = std::string::npos;
  size_t end = std::string::npos;
  std::string value_raw;
  int value = -1;

  start = raw_input.find("\"" + key_name + "\"");
  // std::cout << "start: '" << start << "'" << std::endl;
  if (start != std::string::npos) {
    end = raw_input.find_first_of(",}", start);
    if (end != std::string::npos) {
      // start + " + key_name + " + :
      size_t value_content_start = start + 1 + key_name.length() + 1 + 1;
      value_raw = raw_input.substr(
        value_content_start,
        (end)-value_content_start);
      // std::cout << "value_raw: '" << value_raw << "'" << std::endl;
      // now we can convert the element string to a int
      value = std::stoi(value_raw);
    } else {
      std::cout
        << "Error in Config Format: '"
        << key_name
        << "' value end not found."
        << std::endl;
    }
  } else {
    std::cout
      << "Error in Config Format: '"
      << key_name
      << "' value not found."
      << std::endl;
  }

  return value;
}

void parse_config_universe(std::string raw_input) {
  // find "universe": { }
  // std::cout << "raw_input: '" << raw_input << "'" << std::endl;
  std::string key_name = "universe";
  size_t start_section = raw_input.find("\""+key_name+"\"");
  // std::cout << "start_section: '" << start_section << "'" << std::endl;
  if (start_section != std::string::npos) {
    size_t section_content_start = start_section + 1 + key_name.length();
    std::string section_content = raw_input.substr(
      section_content_start);
    // find 'start_address'
    uint16_t u_start_address = parse_value(section_content, "start_address");
    // find 'channel_count'
    uint16_t u_channel_count = parse_value(section_content, "channel_count");
    // find 'input'
    uint16_t u_input = parse_value(section_content, "input");
    // find 'output'
    uint16_t u_output = parse_value(section_content, "output");
    // find 'rescale_max'
    uint16_t u_rescale_max = parse_value(section_content, "rescale_max");
    // done
    std::cout << "start_address: " << u_start_address << std::endl;
    std::cout << "input: " << u_input << std::endl;
    std::cout << "output: " << u_output << std::endl;
    std::cout << "channel_count: " << u_channel_count << std::endl;
    std::cout << "rescale_max: " << u_rescale_max << std::endl;
    universe_in_start_address = u_start_address;
    universe_in = u_input;
    universe_out = u_output;
    universe_channel_count = u_channel_count;
    universe_rescale_max = u_rescale_max;
    std::cout << "universe_in_start_address: " << universe_in_start_address << std::endl;
    std::cout << "universe_in: " << universe_in << std::endl;
    std::cout << "universe_out: " << universe_out << std::endl;
    std::cout << "universe_channel_count: " << universe_channel_count << std::endl;
    std::cout << "universe_rescale_max: " << universe_rescale_max << std::endl;

  } else {
    std::cout
      << "Error in Config Format: 'universe' section not found."
      << std::endl;
  }
}

// void read_config_from_file(std::string filename) {
void read_config_from_file() {
  // std::string filename = "my_map.config";
  std::ifstream myfile("./map.json");
  if (myfile.is_open()) {
    std::string line;
    std::string raw_input;
    // read in all lines and combine theme.
    while ( std::getline(myfile, line) ) {
      std::cout << line << std::endl;
      raw_input += line;
    }
    myfile.close();
    std::cout << std::endl;
    std::cout << std::endl;

    // ------------------------------------------
    // now we can parse the input
    // std::cout << "raw_input: '" << raw_input << "'" << std::endl;

    // search and extract map
    std::cout << "parse_config_map.."<< std::endl;
    parse_config_map(raw_input);

    // search and extract universe information
    std::cout << "parse_config_universe.."<< std::endl;
    parse_config_universe(raw_input);

    std::cout << "parsing done."<< std::endl;

  } else {
    std::cout << "Unable to open file."<< std::endl;
  }
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// helper

void rescale_channels() {
  for (
    size_t channel_output_index = 0;
    channel_output_index < universe_channel_count;
    channel_output_index = channel_output_index +2
  ) {
      uint8_t value_h = 0;
      uint8_t value_l = 0;
      uint16_t value = 0;

      // get channel values
      value_h = channels_out.Get(channel_output_index);
      value_l = channels_out.Get(channel_output_index+1);

      // combine to 16bit value
      value = (value_h << 8) | value_l;

      // rescale:
      uint32_t value_calc = value * universe_rescale_max;
      value = value_calc / 65535;

      // splitt to 8itt values
      value_h = value >> 8;
      value_l = value;

      // set channel values
      channels_out.SetChannel(
        channel_output_index,
        value_h
      );
      channels_out.SetChannel(
        channel_output_index+1,
        value_l
      );
  }
}

// helper for delay:
// http://www.cplusplus.com/forum/unices/10491/#msg49054
#if defined(__WIN32__) || defined(_WIN32) || defined(WIN32) || defined(__WINDOWS__) || defined(__TOS_WIN__)

  #include <windows.h>

  inline void delay( unsigned long ms )
    {
    Sleep( ms );
    }

#else  /* presume POSIX */

  #include <unistd.h>

  inline void delay( unsigned long ms )
    {
    usleep( ms * 1000 );
    }

#endif

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// mapping

// map data to new channels and send frame
void map_channels(const ola::DmxBuffer &data) {
  for (
    size_t channel_output_index = 0;
    channel_output_index < universe_channel_count;
    channel_output_index++
  ) {
    int map_value = my_map[channel_output_index];
    // check if map_value is
    if (map_value > -1) {
        // check if map_value is in range of input channels
        if (map_value < (int)data.Size()) {
          channels_out.SetChannel(
            channel_output_index,
            data.Get(map_value));
        }
    }
  }
  rescale_channels();
  // std::cout << "Send frame: " << std::endl << channels_out << std::endl;
  wrapper.GetClient()->SendDMX(
    universe_out,
    channels_out,
    ola::client::SendDMXArgs());
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// ola things

// Called when universe registration completes.
void RegisterComplete(const ola::client::Result& result) {
  if (!result.Success()) {
    OLA_WARN << "Failed to register universe: " << result.Error();
  }
}

// Called when new DMX data arrives.
void dmx_receive_frame(const ola::client::DMXMetadata &metadata,
  const ola::DmxBuffer &data) {
  // std::cout << "Received " << data.Size()
  // << " channels for universe " << metadata.universe
  // << ", priority " << static_cast<int>(metadata.priority)
  // << std::endl;
  map_channels(data);
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// ola state helper

void ola_connection_closed(ola::io::SelectServer *ss) {
  std::cerr << "Connection to olad was closed" << std::endl;
  // system_state = state_waiting;
  // stop SelectServer
  ss->Terminate();
}

void ola_waiting_for_connection() {
  bool flag_connected = false;
  // try {
   //  std::cout << "try wrapper.Setup() " << std::endl;
    bool available  = wrapper.Setup();
   //  std::cout << "available: " << available << std::endl;
    if (available) {
      flag_connected = true;
   } else {
      // wait 500ms till next request
      delay(500);
   }
  // }
  // catch (const std::exception &exc) {
  //   // catch anything thrown that derives from std::exception
  //   std::cerr << exc.what();
  //   std::cout << "error!!: " << exc.what() << std::endl;
  // }
  // catch (...) {
  //   // catch all
  //   // sleep microseconds
  //   // usleep(500000);
  //   std::cout << "error!!: " << std::endl;
  // }
  // }
  std::cout << "flag_connected: " << flag_connected << std::endl;
  if (flag_connected) {
   //   std::cout << "GetClient: " << std::endl;
    client = wrapper.GetClient();
   //  std::cout << "switch to state_connected." << std::endl;
    system_state = state_connected;
  }
}

void ola_setup() {
  client->SetCloseHandler(
    ola::NewSingleCallback(
      ola_connection_closed,
      wrapper.GetSelectServer() ));

  // clean channels_out buffer
  channels_out.Blackout();

  // Set the callback and register our interest in this universe
  client->SetDMXCallback(ola::NewCallback(&dmx_receive_frame));
  client->RegisterUniverse(
    universe_in,
    ola::client::REGISTER,
    ola::NewSingleCallback(&RegisterComplete));
  std::cout << "map incoming channels." << std::endl;

  system_state = state_running;
}

void ola_run() {
  // this call blocks:
  wrapper.GetSelectServer()->Run();
  // if this exits we switch back to waiting state:
  std::cout << "SelectServer exited." << std::endl;
  std::cout << "wrapper.Cleanup()" << std::endl;
  wrapper.Cleanup();
  // std::cout << "wrapper" << std::endl;
  std::cout << "switching to state_waiting" << std::endl;
  system_state = state_waiting;
}

void ola_statemaschine() {
  switch (system_state) {
    case state_undefined : {
      system_state = state_waiting;
    } break;
    case state_standby : {
      system_state = state_waiting;
    } break;
    case state_waiting : {
      ola_waiting_for_connection();
    } break;
    case state_connected : {
      ola_setup();
    } break;
    case state_running : {
      // attention! blocks untill error..
      ola_run();
    } break;
  }  // end switch
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// main

int main() {
  ola::InitLogging(ola::OLA_LOG_INFO, ola::OLA_LOG_STDERR);
  // read map from file:
  // read_config_from_file("my_map.config");
  read_config_from_file();

  bool flag_run = true;

  while (flag_run) {
      ola_statemaschine();
  }

  // manual cycle
  // std::cout << "ola_waiting_for_connection()" << std::endl;
  // ola_waiting_for_connection();
  // std::cout << "ola_setup()" << std::endl;
  // ola_setup();
  // std::cout << "ola_run()" << std::endl;
  // ola_run();

}
<|endoftext|>


<commit_before>// Copyright (c) 2010 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "chrome/browser/autocomplete/autocomplete_popup_model.h"

#include "unicode/ubidi.h"

#include "base/string_util.h"
#include "chrome/browser/autocomplete/autocomplete_edit.h"
#include "chrome/browser/autocomplete/autocomplete_match.h"
#include "chrome/browser/autocomplete/autocomplete_popup_view.h"
#include "chrome/browser/autocomplete/search_provider.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/extensions/extensions_service.h"
#include "chrome/browser/search_engines/template_url.h"
#include "chrome/browser/search_engines/template_url_model.h"
#include "chrome/common/notification_service.h"
#include "gfx/rect.h"

///////////////////////////////////////////////////////////////////////////////
// AutocompletePopupModel

AutocompletePopupModel::AutocompletePopupModel(
    AutocompletePopupView* popup_view,
    AutocompleteEditModel* edit_model,
    Profile* profile)
    : view_(popup_view),
      edit_model_(edit_model),
      controller_(new AutocompleteController(profile)),
      profile_(profile),
      hovered_line_(kNoMatch),
      selected_line_(kNoMatch) {
  registrar_.Add(this, NotificationType::AUTOCOMPLETE_CONTROLLER_RESULT_UPDATED,
                 Source<AutocompleteController>(controller_.get()));
}

AutocompletePopupModel::~AutocompletePopupModel() {
}

void AutocompletePopupModel::SetProfile(Profile* profile) {
  DCHECK(profile);
  profile_ = profile;
  controller_->SetProfile(profile);
}

void AutocompletePopupModel::StartAutocomplete(
    const std::wstring& text,
    const std::wstring& desired_tld,
    bool prevent_inline_autocomplete,
    bool prefer_keyword) {
  // The user is interacting with the edit, so stop tracking hover.
  SetHoveredLine(kNoMatch);

  manually_selected_match_.Clear();

  controller_->Start(text, desired_tld, prevent_inline_autocomplete,
                     prefer_keyword, true, false);
}

void AutocompletePopupModel::StopAutocomplete() {
  controller_->Stop(true);
}

bool AutocompletePopupModel::IsOpen() const {
  return view_->IsOpen();
}

void AutocompletePopupModel::SetHoveredLine(size_t line) {
  const bool is_disabling = (line == kNoMatch);
  DCHECK(is_disabling || (line < controller_->result().size()));

  if (line == hovered_line_)
    return;  // Nothing to do

  // Make sure the old hovered line is redrawn.  No need to redraw the selected
  // line since selection overrides hover so the appearance won't change.
  if ((hovered_line_ != kNoMatch) && (hovered_line_ != selected_line_))
    view_->InvalidateLine(hovered_line_);

  // Change the hover to the new line.
  hovered_line_ = line;
  if (!is_disabling && (hovered_line_ != selected_line_))
    view_->InvalidateLine(hovered_line_);
}

void AutocompletePopupModel::SetSelectedLine(size_t line,
                                             bool reset_to_default) {
  // We should at least be dealing with the results of the current query.  Note
  // that even if |line| was valid on entry, this may make it invalid.  We clamp
  // it below.
  controller_->CommitIfQueryHasNeverBeenCommitted();

  const AutocompleteResult& result = controller_->result();
  if (result.empty())
    return;

  // Cancel the query so the matches don't change on the user.
  controller_->Stop(false);

  line = std::min(line, result.size() - 1);
  const AutocompleteMatch& match = result.match_at(line);
  if (reset_to_default) {
    manually_selected_match_.Clear();
  } else {
    // Track the user's selection until they cancel it.
    manually_selected_match_.destination_url = match.destination_url;
    manually_selected_match_.provider_affinity = match.provider;
    manually_selected_match_.is_history_what_you_typed_match =
        match.is_history_what_you_typed_match;
  }

  if (line == selected_line_)
    return;  // Nothing else to do.

  // We need to update |selected_line_| before calling OnPopupDataChanged(), so
  // that when the edit notifies its controller that something has changed, the
  // controller can get the correct updated data.
  //
  // NOTE: We should never reach here with no selected line; the same code that
  // opened the popup and made it possible to get here should have also set a
  // selected line.
  CHECK(selected_line_ != kNoMatch);
  GURL current_destination(result.match_at(selected_line_).destination_url);
  view_->InvalidateLine(selected_line_);
  selected_line_ = line;
  view_->InvalidateLine(selected_line_);

  // Update the edit with the new data for this match.
  // TODO(pkasting): If |selected_line_| moves to the controller, this can be
  // eliminated and just become a call to the observer on the edit.
  std::wstring keyword;
  const bool is_keyword_hint = GetKeywordForMatch(match, &keyword);
  if (reset_to_default) {
    std::wstring inline_autocomplete_text;
    if ((match.inline_autocomplete_offset != std::wstring::npos) &&
        (match.inline_autocomplete_offset < match.fill_into_edit.length())) {
      inline_autocomplete_text =
          match.fill_into_edit.substr(match.inline_autocomplete_offset);
    }
    edit_model_->OnPopupDataChanged(inline_autocomplete_text, NULL,
                                    keyword, is_keyword_hint);
  } else {
    edit_model_->OnPopupDataChanged(match.fill_into_edit, &current_destination,
                                    keyword, is_keyword_hint);
  }

  // Repaint old and new selected lines immediately, so that the edit doesn't
  // appear to update [much] faster than the popup.
  view_->PaintUpdatesNow();
}

void AutocompletePopupModel::ResetToDefaultMatch() {
  const AutocompleteResult& result = controller_->result();
  CHECK(!result.empty());
  SetSelectedLine(result.default_match() - result.begin(), true);
  view_->OnDragCanceled();
}

void AutocompletePopupModel::InfoForCurrentSelection(
    AutocompleteMatch* match,
    GURL* alternate_nav_url) const {
  DCHECK(match != NULL);
  const AutocompleteResult* result;
  if (!controller_->done()) {
    // NOTE: Using latest_result() is important here since not only could it
    // contain newer results than result() for the current query, it could even
    // refer to an entirely different query (e.g. if the user is typing rapidly
    // and the controller is purposefully delaying updates to avoid flicker).
    result = &controller_->latest_result();
    // It's technically possible for |result| to be empty if no provider returns
    // a synchronous result but the query has not completed synchronously;
    // pratically, however, that should never actually happen.
    if (result->empty())
      return;
    // The user cannot have manually selected a match, or the query would have
    // stopped.  So the default match must be the desired selection.
    *match = *result->default_match();
  } else {
    CHECK(IsOpen());
    // The query isn't running, so the standard result set can't possibly be out
    // of date.
    //
    // NOTE: In practice, it should actually be safe to use
    // controller_->latest_result() here too, since the controller keeps that
    // up-to-date.  However we generally try to avoid referring to that.
    result = &controller_->result();
    // If there are no results, the popup should be closed (so we should have
    // failed the CHECK above), and URLsForDefaultMatch() should have been
    // called instead.
    CHECK(!result->empty());
    CHECK(selected_line_ < result->size());
    *match = result->match_at(selected_line_);
  }
  if (alternate_nav_url && manually_selected_match_.empty())
    *alternate_nav_url = result->alternate_nav_url();
}

bool AutocompletePopupModel::GetKeywordForMatch(const AutocompleteMatch& match,
                                                std::wstring* keyword) const {
  // Assume we have no keyword until we find otherwise.
  keyword->clear();

  // If the current match is a keyword, return that as the selected keyword.
  if (TemplateURL::SupportsReplacement(match.template_url)) {
    keyword->assign(match.template_url->keyword());
    return false;
  }

  // See if the current match's fill_into_edit corresponds to a keyword.
  if (!profile_->GetTemplateURLModel())
    return false;
  profile_->GetTemplateURLModel()->Load();
  const std::wstring keyword_hint(
      TemplateURLModel::CleanUserInputKeyword(match.fill_into_edit));
  if (keyword_hint.empty())
    return false;

  // Don't provide a hint if this keyword doesn't support replacement.
  const TemplateURL* const template_url =
      profile_->GetTemplateURLModel()->GetTemplateURLForKeyword(keyword_hint);
  if (!TemplateURL::SupportsReplacement(template_url))
    return false;

  // Don't provide a hint if this is an extension keyword not enabled for
  // incognito mode (and if this is an incognito profile).
  if (template_url->IsExtensionKeyword() && profile_->IsOffTheRecord()) {
    const Extension* extension = profile_->GetExtensionsService()->
        GetExtensionById(template_url->GetExtensionId(), false);
    if (!profile_->GetExtensionsService()->IsIncognitoEnabled(extension))
      return false;
  }

  keyword->assign(keyword_hint);
  return true;
}

void AutocompletePopupModel::FinalizeInstantQuery(const std::wstring& text) {
  if (IsOpen()) {
    SearchProvider* search_provider = controller_->search_provider();
    search_provider->FinalizeInstantQuery(text);
  }
}

AutocompleteLog* AutocompletePopupModel::GetAutocompleteLog() {
  return new AutocompleteLog(controller_->input().text(),
      controller_->input().type(), selected_line_, 0, controller_->result());
}

void AutocompletePopupModel::Move(int count) {
  const AutocompleteResult& result = controller_->result();
  if (result.empty())
    return;

  // The user is using the keyboard to change the selection, so stop tracking
  // hover.
  SetHoveredLine(kNoMatch);

  // Clamp the new line to [0, result_.count() - 1].
  const size_t new_line = selected_line_ + count;
  SetSelectedLine(((count < 0) && (new_line >= selected_line_)) ? 0 : new_line,
                  false);
}

void AutocompletePopupModel::TryDeletingCurrentItem() {
  // We could use InfoForCurrentSelection() here, but it seems better to try
  // and shift-delete the actual selection, rather than any "in progress, not
  // yet visible" one.
  if (selected_line_ == kNoMatch)
    return;

  // Cancel the query so the matches don't change on the user.
  controller_->Stop(false);

  const AutocompleteMatch& match =
      controller_->result().match_at(selected_line_);
  if (match.deletable) {
    const size_t selected_line = selected_line_;
    controller_->DeleteMatch(match);  // This may synchronously notify us that
                                      // the results have changed.
    const AutocompleteResult& result = controller_->result();
    if (!result.empty()) {
      // Move the selection to the next choice after the deleted one.
      // SetSelectedLine() will clamp to take care of the case where we deleted
      // the last item.
      // TODO(pkasting): Eventually the controller should take care of this
      // before notifying us, reducing flicker.  At that point the check for
      // deletability can move there too.
      SetSelectedLine(selected_line, false);
    }
  }
}

void AutocompletePopupModel::Observe(NotificationType type,
                                     const NotificationSource& source,
                                     const NotificationDetails& details) {
  DCHECK_EQ(NotificationType::AUTOCOMPLETE_CONTROLLER_RESULT_UPDATED,
            type.value);

  const AutocompleteResult* result =
      Details<const AutocompleteResult>(details).ptr();
  selected_line_ = result->default_match() == result->end() ?
      kNoMatch : static_cast<size_t>(result->default_match() - result->begin());
  // There had better not be a nonempty result set with no default match.
  CHECK((selected_line_ != kNoMatch) || result->empty());
  // If we're going to trim the window size to no longer include the hovered
  // line, turn hover off.  Practically, this shouldn't happen, but it
  // doesn't hurt to be defensive.
  if ((hovered_line_ != kNoMatch) && (result->size() <= hovered_line_))
    SetHoveredLine(kNoMatch);

  view_->UpdatePopupAppearance();
  edit_model_->ResultsUpdated();
  edit_model_->PopupBoundsChangedTo(view_->GetTargetBounds());
}

const SkBitmap* AutocompletePopupModel::GetSpecialIconForMatch(
    const AutocompleteMatch& match) const {
  if (!match.template_url || !match.template_url->IsExtensionKeyword())
    return NULL;

  return &profile_->GetExtensionsService()->GetOmniboxPopupIcon(
      match.template_url->GetExtensionId());
}
<commit_msg>Fix a browser crash when typing a disabled extension keyword in an incognito window's URL bar.<commit_after>// Copyright (c) 2010 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "chrome/browser/autocomplete/autocomplete_popup_model.h"

#include "unicode/ubidi.h"

#include "base/string_util.h"
#include "chrome/browser/autocomplete/autocomplete_edit.h"
#include "chrome/browser/autocomplete/autocomplete_match.h"
#include "chrome/browser/autocomplete/autocomplete_popup_view.h"
#include "chrome/browser/autocomplete/search_provider.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/extensions/extensions_service.h"
#include "chrome/browser/search_engines/template_url.h"
#include "chrome/browser/search_engines/template_url_model.h"
#include "chrome/common/notification_service.h"
#include "gfx/rect.h"

///////////////////////////////////////////////////////////////////////////////
// AutocompletePopupModel

AutocompletePopupModel::AutocompletePopupModel(
    AutocompletePopupView* popup_view,
    AutocompleteEditModel* edit_model,
    Profile* profile)
    : view_(popup_view),
      edit_model_(edit_model),
      controller_(new AutocompleteController(profile)),
      profile_(profile),
      hovered_line_(kNoMatch),
      selected_line_(kNoMatch) {
  registrar_.Add(this, NotificationType::AUTOCOMPLETE_CONTROLLER_RESULT_UPDATED,
                 Source<AutocompleteController>(controller_.get()));
}

AutocompletePopupModel::~AutocompletePopupModel() {
}

void AutocompletePopupModel::SetProfile(Profile* profile) {
  DCHECK(profile);
  profile_ = profile;
  controller_->SetProfile(profile);
}

void AutocompletePopupModel::StartAutocomplete(
    const std::wstring& text,
    const std::wstring& desired_tld,
    bool prevent_inline_autocomplete,
    bool prefer_keyword) {
  // The user is interacting with the edit, so stop tracking hover.
  SetHoveredLine(kNoMatch);

  manually_selected_match_.Clear();

  controller_->Start(text, desired_tld, prevent_inline_autocomplete,
                     prefer_keyword, true, false);
}

void AutocompletePopupModel::StopAutocomplete() {
  controller_->Stop(true);
}

bool AutocompletePopupModel::IsOpen() const {
  return view_->IsOpen();
}

void AutocompletePopupModel::SetHoveredLine(size_t line) {
  const bool is_disabling = (line == kNoMatch);
  DCHECK(is_disabling || (line < controller_->result().size()));

  if (line == hovered_line_)
    return;  // Nothing to do

  // Make sure the old hovered line is redrawn.  No need to redraw the selected
  // line since selection overrides hover so the appearance won't change.
  if ((hovered_line_ != kNoMatch) && (hovered_line_ != selected_line_))
    view_->InvalidateLine(hovered_line_);

  // Change the hover to the new line.
  hovered_line_ = line;
  if (!is_disabling && (hovered_line_ != selected_line_))
    view_->InvalidateLine(hovered_line_);
}

void AutocompletePopupModel::SetSelectedLine(size_t line,
                                             bool reset_to_default) {
  // We should at least be dealing with the results of the current query.  Note
  // that even if |line| was valid on entry, this may make it invalid.  We clamp
  // it below.
  controller_->CommitIfQueryHasNeverBeenCommitted();

  const AutocompleteResult& result = controller_->result();
  if (result.empty())
    return;

  // Cancel the query so the matches don't change on the user.
  controller_->Stop(false);

  line = std::min(line, result.size() - 1);
  const AutocompleteMatch& match = result.match_at(line);
  if (reset_to_default) {
    manually_selected_match_.Clear();
  } else {
    // Track the user's selection until they cancel it.
    manually_selected_match_.destination_url = match.destination_url;
    manually_selected_match_.provider_affinity = match.provider;
    manually_selected_match_.is_history_what_you_typed_match =
        match.is_history_what_you_typed_match;
  }

  if (line == selected_line_)
    return;  // Nothing else to do.

  // We need to update |selected_line_| before calling OnPopupDataChanged(), so
  // that when the edit notifies its controller that something has changed, the
  // controller can get the correct updated data.
  //
  // NOTE: We should never reach here with no selected line; the same code that
  // opened the popup and made it possible to get here should have also set a
  // selected line.
  CHECK(selected_line_ != kNoMatch);
  GURL current_destination(result.match_at(selected_line_).destination_url);
  view_->InvalidateLine(selected_line_);
  selected_line_ = line;
  view_->InvalidateLine(selected_line_);

  // Update the edit with the new data for this match.
  // TODO(pkasting): If |selected_line_| moves to the controller, this can be
  // eliminated and just become a call to the observer on the edit.
  std::wstring keyword;
  const bool is_keyword_hint = GetKeywordForMatch(match, &keyword);
  if (reset_to_default) {
    std::wstring inline_autocomplete_text;
    if ((match.inline_autocomplete_offset != std::wstring::npos) &&
        (match.inline_autocomplete_offset < match.fill_into_edit.length())) {
      inline_autocomplete_text =
          match.fill_into_edit.substr(match.inline_autocomplete_offset);
    }
    edit_model_->OnPopupDataChanged(inline_autocomplete_text, NULL,
                                    keyword, is_keyword_hint);
  } else {
    edit_model_->OnPopupDataChanged(match.fill_into_edit, &current_destination,
                                    keyword, is_keyword_hint);
  }

  // Repaint old and new selected lines immediately, so that the edit doesn't
  // appear to update [much] faster than the popup.
  view_->PaintUpdatesNow();
}

void AutocompletePopupModel::ResetToDefaultMatch() {
  const AutocompleteResult& result = controller_->result();
  CHECK(!result.empty());
  SetSelectedLine(result.default_match() - result.begin(), true);
  view_->OnDragCanceled();
}

void AutocompletePopupModel::InfoForCurrentSelection(
    AutocompleteMatch* match,
    GURL* alternate_nav_url) const {
  DCHECK(match != NULL);
  const AutocompleteResult* result;
  if (!controller_->done()) {
    // NOTE: Using latest_result() is important here since not only could it
    // contain newer results than result() for the current query, it could even
    // refer to an entirely different query (e.g. if the user is typing rapidly
    // and the controller is purposefully delaying updates to avoid flicker).
    result = &controller_->latest_result();
    // It's technically possible for |result| to be empty if no provider returns
    // a synchronous result but the query has not completed synchronously;
    // pratically, however, that should never actually happen.
    if (result->empty())
      return;
    // The user cannot have manually selected a match, or the query would have
    // stopped.  So the default match must be the desired selection.
    *match = *result->default_match();
  } else {
    CHECK(IsOpen());
    // The query isn't running, so the standard result set can't possibly be out
    // of date.
    //
    // NOTE: In practice, it should actually be safe to use
    // controller_->latest_result() here too, since the controller keeps that
    // up-to-date.  However we generally try to avoid referring to that.
    result = &controller_->result();
    // If there are no results, the popup should be closed (so we should have
    // failed the CHECK above), and URLsForDefaultMatch() should have been
    // called instead.
    CHECK(!result->empty());
    CHECK(selected_line_ < result->size());
    *match = result->match_at(selected_line_);
  }
  if (alternate_nav_url && manually_selected_match_.empty())
    *alternate_nav_url = result->alternate_nav_url();
}

bool AutocompletePopupModel::GetKeywordForMatch(const AutocompleteMatch& match,
                                                std::wstring* keyword) const {
  // Assume we have no keyword until we find otherwise.
  keyword->clear();

  // If the current match is a keyword, return that as the selected keyword.
  if (TemplateURL::SupportsReplacement(match.template_url)) {
    keyword->assign(match.template_url->keyword());
    return false;
  }

  // See if the current match's fill_into_edit corresponds to a keyword.
  if (!profile_->GetTemplateURLModel())
    return false;
  profile_->GetTemplateURLModel()->Load();
  const std::wstring keyword_hint(
      TemplateURLModel::CleanUserInputKeyword(match.fill_into_edit));
  if (keyword_hint.empty())
    return false;

  // Don't provide a hint if this keyword doesn't support replacement.
  const TemplateURL* const template_url =
      profile_->GetTemplateURLModel()->GetTemplateURLForKeyword(keyword_hint);
  if (!TemplateURL::SupportsReplacement(template_url))
    return false;

  // Don't provide a hint for inactive/disabled extension keywords.
  if (template_url->IsExtensionKeyword()) {
    const Extension* extension = profile_->GetExtensionsService()->
        GetExtensionById(template_url->GetExtensionId(), false);
    if (!extension ||
        (profile_->IsOffTheRecord() &&
         !profile_->GetExtensionsService()->IsIncognitoEnabled(extension)))
      return false;
  }

  keyword->assign(keyword_hint);
  return true;
}

void AutocompletePopupModel::FinalizeInstantQuery(const std::wstring& text) {
  if (IsOpen()) {
    SearchProvider* search_provider = controller_->search_provider();
    search_provider->FinalizeInstantQuery(text);
  }
}

AutocompleteLog* AutocompletePopupModel::GetAutocompleteLog() {
  return new AutocompleteLog(controller_->input().text(),
      controller_->input().type(), selected_line_, 0, controller_->result());
}

void AutocompletePopupModel::Move(int count) {
  const AutocompleteResult& result = controller_->result();
  if (result.empty())
    return;

  // The user is using the keyboard to change the selection, so stop tracking
  // hover.
  SetHoveredLine(kNoMatch);

  // Clamp the new line to [0, result_.count() - 1].
  const size_t new_line = selected_line_ + count;
  SetSelectedLine(((count < 0) && (new_line >= selected_line_)) ? 0 : new_line,
                  false);
}

void AutocompletePopupModel::TryDeletingCurrentItem() {
  // We could use InfoForCurrentSelection() here, but it seems better to try
  // and shift-delete the actual selection, rather than any "in progress, not
  // yet visible" one.
  if (selected_line_ == kNoMatch)
    return;

  // Cancel the query so the matches don't change on the user.
  controller_->Stop(false);

  const AutocompleteMatch& match =
      controller_->result().match_at(selected_line_);
  if (match.deletable) {
    const size_t selected_line = selected_line_;
    controller_->DeleteMatch(match);  // This may synchronously notify us that
                                      // the results have changed.
    const AutocompleteResult& result = controller_->result();
    if (!result.empty()) {
      // Move the selection to the next choice after the deleted one.
      // SetSelectedLine() will clamp to take care of the case where we deleted
      // the last item.
      // TODO(pkasting): Eventually the controller should take care of this
      // before notifying us, reducing flicker.  At that point the check for
      // deletability can move there too.
      SetSelectedLine(selected_line, false);
    }
  }
}

void AutocompletePopupModel::Observe(NotificationType type,
                                     const NotificationSource& source,
                                     const NotificationDetails& details) {
  DCHECK_EQ(NotificationType::AUTOCOMPLETE_CONTROLLER_RESULT_UPDATED,
            type.value);

  const AutocompleteResult* result =
      Details<const AutocompleteResult>(details).ptr();
  selected_line_ = result->default_match() == result->end() ?
      kNoMatch : static_cast<size_t>(result->default_match() - result->begin());
  // There had better not be a nonempty result set with no default match.
  CHECK((selected_line_ != kNoMatch) || result->empty());
  // If we're going to trim the window size to no longer include the hovered
  // line, turn hover off.  Practically, this shouldn't happen, but it
  // doesn't hurt to be defensive.
  if ((hovered_line_ != kNoMatch) && (result->size() <= hovered_line_))
    SetHoveredLine(kNoMatch);

  view_->UpdatePopupAppearance();
  edit_model_->ResultsUpdated();
  edit_model_->PopupBoundsChangedTo(view_->GetTargetBounds());
}

const SkBitmap* AutocompletePopupModel::GetSpecialIconForMatch(
    const AutocompleteMatch& match) const {
  if (!match.template_url || !match.template_url->IsExtensionKeyword())
    return NULL;

  return &profile_->GetExtensionsService()->GetOmniboxPopupIcon(
      match.template_url->GetExtensionId());
}
<|endoftext|>