<commit_before>#ifndef array_view_hh_INCLUDED
#define array_view_hh_INCLUDED

#include <vector>
#include <initializer_list>
#include <type_traits>

namespace Kakoune
{

// An ArrayView provides a typed, non owning view of a memory
// range with an interface similar to std::vector.
template<typename T>
class ArrayView
{
public:
    using size_t = std::size_t;

    constexpr ArrayView()
        : m_pointer(nullptr), m_size(0) {}

    constexpr ArrayView(T& oneval)
        : m_pointer(&oneval), m_size(1) {}

    constexpr ArrayView(T* pointer, size_t size)
        : m_pointer(pointer), m_size(size) {}

    constexpr ArrayView(T* begin, T* end)
        : m_pointer(begin), m_size(end - begin) {}

    template<size_t N>
    constexpr ArrayView(T(&array)[N]) : m_pointer(array), m_size(N) {}

    template<typename Iterator>
    constexpr ArrayView(const Iterator& begin, const Iterator& end)
        : m_pointer(&(*begin)), m_size(end - begin) {}

    template<typename Alloc, typename U>
    constexpr ArrayView(const std::vector<U, Alloc>& v)
        : m_pointer(&v[0]), m_size(v.size()) {}

    constexpr ArrayView(const std::initializer_list<T>& v)
        : m_pointer(v.begin()), m_size(v.size()) {}

    constexpr T* pointer() const { return m_pointer; }
    constexpr size_t size() const { return m_size; }
    constexpr T& operator[](size_t n) const { return *(m_pointer + n); }

    constexpr T* begin() const { return m_pointer; }
    constexpr T* end()   const { return m_pointer+m_size; }

    using reverse_iterator = std::reverse_iterator<T*>;
    constexpr reverse_iterator rbegin() const { return reverse_iterator(m_pointer+m_size); }
    constexpr reverse_iterator rend()   const { return reverse_iterator(m_pointer); }

    constexpr T& front() const { return *m_pointer; }
    constexpr T& back()  const { return *(m_pointer + m_size - 1); }

    constexpr bool empty() const { return m_size == 0; }

    constexpr ArrayView subrange(size_t first, size_t count) const
    {
        return ArrayView(m_pointer + first, count);
    }

private:
    T* m_pointer;
    size_t   m_size;
};

template<typename T>
using ConstArrayView = ArrayView<const T>;

}

#endif // array_view_hh_INCLUDED
<commit_msg>Small alignement change<commit_after>#ifndef array_view_hh_INCLUDED
#define array_view_hh_INCLUDED

#include <vector>
#include <initializer_list>
#include <type_traits>

namespace Kakoune
{

// An ArrayView provides a typed, non owning view of a memory
// range with an interface similar to std::vector.
template<typename T>
class ArrayView
{
public:
    using size_t = std::size_t;

    constexpr ArrayView()
        : m_pointer(nullptr), m_size(0) {}

    constexpr ArrayView(T& oneval)
        : m_pointer(&oneval), m_size(1) {}

    constexpr ArrayView(T* pointer, size_t size)
        : m_pointer(pointer), m_size(size) {}

    constexpr ArrayView(T* begin, T* end)
        : m_pointer(begin), m_size(end - begin) {}

    template<size_t N>
    constexpr ArrayView(T(&array)[N]) : m_pointer(array), m_size(N) {}

    template<typename Iterator>
    constexpr ArrayView(const Iterator& begin, const Iterator& end)
        : m_pointer(&(*begin)), m_size(end - begin) {}

    template<typename Alloc, typename U>
    constexpr ArrayView(const std::vector<U, Alloc>& v)
        : m_pointer(&v[0]), m_size(v.size()) {}

    constexpr ArrayView(const std::initializer_list<T>& v)
        : m_pointer(v.begin()), m_size(v.size()) {}

    constexpr T* pointer() const { return m_pointer; }
    constexpr size_t size() const { return m_size; }
    constexpr T& operator[](size_t n) const { return *(m_pointer + n); }

    constexpr T* begin() const { return m_pointer; }
    constexpr T* end()   const { return m_pointer+m_size; }

    using reverse_iterator = std::reverse_iterator<T*>;
    constexpr reverse_iterator rbegin() const { return reverse_iterator(m_pointer+m_size); }
    constexpr reverse_iterator rend()   const { return reverse_iterator(m_pointer); }

    constexpr T& front() const { return *m_pointer; }
    constexpr T& back()  const { return *(m_pointer + m_size - 1); }

    constexpr bool empty() const { return m_size == 0; }

    constexpr ArrayView subrange(size_t first, size_t count) const
    {
        return ArrayView(m_pointer + first, count);
    }

private:
    T* m_pointer;
    size_t m_size;
};

template<typename T>
using ConstArrayView = ArrayView<const T>;

}

#endif // array_view_hh_INCLUDED
<|endoftext|>


<commit_before>#include "src/block_sync.h"

#include <utility>
#include <vector>

#include "src/util.h"

namespace redsea {

const unsigned kBitmask16 = 0x000FFFF;
const unsigned kBitmask26 = 0x3FFFFFF;
const unsigned kBitmask28 = 0xFFFFFFF;

const eBlockNumber g_block_number_for_offset[5] =
    {BLOCK1, BLOCK2, BLOCK3, BLOCK3, BLOCK4};

// Section B.1.1: '-- calculated by the modulo-two addition of all the rows of
// the -- matrix for which the corresponding coefficient in the -- vector is 1.'
uint32_t MatrixMultiply(uint32_t vec, const std::vector<uint32_t>& matrix) {
  uint32_t result = 0;

  for (size_t k=0; k < matrix.size(); k++)
    if ((vec >> k) & 0x01)
      result ^= matrix[matrix.size() - 1 - k];

  return result;
}

// Section B.2.1: 'The calculation of the syndromes -- can easily be done by
// multiplying each word with the parity matrix H.'
uint32_t CalcSyndrome(uint32_t vec) {
  static const std::vector<uint32_t> parity_check_matrix({
      0x200, 0x100, 0x080, 0x040, 0x020, 0x010, 0x008, 0x004,
      0x002, 0x001, 0x2dc, 0x16e, 0x0b7, 0x287, 0x39f, 0x313,
      0x355, 0x376, 0x1bb, 0x201, 0x3dc,
      0x1ee, 0x0f7, 0x2a7, 0x38f, 0x31b
  });

  return MatrixMultiply(vec, parity_check_matrix);
}

eOffset nextOffsetFor(eOffset this_offset) {
  static const std::map<eOffset, eOffset> next_offset({
      {OFFSET_A, OFFSET_B}, {OFFSET_B, OFFSET_C},
      {OFFSET_C, OFFSET_D}, {OFFSET_C_PRIME, OFFSET_D},
      {OFFSET_D, OFFSET_A}, {OFFSET_INVALID, OFFSET_A}
  });
  return next_offset.at(this_offset);
}

// Precompute mapping of syndromes to error vectors

std::map<std::pair<uint16_t, eOffset>, uint32_t> MakeErrorLookupTable() {
  std::map<std::pair<uint16_t, eOffset>, uint32_t> result;

  const std::vector<uint16_t> offset_words =
      {0x0FC, 0x198, 0x168, 0x350, 0x1B4};

  for (eOffset offset : {OFFSET_A, OFFSET_B, OFFSET_C,
                         OFFSET_C_PRIME, OFFSET_D}) {
    // "...the error-correction system should be enabled, but should be
    // restricted by attempting to correct bursts of errors spanning one or two
    // bits."
    // Kopitz & Marks 1999: "RDS: The Radio Data System", p. 224
    for (uint32_t error_bits : {0x1, 0x3}) {
      for (int shift=0; shift < 26; shift++) {
        uint32_t error_vector = ((error_bits << shift) & kBitmask26);

        uint32_t syndrome = CalcSyndrome(error_vector ^ offset_words[offset]);
        result.insert({{syndrome, offset}, error_vector});
      }
    }
  }
  return result;
}

eOffset OffsetForSyndrome(uint16_t syndrome) {
  static const std::map<uint16_t, eOffset> offset_syndromes =
    {{0x3D8, OFFSET_A},  {0x3D4, OFFSET_B}, {0x25C, OFFSET_C},
     {0x3CC, OFFSET_C_PRIME}, {0x258, OFFSET_D}};

  if (offset_syndromes.count(syndrome) > 0)
    return offset_syndromes.at(syndrome);
  else
    return OFFSET_INVALID;
}

std::map<std::pair<uint16_t, eOffset>, uint32_t> kErrorLookup =
    MakeErrorLookupTable();

// Section B.2.2
uint32_t CorrectBurstErrors(uint32_t block, eOffset offset) {
  uint16_t syndrome = CalcSyndrome(block);
  uint32_t corrected_block = block;

  if (kErrorLookup.count({syndrome, offset}) > 0) {
    uint32_t err = kErrorLookup.at({syndrome, offset});
    corrected_block ^= err;
  }

  return corrected_block;
}

BlockStream::BlockStream(const Options& options) : bitcount_(0),
  prevbitcount_(0), left_to_read_(0), padded_block_(0), prevsync_(0),
  block_counter_(0), expected_offset_(OFFSET_A),
  received_offset_(OFFSET_INVALID), pi_(0x0000), is_in_sync_(false),
  block_has_errors_(50),
#ifdef HAVE_LIQUID
  subcarrier_(options),
#endif
  ascii_bits_(options.feed_thru),
  input_type_(options.input_type), is_eof_(false) {
}

int BlockStream::NextBit() {
  int result = 0;
#ifdef HAVE_LIQUID
  if (input_type_ == INPUT_MPX) {
    result = subcarrier_.NextBit();
    is_eof_ = subcarrier_.eof();
  }
#endif
  if (input_type_ == INPUT_ASCIIBITS) {
    result = ascii_bits_.NextBit();
    is_eof_ = ascii_bits_.eof();
  }

  return result;
}

// A block can't be decoded
void BlockStream::Uncorrectable() {
  block_has_errors_[block_counter_ % block_has_errors_.size()] = true;

  unsigned num_erroneous_blocks = 0;
  for (bool e : block_has_errors_) {
    if (e)
      num_erroneous_blocks++;
  }

  // Sync is lost when >45 out of last 50 blocks are erroneous (Section C.1.2)
  if (is_in_sync_ && num_erroneous_blocks > 45) {
    is_in_sync_ = false;
    for (size_t i=0; i < block_has_errors_.size(); i++)
      block_has_errors_[i] = false;
    pi_ = 0x0000;
  }
}

bool BlockStream::AcquireSync() {
  if (is_in_sync_)
    return true;

  // Try to find the repeating offset sequence
  if (received_offset_ != OFFSET_INVALID) {
    int dist = bitcount_ - prevbitcount_;

    if (dist % 26 == 0 && dist <= 156 &&
        (g_block_number_for_offset[prevsync_] + dist/26) % 4 ==
        g_block_number_for_offset[received_offset_]) {
      is_in_sync_ = true;
      expected_offset_ = received_offset_;
    } else {
      prevbitcount_ = bitcount_;
      prevsync_ = received_offset_;
    }
  }

  return is_in_sync_;
}

Group BlockStream::NextGroup() {
  Group group;

  while (!eof()) {
    // Compensate for clock slip corrections
    bitcount_ += 26 - left_to_read_;

    // Read from radio
    for (int i=0; i < (is_in_sync_ ? left_to_read_ : 1); i++, bitcount_++) {
      padded_block_ = (padded_block_ << 1) + NextBit();
    }

    left_to_read_ = 26;
    padded_block_ &= kBitmask28;

    uint32_t block = (padded_block_ >> 1) & kBitmask26;
    uint16_t message = block >> 10;

    received_offset_ = OffsetForSyndrome(CalcSyndrome(block));

    if (!AcquireSync())
      continue;

    block_counter_++;

    if (expected_offset_ == OFFSET_C && received_offset_ == OFFSET_C_PRIME)
      expected_offset_ = OFFSET_C_PRIME;

    block_has_errors_[block_counter_ % block_has_errors_.size()] = false;

    if (received_offset_ != expected_offset_) {
      block_has_errors_[block_counter_ % block_has_errors_.size()] = true;

      // Detect & correct clock slips (Section C.1.2)
      if (expected_offset_ == OFFSET_A && pi_ != 0x0000 &&
          ((padded_block_ >> 12) & kBitmask16) == pi_) {
        message = pi_;
        padded_block_ >>= 1;
        received_offset_ = OFFSET_A;
      } else if (expected_offset_ == OFFSET_A && pi_ != 0x0000 &&
          ((padded_block_ >> 10) & kBitmask16) == pi_) {
        message = pi_;
        padded_block_ = (padded_block_ << 1) + NextBit();
        received_offset_ = OFFSET_A;
        left_to_read_ = 25;
      } else {
        uint32_t corrected_block = CorrectBurstErrors(block, expected_offset_);
        if (corrected_block != block) {
          message = corrected_block >> 10;
          received_offset_ = expected_offset_;
        }
      }

      // Still no valid syndrome
      if (received_offset_ != expected_offset_)
        Uncorrectable();
    }

    // Error-free block received

    if (received_offset_ == expected_offset_) {
      if (expected_offset_ == OFFSET_C_PRIME)
        group.set_c_prime(message);
      else
        group.set(g_block_number_for_offset[expected_offset_], message);

      if (group.has_pi())
        pi_ = group.pi();
    }

    expected_offset_ = nextOffsetFor(expected_offset_);

    if (expected_offset_ == OFFSET_A) {
      break;
    }
  }

  return group;
}

bool BlockStream::eof() const {
  return is_eof_;
}

#ifdef DEBUG
float BlockStream::t() const {
  return subcarrier_.t();
}
#endif

}  // namespace redsea
<commit_msg>formatting<commit_after>#include "src/block_sync.h"

#include <utility>
#include <vector>

#include "src/util.h"

