<commit_before>#include <cassert>
#include "ZigzagConnectorProcessor.h"

using namespace cura;

void ZigzagConnectorProcessor::registerVertex(const Point& vertex)
{
    if (this->is_first_connector)
    {
        this->first_connector.push_back(vertex);
    }
    else
    { // it's yet unclear whether the polygon segment should be included, so we store it until we know
        this->current_connector.push_back(vertex);
    }
}

bool ZigzagConnectorProcessor::shouldAddCurrentConnector(int start_scanline_idx, int end_scanline_idx, int direction) const
{
    assert((direction == 1 || direction == -1) && "direction should be either +1 or -1");
    //
    // Decide whether we should add this connection or not.
    // Add this zag connection in the following cases:
    //  - if this zag lays in an even-numbered scanline segment
    //  - if this zag is an end piece (check if the previous and the current scanlines are the same)
    //    and "use end piece" is enabled
    // Don't add a zag if:
    //  - this zag is NOT an end piece, "skip some zags" is enabled, and this zag lays in a segment
    //    which needs to be skipped.
    // Moreover:
    //  - if a "connected end pieces" is not enabled and this is an end piece, the last line
    //    of this end piece will not be added.
    //
    // The rules above also apply to how the last part is processed (in polygon finishes)
    //
    const bool is_this_endpiece = start_scanline_idx == end_scanline_idx;
    const bool is_this_connection_even = start_scanline_idx % 2 == 0;
    bool should_skip_this_connection = false;
    if (this->skip_some_zags && this->zag_skip_count > 0)
    {
        //
        // Skipping some zags is done in the following way:
        //  > direction: negative number means from <right> -> <left>
        //               positive number means from <left> -> <right>
        //  > for a connection:
        //    - if it comes from <left> -> <right> (direction >= 0), we skip connections that
        //      lay in segments which mean the condition: "index mod skip_count = 0"
        //    - for connections that come from the other direction, we skip on
        //      "(index - 1) mod skip_count = 0"
        //
        if (direction > 0)
        {
            should_skip_this_connection = start_scanline_idx % this->zag_skip_count == 0;
        }
        else
        {
            should_skip_this_connection = (start_scanline_idx - 1) % this->zag_skip_count == 0;
        }
    }

    const bool should_add =
        (is_this_connection_even && !is_this_endpiece && !should_skip_this_connection) // normal connections that should be added
        || (this->use_endpieces && is_this_endpiece);  // end piece if it is enabled;

    return should_add;
}

void ZigzagConnectorProcessor::registerScanlineSegmentIntersection(const Point& intersection, int scanline_index, int direction)
{

    if (this->is_first_connector)
    {
        // process as the first connector if we haven't found one yet
        // this will be processed with the last remaining piece at the end (when the polygon finishes)
        this->first_connector.push_back(intersection);
        this->first_connector_end_scanline_index = scanline_index;
        this->is_first_connector = false;
    }
    else
    {
        // add this connector if needed
        if (this->shouldAddThisConnector(this->last_connector_index, scanline_index, direction))
        {
            for (unsigned int point_idx = 0; point_idx < this->current_connector.size() - 1; ++point_idx)
            {
                addLine(this->current_connector[point_idx], this->current_connector[point_idx + 1]);
            }
            // only add the last line if:
            //  - it is not an end piece, or
            //  - it is an end piece and "connected end pieces" is enabled
            const bool is_this_endpiece = scanline_index == this->last_connector_index;
            if (!is_this_endpiece || (is_this_endpiece && this->connected_endpieces))
            {
                addLine(this->current_connector.back(), intersection);
            }
        }
    }

    // update state
    this->current_connector.clear(); // we're starting a new (odd) zigzag connector, so clear the old one
    this->current_connector.push_back(intersection);
    this->last_connector_index = scanline_index;
}

void ZigzagConnectorProcessor::registerPolyFinished()
{
    int scanline_start_index = this->last_connector_index;
    int scanline_end_index = this->first_connector_end_scanline_index;
    int direction = scanline_end_index > scanline_start_index ? 1 : -1;
    const bool is_endpiece = this->is_first_connector || (!this->is_first_connector && scanline_start_index == scanline_end_index);

    // decides whether to add this zag according to the following rules
    if ((is_endpiece && this->use_endpieces)
        || (!is_endpiece && this->shouldAddThisConnector(scanline_start_index, scanline_end_index, direction)))
    {
        // for convenience, put every point in one vector
        for (const Point& point : this->first_connector)
        {
            this->current_connector.push_back(point);
        }
        this->first_connector.clear();

        for (unsigned int point_idx = 1; point_idx < this->current_connector.size() - 1; ++point_idx)
        {
            addLine(this->current_connector[point_idx - 1], this->current_connector[point_idx]);
        }
        // only add the last line if:
        //  - it is not an end piece, or
        //  - it is an end piece and "connected end pieces" is enabled
        if (!is_endpiece || (is_endpiece && this->connected_endpieces && this->current_connector.size() >= 2))
        {
            addLine(this->current_connector[current_connector.size() - 2],
                    this->current_connector[current_connector.size() - 1]);
        }
    }

    // reset member variables
    this->reset();
}
<commit_msg>Fix renaming function to shouldAddCurrentConnector<commit_after>#include <cassert>
#include "ZigzagConnectorProcessor.h"

using namespace cura;

void ZigzagConnectorProcessor::registerVertex(const Point& vertex)
{
    if (this->is_first_connector)
    {
        this->first_connector.push_back(vertex);
    }
    else
    { // it's yet unclear whether the polygon segment should be included, so we store it until we know
        this->current_connector.push_back(vertex);
    }
}

bool ZigzagConnectorProcessor::shouldAddCurrentConnector(int start_scanline_idx, int end_scanline_idx, int direction) const
{
    assert((direction == 1 || direction == -1) && "direction should be either +1 or -1");
    //
    // Decide whether we should add this connection or not.
    // Add this zag connection in the following cases:
    //  - if this zag lays in an even-numbered scanline segment
    //  - if this zag is an end piece (check if the previous and the current scanlines are the same)
    //    and "use end piece" is enabled
    // Don't add a zag if:
    //  - this zag is NOT an end piece, "skip some zags" is enabled, and this zag lays in a segment
    //    which needs to be skipped.
    // Moreover:
    //  - if a "connected end pieces" is not enabled and this is an end piece, the last line
    //    of this end piece will not be added.
    //
    // The rules above also apply to how the last part is processed (in polygon finishes)
    //
    const bool is_this_endpiece = start_scanline_idx == end_scanline_idx;
    const bool is_this_connection_even = start_scanline_idx % 2 == 0;
    bool should_skip_this_connection = false;
    if (this->skip_some_zags && this->zag_skip_count > 0)
    {
        //
        // Skipping some zags is done in the following way:
        //  > direction: negative number means from <right> -> <left>
        //               positive number means from <left> -> <right>
        //  > for a connection:
        //    - if it comes from <left> -> <right> (direction >= 0), we skip connections that
        //      lay in segments which mean the condition: "index mod skip_count = 0"
        //    - for connections that come from the other direction, we skip on
        //      "(index - 1) mod skip_count = 0"
        //
        if (direction > 0)
        {
            should_skip_this_connection = start_scanline_idx % this->zag_skip_count == 0;
        }
        else
        {
            should_skip_this_connection = (start_scanline_idx - 1) % this->zag_skip_count == 0;
        }
    }

    const bool should_add =
        (is_this_connection_even && !is_this_endpiece && !should_skip_this_connection) // normal connections that should be added
        || (this->use_endpieces && is_this_endpiece);  // end piece if it is enabled;

    return should_add;
}

void ZigzagConnectorProcessor::registerScanlineSegmentIntersection(const Point& intersection, int scanline_index, int direction)
{

    if (this->is_first_connector)
    {
        // process as the first connector if we haven't found one yet
        // this will be processed with the last remaining piece at the end (when the polygon finishes)
        this->first_connector.push_back(intersection);
        this->first_connector_end_scanline_index = scanline_index;
        this->is_first_connector = false;
    }
    else
    {
        // add this connector if needed
        if (this->shouldAddCurrentConnector(this->last_connector_index, scanline_index, direction))
        {
            for (unsigned int point_idx = 0; point_idx < this->current_connector.size() - 1; ++point_idx)
            {
                addLine(this->current_connector[point_idx], this->current_connector[point_idx + 1]);
            }
            // only add the last line if:
            //  - it is not an end piece, or
            //  - it is an end piece and "connected end pieces" is enabled
            const bool is_this_endpiece = scanline_index == this->last_connector_index;
            if (!is_this_endpiece || (is_this_endpiece && this->connected_endpieces))
            {
                addLine(this->current_connector.back(), intersection);
            }
        }
    }

    // update state
    this->current_connector.clear(); // we're starting a new (odd) zigzag connector, so clear the old one
    this->current_connector.push_back(intersection);
    this->last_connector_index = scanline_index;
}

void ZigzagConnectorProcessor::registerPolyFinished()
{
    int scanline_start_index = this->last_connector_index;
    int scanline_end_index = this->first_connector_end_scanline_index;
    int direction = scanline_end_index > scanline_start_index ? 1 : -1;
    const bool is_endpiece = this->is_first_connector || (!this->is_first_connector && scanline_start_index == scanline_end_index);

    // decides whether to add this zag according to the following rules
    if ((is_endpiece && this->use_endpieces)
        || (!is_endpiece && this->shouldAddCurrentConnector(scanline_start_index, scanline_end_index, direction)))
    {
        // for convenience, put every point in one vector
        for (const Point& point : this->first_connector)
        {
            this->current_connector.push_back(point);
        }
        this->first_connector.clear();

        for (unsigned int point_idx = 1; point_idx < this->current_connector.size() - 1; ++point_idx)
        {
            addLine(this->current_connector[point_idx - 1], this->current_connector[point_idx]);
        }
        // only add the last line if:
        //  - it is not an end piece, or
        //  - it is an end piece and "connected end pieces" is enabled
        if (!is_endpiece || (is_endpiece && this->connected_endpieces && this->current_connector.size() >= 2))
        {
            addLine(this->current_connector[current_connector.size() - 2],
                    this->current_connector[current_connector.size() - 1]);
        }
    }

    // reset member variables
    this->reset();
}
<|endoftext|>


<commit_before>#include <UnitTest++/UnitTest++.h>

#include <algorithm>
#include <iterator>
#include <memory>
#include <vector>

#include "Article.h"
#include "WalkerException.h"

SUITE(ArticleTests)
{
  using namespace WikiWalker;

  TEST(Article_GetCountLinks_Uninited_ThrowsException)
  {
    Article a("Foo");
    CHECK_EQUAL(a.analyzed(), false);
    CHECK_THROW(a.countLinks(), WalkerException);
  }

  TEST(Article_GetCountLinks_Inited_ReturnsNull)
  {
    Article a("Foo");
    a.analyzed(true);
    CHECK_EQUAL(a.analyzed(), true);
    CHECK_EQUAL(0, a.countLinks());
  }

  TEST(Article_AddLinks_OneLinkAdded)
  {
    Article a("Foo");

    auto link = std::make_shared<Article>("Barmiz");
    a.addLink(link);

    CHECK_EQUAL(a.analyzed(), true);
    CHECK_EQUAL(1, a.countLinks());
  }

  TEST(Article_AddLinks_DuplicateInstance)
  {
    Article a("Foo");

    auto arl = std::make_shared<Article>("Barmiz");
    CHECK(a.addLink(arl));
    CHECK(!a.addLink(arl));

    CHECK_EQUAL(a.analyzed(), true);
    CHECK_EQUAL(1, a.countLinks());
  }

  TEST(Article_Iterator_Test)
  {
    Article a("Foo");

    std::vector<std::string> titles{"Barmiz", "Kodopa", "Minting"};
    // must keep them in scope
    std::vector<std::shared_ptr<Article>> articleLinks;

    std::transform(titles.begin(),
                   titles.end(),
                   std::back_inserter(articleLinks),
                   [](std::string s) { return std::make_shared<Article>(s); });

    for(const auto& s : articleLinks) {
      a.addLink(s);
    }

    CHECK_EQUAL(a.analyzed(), true);
    CHECK_EQUAL(3, a.countLinks());

    int num = 0;
    for(auto x = a.linkBegin(); x != a.linkEnd(); x++) {
      num++;
      auto atitle  = x->lock()->title();
      auto findpos = std::find(titles.cbegin(), titles.cend(), atitle);
      bool isFound = (titles.end() != findpos);
      CHECK(isFound);
    }

    CHECK_EQUAL(titles.size(), num);
  }

  TEST(Article_Marked_State)
  {
    Article a("Todo");
    CHECK_EQUAL(false, a.marked());
    a.marked(true);
    CHECK_EQUAL(true, a.marked());
    a.marked(false);
    CHECK_EQUAL(false, a.marked());
  }
}
<commit_msg>Fix order of arguments in CHECK_EQUAL where they're wrong<commit_after>#include <UnitTest++/UnitTest++.h>

