<commit_before>// Copyright (c) 2015-2016 Andrew Sutton
// All rights reserved

#include "lookup.hpp"
#include "ast.hpp"
#include "context.hpp"
#include "scope.hpp"
#include "print.hpp"

#include <iostream>

namespace banjo
{

// Returns the non-empty set of declarations for give (unqualified) id.
// Throws an exception if no matching declarations are found.
//
// Lookup ends as soon as a declaration is found for the given name.
//
// TODO: How should we handle non-simple id's like operator-ids
// and conversion function ids.
Decl_list
unqualified_lookup(Context& cxt, Scope& scope, Simple_id const& id)
{
  Scope* p = &scope;
  while (p) {
    // In general, a name used in any context must be declared
    // before it's use. Search this scope for such a declaration.
    if (Overload_set* ovl = p->lookup(id))
      return *ovl;

    // Depending on current scope, we might re-direct the scope
    // to search different things.

    if (Function_scope* s = as<Function_scope>(p)) {
      Decl& f = s->declaration();
      (void)f;

      // TODO: If fn is defined by a qualified-id, then we should
      // should search the scope(s) named in the id before resuming
      // the search.
    }

    else if (Class_scope* cs = as<Class_scope>(p)) {
      Class_decl& c = cs->declaration();
      (void)c;

      // TODO: Include base classes of c. Lookup also depends on
      // the declarative region of c (nested classes, locals, etc).
    }

    else if (Initializer_scope* s = as<Initializer_scope>(p)) {
      Decl& v = s->declaration();
      (void)v;

      // TODO: If v is declared by a qualified-id, then re-direct
      // to the scope of v before working outwards.
    }

    p = p->enclosing_scope();
  }

  throw Lookup_error(cxt, "no matching declaration for '{}'", id);
}

// Simple lookup is a form of unqualified lookup that returns the
// single declaration associated with the name.
Decl&
simple_lookup(Context& cxt, Scope& scope, Simple_id const& id)
{
  Decl_list result = unqualified_lookup(cxt, scope, id);

  // FIXME: Can we find names that are *like* id?
  if (result.empty())
    throw Lookup_error(cxt, "no matching declaration for '{}'", id);

  // FIXME: Find some way of attaching informative diagnotics
  // to the error (i.e., candidates).
  if (result.size() > 1)
    throw Lookup_error(cxt, "lookup of '{}' is ambiguous", id);

  return result.front();
}

/*
Decl_list
qualified_lookup(Scope&, Symbol const&)
{
  return nullptr;
}

Decl_list
argument_dependent_lookup(Scope&, Expr_list&)
{
  return nullptr;
}
*/

static Type_list
get_operand_types(Call_expr& e)
{
  Type_list ts;
  ts.push_back(e.function().type());
  for (Expr& e : e.arguments())
    ts.push_back(e.type());
  return ts;
}

static Type_list
get_operand_types(Expr& e)
{
  struct fn
  {
    Type_list operator()(Expr& e)        { banjo_unhandled_case(e); }
    Type_list operator()(Unary_expr& e)  { return {&e.operand().type()}; }
    Type_list operator()(Binary_expr& e) { return {&e.left().type(), &e.right().type()}; }
    Type_list operator()(Call_expr& e)   { return get_operand_types(e); }
  };
  return apply(e, fn{});
}

// Lookup the expression in the current requirement scope. This
// returns the expressions whose operands have equivalent type or
// nullptr if they no such expression has been declared.
//
// FIXME: This is a hack. Lookup should use an operator-id and
// perform a lookup in a table, and NOT searching through a
// list of requirements.
Expr*
requirement_lookup(Context& cxt, Expr& e)
{
  Requires_scope& s = *cxt.current_requires_scope();

  Type_list t1 = get_operand_types(e); // Yuck.
  for (Expr& e2 : s.exprs) {
    // Expressions of different kinds are not comparable.
    if (typeid(e) != typeid(e2))
      continue;

    // Compare the types of operands.
    Type_list t2 = get_operand_types(e2);
    if (is_equivalent(t1, t2)) {
      return &e;
    }
  }
  return nullptr;
}

} // namespace banjo
<commit_msg>Fix an unreported lookup bug from Clang.<commit_after>// Copyright (c) 2015-2016 Andrew Sutton
// All rights reserved

#include "lookup.hpp"
#include "ast.hpp"
#include "context.hpp"
#include "scope.hpp"
#include "print.hpp"

#include <iostream>

namespace banjo
{

// Returns the non-empty set of declarations for give (unqualified) id.
// Throws an exception if no matching declarations are found.
//
// Lookup ends as soon as a declaration is found for the given name.
//
// TODO: How should we handle non-simple id's like operator-ids
// and conversion function ids.
Decl_list
unqualified_lookup(Context& cxt, Scope& scope, Simple_id const& id)
{
  Scope* p = &scope;
  while (p) {
    // In general, a name used in any context must be declared
    // before it's use. Search this scope for such a declaration.
    if (Overload_set* ovl = p->lookup(id))
      return *ovl;

    // Depending on current scope, we might re-direct the scope
    // to search different things.

    if (Function_scope* s = as<Function_scope>(p)) {
      Decl& f = s->declaration();
      (void)f;

      // TODO: If fn is defined by a qualified-id, then we should
      // should search the scope(s) named in the id before resuming
      // the search.
    }

    else if (Class_scope* cs = as<Class_scope>(p)) {
      Class_decl& c = cs->declaration();
      (void)c;

      // TODO: Include base classes of c. Lookup also depends on
      // the declarative region of c (nested classes, locals, etc).
    }

    else if (Initializer_scope* s = as<Initializer_scope>(p)) {
      Decl& v = s->declaration();
      (void)v;

      // TODO: If v is declared by a qualified-id, then re-direct
      // to the scope of v before working outwards.
    }

    p = p->enclosing_scope();
  }

  throw Lookup_error(cxt, "no matching declaration for '{}'", id);
}

// Simple lookup is a form of unqualified lookup that returns the
// single declaration associated with the name.
Decl&
simple_lookup(Context& cxt, Scope& scope, Simple_id const& id)
{
  Decl_list result = unqualified_lookup(cxt, scope, id);

  // FIXME: Can we find names that are *like* id?
  if (result.empty())
    throw Lookup_error(cxt, "no matching declaration for '{}'", id);

  // FIXME: Find some way of attaching informative diagnotics
  // to the error (i.e., candidates).
  if (result.size() > 1)
    throw Lookup_error(cxt, "lookup of '{}' is ambiguous", id);

  return result.front();
}

/*
Decl_list
qualified_lookup(Scope&, Symbol const&)
{
  return nullptr;
}

Decl_list
argument_dependent_lookup(Scope&, Expr_list&)
{
  return nullptr;
}
*/

static Type_list
get_operand_types(Call_expr& e)
{
  Type_list ts;
  ts.push_back(e.function().type());
  for (Expr& a : e.arguments())
    ts.push_back(a.type());
  return ts;
}

static Type_list
get_operand_types(Expr& e)
{
  struct fn
  {
    Type_list operator()(Expr& e)        { banjo_unhandled_case(e); }
    Type_list operator()(Unary_expr& e)  { return {&e.operand().type()}; }
    Type_list operator()(Binary_expr& e) { return {&e.left().type(), &e.right().type()}; }
    Type_list operator()(Call_expr& e)   { return get_operand_types(e); }
  };
  return apply(e, fn{});
}

// Lookup the expression in the current requirement scope. This
// returns the expressions whose operands have equivalent type or
// nullptr if they no such expression has been declared.
//
// FIXME: This is a hack. Lookup should use an operator-id and
// perform a lookup in a table, and NOT searching through a
// list of requirements.
Expr*
requirement_lookup(Context& cxt, Expr& e)
{
  Requires_scope& s = *cxt.current_requires_scope();

  Type_list t1 = get_operand_types(e); // Yuck.
  for (Expr& e2 : s.exprs) {
    // Expressions of different kinds are not comparable.
    if (typeid(e) != typeid(e2))
      continue;

    // Compare the types of operands.
    Type_list t2 = get_operand_types(e2);
    if (is_equivalent(t1, t2)) {
      return &e;
    }
  }
  return nullptr;
}

} // namespace banjo
<|endoftext|>


<commit_before>#include "stack.hpp"
#include "perf_testing.hpp"
#include "debug_t.hpp"
#include <numeric>
#include <deque>

#define CATCH_CONFIG_MAIN
#include "include_catch.hpp"

template<typename It>
void cheat_sort(It first, It last) {
  if (std::distance(first, last) < 20) {
    std::sort(first, last);
    return;
  }

  if (first.outer() == last.outer()) {
    std::sort(first.inner(), last.inner());
  }
  else {
    using T = typename It::value_type;
    std::array<T,3> pivots{{ *first, *(first + (last - first) / 2), *(last - 1) }};
    std::sort(pivots.begin(), pivots.end());
    auto pivot = pivots[1];
    auto middle = std::partition(first, last, [=](const T& val) { return val < pivot; });
    cheat_sort(first, middle);
    cheat_sort(middle, last);
  }
}

template<typename C>
struct cheat_sort_perf_test {
  cheat_sort_perf_test(size_t N) {
    random_generator<typename C::value_type> generator;
    std::generate_n(std::back_inserter(values), N, [&] { return generator(engine); });
  }

  void operator()() {
    cheat_sort(values.begin(), values.end());
  }

  std::mt19937 engine;
  C values;
};

template<typename container_t>
double get_cheat_sort_time(size_t N) {
  return measure_time_ns([N] { return cheat_sort_perf_test<container_t>(N); });
}

TEST_CASE("New stack is empty") {
  cwt::stack<int> s;
  REQUIRE(s.size() == 0);
}

TEST_CASE("New stack is empty range") {
  cwt::stack<int> s;
  REQUIRE(s.begin() == s.end());
}

TEST_CASE("Add one element to stack") {
  cwt::stack<int> s;
  s.push_back(6);
  REQUIRE(s.size() == 1);
  REQUIRE(std::distance(s.begin(), s.end()) == 1);
  REQUIRE(s[0] == 6);
  REQUIRE(*s.begin() == 6);
  REQUIRE(*(s.end() - 1) == 6);
  REQUIRE(std::accumulate(s.begin(), s.end(), 0) == 6);
}

TEST_CASE("Add three elements to stack") {
  cwt::stack<int> s;
  s.push_back(6);
  s.push_back(3);
  s.push_back(7);
  REQUIRE(s.size() == 3);
  REQUIRE(std::distance(s.begin(), s.end()) == 3);
  REQUIRE(s[0] == 6);
  REQUIRE(s[1] == 3);
  REQUIRE(s[2] == 7);
  REQUIRE(*s.begin() == 6);
  REQUIRE(*(s.end() - 1) == 7);
  REQUIRE(std::accumulate(s.begin(), s.end(), 0) == 16);
}

TEST_CASE("Add many elements to stack") {
  cwt::stack<int> s;
  std::vector<int> v;

  for (int i = 0; i < 1000; ++i) {
    s.push_back(i);
    v.push_back(i);
    REQUIRE(s.size() == v.size());
    REQUIRE(*(s.begin() + (static_cast<int>(v.size()) - 1)) == i);
  }

  REQUIRE(std::equal(s.begin(), s.end(), v.begin()));
}

TEST_CASE("Stack calls correct constructors/destructors") {
  struct test_tag {};

  {
    cwt::stack<cwt::debug_t<test_tag>> s;
    REQUIRE(cwt::debug_t<test_tag>::live_objects().size() == 0);

    for (int i = 0; i < 100; ++i) {
      s.push_back(i);
    }

    REQUIRE(s.size() == 100);
    REQUIRE(cwt::debug_t<test_tag>::live_objects().size() == 100);
  }

  REQUIRE(cwt::debug_t<test_tag>::live_objects().size() == 0);
}

TEST_CASE("Iterators work for sorting") {
  cwt::stack<int> s;
  for (int i = 0; i < 1000; ++i) {
    s.push_back(i);
  }

  std::mt19937 engine;
  std::shuffle(s.begin(), s.end(), engine);

  std::vector<int> v(s.begin(), s.end());
  std::sort(s.begin(), s.end());
  std::sort(v.begin(), v.end());

  REQUIRE(s.size() == v.size());
  REQUIRE(std::equal(v.begin(), v.end(), s.begin(), s.end()));
}

TEST_CASE("integer push back average memory usage") {
  std::cout << std::endl << "integer push back average memory usage" << std::endl;
  std::cout << "N, vector, stack, deque" << std::endl;
  for (size_t N = 1; N < 100'000; N = static_cast<size_t>(static_cast<double>(N) * 1.5 + 1)) {
    auto vector_time = get_average_memory_usage<std::vector, int>(N);
    auto stack_time = get_average_memory_usage<cwt::stack, int>(N);
    auto dequeue_time = get_average_memory_usage<std::deque, int>(N);
    std::cout << N << ", " << vector_time << ", " << stack_time << ", " << dequeue_time << std::endl;
  }
}

