<commit_before>/*
 * Copyright (C) 2018 Nagisa Sekiguchi
 *
 * 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.
 */

#ifndef MISC_LIB_RESULT_HPP
#define MISC_LIB_RESULT_HPP

#include <cassert>
#include <type_traits>

#include "noncopyable.h"

BEGIN_MISC_LIB_NAMESPACE_DECL

template <typename T>
struct TypeHolder {
  using type = T;
};

namespace __detail {

constexpr size_t maxOf(size_t v) { return v; }

template <typename... S>
constexpr size_t maxOf(size_t v, S... rest) {
  return std::max(v, maxOf(rest...));
}

constexpr bool andAll(bool b) { return b; }

template <typename... T>
constexpr bool andAll(bool b, T &&...t) {
  return b && andAll(std::forward<T>(t)...);
}

template <typename T>
constexpr int toTypeIndex(int) {
  return -1;
}

template <typename T, typename F, typename... R>
constexpr int toTypeIndex(int index) {
  return std::is_same<T, F>::value ? index : toTypeIndex<T, R...>(index + 1);
}

template <std::size_t I, std::size_t N, typename F, typename... R>
struct TypeByIndex_ : TypeByIndex_<I + 1, N, R...> {};

template <std::size_t N, typename F, typename... R>
struct TypeByIndex_<N, N, F, R...> {
  using type = F;
};

template <typename... T>
struct OverloadResolver;

template <typename F, typename... T>
struct OverloadResolver<F, T...> : OverloadResolver<T...> {
  using OverloadResolver<T...>::operator();

  TypeHolder<F> operator()(F) const;
};

template <>
struct OverloadResolver<> {
  void operator()() const;
};

template <typename F, typename... T>
using resolvedType = typename std::invoke_result_t<OverloadResolver<T...>, F>::type;

template <ssize_t N>
struct index_holder {};

} // namespace __detail

template <typename U, typename... T>
struct TypeTag {
  static constexpr int value = __detail::toTypeIndex<U, T...>(0);
};

template <std::size_t N, typename T0, typename... T>
struct TypeByIndex {
  static_assert(N < sizeof...(T) + 1, "out of range");
  using type = typename __detail::TypeByIndex_<0, N, T0, T...>::type;
};

// #####################
// ##     Storage     ##
// #####################

template <typename... T>
struct Storage {
  alignas(T...) unsigned char data[__detail::maxOf(sizeof(T)...)];

  template <typename U, typename F = __detail::resolvedType<U, T...>>
  void obtain(U &&value) {
    static_assert(TypeTag<F, T...>::value > -1, "invalid type");

    using Decayed = typename std::decay<F>::type;
    new (&this->data) Decayed(std::forward<U>(value));
  }
};

template <typename T, typename... R>
inline T &get(Storage<R...> &storage) {
  static_assert(TypeTag<T, R...>::value > -1, "invalid type");

  return *reinterpret_cast<T *>(&storage.data);
}

template <typename T, typename... R>
inline const T &get(const Storage<R...> &storage) {
  static_assert(TypeTag<T, R...>::value > -1, "invalid type");

  return *reinterpret_cast<const T *>(&storage.data);
}

template <typename T, typename... R>
inline void destroy(Storage<R...> &storage) {
  get<T>(storage).~T();
}

/**
 *
 * @tparam T
 * @tparam R
 * @param src
 * @param dest
 * must be uninitialized
 */
template <typename T, typename... R>
inline void move(Storage<R...> &src, Storage<R...> &dest) {
  dest.obtain(std::move(get<T>(src)));
}

template <typename T, typename... R>
inline void copy(const Storage<R...> &src, Storage<R...> &dest) {
  dest.obtain(get<T>(src));
}

namespace __detail {

template <ssize_t N, typename... R>
inline void destroy(Storage<R...> &storage, int tag, index_holder<N>) {
  if constexpr (N == -1) {
  } // do nothing
  else if (tag == N) {
    using T = typename TypeByIndex<N, R...>::type;
    get<T>(storage).~T();
  } else {
    destroy(storage, tag, index_holder<N - 1>{});
  }
}

template <typename... R>
inline void destroy(Storage<R...> &storage, int tag) {
  destroy(storage, tag, index_holder<sizeof...(R) - 1>{});
}

template <ssize_t N, typename... R>
inline void move(Storage<R...> &src, int srcTag, index_holder<N>, Storage<R...> &dest) {
  if constexpr (N == -1) {
  } // do nothing
  else if (srcTag == N) {
    using T = typename TypeByIndex<N, R...>::type;
    dest.obtain(std::move(get<T>(src)));
  } else {
    move(src, srcTag, index_holder<N - 1>{}, dest);
  }
}

template <typename... R>
inline void move(Storage<R...> &src, int srcTag, Storage<R...> &dest) {
  move(src, srcTag, index_holder<sizeof...(R) - 1>{}, dest);
}

template <ssize_t N, typename... R>
inline void copy(const Storage<R...> &src, int srcTag, index_holder<N>, Storage<R...> &dest) {
  if constexpr (N == -1) {
  } // do nothing
  else if (srcTag == N) {
    using T = typename TypeByIndex<N, R...>::type;
    dest.obtain(get<T>(src));
  } else {
    copy(src, srcTag, index_holder<N - 1>{}, dest);
  }
}

template <typename... R>
inline void copy(const Storage<R...> &src, int srcTag, Storage<R...> &dest) {
  return copy(src, srcTag, index_holder<sizeof...(R) - 1>{}, dest);
}

} // namespace __detail

// ###################
// ##     Union     ##
// ###################

template <typename... T>
class Union {
private:
  static_assert(__detail::andAll(std::is_move_constructible<T>::value...),
                "must be move-constructible");

  using StorageType = Storage<T...>;
  StorageType value_;
  int tag_;

public:
  template <typename R>
  static constexpr int TAG = TypeTag<R, T...>::value;

  Union() noexcept : tag_(-1) {}

  template <typename U, typename F = __detail::resolvedType<U, T...>>
  Union(U &&value) noexcept : tag_(TAG<F>) { // NOLINT
    this->value_.obtain(std::forward<U>(value));
  }

  Union(Union &&value) noexcept : tag_(value.tag()) {
    __detail::move(value.value(), this->tag(), this->value());
    value.tag_ = -1;
  }

  Union(const Union &value) : tag_(value.tag()) {
    __detail::copy(value.value(), this->tag(), this->value());
  }

  ~Union() { __detail::destroy(this->value(), this->tag()); }

  Union &operator=(Union &&value) noexcept {
    if (this != std::addressof(value)) {
      this->moveAssign(value);
    }
    return *this;
  }

  Union &operator=(const Union &value) {
    if (this != std::addressof(value)) {
      this->copyAssign(value);
    }
    return *this;
  }

  StorageType &value() { return this->value_; }

  const StorageType &value() const { return this->value_; }

  int tag() const { return this->tag_; }

  bool hasValue() const { return this->tag() > -1; }

private:
  void moveAssign(Union &value) noexcept {
    __detail::destroy(this->value(), this->tag());
    __detail::move(value.value(), value.tag(), this->value());
    this->tag_ = value.tag();
    value.tag_ = -1;
  }

  void copyAssign(const Union &value) {
    __detail::destroy(this->value(), this->tag());
    __detail::copy(value.value(), value.tag(), this->value());
    this->tag_ = value.tag();
  }
};

template <typename T, typename... R>
inline bool is(const Union<R...> &value) {
  using Tag = TypeTag<T, R...>;
  static_assert(Tag::value > -1, "invalid type");
  return value.tag() == Tag::value;
}

template <typename T, typename... R>
inline T &get(Union<R...> &value) {
  assert(is<T>(value));
  return get<T>(value.value());
}

template <typename T, typename... R>
inline const T &get(const Union<R...> &value) {
  assert(is<T>(value));
  return get<T>(value.value());
}

// ######################
// ##     Optional     ##
// ######################

template <typename T>
class OptionalBase : public Union<T> {
public:
  using base_type = Union<T>;

  OptionalBase() noexcept : Union<T>() {}

  OptionalBase(T &&value) noexcept : Union<T>(std::forward<T>(value)) {} // NOLINT

  T &unwrap() noexcept { return get<T>(*this); }

  const T &unwrap() const noexcept { return get<T>(*this); }
};

template <typename... T>
class OptionalBase<Union<T...>> : public Union<T...> {
public:
  using base_type = Union<T...>;

  OptionalBase() noexcept : Union<T...>() {}

  template <typename U>
  OptionalBase(U &&value) noexcept : Union<T...>(std::forward<U>(value)) {} // NOLINT

  Union<T...> &unwrap() noexcept { return static_cast<base_type &>(*this); }

  const Union<T...> &unwrap() const noexcept { return static_cast<const base_type &>(*this); }
};

template <typename T>
struct OptFlattener {
  using type = T;
};

template <typename T>
struct OptFlattener<OptionalBase<T>> : OptFlattener<T> {};

template <typename T>
using Optional = OptionalBase<typename OptFlattener<T>::type>;

// ####################
// ##     Result     ##
// ####################

template <typename T>
struct OkHolder {
  T value;

  explicit OkHolder(T &&value) : value(std::move(value)) {}
  explicit OkHolder(const T &value) : value(value) {}
};

template <typename E>
struct ErrHolder {
  E value;

  explicit ErrHolder(E &&value) : value(std::move(value)) {}
  explicit ErrHolder(const E &value) : value(value) {}
};

template <typename T, typename Decayed = typename std::decay<T>::type>
OkHolder<Decayed> Ok(T &&value) {
  return OkHolder<Decayed>(std::forward<T>(value));
}

template <typename E, typename Decayed = typename std::decay<E>::type>
ErrHolder<Decayed> Err(E &&value) {
  return ErrHolder<Decayed>(std::forward<E>(value));
}

template <typename T, typename E>
class Result : public Union<T, E> {
public:
  NON_COPYABLE(Result);

  Result() = delete;

  template <typename T0>
  Result(OkHolder<T0> &&okHolder) noexcept : Union<T, E>(std::move(okHolder.value)) {} // NOLINT

  Result(ErrHolder<E> &&errHolder) noexcept : Union<T, E>(std::move(errHolder.value)) {} // NOLINT

  Result(Result &&result) noexcept = default;

  ~Result() = default;

  Result &operator=(Result &&result) noexcept = default;

  explicit operator bool() const { return is<T>(*this); }

  T &asOk() { return get<T>(*this); }

  E &asErr() { return get<E>(*this); }

  const T &asOk() const { return get<T>(*this); }

  const E &asErr() const { return get<E>(*this); }

  T &&take() && { return std::move(this->asOk()); }

  E &&takeError() && { return std::move(this->asErr()); }
};

END_MISC_LIB_NAMESPACE_DECL

#endif // MISC_LIB_RESULT_HPP
<commit_msg>add launder to Union<commit_after>/*
 * Copyright (C) 2018 Nagisa Sekiguchi
 *
 * 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.
 */

#ifndef MISC_LIB_RESULT_HPP
#define MISC_LIB_RESULT_HPP

#include <cassert>
#include <type_traits>

#include "noncopyable.h"

BEGIN_MISC_LIB_NAMESPACE_DECL

template <typename T>
struct TypeHolder {
  using type = T;
};

namespace __detail {

constexpr size_t maxOf(size_t v) { return v; }

template <typename... S>
constexpr size_t maxOf(size_t v, S... rest) {
  return std::max(v, maxOf(rest...));
}

constexpr bool andAll(bool b) { return b; }

template <typename... T>
constexpr bool andAll(bool b, T &&...t) {
  return b && andAll(std::forward<T>(t)...);
}

template <typename T>
constexpr int toTypeIndex(int) {
  return -1;
}

template <typename T, typename F, typename... R>
constexpr int toTypeIndex(int index) {
  return std::is_same<T, F>::value ? index : toTypeIndex<T, R...>(index + 1);
}

template <std::size_t I, std::size_t N, typename F, typename... R>
struct TypeByIndex_ : TypeByIndex_<I + 1, N, R...> {};

template <std::size_t N, typename F, typename... R>
struct TypeByIndex_<N, N, F, R...> {
  using type = F;
};

template <typename... T>
struct OverloadResolver;

template <typename F, typename... T>
struct OverloadResolver<F, T...> : OverloadResolver<T...> {
  using OverloadResolver<T...>::operator();

  TypeHolder<F> operator()(F) const;
};

template <>
struct OverloadResolver<> {
  void operator()() const;
};

template <typename F, typename... T>
using resolvedType = typename std::invoke_result_t<OverloadResolver<T...>, F>::type;

template <ssize_t N>
struct index_holder {};

} // namespace __detail

template <typename U, typename... T>
struct TypeTag {
  static constexpr int value = __detail::toTypeIndex<U, T...>(0);
};

template <std::size_t N, typename T0, typename... T>
struct TypeByIndex {
  static_assert(N < sizeof...(T) + 1, "out of range");
  using type = typename __detail::TypeByIndex_<0, N, T0, T...>::type;
};

// #####################
// ##     Storage     ##
// #####################

template <typename... T>
class Storage {
private:
  alignas(T...) unsigned char data_[__detail::maxOf(sizeof(T)...)];

public:
  template <typename U, typename F = __detail::resolvedType<U, T...>>
  void obtain(U &&value) {
    static_assert(TypeTag<F, T...>::value > -1, "invalid type");

    using Decayed = typename std::decay<F>::type;
    new (&this->data_) Decayed(std::forward<U>(value));
  }

  template <typename F>
  F *data() {
    static_assert(TypeTag<F, T...>::value > -1, "invalid type");
#ifdef __cpp_lib_launder
    return std::launder(reinterpret_cast<F *>(&this->data_));
#else
    return reinterpret_cast<F *>(&this->data_);
#endif
  }