#include <algorithm>
#include <iterator>
#include <memory>
#include <vector>

#include "Article.h"
#include "WalkerException.h"

SUITE(ArticleTests)
{
  using namespace WikiWalker;

  TEST(Article_GetCountLinks_Uninited_ThrowsException)
  {
    Article a("Foo");
    CHECK_EQUAL(false, a.analyzed());
    CHECK_THROW(a.countLinks(), WalkerException);
  }

  TEST(Article_GetCountLinks_Inited_ReturnsNull)
  {
    Article a("Foo");
    a.analyzed(true);
    CHECK_EQUAL(true, a.analyzed());
    CHECK_EQUAL(0, a.countLinks());
  }

  TEST(Article_AddLinks_OneLinkAdded)
  {
    Article a("Foo");

    auto link = std::make_shared<Article>("Barmiz");
    a.addLink(link);

    CHECK_EQUAL(true, a.analyzed());
    CHECK_EQUAL(1, a.countLinks());
  }

  TEST(Article_AddLinks_DuplicateInstance)
  {
    Article a("Foo");

    auto arl = std::make_shared<Article>("Barmiz");
    CHECK(a.addLink(arl));
    CHECK(!a.addLink(arl));

    CHECK_EQUAL(true, a.analyzed());
    CHECK_EQUAL(1, a.countLinks());
  }

  TEST(Article_Iterator_Test)
  {
    Article a("Foo");

    std::vector<std::string> titles{"Barmiz", "Kodopa", "Minting"};
    // must keep them in scope
    std::vector<std::shared_ptr<Article>> articleLinks;

    std::transform(titles.begin(),
                   titles.end(),
                   std::back_inserter(articleLinks),
                   [](std::string s) { return std::make_shared<Article>(s); });

    for(const auto& s : articleLinks) {
      a.addLink(s);
    }

    CHECK_EQUAL(true, a.analyzed());
    CHECK_EQUAL(3, a.countLinks());

    int num = 0;
    for(auto x = a.linkBegin(); x != a.linkEnd(); x++) {
      num++;
      auto atitle  = x->lock()->title();
      auto findpos = std::find(titles.cbegin(), titles.cend(), atitle);
      bool isFound = (titles.end() != findpos);
      CHECK(isFound);
    }

    CHECK_EQUAL(num, titles.size());
  }

  TEST(Article_Marked_State)
  {
    Article a("Todo");
    CHECK_EQUAL(false, a.marked());
    a.marked(true);
    CHECK_EQUAL(true, a.marked());
    a.marked(false);
    CHECK_EQUAL(false, a.marked());
  }
}
<|endoftext|>


<commit_before>#include <pthread.h>
#include <sys/time.h>

#include "stinger_core/xmalloc.h"
#include "stinger_core/x86_full_empty.h"
#include "stinger_core/stinger_shared.h"
#include "stinger_core/stinger.h"
#include "stinger_mon.h"

#define LOG_AT_W
#include "stinger_core/stinger_error.h"

using namespace gt::stinger;

static uint64_t singleton_lock = 0;
static StingerMon * state = NULL;

StingerMon &
StingerMon::get_mon() {
  if(!state) {
    readfe(&singleton_lock);
      if(!state) {
	state = new StingerMon();
      }
    writeef(&singleton_lock, 1);
  }
  return *state;
}

StingerMon::StingerMon() : stinger(NULL),
  stinger_loc(""), stinger_sz(0), algs(NULL), alg_map(NULL),
  waiting(0), wait_lock(0), max_time(-922337203685477580)
{
  pthread_rwlock_init(&alg_lock, NULL);
  sem_init(&sync_lock, 0, 0);
}

StingerMon::~StingerMon()
{
  sem_destroy(&sync_lock);
}

size_t
StingerMon::get_num_algs()
{
  if(algs)
    return algs->size();
  else
    return 0;
}

StingerAlgState *
StingerMon::get_alg(size_t num)
{
  if(algs)
    return (*algs)[num];
  else
    return NULL;
}

StingerAlgState *
StingerMon::get_alg(const std::string & name)
{
  if(alg_map && has_alg(name))
    return (*alg_map)[name];
  else
    return NULL;
}

bool
StingerMon::has_alg(const std::string & name)
{
  if(alg_map)
    return alg_map->count(name) > 0;
  else
    return false;
}

void
StingerMon::get_alg_read_lock()
{
  LOG_D("read lock get");
  pthread_rwlock_rdlock(&alg_lock);
  LOG_D("read lock received");
}

void
StingerMon::release_alg_read_lock()
{
  LOG_D("read lock release");
  pthread_rwlock_unlock(&alg_lock);
  LOG_D("read lock released");
}

void
StingerMon::update_algs(stinger_t * stinger_copy, std::string new_loc, int64_t new_sz,
  std::vector<StingerAlgState *> * new_algs, std::map<std::string, StingerAlgState *> * new_alg_map,
  const StingerBatch & batch)
{
  LOG_D_A("Called with %s, %ld", new_loc.c_str(), (long)new_sz);
  LOG_D("write lock get");
  pthread_rwlock_wrlock(&alg_lock);
  LOG_D("write lock received");
  /* remap stinger */
  if(stinger) {
    stinger_shared_free(stinger, stinger_loc.c_str(), stinger_sz);
  }
  stinger = stinger_copy;
  stinger_loc = new_loc;
  stinger_sz = new_sz;

  /* unmap / delete existing algs */
  if(algs) {
    for(int64_t i = 0; i < algs->size(); i++) {
      StingerAlgState * cur_alg = (*algs)[i];
      if(cur_alg) {
	shmunmap(cur_alg->data_loc.c_str(), cur_alg->data, cur_alg->data_per_vertex * stinger->max_nv);
	delete cur_alg;
      }
    }

    delete algs;
  }
  if(alg_map)
    delete alg_map;

  algs = new_algs;
  alg_map = new_alg_map;

  /* update max time with latest insertion time */
  int64_t new_max_time = max_time;
  for(int64_t i = 0; i < batch.insertions_size(); i++) {
    int64_t edge_time = batch.insertions(i).time();
    if(edge_time > new_max_time)
      new_max_time = edge_time;
  }
  max_time = new_max_time;

  LOG_D("write lock release");
  pthread_rwlock_unlock(&alg_lock);
  LOG_D("write lock released");
}

int64_t
StingerMon::get_max_time() {
  return max_time;
}

void
StingerMon::wait_for_sync()
{
  readfe((uint64_t *)&wait_lock);
    waiting++;
  writeef((uint64_t *)&wait_lock, 0);

  sem_wait(&sync_lock);
}

void
StingerMon::sync()
{
  readfe((uint64_t *)&wait_lock);
    for(int64_t i = 0; i < waiting; i++)
      sem_post(&sync_lock);
    waiting = 0;
  writeef((uint64_t *)&wait_lock, 0);
}

stinger_t *
StingerMon::get_stinger()
{
  return stinger;
}
<commit_msg>Unmap rather than free in stinger_mon.<commit_after>#include <pthread.h>
#include <sys/time.h>

#include "stinger_core/xmalloc.h"
#include "stinger_core/x86_full_empty.h"
#include "stinger_core/stinger_shared.h"
#include "stinger_core/stinger.h"
#include "stinger_mon.h"

#define LOG_AT_W
#include "stinger_core/stinger_error.h"

using namespace gt::stinger;

static uint64_t singleton_lock = 0;
static StingerMon * state = NULL;

StingerMon &
StingerMon::get_mon() {
  if(!state) {
    readfe(&singleton_lock);
      if(!state) {
	state = new StingerMon();
      }
    writeef(&singleton_lock, 1);
  }
  return *state;
}

StingerMon::StingerMon() : stinger(NULL),
  stinger_loc(""), stinger_sz(0), algs(NULL), alg_map(NULL),
  waiting(0), wait_lock(0), max_time(-922337203685477580)
{
  pthread_rwlock_init(&alg_lock, NULL);
  sem_init(&sync_lock, 0, 0);
}

StingerMon::~StingerMon()
{
  sem_destroy(&sync_lock);
}

size_t
StingerMon::get_num_algs()
{
  if(algs)
    return algs->size();
  else
    return 0;
}

StingerAlgState *
StingerMon::get_alg(size_t num)
{
  if(algs)
    return (*algs)[num];
  else
    return NULL;
}

StingerAlgState *
StingerMon::get_alg(const std::string & name)
{
  if(alg_map && has_alg(name))
    return (*alg_map)[name];
  else
    return NULL;
}

bool
StingerMon::has_alg(const std::string & name)
{
  if(alg_map)
    return alg_map->count(name) > 0;
  else
    return false;
}

void
StingerMon::get_alg_read_lock()
{
  LOG_D("read lock get");
  pthread_rwlock_rdlock(&alg_lock);
  LOG_D("read lock received");
}

void
StingerMon::release_alg_read_lock()
{
  LOG_D("read lock release");
  pthread_rwlock_unlock(&alg_lock);
  LOG_D("read lock released");
}

void
StingerMon::update_algs(stinger_t * stinger_copy, std::string new_loc, int64_t new_sz,
  std::vector<StingerAlgState *> * new_algs, std::map<std::string, StingerAlgState *> * new_alg_map,
  const StingerBatch & batch)
{
  LOG_D_A("Called with %s, %ld", new_loc.c_str(), (long)new_sz);
  LOG_D("write lock get");
  pthread_rwlock_wrlock(&alg_lock);
  LOG_D("write lock received");
  /* remap stinger */
  if(stinger) {
    stinger_shared_unmap (stinger, stinger_loc.c_str(), stinger_sz);
  }
  stinger = stinger_copy;
  stinger_loc = new_loc;
  stinger_sz = new_sz;

  /* unmap / delete existing algs */
  if(algs) {
    for(int64_t i = 0; i < algs->size(); i++) {
      StingerAlgState * cur_alg = (*algs)[i];
      if(cur_alg) {
	shmunmap(cur_alg->data_loc.c_str(), cur_alg->data, cur_alg->data_per_vertex * stinger->max_nv);
	delete cur_alg;
      }
    }

    delete algs;
  }
  if(alg_map)
    delete alg_map;

  algs = new_algs;
  alg_map = new_alg_map;

  /* update max time with latest insertion time */
  int64_t new_max_time = max_time;
  for(int64_t i = 0; i < batch.insertions_size(); i++) {
    int64_t edge_time = batch.insertions(i).time();
    if(edge_time > new_max_time)
      new_max_time = edge_time;
  }
  max_time = new_max_time;

  LOG_D("write lock release");
  pthread_rwlock_unlock(&alg_lock);
  LOG_D("write lock released");
}

int64_t
StingerMon::get_max_time() {
  return max_time;
}

void
StingerMon::wait_for_sync()
{
  readfe((uint64_t *)&wait_lock);
    waiting++;
  writeef((uint64_t *)&wait_lock, 0);

  sem_wait(&sync_lock);
}

void
StingerMon::sync()
{
  readfe((uint64_t *)&wait_lock);
    for(int64_t i = 0; i < waiting; i++)
      sem_post(&sync_lock);
    waiting = 0;
  writeef((uint64_t *)&wait_lock, 0);
}

stinger_t *
StingerMon::get_stinger()
{
  return stinger;
}
<|endoftext|>


<commit_before>/**
 * @file   gtest_brutil.cpp
 * @author Shane Barnes
 * @date   18 Mar 2016
 * @brief  Bottlerocket utility Google unit tests.
 */

#include "logger.c"
#include "output_if_std.c"
#include "mutex_instance.c"
#include "util_date.c"
#include "util_string.c"

#include <gtest/gtest.h>