TEST_CASE("integer push back total bytes") {
  std::cout << std::endl << "integer push back total bytes" << std::endl;
  std::cout << "N, vector, stack, deque" << std::endl;
  for (size_t N = 1; N < 100'000; N = static_cast<size_t>(static_cast<double>(N) * 1.5 + 1)) {
    auto vector_time = count_total_allocated_bytes<std::vector, int>(N);
    auto stack_time = count_total_allocated_bytes<cwt::stack, int>(N);
    auto dequeue_time = count_total_allocated_bytes<std::deque, int>(N);
    std::cout << N << ", " << vector_time << ", " << stack_time << ", " << dequeue_time << std::endl;
  }
}

#ifdef NDEBUG
TEST_CASE("Stack is faster than vector for integer push_back") {
  auto vec_time = get_push_back_time<std::vector<int>>(1'000'000);
  auto queue_time = get_push_back_time<std::deque<int>>(1'000'000);
  auto stack_time = get_push_back_time<cwt::stack<int>>(1'000'000);

  WARN(vec_time);
  WARN(queue_time);
  WARN(stack_time);

  CHECK(stack_time < vec_time);
  CHECK(stack_time < queue_time);
}

/*TEST_CASE("Measure sort time for stack") {
  std::cout << std::endl << "integer sorting" << std::endl;
  std::cout << "N, vector, stack, deque" << std::endl;
  for (int N = 10; N < 1'000'000; N *= 2) {
    auto vector_time = get_sort_time<std::vector<int>>(N);
    auto stack_time = get_sort_time<cwt::stack<int>>(N);
    auto dequeue_time = get_sort_time<std::deque<int>>(N);
    std::cout << N << ", " << vector_time << ", " << stack_time << ", " << dequeue_time << std::endl;
  }
}*/

TEST_CASE("Measure cheat sort time for stack") {
  std::cout << std::endl << "integer sorting" << std::endl;
  std::cout << "N, vector, stack, deque" << std::endl;
  for (size_t N = 10; N < 1'000'000; N *= 2) {
    auto vector_time = get_sort_time<std::vector<int>>(N);
    auto stack_time = get_cheat_sort_time<cwt::stack<int>>(N);
    auto dequeue_time = get_sort_time<std::deque<int>>(N);
    std::cout << N << ", " << vector_time << ", " << stack_time << ", " << dequeue_time << std::endl;
  }
}
#endif

<commit_msg>test speed at various N<commit_after>#include "stack.hpp"
#include "perf_testing.hpp"
#include "debug_t.hpp"
#include <numeric>
#include <deque>

#define CATCH_CONFIG_MAIN
#include "include_catch.hpp"

template<typename It>
void cheat_sort(It first, It last) {
  if (std::distance(first, last) < 20) {
    std::sort(first, last);
    return;
  }

  if (first.outer() == last.outer()) {
    std::sort(first.inner(), last.inner());
  }
  else {
    using T = typename It::value_type;
    std::array<T,3> pivots{{ *first, *(first + (last - first) / 2), *(last - 1) }};
    std::sort(pivots.begin(), pivots.end());
    auto pivot = pivots[1];
    auto middle = std::partition(first, last, [=](const T& val) { return val < pivot; });
    cheat_sort(first, middle);
    cheat_sort(middle, last);
  }
}

template<typename C>
struct cheat_sort_perf_test {
  cheat_sort_perf_test(size_t N) {
    random_generator<typename C::value_type> generator;
    std::generate_n(std::back_inserter(values), N, [&] { return generator(engine); });
  }

  void operator()() {
    cheat_sort(values.begin(), values.end());
  }

  std::mt19937 engine;
  C values;
};

template<typename container_t>
double get_cheat_sort_time(size_t N) {
  return measure_time_ns([N] { return cheat_sort_perf_test<container_t>(N); });
}

TEST_CASE("New stack is empty") {
  cwt::stack<int> s;
  REQUIRE(s.size() == 0);
}

TEST_CASE("New stack is empty range") {
  cwt::stack<int> s;
  REQUIRE(s.begin() == s.end());
}

TEST_CASE("Add one element to stack") {
  cwt::stack<int> s;
  s.push_back(6);
  REQUIRE(s.size() == 1);
  REQUIRE(std::distance(s.begin(), s.end()) == 1);
  REQUIRE(s[0] == 6);
  REQUIRE(*s.begin() == 6);
  REQUIRE(*(s.end() - 1) == 6);
  REQUIRE(std::accumulate(s.begin(), s.end(), 0) == 6);
}

TEST_CASE("Add three elements to stack") {
  cwt::stack<int> s;
  s.push_back(6);
  s.push_back(3);
  s.push_back(7);
  REQUIRE(s.size() == 3);
  REQUIRE(std::distance(s.begin(), s.end()) == 3);
  REQUIRE(s[0] == 6);
  REQUIRE(s[1] == 3);
  REQUIRE(s[2] == 7);
  REQUIRE(*s.begin() == 6);
  REQUIRE(*(s.end() - 1) == 7);
  REQUIRE(std::accumulate(s.begin(), s.end(), 0) == 16);
}

TEST_CASE("Add many elements to stack") {
  cwt::stack<int> s;
  std::vector<int> v;

  for (int i = 0; i < 1000; ++i) {
    s.push_back(i);
    v.push_back(i);
    REQUIRE(s.size() == v.size());
    REQUIRE(*(s.begin() + (static_cast<int>(v.size()) - 1)) == i);
  }

  REQUIRE(std::equal(s.begin(), s.end(), v.begin()));
}

TEST_CASE("Stack calls correct constructors/destructors") {
  struct test_tag {};

  {
    cwt::stack<cwt::debug_t<test_tag>> s;
    REQUIRE(cwt::debug_t<test_tag>::live_objects().size() == 0);

    for (int i = 0; i < 100; ++i) {
      s.push_back(i);
    }

    REQUIRE(s.size() == 100);
    REQUIRE(cwt::debug_t<test_tag>::live_objects().size() == 100);
  }

  REQUIRE(cwt::debug_t<test_tag>::live_objects().size() == 0);
}

TEST_CASE("Iterators work for sorting") {
  cwt::stack<int> s;
  for (int i = 0; i < 1000; ++i) {
    s.push_back(i);
  }

  std::mt19937 engine;
  std::shuffle(s.begin(), s.end(), engine);

  std::vector<int> v(s.begin(), s.end());
  std::sort(s.begin(), s.end());
  std::sort(v.begin(), v.end());

  REQUIRE(s.size() == v.size());
  REQUIRE(std::equal(v.begin(), v.end(), s.begin(), s.end()));
}

TEST_CASE("integer push back average memory usage") {
  std::cout << std::endl << "integer push back average memory usage" << std::endl;
  std::cout << "N, vector, stack, deque" << std::endl;
  for (size_t N = 1; N < 100'000; N = static_cast<size_t>(static_cast<double>(N) * 1.5 + 1)) {
    auto vector_time = get_average_memory_usage<std::vector, int>(N);
    auto stack_time = get_average_memory_usage<cwt::stack, int>(N);
    auto dequeue_time = get_average_memory_usage<std::deque, int>(N);
    std::cout << N << ", " << vector_time << ", " << stack_time << ", " << dequeue_time << std::endl;
  }
}

TEST_CASE("integer push back total bytes") {
  std::cout << std::endl << "integer push back total bytes" << std::endl;
  std::cout << "N, vector, stack, deque" << std::endl;
  for (size_t N = 1; N < 100'000; N = static_cast<size_t>(static_cast<double>(N) * 1.5 + 1)) {
    auto vector_time = count_total_allocated_bytes<std::vector, int>(N);
    auto stack_time = count_total_allocated_bytes<cwt::stack, int>(N);
    auto dequeue_time = count_total_allocated_bytes<std::deque, int>(N);
    std::cout << N << ", " << vector_time << ", " << stack_time << ", " << dequeue_time << std::endl;
  }
}

#ifdef NDEBUG
TEST_CASE("Stack is faster than vector for integer push_back") {
  std::cout << std::endl << "integer push back" << std::endl;
  std::cout << "N, vector, stack, deque" << std::endl;
  for (size_t N = 1000; N < 1'000'000; N *= 2) {
    auto vec_time = get_push_back_time<std::vector<int>>(N);
    auto queue_time = get_push_back_time<std::deque<int>>(N);
    auto stack_time = get_push_back_time<cwt::stack<int>>(N);
    std::cout << N
      << ", " << vec_time
      << ", " << stack_time
      << ", " << queue_time
      << std::endl;

    CHECK(stack_time < vec_time);
    CHECK(stack_time < queue_time);
  }
}

/*TEST_CASE("Measure sort time for stack") {
  std::cout << std::endl << "integer sorting" << std::endl;
  std::cout << "N, vector, stack, deque" << std::endl;
  for (int N = 10; N < 1'000'000; N *= 2) {
    auto vector_time = get_sort_time<std::vector<int>>(N);
    auto stack_time = get_sort_time<cwt::stack<int>>(N);
    auto dequeue_time = get_sort_time<std::deque<int>>(N);
    std::cout << N << ", " << vector_time << ", " << stack_time << ", " << dequeue_time << std::endl;
  }
}*/

TEST_CASE("Measure cheat sort time for stack") {
  std::cout << std::endl << "integer sorting" << std::endl;
  std::cout << "N, vector, stack, deque" << std::endl;
  for (size_t N = 10; N < 1'000'000; N *= 2) {
    auto vector_time = get_sort_time<std::vector<int>>(N);
    auto stack_time = get_cheat_sort_time<cwt::stack<int>>(N);
    auto dequeue_time = get_sort_time<std::deque<int>>(N);
    std::cout << N << ", " << vector_time << ", " << stack_time << ", " << dequeue_time << std::endl;
  }
}
#endif

<|endoftext|>


<commit_before>//===-- PlatformAndroid.cpp -------------------------------------*- C++ -*-===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//

// C Includes
// C++ Includes
// Other libraries and framework includes
#include "lldb/Core/Log.h"
#include "lldb/Core/PluginManager.h"
#include "lldb/Host/HostInfo.h"
#include "Utility/UriParser.h"

// Project includes
#include "AdbClient.h"
#include "PlatformAndroid.h"
#include "PlatformAndroidRemoteGDBServer.h"

using namespace lldb;
using namespace lldb_private;
using namespace lldb_private::platform_android;

static uint32_t g_initialize_count = 0;

void
PlatformAndroid::Initialize ()
{
    PlatformLinux::Initialize ();

    if (g_initialize_count++ == 0)
    {
#if defined(__ANDROID__)
        PlatformSP default_platform_sp (new PlatformAndroid(true));
        default_platform_sp->SetSystemArchitecture(HostInfo::GetArchitecture());
        Platform::SetHostPlatform (default_platform_sp);
#endif
        PluginManager::RegisterPlugin (PlatformAndroid::GetPluginNameStatic(false),
                                       PlatformAndroid::GetPluginDescriptionStatic(false),
                                       PlatformAndroid::CreateInstance);
    }
}

void
PlatformAndroid::Terminate ()
{
    if (g_initialize_count > 0)
    {
        if (--g_initialize_count == 0)
        {
            PluginManager::UnregisterPlugin (PlatformAndroid::CreateInstance);
        }
    }

    PlatformLinux::Terminate ();
}

PlatformSP
PlatformAndroid::CreateInstance (bool force, const ArchSpec *arch)
{
    Log *log(GetLogIfAllCategoriesSet (LIBLLDB_LOG_PLATFORM));
    if (log)
    {
        const char *arch_name;
        if (arch && arch->GetArchitectureName ())
            arch_name = arch->GetArchitectureName ();
        else
            arch_name = "<null>";

        const char *triple_cstr = arch ? arch->GetTriple ().getTriple ().c_str() : "<null>";

        log->Printf ("PlatformAndroid::%s(force=%s, arch={%s,%s})", __FUNCTION__, force ? "true" : "false", arch_name, triple_cstr);
    }

    bool create = force;
    if (create == false && arch && arch->IsValid())
    {
        const llvm::Triple &triple = arch->GetTriple();
        switch (triple.getVendor())
        {
            case llvm::Triple::PC:
                create = true;
                break;

#if defined(__ANDROID__)
            // Only accept "unknown" for the vendor if the host is android and
            // it "unknown" wasn't specified (it was just returned because it
            // was NOT specified_
            case llvm::Triple::VendorType::UnknownVendor:
                create = !arch->TripleVendorWasSpecified();
                break;
#endif
            default:
                break;
        }

        if (create)
        {
            switch (triple.getOS())
            {
                case llvm::Triple::Android:
                    break;

#if defined(__ANDROID__)
                // Only accept "unknown" for the OS if the host is android and
                // it "unknown" wasn't specified (it was just returned because it
                // was NOT specified)
                case llvm::Triple::OSType::UnknownOS:
                    create = !arch->TripleOSWasSpecified();
                    break;
#endif
                default:
                    create = false;
                    break;
            }
        }
    }

    if (create)
    {
        if (log)
            log->Printf ("PlatformAndroid::%s() creating remote-android platform", __FUNCTION__);
        return PlatformSP(new PlatformAndroid(false));
    }

    if (log)
        log->Printf ("PlatformAndroid::%s() aborting creation of remote-android platform", __FUNCTION__);

    return PlatformSP();
}

