<commit_before>#include <iostream>
#include "util.h"
#include "tlang.h"
#include <taichi/common/util.h>
#include <taichi/math.h>
#include <taichi/common/testing.h>
#include <taichi/system/timer.h>
#include <unordered_map>

using namespace taichi;
using Tlang::measure_cpe;

TLANG_NAMESPACE_BEGIN

Expr length(Vector vec) {
  Expr t = vec(0) * vec(0);
  for (int i = 1; i < (int)vec.entries.size(); i++) {
    t = t + vec.entries[i] * vec.entries[i];
  }
  return sqrt(t);
}

TC_TEST("mass_spring") {
  return;
  Program prog;
  prog.config.simd_width = 1;
  // TC_WARN("optimization off");
  // prog.config.external_optimization_level = 1;

  const int dim = 3;
  auto i = ind(), j = ind();

  Matrix K(dim, dim), K_self(dim, dim);
  Vector x(dim), v(dim), fmg(dim), p(dim), r(dim), Ap(dim), vec(dim);

  auto mass = var<float32>(), fixed = var<float32>();
  auto l0 = var<float32>(), stiffness = var<float32>();
  auto neighbour = var<int32>();
  auto alpha = var<float32>(), beta = var<float32>();
  auto denorm = var<float32>(), normr2 = var<float32>();

  const auto h = 1.0e-2_f;
  const auto viscous = 2_f;
  const auto grav = -9.81_f;
  // const auto grav = 0;

  int n, m;
  std::FILE *f = std::fopen("data/bunny.txt", "r");
  TC_ASSERT(f);
  fscanf(f, "%d%d", &n, &m);
  TC_P(n);
  int max_n = bit::least_pot_bound(n);
  TC_P(m);
  int max_edges = 64;
  TC_P(max_n);

  layout([&] {
    root.fixed(i, max_n)//.multi_threaded()
        .dynamic(j, max_edges)
        .place(neighbour);
    auto &fork2 = root.fixed(i, max_n);

    for (int i = 0; i < dim; i++) {
      for (int j = 0; j < dim; j++) {
        K(i, j) = var<float32>();
      }
    }
    auto place_fixed = [&](Expr expr) {
      fork2.fixed(j, max_edges).place(expr);
    };

    auto &fork3 = root.fixed(i, max_n).fixed(j, max_edges);
    auto place_blocked = [&](Expr expr) { fork3.place(expr); };

    place_fixed(l0);
    place_fixed(stiffness);
    for (auto &e : K.entries) {
      place_blocked(e);
    }

    auto &particle = root.fixed(i, max_n);
    for (int i = 0; i < dim; i++) {
      x(i) = var<float32>();
      v(i) = var<float32>();
      fmg(i) = var<float32>();
      r(i) = var<float32>();
      p(i) = var<float32>();
      Ap(i) = var<float32>();
      vec(i) = var<float32>();
      particle.place(x(i));
      particle.place(v(i));
      particle.place(fmg(i));
      particle.place(r(i));
      particle.place(p(i));
      particle.place(Ap(i));
    }
    particle.place(fixed);
    for (int i = 0; i < dim; i++) {
      for (int j = 0; j < dim; j++) {
        K_self(i, j) = var<float32>();
        particle.place(K_self(i, j));
      }
    }
    particle.place(mass);

    for (int d = 0; d < dim; d++) {
      root.fixed(i, max_n).place(vec(d));
    }
    root.place(alpha);
    root.place(beta);
    root.place(denorm);
    root.place(normr2);
  });

  auto clear_matrix = kernel(neighbour, [&] {
    for (int t = 0; t < dim; t++) {
      for (int d = 0; d < dim; d++) {
        K[i, j](t, d) = 0;
      }
    }
  });

  auto build_matrix = kernel(neighbour, [&] {
    auto k = neighbour[i, j];
    auto dx = x[k] - x[i];
    auto l = length(dx) +
             imm(0.00000000001_f);  // NOTE: this may lead to a difference
    auto U = dx * (imm(1.0_f) / l);
    auto s = load(stiffness[i, j]);
    auto f = s * (l - l0[i, j]);
    auto fe0 = (imm(1.0_f) - fixed[i]) * imm(h) * f * U;

    Matrix UUt = outer_product(U, U);

    auto k_e = imm(h * h) * ((s - f * (imm(1.0_f) / l)) * UUt);
    for (int t = 0; t < dim; t++)
      k_e(t, t) = k_e(t, t) + f / l * imm(h * h);

    k_e = k_e * (imm(1.0_f) - fixed[i]);

    K[i, j] = -k_e;

    for (int d = 0; d < dim; d++) {
      reduce(fmg[i](d), fe0(d));
      for (int t = 0; t < dim; t++) {
        reduce(K_self(d, t)[i], k_e(d, t));
      }
    }
  });

  auto preprocess_particles = kernel(x(0), [&] {
    auto fmg_t = mass[i] * v[i];
    fmg_t(1) = fmg_t(1) +
               imm(h * grav) * mass[i] * (imm(1.0_f) - fixed[i]);  // gravity
    fmg_t = fmg_t * (imm(1.0_f) - fixed[i]);
    fmg[i] = fmg_t;
    for (int t = 0; t < dim; t++) {
      K_self[i](t, t) = select(cast<int>(load(fixed[i])), imm(1.0_f),
                               mass[i] + imm(h * viscous));
      for (int d = 0; d < dim; d++) {
        if (t != d)
          K_self[i](t, d) = imm(0.0_f);
      }
    }

  });

  auto advect = kernel(mass, [&] { x[i] = x[i] + imm(h) * v[i]; });

  auto copy_r_to_p = kernel(mass, [&] { p[i] = r[i]; });

  auto compute_Ap1 = kernel(neighbour, [&] {
    kernel_name("compute_Ap1");
    Vector ve(3);
    auto offset = neighbour[i, j];
    for (int d = 0; d < dim; d++) {
      ve(d) = load(vec(d)[offset]);
    }
    auto tmp = K[i, j] * ve;
    for (int d = 0; d < dim; d++) {
      reduce(Ap[i](d), tmp(d));
    }
  });

  auto compute_Ap2 = kernel(mass, [&] { Ap[i] = K_self[i] * vec[i]; });

  auto compute_Ap = [&] {
    compute_Ap2();
    TC_TIME(compute_Ap1());
  };

  auto compute_denorm = kernel(mass, [&] {
    reduce(global(denorm), p[i].element_wise_prod(Ap[i]).sum());
  });

  auto compute_r = kernel(mass, [&] { r[i] = fmg[i] - Ap[i]; });

  auto compute_v = kernel(mass, [&] { v[i] = v[i] + global(alpha) * p[i]; });

  auto compute_normr2 = kernel(mass, [&] {
    reduce(global(normr2), r[i].element_wise_prod(r[i]).sum());
  });

  auto compute_r2 = kernel(mass, [&] { r[i] = r[i] - global(alpha) * Ap[i]; });

  auto compute_p = kernel(mass, [&] { p[i] = r[i] + global(beta) * p[i]; });

  auto copy_v_to_vec = kernel(mass, [&] { vec[i] = v[i]; });

  auto copy_p_to_vec = kernel(mass, [&] { vec[i] = p[i]; });

  auto print_vector = [&](std::string name, Vector e) {
    return;
    fmt::print(name);
    for (int i = 0; i < n; i++) {
      fmt::print(" {} {} {}, ", e(0).val<float>(i), e(1).val<float>(i),
                 e(2).val<float>(i));
    }
    fmt::print("\n");
  };

  std::vector<int> degrees(n, 0);
  auto time_step = [&] {
    clear_matrix();
    preprocess_particles();
    TC_TIME(build_matrix());

    // print_vector("x", x);
    // print_vector("v", v);

    /*
    for (int u = 0; u < n; u++) {
      printf("u: %d\n", u);
      for (int i = 0; i < dim; i++) {
        for (int j = 0; j < dim; j++) {
          printf("K_self %f\n", K_self(i, j).val<float32>(u));
        }
      }
      for (int k = 0; k < degrees[u]; k++) {
        int v = neighbour.val<int32>(u, k);
        printf("v: %d\n", v);
        for (int i = 0; i < dim; i++) {
          for (int j = 0; j < dim; j++) {
            printf("K %f\n", K(i, j).val<float32>(u, k));
          }
        }
      }

    }
    */

    // print_vector("fmg", fmg);
    copy_v_to_vec();  // vec = v;
    // print_vector("vec", vec);
    compute_Ap();  // Ap = K vec
    // print_vector("Ap", Ap);
    compute_r();  // r = fmg - Ap

    print_vector("r", r);
    copy_r_to_p();  // p = r
    // print_vector("p", p);
    normr2.val<float32>() = 0;
    compute_normr2();  // normr2 = r' * r
    // TC_P(normr2.val<float32>());
    auto h_normr2 = normr2.val<float32>();
    int cnt = 0;
    for (int i = 0; i < 50; i++) {
      // TC_P(i);
      cnt = i;
      if (h_normr2 < 1e-8f) {
        break;
      }
      copy_p_to_vec();        // vec = p
      compute_Ap();  // Ap = K vec
      // print_vector("Ap", Ap);
      denorm.val<float32>() = 0;
      compute_denorm();  // denorm = p' Ap
      alpha.val<float32>() =
          normr2.val<float32>() / (denorm.val<float32>() + 1e-30f);
      // TC_P(alpha.val<float32>());
      // print_vector("p", p);
      compute_v();   // v = v + alpha * p
      compute_r2();  // r = r - alpha * Ap
      // print_vector("r", r);
      // normr2.val()
      auto normr2_old = normr2.val<float32>();
      // TC_P(normr2_old);
      normr2.val<float32>() = 0;
      compute_normr2();  // normr2 = r'r
      // TC_P(normr2.val<float32>());
      if (normr2.val<float32>() < 1e-8_f)
        break;
      beta.val<float32>() = normr2.val<float32>() / normr2_old;
      compute_p();  // p = r + beta * p
    }
    TC_INFO("# cg iterations {}", cnt);
    print_vector("x", x);
    print_vector("v", v);
    print_vector("r", r);
    advect();
  };

  for (int i = 0; i < n; i++) {
    float32 x_, y_, z_, fixed_;
    fscanf(f, "%f%f%f%f", &x_, &y_, &z_, &fixed_);
    x(0).val<float32>(i) = x_;
    x(1).val<float32>(i) = y_;
    x(2).val<float32>(i) = z_;
    fixed.val<float32>(i) = fixed_;
  }

  for (int i = 0; i < m; i++) {
    int u, v;
    float32 l0_, stiffness_;
    fscanf(f, "%d%d%f%f", &u, &v, &l0_, &stiffness_);

    if (std::max(degrees[v], degrees[u]) >= max_edges) {
      TC_WARN("Skipping edge");
      continue;
    }

    l0.val<float>(u, degrees[u]) = l0_;
    l0.val<float>(v, degrees[v]) = l0_;
    stiffness.val<float>(u, degrees[u]) = stiffness_;
    stiffness.val<float>(v, degrees[v]) = stiffness_;

    neighbour.val<int>(u, degrees[u]) = v;
    neighbour.val<int>(v, degrees[v]) = u;

    degrees[u]++;
    degrees[v]++;
  }

  int max_degrees = 0;
  int total_degrees = 0;
  for (int i = 0; i < n; i++) {
    float32 mass_;
    fscanf(f, "%f", &mass_);
    mass.val<float32>(i) = mass_;
    max_degrees = std::max(max_degrees, degrees[i]);
    total_degrees += degrees[i];
  }
  TC_P(max_degrees);
  TC_P(1.0_f * total_degrees / n);

  for (int i = 0; i < 500; i++) {
    for (int i = 0; i < 10; i++)
      TC_TIME(time_step());
    std::vector<Vector3> parts;
    for (int i = 0; i < n; i++) {
      parts.push_back(Vector3(x(0).val<float32>(i), x(1).val<float32>(i),
                              x(2).val<float32>(i)));
    }
    write_partio(parts, fmt::format("ms_output/{:05d}.bgeo", i));
  }
}

TLANG_NAMESPACE_END
<commit_msg>soa for everything, 4% faster than simit<commit_after>#include <iostream>
#include "util.h"
#include "tlang.h"
#include <taichi/common/util.h>
#include <taichi/math.h>
#include <taichi/common/testing.h>
#include <taichi/system/timer.h>
#include <unordered_map>

using namespace taichi;
using Tlang::measure_cpe;

TLANG_NAMESPACE_BEGIN

Expr length(Vector vec) {
  Expr t = vec(0) * vec(0);
  for (int i = 1; i < (int)vec.entries.size(); i++) {
    t = t + vec.entries[i] * vec.entries[i];
  }
  return sqrt(t);
}