TEST (ManipStringTest, Compare)
{
    // Empty strings or null pointers.
    ASSERT_TRUE(utilstring_compare("", "", false));
    ASSERT_TRUE(utilstring_compare("", "", true));
    ASSERT_FALSE(utilstring_compare(NULL, "", false));
    ASSERT_FALSE(utilstring_compare("", NULL, false));
    ASSERT_FALSE(utilstring_compare(NULL, "", true));
    ASSERT_FALSE(utilstring_compare("", NULL, true));
    ASSERT_FALSE(utilstring_compare(NULL, NULL, false));
    ASSERT_FALSE(utilstring_compare(NULL, NULL, true));

    // Strings containing only alphabetic characters.
    ASSERT_TRUE(utilstring_compare("string", "string", false));
    ASSERT_TRUE(utilstring_compare("string", "string", true));
    ASSERT_FALSE(utilstring_compare("string", "STRING", false));
    ASSERT_TRUE(utilstring_compare("string", "STRING", true));

    // Strings containing only numeric characters.
    ASSERT_TRUE(utilstring_compare("123", "123", false));
    ASSERT_TRUE(utilstring_compare("123", "123", true));

    // String containing alphanumeric characters.
    ASSERT_TRUE(utilstring_compare("string123", "string123", false));
    ASSERT_TRUE(utilstring_compare("string123", "string123", true));
    ASSERT_FALSE(utilstring_compare("string123", "STRING123", false));
    ASSERT_TRUE(utilstring_compare("string123", "STRING123", true));
}

TEST (ManipStringTest, Concat)
{
    char buf[16];
    const size_t bufsize = sizeof(buf);
    const char *str = "string";
    const int32_t strsize = (int32_t)strlen(str);

    // Empty buffer, empty strings, or null pointers.
    ASSERT_EQ(-1, utilstring_concat(buf, 0, NULL, NULL));
    ASSERT_EQ(-1, utilstring_concat(buf, 0, "%s", NULL));
    ASSERT_EQ(-1, utilstring_concat(buf, 0, NULL, ""));
    ASSERT_EQ(-1, utilstring_concat(buf, 0, NULL, str));
    ASSERT_EQ(-1, utilstring_concat(buf, 0, "", ""));
    ASSERT_EQ(-1, utilstring_concat(buf, 0, "%s", str));
    ASSERT_EQ(-1, utilstring_concat(NULL, 0, "%s", str));
    ASSERT_EQ(6, utilstring_concat(buf, bufsize, "%s", NULL)); // ??

    // Single- and multiple-variable concatenations.
    ASSERT_EQ(0, utilstring_concat(buf, bufsize, "%s", ""));
    ASSERT_EQ(1, utilstring_concat(buf, bufsize, "%d", 0));
    ASSERT_EQ(2, utilstring_concat(buf, bufsize, "%d", -1));
    ASSERT_EQ(2, utilstring_concat(buf, bufsize, "%d", 10));
    ASSERT_EQ(strsize, utilstring_concat(buf, bufsize, "%s", str));
    ASSERT_EQ(strsize + 1, utilstring_concat(buf, bufsize, "%s%d", str, 1));

    // Buffer overflow.
    ASSERT_EQ(strsize, utilstring_concat(buf, strsize, "%s", str));
    ASSERT_EQ(strsize, utilstring_concat(buf, strsize - 1, "%s", str));
}

int main(int argc, char **argv)
{
    ::testing::InitGoogleTest(&argc, argv);
    return RUN_ALL_TESTS();
}
<commit_msg>gtest_brutil: added copyright tag<commit_after>/**
 * @file      gtest_brutil.cpp
 * @brief     Bottlerocket utility Google unit tests.
 * @author    Shane Barnes
 * @date      18 Mar 2016
 * @copyright Copyright 2016 Shane Barnes. All rights reserved.
 *            This project is released under the MIT license.
 */

#include "logger.c"
#include "output_if_std.c"
#include "mutex_instance.c"
#include "util_date.c"
#include "util_string.c"

#include <gtest/gtest.h>

TEST (ManipStringTest, Compare)
{
    // Empty strings or null pointers.
    ASSERT_TRUE(utilstring_compare("", "", false));
    ASSERT_TRUE(utilstring_compare("", "", true));
    ASSERT_FALSE(utilstring_compare(NULL, "", false));
    ASSERT_FALSE(utilstring_compare("", NULL, false));
    ASSERT_FALSE(utilstring_compare(NULL, "", true));
    ASSERT_FALSE(utilstring_compare("", NULL, true));
    ASSERT_FALSE(utilstring_compare(NULL, NULL, false));
    ASSERT_FALSE(utilstring_compare(NULL, NULL, true));

    // Strings containing only alphabetic characters.
    ASSERT_TRUE(utilstring_compare("string", "string", false));
    ASSERT_TRUE(utilstring_compare("string", "string", true));
    ASSERT_FALSE(utilstring_compare("string", "STRING", false));
    ASSERT_TRUE(utilstring_compare("string", "STRING", true));

    // Strings containing only numeric characters.
    ASSERT_TRUE(utilstring_compare("123", "123", false));
    ASSERT_TRUE(utilstring_compare("123", "123", true));

    // String containing alphanumeric characters.
    ASSERT_TRUE(utilstring_compare("string123", "string123", false));
    ASSERT_TRUE(utilstring_compare("string123", "string123", true));
    ASSERT_FALSE(utilstring_compare("string123", "STRING123", false));
    ASSERT_TRUE(utilstring_compare("string123", "STRING123", true));
}

TEST (ManipStringTest, Concat)
{
    char buf[16];
    const size_t bufsize = sizeof(buf);
    const char *str = "string";
    const int32_t strsize = (int32_t)strlen(str);

    // Empty buffer, empty strings, or null pointers.
    ASSERT_EQ(-1, utilstring_concat(buf, 0, NULL, NULL));
    ASSERT_EQ(-1, utilstring_concat(buf, 0, "%s", NULL));
    ASSERT_EQ(-1, utilstring_concat(buf, 0, NULL, ""));
    ASSERT_EQ(-1, utilstring_concat(buf, 0, NULL, str));
    ASSERT_EQ(-1, utilstring_concat(buf, 0, "", ""));
    ASSERT_EQ(-1, utilstring_concat(buf, 0, "%s", str));
    ASSERT_EQ(-1, utilstring_concat(NULL, 0, "%s", str));
    ASSERT_EQ(6, utilstring_concat(buf, bufsize, "%s", NULL)); // ??

    // Single- and multiple-variable concatenations.
    ASSERT_EQ(0, utilstring_concat(buf, bufsize, "%s", ""));
    ASSERT_EQ(1, utilstring_concat(buf, bufsize, "%d", 0));
    ASSERT_EQ(2, utilstring_concat(buf, bufsize, "%d", -1));
    ASSERT_EQ(2, utilstring_concat(buf, bufsize, "%d", 10));
    ASSERT_EQ(strsize, utilstring_concat(buf, bufsize, "%s", str));
    ASSERT_EQ(strsize + 1, utilstring_concat(buf, bufsize, "%s%d", str, 1));

    // Buffer overflow.
    ASSERT_EQ(strsize, utilstring_concat(buf, strsize, "%s", str));
    ASSERT_EQ(strsize, utilstring_concat(buf, strsize - 1, "%s", str));
}

int main(int argc, char **argv)
{
    ::testing::InitGoogleTest(&argc, argv);
    return RUN_ALL_TESTS();
}
<|endoftext|>


<commit_before>#include <product.hpp>

#define DEFINE_BASIC_ITERABLE_COPY_CTOR
#define DEFINE_BASIC_ITERABLE_CONST_BEGIN_AND_END
#include "helpers.hpp"
#undef DEFINE_BASIC_ITERABLE_CONST_BEGIN_AND_END
#undef DEFINE_BASIC_ITERABLE_COPY_CTOR

#include <iterator>
#include <string>
#include <vector>

#include "catch.hpp"

using iter::product;
using Vec = const std::vector<int>;

TEST_CASE("product: basic test, two sequences", "[product]") {
  using TP = std::tuple<int, char>;
  using ResType = std::vector<TP>;

  Vec n1 = {0, 1};
  const std::string s{"abc"};

  auto p = product(n1, s);
  ResType v(std::begin(p), std::end(p));
  ResType vc = {
      TP{0, 'a'}, TP{0, 'b'}, TP{0, 'c'}, TP{1, 'a'}, TP{1, 'b'}, TP{1, 'c'}};

  REQUIRE(v == vc);
}

TEST_CASE("product: two sequences where one has different begin and end",
    "[product]") {
  using TP = std::tuple<int, char>;
  using ResType = std::vector<TP>;

  Vec n1 = {0, 1};
  CharRange cr('d');

  auto p = product(n1, cr);
  ResType v(std::begin(p), std::end(p));
  ResType vc = {
      TP{0, 'a'}, TP{0, 'b'}, TP{0, 'c'}, TP{1, 'a'}, TP{1, 'b'}, TP{1, 'c'}};

  REQUIRE(v == vc);
}

TEST_CASE("product: three sequences", "[product]") {
  using TP = std::tuple<int, char, int>;
  using ResType = const std::vector<TP>;

  Vec n1 = {0, 1};
  const std::string s{"ab"};
  Vec n2 = {2};

  auto p = product(n1, s, n2);
  ResType v(std::begin(p), std::end(p));

  ResType vc = {TP{0, 'a', 2}, TP{0, 'b', 2}, TP{1, 'a', 2}, TP{1, 'b', 2}};

  REQUIRE(v == vc);
}

TEST_CASE("product: with repeat", "[product]") {
  using TP = std::tuple<char, char, char>;
  using ResType = const std::vector<TP>;
  const std::string s = "hop";
  auto p = product<3>(s);
  ResType v(std::begin(p), std::end(p));

  ResType vc = {
      TP{'h', 'h', 'h'}, TP{'h', 'h', 'o'}, TP{'h', 'h', 'p'},
      TP{'h', 'o', 'h'}, TP{'h', 'o', 'o'}, TP{'h', 'o', 'p'},
      TP{'h', 'p', 'h'}, TP{'h', 'p', 'o'}, TP{'h', 'p', 'p'},
      TP{'o', 'h', 'h'}, TP{'o', 'h', 'o'}, TP{'o', 'h', 'p'},
      TP{'o', 'o', 'h'}, TP{'o', 'o', 'o'}, TP{'o', 'o', 'p'},
      TP{'o', 'p', 'h'}, TP{'o', 'p', 'o'}, TP{'o', 'p', 'p'},
      TP{'p', 'h', 'h'}, TP{'p', 'h', 'o'}, TP{'p', 'h', 'p'},
      TP{'p', 'o', 'h'}, TP{'p', 'o', 'o'}, TP{'p', 'o', 'p'},
      TP{'p', 'p', 'h'}, TP{'p', 'p', 'o'}, TP{'p', 'p', 'p'},
  };
  REQUIRE(v == vc);
}

TEST_CASE("product: empty when any iterable is empty", "[product]") {
  Vec n1 = {0, 1};
  Vec n2 = {0, 1, 2};
  Vec emp = {};

  SECTION("first iterable is empty") {
    auto p = product(emp, n1, n2);
    REQUIRE(std::begin(p) == std::end(p));
  }

  SECTION("middle iterable is empty") {
    auto p = product(n1, emp, n2);
    REQUIRE(std::begin(p) == std::end(p));
  }

  SECTION("last iterable is empty") {
    auto p = product(n1, n2, emp);
    REQUIRE(std::begin(p) == std::end(p));
  }
}

TEST_CASE("product: single iterable", "[product]") {
  const std::string s{"ab"};
  using TP = std::tuple<char>;
  using ResType = const std::vector<TP>;

  auto p = product(s);
  ResType v(std::begin(p), std::end(p));
  ResType vc = {TP{'a'}, TP{'b'}};

  REQUIRE(v == vc);
}

TEST_CASE("product: no arguments gives one empty tuple", "[product") {
  auto p = product();
  auto it = std::begin(p);
  REQUIRE(it != std::end(p));
  REQUIRE(*it == std::make_tuple());
  ++it;
  REQUIRE(it == std::end(p));
}

TEST_CASE("product: binds to lvalues and moves rvalues", "[product]") {
  itertest::BasicIterable<char> bi{'x', 'y'};
  itertest::BasicIterable<int> bi2{0, 1};

  SECTION("First ref'd, second moved") {
    product(bi, std::move(bi2));
    REQUIRE_FALSE(bi.was_moved_from());
    REQUIRE_FALSE(bi.was_copied_from());
    REQUIRE(bi2.was_moved_from());
  }

  SECTION("First moved, second ref'd") {
    product(std::move(bi), bi2);
    REQUIRE(bi.was_moved_from());
    REQUIRE_FALSE(bi2.was_copied_from());
    REQUIRE_FALSE(bi2.was_moved_from());
  }

  SECTION("repeat, lvalue not moved or copied") {
    product<2>(bi);
    REQUIRE_FALSE(bi.was_moved_from());
    REQUIRE_FALSE(bi.was_copied_from());
  }

  SECTION("repeat, const lvalue not moved or copied") {
    const auto& r = bi;
    product<2>(r);
    REQUIRE_FALSE(bi.was_moved_from());
    REQUIRE_FALSE(bi.was_copied_from());
  }

  SECTION("repeat, rvalue copied") {
    product<2>(std::move(bi));
    REQUIRE_FALSE(bi.was_moved_from());
    REQUIRE(bi.was_copied_from());
  }
}