PlatformAndroid::PlatformAndroid (bool is_host) :
    PlatformLinux(is_host)
{
}

PlatformAndroid::~PlatformAndroid()
{
}

ConstString
PlatformAndroid::GetPluginNameStatic (bool is_host)
{
    if (is_host)
    {
        static ConstString g_host_name(Platform::GetHostPlatformName ());
        return g_host_name;
    }
    else
    {
        static ConstString g_remote_name("remote-android");
        return g_remote_name;
    }
}

const char *
PlatformAndroid::GetPluginDescriptionStatic (bool is_host)
{
    if (is_host)
        return "Local Android user platform plug-in.";
    else
        return "Remote Android user platform plug-in.";
}

ConstString
PlatformAndroid::GetPluginName()
{
    return GetPluginNameStatic(IsHost());
}

Error
PlatformAndroid::ConnectRemote(Args& args)
{
    m_device_id.clear();

    if (IsHost())
    {
        return Error ("can't connect to the host platform '%s', always connected", GetPluginName().GetCString());
    }

    if (!m_remote_platform_sp)
        m_remote_platform_sp = PlatformSP(new PlatformAndroidRemoteGDBServer());

    int port;
    std::string scheme, host, path;
    const char *url = args.GetArgumentAtIndex(0);
    if (!url)
        return Error("URL is null.");
    if (!UriParser::Parse(url, scheme, host, port, path))
        return Error("Invalid URL: %s", url);
    if (scheme == "adb")
        m_device_id = host;

    auto error = PlatformLinux::ConnectRemote(args);
    if (error.Success())
    {
        AdbClient adb;
        error = AdbClient::CreateByDeviceID(m_device_id, adb);
        if (error.Fail())
            return error;

        m_device_id = adb.GetDeviceID();
    }
    return error;
}

Error
PlatformAndroid::GetFile (const FileSpec& source,
                          const FileSpec& destination)
{
    if (IsHost() || !m_remote_platform_sp)
        return PlatformLinux::GetFile(source, destination);

    FileSpec source_spec (source.GetPath (false), false, FileSpec::ePathSyntaxPosix);
    if (source_spec.IsRelativeToCurrentWorkingDirectory ())
        source_spec = GetRemoteWorkingDirectory ().CopyByAppendingPathComponent (source_spec.GetCString (false));

    AdbClient adb (m_device_id);
    return adb.PullFile (source_spec, destination);
}

Error
PlatformAndroid::PutFile (const FileSpec& source,
                          const FileSpec& destination,
                          uint32_t uid,
                          uint32_t gid)
{
    if (!IsHost() && m_remote_platform_sp)
    {
        AdbClient adb (m_device_id);
        // TODO: Set correct uid and gid on remote file.
        return adb.PushFile(source, destination);
    }
    return PlatformLinux::PutFile(source, destination, uid, gid);
}

const char *
PlatformAndroid::GetCacheHostname ()
{
    return m_device_id.c_str ();
}

Error
PlatformAndroid::DownloadModuleSlice (const FileSpec &src_file_spec,
                                      const uint64_t src_offset,
                                      const uint64_t src_size,
                                      const FileSpec &dst_file_spec)
{
    if (src_offset != 0)
        return Error ("Invalid offset - %" PRIu64, src_offset);

    return GetFile (src_file_spec, dst_file_spec);
}
<commit_msg>Fix PlatformAndroid::PutFile to support relative destination paths.<commit_after>//===-- PlatformAndroid.cpp -------------------------------------*- C++ -*-===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//

// C Includes
// C++ Includes
// Other libraries and framework includes
#include "lldb/Core/Log.h"
#include "lldb/Core/PluginManager.h"
#include "lldb/Host/HostInfo.h"
#include "Utility/UriParser.h"

// Project includes
#include "AdbClient.h"
#include "PlatformAndroid.h"
#include "PlatformAndroidRemoteGDBServer.h"

using namespace lldb;
using namespace lldb_private;
using namespace lldb_private::platform_android;

static uint32_t g_initialize_count = 0;

void
PlatformAndroid::Initialize ()
{
    PlatformLinux::Initialize ();

    if (g_initialize_count++ == 0)
    {
#if defined(__ANDROID__)
        PlatformSP default_platform_sp (new PlatformAndroid(true));
        default_platform_sp->SetSystemArchitecture(HostInfo::GetArchitecture());
        Platform::SetHostPlatform (default_platform_sp);
#endif
        PluginManager::RegisterPlugin (PlatformAndroid::GetPluginNameStatic(false),
                                       PlatformAndroid::GetPluginDescriptionStatic(false),
                                       PlatformAndroid::CreateInstance);
    }
}

void
PlatformAndroid::Terminate ()
{
    if (g_initialize_count > 0)
    {
        if (--g_initialize_count == 0)
        {
            PluginManager::UnregisterPlugin (PlatformAndroid::CreateInstance);
        }
    }

    PlatformLinux::Terminate ();
}

PlatformSP
PlatformAndroid::CreateInstance (bool force, const ArchSpec *arch)
{
    Log *log(GetLogIfAllCategoriesSet (LIBLLDB_LOG_PLATFORM));
    if (log)
    {
        const char *arch_name;
        if (arch && arch->GetArchitectureName ())
            arch_name = arch->GetArchitectureName ();
        else
            arch_name = "<null>";

        const char *triple_cstr = arch ? arch->GetTriple ().getTriple ().c_str() : "<null>";

        log->Printf ("PlatformAndroid::%s(force=%s, arch={%s,%s})", __FUNCTION__, force ? "true" : "false", arch_name, triple_cstr);
    }

    bool create = force;
    if (create == false && arch && arch->IsValid())
    {
        const llvm::Triple &triple = arch->GetTriple();
        switch (triple.getVendor())
        {
            case llvm::Triple::PC:
                create = true;
                break;

#if defined(__ANDROID__)
            // Only accept "unknown" for the vendor if the host is android and
            // it "unknown" wasn't specified (it was just returned because it
            // was NOT specified_
            case llvm::Triple::VendorType::UnknownVendor:
                create = !arch->TripleVendorWasSpecified();
                break;
#endif
            default:
                break;
        }

        if (create)
        {
            switch (triple.getOS())
            {
                case llvm::Triple::Android:
                    break;

#if defined(__ANDROID__)
                // Only accept "unknown" for the OS if the host is android and
                // it "unknown" wasn't specified (it was just returned because it
                // was NOT specified)
                case llvm::Triple::OSType::UnknownOS:
                    create = !arch->TripleOSWasSpecified();
                    break;
#endif
                default:
                    create = false;
                    break;
            }
        }
    }

    if (create)
    {
        if (log)
            log->Printf ("PlatformAndroid::%s() creating remote-android platform", __FUNCTION__);
        return PlatformSP(new PlatformAndroid(false));
    }

    if (log)
        log->Printf ("PlatformAndroid::%s() aborting creation of remote-android platform", __FUNCTION__);

    return PlatformSP();
}

PlatformAndroid::PlatformAndroid (bool is_host) :
    PlatformLinux(is_host)
{
}

PlatformAndroid::~PlatformAndroid()
{
}

ConstString
PlatformAndroid::GetPluginNameStatic (bool is_host)
{
    if (is_host)
    {
        static ConstString g_host_name(Platform::GetHostPlatformName ());
        return g_host_name;
    }
    else
    {
        static ConstString g_remote_name("remote-android");
        return g_remote_name;
    }
}

const char *
PlatformAndroid::GetPluginDescriptionStatic (bool is_host)
{
    if (is_host)
        return "Local Android user platform plug-in.";
    else
        return "Remote Android user platform plug-in.";
}

ConstString
PlatformAndroid::GetPluginName()
{
    return GetPluginNameStatic(IsHost());
}

Error
PlatformAndroid::ConnectRemote(Args& args)
{
    m_device_id.clear();

    if (IsHost())
    {
        return Error ("can't connect to the host platform '%s', always connected", GetPluginName().GetCString());
    }

    if (!m_remote_platform_sp)
        m_remote_platform_sp = PlatformSP(new PlatformAndroidRemoteGDBServer());

    int port;
    std::string scheme, host, path;
    const char *url = args.GetArgumentAtIndex(0);
    if (!url)
        return Error("URL is null.");
    if (!UriParser::Parse(url, scheme, host, port, path))
        return Error("Invalid URL: %s", url);
    if (scheme == "adb")
        m_device_id = host;

    auto error = PlatformLinux::ConnectRemote(args);
    if (error.Success())
    {
        AdbClient adb;
        error = AdbClient::CreateByDeviceID(m_device_id, adb);
        if (error.Fail())
            return error;

        m_device_id = adb.GetDeviceID();
    }
    return error;
}

Error
PlatformAndroid::GetFile (const FileSpec& source,
                          const FileSpec& destination)
{
    if (IsHost() || !m_remote_platform_sp)
        return PlatformLinux::GetFile(source, destination);

    FileSpec source_spec (source.GetPath (false), false, FileSpec::ePathSyntaxPosix);
    if (source_spec.IsRelativeToCurrentWorkingDirectory ())
        source_spec = GetRemoteWorkingDirectory ().CopyByAppendingPathComponent (source_spec.GetCString (false));

    AdbClient adb (m_device_id);
    return adb.PullFile (source_spec, destination);
}

Error
PlatformAndroid::PutFile (const FileSpec& source,
                          const FileSpec& destination,
                          uint32_t uid,
                          uint32_t gid)
{
    if (IsHost() || !m_remote_platform_sp)
        return PlatformLinux::PutFile (source, destination, uid, gid);

    FileSpec destination_spec (destination.GetPath (false), false, FileSpec::ePathSyntaxPosix);
    if (destination_spec.IsRelativeToCurrentWorkingDirectory ())
        destination_spec = GetRemoteWorkingDirectory ().CopyByAppendingPathComponent (destination_spec.GetCString (false));

    AdbClient adb (m_device_id);
    // TODO: Set correct uid and gid on remote file.
    return adb.PushFile(source, destination_spec);
}

const char *
PlatformAndroid::GetCacheHostname ()
{
    return m_device_id.c_str ();
}

Error
PlatformAndroid::DownloadModuleSlice (const FileSpec &src_file_spec,
                                      const uint64_t src_offset,
                                      const uint64_t src_size,
                                      const FileSpec &dst_file_spec)
{
    if (src_offset != 0)
        return Error ("Invalid offset - %" PRIu64, src_offset);

    return GetFile (src_file_spec, dst_file_spec);
}
<|endoftext|>


<commit_before><commit_msg>WaE: overriding virtual function declaration not marked 'override'<commit_after><|endoftext|>


<commit_before>#pragma once

#include "concurrent_queue.hpp"
#include "delegate.hpp"
#include <thread>
#include <vector>
#include <atomic>
#include <condition_variable>

#define TASK_SIZE_BYTES 48

namespace dw
{
    using WorkerFunction = Delegate<void(void*)>;

    struct Task
    {
        WorkerFunction _function;
        char						 _data[TASK_SIZE_BYTES];
    };

    template <typename T>
    inline T* task_data(Task& task)
    {
        return static_cast<T*>(&task._data[0]);
    }

    template <size_t WorkerCount = 4, size_t QueueSize = 1024>
    class ThreadPool
    {
        using TaskQueue = ConcurrentQueue<Task, QueueSize>;

    public:
        ThreadPool()
        {
            _shutdown = false;
            _pending_tasks = 0;

            // clear queue
            concurrent_queue::clear(_queue);

            // get number of logical threads on CPU
            _num_logical_threads = std::thread::hardware_concurrency();

            // spawn worker threads
            for (int i = 0; i < WorkerCount; i++)
                _worker_threads.push_back(std::thread(&ThreadPool::worker_function, this, i));
        }

        ~ThreadPool()
        {
            _mutex.lock();
            _shutdown = true;
            _condition.notify_all();
            _mutex.unlock();

            for (auto& thread : _worker_threads)
                thread.join();
        }

        inline void enqueue(Task& task)
        {
            concurrent_queue::push(_queue, task);
            _pending_tasks++;
            _condition.notify_one();
        }

        inline void wait()
        {
            std::unique_lock<std::mutex> lock(_mutex);
            _condition.wait(lock, [this]
                            {
                                return (_pending_tasks == 0);
                            });
        }

        inline size_t get_num_logical_threads()
        {
            return _num_logical_threads;
        }

    private:
        inline void worker_function(int index)
        {
            while (true)
            {
                //if (concurrent_queue::empty(_queue))
                {
                    // lock thread
                    std::unique_lock<std::mutex> lock(_mutex);

                    _condition.wait(lock, [this]
                                    {
                                        return (!concurrent_queue::empty(_queue) || _shutdown) ;
                                    });

                    if (_shutdown)
                        return;
                }
                //else
                {
                    // pop front item
                    Task task = concurrent_queue::pop(_queue);

                    // execute task
                    task._function.Invoke(&task._data);

                    if(_pending_tasks > 0)
                        _pending_tasks--;

                    _condition.notify_all();
                }
            }
        }

