<commit_before>#define DEBUG 1
/**
 * File    : F.cpp
 * Author  : Kazune Takahashi
 * Created : 2020/6/23 5:42:51
 * 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);
}

// ----- ReadGraph -----
// Referring to ymatsux-san's source code: https://atcoder.jp/contests/abc138/submissions/7016619

struct Edge
{
  int src, dst, id, rev;
  // ll cost;
  Edge() {}
  Edge(int src, int dst, int id, int rev) : src{src}, dst{dst}, id{id}, rev{rev} {}

  void added_edge(vector<vector<Edge>> &V)
  {
    V[src].push_back(*this);
  }

  void added_rev(vector<vector<Edge>> &V)
  {
    V[dst].push_back(rev_edge());
  }

  Edge rev_edge()
  {
    Edge edge{*this};
    swap(edge.src, edge.dst);
    swap(edge.id, edge.rev);
    return edge;
  }
};

enum class GraphType
{
  Undirected,
  Directed,
  RevEdge,
};

tuple<vector<vector<Edge>>, vector<Edge>> ReadGraphWithEdges(int N, int M, GraphType type = GraphType::Undirected, bool is_one_indexed = true)
{
  vector<vector<Edge>> V(N);
  vector<Edge> E;
  for (auto i = 0; i < M; ++i)
  {
    int v, w;
    cin >> v >> w;
    if (is_one_indexed)
    {
      --v;
      --w;
    }
    switch (type)
    {
    case GraphType::Undirected:
    {
      Edge edge{v, w, static_cast<int>(E.size()), static_cast<int>(E.size())};
      edge.added_edge(V);
      edge.added_rev(V);
      E.push_back(edge);
      break;
    }
    case GraphType::Directed:
    {
      Edge edge{v, w, static_cast<int>(E.size()), static_cast<int>(E.size())};
      edge.added_edge(V);
      E.push_back(edge);
      break;
    }
    case GraphType::RevEdge:
    {
      Edge edge{v, w, static_cast<int>(E.size()), static_cast<int>(E.size()) + 1};
      edge.added_edge(V);
      edge.added_rev(V);
      E.push_back(edge);
      E.push_back(edge.rev_edge());
      break;
    }
    default:
      break;
    }
  }
  return make_tuple(V, E);
}

vector<vector<Edge>> ReadGraph(int N, int M, GraphType type = GraphType::Undirected, bool is_one_indexed = true)
{
  return get<0>(ReadGraphWithEdges(N, M, type, is_one_indexed));
}

tuple<vector<vector<Edge>>, vector<Edge>> ReadTreeWithEdges(int N, GraphType type = GraphType::Undirected, bool is_one_indexed = true)
{
  return ReadGraphWithEdges(N, N - 1, type, is_one_indexed);
}

vector<vector<Edge>> ReadTree(int N, GraphType type = GraphType::Undirected, bool is_one_indexed = true)
{
  return ReadGraph(N, N - 1, type, is_one_indexed);
}

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

chrono::system_clock::time_point time_start = chrono::system_clock::now();

void TimeStamp()
{
  cout << "Time: " << chrono::duration_cast<std::chrono::milliseconds>(chrono::system_clock::now() - time_start).count() << endl;
}

struct SubTree
{
  ll id, size;
};

class Solve
{
  ll N, id;
  vector<queue<SubTree>> Q;
  vector<ll> C;
  vector<vector<Edge>> V;
  vector<vector<ll>> S;
  vector<ll> color_to_count;

public:
  Solve(ll N) : N{N}, id{0}, Q(N), C(N), S(N), color_to_count(N, 0)
  {
    TimeStamp();
    for (auto i{0}; i < N; ++i)
    {
      cin >> C[i];
      C[i]--;
      color_to_count[C[i]]++;
    }
    V = ReadTree(N);
  }

  void flush()
  {
    dfs(3000);
    for (auto i{0}; i < N; ++i)
    {
      auto sum{accumulate(S[i].begin(), S[i].end(), 0)};
      S[i].push_back(N - sum - color_to_count[i]);
      ll ans{0};
      for (auto e : S[i])
      {
        ans += e * (e + 1) / 2;
      }
      cout << N * (N + 1) / 2 - ans << endl;
    }
  }

private:
  ll dfs(ll src = 0, ll parent = -1)
  {
    auto src_id{id++};
    auto &subtree_queue{Q[C[src]]};
    for (auto const &e : V[src])
    {
      if (e.dst == parent)
      {
        continue;
      }
      auto colorless_tree_size{dfs(e.dst, src)};
      while (!subtree_queue.empty() && subtree_queue.front().id > src_id)
      {
        colorless_tree_size -= subtree_queue.front().size;
        subtree_queue.pop();
      }
      S[C[src]].push_back(colorless_tree_size);
    }
    auto subtree_size{id - src_id};
    subtree_queue.push(SubTree{src_id, subtree_size});
    return subtree_size;
  }
};

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

int main()
{
  ll N;
  cin >> N;
  Solve solve(N);
  solve.flush();
}
<commit_msg>tried F.cpp to 'F'<commit_after>#define DEBUG 1
/**
 * File    : F.cpp
 * Author  : Kazune Takahashi
 * Created : 2020/6/23 5:42:51
 * 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);
}

// ----- ReadGraph -----
// Referring to ymatsux-san's source code: https://atcoder.jp/contests/abc138/submissions/7016619

struct Edge
{
  int src, dst, id, rev;
  // ll cost;
  Edge() {}
  Edge(int src, int dst, int id, int rev) : src{src}, dst{dst}, id{id}, rev{rev} {}

  void added_edge(vector<vector<Edge>> &V)
  {
    V[src].push_back(*this);
  }

  void added_rev(vector<vector<Edge>> &V)
  {
    V[dst].push_back(rev_edge());
  }

  Edge rev_edge()
  {
    Edge edge{*this};
    swap(edge.src, edge.dst);
    swap(edge.id, edge.rev);
    return edge;
  }
};

enum class GraphType
{
  Undirected,
  Directed,
  RevEdge,
};

tuple<vector<vector<Edge>>, vector<Edge>> ReadGraphWithEdges(int N, int M, GraphType type = GraphType::Undirected, bool is_one_indexed = true)
{
  vector<vector<Edge>> V(N);
  vector<Edge> E;
  for (auto i = 0; i < M; ++i)
  {
    int v, w;
    cin >> v >> w;
    if (is_one_indexed)
    {
      --v;
      --w;
    }
    switch (type)
    {
    case GraphType::Undirected:
    {
      Edge edge{v, w, static_cast<int>(E.size()), static_cast<int>(E.size())};
      edge.added_edge(V);
      edge.added_rev(V);
      E.push_back(edge);
      break;
    }
    case GraphType::Directed:
    {
      Edge edge{v, w, static_cast<int>(E.size()), static_cast<int>(E.size())};
      edge.added_edge(V);
      E.push_back(edge);
      break;
    }
    case GraphType::RevEdge:
    {
      Edge edge{v, w, static_cast<int>(E.size()), static_cast<int>(E.size()) + 1};
      edge.added_edge(V);
      edge.added_rev(V);
      E.push_back(edge);
      E.push_back(edge.rev_edge());
      break;
    }
    default:
      break;
    }
  }
  return make_tuple(V, E);
}

vector<vector<Edge>> ReadGraph(int N, int M, GraphType type = GraphType::Undirected, bool is_one_indexed = true)
{
  return get<0>(ReadGraphWithEdges(N, M, type, is_one_indexed));
}

tuple<vector<vector<Edge>>, vector<Edge>> ReadTreeWithEdges(int N, GraphType type = GraphType::Undirected, bool is_one_indexed = true)
{
  return ReadGraphWithEdges(N, N - 1, type, is_one_indexed);
}

vector<vector<Edge>> ReadTree(int N, GraphType type = GraphType::Undirected, bool is_one_indexed = true)
{
  return ReadGraph(N, N - 1, type, is_one_indexed);
}

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

chrono::system_clock::time_point time_start = chrono::system_clock::now();

void TimeStamp()
{
  cout << "Time: " << chrono::duration_cast<std::chrono::milliseconds>(chrono::system_clock::now() - time_start).count() << endl;
}

struct SubTree
{
  ll id, size;
};

class Solve
{
  ll N, id;
  vector<queue<SubTree>> Q;
  vector<ll> C;
  vector<vector<Edge>> V;
  vector<vector<ll>> S;
  vector<ll> color_to_count;

public:
  Solve(ll N) : N{N}, id{0}, Q(N), C(N), S(N), color_to_count(N, 0)
  {
    for (auto i{0}; i < N; ++i)
    {
      cin >> C[i];
      C[i]--;
      color_to_count[C[i]]++;
    }
    V = ReadTree(N);
  }

  void flush()
  {
    dfs(3000);
    for (auto i{0}; i < N; ++i)
    {
      auto sum{accumulate(S[i].begin(), S[i].end(), 0)};
      S[i].push_back(N - sum - color_to_count[i]);
      ll ans{0};
      for (auto e : S[i])
      {
        ans += e * (e + 1) / 2;
      }
      cout << N * (N + 1) / 2 - ans << endl;
    }
  }

private:
  ll dfs(ll src = 0, ll parent = -1)
  {
    auto src_id{id++};
    auto &subtree_queue{Q[C[src]]};
    for (auto const &e : V[src])
    {
      if (e.dst == parent)
      {
        continue;
      }
      auto colorless_tree_size{dfs(e.dst, src)};
      while (!subtree_queue.empty() && subtree_queue.front().id > src_id)
      {
        colorless_tree_size -= subtree_queue.front().size;
        subtree_queue.pop();
      }
      S[C[src]].push_back(colorless_tree_size);
    }
    auto subtree_size{id - src_id};
    subtree_queue.push(SubTree{src_id, subtree_size});
    return subtree_size;
  }
};

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

int main()
{
  ll N;
  cin >> N;
  Solve solve(N);
  solve.flush();
}
<|endoftext|>


<commit_before>#include <string>
#include <vector>
#include <list>
#include <map>
#include <set>
#include <deque>
#include <stack>
#include <bitset>
#include <algorithm>
#include <functional>
#include <numeric>
#include <utility>
#include <sstream>
#include <iostream>
#include <iomanip>
#include <cstdio>
#include <cmath>
#include <cstdlib>
#include <ctime>
#include <iterator>
#include <tuple>
#include <regex>
#include <array>
#include <valarray>
#define all(v)begin(v),end(v)
#define dump(v)copy(all(v),ostream_iterator<decltype(*v.begin())>(cout," "))
#define rg(i,a,b)for(int i=a,i##e=b;i<i##e;++i)
#define fr(i,n)for(int i=0,i##e=n;i<i##e;++i)
#define rf(i,n)for(int i=n-1;i>=0;--i)
#define ei(a,m)for(auto&a:m)if(int a##i=&a-&*begin(m)+1)if(--a##i,1)
#define sz(v)int(v.size())
#define sr(v)sort(all(v))
#define rs(v)sort(all(v),greater<int>())
#define rev(v)reverse(all(v))
#define eb emplace_back
#define stst stringstream
#define big numeric_limits<int>::max()
#define g(t,i)get<i>(t)
#define cb(v,w)copy(all(v),back_inserter(w))
#define uni(v)sort(all(v));v.erase(unique(all(v)),end(v))
#define vt(...)vector<tuple<__VA_ARGS__>>
#define smx(a,b)a=max(a,b)
#define smn(a,b)a=min(a,b)
#define words(w,q)vector<string>w;[&w](string&&s){stringstream u(s);string r;while(u>>r)w.eb(r);}(q);
#define digits(d,n,s)vector<int>d;[&d](int m){while(m)d.eb(m%s),m/=s;}(n);
typedef long long ll;
using namespace std;

struct Containers {
	int wastedSpace(vector <int> r, vector <int> packages) {
		int c = 0;
		ei(a, packages) {
			if (a > r[c]) {
				++c;
			} else {
				r[c] -= a;
			}
			dump(r); cout << endl;
		}
		int w = 0;
		ei(a, r) w += a;
		return w;
	}
};

// BEGIN KAWIGIEDIT TESTING
// Generated by KawigiEdit-pf 2.3.0
#include <iostream>
#include <string>
#include <vector>
#include <ctime>
#include <cmath>
using namespace std;
bool KawigiEdit_RunTest(int testNum, vector <int> p0, vector <int> p1, bool hasAnswer, int p2) {
	cout << "Test " << testNum << ": [" << "{";
	for (int i = 0; int(p0.size()) > i; ++i) {
		if (i > 0) {
			cout << ",";
		}
		cout << p0[i];
	}
	cout << "}" << "," << "{";
	for (int i = 0; int(p1.size()) > i; ++i) {
		if (i > 0) {
			cout << ",";
		}
		cout << p1[i];
	}
	cout << "}";
	cout << "]" << endl;
	Containers *obj;
	int answer;
	obj = new Containers();
	clock_t startTime = clock();
	answer = obj->wastedSpace(p0, p1);
	clock_t endTime = clock();
	delete obj;
	bool res;
	res = true;
	cout << "Time: " << double(endTime - startTime) / CLOCKS_PER_SEC << " seconds" << endl;
	if (hasAnswer) {
		cout << "Desired answer:" << endl;
		cout << "\t" << p2 << endl;
	}
	cout << "Your answer:" << endl;
	cout << "\t" << answer << endl;
	if (hasAnswer) {
		res = answer == p2;
	}
	if (!res) {
		cout << "DOESN'T MATCH!!!!" << endl;
	} else if (double(endTime - startTime) / CLOCKS_PER_SEC >= 2) {
		cout << "FAIL the timeout" << endl;
		res = false;
	} else if (hasAnswer) {
		cout << "Match :-)" << endl;
	} else {
		cout << "OK, but is it right?" << endl;
	}
	cout << "" << endl;
	return res;
}
int main() {
	bool all_right;
	bool disabled;
	bool tests_disabled;
	all_right = true;
	tests_disabled = false;

	vector <int> p0;
	vector <int> p1;
	int p2;

	// ----- test 0 -----
	disabled = false;
	p0 = {5,5,5};
	p1 = {5,5,5};
	p2 = 0;
	all_right = (disabled || KawigiEdit_RunTest(0, p0, p1, true, p2) ) && all_right;
	tests_disabled = tests_disabled || disabled;
	// ------------------

	// ----- test 1 -----
	disabled = false;
	p0 = {5,6,7};
	p1 = {5,5,5};
	p2 = 3;
	all_right = (disabled || KawigiEdit_RunTest(1, p0, p1, true, p2) ) && all_right;
	tests_disabled = tests_disabled || disabled;
	// ------------------

	// ----- test 2 -----
	disabled = false;
	p0 = {2,3,5};
	p1 = {3};
	p2 = 7;
	all_right = (disabled || KawigiEdit_RunTest(2, p0, p1, true, p2) ) && all_right;
	tests_disabled = tests_disabled || disabled;
	// ------------------

	// ----- test 3 -----
	disabled = false;
	p0 = {3,4,5,6};
	p1 = {3,3,3,3,3};
	p2 = 3;
	all_right = (disabled || KawigiEdit_RunTest(3, p0, p1, true, p2) ) && all_right;
	tests_disabled = tests_disabled || disabled;
	// ------------------

	if (all_right) {
		if (tests_disabled) {
			cout << "You're a stud (but some test cases were disabled)!" << endl;
		} else {
			cout << "You're a stud (at least on given cases)!" << endl;
		}
	} else {
		cout << "Some of the test cases had errors." << endl;
	}
	return 0;
}
// END KAWIGIEDIT TESTING
<commit_msg>Containers<commit_after>#include <string>
#include <vector>
#include <list>
#include <map>
#include <set>
#include <deque>
#include <stack>
#include <bitset>
#include <algorithm>
#include <functional>
#include <numeric>
#include <utility>
#include <sstream>
#include <iostream>
#include <iomanip>
#include <cstdio>
#include <cmath>
#include <cstdlib>
#include <ctime>
#include <iterator>
#include <tuple>
#include <regex>
#include <array>
#include <valarray>
#define all(v)begin(v),end(v)
#define dump(v)copy(all(v),ostream_iterator<decltype(*v.begin())>(cout," "))
#define rg(i,a,b)for(int i=a,i##e=b;i<i##e;++i)
#define fr(i,n)for(int i=0,i##e=n;i<i##e;++i)
#define rf(i,n)for(int i=n-1;i>=0;--i)
#define ei(a,m)for(auto&a:m)if(int a##i=&a-&*begin(m)+1)if(--a##i,1)
#define sz(v)int(v.size())
#define sr(v)sort(all(v))
#define rs(v)sort(all(v),greater<int>())
#define rev(v)reverse(all(v))
#define eb emplace_back
#define stst stringstream
#define big numeric_limits<int>::max()
#define g(t,i)get<i>(t)
#define cb(v,w)copy(all(v),back_inserter(w))
#define uni(v)sort(all(v));v.erase(unique(all(v)),end(v))
#define vt(...)vector<tuple<__VA_ARGS__>>
#define smx(a,b)a=max(a,b)
#define smn(a,b)a=min(a,b)
#define words(w,q)vector<string>w;[&w](string&&s){stringstream u(s);string r;while(u>>r)w.eb(r);}(q);
#define digits(d,n,s)vector<int>d;[&d](int m){while(m)d.eb(m%s),m/=s;}(n);
typedef long long ll;
using namespace std;

struct Containers {
	int wastedSpace(vector <int> r, vector <int> packages) {
		int c = 0;
		ei(a, packages) {
			while (a > r[c]) {
				++c;
			}
			r[c] -= a;
		}
		int w = 0;
		ei(a, r) w += a;
		return w;
	}
};

// BEGIN KAWIGIEDIT TESTING
// Generated by KawigiEdit-pf 2.3.0
#include <iostream>
#include <string>
#include <vector>
#include <ctime>
#include <cmath>
using namespace std;
bool KawigiEdit_RunTest(int testNum, vector <int> p0, vector <int> p1, bool hasAnswer, int p2) {
	cout << "Test " << testNum << ": [" << "{";
	for (int i = 0; int(p0.size()) > i; ++i) {
		if (i > 0) {
			cout << ",";
		}
		cout << p0[i];
	}
	cout << "}" << "," << "{";
	for (int i = 0; int(p1.size()) > i; ++i) {
		if (i > 0) {
			cout << ",";
		}
		cout << p1[i];
	}
	cout << "}";
	cout << "]" << endl;
	Containers *obj;
	int answer;
	obj = new Containers();
	clock_t startTime = clock();
	answer = obj->wastedSpace(p0, p1);
	clock_t endTime = clock();
	delete obj;
	bool res;
	res = true;
	cout << "Time: " << double(endTime - startTime) / CLOCKS_PER_SEC << " seconds" << endl;
	if (hasAnswer) {
		cout << "Desired answer:" << endl;
		cout << "\t" << p2 << endl;
	}
	cout << "Your answer:" << endl;
	cout << "\t" << answer << endl;
	if (hasAnswer) {
		res = answer == p2;
	}
	if (!res) {
		cout << "DOESN'T MATCH!!!!" << endl;
	} else if (double(endTime - startTime) / CLOCKS_PER_SEC >= 2) {
		cout << "FAIL the timeout" << endl;
		res = false;
	} else if (hasAnswer) {
		cout << "Match :-)" << endl;
	} else {
		cout << "OK, but is it right?" << endl;
	}
	cout << "" << endl;
	return res;
}
int main() {
	bool all_right;
	bool disabled;
	bool tests_disabled;
	all_right = true;
	tests_disabled = false;

	vector <int> p0;
	vector <int> p1;
	int p2;

	// ----- test 0 -----
	disabled = false;
	p0 = {5,5,5};
	p1 = {5,5,5};
	p2 = 0;
	all_right = (disabled || KawigiEdit_RunTest(0, p0, p1, true, p2) ) && all_right;
	tests_disabled = tests_disabled || disabled;
	// ------------------

	// ----- test 1 -----
	disabled = false;
	p0 = {5,6,7};
	p1 = {5,5,5};
	p2 = 3;
	all_right = (disabled || KawigiEdit_RunTest(1, p0, p1, true, p2) ) && all_right;
	tests_disabled = tests_disabled || disabled;
	// ------------------

	// ----- test 2 -----
	disabled = false;
	p0 = {2,3,5};
	p1 = {3};
	p2 = 7;
	all_right = (disabled || KawigiEdit_RunTest(2, p0, p1, true, p2) ) && all_right;
	tests_disabled = tests_disabled || disabled;
	// ------------------

	// ----- test 3 -----
	disabled = false;
	p0 = {3,4,5,6};
	p1 = {3,3,3,3,3};
	p2 = 3;
	all_right = (disabled || KawigiEdit_RunTest(3, p0, p1, true, p2) ) && all_right;
	tests_disabled = tests_disabled || disabled;
	// ------------------

	if (all_right) {
		if (tests_disabled) {
			cout << "You're a stud (but some test cases were disabled)!" << endl;
		} else {
			cout << "You're a stud (at least on given cases)!" << endl;
		}
	} else {
		cout << "Some of the test cases had errors." << endl;
	}
	return 0;
}
// END KAWIGIEDIT TESTING
<|endoftext|>


<commit_before>/*
 @ 0xCCCCCCCC
*/