TEST_CASE("product: doesn't move or copy elements of iterable", "[product]") {
  constexpr itertest::SolidInt arr[] = {{1}, {0}, {2}};
  for (auto&& t : product(arr)) {
    (void)std::get<0>(t);
  }
}

TEST_CASE("product: iterator meets requirements", "[product]") {
  std::string s{"abc"};
  auto c = product(s, s);
  REQUIRE(itertest::IsIterator<decltype(std::begin(c))>::value);
}

template <typename... Ts>
using ImpT = decltype(product(std::declval<Ts>()...));
TEST_CASE("product: has correct ctor and assign ops", "[product]") {
  using T = ImpT<std::string&, std::vector<double>, std::vector<std::string>>;
  REQUIRE(itertest::IsMoveConstructibleOnly<T>::value);
}
<commit_msg>Tests const iteration of product<commit_after>#include <product.hpp>

#define DEFINE_BASIC_ITERABLE_COPY_CTOR
#define DEFINE_BASIC_ITERABLE_CONST_BEGIN_AND_END
#include "helpers.hpp"
#undef DEFINE_BASIC_ITERABLE_CONST_BEGIN_AND_END
#undef DEFINE_BASIC_ITERABLE_COPY_CTOR

#include <iterator>
#include <string>
#include <vector>

#include "catch.hpp"

using iter::product;
using Vec = const std::vector<int>;

TEST_CASE("product: basic test, two sequences", "[product]") {
  using TP = std::tuple<int, char>;
  using ResType = std::vector<TP>;

  Vec n1 = {0, 1};
  const std::string s{"abc"};

  auto p = product(n1, s);
  ResType v(std::begin(p), std::end(p));
  ResType vc = {
      TP{0, 'a'}, TP{0, 'b'}, TP{0, 'c'}, TP{1, 'a'}, TP{1, 'b'}, TP{1, 'c'}};

  REQUIRE(v == vc);
}

TEST_CASE("product: const iteration", "[product][const]") {
  using TP = std::tuple<int, char>;
  using ResType = std::vector<TP>;

  Vec n1 = {0, 1};
  const std::string s{"abc"};

  const auto p = product(n1, s);
  ResType v(std::begin(p), std::end(p));
  ResType vc = {
      TP{0, 'a'}, TP{0, 'b'}, TP{0, 'c'}, TP{1, 'a'}, TP{1, 'b'}, TP{1, 'c'}};

  REQUIRE(v == vc);
}

TEST_CASE("product: const iterators can be compared to non-const iterators",
    "[product][const]") {
  std::string s;
  auto p = product(Vec{}, s);
  const auto& cp = p;
  (void)(std::begin(p) == std::end(cp));
}

TEST_CASE("product: two sequences where one has different begin and end",
    "[product]") {
  using TP = std::tuple<int, char>;
  using ResType = std::vector<TP>;

  Vec n1 = {0, 1};
  CharRange cr('d');

  auto p = product(n1, cr);
  ResType v(std::begin(p), std::end(p));
  ResType vc = {
      TP{0, 'a'}, TP{0, 'b'}, TP{0, 'c'}, TP{1, 'a'}, TP{1, 'b'}, TP{1, 'c'}};

  REQUIRE(v == vc);
}

TEST_CASE("product: three sequences", "[product]") {
  using TP = std::tuple<int, char, int>;
  using ResType = const std::vector<TP>;

  Vec n1 = {0, 1};
  const std::string s{"ab"};
  Vec n2 = {2};

  auto p = product(n1, s, n2);
  ResType v(std::begin(p), std::end(p));

  ResType vc = {TP{0, 'a', 2}, TP{0, 'b', 2}, TP{1, 'a', 2}, TP{1, 'b', 2}};

  REQUIRE(v == vc);
}

TEST_CASE("product: with repeat", "[product]") {
  using TP = std::tuple<char, char, char>;
  using ResType = const std::vector<TP>;
  const std::string s = "hop";
  auto p = product<3>(s);
  ResType v(std::begin(p), std::end(p));

  ResType vc = {
      TP{'h', 'h', 'h'}, TP{'h', 'h', 'o'}, TP{'h', 'h', 'p'},
      TP{'h', 'o', 'h'}, TP{'h', 'o', 'o'}, TP{'h', 'o', 'p'},
      TP{'h', 'p', 'h'}, TP{'h', 'p', 'o'}, TP{'h', 'p', 'p'},
      TP{'o', 'h', 'h'}, TP{'o', 'h', 'o'}, TP{'o', 'h', 'p'},
      TP{'o', 'o', 'h'}, TP{'o', 'o', 'o'}, TP{'o', 'o', 'p'},
      TP{'o', 'p', 'h'}, TP{'o', 'p', 'o'}, TP{'o', 'p', 'p'},
      TP{'p', 'h', 'h'}, TP{'p', 'h', 'o'}, TP{'p', 'h', 'p'},
      TP{'p', 'o', 'h'}, TP{'p', 'o', 'o'}, TP{'p', 'o', 'p'},
      TP{'p', 'p', 'h'}, TP{'p', 'p', 'o'}, TP{'p', 'p', 'p'},
  };
  REQUIRE(v == vc);
}

TEST_CASE("product: empty when any iterable is empty", "[product]") {
  Vec n1 = {0, 1};
  Vec n2 = {0, 1, 2};
  Vec emp = {};

  SECTION("first iterable is empty") {
    auto p = product(emp, n1, n2);
    REQUIRE(std::begin(p) == std::end(p));
  }

  SECTION("middle iterable is empty") {
    auto p = product(n1, emp, n2);
    REQUIRE(std::begin(p) == std::end(p));
  }

  SECTION("last iterable is empty") {
    auto p = product(n1, n2, emp);
    REQUIRE(std::begin(p) == std::end(p));
  }
}

TEST_CASE("product: single iterable", "[product]") {
  const std::string s{"ab"};
  using TP = std::tuple<char>;
  using ResType = const std::vector<TP>;

  auto p = product(s);
  ResType v(std::begin(p), std::end(p));
  ResType vc = {TP{'a'}, TP{'b'}};

  REQUIRE(v == vc);
}

TEST_CASE("product: no arguments gives one empty tuple", "[product") {
  auto p = product();
  auto it = std::begin(p);
  REQUIRE(it != std::end(p));
  REQUIRE(*it == std::make_tuple());
  ++it;
  REQUIRE(it == std::end(p));
}

TEST_CASE("product: binds to lvalues and moves rvalues", "[product]") {
  itertest::BasicIterable<char> bi{'x', 'y'};
  itertest::BasicIterable<int> bi2{0, 1};

  SECTION("First ref'd, second moved") {
    product(bi, std::move(bi2));
    REQUIRE_FALSE(bi.was_moved_from());
    REQUIRE_FALSE(bi.was_copied_from());
    REQUIRE(bi2.was_moved_from());
  }

  SECTION("First moved, second ref'd") {
    product(std::move(bi), bi2);
    REQUIRE(bi.was_moved_from());
    REQUIRE_FALSE(bi2.was_copied_from());
    REQUIRE_FALSE(bi2.was_moved_from());
  }

  SECTION("repeat, lvalue not moved or copied") {
    product<2>(bi);
    REQUIRE_FALSE(bi.was_moved_from());
    REQUIRE_FALSE(bi.was_copied_from());
  }

  SECTION("repeat, const lvalue not moved or copied") {
    const auto& r = bi;
    product<2>(r);
    REQUIRE_FALSE(bi.was_moved_from());
    REQUIRE_FALSE(bi.was_copied_from());
  }

  SECTION("repeat, rvalue copied") {
    product<2>(std::move(bi));
    REQUIRE_FALSE(bi.was_moved_from());
    REQUIRE(bi.was_copied_from());
  }
}

TEST_CASE("product: doesn't move or copy elements of iterable", "[product]") {
  constexpr itertest::SolidInt arr[] = {{1}, {0}, {2}};
  for (auto&& t : product(arr)) {
    (void)std::get<0>(t);
  }
}

TEST_CASE("product: iterator meets requirements", "[product]") {
  std::string s{"abc"};
  auto c = product(s, s);
  REQUIRE(itertest::IsIterator<decltype(std::begin(c))>::value);
}

template <typename... Ts>
using ImpT = decltype(product(std::declval<Ts>()...));
TEST_CASE("product: has correct ctor and assign ops", "[product]") {
  using T = ImpT<std::string&, std::vector<double>, std::vector<std::string>>;
  REQUIRE(itertest::IsMoveConstructibleOnly<T>::value);
}
<|endoftext|>


<commit_before>/*  This file is part of the KDE project
    Copyright (C) 2006-2007 Matthias Kretz <kretz@kde.org>

    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License version 2
    as published by the Free Software Foundation.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
    02110-1301, USA.

*/

#include "mediacontrols.h"

#include <QtCore/QTimer>
#include <QtGui/QAction>
#include <QtGui/QLabel>
#include <QtGui/QDockWidget>
#include <QtGui/QMainWindow>
#include <QtGui/QBoxLayout>
#include <QtGui/QCheckBox>
#include <QtGui/QComboBox>
#include <QtGui/QPushButton>
#include <QtGui/QSlider>

#include <phonon/audiooutput.h>
#include <phonon/backendcapabilities.h>
#include <phonon/effect.h>
#include <phonon/effectwidget.h>
#include <phonon/mediaobject.h>
#include <phonon/path.h>
#include <phonon/videowidget.h>

#include <kaboutdata.h>
#include <kdebug.h>
#include <kfiledialog.h>
#include <kapplication.h>
#include <kcmdlineargs.h>
#include <kicon.h>
#include <kurl.h>

#include <cstdlib>

using Phonon::MediaObject;
using Phonon::MediaSource;
using Phonon::AudioOutput;
using Phonon::VideoWidget;
using Phonon::MediaControls;
using Phonon::Effect;
using Phonon::EffectWidget;

class MediaPlayer : public QMainWindow
{
    Q_OBJECT
    public:
        MediaPlayer();
        void setUrl(const KUrl &url);

    private Q_SLOTS:
        void stateChanged(Phonon::State newstate);
        void workaroundQtBug();
        void getNextUrl();
        void startupReady();
        void openEffectWidget();
        void toggleScaleMode(bool);
        void switchAspectRatio(int x);
        void setBrightness(int b);

    private:
        bool setNextSource();

        QWidget *m_settingsWidget;
        Phonon::MediaObject *m_media;
        Phonon::Path m_apath;
        Phonon::AudioOutput *m_aoutput;
        Phonon::Path m_vpath;
        Phonon::Effect *m_effect;
        Phonon::VideoWidget *m_vwidget;
        Phonon::MediaControls *m_controls;
        Phonon::EffectWidget *m_effectWidget;
        QAction *m_fullScreenAction;
};