namespace redsea {

const unsigned kBitmask16 = 0x000FFFF;
const unsigned kBitmask26 = 0x3FFFFFF;
const unsigned kBitmask28 = 0xFFFFFFF;

const eBlockNumber g_block_number_for_offset[5] =
    {BLOCK1, BLOCK2, BLOCK3, BLOCK3, BLOCK4};

// Section B.1.1: '-- calculated by the modulo-two addition of all the rows of
// the -- matrix for which the corresponding coefficient in the -- vector is 1.'
uint32_t MatrixMultiply(uint32_t vec, const std::vector<uint32_t>& matrix) {
  uint32_t result = 0;

  for (size_t k=0; k < matrix.size(); k++)
    if ((vec >> k) & 0x01)
      result ^= matrix[matrix.size() - 1 - k];

  return result;
}

// Section B.2.1: 'The calculation of the syndromes -- can easily be done by
// multiplying each word with the parity matrix H.'
uint32_t CalcSyndrome(uint32_t vec) {
  static const std::vector<uint32_t> parity_check_matrix({
      0x200, 0x100, 0x080, 0x040, 0x020, 0x010, 0x008, 0x004,
      0x002, 0x001, 0x2dc, 0x16e, 0x0b7, 0x287, 0x39f, 0x313,
      0x355, 0x376, 0x1bb, 0x201, 0x3dc,
      0x1ee, 0x0f7, 0x2a7, 0x38f, 0x31b
  });

  return MatrixMultiply(vec, parity_check_matrix);
}

eOffset nextOffsetFor(eOffset this_offset) {
  static const std::map<eOffset, eOffset> next_offset({
      {OFFSET_A, OFFSET_B}, {OFFSET_B, OFFSET_C},
      {OFFSET_C, OFFSET_D}, {OFFSET_C_PRIME, OFFSET_D},
      {OFFSET_D, OFFSET_A}, {OFFSET_INVALID, OFFSET_A}
  });
  return next_offset.at(this_offset);
}

// Precompute mapping of syndromes to error vectors

std::map<std::pair<uint16_t, eOffset>, uint32_t> MakeErrorLookupTable() {
  std::map<std::pair<uint16_t, eOffset>, uint32_t> result;

  const std::vector<uint16_t> offset_words =
      {0x0FC, 0x198, 0x168, 0x350, 0x1B4};

  for (eOffset offset : {OFFSET_A, OFFSET_B, OFFSET_C,
                         OFFSET_C_PRIME, OFFSET_D}) {
    // "...the error-correction system should be enabled, but should be
    // restricted by attempting to correct bursts of errors spanning one or two
    // bits."
    // Kopitz & Marks 1999: "RDS: The Radio Data System", p. 224
    for (uint32_t error_bits : {0x1, 0x3}) {
      for (int shift=0; shift < 26; shift++) {
        uint32_t error_vector = ((error_bits << shift) & kBitmask26);

        uint32_t syndrome = CalcSyndrome(error_vector ^ offset_words[offset]);
        result.insert({{syndrome, offset}, error_vector});
      }
    }
  }
  return result;
}

eOffset OffsetForSyndrome(uint16_t syndrome) {
  static const std::map<uint16_t, eOffset> offset_syndromes =
    {{0x3D8, OFFSET_A},  {0x3D4, OFFSET_B}, {0x25C, OFFSET_C},
     {0x3CC, OFFSET_C_PRIME}, {0x258, OFFSET_D}};

  if (offset_syndromes.count(syndrome) > 0)
    return offset_syndromes.at(syndrome);
  else
    return OFFSET_INVALID;
}

std::map<std::pair<uint16_t, eOffset>, uint32_t> kErrorLookup =
    MakeErrorLookupTable();

// Section B.2.2
uint32_t CorrectBurstErrors(uint32_t block, eOffset offset) {
  uint16_t syndrome = CalcSyndrome(block);
  uint32_t corrected_block = block;

  if (kErrorLookup.count({syndrome, offset}) > 0) {
    uint32_t err = kErrorLookup.at({syndrome, offset});
    corrected_block ^= err;
  }

  return corrected_block;
}

BlockStream::BlockStream(const Options& options) : bitcount_(0),
  prevbitcount_(0), left_to_read_(0), padded_block_(0), prevsync_(0),
  block_counter_(0), expected_offset_(OFFSET_A),
  received_offset_(OFFSET_INVALID), pi_(0x0000), is_in_sync_(false),
  block_has_errors_(50),
#ifdef HAVE_LIQUID
  subcarrier_(options),
#endif
  ascii_bits_(options.feed_thru),
  input_type_(options.input_type), is_eof_(false) {
}

int BlockStream::NextBit() {
  int result = 0;
#ifdef HAVE_LIQUID
  if (input_type_ == INPUT_MPX) {
    result = subcarrier_.NextBit();
    is_eof_ = subcarrier_.eof();
  }
#endif
  if (input_type_ == INPUT_ASCIIBITS) {
    result = ascii_bits_.NextBit();
    is_eof_ = ascii_bits_.eof();
  }

  return result;
}

// A block can't be decoded
void BlockStream::Uncorrectable() {
  block_has_errors_[block_counter_ % block_has_errors_.size()] = true;

  unsigned num_erroneous_blocks = 0;
  for (bool e : block_has_errors_) {
    if (e)
      num_erroneous_blocks++;
  }

  // Sync is lost when >45 out of last 50 blocks are erroneous (Section C.1.2)
  if (is_in_sync_ && num_erroneous_blocks > 45) {
    is_in_sync_ = false;
    for (size_t i=0; i < block_has_errors_.size(); i++)
      block_has_errors_[i] = false;
    pi_ = 0x0000;
  }
}

bool BlockStream::AcquireSync() {
  if (is_in_sync_)
    return true;

  // Try to find the repeating offset sequence
  if (received_offset_ != OFFSET_INVALID) {
    int dist = bitcount_ - prevbitcount_;

    if (dist % 26 == 0 && dist <= 156 &&
        (g_block_number_for_offset[prevsync_] + dist/26) % 4 ==
        g_block_number_for_offset[received_offset_]) {
      is_in_sync_ = true;
      expected_offset_ = received_offset_;
    } else {
      prevbitcount_ = bitcount_;
      prevsync_ = received_offset_;
    }
  }

  return is_in_sync_;
}

Group BlockStream::NextGroup() {
  Group group;

  while (!eof()) {
    // Compensate for clock slip corrections
    bitcount_ += 26 - left_to_read_;

    // Read from radio
    for (int i=0; i < (is_in_sync_ ? left_to_read_ : 1); i++, bitcount_++) {
      padded_block_ = (padded_block_ << 1) + NextBit();
    }

    left_to_read_ = 26;
    padded_block_ &= kBitmask28;

    uint32_t block = (padded_block_ >> 1) & kBitmask26;
    uint16_t message = block >> 10;

    received_offset_ = OffsetForSyndrome(CalcSyndrome(block));

    if (!AcquireSync())
      continue;

    block_counter_++;

    if (expected_offset_ == OFFSET_C && received_offset_ == OFFSET_C_PRIME)
      expected_offset_ = OFFSET_C_PRIME;

    block_has_errors_[block_counter_ % block_has_errors_.size()] = false;

    if (received_offset_ != expected_offset_) {
      block_has_errors_[block_counter_ % block_has_errors_.size()] = true;

      // Detect & correct clock slips (Section C.1.2)
      if (expected_offset_ == OFFSET_A && pi_ != 0x0000 &&
          ((padded_block_ >> 12) & kBitmask16) == pi_) {
        message = pi_;
        padded_block_ >>= 1;
        received_offset_ = OFFSET_A;
      } else if (expected_offset_ == OFFSET_A && pi_ != 0x0000 &&
          ((padded_block_ >> 10) & kBitmask16) == pi_) {
        message = pi_;
        padded_block_ = (padded_block_ << 1) + NextBit();
        received_offset_ = OFFSET_A;
        left_to_read_ = 25;
      } else {
        uint32_t corrected_block = CorrectBurstErrors(block, expected_offset_);
        if (corrected_block != block) {
          message = corrected_block >> 10;
          received_offset_ = expected_offset_;
        }
      }

      // Still no valid syndrome
      if (received_offset_ != expected_offset_)
        Uncorrectable();
    }

    // Error-free block received

    if (received_offset_ == expected_offset_) {
      if (expected_offset_ == OFFSET_C_PRIME)
        group.set_c_prime(message);
      else
        group.set(g_block_number_for_offset[expected_offset_], message);

      if (group.has_pi())
        pi_ = group.pi();
    }

    expected_offset_ = nextOffsetFor(expected_offset_);

    if (expected_offset_ == OFFSET_A)
      break;
  }

  return group;
}

bool BlockStream::eof() const {
  return is_eof_;
}

#ifdef DEBUG
float BlockStream::t() const {
  return subcarrier_.t();
}
#endif

}  // namespace redsea
<|endoftext|>


<commit_before>/* Copyright (c) 2008-2009, Avian Contributors

   Permission to use, copy, modify, and/or distribute this software
   for any purpose with or without fee is hereby granted, provided
   that the above copyright notice and this permission notice appear
   in all copies.

   There is NO WARRANTY for this software.  See license.txt for
   details. */

#include "bootimage.h"
#include "heapwalk.h"
#include "common.h"
#include "machine.h"
#include "util.h"
#include "assembler.h"

// since we aren't linking against libstdc++, we must implement this
// ourselves:
extern "C" void __cxa_pure_virtual(void) { abort(); }

using namespace vm;