TC_TEST("mass_spring") {
  Program prog;
  prog.config.simd_width = 1;
  // TC_WARN("optimization off");
  // prog.config.external_optimization_level = 1;

  const int dim = 3;
  auto i = ind(), j = ind();

  Matrix K(dim, dim), K_self(dim, dim);
  Vector x(dim), v(dim), fmg(dim), p(dim), r(dim), Ap(dim), vec(dim);

  auto mass = var<float32>(), fixed = var<float32>();
  auto l0 = var<float32>(), stiffness = var<float32>();
  auto neighbour = var<int32>();
  auto alpha = var<float32>(), beta = var<float32>();
  auto denorm = var<float32>(), normr2 = var<float32>();

  const auto h = 1.0e-2_f;
  const auto viscous = 2_f;
  const auto grav = -9.81_f;
  // const auto grav = 0;

  int n, m;
  std::FILE *f = std::fopen("data/bunny.txt", "r");
  TC_ASSERT(f);
  fscanf(f, "%d%d", &n, &m);
  TC_P(n);
  int max_n = bit::least_pot_bound(n);
  TC_P(m);
  int max_edges = 64;
  TC_P(max_n);

  layout([&] {
    root.fixed(i, max_n)  //.multi_threaded()
        .dynamic(j, max_edges)
        .place(neighbour);
    auto &fork2 = root.fixed(i, max_n);

    for (int i = 0; i < dim; i++) {
      for (int j = 0; j < dim; j++) {
        K(i, j) = var<float32>();
      }
    }
    auto place_fixed = [&](Expr expr) {
      fork2.fixed(j, max_edges).place(expr);
    };

    auto &fork3 = root.fixed(i, max_n).fixed(j, max_edges);
    auto place_blocked = [&](Expr expr) { fork3.place(expr); };

    place_fixed(l0);
    place_fixed(stiffness);
    for (auto &e : K.entries) {
      place_blocked(e);
    }

    auto &particle = root.fixed(i, max_n);

    auto place_vector_soa = [&](Vector &vec) {
      auto &f = root.fixed(i, max_n);
      for (int i = 0; i < dim; i++) {
        vec(i) = var<float32>();
        f.place(vec(i));
      }
    };

    place_vector_soa(x);
    place_vector_soa(v);
    place_vector_soa(fmg);
    place_vector_soa(r);
    place_vector_soa(p);
    place_vector_soa(Ap);
    place_vector_soa(vec);

    /*
    for (int i = 0; i < dim; i++) {
      x(i) = var<float32>();
      v(i) = var<float32>();
      fmg(i) = var<float32>();
      r(i) = var<float32>();
      p(i) = var<float32>();
      Ap(i) = var<float32>();
      vec(i) = var<float32>();
      particle.place(x(i));
      particle.place(v(i));
      particle.place(fmg(i));
      particle.place(r(i));
      particle.place(p(i));
      particle.place(Ap(i));
    }
    */
    particle.place(fixed);
    for (int i = 0; i < dim; i++) {
      for (int j = 0; j < dim; j++) {
        K_self(i, j) = var<float32>();
        particle.place(K_self(i, j));
      }
    }
    particle.place(mass);

    auto &f = root.fixed(i, max_n);
    for (int d = 0; d < dim; d++) {
      f.place(vec(d));
    }
    root.place(alpha);
    root.place(beta);
    root.place(denorm);
    root.place(normr2);
  });

  auto clear_matrix = kernel(neighbour, [&] {
    for (int t = 0; t < dim; t++) {
      for (int d = 0; d < dim; d++) {
        K[i, j](t, d) = 0;
      }
    }
  });

  auto build_matrix = kernel(neighbour, [&] {
    auto k = neighbour[i, j];
    auto dx = x[k] - x[i];
    auto l = length(dx) +
             imm(0.00000000001_f);  // NOTE: this may lead to a difference
    auto U = dx * (imm(1.0_f) / l);
    auto s = load(stiffness[i, j]);
    auto f = s * (l - l0[i, j]);
    auto fe0 = (imm(1.0_f) - fixed[i]) * imm(h) * f * U;

    Matrix UUt = outer_product(U, U);

    auto k_e = imm(h * h) * ((s - f * (imm(1.0_f) / l)) * UUt);
    for (int t = 0; t < dim; t++)
      k_e(t, t) = k_e(t, t) + f / l * imm(h * h);

    k_e = k_e * (imm(1.0_f) - fixed[i]);

    K[i, j] = -k_e;

    for (int d = 0; d < dim; d++) {
      reduce(fmg[i](d), fe0(d));
      for (int t = 0; t < dim; t++) {
        reduce(K_self(d, t)[i], k_e(d, t));
      }
    }
  });

  auto preprocess_particles = kernel(x(0), [&] {
    auto fmg_t = mass[i] * v[i];
    fmg_t(1) = fmg_t(1) +
               imm(h * grav) * mass[i] * (imm(1.0_f) - fixed[i]);  // gravity
    fmg_t = fmg_t * (imm(1.0_f) - fixed[i]);
    fmg[i] = fmg_t;
    for (int t = 0; t < dim; t++) {
      K_self[i](t, t) = select(cast<int>(load(fixed[i])), imm(1.0_f),
                               mass[i] + imm(h * viscous));
      for (int d = 0; d < dim; d++) {
        if (t != d)
          K_self[i](t, d) = imm(0.0_f);
      }
    }

  });

  auto advect = kernel(mass, [&] { x[i] = x[i] + imm(h) * v[i]; });

  auto copy_r_to_p = kernel(mass, [&] { p[i] = r[i]; });

  auto compute_Ap1 = kernel(neighbour, [&] {
    kernel_name("compute_Ap1");
    Vector ve(3);
    auto offset = neighbour[i, j];
    for (int d = 0; d < dim; d++) {
      ve(d) = load(vec(d)[offset]);
    }
    auto tmp = K[i, j] * ve;
    for (int d = 0; d < dim; d++) {
      reduce(Ap[i](d), tmp(d));
    }
  });

  auto compute_Ap2 = kernel(mass, [&] { Ap[i] = K_self[i] * vec[i]; });

  auto compute_Ap = [&] {
    compute_Ap2();
    TC_TIME(compute_Ap1());
  };

  auto compute_denorm = kernel(mass, [&] {
    reduce(global(denorm), p[i].element_wise_prod(Ap[i]).sum());
  });

  auto compute_r = kernel(mass, [&] { r[i] = fmg[i] - Ap[i]; });

  auto compute_v = kernel(mass, [&] { v[i] = v[i] + global(alpha) * p[i]; });

  auto compute_normr2 = kernel(mass, [&] {
    reduce(global(normr2), r[i].element_wise_prod(r[i]).sum());
  });

  auto compute_r2 = kernel(mass, [&] { r[i] = r[i] - global(alpha) * Ap[i]; });

  auto compute_p = kernel(mass, [&] { p[i] = r[i] + global(beta) * p[i]; });

  auto copy_v_to_vec = kernel(mass, [&] { vec[i] = v[i]; });

  auto copy_p_to_vec = kernel(mass, [&] { vec[i] = p[i]; });

  auto print_vector = [&](std::string name, Vector e) {
    return;
    fmt::print(name);
    for (int i = 0; i < n; i++) {
      fmt::print(" {} {} {}, ", e(0).val<float>(i), e(1).val<float>(i),
                 e(2).val<float>(i));
    }
    fmt::print("\n");
  };

  std::vector<int> degrees(n, 0);
  auto time_step = [&] {
    clear_matrix();
    preprocess_particles();
    TC_TIME(build_matrix());

    // print_vector("x", x);
    // print_vector("v", v);

    /*
    for (int u = 0; u < n; u++) {
      printf("u: %d\n", u);
      for (int i = 0; i < dim; i++) {
        for (int j = 0; j < dim; j++) {
          printf("K_self %f\n", K_self(i, j).val<float32>(u));
        }
      }
      for (int k = 0; k < degrees[u]; k++) {
        int v = neighbour.val<int32>(u, k);
        printf("v: %d\n", v);
        for (int i = 0; i < dim; i++) {
          for (int j = 0; j < dim; j++) {
            printf("K %f\n", K(i, j).val<float32>(u, k));
          }
        }
      }

    }
    */

    // print_vector("fmg", fmg);
    copy_v_to_vec();  // vec = v;
    // print_vector("vec", vec);
    compute_Ap();  // Ap = K vec
    // print_vector("Ap", Ap);
    compute_r();  // r = fmg - Ap

    print_vector("r", r);
    copy_r_to_p();  // p = r
    // print_vector("p", p);
    normr2.val<float32>() = 0;
    compute_normr2();  // normr2 = r' * r
    // TC_P(normr2.val<float32>());
    auto h_normr2 = normr2.val<float32>();
    int cnt = 0;
    for (int i = 0; i < 50; i++) {
      // TC_P(i);
      cnt = i;
      if (h_normr2 < 1e-8f) {
        break;
      }
      copy_p_to_vec();  // vec = p
      compute_Ap();     // Ap = K vec
      // print_vector("Ap", Ap);
      denorm.val<float32>() = 0;
      compute_denorm();  // denorm = p' Ap
      alpha.val<float32>() =
          normr2.val<float32>() / (denorm.val<float32>() + 1e-30f);
      // TC_P(alpha.val<float32>());
      // print_vector("p", p);
      compute_v();   // v = v + alpha * p
      compute_r2();  // r = r - alpha * Ap
      // print_vector("r", r);
      // normr2.val()
      auto normr2_old = normr2.val<float32>();
      // TC_P(normr2_old);
      normr2.val<float32>() = 0;
      compute_normr2();  // normr2 = r'r
      // TC_P(normr2.val<float32>());
      if (normr2.val<float32>() < 1e-8_f)
        break;
      beta.val<float32>() = normr2.val<float32>() / normr2_old;
      compute_p();  // p = r + beta * p
    }
    TC_INFO("# cg iterations {}", cnt);
    print_vector("x", x);
    print_vector("v", v);
    print_vector("r", r);
    advect();
  };

  for (int i = 0; i < n; i++) {
    float32 x_, y_, z_, fixed_;
    fscanf(f, "%f%f%f%f", &x_, &y_, &z_, &fixed_);
    x(0).val<float32>(i) = x_;
    x(1).val<float32>(i) = y_;
    x(2).val<float32>(i) = z_;
    fixed.val<float32>(i) = fixed_;
  }

  for (int i = 0; i < m; i++) {
    int u, v;
    float32 l0_, stiffness_;
    fscanf(f, "%d%d%f%f", &u, &v, &l0_, &stiffness_);

    if (std::max(degrees[v], degrees[u]) >= max_edges) {
      TC_WARN("Skipping edge");
      continue;
    }

    l0.val<float>(u, degrees[u]) = l0_;
    l0.val<float>(v, degrees[v]) = l0_;
    stiffness.val<float>(u, degrees[u]) = stiffness_;
    stiffness.val<float>(v, degrees[v]) = stiffness_;

    neighbour.val<int>(u, degrees[u]) = v;
    neighbour.val<int>(v, degrees[v]) = u;

    degrees[u]++;
    degrees[v]++;
  }

  int max_degrees = 0;
  int total_degrees = 0;
  for (int i = 0; i < n; i++) {
    float32 mass_;
    fscanf(f, "%f", &mass_);
    mass.val<float32>(i) = mass_;
    max_degrees = std::max(max_degrees, degrees[i]);
    total_degrees += degrees[i];
  }
  TC_P(max_degrees);
  TC_P(1.0_f * total_degrees / n);

  for (int i = 0; i < 500; i++) {
    for (int i = 0; i < 10; i++)
      TC_TIME(time_step());
    std::vector<Vector3> parts;
    for (int i = 0; i < n; i++) {
      parts.push_back(Vector3(x(0).val<float32>(i), x(1).val<float32>(i),
                              x(2).val<float32>(i)));
    }
    write_partio(parts, fmt::format("ms_output/{:05d}.bgeo", i));
  }
}

TLANG_NAMESPACE_END
<|endoftext|>


<commit_before>//===-- RuntimeDyldMachO.cpp - Run-time dynamic linker for MC-JIT -*- C++ -*-=//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// Implementation of the MC-JIT runtime dynamic linker.
//
//===----------------------------------------------------------------------===//

#define DEBUG_TYPE "dyld"
#include "llvm/ADT/OwningPtr.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/ADT/STLExtras.h"
#include "RuntimeDyldMachO.h"
using namespace llvm;
using namespace llvm::object;