    private:
        bool									  _shutdown;
        uint16_t							  _num_logical_threads;
        TaskQueue						  _queue;
        std::vector<std::thread> _worker_threads;
        std::mutex						  _mutex;
        std::condition_variable   _condition;
        std::atomic_int				  _pending_tasks;

    };
}
<commit_msg>- Fixed race condition during enqueue. - Increased Task data size to 100 bytes. - Changed static_cast in task_data helper to C-style cast.<commit_after>#pragma once

#include "concurrent_queue.hpp"
#include "delegate.hpp"
#include <thread>
#include <vector>
#include <atomic>
#include <condition_variable>

#define TASK_SIZE_BYTES 100

namespace dw
{
    using WorkerFunction = Delegate<void(void*)>;

    struct Task
    {
        WorkerFunction _function;
        char		   _data[TASK_SIZE_BYTES];
    };

    template <typename T>
    inline T* task_data(Task& task)
    {
        return (T*)(&task._data[0]);
    }

    template <size_t WorkerCount = 4, size_t QueueSize = 1024>
    class ThreadPool
    {
        using TaskQueue = ConcurrentQueue<Task, QueueSize>;

    public:
        ThreadPool()
        {
            _shutdown = false;
            _pending_tasks = 0;

            // clear queue
            concurrent_queue::clear(_queue);

            // get number of logical threads on CPU
            _num_logical_threads = std::thread::hardware_concurrency();

            // spawn worker threads
            for (int i = 0; i < WorkerCount; i++)
                _worker_threads.push_back(std::thread(&ThreadPool::worker_function, this, i));
        }

        ~ThreadPool()
        {
            _mutex.lock();
            _shutdown = true;
            _condition.notify_all();
            _mutex.unlock();

            for (auto& thread : _worker_threads)
                thread.join();
        }

        inline void enqueue(Task& task)
        {
            std::lock_guard<std::mutex> lock(_mutex);
            concurrent_queue::push(_queue, task);
            _pending_tasks++;
            _condition.notify_one();
        }

        inline void wait()
        {
            std::unique_lock<std::mutex> lock(_mutex);
            _condition.wait(lock, [this]
                            {
                                return (_pending_tasks == 0);
                            });
        }

        inline size_t get_num_logical_threads()
        {
            return _num_logical_threads;
        }

    private:
        inline void worker_function(int index)
        {
            while (true)
            {
                //if (concurrent_queue::empty(_queue))
                {
                    // lock thread
                    std::unique_lock<std::mutex> lock(_mutex);

                    _condition.wait(lock, [this]
                                    {
                                        return (!concurrent_queue::empty(_queue) || _shutdown) ;
                                    });

                    if (_shutdown)
                        return;
                }
                //else
                {
                    // pop front item
                    Task task = concurrent_queue::pop(_queue);

                    // execute task
                    task._function.Invoke(&task._data);

                    if(_pending_tasks > 0)
                        _pending_tasks--;

                    _condition.notify_all();
                }
            }
        }

    private:
        bool					  _shutdown;
        uint16_t				  _num_logical_threads;
        TaskQueue				  _queue;
        std::vector<std::thread>  _worker_threads;
        std::mutex				  _mutex;
        std::condition_variable   _condition;
        std::atomic_int			  _pending_tasks;

    };
}
<|endoftext|>


<commit_before>#include "Distributions.hh"
#include "conf.hh"
#include "LinearAlgebra.hh"

conf::Config config;

int
main(int argc, char *argv[])
{
  try {
    config("usage: gconvert [OPTION...]\n")
      ('h', "help", "", "", "display help")
      ('g', "gk=FILE", "arg must", "", "previous distributions (.gk)")
      ('o', "out=FILE", "arg must", "", "converted file (.gk)")
      ('d', "to-diagonal", "", "", "convert Gaussians to diagonal")
      ('f', "to-full", "", "", "convert Gaussians to full covariances")
      ;
    config.default_parse(argc, argv);

    if (config["to-diagonal"].specified && config["to-full"].specified)
      throw std::string("Don't define both -d and -f!");

    if (!config["to-diagonal"].specified && !config["to-full"].specified)
      throw std::string("Define either -d and -f!");

    PDFPool pool;
    PDFPool new_pool;
    pool.read_gk(config["gk"].get_str());

    Matrix covariance;
    Vector mean;
    for (int i=0; i<pool.size(); i++) {

      // Fetch source Gaussian
      Gaussian *gaussian = dynamic_cast< Gaussian* > (pool.get_pdf(i));
      if (gaussian == NULL)
        continue;

      // Create target Gaussian
      Gaussian *new_gaussian = NULL;
      if (config["to-diagonal"].specified)
        new_gaussian = new DiagonalGaussian(gaussian->dim());
      if (config["to-full"].specified)
        new_gaussian = new FullCovarianceGaussian(gaussian->dim());

      // Convert
      gaussian->get_covariance(covariance);
      gaussian->get_mean(mean);
      new_gaussian->set_covariance(covariance);
      new_gaussian->set_mean(mean);

      new_pool.set_pdf(i, new_gaussian);
    }

    new_pool.write_gk(config["out"].get_str());
  }
  catch (std::exception &e) {
    fprintf(stderr, "exception: %s\n", e.what());
    abort();
  }
}
<commit_msg>dim fix for gconvert<commit_after>#include "Distributions.hh"
#include "conf.hh"
#include "LinearAlgebra.hh"

conf::Config config;

int
main(int argc, char *argv[])
{
  try {
    config("usage: gconvert [OPTION...]\n")
      ('h', "help", "", "", "display help")
      ('g', "gk=FILE", "arg must", "", "previous distributions (.gk)")
      ('o', "out=FILE", "arg must", "", "converted file (.gk)")
      ('d', "to-diagonal", "", "", "convert Gaussians to diagonal")
      ('f', "to-full", "", "", "convert Gaussians to full covariances")
      ;
    config.default_parse(argc, argv);

    if (config["to-diagonal"].specified && config["to-full"].specified)
      throw std::string("Don't define both -d and -f!");

    if (!config["to-diagonal"].specified && !config["to-full"].specified)
      throw std::string("Define either -d and -f!");

    PDFPool pool;
    PDFPool new_pool;
    pool.read_gk(config["gk"].get_str());
    new_pool.set_dim(pool.dim());

    Matrix covariance;
    Vector mean;
    for (int i=0; i<pool.size(); i++) {

      // Fetch source Gaussian
      Gaussian *gaussian = dynamic_cast< Gaussian* > (pool.get_pdf(i));
      if (gaussian == NULL)
        continue;

      // Create target Gaussian
      Gaussian *new_gaussian = NULL;
      if (config["to-diagonal"].specified)
        new_gaussian = new DiagonalGaussian(gaussian->dim());
      if (config["to-full"].specified)
        new_gaussian = new FullCovarianceGaussian(gaussian->dim());

      // Convert
      gaussian->get_covariance(covariance);
      gaussian->get_mean(mean);
      new_gaussian->set_covariance(covariance);
      new_gaussian->set_mean(mean);

      new_pool.set_pdf(i, new_gaussian);
    }

    new_pool.write_gk(config["out"].get_str());
  }
  catch (std::exception &e) {
    fprintf(stderr, "exception: %s\n", e.what());
    abort();
  }
}
<|endoftext|>


<commit_before>// Copyright (c) 2015 Andrew Sutton
// All rights reserved

#include "scope.hpp"
#include "decl.hpp"

// Returns the innermost declaration context.
Decl*
Scope_stack::context() const
{
  for (auto iter = rbegin(); iter != rend(); ++iter) {
    Scope const* s = *iter;
    if (s->decl)
      return s->decl;
  }
  return nullptr;
}

// Returns the current module. This always the bottom
// of the stack.
Module_decl*
Scope_stack::module() const
{
  return cast<Module_decl>(bottom().decl);
}

// Returns the current function. The current function is found
// by working outwards through the declaration context stack.
// If there is no current function, this returns nullptr.
Function_decl*
Scope_stack::function() const
{
  for (auto iter = rbegin(); iter != rend(); ++iter) {
    Scope const* s = *iter;
    if (Function_decl* fn = as<Function_decl>(s->decl))
      return fn;
  }
  return nullptr;
}

// Returns the current record. The current function is found
// by working outwards through the declaration context stack.
// If there is no current function, this returns nullptr.
Record_decl*
Scope_stack::record() const
{
  for (auto iter = rbegin(); iter != rend(); ++iter) {
    Scope const* s = *iter;
    if (Record_decl* fn = as<Record_decl>(s->decl))
      return fn;
  }
  return nullptr;
}

auto
Record_scope::lookup(Symbol const* sym) -> Binding* {
  //TODO: check decl if it's a record?
  //perform record lookup?
  if(Field_decl* fn = as<Field_decl>(this->decl)) {
    for (int i = 0; i < fn->index().size(); i++) {
      if (Binding* bind = Environment::lookup(fn->name()))
        return bind;
    }
  }

  return nullptr;
}<commit_msg>Woring on scope lookup<commit_after>// Copyright (c) 2015 Andrew Sutton
// All rights reserved

#include "scope.hpp"
#include "decl.hpp"

// Returns the innermost declaration context.
Decl*
Scope_stack::context() const
{
  for (auto iter = rbegin(); iter != rend(); ++iter) {
    Scope const* s = *iter;
    if (s->decl)
      return s->decl;
  }
  return nullptr;
}

// Returns the current module. This always the bottom
// of the stack.
Module_decl*
Scope_stack::module() const
{
  return cast<Module_decl>(bottom().decl);
}

// Returns the current function. The current function is found
// by working outwards through the declaration context stack.
// If there is no current function, this returns nullptr.
Function_decl*
Scope_stack::function() const
{
  for (auto iter = rbegin(); iter != rend(); ++iter) {
    Scope const* s = *iter;
    if (Function_decl* fn = as<Function_decl>(s->decl))
      return fn;
  }
  return nullptr;
}

// Returns the current record. The current function is found
// by working outwards through the declaration context stack.
// If there is no current function, this returns nullptr.
Record_decl*
Scope_stack::record() const
{
  for (auto iter = rbegin(); iter != rend(); ++iter) {
    Scope const* s = *iter;
    if (Record_decl* fn = as<Record_decl>(s->decl))
      return fn;
  }
  return nullptr;
}

auto
Record_scope::lookup(Symbol const* sym) -> Binding* {
  //TODO: check decl if it's a record?
  //perform record lookup?
  if(Record_decl* rec = as<Record_decl>(this->decl)) {
    for(auto x : rec->fields()){
      if(Binding* bind = Environment::lookup(x->name()))
        return bind;
    }
  }

  return nullptr;
}<|endoftext|>


<commit_before>#pragma once

#include <agency/detail/config.hpp>
#include "deferred_future.hpp"
#include <agency/cuda/future.hpp>
#include <agency/detail/variant.hpp>

template<class T>
class uber_future
{
  private:
    using variant_type = agency::detail::variant<deferred_future<T>, agency::cuda::future<T>>;

  public:
    __AGENCY_ANNOTATION
    uber_future() = default;

    __AGENCY_ANNOTATION
    uber_future(uber_future&&) = default;

    template<class Future,
             class = typename std::enable_if<
               std::is_constructible<variant_type,Future&&>::value
             >::type>
    __AGENCY_ANNOTATION
    uber_future(Future&& other)
      : variant_(std::forward<Future>(other))
    {}

    __AGENCY_ANNOTATION
    uber_future& operator=(uber_future&& other) = default;

  private:
    struct valid_visitor
    {
      template<class Future>
      __AGENCY_ANNOTATION
      bool operator()(const Future& f) const
      {
        return f.valid();
      }
    };

  public:
    __AGENCY_ANNOTATION
    bool valid() const
    {
      auto visitor = valid_visitor();
      return agency::detail::visit(visitor, variant_);
    }

  private:
    struct wait_visitor
    {
      template<class Future>
      __AGENCY_ANNOTATION
      void operator()(Future& f) const
      {
        f.wait();
      }
    };

  public:
    __AGENCY_ANNOTATION
    void wait()
    {
      auto visitor = wait_visitor();
      return agency::detail::visit(visitor, variant_);
    }

  private:
    struct get_visitor
    {
      template<class Future>
      __AGENCY_ANNOTATION
      T operator()(Future& f) const
      {
        return f.get();
      }
    };

  public:
    __AGENCY_ANNOTATION
    T get()
    {
      auto visitor = get_visitor();
      return agency::detail::visit(visitor, variant_);
    }

    template<class... Args,
             class = typename std::enable_if<
               agency::cuda::detail::is_constructible_or_void<T,Args...>::value
             >::type>
    __AGENCY_ANNOTATION
    static uber_future make_ready(Args&&... args)
    {
      return deferred_future<T>::make_ready(std::forward<Args>(args)...);
    }

  private:
    template<class Function>
    struct then_visitor
    {
      mutable Function f;

      __AGENCY_ANNOTATION
      uber_future<
        agency::detail::result_of_continuation_t<
          Function,
          deferred_future<T>
        >
      >
        operator()(deferred_future<T>& fut) const
      {
        return fut.then(std::move(f));
      }