  template <typename F>
  const F *data() const {
    static_assert(TypeTag<F, T...>::value > -1, "invalid type");
#ifdef __cpp_lib_launder
    return std::launder(reinterpret_cast<const F *>(&this->data_));
#else
    return reinterpret_cast<const F *>(&this->data_);
#endif
  }
};

template <typename T, typename... R>
inline T &get(Storage<R...> &storage) {
  static_assert(TypeTag<T, R...>::value > -1, "invalid type");
  return *storage.template data<T>();
}

template <typename T, typename... R>
inline const T &get(const Storage<R...> &storage) {
  static_assert(TypeTag<T, R...>::value > -1, "invalid type");
  return *storage.template data<T>();
}

template <typename T, typename... R>
inline void destroy(Storage<R...> &storage) {
  get<T>(storage).~T();
}

/**
 *
 * @tparam T
 * @tparam R
 * @param src
 * @param dest
 * must be uninitialized
 */
template <typename T, typename... R>
inline void move(Storage<R...> &src, Storage<R...> &dest) {
  dest.obtain(std::move(get<T>(src)));
}

template <typename T, typename... R>
inline void copy(const Storage<R...> &src, Storage<R...> &dest) {
  dest.obtain(get<T>(src));
}

namespace __detail {

template <ssize_t N, typename... R>
inline void destroy(Storage<R...> &storage, int tag, index_holder<N>) {
  if constexpr (N == -1) {
  } // do nothing
  else if (tag == N) {
    using T = typename TypeByIndex<N, R...>::type;
    get<T>(storage).~T();
  } else {
    destroy(storage, tag, index_holder<N - 1>{});
  }
}

template <typename... R>
inline void destroy(Storage<R...> &storage, int tag) {
  destroy(storage, tag, index_holder<sizeof...(R) - 1>{});
}

template <ssize_t N, typename... R>
inline void move(Storage<R...> &src, int srcTag, index_holder<N>, Storage<R...> &dest) {
  if constexpr (N == -1) {
  } // do nothing
  else if (srcTag == N) {
    using T = typename TypeByIndex<N, R...>::type;
    dest.obtain(std::move(get<T>(src)));
  } else {
    move(src, srcTag, index_holder<N - 1>{}, dest);
  }
}

template <typename... R>
inline void move(Storage<R...> &src, int srcTag, Storage<R...> &dest) {
  move(src, srcTag, index_holder<sizeof...(R) - 1>{}, dest);
}

template <ssize_t N, typename... R>
inline void copy(const Storage<R...> &src, int srcTag, index_holder<N>, Storage<R...> &dest) {
  if constexpr (N == -1) {
  } // do nothing
  else if (srcTag == N) {
    using T = typename TypeByIndex<N, R...>::type;
    dest.obtain(get<T>(src));
  } else {
    copy(src, srcTag, index_holder<N - 1>{}, dest);
  }
}

template <typename... R>
inline void copy(const Storage<R...> &src, int srcTag, Storage<R...> &dest) {
  return copy(src, srcTag, index_holder<sizeof...(R) - 1>{}, dest);
}

} // namespace __detail

// ###################
// ##     Union     ##
// ###################

template <typename... T>
class Union {
private:
  static_assert(__detail::andAll(std::is_move_constructible<T>::value...),
                "must be move-constructible");

  using StorageType = Storage<T...>;
  StorageType value_;
  int tag_;

public:
  template <typename R>
  static constexpr int TAG = TypeTag<R, T...>::value;

  Union() noexcept : tag_(-1) {}

  template <typename U, typename F = __detail::resolvedType<U, T...>>
  Union(U &&value) noexcept : tag_(TAG<F>) { // NOLINT
    this->value_.obtain(std::forward<U>(value));
  }

  Union(Union &&value) noexcept : tag_(value.tag()) {
    __detail::move(value.value(), this->tag(), this->value());
    value.tag_ = -1;
  }

  Union(const Union &value) : tag_(value.tag()) {
    __detail::copy(value.value(), this->tag(), this->value());
  }

  ~Union() { __detail::destroy(this->value(), this->tag()); }

  Union &operator=(Union &&value) noexcept {
    if (this != std::addressof(value)) {
      this->moveAssign(value);
    }
    return *this;
  }

  Union &operator=(const Union &value) {
    if (this != std::addressof(value)) {
      this->copyAssign(value);
    }
    return *this;
  }

  StorageType &value() { return this->value_; }

  const StorageType &value() const { return this->value_; }

  int tag() const { return this->tag_; }

  bool hasValue() const { return this->tag() > -1; }

private:
  void moveAssign(Union &value) noexcept {
    __detail::destroy(this->value(), this->tag());
    __detail::move(value.value(), value.tag(), this->value());
    this->tag_ = value.tag();
    value.tag_ = -1;
  }

  void copyAssign(const Union &value) {
    __detail::destroy(this->value(), this->tag());
    __detail::copy(value.value(), value.tag(), this->value());
    this->tag_ = value.tag();
  }
};

template <typename T, typename... R>
inline bool is(const Union<R...> &value) {
  using Tag = TypeTag<T, R...>;
  static_assert(Tag::value > -1, "invalid type");
  return value.tag() == Tag::value;
}

template <typename T, typename... R>
inline T &get(Union<R...> &value) {
  assert(is<T>(value));
  return get<T>(value.value());
}

template <typename T, typename... R>
inline const T &get(const Union<R...> &value) {
  assert(is<T>(value));
  return get<T>(value.value());
}

// ######################
// ##     Optional     ##
// ######################

template <typename T>
class OptionalBase : public Union<T> {
public:
  using base_type = Union<T>;

  OptionalBase() noexcept : Union<T>() {}

  OptionalBase(T &&value) noexcept : Union<T>(std::forward<T>(value)) {} // NOLINT

  T &unwrap() noexcept { return get<T>(*this); }

  const T &unwrap() const noexcept { return get<T>(*this); }
};

template <typename... T>
class OptionalBase<Union<T...>> : public Union<T...> {
public:
  using base_type = Union<T...>;

  OptionalBase() noexcept : Union<T...>() {}

  template <typename U>
  OptionalBase(U &&value) noexcept : Union<T...>(std::forward<U>(value)) {} // NOLINT

  Union<T...> &unwrap() noexcept { return static_cast<base_type &>(*this); }

  const Union<T...> &unwrap() const noexcept { return static_cast<const base_type &>(*this); }
};

template <typename T>
struct OptFlattener {
  using type = T;
};

template <typename T>
struct OptFlattener<OptionalBase<T>> : OptFlattener<T> {};

template <typename T>
using Optional = OptionalBase<typename OptFlattener<T>::type>;

// ####################
// ##     Result     ##
// ####################

template <typename T>
struct OkHolder {
  T value;

  explicit OkHolder(T &&value) : value(std::move(value)) {}
  explicit OkHolder(const T &value) : value(value) {}
};

template <typename E>
struct ErrHolder {
  E value;

  explicit ErrHolder(E &&value) : value(std::move(value)) {}
  explicit ErrHolder(const E &value) : value(value) {}
};

template <typename T, typename Decayed = typename std::decay<T>::type>
OkHolder<Decayed> Ok(T &&value) {
  return OkHolder<Decayed>(std::forward<T>(value));
}

template <typename E, typename Decayed = typename std::decay<E>::type>
ErrHolder<Decayed> Err(E &&value) {
  return ErrHolder<Decayed>(std::forward<E>(value));
}

template <typename T, typename E>
class Result : public Union<T, E> {
public:
  NON_COPYABLE(Result);

  Result() = delete;

  template <typename T0>
  Result(OkHolder<T0> &&okHolder) noexcept : Union<T, E>(std::move(okHolder.value)) {} // NOLINT

  Result(ErrHolder<E> &&errHolder) noexcept : Union<T, E>(std::move(errHolder.value)) {} // NOLINT

  Result(Result &&result) noexcept = default;

  ~Result() = default;

  Result &operator=(Result &&result) noexcept = default;

  explicit operator bool() const { return is<T>(*this); }

  T &asOk() { return get<T>(*this); }

  E &asErr() { return get<E>(*this); }

  const T &asOk() const { return get<T>(*this); }

  const E &asErr() const { return get<E>(*this); }

  T &&take() && { return std::move(this->asOk()); }

  E &&takeError() && { return std::move(this->asErr()); }
};

END_MISC_LIB_NAMESPACE_DECL

#endif // MISC_LIB_RESULT_HPP
<|endoftext|>


<commit_before>#pragma once

#include "handle_map.hpp"

namespace helene
{
template <class LabelType, LabelType Label, class T>
struct column_description
{
};

namespace detail
{
template <class LabelType, LabelType Label, class... ColumnDescriptions>
struct type_by_label;

template <class LabelType,
          LabelType Label,
          LabelType FirstLabel,
          LabelType... RestLabels,
          class FirstType,
          class... RestTypes>
struct type_by_label<LabelType,
                     Label,
                     column_description<LabelType, FirstLabel, FirstType>,
                     column_description<LabelType, RestLabels, RestTypes>...>
    : type_by_label<LabelType,
                    Label,
                    column_description<LabelType, RestLabels, RestTypes>...>
{
};

template <class LabelType,
          LabelType Label,
          LabelType... RestLabels,
          class FirstType,
          class... RestTypes>
struct type_by_label<LabelType,
                     Label,
                     column_description<LabelType, Label, FirstType>,
                     column_description<LabelType, RestLabels, RestTypes>...>
{
    typedef FirstType type;
};

template <class LabelType, LabelType Label, class... ColumnDescriptions>
using type_by_label_t =
    typename type_by_label<LabelType, Label, ColumnDescriptions...>::type;
}; // namespace detail

template <class ColumnDescription>
class column;

template <class LabelType, LabelType Label, class T>
class column<column_description<LabelType, Label, T>>
{
protected:
    handle_map<T> data_;
};

template <class LabelType, class... ColumnDescriptions>
class table;

template <class LabelType, LabelType... Labels, class... Ts>
class table<LabelType, column_description<LabelType, Labels, Ts>...>
    : public column<column_description<LabelType, Labels, Ts>>...
{
    template <LabelType Label>
    using get_type_t =
        detail::type_by_label_t<LabelType,
                                Label,
                                column_description<LabelType, Labels, Ts>...>;

    template <LabelType Label>
    using get_column_t =
        column<column_description<LabelType, Label, get_type_t<Label>>>;

public:
    typedef std::size_t row_index_type;

public:
    row_index_type
    insert_row(const Ts&... elms)
    {
        row_index_type dummy[] = {
            column<column_description<LabelType, Labels, Ts>>::data_.insert(
                elms)...};

        return dummy[0];
    }

    template <LabelType Label>
    get_type_t<Label>&
    get(row_index_type n)
    {
        return get_column_t<Label>::data_[n];
    }
};

} // namespace helene
<commit_msg>Add const overload for 'get'. 	modified:   include/ecs.hpp<commit_after>#pragma once

#include "handle_map.hpp"

namespace helene
{
template <class LabelType, LabelType Label, class T>
struct column_description
{
};

namespace detail
{
template <class LabelType, LabelType Label, class... ColumnDescriptions>
struct type_by_label;

template <class LabelType,
          LabelType Label,
          LabelType FirstLabel,
          LabelType... RestLabels,
          class FirstType,
          class... RestTypes>
struct type_by_label<LabelType,
                     Label,
                     column_description<LabelType, FirstLabel, FirstType>,
                     column_description<LabelType, RestLabels, RestTypes>...>
    : type_by_label<LabelType,
                    Label,
                    column_description<LabelType, RestLabels, RestTypes>...>
{
};

template <class LabelType,
          LabelType Label,
          LabelType... RestLabels,
          class FirstType,
          class... RestTypes>
struct type_by_label<LabelType,
                     Label,
                     column_description<LabelType, Label, FirstType>,
                     column_description<LabelType, RestLabels, RestTypes>...>
{
    typedef FirstType type;
};

template <class LabelType, LabelType Label, class... ColumnDescriptions>
using type_by_label_t =
    typename type_by_label<LabelType, Label, ColumnDescriptions...>::type;
}; // namespace detail

template <class ColumnDescription>
class column;

template <class LabelType, LabelType Label, class T>
class column<column_description<LabelType, Label, T>>
{
protected:
    handle_map<T> data_;
};

template <class LabelType, class... ColumnDescriptions>
class table;

template <class LabelType, LabelType... Labels, class... Ts>
class table<LabelType, column_description<LabelType, Labels, Ts>...>
    : public column<column_description<LabelType, Labels, Ts>>...
{
    template <LabelType Label>
    using get_type_t =
        detail::type_by_label_t<LabelType,
                                Label,
                                column_description<LabelType, Labels, Ts>...>;

    template <LabelType Label>
    using get_column_t =
        column<column_description<LabelType, Label, get_type_t<Label>>>;

public:
    typedef std::size_t row_index_type;

public:
    row_index_type
    insert_row(const Ts&... elms)
    {
        row_index_type dummy[] = {
            column<column_description<LabelType, Labels, Ts>>::data_.insert(
                elms)...};

        return dummy[0];
    }

    template <LabelType Label>
    get_type_t<Label>&
    get(row_index_type n)
    {
        return get_column_t<Label>::data_[n];
    }

    template <LabelType Label>
    const get_type_t<Label>&
    get(row_index_type n) const
    {
        return get_column_t<Label>::data_[n];
    }
};

} // namespace helene
<|endoftext|>


<commit_before>#include <libmesh/libmesh.h>
#include <libmesh/mesh.h>
#include <libmesh/elem.h>
#include <libmesh/mesh_generation.h>
#include <libmesh/mesh_refinement.h>

#include <libmesh/exodusII_io.h>

#include "test_comm.h"
#include "libmesh_cppunit.h"

#include <array>
#include <cstddef> // std::ptrdiff_t

using namespace libMesh;