int main()
{
    return 0;
}<commit_msg>CaptureCallStack: add quick test code.<commit_after>/*
 @ 0xCCCCCCCC
*/

#include <conio.h>

#include <iostream>

#include "stack_walker.h"

void CaptureCallStack()
{
    StackWalker callstack;
    callstack.OutputCallStack(std::cout);
}

void Func3(int& val)
{
    ++val;
    std::cout << val;
    CaptureCallStack();
}

void Func2(int& val)
{
    ++val;
    Func3(val);
}

void Func1(int& val)
{
    ++val;
    Func2(val);
}

int main()
{
    int i = 0;
    Func1(i);
    _getch();
    return 0;
}<|endoftext|>


<commit_before>/*
 * jcom.receivemaster
 * Manage jcom.receive instances
 * By Tim Place, Copyright  2007
 *
 * License: This code is licensed under the terms of the GNU LGPL
 * http://www.gnu.org/licenses/lgpl.html
 */

#include "ext.h"				// Max Header
#include "ext_obex.h"			// Max Object Extensions (attributes) Header
#include "commonsyms.h"			// Common symbols used by the Max 4.5 API
#include "jcom.core.h"
#include "jcom.sendreceive.h"

// Prototypes
void *receivemaster_new(t_symbol *msg, long argc, t_atom *argv);
void receivemaster_free(t_jcom_receivemaster *x);
void receivemaster_dispatch(t_jcom_receivemaster *x, t_symbol *name, t_symbol *msg, long argc, t_atom *argv);
void receivemaster_add(t_jcom_receivemaster *x, t_symbol *name, t_object *obj);
void receivemaster_remove(t_jcom_receivemaster *x, t_symbol *name, t_object *obj);