      __AGENCY_ANNOTATION
      uber_future<
        agency::detail::result_of_continuation_t<
          Function,
          agency::cuda::future<T>
        >
      >
        operator()(agency::cuda::future<T>& fut) const
      {
        //return fut.then(std::move(f));

        // XXX Function is often move-only
        //     the problem is that the above fut.then() will result in a CUDA kernel launch
        //     and kernel parameters must be copyable
        //     we should either implement movable CUDA kernel parameters
        //     or find a way to attach a deferred continuation onto an asynchronous CUDA future
        //     there ought to be a way to do it by implementing a deferred_continuation which waits on fut
        printf("uber_future::then_visitor::operator()(cuda::future): unimplemented\n");
        assert(0);

        using result_type = agency::detail::result_of_continuation_t<
          Function,
          agency::cuda::future<T>
        >;

        return uber_future<result_type>();
      }
    };

  public:
    template<class Function>
    __AGENCY_ANNOTATION
    uber_future<
      agency::detail::result_of_continuation_t<
        typename std::decay<Function>::type,
        uber_future
      >
    >
      then(Function&& f)
    {
      auto visitor = then_visitor<typename std::decay<Function>::type>{std::forward<Function>(f)};
      return agency::detail::visit(visitor, variant_);
    }

  private:
    variant_type variant_;
};

<commit_msg>Add a note to then_visitor<commit_after>#pragma once

#include <agency/detail/config.hpp>
#include "deferred_future.hpp"
#include <agency/cuda/future.hpp>
#include <agency/detail/variant.hpp>

template<class T>
class uber_future
{
  private:
    using variant_type = agency::detail::variant<deferred_future<T>, agency::cuda::future<T>>;

  public:
    __AGENCY_ANNOTATION
    uber_future() = default;

    __AGENCY_ANNOTATION
    uber_future(uber_future&&) = default;

    template<class Future,
             class = typename std::enable_if<
               std::is_constructible<variant_type,Future&&>::value
             >::type>
    __AGENCY_ANNOTATION
    uber_future(Future&& other)
      : variant_(std::forward<Future>(other))
    {}

    __AGENCY_ANNOTATION
    uber_future& operator=(uber_future&& other) = default;

  private:
    struct valid_visitor
    {
      template<class Future>
      __AGENCY_ANNOTATION
      bool operator()(const Future& f) const
      {
        return f.valid();
      }
    };

  public:
    __AGENCY_ANNOTATION
    bool valid() const
    {
      auto visitor = valid_visitor();
      return agency::detail::visit(visitor, variant_);
    }

  private:
    struct wait_visitor
    {
      template<class Future>
      __AGENCY_ANNOTATION
      void operator()(Future& f) const
      {
        f.wait();
      }
    };

  public:
    __AGENCY_ANNOTATION
    void wait()
    {
      auto visitor = wait_visitor();
      return agency::detail::visit(visitor, variant_);
    }

  private:
    struct get_visitor
    {
      template<class Future>
      __AGENCY_ANNOTATION
      T operator()(Future& f) const
      {
        return f.get();
      }
    };

  public:
    __AGENCY_ANNOTATION
    T get()
    {
      auto visitor = get_visitor();
      return agency::detail::visit(visitor, variant_);
    }

    template<class... Args,
             class = typename std::enable_if<
               agency::cuda::detail::is_constructible_or_void<T,Args...>::value
             >::type>
    __AGENCY_ANNOTATION
    static uber_future make_ready(Args&&... args)
    {
      return deferred_future<T>::make_ready(std::forward<Args>(args)...);
    }

  private:
    template<class Function>
    struct then_visitor
    {
      mutable Function f;

      __AGENCY_ANNOTATION
      uber_future<
        agency::detail::result_of_continuation_t<
          Function,
          deferred_future<T>
        >
      >
        operator()(deferred_future<T>& fut) const
      {
        return fut.then(std::move(f));
      }

      __AGENCY_ANNOTATION
      uber_future<
        agency::detail::result_of_continuation_t<
          Function,
          agency::cuda::future<T>
        >
      >
        operator()(agency::cuda::future<T>& fut) const
      {
        //return fut.then(std::move(f));

        // XXX Function is often move-only
        //     the problem is that the above fut.then() will result in a CUDA kernel launch
        //     and kernel parameters must be copyable
        //     we should either implement movable CUDA kernel parameters
        //     or find a way to attach a deferred continuation onto an asynchronous CUDA future
        //     there ought to be a way to do it by implementing a deferred_continuation which waits on fut
        // XXX when Function is copyable, we ought to just use fut.then()
        printf("uber_future::then_visitor::operator()(cuda::future): unimplemented\n");
        assert(0);

        using result_type = agency::detail::result_of_continuation_t<
          Function,
          agency::cuda::future<T>
        >;

        return uber_future<result_type>();
      }
    };

  public:
    template<class Function>
    __AGENCY_ANNOTATION
    uber_future<
      agency::detail::result_of_continuation_t<
        typename std::decay<Function>::type,
        uber_future
      >
    >
      then(Function&& f)
    {
      auto visitor = then_visitor<typename std::decay<Function>::type>{std::forward<Function>(f)};
      return agency::detail::visit(visitor, variant_);
    }

  private:
    variant_type variant_;
};

<|endoftext|>


<commit_before>#include "Status.h"
#include "Logger.h"
#include "Quirks.h"
#include "platform.h"
#include <3ds/services/apt.h>

using namespace WalrusRPG;

namespace
{
    static bool askedToQuit;
}

void Status::init()
{
    Logger::log("Status init");
    askedToQuit = false;
}

void Status::deinit()
{
    Logger::log("Status deinit");
}

void Status::update()
{
    if (!aptMainLoop())
        askedToQuit = true;
    if (Quirks::get_key(KEY_ZL))
        askedToQuit = true;
}

bool Status::mustQuit()
{
    return askedToQuit;
}
<commit_msg>Made the exit condition a bit more secure<commit_after>#include "Status.h"
#include "Logger.h"
#include "Quirks.h"
#include "platform.h"
#include <3ds/services/apt.h>

using namespace WalrusRPG;

namespace
{
    static bool askedToQuit;
}

void Status::init()
{
    Logger::log("Status init");
    askedToQuit = false;
}

void Status::deinit()
{
    Logger::log("Status deinit");
}

void Status::update()
{
    if (!aptMainLoop())
        askedToQuit = true;
    if (Quirks::get_key(KEY_ZL) && Quirks::get_key(KEY_ZR))
        askedToQuit = true;
}

bool Status::mustQuit()
{
    return askedToQuit;
}
<|endoftext|>


<commit_before>#include "Benchmark.h"

using namespace teetime;

void io_teetime_noAffinity(const Params& params, int threads);
void io_teetime_preferSameCpu(const Params& params, int threads);
void io_teetime_avoidSameCore(const Params& params, int threads);
void io_fastflow(const Params& params, int threads);
void io_fastflow_allocator(const Params& params, int threads);

static void writeFile(const char* filename, const std::vector<char>& writeBuffer, int size)
{
  std::ofstream file;
  file.open(filename, std::ios_base::out | std::ios_base::binary);

  file.write(writeBuffer.data(), size);

  file.close();
}

static int readFile(const char* filename, std::vector<char>& readBuffer, int size)
{
  std::ifstream file;
  file.open(filename, std::ios_base::in | std::ios_base::binary);

  file.seekg(0, file.end);
  std::streamsize length = file.tellg();
  file.seekg(0, file.beg);

  assert(length >= 0);
  assert(length == size);

  file.read(readBuffer.data(), length);

  file.close();

  platform::removeFile(filename);
  return static_cast<int>(length);
}

int writeAndReadFile(const char* fileprefix, int fileNum, const std::vector<char>& writeBuffer, std::vector<char>& readBuffer, int size)
{
  char filename[256];
  sprintf(filename, "%s_%d", fileprefix, fileNum);

  writeFile(filename, writeBuffer, size);
  int count = readFile(filename, readBuffer, size);

  assert(count == size);
  return count;
}

int main(int argc, char** argv)
{
  setLogCallback(::teetime::simpleLogging);
  setLogLevel(getLogLevelFromArgs(argc, argv));

  Arguments args(argc, argv);

  const char* name = "io";
  const char* prettyname = name;
  int num = 0;
  int value = 0;
  int minthreads = 1;
  int maxthreads = 34;

  if (args.contains("fine"))
  {
    num = 1000000;
    value = 1024;
    name = "io_fine";
    prettyname = "IO Benchmark, fine grain (1,000,000 * 1kb)";
  }
  else if (args.contains("medium-fine"))
  {
    num = 100000;
    value = 1024 * 128;
    name = "io_medium-fine";
    prettyname = "IO Benchmark, medium-fine grain (100,000 * 128kb)";
  }
  else if (args.contains("medium"))
  {
    num = 20000;
    value = 1024 * 1024;
    name = "io_medium";
    prettyname = "IO Benchmark, medium grain (20,000 * 1024Kb)";
  }
  else if (args.contains("coarse"))
  {
    num = 2000;
    value = 1024 * 1024 * 10;
    name = "io_coarse";
    prettyname = "IO Benchmark, coarse grain (2,000 * 10Mb)";
  }

  num = args.getInt("num", num);
  value = args.getInt("value", value);
  minthreads = args.getInt("minthreads", minthreads);
  maxthreads = args.getInt("threads", maxthreads);

  std::cout << "settings: num=" << num << ", value=" << value << ", min threads=" << minthreads << ", max threads=" << maxthreads << std::endl;

  Benchmark benchmark;
  benchmark.setNumValues(num);
  benchmark.setValueRange(value, value);
  benchmark.setThreadRange(minthreads, maxthreads);

  if(!args.contains("noteetime"))
    benchmark.addConfiguration(io_teetime_noAffinity, "teetime (no affinity)");

  if(!args.contains("noteetime_sameCPU"))
    benchmark.addConfiguration(io_teetime_preferSameCpu, "teetime (prefer same CPU)");

  if(!args.contains("noteetime_sameCore"))
    benchmark.addConfiguration(io_teetime_avoidSameCore, "teetime (avoid same core)");

  if(!args.contains("nofastflow"))
    benchmark.addConfiguration(io_fastflow, "fastflow (multi alloc)");

  if(!args.contains("nofastflow_alloc"))
    benchmark.addConfiguration(io_fastflow_allocator, "fastflow (single alloc)");

  benchmark.runAll();
  benchmark.print();
  benchmark.save(name, prettyname);

  return EXIT_SUCCESS;
}
<commit_msg>save tmp files of io benchmark in /tmp directory on linux<commit_after>#include "Benchmark.h"

using namespace teetime;

void io_teetime_noAffinity(const Params& params, int threads);
void io_teetime_preferSameCpu(const Params& params, int threads);
void io_teetime_avoidSameCore(const Params& params, int threads);
void io_fastflow(const Params& params, int threads);
void io_fastflow_allocator(const Params& params, int threads);

static void writeFile(const char* filename, const std::vector<char>& writeBuffer, int size)
{
  std::ofstream file;
  file.open(filename, std::ios_base::out | std::ios_base::binary);

  file.write(writeBuffer.data(), size);

  file.close();
}

static int readFile(const char* filename, std::vector<char>& readBuffer, int size)
{
  std::ifstream file;
  file.open(filename, std::ios_base::in | std::ios_base::binary);

  file.seekg(0, file.end);
  std::streamsize length = file.tellg();
  file.seekg(0, file.beg);

  assert(length >= 0);
  assert(length == size);

  file.read(readBuffer.data(), length);

  file.close();

  platform::removeFile(filename);
  return static_cast<int>(length);
}

int writeAndReadFile(const char* fileprefix, int fileNum, const std::vector<char>& writeBuffer, std::vector<char>& readBuffer, int size)
{
  char filename[256];
#ifdef __linux__
  sprintf(filename, "/tmp/%s_%d", fileprefix, fileNum);
#else
  sprintf(filename, "%s_%d", fileprefix, fileNum);
#endif

  writeFile(filename, writeBuffer, size);
  int count = readFile(filename, readBuffer, size);

  assert(count == size);
  return count;
}

int main(int argc, char** argv)
{
  setLogCallback(::teetime::simpleLogging);
  setLogLevel(getLogLevelFromArgs(argc, argv));

  Arguments args(argc, argv);

  const char* name = "io";
  const char* prettyname = name;
  int num = 0;
  int value = 0;
  int minthreads = 1;
  int maxthreads = 34;

  if (args.contains("fine"))
  {
    num = 1000000;
    value = 1024;
    name = "io_fine";
    prettyname = "IO Benchmark, fine grain (1,000,000 * 1kb)";
  }
  else if (args.contains("medium-fine"))
  {
    num = 100000;
    value = 1024 * 128;
    name = "io_medium-fine";
    prettyname = "IO Benchmark, medium-fine grain (100,000 * 128kb)";
  }
  else if (args.contains("medium"))
  {
    num = 20000;
    value = 1024 * 1024;
    name = "io_medium";
    prettyname = "IO Benchmark, medium grain (20,000 * 1024Kb)";
  }
  else if (args.contains("coarse"))
  {
    num = 2000;
    value = 1024 * 1024 * 10;
    name = "io_coarse";
    prettyname = "IO Benchmark, coarse grain (2,000 * 10Mb)";
  }

  num = args.getInt("num", num);
  value = args.getInt("value", value);
  minthreads = args.getInt("minthreads", minthreads);
  maxthreads = args.getInt("threads", maxthreads);

  std::cout << "settings: num=" << num << ", value=" << value << ", min threads=" << minthreads << ", max threads=" << maxthreads << std::endl;

  Benchmark benchmark;
  benchmark.setNumValues(num);
  benchmark.setValueRange(value, value);
  benchmark.setThreadRange(minthreads, maxthreads);

  if(!args.contains("noteetime"))
    benchmark.addConfiguration(io_teetime_noAffinity, "teetime (no affinity)");

  if(!args.contains("noteetime_sameCPU"))
    benchmark.addConfiguration(io_teetime_preferSameCpu, "teetime (prefer same CPU)");

  if(!args.contains("noteetime_sameCore"))
    benchmark.addConfiguration(io_teetime_avoidSameCore, "teetime (avoid same core)");

  if(!args.contains("nofastflow"))
    benchmark.addConfiguration(io_fastflow, "fastflow (multi alloc)");

  if(!args.contains("nofastflow_alloc"))
    benchmark.addConfiguration(io_fastflow_allocator, "fastflow (single alloc)");

  benchmark.runAll();
  benchmark.print();
  benchmark.save(name, prettyname);

  return EXIT_SUCCESS;
}
<|endoftext|>