MediaPlayer::MediaPlayer()
    : QMainWindow(0), m_effectWidget(0)
{
    QDockWidget *dock = new QDockWidget(this);
    dock->setAllowedAreas(Qt::BottomDockWidgetArea);

    m_settingsWidget = new QWidget(dock);
    dock->setWidget(m_settingsWidget);
    addDockWidget(Qt::BottomDockWidgetArea, dock);

    QVBoxLayout *layout = new QVBoxLayout(m_settingsWidget);

    m_vwidget = new VideoWidget(this);
    setCentralWidget(m_vwidget);

    m_fullScreenAction = new QAction(m_vwidget);
    m_fullScreenAction->setShortcut(Qt::Key_F);
    m_fullScreenAction->setCheckable(true);
    m_fullScreenAction->setChecked(false);
    this->addAction(m_fullScreenAction);
    connect(m_fullScreenAction, SIGNAL(toggled(bool)), m_vwidget, SLOT(setFullScreen(bool)));
    connect(m_fullScreenAction, SIGNAL(toggled(bool)), SLOT(workaroundQtBug()));

    m_aoutput = new AudioOutput(Phonon::VideoCategory, this);

    m_media = new MediaObject(this);
    connect(m_media, SIGNAL(finished()), SLOT(getNextUrl()));
    connect(m_media, SIGNAL(stateChanged(Phonon::State, Phonon::State)), SLOT(stateChanged(Phonon::State)));

    createPath(m_media, m_vwidget);
    m_apath = createPath(m_media, m_aoutput);

    m_controls = new MediaControls(m_settingsWidget);
    layout->addWidget(m_controls);
    m_controls->setMediaObject(m_media);
    m_controls->setAudioOutput(m_aoutput);
    m_controls->setMaximumHeight(28);

    /*
    QList<AudioEffectDescription> effectList = BackendCapabilities::availableAudioEffects();
    if (!effectList.isEmpty())
    {
        m_effect = new AudioEffect(BackendCapabilities::availableAudioEffects().first(), m_apath);
        m_apath->insertEffect(m_effect);
        QPushButton *button = new QPushButton(m_settingsWidget);
        layout->addWidget(button);
        button->setText("configure effect");
        connect(button, SIGNAL(clicked()), SLOT(openEffectWidget()));
    }
    */

    QSlider *slider = new QSlider(m_settingsWidget);
    layout->addWidget(slider);
    slider->setOrientation(Qt::Horizontal);
    slider->setRange(-100, 100);
    slider->setValue(static_cast<int>(m_vwidget->brightness() * 100));
    connect(slider, SIGNAL(valueChanged(int)), this, SLOT(setBrightness(int)));

    QCheckBox *scaleModeCheck = new QCheckBox(m_settingsWidget);
    layout->addWidget(scaleModeCheck);
    connect(scaleModeCheck, SIGNAL(toggled(bool)), SLOT(toggleScaleMode(bool)));

    QWidget *box = new QWidget(m_settingsWidget);
    layout->addWidget(box);

    QLabel *label = new QLabel("Aspect Ratio:", box);
    label->setAlignment(Qt::AlignRight);
    QComboBox *aspectRatioCombo = new QComboBox(box);
    QHBoxLayout *hbox = new QHBoxLayout(box);
    hbox->addWidget(label);
    hbox->addWidget(aspectRatioCombo);
    label->setBuddy(aspectRatioCombo);

    connect(aspectRatioCombo, SIGNAL(currentIndexChanged(int)), SLOT(switchAspectRatio(int)));
    aspectRatioCombo->addItem("auto");
    aspectRatioCombo->addItem("fit");
    aspectRatioCombo->addItem("4:3");
    aspectRatioCombo->addItem("16:9");

    this->resize(width(), height() + 240 - m_vwidget->height());

    QTimer::singleShot(0, this, SLOT(startupReady()));
}

void MediaPlayer::stateChanged(Phonon::State newstate)
{
    switch (newstate) {
    case Phonon::ErrorState:
    case Phonon::StoppedState:
        getNextUrl();
        break;
    default:
        break;
    }
}

void MediaPlayer::workaroundQtBug()
{
    kDebug();
    if (m_vwidget->actions().contains(m_fullScreenAction)) {
        m_vwidget->removeAction(m_fullScreenAction);
        this->addAction(m_fullScreenAction);
    } else {
        this->removeAction(m_fullScreenAction);
        m_vwidget->addAction(m_fullScreenAction);
    }
}

bool MediaPlayer::setNextSource()
{
    QWidget *extraWidget = new QWidget;
    QHBoxLayout *layout = new QHBoxLayout(extraWidget);
    layout->setMargin(0);
    layout->addStretch();
    QPushButton *dvdButton = new QPushButton(i18n("DVD"), extraWidget);
    dvdButton->setCheckable(true);
    dvdButton->setChecked(false);
    layout->addWidget(dvdButton);
    QPushButton *cdButton = new QPushButton(i18n("Audio CD"), extraWidget);
    cdButton->setCheckable(true);
    cdButton->setChecked(false);
    layout->addWidget(cdButton);
    KFileDialog dlg(KUrl(), QString(), 0, extraWidget);
    connect(dvdButton, SIGNAL(toggled(bool)), &dlg, SLOT(accept()));
    connect(cdButton, SIGNAL(toggled(bool)), &dlg, SLOT(accept()));
    dlg.setOperationMode(KFileDialog::Opening);
    dlg.setWindowTitle(i18n("Open"));
    dlg.setMode(KFile::File);
    dlg.exec();
    KUrl url = dlg.selectedUrl();

    if (dvdButton->isChecked()) {
        if (url.isLocalFile()) {
            m_media->setCurrentSource(MediaSource(Phonon::Dvd, url.path()));
        } else {
            m_media->setCurrentSource(Phonon::Dvd);
        }
    } else if (cdButton->isChecked()) {
        m_media->setCurrentSource(Phonon::Cd);
    } else if (url.isValid()) {
        m_media->setCurrentSource(url);
    } else {
        QApplication::instance()->quit();
        return false;
    }
    return true;
}

void MediaPlayer::getNextUrl()
{
    static bool fileDialogAlreadyOpen = false;
    if (fileDialogAlreadyOpen) {
        return;
    }
    fileDialogAlreadyOpen = true;
    if (!setNextSource()) {
        return;
    }
    m_media->play();
    fileDialogAlreadyOpen = false;
}

void MediaPlayer::startupReady()
{
    if (m_media->currentSource().type() == MediaSource::Invalid) {
        if (!setNextSource()) {
            return;
        }
    }
    m_media->play();
}

void MediaPlayer::setBrightness(int b)
{
    m_vwidget->setBrightness(b * 0.01);
}

void MediaPlayer::switchAspectRatio(int x)
{
    m_vwidget->setAspectRatio(static_cast<VideoWidget::AspectRatio>(x));
}

void MediaPlayer::toggleScaleMode(bool mode)
{
    if (mode) {
        m_vwidget->setScaleMode(VideoWidget::ScaleAndCrop);
    } else {
        m_vwidget->setScaleMode(VideoWidget::FitInView);
    }
}

void MediaPlayer::openEffectWidget()
{
    if (!m_effectWidget)
        m_effectWidget = new EffectWidget(m_effect);
    m_effectWidget->show();
    m_effectWidget->raise();
}

void MediaPlayer::setUrl(const KUrl &url)
{
    m_media->setCurrentSource(url);
    //m_vwidget->setVisible(m_media->hasVideo());
}

int main(int argc, char ** argv)
{
    KAboutData about("phononmediaplayer", 0, ki18n("Phonon Media Player"),
            "0.1", ki18n("Media Player"),
            KAboutData::License_GPL);
    about.addAuthor(ki18n("Matthias Kretz"), KLocalizedString(), "kretz@kde.org");

    KCmdLineArgs::init(argc, argv, &about);
    KCmdLineOptions options;
    options.add("+[url]", ki18n("File to play"));
    KCmdLineArgs::addCmdLineOptions( options );

    KApplication app;
    MediaPlayer foo;
    foo.setWindowIcon(KIcon("phonon"));
    foo.show();

    KCmdLineArgs *args = KCmdLineArgs::parsedArgs();
    if (args->count() == 1) {
        KUrl url = args->url(0);
        if (url.isValid()) {
            foo.setUrl(url);
        }
    }
    args->clear();
    return app.exec();
}

#include "mediaplayer.moc"
#include "mediacontrols.cpp"
#include "moc_mediacontrols.cpp"
<commit_msg>Fixed test - had to create dummy QString and KUrl objects to pass to the KFileDialog constructor as file wouldn't compile otherwise.<commit_after>/*  This file is part of the KDE project
    Copyright (C) 2006-2007 Matthias Kretz <kretz@kde.org>

    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License version 2
    as published by the Free Software Foundation.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
    02110-1301, USA.

*/

#include "mediacontrols.h"

#include <QtCore/QTimer>
#include <QtGui/QAction>
#include <QtGui/QLabel>
#include <QtGui/QDockWidget>
#include <QtGui/QMainWindow>
#include <QtGui/QBoxLayout>
#include <QtGui/QCheckBox>
#include <QtGui/QComboBox>
#include <QtGui/QPushButton>
#include <QtGui/QSlider>

#include <phonon/audiooutput.h>
#include <phonon/backendcapabilities.h>
#include <phonon/effect.h>
#include <phonon/effectwidget.h>
#include <phonon/mediaobject.h>
#include <phonon/path.h>
#include <phonon/videowidget.h>

#include <kaboutdata.h>
#include <kdebug.h>
#include <kfiledialog.h>
#include <kapplication.h>
#include <kcmdlineargs.h>
#include <kicon.h>
#include <kurl.h>

#include <cstdlib>

using Phonon::MediaObject;
using Phonon::MediaSource;
using Phonon::AudioOutput;
using Phonon::VideoWidget;
using Phonon::MediaControls;
using Phonon::Effect;
using Phonon::EffectWidget;

class MediaPlayer : public QMainWindow
{
    Q_OBJECT
    public:
        MediaPlayer();
        void setUrl(const KUrl &url);

    private Q_SLOTS:
        void stateChanged(Phonon::State newstate);
        void workaroundQtBug();
        void getNextUrl();
        void startupReady();
        void openEffectWidget();
        void toggleScaleMode(bool);
        void switchAspectRatio(int x);
        void setBrightness(int b);

    private:
        bool setNextSource();

        QWidget *m_settingsWidget;
        Phonon::MediaObject *m_media;
        Phonon::Path m_apath;
        Phonon::AudioOutput *m_aoutput;
        Phonon::Path m_vpath;
        Phonon::Effect *m_effect;
        Phonon::VideoWidget *m_vwidget;
        Phonon::MediaControls *m_controls;
        Phonon::EffectWidget *m_effectWidget;
        QAction *m_fullScreenAction;
};

MediaPlayer::MediaPlayer()
    : QMainWindow(0), m_effectWidget(0)
{
    QDockWidget *dock = new QDockWidget(this);
    dock->setAllowedAreas(Qt::BottomDockWidgetArea);

    m_settingsWidget = new QWidget(dock);
    dock->setWidget(m_settingsWidget);
    addDockWidget(Qt::BottomDockWidgetArea, dock);

    QVBoxLayout *layout = new QVBoxLayout(m_settingsWidget);

    m_vwidget = new VideoWidget(this);
    setCentralWidget(m_vwidget);

    m_fullScreenAction = new QAction(m_vwidget);
    m_fullScreenAction->setShortcut(Qt::Key_F);
    m_fullScreenAction->setCheckable(true);
    m_fullScreenAction->setChecked(false);
    this->addAction(m_fullScreenAction);
    connect(m_fullScreenAction, SIGNAL(toggled(bool)), m_vwidget, SLOT(setFullScreen(bool)));
    connect(m_fullScreenAction, SIGNAL(toggled(bool)), SLOT(workaroundQtBug()));

    m_aoutput = new AudioOutput(Phonon::VideoCategory, this);

    m_media = new MediaObject(this);
    connect(m_media, SIGNAL(finished()), SLOT(getNextUrl()));
    connect(m_media, SIGNAL(stateChanged(Phonon::State, Phonon::State)), SLOT(stateChanged(Phonon::State)));

    createPath(m_media, m_vwidget);
    m_apath = createPath(m_media, m_aoutput);

    m_controls = new MediaControls(m_settingsWidget);
    layout->addWidget(m_controls);
    m_controls->setMediaObject(m_media);
    m_controls->setAudioOutput(m_aoutput);
    m_controls->setMaximumHeight(28);

    /*
    QList<AudioEffectDescription> effectList = BackendCapabilities::availableAudioEffects();
    if (!effectList.isEmpty())
    {
        m_effect = new AudioEffect(BackendCapabilities::availableAudioEffects().first(), m_apath);
        m_apath->insertEffect(m_effect);
        QPushButton *button = new QPushButton(m_settingsWidget);
        layout->addWidget(button);
        button->setText("configure effect");
        connect(button, SIGNAL(clicked()), SLOT(openEffectWidget()));
    }
    */

    QSlider *slider = new QSlider(m_settingsWidget);
    layout->addWidget(slider);
    slider->setOrientation(Qt::Horizontal);
    slider->setRange(-100, 100);
    slider->setValue(static_cast<int>(m_vwidget->brightness() * 100));
    connect(slider, SIGNAL(valueChanged(int)), this, SLOT(setBrightness(int)));

    QCheckBox *scaleModeCheck = new QCheckBox(m_settingsWidget);
    layout->addWidget(scaleModeCheck);
    connect(scaleModeCheck, SIGNAL(toggled(bool)), SLOT(toggleScaleMode(bool)));

    QWidget *box = new QWidget(m_settingsWidget);
    layout->addWidget(box);

    QLabel *label = new QLabel("Aspect Ratio:", box);
    label->setAlignment(Qt::AlignRight);
    QComboBox *aspectRatioCombo = new QComboBox(box);
    QHBoxLayout *hbox = new QHBoxLayout(box);
    hbox->addWidget(label);
    hbox->addWidget(aspectRatioCombo);
    label->setBuddy(aspectRatioCombo);

    connect(aspectRatioCombo, SIGNAL(currentIndexChanged(int)), SLOT(switchAspectRatio(int)));
    aspectRatioCombo->addItem("auto");
    aspectRatioCombo->addItem("fit");
    aspectRatioCombo->addItem("4:3");
    aspectRatioCombo->addItem("16:9");

    this->resize(width(), height() + 240 - m_vwidget->height());

    QTimer::singleShot(0, this, SLOT(startupReady()));
}