// Globals
static t_class		*s_receivemaster_class;		///< Required: Global pointer the jcom.receivemaster class
static t_hashtab	*s_receive_lists;			///< hash full of linked lists, keyed on the name of the jcom.receive instances

/************************************************************************************/

void receivemaster_initclass()
{
	// Define our class
	s_receivemaster_class = class_new(	"jcom.receivemaster",
										(method)receivemaster_new,
										(method)receivemaster_free,
										(short)sizeof(t_jcom_receivemaster),
										(method)0L,
										A_GIMME,
										0);
	class_obexoffset_set(s_receivemaster_class, calcoffset(t_jcom_receivemaster, obex));

	// Make methods accessible for our class:
	class_addmethod(s_receivemaster_class, (method)receivemaster_dispatch,	"dispatch",	A_CANT, 0L);
	class_addmethod(s_receivemaster_class, (method)receivemaster_add,		"add",		A_CANT, 0L);
	class_addmethod(s_receivemaster_class, (method)receivemaster_remove,	"remove",	A_CANT, 0L);

	// Finalize our class
	class_register(CLASS_NOBOX, s_receivemaster_class);
}

/************************************************************************************/
// Object Life

void *receivemaster_new(t_symbol *msg, long argc, t_atom *argv)
{
	t_jcom_receivemaster *x = (t_jcom_receivemaster *)object_alloc(s_receivemaster_class);

	if(!s_receive_lists)
		s_receive_lists = hashtab_new(0);
	return x;
}

void receivemaster_free(t_jcom_receivemaster *x)
{
	;	// we could delete the hashtab, but this class is never deleted so it doesn't really make a difference
		// does it?
}

/************************************************************************************/
// Methods

void receivemaster_dispatch(t_jcom_receivemaster *x, t_symbol *name, t_symbol *msg, long argc, t_atom *argv)
{
	t_linklist	*list;												// linklist of receives with this name

	hashtab_lookup(s_receive_lists, name, (t_object **)&list);		// 1. Look up the correct linklist in the hashtab
	linklist_methodall(list, ps_dispatch, msg, argc, argv);			// 2. Call method on every object in the linklist
}

void receivemaster_add(t_jcom_receivemaster *x, t_symbol *name, t_object *obj)
{
	t_linklist	*list;

	hashtab_lookup(s_receive_lists, name, (t_object **)&list);		// 1. Look up the correct linklist in the hashtab
	if(!list){
		list = linklist_new();										// if there isn't a linklist for this name yet,
		hashtab_store(s_receive_lists, name, (t_object *)list);	//	then we make one and store it in the hashtab
	}
	linklist_append(list, obj);										// 2. We add the object to the appropriate linklist
}

void receivemaster_remove(t_jcom_receivemaster *x, t_symbol *name, t_object *obj)
{
	t_linklist	*list;

	hashtab_lookup(s_receive_lists, name, (t_object **)&list);		// 1. Look up the correct linklist in the hashtab
	linklist_chuckobject(list, obj);								//	TODO: should this be chuckobject or delete object?
	if(!linklist_getsize(list))
		hashtab_chuckkey(s_receive_lists, name);					// 2. Chuck the key if there are no more objects with this name
}
<commit_msg>Fix for functions not exported from Max 4.x<commit_after>/*
 * jcom.receivemaster
 * Manage jcom.receive instances
 * By Tim Place, Copyright  2007
 *
 * License: This code is licensed under the terms of the GNU LGPL
 * http://www.gnu.org/licenses/lgpl.html
 */

#include "ext.h"				// Max Header
#include "ext_obex.h"			// Max Object Extensions (attributes) Header
#include "commonsyms.h"			// Common symbols used by the Max 4.5 API
#include "jcom.core.h"
#include "jcom.sendreceive.h"

// Prototypes
void *receivemaster_new(t_symbol *msg, long argc, t_atom *argv);
void receivemaster_free(t_jcom_receivemaster *x);
void receivemaster_dispatch(t_jcom_receivemaster *x, t_symbol *name, t_symbol *msg, long argc, t_atom *argv);
void receivemaster_add(t_jcom_receivemaster *x, t_symbol *name, t_object *obj);
void receivemaster_remove(t_jcom_receivemaster *x, t_symbol *name, t_object *obj);

// Globals
static t_class		*s_receivemaster_class;		///< Required: Global pointer the jcom.receivemaster class
static t_hashtab	*s_receive_lists;			///< hash full of linked lists, keyed on the name of the jcom.receive instances

/************************************************************************************/