namespace {

bool
endsWith(const char* suffix, const char* s, unsigned length)
{
  unsigned suffixLength = strlen(suffix);
  return length >= suffixLength
    and memcmp(suffix, s + (length - suffixLength), suffixLength) == 0;
}

object
makeCodeImage(Thread* t, Zone* zone, BootImage* image, uint8_t* code,
              uintptr_t* codeMap, const char* className,
              const char* methodName, const char* methodSpec)
{
  object constants = 0;
  PROTECT(t, constants);

  object calls = 0;
  PROTECT(t, calls);

  DelayedPromise* addresses = 0;

  for (Finder::Iterator it(t->m->finder); it.hasMore();) {
    unsigned nameSize = 0;
    const char* name = it.next(&nameSize);

    if (endsWith(".class", name, nameSize)
        and (className == 0 or strncmp(name, className, nameSize - 6) == 0))
    {
//       fprintf(stderr, "%.*s\n", nameSize - 6, name);
      object c = resolveClass
        (t, makeByteArray(t, "%.*s", nameSize - 6, name));

      if (t->exception) return 0;

      PROTECT(t, c);

      if (classMethodTable(t, c)) {
        for (unsigned i = 0; i < arrayLength(t, classMethodTable(t, c)); ++i) {
          object method = arrayBody(t, classMethodTable(t, c), i);
          if ((methodCode(t, method) or (methodFlags(t, method) & ACC_NATIVE))
              and ((methodName == 0
                    or strcmp
                    (reinterpret_cast<char*>
                     (&byteArrayBody
                      (t, vm::methodName(t, method), 0)), methodName) == 0)
                   and (methodSpec == 0
                        or strcmp
                        (reinterpret_cast<char*>
                         (&byteArrayBody
                          (t, vm::methodSpec(t, method), 0)), methodSpec)
                        == 0)))
          {
            t->m->processor->compileMethod
              (t, zone, &constants, &calls, &addresses, method);
          }
        }
      }
    }
  }

  for (; calls; calls = tripleThird(t, calls)) {
    object method = tripleFirst(t, calls);
    uintptr_t address;
    if (methodFlags(t, method) & ACC_NATIVE) {
      address = reinterpret_cast<uintptr_t>(code + image->nativeThunk);
    } else {
      address = methodCompiled(t, method);
    }

    static_cast<ListenPromise*>(pointerValue(t, tripleSecond(t, calls)))
      ->listener->resolve(address, 0);
  }

  for (; addresses; addresses = addresses->next) {
    uint8_t* value = reinterpret_cast<uint8_t*>(addresses->basis->value());
    assert(t, value >= code);

    void* location;
    bool flat = addresses->listener->resolve(0, &location);
    uintptr_t offset = value - code;
    if (flat) {
      offset |= BootFlatConstant;
    }
    memcpy(location, &offset, BytesPerWord);

    assert(t, reinterpret_cast<intptr_t>(location)
           >= reinterpret_cast<intptr_t>(code));

    markBit(codeMap, reinterpret_cast<intptr_t>(location)
            - reinterpret_cast<intptr_t>(code));
  }

  return constants;
}

unsigned
objectSize(Thread* t, object o)
{
  assert(t, not objectExtended(t, o));

  return baseSize(t, o, objectClass(t, o));
}

void
visitRoots(Thread* t, BootImage* image, HeapWalker* w, object constants)
{
  Machine* m = t->m;

  for (HashMapIterator it(t, m->classMap); it.hasMore();) {
    w->visitRoot(tripleSecond(t, it.next()));
  }

  image->loader = w->visitRoot(m->loader);
  image->types = w->visitRoot(m->types);

  m->processor->visitRoots(w);

  for (; constants; constants = tripleThird(t, constants)) {
    w->visitRoot(tripleFirst(t, constants));
  }
}

HeapWalker*
makeHeapImage(Thread* t, BootImage* image, uintptr_t* heap, uintptr_t* map,
              unsigned capacity, object constants)
{
  class Visitor: public HeapVisitor {
   public:
    Visitor(Thread* t, uintptr_t* heap, uintptr_t* map, unsigned capacity):
      t(t), currentObject(0), currentNumber(0), currentOffset(0), heap(heap),
      map(map), position(0), capacity(capacity)
    { }

    void visit(unsigned number) {
      if (currentObject) {
        unsigned offset = currentNumber - 1 + currentOffset;
        unsigned mark = heap[offset] & (~PointerMask);
        unsigned value = number | (mark << BootShift);

        if (value) markBit(map, offset);

        heap[offset] = value;
      }
    }

    virtual void root() {
      currentObject = 0;
    }

    virtual unsigned visitNew(object p) {
      if (p) {
        unsigned size = objectSize(t, p);

        unsigned number;
        if (currentObject
            and (currentOffset * BytesPerWord) == ClassStaticTable)
        {
          FixedAllocator allocator
            (t->m->system, reinterpret_cast<uint8_t*>(heap + position),
             (capacity - position) * BytesPerWord);

          unsigned totalInBytes;
          uintptr_t* dst = static_cast<uintptr_t*>
            (t->m->heap->allocateImmortalFixed
             (&allocator, size, true, &totalInBytes));

          memcpy(dst, p, size * BytesPerWord);

          dst[0] |= FixedMark;

          number = (dst - heap) + 1;
          position += ceiling(totalInBytes, BytesPerWord);
        } else {
          assert(t, position + size < capacity);
          memcpy(heap + position, p, size * BytesPerWord);

          number = position + 1;
          position += size;
        }

        visit(number);

        return number;
      } else {
        return 0;
      }
    }

    virtual void visitOld(object, unsigned number) {
      visit(number);
    }

    virtual void push(object object, unsigned number, unsigned offset) {
      currentObject = object;
      currentNumber = number;
      currentOffset = offset;
    }

    virtual void pop() {
      currentObject = 0;
    }

    Thread* t;
    object currentObject;
    unsigned currentNumber;
    unsigned currentOffset;
    uintptr_t* heap;
    uintptr_t* map;
    unsigned position;
    unsigned capacity;
  } visitor(t, heap, map, capacity / BytesPerWord);

  HeapWalker* w = makeHeapWalker(t, &visitor);
  visitRoots(t, image, w, constants);

  image->heapSize = visitor.position * BytesPerWord;

  return w;
}

void
updateConstants(Thread* t, object constants, uint8_t* code, uintptr_t* codeMap,
                HeapMap* heapTable)
{
  for (; constants; constants = tripleThird(t, constants)) {
    unsigned target = heapTable->find(tripleFirst(t, constants));
    assert(t, target > 0);

    for (Promise::Listener* pl = static_cast<ListenPromise*>
           (pointerValue(t, tripleSecond(t, constants)))->listener;
         pl; pl = pl->next)
    {
      void* location;
      bool flat = pl->resolve(0, &location);
      uintptr_t offset = target | BootHeapOffset;
      if (flat) {
        offset |= BootFlatConstant;
      }
      memcpy(location, &offset, BytesPerWord);

      assert(t, reinterpret_cast<intptr_t>(location)
             >= reinterpret_cast<intptr_t>(code));

      markBit(codeMap, reinterpret_cast<intptr_t>(location)
              - reinterpret_cast<intptr_t>(code));
    }
  }
}

unsigned
offset(object a, uintptr_t* b)
{
  return reinterpret_cast<uintptr_t>(b) - reinterpret_cast<uintptr_t>(a);
}

void
writeBootImage(Thread* t, FILE* out, BootImage* image, uint8_t* code,
               unsigned codeCapacity, const char* className,
               const char* methodName, const char* methodSpec)
{
  Zone zone(t->m->system, t->m->heap, 64 * 1024);

  uintptr_t* codeMap = static_cast<uintptr_t*>
    (t->m->heap->allocate(codeMapSize(codeCapacity)));
  memset(codeMap, 0, codeMapSize(codeCapacity));

  object constants = makeCodeImage
    (t, &zone, image, code, codeMap, className, methodName, methodSpec);

  if (t->exception) return;

  PROTECT(t, constants);

  const unsigned HeapCapacity = 32 * 1024 * 1024;
  uintptr_t* heap = static_cast<uintptr_t*>
    (t->m->heap->allocate(HeapCapacity));
  uintptr_t* heapMap = static_cast<uintptr_t*>
    (t->m->heap->allocate(heapMapSize(HeapCapacity)));
  memset(heapMap, 0, heapMapSize(HeapCapacity));

  collect(t, Heap::MajorCollection);

  HeapWalker* heapWalker = makeHeapImage
    (t, image, heap, heapMap, HeapCapacity, constants);

  updateConstants(t, constants, code, codeMap, heapWalker->map());

  image->classCount = hashMapSize(t, t->m->classMap);
  unsigned* classTable = static_cast<unsigned*>
    (t->m->heap->allocate(image->classCount * sizeof(unsigned)));

  { unsigned i = 0;
    for (HashMapIterator it(t, t->m->classMap); it.hasMore();) {
      classTable[i++] = heapWalker->map()->find(tripleSecond(t, it.next()));
    }
  }

  image->stringCount = hashMapSize(t, t->m->stringMap);
  unsigned* stringTable = static_cast<unsigned*>
    (t->m->heap->allocate(image->stringCount * sizeof(unsigned)));

  { unsigned i = 0;
    for (HashMapIterator it(t, t->m->stringMap); it.hasMore();) {
      stringTable[i++] = heapWalker->map()->find
        (jreferenceTarget(t, tripleFirst(t, it.next())));
    }
  }

  unsigned* callTable = t->m->processor->makeCallTable(t, heapWalker);

  heapWalker->dispose();

  image->magic = BootImage::Magic;
  image->codeBase = reinterpret_cast<uintptr_t>(code);

  fprintf(stderr, "class count %d string count %d call count %d\n"
          "heap size %d code size %d\n",
          image->classCount, image->stringCount, image->callCount,
          image->heapSize, image->codeSize);

  if (true) {
    fwrite(image, sizeof(BootImage), 1, out);

    fwrite(classTable, image->classCount * sizeof(unsigned), 1, out);
    fwrite(stringTable, image->stringCount * sizeof(unsigned), 1, out);
    fwrite(callTable, image->callCount * sizeof(unsigned) * 2, 1, out);

    unsigned offset = (image->classCount * sizeof(unsigned))
      + (image->stringCount * sizeof(unsigned))
      + (image->callCount * sizeof(unsigned) * 2);

    while (offset % BytesPerWord) {
      uint8_t c = 0;
      fwrite(&c, 1, 1, out);
      ++ offset;
    }

    fwrite(heapMap, pad(heapMapSize(image->heapSize)), 1, out);
    fwrite(heap, pad(image->heapSize), 1, out);

    fwrite(codeMap, pad(codeMapSize(image->codeSize)), 1, out);
    fwrite(code, pad(image->codeSize), 1, out);
  }
}

} // namespace

int
main(int ac, const char** av)
{
  if (ac < 3 or ac > 6) {
    fprintf(stderr, "usage: %s <classpath> <output file> "
            "[<class name> [<method name> [<method spec>]]]\n", av[0]);
    return -1;
  }

  System* s = makeSystem(0);
  Heap* h = makeHeap(s, 128 * 1024 * 1024);
  Finder* f = makeFinder(s, av[1], 0);
  Processor* p = makeProcessor(s, h);

  BootImage image;
  const unsigned CodeCapacity = 32 * 1024 * 1024;
  uint8_t* code = static_cast<uint8_t*>(h->allocate(CodeCapacity));
  p->initialize(&image, code, CodeCapacity);

  Machine* m = new (h->allocate(sizeof(Machine))) Machine(s, h, f, p, 0, 0);
  Thread* t = p->makeThread(m, 0, 0);

  enter(t, Thread::ActiveState);
  enter(t, Thread::IdleState);

  FILE* output = fopen(av[2], "wb");
  if (output == 0) {
    fprintf(stderr, "unable to open %s\n", av[2]);
    return -1;
  }

  writeBootImage
    (t, output, &image, code, CodeCapacity,
     (ac > 3 ? av[3] : 0), (ac > 4 ? av[4] : 0), (ac > 5 ? av[5] : 0));

  fclose(output);

  if (t->exception) {
    printTrace(t, t->exception);
  }

  return 0;
}
<commit_msg>clear Machine::byteArrayMap before generating boot image since it will not be used when the image is loaded<commit_after>/* Copyright (c) 2008-2009, Avian Contributors

   Permission to use, copy, modify, and/or distribute this software
   for any purpose with or without fee is hereby granted, provided
   that the above copyright notice and this permission notice appear
   in all copies.

   There is NO WARRANTY for this software.  See license.txt for
   details. */

#include "bootimage.h"
#include "heapwalk.h"
#include "common.h"
#include "machine.h"
#include "util.h"
#include "assembler.h"

// since we aren't linking against libstdc++, we must implement this
// ourselves:
extern "C" void __cxa_pure_virtual(void) { abort(); }

using namespace vm;