void MediaPlayer::stateChanged(Phonon::State newstate)
{
    switch (newstate) {
    case Phonon::ErrorState:
    case Phonon::StoppedState:
        getNextUrl();
        break;
    default:
        break;
    }
}

void MediaPlayer::workaroundQtBug()
{
    kDebug();
    if (m_vwidget->actions().contains(m_fullScreenAction)) {
        m_vwidget->removeAction(m_fullScreenAction);
        this->addAction(m_fullScreenAction);
    } else {
        this->removeAction(m_fullScreenAction);
        m_vwidget->addAction(m_fullScreenAction);
    }
}

bool MediaPlayer::setNextSource()
{
    QWidget *extraWidget = new QWidget;
    QHBoxLayout *layout = new QHBoxLayout(extraWidget);
    layout->setMargin(0);
    layout->addStretch();
    QPushButton *dvdButton = new QPushButton(i18n("DVD"), extraWidget);
    dvdButton->setCheckable(true);
    dvdButton->setChecked(false);
    layout->addWidget(dvdButton);
    QPushButton *cdButton = new QPushButton(i18n("Audio CD"), extraWidget);
    cdButton->setCheckable(true);
    cdButton->setChecked(false);
    layout->addWidget(cdButton);
    const QString dummyString;
    const KUrl dummyUrl;
    KFileDialog dlg(dummyUrl, dummyString, 0, extraWidget);
    connect(dvdButton, SIGNAL(toggled(bool)), &dlg, SLOT(accept()));
    connect(cdButton, SIGNAL(toggled(bool)), &dlg, SLOT(accept()));
    dlg.setOperationMode(KFileDialog::Opening);
    dlg.setWindowTitle(i18n("Open"));
    dlg.setMode(KFile::File);
    dlg.exec();
    KUrl url = dlg.selectedUrl();

    if (dvdButton->isChecked()) {
        if (url.isLocalFile()) {
            m_media->setCurrentSource(MediaSource(Phonon::Dvd, url.path()));
        } else {
            m_media->setCurrentSource(Phonon::Dvd);
        }
    } else if (cdButton->isChecked()) {
        m_media->setCurrentSource(Phonon::Cd);
    } else if (url.isValid()) {
        m_media->setCurrentSource(url);
    } else {
        QApplication::instance()->quit();
        return false;
    }
    return true;
}

void MediaPlayer::getNextUrl()
{
    static bool fileDialogAlreadyOpen = false;
    if (fileDialogAlreadyOpen) {
        return;
    }
    fileDialogAlreadyOpen = true;
    if (!setNextSource()) {
        return;
    }
    m_media->play();
    fileDialogAlreadyOpen = false;
}

void MediaPlayer::startupReady()
{
    if (m_media->currentSource().type() == MediaSource::Invalid) {
        if (!setNextSource()) {
            return;
        }
    }
    m_media->play();
}

void MediaPlayer::setBrightness(int b)
{
    m_vwidget->setBrightness(b * 0.01);
}

void MediaPlayer::switchAspectRatio(int x)
{
    m_vwidget->setAspectRatio(static_cast<VideoWidget::AspectRatio>(x));
}

void MediaPlayer::toggleScaleMode(bool mode)
{
    if (mode) {
        m_vwidget->setScaleMode(VideoWidget::ScaleAndCrop);
    } else {
        m_vwidget->setScaleMode(VideoWidget::FitInView);
    }
}

void MediaPlayer::openEffectWidget()
{
    if (!m_effectWidget)
        m_effectWidget = new EffectWidget(m_effect);
    m_effectWidget->show();
    m_effectWidget->raise();
}

void MediaPlayer::setUrl(const KUrl &url)
{
    m_media->setCurrentSource(url);
    //m_vwidget->setVisible(m_media->hasVideo());
}

int main(int argc, char ** argv)
{
    KAboutData about("phononmediaplayer", 0, ki18n("Phonon Media Player"),
            "0.1", ki18n("Media Player"),
            KAboutData::License_GPL);
    about.addAuthor(ki18n("Matthias Kretz"), KLocalizedString(), "kretz@kde.org");

    KCmdLineArgs::init(argc, argv, &about);
    KCmdLineOptions options;
    options.add("+[url]", ki18n("File to play"));
    KCmdLineArgs::addCmdLineOptions( options );

    KApplication app;
    MediaPlayer foo;
    foo.setWindowIcon(KIcon("phonon"));
    foo.show();

    KCmdLineArgs *args = KCmdLineArgs::parsedArgs();
    if (args->count() == 1) {
        KUrl url = args->url(0);
        if (url.isValid()) {
            foo.setUrl(url);
        }
    }
    args->clear();
    return app.exec();
}

#include "mediaplayer.moc"
#include "mediacontrols.cpp"
#include "moc_mediacontrols.cpp"
<|endoftext|>


<commit_before>// ConsoleApp.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"
#include <debug.h>
#include <file.h>
#include <input.h>
#include <sound.h>
#include <exceptions.h>
#include <network.h>
#include <iostream>

int main()
{
	_CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF);
	test::debug::enableDebugOutput();
	test::debug::enableFileOutput(L"log" ".txt");

	try {
		test::file::initWithFileSystem(L".");
		//ASSERT(0);

		test::network::initialize();
		test::network::finalize();

		test::input::DInput di(nullptr);

		::LoadLibrary(L"notfound.dll");
		DWORD code = ::GetLastError();
		throw test::error::DXError("DXError test", D3D11_ERROR_FILE_NOT_FOUND);
		throw test::error::Win32Error("err test", code);
	}
	catch (std::exception &e) {
		test::debug::writeLine(e.what());
		puts(e.what());
	}

	{
		test::sound::XAudio2 sound;
		sound.loadSoundEffect("testwav", L"/C:/Windows/Media/chimes.wav");
		sound.playSoundEffect("testwav");
	}

	test::debug::shutdownDebugOutput();

    return 0;
}
<commit_msg>Test: play multi se simultaneously<commit_after>// ConsoleApp.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"
#include <debug.h>
#include <file.h>
#include <input.h>
#include <sound.h>
#include <exceptions.h>
#include <network.h>
#include <iostream>

int main()
{
	_CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF);
	test::debug::enableDebugOutput();
	test::debug::enableFileOutput(L"log" ".txt");

	try {
		test::file::initWithFileSystem(L".");
		//ASSERT(0);

		test::network::initialize();
		test::network::finalize();

		test::input::DInput di(nullptr);

		::LoadLibrary(L"notfound.dll");
		DWORD code = ::GetLastError();
		throw test::error::DXError("DXError test", D3D11_ERROR_FILE_NOT_FOUND);
		throw test::error::Win32Error("err test", code);
	}
	catch (std::exception &e) {
		test::debug::writeLine(e.what());
		puts(e.what());
	}

	{
		test::sound::XAudio2 sound;
		sound.loadSoundEffect("testwav", L"/C:/Windows/Media/chimes.wav");
		for (int i = 0; i < 8; i++) {
			sound.playSoundEffect("testwav");
			Sleep(500);
		}
	}

	test::debug::shutdownDebugOutput();

    return 0;
}
<|endoftext|>


<commit_before>// TODO: Implement all creation functions (*) and ensure that they take constructor args
#pragma once

#include <stack>
#include <string>
#include <tuple>
#include <list>
#include <forward_list>

#include <boost/variant.hpp>

#include <btBulletDynamicsCommon.h>
// #include <dcollide.h>

#include "es/storage.hpp"
#include "Graphics.hpp"
#include "MathFuncs.hpp"
#include "VoxelWorld.hpp"
#include "PreparedShaders.hpp"
#include "TriplanarGradientMap.hpp"
#include "BasicRenderer.hpp"
#include "TransformHelper.hpp"
#include "Actor.hpp"
#include "SkeletalAnim.hpp"
#include "BasicModel.hpp"
#include "AnimatedModel.hpp"
#include "TransformHelper.hpp"
#include "Prop.hpp"
#include "Scenery.hpp"
#include "Body.hpp"
#include "Shape.hpp"
#include "Component.hpp"
#include "GlobalComponents.hpp"
// #include "IntrusiveBase.hpp"

#include <standalone/brigand.hpp>
#include <lemon/smart_graph.h>
#include <lemon/list_graph.h>
#include <lemon/lgf_writer.h>

namespace noob
{
	typedef noob::component<std::unique_ptr<noob::body>> bodies_holder;

	class stage
	{
		public:
			stage() : show_origin(true), view_mat(noob::identity_mat4()), projection_mat(noob::identity_mat4()), basic_lights( { noob::vec4(0.0, 1.0, 0.0, 0.3), noob::vec4(1.0, 0.0, 0.0, 0.3) } ), bodies_mapping(draw_graph), basic_models_mapping(draw_graph), shaders_mapping(draw_graph) {}

			~stage();

			// This one must be called by the application. It really sucks but that's because the graphics API is (currently) static. This may well change soon enough.
			void init();

			// This one provides a way to bring everything back to scratch
			void tear_down();

			// Call those every frame or so.
			void update(double dt);
			// TODO: Implement
			void draw(float window_width, float window_height) const;

			// Creates physics body. Those get made lots.
			noob::bodies_holder::handle body(const noob::body_type, const noob::shapes_holder::handle, float mass, const noob::vec3& pos, const noob::versor& orient = noob::versor(0.0, 0.0, 0.0, 1.0), bool ccd = false);

			noob::bodies_holder bodies;

			// Functions to create commonly-used configurations:
			void actor(const noob::bodies_holder::handle, const noob::animated_models_holder::handle, const noob::shaders_holder::handle);

			void actor(const noob::bodies_holder::handle, const noob::globals::scaled_model&, const noob::shaders_holder::handle);

			// void actor(const noob::shapes_holder::handle, const noob::vec3& pos, const noob::vec3& orient, const noob::vec3& scale, const noob::shaders_holder::handle);

			// Scenery is a non-movable item that uses indexed triangle meshes as input.
			void scenery(const noob::basic_mesh&, const noob::vec3& pos, const noob::versor& orient, const noob::shaders_holder::handle, const std::string& name);

			void set_basic_light(unsigned int i, const noob::vec4& light);

			noob::vec4 get_basic_light(unsigned int i) const;

			void write_graph(const std::string& filename) const;

			bool show_origin;

			noob::mat4 view_mat, projection_mat;

			noob::prepared_shaders renderer;

		protected:
			const int NUM_RESERVED_NODES = 12000;
			const int NUM_RESERVED_ARCS = 12000;

			std::array<noob::vec4, 2> basic_lights;

			btBroadphaseInterface* broadphase;
			btDefaultCollisionConfiguration* collision_configuration;
			btCollisionDispatcher* collision_dispatcher;
			btSequentialImpulseConstraintSolver* solver;
			btDiscreteDynamicsWorld* dynamics_world;

			lemon::ListDigraph draw_graph;
			lemon::ListDigraph::NodeMap<size_t> bodies_mapping;
			lemon::ListDigraph::NodeMap<size_t> basic_models_mapping;
			lemon::ListDigraph::NodeMap<size_t> shaders_mapping;
			lemon::ListDigraph::Node root_node;

			std::unordered_map<size_t, noob::shapes_holder::handle> bodies_to_shapes;
			std::map<size_t, lemon::ListDigraph::Node> bodies_to_nodes;
			std::map<size_t, lemon::ListDigraph::Node> basic_models_to_nodes;
			std::map<size_t, lemon::ListDigraph::Node> shaders_to_nodes;

	};
}
<commit_msg>Tweaks<commit_after>// TODO: Implement all creation functions (*) and ensure that they take constructor args
#pragma once