void receivemaster_initclass()
{
	// Define our class
	s_receivemaster_class = class_new(	"jcom.receivemaster",
										(method)receivemaster_new,
										(method)receivemaster_free,
										(short)sizeof(t_jcom_receivemaster),
										(method)0L,
										A_GIMME,
										0);
	class_obexoffset_set(s_receivemaster_class, calcoffset(t_jcom_receivemaster, obex));

	// Make methods accessible for our class:
	class_addmethod(s_receivemaster_class, (method)receivemaster_dispatch,	"dispatch",	A_CANT, 0L);
	class_addmethod(s_receivemaster_class, (method)receivemaster_add,		"add",		A_CANT, 0L);
	class_addmethod(s_receivemaster_class, (method)receivemaster_remove,	"remove",	A_CANT, 0L);

	// Finalize our class
	class_register(CLASS_NOBOX, s_receivemaster_class);
}

/************************************************************************************/
// Object Life

void *receivemaster_new(t_symbol *msg, long argc, t_atom *argv)
{
	t_jcom_receivemaster *x = (t_jcom_receivemaster *)object_alloc(s_receivemaster_class);

	if(!s_receive_lists)
		s_receive_lists = hashtab_new(0);
	return x;
}

void receivemaster_free(t_jcom_receivemaster *x)
{
	;	// we could delete the hashtab, but this class is never deleted so it doesn't really make a difference
		// does it?
}

/************************************************************************************/
// Methods

void receivemaster_dispatch(t_jcom_receivemaster *x, t_symbol *name, t_symbol *msg, long argc, t_atom *argv)
{
	t_linklist	*list;												// linklist of receives with this name

	hashtab_lookup(s_receive_lists, name, (t_object **)&list);		// 1. Look up the correct linklist in the hashtab
	linklist_methodall(list, ps_dispatch, msg, argc, argv);			// 2. Call method on every object in the linklist
}

void receivemaster_add(t_jcom_receivemaster *x, t_symbol *name, t_object *obj)
{
	t_linklist	*list;

	hashtab_lookup(s_receive_lists, name, (t_object **)&list);		// 1. Look up the correct linklist in the hashtab
	if(!list){
		list = linklist_new();										// if there isn't a linklist for this name yet,
		hashtab_store(s_receive_lists, name, (t_object *)list);	//	then we make one and store it in the hashtab
	}
	linklist_append(list, obj);										// 2. We add the object to the appropriate linklist
}

// TODO: When we switch to Max5 then remove these function definitions
#if 1
long linklist_match(void *a, void *b)
{
	return a == b;
}

void linklist_chuckobject(t_linklist *x, void *o)
{
	void *obj;

	long index = linklist_findfirst(x, &obj, linklist_match, o);
	if(index != -1)
		linklist_chuckindex(x, index);
}
#endif

void receivemaster_remove(t_jcom_receivemaster *x, t_symbol *name, t_object *obj)
{
	t_linklist	*list;

	hashtab_lookup(s_receive_lists, name, (t_object **)&list);		// 1. Look up the correct linklist in the hashtab
	linklist_chuckobject(list, obj);								//	TODO: should this be chuckobject or delete object?
	if(!linklist_getsize(list))
		hashtab_chuckkey(s_receive_lists, name);					// 2. Chuck the key if there are no more objects with this name
}
<|endoftext|>


<commit_before>/*****************************************************************************
 *
 * This file is part of Mapnik (c++ mapping toolkit)
 *
 * Copyright (C) 2007 Artem Pavlenko
 *
 * 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, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 *
 *****************************************************************************/
// $Id$

#include "sqlite_datasource.hpp"
#include "sqlite_featureset.hpp"

// mapnik
#include <mapnik/ptree_helpers.hpp>
#include <mapnik/sql_utils.hpp>

// boost
#include <boost/algorithm/string.hpp>
#include <boost/lexical_cast.hpp>
#include <boost/tokenizer.hpp>
#include <boost/filesystem/operations.hpp>

using std::clog;
using std::endl;

using boost::lexical_cast;
using boost::bad_lexical_cast;

using mapnik::datasource;
using mapnik::parameters;

DATASOURCE_PLUGIN(sqlite_datasource)

using mapnik::box2d;
using mapnik::coord2d;
using mapnik::query;
using mapnik::featureset_ptr;
using mapnik::layer_descriptor;
using mapnik::attribute_descriptor;
using mapnik::datasource_exception;

sqlite_datasource::sqlite_datasource(parameters const& params, bool bind)
   : datasource(params),
     extent_(),
     extent_initialized_(false),
     type_(datasource::Vector),
     table_(*params.get<std::string>("table","")),
     metadata_(*params.get<std::string>("metadata","")),
     geometry_field_(*params.get<std::string>("geometry_field","the_geom")),
     key_field_(*params.get<std::string>("key_field","OGC_FID")),
     row_offset_(*params_.get<int>("row_offset",0)),
     row_limit_(*params_.get<int>("row_limit",0)),
     desc_(*params.get<std::string>("type"), *params.get<std::string>("encoding","utf-8")),
     format_(mapnik::wkbGeneric)
{
    boost::optional<std::string> file = params.get<std::string>("file");
    if (!file) throw datasource_exception("missing <file> parameter");

    boost::optional<std::string> wkb = params.get<std::string>("wkb_format");
    if (wkb)
    {
        if (*wkb == "spatialite")
            format_ = mapnik::wkbSpatiaLite;
    }

    multiple_geometries_ = *params_.get<mapnik::boolean>("multiple_geometries",false);
    use_spatial_index_ = *params_.get<mapnik::boolean>("use_spatial_index",true);

    boost::optional<std::string> base = params.get<std::string>("base");
    if (base)
        dataset_name_ = *base + "/" + *file;
    else
        dataset_name_ = *file;

    if (bind)
    {
        this->bind();
    }
}

void sqlite_datasource::bind() const
{
    if (is_bound_) return;

    if (!boost::filesystem::exists(dataset_name_)) throw datasource_exception(dataset_name_ + " does not exist");

    dataset_ = new sqlite_connection (dataset_name_);

    boost::optional<std::string> ext  = params_.get<std::string>("extent");
    if (ext)
    {
        boost::char_separator<char> sep(",");
        boost::tokenizer<boost::char_separator<char> > tok(*ext,sep);
        unsigned i = 0;
        bool success = false;
        double d[4];
        for (boost::tokenizer<boost::char_separator<char> >::iterator beg=tok.begin();
             beg!=tok.end();++beg)
        {
            try
            {
                d[i] = boost::lexical_cast<double>(*beg);
            }
            catch (boost::bad_lexical_cast & ex)
            {
                std::clog << ex.what() << "\n";
                break;
            }
            if (i==3)
            {
                success = true;
                break;
            }
            ++i;
        }

        if (success)
        {
            extent_.init(d[0],d[1],d[2],d[3]);
            extent_initialized_ = true;
        }
    }

    std::string table_name = mapnik::table_from_sql(table_);

    if (metadata_ != "" && ! extent_initialized_)
    {
        std::ostringstream s;
        s << "select xmin, ymin, xmax, ymax from " << metadata_;
        s << " where lower(f_table_name) = lower('" << table_name << "')";
        boost::scoped_ptr<sqlite_resultset> rs (dataset_->execute_query (s.str()));
        if (rs->is_valid () && rs->step_next())
        {
            double xmin = rs->column_double (0);
            double ymin = rs->column_double (1);
            double xmax = rs->column_double (2);
            double ymax = rs->column_double (3);

            extent_.init (xmin,ymin,xmax,ymax);
            extent_initialized_ = true;
        }
    }

    if (use_spatial_index_)
    {
        std::ostringstream s;
        s << "select count (*) from sqlite_master";
        s << " where lower(name) = lower('idx_" << table_name << "_" << geometry_field_ << "')";
        boost::scoped_ptr<sqlite_resultset> rs (dataset_->execute_query (s.str()));
        if (rs->is_valid () && rs->step_next())
        {
            use_spatial_index_ = rs->column_integer (0) == 1;
        }

#ifdef MAPNIK_DEBUG
        if (! use_spatial_index_)
           clog << "cannot use the spatial index " << endl;
#endif
    }

    {
        /*
            XXX - This is problematic, if we do not have at least a row,
                  we cannot determine the right columns types and names
                  as all column_type are SQLITE_NULL
        */

        std::string::size_type idx = table_.find(table_name);
        std::ostringstream s;
        s << "select * from (" << table_.substr(0,idx + table_name.length()) << ") limit 1";

        boost::scoped_ptr<sqlite_resultset> rs (dataset_->execute_query (s.str()));
        if (rs->is_valid () && rs->step_next())
        {
            for (int i = 0; i < rs->column_count (); ++i)
            {
               const int type_oid = rs->column_type (i);
               const char* fld_name = rs->column_name (i);
               switch (type_oid)
               {
                  case SQLITE_INTEGER:
                     desc_.add_descriptor(attribute_descriptor(fld_name,mapnik::Integer));
                     break;

                  case SQLITE_FLOAT:
                     desc_.add_descriptor(attribute_descriptor(fld_name,mapnik::Double));
                     break;

                  case SQLITE_TEXT:
                     desc_.add_descriptor(attribute_descriptor(fld_name,mapnik::String));
                     break;

                  case SQLITE_NULL:
                  case SQLITE_BLOB:
                     break;

                  default:
#ifdef MAPNIK_DEBUG
                     clog << "unknown type_oid="<<type_oid<<endl;
#endif
                     break;
                }
            }
        }
    }

    is_bound_ = true;
}