namespace llvm {

void RuntimeDyldMachO::resolveRelocation(uint8_t *LocalAddress,
                                         uint64_t FinalAddress,
                                         uint64_t Value,
                                         uint32_t Type,
                                         int64_t Addend) {
  bool isPCRel = (Type >> 24) & 1;
  unsigned MachoType = (Type >> 28) & 0xf;
  unsigned Size = 1 << ((Type >> 25) & 3);

  DEBUG(dbgs() << "resolveRelocation LocalAddress: "
        << format("%p", LocalAddress)
        << " FinalAddress: " << format("%p", FinalAddress)
        << " Value: " << format("%p", Value)
        << " Addend: " << Addend
        << " isPCRel: " << isPCRel
        << " MachoType: " << MachoType
        << " Size: " << Size
        << "\n");

  // This just dispatches to the proper target specific routine.
  switch (Arch) {
  default: llvm_unreachable("Unsupported CPU type!");
  case Triple::x86_64:
    resolveX86_64Relocation(LocalAddress,
                            FinalAddress,
                            (uintptr_t)Value,
                            isPCRel,
                            MachoType,
                            Size,
                            Addend);
    break;
  case Triple::x86:
    resolveI386Relocation(LocalAddress,
                          FinalAddress,
                          (uintptr_t)Value,
                          isPCRel,
                          Type,
                          Size,
                          Addend);
    break;
  case Triple::arm:    // Fall through.
  case Triple::thumb:
    resolveARMRelocation(LocalAddress,
                         FinalAddress,
                         (uintptr_t)Value,
                         isPCRel,
                         MachoType,
                         Size,
                         Addend);
    break;
  }
}

bool RuntimeDyldMachO::resolveI386Relocation(uint8_t *LocalAddress,
                                             uint64_t FinalAddress,
                                             uint64_t Value,
                                             bool isPCRel,
                                             unsigned Type,
                                             unsigned Size,
                                             int64_t Addend) {
  if (isPCRel)
    Value -= FinalAddress + 4; // see resolveX86_64Relocation

  switch (Type) {
  default:
    llvm_unreachable("Invalid relocation type!");
  case macho::RIT_Vanilla: {
    uint8_t *p = LocalAddress;
    uint64_t ValueToWrite = Value + Addend;
    for (unsigned i = 0; i < Size; ++i) {
      *p++ = (uint8_t)(ValueToWrite & 0xff);
      ValueToWrite >>= 8;
    }
  }
  case macho::RIT_Difference:
  case macho::RIT_Generic_LocalDifference:
  case macho::RIT_Generic_PreboundLazyPointer:
    return Error("Relocation type not implemented yet!");
  }
}

bool RuntimeDyldMachO::resolveX86_64Relocation(uint8_t *LocalAddress,
                                               uint64_t FinalAddress,
                                               uint64_t Value,
                                               bool isPCRel,
                                               unsigned Type,
                                               unsigned Size,
                                               int64_t Addend) {
  // If the relocation is PC-relative, the value to be encoded is the
  // pointer difference.
  if (isPCRel)
    // FIXME: It seems this value needs to be adjusted by 4 for an effective PC
    // address. Is that expected? Only for branches, perhaps?
    Value -= FinalAddress + 4;

  switch(Type) {
  default:
    llvm_unreachable("Invalid relocation type!");
  case macho::RIT_X86_64_Signed1:
  case macho::RIT_X86_64_Signed2:
  case macho::RIT_X86_64_Signed4:
  case macho::RIT_X86_64_Signed:
  case macho::RIT_X86_64_Unsigned:
  case macho::RIT_X86_64_Branch: {
    Value += Addend;
    // Mask in the target value a byte at a time (we don't have an alignment
    // guarantee for the target address, so this is safest).
    uint8_t *p = (uint8_t*)LocalAddress;
    for (unsigned i = 0; i < Size; ++i) {
      *p++ = (uint8_t)Value;
      Value >>= 8;
    }
    return false;
  }
  case macho::RIT_X86_64_GOTLoad:
  case macho::RIT_X86_64_GOT:
  case macho::RIT_X86_64_Subtractor:
  case macho::RIT_X86_64_TLV:
    return Error("Relocation type not implemented yet!");
  }
}

bool RuntimeDyldMachO::resolveARMRelocation(uint8_t *LocalAddress,
                                            uint64_t FinalAddress,
                                            uint64_t Value,
                                            bool isPCRel,
                                            unsigned Type,
                                            unsigned Size,
                                            int64_t Addend) {
  // If the relocation is PC-relative, the value to be encoded is the
  // pointer difference.
  if (isPCRel) {
    Value -= FinalAddress;
    // ARM PCRel relocations have an effective-PC offset of two instructions
    // (four bytes in Thumb mode, 8 bytes in ARM mode).
    // FIXME: For now, assume ARM mode.
    Value -= 8;
  }

  switch(Type) {
  default:
    llvm_unreachable("Invalid relocation type!");
  case macho::RIT_Vanilla: {
    // Mask in the target value a byte at a time (we don't have an alignment
    // guarantee for the target address, so this is safest).
    uint8_t *p = (uint8_t*)LocalAddress;
    for (unsigned i = 0; i < Size; ++i) {
      *p++ = (uint8_t)Value;
      Value >>= 8;
    }
    break;
  }
  case macho::RIT_ARM_Branch24Bit: {
    // Mask the value into the target address. We know instructions are
    // 32-bit aligned, so we can do it all at once.
    uint32_t *p = (uint32_t*)LocalAddress;
    // The low two bits of the value are not encoded.
    Value >>= 2;
    // Mask the value to 24 bits.
    Value &= 0xffffff;
    // FIXME: If the destination is a Thumb function (and the instruction
    // is a non-predicated BL instruction), we need to change it to a BLX
    // instruction instead.

    // Insert the value into the instruction.
    *p = (*p & ~0xffffff) | Value;
    break;
  }
  case macho::RIT_ARM_ThumbBranch22Bit:
  case macho::RIT_ARM_ThumbBranch32Bit:
  case macho::RIT_ARM_Half:
  case macho::RIT_ARM_HalfDifference:
  case macho::RIT_Pair:
  case macho::RIT_Difference:
  case macho::RIT_ARM_LocalDifference:
  case macho::RIT_ARM_PreboundLazyPointer:
    return Error("Relocation type not implemented yet!");
  }
  return false;
}

void RuntimeDyldMachO::processRelocationRef(const ObjRelocationInfo &Rel,
                                            ObjectImage &Obj,
                                            ObjSectionToIDMap &ObjSectionToID,
                                            const SymbolTableMap &Symbols,
                                            StubMap &Stubs) {

  uint32_t RelType = (uint32_t) (Rel.Type & 0xffffffffL);
  RelocationValueRef Value;
  SectionEntry &Section = Sections[Rel.SectionID];
  uint8_t *Target = Section.Address + Rel.Offset;

  bool isExtern = (RelType >> 27) & 1;
  if (isExtern) {
    // Obtain the symbol name which is referenced in the relocation
    StringRef TargetName;
    const SymbolRef &Symbol = Rel.Symbol;
    Symbol.getName(TargetName);
    // First search for the symbol in the local symbol table
    SymbolTableMap::const_iterator lsi = Symbols.find(TargetName.data());
    if (lsi != Symbols.end()) {
      Value.SectionID = lsi->second.first;
      Value.Addend = lsi->second.second;
    } else {
      // Search for the symbol in the global symbol table
      SymbolTableMap::const_iterator gsi = GlobalSymbolTable.find(TargetName.data());
      if (gsi != GlobalSymbolTable.end()) {
        Value.SectionID = gsi->second.first;
        Value.Addend = gsi->second.second;
      } else
        Value.SymbolName = TargetName.data();
    }
  } else {
    error_code err;
    uint8_t sectionIndex = static_cast<uint8_t>(RelType & 0xFF);
    section_iterator si = Obj.begin_sections(),
                     se = Obj.end_sections();
    for (uint8_t i = 1; i < sectionIndex; i++) {
      error_code err;
      si.increment(err);
      if (si == se)
        break;
    }
    assert(si != se && "No section containing relocation!");
    Value.SectionID = findOrEmitSection(Obj, *si, true, ObjSectionToID);
    Value.Addend = *(const intptr_t *)Target;
    if (Value.Addend) {
      // The MachO addend is an offset from the current section.  We need it
      // to be an offset from the destination section
      Value.Addend += Section.ObjAddress - Sections[Value.SectionID].ObjAddress;
    }
  }

  if (Arch == Triple::arm && RelType == macho::RIT_ARM_Branch24Bit) {
    // This is an ARM branch relocation, need to use a stub function.

    //  Look up for existing stub.
    StubMap::const_iterator i = Stubs.find(Value);
    if (i != Stubs.end())
      resolveRelocation(Target, (uint64_t)Target,
                        (uint64_t)Section.Address + i->second,
                        RelType, 0);
    else {
      // Create a new stub function.
      Stubs[Value] = Section.StubOffset;
      uint8_t *StubTargetAddr = createStubFunction(Section.Address +
                                                   Section.StubOffset);
      RelocationEntry RE(Rel.SectionID, StubTargetAddr - Section.Address,
                         macho::RIT_Vanilla, Value.Addend);
      if (Value.SymbolName)
        addRelocationForSymbol(RE, Value.SymbolName);
      else
        addRelocationForSection(RE, Value.SectionID);
      resolveRelocation(Target, (uint64_t)Target,
                        (uint64_t)Section.Address + Section.StubOffset,
                        RelType, 0);
      Section.StubOffset += getMaxStubSize();
    }
  } else {
    RelocationEntry RE(Rel.SectionID, Rel.Offset, RelType, Value.Addend);
    if (Value.SymbolName)
      addRelocationForSymbol(RE, Value.SymbolName);
    else
      addRelocationForSection(RE, Value.SectionID);
  }
}

bool RuntimeDyldMachO::isCompatibleFormat(
        const MemoryBuffer *InputBuffer) const {
  StringRef Magic = InputBuffer->getBuffer().slice(0, 4);
  if (Magic == "\xFE\xED\xFA\xCE") return true;
  if (Magic == "\xCE\xFA\xED\xFE") return true;
  if (Magic == "\xFE\xED\xFA\xCF") return true;
  if (Magic == "\xCF\xFA\xED\xFE") return true;
  return false;
}

} // end namespace llvm
<commit_msg>MCJIT: Pass the i386 MachO relocation type properly.<commit_after>//===-- RuntimeDyldMachO.cpp - Run-time dynamic linker for MC-JIT -*- C++ -*-=//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// Implementation of the MC-JIT runtime dynamic linker.
//
//===----------------------------------------------------------------------===//

#define DEBUG_TYPE "dyld"
#include "llvm/ADT/OwningPtr.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/ADT/STLExtras.h"
#include "RuntimeDyldMachO.h"
using namespace llvm;
using namespace llvm::object;