<commit_before>// igFrame.cpp

#include "igHeader.h"

//===========================================================================
igFrame::igFrame( const wxPoint& pos /*= wxDefaultPosition*/, const wxSize& size /*= wxDefaultSize*/ ) :
								wxFrame( 0, wxID_ANY, "Image Generator", pos, size )
{
	wxMenu* programMenu = new wxMenu();
	wxMenuItem* loadPluginMenuItem = new wxMenuItem( programMenu, ID_LoadPlugin, "Load Plugin", "Load an image generator plugin." );
	wxMenuItem* unloadPluginMenuItem = new wxMenuItem( programMenu, ID_UnloadPlugin, "Unload Plugin", "Unload the currently loaded image generator plugin, if any." );
	wxMenuItem* optionsMenuItem = new wxMenuItem( programMenu, ID_Options, "Options", "Show the options dialog box." );
	wxMenuItem* generateImageMenuItem = new wxMenuItem( programMenu, ID_GenerateImage, "Generate Image", "Use the currently loaded image generator plugin, if any, to generate an image." );
	wxMenuItem* saveImageMenuItem = new wxMenuItem( programMenu, ID_SaveImage, "Save Image", "Save the currently generated image, if any." );
	wxMenuItem* generateVideoMenuItem = new wxMenuItem( programMenu, ID_GenerateVideo, "Generate Video", "Use the currently loaded image generated plugin, if any, to generate a video." );
	wxMenuItem* exitMenuItem = new wxMenuItem( programMenu, ID_Exit, "Exit", "Exit this program." );
	programMenu->Append( loadPluginMenuItem );
	programMenu->Append( unloadPluginMenuItem );
	programMenu->AppendSeparator();
	programMenu->Append( optionsMenuItem );
	programMenu->AppendSeparator();
	programMenu->Append( generateImageMenuItem );
	programMenu->Append( saveImageMenuItem );
	programMenu->AppendSeparator();
	programMenu->Append( generateVideoMenuItem );
	programMenu->AppendSeparator();
	programMenu->Append( exitMenuItem );

	wxMenu* zoomMenu = new wxMenu();
	wxMenuItem* zoom25MenuItem = new wxMenuItem( zoomMenu, ID_Zoom25, "25%", "Show the image at 25% of its normal size.", wxITEM_CHECK );
	wxMenuItem* zoom50MenuItem = new wxMenuItem( zoomMenu, ID_Zoom50, "50%", "Show the image at 50% of its normal size.", wxITEM_CHECK );
	wxMenuItem* zoom100MenuItem = new wxMenuItem( zoomMenu, ID_Zoom100, "100%", "Show the image in its normal size.", wxITEM_CHECK );
	wxMenuItem* zoom150MenuItem = new wxMenuItem( zoomMenu, ID_Zoom150, "150%", "Show the image at 150% of its normal size.", wxITEM_CHECK );
	wxMenuItem* zoom200MenuItem = new wxMenuItem( zoomMenu, ID_Zoom200, "200%", "Show the image at 200% of its normal size.", wxITEM_CHECK );
	zoomMenu->Append( zoom25MenuItem );
	zoomMenu->Append( zoom50MenuItem );
	zoomMenu->Append( zoom100MenuItem );
	zoomMenu->Append( zoom150MenuItem );
	zoomMenu->Append( zoom200MenuItem );

	wxMenu* helpMenu = new wxMenu();
	wxMenuItem* aboutMenuItem = new wxMenuItem( helpMenu, ID_About, "About", "Show the about-box." );
	helpMenu->Append( aboutMenuItem );

	wxMenuBar* menuBar = new wxMenuBar();
	menuBar->Append( programMenu, "Program" );
	menuBar->Append( zoomMenu, "Zoom" );
	menuBar->Append( helpMenu, "Help" );
	SetMenuBar( menuBar );

	wxStatusBar* statusBar = new wxStatusBar( this );
	SetStatusBar( statusBar );

	canvas = new igCanvas( this );
	canvas->SetScrollRate( 1, 1 );

	wxBoxSizer* boxSizer = new wxBoxSizer( wxVERTICAL );
	boxSizer->Add( canvas, 1, wxEXPAND | wxALL, 0 );
	SetSizer( boxSizer );

	Bind( wxEVT_MENU, &igFrame::OnLoadPlugin, this, ID_LoadPlugin );
	Bind( wxEVT_MENU, &igFrame::OnUnloadPlugin, this, ID_UnloadPlugin );
	Bind( wxEVT_MENU, &igFrame::OnOptions, this, ID_Options );
	Bind( wxEVT_MENU, &igFrame::OnGenerateImage, this, ID_GenerateImage );
	Bind( wxEVT_MENU, &igFrame::OnSaveImage, this, ID_SaveImage );
	Bind( wxEVT_MENU, &igFrame::OnGenerateVideo, this, ID_GenerateVideo );
	Bind( wxEVT_MENU, &igFrame::OnZoom, this, ID_Zoom25 );
	Bind( wxEVT_MENU, &igFrame::OnZoom, this, ID_Zoom50 );
	Bind( wxEVT_MENU, &igFrame::OnZoom, this, ID_Zoom100 );
	Bind( wxEVT_MENU, &igFrame::OnZoom, this, ID_Zoom150 );
	Bind( wxEVT_MENU, &igFrame::OnZoom, this, ID_Zoom200 );
	Bind( wxEVT_MENU, &igFrame::OnExit, this, ID_Exit );
	Bind( wxEVT_MENU, &igFrame::OnAbout, this, ID_About );
	Bind( wxEVT_UPDATE_UI, &igFrame::OnUpdateMenuItemUI, this, ID_LoadPlugin );
	Bind( wxEVT_UPDATE_UI, &igFrame::OnUpdateMenuItemUI, this, ID_UnloadPlugin );
	Bind( wxEVT_UPDATE_UI, &igFrame::OnUpdateMenuItemUI, this, ID_GenerateImage );
	Bind( wxEVT_UPDATE_UI, &igFrame::OnUpdateMenuItemUI, this, ID_SaveImage );
	Bind( wxEVT_UPDATE_UI, &igFrame::OnUpdateMenuItemUI, this, ID_GenerateVideo );
	Bind( wxEVT_UPDATE_UI, &igFrame::OnUpdateMenuItemUI, this, ID_Zoom25 );
	Bind( wxEVT_UPDATE_UI, &igFrame::OnUpdateMenuItemUI, this, ID_Zoom50 );
	Bind( wxEVT_UPDATE_UI, &igFrame::OnUpdateMenuItemUI, this, ID_Zoom100 );
	Bind( wxEVT_UPDATE_UI, &igFrame::OnUpdateMenuItemUI, this, ID_Zoom150 );
	Bind( wxEVT_UPDATE_UI, &igFrame::OnUpdateMenuItemUI, this, ID_Zoom200 );
}

//===========================================================================
/*virtual*/ igFrame::~igFrame( void )
{
}

//===========================================================================
void igFrame::UpdateTitle( void )
{
	igPlugin* plugin = wxGetApp().Plugin();
	if( plugin )
		SetTitle( plugin->Name() + " -- Image Generator" );
	else
		SetTitle( "Image Generator" );
}

//===========================================================================
void igFrame::OnLoadPlugin( wxCommandEvent& event )
{
	if( wxGetApp().Plugin() )
		return;

	wxFileDialog fileDialog( this, "Open image generator plugin",
								wxEmptyString, wxEmptyString,
								"Image Generator Plugin (*.ig)|*.ig",
								wxFD_OPEN | wxFD_FILE_MUST_EXIST );

	if( fileDialog.ShowModal() == wxID_CANCEL )
		return;

	wxString pluginPath = fileDialog.GetPath();
	if( !wxGetApp().LoadPlugin( pluginPath ) )
		wxMessageBox( "Failed to load plugin \"" + pluginPath + "\"." );
	else
		UpdateTitle();
}

//===========================================================================
void igFrame::OnUnloadPlugin( wxCommandEvent& event )
{
	if( !wxGetApp().Plugin() )
		return;

	wxGetApp().UnloadPlugin();
	UpdateTitle();
}

//===========================================================================
void igFrame::OnOptions( wxCommandEvent& event )
{
	igOptionsDialog optionsDialog( this, wxGetApp().GetOptions() );
	if( wxID_OK == optionsDialog.ShowModal() )
		wxGetApp().SetOptions( optionsDialog.Options() );
}

//===========================================================================
void igFrame::OnGenerateImage( wxCommandEvent& event )
{
	if( !wxGetApp().GenerateImage() )
		wxMessageBox( "Failed to generate image." );
	else
	{
		canvas->InvalidateCachedBitmap();
		canvas->Refresh();
	}
}

//===========================================================================
void igFrame::OnSaveImage( wxCommandEvent& event )
{
	wxImage* image = wxGetApp().Image();
	if( !image )
		return;

	wxFileDialog fileDialog( this, "Save generated image",
								wxEmptyString, wxEmptyString,
								"PNG file (*.png)|*.png",
								wxFD_SAVE | wxFD_OVERWRITE_PROMPT );

	if( fileDialog.ShowModal() == wxID_CANCEL )
		return;

	wxString imagePath = fileDialog.GetPath();
	if( !image->SaveFile( imagePath, wxBITMAP_TYPE_PNG ) )
		wxMessageBox( "Failed to save image \"" + imagePath + "\"." );
}

//===========================================================================
void igFrame::OnGenerateVideo( wxCommandEvent& event )
{
#ifdef VIDEO_SUPPORT
	wxFileDialog fileDialog( this, "Save generated video",
								wxEmptyString, wxEmptyString,
								"MPEG file (*.mpeg)|*.mpeg",
								wxFD_SAVE | wxFD_OVERWRITE_PROMPT );

	if( fileDialog.ShowModal() == wxID_CANCEL )
		return;

	wxString videoPath = fileDialog.GetPath();
	if( !wxGetApp().GenerateVideo( videoPath ) )
		wxMessageBox( "Failed to generate video." );
#else
	wxMessageBox( "No video support compiled in." );
#endif //VIDEO_SUPPORT
}

//===========================================================================
void igFrame::OnZoom( wxCommandEvent& event )
{
	igCanvas::Zoom zoom = igCanvas::ZOOM_100;
	switch( event.GetId() )
	{
		case ID_Zoom25: zoom = igCanvas::ZOOM_25; break;
		case ID_Zoom50: zoom = igCanvas::ZOOM_50; break;
		case ID_Zoom100: zoom = igCanvas::ZOOM_100; break;
		case ID_Zoom150: zoom = igCanvas::ZOOM_150; break;
		case ID_Zoom200: zoom = igCanvas::ZOOM_200; break;
	}

	if( zoom != canvas->GetZoom() )
	{
		canvas->SetZoom( zoom );
		canvas->InvalidateCachedBitmap();
		canvas->Refresh();
	}
}

//===========================================================================
void igFrame::OnUpdateMenuItemUI( wxUpdateUIEvent& event )
{
	switch( event.GetId() )
	{
		case ID_LoadPlugin:
		{
			event.Enable( wxGetApp().Plugin() ? false : true );
			break;
		}
		case ID_UnloadPlugin:
		case ID_GenerateImage:
		case ID_GenerateVideo:
		{
#ifdef VIDEO_SUPPORT
			event.Enable( wxGetApp().Plugin() ? true : false );
#else
			event.Enable( false );
#endif //VIDEO_SUPPORT
			break;
		}
		case ID_SaveImage:
		{
			event.Enable( wxGetApp().Image() ? true : false );
			break;
		}
		case ID_Zoom25:
		case ID_Zoom50:
		case ID_Zoom100:
		case ID_Zoom150:
		case ID_Zoom200:
		{
			event.Enable( wxGetApp().Image() ? true : false );

			bool checked =
					( event.GetId() == ID_Zoom25 && canvas->GetZoom() == igCanvas::ZOOM_25 ) ||
					( event.GetId() == ID_Zoom50 && canvas->GetZoom() == igCanvas::ZOOM_50 ) ||
					( event.GetId() == ID_Zoom100 && canvas->GetZoom() == igCanvas::ZOOM_100 ) ||
					( event.GetId() == ID_Zoom150 && canvas->GetZoom() == igCanvas::ZOOM_150 ) ||
					( event.GetId() == ID_Zoom200 && canvas->GetZoom() == igCanvas::ZOOM_200 );

			event.Check( checked );

			break;
		}
	}
}