sqlite_datasource::~sqlite_datasource()
{
    if (is_bound_)
    {
        delete dataset_;
    }
}

std::string const sqlite_datasource::name_="sqlite";

std::string sqlite_datasource::name()
{
   return name_;
}

int sqlite_datasource::type() const
{
   return type_;
}

box2d<double> sqlite_datasource::envelope() const
{
   if (!is_bound_) bind();
   return extent_;
}

layer_descriptor sqlite_datasource::get_descriptor() const
{
   if (!is_bound_) bind();
   return desc_;
}

featureset_ptr sqlite_datasource::features(query const& q) const
{
   if (!is_bound_) bind();
   if (dataset_)
   {
        mapnik::box2d<double> const& e = q.get_bbox();

        std::ostringstream s;

        s << "select " << geometry_field_ << "," << key_field_;
        std::set<std::string> const& props = q.property_names();
        std::set<std::string>::const_iterator pos = props.begin();
        std::set<std::string>::const_iterator end = props.end();
        while (pos != end)
        {
           s << "," << *pos << "";
           ++pos;
        }

        s << " from ";

        std::string query (table_);

        if (use_spatial_index_)
        {
           std::string table_name = table_from_sql(query);
           std::ostringstream spatial_sql;
           spatial_sql << std::setprecision(16);
           spatial_sql << " where rowid in (select pkid from idx_" << table_name << "_" << geometry_field_;
           spatial_sql << " where xmax>=" << e.minx() << " and xmin<=" << e.maxx() ;
           spatial_sql << " and ymax>=" << e.miny() << " and ymin<=" << e.maxy() << ")";
           if (boost::algorithm::ifind_first(query,"where"))
           {
              boost::algorithm::ireplace_first(query, "where", spatial_sql.str() + " and");
           }
           else if (boost::algorithm::find_first(query,table_name))
           {
              boost::algorithm::ireplace_first(query, table_name , table_name + " " + spatial_sql.str());
           }
        }

        s << query ;

        if (row_limit_ > 0) {
            s << " limit " << row_limit_;
        }

        if (row_offset_ > 0) {
            s << " offset " << row_offset_;
        }

#ifdef MAPNIK_DEBUG
        std::cerr << s.str() << "\n";
#endif

        boost::shared_ptr<sqlite_resultset> rs (dataset_->execute_query (s.str()));

        return featureset_ptr (new sqlite_featureset(rs, desc_.get_encoding(), format_, multiple_geometries_));
   }

   return featureset_ptr();
}

featureset_ptr sqlite_datasource::features_at_point(coord2d const& pt) const
{
   if (!is_bound_) bind();
#if 0
   if (dataset_ && layer_)
   {
        OGRPoint point;
        point.setX (pt.x);
        point.setY (pt.y);

        layer_->SetSpatialFilter (&point);

        return featureset_ptr(new ogr_featureset(*dataset_, *layer_, desc_.get_encoding(), multiple_geometries_));
   }
#endif

   return featureset_ptr();
}

<commit_msg>- forgot to declare a namespace (oops!)<commit_after>/*****************************************************************************
 *
 * This file is part of Mapnik (c++ mapping toolkit)
 *
 * Copyright (C) 2007 Artem Pavlenko
 *
 * 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, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 *
 *****************************************************************************/
// $Id$

#include "sqlite_datasource.hpp"
#include "sqlite_featureset.hpp"

// mapnik
#include <mapnik/ptree_helpers.hpp>
#include <mapnik/sql_utils.hpp>

// boost
#include <boost/algorithm/string.hpp>
#include <boost/lexical_cast.hpp>
#include <boost/tokenizer.hpp>
#include <boost/filesystem/operations.hpp>

using std::clog;
using std::endl;

using boost::lexical_cast;
using boost::bad_lexical_cast;

using mapnik::datasource;
using mapnik::parameters;

DATASOURCE_PLUGIN(sqlite_datasource)

using mapnik::box2d;
using mapnik::coord2d;
using mapnik::query;
using mapnik::featureset_ptr;
using mapnik::layer_descriptor;
using mapnik::attribute_descriptor;
using mapnik::datasource_exception;

sqlite_datasource::sqlite_datasource(parameters const& params, bool bind)
   : datasource(params),
     extent_(),
     extent_initialized_(false),
     type_(datasource::Vector),
     table_(*params.get<std::string>("table","")),
     metadata_(*params.get<std::string>("metadata","")),
     geometry_field_(*params.get<std::string>("geometry_field","the_geom")),
     key_field_(*params.get<std::string>("key_field","OGC_FID")),
     row_offset_(*params_.get<int>("row_offset",0)),
     row_limit_(*params_.get<int>("row_limit",0)),
     desc_(*params.get<std::string>("type"), *params.get<std::string>("encoding","utf-8")),
     format_(mapnik::wkbGeneric)
{
    boost::optional<std::string> file = params.get<std::string>("file");
    if (!file) throw datasource_exception("missing <file> parameter");

    boost::optional<std::string> wkb = params.get<std::string>("wkb_format");
    if (wkb)
    {
        if (*wkb == "spatialite")
            format_ = mapnik::wkbSpatiaLite;
    }

    multiple_geometries_ = *params_.get<mapnik::boolean>("multiple_geometries",false);
    use_spatial_index_ = *params_.get<mapnik::boolean>("use_spatial_index",true);

    boost::optional<std::string> base = params.get<std::string>("base");
    if (base)
        dataset_name_ = *base + "/" + *file;
    else
        dataset_name_ = *file;

    if (bind)
    {
        this->bind();
    }
}

void sqlite_datasource::bind() const
{
    if (is_bound_) return;

    if (!boost::filesystem::exists(dataset_name_)) throw datasource_exception(dataset_name_ + " does not exist");

    dataset_ = new sqlite_connection (dataset_name_);

    boost::optional<std::string> ext  = params_.get<std::string>("extent");
    if (ext)
    {
        boost::char_separator<char> sep(",");
        boost::tokenizer<boost::char_separator<char> > tok(*ext,sep);
        unsigned i = 0;
        bool success = false;
        double d[4];
        for (boost::tokenizer<boost::char_separator<char> >::iterator beg=tok.begin();
             beg!=tok.end();++beg)
        {
            try
            {
                d[i] = boost::lexical_cast<double>(*beg);
            }
            catch (boost::bad_lexical_cast & ex)
            {
                std::clog << ex.what() << "\n";
                break;
            }
            if (i==3)
            {
                success = true;
                break;
            }
            ++i;
        }

        if (success)
        {
            extent_.init(d[0],d[1],d[2],d[3]);
            extent_initialized_ = true;
        }
    }

    std::string table_name = mapnik::table_from_sql(table_);

    if (metadata_ != "" && ! extent_initialized_)
    {
        std::ostringstream s;
        s << "select xmin, ymin, xmax, ymax from " << metadata_;
        s << " where lower(f_table_name) = lower('" << table_name << "')";
        boost::scoped_ptr<sqlite_resultset> rs (dataset_->execute_query (s.str()));
        if (rs->is_valid () && rs->step_next())
        {
            double xmin = rs->column_double (0);
            double ymin = rs->column_double (1);
            double xmax = rs->column_double (2);
            double ymax = rs->column_double (3);

            extent_.init (xmin,ymin,xmax,ymax);
            extent_initialized_ = true;
        }
    }

    if (use_spatial_index_)
    {
        std::ostringstream s;
        s << "select count (*) from sqlite_master";
        s << " where lower(name) = lower('idx_" << table_name << "_" << geometry_field_ << "')";
        boost::scoped_ptr<sqlite_resultset> rs (dataset_->execute_query (s.str()));
        if (rs->is_valid () && rs->step_next())
        {
            use_spatial_index_ = rs->column_integer (0) == 1;
        }

#ifdef MAPNIK_DEBUG
        if (! use_spatial_index_)
           clog << "cannot use the spatial index " << endl;
#endif
    }

    {
        /*
            XXX - This is problematic, if we do not have at least a row,
                  we cannot determine the right columns types and names
                  as all column_type are SQLITE_NULL
        */

        std::string::size_type idx = table_.find(table_name);
        std::ostringstream s;
        s << "select * from (" << table_.substr(0,idx + table_name.length()) << ") limit 1";

        boost::scoped_ptr<sqlite_resultset> rs (dataset_->execute_query (s.str()));
        if (rs->is_valid () && rs->step_next())
        {
            for (int i = 0; i < rs->column_count (); ++i)
            {
               const int type_oid = rs->column_type (i);
               const char* fld_name = rs->column_name (i);
               switch (type_oid)
               {
                  case SQLITE_INTEGER:
                     desc_.add_descriptor(attribute_descriptor(fld_name,mapnik::Integer));
                     break;

                  case SQLITE_FLOAT:
                     desc_.add_descriptor(attribute_descriptor(fld_name,mapnik::Double));
                     break;

                  case SQLITE_TEXT:
                     desc_.add_descriptor(attribute_descriptor(fld_name,mapnik::String));
                     break;

                  case SQLITE_NULL:
                  case SQLITE_BLOB:
                     break;

                  default:
#ifdef MAPNIK_DEBUG
                     clog << "unknown type_oid="<<type_oid<<endl;
#endif
                     break;
                }
            }
        }
    }

    is_bound_ = true;
}