namespace llvm {

void RuntimeDyldMachO::resolveRelocation(uint8_t *LocalAddress,
                                         uint64_t FinalAddress,
                                         uint64_t Value,
                                         uint32_t Type,
                                         int64_t Addend) {
  bool isPCRel = (Type >> 24) & 1;
  unsigned MachoType = (Type >> 28) & 0xf;
  unsigned Size = 1 << ((Type >> 25) & 3);

  DEBUG(dbgs() << "resolveRelocation LocalAddress: "
        << format("%p", LocalAddress)
        << " FinalAddress: " << format("%p", FinalAddress)
        << " Value: " << format("%p", Value)
        << " Addend: " << Addend
        << " isPCRel: " << isPCRel
        << " MachoType: " << MachoType
        << " Size: " << Size
        << "\n");

  // This just dispatches to the proper target specific routine.
  switch (Arch) {
  default: llvm_unreachable("Unsupported CPU type!");
  case Triple::x86_64:
    resolveX86_64Relocation(LocalAddress,
                            FinalAddress,
                            (uintptr_t)Value,
                            isPCRel,
                            MachoType,
                            Size,
                            Addend);
    break;
  case Triple::x86:
    resolveI386Relocation(LocalAddress,
                          FinalAddress,
                          (uintptr_t)Value,
                          isPCRel,
                          MachoType,
                          Size,
                          Addend);
    break;
  case Triple::arm:    // Fall through.
  case Triple::thumb:
    resolveARMRelocation(LocalAddress,
                         FinalAddress,
                         (uintptr_t)Value,
                         isPCRel,
                         MachoType,
                         Size,
                         Addend);
    break;
  }
}

bool RuntimeDyldMachO::resolveI386Relocation(uint8_t *LocalAddress,
                                             uint64_t FinalAddress,
                                             uint64_t Value,
                                             bool isPCRel,
                                             unsigned Type,
                                             unsigned Size,
                                             int64_t Addend) {
  if (isPCRel)
    Value -= FinalAddress + 4; // see resolveX86_64Relocation

  switch (Type) {
  default:
    llvm_unreachable("Invalid relocation type!");
  case macho::RIT_Vanilla: {
    uint8_t *p = LocalAddress;
    uint64_t ValueToWrite = Value + Addend;
    for (unsigned i = 0; i < Size; ++i) {
      *p++ = (uint8_t)(ValueToWrite & 0xff);
      ValueToWrite >>= 8;
    }
  }
  case macho::RIT_Difference:
  case macho::RIT_Generic_LocalDifference:
  case macho::RIT_Generic_PreboundLazyPointer:
    return Error("Relocation type not implemented yet!");
  }
}

bool RuntimeDyldMachO::resolveX86_64Relocation(uint8_t *LocalAddress,
                                               uint64_t FinalAddress,
                                               uint64_t Value,
                                               bool isPCRel,
                                               unsigned Type,
                                               unsigned Size,
                                               int64_t Addend) {
  // If the relocation is PC-relative, the value to be encoded is the
  // pointer difference.
  if (isPCRel)
    // FIXME: It seems this value needs to be adjusted by 4 for an effective PC
    // address. Is that expected? Only for branches, perhaps?
    Value -= FinalAddress + 4;

  switch(Type) {
  default:
    llvm_unreachable("Invalid relocation type!");
  case macho::RIT_X86_64_Signed1:
  case macho::RIT_X86_64_Signed2:
  case macho::RIT_X86_64_Signed4:
  case macho::RIT_X86_64_Signed:
  case macho::RIT_X86_64_Unsigned:
  case macho::RIT_X86_64_Branch: {
    Value += Addend;
    // Mask in the target value a byte at a time (we don't have an alignment
    // guarantee for the target address, so this is safest).
    uint8_t *p = (uint8_t*)LocalAddress;
    for (unsigned i = 0; i < Size; ++i) {
      *p++ = (uint8_t)Value;
      Value >>= 8;
    }
    return false;
  }
  case macho::RIT_X86_64_GOTLoad:
  case macho::RIT_X86_64_GOT:
  case macho::RIT_X86_64_Subtractor:
  case macho::RIT_X86_64_TLV:
    return Error("Relocation type not implemented yet!");
  }
}

bool RuntimeDyldMachO::resolveARMRelocation(uint8_t *LocalAddress,
                                            uint64_t FinalAddress,
                                            uint64_t Value,
                                            bool isPCRel,
                                            unsigned Type,
                                            unsigned Size,
                                            int64_t Addend) {
  // If the relocation is PC-relative, the value to be encoded is the
  // pointer difference.
  if (isPCRel) {
    Value -= FinalAddress;
    // ARM PCRel relocations have an effective-PC offset of two instructions
    // (four bytes in Thumb mode, 8 bytes in ARM mode).
    // FIXME: For now, assume ARM mode.
    Value -= 8;
  }

  switch(Type) {
  default:
    llvm_unreachable("Invalid relocation type!");
  case macho::RIT_Vanilla: {
    // Mask in the target value a byte at a time (we don't have an alignment
    // guarantee for the target address, so this is safest).
    uint8_t *p = (uint8_t*)LocalAddress;
    for (unsigned i = 0; i < Size; ++i) {
      *p++ = (uint8_t)Value;
      Value >>= 8;
    }
    break;
  }
  case macho::RIT_ARM_Branch24Bit: {
    // Mask the value into the target address. We know instructions are
    // 32-bit aligned, so we can do it all at once.
    uint32_t *p = (uint32_t*)LocalAddress;
    // The low two bits of the value are not encoded.
    Value >>= 2;
    // Mask the value to 24 bits.
    Value &= 0xffffff;
    // FIXME: If the destination is a Thumb function (and the instruction
    // is a non-predicated BL instruction), we need to change it to a BLX
    // instruction instead.

    // Insert the value into the instruction.
    *p = (*p & ~0xffffff) | Value;
    break;
  }
  case macho::RIT_ARM_ThumbBranch22Bit:
  case macho::RIT_ARM_ThumbBranch32Bit:
  case macho::RIT_ARM_Half:
  case macho::RIT_ARM_HalfDifference:
  case macho::RIT_Pair:
  case macho::RIT_Difference:
  case macho::RIT_ARM_LocalDifference:
  case macho::RIT_ARM_PreboundLazyPointer:
    return Error("Relocation type not implemented yet!");
  }
  return false;
}

void RuntimeDyldMachO::processRelocationRef(const ObjRelocationInfo &Rel,
                                            ObjectImage &Obj,
                                            ObjSectionToIDMap &ObjSectionToID,
                                            const SymbolTableMap &Symbols,
                                            StubMap &Stubs) {

  uint32_t RelType = (uint32_t) (Rel.Type & 0xffffffffL);
  RelocationValueRef Value;
  SectionEntry &Section = Sections[Rel.SectionID];
  uint8_t *Target = Section.Address + Rel.Offset;

  bool isExtern = (RelType >> 27) & 1;
  if (isExtern) {
    // Obtain the symbol name which is referenced in the relocation
    StringRef TargetName;
    const SymbolRef &Symbol = Rel.Symbol;
    Symbol.getName(TargetName);
    // First search for the symbol in the local symbol table
    SymbolTableMap::const_iterator lsi = Symbols.find(TargetName.data());
    if (lsi != Symbols.end()) {
      Value.SectionID = lsi->second.first;
      Value.Addend = lsi->second.second;
    } else {
      // Search for the symbol in the global symbol table
      SymbolTableMap::const_iterator gsi = GlobalSymbolTable.find(TargetName.data());
      if (gsi != GlobalSymbolTable.end()) {
        Value.SectionID = gsi->second.first;
        Value.Addend = gsi->second.second;
      } else
        Value.SymbolName = TargetName.data();
    }
  } else {
    error_code err;
    uint8_t sectionIndex = static_cast<uint8_t>(RelType & 0xFF);
    section_iterator si = Obj.begin_sections(),
                     se = Obj.end_sections();
    for (uint8_t i = 1; i < sectionIndex; i++) {
      error_code err;
      si.increment(err);
      if (si == se)
        break;
    }
    assert(si != se && "No section containing relocation!");
    Value.SectionID = findOrEmitSection(Obj, *si, true, ObjSectionToID);
    Value.Addend = *(const intptr_t *)Target;
    if (Value.Addend) {
      // The MachO addend is an offset from the current section.  We need it
      // to be an offset from the destination section
      Value.Addend += Section.ObjAddress - Sections[Value.SectionID].ObjAddress;
    }
  }

  if (Arch == Triple::arm && RelType == macho::RIT_ARM_Branch24Bit) {
    // This is an ARM branch relocation, need to use a stub function.

    //  Look up for existing stub.
    StubMap::const_iterator i = Stubs.find(Value);
    if (i != Stubs.end())
      resolveRelocation(Target, (uint64_t)Target,
                        (uint64_t)Section.Address + i->second,
                        RelType, 0);
    else {
      // Create a new stub function.
      Stubs[Value] = Section.StubOffset;
      uint8_t *StubTargetAddr = createStubFunction(Section.Address +
                                                   Section.StubOffset);
      RelocationEntry RE(Rel.SectionID, StubTargetAddr - Section.Address,
                         macho::RIT_Vanilla, Value.Addend);
      if (Value.SymbolName)
        addRelocationForSymbol(RE, Value.SymbolName);
      else
        addRelocationForSection(RE, Value.SectionID);
      resolveRelocation(Target, (uint64_t)Target,
                        (uint64_t)Section.Address + Section.StubOffset,
                        RelType, 0);
      Section.StubOffset += getMaxStubSize();
    }
  } else {
    RelocationEntry RE(Rel.SectionID, Rel.Offset, RelType, Value.Addend);
    if (Value.SymbolName)
      addRelocationForSymbol(RE, Value.SymbolName);
    else
      addRelocationForSection(RE, Value.SectionID);
  }
}

bool RuntimeDyldMachO::isCompatibleFormat(
        const MemoryBuffer *InputBuffer) const {
  StringRef Magic = InputBuffer->getBuffer().slice(0, 4);
  if (Magic == "\xFE\xED\xFA\xCE") return true;
  if (Magic == "\xCE\xFA\xED\xFE") return true;
  if (Magic == "\xFE\xED\xFA\xCF") return true;
  if (Magic == "\xCF\xFA\xED\xFE") return true;
  return false;
}

} // end namespace llvm
<|endoftext|>


<commit_before>#define BOOST_TEST_MODULE "test_extended_conversions"
#ifdef UNITTEST_FRAMEWORK_LIBRARY_EXIST
#include <boost/test/unit_test.hpp>
#else
#define BOOST_TEST_NO_LIB
#include <boost/test/included/unit_test.hpp>
#endif
#include <toml.hpp>
#include <deque>
#include <map>

namespace extlib
{
struct foo
{
    int a;
    std::string b;
};
struct bar
{
    int a;
    std::string b;

    void from_toml(const toml::value& v)
    {
        this->a = toml::find<int>(v, "a");
        this->b = toml::find<std::string>(v, "b");
        return ;
    }

    toml::table into_toml() const
    {
        return toml::table{{"a", this->a}, {"b", this->b}};
    }
};
} // extlib

namespace toml
{
template<>
struct from<extlib::foo>
{
    static extlib::foo from_toml(const toml::value& v)
    {
        return extlib::foo{toml::find<int>(v, "a"), toml::find<std::string>(v, "b")};
    }
};

template<>
struct into<extlib::foo>
{
    static toml::table into_toml(const extlib::foo& f)
    {
        return toml::table{{"a", f.a}, {"b", f.b}};
    }
};
} // toml

// ---------------------------------------------------------------------------

namespace extlib2
{
struct foo
{
    int a;
    std::string b;
};
struct bar
{
    int a;
    std::string b;

    template<typename C, template<typename ...> class M, template<typename ...> class A>
    void from_toml(const toml::basic_value<C, M, A>& v)
    {
        this->a = toml::find<int>(v, "a");
        this->b = toml::find<std::string>(v, "b");
        return ;
    }

    toml::table into_toml() const
    {
        return toml::table{{"a", this->a}, {"b", this->b}};
    }
};
} // extlib2

namespace toml
{
template<>
struct from<extlib2::foo>
{
    template<typename C, template<typename ...> class M, template<typename ...> class A>
    static extlib2::foo from_toml(const toml::basic_value<C, M, A>& v)
    {
        return extlib2::foo{toml::find<int>(v, "a"), toml::find<std::string>(v, "b")};
    }
};

template<>
struct into<extlib2::foo>
{
    static toml::table into_toml(const extlib2::foo& f)
    {
        return toml::table{{"a", f.a}, {"b", f.b}};
    }
};
} // toml

// ---------------------------------------------------------------------------

BOOST_AUTO_TEST_CASE(test_conversion_by_member_methods)
{
    {
        const toml::value v{{"a", 42}, {"b", "baz"}};

        const auto foo = toml::get<extlib::foo>(v);
        BOOST_TEST(foo.a == 42);
        BOOST_TEST(foo.b == "baz");

        const toml::value v2(foo);

        BOOST_TEST(v == v2);
    }

    {
        const toml::value v{{"a", 42}, {"b", "baz"}};

        const auto foo = toml::get<extlib2::foo>(v);
        BOOST_TEST(foo.a == 42);
        BOOST_TEST(foo.b == "baz");

        const toml::value v2(foo);
        BOOST_TEST(v == v2);
    }

    {
        const toml::basic_value<toml::discard_comments, std::map, std::deque>
            v{{"a", 42}, {"b", "baz"}};

        const auto foo = toml::get<extlib2::foo>(v);
        BOOST_TEST(foo.a == 42);
        BOOST_TEST(foo.b == "baz");

        const toml::basic_value<toml::discard_comments, std::map, std::deque>
            v2(foo);

        BOOST_TEST(v == v2);
    }
}

BOOST_AUTO_TEST_CASE(test_conversion_by_specialization)
{
    {
        const toml::value v{{"a", 42}, {"b", "baz"}};

        const auto bar = toml::get<extlib::bar>(v);
        BOOST_TEST(bar.a == 42);
        BOOST_TEST(bar.b == "baz");

        const toml::value v2(bar);

        BOOST_TEST(v == v2);
    }
    {
        const toml::value v{{"a", 42}, {"b", "baz"}};

        const auto bar = toml::get<extlib2::bar>(v);
        BOOST_TEST(bar.a == 42);
        BOOST_TEST(bar.b == "baz");

        const toml::value v2(bar);

        BOOST_TEST(v == v2);
    }
    {
        const toml::basic_value<toml::discard_comments, std::map, std::deque>
            v{{"a", 42}, {"b", "baz"}};

        const auto bar = toml::get<extlib2::bar>(v);
        BOOST_TEST(bar.a == 42);
        BOOST_TEST(bar.b == "baz");

        const toml::basic_value<toml::discard_comments, std::map, std::deque>
            v2(bar);

        BOOST_TEST(v == v2);
    }
}