//===========================================================================
void igFrame::OnExit( wxCommandEvent& event )
{
	igApp::FrameLayout& frameLayout = wxGetApp().frameLayout;
	frameLayout.pos = GetPosition();
	frameLayout.size = GetSize();

	Close( true );
}

//===========================================================================
void igFrame::OnAbout( wxCommandEvent& event )
{
	wxAboutDialogInfo aboutDialogInfo;

	aboutDialogInfo.SetName( "Image Generator" );
	aboutDialogInfo.SetVersion( "v1.0" );
	aboutDialogInfo.SetDescription( "Generate an image on multiple threads." );
	aboutDialogInfo.SetCopyright( "Copyright (C) 2013, 2016, 2018" );
	aboutDialogInfo.AddDeveloper( "Spencer T. Parkin" );
	aboutDialogInfo.SetLicense( "Not licensed!" );

	wxAboutBox( aboutDialogInfo );
}

// igFrame.cpp<commit_msg>fix bug<commit_after>// igFrame.cpp

#include "igHeader.h"

//===========================================================================
igFrame::igFrame( const wxPoint& pos /*= wxDefaultPosition*/, const wxSize& size /*= wxDefaultSize*/ ) :
								wxFrame( 0, wxID_ANY, "Image Generator", pos, size )
{
	wxMenu* programMenu = new wxMenu();
	wxMenuItem* loadPluginMenuItem = new wxMenuItem( programMenu, ID_LoadPlugin, "Load Plugin", "Load an image generator plugin." );
	wxMenuItem* unloadPluginMenuItem = new wxMenuItem( programMenu, ID_UnloadPlugin, "Unload Plugin", "Unload the currently loaded image generator plugin, if any." );
	wxMenuItem* optionsMenuItem = new wxMenuItem( programMenu, ID_Options, "Options", "Show the options dialog box." );
	wxMenuItem* generateImageMenuItem = new wxMenuItem( programMenu, ID_GenerateImage, "Generate Image", "Use the currently loaded image generator plugin, if any, to generate an image." );
	wxMenuItem* saveImageMenuItem = new wxMenuItem( programMenu, ID_SaveImage, "Save Image", "Save the currently generated image, if any." );
	wxMenuItem* generateVideoMenuItem = new wxMenuItem( programMenu, ID_GenerateVideo, "Generate Video", "Use the currently loaded image generated plugin, if any, to generate a video." );
	wxMenuItem* exitMenuItem = new wxMenuItem( programMenu, ID_Exit, "Exit", "Exit this program." );
	programMenu->Append( loadPluginMenuItem );
	programMenu->Append( unloadPluginMenuItem );
	programMenu->AppendSeparator();
	programMenu->Append( optionsMenuItem );
	programMenu->AppendSeparator();
	programMenu->Append( generateImageMenuItem );
	programMenu->Append( saveImageMenuItem );
	programMenu->AppendSeparator();
	programMenu->Append( generateVideoMenuItem );
	programMenu->AppendSeparator();
	programMenu->Append( exitMenuItem );

	wxMenu* zoomMenu = new wxMenu();
	wxMenuItem* zoom25MenuItem = new wxMenuItem( zoomMenu, ID_Zoom25, "25%", "Show the image at 25% of its normal size.", wxITEM_CHECK );
	wxMenuItem* zoom50MenuItem = new wxMenuItem( zoomMenu, ID_Zoom50, "50%", "Show the image at 50% of its normal size.", wxITEM_CHECK );
	wxMenuItem* zoom100MenuItem = new wxMenuItem( zoomMenu, ID_Zoom100, "100%", "Show the image in its normal size.", wxITEM_CHECK );
	wxMenuItem* zoom150MenuItem = new wxMenuItem( zoomMenu, ID_Zoom150, "150%", "Show the image at 150% of its normal size.", wxITEM_CHECK );
	wxMenuItem* zoom200MenuItem = new wxMenuItem( zoomMenu, ID_Zoom200, "200%", "Show the image at 200% of its normal size.", wxITEM_CHECK );
	zoomMenu->Append( zoom25MenuItem );
	zoomMenu->Append( zoom50MenuItem );
	zoomMenu->Append( zoom100MenuItem );
	zoomMenu->Append( zoom150MenuItem );
	zoomMenu->Append( zoom200MenuItem );

	wxMenu* helpMenu = new wxMenu();
	wxMenuItem* aboutMenuItem = new wxMenuItem( helpMenu, ID_About, "About", "Show the about-box." );
	helpMenu->Append( aboutMenuItem );

	wxMenuBar* menuBar = new wxMenuBar();
	menuBar->Append( programMenu, "Program" );
	menuBar->Append( zoomMenu, "Zoom" );
	menuBar->Append( helpMenu, "Help" );
	SetMenuBar( menuBar );

	wxStatusBar* statusBar = new wxStatusBar( this );
	SetStatusBar( statusBar );

	canvas = new igCanvas( this );
	canvas->SetScrollRate( 1, 1 );

	wxBoxSizer* boxSizer = new wxBoxSizer( wxVERTICAL );
	boxSizer->Add( canvas, 1, wxEXPAND | wxALL, 0 );
	SetSizer( boxSizer );

	Bind( wxEVT_MENU, &igFrame::OnLoadPlugin, this, ID_LoadPlugin );
	Bind( wxEVT_MENU, &igFrame::OnUnloadPlugin, this, ID_UnloadPlugin );
	Bind( wxEVT_MENU, &igFrame::OnOptions, this, ID_Options );
	Bind( wxEVT_MENU, &igFrame::OnGenerateImage, this, ID_GenerateImage );
	Bind( wxEVT_MENU, &igFrame::OnSaveImage, this, ID_SaveImage );
	Bind( wxEVT_MENU, &igFrame::OnGenerateVideo, this, ID_GenerateVideo );
	Bind( wxEVT_MENU, &igFrame::OnZoom, this, ID_Zoom25 );
	Bind( wxEVT_MENU, &igFrame::OnZoom, this, ID_Zoom50 );
	Bind( wxEVT_MENU, &igFrame::OnZoom, this, ID_Zoom100 );
	Bind( wxEVT_MENU, &igFrame::OnZoom, this, ID_Zoom150 );
	Bind( wxEVT_MENU, &igFrame::OnZoom, this, ID_Zoom200 );
	Bind( wxEVT_MENU, &igFrame::OnExit, this, ID_Exit );
	Bind( wxEVT_MENU, &igFrame::OnAbout, this, ID_About );
	Bind( wxEVT_UPDATE_UI, &igFrame::OnUpdateMenuItemUI, this, ID_LoadPlugin );
	Bind( wxEVT_UPDATE_UI, &igFrame::OnUpdateMenuItemUI, this, ID_UnloadPlugin );
	Bind( wxEVT_UPDATE_UI, &igFrame::OnUpdateMenuItemUI, this, ID_GenerateImage );
	Bind( wxEVT_UPDATE_UI, &igFrame::OnUpdateMenuItemUI, this, ID_SaveImage );
	Bind( wxEVT_UPDATE_UI, &igFrame::OnUpdateMenuItemUI, this, ID_GenerateVideo );
	Bind( wxEVT_UPDATE_UI, &igFrame::OnUpdateMenuItemUI, this, ID_Zoom25 );
	Bind( wxEVT_UPDATE_UI, &igFrame::OnUpdateMenuItemUI, this, ID_Zoom50 );
	Bind( wxEVT_UPDATE_UI, &igFrame::OnUpdateMenuItemUI, this, ID_Zoom100 );
	Bind( wxEVT_UPDATE_UI, &igFrame::OnUpdateMenuItemUI, this, ID_Zoom150 );
	Bind( wxEVT_UPDATE_UI, &igFrame::OnUpdateMenuItemUI, this, ID_Zoom200 );
}

//===========================================================================
/*virtual*/ igFrame::~igFrame( void )
{
}

//===========================================================================
void igFrame::UpdateTitle( void )
{
	igPlugin* plugin = wxGetApp().Plugin();
	if( plugin )
		SetTitle( plugin->Name() + " -- Image Generator" );
	else
		SetTitle( "Image Generator" );
}

//===========================================================================
void igFrame::OnLoadPlugin( wxCommandEvent& event )
{
	if( wxGetApp().Plugin() )
		return;

	wxFileDialog fileDialog( this, "Open image generator plugin",
								wxEmptyString, wxEmptyString,
								"Image Generator Plugin (*.ig)|*.ig",
								wxFD_OPEN | wxFD_FILE_MUST_EXIST );

	if( fileDialog.ShowModal() == wxID_CANCEL )
		return;

	wxString pluginPath = fileDialog.GetPath();
	if( !wxGetApp().LoadPlugin( pluginPath ) )
		wxMessageBox( "Failed to load plugin \"" + pluginPath + "\"." );
	else
		UpdateTitle();
}

//===========================================================================
void igFrame::OnUnloadPlugin( wxCommandEvent& event )
{
	if( !wxGetApp().Plugin() )
		return;

	wxGetApp().UnloadPlugin();
	UpdateTitle();
}

//===========================================================================
void igFrame::OnOptions( wxCommandEvent& event )
{
	igOptionsDialog optionsDialog( this, wxGetApp().GetOptions() );
	if( wxID_OK == optionsDialog.ShowModal() )
		wxGetApp().SetOptions( optionsDialog.Options() );
}

//===========================================================================
void igFrame::OnGenerateImage( wxCommandEvent& event )
{
	if( !wxGetApp().GenerateImage() )
		wxMessageBox( "Failed to generate image." );
	else
	{
		canvas->InvalidateCachedBitmap();
		canvas->Refresh();
	}
}

//===========================================================================
void igFrame::OnSaveImage( wxCommandEvent& event )
{
	wxImage* image = wxGetApp().Image();
	if( !image )
		return;

	wxFileDialog fileDialog( this, "Save generated image",
								wxEmptyString, wxEmptyString,
								"PNG file (*.png)|*.png",
								wxFD_SAVE | wxFD_OVERWRITE_PROMPT );

	if( fileDialog.ShowModal() == wxID_CANCEL )
		return;

	wxString imagePath = fileDialog.GetPath();
	if( !image->SaveFile( imagePath, wxBITMAP_TYPE_PNG ) )
		wxMessageBox( "Failed to save image \"" + imagePath + "\"." );
}

//===========================================================================
void igFrame::OnGenerateVideo( wxCommandEvent& event )
{
#ifdef VIDEO_SUPPORT
	wxFileDialog fileDialog( this, "Save generated video",
								wxEmptyString, wxEmptyString,
								"MPEG file (*.mpeg)|*.mpeg",
								wxFD_SAVE | wxFD_OVERWRITE_PROMPT );

	if( fileDialog.ShowModal() == wxID_CANCEL )
		return;

	wxString videoPath = fileDialog.GetPath();
	if( !wxGetApp().GenerateVideo( videoPath ) )
		wxMessageBox( "Failed to generate video." );
#else
	wxMessageBox( "No video support compiled in." );
#endif //VIDEO_SUPPORT
}

//===========================================================================
void igFrame::OnZoom( wxCommandEvent& event )
{
	igCanvas::Zoom zoom = igCanvas::ZOOM_100;
	switch( event.GetId() )
	{
		case ID_Zoom25: zoom = igCanvas::ZOOM_25; break;
		case ID_Zoom50: zoom = igCanvas::ZOOM_50; break;
		case ID_Zoom100: zoom = igCanvas::ZOOM_100; break;
		case ID_Zoom150: zoom = igCanvas::ZOOM_150; break;
		case ID_Zoom200: zoom = igCanvas::ZOOM_200; break;
	}

	if( zoom != canvas->GetZoom() )
	{
		canvas->SetZoom( zoom );
		canvas->InvalidateCachedBitmap();
		canvas->Refresh();
	}
}

//===========================================================================
void igFrame::OnUpdateMenuItemUI( wxUpdateUIEvent& event )
{
	switch( event.GetId() )
	{
		case ID_LoadPlugin:
		{
			event.Enable( wxGetApp().Plugin() ? false : true );
			break;
		}
		case ID_GenerateVideo:
		{
#ifdef VIDEO_SUPPORT
			event.Enable( wxGetApp().Plugin() ? true : false );
#else
			event.Enable( false );
#endif //VIDEO_SUPPORT
			break;
		}
		case ID_UnloadPlugin:
		case ID_GenerateImage:
		{
			event.Enable( wxGetApp().Plugin() ? true : false );
			break;
		}
		case ID_SaveImage:
		{
			event.Enable( wxGetApp().Image() ? true : false );
			break;
		}
		case ID_Zoom25:
		case ID_Zoom50:
		case ID_Zoom100:
		case ID_Zoom150:
		case ID_Zoom200:
		{
			event.Enable( wxGetApp().Image() ? true : false );

			bool checked =
					( event.GetId() == ID_Zoom25 && canvas->GetZoom() == igCanvas::ZOOM_25 ) ||
					( event.GetId() == ID_Zoom50 && canvas->GetZoom() == igCanvas::ZOOM_50 ) ||
					( event.GetId() == ID_Zoom100 && canvas->GetZoom() == igCanvas::ZOOM_100 ) ||
					( event.GetId() == ID_Zoom150 && canvas->GetZoom() == igCanvas::ZOOM_150 ) ||
					( event.GetId() == ID_Zoom200 && canvas->GetZoom() == igCanvas::ZOOM_200 );

			event.Check( checked );

			break;
		}
	}
}