#include <stack>
#include <string>
#include <tuple>
#include <list>
#include <forward_list>

#include <boost/variant.hpp>

#include <btBulletDynamicsCommon.h>
// #include <dcollide.h>

#include "es/storage.hpp"
#include "Graphics.hpp"
#include "MathFuncs.hpp"
#include "VoxelWorld.hpp"
#include "PreparedShaders.hpp"
#include "TriplanarGradientMap.hpp"
#include "BasicRenderer.hpp"
#include "TransformHelper.hpp"
#include "Actor.hpp"
#include "SkeletalAnim.hpp"
#include "BasicModel.hpp"
#include "AnimatedModel.hpp"
#include "TransformHelper.hpp"
#include "Prop.hpp"
#include "Scenery.hpp"
#include "Body.hpp"
#include "Shape.hpp"
#include "Component.hpp"
#include "GlobalComponents.hpp"
// #include "IntrusiveBase.hpp"

#include <standalone/brigand.hpp>
#include <lemon/smart_graph.h>
#include <lemon/list_graph.h>
#include <lemon/lgf_writer.h>

namespace noob
{
	typedef noob::component<std::unique_ptr<noob::body>> bodies_holder;

	class stage
	{
		public:
			stage() : show_origin(true), view_mat(noob::identity_mat4()), projection_mat(noob::identity_mat4()), basic_lights( { noob::vec4(0.0, 1.0, 0.0, 0.1), noob::vec4(1.0, 0.0, 0.0, 0.1) } ), bodies_mapping(draw_graph), basic_models_mapping(draw_graph), shaders_mapping(draw_graph) {}

			~stage();

			// This one must be called by the application. It really sucks but that's because the graphics API is (currently) static. This may well change soon enough.
			void init();

			// This one provides a way to bring everything back to scratch
			void tear_down();

			// Call those every frame or so.
			void update(double dt);
			// TODO: Implement
			void draw(float window_width, float window_height) const;

			// Creates physics body. Those get made lots.
			noob::bodies_holder::handle body(const noob::body_type, const noob::shapes_holder::handle, float mass, const noob::vec3& pos, const noob::versor& orient = noob::versor(0.0, 0.0, 0.0, 1.0), bool ccd = false);

			noob::bodies_holder bodies;

			// Functions to create commonly-used configurations:
			void actor(const noob::bodies_holder::handle, const noob::animated_models_holder::handle, const noob::shaders_holder::handle);

			void actor(const noob::bodies_holder::handle, const noob::globals::scaled_model&, const noob::shaders_holder::handle);

			// void actor(const noob::shapes_holder::handle, const noob::vec3& pos, const noob::vec3& orient, const noob::vec3& scale, const noob::shaders_holder::handle);

			// Scenery is a non-movable item that uses indexed triangle meshes as input.
			void scenery(const noob::basic_mesh&, const noob::vec3& pos, const noob::versor& orient, const noob::shaders_holder::handle, const std::string& name);

			void set_basic_light(unsigned int i, const noob::vec4& light);

			noob::vec4 get_basic_light(unsigned int i) const;

			void write_graph(const std::string& filename) const;

			bool show_origin;

			noob::mat4 view_mat, projection_mat;

			noob::prepared_shaders renderer;

		protected:
			const int NUM_RESERVED_NODES = 12000;
			const int NUM_RESERVED_ARCS = 12000;

			std::array<noob::vec4, 2> basic_lights;

			btBroadphaseInterface* broadphase;
			btDefaultCollisionConfiguration* collision_configuration;
			btCollisionDispatcher* collision_dispatcher;
			btSequentialImpulseConstraintSolver* solver;
			btDiscreteDynamicsWorld* dynamics_world;

			lemon::ListDigraph draw_graph;
			lemon::ListDigraph::NodeMap<size_t> bodies_mapping;
			lemon::ListDigraph::NodeMap<size_t> basic_models_mapping;
			lemon::ListDigraph::NodeMap<size_t> shaders_mapping;
			lemon::ListDigraph::Node root_node;

			std::unordered_map<size_t, noob::shapes_holder::handle> bodies_to_shapes;
			std::map<size_t, lemon::ListDigraph::Node> bodies_to_nodes;
			std::map<size_t, lemon::ListDigraph::Node> basic_models_to_nodes;
			std::map<size_t, lemon::ListDigraph::Node> shaders_to_nodes;

	};
}
<|endoftext|>