class ExtraIntegersTest : public CppUnit::TestCase
{
  /**
   * The goal of this test is to verify the ability to add extra
   * integer storage to a Mesh object, then set and query those extra
   * integers in the objects within the mesh.
   */
public:
  CPPUNIT_TEST_SUITE( ExtraIntegersTest );

  CPPUNIT_TEST( testExtraIntegersEdge2 );
  CPPUNIT_TEST( testExtraIntegersTri6 );

#ifdef LIBMESH_HAVE_EXODUS_API
  CPPUNIT_TEST( testExtraIntegersExodusReading );
#endif
#if defined(LIBMESH_HAVE_EXODUS_API) && defined(LIBMESH_ENABLE_EXCEPTIONS)
  CPPUNIT_TEST( testBadExtraIntegersExodusReading );
#endif

#ifdef LIBMESH_HAVE_XDR
  CPPUNIT_TEST( testExtraIntegersCheckpointEdge3 );
  CPPUNIT_TEST( testExtraIntegersCheckpointHex8 );
#endif

  CPPUNIT_TEST_SUITE_END();

protected:
  // Helper functions called by the test implementations, saves a few lines of code.
  std::array<unsigned int, 6>
    build_mesh(Mesh & mesh, ElemType elem_type, unsigned int n_elem_per_side)
  {
    // Request some extra integers before building
    unsigned int i1 = mesh.add_elem_integer("i1");
    unsigned int r1 = mesh.add_elem_datum<Real>("r1");
    unsigned int ni1 = mesh.add_node_integer("ni1");
    unsigned int ni2 = mesh.add_node_integer("ni2");
    unsigned int nr1 = mesh.add_node_datum<Real>("nr1");
    unsigned int nr2 = mesh.add_node_datum<Real>("nr2");

    const std::unique_ptr<Elem> test_elem = Elem::build(elem_type);
    const unsigned int ymax = test_elem->dim() > 1;
    const unsigned int zmax = test_elem->dim() > 2;
    const unsigned int ny = ymax * n_elem_per_side;
    const unsigned int nz = zmax * n_elem_per_side;

    MeshTools::Generation::build_cube (mesh,
                                       n_elem_per_side,
                                       ny,
                                       nz,
                                       0., 1.,
                                       0., ymax,
                                       0., zmax,
                                       elem_type);
    return {i1, r1, ni1, ni2, nr1, nr2};
  }

  void test_and_set_initial_data
    (Mesh & mesh, std::array<unsigned int, 6> ini)
  {
    const unsigned int i1 = ini[0],
                       r1 = ini[1],
                       ni1 = ini[2],
                       ni2 = ini[3],
                       nr1 = ini[4];
    for (const auto & elem : mesh.element_ptr_range())
      {
        const unsigned int expected_extra_ints =
          2 + (sizeof(Real)-1)/sizeof(dof_id_type);
        CPPUNIT_ASSERT_EQUAL(elem->n_extra_integers(), expected_extra_ints);
        CPPUNIT_ASSERT_EQUAL(elem->get_extra_integer(i1), DofObject::invalid_id);
        elem->set_extra_integer(i1, dof_id_type(elem->point(0)(0)*100));
        CPPUNIT_ASSERT_EQUAL(elem->get_extra_integer(i1), dof_id_type(elem->point(0)(0)*100));
        elem->set_extra_datum<Real>(r1, elem->point(0)(0)*1000);
        CPPUNIT_ASSERT_EQUAL(elem->get_extra_datum<Real>(r1), elem->point(0)(0)*1000);
      }

    for (const auto & node : mesh.node_ptr_range())
      {
        const unsigned int expected_extra_ints =
          4 + (sizeof(Real)-1)/sizeof(dof_id_type)*2;
        CPPUNIT_ASSERT_EQUAL(node->n_extra_integers(), expected_extra_ints);
        CPPUNIT_ASSERT_EQUAL(node->get_extra_integer(ni1), DofObject::invalid_id);
        CPPUNIT_ASSERT_EQUAL(node->get_extra_integer(ni2), DofObject::invalid_id);
        node->set_extra_datum<Real>(nr1, (*node)(0)*1000);
        CPPUNIT_ASSERT_EQUAL(node->get_extra_datum<Real>(nr1), (*node)(0)*1000);
      }

  }

  void test_final_integers(Mesh & mesh, unsigned int i1)
  {
    // Make sure old (level 0) elements have the same integers and any new
    // elements have inherited their ancestors' settings
    for (const auto & elem : mesh.element_ptr_range())
      {
        const Elem * top_parent = elem;
#ifdef LIBMESH_ENABLE_AMR
        top_parent = elem->top_parent();

        if (!elem->level())
#endif
          for (auto & node : elem->node_ref_range())
            {
              const unsigned int expected_extra_ints =
                4 + (sizeof(Real)-1)/sizeof(dof_id_type)*2;
              CPPUNIT_ASSERT_EQUAL(node.n_extra_integers(), expected_extra_ints);
            }

        const unsigned int expected_extra_ints =
          2 + (sizeof(Real)-1)/sizeof(dof_id_type);
        CPPUNIT_ASSERT_EQUAL(elem->n_extra_integers(), expected_extra_ints);
        CPPUNIT_ASSERT_EQUAL(elem->get_extra_integer(i1), dof_id_type(top_parent->point(0)(0)*100));
      }
  }

  void test_helper(ElemType elem_type, unsigned int n_elem_per_side)
  {
    Mesh mesh(*TestCommWorld);

    std::array<unsigned int, 6> ini = build_mesh(mesh, elem_type, n_elem_per_side);
    const unsigned int i1 = ini[0],
                       ni1 = ini[2],
                       ni2 = ini[3];

    test_and_set_initial_data(mesh, ini);

    // Force (in parallel) a different partitioning - we'll simply put
    // everything on rank 0, which hopefully is not what our default
    // partitioner did!
    mesh.partition(1);

    CPPUNIT_ASSERT_EQUAL(i1, mesh.add_elem_integer("i1"));
    CPPUNIT_ASSERT_EQUAL(ni1, mesh.add_node_integer("ni1"));
    CPPUNIT_ASSERT_EQUAL(ni2, mesh.add_node_integer("ni2"));

    // Make sure we didn't screw up any extra integers thereby.
    test_final_integers(mesh, i1);

#ifdef LIBMESH_ENABLE_AMR
    MeshRefinement mr(mesh);
    mr.uniformly_refine(1);

    test_final_integers(mesh, i1);
#endif
  }

  void checkpoint_helper(ElemType elem_type, unsigned int n_elem_per_side, bool binary)
  {
    Mesh mesh(*TestCommWorld);

    std::array<unsigned int, 6> ini = build_mesh(mesh, elem_type, n_elem_per_side);
    const unsigned int i1 = ini[0], ni1 = ini[2], ni2 = ini[3];

    test_and_set_initial_data(mesh, ini);

    const std::string filename =
      std::string("extra_integers.cp") + (binary ? "r" : "a");

    mesh.write(filename);

    TestCommWorld->barrier();

    Mesh mesh2(*TestCommWorld);

    mesh2.read(filename);

    // Make sure the integers got transferred to the second mesh
    CPPUNIT_ASSERT_EQUAL(i1, mesh2.add_elem_integer("i1"));
    CPPUNIT_ASSERT_EQUAL(ni1, mesh2.add_node_integer("ni1"));
    CPPUNIT_ASSERT_EQUAL(ni2, mesh2.add_node_integer("ni2"));

    // Make sure we didn't screw up any extra integers thereby.
    test_final_integers(mesh2, i1);
  }

public:
  void setUp() {}

  void tearDown() {}

  void testExtraIntegersEdge2() { test_helper(EDGE2, 5); }

  void testExtraIntegersTri6() { test_helper(TRI6, 4); }

  void testExtraIntegersCheckpointEdge3() { checkpoint_helper(EDGE3, 5, false); }

  void testExtraIntegersCheckpointHex8() { checkpoint_helper(HEX8, 2, true); }

#ifdef LIBMESH_HAVE_EXODUS_API
  void testExtraIntegersExodusReading()
  {
    Mesh mesh(*TestCommWorld);
    mesh.allow_renumbering(false);

    // This 3-by-3 mesh contains the following element integers:
    std::vector<std::ptrdiff_t> material_id = {0, -1, 2,
                                               1,  3, 450359962,
                                               2,  3, 450359963};
    const std::string filename = "meshes/good_32bit_elem_integers.e";
    ExodusII_IO exreader(mesh);
    exreader.set_extra_integer_vars({"material_id"});
    exreader.read(filename);

    // Test that the ExodusII_IO::get_{elem,node}_num_map() APIs give
    // us something sensible.  Note: this is unrelated to reading
    // extra integers, but, in my opinion, it does not warrant its own
    // standalone test either.
    const auto & elem_num_map = exreader.get_elem_num_map();
    const auto & node_num_map = exreader.get_node_num_map();

    // This mesh has trivial elem_num_map and node_num_map
    CPPUNIT_ASSERT_EQUAL(int(elem_num_map.size()), 9);
    CPPUNIT_ASSERT_EQUAL(int(node_num_map.size()), 16);
    for (int i=0; i != 9; ++i)
      CPPUNIT_ASSERT_EQUAL(elem_num_map[i], i+1);
    for (int i=0; i != 16; ++i)
      CPPUNIT_ASSERT_EQUAL(node_num_map[i], i+1);

    CPPUNIT_ASSERT(mesh.has_elem_integer("material_id"));
    unsigned int int_idx = mesh.get_elem_integer_index("material_id");
    for (dof_id_type i=0; i != 9; ++i)
      {
        Elem * elem = mesh.query_elem_ptr(i);
        if (!elem)
          continue;
        if (material_id[i] == -1)
          CPPUNIT_ASSERT_EQUAL(DofObject::invalid_id, elem->get_extra_integer(int_idx));
        else
          CPPUNIT_ASSERT_EQUAL(dof_id_type(material_id[i]), elem->get_extra_integer(int_idx));
      }
  }
#endif

#if defined(LIBMESH_HAVE_EXODUS_API) && defined(LIBMESH_ENABLE_EXCEPTIONS)
  void testBadExtraIntegersExodusReading()
  {
    Mesh mesh(*TestCommWorld);
    /*
     This 3-by-3 mesh contains the following element integers:
     material_id = '0 -1    (unsigned long long)(-2) (bad)
                    1  3    4503599627370496
                    2  3    4503599627370497'
     Real(-2) != Real(-1) (used for invalid_id), so we can tell
     this is an error.
    */
    const std::string filename = "meshes/bad_64bit_elem_integers.e";
    ExodusII_IO exreader(mesh);
    exreader.set_extra_integer_vars({"material_id"});
    CPPUNIT_ASSERT_THROW_MESSAGE("Bad elem integer not detected",
                                 exreader.read(filename),
                                 libMesh::LogicError);
  }
#endif
};

CPPUNIT_TEST_SUITE_REGISTRATION( ExtraIntegersTest );
<commit_msg>Test that all_*_order() preserves extra integers<commit_after>#include <libmesh/libmesh.h>
#include <libmesh/mesh.h>
#include <libmesh/elem.h>
#include <libmesh/mesh_generation.h>
#include <libmesh/mesh_refinement.h>

#include <libmesh/exodusII_io.h>

#include "test_comm.h"
#include "libmesh_cppunit.h"

#include <array>
#include <cstddef> // std::ptrdiff_t

using namespace libMesh;

class ExtraIntegersTest : public CppUnit::TestCase
{
  /**
   * The goal of this test is to verify the ability to add extra
   * integer storage to a Mesh object, then set and query those extra
   * integers in the objects within the mesh.
   */
public:
  CPPUNIT_TEST_SUITE( ExtraIntegersTest );

  CPPUNIT_TEST( testExtraIntegersEdge2 );
  CPPUNIT_TEST( testExtraIntegersTri6 );

#ifdef LIBMESH_HAVE_EXODUS_API
  CPPUNIT_TEST( testExtraIntegersExodusReading );
#endif
#if defined(LIBMESH_HAVE_EXODUS_API) && defined(LIBMESH_ENABLE_EXCEPTIONS)
  CPPUNIT_TEST( testBadExtraIntegersExodusReading );
#endif

#ifdef LIBMESH_HAVE_XDR
  CPPUNIT_TEST( testExtraIntegersCheckpointEdge3 );
  CPPUNIT_TEST( testExtraIntegersCheckpointHex8 );
#endif

  CPPUNIT_TEST_SUITE_END();

protected:
  // Helper functions called by the test implementations, saves a few lines of code.
  std::array<unsigned int, 6>
    build_mesh(Mesh & mesh, ElemType elem_type, unsigned int n_elem_per_side)
  {
    // Request some extra integers before building
    unsigned int i1 = mesh.add_elem_integer("i1");
    unsigned int r1 = mesh.add_elem_datum<Real>("r1");
    unsigned int ni1 = mesh.add_node_integer("ni1");
    unsigned int ni2 = mesh.add_node_integer("ni2");
    unsigned int nr1 = mesh.add_node_datum<Real>("nr1");
    unsigned int nr2 = mesh.add_node_datum<Real>("nr2");

    const std::unique_ptr<Elem> test_elem = Elem::build(elem_type);
    const unsigned int ymax = test_elem->dim() > 1;
    const unsigned int zmax = test_elem->dim() > 2;
    const unsigned int ny = ymax * n_elem_per_side;
    const unsigned int nz = zmax * n_elem_per_side;

    MeshTools::Generation::build_cube (mesh,
                                       n_elem_per_side,
                                       ny,
                                       nz,
                                       0., 1.,
                                       0., ymax,
                                       0., zmax,
                                       elem_type);
    return {i1, r1, ni1, ni2, nr1, nr2};
  }