sqlite_datasource::~sqlite_datasource()
{
    if (is_bound_)
    {
        delete dataset_;
    }
}

std::string const sqlite_datasource::name_="sqlite";

std::string sqlite_datasource::name()
{
   return name_;
}

int sqlite_datasource::type() const
{
   return type_;
}

box2d<double> sqlite_datasource::envelope() const
{
   if (!is_bound_) bind();
   return extent_;
}

layer_descriptor sqlite_datasource::get_descriptor() const
{
   if (!is_bound_) bind();
   return desc_;
}

featureset_ptr sqlite_datasource::features(query const& q) const
{
   if (!is_bound_) bind();
   if (dataset_)
   {
        mapnik::box2d<double> const& e = q.get_bbox();

        std::ostringstream s;

        s << "select " << geometry_field_ << "," << key_field_;
        std::set<std::string> const& props = q.property_names();
        std::set<std::string>::const_iterator pos = props.begin();
        std::set<std::string>::const_iterator end = props.end();
        while (pos != end)
        {
           s << "," << *pos << "";
           ++pos;
        }

        s << " from ";

        std::string query (table_);

        if (use_spatial_index_)
        {
           std::string table_name = mapnik::table_from_sql(query);
           std::ostringstream spatial_sql;
           spatial_sql << std::setprecision(16);
           spatial_sql << " where rowid in (select pkid from idx_" << table_name << "_" << geometry_field_;
           spatial_sql << " where xmax>=" << e.minx() << " and xmin<=" << e.maxx() ;
           spatial_sql << " and ymax>=" << e.miny() << " and ymin<=" << e.maxy() << ")";
           if (boost::algorithm::ifind_first(query,"where"))
           {
              boost::algorithm::ireplace_first(query, "where", spatial_sql.str() + " and");
           }
           else if (boost::algorithm::find_first(query,table_name))
           {
              boost::algorithm::ireplace_first(query, table_name , table_name + " " + spatial_sql.str());
           }
        }

        s << query ;

        if (row_limit_ > 0) {
            s << " limit " << row_limit_;
        }

        if (row_offset_ > 0) {
            s << " offset " << row_offset_;
        }

#ifdef MAPNIK_DEBUG
        std::cerr << s.str() << "\n";
#endif

        boost::shared_ptr<sqlite_resultset> rs (dataset_->execute_query (s.str()));

        return featureset_ptr (new sqlite_featureset(rs, desc_.get_encoding(), format_, multiple_geometries_));
   }

   return featureset_ptr();
}

featureset_ptr sqlite_datasource::features_at_point(coord2d const& pt) const
{
   if (!is_bound_) bind();
#if 0
   if (dataset_ && layer_)
   {
        OGRPoint point;
        point.setX (pt.x);
        point.setY (pt.y);

        layer_->SetSpatialFilter (&point);

        return featureset_ptr(new ogr_featureset(*dataset_, *layer_, desc_.get_encoding(), multiple_geometries_));
   }
#endif

   return featureset_ptr();
}

<|endoftext|>


<commit_before>//===--- Mangler.cpp - Base class for Swift name mangling -----------------===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See https://swift.org/LICENSE.txt for license information
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===----------------------------------------------------------------------===//

#define CHECK_MANGLING_AGAINST_OLD

#include "swift/Basic/Mangler.h"
#include "swift/Basic/Punycode.h"
#include "swift/Basic/ManglingMacros.h"
#include "llvm/ADT/StringMap.h"
#include "llvm/Support/CommandLine.h"
#ifdef CHECK_MANGLING_AGAINST_OLD
#include "swift/Basic/Demangle.h"
#include "swift/Basic/DemangleWrappers.h"
#endif
#include <algorithm>

using namespace swift;
using namespace NewMangling;

llvm::cl::opt<bool> NewManglingForTests(
                       "new-mangling-for-tests", llvm::cl::init(false),
                       llvm::cl::desc("Use new mangling for compiler tests"));

#ifndef USE_NEW_MANGLING

static bool containsNonSwiftModule(Demangle::NodePointer Nd) {
  switch (Nd->getKind()) {
    case Demangle::Node::Kind::Module:
      if (Nd->getText() != "Swift")
        return true;
      break;
    case Demangle::Node::Kind::ReabstractionThunk:
    case Demangle::Node::Kind::ReabstractionThunkHelper:
      return true;
    default:
      break;
  }

  for (auto Child : *Nd) {
    if (containsNonSwiftModule(Child))
      return true;
  }
  return false;
}

#endif // USE_NEW_MANGLING

bool swift::useNewMangling(Demangle::NodePointer Node) {
#ifdef USE_NEW_MANGLING
  return true;
#else
  if (NewManglingForTests && Node && containsNonSwiftModule(Node))
    return true;
  return false;
#endif
}

#ifndef NDEBUG

llvm::cl::opt<bool> PrintSwiftManglingStats(
    "print-swift-mangling-stats", llvm::cl::init(false),
    llvm::cl::desc("Print statistics about Swift symbol mangling"));

namespace {

#ifdef CHECK_MANGLING_AGAINST_OLD

static bool areTreesEqual(Demangle::NodePointer Old, Demangle::NodePointer New) {
  if ((Old != nullptr) != (New != nullptr))
    return false;
  if (!Old)
    return true;

  if (Old->getKind() == Demangle::Node::Kind::CurryThunk)
    Old = Old->getFirstChild();
  if (New->getKind() == Demangle::Node::Kind::CurryThunk)
    New = New->getFirstChild();

  if (Old->getKind() != New->getKind()) {
    if (Old->getKind() != Demangle::Node::Kind::UncurriedFunctionType ||
        New->getKind() != Demangle::Node::Kind::FunctionType)
      return false;
  }
  if (Old->hasText() != New->hasText())
    return false;
  if (Old->hasIndex() != New->hasIndex())
    return false;
  if (Old->hasText() && Old->getText() != New->getText())
    return false;
  if (Old->hasIndex() && Old->getIndex() != New->getIndex())
    return false;

  size_t OldNum = Old->getNumChildren();
  size_t NewNum = New->getNumChildren();

  if (OldNum >= 1 && NewNum == 1 &&
      Old->getChild(OldNum - 1)->getKind() == Demangle::Node::Kind::Suffix) {
    switch (New->getFirstChild()->getKind()) {
      case Demangle::Node::Kind::ReflectionMetadataBuiltinDescriptor:
      case Demangle::Node::Kind::ReflectionMetadataFieldDescriptor:
      case Demangle::Node::Kind::ReflectionMetadataAssocTypeDescriptor:
      case Demangle::Node::Kind::ReflectionMetadataSuperclassDescriptor:
      case Demangle::Node::Kind::PartialApplyForwarder:
        return true;
      default:
        return false;
    }
  }

  if (Old->getKind() == Demangle::Node::Kind::DependentAssociatedTypeRef &&
      OldNum + NewNum == 1) {
    OldNum = 0;
    NewNum = 0;
  }
  if (Old->getKind() == Demangle::Node::Kind::GenericSpecializationParam &&
      OldNum > 1 && NewNum == 1)
    OldNum = 1;

  if (OldNum != NewNum) {
    return false;
  }
  for (unsigned Idx = 0, End = OldNum; Idx < End; ++Idx) {
    if (!areTreesEqual(Old->getChild(Idx), New->getChild(Idx)))
      return false;
  }
  return true;
}

static bool treeContains(Demangle::NodePointer Nd, Demangle::Node::Kind Kind) {
  if (Nd->getKind() == Kind)
    return true;

  for (auto Child : *Nd) {
    if (treeContains(Child, Kind))
      return true;
  }
  return false;
}

#endif // CHECK_MANGLING_AGAINST_OLD

struct SizeStatEntry {
  int sizeDiff;
  std::string Old;
  std::string New;
};

static std::vector<SizeStatEntry> SizeStats;

static int numSmaller = 0;
static int numEqual = 0;
static int numLarger = 0;
static int totalOldSize = 0;
static int totalNewSize = 0;
static int mergedSubsts = 0;

struct OpStatEntry {
  OpStatEntry() : num(0), size(0) { }

  int num;
  int size;
};

static llvm::StringMap<OpStatEntry> OpStats;

} // end anonymous namespace

void Mangler::recordOpStatImpl(StringRef op, size_t OldPos) {
  if (PrintSwiftManglingStats) {
    OpStatEntry &E = OpStats[op];
    E.num++;
    E.size += Storage.size() - OldPos;
  }
}

#endif // NDEBUG