//===========================================================================
void igFrame::OnExit( wxCommandEvent& event )
{
	igApp::FrameLayout& frameLayout = wxGetApp().frameLayout;
	frameLayout.pos = GetPosition();
	frameLayout.size = GetSize();

	Close( true );
}

//===========================================================================
void igFrame::OnAbout( wxCommandEvent& event )
{
	wxAboutDialogInfo aboutDialogInfo;

	aboutDialogInfo.SetName( "Image Generator" );
	aboutDialogInfo.SetVersion( "v1.0" );
	aboutDialogInfo.SetDescription( "Generate an image on multiple threads." );
	aboutDialogInfo.SetCopyright( "Copyright (C) 2013, 2016, 2018" );
	aboutDialogInfo.AddDeveloper( "Spencer T. Parkin" );
	aboutDialogInfo.SetLicense( "Not licensed!" );

	wxAboutBox( aboutDialogInfo );
}

// igFrame.cpp<|endoftext|>


<commit_before>/**********************************************************************
 * $Id$
 *
 * GEOS - Geometry Engine Open Source
 * http://geos.refractions.net
 *
 * Copyright (C) 2001-2002 Vivid Solutions Inc.
 *
 * This is free software; you can redistribute and/or modify it under
 * the terms of the GNU Lesser General Public Licence as published
 * by the Free Software Foundation.
 * See the COPYING file for more information.
 *
 **********************************************************************
 * $Log$
 * Revision 1.8  2004/09/21 09:47:36  strk
 * fixed a mis-initialization bug in ::reduce
 *
 * Revision 1.7  2004/07/08 19:34:50  strk
 * Mirrored JTS interface of CoordinateSequence, factory and
 * default implementations.
 * Added DefaultCoordinateSequenceFactory::instance() function.
 *
 * Revision 1.6  2004/07/06 17:58:22  strk
 * Removed deprecated Geometry constructors based on PrecisionModel and
 * SRID specification. Removed SimpleGeometryPrecisionReducer capability
 * of changing Geometry's factory. Reverted Geometry::factory member
 * to be a reference to external factory.
 *
 * Revision 1.5  2004/07/02 13:28:29  strk
 * Fixed all #include lines to reflect headers layout change.
 * Added client application build tips in README.
 *
 * Revision 1.4  2004/05/03 17:15:38  strk
 * leaks on exception fixed.
 *
 * Revision 1.3  2004/04/20 10:14:20  strk
 * Memory leaks removed.
 *
 * Revision 1.2  2004/04/20 08:52:01  strk
 * GeometryFactory and Geometry const correctness.
 * Memory leaks removed from SimpleGeometryPrecisionReducer
 * and GeometryFactory.
 *
 * Revision 1.1  2004/04/10 22:41:25  ybychkov
 * "precision" upgraded to JTS 1.4
 *
 *
 **********************************************************************/

#include <geos/precision.h>
#include <typeinfo>

namespace geos {

SimpleGeometryPrecisionReducer::SimpleGeometryPrecisionReducer(PrecisionModel *pm){
	removeCollapsed = true;
	//changePrecisionModel = false;
	newPrecisionModel = pm;
}

/**
* Sets whether the reduction will result in collapsed components
* being removed completely, or simply being collapsed to an (invalid)
* Geometry of the same type.
*
* @param removeCollapsed if true collapsed components will be removed
*/
void SimpleGeometryPrecisionReducer::setRemoveCollapsedComponents(bool nRemoveCollapsed){
	removeCollapsed=nRemoveCollapsed;
}

/*
* Sets whether the PrecisionModel of the new reduced Geometry
* will be changed to be the PrecisionModel supplied to
* specify the reduction.  The default is to not change the precision model.
* Caller will need to take care of deletion of the newly created
* GeometryFactory if nChangePrecisionModel is set to true (see Geometry::getFactory())
*
* @param changePrecisionModel if true the precision model of the created Geometry will be the
* the precisionModel supplied in the constructor.
*/
//void SimpleGeometryPrecisionReducer::setChangePrecisionModel(bool nChangePrecisionModel){
//	changePrecisionModel=nChangePrecisionModel;
//}

PrecisionModel* SimpleGeometryPrecisionReducer::getPrecisionModel() {
	return newPrecisionModel;
}

bool SimpleGeometryPrecisionReducer::getRemoveCollapsed() {
	return removeCollapsed;
}

Geometry* SimpleGeometryPrecisionReducer::reduce(const Geometry *geom){
	GeometryEditor geomEdit;
	PrecisionReducerCoordinateOperation prco(this);
	Geometry *g=geomEdit.edit(geom, &prco);
	return g;
}

PrecisionReducerCoordinateOperation::PrecisionReducerCoordinateOperation(SimpleGeometryPrecisionReducer *newSgpr) {
	sgpr=newSgpr;
}

CoordinateSequence*
PrecisionReducerCoordinateOperation::edit(const CoordinateSequence *cs, const Geometry *geom)
{
	if (cs->getSize()==0) return NULL;

	vector<Coordinate> *vc = new vector<Coordinate>(cs->getSize());

	// copy coordinates and reduce
	for (int i=0;i<cs->getSize(); i++) {
		Coordinate *coord=new Coordinate(cs->getAt(i));
		sgpr->getPrecisionModel()->makePrecise(coord);
		//reducedCoords->setAt(*coord,i);
		(*vc)[i] = *coord;
		delete coord;
	}

	CoordinateSequence *reducedCoords = geom->getFactory()->getCoordinateSequenceFactory()->create(vc);

	// remove repeated points, to simplify returned geometry as much as possible
	CoordinateSequence *noRepeatedCoords=CoordinateSequence::removeRepeatedPoints(reducedCoords);

	/**
	* Check to see if the removal of repeated points
	* collapsed the coordinate List to an invalid length
	* for the type of the parent geometry.
	* It is not necessary to check for Point collapses, since the coordinate list can
	* never collapse to less than one point.
	* If the length is invalid, return the full-length coordinate array
	* first computed, or null if collapses are being removed.
	* (This may create an invalid geometry - the client must handle this.)
	*/
	int minLength = 0;
	if (typeid(*geom)==typeid(LineString)) minLength = 2;
	if (typeid(*geom)==typeid(LinearRing)) minLength = 4;
	CoordinateSequence *collapsedCoords = reducedCoords;
	if (sgpr->getRemoveCollapsed()) collapsedCoords=NULL;
	// return null or orginal length coordinate array
	if (noRepeatedCoords->getSize()<minLength) {
		delete noRepeatedCoords;
		return collapsedCoords;
	}
	// ok to return shorter coordinate array
	delete reducedCoords;
	return noRepeatedCoords;
}
}
<commit_msg>Another getSize in for loop, another int-unsigned int warning<commit_after>/**********************************************************************
 * $Id$
 *
 * GEOS - Geometry Engine Open Source
 * http://geos.refractions.net
 *
 * Copyright (C) 2001-2002 Vivid Solutions Inc.
 *
 * This is free software; you can redistribute and/or modify it under
 * the terms of the GNU Lesser General Public Licence as published
 * by the Free Software Foundation.
 * See the COPYING file for more information.
 *
 **********************************************************************
 * $Log$
 * Revision 1.9  2005/11/25 11:40:21  strk
 * Another getSize in for loop, another int-unsigned int warning
 *
 * Revision 1.8  2004/09/21 09:47:36  strk
 * fixed a mis-initialization bug in ::reduce
 *
 * Revision 1.7  2004/07/08 19:34:50  strk
 * Mirrored JTS interface of CoordinateSequence, factory and
 * default implementations.
 * Added DefaultCoordinateSequenceFactory::instance() function.
 *
 * Revision 1.6  2004/07/06 17:58:22  strk
 * Removed deprecated Geometry constructors based on PrecisionModel and
 * SRID specification. Removed SimpleGeometryPrecisionReducer capability
 * of changing Geometry's factory. Reverted Geometry::factory member
 * to be a reference to external factory.
 *
 * Revision 1.5  2004/07/02 13:28:29  strk
 * Fixed all #include lines to reflect headers layout change.
 * Added client application build tips in README.
 *
 * Revision 1.4  2004/05/03 17:15:38  strk
 * leaks on exception fixed.
 *
 * Revision 1.3  2004/04/20 10:14:20  strk
 * Memory leaks removed.
 *
 * Revision 1.2  2004/04/20 08:52:01  strk
 * GeometryFactory and Geometry const correctness.
 * Memory leaks removed from SimpleGeometryPrecisionReducer
 * and GeometryFactory.
 *
 * Revision 1.1  2004/04/10 22:41:25  ybychkov
 * "precision" upgraded to JTS 1.4
 *
 *
 **********************************************************************/

#include <geos/precision.h>
#include <typeinfo>

namespace geos {

SimpleGeometryPrecisionReducer::SimpleGeometryPrecisionReducer(PrecisionModel *pm){
	removeCollapsed = true;
	//changePrecisionModel = false;
	newPrecisionModel = pm;
}

/**
* Sets whether the reduction will result in collapsed components
* being removed completely, or simply being collapsed to an (invalid)
* Geometry of the same type.
*
* @param removeCollapsed if true collapsed components will be removed
*/
void SimpleGeometryPrecisionReducer::setRemoveCollapsedComponents(bool nRemoveCollapsed){
	removeCollapsed=nRemoveCollapsed;
}

/*
* Sets whether the PrecisionModel of the new reduced Geometry
* will be changed to be the PrecisionModel supplied to
* specify the reduction.  The default is to not change the precision model.
* Caller will need to take care of deletion of the newly created
* GeometryFactory if nChangePrecisionModel is set to true (see Geometry::getFactory())
*
* @param changePrecisionModel if true the precision model of the created Geometry will be the
* the precisionModel supplied in the constructor.
*/
//void SimpleGeometryPrecisionReducer::setChangePrecisionModel(bool nChangePrecisionModel){
//	changePrecisionModel=nChangePrecisionModel;
//}

PrecisionModel* SimpleGeometryPrecisionReducer::getPrecisionModel() {
	return newPrecisionModel;
}

bool SimpleGeometryPrecisionReducer::getRemoveCollapsed() {
	return removeCollapsed;
}

Geometry* SimpleGeometryPrecisionReducer::reduce(const Geometry *geom){
	GeometryEditor geomEdit;
	PrecisionReducerCoordinateOperation prco(this);
	Geometry *g=geomEdit.edit(geom, &prco);
	return g;
}

PrecisionReducerCoordinateOperation::PrecisionReducerCoordinateOperation(SimpleGeometryPrecisionReducer *newSgpr) {
	sgpr=newSgpr;
}

CoordinateSequence*
PrecisionReducerCoordinateOperation::edit(const CoordinateSequence *cs, const Geometry *geom)
{
	if (cs->getSize()==0) return NULL;

	unsigned int csSize=cs->getSize();

	vector<Coordinate> *vc = new vector<Coordinate>(csSize);

	// copy coordinates and reduce
	for (unsigned int i=0; i<csSize; ++i) {
		Coordinate coord=cs->getAt(i);
		sgpr->getPrecisionModel()->makePrecise(&coord);
		//reducedCoords->setAt(*coord,i);
		(*vc)[i] = coord;
	}

	CoordinateSequence *reducedCoords = geom->getFactory()->getCoordinateSequenceFactory()->create(vc);

	// remove repeated points, to simplify returned geometry as much as possible
	CoordinateSequence *noRepeatedCoords=CoordinateSequence::removeRepeatedPoints(reducedCoords);

	/**
	* Check to see if the removal of repeated points
	* collapsed the coordinate List to an invalid length
	* for the type of the parent geometry.
	* It is not necessary to check for Point collapses, since the coordinate list can
	* never collapse to less than one point.
	* If the length is invalid, return the full-length coordinate array
	* first computed, or null if collapses are being removed.
	* (This may create an invalid geometry - the client must handle this.)
	*/
	unsigned int minLength = 0;
	if (typeid(*geom)==typeid(LineString)) minLength = 2;
	if (typeid(*geom)==typeid(LinearRing)) minLength = 4;
	CoordinateSequence *collapsedCoords = reducedCoords;
	if (sgpr->getRemoveCollapsed()) collapsedCoords=NULL;
	// return null or orginal length coordinate array
	if (noRepeatedCoords->getSize()<minLength) {
		delete noRepeatedCoords;
		return collapsedCoords;
	}
	// ok to return shorter coordinate array
	delete reducedCoords;
	return noRepeatedCoords;
}

} // namespace geos
<|endoftext|>