  void test_and_set_initial_data
    (Mesh & mesh, std::array<unsigned int, 6> ini)
  {
    const unsigned int i1 = ini[0],
                       r1 = ini[1],
                       ni1 = ini[2],
                       ni2 = ini[3],
                       nr1 = ini[4];
    for (const auto & elem : mesh.element_ptr_range())
      {
        const unsigned int expected_extra_ints =
          2 + (sizeof(Real)-1)/sizeof(dof_id_type);
        CPPUNIT_ASSERT_EQUAL(elem->n_extra_integers(), expected_extra_ints);
        CPPUNIT_ASSERT_EQUAL(elem->get_extra_integer(i1), DofObject::invalid_id);
        elem->set_extra_integer(i1, dof_id_type(elem->point(0)(0)*100));
        CPPUNIT_ASSERT_EQUAL(elem->get_extra_integer(i1), dof_id_type(elem->point(0)(0)*100));
        elem->set_extra_datum<Real>(r1, elem->point(0)(0)*1000);
        CPPUNIT_ASSERT_EQUAL(elem->get_extra_datum<Real>(r1), elem->point(0)(0)*1000);
      }

    for (const auto & node : mesh.node_ptr_range())
      {
        const unsigned int expected_extra_ints =
          4 + (sizeof(Real)-1)/sizeof(dof_id_type)*2;
        CPPUNIT_ASSERT_EQUAL(node->n_extra_integers(), expected_extra_ints);
        CPPUNIT_ASSERT_EQUAL(node->get_extra_integer(ni1), DofObject::invalid_id);
        CPPUNIT_ASSERT_EQUAL(node->get_extra_integer(ni2), DofObject::invalid_id);
        node->set_extra_datum<Real>(nr1, (*node)(0)*1000);
        CPPUNIT_ASSERT_EQUAL(node->get_extra_datum<Real>(nr1), (*node)(0)*1000);
      }

  }

  void test_final_integers(Mesh & mesh, unsigned int i1)
  {
    // Make sure old (level 0) elements have the same integers and any new
    // elements have inherited their ancestors' settings
    for (const auto & elem : mesh.element_ptr_range())
      {
        const Elem * top_parent = elem;
#ifdef LIBMESH_ENABLE_AMR
        top_parent = elem->top_parent();

        if (!elem->level())
#endif
          for (auto & node : elem->node_ref_range())
            {
              const unsigned int expected_extra_ints =
                4 + (sizeof(Real)-1)/sizeof(dof_id_type)*2;
              CPPUNIT_ASSERT_EQUAL(node.n_extra_integers(), expected_extra_ints);
            }

        const unsigned int expected_extra_ints =
          2 + (sizeof(Real)-1)/sizeof(dof_id_type);
        CPPUNIT_ASSERT_EQUAL(elem->n_extra_integers(), expected_extra_ints);
        CPPUNIT_ASSERT_EQUAL(elem->get_extra_integer(i1), dof_id_type(top_parent->point(0)(0)*100));
      }
  }

  void test_helper(ElemType elem_type, unsigned int n_elem_per_side)
  {
    Mesh mesh(*TestCommWorld);

    std::array<unsigned int, 6> ini = build_mesh(mesh, elem_type, n_elem_per_side);
    const unsigned int i1 = ini[0],
                       ni1 = ini[2],
                       ni2 = ini[3];

    test_and_set_initial_data(mesh, ini);

    // Force (in parallel) a different partitioning - we'll simply put
    // everything on rank 0, which hopefully is not what our default
    // partitioner did!
    mesh.partition(1);

    CPPUNIT_ASSERT_EQUAL(i1, mesh.add_elem_integer("i1"));
    CPPUNIT_ASSERT_EQUAL(ni1, mesh.add_node_integer("ni1"));
    CPPUNIT_ASSERT_EQUAL(ni2, mesh.add_node_integer("ni2"));

    // Make sure we didn't screw up any extra integers thereby.
    test_final_integers(mesh, i1);

    // Try out switching to 2nd order and back
    mesh.all_second_order();

    test_final_integers(mesh, i1);

    mesh.all_first_order();

    test_final_integers(mesh, i1);

    // And try refining if we can
#ifdef LIBMESH_ENABLE_AMR
    MeshRefinement mr(mesh);
    mr.uniformly_refine(1);

    test_final_integers(mesh, i1);
#endif
  }

  void checkpoint_helper(ElemType elem_type, unsigned int n_elem_per_side, bool binary)
  {
    Mesh mesh(*TestCommWorld);

    std::array<unsigned int, 6> ini = build_mesh(mesh, elem_type, n_elem_per_side);
    const unsigned int i1 = ini[0], ni1 = ini[2], ni2 = ini[3];

    test_and_set_initial_data(mesh, ini);

    const std::string filename =
      std::string("extra_integers.cp") + (binary ? "r" : "a");

    mesh.write(filename);

    TestCommWorld->barrier();

    Mesh mesh2(*TestCommWorld);

    mesh2.read(filename);

    // Make sure the integers got transferred to the second mesh
    CPPUNIT_ASSERT_EQUAL(i1, mesh2.add_elem_integer("i1"));
    CPPUNIT_ASSERT_EQUAL(ni1, mesh2.add_node_integer("ni1"));
    CPPUNIT_ASSERT_EQUAL(ni2, mesh2.add_node_integer("ni2"));

    // Make sure we didn't screw up any extra integers thereby.
    test_final_integers(mesh2, i1);
  }

public:
  void setUp() {}

  void tearDown() {}

  void testExtraIntegersEdge2() { test_helper(EDGE2, 5); }

  void testExtraIntegersTri6() { test_helper(TRI6, 4); }

  void testExtraIntegersCheckpointEdge3() { checkpoint_helper(EDGE3, 5, false); }

  void testExtraIntegersCheckpointHex8() { checkpoint_helper(HEX8, 2, true); }

#ifdef LIBMESH_HAVE_EXODUS_API
  void testExtraIntegersExodusReading()
  {
    Mesh mesh(*TestCommWorld);
    mesh.allow_renumbering(false);

    // This 3-by-3 mesh contains the following element integers:
    std::vector<std::ptrdiff_t> material_id = {0, -1, 2,
                                               1,  3, 450359962,
                                               2,  3, 450359963};
    const std::string filename = "meshes/good_32bit_elem_integers.e";
    ExodusII_IO exreader(mesh);
    exreader.set_extra_integer_vars({"material_id"});
    exreader.read(filename);

    // Test that the ExodusII_IO::get_{elem,node}_num_map() APIs give
    // us something sensible.  Note: this is unrelated to reading
    // extra integers, but, in my opinion, it does not warrant its own
    // standalone test either.
    const auto & elem_num_map = exreader.get_elem_num_map();
    const auto & node_num_map = exreader.get_node_num_map();

    // This mesh has trivial elem_num_map and node_num_map
    CPPUNIT_ASSERT_EQUAL(int(elem_num_map.size()), 9);
    CPPUNIT_ASSERT_EQUAL(int(node_num_map.size()), 16);
    for (int i=0; i != 9; ++i)
      CPPUNIT_ASSERT_EQUAL(elem_num_map[i], i+1);
    for (int i=0; i != 16; ++i)
      CPPUNIT_ASSERT_EQUAL(node_num_map[i], i+1);

    CPPUNIT_ASSERT(mesh.has_elem_integer("material_id"));
    unsigned int int_idx = mesh.get_elem_integer_index("material_id");
    for (dof_id_type i=0; i != 9; ++i)
      {
        Elem * elem = mesh.query_elem_ptr(i);
        if (!elem)
          continue;
        if (material_id[i] == -1)
          CPPUNIT_ASSERT_EQUAL(DofObject::invalid_id, elem->get_extra_integer(int_idx));
        else
          CPPUNIT_ASSERT_EQUAL(dof_id_type(material_id[i]), elem->get_extra_integer(int_idx));
      }
  }
#endif

#if defined(LIBMESH_HAVE_EXODUS_API) && defined(LIBMESH_ENABLE_EXCEPTIONS)
  void testBadExtraIntegersExodusReading()
  {
    Mesh mesh(*TestCommWorld);
    /*
     This 3-by-3 mesh contains the following element integers:
     material_id = '0 -1    (unsigned long long)(-2) (bad)
                    1  3    4503599627370496
                    2  3    4503599627370497'
     Real(-2) != Real(-1) (used for invalid_id), so we can tell
     this is an error.
    */
    const std::string filename = "meshes/bad_64bit_elem_integers.e";
    ExodusII_IO exreader(mesh);
    exreader.set_extra_integer_vars({"material_id"});
    CPPUNIT_ASSERT_THROW_MESSAGE("Bad elem integer not detected",
                                 exreader.read(filename),
                                 libMesh::LogicError);
  }
#endif
};

CPPUNIT_TEST_SUITE_REGISTRATION( ExtraIntegersTest );
<|endoftext|>


<commit_before>#include "client.h"
#include "tests/test.h"
#include "webrequester.h"
#include "measurement/ping/ping.h"
#include "connectiontester.h"
#include "network/requests/requests.h"
#include "scheduler/scheduler.h"
#include "scheduler/schedulermodel.h"
#include "report/reportscheduler.h"
#include "report/reportmodel.h"
#include "task/taskexecutor.h"
#include "controller/reportcontroller.h"
#include "settings.h"
#include "storage/storagepaths.h"

#include "qtquick2applicationviewer.h"

#include <QGuiApplication>
#include <QQuickView>
#include <QQmlContext>
#include <QQmlEngine>
#include <QtQml>
#include <QUrl>

#ifdef Q_OS_ANDROID
#include "statusbarhelper.h"
#include "androidimageprovider.h"
#include "androidprocessmodel.h"
#elif !defined(Q_OS_IOS)
#include <QApplication>
#include "desktopstatusbarhelper.h"
#endif // Q_OS_ANDROID

#ifdef Q_OS_OSX
#include <macprocessmodel.h>
#include <macimageprovider.h>
#endif

#define HAVE_BREAKPAD
#ifdef HAVE_BREAKPAD
#include "crashhandler.h"
#endif

#ifdef Q_OS_IOS
#include <QtPlugin>
Q_IMPORT_PLUGIN(QtQuick2Plugin)
Q_IMPORT_PLUGIN(QtQuick2WindowPlugin)
Q_IMPORT_PLUGIN(QtQuickControlsPlugin)
#endif

class Time : public QObject
{
    Q_OBJECT

public:
    Time(QObject* parent = 0) : QObject(parent) {
    }

    Q_INVOKABLE int restart() {
        return time.restart();
    }

    Q_INVOKABLE int elapsed() const {
        return time.elapsed();
    }

protected:
    QTime time;
};

int main(int argc, char* argv[])
{
    QCoreApplication::setOrganizationDomain("de.hsaugsburg.informatik");
    QCoreApplication::setOrganizationName("HS Augsburg");
    QCoreApplication::setApplicationName("mPlaneClient");

#if defined(Q_OS_ANDROID) || defined(Q_OS_IOS)
    QGuiApplication app(argc, argv);
#else
    QApplication app(argc, argv);
    app.setQuitOnLastWindowClosed(true);
#endif

#ifdef HAVE_BREAKPAD
    QDir crashdumpDir = StoragePaths().crashDumpDirectory();
    if (!crashdumpDir.exists()) {
        QDir upper = crashdumpDir;
        upper.cdUp();

        if (!upper.mkdir(crashdumpDir.dirName())) {
            qDebug() << "Failed to create crashdump directory";
        }
    }

    CrashHandler crashHandler;
    crashHandler.init(crashdumpDir.absolutePath());
#endif // HAVE_BREAKPAD

    qmlRegisterUncreatableType<AbstractTest>("mplane", 1, 0, "AbstractTest", "abstract class");
    qmlRegisterUncreatableType<Client>("mplane", 1, 0, "Client", "This is a singleton");

    qmlRegisterUncreatableType<Scheduler>("mplane", 1, 0, "Scheduler", "uncreatable type");
    qmlRegisterType<SchedulerModel>("mplane", 1, 0, "SchedulerModel");

    qmlRegisterUncreatableType<TaskExecutor>("mplane", 1, 0, "TaskExecutor", "uncreatable type");
    qmlRegisterUncreatableType<ReportController>("mplane", 1, 0, "ReportController", "uncreatable type");
    qmlRegisterUncreatableType<ReportScheduler>("mplane", 1, 0, "ReportScheduler", "uncreatable type");
    qmlRegisterType<ReportModel>("mplane", 1, 0, "ReportModel");

    // Common objects
    qmlRegisterType<TimingInformation>("mplane", 1, 0, "TimingInformation");

    // Requests
    qmlRegisterUncreatableType<Request>("mplane", 1, 0, "Request", "abstract class");
    qmlRegisterType<RegisterDeviceRequest>("mplane", 1, 0, "RegisterDeviceRequest");
    qmlRegisterType<ManualRequest>("mplane", 1, 0, "TestRequest");
    qmlRegisterType<UserRegisterRequest>("mplane", 1, 0, "UserRegisterRequest");
    qmlRegisterType<LoginRequest>("mplane", 1, 0, "LoginRequest");
    qmlRegisterType<GetConfigRequest>("mplane", 1, 0, "GetConfigRequest");

    // Responses
    qmlRegisterUncreatableType<Response>("mplane", 1, 0, "Response", "abstract class");
    qmlRegisterType<RegisterUserResponse>("mplane", 1, 0, "UserRegisterResponse");
    qmlRegisterType<LoginResponse>("mplane", 1, 0, "LoginResponse");
    qmlRegisterType<RegisterDeviceResponse>("mplane", 1, 0, "RegisterDeviceResponse");
    qmlRegisterType<GetConfigResponse>("mplane", 1, 0, "GetConfigResponse");

    qmlRegisterType<Settings>("mplane", 1, 0, "Settings");
    qmlRegisterType<WebRequester>("mplane", 1, 0, "WebRequester");
    qmlRegisterType<Ping>("mplane", 1, 0, "Ping");
    qmlRegisterType<ConnectionTester>("mplane", 1, 0, "ConnectionTester");
    qmlRegisterType<ConnectionTesterModel>("mplane", 1, 0, "ConnectionTesterModel");
    qmlRegisterType<Time>("mplane", 1, 0, "Time");

#ifdef Q_OS_ANDROID
    qmlRegisterType<AndroidProcessModel>("mplane", 1, 0, "ProcessModel");
#endif // Q_OS_ANDROID

#ifdef Q_OS_OSX
    qmlRegisterType<MacProcessModel>("mplane", 1, 0, "ProcessModel");
#endif // Q_OS_MAC

    QtQuick2ApplicationViewer view;

    QQmlEngine* engine = view.engine();
    // Allow QFileSelector to be automatically applied on qml scripting
    QQmlFileSelector selector;
    engine->setUrlInterceptor(&selector);

    QQmlContext* rootContext = view.rootContext();
    rootContext->setContextProperty("client", Client::instance());
#ifdef Q_OS_ANDROID
    view.engine()->addImageProvider("android", new AndroidImageProvider);
    rootContext->setContextProperty("statusBar", new StatusBarHelper(&view));
#elif defined(Q_OS_IOS)
    // TODO: iOS Code
#else
    rootContext->setContextProperty("statusBar", new DesktopStatusBarHelper(&view));
#endif // Q_OS_ANDROID

#ifdef Q_OS_OSX
    view.engine()->addImageProvider("android", new MacImageProvider);
#endif // Q_OS_MAC

#ifdef Q_OS_IOS
    view.addImportPath(QStringLiteral("imports/qml"));
#endif

    view.setMainQmlFile(QStringLiteral("qml/main.qml"));
    view.showExpanded();

    int returnCode = app.exec();

    // Cleanly shutdown
    Client::instance()->deleteLater();
    QTimer::singleShot(1, &app, SLOT(quit()));
    app.exec();

    return returnCode;
}