namespace {

bool
endsWith(const char* suffix, const char* s, unsigned length)
{
  unsigned suffixLength = strlen(suffix);
  return length >= suffixLength
    and memcmp(suffix, s + (length - suffixLength), suffixLength) == 0;
}

object
makeCodeImage(Thread* t, Zone* zone, BootImage* image, uint8_t* code,
              uintptr_t* codeMap, const char* className,
              const char* methodName, const char* methodSpec)
{
  object constants = 0;
  PROTECT(t, constants);

  object calls = 0;
  PROTECT(t, calls);

  DelayedPromise* addresses = 0;

  for (Finder::Iterator it(t->m->finder); it.hasMore();) {
    unsigned nameSize = 0;
    const char* name = it.next(&nameSize);

    if (endsWith(".class", name, nameSize)
        and (className == 0 or strncmp(name, className, nameSize - 6) == 0))
    {
//       fprintf(stderr, "%.*s\n", nameSize - 6, name);
      object c = resolveClass
        (t, makeByteArray(t, "%.*s", nameSize - 6, name));

      if (t->exception) return 0;

      PROTECT(t, c);

      if (classMethodTable(t, c)) {
        for (unsigned i = 0; i < arrayLength(t, classMethodTable(t, c)); ++i) {
          object method = arrayBody(t, classMethodTable(t, c), i);
          if ((methodCode(t, method) or (methodFlags(t, method) & ACC_NATIVE))
              and ((methodName == 0
                    or strcmp
                    (reinterpret_cast<char*>
                     (&byteArrayBody
                      (t, vm::methodName(t, method), 0)), methodName) == 0)
                   and (methodSpec == 0
                        or strcmp
                        (reinterpret_cast<char*>
                         (&byteArrayBody
                          (t, vm::methodSpec(t, method), 0)), methodSpec)
                        == 0)))
          {
            t->m->processor->compileMethod
              (t, zone, &constants, &calls, &addresses, method);
          }
        }
      }
    }
  }

  for (; calls; calls = tripleThird(t, calls)) {
    object method = tripleFirst(t, calls);
    uintptr_t address;
    if (methodFlags(t, method) & ACC_NATIVE) {
      address = reinterpret_cast<uintptr_t>(code + image->nativeThunk);
    } else {
      address = methodCompiled(t, method);
    }

    static_cast<ListenPromise*>(pointerValue(t, tripleSecond(t, calls)))
      ->listener->resolve(address, 0);
  }

  for (; addresses; addresses = addresses->next) {
    uint8_t* value = reinterpret_cast<uint8_t*>(addresses->basis->value());
    assert(t, value >= code);

    void* location;
    bool flat = addresses->listener->resolve(0, &location);
    uintptr_t offset = value - code;
    if (flat) {
      offset |= BootFlatConstant;
    }
    memcpy(location, &offset, BytesPerWord);

    assert(t, reinterpret_cast<intptr_t>(location)
           >= reinterpret_cast<intptr_t>(code));

    markBit(codeMap, reinterpret_cast<intptr_t>(location)
            - reinterpret_cast<intptr_t>(code));
  }

  return constants;
}

unsigned
objectSize(Thread* t, object o)
{
  assert(t, not objectExtended(t, o));

  return baseSize(t, o, objectClass(t, o));
}

void
visitRoots(Thread* t, BootImage* image, HeapWalker* w, object constants)
{
  Machine* m = t->m;

  for (HashMapIterator it(t, m->classMap); it.hasMore();) {
    w->visitRoot(tripleSecond(t, it.next()));
  }

  image->loader = w->visitRoot(m->loader);
  image->types = w->visitRoot(m->types);

  m->processor->visitRoots(w);

  for (; constants; constants = tripleThird(t, constants)) {
    w->visitRoot(tripleFirst(t, constants));
  }
}

HeapWalker*
makeHeapImage(Thread* t, BootImage* image, uintptr_t* heap, uintptr_t* map,
              unsigned capacity, object constants)
{
  class Visitor: public HeapVisitor {
   public:
    Visitor(Thread* t, uintptr_t* heap, uintptr_t* map, unsigned capacity):
      t(t), currentObject(0), currentNumber(0), currentOffset(0), heap(heap),
      map(map), position(0), capacity(capacity)
    { }

    void visit(unsigned number) {
      if (currentObject) {
        unsigned offset = currentNumber - 1 + currentOffset;
        unsigned mark = heap[offset] & (~PointerMask);
        unsigned value = number | (mark << BootShift);

        if (value) markBit(map, offset);

        heap[offset] = value;
      }
    }

    virtual void root() {
      currentObject = 0;
    }

    virtual unsigned visitNew(object p) {
      if (p) {
        unsigned size = objectSize(t, p);

        unsigned number;
        if (currentObject
            and (currentOffset * BytesPerWord) == ClassStaticTable)
        {
          FixedAllocator allocator
            (t->m->system, reinterpret_cast<uint8_t*>(heap + position),
             (capacity - position) * BytesPerWord);

          unsigned totalInBytes;
          uintptr_t* dst = static_cast<uintptr_t*>
            (t->m->heap->allocateImmortalFixed
             (&allocator, size, true, &totalInBytes));

          memcpy(dst, p, size * BytesPerWord);

          dst[0] |= FixedMark;

          number = (dst - heap) + 1;
          position += ceiling(totalInBytes, BytesPerWord);
        } else {
          assert(t, position + size < capacity);
          memcpy(heap + position, p, size * BytesPerWord);

          number = position + 1;
          position += size;
        }

        visit(number);

        return number;
      } else {
        return 0;
      }
    }

    virtual void visitOld(object, unsigned number) {
      visit(number);
    }

    virtual void push(object object, unsigned number, unsigned offset) {
      currentObject = object;
      currentNumber = number;
      currentOffset = offset;
    }

    virtual void pop() {
      currentObject = 0;
    }

    Thread* t;
    object currentObject;
    unsigned currentNumber;
    unsigned currentOffset;
    uintptr_t* heap;
    uintptr_t* map;
    unsigned position;
    unsigned capacity;
  } visitor(t, heap, map, capacity / BytesPerWord);

  HeapWalker* w = makeHeapWalker(t, &visitor);
  visitRoots(t, image, w, constants);

  image->heapSize = visitor.position * BytesPerWord;

  return w;
}

void
updateConstants(Thread* t, object constants, uint8_t* code, uintptr_t* codeMap,
                HeapMap* heapTable)
{
  for (; constants; constants = tripleThird(t, constants)) {
    unsigned target = heapTable->find(tripleFirst(t, constants));
    assert(t, target > 0);

    for (Promise::Listener* pl = static_cast<ListenPromise*>
           (pointerValue(t, tripleSecond(t, constants)))->listener;
         pl; pl = pl->next)
    {
      void* location;
      bool flat = pl->resolve(0, &location);
      uintptr_t offset = target | BootHeapOffset;
      if (flat) {
        offset |= BootFlatConstant;
      }
      memcpy(location, &offset, BytesPerWord);

      assert(t, reinterpret_cast<intptr_t>(location)
             >= reinterpret_cast<intptr_t>(code));

      markBit(codeMap, reinterpret_cast<intptr_t>(location)
              - reinterpret_cast<intptr_t>(code));
    }
  }
}

unsigned
offset(object a, uintptr_t* b)
{
  return reinterpret_cast<uintptr_t>(b) - reinterpret_cast<uintptr_t>(a);
}

void
writeBootImage(Thread* t, FILE* out, BootImage* image, uint8_t* code,
               unsigned codeCapacity, const char* className,
               const char* methodName, const char* methodSpec)
{
  Zone zone(t->m->system, t->m->heap, 64 * 1024);

  uintptr_t* codeMap = static_cast<uintptr_t*>
    (t->m->heap->allocate(codeMapSize(codeCapacity)));
  memset(codeMap, 0, codeMapSize(codeCapacity));

  object constants = makeCodeImage
    (t, &zone, image, code, codeMap, className, methodName, methodSpec);

  if (t->exception) return;

  PROTECT(t, constants);

  const unsigned HeapCapacity = 32 * 1024 * 1024;
  uintptr_t* heap = static_cast<uintptr_t*>
    (t->m->heap->allocate(HeapCapacity));
  uintptr_t* heapMap = static_cast<uintptr_t*>
    (t->m->heap->allocate(heapMapSize(HeapCapacity)));
  memset(heapMap, 0, heapMapSize(HeapCapacity));

  // this map will not be used when the bootimage is loaded, so
  // there's no need to preserve it:
  t->m->byteArrayMap = makeWeakHashMap(t, 0, 0);

  collect(t, Heap::MajorCollection);

  HeapWalker* heapWalker = makeHeapImage
    (t, image, heap, heapMap, HeapCapacity, constants);

  updateConstants(t, constants, code, codeMap, heapWalker->map());

  image->classCount = hashMapSize(t, t->m->classMap);
  unsigned* classTable = static_cast<unsigned*>
    (t->m->heap->allocate(image->classCount * sizeof(unsigned)));

  { unsigned i = 0;
    for (HashMapIterator it(t, t->m->classMap); it.hasMore();) {
      classTable[i++] = heapWalker->map()->find(tripleSecond(t, it.next()));
    }
  }

  image->stringCount = hashMapSize(t, t->m->stringMap);
  unsigned* stringTable = static_cast<unsigned*>
    (t->m->heap->allocate(image->stringCount * sizeof(unsigned)));

  { unsigned i = 0;
    for (HashMapIterator it(t, t->m->stringMap); it.hasMore();) {
      stringTable[i++] = heapWalker->map()->find
        (jreferenceTarget(t, tripleFirst(t, it.next())));
    }
  }

  unsigned* callTable = t->m->processor->makeCallTable(t, heapWalker);

  heapWalker->dispose();

  image->magic = BootImage::Magic;
  image->codeBase = reinterpret_cast<uintptr_t>(code);

  fprintf(stderr, "class count %d string count %d call count %d\n"
          "heap size %d code size %d\n",
          image->classCount, image->stringCount, image->callCount,
          image->heapSize, image->codeSize);

  if (true) {
    fwrite(image, sizeof(BootImage), 1, out);

    fwrite(classTable, image->classCount * sizeof(unsigned), 1, out);
    fwrite(stringTable, image->stringCount * sizeof(unsigned), 1, out);
    fwrite(callTable, image->callCount * sizeof(unsigned) * 2, 1, out);

    unsigned offset = (image->classCount * sizeof(unsigned))
      + (image->stringCount * sizeof(unsigned))
      + (image->callCount * sizeof(unsigned) * 2);

    while (offset % BytesPerWord) {
      uint8_t c = 0;
      fwrite(&c, 1, 1, out);
      ++ offset;
    }

    fwrite(heapMap, pad(heapMapSize(image->heapSize)), 1, out);
    fwrite(heap, pad(image->heapSize), 1, out);

    fwrite(codeMap, pad(codeMapSize(image->codeSize)), 1, out);
    fwrite(code, pad(image->codeSize), 1, out);
  }
}

} // namespace

int
main(int ac, const char** av)
{
  if (ac < 3 or ac > 6) {
    fprintf(stderr, "usage: %s <classpath> <output file> "
            "[<class name> [<method name> [<method spec>]]]\n", av[0]);
    return -1;
  }

  System* s = makeSystem(0);
  Heap* h = makeHeap(s, 128 * 1024 * 1024);
  Finder* f = makeFinder(s, av[1], 0);
  Processor* p = makeProcessor(s, h);

  BootImage image;
  const unsigned CodeCapacity = 32 * 1024 * 1024;
  uint8_t* code = static_cast<uint8_t*>(h->allocate(CodeCapacity));
  p->initialize(&image, code, CodeCapacity);

  Machine* m = new (h->allocate(sizeof(Machine))) Machine(s, h, f, p, 0, 0);
  Thread* t = p->makeThread(m, 0, 0);

  enter(t, Thread::ActiveState);
  enter(t, Thread::IdleState);

  FILE* output = fopen(av[2], "wb");
  if (output == 0) {
    fprintf(stderr, "unable to open %s\n", av[2]);
    return -1;
  }

  writeBootImage
    (t, output, &image, code, CodeCapacity,
     (ac > 3 ? av[3] : 0), (ac > 4 ? av[4] : 0), (ac > 5 ? av[5] : 0));

  fclose(output);

  if (t->exception) {
    printTrace(t, t->exception);
  }

  return 0;
}
<|endoftext|>


<commit_before><commit_msg>Added some functionality to uintqueue<commit_after><|endoftext|>


<commit_before>// timer.t.cpp
#include <engine/utility/timer.h>
#include <gtest/gtest.h>

TEST( Timer, Construction )
{
    using namespace nge::util;

    Timer timer;
    Timer copy( timer );

    timer = copy;
}

TEST( Timer, StartAndStop )
{
    using namespace nge::util;

    Timer timer;

    ASSERT_EQ( 0.0f, timer.elapsed() );
    ASSERT_EQ( 0, timer.elapsedTicks() );

    timer.start();

    usleep( 1000 );

    EXPECT_TRUE( timer.elapsed() > 0.001f );
    EXPECT_TRUE( timer.elapsedTicks() > 1000000 );

    timer.stop();

    usleep( 1000 );

    EXPECT_TRUE( timer.elapsed() > 0.001f );
    EXPECT_TRUE( timer.elapsedTicks() > 1000000 );
    EXPECT_FALSE( timer.elapsed() > 0.002f );
    EXPECT_FALSE( timer.elapsedTicks() > 2000000 );

    timer.start();
    timer.stop();

    EXPECT_TRUE( timer.elapsed() < 0.001f );
    EXPECT_TRUE( timer.elapsedTicks() < 1000000 );
}

TEST( Timer, PauseAndResumeAndLapAndTotal )
{
    using namespace nge::util;

    Timer timer;

    ASSERT_EQ( 0.0f, timer.elapsed() );
    ASSERT_EQ( 0.0f, timer.elapsedTicks() );
    ASSERT_EQ( 0.0f, timer.lap() );

    timer.start();

    usleep( 1000 );

    EXPECT_TRUE( timer.elapsed() > 0.001f );
    EXPECT_TRUE( timer.elapsedTicks() > 1 );

    timer.pause();

    usleep( 1000 );

    EXPECT_TRUE( timer.elapsed() > 0.001f );
    EXPECT_TRUE( timer.elapsedTicks() > 1000000 );
    EXPECT_FALSE( timer.elapsed() > 0.002f );
    EXPECT_FALSE( timer.elapsedTicks() > 2000000 );

    timer.resume();

    usleep( 1000 );

    EXPECT_TRUE( timer.elapsed() > 0.002f );
    EXPECT_TRUE( timer.elapsedTicks() > 2000000 );

    usleep( 1000 );

    EXPECT_FALSE( timer.total() > 0.002f );
    EXPECT_FALSE( timer.totalTicks() > 2000000 );
    EXPECT_TRUE( timer.elapsed() > 0.002f );
    EXPECT_TRUE( timer.elapsedTicks() > 2000000 );

    timer.lap();

    EXPECT_TRUE( timer.total() > 0.002f );
    EXPECT_TRUE( timer.totalTicks() > 2000000 );
    EXPECT_TRUE( timer.elapsed() > 0.002f );
    EXPECT_TRUE( timer.elapsedTicks() > 2000000 );

    timer.stop();
}

TEST( Timer, TimeScale )
{
    using namespace nge::util;

    Timer timer;

    ASSERT_EQ( 1.0f, timer.timeScale() );

    timer.setTimeScale( 2.0f );
    timer.start();

    usleep( 1000 );

    EXPECT_TRUE( timer.elapsed() > 0.002f );
    EXPECT_TRUE( timer.elapsedTicks() > 2000000 );

    timer.stop();
    timer.setTimeScale( 0.5f );
    timer.start();

    EXPECT_FALSE( timer.elapsed() > 0.001f );
    EXPECT_FALSE( timer.elapsedTicks() > 1000000 );

    timer.stop();
}<commit_msg>use multi-platform sleep function<commit_after>// timer.t.cpp
#include <engine/utility/timer.h>
#include <gtest/gtest.h>
#include <chrono>
#include <thread>

TEST( Timer, Construction )
{
    using namespace nge::util;

    Timer timer;
    Timer copy( timer );

    timer = copy;
}

TEST( Timer, StartAndStop )
{
    using namespace nge::util;

    Timer timer;

    ASSERT_EQ( 0.0f, timer.elapsed() );
    ASSERT_EQ( 0, timer.elapsedTicks() );

    timer.start();

	std::this_thread::sleep_for( std::chrono::microseconds( 1000 ) );

    EXPECT_TRUE( timer.elapsed() > 0.001f );
    EXPECT_TRUE( timer.elapsedTicks() > 1000000 );

    timer.stop();

	std::this_thread::sleep_for(std::chrono::microseconds(1000));

    EXPECT_TRUE( timer.elapsed() > 0.001f );
    EXPECT_TRUE( timer.elapsedTicks() > 1000000 );
    EXPECT_FALSE( timer.elapsed() > 0.002f );
    EXPECT_FALSE( timer.elapsedTicks() > 2000000 );

    timer.start();
    timer.stop();

    EXPECT_TRUE( timer.elapsed() < 0.001f );
    EXPECT_TRUE( timer.elapsedTicks() < 1000000 );
}

TEST( Timer, PauseAndResumeAndLapAndTotal )
{
    using namespace nge::util;

    Timer timer;

    ASSERT_EQ( 0.0f, timer.elapsed() );
    ASSERT_EQ( 0.0f, timer.elapsedTicks() );
    ASSERT_EQ( 0.0f, timer.lap() );

    timer.start();

	std::this_thread::sleep_for(std::chrono::microseconds(1000));

    EXPECT_TRUE( timer.elapsed() > 0.001f );
    EXPECT_TRUE( timer.elapsedTicks() > 1 );

    timer.pause();

	std::this_thread::sleep_for(std::chrono::microseconds(1000));

    EXPECT_TRUE( timer.elapsed() > 0.001f );
    EXPECT_TRUE( timer.elapsedTicks() > 1000000 );
    EXPECT_FALSE( timer.elapsed() > 0.002f );
    EXPECT_FALSE( timer.elapsedTicks() > 2000000 );

    timer.resume();

	std::this_thread::sleep_for(std::chrono::microseconds(1000));

    EXPECT_TRUE( timer.elapsed() > 0.002f );
    EXPECT_TRUE( timer.elapsedTicks() > 2000000 );

	std::this_thread::sleep_for(std::chrono::microseconds(1000));

    EXPECT_FALSE( timer.total() > 0.002f );
    EXPECT_FALSE( timer.totalTicks() > 2000000 );
    EXPECT_TRUE( timer.elapsed() > 0.002f );
    EXPECT_TRUE( timer.elapsedTicks() > 2000000 );

    timer.lap();

    EXPECT_TRUE( timer.total() > 0.002f );
    EXPECT_TRUE( timer.totalTicks() > 2000000 );
    EXPECT_TRUE( timer.elapsed() > 0.002f );
    EXPECT_TRUE( timer.elapsedTicks() > 2000000 );

    timer.stop();
}

