<commit_before>#define DEBUG 1
/**
 * File    : F.cpp
 * Author  : Kazune Takahashi
 * Created : 3/3/2020, 9:55:07 PM
 * Powered by Visual Studio Code
 */
#include <algorithm>
#include <bitset>
#include <cassert>
#include <cctype>
#include <chrono>
#include <cmath>
#include <complex>
#include <cstdint>
#include <cstdio>
#include <cstdlib>
#include <functional>
#include <iomanip>
#include <iostream>
#include <map>
#include <queue>
#include <random>
#include <set>
#include <stack>
#include <string>
#include <tuple>
#include <unordered_map>
#include <unordered_set>
#include <vector>
// ----- boost -----
#include <boost/rational.hpp>
#include <boost/multiprecision/cpp_int.hpp>
// ----- using directives and manipulations -----
using namespace std;
using boost::rational;
using boost::multiprecision::cpp_int;
using ll = long long;
template <typename T>
using max_heap = priority_queue<T>;
template <typename T>
using min_heap = priority_queue<T, vector<T>, greater<T>>;
// ----- constexpr for Mint and Combination -----
constexpr ll MOD{1000000007LL};
// constexpr ll MOD{998244353LL}; // be careful
constexpr ll MAX_SIZE{3000010LL};
// constexpr ll MAX_SIZE{30000010LL}; // if 10^7 is needed
// ----- ch_max and ch_min -----
template <typename T>
void ch_max(T &left, T right)
{
  if (left < right)
  {
    left = right;
  }
}
template <typename T>
void ch_min(T &left, T right)
{
  if (left > right)
  {
    left = right;
  }
}
// ----- Mint -----
template <ll MOD = MOD>
class Mint
{
public:
  ll x;
  Mint() : x{0LL} {}
  Mint(ll x) : x{(x % MOD + MOD) % MOD} {}
  Mint operator-() const { return x ? MOD - x : 0; }
  Mint &operator+=(const Mint &a)
  {
    if ((x += a.x) >= MOD)
    {
      x -= MOD;
    }
    return *this;
  }
  Mint &operator-=(const Mint &a) { return *this += -a; }
  Mint &operator++() { return *this += 1; }
  Mint &operator++(int)
  {
    Mint tmp{*this};
    ++*this;
    return tmp;
  }
  Mint &operator--() { return *this -= 1; }
  Mint &operator--(int)
  {
    Mint tmp{*this};
    --*this;
    return tmp;
  }
  Mint &operator*=(const Mint &a)
  {
    (x *= a.x) %= MOD;
    return *this;
  }
  Mint &operator/=(const Mint &a)
  {
    Mint b{a};
    return *this *= b.power(MOD - 2);
  }
  Mint operator+(const Mint &a) const { return Mint(*this) += a; }
  Mint operator-(const Mint &a) const { return Mint(*this) -= a; }
  Mint operator*(const Mint &a) const { return Mint(*this) *= a; }
  Mint operator/(const Mint &a) const { return Mint(*this) /= a; }
  bool operator<(const Mint &a) const { return x < a.x; }
  bool operator<=(const Mint &a) const { return x <= a.x; }
  bool operator>(const Mint &a) const { return x > a.x; }
  bool operator>=(const Mint &a) const { return x >= a.x; }
  bool operator==(const Mint &a) const { return x == a.x; }
  bool operator!=(const Mint &a) const { return !(*this == a); }
  const Mint power(ll N)
  {
    if (N == 0)
    {
      return 1;
    }
    else if (N % 2 == 1)
    {
      return *this * power(N - 1);
    }
    else
    {
      Mint half = power(N / 2);
      return half * half;
    }
  }
};
template <ll MOD>
Mint<MOD> operator+(ll lhs, const Mint<MOD> &rhs)
{
  return rhs + lhs;
}
template <ll MOD>
Mint<MOD> operator-(ll lhs, const Mint<MOD> &rhs)
{
  return -rhs + lhs;
}
template <ll MOD>
Mint<MOD> operator*(ll lhs, const Mint<MOD> &rhs)
{
  return rhs * lhs;
}
template <ll MOD>
Mint<MOD> operator/(ll lhs, const Mint<MOD> &rhs)
{
  return Mint<MOD>{lhs} / rhs;
}
template <ll MOD>
istream &operator>>(istream &stream, Mint<MOD> &a)
{
  return stream >> a.x;
}
template <ll MOD>
ostream &operator<<(ostream &stream, const Mint<MOD> &a)
{
  return stream << a.x;
}
// ----- Combination -----
template <ll MOD = MOD, ll MAX_SIZE = MAX_SIZE>
class Combination
{
public:
  vector<Mint<MOD>> inv, fact, factinv;
  Combination() : inv(MAX_SIZE), fact(MAX_SIZE), factinv(MAX_SIZE)
  {
    inv[1] = 1;
    for (auto i = 2LL; i < MAX_SIZE; i++)
    {
      inv[i] = (-inv[MOD % i]) * (MOD / i);
    }
    fact[0] = factinv[0] = 1;
    for (auto i = 1LL; i < MAX_SIZE; i++)
    {
      fact[i] = Mint<MOD>(i) * fact[i - 1];
      factinv[i] = inv[i] * factinv[i - 1];
    }
  }
  Mint<MOD> operator()(int n, int k)
  {
    if (n >= 0 && k >= 0 && n - k >= 0)
    {
      return fact[n] * factinv[k] * factinv[n - k];
    }
    return 0;
  }
  Mint<MOD> catalan(int x, int y)
  {
    return (*this)(x + y, y) - (*this)(x + y, y - 1);
  }
};
// ----- for C++14 -----
using mint = Mint<MOD>;
using combination = Combination<MOD, MAX_SIZE>;
template <typename T>
T gcd(T x, T y) { return y ? gcd(y, x % y) : x; }
template <typename T>
T lcm(T x, T y) { return x / gcd(x, y) * y; }
// ----- for C++17 -----
template <typename T>
int popcount(T x) // C++20
{
  int ans{0};
  while (x != 0)
  {
    ans += x & 1;
    x >>= 1;
  }
  return ans;
}
// ----- frequently used constexpr -----
// constexpr double epsilon{1e-10};
// constexpr ll infty{1000000000000000LL}; // or
constexpr int infty{1'000'000'010};
// constexpr int dx[4] = {1, 0, -1, 0};
// constexpr int dy[4] = {0, 1, 0, -1};
// ----- Yes() and No() -----
void Yes()
{
  cout << "Yes" << endl;
  exit(0);
}
void No()
{
  cout << "-1" << endl;
  exit(0);
}
// ----- main() -----

using bomb = tuple<int, int>;
using sw = tuple<int, int>;

class Solve
{
  int N, M;
  vector<bomb> V;
  vector<sw> W;
  using edge = tuple<int, int>;
  vector<vector<edge>> E;
  vector<int> F;
  vector<bool> visited;
  vector<int> ans;

public:
  Solve(int N, int M, vector<bomb> V, vector<sw> W) : N{N}, M{M}, V(V), W(W), E(N + 1), F(N + 1), visited(N + 1, false)
  {
    init();
    execute_dfs();
    flush();
  }

private:
  void init()
  {
    vector<int> X(N);
    for (auto i = 0; i < N; ++i)
    {
      X[i] = get<0>(V[i]);
    }
    for (auto i = 0; i < M; ++i)
    {
      auto start{lower_bound(X.begin(), X.end(), get<0>(W[i])) - X.begin()};
      auto finish{lower_bound(X.begin(), X.end(), get<1>(W[i])) - X.begin()};
      if (start != finish)
      {
        E[start].push_back(edge(finish, i));
        E[finish].push_back(edge(start, i));
      }
    }
    F[0] = get<1>(V[0]);
    for (auto i = 0; i < N; ++i)
    {
      F[i + 1] = get<1>(V[i]) ^ get<1>(V[i + 1]);
    }
  }

  void execute_dfs()
  {
    for (auto i = 0; i <= N; ++i)
    {
      if (!visited[i])
      {
        dfs(i);
      }
    }
  }

  void flush()
  {
    for (auto i = 0; i <= N; ++i)
    {
      if (F[i] == 1)
      {
        No();
      }
    }
    sort(ans.begin(), ans.end());
    cout << ans.size() << endl;
    for (auto it = ans.begin(); it != ans.end(); ++it)
    {
      cout << *it;
      if (it + 1 != ans.end())
      {
        cout << " ";
      }
      else
      {
        cout << endl;
      }
    }
  }

  void dfs(int v)
  {
#if DEBUG == 1
    cerr << "v = " << v << endl;
#endif
    visited[v] = true;
    for (auto const &e : E[v])
    {
      int w, n;
      tie(w, n) = e;
      if (!visited[w])
      {
        dfs(w);
        if (F[w] == 1)
        {
          F[w] = 0;
          F[v] = 1 - F[v];
          ans.push_back(n);
        }
      }
    }
  }
};

int main()
{
  int N, M;
  cin >> N >> M;
  vector<bomb> V(N + 1);
  for (auto i = 0; i < N; ++i)
  {
    cin >> get<0>(V[i]) >> get<1>(V[i]);
  }
  vector<sw> W;
  for (auto i = 0; i < M; ++i)
  {
    cin >> get<0>(W[i]) >> get<1>(W[i]);
    get<1>(W[i])++;
  }
  sort(V.begin(), V.end());
  Solve solve(N, M, V, W);
}
<commit_msg>tried F.cpp to 'F'<commit_after>#define DEBUG 1
/**
 * File    : F.cpp
 * Author  : Kazune Takahashi
 * Created : 3/3/2020, 9:55:07 PM
 * Powered by Visual Studio Code
 */
#include <algorithm>
#include <bitset>
#include <cassert>
#include <cctype>
#include <chrono>
#include <cmath>
#include <complex>
#include <cstdint>
#include <cstdio>
#include <cstdlib>
#include <functional>
#include <iomanip>
#include <iostream>
#include <map>
#include <queue>
#include <random>
#include <set>
#include <stack>
#include <string>
#include <tuple>
#include <unordered_map>
#include <unordered_set>
#include <vector>
// ----- boost -----
#include <boost/rational.hpp>
#include <boost/multiprecision/cpp_int.hpp>
// ----- using directives and manipulations -----
using namespace std;
using boost::rational;
using boost::multiprecision::cpp_int;
using ll = long long;
template <typename T>
using max_heap = priority_queue<T>;
template <typename T>
using min_heap = priority_queue<T, vector<T>, greater<T>>;
// ----- constexpr for Mint and Combination -----
constexpr ll MOD{1000000007LL};
// constexpr ll MOD{998244353LL}; // be careful
constexpr ll MAX_SIZE{3000010LL};
// constexpr ll MAX_SIZE{30000010LL}; // if 10^7 is needed
// ----- ch_max and ch_min -----
template <typename T>
void ch_max(T &left, T right)
{
  if (left < right)
  {
    left = right;
  }
}
template <typename T>
void ch_min(T &left, T right)
{
  if (left > right)
  {
    left = right;
  }
}
// ----- Mint -----
template <ll MOD = MOD>
class Mint
{
public:
  ll x;
  Mint() : x{0LL} {}
  Mint(ll x) : x{(x % MOD + MOD) % MOD} {}
  Mint operator-() const { return x ? MOD - x : 0; }
  Mint &operator+=(const Mint &a)
  {
    if ((x += a.x) >= MOD)
    {
      x -= MOD;
    }
    return *this;
  }
  Mint &operator-=(const Mint &a) { return *this += -a; }
  Mint &operator++() { return *this += 1; }
  Mint &operator++(int)
  {
    Mint tmp{*this};
    ++*this;
    return tmp;
  }
  Mint &operator--() { return *this -= 1; }
  Mint &operator--(int)
  {
    Mint tmp{*this};
    --*this;
    return tmp;
  }
  Mint &operator*=(const Mint &a)
  {
    (x *= a.x) %= MOD;
    return *this;
  }
  Mint &operator/=(const Mint &a)
  {
    Mint b{a};
    return *this *= b.power(MOD - 2);
  }
  Mint operator+(const Mint &a) const { return Mint(*this) += a; }
  Mint operator-(const Mint &a) const { return Mint(*this) -= a; }
  Mint operator*(const Mint &a) const { return Mint(*this) *= a; }
  Mint operator/(const Mint &a) const { return Mint(*this) /= a; }
  bool operator<(const Mint &a) const { return x < a.x; }
  bool operator<=(const Mint &a) const { return x <= a.x; }
  bool operator>(const Mint &a) const { return x > a.x; }
  bool operator>=(const Mint &a) const { return x >= a.x; }
  bool operator==(const Mint &a) const { return x == a.x; }
  bool operator!=(const Mint &a) const { return !(*this == a); }
  const Mint power(ll N)
  {
    if (N == 0)
    {
      return 1;
    }
    else if (N % 2 == 1)
    {
      return *this * power(N - 1);
    }
    else
    {
      Mint half = power(N / 2);
      return half * half;
    }
  }
};
template <ll MOD>
Mint<MOD> operator+(ll lhs, const Mint<MOD> &rhs)
{
  return rhs + lhs;
}
template <ll MOD>
Mint<MOD> operator-(ll lhs, const Mint<MOD> &rhs)
{
  return -rhs + lhs;
}
template <ll MOD>
Mint<MOD> operator*(ll lhs, const Mint<MOD> &rhs)
{
  return rhs * lhs;
}
template <ll MOD>
Mint<MOD> operator/(ll lhs, const Mint<MOD> &rhs)
{
  return Mint<MOD>{lhs} / rhs;
}
template <ll MOD>
istream &operator>>(istream &stream, Mint<MOD> &a)
{
  return stream >> a.x;
}
template <ll MOD>
ostream &operator<<(ostream &stream, const Mint<MOD> &a)
{
  return stream << a.x;
}
// ----- Combination -----
template <ll MOD = MOD, ll MAX_SIZE = MAX_SIZE>
class Combination
{
public:
  vector<Mint<MOD>> inv, fact, factinv;
  Combination() : inv(MAX_SIZE), fact(MAX_SIZE), factinv(MAX_SIZE)
  {
    inv[1] = 1;
    for (auto i = 2LL; i < MAX_SIZE; i++)
    {
      inv[i] = (-inv[MOD % i]) * (MOD / i);
    }
    fact[0] = factinv[0] = 1;
    for (auto i = 1LL; i < MAX_SIZE; i++)
    {
      fact[i] = Mint<MOD>(i) * fact[i - 1];
      factinv[i] = inv[i] * factinv[i - 1];
    }
  }
  Mint<MOD> operator()(int n, int k)
  {
    if (n >= 0 && k >= 0 && n - k >= 0)
    {
      return fact[n] * factinv[k] * factinv[n - k];
    }
    return 0;
  }
  Mint<MOD> catalan(int x, int y)
  {
    return (*this)(x + y, y) - (*this)(x + y, y - 1);
  }
};
// ----- for C++14 -----
using mint = Mint<MOD>;
using combination = Combination<MOD, MAX_SIZE>;
template <typename T>
T gcd(T x, T y) { return y ? gcd(y, x % y) : x; }
template <typename T>
T lcm(T x, T y) { return x / gcd(x, y) * y; }
// ----- for C++17 -----
template <typename T>
int popcount(T x) // C++20
{
  int ans{0};
  while (x != 0)
  {
    ans += x & 1;
    x >>= 1;
  }
  return ans;
}
// ----- frequently used constexpr -----
// constexpr double epsilon{1e-10};
// constexpr ll infty{1000000000000000LL}; // or
constexpr int infty{1'000'000'010};
// constexpr int dx[4] = {1, 0, -1, 0};
// constexpr int dy[4] = {0, 1, 0, -1};
// ----- Yes() and No() -----
void Yes()
{
  cout << "Yes" << endl;
  exit(0);
}
void No()
{
  cout << "-1" << endl;
  exit(0);
}
// ----- main() -----

using bomb = tuple<int, int>;
using sw = tuple<int, int>;

class Solve
{
  int N, M;
  vector<bomb> V;
  vector<sw> W;
  using edge = tuple<int, int>;
  vector<vector<edge>> E;
  vector<int> F;
  vector<bool> visited;
  vector<int> ans;

public:
  Solve(int N, int M, vector<bomb> V, vector<sw> W) : N{N}, M{M}, V(V), W(W), E(N + 1), F(N + 1), visited(N + 1, false)
  {
    init();
    execute_dfs();
    flush();
  }

private:
  void init()
  {
    sort(V.begin(), V.end());
    vector<int> X(N);
    for (auto i = 0; i < N; ++i)
    {
      X[i] = get<0>(V[i]);
    }
    for (auto i = 0; i < M; ++i)
    {
      auto start{lower_bound(X.begin(), X.end(), get<0>(W[i])) - X.begin()};
      auto finish{lower_bound(X.begin(), X.end(), get<1>(W[i])) - X.begin()};
      if (start != finish)
      {
        E[start].push_back(edge(finish, i));
        E[finish].push_back(edge(start, i));
      }
    }
    F[0] = get<1>(V[0]);
    for (auto i = 0; i < N; ++i)
    {
      F[i + 1] = get<1>(V[i]) ^ get<1>(V[i + 1]);
    }
  }

  void execute_dfs()
  {
    for (auto i = 0; i <= N; ++i)
    {
      if (!visited[i])
      {
        dfs(i);
      }
    }
  }

  void flush()
  {
    for (auto i = 0; i <= N; ++i)
    {
      if (F[i] == 1)
      {
        No();
      }
    }
    sort(ans.begin(), ans.end());
    cout << ans.size() << endl;
    for (auto it = ans.begin(); it != ans.end(); ++it)
    {
      cout << *it;
      if (it + 1 != ans.end())
      {
        cout << " ";
      }
      else
      {
        cout << endl;
      }
    }
  }

  void dfs(int v)
  {
#if DEBUG == 1
    cerr << "v = " << v << endl;
#endif
    visited[v] = true;
    for (auto const &e : E[v])
    {
      int w, n;
      tie(w, n) = e;
      if (!visited[w])
      {
        dfs(w);
        if (F[w] == 1)
        {
          F[w] = 0;
          F[v] = 1 - F[v];
          ans.push_back(n);
        }
      }
    }
  }
};

int main()
{
  int N, M;
  cin >> N >> M;
  vector<bomb> V(N + 1);
  for (auto i = 0; i < N; ++i)
  {
    cin >> get<0>(V[i]) >> get<1>(V[i]);
  }
  vector<sw> W(M);
  for (auto i = 0; i < M; ++i)
  {
    cin >> get<0>(W[i]) >> get<1>(W[i]);
    get<1>(W[i])++;
  }
  Solve solve(N, M, V, W);
}
<|endoftext|>


<commit_before>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

#include <gflags/gflags.h>
#include <glog/logging.h>

#include "roflibs/netlink/cnetlink.hpp"
#include "roflibs/of-dpa/cbasebox.hpp"

static bool validate_port(const char *flagname, google::int32 value) {
  if (value > 0 && value < 32768) // value is ok
    return true;
  return false;
}

DEFINE_int32(port, 6653, "Listening port");

int main(int argc, char **argv) {

  if (!google::RegisterFlagValidator(&FLAGS_port, &validate_port)) {
    std::cerr << "Failed to register port validator" << std::endl;
    exit(1);
  }

  gflags::SetUsageMessage("");
  gflags::SetVersionString(PACKAGE_VERSION);

  gflags::ParseCommandLineFlags(&argc, &argv, true);
  google::InitGoogleLogging(argv[0]);

  rofl::openflow::cofhello_elem_versionbitmap versionbitmap;
  versionbitmap.add_ofp_version(rofl::openflow13::OFP_VERSION);
  LOG(INFO) << "[baseboxd][main] using OpenFlow version-bitmap:" << std::endl
            << versionbitmap;

  // start netlink
  rofcore::nbi *nbi = &rofcore::cnetlink::get_instance();
  // XXX FIXME move tap_manager here
  std::unique_ptr<basebox::cbasebox> box(
      new basebox::cbasebox(nbi, versionbitmap));

  rofl::csockaddr baddr(AF_INET, std::string("0.0.0.0"),
                        FLAGS_port);
  box->dpt_sock_listen(baddr);

  while (basebox::cbasebox::running()) {
    try {
      // Launch main I/O loop
      struct timeval tv;
      tv.tv_sec = 10;
      tv.tv_usec = 0;
      select(0, NULL, NULL, NULL, &tv);

    } catch (std::exception &e) {
      std::cerr << "exception caught, what: " << e.what() << std::endl;
    }
  }

  return EXIT_SUCCESS;
}
<commit_msg>fix gflags namespaces<commit_after>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

#include <gflags/gflags.h>
#include <glog/logging.h>

#include "roflibs/netlink/cnetlink.hpp"
#include "roflibs/of-dpa/cbasebox.hpp"

static bool validate_port(const char *flagname, gflags::int32 value) {
  if (value > 0 && value < 32768) // value is ok
    return true;
  return false;
}

DEFINE_int32(port, 6653, "Listening port");

int main(int argc, char **argv) {

  if (!gflags::RegisterFlagValidator(&FLAGS_port, &validate_port)) {
    std::cerr << "Failed to register port validator" << std::endl;
    exit(1);
  }

  gflags::SetUsageMessage("");
  gflags::SetVersionString(PACKAGE_VERSION);

  gflags::ParseCommandLineFlags(&argc, &argv, true);
  google::InitGoogleLogging(argv[0]);

  rofl::openflow::cofhello_elem_versionbitmap versionbitmap;
  versionbitmap.add_ofp_version(rofl::openflow13::OFP_VERSION);
  LOG(INFO) << "[baseboxd][main] using OpenFlow version-bitmap:" << std::endl
            << versionbitmap;

  // start netlink
  rofcore::nbi *nbi = &rofcore::cnetlink::get_instance();
  // XXX FIXME move tap_manager here
  std::unique_ptr<basebox::cbasebox> box(
      new basebox::cbasebox(nbi, versionbitmap));

  rofl::csockaddr baddr(AF_INET, std::string("0.0.0.0"),
                        FLAGS_port);
  box->dpt_sock_listen(baddr);

  while (basebox::cbasebox::running()) {
    try {
      // Launch main I/O loop
      struct timeval tv;
      tv.tv_sec = 10;
      tv.tv_usec = 0;
      select(0, NULL, NULL, NULL, &tv);

    } catch (std::exception &e) {
      std::cerr << "exception caught, what: " << e.what() << std::endl;
    }
  }

  return EXIT_SUCCESS;
}
<|endoftext|>


<commit_before>#define DEBUG 1
/**
 * File    : E.cpp
 * Author  : Kazune Takahashi
 * Created : 6/19/2020, 12:05:05 AM
 * Powered by Visual Studio Code
 */
#include <algorithm>
#include <bitset>
#include <cassert>
#include <cctype>
#include <chrono>
#include <climits>
#include <cmath>
#include <complex>
#include <cstdint>
#include <cstdio>
#include <cstdlib>
#include <functional>
#include <iomanip>
#include <iostream>
#include <limits>
#include <map>
#include <queue>
#include <random>
#include <set>
#include <stack>
#include <string>
#include <tuple>
#include <unordered_map>
#include <unordered_set>
#include <vector>
// ----- boost -----
#include <boost/integer/common_factor_rt.hpp>
#include <boost/multiprecision/cpp_int.hpp>
#include <boost/rational.hpp>
// ----- using directives and manipulations -----
using namespace std;
using boost::rational;
using boost::integer::gcd; // for C++14 or for cpp_int
using boost::integer::lcm; // for C++14 or for cpp_int
using boost::multiprecision::cpp_int;
using ll = long long;
using ld = long double;
template <typename T>
using max_heap = priority_queue<T>;
template <typename T>
using min_heap = priority_queue<T, vector<T>, greater<T>>;
// ----- constexpr for Mint and Combination -----
constexpr ll MOD{1'000'000'007LL};
// constexpr ll MOD{998'244'353LL}; // be careful
constexpr ll MAX_SIZE{3'000'010LL};
// constexpr ll MAX_SIZE{30'000'010LL}; // if 10^7 is needed
// ----- ch_max and ch_min -----
template <typename T>
bool ch_max(T &left, T right)
{
  if (left < right)
  {
    left = right;
    return true;
  }
  return false;
}
template <typename T>
bool ch_min(T &left, T right)
{
  if (left > right)
  {
    left = right;
    return true;
  }
  return false;
}
// ----- Mint -----
template <ll MOD = MOD>
class Mint
{
public:
  ll x;
  Mint() : x{0LL} {}
  Mint(ll x) : x{(x % MOD + MOD) % MOD} {}
  Mint operator-() const { return x ? MOD - x : 0; }
  Mint &operator+=(Mint const &a)
  {
    if ((x += a.x) >= MOD)
    {
      x -= MOD;
    }
    return *this;
  }
  Mint &operator-=(Mint const &a) { return *this += -a; }
  Mint &operator++() { return *this += 1; }
  Mint operator++(int)
  {
    Mint tmp{*this};
    ++*this;
    return tmp;
  }
  Mint &operator--() { return *this -= 1; }
  Mint operator--(int)
  {
    Mint tmp{*this};
    --*this;
    return tmp;
  }
  Mint &operator*=(Mint const &a)
  {
    (x *= a.x) %= MOD;
    return *this;
  }
  Mint &operator/=(Mint const &a)
  {
    Mint b{a};
    return *this *= b.power(MOD - 2);
  }
  Mint operator+(Mint const &a) const { return Mint(*this) += a; }
  Mint operator-(Mint const &a) const { return Mint(*this) -= a; }
  Mint operator*(Mint const &a) const { return Mint(*this) *= a; }
  Mint operator/(Mint const &a) const { return Mint(*this) /= a; }
  bool operator<(Mint const &a) const { return x < a.x; }
  bool operator<=(Mint const &a) const { return x <= a.x; }
  bool operator>(Mint const &a) const { return x > a.x; }
  bool operator>=(Mint const &a) const { return x >= a.x; }
  bool operator==(Mint const &a) const { return x == a.x; }
  bool operator!=(Mint const &a) const { return !(*this == a); }
  Mint power(ll N) const
  {
    if (N == 0)
    {
      return 1;
    }
    else if (N % 2 == 1)
    {
      return *this * power(N - 1);
    }
    else
    {
      Mint half = power(N / 2);
      return half * half;
    }
  }
};
template <ll MOD>
Mint<MOD> operator+(ll lhs, Mint<MOD> const &rhs) { return rhs + lhs; }
template <ll MOD>
Mint<MOD> operator-(ll lhs, Mint<MOD> const &rhs) { return -rhs + lhs; }
template <ll MOD>
Mint<MOD> operator*(ll lhs, Mint<MOD> const &rhs) { return rhs * lhs; }
template <ll MOD>
Mint<MOD> operator/(ll lhs, Mint<MOD> const &rhs) { return Mint<MOD>{lhs} / rhs; }
template <ll MOD>
istream &operator>>(istream &stream, Mint<MOD> &a) { return stream >> a.x; }
template <ll MOD>
ostream &operator<<(ostream &stream, Mint<MOD> const &a) { return stream << a.x; }
// ----- Combination -----
template <ll MOD = MOD, ll MAX_SIZE = MAX_SIZE>
class Combination
{
public:
  vector<Mint<MOD>> inv, fact, factinv;
  Combination() : inv(MAX_SIZE), fact(MAX_SIZE), factinv(MAX_SIZE)
  {
    inv[1] = 1;
    for (auto i{2LL}; i < MAX_SIZE; i++)
    {
      inv[i] = (-inv[MOD % i]) * (MOD / i);
    }
    fact[0] = factinv[0] = 1;
    for (auto i{1LL}; i < MAX_SIZE; i++)
    {
      fact[i] = Mint<MOD>(i) * fact[i - 1];
      factinv[i] = inv[i] * factinv[i - 1];
    }
  }
  Mint<MOD> operator()(int n, int k)
  {
    if (n >= 0 && k >= 0 && n - k >= 0)
    {
      return fact[n] * factinv[k] * factinv[n - k];
    }
    return 0;
  }
  Mint<MOD> catalan(int x, int y)
  {
    return (*this)(x + y, y) - (*this)(x + y, y - 1);
  }
};
// ----- for C++14 -----
using mint = Mint<MOD>;
using combination = Combination<MOD, MAX_SIZE>;
// ----- for C++17 -----
template <typename T, typename enable_if<is_integral<T>::value>::type * = nullptr>
size_t popcount(T x) { return bitset<64>(x).count(); }
size_t popcount(string const &S) { return bitset<200010>{S}.count(); }
// ----- Infty -----
template <typename T>
constexpr T Infty() { return numeric_limits<T>::max(); }
template <typename T>
constexpr T mInfty() { return numeric_limits<T>::min(); }
// ----- frequently used constexpr -----
// constexpr double epsilon{1e-10};
// constexpr ll infty{1'000'000'000'000'010LL}; // or
// constexpr int infty{1'000'000'010};
// constexpr int dx[4] = {1, 0, -1, 0};
// constexpr int dy[4] = {0, 1, 0, -1};
// ----- Yes() and No() -----
void Yes()
{
  cout << "Yes" << endl;
  exit(0);
}
void No()
{
  cout << "No" << endl;
  exit(0);
}

// ----- Solve -----

class Solve
{
  ll N, P;
  string S;

public:
  Solve(ll N, ll P, string S) : N{N}, P{P}, S{S}
  {
    reverse(S.begin(), S.end());
  }

  void flush()
  {
    vector<ll> V(P, 0);
    V[0] = 1;
    ll base{1};
    ll ans{0};
    ll now{0};
    for (auto i{0}; i < N; ++i)
    {
      now += (base * static_cast<ll>(S[i] - '0')) % P;
      now %= P;
      ans += V[now];
      V[now]++;
      base *= 10;
      base %= P;
    }
    cout << ans << endl;
  }

private:
};

// ----- main() -----

int main()
{
  ll N, P;
  string S;
  cin >> N >> P >> S;
  if (P == 2 || P == 5)
  {
    ll ans{0};
    for (auto i{0LL}; i < N; ++i)
    {
      if ((S[i] - '0') % P == 0)
      {
        ans += i + 1;
      }
    }
    cout << ans << endl;
  }
  else
  {
    Solve solve(N, P, S);
    solve.flush();
  }
}
<commit_msg>tried E.cpp to 'E'<commit_after>#define DEBUG 1
/**
 * File    : E.cpp
 * Author  : Kazune Takahashi
 * Created : 6/19/2020, 12:05:05 AM
 * Powered by Visual Studio Code
 */
#include <algorithm>
#include <bitset>
#include <cassert>
#include <cctype>
#include <chrono>
#include <climits>
#include <cmath>
#include <complex>
#include <cstdint>
#include <cstdio>
#include <cstdlib>
#include <functional>
#include <iomanip>
#include <iostream>
#include <limits>
#include <map>
#include <queue>
#include <random>
#include <set>
#include <stack>
#include <string>
#include <tuple>
#include <unordered_map>
#include <unordered_set>
#include <vector>
// ----- boost -----
#include <boost/integer/common_factor_rt.hpp>
#include <boost/multiprecision/cpp_int.hpp>
#include <boost/rational.hpp>
// ----- using directives and manipulations -----
using namespace std;
using boost::rational;
using boost::integer::gcd; // for C++14 or for cpp_int
using boost::integer::lcm; // for C++14 or for cpp_int
using boost::multiprecision::cpp_int;
using ll = long long;
using ld = long double;
template <typename T>
using max_heap = priority_queue<T>;
template <typename T>
using min_heap = priority_queue<T, vector<T>, greater<T>>;
// ----- constexpr for Mint and Combination -----
constexpr ll MOD{1'000'000'007LL};
// constexpr ll MOD{998'244'353LL}; // be careful
constexpr ll MAX_SIZE{3'000'010LL};
// constexpr ll MAX_SIZE{30'000'010LL}; // if 10^7 is needed
// ----- ch_max and ch_min -----
template <typename T>
bool ch_max(T &left, T right)
{
  if (left < right)
  {
    left = right;
    return true;
  }
  return false;
}
template <typename T>
bool ch_min(T &left, T right)
{
  if (left > right)
  {
    left = right;
    return true;
  }
  return false;
}
// ----- Mint -----
template <ll MOD = MOD>
class Mint
{
public:
  ll x;
  Mint() : x{0LL} {}
  Mint(ll x) : x{(x % MOD + MOD) % MOD} {}
  Mint operator-() const { return x ? MOD - x : 0; }
  Mint &operator+=(Mint const &a)
  {
    if ((x += a.x) >= MOD)
    {
      x -= MOD;
    }
    return *this;
  }
  Mint &operator-=(Mint const &a) { return *this += -a; }
  Mint &operator++() { return *this += 1; }
  Mint operator++(int)
  {
    Mint tmp{*this};
    ++*this;
    return tmp;
  }
  Mint &operator--() { return *this -= 1; }
  Mint operator--(int)
  {
    Mint tmp{*this};
    --*this;
    return tmp;
  }
  Mint &operator*=(Mint const &a)
  {
    (x *= a.x) %= MOD;
    return *this;
  }
  Mint &operator/=(Mint const &a)
  {
    Mint b{a};
    return *this *= b.power(MOD - 2);
  }
  Mint operator+(Mint const &a) const { return Mint(*this) += a; }
  Mint operator-(Mint const &a) const { return Mint(*this) -= a; }
  Mint operator*(Mint const &a) const { return Mint(*this) *= a; }
  Mint operator/(Mint const &a) const { return Mint(*this) /= a; }
  bool operator<(Mint const &a) const { return x < a.x; }
  bool operator<=(Mint const &a) const { return x <= a.x; }
  bool operator>(Mint const &a) const { return x > a.x; }
  bool operator>=(Mint const &a) const { return x >= a.x; }
  bool operator==(Mint const &a) const { return x == a.x; }
  bool operator!=(Mint const &a) const { return !(*this == a); }
  Mint power(ll N) const
  {
    if (N == 0)
    {
      return 1;
    }
    else if (N % 2 == 1)
    {
      return *this * power(N - 1);
    }
    else
    {
      Mint half = power(N / 2);
      return half * half;
    }
  }
};
template <ll MOD>
Mint<MOD> operator+(ll lhs, Mint<MOD> const &rhs) { return rhs + lhs; }
template <ll MOD>
Mint<MOD> operator-(ll lhs, Mint<MOD> const &rhs) { return -rhs + lhs; }
template <ll MOD>
Mint<MOD> operator*(ll lhs, Mint<MOD> const &rhs) { return rhs * lhs; }
template <ll MOD>
Mint<MOD> operator/(ll lhs, Mint<MOD> const &rhs) { return Mint<MOD>{lhs} / rhs; }
template <ll MOD>
istream &operator>>(istream &stream, Mint<MOD> &a) { return stream >> a.x; }
template <ll MOD>
ostream &operator<<(ostream &stream, Mint<MOD> const &a) { return stream << a.x; }
// ----- Combination -----
template <ll MOD = MOD, ll MAX_SIZE = MAX_SIZE>
class Combination
{
public:
  vector<Mint<MOD>> inv, fact, factinv;
  Combination() : inv(MAX_SIZE), fact(MAX_SIZE), factinv(MAX_SIZE)
  {
    inv[1] = 1;
    for (auto i{2LL}; i < MAX_SIZE; i++)
    {
      inv[i] = (-inv[MOD % i]) * (MOD / i);
    }
    fact[0] = factinv[0] = 1;
    for (auto i{1LL}; i < MAX_SIZE; i++)
    {
      fact[i] = Mint<MOD>(i) * fact[i - 1];
      factinv[i] = inv[i] * factinv[i - 1];
    }
  }
  Mint<MOD> operator()(int n, int k)
  {
    if (n >= 0 && k >= 0 && n - k >= 0)
    {
      return fact[n] * factinv[k] * factinv[n - k];
    }
    return 0;
  }
  Mint<MOD> catalan(int x, int y)
  {
    return (*this)(x + y, y) - (*this)(x + y, y - 1);
  }
};
// ----- for C++14 -----
using mint = Mint<MOD>;
using combination = Combination<MOD, MAX_SIZE>;
// ----- for C++17 -----
template <typename T, typename enable_if<is_integral<T>::value>::type * = nullptr>
size_t popcount(T x) { return bitset<64>(x).count(); }
size_t popcount(string const &S) { return bitset<200010>{S}.count(); }
// ----- Infty -----
template <typename T>
constexpr T Infty() { return numeric_limits<T>::max(); }
template <typename T>
constexpr T mInfty() { return numeric_limits<T>::min(); }
// ----- frequently used constexpr -----
// constexpr double epsilon{1e-10};
// constexpr ll infty{1'000'000'000'000'010LL}; // or
// constexpr int infty{1'000'000'010};
// constexpr int dx[4] = {1, 0, -1, 0};
// constexpr int dy[4] = {0, 1, 0, -1};
// ----- Yes() and No() -----
void Yes()
{
  cout << "Yes" << endl;
  exit(0);
}
void No()
{
  cout << "No" << endl;
  exit(0);
}

// ----- Solve -----

class Solve
{
  ll N, P;
  string S;

public:
  Solve(ll N, ll P, string S) : N{N}, P{P}, S{S}
  {
    reverse(S.begin(), S.end());
  }

  void flush()
  {
    vector<ll> V(P, 0);
    V[0] = 1;
    ll base{1};
    ll ans{0};
    ll now{0};
    for (auto i{0}; i < N; ++i)
    {
      now += (base * static_cast<ll>(S[i] - '0')) % P;
      now %= P;
#if DEBUG == 1
      cerr << "now = " << now << endl;
#endif
      ans += V[now];
      V[now]++;
      base *= 10;
      base %= P;
    }
    cout << ans << endl;
  }

private:
};

// ----- main() -----

int main()
{
  ll N, P;
  string S;
  cin >> N >> P >> S;
  if (P == 2 || P == 5)
  {
    ll ans{0};
    for (auto i{0LL}; i < N; ++i)
    {
      if ((S[i] - '0') % P == 0)
      {
        ans += i + 1;
      }
    }
    cout << ans << endl;
  }
  else
  {
    Solve solve(N, P, S);
    solve.flush();
  }
}
<|endoftext|>


<commit_before>// Copyright (C) 2010-2014  CEA/DEN, EDF R&D
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2.1 of the License.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
//
// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
//

#include "vtkELNOSurfaceFilter.h"
#include "vtkInformation.h"
#include "vtkInformationVector.h"
#include "vtkObjectFactory.h"
#include "vtkPolyDataAlgorithm.h"
#include "vtkPolyData.h"
#include "vtkIdTypeArray.h"
#include "vtkInformationQuadratureSchemeDefinitionVectorKey.h"
#include "vtkQuadratureSchemeDefinition.h"
#include "vtkUnstructuredGrid.h"
#include "vtkPVGeometryFilter.h"
#include "vtkShrinkFilter.h"
#include "vtkSmartPointer.h"
#include "vtkPointData.h"
#include "vtkCellData.h"
#include "vtkIdList.h"

//vtkCxxRevisionMacro(vtkELNOSurfaceFilter, "$Revision$")
//;
vtkStandardNewMacro(vtkELNOSurfaceFilter)
;

vtkELNOSurfaceFilter::vtkELNOSurfaceFilter()
{
}

vtkELNOSurfaceFilter::~vtkELNOSurfaceFilter()
{
}

int vtkELNOSurfaceFilter::RequestData(vtkInformation *request,
    vtkInformationVector **input, vtkInformationVector *output)
{
  vtkUnstructuredGrid *usgIn=vtkUnstructuredGrid::SafeDownCast(
      input[0]->GetInformationObject(0)->Get(vtkDataObject::DATA_OBJECT()));

  vtkUnstructuredGrid *usgOut=vtkUnstructuredGrid::SafeDownCast(
      output->GetInformationObject(0)->Get(vtkDataObject::DATA_OBJECT()));

  vtkIdTypeArray* usg_offsets=vtkIdTypeArray::SafeDownCast(
      this->GetInputArrayToProcess(0, input));

  if(usgIn==NULL||usg_offsets==NULL||usgOut==NULL)
    {
    vtkDebugMacro("vtkELNOSurfaceFilter no correctly configured : offsets = " << usg_offsets);
    return 1;
    }

  // first shrink the input
  vtkUnstructuredGrid* usgInClone=usgIn->NewInstance();

  usgInClone->ShallowCopy(usgIn);

  vtkSmartPointer<vtkPVGeometryFilter> geomFilter=vtkSmartPointer<
      vtkPVGeometryFilter>::New();
  geomFilter->SetInputData(usgInClone);
  geomFilter->SetPassThroughCellIds(1);
  geomFilter->SetPassThroughPointIds(1);
  geomFilter->SetUseOutline(0);
  geomFilter->Update();

  vtkPolyData* surface=vtkPolyData::SafeDownCast(geomFilter->GetOutput());
  vtkIdTypeArray* originalCellIds=vtkIdTypeArray::SafeDownCast(
      surface->GetCellData()->GetArray("vtkOriginalCellIds"));
  vtkIdTypeArray* originalPointIds=vtkIdTypeArray::SafeDownCast(
      surface->GetPointData()->GetArray("vtkOriginalPointIds"));

  if( originalCellIds == NULL )
  {
    vtkErrorMacro("vtkPVGeometryFilter return NULL 'vtkOriginalCellIds' array");
    return 0;
  }

  if(originalPointIds==NULL)
  {
    vtkErrorMacro("vtkPVGeometryFilter return NULL 'vtkOriginalPointIds' array");
    return 0;
  }

  vtkSmartPointer<vtkShrinkFilter> shrink=
      vtkSmartPointer<vtkShrinkFilter>::New();
  shrink->SetInputConnection(geomFilter->GetOutputPort(0));
  shrink->SetShrinkFactor(0.9999);
  shrink->Update();

  vtkUnstructuredGrid* shrinked=shrink->GetOutput();

  usgInClone->Delete();

  usgOut->ShallowCopy(shrinked);

  vtkIdTypeArray* offsets=vtkIdTypeArray::SafeDownCast(
      shrinked->GetCellData()->GetArray(usg_offsets->GetName()));

  // now copy ELNO data. Start by verifying if it is possible to
  // shallow copy the array.
  vtkInformation *info=offsets->GetInformation();
  vtkInformationQuadratureSchemeDefinitionVectorKey *key=
      vtkQuadratureSchemeDefinition::DICTIONARY();
  if(!key->Has(info))
    {
    vtkDebugMacro("Dictionary is not present in array " << offsets->GetName()
                  << " " << offsets << " Aborting." );
    return 0;
    }
  int dictSize=key->Size(info);
  vtkQuadratureSchemeDefinition **dict=
      new vtkQuadratureSchemeDefinition *[dictSize];
  key->GetRange(info, dict, 0, 0, dictSize);

  vtkIdType ncell=shrinked->GetNumberOfCells();

  vtkFieldData* fielddata=usgIn->GetFieldData();
  vtkIdList *ids=vtkIdList::New();
  vtkIdList *surfaceIds=vtkIdList::New();
  vtkIdList *originalIds=vtkIdList::New();
  for(int index=0; index<fielddata->GetNumberOfArrays(); index++)
    {
    vtkDataArray* data=fielddata->GetArray(index);
    if(data==NULL)
      continue;

    vtkInformation* info=data->GetInformation();
    const char* arrayOffsetName=info->Get(
        vtkQuadratureSchemeDefinition::QUADRATURE_OFFSET_ARRAY_NAME());

    if(arrayOffsetName == NULL ||
       strcmp(arrayOffsetName, offsets->GetName())!=0)
      {
      usgOut->GetFieldData()->AddArray(data);

      continue;
      }

    vtkDataArray* newArray=data->NewInstance();
    newArray->SetName(data->GetName());
    usgOut->GetPointData()->AddArray(newArray);
    newArray->SetNumberOfComponents(data->GetNumberOfComponents());
    newArray->SetNumberOfTuples(usgOut->GetNumberOfPoints());
    newArray->CopyComponentNames(data);
    newArray->Delete();

    for(vtkIdType cellId=0; cellId<ncell; cellId++)
      {
      vtkIdType offset=offsets->GetValue(cellId);

      vtkIdType originalCellId=originalCellIds->GetValue(cellId);
      int originalCellType=usgIn->GetCellType(originalCellId);

      shrinked->GetCellPoints(cellId, ids);
      surface->GetCellPoints(cellId, surfaceIds);

      for(int id=0; id<ids->GetNumberOfIds(); id++)
        {
        vtkIdType surfaceId=surfaceIds->GetId(id);
        vtkIdType shrinkedId=ids->GetId(id);
        vtkIdType originalPointId = originalPointIds->GetValue(surfaceId);

        usgIn->GetCellPoints(originalCellId, originalIds);
        int originalLocalId=-1;
        for(int li=0; li<originalIds->GetNumberOfIds(); li++)
          {
          if(originalPointId==originalIds->GetId(li))
            {
            originalLocalId=li;
            break;
            }
          }
        if(originalLocalId==-1)
          {
          originalLocalId=0;
          vtkErrorMacro("cannot find original id");
          }

        const double * w=dict[originalCellType]->GetShapeFunctionWeights(
            originalLocalId);
        int j;
        for(j=0; j<dict[originalCellType]->GetNumberOfNodes(); j++)
          {
          if(w[j]==1.0)
            break;
          }
        if(j==dict[originalCellType]->GetNumberOfNodes())
          {
            //vtkErrorMacro("cannot find elno weigth.");
          j=id;
          }
        newArray->SetTuple(shrinkedId, offset+j, data);
        }
      }
    }

  ids->FastDelete();
  surfaceIds->FastDelete();
  originalIds->FastDelete();
  delete[] dict;

  return 1;
}

void vtkELNOSurfaceFilter::PrintSelf(ostream& os, vtkIndent indent)
{
  this->Superclass::PrintSelf(os, indent);
}
<commit_msg>Improve the clearness of the message in case of the ELNO surface filter is used instead of ELNO mesh for non 3D datasets.<commit_after>// Copyright (C) 2010-2014  CEA/DEN, EDF R&D
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2.1 of the License.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
//
// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
//

#include "vtkELNOSurfaceFilter.h"
#include "vtkInformation.h"
#include "vtkInformationVector.h"
#include "vtkObjectFactory.h"
#include "vtkPolyDataAlgorithm.h"
#include "vtkPolyData.h"
#include "vtkIdTypeArray.h"
#include "vtkInformationQuadratureSchemeDefinitionVectorKey.h"
#include "vtkQuadratureSchemeDefinition.h"
#include "vtkUnstructuredGrid.h"
#include "vtkPVGeometryFilter.h"
#include "vtkShrinkFilter.h"
#include "vtkSmartPointer.h"
#include "vtkPointData.h"
#include "vtkCellData.h"
#include "vtkIdList.h"

//vtkCxxRevisionMacro(vtkELNOSurfaceFilter, "$Revision$")
//;
vtkStandardNewMacro(vtkELNOSurfaceFilter)
;

vtkELNOSurfaceFilter::vtkELNOSurfaceFilter()
{
}

vtkELNOSurfaceFilter::~vtkELNOSurfaceFilter()
{
}

int vtkELNOSurfaceFilter::RequestData(vtkInformation *request, vtkInformationVector **input, vtkInformationVector *output)
{
  vtkUnstructuredGrid *usgIn=vtkUnstructuredGrid::SafeDownCast(
      input[0]->GetInformationObject(0)->Get(vtkDataObject::DATA_OBJECT()));

  vtkUnstructuredGrid *usgOut=vtkUnstructuredGrid::SafeDownCast(
      output->GetInformationObject(0)->Get(vtkDataObject::DATA_OBJECT()));

  vtkIdTypeArray* usg_offsets=vtkIdTypeArray::SafeDownCast(
      this->GetInputArrayToProcess(0, input));

  if(usgIn==NULL||usg_offsets==NULL||usgOut==NULL)
    {
    vtkDebugMacro("vtkELNOSurfaceFilter no correctly configured : offsets = " << usg_offsets);
    return 1;
    }

  // first shrink the input
  vtkUnstructuredGrid* usgInClone=usgIn->NewInstance();

  usgInClone->ShallowCopy(usgIn);

  vtkSmartPointer<vtkPVGeometryFilter> geomFilter=vtkSmartPointer<
      vtkPVGeometryFilter>::New();
  geomFilter->SetInputData(usgInClone);
  geomFilter->SetPassThroughCellIds(1);
  geomFilter->SetPassThroughPointIds(1);
  geomFilter->SetUseOutline(0);
  geomFilter->Update();

  vtkPolyData* surface=vtkPolyData::SafeDownCast(geomFilter->GetOutput());
  vtkIdTypeArray* originalCellIds=vtkIdTypeArray::SafeDownCast(
      surface->GetCellData()->GetArray("vtkOriginalCellIds"));
  vtkIdTypeArray* originalPointIds=vtkIdTypeArray::SafeDownCast(
      surface->GetPointData()->GetArray("vtkOriginalPointIds"));

  if( originalCellIds == NULL )
  {
    vtkErrorMacro("vtkPVGeometryFilter return NULL 'vtkOriginalCellIds' array");
    return 0;
  }

  if(originalPointIds==NULL)
  {
    vtkErrorMacro("It appears that your dataset is not reduced using vtkPVGeometryFilter (NULL 'vtkOriginalPointIds).\n==================================================================================================\nProbably your dataset is not 3D.\nIf it is not a 3D dataset you are expected to use ELNO Mesh filter instead of ELNO Surface filter.\n==================================================================================================\n");
    return 0;
  }

  vtkSmartPointer<vtkShrinkFilter> shrink=
      vtkSmartPointer<vtkShrinkFilter>::New();
  shrink->SetInputConnection(geomFilter->GetOutputPort(0));
  shrink->SetShrinkFactor(0.9999);
  shrink->Update();

  vtkUnstructuredGrid* shrinked=shrink->GetOutput();

  usgInClone->Delete();

  usgOut->ShallowCopy(shrinked);

  vtkIdTypeArray* offsets=vtkIdTypeArray::SafeDownCast(
      shrinked->GetCellData()->GetArray(usg_offsets->GetName()));

  // now copy ELNO data. Start by verifying if it is possible to
  // shallow copy the array.
  vtkInformation *info=offsets->GetInformation();
  vtkInformationQuadratureSchemeDefinitionVectorKey *key=
      vtkQuadratureSchemeDefinition::DICTIONARY();
  if(!key->Has(info))
    {
    vtkDebugMacro("Dictionary is not present in array " << offsets->GetName()
                  << " " << offsets << " Aborting." );
    return 0;
    }
  int dictSize=key->Size(info);
  vtkQuadratureSchemeDefinition **dict=
      new vtkQuadratureSchemeDefinition *[dictSize];
  key->GetRange(info, dict, 0, 0, dictSize);

  vtkIdType ncell=shrinked->GetNumberOfCells();

  vtkFieldData* fielddata=usgIn->GetFieldData();
  vtkIdList *ids=vtkIdList::New();
  vtkIdList *surfaceIds=vtkIdList::New();
  vtkIdList *originalIds=vtkIdList::New();
  for(int index=0; index<fielddata->GetNumberOfArrays(); index++)
    {
    vtkDataArray* data=fielddata->GetArray(index);
    if(data==NULL)
      continue;

    vtkInformation* info=data->GetInformation();
    const char* arrayOffsetName=info->Get(
        vtkQuadratureSchemeDefinition::QUADRATURE_OFFSET_ARRAY_NAME());

    if(arrayOffsetName == NULL ||
       strcmp(arrayOffsetName, offsets->GetName())!=0)
      {
      usgOut->GetFieldData()->AddArray(data);

      continue;
      }

    vtkDataArray* newArray=data->NewInstance();
    newArray->SetName(data->GetName());
    usgOut->GetPointData()->AddArray(newArray);
    newArray->SetNumberOfComponents(data->GetNumberOfComponents());
    newArray->SetNumberOfTuples(usgOut->GetNumberOfPoints());
    newArray->CopyComponentNames(data);
    newArray->Delete();

    for(vtkIdType cellId=0; cellId<ncell; cellId++)
      {
      vtkIdType offset=offsets->GetValue(cellId);

      vtkIdType originalCellId=originalCellIds->GetValue(cellId);
      int originalCellType=usgIn->GetCellType(originalCellId);

      shrinked->GetCellPoints(cellId, ids);
      surface->GetCellPoints(cellId, surfaceIds);

      for(int id=0; id<ids->GetNumberOfIds(); id++)
        {
        vtkIdType surfaceId=surfaceIds->GetId(id);
        vtkIdType shrinkedId=ids->GetId(id);
        vtkIdType originalPointId = originalPointIds->GetValue(surfaceId);

        usgIn->GetCellPoints(originalCellId, originalIds);
        int originalLocalId=-1;
        for(int li=0; li<originalIds->GetNumberOfIds(); li++)
          {
          if(originalPointId==originalIds->GetId(li))
            {
            originalLocalId=li;
            break;
            }
          }
        if(originalLocalId==-1)
          {
          originalLocalId=0;
          vtkErrorMacro("cannot find original id");
          }

        const double * w=dict[originalCellType]->GetShapeFunctionWeights(
            originalLocalId);
        int j;
        for(j=0; j<dict[originalCellType]->GetNumberOfNodes(); j++)
          {
          if(w[j]==1.0)
            break;
          }
        if(j==dict[originalCellType]->GetNumberOfNodes())
          {
            //vtkErrorMacro("cannot find elno weigth.");
          j=id;
          }
        newArray->SetTuple(shrinkedId, offset+j, data);
        }
      }
    }

  ids->FastDelete();
  surfaceIds->FastDelete();
  originalIds->FastDelete();
  delete[] dict;

  return 1;
}

void vtkELNOSurfaceFilter::PrintSelf(ostream& os, vtkIndent indent)
{
  this->Superclass::PrintSelf(os, indent);
}
<|endoftext|>


<commit_before>//=====================================================================//
/*!	@file
	@brief	R8C AD9833 サンプル
    @author 平松邦仁 (hira@rvf-rc45.net)
	@copyright	Copyright (C) 2018 Kunihito Hiramatsu @n
				Released under the MIT license @n
				https://github.com/hirakuni45/R8C/blob/master/LICENSE
*/
//=====================================================================//
#include "system.hpp"
#include "clock.hpp"
#include "common/delay.hpp"
#include "common/intr_utils.hpp"
#include "common/port_map.hpp"
#include "common/fifo.hpp"
#include "common/uart_io.hpp"
#include "common/trb_io.hpp"
#include "common/command.hpp"
#include "common/format.hpp"
#include "common/spi_io.hpp"
#include "chip/AD9833.hpp"

namespace {

//	typedef device::PORT<device::PORT1, device::bitpos::B3> LED;

	typedef device::trb_io<utils::null_task, uint8_t> timer_b;
	timer_b timer_b_;

	typedef utils::fifo<uint8_t, 16> buffer;
	typedef device::uart_io<device::UART0, buffer, buffer> uart;
	uart uart_;

	// P1_0(20):
	typedef device::PORT<device::PORT1, device::bitpos::B0> SPI_SDO;
	// P1_1(19):
	typedef device::PORT<device::PORT1, device::bitpos::B1> SPI_SCK;
	// P1_2(18):
	typedef device::PORT<device::PORT1, device::bitpos::B2> FSYNC;  // select

	typedef device::spi_io<device::NULL_PORT, SPI_SDO, SPI_SCK, device::soft_spi_mode::CK10> SPI;
	SPI		spi_;

	typedef chip::AD9833<SPI, FSYNC> AD9833;
	AD9833	ad9833_(spi_);

	utils::command<64> command_;
}

extern "C" {

	void sci_putch(char ch) {
		uart_.putch(ch);
	}

	char sci_getch(void) {
		return uart_.getch();
	}

	uint16_t sci_length() {
		return uart_.length();
	}

	void sci_puts(const char* str) {
		uart_.puts(str);
	}

	void TIMER_RB_intr(void) {
		timer_b_.itask();
	}

	void UART0_TX_intr(void) {
		uart_.isend();
	}

	void UART0_RX_intr(void) {
		uart_.irecv();
	}
}

//__attribute__ ((section (".exttext")))
int main(int argc, char *argv[])
{
	using namespace device;

// クロック関係レジスタ・プロテクト解除
	PRCR.PRC0 = 1;

// 高速オンチップオシレーターへ切り替え(20MHz)
// ※ F_CLK を設定する事（Makefile内）
	OCOCR.HOCOE = 1;
	utils::delay::micro_second(1);  // >=30us(125KHz)
	SCKCR.HSCKSEL = 1;
	CKSTPR.SCKSEL = 1;

	// タイマーＢ初期化
	{
		uint8_t ir_level = 2;
		timer_b_.start_timer(60, ir_level);
	}

	// UART の設定 (P1_4: TXD0[out], P1_5: RXD0[in])
	// ※シリアルライターでは、RXD 端子は、P1_6 となっているので注意！
	{
		utils::PORT_MAP(utils::port_map::P14::TXD0);
		utils::PORT_MAP(utils::port_map::P15::RXD0);
		uint8_t ir_level = 1;
		uart_.start(57600, ir_level);
	}

	{  // SPI 開始
		spi_.start(1000000);
	}

	{  // AD9833 開始
		ad9833_.start();
		ad9833_.setup(AD9833::WAVE_FORM::SINE,
///		ad9833_.setup(AD9833::WAVE_FORM::TRIANGLE,
///		ad9833_.setup(AD9833::WAVE_FORM::SQUARE,
			AD9833::REGISTERS::REG0, 1000.0f, AD9833::REGISTERS::REG1, 0.0f);
		ad9833_.enable_output();
	}

	utils::format("Start R8C AD9833 sample\n");
	command_.set_prompt("# ");

///	LED::DIR = 1;

	uint8_t cnt = 0;
	while(1) {
		timer_b_.sync();

		if(cnt >= 20) {
			cnt = 0;
		}
///		if(cnt < 10) LED::P = 1;
///		else LED::P = 0;
		++cnt;

		// コマンド入力と、コマンド解析
		if(command_.service()) {
			uint8_t cmdn = command_.get_words();
			if(cmdn >= 1) {
//				if(command_.cmp_word(0, "date")) {
//				} else if(command_.cmp_word(0, "help")) {
//					sci_puts("date\n");
//					sci_puts("date yyyy/mm/dd hh:mm[:ss]\n");
//				} else {
//					char buff[12];
//					if(command_.get_word(0, sizeof(buff), buff)) {
//						sci_puts("Command error: ");
//						sci_puts(buff);
//						sci_putch('\n');
//					}
//				}
			}
		}
	}
}
<commit_msg>update form/freq/help command<commit_after>//=====================================================================//
/*!	@file
	@brief	R8C AD9833 サンプル
    @author 平松邦仁 (hira@rvf-rc45.net)
	@copyright	Copyright (C) 2018 Kunihito Hiramatsu @n
				Released under the MIT license @n
				https://github.com/hirakuni45/R8C/blob/master/LICENSE
*/
//=====================================================================//
#include "system.hpp"
#include "clock.hpp"
#include "common/delay.hpp"
#include "common/intr_utils.hpp"
#include "common/port_map.hpp"
#include "common/fifo.hpp"
#include "common/uart_io.hpp"
#include "common/trb_io.hpp"
#include "common/command.hpp"
#include "common/format.hpp"
#include "common/input.hpp"
#include "common/spi_io.hpp"
#include "chip/AD9833.hpp"

// インジケーターＬＥＤ点滅を行う場合
// #define INDICATOR_LED

namespace {

#ifdef INDICATOR_LED
	typedef device::PORT<device::PORT1, device::bitpos::B3> LED;
#endif

	typedef device::trb_io<utils::null_task, uint8_t> timer_b;
	timer_b timer_b_;

	typedef utils::fifo<uint8_t, 16> buffer;
	typedef device::uart_io<device::UART0, buffer, buffer> uart;
	uart uart_;

	// P1_0(20):
	typedef device::PORT<device::PORT1, device::bitpos::B0> SPI_SDO;
	// P1_1(19):
	typedef device::PORT<device::PORT1, device::bitpos::B1> SPI_SCK;
	// P1_2(18):
	typedef device::PORT<device::PORT1, device::bitpos::B2> FSYNC;  // select

	typedef device::spi_io<device::NULL_PORT, SPI_SDO, SPI_SCK, device::soft_spi_mode::CK10> SPI;
	SPI		spi_;

	typedef chip::AD9833<SPI, FSYNC> AD9833;
	AD9833	ad9833_(spi_);

	AD9833::WAVE_FORM	form_;
	float				freq_;

	utils::command<64> command_;

	void setup_()
	{
		ad9833_.setup(form_, AD9833::REGISTERS::REG0, freq_, AD9833::REGISTERS::REG1, 0.0f);
	}
}

extern "C" {

	void sci_putch(char ch) {
		uart_.putch(ch);
	}

	char sci_getch(void) {
		return uart_.getch();
	}

	uint16_t sci_length() {
		return uart_.length();
	}

	void sci_puts(const char* str) {
		uart_.puts(str);
	}

	void TIMER_RB_intr(void) {
		timer_b_.itask();
	}

	void UART0_TX_intr(void) {
		uart_.isend();
	}

	void UART0_RX_intr(void) {
		uart_.irecv();
	}
}

//__attribute__ ((section (".exttext")))
int main(int argc, char *argv[])
{
	using namespace device;

// クロック関係レジスタ・プロテクト解除
	PRCR.PRC0 = 1;

// 高速オンチップオシレーターへ切り替え(20MHz)
// ※ F_CLK を設定する事（Makefile内）
	OCOCR.HOCOE = 1;
	utils::delay::micro_second(1);  // >=30us(125KHz)
	SCKCR.HSCKSEL = 1;
	CKSTPR.SCKSEL = 1;

	// タイマーＢ初期化
	{
		uint8_t ir_level = 2;
		timer_b_.start_timer(60, ir_level);
	}

	// UART の設定 (P1_4: TXD0[out], P1_5: RXD0[in])
	// ※シリアルライターでは、RXD 端子は、P1_6 となっているので注意！
	{
		utils::PORT_MAP(utils::port_map::P14::TXD0);
		utils::PORT_MAP(utils::port_map::P15::RXD0);
		uint8_t ir_level = 1;
		uart_.start(57600, ir_level);
	}

	{  // SPI 開始
		spi_.start(1000000);
	}

	{  // AD9833 開始
		ad9833_.start();
		form_ = AD9833::WAVE_FORM::SINE;
		freq_ = 1000.0f;
		setup_();
		ad9833_.enable_output();
	}

	utils::format("Start R8C AD9833 sample\n");
	command_.set_prompt("# ");

#ifdef INDICATOR_LED
	LED::DIR = 1;
	uint8_t cnt = 0;
#endif

	while(1) {
		timer_b_.sync();

#ifdef INDICATOR_LED
		++cnt;
		if(cnt >= 30) {
			cnt = 0;
		}
		if(cnt < 10) LED::P = 1;
		else LED::P = 0;
#endif

		// コマンド入力と、コマンド解析
		if(command_.service()) {
			bool error = false;
			char emsg[16];
			emsg[0] = 0;
			uint8_t cmdn = command_.get_words();
			if(cmdn >= 1) {
				if(command_.cmp_word(0, "form")) {
					if(cmdn == 1) {
						utils::format("form: ");
						switch(form_) {
						case AD9833::WAVE_FORM::SINE:
							utils::format("sin (SIN)\n");
							break;
						case AD9833::WAVE_FORM::TRIANGLE:
							utils::format("tri (TRIANGLE)\n");
							break;
						case AD9833::WAVE_FORM::SQUARE:
							utils::format("sqr (SQUARE)\n");
							break;
						default:
							break;
						}
					} else {
						if(command_.cmp_word(1, "sin")) form_ = AD9833::WAVE_FORM::SINE;
						else if(command_.cmp_word(1, "tri")) form_ = AD9833::WAVE_FORM::TRIANGLE;
						else if(command_.cmp_word(1, "sqr")) form_ = AD9833::WAVE_FORM::SQUARE;
						else {
							command_.get_word(1, sizeof(emsg), emsg);
							error = true;
						}
						if(!error) {
							setup_();
						}
					}
				} else if(command_.cmp_word(0, "freq")) {
					if(cmdn == 1) {
						utils::format("freq: %1.3f\n") % freq_;
					} else {
						float a = 0.0f;
						command_.get_word(1, sizeof(emsg), emsg);
						if((utils::input("%f", emsg) % a).status()) {
							freq_ = a;
							setup_();
						} else {
							error = true;
						}
					}
				} else if(command_.cmp_word(0, "help")) {
					utils::format("form [sin,tri,sqr]\n");
					utils::format("freq [xxxx(Hz)]\n");
				} else {
					command_.get_word(0, sizeof(emsg), emsg);
					error = true;
				}
				if(error) {
					utils::format("Command error: '%s'\n") % emsg;
				}
			}
		}
	}
}
<|endoftext|>


<commit_before>/*
 * Copyright (c) 2013 Juniper Networks, Inc. All rights reserved.
 */

#include <boost/foreach.hpp>
#include <boost/scoped_ptr.hpp>

#include "base/task_annotations.h"
#include "net/bgp_af.h"
#include "bgp/bgp_factory.h"
#include "bgp/bgp_log.h"
#include "bgp/bgp_peer.h"
#include "bgp/bgp_peer_close.h"
#include "bgp/bgp_peer_types.h"
#include "bgp/peer_close_manager.h"

using std::string;
using std::vector;

BgpPeerClose::BgpPeerClose(BgpPeer *peer)
        : peer_(peer), flap_count_(0) {
}

BgpPeerClose::~BgpPeerClose() {
}

PeerCloseManager *BgpPeerClose::GetManager() const {
    return peer_->close_manager();
}

void BgpPeerClose::CustomClose() {
    return peer_->CustomClose();
}

void BgpPeerClose::GracefulRestartStale() {
    negotiated_families_ = peer_->negotiated_families();
}

void BgpPeerClose::LongLivedGracefulRestartStale() {
}

void BgpPeerClose::GracefulRestartSweep() {
    negotiated_families_.clear();
}

bool BgpPeerClose::IsReady() const {
    return peer_->IsReady();
}

IPeer *BgpPeerClose::peer() const {
    return peer_;
}

// Return the time to wait for, in seconds to exit GR_TIMER state.
int BgpPeerClose::GetGracefulRestartTime() const {
    return gr_params_.time;
}

// Return the time to wait for, in seconds to exit LLGR_TIMER state.
int BgpPeerClose::GetLongLivedGracefulRestartTime() const {
    return llgr_params_.time;
}

void BgpPeerClose::ReceiveEndOfRIB(Address::Family family) {
    peer_->ReceiveEndOfRIB(family, 0);
}

const char *BgpPeerClose::GetTaskName() const {
    return "bgp::StateMachine";
}

int BgpPeerClose::GetTaskInstance() const {
    return peer_->GetTaskInstance();
}

void BgpPeerClose::MembershipRequestCallbackComplete() {
    CHECK_CONCURRENCY("bgp::StateMachine");
}

bool BgpPeerClose::IsGRHelperModeEnabled() const {
    return peer_->server()->IsGRHelperModeEnabled();
}

const std::vector<std::string> &BgpPeerClose::PeerNegotiatedFamilies() const {
    return peer_->negotiated_families();
}

bool BgpPeerClose::IsPeerDeleted() const {
    return peer_->IsDeleted();
}

bool BgpPeerClose::IsPeerAdminDown() const {
    return peer_->IsAdminDown();
}

bool BgpPeerClose::IsServerDeleted() const {
    return peer_->server()->IsDeleted();
}

bool BgpPeerClose::IsServerAdminDown() const {
    return peer_->server()->admin_down();
}

bool BgpPeerClose::IsInGRTimerWaitState() const {
    return GetManager()->IsInGRTimerWaitState();
}

bool BgpPeerClose::IsInLlgrTimerWaitState() const {
    return GetManager()->IsInLlgrTimerWaitState();
}

const std::vector<std::string> &BgpPeerClose::negotiated_families() const {
    return negotiated_families_;
}

const std::vector<BgpProto::OpenMessage::Capability *> &
BgpPeerClose::capabilities() const {
    return peer_->capabilities();
}

void BgpPeerClose::Close(bool non_graceful) {
    // Abort GR-Closure if this request is for non-graceful closure.
    // Reset GR-Closure if previous closure is still in progress or if
    // this is a flip (from established state).
    if (non_graceful || flap_count_ != peer_->total_flap_count()) {
        if (flap_count_ != peer_->total_flap_count()) {
            flap_count_++;
            assert(peer_->total_flap_count() == flap_count_);
        }
        GetManager()->Close(non_graceful);
        return;
    }

    // Ignore if close is already in progress.
    if (GetManager()->IsCloseInProgress() && !IsInGRTimerWaitState())
        return;

    if (peer_->IsDeleted()) {
        peer_->RetryDelete();
    } else {
        CustomClose();
        CloseComplete();
    }
}

void BgpPeerClose::Delete() {
    gr_params_.Initialize();
    llgr_params_.Initialize();
    gr_families_.clear();
    llgr_families_.clear();
    negotiated_families_.clear();
    if (peer_->IsDeleted()) {
        peer_->RetryDelete();
    } else {
        CloseComplete();
    }
}

bool BgpPeerClose::IsGRReady() const {
    // Check if GR Helper mode is disabled.
    if (!IsGRHelperModeEnabled()) {
        BGP_LOG_PEER(Message, peer_, SandeshLevel::SYS_DEBUG, BGP_LOG_FLAG_ALL,
            BGP_PEER_DIR_IN, "GR Helper mode is not enabled because it is not"
            " configured ");
        return false;
    }

    // Check if GR is supported by the peer.
    if (gr_params_.families.empty()) {
        BGP_LOG_PEER(Message, peer_, SandeshLevel::SYS_DEBUG, BGP_LOG_FLAG_ALL,
            BGP_PEER_DIR_IN, "GR Helper mode is not enabled because received "
            "GR address families list is empty");
        return false;
    }

    // Restart time must be non-zero in order to enable GR Helper mode.
    if (!gr_params_.time) {
        BGP_LOG_PEER(Message, peer_, SandeshLevel::SYS_DEBUG, BGP_LOG_FLAG_ALL,
            BGP_PEER_DIR_IN, "GR Helper mode is not enabled because received "
            "GR restart time value is 0 seconds");
        return false;
    }

    // Abort GR if currently negotiated families differ from already
    // staled address families.
    if (!negotiated_families().empty() &&
            PeerNegotiatedFamilies() != negotiated_families()) {
        BGP_LOG_PEER(Message, peer_, SandeshLevel::SYS_DEBUG, BGP_LOG_FLAG_ALL,
            BGP_PEER_DIR_IN, "GR Helper mode is aborted because received "
            "GR families list differs from the list received last time");
        return false;
    }

    // If GR is not supported for any of the negotiated address family,
    // then consider GR as not supported
    if (PeerNegotiatedFamilies() != gr_families_) {
        BGP_LOG_PEER(Message, peer_, SandeshLevel::SYS_DEBUG, BGP_LOG_FLAG_ALL,
            BGP_PEER_DIR_IN, "GR Helper mode is not enabled because GR address "
            "families differs from negotiated address families");
        return false;
    }

    // Make sure that forwarding state is preserved for all families in
    // the restarting speaker.
    BOOST_FOREACH(BgpProto::OpenMessage::Capability::GR::Family family,
                  gr_params_.families) {
        if (!family.forwarding_state_preserved()) {
            string family_str = Address::FamilyToString(BgpAf::AfiSafiToFamily(
                                                            family.afi,
                                                            family.safi));
            BGP_LOG_PEER(Message, peer_, SandeshLevel::SYS_DEBUG,
                BGP_LOG_FLAG_ALL, BGP_PEER_DIR_IN, "GR Helper mode is not  "
                "enabled because after restart, GR forwarding state is not "
                "preserved for address family " << family_str);
            return false;
        }
    }
    return true;
}

// If the peer is deleted or administratively held down, do not attempt
// graceful restart
bool BgpPeerClose::IsCloseGraceful() const {
    if (IsPeerDeleted()) {
        BGP_LOG_PEER(Message, peer_, SandeshLevel::SYS_DEBUG, BGP_LOG_FLAG_ALL,
            BGP_PEER_DIR_IN, "GR Helper mode is not enabled because BgpPeer has"
            " been deleted");
        return false;
    }

    if (IsPeerAdminDown()) {
        BGP_LOG_PEER(Message, peer_, SandeshLevel::SYS_DEBUG, BGP_LOG_FLAG_ALL,
            BGP_PEER_DIR_IN, "GR Helper mode is not enabled because BgpPeer has"
            "been held administratively down");
        return false;
    }

    if (IsServerDeleted()) {
        BGP_LOG_PEER(Message, peer_, SandeshLevel::SYS_DEBUG, BGP_LOG_FLAG_ALL,
            BGP_PEER_DIR_IN, "GR Helper mode is not enabled because BgpServer "
            "has been deletd");
        return false;
    }

    if (IsServerAdminDown()) {
        BGP_LOG_PEER(Message, peer_, SandeshLevel::SYS_DEBUG, BGP_LOG_FLAG_ALL,
            BGP_PEER_DIR_IN, "GR Helper mode is not enabled because BgpServer "
            "has been held administratively down");
        return false;
    }

    if (!IsGRReady())
        return false;
    return true;
}

// Check if we need to trigger Long Lived Graceful Restart. In addition to
// normal GR checks, we also need to check LLGR capability was negotiated
// and non-zero restart time was inferred.
bool BgpPeerClose::IsCloseLongLivedGraceful() const {
    if (!IsCloseGraceful())
        return false;

    if (llgr_params_.families.empty()) {
        BGP_LOG_PEER(Message, peer_, SandeshLevel::SYS_DEBUG, BGP_LOG_FLAG_ALL,
            BGP_PEER_DIR_IN,
            "No LLGR support due to empty LLGR address families list");
        return false;
    }
    if (!llgr_params_.time) {
        BGP_LOG_PEER(Message, peer_, SandeshLevel::SYS_DEBUG, BGP_LOG_FLAG_ALL,
            BGP_PEER_DIR_IN, "No LLGR support due to zero time value");
        return false;
    }

    // LLGR families should be identical to GR families.
    if (gr_families_ != llgr_families_) {
        BGP_LOG_PEER(Message, peer_, SandeshLevel::SYS_DEBUG, BGP_LOG_FLAG_ALL,
            BGP_PEER_DIR_IN, "No LLGR support due to dissimilar "
            "GR address families and LLGR address families");
        return false;
    }

    // Make sure that forwarding state is preserved for all families in
    // the restarting speaker.
    BOOST_FOREACH(BgpProto::OpenMessage::Capability::LLGR::Family family,
                  llgr_params_.families) {
        if (!family.forwarding_state_preserved()) {
            string family_str = Address::FamilyToString(BgpAf::AfiSafiToFamily(
                                                            family.afi,
                                                            family.safi));
            BGP_LOG_PEER(Message, peer_, SandeshLevel::SYS_DEBUG,
                BGP_LOG_FLAG_ALL, BGP_PEER_DIR_IN, "GR Helper mode is not  "
                "enabled because after restart, LLGR forwarding state is not "
                "preserved for address family " << family_str);
            return false;
        }
    }
    return true;
}

// Close process for this peer is complete. Restart the state machine and
// attempt to bring up session with the neighbor
void BgpPeerClose::CloseComplete() {
    if (!peer_->IsDeleted() && !peer_->IsAdminDown())
        peer_->state_machine()->Initialize();
}

void BgpPeerClose::GetGracefulRestartFamilies(Families *families) const {
    families->clear();
    BOOST_FOREACH(const string family, gr_families_) {
        families->insert(Address::FamilyFromString(family));
    }
}

void BgpPeerClose::AddGRCapabilities(
        BgpProto::OpenMessage::OptParam *opt_param) {
    vector<Address::Family> gr_families;
    vector<uint8_t> afi_flags;
    uint16_t time = peer_->server()->GetGracefulRestartTime();

    // Indicate EOR support by default.
    if (!time) {
        BgpProto::OpenMessage::Capability *gr_cap =
            BgpProto::OpenMessage::Capability::GR::Encode(0, 0, afi_flags,
                                                          gr_families);
        opt_param->capabilities.push_back(gr_cap);
        return;
    }

    BOOST_FOREACH(Address::Family family, peer_->supported_families()) {
        if (!peer_->LookupFamily(family))
            continue;
        gr_families.push_back(family);
        afi_flags.push_back(
            BgpProto::OpenMessage::Capability::GR::ForwardingStatePreserved);
    }

    uint8_t flags = 0;
    BgpProto::OpenMessage::Capability *gr_cap =
        BgpProto::OpenMessage::Capability::GR::Encode(time, flags, afi_flags,
                                                      gr_families);
    opt_param->capabilities.push_back(gr_cap);
}

// Process received GR and LLGR Capabilities. Return true if the values are sane
// to proceed with further processing. Return false if not to abort any ongoing
// GR and instead trigger non-graceful closure.
bool BgpPeerClose::SetGRCapabilities(BgpPeerInfoData *peer_info) {
    BgpProto::OpenMessage::Capability::GR::Decode(&gr_params_, capabilities());
    BgpProto::OpenMessage::Capability::GR::GetFamilies(gr_params_,
                                                       &gr_families_);

    BgpProto::OpenMessage::Capability::LLGR::Decode(&llgr_params_,
                                                    capabilities());
    BgpProto::OpenMessage::Capability::LLGR::GetFamilies(llgr_params_,
                                                         &llgr_families_);

    if (peer_info) {
        peer_info->set_graceful_restart_families(gr_families_);
        peer_info->set_long_lived_graceful_restart_families(llgr_families_);
        peer_info->set_graceful_restart_time(GetGracefulRestartTime());
        peer_info->set_long_lived_graceful_restart_time(
                GetLongLivedGracefulRestartTime());
        BGPPeerInfo::Send(*peer_info);
    }

    // If we are not in GR Timer waiting state, then there is no case to abort
    // GR when new session is coming up.
    if (!IsInGRTimerWaitState())
        return true;

    // If LLGR is no longer supported, terminate GR right away. This can happen
    // due to mis-match between gr and llgr afis. For now, we expect an
    // identical set.
    if (IsInLlgrTimerWaitState())
        return IsCloseLongLivedGraceful();
    return IsCloseGraceful();
}

void BgpPeerClose::AddLLGRCapabilities(
        BgpProto::OpenMessage::OptParam *opt_param) {
    if (!peer_->server()->GetGracefulRestartTime() ||
            !peer_->server()->GetLongLivedGracefulRestartTime())
        return;

    vector<Address::Family> llgr_families;
    BOOST_FOREACH(Address::Family family, peer_->supported_families()) {
        if (peer_->LookupFamily(family))
            llgr_families.push_back(family);
    }

    uint32_t time = peer_->server()->GetLongLivedGracefulRestartTime();
    uint8_t afi_flags =
        BgpProto::OpenMessage::Capability::LLGR::ForwardingStatePreserved;
    BgpProto::OpenMessage::Capability *llgr_cap =
        BgpProto::OpenMessage::Capability::LLGR::Encode(time, afi_flags,
                                                        llgr_families);
    opt_param->capabilities.push_back(llgr_cap);
}

void BgpPeerClose::FillNeighborInfo(BgpNeighborResp *bnr) const {
    bnr->set_graceful_restart_address_families(gr_families_);
    bnr->set_long_lived_graceful_restart_address_families(llgr_families_);
    bnr->set_graceful_restart_time(GetGracefulRestartTime());
    bnr->set_long_lived_graceful_restart_time(
            GetLongLivedGracefulRestartTime());
}
<commit_msg>Format GR log message with spaces in between words correctly<commit_after>/*
 * Copyright (c) 2013 Juniper Networks, Inc. All rights reserved.
 */

#include <boost/foreach.hpp>
#include <boost/scoped_ptr.hpp>

#include "base/task_annotations.h"
#include "net/bgp_af.h"
#include "bgp/bgp_factory.h"
#include "bgp/bgp_log.h"
#include "bgp/bgp_peer.h"
#include "bgp/bgp_peer_close.h"
#include "bgp/bgp_peer_types.h"
#include "bgp/peer_close_manager.h"

using std::string;
using std::vector;

BgpPeerClose::BgpPeerClose(BgpPeer *peer)
        : peer_(peer), flap_count_(0) {
}

BgpPeerClose::~BgpPeerClose() {
}

PeerCloseManager *BgpPeerClose::GetManager() const {
    return peer_->close_manager();
}

void BgpPeerClose::CustomClose() {
    return peer_->CustomClose();
}

void BgpPeerClose::GracefulRestartStale() {
    negotiated_families_ = peer_->negotiated_families();
}

void BgpPeerClose::LongLivedGracefulRestartStale() {
}

void BgpPeerClose::GracefulRestartSweep() {
    negotiated_families_.clear();
}

bool BgpPeerClose::IsReady() const {
    return peer_->IsReady();
}

IPeer *BgpPeerClose::peer() const {
    return peer_;
}

// Return the time to wait for, in seconds to exit GR_TIMER state.
int BgpPeerClose::GetGracefulRestartTime() const {
    return gr_params_.time;
}

// Return the time to wait for, in seconds to exit LLGR_TIMER state.
int BgpPeerClose::GetLongLivedGracefulRestartTime() const {
    return llgr_params_.time;
}

void BgpPeerClose::ReceiveEndOfRIB(Address::Family family) {
    peer_->ReceiveEndOfRIB(family, 0);
}

const char *BgpPeerClose::GetTaskName() const {
    return "bgp::StateMachine";
}

int BgpPeerClose::GetTaskInstance() const {
    return peer_->GetTaskInstance();
}

void BgpPeerClose::MembershipRequestCallbackComplete() {
    CHECK_CONCURRENCY("bgp::StateMachine");
}

bool BgpPeerClose::IsGRHelperModeEnabled() const {
    return peer_->server()->IsGRHelperModeEnabled();
}

const std::vector<std::string> &BgpPeerClose::PeerNegotiatedFamilies() const {
    return peer_->negotiated_families();
}

bool BgpPeerClose::IsPeerDeleted() const {
    return peer_->IsDeleted();
}

bool BgpPeerClose::IsPeerAdminDown() const {
    return peer_->IsAdminDown();
}

bool BgpPeerClose::IsServerDeleted() const {
    return peer_->server()->IsDeleted();
}

bool BgpPeerClose::IsServerAdminDown() const {
    return peer_->server()->admin_down();
}

bool BgpPeerClose::IsInGRTimerWaitState() const {
    return GetManager()->IsInGRTimerWaitState();
}

bool BgpPeerClose::IsInLlgrTimerWaitState() const {
    return GetManager()->IsInLlgrTimerWaitState();
}

const std::vector<std::string> &BgpPeerClose::negotiated_families() const {
    return negotiated_families_;
}

const std::vector<BgpProto::OpenMessage::Capability *> &
BgpPeerClose::capabilities() const {
    return peer_->capabilities();
}

void BgpPeerClose::Close(bool non_graceful) {
    // Abort GR-Closure if this request is for non-graceful closure.
    // Reset GR-Closure if previous closure is still in progress or if
    // this is a flip (from established state).
    if (non_graceful || flap_count_ != peer_->total_flap_count()) {
        if (flap_count_ != peer_->total_flap_count()) {
            flap_count_++;
            assert(peer_->total_flap_count() == flap_count_);
        }
        GetManager()->Close(non_graceful);
        return;
    }

    // Ignore if close is already in progress.
    if (GetManager()->IsCloseInProgress() && !IsInGRTimerWaitState())
        return;

    if (peer_->IsDeleted()) {
        peer_->RetryDelete();
    } else {
        CustomClose();
        CloseComplete();
    }
}

void BgpPeerClose::Delete() {
    gr_params_.Initialize();
    llgr_params_.Initialize();
    gr_families_.clear();
    llgr_families_.clear();
    negotiated_families_.clear();
    if (peer_->IsDeleted()) {
        peer_->RetryDelete();
    } else {
        CloseComplete();
    }
}

bool BgpPeerClose::IsGRReady() const {
    // Check if GR Helper mode is disabled.
    if (!IsGRHelperModeEnabled()) {
        BGP_LOG_PEER(Message, peer_, SandeshLevel::SYS_DEBUG, BGP_LOG_FLAG_ALL,
            BGP_PEER_DIR_IN, "GR Helper mode is not enabled because it is not"
            " configured");
        return false;
    }

    // Check if GR is supported by the peer.
    if (gr_params_.families.empty()) {
        BGP_LOG_PEER(Message, peer_, SandeshLevel::SYS_DEBUG, BGP_LOG_FLAG_ALL,
            BGP_PEER_DIR_IN, "GR Helper mode is not enabled because received "
            "GR address families list is empty");
        return false;
    }

    // Restart time must be non-zero in order to enable GR Helper mode.
    if (!gr_params_.time) {
        BGP_LOG_PEER(Message, peer_, SandeshLevel::SYS_DEBUG, BGP_LOG_FLAG_ALL,
            BGP_PEER_DIR_IN, "GR Helper mode is not enabled because received "
            "GR restart time value is 0 seconds");
        return false;
    }

    // Abort GR if currently negotiated families differ from already
    // staled address families.
    if (!negotiated_families().empty() &&
            PeerNegotiatedFamilies() != negotiated_families()) {
        BGP_LOG_PEER(Message, peer_, SandeshLevel::SYS_DEBUG, BGP_LOG_FLAG_ALL,
            BGP_PEER_DIR_IN, "GR Helper mode is aborted because received "
            "GR families list differs from the list received last time");
        return false;
    }

    // If GR is not supported for any of the negotiated address family,
    // then consider GR as not supported
    if (PeerNegotiatedFamilies() != gr_families_) {
        BGP_LOG_PEER(Message, peer_, SandeshLevel::SYS_DEBUG, BGP_LOG_FLAG_ALL,
            BGP_PEER_DIR_IN, "GR Helper mode is not enabled because GR address "
            "families differs from negotiated address families");
        return false;
    }

    // Make sure that forwarding state is preserved for all families in
    // the restarting speaker.
    BOOST_FOREACH(BgpProto::OpenMessage::Capability::GR::Family family,
                  gr_params_.families) {
        if (!family.forwarding_state_preserved()) {
            string family_str = Address::FamilyToString(BgpAf::AfiSafiToFamily(
                                                            family.afi,
                                                            family.safi));
            BGP_LOG_PEER(Message, peer_, SandeshLevel::SYS_DEBUG,
                BGP_LOG_FLAG_ALL, BGP_PEER_DIR_IN, "GR Helper mode is not  "
                "enabled because after restart, GR forwarding state is not "
                "preserved for address family " << family_str);
            return false;
        }
    }
    return true;
}

// If the peer is deleted or administratively held down, do not attempt
// graceful restart
bool BgpPeerClose::IsCloseGraceful() const {
    if (IsPeerDeleted()) {
        BGP_LOG_PEER(Message, peer_, SandeshLevel::SYS_DEBUG, BGP_LOG_FLAG_ALL,
            BGP_PEER_DIR_IN, "GR Helper mode is not enabled because BgpPeer has"
            " been deleted");
        return false;
    }

    if (IsPeerAdminDown()) {
        BGP_LOG_PEER(Message, peer_, SandeshLevel::SYS_DEBUG, BGP_LOG_FLAG_ALL,
            BGP_PEER_DIR_IN, "GR Helper mode is not enabled because BgpPeer has"
            " been held administratively down");
        return false;
    }

    if (IsServerDeleted()) {
        BGP_LOG_PEER(Message, peer_, SandeshLevel::SYS_DEBUG, BGP_LOG_FLAG_ALL,
            BGP_PEER_DIR_IN, "GR Helper mode is not enabled because BgpServer "
            "has been deletd");
        return false;
    }

    if (IsServerAdminDown()) {
        BGP_LOG_PEER(Message, peer_, SandeshLevel::SYS_DEBUG, BGP_LOG_FLAG_ALL,
            BGP_PEER_DIR_IN, "GR Helper mode is not enabled because BgpServer "
            "has been held administratively down");
        return false;
    }

    if (!IsGRReady())
        return false;
    return true;
}

// Check if we need to trigger Long Lived Graceful Restart. In addition to
// normal GR checks, we also need to check LLGR capability was negotiated
// and non-zero restart time was inferred.
bool BgpPeerClose::IsCloseLongLivedGraceful() const {
    if (!IsCloseGraceful())
        return false;

    if (llgr_params_.families.empty()) {
        BGP_LOG_PEER(Message, peer_, SandeshLevel::SYS_DEBUG, BGP_LOG_FLAG_ALL,
            BGP_PEER_DIR_IN,
            "No LLGR support due to empty LLGR address families list");
        return false;
    }
    if (!llgr_params_.time) {
        BGP_LOG_PEER(Message, peer_, SandeshLevel::SYS_DEBUG, BGP_LOG_FLAG_ALL,
            BGP_PEER_DIR_IN, "No LLGR support due to zero time value");
        return false;
    }

    // LLGR families should be identical to GR families.
    if (gr_families_ != llgr_families_) {
        BGP_LOG_PEER(Message, peer_, SandeshLevel::SYS_DEBUG, BGP_LOG_FLAG_ALL,
            BGP_PEER_DIR_IN, "No LLGR support due to dissimilar "
            "GR address families and LLGR address families");
        return false;
    }

    // Make sure that forwarding state is preserved for all families in
    // the restarting speaker.
    BOOST_FOREACH(BgpProto::OpenMessage::Capability::LLGR::Family family,
                  llgr_params_.families) {
        if (!family.forwarding_state_preserved()) {
            string family_str = Address::FamilyToString(BgpAf::AfiSafiToFamily(
                                                            family.afi,
                                                            family.safi));
            BGP_LOG_PEER(Message, peer_, SandeshLevel::SYS_DEBUG,
                BGP_LOG_FLAG_ALL, BGP_PEER_DIR_IN, "GR Helper mode is not "
                "enabled because after restart, LLGR forwarding state is not "
                "preserved for address family " << family_str);
            return false;
        }
    }
    return true;
}

// Close process for this peer is complete. Restart the state machine and
// attempt to bring up session with the neighbor
void BgpPeerClose::CloseComplete() {
    if (!peer_->IsDeleted() && !peer_->IsAdminDown())
        peer_->state_machine()->Initialize();
}

void BgpPeerClose::GetGracefulRestartFamilies(Families *families) const {
    families->clear();
    BOOST_FOREACH(const string family, gr_families_) {
        families->insert(Address::FamilyFromString(family));
    }
}

void BgpPeerClose::AddGRCapabilities(
        BgpProto::OpenMessage::OptParam *opt_param) {
    vector<Address::Family> gr_families;
    vector<uint8_t> afi_flags;
    uint16_t time = peer_->server()->GetGracefulRestartTime();

    // Indicate EOR support by default.
    if (!time) {
        BgpProto::OpenMessage::Capability *gr_cap =
            BgpProto::OpenMessage::Capability::GR::Encode(0, 0, afi_flags,
                                                          gr_families);
        opt_param->capabilities.push_back(gr_cap);
        return;
    }

    BOOST_FOREACH(Address::Family family, peer_->supported_families()) {
        if (!peer_->LookupFamily(family))
            continue;
        gr_families.push_back(family);
        afi_flags.push_back(
            BgpProto::OpenMessage::Capability::GR::ForwardingStatePreserved);
    }

    uint8_t flags = 0;
    BgpProto::OpenMessage::Capability *gr_cap =
        BgpProto::OpenMessage::Capability::GR::Encode(time, flags, afi_flags,
                                                      gr_families);
    opt_param->capabilities.push_back(gr_cap);
}

// Process received GR and LLGR Capabilities. Return true if the values are sane
// to proceed with further processing. Return false if not to abort any ongoing
// GR and instead trigger non-graceful closure.
bool BgpPeerClose::SetGRCapabilities(BgpPeerInfoData *peer_info) {
    BgpProto::OpenMessage::Capability::GR::Decode(&gr_params_, capabilities());
    BgpProto::OpenMessage::Capability::GR::GetFamilies(gr_params_,
                                                       &gr_families_);

    BgpProto::OpenMessage::Capability::LLGR::Decode(&llgr_params_,
                                                    capabilities());
    BgpProto::OpenMessage::Capability::LLGR::GetFamilies(llgr_params_,
                                                         &llgr_families_);

    if (peer_info) {
        peer_info->set_graceful_restart_families(gr_families_);
        peer_info->set_long_lived_graceful_restart_families(llgr_families_);
        peer_info->set_graceful_restart_time(GetGracefulRestartTime());
        peer_info->set_long_lived_graceful_restart_time(
                GetLongLivedGracefulRestartTime());
        BGPPeerInfo::Send(*peer_info);
    }

    // If we are not in GR Timer waiting state, then there is no case to abort
    // GR when new session is coming up.
    if (!IsInGRTimerWaitState())
        return true;

    // If LLGR is no longer supported, terminate GR right away. This can happen
    // due to mis-match between gr and llgr afis. For now, we expect an
    // identical set.
    if (IsInLlgrTimerWaitState())
        return IsCloseLongLivedGraceful();
    return IsCloseGraceful();
}

void BgpPeerClose::AddLLGRCapabilities(
        BgpProto::OpenMessage::OptParam *opt_param) {
    if (!peer_->server()->GetGracefulRestartTime() ||
            !peer_->server()->GetLongLivedGracefulRestartTime())
        return;

    vector<Address::Family> llgr_families;
    BOOST_FOREACH(Address::Family family, peer_->supported_families()) {
        if (peer_->LookupFamily(family))
            llgr_families.push_back(family);
    }

    uint32_t time = peer_->server()->GetLongLivedGracefulRestartTime();
    uint8_t afi_flags =
        BgpProto::OpenMessage::Capability::LLGR::ForwardingStatePreserved;
    BgpProto::OpenMessage::Capability *llgr_cap =
        BgpProto::OpenMessage::Capability::LLGR::Encode(time, afi_flags,
                                                        llgr_families);
    opt_param->capabilities.push_back(llgr_cap);
}

void BgpPeerClose::FillNeighborInfo(BgpNeighborResp *bnr) const {
    bnr->set_graceful_restart_address_families(gr_families_);
    bnr->set_long_lived_graceful_restart_address_families(llgr_families_);
    bnr->set_graceful_restart_time(GetGracefulRestartTime());
    bnr->set_long_lived_graceful_restart_time(
            GetLongLivedGracefulRestartTime());
}
<|endoftext|>


<commit_before>/*
 *  Copyright (C) 2013 Stephen F. Booth <me@sbooth.org>
 *  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 Stephen F. Booth 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 COPYRIGHT
 *  HOLDER 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 <cstdlib>
#include <stdexcept>
#include <functional>

#include "AudioChannelLayout.h"

namespace {

	/*! @brief Get the size in bytes of an \c AudioChannelLayout with the specified number of channel descriptions */
	size_t GetChannelLayoutSize(UInt32 numberChannelDescriptions)
	{
		return offsetof(AudioChannelLayout, mChannelDescriptions) + (numberChannelDescriptions * sizeof(AudioChannelDescription));
	}

	/*!
	 * @brief Allocate an \c AudioChannelLayout
	 * @param numberChannelDescriptions The number of channel descriptions that will be stored in the channel layout
	 * @return An \c AudioChannelLayout
	 * @throws std::bad_alloc
	 */
	AudioChannelLayout * CreateChannelLayout(UInt32 numberChannelDescriptions)
	{
		size_t layoutSize = GetChannelLayoutSize(numberChannelDescriptions);
		AudioChannelLayout *channelLayout = (AudioChannelLayout *)malloc(layoutSize);
		if(nullptr == channelLayout)
			throw std::bad_alloc();

		memset(channelLayout, 0, layoutSize);

		return channelLayout;
	}

	/*! @brief Create a copy of \c rhs */
	AudioChannelLayout * CopyChannelLayout(const AudioChannelLayout *rhs)
	{
		if(nullptr == rhs)
			return nullptr;

		size_t layoutSize = GetChannelLayoutSize(rhs->mNumberChannelDescriptions);
		AudioChannelLayout *channelLayout = (AudioChannelLayout *)malloc(layoutSize);
		if(nullptr == channelLayout)
			throw std::bad_alloc();

		memcpy(channelLayout, rhs, layoutSize);

		return channelLayout;
	}

}

// Constants
const SFB::Audio::ChannelLayout SFB::Audio::ChannelLayout::Mono		= SFB::Audio::ChannelLayout::ChannelLayoutWithTag(kAudioChannelLayoutTag_Mono);
const SFB::Audio::ChannelLayout SFB::Audio::ChannelLayout::Stereo	= SFB::Audio::ChannelLayout::ChannelLayoutWithTag(kAudioChannelLayoutTag_Stereo);

SFB::Audio::ChannelLayout SFB::Audio::ChannelLayout::ChannelLayoutWithTag(AudioChannelLayoutTag layoutTag)
{
	auto channelLayout = ChannelLayout((UInt32)0);
	channelLayout.mChannelLayout->mChannelLayoutTag = layoutTag;
	return channelLayout;
}

SFB::Audio::ChannelLayout SFB::Audio::ChannelLayout::ChannelLayoutWithChannelLabels(std::vector<AudioChannelLabel> channelLabels)
{
	auto channelLayout = ChannelLayout((UInt32)channelLabels.size());

	channelLayout.mChannelLayout->mChannelLayoutTag = kAudioChannelLayoutTag_UseChannelDescriptions;
	channelLayout.mChannelLayout->mChannelBitmap = 0;

	channelLayout.mChannelLayout->mNumberChannelDescriptions = (UInt32)channelLabels.size();

	for(std::vector<AudioChannelLabel>::size_type i = 0; i != channelLabels.size(); ++i)
		channelLayout.mChannelLayout->mChannelDescriptions[i].mChannelLabel = channelLabels[i];

	return channelLayout;
}

SFB::Audio::ChannelLayout SFB::Audio::ChannelLayout::ChannelLayoutWithBitmap(UInt32 channelBitmap)
{
	auto channelLayout = ChannelLayout((UInt32)0);
	channelLayout.mChannelLayout->mChannelBitmap = channelBitmap;
	return channelLayout;
}

SFB::Audio::ChannelLayout::ChannelLayout()
	: mChannelLayout(nullptr, nullptr)
{}

SFB::Audio::ChannelLayout::ChannelLayout(UInt32 numberChannelDescriptions)
	: mChannelLayout(CreateChannelLayout(numberChannelDescriptions), ::free)
{}

SFB::Audio::ChannelLayout::ChannelLayout(const AudioChannelLayout *channelLayout)
	: mChannelLayout(CopyChannelLayout(channelLayout), ::free)
{}

SFB::Audio::ChannelLayout::ChannelLayout(ChannelLayout&& rhs)
	: mChannelLayout(std::move(rhs.mChannelLayout))
{}

SFB::Audio::ChannelLayout& SFB::Audio::ChannelLayout::operator=(ChannelLayout&& rhs)
{
	if(this != &rhs)
		mChannelLayout = std::move(rhs.mChannelLayout);
	return *this;
}

SFB::Audio::ChannelLayout::ChannelLayout(const ChannelLayout& rhs)
	: ChannelLayout()
{
	*this = rhs;
}

SFB::Audio::ChannelLayout& SFB::Audio::ChannelLayout::operator=(const ChannelLayout& rhs)
{
	if(this != &rhs) {
		if(!rhs)
			mChannelLayout.reset();
		else
			mChannelLayout = unique_AudioChannelLayout_ptr(CopyChannelLayout(rhs.mChannelLayout.get()), ::free);
	}

	return *this;
}

SFB::Audio::ChannelLayout& SFB::Audio::ChannelLayout::operator=(const AudioChannelLayout *rhs)
{
	if(nullptr == rhs)
		mChannelLayout.reset();
	else
		mChannelLayout = unique_AudioChannelLayout_ptr(CopyChannelLayout(rhs), ::free);

	return *this;
}

bool SFB::Audio::ChannelLayout::operator==(const ChannelLayout& rhs) const
{
	if(!mChannelLayout || !rhs.mChannelLayout)
		return false;

	const AudioChannelLayout *layouts [] = {
		rhs.GetACL(),
		GetACL()
	};

	UInt32 layoutsEqual = false;
	UInt32 propertySize = sizeof(layoutsEqual);
	OSStatus result = AudioFormatGetProperty(kAudioFormatProperty_AreChannelLayoutsEquivalent, sizeof(layouts), (void *)layouts, &propertySize, &layoutsEqual);

	if(noErr != result)
		return false;
		//LOGGER_ERR("org.sbooth.AudioEngine.Player", "AudioFormatGetProperty (kAudioFormatProperty_AreChannelLayoutsEquivalent) failed: " << result);

	return layoutsEqual;
}
<commit_msg>Two empty layouts should be equivalent<commit_after>/*
 *  Copyright (C) 2013 Stephen F. Booth <me@sbooth.org>
 *  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 Stephen F. Booth 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 COPYRIGHT
 *  HOLDER 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 <cstdlib>
#include <stdexcept>
#include <functional>

#include "AudioChannelLayout.h"

namespace {

	/*! @brief Get the size in bytes of an \c AudioChannelLayout with the specified number of channel descriptions */
	size_t GetChannelLayoutSize(UInt32 numberChannelDescriptions)
	{
		return offsetof(AudioChannelLayout, mChannelDescriptions) + (numberChannelDescriptions * sizeof(AudioChannelDescription));
	}

	/*!
	 * @brief Allocate an \c AudioChannelLayout
	 * @param numberChannelDescriptions The number of channel descriptions that will be stored in the channel layout
	 * @return An \c AudioChannelLayout
	 * @throws std::bad_alloc
	 */
	AudioChannelLayout * CreateChannelLayout(UInt32 numberChannelDescriptions)
	{
		size_t layoutSize = GetChannelLayoutSize(numberChannelDescriptions);
		AudioChannelLayout *channelLayout = (AudioChannelLayout *)malloc(layoutSize);
		if(nullptr == channelLayout)
			throw std::bad_alloc();

		memset(channelLayout, 0, layoutSize);

		return channelLayout;
	}

	/*! @brief Create a copy of \c rhs */
	AudioChannelLayout * CopyChannelLayout(const AudioChannelLayout *rhs)
	{
		if(nullptr == rhs)
			return nullptr;

		size_t layoutSize = GetChannelLayoutSize(rhs->mNumberChannelDescriptions);
		AudioChannelLayout *channelLayout = (AudioChannelLayout *)malloc(layoutSize);
		if(nullptr == channelLayout)
			throw std::bad_alloc();

		memcpy(channelLayout, rhs, layoutSize);

		return channelLayout;
	}

}

// Constants
const SFB::Audio::ChannelLayout SFB::Audio::ChannelLayout::Mono		= SFB::Audio::ChannelLayout::ChannelLayoutWithTag(kAudioChannelLayoutTag_Mono);
const SFB::Audio::ChannelLayout SFB::Audio::ChannelLayout::Stereo	= SFB::Audio::ChannelLayout::ChannelLayoutWithTag(kAudioChannelLayoutTag_Stereo);

SFB::Audio::ChannelLayout SFB::Audio::ChannelLayout::ChannelLayoutWithTag(AudioChannelLayoutTag layoutTag)
{
	auto channelLayout = ChannelLayout((UInt32)0);
	channelLayout.mChannelLayout->mChannelLayoutTag = layoutTag;
	return channelLayout;
}

SFB::Audio::ChannelLayout SFB::Audio::ChannelLayout::ChannelLayoutWithChannelLabels(std::vector<AudioChannelLabel> channelLabels)
{
	auto channelLayout = ChannelLayout((UInt32)channelLabels.size());

	channelLayout.mChannelLayout->mChannelLayoutTag = kAudioChannelLayoutTag_UseChannelDescriptions;
	channelLayout.mChannelLayout->mChannelBitmap = 0;

	channelLayout.mChannelLayout->mNumberChannelDescriptions = (UInt32)channelLabels.size();

	for(std::vector<AudioChannelLabel>::size_type i = 0; i != channelLabels.size(); ++i)
		channelLayout.mChannelLayout->mChannelDescriptions[i].mChannelLabel = channelLabels[i];

	return channelLayout;
}

SFB::Audio::ChannelLayout SFB::Audio::ChannelLayout::ChannelLayoutWithBitmap(UInt32 channelBitmap)
{
	auto channelLayout = ChannelLayout((UInt32)0);
	channelLayout.mChannelLayout->mChannelBitmap = channelBitmap;
	return channelLayout;
}

SFB::Audio::ChannelLayout::ChannelLayout()
	: mChannelLayout(nullptr, nullptr)
{}

SFB::Audio::ChannelLayout::ChannelLayout(UInt32 numberChannelDescriptions)
	: mChannelLayout(CreateChannelLayout(numberChannelDescriptions), ::free)
{}

SFB::Audio::ChannelLayout::ChannelLayout(const AudioChannelLayout *channelLayout)
	: mChannelLayout(CopyChannelLayout(channelLayout), ::free)
{}

SFB::Audio::ChannelLayout::ChannelLayout(ChannelLayout&& rhs)
	: mChannelLayout(std::move(rhs.mChannelLayout))
{}

SFB::Audio::ChannelLayout& SFB::Audio::ChannelLayout::operator=(ChannelLayout&& rhs)
{
	if(this != &rhs)
		mChannelLayout = std::move(rhs.mChannelLayout);
	return *this;
}

SFB::Audio::ChannelLayout::ChannelLayout(const ChannelLayout& rhs)
	: ChannelLayout()
{
	*this = rhs;
}

SFB::Audio::ChannelLayout& SFB::Audio::ChannelLayout::operator=(const ChannelLayout& rhs)
{
	if(this != &rhs) {
		if(!rhs)
			mChannelLayout.reset();
		else
			mChannelLayout = unique_AudioChannelLayout_ptr(CopyChannelLayout(rhs.mChannelLayout.get()), ::free);
	}

	return *this;
}

SFB::Audio::ChannelLayout& SFB::Audio::ChannelLayout::operator=(const AudioChannelLayout *rhs)
{
	if(nullptr == rhs)
		mChannelLayout.reset();
	else
		mChannelLayout = unique_AudioChannelLayout_ptr(CopyChannelLayout(rhs), ::free);

	return *this;
}

bool SFB::Audio::ChannelLayout::operator==(const ChannelLayout& rhs) const
{
	// Two empty channel layouts are considered equivalent
	if(!mChannelLayout && !rhs.mChannelLayout)
		return true;

	if(!mChannelLayout || !rhs.mChannelLayout)
		return false;

	const AudioChannelLayout *layouts [] = {
		rhs.GetACL(),
		GetACL()
	};

	UInt32 layoutsEqual = false;
	UInt32 propertySize = sizeof(layoutsEqual);
	OSStatus result = AudioFormatGetProperty(kAudioFormatProperty_AreChannelLayoutsEquivalent, sizeof(layouts), (void *)layouts, &propertySize, &layoutsEqual);

	if(noErr != result)
		return false;
		//LOGGER_ERR("org.sbooth.AudioEngine.Player", "AudioFormatGetProperty (kAudioFormatProperty_AreChannelLayoutsEquivalent) failed: " << result);

	return layoutsEqual;
}
<|endoftext|>