BOOST_AUTO_TEST_CASE(test_recursive_conversion)
{
    {
        const toml::value v{
            toml::table{{"a", 42}, {"b", "baz"}},
            toml::table{{"a", 43}, {"b", "qux"}},
            toml::table{{"a", 44}, {"b", "quux"}},
            toml::table{{"a", 45}, {"b", "foobar"}},
        };

        const auto foos = toml::get<std::vector<extlib::foo>>(v);
        BOOST_TEST(foos.size()  == 4ul);
        BOOST_TEST(foos.at(0).a == 42);
        BOOST_TEST(foos.at(1).a == 43);
        BOOST_TEST(foos.at(2).a == 44);
        BOOST_TEST(foos.at(3).a == 45);

        BOOST_TEST(foos.at(0).b == "baz");
        BOOST_TEST(foos.at(1).b == "qux");
        BOOST_TEST(foos.at(2).b == "quux");
        BOOST_TEST(foos.at(3).b == "foobar");

        const auto bars = toml::get<std::vector<extlib::bar>>(v);
        BOOST_TEST(bars.size()  == 4ul);
        BOOST_TEST(bars.at(0).a == 42);
        BOOST_TEST(bars.at(1).a == 43);
        BOOST_TEST(bars.at(2).a == 44);
        BOOST_TEST(bars.at(3).a == 45);

        BOOST_TEST(bars.at(0).b == "baz");
        BOOST_TEST(bars.at(1).b == "qux");
        BOOST_TEST(bars.at(2).b == "quux");
        BOOST_TEST(bars.at(3).b == "foobar");
    }
    {
        const toml::value v{
                toml::table{{"a", 42}, {"b", "baz"}},
                toml::table{{"a", 43}, {"b", "qux"}},
                toml::table{{"a", 44}, {"b", "quux"}},
                toml::table{{"a", 45}, {"b", "foobar"}},
            };

        const auto foos = toml::get<std::vector<extlib2::foo>>(v);
        BOOST_TEST(foos.size()  == 4ul);
        BOOST_TEST(foos.at(0).a == 42);
        BOOST_TEST(foos.at(1).a == 43);
        BOOST_TEST(foos.at(2).a == 44);
        BOOST_TEST(foos.at(3).a == 45);

        BOOST_TEST(foos.at(0).b == "baz");
        BOOST_TEST(foos.at(1).b == "qux");
        BOOST_TEST(foos.at(2).b == "quux");
        BOOST_TEST(foos.at(3).b == "foobar");

        const auto bars = toml::get<std::vector<extlib2::bar>>(v);
        BOOST_TEST(bars.size()  == 4ul);
        BOOST_TEST(bars.at(0).a == 42);
        BOOST_TEST(bars.at(1).a == 43);
        BOOST_TEST(bars.at(2).a == 44);
        BOOST_TEST(bars.at(3).a == 45);

        BOOST_TEST(bars.at(0).b == "baz");
        BOOST_TEST(bars.at(1).b == "qux");
        BOOST_TEST(bars.at(2).b == "quux");
        BOOST_TEST(bars.at(3).b == "foobar");
    }

    {
        const toml::basic_value<toml::discard_comments, std::map, std::deque>
            v{
                toml::table{{"a", 42}, {"b", "baz"}},
                toml::table{{"a", 43}, {"b", "qux"}},
                toml::table{{"a", 44}, {"b", "quux"}},
                toml::table{{"a", 45}, {"b", "foobar"}}
            };

        const auto foos = toml::get<std::vector<extlib2::foo>>(v);
        BOOST_TEST(foos.size()  == 4ul);
        BOOST_TEST(foos.at(0).a == 42);
        BOOST_TEST(foos.at(1).a == 43);
        BOOST_TEST(foos.at(2).a == 44);
        BOOST_TEST(foos.at(3).a == 45);

        BOOST_TEST(foos.at(0).b == "baz");
        BOOST_TEST(foos.at(1).b == "qux");
        BOOST_TEST(foos.at(2).b == "quux");
        BOOST_TEST(foos.at(3).b == "foobar");

        const auto bars = toml::get<std::vector<extlib2::bar>>(v);
        BOOST_TEST(bars.size()  == 4ul);
        BOOST_TEST(bars.at(0).a == 42);
        BOOST_TEST(bars.at(1).a == 43);
        BOOST_TEST(bars.at(2).a == 44);
        BOOST_TEST(bars.at(3).a == 45);

        BOOST_TEST(bars.at(0).b == "baz");
        BOOST_TEST(bars.at(1).b == "qux");
        BOOST_TEST(bars.at(2).b == "quux");
        BOOST_TEST(bars.at(3).b == "foobar");
    }
}

<commit_msg>test: add test cases for one-way conversion<commit_after>#define BOOST_TEST_MODULE "test_extended_conversions"
#ifdef UNITTEST_FRAMEWORK_LIBRARY_EXIST
#include <boost/test/unit_test.hpp>
#else
#define BOOST_TEST_NO_LIB
#include <boost/test/included/unit_test.hpp>
#endif
#include <toml.hpp>
#include <deque>
#include <map>

namespace extlib
{
struct foo
{
    int a;
    std::string b;
};
struct bar
{
    int a;
    std::string b;

    void from_toml(const toml::value& v)
    {
        this->a = toml::find<int>(v, "a");
        this->b = toml::find<std::string>(v, "b");
        return ;
    }

    toml::table into_toml() const
    {
        return toml::table{{"a", this->a}, {"b", this->b}};
    }
};

struct baz
{
    int a;
    std::string b;
};
struct qux
{
    int a;
    std::string b;
};
} // extlib

namespace toml
{
template<>
struct from<extlib::foo>
{
    static extlib::foo from_toml(const toml::value& v)
    {
        return extlib::foo{toml::find<int>(v, "a"), toml::find<std::string>(v, "b")};
    }
};

template<>
struct into<extlib::foo>
{
    static toml::table into_toml(const extlib::foo& f)
    {
        return toml::table{{"a", f.a}, {"b", f.b}};
    }
};

template<>
struct from<extlib::baz>
{
    static extlib::baz from_toml(const toml::value& v)
    {
        return extlib::baz{toml::find<int>(v, "a"), toml::find<std::string>(v, "b")};
    }
};

template<>
struct into<extlib::qux>
{
    static toml::table into_toml(const extlib::qux& f)
    {
        return toml::table{{"a", f.a}, {"b", f.b}};
    }
};
} // toml

// ---------------------------------------------------------------------------

namespace extlib2
{
struct foo
{
    int a;
    std::string b;
};
struct bar
{
    int a;
    std::string b;

    template<typename C, template<typename ...> class M, template<typename ...> class A>
    void from_toml(const toml::basic_value<C, M, A>& v)
    {
        this->a = toml::find<int>(v, "a");
        this->b = toml::find<std::string>(v, "b");
        return ;
    }

    toml::table into_toml() const
    {
        return toml::table{{"a", this->a}, {"b", this->b}};
    }
};
struct baz
{
    int a;
    std::string b;
};
struct qux
{
    int a;
    std::string b;
};
} // extlib2

namespace toml
{
template<>
struct from<extlib2::foo>
{
    template<typename C, template<typename ...> class M, template<typename ...> class A>
    static extlib2::foo from_toml(const toml::basic_value<C, M, A>& v)
    {
        return extlib2::foo{toml::find<int>(v, "a"), toml::find<std::string>(v, "b")};
    }
};

template<>
struct into<extlib2::foo>
{
    static toml::table into_toml(const extlib2::foo& f)
    {
        return toml::table{{"a", f.a}, {"b", f.b}};
    }
};

template<>
struct from<extlib2::baz>
{
    template<typename C, template<typename ...> class M, template<typename ...> class A>
    static extlib2::baz from_toml(const toml::basic_value<C, M, A>& v)
    {
        return extlib2::baz{toml::find<int>(v, "a"), toml::find<std::string>(v, "b")};
    }
};

template<>
struct into<extlib2::qux>
{
    static toml::basic_value<toml::preserve_comments, std::map>
    into_toml(const extlib2::qux& f)
    {
        return toml::basic_value<toml::preserve_comments, std::map>{
            {"a", f.a}, {"b", f.b}
        };
    }
};
} // toml

// ---------------------------------------------------------------------------

BOOST_AUTO_TEST_CASE(test_conversion_by_member_methods)
{
    {
        const toml::value v{{"a", 42}, {"b", "baz"}};

        const auto foo = toml::get<extlib::foo>(v);
        BOOST_TEST(foo.a == 42);
        BOOST_TEST(foo.b == "baz");

        const toml::value v2(foo);

        BOOST_TEST(v == v2);
    }

    {
        const toml::value v{{"a", 42}, {"b", "baz"}};

        const auto foo = toml::get<extlib2::foo>(v);
        BOOST_TEST(foo.a == 42);
        BOOST_TEST(foo.b == "baz");

        const toml::value v2(foo);
        BOOST_TEST(v == v2);
    }

    {
        const toml::basic_value<toml::discard_comments, std::map, std::deque>
            v{{"a", 42}, {"b", "baz"}};

        const auto foo = toml::get<extlib2::foo>(v);
        BOOST_TEST(foo.a == 42);
        BOOST_TEST(foo.b == "baz");

        const toml::basic_value<toml::discard_comments, std::map, std::deque>
            v2(foo);

        BOOST_TEST(v == v2);
    }
}

BOOST_AUTO_TEST_CASE(test_conversion_by_specialization)
{
    {
        const toml::value v{{"a", 42}, {"b", "baz"}};

        const auto bar = toml::get<extlib::bar>(v);
        BOOST_TEST(bar.a == 42);
        BOOST_TEST(bar.b == "baz");

        const toml::value v2(bar);

        BOOST_TEST(v == v2);
    }
    {
        const toml::value v{{"a", 42}, {"b", "baz"}};

        const auto bar = toml::get<extlib2::bar>(v);
        BOOST_TEST(bar.a == 42);
        BOOST_TEST(bar.b == "baz");

        const toml::value v2(bar);

        BOOST_TEST(v == v2);
    }
    {
        const toml::basic_value<toml::discard_comments, std::map, std::deque>
            v{{"a", 42}, {"b", "baz"}};

        const auto bar = toml::get<extlib2::bar>(v);
        BOOST_TEST(bar.a == 42);
        BOOST_TEST(bar.b == "baz");

        const toml::basic_value<toml::discard_comments, std::map, std::deque>
            v2(bar);

        BOOST_TEST(v == v2);
    }
}

BOOST_AUTO_TEST_CASE(test_conversion_one_way)
{
    {
        const toml::value v{{"a", 42}, {"b", "baz"}};

        const auto baz = toml::get<extlib::baz>(v);
        BOOST_TEST(baz.a == 42);
        BOOST_TEST(baz.b == "baz");
    }
    {
        const extlib::qux q{42, "qux"};
        const toml::value v(q);

        BOOST_TEST(toml::find<int>(v, "a")         == 42);
        BOOST_TEST(toml::find<std::string>(v, "b") == "qux");
    }

    {
        const toml::basic_value<toml::discard_comments, std::map> v{
            {"a", 42}, {"b", "baz"}
        };

        const auto baz = toml::get<extlib2::baz>(v);
        BOOST_TEST(baz.a == 42);
        BOOST_TEST(baz.b == "baz");
    }
    {
        const extlib::qux q{42, "qux"};
        const toml::basic_value<toml::preserve_comments, std::map> v(q);

        BOOST_TEST(toml::find<int>(v, "a")         == 42);
        BOOST_TEST(toml::find<std::string>(v, "b") == "qux");
    }
}