TEST( Timer, TimeScale )
{
    using namespace nge::util;

    Timer timer;

    ASSERT_EQ( 1.0f, timer.timeScale() );

    timer.setTimeScale( 2.0f );
    timer.start();

	std::this_thread::sleep_for(std::chrono::microseconds(1000));

    EXPECT_TRUE( timer.elapsed() > 0.002f );
    EXPECT_TRUE( timer.elapsedTicks() > 2000000 );

    timer.stop();
    timer.setTimeScale( 0.5f );
    timer.start();

    EXPECT_FALSE( timer.elapsed() > 0.001f );
    EXPECT_FALSE( timer.elapsedTicks() > 1000000 );

    timer.stop();
}<|endoftext|>


<commit_before>// Copyright 2013 Velodyne Acoustics, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// Copyright 2013 Velodyne Acoustics, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include "vvMainWindow.h"
#include "ui_vvMainWindow.h"

#include "vvLoadDataReaction.h"
#include "vvToggleSpreadSheetReaction.h"

#include <pqActiveObjects.h>
#include <pqApplicationCore.h>
#include <pqAutoLoadPluginXMLBehavior.h>
#include <pqCommandLineOptionsBehavior.h>
#include <pqCrashRecoveryBehavior.h>
#include <pqDataTimeStepBehavior.h>
#include <pqDefaultViewBehavior.h>
#include <pqInterfaceTracker.h>
#include <pqObjectBuilder.h>
#include "pqObjectPickingBehavior.h"
#include <pqPersistentMainWindowStateBehavior.h>
#include <pqPythonShellReaction.h>
#include <pqQtMessageHandlerBehavior.h>
#include <pqRenderView.h>
#include <pqRenderViewSelectionReaction.h>
#include <pqServer.h>
#include <pqSettings.h>
#include <pqSpreadSheetView.h>
#include <pqSpreadSheetVisibilityBehavior.h>
#include <pqSpreadSheetViewDecorator.h>
#include <pqStandardPropertyWidgetInterface.h>
#include <pqStandardViewFrameActionsImplementation.h>
#include <pqVelodyneManager.h>
#include <vtkPVPlugin.h>
#include <vtkSMPropertyHelper.h>

#include <QLabel>
#include <QSplitter>

#include <cassert>

// Declare the plugin to load.
PV_PLUGIN_IMPORT_INIT(VelodyneHDLPlugin);
PV_PLUGIN_IMPORT_INIT(PythonQtPlugin);

class vvMainWindow::pqInternals
{
public:
  pqInternals(vvMainWindow* window) : Ui(), MainView(0)
    {
    this->Ui.setupUi(window);
    this->paraviewInit(window);
    this->setupUi(window);

    QActionGroup* dualReturnFilterActions = new QActionGroup(window);
    dualReturnFilterActions->addAction(this->Ui.actionDualReturnModeDual);
    dualReturnFilterActions->addAction(this->Ui.actionDualReturnDistanceNear);
    dualReturnFilterActions->addAction(this->Ui.actionDualReturnDistanceFar);
    dualReturnFilterActions->addAction(this->Ui.actionDualReturnIntensityHigh);
    dualReturnFilterActions->addAction(this->Ui.actionDualReturnIntensityLow);

    window->show();
    window->raise();
    window->activateWindow();
    }
  Ui::vvMainWindow Ui;
  pqRenderView* MainView;

private:
  void paraviewInit(vvMainWindow* window)
    {
    pqApplicationCore* core = pqApplicationCore::instance();

    // Register ParaView interfaces.
    pqInterfaceTracker* pgm = core->interfaceTracker();
//    pgm->addInterface(new pqStandardViewModules(pgm));
    pgm->addInterface(new pqStandardPropertyWidgetInterface(pgm));
    pgm->addInterface(new pqStandardViewFrameActionsImplementation(pgm));

    // Define application behaviors.
    new pqQtMessageHandlerBehavior(window);
    new pqDataTimeStepBehavior(window);
    new pqSpreadSheetVisibilityBehavior(window);
    new pqObjectPickingBehavior(window);
//    new pqDefaultViewBehavior(window);
    new pqCrashRecoveryBehavior(window);
    new pqAutoLoadPluginXMLBehavior(window);
    new pqCommandLineOptionsBehavior(window);
    new pqPersistentMainWindowStateBehavior(window);

//    pqServer::setCoincidentTopologyResolutionModeSetting(0);

    // Connect to builtin server.
    pqObjectBuilder* builder = core->getObjectBuilder();
    pqServer* server = builder->createServer(pqServerResource("builtin:"));
    pqActiveObjects::instance().setActiveServer(server);

    // Create a default view.
    pqRenderView* view = qobject_cast<pqRenderView*>(builder->createView(pqRenderView::renderViewType(), server));
    assert(view);
    this->MainView = view;

    vtkSMPropertyHelper(view->getProxy(),"CenterAxesVisibility").Set(0);
    double bgcolor[3] = {0, 0, 0};
    vtkSMPropertyHelper(view->getProxy(), "Background").Set(bgcolor, 3);
    // MultiSamples doesn't work, we need to set that up before registering the proxy.
    //vtkSMPropertyHelper(view->getProxy(),"MultiSamples").Set(1);
    view->getProxy()->UpdateVTKObjects();

    // Create a horizontal splitter as the central widget, add views to splitter
    QSplitter* splitter = new QSplitter(Qt::Horizontal);
    window->setCentralWidget(splitter);

    // Add the main widget to the left
    splitter->addWidget(view->getWidget());

    QSplitter* vSplitter = new QSplitter(Qt::Vertical);
    splitter->addWidget(vSplitter);

    pqView* overheadView = builder->createView(pqRenderView::renderViewType(), server);
//    overheadView->SetInteractionMode("2D");
    overheadView->getProxy()->UpdateVTKObjects();
    // dont add to the splitter just yet
    // TODO: These sizes should not be absolute things
    overheadView->getWidget()->setMinimumSize(300, 200);
    vSplitter->addWidget(overheadView->getWidget());
    new vvToggleSpreadSheetReaction(this->Ui.actionOverheadView, overheadView);

    pqView* spreadsheetView = builder->createView(pqSpreadSheetView::spreadsheetViewType(), server);
    spreadsheetView->getProxy()->UpdateVTKObjects();
    vSplitter->addWidget(spreadsheetView->getWidget());
    new vvToggleSpreadSheetReaction(this->Ui.actionSpreadsheet, spreadsheetView);
    pqSpreadSheetView* ssview = qobject_cast<pqSpreadSheetView*>(spreadsheetView);
    assert(spreadsheetView);
    new pqSpreadSheetViewDecorator(ssview);

    pqActiveObjects::instance().setActiveView(view);
    }

  void setupUi(vvMainWindow* window)
    {
    new pqRenderViewSelectionReaction(
                                      this->Ui.actionSelect_Visible_Points,
                                      this->MainView,
                                      pqRenderViewSelectionReaction::SELECT_SURFACE_POINTS
                                      );
    new pqRenderViewSelectionReaction(
                                      this->Ui.actionSelect_All_Points,
                                      this->MainView,
                                      pqRenderViewSelectionReaction::SELECT_FRUSTUM_POINTS
                                      );

    new pqPythonShellReaction(this->Ui.actionPython_Console);

    pqVelodyneManager::instance()->setup();

    pqSettings* const settings = pqApplicationCore::instance()->settings();
    const QVariant& gridVisible =
      settings->value("VelodyneHDLPlugin/MeasurementGrid/Visibility", true);
    this->Ui.actionMeasurement_Grid->setChecked(gridVisible.toBool());

    new vvLoadDataReaction(this->Ui.actionOpenPcap, false);
    new vvLoadDataReaction(this->Ui.actionOpenApplanix, true);

    connect(this->Ui.actionOpen_Sensor_Stream, SIGNAL(triggered()),
            pqVelodyneManager::instance(), SLOT(onOpenSensor()));

    connect(this->Ui.actionMeasurement_Grid, SIGNAL(toggled(bool)),
            pqVelodyneManager::instance(), SLOT(onMeasurementGrid(bool)));
    }
};

//-----------------------------------------------------------------------------
vvMainWindow::vvMainWindow() : Internals (new vvMainWindow::pqInternals(this))
{
//  this->tabifyDockWidget(
//    this->Internal->colorMapEditorDock,
//    this->Internal->memoryInspectorDock);
  pqApplicationCore::instance()->registerManager(
    "COLOR_EDITOR_PANEL", this->Internals->Ui.colorMapEditorDock);
  this->Internals->Ui.colorMapEditorDock->hide();

  PV_PLUGIN_IMPORT(VelodyneHDLPlugin);
  PV_PLUGIN_IMPORT(PythonQtPlugin);
}

//-----------------------------------------------------------------------------
vvMainWindow::~vvMainWindow()
{
  delete this->Internals;
  this->Internals = NULL;
}

//-----------------------------------------------------------------------------
<commit_msg>Fix problem with coincident topology resolution<commit_after>// Copyright 2013 Velodyne Acoustics, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// Copyright 2013 Velodyne Acoustics, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include "vvMainWindow.h"
#include "ui_vvMainWindow.h"

#include "vvLoadDataReaction.h"
#include "vvToggleSpreadSheetReaction.h"

#include <vtkSMProxyManager.h>
#include <vtkSMSessionProxyManager.h>

#include <pqActiveObjects.h>
#include <pqApplicationCore.h>
#include <pqAutoLoadPluginXMLBehavior.h>
#include <pqCommandLineOptionsBehavior.h>
#include <pqCrashRecoveryBehavior.h>
#include <pqDataTimeStepBehavior.h>
#include <pqDefaultViewBehavior.h>
#include <pqInterfaceTracker.h>
#include <pqObjectBuilder.h>
#include "pqObjectPickingBehavior.h"
#include <pqPersistentMainWindowStateBehavior.h>
#include <pqPythonShellReaction.h>
#include <pqQtMessageHandlerBehavior.h>
#include <pqRenderView.h>
#include <pqRenderViewSelectionReaction.h>
#include <pqServer.h>
#include <pqSettings.h>
#include <pqSpreadSheetView.h>
#include <pqSpreadSheetVisibilityBehavior.h>
#include <pqSpreadSheetViewDecorator.h>
#include <pqStandardPropertyWidgetInterface.h>
#include <pqStandardViewFrameActionsImplementation.h>
#include <pqVelodyneManager.h>
#include <vtkPVPlugin.h>
#include <vtkSMPropertyHelper.h>

#include <QLabel>
#include <QSplitter>

#include <cassert>

// Declare the plugin to load.
PV_PLUGIN_IMPORT_INIT(VelodyneHDLPlugin);
PV_PLUGIN_IMPORT_INIT(PythonQtPlugin);

class vvMainWindow::pqInternals
{
public:
  pqInternals(vvMainWindow* window) : Ui(), MainView(0)
    {
    this->Ui.setupUi(window);
    this->paraviewInit(window);
    this->setupUi(window);

    QActionGroup* dualReturnFilterActions = new QActionGroup(window);
    dualReturnFilterActions->addAction(this->Ui.actionDualReturnModeDual);
    dualReturnFilterActions->addAction(this->Ui.actionDualReturnDistanceNear);
    dualReturnFilterActions->addAction(this->Ui.actionDualReturnDistanceFar);
    dualReturnFilterActions->addAction(this->Ui.actionDualReturnIntensityHigh);
    dualReturnFilterActions->addAction(this->Ui.actionDualReturnIntensityLow);

    window->show();
    window->raise();
    window->activateWindow();
    }
  Ui::vvMainWindow Ui;
  pqRenderView* MainView;

private:
  void paraviewInit(vvMainWindow* window)
    {
    pqApplicationCore* core = pqApplicationCore::instance();

    // Register ParaView interfaces.
    pqInterfaceTracker* pgm = core->interfaceTracker();
//    pgm->addInterface(new pqStandardViewModules(pgm));
    pgm->addInterface(new pqStandardPropertyWidgetInterface(pgm));
    pgm->addInterface(new pqStandardViewFrameActionsImplementation(pgm));

    // Define application behaviors.
    new pqQtMessageHandlerBehavior(window);
    new pqDataTimeStepBehavior(window);
    new pqSpreadSheetVisibilityBehavior(window);
    new pqObjectPickingBehavior(window);
//    new pqDefaultViewBehavior(window);
    new pqCrashRecoveryBehavior(window);
    new pqAutoLoadPluginXMLBehavior(window);
    new pqCommandLineOptionsBehavior(window);
    new pqPersistentMainWindowStateBehavior(window);

    // Connect to builtin server.
    pqObjectBuilder* builder = core->getObjectBuilder();
    pqServer* server = builder->createServer(pqServerResource("builtin:"));
    pqActiveObjects::instance().setActiveServer(server);

    // Set default render view settings
    vtkSMSessionProxyManager* pxm = vtkSMProxyManager::GetProxyManager()->GetActiveSessionProxyManager();
    vtkSMProxy* renderviewsettings =  pxm->GetProxy("RenderViewSettings");
    assert(renderviewsettings);

    vtkSMPropertyHelper(renderviewsettings,
                        "ResolveCoincidentTopology").Set(0);

    // Create a default view.
    pqRenderView* view = qobject_cast<pqRenderView*>(builder->createView(pqRenderView::renderViewType(), server));
    assert(view);
    this->MainView = view;

    vtkSMPropertyHelper(view->getProxy(),"CenterAxesVisibility").Set(0);
    double bgcolor[3] = {0, 0, 0};
    vtkSMPropertyHelper(view->getProxy(), "Background").Set(bgcolor, 3);
    // MultiSamples doesn't work, we need to set that up before registering the proxy.
    //vtkSMPropertyHelper(view->getProxy(),"MultiSamples").Set(1);
    view->getProxy()->UpdateVTKObjects();

    // Create a horizontal splitter as the central widget, add views to splitter
    QSplitter* splitter = new QSplitter(Qt::Horizontal);
    window->setCentralWidget(splitter);

    // Add the main widget to the left
    splitter->addWidget(view->getWidget());

    QSplitter* vSplitter = new QSplitter(Qt::Vertical);
    splitter->addWidget(vSplitter);

    pqView* overheadView = builder->createView(pqRenderView::renderViewType(), server);
//    overheadView->SetInteractionMode("2D");
    overheadView->getProxy()->UpdateVTKObjects();
    // dont add to the splitter just yet
    // TODO: These sizes should not be absolute things
    overheadView->getWidget()->setMinimumSize(300, 200);
    vSplitter->addWidget(overheadView->getWidget());
    new vvToggleSpreadSheetReaction(this->Ui.actionOverheadView, overheadView);

    pqView* spreadsheetView = builder->createView(pqSpreadSheetView::spreadsheetViewType(), server);
    spreadsheetView->getProxy()->UpdateVTKObjects();
    vSplitter->addWidget(spreadsheetView->getWidget());
    new vvToggleSpreadSheetReaction(this->Ui.actionSpreadsheet, spreadsheetView);
    pqSpreadSheetView* ssview = qobject_cast<pqSpreadSheetView*>(spreadsheetView);
    assert(spreadsheetView);
    new pqSpreadSheetViewDecorator(ssview);

    pqActiveObjects::instance().setActiveView(view);
    }