std::string NewMangling::selectMangling(const std::string &Old,
                                        const std::string &New,
                                        bool compareTrees) {
  using namespace Demangle;

  NodePointer NewNode = demangleSymbolAsNode(New);

  if (!NewNode && StringRef(New).startswith("s:")) {
    std::string demangleStr = MANGLING_PREFIX_STR + New.substr(2);
    NewNode = demangleSymbolAsNode(demangleStr);
  }

#ifndef NDEBUG
#ifdef CHECK_MANGLING_AGAINST_OLD

  static int numCmp = 0;

  NodePointer OldNode;
  if (compareTrees)
    OldNode = demangleSymbolAsNode(Old);

  if (StringRef(New).startswith(MANGLING_PREFIX_STR) &&
      (!NewNode || treeContains(NewNode, Demangle::Node::Kind::Suffix))) {
    llvm::errs() << "Can't demangle " << New << '\n';
    assert(false);
  }

  if (OldNode && !treeContains(OldNode, Demangle::Node::Kind::Suffix)) {
    if (!areTreesEqual(OldNode, NewNode)) {
      llvm::errs() << "Mangling differs at #" << numCmp << ":\n"
                      "old: " << Old << "\n"
                      "new: " << New << "\n\n"
                      "### old tree: ###\n";
      demangle_wrappers::NodeDumper(OldNode).print(llvm::errs());
      llvm::errs() << "\n### new tree: ###\n";
      demangle_wrappers::NodeDumper(NewNode).print(llvm::errs());
      llvm::errs() << '\n';
      assert(false);
    }
    if (StringRef(New).startswith(MANGLING_PREFIX_STR)) {
      std::string Remangled = mangleNode(NewNode);
      if (New != Remangled) {
        bool isEqual = false;
        if (treeContains(NewNode,
                         Demangle::Node::Kind::DependentAssociatedTypeRef) ||
            // Does the mangling contain an identifier which is the name of
            // an old-mangled function?
            New.find("_T", 2) != std::string::npos) {
          NodePointer RemangledNode = demangleSymbolAsNode(Remangled);
          isEqual = areTreesEqual(NewNode, RemangledNode);
        }
        if (!isEqual) {
          llvm::errs() << "Remangling failed at #" << numCmp << ":\n"
                          "original:  " << New << "\n"
                          "remangled: " << Remangled << "\n";
          assert(false);
        }
      }
    }
  }
  numCmp++;
#endif // CHECK_MANGLING_AGAINST_OLD

  if (PrintSwiftManglingStats) {
    int OldSize = (int)Old.size();
    int NewSize = (int)New.size();
    if (NewSize > OldSize) {
      numLarger++;
      SizeStats.push_back({NewSize - OldSize, Old, New});
    } else if (OldSize > NewSize) {
      numSmaller++;
    } else {
      numEqual++;
    }
    totalOldSize += OldSize;
    totalNewSize += NewSize;
  }
#endif // NDEBUG

  return useNewMangling(NewNode) ? New : Old;
}

void NewMangling::printManglingStats() {
#ifndef NDEBUG
  if (!PrintSwiftManglingStats)
    return;

  std::sort(SizeStats.begin(), SizeStats.end(),
    [](const SizeStatEntry &LHS, const SizeStatEntry &RHS) {
      return LHS.sizeDiff < RHS.sizeDiff;
    });

  llvm::outs() << "Mangling size stats:\n"
                  "  num smaller: " << numSmaller << "\n"
                  "  num larger:  " << numLarger << "\n"
                  "  num equal:   " << numEqual << "\n"
                  "  total old size: " << totalOldSize << "\n"
                  "  total new size: " << totalNewSize << "\n"
                  "  new - old size: " << (totalNewSize - totalOldSize) << "\n"
                  "List or larger:\n";
  for (const SizeStatEntry &E : SizeStats) {
    llvm::outs() << "  delta " << E.sizeDiff << ": " << E.Old << " - " << E.New
                 << '\n';
  }

  llvm::outs() << "Mangling operator stats:\n";

  typedef llvm::StringMapEntry<OpStatEntry> MapEntry;
  std::vector<const MapEntry *> SortedOpStats;
  for (const MapEntry &ME : OpStats) {
    SortedOpStats.push_back(&ME);
  }
  std::sort(SortedOpStats.begin(), SortedOpStats.end(),
    [](const MapEntry *LHS, const MapEntry *RHS) {
      return LHS->getKey() < RHS->getKey();
    });

  for (const MapEntry *E : SortedOpStats) {
    llvm::outs() << "  " << E->getKey() << ": num = " << E->getValue().num
                 << ", size = " << E->getValue().size << '\n';
  }
  llvm::outs() << "  merged substitutions: " << mergedSubsts << '\n';
#endif
}

void Mangler::beginMangling() {
  Storage.clear();
  Substitutions.clear();
  StringSubstitutions.clear();
  lastSubstIdx = -2;
  Words.clear();
  Buffer << MANGLING_PREFIX_STR;
}

/// Finish the mangling of the symbol and return the mangled name.
std::string Mangler::finalize() {
  assert(Storage.size() && "Mangling an empty name");
  std::string result = std::string(Storage.data(), Storage.size());
  Storage.clear();
  return result;
}

/// Finish the mangling of the symbol and write the mangled name into
/// \p stream.
void Mangler::finalize(llvm::raw_ostream &stream) {
  std::string result = finalize();
  stream.write(result.data(), result.size());
}

void Mangler::appendIdentifier(StringRef ident) {
  auto Iter = StringSubstitutions.find(ident);
  if (Iter != StringSubstitutions.end())
    return mangleSubstitution(Iter->second);

  size_t OldPos = Storage.size();
  addSubstitution(ident);

  mangleIdentifier(*this, ident);

  recordOpStat("<identifier>", OldPos);
}

bool Mangler::tryMangleSubstitution(const void *ptr) {
  auto ir = Substitutions.find(ptr);
  if (ir == Substitutions.end())
    return false;

  mangleSubstitution(ir->second);
  return true;
}

void Mangler::mangleSubstitution(unsigned Idx) {
  if (Idx >= 26)
    return appendOperator("A", Index(Idx - 26));

  char c = Idx + 'A';
  if (lastSubstIdx == (int)Storage.size() - 1) {
    assert(isUpperLetter(Storage[lastSubstIdx]));
    Storage[lastSubstIdx] = Storage[lastSubstIdx] - 'A' + 'a';
    Buffer << c;
#ifndef NDEBUG
    mergedSubsts++;
#endif
  } else {
    appendOperator("A", StringRef(&c, 1));
  }
  lastSubstIdx = (int)Storage.size() - 1;
}

<commit_msg>Temporarily disable the re-mangling check.<commit_after>//===--- Mangler.cpp - Base class for Swift name mangling -----------------===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See https://swift.org/LICENSE.txt for license information
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===----------------------------------------------------------------------===//

#define CHECK_MANGLING_AGAINST_OLD

#include "swift/Basic/Mangler.h"
#include "swift/Basic/Punycode.h"
#include "swift/Basic/ManglingMacros.h"
#include "llvm/ADT/StringMap.h"
#include "llvm/Support/CommandLine.h"
#ifdef CHECK_MANGLING_AGAINST_OLD
#include "swift/Basic/Demangle.h"
#include "swift/Basic/DemangleWrappers.h"
#endif
#include <algorithm>

using namespace swift;
using namespace NewMangling;

llvm::cl::opt<bool> NewManglingForTests(
                       "new-mangling-for-tests", llvm::cl::init(false),
                       llvm::cl::desc("Use new mangling for compiler tests"));

#ifndef USE_NEW_MANGLING

static bool containsNonSwiftModule(Demangle::NodePointer Nd) {
  switch (Nd->getKind()) {
    case Demangle::Node::Kind::Module:
      if (Nd->getText() != "Swift")
        return true;
      break;
    case Demangle::Node::Kind::ReabstractionThunk:
    case Demangle::Node::Kind::ReabstractionThunkHelper:
      return true;
    default:
      break;
  }

  for (auto Child : *Nd) {
    if (containsNonSwiftModule(Child))
      return true;
  }
  return false;
}

#endif // USE_NEW_MANGLING

bool swift::useNewMangling(Demangle::NodePointer Node) {
#ifdef USE_NEW_MANGLING
  return true;
#else
  if (NewManglingForTests && Node && containsNonSwiftModule(Node))
    return true;
  return false;
#endif
}

#ifndef NDEBUG

llvm::cl::opt<bool> PrintSwiftManglingStats(
    "print-swift-mangling-stats", llvm::cl::init(false),
    llvm::cl::desc("Print statistics about Swift symbol mangling"));