#include "main.moc"
<commit_msg>main() has a logger now.<commit_after>#include "client.h"
#include "tests/test.h"
#include "webrequester.h"
#include "measurement/ping/ping.h"
#include "connectiontester.h"
#include "network/requests/requests.h"
#include "scheduler/scheduler.h"
#include "scheduler/schedulermodel.h"
#include "report/reportscheduler.h"
#include "report/reportmodel.h"
#include "task/taskexecutor.h"
#include "controller/reportcontroller.h"
#include "settings.h"
#include "storage/storagepaths.h"
#include "log/logger.h"

#include "qtquick2applicationviewer.h"

#include <QGuiApplication>
#include <QQuickView>
#include <QQmlContext>
#include <QQmlEngine>
#include <QtQml>
#include <QUrl>

#ifdef Q_OS_ANDROID
#include "statusbarhelper.h"
#include "androidimageprovider.h"
#include "androidprocessmodel.h"
#elif !defined(Q_OS_IOS)
#include <QApplication>
#include "desktopstatusbarhelper.h"
#endif // Q_OS_ANDROID

#ifdef Q_OS_OSX
#include <macprocessmodel.h>
#include <macimageprovider.h>
#endif

#define HAVE_BREAKPAD
#ifdef HAVE_BREAKPAD
#include "crashhandler.h"
#endif

#ifdef Q_OS_IOS
#include <QtPlugin>
Q_IMPORT_PLUGIN(QtQuick2Plugin)
Q_IMPORT_PLUGIN(QtQuick2WindowPlugin)
Q_IMPORT_PLUGIN(QtQuickControlsPlugin)
#endif

LOGGER(main)

class Time : public QObject
{
    Q_OBJECT

public:
    Time(QObject* parent = 0) : QObject(parent) {
    }

    Q_INVOKABLE int restart() {
        return time.restart();
    }

    Q_INVOKABLE int elapsed() const {
        return time.elapsed();
    }

protected:
    QTime time;
};

int main(int argc, char* argv[])
{
    QCoreApplication::setOrganizationDomain("de.hsaugsburg.informatik");
    QCoreApplication::setOrganizationName("HS Augsburg");
    QCoreApplication::setApplicationName("mPlaneClient");

#if defined(Q_OS_ANDROID) || defined(Q_OS_IOS)
    QGuiApplication app(argc, argv);
#else
    QApplication app(argc, argv);
    app.setQuitOnLastWindowClosed(true);
#endif

#ifdef HAVE_BREAKPAD
    QDir crashdumpDir = StoragePaths().crashDumpDirectory();
    if (!crashdumpDir.exists()) {
        if (!QDir::root().mkpath(crashdumpDir.absolutePath())) {
            LOG_ERROR(QString("Failed to create crashdump directory: %1").arg(crashdumpDir.absolutePath()));
        } else {
            LOG_INFO("Crashdump directory created");
        }
    }

    CrashHandler crashHandler;
    crashHandler.init(crashdumpDir.absolutePath());
#endif // HAVE_BREAKPAD

    qmlRegisterUncreatableType<AbstractTest>("mplane", 1, 0, "AbstractTest", "abstract class");
    qmlRegisterUncreatableType<Client>("mplane", 1, 0, "Client", "This is a singleton");

    qmlRegisterUncreatableType<Scheduler>("mplane", 1, 0, "Scheduler", "uncreatable type");
    qmlRegisterType<SchedulerModel>("mplane", 1, 0, "SchedulerModel");

    qmlRegisterUncreatableType<TaskExecutor>("mplane", 1, 0, "TaskExecutor", "uncreatable type");
    qmlRegisterUncreatableType<ReportController>("mplane", 1, 0, "ReportController", "uncreatable type");
    qmlRegisterUncreatableType<ReportScheduler>("mplane", 1, 0, "ReportScheduler", "uncreatable type");
    qmlRegisterType<ReportModel>("mplane", 1, 0, "ReportModel");

    // Common objects
    qmlRegisterType<TimingInformation>("mplane", 1, 0, "TimingInformation");

    // Requests
    qmlRegisterUncreatableType<Request>("mplane", 1, 0, "Request", "abstract class");
    qmlRegisterType<RegisterDeviceRequest>("mplane", 1, 0, "RegisterDeviceRequest");
    qmlRegisterType<ManualRequest>("mplane", 1, 0, "TestRequest");
    qmlRegisterType<UserRegisterRequest>("mplane", 1, 0, "UserRegisterRequest");
    qmlRegisterType<LoginRequest>("mplane", 1, 0, "LoginRequest");
    qmlRegisterType<GetConfigRequest>("mplane", 1, 0, "GetConfigRequest");

    // Responses
    qmlRegisterUncreatableType<Response>("mplane", 1, 0, "Response", "abstract class");
    qmlRegisterType<RegisterUserResponse>("mplane", 1, 0, "UserRegisterResponse");
    qmlRegisterType<LoginResponse>("mplane", 1, 0, "LoginResponse");
    qmlRegisterType<RegisterDeviceResponse>("mplane", 1, 0, "RegisterDeviceResponse");
    qmlRegisterType<GetConfigResponse>("mplane", 1, 0, "GetConfigResponse");

    qmlRegisterType<Settings>("mplane", 1, 0, "Settings");
    qmlRegisterType<WebRequester>("mplane", 1, 0, "WebRequester");
    qmlRegisterType<Ping>("mplane", 1, 0, "Ping");
    qmlRegisterType<ConnectionTester>("mplane", 1, 0, "ConnectionTester");
    qmlRegisterType<ConnectionTesterModel>("mplane", 1, 0, "ConnectionTesterModel");
    qmlRegisterType<Time>("mplane", 1, 0, "Time");

#ifdef Q_OS_ANDROID
    qmlRegisterType<AndroidProcessModel>("mplane", 1, 0, "ProcessModel");
#endif // Q_OS_ANDROID

#ifdef Q_OS_OSX
    qmlRegisterType<MacProcessModel>("mplane", 1, 0, "ProcessModel");
#endif // Q_OS_MAC

    QtQuick2ApplicationViewer view;

    QQmlEngine* engine = view.engine();
    // Allow QFileSelector to be automatically applied on qml scripting
    QQmlFileSelector selector;
    engine->setUrlInterceptor(&selector);

    QQmlContext* rootContext = view.rootContext();
    rootContext->setContextProperty("client", Client::instance());
#ifdef Q_OS_ANDROID
    view.engine()->addImageProvider("android", new AndroidImageProvider);
    rootContext->setContextProperty("statusBar", new StatusBarHelper(&view));
#elif defined(Q_OS_IOS)
    // TODO: iOS Code
#else
    rootContext->setContextProperty("statusBar", new DesktopStatusBarHelper(&view));
#endif // Q_OS_ANDROID

#ifdef Q_OS_OSX
    view.engine()->addImageProvider("android", new MacImageProvider);
#endif // Q_OS_MAC

#ifdef Q_OS_IOS
    view.addImportPath(QStringLiteral("imports/qml"));
#endif

    view.setMainQmlFile(QStringLiteral("qml/main.qml"));
    view.showExpanded();

    int returnCode = app.exec();

    // Cleanly shutdown
    Client::instance()->deleteLater();
    QTimer::singleShot(1, &app, SLOT(quit()));
    app.exec();

    return returnCode;
}

#include "main.moc"
<|endoftext|>


<commit_before>#include "AsyncTask.h"
#include "ResourceAPI.h"

#include <tasks_loader.h>

#define THREAD_NUM  (2)

namespace dtex
{

SINGLETON_DEFINITION(AsyncTask);

void load(const char* filepath, void (*unpack)(const void* data, size_t size, void* ud), void* ud)
{
	ResourceAPI::LoadFile(filepath, false, unpack, ud);
}

AsyncTask::AsyncTask()
{
	m_loader = tasks_loader_create(THREAD_NUM);
}

AsyncTask::~AsyncTask()
{
	tasks_loader_release(m_loader);
	free(m_loader);
	m_loader = NULL;
}

void AsyncTask::Load(const std::string& filepath,
					 void (*parser)(const void* data, size_t size, void* ud),
					 void (*release)(void* ud),
					 void* ud)
{
	struct tasks_load_cb params;
	params.load = load;
	params.parser    = parser;
	params.release   = release;
	params.parser_ud = ud;
	tasks_load_file(m_loader, filepath.c_str(), &params, "");
}

void AsyncTask::Update()
{
	tasks_loader_update(m_loader);
}

void AsyncTask::Clear()
{
	// tasks_loader_clear(m_loader);
	tasks_loader_release(m_loader);
	free(m_loader);
	m_loader = tasks_loader_create(THREAD_NUM);
}

bool AsyncTask::IsEmpty() const
{
	return tasks_loader_empty(m_loader);
}

}<commit_msg>fix include<commit_after>#include <stdlib.h>
#include "AsyncTask.h"
#include "ResourceAPI.h"

#include <tasks_loader.h>

#define THREAD_NUM  (2)

namespace dtex
{

SINGLETON_DEFINITION(AsyncTask);

void load(const char* filepath, void (*unpack)(const void* data, size_t size, void* ud), void* ud)
{
	ResourceAPI::LoadFile(filepath, false, unpack, ud);
}

AsyncTask::AsyncTask()
{
	m_loader = tasks_loader_create(THREAD_NUM);
}

AsyncTask::~AsyncTask()
{
	tasks_loader_release(m_loader);
	free(m_loader);
	m_loader = NULL;
}

void AsyncTask::Load(const std::string& filepath,
					 void (*parser)(const void* data, size_t size, void* ud),
					 void (*release)(void* ud),
					 void* ud)
{
	struct tasks_load_cb params;
	params.load = load;
	params.parser    = parser;
	params.release   = release;
	params.parser_ud = ud;
	tasks_load_file(m_loader, filepath.c_str(), &params, "");
}

void AsyncTask::Update()
{
	tasks_loader_update(m_loader);
}

void AsyncTask::Clear()
{
	// tasks_loader_clear(m_loader);
	tasks_loader_release(m_loader);
	free(m_loader);
	m_loader = tasks_loader_create(THREAD_NUM);
}

bool AsyncTask::IsEmpty() const
{
	return tasks_loader_empty(m_loader);
}

}<|endoftext|>


<commit_before>#include "gum/Painting2.h"
#include "gum/GTxt.h"

#include <gtxt_label.h>
#include <painting2/Callback.h>
#include <painting2/Color.h>
#include <painting2/Text.h>

#include <sm_const.h>

namespace
{

void copy_color(gtxt_glyph_color& dst, const pt2::GradientColor& src)
{
	if (src.items.size() == 3)
	{
		dst.mode_type = 2;
		dst.mode.THREE.begin_col.integer = src.items[0].col.ToRGBA();
		dst.mode.THREE.mid_col.integer = src.items[1].col.ToRGBA();
		dst.mode.THREE.end_col.integer = src.items[2].col.ToRGBA();
		dst.mode.THREE.begin_pos = src.items[0].pos;
		dst.mode.THREE.mid_pos = src.items[1].pos;
		dst.mode.THREE.end_pos = src.items[2].pos;
		dst.mode.THREE.angle = src.angle * SM_DEG_TO_RAD;
	}
	else if (src.items.size() == 2)
	{
		dst.mode_type = 1;
		dst.mode.TWO.begin_col.integer = src.items[0].col.ToRGBA();
		dst.mode.TWO.end_col.integer = src.items[1].col.ToRGBA();
		dst.mode.TWO.begin_pos = src.items[0].pos;
		dst.mode.TWO.end_pos = src.items[1].pos;
		dst.mode.TWO.angle = src.angle * SM_DEG_TO_RAD;
	}
	else
	{
		assert(src.items.size() == 1);
		dst.mode_type = 0;
		dst.mode.ONE.color.integer = src.items[0].col.ToRGBA();
	}
}

void draw_text(const pt2::Text& text, const sm::Matrix2D& mat)
{
	auto& tb = text.tb;

	gtxt_label_style ls;

	ls.width   = tb.width;
	ls.height  = tb.height;
	ls.align_h = tb.align_hori;
	ls.align_v = tb.align_vert;
	ls.space_h = tb.space_hori;
	ls.space_v = tb.space_vert;
	ls.overflow = tb.overflow;

	ls.gs.font = tb.font_type;
	ls.gs.font_size = tb.font_size;
	copy_color(ls.gs.font_color, tb.font_color);

	ls.gs.edge      = tb.has_edge;
	ls.gs.edge_size = tb.edge_size;
	copy_color(ls.gs.edge_color, tb.edge_color);

	gum::GTxt::Instance()->Draw(nullptr, ls, mat,
		pt2::Color(255, 255, 255), pt2::Color(0, 0, 0, 0), text.text.c_str(), 0, false);
}

}