  void setupUi(vvMainWindow* window)
    {
    new pqRenderViewSelectionReaction(
                                      this->Ui.actionSelect_Visible_Points,
                                      this->MainView,
                                      pqRenderViewSelectionReaction::SELECT_SURFACE_POINTS
                                      );
    new pqRenderViewSelectionReaction(
                                      this->Ui.actionSelect_All_Points,
                                      this->MainView,
                                      pqRenderViewSelectionReaction::SELECT_FRUSTUM_POINTS
                                      );

    new pqPythonShellReaction(this->Ui.actionPython_Console);

    pqVelodyneManager::instance()->setup();

    pqSettings* const settings = pqApplicationCore::instance()->settings();
    const QVariant& gridVisible =
      settings->value("VelodyneHDLPlugin/MeasurementGrid/Visibility", true);
    this->Ui.actionMeasurement_Grid->setChecked(gridVisible.toBool());

    new vvLoadDataReaction(this->Ui.actionOpenPcap, false);
    new vvLoadDataReaction(this->Ui.actionOpenApplanix, true);

    connect(this->Ui.actionOpen_Sensor_Stream, SIGNAL(triggered()),
            pqVelodyneManager::instance(), SLOT(onOpenSensor()));

    connect(this->Ui.actionMeasurement_Grid, SIGNAL(toggled(bool)),
            pqVelodyneManager::instance(), SLOT(onMeasurementGrid(bool)));
    }
};

//-----------------------------------------------------------------------------
vvMainWindow::vvMainWindow() : Internals (new vvMainWindow::pqInternals(this))
{
//  this->tabifyDockWidget(
//    this->Internal->colorMapEditorDock,
//    this->Internal->memoryInspectorDock);
  pqApplicationCore::instance()->registerManager(
    "COLOR_EDITOR_PANEL", this->Internals->Ui.colorMapEditorDock);
  this->Internals->Ui.colorMapEditorDock->hide();

  PV_PLUGIN_IMPORT(VelodyneHDLPlugin);
  PV_PLUGIN_IMPORT(PythonQtPlugin);
}

//-----------------------------------------------------------------------------
vvMainWindow::~vvMainWindow()
{
  delete this->Internals;
  this->Internals = NULL;
}

//-----------------------------------------------------------------------------
<|endoftext|>


<commit_before>#include <simcode/net/NetLogger.h>
#include <stdio.h>
using namespace simcode;
using namespace net;

int NetLogLevel::LEVEL_DEBUG = 2;
int NetLogLevel::LEVEL_INFO  = 3;
int NetLogLevel::LEVEL_WARN  = 4;
int NetLogLevel::LEVEL_ERROR = 5;
int NetLogLevel::LEVEL_FATAL = 6;

int NetLogger::level_ = NetLogLevel::LEVEL_DEBUG;
NetLogger::log_func_t NetLogger::log_func_ = NetLogger::log_out;

void NetLogger::set_level(int l)
{
    level_ = l;
}

void NetLogger::set_log_fun(log_func_t f)
{
    log_func_ = f;
}

void NetLogger::log_write(int level,
                          const char* filename,
                          int linenum,
                          const char* fmt, ...)
{
    if (level < level_) return;
    va_list ap;
    va_start(ap, fmt);
    log_out_valist(level, filename, linenum, fmt, ap);
    va_end(ap);
}

#define LOG_BUF_LEN       4096
void NetLogger::log_out_valist(int level,
                        const char* filename,
                        int linenum,
                        const char* fmt,
                        va_list ap)
{
    char buf[LOG_BUF_LEN];
    vsnprintf(buf, LOG_BUF_LEN, fmt, ap);
    log_out(level, filename, linenum, buf);
}

void NetLogger::log_out(int level,
                        const char* filename,
                        int linenum,
                        const char* msg)
{
    printf("log_level=%d|%s|%d|%s\n", level, filename, linenum, msg);
}
<commit_msg>mod loglevel<commit_after>#include <simcode/net/NetLogger.h>
#include <stdio.h>
using namespace simcode;
using namespace net;

int NetLogLevel::LEVEL_DEBUG = 1;
int NetLogLevel::LEVEL_INFO  = 2;
int NetLogLevel::LEVEL_WARN  = 3;
int NetLogLevel::LEVEL_ERROR = 4;
int NetLogLevel::LEVEL_FATAL = 5;

int NetLogger::level_ = NetLogLevel::LEVEL_DEBUG;
NetLogger::log_func_t NetLogger::log_func_ = NetLogger::log_out;

void NetLogger::set_level(int l)
{
    level_ = l;
}

void NetLogger::set_log_fun(log_func_t f)
{
    log_func_ = f;
}

void NetLogger::log_write(int level,
                          const char* filename,
                          int linenum,
                          const char* fmt, ...)
{
    if (level < level_) return;
    va_list ap;
    va_start(ap, fmt);
    log_out_valist(level, filename, linenum, fmt, ap);
    va_end(ap);
}

#define LOG_BUF_LEN       4096
void NetLogger::log_out_valist(int level,
                        const char* filename,
                        int linenum,
                        const char* fmt,
                        va_list ap)
{
    char buf[LOG_BUF_LEN];
    vsnprintf(buf, LOG_BUF_LEN, fmt, ap);
    log_func_(level, filename, linenum, buf);
}

void NetLogger::log_out(int level,
                        const char* filename,
                        int linenum,
                        const char* msg)
{
    printf("log_level=%d|%s|%d|%s\n", level, filename, linenum, msg);
}
<|endoftext|>


<commit_before>#include "GeoCoordinate.hpp"
#include "entities/Element.hpp"
#include "entities/Node.hpp"
#include "entities/Way.hpp"
#include "entities/Area.hpp"
#include "entities/Relation.hpp"
#include "index/ElementStore.hpp"
#include "mapcss/StyleProvider.hpp"
#include "test_utils/ElementUtils.hpp"
#include "test_utils/MapCssUtils.hpp"

#include <boost/test/unit_test.hpp>

#include <functional>
#include <initializer_list>
#include <utility>

using namespace utymap::entities;
using namespace utymap::index;
using namespace utymap::mapcss;

typedef std::function<void(const Element&, const utymap::QuadKey&)> StoreCallback;

class TestElementStore : public ElementStore
{
public:

    int times;

    TestElementStore(const StyleProvider& styleProvider, StringTable& stringTable, StoreCallback function) :
        ElementStore(styleProvider, stringTable),
        function_(function),
        times(0)
    {
    }

protected:
    void storeImpl(const Element& element, const utymap::QuadKey& quadKey)
    {
        times++;
        function_(element, quadKey);
    }
private:
    StoreCallback function_;
};

struct Index_ElementStoreFixture
{
    Index_ElementStoreFixture() :
        stringTablePtr(new StringTable("")),
        styleProviderPtr(nullptr),
        elementStorePtr()
    {
        BOOST_TEST_MESSAGE("setup fixture");
    }

    ~Index_ElementStoreFixture()
    {
        BOOST_TEST_MESSAGE("teardown fixture");
        BOOST_TEST_CHECK(elementStorePtr->times > 0);
        delete elementStorePtr;
        delete styleProviderPtr;
        delete stringTablePtr;
        std::remove("string.idx");
        std::remove("string.dat");
    }

    void createElementStore(std::string stylesheet, const StoreCallback callback)
    {
        styleProviderPtr = MapCssUtils::createStyleProviderFromString(*stringTablePtr, stylesheet);
        elementStorePtr = new TestElementStore(*styleProviderPtr, *stringTablePtr, callback);
    }

    StringTable* stringTablePtr;
    StyleProvider* styleProviderPtr;
    TestElementStore* elementStorePtr;
};

bool checkQuadKey(const utymap::QuadKey& quadKey, int lod, int tileX, int tileY)
{
    return quadKey.levelOfDetail == lod &&
           quadKey.tileX == tileX &&
           quadKey.tileY == tileY;
}

template<typename T>
void checkGeometry(const T& t, std::initializer_list<std::pair<double, double>> geometry)
{
    BOOST_CHECK_EQUAL(t.coordinates.size(), geometry.size());
    int i = 0;
    for (const auto& pair : geometry) {
        BOOST_CHECK_EQUAL(pair.first, t.coordinates[i].latitude);
        BOOST_CHECK_EQUAL(pair.second, t.coordinates[i].longitude);
        i++;
    }
}

BOOST_FIXTURE_TEST_SUITE(Index_ElementStore, Index_ElementStoreFixture)

BOOST_AUTO_TEST_CASE(GivenWayIntersectsTwoTilesOnce_WhenStore_GeometryIsClipped)
{
    Way way = ElementUtils::createElement<Way>(*stringTablePtr,
        { { "test", "Foo" } },
        { { 10, 10 }, { 10, -10 }});
    createElementStore("way|z1[test=Foo] { key:val; clip: true;}",
        [&](const Element& element, const utymap::QuadKey& quadKey) {
        if (checkQuadKey(quadKey, 1, 0, 0)) {
            checkGeometry<Way>(reinterpret_cast<const Way&>(element), { { 10, -10 }, { 10, 0 } });
        }
        else if (checkQuadKey(quadKey, 1, 1, 0)) {
            checkGeometry<Way>(reinterpret_cast<const Way&>(element), { { 10, 0 }, { 10, 10 } });
        }
        else {
            BOOST_TEST_FAIL("Unexpected quadKey!");
        }
    });

    elementStorePtr->store(way, LodRange(1,1));

    BOOST_CHECK_EQUAL(elementStorePtr->times, 2);
}

BOOST_AUTO_TEST_CASE(GivenWayIntersectsTwoTilesTwice_WhenStore_GeometryIsClipped)
{
    Way way = ElementUtils::createElement<Way>(*stringTablePtr,
    { { "test", "Foo" } },
    { { 10, 10 }, { 10, -10 }, { 20, -10 }, {20, 10} });
    createElementStore("way|z1[test=Foo] { key:val; clip: true;}",
        [&](const Element& element, const utymap::QuadKey& quadKey) {
        if (checkQuadKey(quadKey, 1, 0, 0)) {
            checkGeometry<Way>(reinterpret_cast<const Way&>(element), { { 20, 0 }, { 20, -10 }, { 10, -10 }, {10, 0} });
        }
        else if (checkQuadKey(quadKey, 1, 1, 0)) {
            const Relation& relation = reinterpret_cast<const Relation&>(element);
            BOOST_CHECK_EQUAL(relation.elements.size(), 2);
            checkGeometry<Way>(reinterpret_cast<const Way&>(*relation.elements[0]), { { 20, 10 }, { 20, 0 } });
            checkGeometry<Way>(reinterpret_cast<const Way&>(*relation.elements[1]), { { 10, 0 }, { 10, 10 } });
        }
        else {
            BOOST_TEST_FAIL("Unexpected quadKey!");
        }
    });

    elementStorePtr->store(way, LodRange(1, 1));

    BOOST_CHECK_EQUAL(elementStorePtr->times, 2);
}

BOOST_AUTO_TEST_CASE(GivenAreaIntersectsTwoTilesOnce_WhenStore_GeometryIsClipped)
{
    Area way = ElementUtils::createElement<Area>(*stringTablePtr,
    { { "test", "Foo" } },
    { { 10, 10 }, { 20, 10 }, { 20, -10 }, { 10, -10 } });
    createElementStore("area|z1[test=Foo] { key:val; clip: true;}",
        [&](const Element& element, const utymap::QuadKey& quadKey) {
        if (checkQuadKey(quadKey, 1, 0, 0)) {
            checkGeometry<Area>(reinterpret_cast<const Area&>(element), { { 20, 0 }, { 20, -10 }, {10, -10}, {10, 0} });
        }
        else if (checkQuadKey(quadKey, 1, 1, 0)) {
            checkGeometry<Area>(reinterpret_cast<const Area&>(element), { { 20, 10 }, { 20, 0 }, { 10, 0 }, { 10, 10 } });
        }
        else {
            BOOST_TEST_FAIL("Unexpected quadKey!");
        }
    });

    elementStorePtr->store(way, LodRange(1, 1));

    BOOST_CHECK_EQUAL(elementStorePtr->times, 2);
}