namespace {

#ifdef CHECK_MANGLING_AGAINST_OLD

static bool areTreesEqual(Demangle::NodePointer Old, Demangle::NodePointer New) {
  if ((Old != nullptr) != (New != nullptr))
    return false;
  if (!Old)
    return true;

  if (Old->getKind() == Demangle::Node::Kind::CurryThunk)
    Old = Old->getFirstChild();
  if (New->getKind() == Demangle::Node::Kind::CurryThunk)
    New = New->getFirstChild();

  if (Old->getKind() != New->getKind()) {
    if (Old->getKind() != Demangle::Node::Kind::UncurriedFunctionType ||
        New->getKind() != Demangle::Node::Kind::FunctionType)
      return false;
  }
  if (Old->hasText() != New->hasText())
    return false;
  if (Old->hasIndex() != New->hasIndex())
    return false;
  if (Old->hasText() && Old->getText() != New->getText())
    return false;
  if (Old->hasIndex() && Old->getIndex() != New->getIndex())
    return false;

  size_t OldNum = Old->getNumChildren();
  size_t NewNum = New->getNumChildren();

  if (OldNum >= 1 && NewNum == 1 &&
      Old->getChild(OldNum - 1)->getKind() == Demangle::Node::Kind::Suffix) {
    switch (New->getFirstChild()->getKind()) {
      case Demangle::Node::Kind::ReflectionMetadataBuiltinDescriptor:
      case Demangle::Node::Kind::ReflectionMetadataFieldDescriptor:
      case Demangle::Node::Kind::ReflectionMetadataAssocTypeDescriptor:
      case Demangle::Node::Kind::ReflectionMetadataSuperclassDescriptor:
      case Demangle::Node::Kind::PartialApplyForwarder:
        return true;
      default:
        return false;
    }
  }

  if (Old->getKind() == Demangle::Node::Kind::DependentAssociatedTypeRef &&
      OldNum + NewNum == 1) {
    OldNum = 0;
    NewNum = 0;
  }
  if (Old->getKind() == Demangle::Node::Kind::GenericSpecializationParam &&
      OldNum > 1 && NewNum == 1)
    OldNum = 1;

  if (OldNum != NewNum) {
    return false;
  }
  for (unsigned Idx = 0, End = OldNum; Idx < End; ++Idx) {
    if (!areTreesEqual(Old->getChild(Idx), New->getChild(Idx)))
      return false;
  }
  return true;
}

static bool treeContains(Demangle::NodePointer Nd, Demangle::Node::Kind Kind) {
  if (Nd->getKind() == Kind)
    return true;

  for (auto Child : *Nd) {
    if (treeContains(Child, Kind))
      return true;
  }
  return false;
}

#endif // CHECK_MANGLING_AGAINST_OLD

struct SizeStatEntry {
  int sizeDiff;
  std::string Old;
  std::string New;
};

static std::vector<SizeStatEntry> SizeStats;

static int numSmaller = 0;
static int numEqual = 0;
static int numLarger = 0;
static int totalOldSize = 0;
static int totalNewSize = 0;
static int mergedSubsts = 0;

struct OpStatEntry {
  OpStatEntry() : num(0), size(0) { }

  int num;
  int size;
};

static llvm::StringMap<OpStatEntry> OpStats;

} // end anonymous namespace

void Mangler::recordOpStatImpl(StringRef op, size_t OldPos) {
  if (PrintSwiftManglingStats) {
    OpStatEntry &E = OpStats[op];
    E.num++;
    E.size += Storage.size() - OldPos;
  }
}

#endif // NDEBUG

std::string NewMangling::selectMangling(const std::string &Old,
                                        const std::string &New,
                                        bool compareTrees) {
  using namespace Demangle;

  NodePointer NewNode = demangleSymbolAsNode(New);

  if (!NewNode && StringRef(New).startswith("s:")) {
    std::string demangleStr = MANGLING_PREFIX_STR + New.substr(2);
    NewNode = demangleSymbolAsNode(demangleStr);
  }

#ifndef NDEBUG
#ifdef CHECK_MANGLING_AGAINST_OLD

  static int numCmp = 0;

  NodePointer OldNode;
  if (compareTrees)
    OldNode = demangleSymbolAsNode(Old);

  if (StringRef(New).startswith(MANGLING_PREFIX_STR) &&
      (!NewNode || treeContains(NewNode, Demangle::Node::Kind::Suffix))) {
    llvm::errs() << "Can't demangle " << New << '\n';
    assert(false);
  }

  if (OldNode && !treeContains(OldNode, Demangle::Node::Kind::Suffix)) {
    if (!areTreesEqual(OldNode, NewNode)) {
      llvm::errs() << "Mangling differs at #" << numCmp << ":\n"
                      "old: " << Old << "\n"
                      "new: " << New << "\n\n"
                      "### old tree: ###\n";
      demangle_wrappers::NodeDumper(OldNode).print(llvm::errs());
      llvm::errs() << "\n### new tree: ###\n";
      demangle_wrappers::NodeDumper(NewNode).print(llvm::errs());
      llvm::errs() << '\n';
      assert(false);
    }
    if (StringRef(New).startswith(MANGLING_PREFIX_STR)) {
      std::string Remangled = mangleNode(NewNode);
      if (New != Remangled) {
        bool isEqual = false;
        if (treeContains(NewNode,
                         Demangle::Node::Kind::DependentAssociatedTypeRef) ||
            // Does the mangling contain an identifier which is the name of
            // an old-mangled function?
            New.find("_T", 2) != std::string::npos) {
          NodePointer RemangledNode = demangleSymbolAsNode(Remangled);
          isEqual = areTreesEqual(NewNode, RemangledNode);
        }

// TODO: Check disabled until rdar://problem/30592808 is fixed.
#if 0
        if (!isEqual) {
          llvm::errs() << "Remangling failed at #" << numCmp << ":\n"
                          "original:  " << New << "\n"
                          "remangled: " << Remangled << "\n";
          assert(false);
        }
#endif
      }
    }
  }
  numCmp++;
#endif // CHECK_MANGLING_AGAINST_OLD

  if (PrintSwiftManglingStats) {
    int OldSize = (int)Old.size();
    int NewSize = (int)New.size();
    if (NewSize > OldSize) {
      numLarger++;
      SizeStats.push_back({NewSize - OldSize, Old, New});
    } else if (OldSize > NewSize) {
      numSmaller++;
    } else {
      numEqual++;
    }
    totalOldSize += OldSize;
    totalNewSize += NewSize;
  }
#endif // NDEBUG

  return useNewMangling(NewNode) ? New : Old;
}

void NewMangling::printManglingStats() {
#ifndef NDEBUG
  if (!PrintSwiftManglingStats)
    return;

  std::sort(SizeStats.begin(), SizeStats.end(),
    [](const SizeStatEntry &LHS, const SizeStatEntry &RHS) {
      return LHS.sizeDiff < RHS.sizeDiff;
    });

  llvm::outs() << "Mangling size stats:\n"
                  "  num smaller: " << numSmaller << "\n"
                  "  num larger:  " << numLarger << "\n"
                  "  num equal:   " << numEqual << "\n"
                  "  total old size: " << totalOldSize << "\n"
                  "  total new size: " << totalNewSize << "\n"
                  "  new - old size: " << (totalNewSize - totalOldSize) << "\n"
                  "List or larger:\n";
  for (const SizeStatEntry &E : SizeStats) {
    llvm::outs() << "  delta " << E.sizeDiff << ": " << E.Old << " - " << E.New
                 << '\n';
  }

  llvm::outs() << "Mangling operator stats:\n";

  typedef llvm::StringMapEntry<OpStatEntry> MapEntry;
  std::vector<const MapEntry *> SortedOpStats;
  for (const MapEntry &ME : OpStats) {
    SortedOpStats.push_back(&ME);
  }
  std::sort(SortedOpStats.begin(), SortedOpStats.end(),
    [](const MapEntry *LHS, const MapEntry *RHS) {
      return LHS->getKey() < RHS->getKey();
    });

  for (const MapEntry *E : SortedOpStats) {
    llvm::outs() << "  " << E->getKey() << ": num = " << E->getValue().num
                 << ", size = " << E->getValue().size << '\n';
  }
  llvm::outs() << "  merged substitutions: " << mergedSubsts << '\n';
#endif
}

void Mangler::beginMangling() {
  Storage.clear();
  Substitutions.clear();
  StringSubstitutions.clear();
  lastSubstIdx = -2;
  Words.clear();
  Buffer << MANGLING_PREFIX_STR;
}

/// Finish the mangling of the symbol and return the mangled name.
std::string Mangler::finalize() {
  assert(Storage.size() && "Mangling an empty name");
  std::string result = std::string(Storage.data(), Storage.size());
  Storage.clear();
  return result;
}

/// Finish the mangling of the symbol and write the mangled name into
/// \p stream.
void Mangler::finalize(llvm::raw_ostream &stream) {
  std::string result = finalize();
  stream.write(result.data(), result.size());
}

void Mangler::appendIdentifier(StringRef ident) {
  auto Iter = StringSubstitutions.find(ident);
  if (Iter != StringSubstitutions.end())
    return mangleSubstitution(Iter->second);

  size_t OldPos = Storage.size();
  addSubstitution(ident);

  mangleIdentifier(*this, ident);

  recordOpStat("<identifier>", OldPos);
}

bool Mangler::tryMangleSubstitution(const void *ptr) {
  auto ir = Substitutions.find(ptr);
  if (ir == Substitutions.end())
    return false;

  mangleSubstitution(ir->second);
  return true;
}

void Mangler::mangleSubstitution(unsigned Idx) {
  if (Idx >= 26)
    return appendOperator("A", Index(Idx - 26));

  char c = Idx + 'A';
  if (lastSubstIdx == (int)Storage.size() - 1) {
    assert(isUpperLetter(Storage[lastSubstIdx]));
    Storage[lastSubstIdx] = Storage[lastSubstIdx] - 'A' + 'a';
    Buffer << c;
#ifndef NDEBUG
    mergedSubsts++;
#endif
  } else {
    appendOperator("A", StringRef(&c, 1));
  }
  lastSubstIdx = (int)Storage.size() - 1;
}

<|endoftext|>