namespace gum
{

CU_SINGLETON_DEFINITION(Painting2);

Painting2::Painting2()
{
}

void Painting2::Init()
{
	pt2::Callback::Funs cb;
	cb.draw_text = draw_text;

	pt2::Callback::RegisterCallback(cb);
}

}<commit_msg>[CHANGED] trans angle deg and rad<commit_after>#include "gum/Painting2.h"
#include "gum/GTxt.h"

#include <gtxt_label.h>
#include <painting2/Callback.h>
#include <painting2/Color.h>
#include <painting2/Text.h>

#include <sm_const.h>

namespace
{

void copy_color(gtxt_glyph_color& dst, const pt2::GradientColor& src)
{
	if (src.items.size() == 3)
	{
		dst.mode_type = 2;
		dst.mode.THREE.begin_col.integer = src.items[0].col.ToRGBA();
		dst.mode.THREE.mid_col.integer = src.items[1].col.ToRGBA();
		dst.mode.THREE.end_col.integer = src.items[2].col.ToRGBA();
		dst.mode.THREE.begin_pos = src.items[0].pos;
		dst.mode.THREE.mid_pos = src.items[1].pos;
		dst.mode.THREE.end_pos = src.items[2].pos;
		dst.mode.THREE.angle = src.angle;
	}
	else if (src.items.size() == 2)
	{
		dst.mode_type = 1;
		dst.mode.TWO.begin_col.integer = src.items[0].col.ToRGBA();
		dst.mode.TWO.end_col.integer = src.items[1].col.ToRGBA();
		dst.mode.TWO.begin_pos = src.items[0].pos;
		dst.mode.TWO.end_pos = src.items[1].pos;
		dst.mode.TWO.angle = src.angle;
	}
	else
	{
		assert(src.items.size() == 1);
		dst.mode_type = 0;
		dst.mode.ONE.color.integer = src.items[0].col.ToRGBA();
	}
}

void draw_text(const pt2::Text& text, const sm::Matrix2D& mat)
{
	auto& tb = text.tb;

	gtxt_label_style ls;

	ls.width   = tb.width;
	ls.height  = tb.height;
	ls.align_h = tb.align_hori;
	ls.align_v = tb.align_vert;
	ls.space_h = tb.space_hori;
	ls.space_v = tb.space_vert;
	ls.overflow = tb.overflow;

	ls.gs.font = tb.font_type;
	ls.gs.font_size = tb.font_size;
	copy_color(ls.gs.font_color, tb.font_color);

	ls.gs.edge      = tb.has_edge;
	ls.gs.edge_size = tb.edge_size;
	copy_color(ls.gs.edge_color, tb.edge_color);

	gum::GTxt::Instance()->Draw(nullptr, ls, mat,
		pt2::Color(255, 255, 255), pt2::Color(0, 0, 0, 0), text.text.c_str(), 0, false);
}

}

namespace gum
{

CU_SINGLETON_DEFINITION(Painting2);

Painting2::Painting2()
{
}

void Painting2::Init()
{
	pt2::Callback::Funs cb;
	cb.draw_text = draw_text;

	pt2::Callback::RegisterCallback(cb);
}

}<|endoftext|>


<commit_before>/* mbed Microcontroller Library
 * Copyright (c) 2006-2013 ARM Limited
 *
 * 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 <stdio.h>
#include "ble/BLE.h"
#include "ble/BLEInstanceBase.h"

#if defined(TARGET_OTA_ENABLED)
#include "ble/services/DFUService.h"
#endif

#ifdef YOTTA_CFG_MBED_OS
#include <minar/minar.h>
#endif

#if !defined(YOTTA_CFG_MBED_OS)
#include <mbed_error.h>
#include <toolchain.h>
#endif

#if defined(__GNUC__) && !defined(__CC_ARM)
#define BLE_DEPRECATED_API_USE_BEGIN \
    _Pragma("GCC diagnostic push") \
    _Pragma("GCC diagnostic ignored \"-Wdeprecated-declarations\"")
#elif defined(__CC_ARM)
#define BLE_DEPRECATED_API_USE_BEGIN \
    _Pragma("push") \
    _Pragma("diag_suppress 1361")
#else
#define BLE_DEPRECATED_API_USE_BEGIN
#endif

#if defined(__GNUC__) && !defined(__CC_ARM)
#define BLE_DEPRECATED_API_USE_END \
    _Pragma("GCC diagnostic pop")
#elif defined(__CC_ARM)
#define BLE_DEPRECATED_API_USE_END \
        _Pragma("pop")
#else
#define BLE_DEPRECATED_API_USE_BEGIN
#endif

static const char* error_strings[] = {
    "BLE_ERROR_NONE: No error",
    "BLE_ERROR_BUFFER_OVERFLOW: The requested action would cause a buffer overflow and has been aborted",
    "BLE_ERROR_NOT_IMPLEMENTED: Requested a feature that isn't yet implement or isn't supported by the target HW",
    "BLE_ERROR_PARAM_OUT_OF_RANGE: One of the supplied parameters is outside the valid range",
    "BLE_ERROR_INVALID_PARAM: One of the supplied parameters is invalid",
    "BLE_STACK_BUSY: The stack is busy",
    "BLE_ERROR_INVALID_STATE: Invalid state",
    "BLE_ERROR_NO_MEM: Out of Memory",
    "BLE_ERROR_OPERATION_NOT_PERMITTED: The operation requested is not permitted",
    "BLE_ERROR_INITIALIZATION_INCOMPLETE: The BLE subsystem has not completed its initialisation",
    "BLE_ERROR_ALREADY_INITIALIZED: The BLE system has already been initialised",
    "BLE_ERROR_UNSPECIFIED: Unknown error",
    "BLE_ERROR_INTERNAL_STACK_FAILURE: The platform-specific stack failed"
};

const char* BLE::errorToString(ble_error_t error)
{
    if (error > BLE_ERROR_INTERNAL_STACK_FAILURE) {
        return "Illegal error code";
    }
    return error_strings[error];
}

ble_error_t
BLE::initImplementation(FunctionPointerWithContext<InitializationCompleteCallbackContext*> callback)
{
    ble_error_t err = transport->init(instanceID, callback);
    if (err != BLE_ERROR_NONE) {
        return err;
    }

    /* Platforms enabled for DFU should introduce the DFU Service into
     * applications automatically. */
#if defined(TARGET_OTA_ENABLED)
    static DFUService dfu(*this); // defined static so that the object remains alive
#endif // TARGET_OTA_ENABLED

    return BLE_ERROR_NONE;
}

/**
 * BLE::Instance() and BLE constructor rely upon a static array of initializers
 * to create actual BLE transport instances. A description of these instances
 * and initializers is supposed to be put in some .json file contributing to
 * yotta's configuration (typically in the target definition described by
 * target.json). Here's a sample:
 *
 *  "config": {
 *    ...
 *    "ble_instances": {
 *      "count": 1,
 *      "0" : {
 *        "initializer" : "createBLEInstance"
 *      }
 *    }
 *    ...
 *  }
 *
 * The following macros result in translating the above config into a static
 * array: instanceConstructors.
 */
#ifdef YOTTA_CFG_BLE_INSTANCES_COUNT
#define CONCATENATE(A, B) A ## B
#define EXPAND(X) X /* this adds a level of indirection needed to allow macro-expansion following a token-paste operation (see use of CONCATENATE() below). */

#define INITIALIZER_LIST_FOR_INSTANCE_CONSTRUCTORS_1 YOTTA_CFG_BLE_INSTANCES_0_INITIALIZER
#define INITIALIZER_LIST_FOR_INSTANCE_CONSTRUCTORS_2 INITIALIZER_LIST_FOR_INSTANCE_CONSTRUCTORS_1, YOTTA_CFG_BLE_INSTANCES_1_INITIALIZER
#define INITIALIZER_LIST_FOR_INSTANCE_CONSTRUCTORS_3 INITIALIZER_LIST_FOR_INSTANCE_CONSTRUCTORS_2, YOTTA_CFG_BLE_INSTANCES_2_INITIALIZER
#define INITIALIZER_LIST_FOR_INSTANCE_CONSTRUCTORS_4 INITIALIZER_LIST_FOR_INSTANCE_CONSTRUCTORS_3, YOTTA_CFG_BLE_INSTANCES_3_INITIALIZER
#define INITIALIZER_LIST_FOR_INSTANCE_CONSTRUCTORS_5 INITIALIZER_LIST_FOR_INSTANCE_CONSTRUCTORS_4, YOTTA_CFG_BLE_INSTANCES_4_INITIALIZER
/* ... add more of the above if ever needed */

#define INITIALIZER_LIST_FOR_INSTANCE_CONSTRUCTORS(N) EXPAND(CONCATENATE(INITIALIZER_LIST_FOR_INSTANCE_CONSTRUCTORS_, N))
#elif !defined(INITIALIZER_LIST_FOR_INSTANCE_CONSTRUCTORS)
/*
 * The following applies when building without yotta. By default BLE_API provides
 * a trivial initializer list containing a single constructor: createBLEInstance.
 * This may be overridden.
 */
#define INITIALIZER_LIST_FOR_INSTANCE_CONSTRUCTORS createBLEInstance

// yotta unlike mbed-cli has proper dependency mechanisms
// It is not required to defined a stub for createBLEInstance
#if !defined(YOTTA_CFG_MBED_OS)

// this stub is required by ARMCC otherwise link will systematically fail
MBED_WEAK BLEInstanceBase* createBLEInstance() {
    error("Please provide an implementation for mbed BLE");
    return NULL;
}

#endif

#endif /* YOTTA_CFG_BLE_INSTANCES_COUNT */

typedef BLEInstanceBase *(*InstanceConstructor_t)(void);
static const InstanceConstructor_t instanceConstructors[BLE::NUM_INSTANCES] = {
#ifndef YOTTA_CFG_BLE_INSTANCES_COUNT
    INITIALIZER_LIST_FOR_INSTANCE_CONSTRUCTORS
#else
    INITIALIZER_LIST_FOR_INSTANCE_CONSTRUCTORS(YOTTA_CFG_BLE_INSTANCES_COUNT)
#endif
};

BLE &
BLE::Instance(InstanceID_t id)
{
    static BLE *singletons[NUM_INSTANCES];
    if (id < NUM_INSTANCES) {
        if (singletons[id] == NULL) {
BLE_DEPRECATED_API_USE_BEGIN
            singletons[id] = new BLE(id); /* This object will never be freed. */
BLE_DEPRECATED_API_USE_END
        }

        return *singletons[id];
    }

    /* we come here only in the case of a bad interfaceID. */
BLE_DEPRECATED_API_USE_BEGIN
    static BLE badSingleton(NUM_INSTANCES /* this is a bad index; and will result in a NULL transport. */);
BLE_DEPRECATED_API_USE_END
    return badSingleton;
}

#ifdef YOTTA_CFG_MBED_OS
void defaultSchedulingCallback(BLE::OnEventsToProcessCallbackContext* params) {
    minar::Scheduler::postCallback(&params->ble, &BLE::processEvents);
}
#else
#define defaultSchedulingCallback NULL
#endif

bool BLE::hasInitialized(void) const
{
    if (!transport) {
        error("bad handle to underlying transport");
    }

    return transport->hasInitialized();
}

ble_error_t BLE::shutdown(void)
{
    if (!transport) {
        error("bad handle to underlying transport");
    }

    event_signaled = false;
    return transport->shutdown();
}

const char *BLE::getVersion(void)
{
    if (!transport) {
        error("bad handle to underlying transport");
    }

    return transport->getVersion();
}

const Gap &BLE::gap() const
{
    if (!transport) {
        error("bad handle to underlying transport");
    }

    return transport->getGap();
}

Gap &BLE::gap()
{
    if (!transport) {
        error("bad handle to underlying transport");
    }

    return transport->getGap();
}

const GattServer& BLE::gattServer() const
{
    if (!transport) {
        error("bad handle to underlying transport");
    }

    return transport->getGattServer();
}

GattServer& BLE::gattServer()
{
    if (!transport) {
        error("bad handle to underlying transport");
    }

    return transport->getGattServer();
}

const GattClient& BLE::gattClient() const
{
    if (!transport) {
        error("bad handle to underlying transport");
    }

    return transport->getGattClient();
}

GattClient& BLE::gattClient()
{
    if (!transport) {
        error("bad handle to underlying transport");
    }

    return transport->getGattClient();
}

const SecurityManager& BLE::securityManager() const
{
    if (!transport) {
        error("bad handle to underlying transport");
    }

    return transport->getSecurityManager();
}

SecurityManager& BLE::securityManager()
{
    if (!transport) {
        error("bad handle to underlying transport");
    }

    return transport->getSecurityManager();
}

void BLE::waitForEvent(void)
{
    if (!transport) {
        error("bad handle to underlying transport");
    }

    transport->waitForEvent();
}

void BLE::processEvents()
{
    if (event_signaled == false) {
        return;
    }

    if (!transport) {
        error("bad handle to underlying transport");
    }

    event_signaled = false;

    transport->processEvents();
}