BOOST_AUTO_TEST_CASE(test_recursive_conversion)
{
    {
        const toml::value v{
            toml::table{{"a", 42}, {"b", "baz"}},
            toml::table{{"a", 43}, {"b", "qux"}},
            toml::table{{"a", 44}, {"b", "quux"}},
            toml::table{{"a", 45}, {"b", "foobar"}},
        };

        const auto foos = toml::get<std::vector<extlib::foo>>(v);
        BOOST_TEST(foos.size()  == 4ul);
        BOOST_TEST(foos.at(0).a == 42);
        BOOST_TEST(foos.at(1).a == 43);
        BOOST_TEST(foos.at(2).a == 44);
        BOOST_TEST(foos.at(3).a == 45);

        BOOST_TEST(foos.at(0).b == "baz");
        BOOST_TEST(foos.at(1).b == "qux");
        BOOST_TEST(foos.at(2).b == "quux");
        BOOST_TEST(foos.at(3).b == "foobar");

        const auto bars = toml::get<std::vector<extlib::bar>>(v);
        BOOST_TEST(bars.size()  == 4ul);
        BOOST_TEST(bars.at(0).a == 42);
        BOOST_TEST(bars.at(1).a == 43);
        BOOST_TEST(bars.at(2).a == 44);
        BOOST_TEST(bars.at(3).a == 45);

        BOOST_TEST(bars.at(0).b == "baz");
        BOOST_TEST(bars.at(1).b == "qux");
        BOOST_TEST(bars.at(2).b == "quux");
        BOOST_TEST(bars.at(3).b == "foobar");
    }
    {
        const toml::value v{
                toml::table{{"a", 42}, {"b", "baz"}},
                toml::table{{"a", 43}, {"b", "qux"}},
                toml::table{{"a", 44}, {"b", "quux"}},
                toml::table{{"a", 45}, {"b", "foobar"}},
            };

        const auto foos = toml::get<std::vector<extlib2::foo>>(v);
        BOOST_TEST(foos.size()  == 4ul);
        BOOST_TEST(foos.at(0).a == 42);
        BOOST_TEST(foos.at(1).a == 43);
        BOOST_TEST(foos.at(2).a == 44);
        BOOST_TEST(foos.at(3).a == 45);

        BOOST_TEST(foos.at(0).b == "baz");
        BOOST_TEST(foos.at(1).b == "qux");
        BOOST_TEST(foos.at(2).b == "quux");
        BOOST_TEST(foos.at(3).b == "foobar");

        const auto bars = toml::get<std::vector<extlib2::bar>>(v);
        BOOST_TEST(bars.size()  == 4ul);
        BOOST_TEST(bars.at(0).a == 42);
        BOOST_TEST(bars.at(1).a == 43);
        BOOST_TEST(bars.at(2).a == 44);
        BOOST_TEST(bars.at(3).a == 45);

        BOOST_TEST(bars.at(0).b == "baz");
        BOOST_TEST(bars.at(1).b == "qux");
        BOOST_TEST(bars.at(2).b == "quux");
        BOOST_TEST(bars.at(3).b == "foobar");
    }

    {
        const toml::basic_value<toml::discard_comments, std::map, std::deque>
            v{
                toml::table{{"a", 42}, {"b", "baz"}},
                toml::table{{"a", 43}, {"b", "qux"}},
                toml::table{{"a", 44}, {"b", "quux"}},
                toml::table{{"a", 45}, {"b", "foobar"}}
            };

        const auto foos = toml::get<std::vector<extlib2::foo>>(v);
        BOOST_TEST(foos.size()  == 4ul);
        BOOST_TEST(foos.at(0).a == 42);
        BOOST_TEST(foos.at(1).a == 43);
        BOOST_TEST(foos.at(2).a == 44);
        BOOST_TEST(foos.at(3).a == 45);

        BOOST_TEST(foos.at(0).b == "baz");
        BOOST_TEST(foos.at(1).b == "qux");
        BOOST_TEST(foos.at(2).b == "quux");
        BOOST_TEST(foos.at(3).b == "foobar");

        const auto bars = toml::get<std::vector<extlib2::bar>>(v);
        BOOST_TEST(bars.size()  == 4ul);
        BOOST_TEST(bars.at(0).a == 42);
        BOOST_TEST(bars.at(1).a == 43);
        BOOST_TEST(bars.at(2).a == 44);
        BOOST_TEST(bars.at(3).a == 45);

        BOOST_TEST(bars.at(0).b == "baz");
        BOOST_TEST(bars.at(1).b == "qux");
        BOOST_TEST(bars.at(2).b == "quux");
        BOOST_TEST(bars.at(3).b == "foobar");
    }
}

<|endoftext|>


<commit_before>/*
Assimp2Json
Copyright (c) 2011, Alexander C. Gessler

Licensed under a 3-clause BSD license. See the LICENSE file for more information.

*/

#include <assimp/Importer.hpp>
#include <assimp/Exporter.hpp>

#include <assimp/version.h>
#include <assimp/postprocess.h>
#include <assimp/scene.h>

#include <iostream>

#include "version.h"

// json_exporter.cpp
extern Assimp::Exporter::ExportFormatEntry Assimp2Json_desc;

int unrecog_exit(int ex = -1)
{
	std::cout << "usage: assimp2json [--log --verbose] input [output]" << std::endl;
	return ex;
}

void printver()
{
	std::cout << "assimp2json v" << ASSIMP2JSON_VERSION_MAJOR << "." << ASSIMP2JSON_VERSION_MINOR << "\n";
	std::cout << "(c) 2011, Alexander C. Gessler\nLicensed under a 3-clause BSD license\n" <<
		"(assimp version: "
		<< aiGetVersionMajor() << "."
		<< aiGetVersionMinor() << "."
		<< aiGetVersionRevision() << ")"
		<< std::endl;
}

void printhelp()
{
}

int main (int argc, char *argv[])
{
	if (argc == 1) {
		return unrecog_exit(-1);
	}

	int nextarg = 1;
	while(nextarg < argc && argv[nextarg][0] == '-') {
		if (!strcmp(argv[nextarg],"--help")) {
			printhelp();
			return 0;
		}
		else if (!strcmp(argv[nextarg],"--version")) {
			printver();
			return 0;
		}
		++nextarg;
	}

	if (argc < nextarg+1) {
		return unrecog_exit(-2);
	}

	const char* in = argv[nextarg], *out = (argc < nextarg+2 ? NULL : argv[nextarg+1]);

	Assimp::Importer imp;

	// instruct aiProcess_FindDegenerates to drop degenerates
	imp.SetPropertyBool(AI_CONFIG_PP_FD_REMOVE, true);
	// instruct aiProcess_SortByPrimitiveType to drop line and point meshes
	imp.SetPropertyInteger(AI_CONFIG_PP_SBP_REMOVE, aiPrimitiveType_POINT | aiPrimitiveType_LINE);

	// instruct aiProcess_GenSmoothNormals to not smooth normals with an angle of more than 45deg
	imp.SetPropertyFloat(AI_CONFIG_PP_GSN_MAX_SMOOTHING_ANGLE, AI_MATH_HALF_PI_F * 0.5f );
	// instruct aiProcess_CalcTangents to not smooth normals with an angle of more than 45deg
	imp.SetPropertyFloat(AI_CONFIG_PP_CT_MAX_SMOOTHING_ANGLE, AI_MATH_HALF_PI_F * 0.5f );

	const aiScene* const sc = imp.ReadFile(in,aiProcessPreset_TargetRealtime_MaxQuality);
	if (!sc) {
		std::cerr << "failure reading file: " << in << std::endl;
		return -3;
	}

	Assimp::Exporter exp;
	exp.RegisterExporter(Assimp2Json_desc);

	if(out) {
		if(aiReturn_SUCCESS != exp.Export(sc,"json",out)) {
			std::cerr << "failure exporting file: " << out << ": " << exp.GetErrorString() << std::endl;
			return -4;
		}
	}
	else {
		// write to stdout, but we might do better than using ExportToBlob()
		const aiExportDataBlob* const blob = exp.ExportToBlob(sc,"json");
		if(!blob) {
			std::cerr << "failure exporting to (stdout) " << exp.GetErrorString() << std::endl;
			return -5;
		}

		const std::string s(static_cast<char*>( blob->data), blob->size);
		std::cout << s << std::endl;
	}
	return 0;
}
<commit_msg>Fix import configuration, smoothing angles are specified in degrees.<commit_after>/*
Assimp2Json
Copyright (c) 2011, Alexander C. Gessler

Licensed under a 3-clause BSD license. See the LICENSE file for more information.

*/

#include <assimp/Importer.hpp>
#include <assimp/Exporter.hpp>

#include <assimp/version.h>
#include <assimp/postprocess.h>
#include <assimp/scene.h>

#include <iostream>

#include "version.h"

// json_exporter.cpp
extern Assimp::Exporter::ExportFormatEntry Assimp2Json_desc;

int unrecog_exit(int ex = -1)
{
	std::cout << "usage: assimp2json [--log --verbose] input [output]" << std::endl;
	return ex;
}

void printver()
{
	std::cout << "assimp2json v" << ASSIMP2JSON_VERSION_MAJOR << "." << ASSIMP2JSON_VERSION_MINOR << "\n";
	std::cout << "(c) 2011, Alexander C. Gessler\nLicensed under a 3-clause BSD license\n" <<
		"(assimp version: "
		<< aiGetVersionMajor() << "."
		<< aiGetVersionMinor() << "."
		<< aiGetVersionRevision() << ")"
		<< std::endl;
}

void printhelp()
{
}

int main (int argc, char *argv[])
{
	if (argc == 1) {
		return unrecog_exit(-1);
	}

	int nextarg = 1;
	while(nextarg < argc && argv[nextarg][0] == '-') {
		if (!strcmp(argv[nextarg],"--help")) {
			printhelp();
			return 0;
		}
		else if (!strcmp(argv[nextarg],"--version")) {
			printver();
			return 0;
		}
		++nextarg;
	}

	if (argc < nextarg+1) {
		return unrecog_exit(-2);
	}

	const char* in = argv[nextarg], *out = (argc < nextarg+2 ? NULL : argv[nextarg+1]);

	Assimp::Importer imp;

	// instruct aiProcess_FindDegenerates to drop degenerates
	imp.SetPropertyBool(AI_CONFIG_PP_FD_REMOVE, true);
	// instruct aiProcess_SortByPrimitiveType to drop line and point meshes
	imp.SetPropertyInteger(AI_CONFIG_PP_SBP_REMOVE, aiPrimitiveType_POINT | aiPrimitiveType_LINE);

	// instruct aiProcess_GenSmoothNormals to not smooth normals with an angle of more than 45deg
	imp.SetPropertyFloat(AI_CONFIG_PP_GSN_MAX_SMOOTHING_ANGLE, 45.0f);
	// instruct aiProcess_CalcTangents to not smooth normals with an angle of more than 45deg
	imp.SetPropertyFloat(AI_CONFIG_PP_CT_MAX_SMOOTHING_ANGLE, 45.0f);

	const aiScene* const sc = imp.ReadFile(in,aiProcessPreset_TargetRealtime_MaxQuality);
	if (!sc) {
		std::cerr << "failure reading file: " << in << std::endl;
		return -3;
	}

	Assimp::Exporter exp;
	exp.RegisterExporter(Assimp2Json_desc);

	if(out) {
		if(aiReturn_SUCCESS != exp.Export(sc,"json",out)) {
			std::cerr << "failure exporting file: " << out << ": " << exp.GetErrorString() << std::endl;
			return -4;
		}
	}
	else {
		// write to stdout, but we might do better than using ExportToBlob()
		const aiExportDataBlob* const blob = exp.ExportToBlob(sc,"json");
		if(!blob) {
			std::cerr << "failure exporting to (stdout) " << exp.GetErrorString() << std::endl;
			return -5;
		}

		const std::string s(static_cast<char*>( blob->data), blob->size);
		std::cout << s << std::endl;
	}
	return 0;
}
<|endoftext|>


<commit_before>// CReadConfig
//
// New Class based on pmutils read functionality
// (C) Stefan Hoops 2001

//#include <sstream>
#include <string>
#include <iostream>
#include <fstream>

#include <assert.h>

#include "copasi.h"
#include "CReadConfig.h"

// char *InitInputBuffer(char *name);
static long GetFileSize(const char *name);

CReadConfig::CReadConfig(void)
{
    // initialize everything
    mFilename     = "test.txt";
    mpBufferBegin = NULL;
    mLineNumber   = 0;
    mFail         = 0;

    InitInputBuffer();
}

CReadConfig::CReadConfig(string name)
{
    // initialize everything
    mFilename     = name;
    mpBufferBegin = NULL;
    mLineNumber   = 0;
    mFail         = 0;

    InitInputBuffer();
}

CReadConfig::~CReadConfig(void)
{
    Free();
}

CReadConfig::Free(void)
{
    // if the buffer is initialized we free it and reset the buffer pointer
    if (mpBufferBegin)
    {
        free(mpBufferBegin);
        mpBufferBegin = NULL;
    }
    return mFail;
}

int CReadConfig::Fail()
{
    // return the failure state
    return mFail;
}

int CReadConfig::GetVariable(string name, string type, void * pout)
{
    char* szLine = NULL;
    char* szName = NULL;
    char* szValue= NULL;

    // Assure that the config buffer is initialized
    assert( mpBufferBegin != NULL );

    // For error messages we keep track of the current line number
    mLineNumber++;

    // Get the current line
    szLine = strdup(strtok(mpBufferPos, "\n"));
    // Move pointer to the beginning of the next line
    mpBufferPos += strlen(szLine) + 1;

    // We expect lines in the format Name=Value
    szName  = strtok(szLine, "=");
    szValue = szName + strlen(szName) + 1;

    // Assure that we have the name we are looking for
    if ( name != szName )
    {
        mFail = 1; // Error
    }

    // Return the value depending on the type
    if ( type == "string" )
    {
        *(string *) pout = szValue;
    }
    else if ( type == "double" )
    {
        // may be we should check if Value is really a double
        *(double *) pout = atof(szValue);
    }
    else if ( type == "int" )
    {
        // may be we should check if Value is really a integer
        *(int *) pout = atoi(szValue);
    }
    else
    {
        mFail = 1; //Error
    }

    // We free the line allocated through strdup
    if (szLine) free(szLine);
    return mFail;
}