<commit_before>/*
 Copyright (c) 2013, Trail of Bits
 All rights reserved.

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

 Redistributions of source code must retain the above copyright notice, this
 list of conditions and the following disclaimer.

 Redistributions in binary form must reproduce the above copyright notice, this
 list of conditions and the following disclaimer in the documentation and/or
 other materials provided with the distribution.

 Neither the name of the {organization} nor the names of its
 contributors may be used to endorse or promote products derived from
 this software without specific prior written permission.

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

#include <iostream>

#include <llvm/IR/IntrinsicInst.h>
#include <llvm/IR/Intrinsics.h>
#include <llvm/Support/CodeGen.h>

#include "mcsema/Arch/X86/Util.h"
#include "mcsema/BC/Util.h"
#include "mcsema/CFG/Externals.h"
#include "mcsema/cfgToLLVM/TransExcn.h"

// check if addr falls into a data section, and is at least minAddr.
// the minAddr check exists for times when we are not sure if an address
// is a data reference or an immediate value; in some cases data is mapped
// at 0x0 and determining this could be tricky

bool addrIsInData(VA addr, NativeModulePtr m, VA &base, VA minAddr = 0x0) {
  // sanity check:
  // assume no data references before minAddr.
  if (addr < minAddr) {
    return false;
  }

  auto &sections = m->getData();
  if (sections.empty()) {
    std::cerr << __FUNCTION__ << ": WARNING: no data sections!" << std::endl;
    return false;

  }
  for (auto &curSec : sections) {
    VA low = curSec.getBase();
    VA high = low + curSec.getSize();

    if (addr >= low && addr < high) {
      base = low;
      return true;
    }
  }

  return false;
}

// Compute a Value from a complex address expression
// such as [0x123456+eax*4]
// If the expression references global data, use
// that in the computation instead of assuming values
// are opaque immediates
namespace x86 {
llvm::Value *getAddrFromExpr(llvm::BasicBlock *b, NativeModulePtr mod,
                             const llvm::MCOperand &Obase,
                             const llvm::MCOperand &Oscale,
                             const llvm::MCOperand &Oindex, const int64_t Odisp,
                             const llvm::MCOperand &Oseg, bool dataOffset) {
  TASSERT(Obase.isReg(), "");
  TASSERT(Oscale.isImm(), "");
  TASSERT(Oindex.isReg(), "");
  TASSERT(Oseg.isReg(), "");

  unsigned baseReg = Obase.getReg();
  int64_t disp = Odisp;

  //first, we should ask, is disp an absolute reference to
  //some global symbol in the original source module?
  //if it is, we can replace its value with that of a pointer
  //to global data
  //HANDY HEURISTIC HACK
  //if the base register is the stack pointer or the frame
  //pointer, then skip this part
  llvm::Value *d = nullptr;
  auto iTy = llvm::IntegerType::getInt32Ty(b->getContext());

  if (dataOffset
      || (mod && disp && baseReg != llvm::X86::EBP &&
          baseReg != llvm::X86::ESP)) {
    auto int_val = getGlobalFromOriginalAddr<32>(disp, mod,
                                                 dataOffset ? 0 : 0x1000, b);
    d = int_val;
  } else {
    //there is no disp value, or its relative to esp/ebp in which case
    //we might not want to do anything
  }

  if (nullptr == d) {
    //create a constant integer out of the raw displacement
    //we were unable to assign the displacement to an address
    d = llvm::ConstantInt::getSigned(iTy, disp);
  }

  llvm::Value *rVal = nullptr;

  //read the base register (if given)
  if (baseReg != llvm::X86::NoRegister) {
    rVal = R_READ<32>(b, baseReg);
  } else {
    //if the base is not present, just use 0
    rVal = CONST_V<32>(b, 0);
  }

  llvm::Value *dispComp = nullptr;
  dispComp = llvm::BinaryOperator::Create(llvm::Instruction::Add, rVal, d, "",
                                          b);

  //add the index amount, if present
  if (Oindex.getReg() != llvm::X86::NoRegister) {
    auto index = R_READ<32>(b, Oindex.getReg());

    int64_t scaleAmt = Oscale.getImm();
    if (scaleAmt > 1) {
      index = llvm::BinaryOperator::CreateMul(index, CONST_V<32>(b, scaleAmt),
                                              "", b);
    }

    dispComp = llvm::BinaryOperator::CreateAdd(dispComp, index, "", b);
  }

  //convert the resulting integer into a pointer type
  auto piTy = llvm::Type::getInt32PtrTy(b->getContext());
  return new llvm::IntToPtrInst(dispComp, piTy, "", b);
}
}

llvm::Value *getAddrFromExpr(llvm::BasicBlock *b, NativeModulePtr mod,
                             const llvm::MCInst &inst, NativeInstPtr ip,
                             uint32_t which) {
  const auto &base = inst.getOperand(which + 0);
  const auto &scale = inst.getOperand(which + 1);
  const auto &index = inst.getOperand(which + 2);
  const auto &disp = inst.getOperand(which + 3);
  const auto &seg = inst.getOperand(which + 4);

  TASSERT(base.isReg(), "");
  TASSERT(scale.isImm(), "");
  TASSERT(index.isReg(), "");
  TASSERT(disp.isImm(), "");
  TASSERT(seg.isReg(), "");

  // determine if this instruction is using a memory reference
  // or if the displacement should be used at face value
  bool has_ref = ip->has_reference(NativeInst::MEMRef);
  int64_t real_disp =
      has_ref ? ip->get_reference(NativeInst::MEMRef) : disp.getImm();
  auto M = b->getParent()->getParent();

  if (ArchPointerSize(M) == Pointer32) {

    return x86::getAddrFromExpr(b, mod, base, scale, index, real_disp, seg,
                                has_ref);

  } else {
    return x86_64::getAddrFromExpr(b, mod, base, scale, index, real_disp, seg,
                                   has_ref);
  }

}

llvm::Value *MEM_AS_DATA_REF(llvm::BasicBlock *B, NativeModulePtr natM,
                             const llvm::MCInst &inst, NativeInstPtr ip,
                             uint32_t which) {
  if (false == ip->has_mem_reference) {
    throw TErr(__LINE__, __FILE__,
               "Want to use MEM as data ref but have no MEM reference");
  }
  return getAddrFromExpr(B, natM, inst, ip, which);
}

llvm::Instruction *callMemcpy(llvm::BasicBlock *B, llvm::Value *dest,
                              llvm::Value *src, uint32_t size, uint32_t align,
                              bool isVolatile) {
  auto copySize = CONST_V<32>(B, size);
  // ALIGN: 4 byte alignment, i think
  auto alignSize = CONST_V<32>(B, align);
  // VOLATILE: false
  auto vIsVolatile = CONST_V<1>(B, isVolatile);

  llvm::Type *Tys[] = {dest->getType(), src->getType(), copySize->getType()};

  auto M = B->getParent()->getParent();
  auto doMemCpy = llvm::Intrinsic::getDeclaration(
      M, llvm::Intrinsic::memcpy, Tys);

  llvm::Value *callArgs[] = {dest,  // DST
      src,  // SRC
      copySize,  // SIZE
      alignSize,  // ALIGN
      vIsVolatile  // VOLATILE
      };

  // actually call llvm.memcpy
  return llvm::CallInst::Create(doMemCpy, callArgs, "", B);
}

namespace x86_64 {

llvm::Value *getAddrFromExpr(llvm::BasicBlock *b, NativeModulePtr mod,
                       const llvm::MCOperand &Obase, const llvm::MCOperand &Oscale,
                       const llvm::MCOperand &Oindex, const int64_t Odisp,
                       const llvm::MCOperand &Oseg, bool dataOffset) {
  TASSERT(Obase.isReg(), "");
  TASSERT(Oscale.isImm(), "");
  TASSERT(Oindex.isReg(), "");
  TASSERT(Oseg.isReg(), "");

  unsigned baseReg = Obase.getReg();
  int64_t disp = Odisp;

  // specific function for 64 bit
  llvm::Value *d = nullptr;
  auto iTy = llvm::IntegerType::getInt64Ty(b->getContext());

  if (dataOffset
      || (mod && disp && baseReg != llvm::X86::RBP && baseReg != llvm::X86::RSP)) {
    d = getGlobalFromOriginalAddr<64>(disp, mod,
                                                   dataOffset ? 0 : 0x1000, b);
  } else {

    //there is no disp value, or its relative to esp/ebp in which case
    //we might not want to do anything
  }

  if (!d) {
    //create a constant integer out of the raw displacement
    //we were unable to assign the displacement to an address
    d = llvm::ConstantInt::getSigned(iTy, disp);
  }

  llvm::Value *rVal = nullptr;

  //read the base register (if given)
  if (baseReg != llvm::X86::NoRegister && baseReg != llvm::X86::RIP) {
    rVal = R_READ<64>(b, baseReg);
  } else {
    //if the base is not present, just use 0
    rVal = CONST_V<64>(b, 0);
  }

  llvm::Value *dispComp = nullptr;
  dispComp = llvm::BinaryOperator::Create(llvm::Instruction::Add, rVal, d, "", b);

  //add the index amount, if present
  if (Oindex.getReg() != llvm::X86::NoRegister) {
    auto index = R_READ<64>(b, Oindex.getReg());

    int64_t scaleAmt = Oscale.getImm();
    if (scaleAmt > 1) {
      index = llvm::BinaryOperator::CreateMul(index, CONST_V<64>(b, scaleAmt), "", b);
    }

    dispComp = llvm::BinaryOperator::CreateAdd(dispComp, index, "", b);

  }

  //convert the resulting integer into a pointer type
  auto piTy = llvm::Type::getInt64PtrTy(b->getContext());
  return new llvm::IntToPtrInst(dispComp, piTy, "", b);
}

}  // namespace x86_64
<commit_msg>Fix MEM_REFERENCE to read externals (#198)<commit_after>/*
 Copyright (c) 2013, Trail of Bits
 All rights reserved.

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

 Redistributions of source code must retain the above copyright notice, this
 list of conditions and the following disclaimer.

 Redistributions in binary form must reproduce the above copyright notice, this
 list of conditions and the following disclaimer in the documentation and/or
 other materials provided with the distribution.

 Neither the name of the {organization} nor the names of its
 contributors may be used to endorse or promote products derived from
 this software without specific prior written permission.

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

#include <iostream>

#include <llvm/IR/IntrinsicInst.h>
#include <llvm/IR/Intrinsics.h>
#include <llvm/Support/CodeGen.h>

#include "mcsema/Arch/X86/Util.h"
#include "mcsema/BC/Util.h"
#include "mcsema/CFG/Externals.h"
#include "mcsema/cfgToLLVM/TransExcn.h"

// check if addr falls into a data section, and is at least minAddr.
// the minAddr check exists for times when we are not sure if an address
// is a data reference or an immediate value; in some cases data is mapped
// at 0x0 and determining this could be tricky

bool addrIsInData(VA addr, NativeModulePtr m, VA &base, VA minAddr = 0x0) {
  // sanity check:
  // assume no data references before minAddr.
  if (addr < minAddr) {
    return false;
  }

  auto &sections = m->getData();
  if (sections.empty()) {
    std::cerr << __FUNCTION__ << ": WARNING: no data sections!" << std::endl;
    return false;

  }
  for (auto &curSec : sections) {
    VA low = curSec.getBase();
    VA high = low + curSec.getSize();

    if (addr >= low && addr < high) {
      base = low;
      return true;
    }
  }

  return false;
}

// Compute a Value from a complex address expression
// such as [0x123456+eax*4]
// If the expression references global data, use
// that in the computation instead of assuming values
// are opaque immediates
namespace x86 {
llvm::Value *getAddrFromExpr(llvm::BasicBlock *b, NativeModulePtr mod,
                             const llvm::MCOperand &Obase,
                             const llvm::MCOperand &Oscale,
                             const llvm::MCOperand &Oindex, const int64_t Odisp,
                             const llvm::MCOperand &Oseg, bool dataOffset) {
  TASSERT(Obase.isReg(), "");
  TASSERT(Oscale.isImm(), "");
  TASSERT(Oindex.isReg(), "");
  TASSERT(Oseg.isReg(), "");

  unsigned baseReg = Obase.getReg();
  int64_t disp = Odisp;

  //first, we should ask, is disp an absolute reference to
  //some global symbol in the original source module?
  //if it is, we can replace its value with that of a pointer
  //to global data
  //HANDY HEURISTIC HACK
  //if the base register is the stack pointer or the frame
  //pointer, then skip this part
  llvm::Value *d = nullptr;
  auto iTy = llvm::IntegerType::getInt32Ty(b->getContext());

  if (dataOffset
      || (mod && disp && baseReg != llvm::X86::EBP &&
          baseReg != llvm::X86::ESP)) {
    auto int_val = getGlobalFromOriginalAddr<32>(disp, mod,
                                                 dataOffset ? 0 : 0x1000, b);
    d = int_val;
  } else {
    //there is no disp value, or its relative to esp/ebp in which case
    //we might not want to do anything
  }

  if (nullptr == d) {
    //create a constant integer out of the raw displacement
    //we were unable to assign the displacement to an address
    d = llvm::ConstantInt::getSigned(iTy, disp);
  }

  llvm::Value *rVal = nullptr;

  //read the base register (if given)
  if (baseReg != llvm::X86::NoRegister) {
    rVal = R_READ<32>(b, baseReg);
  } else {
    //if the base is not present, just use 0
    rVal = CONST_V<32>(b, 0);
  }

  llvm::Value *dispComp = nullptr;
  dispComp = llvm::BinaryOperator::Create(llvm::Instruction::Add, rVal, d, "",
                                          b);

  //add the index amount, if present
  if (Oindex.getReg() != llvm::X86::NoRegister) {
    auto index = R_READ<32>(b, Oindex.getReg());

    int64_t scaleAmt = Oscale.getImm();
    if (scaleAmt > 1) {
      index = llvm::BinaryOperator::CreateMul(index, CONST_V<32>(b, scaleAmt),
                                              "", b);
    }

    dispComp = llvm::BinaryOperator::CreateAdd(dispComp, index, "", b);
  }

  //convert the resulting integer into a pointer type
  auto piTy = llvm::Type::getInt32PtrTy(b->getContext());
  return new llvm::IntToPtrInst(dispComp, piTy, "", b);
}
}

llvm::Value *getAddrFromExpr(llvm::BasicBlock *b, NativeModulePtr mod,
                             const llvm::MCInst &inst, NativeInstPtr ip,
                             uint32_t which) {
  const auto &base = inst.getOperand(which + 0);
  const auto &scale = inst.getOperand(which + 1);
  const auto &index = inst.getOperand(which + 2);
  const auto &disp = inst.getOperand(which + 3);
  const auto &seg = inst.getOperand(which + 4);

  TASSERT(base.isReg(), "");
  TASSERT(scale.isImm(), "");
  TASSERT(index.isReg(), "");
  TASSERT(disp.isImm(), "");
  TASSERT(seg.isReg(), "");

  // determine if this instruction is using a memory reference
  // or if the displacement should be used at face value
  bool has_ref = ip->has_reference(NativeInst::MEMRef);
  int64_t real_disp =
      has_ref ? ip->get_reference(NativeInst::MEMRef) : disp.getImm();
  auto M = b->getParent()->getParent();

  if (ArchPointerSize(M) == Pointer32) {

    return x86::getAddrFromExpr(b, mod, base, scale, index, real_disp, seg,
                                has_ref);

  } else {
    return x86_64::getAddrFromExpr(b, mod, base, scale, index, real_disp, seg,
                                   has_ref);
  }

}

llvm::Value *MEM_AS_DATA_REF(llvm::BasicBlock *B, NativeModulePtr natM,
                             const llvm::MCInst &inst, NativeInstPtr ip,
                             uint32_t which) {
  if (ip->has_external_ref()) {
    auto F = B->getParent();
    llvm::Value* addrInt = nullptr;
    llvm::PointerType* piTy = nullptr;
    auto ptrsize = ArchPointerSize(M);
    if (Pointer32 == ptrsize) {
      addrInt = getValueForExternal<32>(F->getParent(), ip, B);
      TASSERT(addrInt != nullptr, "Could not get external data reference");
      piTy = llvm::Type::getInt32PtrTy(B->getContext());
    } else if(Pointer64 == ptrsize) {
      addrInt = getValueForExternal<64>(F->getParent(), ip, B);
      TASSERT(addrInt != nullptr, "Could not get external data reference");
      piTy = llvm::Type::getInt64PtrTy(B->getContext());
    } else {

      throw TErr(__LINE__, __FILE__,
                 "Unknown pointer size used to reference memory");
      // not needed but here just in case
      return nullptr;
    }

    return new llvm::IntToPtrInst(addrInt, piTy, "", B);
  }

  if (false == ip->has_mem_reference) {
    throw TErr(__LINE__, __FILE__,
               "Want to use MEM as data ref but have no MEM reference");
    // not needed but here just in case
    return nullptr;
  }

  return getAddrFromExpr(B, natM, inst, ip, which);
}

llvm::Instruction *callMemcpy(llvm::BasicBlock *B, llvm::Value *dest,
                              llvm::Value *src, uint32_t size, uint32_t align,
                              bool isVolatile) {
  auto copySize = CONST_V<32>(B, size);
  // ALIGN: 4 byte alignment, i think
  auto alignSize = CONST_V<32>(B, align);
  // VOLATILE: false
  auto vIsVolatile = CONST_V<1>(B, isVolatile);

  llvm::Type *Tys[] = {dest->getType(), src->getType(), copySize->getType()};

  auto M = B->getParent()->getParent();
  auto doMemCpy = llvm::Intrinsic::getDeclaration(
      M, llvm::Intrinsic::memcpy, Tys);

  llvm::Value *callArgs[] = {dest,  // DST
      src,  // SRC
      copySize,  // SIZE
      alignSize,  // ALIGN
      vIsVolatile  // VOLATILE
      };

  // actually call llvm.memcpy
  return llvm::CallInst::Create(doMemCpy, callArgs, "", B);
}

namespace x86_64 {

llvm::Value *getAddrFromExpr(llvm::BasicBlock *b, NativeModulePtr mod,
                       const llvm::MCOperand &Obase, const llvm::MCOperand &Oscale,
                       const llvm::MCOperand &Oindex, const int64_t Odisp,
                       const llvm::MCOperand &Oseg, bool dataOffset) {
  TASSERT(Obase.isReg(), "");
  TASSERT(Oscale.isImm(), "");
  TASSERT(Oindex.isReg(), "");
  TASSERT(Oseg.isReg(), "");

  unsigned baseReg = Obase.getReg();
  int64_t disp = Odisp;

  // specific function for 64 bit
  llvm::Value *d = nullptr;
  auto iTy = llvm::IntegerType::getInt64Ty(b->getContext());

  if (dataOffset
      || (mod && disp && baseReg != llvm::X86::RBP && baseReg != llvm::X86::RSP)) {
    d = getGlobalFromOriginalAddr<64>(disp, mod,
                                                   dataOffset ? 0 : 0x1000, b);
  } else {

    //there is no disp value, or its relative to esp/ebp in which case
    //we might not want to do anything
  }

  if (!d) {
    //create a constant integer out of the raw displacement
    //we were unable to assign the displacement to an address
    d = llvm::ConstantInt::getSigned(iTy, disp);
  }

  llvm::Value *rVal = nullptr;

  //read the base register (if given)
  if (baseReg != llvm::X86::NoRegister && baseReg != llvm::X86::RIP) {
    rVal = R_READ<64>(b, baseReg);
  } else {
    //if the base is not present, just use 0
    rVal = CONST_V<64>(b, 0);
  }

  llvm::Value *dispComp = nullptr;
  dispComp = llvm::BinaryOperator::Create(llvm::Instruction::Add, rVal, d, "", b);

  //add the index amount, if present
  if (Oindex.getReg() != llvm::X86::NoRegister) {
    auto index = R_READ<64>(b, Oindex.getReg());

    int64_t scaleAmt = Oscale.getImm();
    if (scaleAmt > 1) {
      index = llvm::BinaryOperator::CreateMul(index, CONST_V<64>(b, scaleAmt), "", b);
    }

    dispComp = llvm::BinaryOperator::CreateAdd(dispComp, index, "", b);

  }

  //convert the resulting integer into a pointer type
  auto piTy = llvm::Type::getInt64PtrTy(b->getContext());
  return new llvm::IntToPtrInst(dispComp, piTy, "", b);
}

}  // namespace x86_64
<|endoftext|>