BOOST_AUTO_TEST_CASE(GivenAreaIntersectsTwoTilesTwice_WhenStore_GeometryIsClipped)
{
    Area way = ElementUtils::createElement<Area>(*stringTablePtr,
    { { "test", "Foo" } },
    { { 20, 10 }, { 20, -10 }, { 5, -10 }, { 5, 10 }, { 10, 10 }, { 10, -5 }, { 15, -5 }, { 15, 10 } });
    createElementStore("area|z1[test=Foo] { key:val; clip: true;}",
        [&](const Element& element, const utymap::QuadKey& quadKey) {
        if (checkQuadKey(quadKey, 1, 0, 0)) {
            checkGeometry<Area>(reinterpret_cast<const Area&>(element),
            { { 10, 0 }, { 10, -5 }, { 15, -5 }, { 15, 0 }, { 20, 0 }, { 20, -10 }, { 5, -10 }, { 5, 0 } });
        }
        else if (checkQuadKey(quadKey, 1, 1, 0)) {
            const Relation& relation = reinterpret_cast<const Relation&>(element);
            BOOST_CHECK_EQUAL(relation.elements.size(), 2);
            checkGeometry<Area>(reinterpret_cast<const Area&>(*relation.elements[0]), { { 15, 10 }, { 20, 10 }, { 20, 0 }, {15, 0} });
            checkGeometry<Area>(reinterpret_cast<const Area&>(*relation.elements[1]), { { 10, 10 }, { 10, 0 }, { 5, 0 }, { 5, 10 } });
        }
        else {
            BOOST_TEST_FAIL("Unexpected quadKey!");
        }
    });

    elementStorePtr->store(way, LodRange(1, 1));

    BOOST_CHECK_EQUAL(elementStorePtr->times, 2);
}

BOOST_AUTO_TEST_CASE(GivenAreaBiggerThanTile_WhenStore_GeometryIsEmpty)
{
    Area way = ElementUtils::createElement<Area>(*stringTablePtr,
    { { "test", "Foo" } },
    { { -10, -10 }, { -10, 181 }, { 91, 181 }, { 91, -10 } });
    createElementStore("area|z1[test=Foo] { key:val; clip: true;}",
        [&](const Element& element, const utymap::QuadKey& quadKey) {
        if (checkQuadKey(quadKey, 1, 1, 0)) {
            BOOST_CHECK_EQUAL(reinterpret_cast<const Area&>(element).coordinates.size(), 0);
        }
    });

    elementStorePtr->store(way, LodRange(1, 1));

    BOOST_CHECK_EQUAL(elementStorePtr->times, 4);
}

BOOST_AUTO_TEST_CASE(GivenRelationOfPolygonWithHole_WhenStore_AreaIsReturnedWithClippedGeometry)
{
    Area outer = ElementUtils::createElement<Area>(*stringTablePtr, {},
    { { 5, 10 }, { 20, 10 }, { 20, -10 }, {5, -10} });
    Area inner = ElementUtils::createElement<Area>(*stringTablePtr, {},
    { { 10, 5 }, { 15, 5 }, { 15, -5 }, { 10, -5 } });
    Relation relation;
    relation.tags = std::vector<Tag>{ ElementUtils::createTag(*stringTablePtr, "test", "Foo") };
    relation.elements.push_back(std::shared_ptr<Area>(new Area(inner)));
    relation.elements.push_back(std::shared_ptr<Area>(new Area(outer)));
    createElementStore("relation|z1[test=Foo] { key:val; clip: true;}",
        [&](const Element& element, const utymap::QuadKey& quadKey) {
        if (checkQuadKey(quadKey, 1, 1, 0)) {
            checkGeometry<Area>(reinterpret_cast<const Area&>(element),
            {
                { 20, 10 }, { 20, 0 }, { 15, 0 }, { 15, 5 }, { 10, 5 }, { 10, 0 }, { 5, 0 }, {5, 10}
            });
        } else if(checkQuadKey(quadKey, 1, 0, 0)) {
            checkGeometry<Area>(reinterpret_cast<const Area&>(element),
            {
                { 10, 0 }, { 10, -5 }, { 15, -5 }, { 15, 0 }, { 20, 0 }, { 20, -10 }, { 5, -10 }, { 5, 0 }
            });
        } else {
            BOOST_TEST_FAIL("Unexpected quadKey!");
        }
    });

    elementStorePtr->store(relation, LodRange(1, 1));

    BOOST_CHECK_EQUAL(elementStorePtr->times, 2);
}

BOOST_AUTO_TEST_CASE(GivenRelationOfPolygonWithHole_WhenStore_RelationIsReturnedWithClippedGeometry)
{
    Area outer = ElementUtils::createElement<Area>(*stringTablePtr, {},
    { { 5, 10 }, { 20, 10 }, { 20, -10 }, { 5, -10 } });
    Area inner = ElementUtils::createElement<Area>(*stringTablePtr, {},
    { { 10, 8 }, { 15, 8 }, { 15, 2 }, { 10, 2 } });
    Relation relation;
    relation.tags = std::vector<Tag>{ ElementUtils::createTag(*stringTablePtr, "test", "Foo") };
    relation.elements.push_back(std::shared_ptr<Area>(new Area(inner)));
    relation.elements.push_back(std::shared_ptr<Area>(new Area(outer)));
    createElementStore("relation|z1[test=Foo] { key:val; clip: true;}",
        [&](const Element& element, const utymap::QuadKey& quadKey) {
        if (checkQuadKey(quadKey, 1, 1, 0)) {
            const Relation& relation = reinterpret_cast<const Relation&>(element);
            BOOST_CHECK_EQUAL(relation.elements.size(), 2);
            checkGeometry<Area>(reinterpret_cast<const Area&>(*relation.elements[0]), { { 20, 10 }, { 20, 0 }, { 5, 0 }, { 5, 10 } });
            checkGeometry<Area>(reinterpret_cast<const Area&>(*relation.elements[1]), { { 10, 2 }, { 15, 2 }, { 15, 8 }, { 10, 8 } });
        }
        else if (checkQuadKey(quadKey, 1, 0, 0)) {
            checkGeometry<Area>(reinterpret_cast<const Area&>(element),
            {
                { 20, 0 }, { 20, -10 }, { 5, -10 }, { 5, 0 }
            });
        }
        else {
            BOOST_TEST_FAIL("Unexpected quadKey!");
        }
    });

    elementStorePtr->store(relation, LodRange(1, 1));

    BOOST_CHECK_EQUAL(elementStorePtr->times, 2);
}

BOOST_AUTO_TEST_SUITE_END()<commit_msg>refactoring: minor code style<commit_after>#include "GeoCoordinate.hpp"
#include "entities/Element.hpp"
#include "entities/Node.hpp"
#include "entities/Way.hpp"
#include "entities/Area.hpp"
#include "entities/Relation.hpp"
#include "index/ElementStore.hpp"
#include "mapcss/StyleProvider.hpp"
#include "test_utils/ElementUtils.hpp"
#include "test_utils/MapCssUtils.hpp"

#include <boost/test/unit_test.hpp>

#include <functional>
#include <initializer_list>
#include <utility>

using namespace utymap::entities;
using namespace utymap::index;
using namespace utymap::mapcss;

typedef std::function<void(const Element&, const utymap::QuadKey&)> StoreCallback;

class TestElementStore : public ElementStore
{
public:

    int times;

    TestElementStore(const StyleProvider& styleProvider, StringTable& stringTable, StoreCallback function) :
        ElementStore(styleProvider, stringTable),
        function_(function),
        times(0)
    {
    }

protected:
    void storeImpl(const Element& element, const utymap::QuadKey& quadKey)
    {
        times++;
        function_(element, quadKey);
    }
private:
    StoreCallback function_;
};

struct Index_ElementStoreFixture
{
    Index_ElementStoreFixture() :
        stringTablePtr(new StringTable("")),
        styleProviderPtr(nullptr),
        elementStorePtr()
    {
        BOOST_TEST_MESSAGE("setup fixture");
    }

    ~Index_ElementStoreFixture()
    {
        BOOST_TEST_MESSAGE("teardown fixture");
        BOOST_TEST_CHECK(elementStorePtr->times > 0);
        delete elementStorePtr;
        delete styleProviderPtr;
        delete stringTablePtr;
        std::remove("string.idx");
        std::remove("string.dat");
    }

    void createElementStore(std::string stylesheet, const StoreCallback callback)
    {
        styleProviderPtr = MapCssUtils::createStyleProviderFromString(*stringTablePtr, stylesheet);
        elementStorePtr = new TestElementStore(*styleProviderPtr, *stringTablePtr, callback);
    }

    StringTable* stringTablePtr;
    StyleProvider* styleProviderPtr;
    TestElementStore* elementStorePtr;
};

bool checkQuadKey(const utymap::QuadKey& quadKey, int lod, int tileX, int tileY)
{
    return quadKey.levelOfDetail == lod &&
           quadKey.tileX == tileX &&
           quadKey.tileY == tileY;
}

template<typename T>
void checkGeometry(const T& t, std::initializer_list<std::pair<double, double>> geometry)
{
    BOOST_CHECK_EQUAL(t.coordinates.size(), geometry.size());
    int i = 0;
    for (const auto& pair : geometry) {
        BOOST_CHECK_EQUAL(pair.first, t.coordinates[i].latitude);
        BOOST_CHECK_EQUAL(pair.second, t.coordinates[i].longitude);
        i++;
    }
}

BOOST_FIXTURE_TEST_SUITE(Index_ElementStore, Index_ElementStoreFixture)

BOOST_AUTO_TEST_CASE(GivenWayIntersectsTwoTilesOnce_WhenStore_GeometryIsClipped)
{
    Way way = ElementUtils::createElement<Way>(*stringTablePtr,
        { { "test", "Foo" } },
        { { 10, 10 }, { 10, -10 }});
    createElementStore("way|z1[test=Foo] { key:val; clip: true;}",
        [&](const Element& element, const utymap::QuadKey& quadKey) {
        if (checkQuadKey(quadKey, 1, 0, 0)) {
            checkGeometry<Way>(reinterpret_cast<const Way&>(element), { { 10, -10 }, { 10, 0 } });
        }
        else if (checkQuadKey(quadKey, 1, 1, 0)) {
            checkGeometry<Way>(reinterpret_cast<const Way&>(element), { { 10, 0 }, { 10, 10 } });
        }
        else {
            BOOST_TEST_FAIL("Unexpected quadKey!");
        }
    });

    elementStorePtr->store(way, LodRange(1,1));

    BOOST_CHECK_EQUAL(elementStorePtr->times, 2);
}

BOOST_AUTO_TEST_CASE(GivenWayIntersectsTwoTilesTwice_WhenStore_GeometryIsClipped)
{
    Way way = ElementUtils::createElement<Way>(*stringTablePtr,
    { { "test", "Foo" } },
    { { 10, 10 }, { 10, -10 }, { 20, -10 }, {20, 10} });
    createElementStore("way|z1[test=Foo] { key:val; clip: true;}",
        [&](const Element& element, const utymap::QuadKey& quadKey) {
        if (checkQuadKey(quadKey, 1, 0, 0)) {
            checkGeometry<Way>(reinterpret_cast<const Way&>(element), { { 20, 0 }, { 20, -10 }, { 10, -10 }, {10, 0} });
        }
        else if (checkQuadKey(quadKey, 1, 1, 0)) {
            const Relation& relation = reinterpret_cast<const Relation&>(element);
            BOOST_CHECK_EQUAL(relation.elements.size(), 2);
            checkGeometry<Way>(reinterpret_cast<const Way&>(*relation.elements[0]), { { 20, 10 }, { 20, 0 } });
            checkGeometry<Way>(reinterpret_cast<const Way&>(*relation.elements[1]), { { 10, 0 }, { 10, 10 } });
        }
        else {
            BOOST_TEST_FAIL("Unexpected quadKey!");
        }
    });

    elementStorePtr->store(way, LodRange(1, 1));

    BOOST_CHECK_EQUAL(elementStorePtr->times, 2);
}

BOOST_AUTO_TEST_CASE(GivenAreaIntersectsTwoTilesOnce_WhenStore_GeometryIsClipped)
{
    Area way = ElementUtils::createElement<Area>(*stringTablePtr,
    { { "test", "Foo" } },
    { { 10, 10 }, { 20, 10 }, { 20, -10 }, { 10, -10 } });
    createElementStore("area|z1[test=Foo] { key:val; clip: true;}",
        [&](const Element& element, const utymap::QuadKey& quadKey) {
        if (checkQuadKey(quadKey, 1, 0, 0)) {
            checkGeometry<Area>(reinterpret_cast<const Area&>(element), { { 20, 0 }, { 20, -10 }, {10, -10}, {10, 0} });
        }
        else if (checkQuadKey(quadKey, 1, 1, 0)) {
            checkGeometry<Area>(reinterpret_cast<const Area&>(element), { { 20, 10 }, { 20, 0 }, { 10, 0 }, { 10, 10 } });
        }
        else {
            BOOST_TEST_FAIL("Unexpected quadKey!");
        }
    });

    elementStorePtr->store(way, LodRange(1, 1));

    BOOST_CHECK_EQUAL(elementStorePtr->times, 2);
}

BOOST_AUTO_TEST_CASE(GivenAreaIntersectsTwoTilesTwice_WhenStore_GeometryIsClipped)
{
    Area way = ElementUtils::createElement<Area>(*stringTablePtr,
    { { "test", "Foo" } },
    { { 20, 10 }, { 20, -10 }, { 5, -10 }, { 5, 10 }, { 10, 10 }, { 10, -5 }, { 15, -5 }, { 15, 10 } });
    createElementStore("area|z1[test=Foo] { key:val; clip: true;}",
        [&](const Element& element, const utymap::QuadKey& quadKey) {
        if (checkQuadKey(quadKey, 1, 0, 0)) {
            checkGeometry<Area>(reinterpret_cast<const Area&>(element),
            { { 10, 0 }, { 10, -5 }, { 15, -5 }, { 15, 0 }, { 20, 0 }, { 20, -10 }, { 5, -10 }, { 5, 0 } });
        }
        else if (checkQuadKey(quadKey, 1, 1, 0)) {
            const Relation& relation = reinterpret_cast<const Relation&>(element);
            BOOST_CHECK_EQUAL(relation.elements.size(), 2);
            checkGeometry<Area>(reinterpret_cast<const Area&>(*relation.elements[0]), { { 15, 10 }, { 20, 10 }, { 20, 0 }, {15, 0} });
            checkGeometry<Area>(reinterpret_cast<const Area&>(*relation.elements[1]), { { 10, 10 }, { 10, 0 }, { 5, 0 }, { 5, 10 } });
        }
        else {
            BOOST_TEST_FAIL("Unexpected quadKey!");
        }
    });

    elementStorePtr->store(way, LodRange(1, 1));

    BOOST_CHECK_EQUAL(elementStorePtr->times, 2);
}