int CReadConfig::InitInputBuffer()
{
    long FileSize = 0;

    // get the file size of the configuration file
    FileSize = GetFileSize(mFilename.c_str());
    if (FileSize == 0)
    {
        mFail = 1;  // Error
    }
    // allocate and zero the configuration buffer
    // add 1 to FileSize for zero terminator
    if (!(mpBufferBegin = (char *) calloc(FileSize + 1, sizeof(char))))
    {
        mFail = 1;  // Error
    }
    // initialze the position pointer to the beginning of the buffer
    mpBufferPos = mpBufferBegin;

    // read the configuration file into the configuration buffer
    ifstream File(mFilename.c_str());
    File.read(mpBufferBegin, FileSize);
    if (FileSize != File.gcount())
    {
        mFail = 1;  // Error
    }
    File.close();

    return mFail;
}

static long GetFileSize(const char *name)
{
    long ByteCnt = 0;

    // open the bytes in the configuration file
    ifstream File(name);
    // check whether we were successful
    if (File.fail())
    {
        cout << "Error initilizing configuration file: "
             << name << endl;
        return 0;
    }

    // count the bytes of the configuration file
    while (!File.eof())
    {
        File.get();
        ByteCnt++;
    }
    File.close();

    // we overcounted the EOF therefore the byte count is reduced by 1
    return ByteCnt-1;
}

<commit_msg>Modified the default constructor to have an empty file name.<commit_after>// CReadConfig
//
// New Class based on pmutils read functionality
// (C) Stefan Hoops 2001

//#include <sstream>
#include <string>
#include <iostream>
#include <fstream>

#include <assert.h>

#include "copasi.h"
#include "CReadConfig.h"

// char *InitInputBuffer(char *name);
static long GetFileSize(const char *name);

CReadConfig::CReadConfig(void)
{
    // initialize everything
    mFilename     = "";
    mpBufferBegin = NULL;
    mLineNumber   = 0;
    mFail         = 0;

    InitInputBuffer();
}

CReadConfig::CReadConfig(string name)
{
    // initialize everything
    mFilename     = name;
    mpBufferBegin = NULL;
    mLineNumber   = 0;
    mFail         = 0;

    InitInputBuffer();
}

CReadConfig::~CReadConfig(void)
{
    Free();
}

CReadConfig::Free(void)
{
    // if the buffer is initialized we free it and reset the buffer pointer
    if (mpBufferBegin)
    {
        free(mpBufferBegin);
        mpBufferBegin = NULL;
    }
    return mFail;
}

int CReadConfig::Fail()
{
    // return the failure state
    return mFail;
}

int CReadConfig::GetVariable(string name, string type, void * pout)
{
    char* szLine = NULL;
    char* szName = NULL;
    char* szValue= NULL;

    // Assure that the config buffer is initialized
    assert( mpBufferBegin != NULL );

    // For error messages we keep track of the current line number
    mLineNumber++;

    // Get the current line
    szLine = strdup(strtok(mpBufferPos, "\n"));
    // Move pointer to the beginning of the next line
    mpBufferPos += strlen(szLine) + 1;

    // We expect lines in the format Name=Value
    szName  = strtok(szLine, "=");
    szValue = szName + strlen(szName) + 1;

    // Assure that we have the name we are looking for
    if ( name != szName )
    {
        mFail = 1; // Error
    }

    // Return the value depending on the type
    if ( type == "string" )
    {
        *(string *) pout = szValue;
    }
    else if ( type == "double" )
    {
        // may be we should check if Value is really a double
        *(double *) pout = atof(szValue);
    }
    else if ( type == "int" )
    {
        // may be we should check if Value is really a integer
        *(int *) pout = atoi(szValue);
    }
    else
    {
        mFail = 1; //Error
    }

    // We free the line allocated through strdup
    if (szLine) free(szLine);
    return mFail;
}

int CReadConfig::InitInputBuffer()
{
    long FileSize = 0;

    // get the file size of the configuration file
    FileSize = GetFileSize(mFilename.c_str());
    if (FileSize == 0)
    {
        mFail = 1;  // Error
    }
    // allocate and zero the configuration buffer
    // add 1 to FileSize for zero terminator
    if (!(mpBufferBegin = (char *) calloc(FileSize + 1, sizeof(char))))
    {
        mFail = 1;  // Error
    }
    // initialze the position pointer to the beginning of the buffer
    mpBufferPos = mpBufferBegin;

    // read the configuration file into the configuration buffer
    ifstream File(mFilename.c_str());
    File.read(mpBufferBegin, FileSize);
    if (FileSize != File.gcount())
    {
        mFail = 1;  // Error
    }
    File.close();

    return mFail;
}

static long GetFileSize(const char *name)
{
    long ByteCnt = 0;

    // open the bytes in the configuration file
    ifstream File(name);
    // check whether we were successful
    if (File.fail())
    {
        cout << "Error initilizing configuration file: "
             << name << endl;
        return 0;
    }

    // count the bytes of the configuration file
    while (!File.eof())
    {
        File.get();
        ByteCnt++;
    }
    File.close();

    // we overcounted the EOF therefore the byte count is reduced by 1
    return ByteCnt-1;
}

<|endoftext|>


<commit_before>// Copyright 2016-2017 John T. Foster, Katy L. Hanson

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

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

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

#include "Teuchos_RCP.hpp"

#include "tadiga_IGES_geometry.h"

tadiga::IgesGeometry::IgesGeometry(
    const Teuchos::RCP<const Teuchos::Comm<int>>& kComm,
    const Teuchos::RCP<Teuchos::ParameterList>& kGeometryParameters)
    : kComm_(kComm) {
    const auto kFileName = kGeometryParameters->get<std::string>("File Name");

    // Open IGES Reader from OpenCASCADE
    const auto kIgesReader = Teuchos::rcp(new IGESControl_Reader);
    const auto status = kIgesReader->ReadFile(kFileName.c_str());

    // TODO(johntfoster@gmail.com): Check the status of the file

    Handle(TColStd_HSequenceOfTransient) myFacesList =
        kIgesReader->GiveList("iges-faces");
    Handle(TColStd_HSequenceOfTransient) myPointsList =
        kIgesReader->GiveList("iges-type(116)");

    // selects all IGES faces in the file and puts them into a list  called
    // //MyList,

    const auto kIgesFaces = myFacesList->Length();
    const auto kTransFaces = kIgesReader->TransferList(myFacesList);
    const auto kIgesPoints = myPointsList->Length();
    const auto kTransPoints = kIgesReader->TransferList(myPointsList);

    // translates MyList,

    std::cout << "IGES Faces: " << kIgesFaces
              << "   Transferred:" << kTransFaces << std::endl;
    std::cout << "IGES Points: " << kIgesPoints
              << "   Transferred:" << kTransPoints << std::endl;
   TopoDS_Shape sh = kIgesReader->OneShape();
};
<commit_msg>Change to read Edge instead of Point<commit_after>// Copyright 2016-2017 John T. Foster, Katy L. Hanson

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

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

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

#include "Teuchos_RCP.hpp"

#include "tadiga_IGES_geometry.h"

tadiga::IgesGeometry::IgesGeometry(
    const Teuchos::RCP<const Teuchos::Comm<int>>& kComm,
    const Teuchos::RCP<Teuchos::ParameterList>& kGeometryParameters)
    : kComm_(kComm) {
    const auto kFileName = kGeometryParameters->get<std::string>("File Name");

    // Open IGES Reader from OpenCASCADE
    const auto kIgesReader = Teuchos::rcp(new IGESControl_Reader);
    const auto status = kIgesReader->ReadFile(kFileName.c_str());

    // TODO(johntfoster@gmail.com): Check the status of the file

    Handle(TColStd_HSequenceOfTransient) myFacesList =
        kIgesReader->GiveList("iges-faces");
    Handle(TColStd_HSequenceOfTransient) myPointsList =
        kIgesReader->GiveList("iges-type(110)");

    // selects all IGES faces in the file and puts them into a list  called
    // //MyList,

    const auto kIgesFaces = myFacesList->Length();
    const auto kTransFaces = kIgesReader->TransferList(myFacesList);
    const auto kIgesPoints = myPointsList->Length();
    const auto kTransPoints = kIgesReader->TransferList(myPointsList);

    // translates MyList,

    std::cout << "IGES Faces: " << kIgesFaces
              << "   Transferred:" << kTransFaces << std::endl;
    std::cout << "IGES Points: " << kIgesPoints
              << "   Transferred:" << kTransPoints << std::endl;
   TopoDS_Shape sh = kIgesReader->OneShape();
};
<|endoftext|>


<commit_before>// Begin CVS Header
//   $Source: /Volumes/Home/Users/shoops/cvs/copasi_dev/copasi/UI/CopasiFileDialog.cpp,v $
//   $Revision: 1.28 $
//   $Name:  $
//   $Author: aekamal $
//   $Date: 2009/09/28 14:51:54 $
// End CVS Header

// Copyright (C) 2008 by Pedro Mendes, Virginia Tech Intellectual
// Properties, Inc., EML Research, gGmbH, University of Heidelberg,
// and The University of Manchester.
// All rights reserved.

// Copyright (C) 2001 - 2007 by Pedro Mendes, Virginia Tech Intellectual
// Properties, Inc. and EML Research, gGmbH.
// All rights reserved.

#include <qfiledialog.h>

#include "copasi.h"

#include "CopasiFileDialog.h"
#include "qtUtilities.h"
#include "CQMessageBox.h"

#include "commandline/COptions.h"
#include "utilities/CDirEntry.h"

#ifdef DEBUG_UI
#include <QtDebug>
#endif

// static
QDir CopasiFileDialog::LastDir;

// static
void CopasiFileDialog::openExampleDir()
{
  std::string ExampleDir;
  COptions::getValue("ExampleDir", ExampleDir);

  if (CDirEntry::isDir(ExampleDir))
    LastDir = FROM_UTF8(ExampleDir);
  else
    CQMessageBox::information(NULL, "Directory Not Found", FROM_UTF8(ExampleDir),
                              QMessageBox::Ok, QMessageBox::Ok);
}

// static
QString CopasiFileDialog::getOpenFileName(QWidget * parent,
    const char * /* name */,
    const QString & startWith,
    const QString & filter,
    const QString & caption,
    QString * pSelectedFilter)
{
  QString newFile = QFileDialog::getOpenFileName(parent,
                    caption,
                    startWith.isNull() ? LastDir.path() : startWith,
                    filter,
                    pSelectedFilter);

  if (newFile != "")
    LastDir = FROM_UTF8(CDirEntry::dirName(TO_UTF8(newFile)));

  return newFile;
}

// static
QString CopasiFileDialog::getSaveFileName(QWidget * parent,
    const char * name,
    const QString & startWith,
    const QString & filter,
    const QString & caption,
    QString * pSelectedFilter)
{
  QString newFile, newFilter = filter;
  bool fileValid;

  if (!pSelectedFilter)
    pSelectedFilter = new QString("");

  if (filter.indexOf("(*)") < 0)
    newFilter += ";;Any File (*)";

  do
    {
      fileValid = true;
      newFile = QFileDialog::getSaveFileName(parent,
                                             caption,
                                             startWith.isNull() ? LastDir.path() : startWith,
                                             newFilter, pSelectedFilter,
                                             QFileDialog::DontConfirmOverwrite);

      if (newFile != "")
        LastDir = FROM_UTF8(CDirEntry::dirName(TO_UTF8(newFile)));
      else
        return QString::null;

      if (pSelectedFilter->indexOf("(*)") >= 0)
        {
          QString fileName = FROM_UTF8(CDirEntry::fileName(TO_UTF8(newFile)));
          QString suffix = FROM_UTF8(CDirEntry::suffix(TO_UTF8(newFile)));

          if (!suffix.length())
            {
              fileValid = true;
            }
          else
            {
              QRegExp rx("\\.\\S{1,4}$");

              if (rx.indexIn(fileName) < 0)
                {
                  CQMessageBox::information(NULL, "Save File Error",
                                            "Filename can have an extension 1 to 4 characters long.",
                                            QMessageBox::Ok, QMessageBox::Ok);
                  fileValid = false;
                  continue;
                }

              QRegExp rxDigits("\\.\\d{1,4}$");

              if (rxDigits.indexIn(fileName) > 0)
                {
                  CQMessageBox::information(NULL, "Save File Error",
                                            "All characters in the file extension cannot be digits.",
                                            QMessageBox::Ok, QMessageBox::Ok);
                  fileValid = false;
                  continue;
                }
            }
        }
    }
  while (fileValid == false);

#ifdef DEBUG_UI
  qDebug() << "user selected Filter = " << usersFilter;
//  qDebug() << "user's Filter = " << *pSelectedFilter;
  qDebug() << "correct extension = " << correctExt;
  qDebug() << "filename = " << newFile;
#endif

  return newFile;
}
<commit_msg>Fix a little bug on debug comment.<commit_after>// Begin CVS Header
//   $Source: /Volumes/Home/Users/shoops/cvs/copasi_dev/copasi/UI/CopasiFileDialog.cpp,v $
//   $Revision: 1.29 $
//   $Name:  $
//   $Author: pwilly $
//   $Date: 2009/10/01 00:12:03 $
// End CVS Header