void BLE::onEventsToProcess(const BLE::OnEventsToProcessCallback_t& callback)
{
    whenEventsToProcess = callback;

    // If events were previously signaled but the handler was not in place then
    // signal immediately events availability
    if (event_signaled && whenEventsToProcess) {
        OnEventsToProcessCallbackContext params = {
            *this
        };
        whenEventsToProcess(&params);
    }
}

void BLE::signalEventsToProcess()
{
    if (event_signaled == true) {
        return;
    }

    event_signaled = true;

    if (whenEventsToProcess) {
        OnEventsToProcessCallbackContext params = {
            *this
        };
        whenEventsToProcess(&params);
    }
}

// start of deprecated functions

BLE_DEPRECATED_API_USE_BEGIN

// NOTE: move and remove deprecation once private
BLE::BLE(InstanceID_t instanceIDIn) : instanceID(instanceIDIn), transport(),
    whenEventsToProcess(defaultSchedulingCallback),
    event_signaled(false)
{
    static BLEInstanceBase *transportInstances[NUM_INSTANCES];

    if (instanceID < NUM_INSTANCES) {
        if (!transportInstances[instanceID]) {
            transportInstances[instanceID] = instanceConstructors[instanceID](); /* Call the stack's initializer for the transport object. */
        }
        transport = transportInstances[instanceID];
    } else {
        transport = NULL;
    }
}

ble_error_t BLE::setAddress(
    BLEProtocol::AddressType_t type,
    const BLEProtocol::AddressBytes_t address
) {
    return gap().setAddress(type, address);
}

ble_error_t BLE::connect(
    const BLEProtocol::AddressBytes_t peerAddr,
    BLEProtocol::AddressType_t peerAddrType,
    const Gap::ConnectionParams_t *connectionParams,
    const GapScanningParams *scanParams
) {
    return gap().connect(peerAddr, peerAddrType, connectionParams, scanParams);
}

ble_error_t BLE::disconnect(Gap::DisconnectionReason_t reason) {
    return gap().disconnect(reason);
}

BLE_DEPRECATED_API_USE_END

<commit_msg>BLE: Fix wrong macro name for IAR<commit_after>/* mbed Microcontroller Library
 * Copyright (c) 2006-2013 ARM Limited
 *
 * 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 <stdio.h>
#include "ble/BLE.h"
#include "ble/BLEInstanceBase.h"

#if defined(TARGET_OTA_ENABLED)
#include "ble/services/DFUService.h"
#endif

#ifdef YOTTA_CFG_MBED_OS
#include <minar/minar.h>
#endif

#if !defined(YOTTA_CFG_MBED_OS)
#include <mbed_error.h>
#include <toolchain.h>
#endif

#if defined(__GNUC__) && !defined(__CC_ARM)
#define BLE_DEPRECATED_API_USE_BEGIN \
    _Pragma("GCC diagnostic push") \
    _Pragma("GCC diagnostic ignored \"-Wdeprecated-declarations\"")
#elif defined(__CC_ARM)
#define BLE_DEPRECATED_API_USE_BEGIN \
    _Pragma("push") \
    _Pragma("diag_suppress 1361")
#else
#define BLE_DEPRECATED_API_USE_BEGIN
#endif

#if defined(__GNUC__) && !defined(__CC_ARM)
#define BLE_DEPRECATED_API_USE_END \
    _Pragma("GCC diagnostic pop")
#elif defined(__CC_ARM)
#define BLE_DEPRECATED_API_USE_END \
        _Pragma("pop")
#else
#define BLE_DEPRECATED_API_USE_END
#endif

static const char* error_strings[] = {
    "BLE_ERROR_NONE: No error",
    "BLE_ERROR_BUFFER_OVERFLOW: The requested action would cause a buffer overflow and has been aborted",
    "BLE_ERROR_NOT_IMPLEMENTED: Requested a feature that isn't yet implement or isn't supported by the target HW",
    "BLE_ERROR_PARAM_OUT_OF_RANGE: One of the supplied parameters is outside the valid range",
    "BLE_ERROR_INVALID_PARAM: One of the supplied parameters is invalid",
    "BLE_STACK_BUSY: The stack is busy",
    "BLE_ERROR_INVALID_STATE: Invalid state",
    "BLE_ERROR_NO_MEM: Out of Memory",
    "BLE_ERROR_OPERATION_NOT_PERMITTED: The operation requested is not permitted",
    "BLE_ERROR_INITIALIZATION_INCOMPLETE: The BLE subsystem has not completed its initialisation",
    "BLE_ERROR_ALREADY_INITIALIZED: The BLE system has already been initialised",
    "BLE_ERROR_UNSPECIFIED: Unknown error",
    "BLE_ERROR_INTERNAL_STACK_FAILURE: The platform-specific stack failed"
};

const char* BLE::errorToString(ble_error_t error)
{
    if (error > BLE_ERROR_INTERNAL_STACK_FAILURE) {
        return "Illegal error code";
    }
    return error_strings[error];
}

ble_error_t
BLE::initImplementation(FunctionPointerWithContext<InitializationCompleteCallbackContext*> callback)
{
    ble_error_t err = transport->init(instanceID, callback);
    if (err != BLE_ERROR_NONE) {
        return err;
    }

    /* Platforms enabled for DFU should introduce the DFU Service into
     * applications automatically. */
#if defined(TARGET_OTA_ENABLED)
    static DFUService dfu(*this); // defined static so that the object remains alive
#endif // TARGET_OTA_ENABLED

    return BLE_ERROR_NONE;
}

/**
 * BLE::Instance() and BLE constructor rely upon a static array of initializers
 * to create actual BLE transport instances. A description of these instances
 * and initializers is supposed to be put in some .json file contributing to
 * yotta's configuration (typically in the target definition described by
 * target.json). Here's a sample:
 *
 *  "config": {
 *    ...
 *    "ble_instances": {
 *      "count": 1,
 *      "0" : {
 *        "initializer" : "createBLEInstance"
 *      }
 *    }
 *    ...
 *  }
 *
 * The following macros result in translating the above config into a static
 * array: instanceConstructors.
 */
#ifdef YOTTA_CFG_BLE_INSTANCES_COUNT
#define CONCATENATE(A, B) A ## B
#define EXPAND(X) X /* this adds a level of indirection needed to allow macro-expansion following a token-paste operation (see use of CONCATENATE() below). */

#define INITIALIZER_LIST_FOR_INSTANCE_CONSTRUCTORS_1 YOTTA_CFG_BLE_INSTANCES_0_INITIALIZER
#define INITIALIZER_LIST_FOR_INSTANCE_CONSTRUCTORS_2 INITIALIZER_LIST_FOR_INSTANCE_CONSTRUCTORS_1, YOTTA_CFG_BLE_INSTANCES_1_INITIALIZER
#define INITIALIZER_LIST_FOR_INSTANCE_CONSTRUCTORS_3 INITIALIZER_LIST_FOR_INSTANCE_CONSTRUCTORS_2, YOTTA_CFG_BLE_INSTANCES_2_INITIALIZER
#define INITIALIZER_LIST_FOR_INSTANCE_CONSTRUCTORS_4 INITIALIZER_LIST_FOR_INSTANCE_CONSTRUCTORS_3, YOTTA_CFG_BLE_INSTANCES_3_INITIALIZER
#define INITIALIZER_LIST_FOR_INSTANCE_CONSTRUCTORS_5 INITIALIZER_LIST_FOR_INSTANCE_CONSTRUCTORS_4, YOTTA_CFG_BLE_INSTANCES_4_INITIALIZER
/* ... add more of the above if ever needed */

#define INITIALIZER_LIST_FOR_INSTANCE_CONSTRUCTORS(N) EXPAND(CONCATENATE(INITIALIZER_LIST_FOR_INSTANCE_CONSTRUCTORS_, N))
#elif !defined(INITIALIZER_LIST_FOR_INSTANCE_CONSTRUCTORS)
/*
 * The following applies when building without yotta. By default BLE_API provides
 * a trivial initializer list containing a single constructor: createBLEInstance.
 * This may be overridden.
 */
#define INITIALIZER_LIST_FOR_INSTANCE_CONSTRUCTORS createBLEInstance

// yotta unlike mbed-cli has proper dependency mechanisms
// It is not required to defined a stub for createBLEInstance
#if !defined(YOTTA_CFG_MBED_OS)

// this stub is required by ARMCC otherwise link will systematically fail
MBED_WEAK BLEInstanceBase* createBLEInstance() {
    error("Please provide an implementation for mbed BLE");
    return NULL;
}

#endif

#endif /* YOTTA_CFG_BLE_INSTANCES_COUNT */

typedef BLEInstanceBase *(*InstanceConstructor_t)(void);
static const InstanceConstructor_t instanceConstructors[BLE::NUM_INSTANCES] = {
#ifndef YOTTA_CFG_BLE_INSTANCES_COUNT
    INITIALIZER_LIST_FOR_INSTANCE_CONSTRUCTORS
#else
    INITIALIZER_LIST_FOR_INSTANCE_CONSTRUCTORS(YOTTA_CFG_BLE_INSTANCES_COUNT)
#endif
};

BLE &
BLE::Instance(InstanceID_t id)
{
    static BLE *singletons[NUM_INSTANCES];
    if (id < NUM_INSTANCES) {
        if (singletons[id] == NULL) {
BLE_DEPRECATED_API_USE_BEGIN
            singletons[id] = new BLE(id); /* This object will never be freed. */
BLE_DEPRECATED_API_USE_END
        }

        return *singletons[id];
    }

    /* we come here only in the case of a bad interfaceID. */
BLE_DEPRECATED_API_USE_BEGIN
    static BLE badSingleton(NUM_INSTANCES /* this is a bad index; and will result in a NULL transport. */);
BLE_DEPRECATED_API_USE_END
    return badSingleton;
}

#ifdef YOTTA_CFG_MBED_OS
void defaultSchedulingCallback(BLE::OnEventsToProcessCallbackContext* params) {
    minar::Scheduler::postCallback(&params->ble, &BLE::processEvents);
}
#else
#define defaultSchedulingCallback NULL
#endif

bool BLE::hasInitialized(void) const
{
    if (!transport) {
        error("bad handle to underlying transport");
    }

    return transport->hasInitialized();
}

ble_error_t BLE::shutdown(void)
{
    if (!transport) {
        error("bad handle to underlying transport");
    }

    event_signaled = false;
    return transport->shutdown();
}

const char *BLE::getVersion(void)
{
    if (!transport) {
        error("bad handle to underlying transport");
    }

    return transport->getVersion();
}

const Gap &BLE::gap() const
{
    if (!transport) {
        error("bad handle to underlying transport");
    }

    return transport->getGap();
}

Gap &BLE::gap()
{
    if (!transport) {
        error("bad handle to underlying transport");
    }

    return transport->getGap();
}

const GattServer& BLE::gattServer() const
{
    if (!transport) {
        error("bad handle to underlying transport");
    }

    return transport->getGattServer();
}

GattServer& BLE::gattServer()
{
    if (!transport) {
        error("bad handle to underlying transport");
    }

    return transport->getGattServer();
}

const GattClient& BLE::gattClient() const
{
    if (!transport) {
        error("bad handle to underlying transport");
    }

    return transport->getGattClient();
}

GattClient& BLE::gattClient()
{
    if (!transport) {
        error("bad handle to underlying transport");
    }

    return transport->getGattClient();
}

const SecurityManager& BLE::securityManager() const
{
    if (!transport) {
        error("bad handle to underlying transport");
    }

    return transport->getSecurityManager();
}

SecurityManager& BLE::securityManager()
{
    if (!transport) {
        error("bad handle to underlying transport");
    }

    return transport->getSecurityManager();
}

void BLE::waitForEvent(void)
{
    if (!transport) {
        error("bad handle to underlying transport");
    }

    transport->waitForEvent();
}

void BLE::processEvents()
{
    if (event_signaled == false) {
        return;
    }

    if (!transport) {
        error("bad handle to underlying transport");
    }

    event_signaled = false;

    transport->processEvents();
}

void BLE::onEventsToProcess(const BLE::OnEventsToProcessCallback_t& callback)
{
    whenEventsToProcess = callback;

    // If events were previously signaled but the handler was not in place then
    // signal immediately events availability
    if (event_signaled && whenEventsToProcess) {
        OnEventsToProcessCallbackContext params = {
            *this
        };
        whenEventsToProcess(&params);
    }
}

void BLE::signalEventsToProcess()
{
    if (event_signaled == true) {
        return;
    }

    event_signaled = true;

    if (whenEventsToProcess) {
        OnEventsToProcessCallbackContext params = {
            *this
        };
        whenEventsToProcess(&params);
    }
}

// start of deprecated functions

BLE_DEPRECATED_API_USE_BEGIN

// NOTE: move and remove deprecation once private
BLE::BLE(InstanceID_t instanceIDIn) : instanceID(instanceIDIn), transport(),
    whenEventsToProcess(defaultSchedulingCallback),
    event_signaled(false)
{
    static BLEInstanceBase *transportInstances[NUM_INSTANCES];

    if (instanceID < NUM_INSTANCES) {
        if (!transportInstances[instanceID]) {
            transportInstances[instanceID] = instanceConstructors[instanceID](); /* Call the stack's initializer for the transport object. */
        }
        transport = transportInstances[instanceID];
    } else {
        transport = NULL;
    }
}

ble_error_t BLE::setAddress(
    BLEProtocol::AddressType_t type,
    const BLEProtocol::AddressBytes_t address
) {
    return gap().setAddress(type, address);
}

ble_error_t BLE::connect(
    const BLEProtocol::AddressBytes_t peerAddr,
    BLEProtocol::AddressType_t peerAddrType,
    const Gap::ConnectionParams_t *connectionParams,
    const GapScanningParams *scanParams
) {
    return gap().connect(peerAddr, peerAddrType, connectionParams, scanParams);
}