BOOST_AUTO_TEST_CASE(GivenAreaBiggerThanTile_WhenStore_GeometryIsEmpty)
{
    Area way = ElementUtils::createElement<Area>(*stringTablePtr,
    { { "test", "Foo" } },
    { { -10, -10 }, { -10, 181 }, { 91, 181 }, { 91, -10 } });
    createElementStore("area|z1[test=Foo] { key:val; clip: true;}",
        [&](const Element& element, const utymap::QuadKey& quadKey) {
        if (checkQuadKey(quadKey, 1, 1, 0)) {
            BOOST_CHECK_EQUAL(reinterpret_cast<const Area&>(element).coordinates.size(), 0);
        }
    });

    elementStorePtr->store(way, LodRange(1, 1));

    BOOST_CHECK_EQUAL(elementStorePtr->times, 4);
}

BOOST_AUTO_TEST_CASE(GivenRelationOfPolygonWithHole_WhenStore_AreaIsReturnedWithClippedGeometry)
{
    Area outer = ElementUtils::createElement<Area>(*stringTablePtr, {},
    { { 5, 10 }, { 20, 10 }, { 20, -10 }, {5, -10} });
    Area inner = ElementUtils::createElement<Area>(*stringTablePtr, {},
    { { 10, 5 }, { 15, 5 }, { 15, -5 }, { 10, -5 } });
    Relation relation;
    relation.tags = std::vector<Tag>{ ElementUtils::createTag(*stringTablePtr, "test", "Foo") };
    relation.elements.push_back(std::shared_ptr<Area>(new Area(inner)));
    relation.elements.push_back(std::shared_ptr<Area>(new Area(outer)));
    createElementStore("relation|z1[test=Foo] { key:val; clip: true;}",
        [&](const Element& element, const utymap::QuadKey& quadKey) {
        if (checkQuadKey(quadKey, 1, 1, 0)) {
            checkGeometry<Area>(reinterpret_cast<const Area&>(element),
            {
                { 20, 10 }, { 20, 0 }, { 15, 0 }, { 15, 5 }, { 10, 5 }, { 10, 0 }, { 5, 0 }, {5, 10}
            });
        } else if(checkQuadKey(quadKey, 1, 0, 0)) {
            checkGeometry<Area>(reinterpret_cast<const Area&>(element),
            {
                { 10, 0 }, { 10, -5 }, { 15, -5 }, { 15, 0 }, { 20, 0 }, { 20, -10 }, { 5, -10 }, { 5, 0 }
            });
        } else {
            BOOST_TEST_FAIL("Unexpected quadKey!");
        }
    });

    elementStorePtr->store(relation, LodRange(1, 1));

    BOOST_CHECK_EQUAL(elementStorePtr->times, 2);
}

BOOST_AUTO_TEST_CASE(GivenRelationOfPolygonWithHole_WhenStore_RelationIsReturnedWithClippedGeometry)
{
    Area outer = ElementUtils::createElement<Area>(*stringTablePtr, {},
    { { 5, 10 }, { 20, 10 }, { 20, -10 }, { 5, -10 } });
    Area inner = ElementUtils::createElement<Area>(*stringTablePtr, {},
    { { 10, 8 }, { 15, 8 }, { 15, 2 }, { 10, 2 } });
    Relation relation;
    relation.tags = std::vector<Tag>{ ElementUtils::createTag(*stringTablePtr, "test", "Foo") };
    relation.elements.push_back(std::shared_ptr<Area>(new Area(inner)));
    relation.elements.push_back(std::shared_ptr<Area>(new Area(outer)));
    createElementStore("relation|z1[test=Foo] { key:val; clip: true;}",
        [&](const Element& element, const utymap::QuadKey& quadKey) {
        if (checkQuadKey(quadKey, 1, 1, 0)) {
            const Relation& relation = reinterpret_cast<const Relation&>(element);
            BOOST_CHECK_EQUAL(relation.elements.size(), 2);
            checkGeometry<Area>(reinterpret_cast<const Area&>(*relation.elements[0]), { { 20, 10 }, { 20, 0 }, { 5, 0 }, { 5, 10 } });
            checkGeometry<Area>(reinterpret_cast<const Area&>(*relation.elements[1]), { { 10, 2 }, { 15, 2 }, { 15, 8 }, { 10, 8 } });
        }
        else if (checkQuadKey(quadKey, 1, 0, 0)) {
            checkGeometry<Area>(reinterpret_cast<const Area&>(element), { { 20, 0 }, { 20, -10 }, { 5, -10 }, { 5, 0 } });
        }
        else {
            BOOST_TEST_FAIL("Unexpected quadKey!");
        }
    });

    elementStorePtr->store(relation, LodRange(1, 1));

    BOOST_CHECK_EQUAL(elementStorePtr->times, 2);
}

BOOST_AUTO_TEST_SUITE_END()<|endoftext|>


<commit_before>#include <boost/smart_ptr/shared_ptr.hpp>

#include "locks.h"

hLockTicket::hLockTicket(pmutexPtr lock, bool locked)
{
	m_lock = lock;
	if (!locked)
	{
		pthread_mutex_lock(m_lock.get());
		m_locked = 1;
	}
}

hLockTicket::hLockTicket(const hLockTicket &a)
{
	m_locked = 1;
	m_lock = a.m_lock;
}

hLockTicket::~hLockTicket()
{
	if (m_locked.load())
		pthread_mutex_unlock(m_lock.get());
}

void hLockTicket::unlock()
{
	if (m_locked.load())
	{
		pthread_mutex_unlock(m_lock.get());
		m_locked = 0;
	}
}

hAutoLock::hAutoLock()
{
	m_lock.reset(new pmutex);
}

hAutoLock::~hAutoLock()
{
}

hLockTicketPtr hAutoLock::lock()
{
	return hLockTicketPtr(new hLockTicket(m_lock, false));
}

hLockTicketPtr hAutoLock::tryLock()
{
	if (pthread_mutex_trylock(m_lock.get()) == 0) {
		return hLockTicketPtr(new hLockTicket (m_lock, true));
	}
	hLockTicketPtr empty_ticket;
	return empty_ticket;
}

hLock& hLock::operator=(const hLock &a)
{
	return *this;
}

hLock::hLock()
{
	pthread_mutex_init(&m, 0);
}

hLock::~hLock()
{

}

void hLock::lock()
{
	pthread_mutex_lock(&m);
}

bool hLock::trylock()
{
	return pthread_mutex_trylock(&m) == 0;
}

void hLock::unlock()
{
	pthread_mutex_unlock(&m);
}

hCondWaiter::hCondWaiter(boost::function<bool()> stateReachedFunc)
{
	pthread_mutex_init(&m_lock, 0);
	pthread_cond_init(&cond, 0);
	m_state_ok = stateReachedFunc;
}

void hCondWaiter::wait()
{
	pthread_mutex_lock(&m_lock);

	while (!m_state_ok())
	{
		pthread_cond_wait(&cond, &m_lock);
	}

	pthread_cond_destroy(&cond);
	pthread_cond_init(&cond, 0);

	pthread_mutex_unlock(&m_lock);
}

void hCondWaiter::lock()
{
	pthread_mutex_lock(&m_lock);
}

void hCondWaiter::unlock()
{
	pthread_mutex_unlock(&m_lock);
}

void hCondWaiter::kick()
{
	pthread_cond_signal(&cond);
}

hRWLockRead::hRWLockRead(pthread_rwlock_t *lock)
{
	m_lock = lock;
	pthread_rwlock_rdlock(m_lock);
}

hRWLockRead::~hRWLockRead()
{
	pthread_rwlock_unlock(m_lock);
}

hRWLockRead::hRWLockRead(const hRWLockRead &a)
{
	this->m_lock = a.m_lock;
}

void hRWLockRead::unlock()
{
	pthread_rwlock_unlock(m_lock);
}

hRWLockWrite::hRWLockWrite(pthread_rwlock_t *lock)
{
	m_lock = lock;
	m_locked = 1;
	pthread_rwlock_wrlock(m_lock);
}

hRWLockWrite::~hRWLockWrite()
{
	if (m_locked.load())
	pthread_rwlock_unlock(m_lock);
}

hRWLockWrite::hRWLockWrite(const hRWLockWrite &a)
{
	m_lock = a.m_lock;
	m_locked = a.m_locked.load();
}

void hRWLockWrite::unlock()
{
	m_locked = 0;
	pthread_rwlock_unlock(m_lock);
}

hRWLock::hRWLock()
{
	m_lock = new pthread_rwlock_t;
	pthread_rwlock_init(m_lock, 0);
}

hRWLock::~hRWLock()
{
	delete m_lock;
}

hRWLockRead hRWLock::read()
{
	return hRWLockRead(m_lock);
}

hRWLockWrite hRWLock::write()
{
	return hRWLockWrite(m_lock);
}<commit_msg>lock fix<commit_after>#include <boost/smart_ptr/shared_ptr.hpp>

#include "locks.h"

hLockTicket::hLockTicket(pmutexPtr lock, bool locked)
{
	m_lock = lock;
	m_locked = locked;
	if (!locked)
	{
		pthread_mutex_lock(m_lock.get());
		m_locked = 1;
	}
}

hLockTicket::hLockTicket(const hLockTicket &a)
{
	m_locked = a.m_locked.load();
	m_lock = a.m_lock;
}

hLockTicket::~hLockTicket()
{
	if (m_locked.load())
	{
		//std::cout << "Realesing AutoLock\n";
		pthread_mutex_unlock(m_lock.get());
	}
}

void hLockTicket::unlock()
{
	if (m_locked.load())
	{
		pthread_mutex_unlock(m_lock.get());
		m_locked = 0;
	}
}

hAutoLock::hAutoLock()
{
	m_lock.reset(new pmutex);
	pthread_mutex_init(m_lock.get(), 0);
}

hAutoLock::~hAutoLock()
{
}

hLockTicketPtr hAutoLock::lock()
{
	return hLockTicketPtr(new hLockTicket(m_lock, false));
}

hLockTicketPtr hAutoLock::tryLock()
{
	if (pthread_mutex_trylock(m_lock.get()) == 0) {
		//std::cout << "Taken AutoLock\n";
		return hLockTicketPtr(new hLockTicket (m_lock, true));
	}
	//std::cout << "Lock not taken\n";
	hLockTicketPtr empty_ticket;
	return empty_ticket;
}

hLock& hLock::operator=(const hLock &a)
{
	return *this;
}

hLock::hLock()
{
	pthread_mutex_init(&m, 0);
}

hLock::~hLock()
{

}

void hLock::lock()
{
	pthread_mutex_lock(&m);
}

bool hLock::trylock()
{
	return pthread_mutex_trylock(&m) == 0;
}

void hLock::unlock()
{
	pthread_mutex_unlock(&m);
}

hCondWaiter::hCondWaiter(boost::function<bool()> stateReachedFunc)
{
	pthread_mutex_init(&m_lock, 0);
	pthread_cond_init(&cond, 0);
	m_state_ok = stateReachedFunc;
}

void hCondWaiter::wait()
{
	pthread_mutex_lock(&m_lock);

	while (!m_state_ok())
	{
		pthread_cond_wait(&cond, &m_lock);
	}

	pthread_cond_destroy(&cond);
	pthread_cond_init(&cond, 0);

	pthread_mutex_unlock(&m_lock);
}

void hCondWaiter::lock()
{
	pthread_mutex_lock(&m_lock);
}

void hCondWaiter::unlock()
{
	pthread_mutex_unlock(&m_lock);
}

void hCondWaiter::kick()
{
	pthread_cond_signal(&cond);
}

hRWLockRead::hRWLockRead(pthread_rwlock_t *lock)
{
	m_lock = lock;
	pthread_rwlock_rdlock(m_lock);
}

hRWLockRead::~hRWLockRead()
{
	pthread_rwlock_unlock(m_lock);
}

hRWLockRead::hRWLockRead(const hRWLockRead &a)
{
	this->m_lock = a.m_lock;
}

void hRWLockRead::unlock()
{
	pthread_rwlock_unlock(m_lock);
}

hRWLockWrite::hRWLockWrite(pthread_rwlock_t *lock)
{
	m_lock = lock;
	m_locked = 1;
	pthread_rwlock_wrlock(m_lock);
}

hRWLockWrite::~hRWLockWrite()
{
	if (m_locked.load())
	pthread_rwlock_unlock(m_lock);
}

hRWLockWrite::hRWLockWrite(const hRWLockWrite &a)
{
	m_lock = a.m_lock;
	m_locked = a.m_locked.load();
}

void hRWLockWrite::unlock()
{
	m_locked = 0;
	pthread_rwlock_unlock(m_lock);
}

hRWLock::hRWLock()
{
	m_lock = new pthread_rwlock_t;
	pthread_rwlock_init(m_lock, 0);
}

hRWLock::~hRWLock()
{
	delete m_lock;
}

hRWLockRead hRWLock::read()
{
	return hRWLockRead(m_lock);
}

hRWLockWrite hRWLock::write()
{
	return hRWLockWrite(m_lock);
}<|endoftext|>