// Copyright (C) 2008 by Pedro Mendes, Virginia Tech Intellectual
// Properties, Inc., EML Research, gGmbH, University of Heidelberg,
// and The University of Manchester.
// All rights reserved.

// Copyright (C) 2001 - 2007 by Pedro Mendes, Virginia Tech Intellectual
// Properties, Inc. and EML Research, gGmbH.
// All rights reserved.

#include <qfiledialog.h>

#include "copasi.h"

#include "CopasiFileDialog.h"
#include "qtUtilities.h"
#include "CQMessageBox.h"

#include "commandline/COptions.h"
#include "utilities/CDirEntry.h"

#ifdef DEBUG_UI
#include <QtDebug>
#endif

// static
QDir CopasiFileDialog::LastDir;

// static
void CopasiFileDialog::openExampleDir()
{
  std::string ExampleDir;
  COptions::getValue("ExampleDir", ExampleDir);

  if (CDirEntry::isDir(ExampleDir))
    LastDir = FROM_UTF8(ExampleDir);
  else
    CQMessageBox::information(NULL, "Directory Not Found", FROM_UTF8(ExampleDir),
                              QMessageBox::Ok, QMessageBox::Ok);
}

// static
QString CopasiFileDialog::getOpenFileName(QWidget * parent,
    const char * /* name */,
    const QString & startWith,
    const QString & filter,
    const QString & caption,
    QString * pSelectedFilter)
{
  QString newFile = QFileDialog::getOpenFileName(parent,
                    caption,
                    startWith.isNull() ? LastDir.path() : startWith,
                    filter,
                    pSelectedFilter);

  if (newFile != "")
    LastDir = FROM_UTF8(CDirEntry::dirName(TO_UTF8(newFile)));

  return newFile;
}

// static
QString CopasiFileDialog::getSaveFileName(QWidget * parent,
    const char * name,
    const QString & startWith,
    const QString & filter,
    const QString & caption,
    QString * pSelectedFilter)
{
  QString newFile, newFilter = filter;
  bool fileValid;

  if (!pSelectedFilter)
    pSelectedFilter = new QString("");

  if (filter.indexOf("(*)") < 0)
    newFilter += ";;Any File (*)";

  do
    {
      fileValid = true;
      newFile = QFileDialog::getSaveFileName(parent,
                                             caption,
                                             startWith.isNull() ? LastDir.path() : startWith,
                                             newFilter, pSelectedFilter,
                                             QFileDialog::DontConfirmOverwrite);

      if (newFile != "")
        LastDir = FROM_UTF8(CDirEntry::dirName(TO_UTF8(newFile)));
      else
        return QString::null;

      if (pSelectedFilter->indexOf("(*)") >= 0)
        {
          QString fileName = FROM_UTF8(CDirEntry::fileName(TO_UTF8(newFile)));
          QString suffix = FROM_UTF8(CDirEntry::suffix(TO_UTF8(newFile)));

          if (!suffix.length())
            {
              fileValid = true;
            }
          else
            {
              QRegExp rx("\\.\\S{1,4}$");

              if (rx.indexIn(fileName) < 0)
                {
                  CQMessageBox::information(NULL, "Save File Error",
                                            "Filename can have an extension 1 to 4 characters long.",
                                            QMessageBox::Ok, QMessageBox::Ok);
                  fileValid = false;
                  continue;
                }

              QRegExp rxDigits("\\.\\d{1,4}$");

              if (rxDigits.indexIn(fileName) > 0)
                {
                  CQMessageBox::information(NULL, "Save File Error",
                                            "All characters in the file extension cannot be digits.",
                                            QMessageBox::Ok, QMessageBox::Ok);
                  fileValid = false;
                  continue;
                }
            }
        }
    }
  while (fileValid == false);

#ifdef DEBUG_UI
//  qDebug() << "user selected Filter = " << usersFilter;
  qDebug() << "user's Filter = " << *pSelectedFilter;
//  qDebug() << "correct extension = " << correctExt;
//  qDebug() << "filename = " << newFile;
#endif

  return newFile;
}
<|endoftext|>


<commit_before>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: parseenv.cxx,v $
 *
 *  $Revision: 1.5 $
 *
 *  last change: $Author: hr $ $Date: 2007-11-02 17:04:12 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    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
 *
 ************************************************************************/

#include <precomp.h>
#include <semantic/parseenv.hxx>

// NOT FULLY DECLARED SERVICES
#include <ary/doc/d_oldcppdocu.hxx>
#include <x_parse.hxx>

void
ParseEnvironment::Enter( E_EnvStackAction   i_eWayOfEntering )
{
    switch (i_eWayOfEntering)
    {
        case push:
                InitData();
                if ( Parent() != 0 )
                {
                    csv_assert( Parent()->CurSubPeUse() != 0 );
                    Parent()->CurSubPeUse()->InitParse();
                }
                break;
        case pop_success:
                break;
        case pop_failure:
                break;
        default:
            csv_assert(false);
    }   // end switch
}

void
ParseEnvironment::Leave( E_EnvStackAction   i_eWayOfLeaving )
{
    switch (i_eWayOfLeaving)
    {
        case push:
                break;
        case pop_success:
                TransferData();
                if ( Parent() != 0 )
                {
                    csv_assert( Parent()->CurSubPeUse() != 0 );
                    Parent()->CurSubPeUse()->GetResults();
                }
                break;
        case pop_failure:
                break;
        default:
            csv_assert(false);
    }   // end switch
}

ParseEnvironment::ParseEnvironment( ParseEnvironment *  i_pParent )
    :   pParent(i_pParent),
        // pDocu,
        pCurSubPe(0)
{
}

void
ParseEnvironment::GlobalHandlingOfSyntaxError( const char * i_sTokenText,
                                               const char * i_sFileName,
                                               uintt        i_nLineCount )
{
    throw X_Parser( X_Parser::x_UnexpectedToken,
                    i_sTokenText,
                    i_sFileName,
                    i_nLineCount );
}

<commit_msg>INTEGRATION: CWS changefileheader (1.5.22); FILE MERGED 2008/03/28 16:02:38 rt 1.5.22.1: #i87441# Change license header to LPGL v3.<commit_after>/*************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2008 by Sun Microsystems, Inc.
 *
 * OpenOffice.org - a multi-platform office productivity suite
 *
 * $RCSfile: parseenv.cxx,v $
 * $Revision: 1.6 $
 *
 * This file is part of OpenOffice.org.
 *
 * OpenOffice.org is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License version 3
 * only, as published by the Free Software Foundation.
 *
 * OpenOffice.org 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 version 3 for more details
 * (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU Lesser General Public License
 * version 3 along with OpenOffice.org.  If not, see
 * <http://www.openoffice.org/license.html>
 * for a copy of the LGPLv3 License.
 *
 ************************************************************************/

#include <precomp.h>
#include <semantic/parseenv.hxx>

// NOT FULLY DECLARED SERVICES
#include <ary/doc/d_oldcppdocu.hxx>
#include <x_parse.hxx>

void
ParseEnvironment::Enter( E_EnvStackAction   i_eWayOfEntering )
{
    switch (i_eWayOfEntering)
    {
        case push:
                InitData();
                if ( Parent() != 0 )
                {
                    csv_assert( Parent()->CurSubPeUse() != 0 );
                    Parent()->CurSubPeUse()->InitParse();
                }
                break;
        case pop_success:
                break;
        case pop_failure:
                break;
        default:
            csv_assert(false);
    }   // end switch
}

void
ParseEnvironment::Leave( E_EnvStackAction   i_eWayOfLeaving )
{
    switch (i_eWayOfLeaving)
    {
        case push:
                break;
        case pop_success:
                TransferData();
                if ( Parent() != 0 )
                {
                    csv_assert( Parent()->CurSubPeUse() != 0 );
                    Parent()->CurSubPeUse()->GetResults();
                }
                break;
        case pop_failure:
                break;
        default:
            csv_assert(false);
    }   // end switch
}

ParseEnvironment::ParseEnvironment( ParseEnvironment *  i_pParent )
    :   pParent(i_pParent),
        // pDocu,
        pCurSubPe(0)
{
}

void
ParseEnvironment::GlobalHandlingOfSyntaxError( const char * i_sTokenText,
                                               const char * i_sFileName,
                                               uintt        i_nLineCount )
{
    throw X_Parser( X_Parser::x_UnexpectedToken,
                    i_sTokenText,
                    i_sFileName,
                    i_nLineCount );
}

<|endoftext|>


<commit_before>/*****************************************************************************
* PROGRAM NAME: COutputEvent.cpp
* PROGRAMMER: Wei Sun	wsun@vt.edu
* PURPOSE: COutputEvent Class Implemention
*****************************************************************************/
#include "copasi.h"
#include "output.h"
// #include "COutputEvent.h"

/**
 *	Default constructor.
 */
COutputEvent::COutputEvent()
{
	mTime = 0;
}

/**
 *	User defined constructor.
 *  @param tra refers to the CTrajectory object.
 *  @param time refers to the output interval
 *	time = 0, header
 *	time = 1, any time of simulation exceution
 *  time = 2, the final result
 */
COutputEvent::COutputEvent(CTrajectory &tra, int time)
{
	mTime = time;
}

/**
 *	User defined constructor.
 *  @param tra refers to the CSS_solution object.
 *  @param time refers to the output interval
 */
COutputEvent::COutputEvent(CSS_Solution &ss)
{
	//mTime = time;
	mTime = 0;				// wsun steady state just output one line data
}

/**
 * Print output at the specified time
 * @param tra refers to the CTrajectory object.
 * @param time refers to the output interval
 * @param list refer to the while output list of this model
 */
void COutputEvent::print(CTrajectory &tra, COutputList list, ofstream &fout)
{

	list.copasiDyn(fout, mTime);
}

/**
 * Print output at the specified time
 * @param tra refers to the CSS_solution object.
 * @param time refers to the output interval
 * @param list refer to the while output list of this model
 */
void COutputEvent::print(CSS_Solution &ss, COutputList list, ofstream &fout)
{
	list.copasiSS(fout);
}

/**
 * Clean Up
 */

void COutputEvent::cleanup()
{
}

/**
 * Deconstructor
 */
COutputEvent::~COutputEvent()
{
	cleanup();
}

<commit_msg>1. Remove parameter time from one constructor. 2. Pass solution to COutput model.<commit_after>/*****************************************************************************
* PROGRAM NAME: COutputEvent.cpp
* PROGRAMMER: Wei Sun	wsun@vt.edu
* PURPOSE: COutputEvent Class Implemention
*****************************************************************************/
#include "copasi.h"
#include "output.h"
// #include "COutputEvent.h"

/**
 *	Default constructor.
 */
COutputEvent::COutputEvent()
{
	mTime = 0;
}

/**
 *	User defined constructor.
 *  @param tra refers to the CTrajectory object.
 *  @param time refers to the output interval
 *	time = 0, header
 *	time = 1, any time of simulation exceution
 *  time = 2, the final result
 */
COutputEvent::COutputEvent(CTrajectory &tra, int time)
{
	mTime = time;
}

/**
 *	User defined constructor.
 *  @param tra refers to the CSS_solution object.
 *  @param time refers to the output interval
 */
COutputEvent::COutputEvent(CSS_Solution &ss)
{
	//mTime = time;
	mTime = 0;				// wsun steady state just output one line data
}

/**
 * Print output at the specified time
 * @param tra refers to the CTrajectory object.
 * @param time refers to the output interval
 * @param list refer to the while output list of this model
 */
void COutputEvent::print(CTrajectory &tra, COutputList list, ofstream &fout)
{

	list.copasiDyn(fout, mTime);
}

/**
 * Print output at the specified time
 * @param tra refers to the CSS_solution object.
 * @param time refers to the output interval
 * @param list refer to the while output list of this model
 */
void COutputEvent::print(CSS_Solution &ss, COutputList list, ofstream &fout)
{
	list.copasiSS(fout, ss.getSolution());
}

/**
 * Clean Up
 */

void COutputEvent::cleanup()
{
}

/**
 * Deconstructor
 */
COutputEvent::~COutputEvent()
{
	cleanup();
}

<|endoftext|>