ble_error_t BLE::disconnect(Gap::DisconnectionReason_t reason) {
    return gap().disconnect(reason);
}

BLE_DEPRECATED_API_USE_END

<|endoftext|>


<commit_before>/* Copyright (C) 2005-2007, Thorvald Natvig <thorvald@natvig.com>

   All rights reserved.

   Redistribution and use in source and binary forms, with or without
   modification, are permitted provided that the following conditions
   are met:

   - Redistributions of source code must retain the above copyright notice,
     this list of conditions and the following disclaimer.
   - Redistributions in binary form must reproduce the above copyright notice,
     this list of conditions and the following disclaimer in the documentation
     and/or other materials provided with the distribution.
   - Neither the name of the Mumble Developers nor the names of its
     contributors may be used to endorse or promote products derived from this
     software without specific prior written permission.

   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
   ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
   A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR
   CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
   EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
   PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
   PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
   LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
   NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
   SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/

#include "Server.h"
#include "Meta.h"

int add_ext(X509 * crt, int nid, char *value) {
	X509_EXTENSION *ex;
	X509V3_CTX ctx;
	X509V3_set_ctx_nodb(&ctx);
	X509V3_set_ctx(&ctx, crt, crt, NULL, NULL, 0);
	ex = X509V3_EXT_conf_nid(NULL, &ctx, nid, value);
	if (!ex)
		return 0;

	X509_add_ext(crt, ex, -1);
	X509_EXTENSION_free(ex);
	return 1;
}

void Server::initializeCert() {
	QByteArray crt, key;

	crt = getConf("certificate", QString()).toByteArray();
	key = getConf("key", QString()).toByteArray();

	if (! crt.isEmpty()) {
		qscCert = QSslCertificate(crt);
		if (qscCert.isNull()) {
			log("Failed to parse certificate.");
		}
	}

	if (! key.isEmpty() && qscCert.isNull()) {
		qscCert = QSslCertificate(key);
		if (! qscCert.isNull()) {
			log("Using certificate from key.");
		}
	}

	if (! qscCert.isNull()) {
		QSsl::KeyAlgorithm alg = qscCert.publicKey().algorithm();

		if (! key.isEmpty()) {
			qskKey = QSslKey(key, alg);
			if (qskKey.isNull()) {
				log("Failed to parse key.");
			}
		}

		if (! crt.isEmpty() && qskKey.isNull()) {
			qskKey = QSslKey(crt, alg);
			if (! qskKey.isNull()) {
				log("Using key from certificate.");
			}
		}

	}

	if (qscCert.isNull() || qskKey.isNull()) {
		if (! key.isEmpty() || ! crt.isEmpty()) {
			log("Certificate specified, but failed to load.");
		}
		qskKey = Meta::mp.qskKey;
		qscCert = Meta::mp.qscCert;
		if (qscCert.isNull() || qskKey.isNull()) {
			log("Generating new server certificate.");

			BIO *bio_err;

			CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_ON);

			bio_err=BIO_new_fp(stderr, BIO_NOCLOSE);

			X509 *x509 = X509_new();
			EVP_PKEY *pkey = EVP_PKEY_new();
			RSA *rsa = RSA_generate_key(1024,RSA_F4,NULL,NULL);
			EVP_PKEY_assign_RSA(pkey, rsa);

			X509_set_version(x509, 2);
			ASN1_INTEGER_set(X509_get_serialNumber(x509),1);
			X509_gmtime_adj(X509_get_notBefore(x509),0);
			X509_gmtime_adj(X509_get_notAfter(x509),60*60*24*365);
			X509_set_pubkey(x509, pkey);

			X509_NAME *name=X509_get_subject_name(x509);

			X509_NAME_add_entry_by_txt(name, "CN", MBSTRING_ASC, reinterpret_cast<const unsigned char *>("Murmur Autogenerated Certificate"), -1, -1, 0);
			X509_set_issuer_name(x509, name);
			add_ext(x509, NID_basic_constraints, "critical,CA:FALSE");
			add_ext(x509, NID_ext_key_usage, "serverAuth,clientAuth");
			add_ext(x509, NID_subject_key_identifier, "hash");
			add_ext(x509, NID_netscape_cert_type, "server");
			add_ext(x509, NID_netscape_comment, "Generated from murmur");

			X509_sign(x509, pkey, EVP_md5());

			crt.resize(i2d_X509(x509, NULL));
			unsigned char *dptr=reinterpret_cast<unsigned char *>(crt.data());
			i2d_X509(x509, &dptr);

			qscCert = QSslCertificate(crt, QSsl::Der);
			if (qscCert.isNull())
				log("Certificate generation failed");

			key.resize(i2d_PrivateKey(pkey, NULL));
			dptr=reinterpret_cast<unsigned char *>(key.data());
			i2d_PrivateKey(pkey, &dptr);

			qskKey = QSslKey(key, QSsl::Rsa, QSsl::Der);
			if (qskKey.isNull())
				log("Key generation failed");

			setConf("certificate", qscCert.toPem());
			setConf("key", qskKey.toPem());
		}
	}

	QList<QSslCipher> pref;
	foreach(QSslCipher c, QSslSocket::defaultCiphers()) {
		if (c.usedBits() < 128)
			continue;
		pref << c;
	}
	if (pref.isEmpty())
		qFatal("No ciphers of at least 128 bit found");
	QSslSocket::setDefaultCiphers(pref);
}

const QString Server::getDigest() const {
	return QString::fromLatin1(qscCert.digest().toHex());
}
<commit_msg>Support prehistoric OpenSSL<commit_after>/* Copyright (C) 2005-2007, Thorvald Natvig <thorvald@natvig.com>

   All rights reserved.

   Redistribution and use in source and binary forms, with or without
   modification, are permitted provided that the following conditions
   are met:

   - Redistributions of source code must retain the above copyright notice,
     this list of conditions and the following disclaimer.
   - Redistributions in binary form must reproduce the above copyright notice,
     this list of conditions and the following disclaimer in the documentation
     and/or other materials provided with the distribution.
   - Neither the name of the Mumble Developers nor the names of its
     contributors may be used to endorse or promote products derived from this
     software without specific prior written permission.

   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
   ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
   A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR
   CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
   EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
   PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
   PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
   LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
   NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
   SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/

#include "Server.h"
#include "Meta.h"

int add_ext(X509 * crt, int nid, char *value) {
	X509_EXTENSION *ex;
	X509V3_CTX ctx;
	X509V3_set_ctx_nodb(&ctx);
	X509V3_set_ctx(&ctx, crt, crt, NULL, NULL, 0);
	ex = X509V3_EXT_conf_nid(NULL, &ctx, nid, value);
	if (!ex)
		return 0;

	X509_add_ext(crt, ex, -1);
	X509_EXTENSION_free(ex);
	return 1;
}

void Server::initializeCert() {
	QByteArray crt, key;

	crt = getConf("certificate", QString()).toByteArray();
	key = getConf("key", QString()).toByteArray();

	if (! crt.isEmpty()) {
		qscCert = QSslCertificate(crt);
		if (qscCert.isNull()) {
			log("Failed to parse certificate.");
		}
	}

	if (! key.isEmpty() && qscCert.isNull()) {
		qscCert = QSslCertificate(key);
		if (! qscCert.isNull()) {
			log("Using certificate from key.");
		}
	}

	if (! qscCert.isNull()) {
		QSsl::KeyAlgorithm alg = qscCert.publicKey().algorithm();

		if (! key.isEmpty()) {
			qskKey = QSslKey(key, alg);
			if (qskKey.isNull()) {
				log("Failed to parse key.");
			}
		}

		if (! crt.isEmpty() && qskKey.isNull()) {
			qskKey = QSslKey(crt, alg);
			if (! qskKey.isNull()) {
				log("Using key from certificate.");
			}
		}

	}

	if (qscCert.isNull() || qskKey.isNull()) {
		if (! key.isEmpty() || ! crt.isEmpty()) {
			log("Certificate specified, but failed to load.");
		}
		qskKey = Meta::mp.qskKey;
		qscCert = Meta::mp.qscCert;
		if (qscCert.isNull() || qskKey.isNull()) {
			log("Generating new server certificate.");

			BIO *bio_err;

			CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_ON);

			bio_err=BIO_new_fp(stderr, BIO_NOCLOSE);

			X509 *x509 = X509_new();
			EVP_PKEY *pkey = EVP_PKEY_new();
			RSA *rsa = RSA_generate_key(1024,RSA_F4,NULL,NULL);
			EVP_PKEY_assign_RSA(pkey, rsa);

			X509_set_version(x509, 2);
			ASN1_INTEGER_set(X509_get_serialNumber(x509),1);
			X509_gmtime_adj(X509_get_notBefore(x509),0);
			X509_gmtime_adj(X509_get_notAfter(x509),60*60*24*365);
			X509_set_pubkey(x509, pkey);

			X509_NAME *name=X509_get_subject_name(x509);

			X509_NAME_add_entry_by_txt(name, "CN", MBSTRING_ASC, reinterpret_cast<unsigned char *>(const_cast<char *>("Murmur Autogenerated Certificate")), -1, -1, 0);
			X509_set_issuer_name(x509, name);
			add_ext(x509, NID_basic_constraints, "critical,CA:FALSE");
			add_ext(x509, NID_ext_key_usage, "serverAuth,clientAuth");
			add_ext(x509, NID_subject_key_identifier, "hash");
			add_ext(x509, NID_netscape_cert_type, "server");
			add_ext(x509, NID_netscape_comment, "Generated from murmur");

			X509_sign(x509, pkey, EVP_md5());

			crt.resize(i2d_X509(x509, NULL));
			unsigned char *dptr=reinterpret_cast<unsigned char *>(crt.data());
			i2d_X509(x509, &dptr);

			qscCert = QSslCertificate(crt, QSsl::Der);
			if (qscCert.isNull())
				log("Certificate generation failed");

			key.resize(i2d_PrivateKey(pkey, NULL));
			dptr=reinterpret_cast<unsigned char *>(key.data());
			i2d_PrivateKey(pkey, &dptr);

			qskKey = QSslKey(key, QSsl::Rsa, QSsl::Der);
			if (qskKey.isNull())
				log("Key generation failed");

			setConf("certificate", qscCert.toPem());
			setConf("key", qskKey.toPem());
		}
	}

	QList<QSslCipher> pref;
	foreach(QSslCipher c, QSslSocket::defaultCiphers()) {
		if (c.usedBits() < 128)
			continue;
		pref << c;
	}
	if (pref.isEmpty())
		qFatal("No ciphers of at least 128 bit found");
	QSslSocket::setDefaultCiphers(pref);
}

const QString Server::getDigest() const {
	return QString::fromLatin1(qscCert.digest().toHex());
}
<|endoftext|>


<commit_before>#include <iostream>

#include <mvp/MVPJobRequest.pb.h>

int main(int argc, char* argv[])
{
  using namespace std;
  using namespace mvp;

  cout << "Hello world" << endl;

  MVPJobRequest job;
  cout << job.plate_georef().tile_size() << endl;

  return 0;
}
<commit_msg>a sketch implementation for mvp_solo<commit_after>#include <iostream>

#include <vw/Image/ImageMath.h>
#include <vw/Image/UtilityViews.h>
#include <vw/Plate/PlateFile.h>

#include <mvp/MVPWorkspace.h>
#include <mvp/MVPTileProcessor.h>

using namespace vw;
using namespace vw::cartography;
using namespace vw::platefile;
using namespace std;
using namespace mvp;

int main(int argc, char* argv[])
{
  const int MAX_OVERLAP = 4;

  PlateGeoReference plate_georef(Datum("D_MOON"), "equi", 256, GeoReference::PixelAsPoint);
  MVPAlgorithmSettings settings;
  settings.set_test_algorithm(true);

  MVPWorkspace work("result.plate", "result-internal.plate", plate_georef, settings);
  work.add_image_pattern("synth.%d.pinhole", "synth.%d.tif", Vector2i(0, 3));

  int render_level = work.equal_resolution_level();
  BBox2i tile_bbox(work.tile_work_area(render_level));

  cout << tile_bbox << endl;
  cout << work.pixel_work_area(render_level) << endl;

  boost::shared_ptr<PlateFile> pf(new PlateFile("output.plate", "equi", "desc", plate_georef.tile_size(), "tif", VW_PIXEL_RGBA, VW_CHANNEL_UINT8));
  Transaction tid = pf->transaction_request("tdesc", -1);

  for (int col = tile_bbox.min().x(); col < tile_bbox.max().x(); col++) {
    for (int row = tile_bbox.min().y(); row < tile_bbox.max().y(); row++) {
      MVPJobRequest job = work.assemble_job(col, row, render_level);
      MVPTileProcessor proc(job);
      MVPTileResult result = proc.process();

      ImageView<PixelRGBA<uint8> > rendered_tile = pixel_cast_rescale<PixelRGB<uint8> >(result.post_height / MAX_OVERLAP);

      pf->write_request();
      pf->write_update(rendered_tile, col, row, render_level, tid);
      pf->sync();
      pf->write_complete();

      cout << "Wrote tile: " << col << " " << row << " " << render_level << endl;
    }
  }

  for (int level = 2; level < render_level; level++) {
    int divisor = render_level - level;
    for (int col = tile_bbox.min().x() >> divisor; col <= tile_bbox.max().x() >> divisor; col++) {
      for (int row = tile_bbox.min().y() >> divisor; row <= tile_bbox.max().y() >> divisor; row++) {
        ImageView<PixelRGBA<uint8> > rendered_tile(constant_view(PixelRGBA<uint8>(255, 0, 0, 255), plate_georef.tile_size(), plate_georef.tile_size()));
        pf->write_request();
        pf->write_update(rendered_tile, col, row, level, tid);
        pf->sync();
        pf->write_complete();
      }
    }
  }

  return 0;
}
<|endoftext|>