<commit_before>#include "gtest/gtest.h"
#include "motor_shield.h"

#define SPEED_L 1
#define DIR_L 2

#define SPEED_R 3
#define DIR_R 4

MotorShield mshield(SPEED_L, DIR_L, SPEED_R, DIR_R);

TEST(MotorShield, Initialization) {
  ASSERT_EQ(0, mshield.getMinSpeed());
  ASSERT_EQ(255, mshield.getMaxSpeed());

  ASSERT_EQ(SPEED_L, mshield.getLeftSpeedPin());
  ASSERT_EQ(SPEED_R, mshield.getRightSpeedPin());

  ASSERT_EQ(DIR_L, mshield.getLeftDirPin());
  ASSERT_EQ(DIR_R, mshield.getRightDirPin());
}

TEST(MotorShield, Setup) {
  ArduinoMock mock;

  EXPECT_CALL(mock, pinMode(SPEED_L, OUTPUT));
  EXPECT_CALL(mock, pinMode(DIR_L, OUTPUT));
  EXPECT_CALL(mock, pinMode(SPEED_R, OUTPUT));
  EXPECT_CALL(mock, pinMode(DIR_R, OUTPUT));

  EXPECT_CALL(mock, analogWrite(SPEED_L, 0));
  EXPECT_CALL(mock, analogWrite(SPEED_R, 0));

  EXPECT_CALL(mock, digitalWrite(DIR_L, LOW));
  EXPECT_CALL(mock, digitalWrite(DIR_R, LOW));

  mshield.init();
}
<commit_msg>Add tests for all methods<commit_after>#include "gtest/gtest.h"
#include "motor_shield.h"

#define SPEED_L 1
#define DIR_L 2

#define SPEED_R 3
#define DIR_R 4

MotorShield mshield(SPEED_L, DIR_L, SPEED_R, DIR_R);

TEST(MotorShield, Initialization) {
  ASSERT_EQ(0, mshield.getMinSpeed());
  ASSERT_EQ(255, mshield.getMaxSpeed());

  ASSERT_EQ(SPEED_L, mshield.getLeftSpeedPin());
  ASSERT_EQ(SPEED_R, mshield.getRightSpeedPin());

  ASSERT_EQ(DIR_L, mshield.getLeftDirPin());
  ASSERT_EQ(DIR_R, mshield.getRightDirPin());
}

TEST(MotorShield, Setup) {
  ArduinoMock mock;

  EXPECT_CALL(mock, pinMode(SPEED_L, OUTPUT));
  EXPECT_CALL(mock, pinMode(DIR_L, OUTPUT));
  EXPECT_CALL(mock, pinMode(SPEED_R, OUTPUT));
  EXPECT_CALL(mock, pinMode(DIR_R, OUTPUT));

  EXPECT_CALL(mock, analogWrite(SPEED_L, 0));
  EXPECT_CALL(mock, analogWrite(SPEED_R, 0));

  EXPECT_CALL(mock, digitalWrite(DIR_L, LOW));
  EXPECT_CALL(mock, digitalWrite(DIR_R, LOW));

  mshield.init();
}

TEST(MotorShield, Forward) {
  ArduinoMock mock;

  EXPECT_CALL(mock, digitalWrite(DIR_L, LOW));
  EXPECT_CALL(mock, digitalWrite(DIR_R, LOW));

  mshield.forward();
}

TEST(MotorShield, Backward) {
  ArduinoMock mock;

  EXPECT_CALL(mock, digitalWrite(DIR_L, HIGH));
  EXPECT_CALL(mock, digitalWrite(DIR_R, HIGH));

  mshield.backward();
}

TEST(MotorShield, Stop) {
  ArduinoMock mock;

  EXPECT_CALL(mock, analogWrite(SPEED_L, 0));
  EXPECT_CALL(mock, analogWrite(SPEED_R, 0));

  mshield.stop();
}

TEST(MotorShield, FullSpeed) {
  ArduinoMock mock;

  EXPECT_CALL(mock, analogWrite(SPEED_L, 255));
  EXPECT_CALL(mock, analogWrite(SPEED_R, 255));

  mshield.fullSpeed();
}

TEST(MotorShield, StopLeft) {
  ArduinoMock mock;

  EXPECT_CALL(mock, analogWrite(SPEED_L, 0));

  mshield.stopLeft();
}

TEST(MotorShield, StopRight) {
  ArduinoMock mock;

  EXPECT_CALL(mock, analogWrite(SPEED_R, 0));

  mshield.stopRight();
}
<|endoftext|>


<commit_before>// Copyright (c) 2011 The LevelDB Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file. See the AUTHORS file for names of contributors.
//
// Decodes the blocks generated by block_builder.cc.

#include "table/block.h"

#include <vector>
#include <algorithm>
#include "leveldb/comparator.h"
#include "util/coding.h"
#include "util/logging.h"

namespace leveldb {

inline uint32_t Block::NumRestarts() const {
  assert(size_ >= 2*sizeof(uint32_t));
  return DecodeFixed32(data_ + size_ - sizeof(uint32_t));
}

Block::Block(const char* data, size_t size)
    : data_(data),
      size_(size) {
  if (size_ < sizeof(uint32_t)) {
    size_ = 0;  // Error marker
  } else {
    restart_offset_ = size_ - (1 + NumRestarts()) * sizeof(uint32_t);
    if (restart_offset_ > size_ - sizeof(uint32_t)) {
      // The size is too small for NumRestarts() and therefore
      // restart_offset_ wrapped around.
      size_ = 0;
    }
  }
}

Block::~Block() {
  delete[] data_;
}

// Helper routine: decode the next block entry starting at "p",
// storing the number of shared key bytes, non_shared key bytes,
// and the length of the value in "*shared", "*non_shared", and
// "*value_length", respectively.  Will not derefence past "limit".
//
// If any errors are detected, returns NULL.  Otherwise, returns a
// pointer to the key delta (just past the three decoded values).
static inline const char* DecodeEntry(const char* p, const char* limit,
                                      uint32_t* shared,
                                      uint32_t* non_shared,
                                      uint32_t* value_length) {
  if (limit - p < 3) return NULL;
  *shared = reinterpret_cast<const unsigned char*>(p)[0];
  *non_shared = reinterpret_cast<const unsigned char*>(p)[1];
  *value_length = reinterpret_cast<const unsigned char*>(p)[2];
  if ((*shared | *non_shared | *value_length) < 128) {
    // Fast path: all three values are encoded in one byte each
    p += 3;
  } else {
    if ((p = GetVarint32Ptr(p, limit, shared)) == NULL) return NULL;
    if ((p = GetVarint32Ptr(p, limit, non_shared)) == NULL) return NULL;
    if ((p = GetVarint32Ptr(p, limit, value_length)) == NULL) return NULL;
  }

  if (static_cast<uint32>(limit - p) < (*non_shared + *value_length)) {
    return NULL;
  }
  return p;
}

class Block::Iter : public Iterator {
 private:
  const Comparator* const comparator_;
  const char* const data_;      // underlying block contents
  uint32_t const restarts_;     // Offset of restart array (list of fixed32)
  uint32_t const num_restarts_; // Number of uint32_t entries in restart array

  // current_ is offset in data_ of current entry.  >= restarts_ if !Valid
  uint32_t current_;
  uint32_t restart_index_;  // Index of restart block in which current_ falls
  std::string key_;
  Slice value_;
  Status status_;

  inline int Compare(const Slice& a, const Slice& b) const {
    return comparator_->Compare(a, b);
  }

  // Return the offset in data_ just past the end of the current entry.
  inline uint32_t NextEntryOffset() const {
    return (value_.data() + value_.size()) - data_;
  }

  uint32_t GetRestartPoint(uint32_t index) {
    assert(index < num_restarts_);
    return DecodeFixed32(data_ + restarts_ + index * sizeof(uint32_t));
  }

  void SeekToRestartPoint(uint32_t index) {
    key_.clear();
    restart_index_ = index;
    // current_ will be fixed by ParseNextKey();

    // ParseNextKey() starts at the end of value_, so set value_ accordingly
    uint32_t offset = GetRestartPoint(index);
    value_ = Slice(data_ + offset, 0);
  }

 public:
  Iter(const Comparator* comparator,
       const char* data,
       uint32_t restarts,
       uint32_t num_restarts)
      : comparator_(comparator),
        data_(data),
        restarts_(restarts),
        num_restarts_(num_restarts),
        current_(restarts_),
        restart_index_(num_restarts_) {
    assert(num_restarts_ > 0);
  }

  virtual bool Valid() const { return current_ < restarts_; }
  virtual Status status() const { return status_; }
  virtual Slice key() const {
    assert(Valid());
    return key_;
  }
  virtual Slice value() const {
    assert(Valid());
    return value_;
  }

  virtual void Next() {
    assert(Valid());
    ParseNextKey();
  }

  virtual void Prev() {
    assert(Valid());

    // Scan backwards to a restart point before current_
    const uint32_t original = current_;
    while (GetRestartPoint(restart_index_) >= original) {
      if (restart_index_ == 0) {
        // No more entries
        current_ = restarts_;
        restart_index_ = num_restarts_;
        return;
      }
      restart_index_--;
    }

    SeekToRestartPoint(restart_index_);
    do {
      // Loop until end of current entry hits the start of original entry
    } while (ParseNextKey() && NextEntryOffset() < original);
  }

  virtual void Seek(const Slice& target) {
    // Binary search in restart array to find the first restart point
    // with a key >= target
    uint32_t left = 0;
    uint32_t right = num_restarts_ - 1;
    while (left < right) {
      uint32_t mid = (left + right + 1) / 2;
      uint32_t region_offset = GetRestartPoint(mid);
      uint32_t shared, non_shared, value_length;
      const char* key_ptr = DecodeEntry(data_ + region_offset,
                                        data_ + restarts_,
                                        &shared, &non_shared, &value_length);
      if (key_ptr == NULL || (shared != 0)) {
        CorruptionError();
        return;
      }
      Slice mid_key(key_ptr, non_shared);
      if (Compare(mid_key, target) < 0) {
        // Key at "mid" is smaller than "target".  Therefore all
        // blocks before "mid" are uninteresting.
        left = mid;
      } else {
        // Key at "mid" is >= "target".  Therefore all blocks at or
        // after "mid" are uninteresting.
        right = mid - 1;
      }
    }

    // Linear search (within restart block) for first key >= target
    SeekToRestartPoint(left);
    while (true) {
      if (!ParseNextKey()) {
        return;
      }
      if (Compare(key_, target) >= 0) {
        return;
      }
    }
  }

  virtual void SeekToFirst() {
    SeekToRestartPoint(0);
    ParseNextKey();
  }

  virtual void SeekToLast() {
    SeekToRestartPoint(num_restarts_ - 1);
    while (ParseNextKey() && NextEntryOffset() < restarts_) {
      // Keep skipping
    }
  }

 private:
  void CorruptionError() {
    current_ = restarts_;
    restart_index_ = num_restarts_;
    status_ = Status::Corruption("bad entry in block");
    key_.clear();
    value_.clear();
  }

  bool ParseNextKey() {
    current_ = NextEntryOffset();
    const char* p = data_ + current_;
    const char* limit = data_ + restarts_;  // Restarts come right after data
    if (p >= limit) {
      // No more entries to return.  Mark as invalid.
      current_ = restarts_;
      restart_index_ = num_restarts_;
      return false;
    }

    // Decode next entry
    uint32_t shared, non_shared, value_length;
    p = DecodeEntry(p, limit, &shared, &non_shared, &value_length);
    if (p == NULL || key_.size() < shared) {
      CorruptionError();
      return false;
    } else {
      key_.resize(shared);
      key_.append(p, non_shared);
      value_ = Slice(p + non_shared, value_length);
      while (restart_index_ + 1 < num_restarts_ &&
             GetRestartPoint(restart_index_ + 1) < current_) {
        ++restart_index_;
      }
      return true;
    }
  }
};

Iterator* Block::NewIterator(const Comparator* cmp) {
  if (size_ < 2*sizeof(uint32_t)) {
    return NewErrorIterator(Status::Corruption("bad block contents"));
  }
  const uint32_t num_restarts = NumRestarts();
  if (num_restarts == 0) {
    return NewEmptyIterator();
  } else {
    return new Iter(cmp, data_, restart_offset_, num_restarts);
  }
}

}
<commit_msg>fix build on at least linux<commit_after>// Copyright (c) 2011 The LevelDB Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file. See the AUTHORS file for names of contributors.
//
// Decodes the blocks generated by block_builder.cc.

#include "table/block.h"

#include <vector>
#include <algorithm>
#include "leveldb/comparator.h"
#include "util/coding.h"
#include "util/logging.h"

namespace leveldb {

inline uint32_t Block::NumRestarts() const {
  assert(size_ >= 2*sizeof(uint32_t));
  return DecodeFixed32(data_ + size_ - sizeof(uint32_t));
}

Block::Block(const char* data, size_t size)
    : data_(data),
      size_(size) {
  if (size_ < sizeof(uint32_t)) {
    size_ = 0;  // Error marker
  } else {
    restart_offset_ = size_ - (1 + NumRestarts()) * sizeof(uint32_t);
    if (restart_offset_ > size_ - sizeof(uint32_t)) {
      // The size is too small for NumRestarts() and therefore
      // restart_offset_ wrapped around.
      size_ = 0;
    }
  }
}

Block::~Block() {
  delete[] data_;
}

// Helper routine: decode the next block entry starting at "p",
// storing the number of shared key bytes, non_shared key bytes,
// and the length of the value in "*shared", "*non_shared", and
// "*value_length", respectively.  Will not derefence past "limit".
//
// If any errors are detected, returns NULL.  Otherwise, returns a
// pointer to the key delta (just past the three decoded values).
static inline const char* DecodeEntry(const char* p, const char* limit,
                                      uint32_t* shared,
                                      uint32_t* non_shared,
                                      uint32_t* value_length) {
  if (limit - p < 3) return NULL;
  *shared = reinterpret_cast<const unsigned char*>(p)[0];
  *non_shared = reinterpret_cast<const unsigned char*>(p)[1];
  *value_length = reinterpret_cast<const unsigned char*>(p)[2];
  if ((*shared | *non_shared | *value_length) < 128) {
    // Fast path: all three values are encoded in one byte each
    p += 3;
  } else {
    if ((p = GetVarint32Ptr(p, limit, shared)) == NULL) return NULL;
    if ((p = GetVarint32Ptr(p, limit, non_shared)) == NULL) return NULL;
    if ((p = GetVarint32Ptr(p, limit, value_length)) == NULL) return NULL;
  }

  if (static_cast<uint32_t>(limit - p) < (*non_shared + *value_length)) {
    return NULL;
  }
  return p;
}

class Block::Iter : public Iterator {
 private:
  const Comparator* const comparator_;
  const char* const data_;      // underlying block contents
  uint32_t const restarts_;     // Offset of restart array (list of fixed32)
  uint32_t const num_restarts_; // Number of uint32_t entries in restart array

  // current_ is offset in data_ of current entry.  >= restarts_ if !Valid
  uint32_t current_;
  uint32_t restart_index_;  // Index of restart block in which current_ falls
  std::string key_;
  Slice value_;
  Status status_;

  inline int Compare(const Slice& a, const Slice& b) const {
    return comparator_->Compare(a, b);
  }

  // Return the offset in data_ just past the end of the current entry.
  inline uint32_t NextEntryOffset() const {
    return (value_.data() + value_.size()) - data_;
  }

  uint32_t GetRestartPoint(uint32_t index) {
    assert(index < num_restarts_);
    return DecodeFixed32(data_ + restarts_ + index * sizeof(uint32_t));
  }

  void SeekToRestartPoint(uint32_t index) {
    key_.clear();
    restart_index_ = index;
    // current_ will be fixed by ParseNextKey();

    // ParseNextKey() starts at the end of value_, so set value_ accordingly
    uint32_t offset = GetRestartPoint(index);
    value_ = Slice(data_ + offset, 0);
  }

 public:
  Iter(const Comparator* comparator,
       const char* data,
       uint32_t restarts,
       uint32_t num_restarts)
      : comparator_(comparator),
        data_(data),
        restarts_(restarts),
        num_restarts_(num_restarts),
        current_(restarts_),
        restart_index_(num_restarts_) {
    assert(num_restarts_ > 0);
  }

  virtual bool Valid() const { return current_ < restarts_; }
  virtual Status status() const { return status_; }
  virtual Slice key() const {
    assert(Valid());
    return key_;
  }
  virtual Slice value() const {
    assert(Valid());
    return value_;
  }

  virtual void Next() {
    assert(Valid());
    ParseNextKey();
  }

  virtual void Prev() {
    assert(Valid());

    // Scan backwards to a restart point before current_
    const uint32_t original = current_;
    while (GetRestartPoint(restart_index_) >= original) {
      if (restart_index_ == 0) {
        // No more entries
        current_ = restarts_;
        restart_index_ = num_restarts_;
        return;
      }
      restart_index_--;
    }

    SeekToRestartPoint(restart_index_);
    do {
      // Loop until end of current entry hits the start of original entry
    } while (ParseNextKey() && NextEntryOffset() < original);
  }

  virtual void Seek(const Slice& target) {
    // Binary search in restart array to find the first restart point
    // with a key >= target
    uint32_t left = 0;
    uint32_t right = num_restarts_ - 1;
    while (left < right) {
      uint32_t mid = (left + right + 1) / 2;
      uint32_t region_offset = GetRestartPoint(mid);
      uint32_t shared, non_shared, value_length;
      const char* key_ptr = DecodeEntry(data_ + region_offset,
                                        data_ + restarts_,
                                        &shared, &non_shared, &value_length);
      if (key_ptr == NULL || (shared != 0)) {
        CorruptionError();
        return;
      }
      Slice mid_key(key_ptr, non_shared);
      if (Compare(mid_key, target) < 0) {
        // Key at "mid" is smaller than "target".  Therefore all
        // blocks before "mid" are uninteresting.
        left = mid;
      } else {
        // Key at "mid" is >= "target".  Therefore all blocks at or
        // after "mid" are uninteresting.
        right = mid - 1;
      }
    }

    // Linear search (within restart block) for first key >= target
    SeekToRestartPoint(left);
    while (true) {
      if (!ParseNextKey()) {
        return;
      }
      if (Compare(key_, target) >= 0) {
        return;
      }
    }
  }

  virtual void SeekToFirst() {
    SeekToRestartPoint(0);
    ParseNextKey();
  }

  virtual void SeekToLast() {
    SeekToRestartPoint(num_restarts_ - 1);
    while (ParseNextKey() && NextEntryOffset() < restarts_) {
      // Keep skipping
    }
  }

 private:
  void CorruptionError() {
    current_ = restarts_;
    restart_index_ = num_restarts_;
    status_ = Status::Corruption("bad entry in block");
    key_.clear();
    value_.clear();
  }

  bool ParseNextKey() {
    current_ = NextEntryOffset();
    const char* p = data_ + current_;
    const char* limit = data_ + restarts_;  // Restarts come right after data
    if (p >= limit) {
      // No more entries to return.  Mark as invalid.
      current_ = restarts_;
      restart_index_ = num_restarts_;
      return false;
    }

    // Decode next entry
    uint32_t shared, non_shared, value_length;
    p = DecodeEntry(p, limit, &shared, &non_shared, &value_length);
    if (p == NULL || key_.size() < shared) {
      CorruptionError();
      return false;
    } else {
      key_.resize(shared);
      key_.append(p, non_shared);
      value_ = Slice(p + non_shared, value_length);
      while (restart_index_ + 1 < num_restarts_ &&
             GetRestartPoint(restart_index_ + 1) < current_) {
        ++restart_index_;
      }
      return true;
    }
  }
};

Iterator* Block::NewIterator(const Comparator* cmp) {
  if (size_ < 2*sizeof(uint32_t)) {
    return NewErrorIterator(Status::Corruption("bad block contents"));
  }
  const uint32_t num_restarts = NumRestarts();
  if (num_restarts == 0) {
    return NewEmptyIterator();
  } else {
    return new Iter(cmp, data_, restart_offset_, num_restarts);
  }
}

}
<|endoftext|>


<commit_before>#include <gl/pogl.h>
#include <thread>
#include "POGLExampleWindow.h"

static const POGL_CHAR SIMPLE_EFFECT_VS[] = { R"(
	#version 330

	layout(location = 0) in vec3 position;
	layout(location = 1) in vec4 color;

	out vec4 vs_Color;

	void main()
	{
		vs_Color = color;
		gl_Position = vec4(position, 1.0);
	}
)"};

static const POGL_CHAR SIMPLE_EFFECT_FS[] = { R"(
	#version 330

	in vec4 vs_Color;

	void main()
	{
		gl_FragColor = vs_Color;
	}
)" };

int main()
{
	// Create a window
	POGL_HANDLE windowHandle = POGLCreateExampleWindow(POGL_SIZEI(1024, 768), POGL_TOSTRING("Example 2: Create Triangle"));

	// Create a POGL device based on the supplied information
	POGL_DEVICE_INFO deviceInfo;
#ifdef _DEBUG
	deviceInfo.flags = POGLDeviceInfoFlags::DEBUG_MODE;
#else
	deviceInfo.flags = 0;
#endif
	deviceInfo.windowHandle = windowHandle;
	deviceInfo.colorBits = 32;
	deviceInfo.depthBits = 16;
	deviceInfo.pixelFormat = POGLPixelFormat::R8G8B8A8;
	IPOGLDevice* device = POGLCreateDevice(&deviceInfo);

	try {
		// Create a device context for main thread
		IPOGLDeviceContext* context = device->GetDeviceContext();

		// Create an effect based on the supplied vertex- and fragment shader
		IPOGLShaderProgram* vertexShader = context->CreateShaderProgramFromMemory(SIMPLE_EFFECT_VS, sizeof(SIMPLE_EFFECT_VS), POGLShaderProgramType::VERTEX_SHADER);
		IPOGLShaderProgram* fragmentShader = context->CreateShaderProgramFromMemory(SIMPLE_EFFECT_FS, sizeof(SIMPLE_EFFECT_FS), POGLShaderProgramType::FRAGMENT_SHADER);
		IPOGLShaderProgram* programs[] = { vertexShader, fragmentShader };
		IPOGLEffect* simpleEffect = context->CreateEffectFromPrograms(programs, 2);
		vertexShader->Release();
		fragmentShader->Release();

		// Create vertex buffer
		const POGL_POSITION_COLOR_VERTEX VERTICES[] = {
			POGL_POSITION_COLOR_VERTEX(POGL_VECTOR3F(-0.5f, -0.5f, 0.0f), POGL_COLOR4F(1.0f, 0.0f, 0.0f, 1.0f)),
			POGL_POSITION_COLOR_VERTEX(POGL_VECTOR3F(0.0f, 0.5f, 0.0f), POGL_COLOR4F(1.0f, 0.0f, 0.0f, 1.0f)),
			POGL_POSITION_COLOR_VERTEX(POGL_VECTOR3F(0.5f, -0.5f, 0.0f), POGL_COLOR4F(1.0f, 0.0f, 0.0f, 1.0f))
		};
		IPOGLVertexBuffer* vertexBuffer = context->CreateVertexBuffer(VERTICES, sizeof(VERTICES), POGLPrimitiveType::TRIANGLE, POGLBufferUsage::STATIC);

		// Create vertex buffer
		const POGL_POSITION_COLOR_VERTEX VERTICES_INV[] = {
			POGL_POSITION_COLOR_VERTEX(POGL_VECTOR3F(0.5f, 0.5f, 0.0f), POGL_COLOR4F(0.0f, 1.0f, 0.0f, 1.0f)),
			POGL_POSITION_COLOR_VERTEX(POGL_VECTOR3F(0.0f, -0.5f, 0.0f), POGL_COLOR4F(0.0f, 1.0f, 0.0f, 1.0f)),
			POGL_POSITION_COLOR_VERTEX(POGL_VECTOR3F(-0.5f, 0.5f, 0.0f), POGL_COLOR4F(0.0f, 1.0f, 0.0f, 1.0f))
		};
		IPOGLVertexBuffer* vertexBufferInv = context->CreateVertexBuffer(VERTICES_INV, sizeof(VERTICES_INV), POGLPrimitiveType::TRIANGLE, POGLBufferUsage::STATIC);

		// Setup effect properties
		simpleEffect->SetBlend(true);
		simpleEffect->SetBlendFunc(POGLSrcFactor::SRC_COLOR, POGLDstFactor::ONE_MINUS_SRC_COLOR);

		while (POGLProcessEvents()) {
			// Prepare the simple effect
			IPOGLRenderState* state = context->Apply(simpleEffect);

			// Clear the color and depth buffer
			state->Clear(POGLClearType::COLOR | POGLClearType::DEPTH);

			// Draw the vertices inside the vertex buffer
			state->Draw(vertexBuffer);
			state->Draw(vertexBufferInv);

			// Nofiy the rendering engine that we are finished using the bound effect this frame
			state->EndFrame();

			// Swap the back buffer with the front buffer
			device->SwapBuffers();
		}

		// Release resources
		vertexBuffer->Release();
		vertexBufferInv->Release();
		simpleEffect->Release();
		context->Release();
	}
	catch (POGLException e) {
		POGLAlert(windowHandle, e);
	}

	device->Release();

	// Destroy the example window
	POGLDestroyExampleWindow(windowHandle);

	// Quit application
	return 0;
}
<commit_msg>Updated title<commit_after>#include <gl/pogl.h>
#include <thread>
#include "POGLExampleWindow.h"

static const POGL_CHAR SIMPLE_EFFECT_VS[] = { R"(
	#version 330

	layout(location = 0) in vec3 position;
	layout(location = 1) in vec4 color;

	out vec4 vs_Color;

	void main()
	{
		vs_Color = color;
		gl_Position = vec4(position, 1.0);
	}
)"};

static const POGL_CHAR SIMPLE_EFFECT_FS[] = { R"(
	#version 330

	in vec4 vs_Color;

	void main()
	{
		gl_FragColor = vs_Color;
	}
)" };

int main()
{
	// Create a window
	POGL_HANDLE windowHandle = POGLCreateExampleWindow(POGL_SIZEI(1024, 768), POGL_TOSTRING("Example 3: Blending"));

	// Create a POGL device based on the supplied information
	POGL_DEVICE_INFO deviceInfo;
#ifdef _DEBUG
	deviceInfo.flags = POGLDeviceInfoFlags::DEBUG_MODE;
#else
	deviceInfo.flags = 0;
#endif
	deviceInfo.windowHandle = windowHandle;
	deviceInfo.colorBits = 32;
	deviceInfo.depthBits = 16;
	deviceInfo.pixelFormat = POGLPixelFormat::R8G8B8A8;
	IPOGLDevice* device = POGLCreateDevice(&deviceInfo);

	try {
		// Create a device context for main thread
		IPOGLDeviceContext* context = device->GetDeviceContext();

		// Create an effect based on the supplied vertex- and fragment shader
		IPOGLShaderProgram* vertexShader = context->CreateShaderProgramFromMemory(SIMPLE_EFFECT_VS, sizeof(SIMPLE_EFFECT_VS), POGLShaderProgramType::VERTEX_SHADER);
		IPOGLShaderProgram* fragmentShader = context->CreateShaderProgramFromMemory(SIMPLE_EFFECT_FS, sizeof(SIMPLE_EFFECT_FS), POGLShaderProgramType::FRAGMENT_SHADER);
		IPOGLShaderProgram* programs[] = { vertexShader, fragmentShader };
		IPOGLEffect* simpleEffect = context->CreateEffectFromPrograms(programs, 2);
		vertexShader->Release();
		fragmentShader->Release();

		// Create vertex buffer
		const POGL_POSITION_COLOR_VERTEX VERTICES[] = {
			POGL_POSITION_COLOR_VERTEX(POGL_VECTOR3F(-0.5f, -0.5f, 0.0f), POGL_COLOR4F(1.0f, 0.0f, 0.0f, 1.0f)),
			POGL_POSITION_COLOR_VERTEX(POGL_VECTOR3F(0.0f, 0.5f, 0.0f), POGL_COLOR4F(1.0f, 0.0f, 0.0f, 1.0f)),
			POGL_POSITION_COLOR_VERTEX(POGL_VECTOR3F(0.5f, -0.5f, 0.0f), POGL_COLOR4F(1.0f, 0.0f, 0.0f, 1.0f))
		};
		IPOGLVertexBuffer* vertexBuffer = context->CreateVertexBuffer(VERTICES, sizeof(VERTICES), POGLPrimitiveType::TRIANGLE, POGLBufferUsage::STATIC);

		// Create vertex buffer
		const POGL_POSITION_COLOR_VERTEX VERTICES_INV[] = {
			POGL_POSITION_COLOR_VERTEX(POGL_VECTOR3F(0.5f, 0.5f, 0.0f), POGL_COLOR4F(0.0f, 1.0f, 0.0f, 1.0f)),
			POGL_POSITION_COLOR_VERTEX(POGL_VECTOR3F(0.0f, -0.5f, 0.0f), POGL_COLOR4F(0.0f, 1.0f, 0.0f, 1.0f)),
			POGL_POSITION_COLOR_VERTEX(POGL_VECTOR3F(-0.5f, 0.5f, 0.0f), POGL_COLOR4F(0.0f, 1.0f, 0.0f, 1.0f))
		};
		IPOGLVertexBuffer* vertexBufferInv = context->CreateVertexBuffer(VERTICES_INV, sizeof(VERTICES_INV), POGLPrimitiveType::TRIANGLE, POGLBufferUsage::STATIC);

		// Setup effect properties
		simpleEffect->SetBlend(true);
		simpleEffect->SetBlendFunc(POGLSrcFactor::SRC_COLOR, POGLDstFactor::ONE_MINUS_SRC_COLOR);

		while (POGLProcessEvents()) {
			// Prepare the simple effect
			IPOGLRenderState* state = context->Apply(simpleEffect);

			// Clear the color and depth buffer
			state->Clear(POGLClearType::COLOR | POGLClearType::DEPTH);

			// Draw the vertices inside the vertex buffer
			state->Draw(vertexBuffer);
			state->Draw(vertexBufferInv);

			// Nofiy the rendering engine that we are finished using the bound effect this frame
			state->EndFrame();

			// Swap the back buffer with the front buffer
			device->SwapBuffers();
		}

		// Release resources
		vertexBuffer->Release();
		vertexBufferInv->Release();
		simpleEffect->Release();
		context->Release();
	}
	catch (POGLException e) {
		POGLAlert(windowHandle, e);
	}

	device->Release();

	// Destroy the example window
	POGLDestroyExampleWindow(windowHandle);

	// Quit application
	return 0;
}
<|endoftext|>


<commit_before>
// Copyright 2010-2012 University of Washington. All Rights Reserved.
// LICENSE_PLACEHOLDER
// This software was created with Government support under DE
// AC05-76RL01830 awarded by the United States Department of
// Energy. The Government has certain rights in the software.

#ifndef __INCOHERENT_RELEASER_HPP__
#define __INCOHERENT_RELEASER_HPP__

#include "Grappa.hpp"
#include "Message.hpp"
#include "MessagePool.hpp"
#include "tasks/TaskingScheduler.hpp"

#ifdef VTRACE
#include <vt_user.h>
#endif

// forward declare for active message templates
template< typename T >
class IncoherentReleaser;

/// Stats for IncoherentReleaser
class IRStatistics {
  private:
    uint64_t release_ams;
    uint64_t release_ams_bytes;
#ifdef VTRACE_SAMPLED
    unsigned ir_grp_vt;
    unsigned release_ams_ev_vt;
    unsigned release_ams_bytes_ev_vt;
#endif

  public:
    IRStatistics();
    void reset();

    inline void count_release_ams( uint64_t bytes ) {
      release_ams++;
      release_ams_bytes+=bytes;
    }

    void dump( std::ostream& o, const char * terminator );
    void sample();
    void profiling_sample();
    void merge(const IRStatistics * other);
};

extern IRStatistics incoherent_releaser_stats;

/// IncoherentReleaser behavior for cache.
template< typename T >
class IncoherentReleaser {
private:
  bool release_started_;
  bool released_;
  GlobalAddress< T > * request_address_;
  size_t * count_;
  T ** pointer_;
  Thread * thread_;
  int num_messages_;
  int response_count_;

public:

  IncoherentReleaser( GlobalAddress< T > * request_address, size_t * count, T ** pointer )
    : request_address_( request_address )
    , count_( count )
    , pointer_( pointer )
    , release_started_( false )
    , released_( false )
    , thread_(NULL)
    , num_messages_(0)
    , response_count_(0)
  {
    reset();
  }

  void reset( ) {
    CHECK( !release_started_ || released_ ) << "inconsistent state for reset";
    release_started_ = false;
    released_ = false;
    thread_ = NULL;
    num_messages_ = 0;
    response_count_ = 0;
    if( *count_ == 0 ) {
      DVLOG(5) << "Zero-length release";
      release_started_ = true;
      released_ = true;
    } else if( request_address_->is_2D() ) {
      num_messages_ = 1;
      if( request_address_->node() == Grappa_mynode() ) {
        release_started_ = true;
        released_ = true;
      }
    } else {
      DVLOG(5) << "Straddle: block_max is " << (*request_address_ + *count_).block_max() ;
      DVLOG(5) << ", request_address is " << *request_address_;
      DVLOG(5) << ", sizeof(T) is " << sizeof(T);
      DVLOG(5) << ", count is " << *count_;
      DVLOG(5) << ", block_min is " << request_address_->block_min();

      DVLOG(5) << "Straddle: address is " << *request_address_ ;
      DVLOG(5) << ", address + count is " << *request_address_ + *count_;

      ptrdiff_t byte_diff = ( (*request_address_ + *count_ - 1).last_byte().block_max() -
                               request_address_->first_byte().block_min() );

      DVLOG(5) << "Straddle: address block max is " << request_address_->block_max();
      DVLOG(5) << " address + count block max is " << (*request_address_ + *count_).block_max();
      DVLOG(5) << " address + count -1 block max is " << (*request_address_ + *count_ - 1).block_max();
      DVLOG(5) << " difference is " << ( (*request_address_ + *count_ - 1).block_max() - request_address_->block_min() );
      DVLOG(5) << " multiplied difference is " << ( (*request_address_ + *count_ - 1).block_max() - request_address_->block_min() ) * sizeof(T);
      DVLOG(5) << " address block min " << request_address_->block_min();
      DVLOG(5) << "Straddle: diff is " << byte_diff << " bs " << block_size;
      num_messages_ = byte_diff / block_size;
    }

    if( num_messages_ > 1 ) DVLOG(5) << "****************************** MULTI BLOCK CACHE REQUEST ******************************";

    DVLOG(5) << "Detecting straddle for sizeof(T):" << sizeof(T)
             << " count:" << *count_
             << " num_messages_:" << num_messages_
             << " request_address:" << *request_address_;
  }

  void start_release() {
    if( !release_started_ ) {
#ifdef VTRACE_FULL
      VT_TRACER("incoherent start_release");
#endif
            DVLOG(5) << "Thread " << CURRENT_THREAD
              << " issuing release for " << *request_address_
              << " * " << *count_ ;
      release_started_ = true;
      size_t total_bytes = *count_ * sizeof(T);

      // allocate enough requests/messages that we don't run out
      size_t nmsg = total_bytes / block_size + 2;
      size_t msg_size = sizeof(Grappa::Message<RequestArgs>);

      if (nmsg*msg_size < Grappa::current_worker().stack_remaining()-8192) {
        // try to put message storage on stack if there's space
        char msg_buf[nmsg*msg_size];
        Grappa::MessagePool pool(msg_buf, sizeof(msg_buf));
        do_release(pool);
      } else {
        // fall back on heap-allocating the storage
        Grappa::MessagePool pool(nmsg*msg_size);
        do_release(pool);
      }
    }
  }

  void do_release(Grappa::impl::MessagePoolBase& pool) {
    size_t total_bytes = *count_ * sizeof(T);

    RequestArgs args;
    args.request_address = *request_address_;
    DVLOG(5) << "Computing request_bytes from block_max " << request_address_->first_byte().block_max() << " and " << *request_address_;
    args.reply_address = make_global( this );
    size_t offset = 0;
    size_t request_bytes = 0;

    for( size_t i = 0;
         offset < total_bytes;
         offset += request_bytes, i++) {

      request_bytes = args.request_address.first_byte().block_max() - args.request_address.first_byte();

      if( request_bytes > total_bytes - offset ) {
        request_bytes = total_bytes - offset;
      }

      DVLOG(5) << "sending release request with " << request_bytes
               << " of total bytes = " << *count_ * sizeof(T)
               << " to " << args.request_address;

      pool.send_message(args.request_address.core(),
        [args](void * payload, size_t payload_size) {
          incoherent_releaser_stats.count_release_ams( payload_size );
          DVLOG(5) << "Thread " << CURRENT_THREAD
          << " received release request to " << args.request_address
          << " reply to " << args.reply_address;
          memcpy( args.request_address.pointer(), payload, payload_size );

          auto reply_address = args.reply_address;
          Grappa::send_heap_message(args.reply_address.core(), [reply_address]{
            DVLOG(5) << "Thread " << CURRENT_THREAD << " received release reply to " << reply_address;
            reply_address.pointer()->release_reply();
          });

          DVLOG(5) << "Thread " << CURRENT_THREAD
          << " sent release reply to " << reply_address;
        },
        (char*)(*pointer_) + offset, request_bytes
      );

      // TODO: change type so we don't screw with pointer like this
      args.request_address = GlobalAddress<T>::Raw( args.request_address.raw_bits() + request_bytes );
    }
    DVLOG(5) << "release started for " << args.request_address;

    // blocks here waiting for messages to be sent
  }

  void block_until_released() {
    if( !released_ ) {
      start_release();
#ifdef VTRACE_FULL
      VT_TRACER("incoherent block_until_released");
#endif
      DVLOG(5) << "Thread " << CURRENT_THREAD
              << " ready to block on " << *request_address_
              << " * " << *count_ ;
      while( !released_ ) {
        DVLOG(5) << "Thread " << CURRENT_THREAD
                << " blocking on " << *request_address_
                << " * " << *count_ ;
        if( !released_ ) {
          thread_ = CURRENT_THREAD;
          Grappa_suspend();
          thread_ = NULL;
        }
        DVLOG(5) << "Thread " << CURRENT_THREAD
                 << " woke up for " << *request_address_
                 << " * " << *count_ ;
      }
    }
  }

  void release_reply( ) {
    DVLOG(5) << "Thread " << CURRENT_THREAD
             << " received release reply ";
    ++response_count_;
    if ( response_count_ == num_messages_ ) {
      released_ = true;
      if( thread_ != NULL ) {
        DVLOG(5) << "Thread " << CURRENT_THREAD
                 << " waking Thread " << thread_;
        Grappa_wake( thread_ );
      }
    }
  }

  bool released() const { return released_; }

  struct RequestArgs {
    GlobalAddress< T > request_address;
    GlobalAddress< IncoherentReleaser > reply_address;
  };
};

#endif
<commit_msg>fix: IncoherentReleaser sends PayloadMessages.<commit_after>
// Copyright 2010-2012 University of Washington. All Rights Reserved.
// LICENSE_PLACEHOLDER
// This software was created with Government support under DE
// AC05-76RL01830 awarded by the United States Department of
// Energy. The Government has certain rights in the software.

#ifndef __INCOHERENT_RELEASER_HPP__
#define __INCOHERENT_RELEASER_HPP__

#include "Grappa.hpp"
#include "Message.hpp"
#include "MessagePool.hpp"
#include "tasks/TaskingScheduler.hpp"

#ifdef VTRACE
#include <vt_user.h>
#endif

// forward declare for active message templates
template< typename T >
class IncoherentReleaser;

/// Stats for IncoherentReleaser
class IRStatistics {
  private:
    uint64_t release_ams;
    uint64_t release_ams_bytes;
#ifdef VTRACE_SAMPLED
    unsigned ir_grp_vt;
    unsigned release_ams_ev_vt;
    unsigned release_ams_bytes_ev_vt;
#endif

  public:
    IRStatistics();
    void reset();

    inline void count_release_ams( uint64_t bytes ) {
      release_ams++;
      release_ams_bytes+=bytes;
    }

    void dump( std::ostream& o, const char * terminator );
    void sample();
    void profiling_sample();
    void merge(const IRStatistics * other);
};

extern IRStatistics incoherent_releaser_stats;

/// IncoherentReleaser behavior for cache.
template< typename T >
class IncoherentReleaser {
private:
  bool release_started_;
  bool released_;
  GlobalAddress< T > * request_address_;
  size_t * count_;
  T ** pointer_;
  Thread * thread_;
  int num_messages_;
  int response_count_;

public:

  IncoherentReleaser( GlobalAddress< T > * request_address, size_t * count, T ** pointer )
    : request_address_( request_address )
    , count_( count )
    , pointer_( pointer )
    , release_started_( false )
    , released_( false )
    , thread_(NULL)
    , num_messages_(0)
    , response_count_(0)
  {
    reset();
  }

  void reset( ) {
    CHECK( !release_started_ || released_ ) << "inconsistent state for reset";
    release_started_ = false;
    released_ = false;
    thread_ = NULL;
    num_messages_ = 0;
    response_count_ = 0;
    if( *count_ == 0 ) {
      DVLOG(5) << "Zero-length release";
      release_started_ = true;
      released_ = true;
    } else if( request_address_->is_2D() ) {
      num_messages_ = 1;
      if( request_address_->node() == Grappa_mynode() ) {
        release_started_ = true;
        released_ = true;
      }
    } else {
      DVLOG(5) << "Straddle: block_max is " << (*request_address_ + *count_).block_max() ;
      DVLOG(5) << ", request_address is " << *request_address_;
      DVLOG(5) << ", sizeof(T) is " << sizeof(T);
      DVLOG(5) << ", count is " << *count_;
      DVLOG(5) << ", block_min is " << request_address_->block_min();

      DVLOG(5) << "Straddle: address is " << *request_address_ ;
      DVLOG(5) << ", address + count is " << *request_address_ + *count_;

      ptrdiff_t byte_diff = ( (*request_address_ + *count_ - 1).last_byte().block_max() -
                               request_address_->first_byte().block_min() );

      DVLOG(5) << "Straddle: address block max is " << request_address_->block_max();
      DVLOG(5) << " address + count block max is " << (*request_address_ + *count_).block_max();
      DVLOG(5) << " address + count -1 block max is " << (*request_address_ + *count_ - 1).block_max();
      DVLOG(5) << " difference is " << ( (*request_address_ + *count_ - 1).block_max() - request_address_->block_min() );
      DVLOG(5) << " multiplied difference is " << ( (*request_address_ + *count_ - 1).block_max() - request_address_->block_min() ) * sizeof(T);
      DVLOG(5) << " address block min " << request_address_->block_min();
      DVLOG(5) << "Straddle: diff is " << byte_diff << " bs " << block_size;
      num_messages_ = byte_diff / block_size;
    }

    if( num_messages_ > 1 ) DVLOG(5) << "****************************** MULTI BLOCK CACHE REQUEST ******************************";

    DVLOG(5) << "Detecting straddle for sizeof(T):" << sizeof(T)
             << " count:" << *count_
             << " num_messages_:" << num_messages_
             << " request_address:" << *request_address_;
  }

  void start_release() {
    if( !release_started_ ) {
#ifdef VTRACE_FULL
      VT_TRACER("incoherent start_release");
#endif
            DVLOG(5) << "Thread " << CURRENT_THREAD
              << " issuing release for " << *request_address_
              << " * " << *count_ ;
      release_started_ = true;
      size_t total_bytes = *count_ * sizeof(T);

      // allocate enough requests/messages that we don't run out
      size_t nmsg = total_bytes / block_size + 2;
      size_t msg_size = sizeof(Grappa::PayloadMessage<RequestArgs>);

      if (nmsg*msg_size < Grappa::current_worker().stack_remaining()-8192) {
        // try to put message storage on stack if there's space
        char msg_buf[nmsg*msg_size];
        Grappa::MessagePool pool(msg_buf, sizeof(msg_buf));
        do_release(pool);
      } else {
        // fall back on heap-allocating the storage
        Grappa::MessagePool pool(nmsg*msg_size);
        do_release(pool);
      }
    }
  }

  void do_release(Grappa::impl::MessagePoolBase& pool) {
    size_t total_bytes = *count_ * sizeof(T);

    RequestArgs args;
    args.request_address = *request_address_;
    DVLOG(5) << "Computing request_bytes from block_max " << request_address_->first_byte().block_max() << " and " << *request_address_;
    args.reply_address = make_global( this );
    size_t offset = 0;
    size_t request_bytes = 0;

    for( size_t i = 0;
         offset < total_bytes;
         offset += request_bytes, i++) {

      request_bytes = args.request_address.first_byte().block_max() - args.request_address.first_byte();

      if( request_bytes > total_bytes - offset ) {
        request_bytes = total_bytes - offset;
      }

      DVLOG(5) << "sending release request with " << request_bytes
               << " of total bytes = " << *count_ * sizeof(T)
               << " to " << args.request_address;

      pool.send_message(args.request_address.core(),
        [args](void * payload, size_t payload_size) {
          incoherent_releaser_stats.count_release_ams( payload_size );
          DVLOG(5) << "Thread " << CURRENT_THREAD
          << " received release request to " << args.request_address
          << " reply to " << args.reply_address;
          memcpy( args.request_address.pointer(), payload, payload_size );

          auto reply_address = args.reply_address;
          Grappa::send_heap_message(args.reply_address.core(), [reply_address]{
            DVLOG(5) << "Thread " << CURRENT_THREAD << " received release reply to " << reply_address;
            reply_address.pointer()->release_reply();
          });

          DVLOG(5) << "Thread " << CURRENT_THREAD
          << " sent release reply to " << reply_address;
        },
        (char*)(*pointer_) + offset, request_bytes
      );

      // TODO: change type so we don't screw with pointer like this
      args.request_address = GlobalAddress<T>::Raw( args.request_address.raw_bits() + request_bytes );
    }
    DVLOG(5) << "release started for " << args.request_address;

    // blocks here waiting for messages to be sent
  }

  void block_until_released() {
    if( !released_ ) {
      start_release();
#ifdef VTRACE_FULL
      VT_TRACER("incoherent block_until_released");
#endif
      DVLOG(5) << "Thread " << CURRENT_THREAD
              << " ready to block on " << *request_address_
              << " * " << *count_ ;
      while( !released_ ) {
        DVLOG(5) << "Thread " << CURRENT_THREAD
                << " blocking on " << *request_address_
                << " * " << *count_ ;
        if( !released_ ) {
          thread_ = CURRENT_THREAD;
          Grappa_suspend();
          thread_ = NULL;
        }
        DVLOG(5) << "Thread " << CURRENT_THREAD
                 << " woke up for " << *request_address_
                 << " * " << *count_ ;
      }
    }
  }

  void release_reply( ) {
    DVLOG(5) << "Thread " << CURRENT_THREAD
             << " received release reply ";
    ++response_count_;
    if ( response_count_ == num_messages_ ) {
      released_ = true;
      if( thread_ != NULL ) {
        DVLOG(5) << "Thread " << CURRENT_THREAD
                 << " waking Thread " << thread_;
        Grappa_wake( thread_ );
      }
    }
  }

  bool released() const { return released_; }

  struct RequestArgs {
    GlobalAddress< T > request_address;
    GlobalAddress< IncoherentReleaser > reply_address;
  };
};

#endif
<|endoftext|>


<commit_before>/*
 * Software License Agreement (BSD License)
 *
 *  Point Cloud Library (PCL) - www.pointclouds.org
 *  Copyright (c) 2010-2011, Willow Garage, Inc.
 *
 *  All rights reserved.
 *
 *  Redistribution and use in source and binary forms, with or without
 *  modification, are permitted provided that the following conditions
 *  are met:
 *
 *   * Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *   * Redistributions in binary form must reproduce the above
 *     copyright notice, this list of conditions and the following
 *     disclaimer in the documentation and/or other materials provided
 *     with the distribution.
 *   * Neither the name of Willow Garage, Inc. nor the names of its
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 *  FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 *  COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 *  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 *  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 *  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 *  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 *  ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 *  POSSIBILITY OF SUCH DAMAGE.
 *
 * $Id$
 *
 */

#include <gtest/gtest.h>
#include <pcl/kdtree/kdtree_flann.h>
#include <pcl/point_types.h>
#include <pcl/point_cloud.h>
#include <pcl/io/pcd_io.h>
#include <pcl/search/search.h>
#include <pcl/features/normal_3d.h>

#include <pcl/segmentation/extract_polygonal_prism_data.h>
#include <pcl/segmentation/segment_differences.h>
//#include <pcl/segmentation/region_growing.h>

using namespace pcl;
using namespace pcl::io;

PointCloud<PointXYZ>::Ptr cloud_;
PointCloud<PointXYZ>::Ptr cloud_t_;
KdTree<PointXYZ>::Ptr tree_;

pcl::PointCloud<pcl::PointXYZ>::Ptr another_cloud_;
pcl::PointCloud<pcl::Normal>::Ptr normals_;
pcl::PointCloud<pcl::Normal>::Ptr another_normals_;

////////////////////////////////////////////////////////////////////////////////////////////////
//TEST (//gionGrowingTest, Segment)
//{
//  pcl::RegionGrowing<pcl::PointXYZ> rg;
//  rg.setCloud(cloud_);
//  rg.setNormals(normals_);
//
//  int num_of_segments = rg.segmentPoints();
//  EXPECT_NE(0, num_of_segments);
//
//  std::vector<std::list<int>> segments;
//  segments = rg.getSegments();
//  EXPECT_NE(0, segments.size());
//}
//
////////////////////////////////////////////////////////////////////////////////////////////////
//TEST (RegionGrowingTest, SegmentWithoutCloud)
//{
//  pcl::RegionGrowing<pcl::PointXYZ> rg;
//  rg.setNormals(normals_);
//
//  int num_of_segments = rg.segmentPoints();
//  EXPECT_EQ(0, num_of_segments);
//
//  std::vector<std::list<int>> segments;
//  segments = rg.getSegments();
//  EXPECT_EQ(0, segments.size());
//}
//
////////////////////////////////////////////////////////////////////////////////////////////////
//TEST (RegionGrowingTest, SegmentWithoutNormals)
//{
//  pcl::RegionGrowing<pcl::PointXYZ> rg;
//  rg.setCloud(cloud_);
//
//  int num_of_segments = rg.segmentPoints();
//  EXPECT_EQ(0, num_of_segments);
//
//  std::vector<std::list<int>> segments;
//  segments = rg.getSegments();
//  EXPECT_EQ(0, segments.size());
//}
//
////////////////////////////////////////////////////////////////////////////////////////////////
//TEST (RegionGrowingTest, SegmentEmptyCloud)
//{
//  pcl::PointCloud<pcl::PointXYZ>::Ptr empty_cloud(new pcl::PointCloud<pcl::PointXYZ>);
//  pcl::PointCloud<pcl::Normal>::Ptr empty_normals(new pcl::PointCloud<pcl::Normal>);
//
//  pcl::RegionGrowing<pcl::PointXYZ> rg;
//  rg.setCloud(empty_cloud);
//  rg.setNormals(empty_normals);
//
//  int num_of_segments = rg.segmentPoints();
//  EXPECT_EQ(0, num_of_segments);
//
//  std::vector<std::list<int>> segments;
//  segments = rg.getSegments();
//  EXPECT_EQ(0, segments.size());
//}
//
////////////////////////////////////////////////////////////////////////////////////////////////
//TEST (RegionGrowingTest, SegmentWithDifferentNormalAndCloudSize)
//{
//  pcl::RegionGrowing<pcl::PointXYZ> rg;
//  rg.setCloud(another_cloud_);
//  rg.setNormals(normals_);
//
//  int first_cloud_size = cloud_->points.size();
//  int second_cloud_size = another_cloud_->points.size();
//  ASSERT_NE(first_cloud_size, second_cloud_size);
//
//  int num_of_segments = rg.segmentPoints();
//  EXPECT_EQ(0, num_of_segments);
//
//  std::vector<std::list<int>> segments;
//  segments = rg.getSegments();
//  EXPECT_EQ(0, segments.size());
//
//  rg.setCloud(cloud_);
//  rg.setNormals(another_normals_);
//
//  num_of_segments = rg.segmentPoints();
//  EXPECT_EQ(0, num_of_segments);
//
//  segments = rg.getSegments();
//  EXPECT_EQ(0, segments.size());
//}
//
////////////////////////////////////////////////////////////////////////////////////////////////
//TEST (RegionGrowingTest, SegmentWithWrongThresholdParameters)
//{
//  pcl::RegionGrowing<pcl::PointXYZ> rg;
//  rg.setCloud(cloud_);
//  rg.setNormals(normals_);
//
//  rg.setNumberOfNeighbours(0);
//
//  int num_of_segments = rg.segmentPoints();
//  EXPECT_EQ(0, num_of_segments);
//
//  std::vector<std::list<int>> segments;
//  segments = rg.getSegments();
//  EXPECT_EQ(0, segments.size());
//
//  rg.setNumberOfNeighbours(30);
//  rg.setResidualThreshold(-10.0);
//
//  num_of_segments = rg.segmentPoints();
//  EXPECT_EQ(0, num_of_segments);
//
//  segments = rg.getSegments();
//  EXPECT_EQ(0, segments.size());
//}
//
////////////////////////////////////////////////////////////////////////////////////////////////
//TEST (RegionGrowingTest, SegmentFromPoint)
//{
//  pcl::RegionGrowing<pcl::PointXYZ> rg;
//
//  std::list<int> segment = rg.getSegmentFromPoint(0);
//  EXPECT_EQ(0, segment.size());
//
//  rg.setCloud(cloud_);
//  rg.setNormals(normals_);
//  segment = rg.getSegmentFromPoint(0);
//  EXPECT_NE(0, segment.size());
//}

//////////////////////////////////////////////////////////////////////////////////////////////
TEST (SegmentDifferences, Segmentation)
{
  SegmentDifferences<PointXYZ> sd;
  sd.setInputCloud (cloud_);
  sd.setDistanceThreshold (0.00005);

  // Set the target as itself
  sd.setTargetCloud (cloud_);

  PointCloud<PointXYZ> output;
  sd.segment (output);

  EXPECT_EQ ((int)output.points.size (), 0);

  // Set a different target
  sd.setTargetCloud (cloud_t_);
  sd.segment (output);
  EXPECT_EQ ((int)output.points.size (), 126);
  //savePCDFile ("./test/0-t.pcd", output);

  // Reverse
  sd.setInputCloud (cloud_t_);
  sd.setTargetCloud (cloud_);
  sd.segment (output);
  EXPECT_EQ ((int)output.points.size (), 127);
  //savePCDFile ("./test/t-0.pcd", output);
}

//////////////////////////////////////////////////////////////////////////////////////////////
TEST (ExtractPolygonalPrism, Segmentation)
{
  PointCloud<PointXYZ>::Ptr hull (new PointCloud<PointXYZ>);
  hull->points.resize (5);

  for (size_t i = 0; i < hull->points.size (); ++i)
  {
    hull->points[i].x = hull->points[i].y = i;
    hull->points[i].z = 0;
  }

  ExtractPolygonalPrismData<PointXYZ> ex;
  ex.setInputCloud (cloud_);
  ex.setInputPlanarHull (hull);

  PointIndices output;
  ex.segment (output);

  EXPECT_EQ ((int)output.indices.size (), 0);
}

/* ---[ */
int
  main (int argc, char** argv)
{
  if (argc < 3)
  {
    std::cerr << "No test file given. Please download `bun0.pcd` and pass its path to the test." << std::endl;
    std::cerr << "The test needs two files. Please, pass two paths of different pcd files." << std::endl;
    return (-1);
  }

  // Load a standard PCD file from disk
  PointCloud<PointXYZ> cloud, cloud_t, another_cloud;
  if (loadPCDFile (argv[1], cloud) < 0)
  {
    std::cerr << "Failed to read test file. Please download `bun0.pcd` and pass its path to the test." << std::endl;
    return (-1);
  }
  if (pcl::io::loadPCDFile (argv[2], another_cloud) < 0)
  {
    std::cerr << "Failed to read test file. Please download `bun0.pcd` and pass its path to the test." << std::endl;
    return (-1);
  }

  // Tranpose the cloud
  cloud_t = cloud;
  for (size_t i = 0; i < cloud.points.size (); ++i)
    cloud_t.points[i].x += 0.01;

  cloud_   = cloud.makeShared ();
  cloud_t_ = cloud_t.makeShared ();

  another_cloud_ = another_cloud.makeShared();
  normals_ = (new pcl::PointCloud<pcl::Normal>)->makeShared();
  pcl::NormalEstimation<pcl::PointXYZ, pcl::Normal> normal_estimator;
  normal_estimator.setInputCloud(cloud_);
  normal_estimator.setKSearch(30);
  normal_estimator.compute(*normals_);

  another_normals_ = (new pcl::PointCloud<pcl::Normal>)->makeShared();
  normal_estimator.setInputCloud(another_cloud_);
  normal_estimator.setKSearch(30);
  normal_estimator.compute(*another_normals_);

  testing::InitGoogleTest (&argc, argv);
  return (RUN_ALL_TESTS ());
}
/* ]--- */
<commit_msg>* fixed line ending to UNIX like, deleted normal_3d header<commit_after>/*
 * Software License Agreement (BSD License)
 *
 *  Point Cloud Library (PCL) - www.pointclouds.org
 *  Copyright (c) 2010-2011, Willow Garage, Inc.
 *
 *  All rights reserved.
 *
 *  Redistribution and use in source and binary forms, with or without
 *  modification, are permitted provided that the following conditions
 *  are met:
 *
 *   * Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *   * Redistributions in binary form must reproduce the above
 *     copyright notice, this list of conditions and the following
 *     disclaimer in the documentation and/or other materials provided
 *     with the distribution.
 *   * Neither the name of Willow Garage, Inc. nor the names of its
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 *  FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 *  COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 *  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 *  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 *  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 *  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 *  ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 *  POSSIBILITY OF SUCH DAMAGE.
 *
 * $Id$
 *
 */

#include <gtest/gtest.h>
#include <pcl/kdtree/kdtree_flann.h>
#include <pcl/point_types.h>
#include <pcl/point_cloud.h>
#include <pcl/io/pcd_io.h>
#include <pcl/search/search.h>
#include <pcl/features/normal_3d.h>

#include <pcl/segmentation/extract_polygonal_prism_data.h>
#include <pcl/segmentation/segment_differences.h>
#include <pcl/segmentation/region_growing.h>

using namespace pcl;
using namespace pcl::io;

PointCloud<PointXYZ>::Ptr cloud_;
PointCloud<PointXYZ>::Ptr cloud_t_;
KdTree<PointXYZ>::Ptr tree_;

pcl::PointCloud<pcl::PointXYZ>::Ptr another_cloud_;
pcl::PointCloud<pcl::Normal>::Ptr normals_;
pcl::PointCloud<pcl::Normal>::Ptr another_normals_;

////////////////////////////////////////////////////////////////////////////////////////////////
TEST (//gionGrowingTest, Segment)
{
  pcl::RegionGrowing<pcl::PointXYZ> rg;
  rg.setCloud(cloud_);
  rg.setNormals(normals_);

  int num_of_segments = rg.segmentPoints();
  EXPECT_NE(0, num_of_segments);

  std::vector<std::list<int>> segments;
  segments = rg.getSegments();
  EXPECT_NE(0, segments.size());
}

////////////////////////////////////////////////////////////////////////////////////////////////
TEST (RegionGrowingTest, SegmentWithoutCloud)
{
  pcl::RegionGrowing<pcl::PointXYZ> rg;
  rg.setNormals(normals_);

  int num_of_segments = rg.segmentPoints();
  EXPECT_EQ(0, num_of_segments);

  std::vector<std::list<int>> segments;
  segments = rg.getSegments();
  EXPECT_EQ(0, segments.size());
}

////////////////////////////////////////////////////////////////////////////////////////////////
TEST (RegionGrowingTest, SegmentWithoutNormals)
{
  pcl::RegionGrowing<pcl::PointXYZ> rg;
  rg.setCloud(cloud_);

  int num_of_segments = rg.segmentPoints();
  EXPECT_EQ(0, num_of_segments);

  std::vector<std::list<int>> segments;
  segments = rg.getSegments();
  EXPECT_EQ(0, segments.size());
}

////////////////////////////////////////////////////////////////////////////////////////////////
TEST (RegionGrowingTest, SegmentEmptyCloud)
{
  pcl::PointCloud<pcl::PointXYZ>::Ptr empty_cloud(new pcl::PointCloud<pcl::PointXYZ>);
  pcl::PointCloud<pcl::Normal>::Ptr empty_normals(new pcl::PointCloud<pcl::Normal>);

  pcl::RegionGrowing<pcl::PointXYZ> rg;
  rg.setCloud(empty_cloud);
  rg.setNormals(empty_normals);

  int num_of_segments = rg.segmentPoints();
  EXPECT_EQ(0, num_of_segments);

  std::vector<std::list<int>> segments;
  segments = rg.getSegments();
  EXPECT_EQ(0, segments.size());
}

////////////////////////////////////////////////////////////////////////////////////////////////
TEST (RegionGrowingTest, SegmentWithDifferentNormalAndCloudSize)
{
  pcl::RegionGrowing<pcl::PointXYZ> rg;
  rg.setCloud(another_cloud_);
  rg.setNormals(normals_);

  int first_cloud_size = cloud_->points.size();
  int second_cloud_size = another_cloud_->points.size();
  ASSERT_NE(first_cloud_size, second_cloud_size);

  int num_of_segments = rg.segmentPoints();
  EXPECT_EQ(0, num_of_segments);

  std::vector<std::list<int>> segments;
  segments = rg.getSegments();
  EXPECT_EQ(0, segments.size());

  rg.setCloud(cloud_);
  rg.setNormals(another_normals_);

  num_of_segments = rg.segmentPoints();
  EXPECT_EQ(0, num_of_segments);

  segments = rg.getSegments();
  EXPECT_EQ(0, segments.size());
}

////////////////////////////////////////////////////////////////////////////////////////////////
TEST (RegionGrowingTest, SegmentWithWrongThresholdParameters)
{
  pcl::RegionGrowing<pcl::PointXYZ> rg;
  rg.setCloud(cloud_);
  rg.setNormals(normals_);

  rg.setNumberOfNeighbours(0);

  int num_of_segments = rg.segmentPoints();
  EXPECT_EQ(0, num_of_segments);

  std::vector<std::list<int>> segments;
  segments = rg.getSegments();
  EXPECT_EQ(0, segments.size());

  rg.setNumberOfNeighbours(30);
  rg.setResidualThreshold(-10.0);

  num_of_segments = rg.segmentPoints();
  EXPECT_EQ(0, num_of_segments);

  segments = rg.getSegments();
  EXPECT_EQ(0, segments.size());
}

////////////////////////////////////////////////////////////////////////////////////////////////
//TEST (RegionGrowingTest, SegmentFromPoint)
{
  pcl::RegionGrowing<pcl::PointXYZ> rg;

  std::list<int> segment = rg.getSegmentFromPoint(0);
  EXPECT_EQ(0, segment.size());

  rg.setCloud(cloud_);
  rg.setNormals(normals_);
  segment = rg.getSegmentFromPoint(0);
  EXPECT_NE(0, segment.size());
}

//////////////////////////////////////////////////////////////////////////////////////////////
TEST (SegmentDifferences, Segmentation)
{
  SegmentDifferences<PointXYZ> sd;
  sd.setInputCloud (cloud_);
  sd.setDistanceThreshold (0.00005);

  // Set the target as itself
  sd.setTargetCloud (cloud_);

  PointCloud<PointXYZ> output;
  sd.segment (output);

  EXPECT_EQ ((int)output.points.size (), 0);

  // Set a different target
  sd.setTargetCloud (cloud_t_);
  sd.segment (output);
  EXPECT_EQ ((int)output.points.size (), 126);
  //savePCDFile ("./test/0-t.pcd", output);

  // Reverse
  sd.setInputCloud (cloud_t_);
  sd.setTargetCloud (cloud_);
  sd.segment (output);
  EXPECT_EQ ((int)output.points.size (), 127);
  //savePCDFile ("./test/t-0.pcd", output);
}

//////////////////////////////////////////////////////////////////////////////////////////////
TEST (ExtractPolygonalPrism, Segmentation)
{
  PointCloud<PointXYZ>::Ptr hull (new PointCloud<PointXYZ>);
  hull->points.resize (5);

  for (size_t i = 0; i < hull->points.size (); ++i)
  {
    hull->points[i].x = hull->points[i].y = i;
    hull->points[i].z = 0;
  }

  ExtractPolygonalPrismData<PointXYZ> ex;
  ex.setInputCloud (cloud_);
  ex.setInputPlanarHull (hull);

  PointIndices output;
  ex.segment (output);

  EXPECT_EQ ((int)output.indices.size (), 0);
}

/* ---[ */
int
  main (int argc, char** argv)
{
  if (argc < 3)
  {
    std::cerr << "No test file given. Please download `bun0.pcd` and pass its path to the test." << std::endl;
    std::cerr << "The test needs two files. Please, pass two paths of different pcd files." << std::endl;
    return (-1);
  }

  // Load a standard PCD file from disk
  PointCloud<PointXYZ> cloud, cloud_t, another_cloud;
  if (loadPCDFile (argv[1], cloud) < 0)
  {
    std::cerr << "Failed to read test file. Please download `bun0.pcd` and pass its path to the test." << std::endl;
    return (-1);
  }
  if (pcl::io::loadPCDFile (argv[2], another_cloud) < 0)
  {
    std::cerr << "Failed to read test file. Please download `bun0.pcd` and pass its path to the test." << std::endl;
    return (-1);
  }

  // Tranpose the cloud
  cloud_t = cloud;
  for (size_t i = 0; i < cloud.points.size (); ++i)
    cloud_t.points[i].x += 0.01;

  cloud_   = cloud.makeShared ();
  cloud_t_ = cloud_t.makeShared ();

  another_cloud_ = another_cloud.makeShared();
  normals_ = (new pcl::PointCloud<pcl::Normal>)->makeShared();
  pcl::NormalEstimation<pcl::PointXYZ, pcl::Normal> normal_estimator;
  normal_estimator.setInputCloud(cloud_);
  normal_estimator.setKSearch(30);
  normal_estimator.compute(*normals_);

  another_normals_ = (new pcl::PointCloud<pcl::Normal>)->makeShared();
  normal_estimator.setInputCloud(another_cloud_);
  normal_estimator.setKSearch(30);
  normal_estimator.compute(*another_normals_);

  testing::InitGoogleTest (&argc, argv);
  return (RUN_ALL_TESTS ());
}
/* ]--- */
<|endoftext|>


<commit_before>#include "../test_helpers.hxx"

namespace
{
  enum colour { red, green, blue };
  enum class weather : int { hot, cold, wet };
}

namespace pqxx
{
  PQXX_DECLARE_ENUM_CONVERSION(colour);
  PQXX_DECLARE_ENUM_CONVERSION(weather);
}

namespace
{
void test_strconv_bool()
{
  PQXX_CHECK_EQUAL(pqxx::to_string(false), "false", "Wrong to_string(false).");
  PQXX_CHECK_EQUAL(pqxx::to_string(true), "true", "Wrong to_string(true).");

  bool result;
  pqxx::from_string("false", result);
  PQXX_CHECK_EQUAL(result, false, "Wrong from_string('false').");
  pqxx::from_string("FALSE", result);
  PQXX_CHECK_EQUAL(result, false, "Wrong from_string('FALSE').");
  pqxx::from_string("f", result);
  PQXX_CHECK_EQUAL(result, false, "Wrong from_string('f').");
  pqxx::from_string("F", result);
  PQXX_CHECK_EQUAL(result, false, "Wrong from_string('F').");
  pqxx::from_string("0", result);
  PQXX_CHECK_EQUAL(result, false, "Wrong from_string('0').");
  pqxx::from_string("true", result);
  PQXX_CHECK_EQUAL(result, true, "Wrong from_string('true').");
  pqxx::from_string("TRUE", result);
  PQXX_CHECK_EQUAL(result, true, "Wrong from_string('TRUE').");
  pqxx::from_string("t", result);
  PQXX_CHECK_EQUAL(result, true, "Wrong from_string('t').");
  pqxx::from_string("T", result);
  PQXX_CHECK_EQUAL(result, true, "Wrong from_string('T').");
  pqxx::from_string("1", result);
  PQXX_CHECK_EQUAL(result, true, "Wrong from_string('1').");
}

void test_strconv_enum()
{
  PQXX_CHECK_EQUAL(pqxx::to_string(red), "0", "Enum value did not convert.");
  PQXX_CHECK_EQUAL(pqxx::to_string(green), "1", "Enum value did not convert.");
  PQXX_CHECK_EQUAL(pqxx::to_string(blue), "2", "Enum value did not convert.");

  colour col;
  pqxx::from_string("2", col);
  PQXX_CHECK_EQUAL(col, blue, "Could not recover enum value from string.");
}

void test_strconv_class_enum()
{
  PQXX_CHECK_EQUAL(
	pqxx::to_string(weather::hot),
	"0",
	"Class enum value did not convert.");
  PQXX_CHECK_EQUAL(
	pqxx::to_string(weather::wet),
	"2",
	"Enum value did not convert.");

  weather w;
  pqxx::from_string("2", w);
  PQXX_CHECK_EQUAL(
	w,
	weather::wet,
	"Could not recover class enum value from string.");
}

PQXX_REGISTER_TEST(test_strconv_bool);
PQXX_REGISTER_TEST(test_strconv_enum);
PQXX_REGISTER_TEST(test_strconv_class_enum);
}
<commit_msg>No need to specify enum's underlying type.<commit_after>#include "../test_helpers.hxx"

namespace
{
  enum colour { red, green, blue };
  enum class weather { hot, cold, wet };
}

namespace pqxx
{
  PQXX_DECLARE_ENUM_CONVERSION(colour);
  PQXX_DECLARE_ENUM_CONVERSION(weather);
}

namespace
{
void test_strconv_bool()
{
  PQXX_CHECK_EQUAL(pqxx::to_string(false), "false", "Wrong to_string(false).");
  PQXX_CHECK_EQUAL(pqxx::to_string(true), "true", "Wrong to_string(true).");

  bool result;
  pqxx::from_string("false", result);
  PQXX_CHECK_EQUAL(result, false, "Wrong from_string('false').");
  pqxx::from_string("FALSE", result);
  PQXX_CHECK_EQUAL(result, false, "Wrong from_string('FALSE').");
  pqxx::from_string("f", result);
  PQXX_CHECK_EQUAL(result, false, "Wrong from_string('f').");
  pqxx::from_string("F", result);
  PQXX_CHECK_EQUAL(result, false, "Wrong from_string('F').");
  pqxx::from_string("0", result);
  PQXX_CHECK_EQUAL(result, false, "Wrong from_string('0').");
  pqxx::from_string("true", result);
  PQXX_CHECK_EQUAL(result, true, "Wrong from_string('true').");
  pqxx::from_string("TRUE", result);
  PQXX_CHECK_EQUAL(result, true, "Wrong from_string('TRUE').");
  pqxx::from_string("t", result);
  PQXX_CHECK_EQUAL(result, true, "Wrong from_string('t').");
  pqxx::from_string("T", result);
  PQXX_CHECK_EQUAL(result, true, "Wrong from_string('T').");
  pqxx::from_string("1", result);
  PQXX_CHECK_EQUAL(result, true, "Wrong from_string('1').");
}

void test_strconv_enum()
{
  PQXX_CHECK_EQUAL(pqxx::to_string(red), "0", "Enum value did not convert.");
  PQXX_CHECK_EQUAL(pqxx::to_string(green), "1", "Enum value did not convert.");
  PQXX_CHECK_EQUAL(pqxx::to_string(blue), "2", "Enum value did not convert.");

  colour col;
  pqxx::from_string("2", col);
  PQXX_CHECK_EQUAL(col, blue, "Could not recover enum value from string.");
}

void test_strconv_class_enum()
{
  PQXX_CHECK_EQUAL(
	pqxx::to_string(weather::hot),
	"0",
	"Class enum value did not convert.");
  PQXX_CHECK_EQUAL(
	pqxx::to_string(weather::wet),
	"2",
	"Enum value did not convert.");

  weather w;
  pqxx::from_string("2", w);
  PQXX_CHECK_EQUAL(
	w,
	weather::wet,
	"Could not recover class enum value from string.");
}

PQXX_REGISTER_TEST(test_strconv_bool);
PQXX_REGISTER_TEST(test_strconv_enum);
PQXX_REGISTER_TEST(test_strconv_class_enum);
}
<|endoftext|>


<commit_before>#include "catch.hpp"
#include <mapnik/text/icu_shaper.hpp>
#include <mapnik/text/harfbuzz_shaper.hpp>
#include <mapnik/text/font_library.hpp>
#include <mapnik/unicode.hpp>

namespace {

void test_shaping( mapnik::font_set const& fontset, mapnik::face_manager& fm,
                   std::vector<std::tuple<unsigned, unsigned>> const& expected, char const* str, bool debug = false)
{
    mapnik::transcoder tr("utf8");
    std::map<unsigned,double> width_map;
    mapnik::text_itemizer itemizer;
    auto props = std::make_unique<mapnik::detail::evaluated_format_properties>();
    props->fontset = fontset;
    props->text_size = 32;

    double scale_factor = 1;
    auto ustr = tr.transcode(str);
    auto length = ustr.length();
    itemizer.add_text(ustr, props);

    mapnik::text_line line(0, length);
    mapnik::harfbuzz_shaper::shape_text(line, itemizer,
                                        width_map,
                                        fm,
                                        scale_factor);

    std::size_t index = 0;
    for (auto const& g : line)
    {
        if (debug)
        {
            if (index++ > 0) std::cerr << ",";
            std::cerr << "{" << g.glyph_index << ", " << g.char_index << "}";
        }
        else
        {
            unsigned glyph_index, char_index;
            CHECK(index < expected.size());
            std::tie(glyph_index, char_index) = expected[index++];
            REQUIRE(glyph_index == g.glyph_index);
            REQUIRE(char_index == g.char_index);
        }
    }
}
}

TEST_CASE("shaping")
{
    mapnik::freetype_engine::register_font("test/data/fonts/NotoSans-Regular.ttc");
    mapnik::freetype_engine::register_fonts("test/data/fonts/Noto");
    mapnik::font_set fontset("fontset");
    for (auto const& name : mapnik::freetype_engine::face_names())
    {
        fontset.add_face_name(name);
    }

    mapnik::font_library fl;
    mapnik::freetype_engine::font_file_mapping_type font_file_mapping;
    mapnik::freetype_engine::font_memory_cache_type font_memory_cache;
    mapnik::face_manager fm(fl, font_file_mapping, font_memory_cache);

    {
        std::vector<std::tuple<unsigned, unsigned>> expected =
            {{0, 0}, {0, 3}, {0, 4}, {0, 7}, {3, 8}, {11, 9}, {68, 10}, {69, 11}, {70, 12}, {12, 13}};
        // with default NotoSans-Regular.ttc and NotoNaskhArabic-Regular.ttf ^^^
        //std::vector<std::tuple<unsigned, unsigned>> expected =
        //  {{977,0}, {1094,3}, {1038,4}, {1168,4}, {9,7}, {3,8}, {11,9}, {68,10}, {69,11}, {70,12}, {12,13}};
        // expected results if "NotoSansTibetan-Regular.ttf is registered^^
        test_shaping(fontset, fm, expected, "སྤུ་ཧྲེང (abc)");
    }

    {
        std::vector<std::tuple<unsigned, unsigned>> expected =
            {{0, 0}, {0, 3}, {0, 4}, {0, 7}, {3, 8}, {11, 9}, {0, 10}, {0, 11}, {0, 12}, {12, 13}};
        test_shaping(fontset, fm, expected, "སྤུ་ཧྲེང (普兰镇)");
    }

    {
        std::vector<std::tuple<unsigned, unsigned>> expected =
            {{68, 0}, {69, 1}, {70, 2}, {3, 3}, {11, 4}, {0, 5}, {0, 6}, {0, 7}, {12, 8}};
        test_shaping(fontset, fm, expected, "abc (普兰镇)");
    }

    {
        std::vector<std::tuple<unsigned, unsigned>> expected =
            {{68, 0}, {69, 1}, {70, 2}, {3, 3}, {11, 4}, {68, 5}, {69, 6}, {70, 7}, {12, 8}};
        test_shaping(fontset, fm, expected, "abc (abc)");
    }

}
<commit_msg>add explicit `u8` (utf8) qualifier<commit_after>#include "catch.hpp"
#include <mapnik/text/icu_shaper.hpp>
#include <mapnik/text/harfbuzz_shaper.hpp>
#include <mapnik/text/font_library.hpp>
#include <mapnik/unicode.hpp>

namespace {

void test_shaping( mapnik::font_set const& fontset, mapnik::face_manager& fm,
                   std::vector<std::tuple<unsigned, unsigned>> const& expected, char const* str, bool debug = false)
{
    mapnik::transcoder tr("utf8");
    std::map<unsigned,double> width_map;
    mapnik::text_itemizer itemizer;
    auto props = std::make_unique<mapnik::detail::evaluated_format_properties>();
    props->fontset = fontset;
    props->text_size = 32;

    double scale_factor = 1;
    auto ustr = tr.transcode(str);
    auto length = ustr.length();
    itemizer.add_text(ustr, props);

    mapnik::text_line line(0, length);
    mapnik::harfbuzz_shaper::shape_text(line, itemizer,
                                        width_map,
                                        fm,
                                        scale_factor);

    std::size_t index = 0;
    for (auto const& g : line)
    {
        if (debug)
        {
            if (index++ > 0) std::cerr << ",";
            std::cerr << "{" << g.glyph_index << ", " << g.char_index << "}";
        }
        else
        {
            unsigned glyph_index, char_index;
            CHECK(index < expected.size());
            std::tie(glyph_index, char_index) = expected[index++];
            REQUIRE(glyph_index == g.glyph_index);
            REQUIRE(char_index == g.char_index);
        }
    }
}
}

TEST_CASE("shaping")
{
    mapnik::freetype_engine::register_font("test/data/fonts/NotoSans-Regular.ttc");
    mapnik::freetype_engine::register_fonts("test/data/fonts/Noto");
    mapnik::font_set fontset("fontset");
    for (auto const& name : mapnik::freetype_engine::face_names())
    {
        fontset.add_face_name(name);
    }

    mapnik::font_library fl;
    mapnik::freetype_engine::font_file_mapping_type font_file_mapping;
    mapnik::freetype_engine::font_memory_cache_type font_memory_cache;
    mapnik::face_manager fm(fl, font_file_mapping, font_memory_cache);

    {
        std::vector<std::tuple<unsigned, unsigned>> expected =
            {{0, 0}, {0, 3}, {0, 4}, {0, 7}, {3, 8}, {11, 9}, {68, 10}, {69, 11}, {70, 12}, {12, 13}};
        // with default NotoSans-Regular.ttc and NotoNaskhArabic-Regular.ttf ^^^
        //std::vector<std::tuple<unsigned, unsigned>> expected =
        //  {{977,0}, {1094,3}, {1038,4}, {1168,4}, {9,7}, {3,8}, {11,9}, {68,10}, {69,11}, {70,12}, {12,13}};
        // expected results if "NotoSansTibetan-Regular.ttf is registered^^
        test_shaping(fontset, fm, expected, u8"སྤུ་ཧྲེང (abc)");
    }

    {
        std::vector<std::tuple<unsigned, unsigned>> expected =
            {{0, 0}, {0, 3}, {0, 4}, {0, 7}, {3, 8}, {11, 9}, {0, 10}, {0, 11}, {0, 12}, {12, 13}};
        test_shaping(fontset, fm, expected, u8"སྤུ་ཧྲེང (普兰镇)");
    }

    {
        std::vector<std::tuple<unsigned, unsigned>> expected =
            {{68, 0}, {69, 1}, {70, 2}, {3, 3}, {11, 4}, {0, 5}, {0, 6}, {0, 7}, {12, 8}};
        test_shaping(fontset, fm, expected, u8"abc (普兰镇)");
    }

    {
        std::vector<std::tuple<unsigned, unsigned>> expected =
            {{68, 0}, {69, 1}, {70, 2}, {3, 3}, {11, 4}, {68, 5}, {69, 6}, {70, 7}, {12, 8}};
        test_shaping(fontset, fm, expected, "abc (abc)");
    }

}
<|endoftext|>


<commit_before>#include "column_like_table_scan_impl.hpp"

#include <algorithm>
#include <array>
#include <map>
#include <memory>
#include <regex>
#include <sstream>
#include <string>
#include <utility>
#include <vector>

#include "storage/create_iterable_from_segment.hpp"
#include "storage/resolve_encoded_segment_type.hpp"
#include "storage/segment_iterables/create_iterable_from_attribute_vector.hpp"
#include "storage/segment_iterate.hpp"
#include "storage/value_segment.hpp"
#include "storage/value_segment/value_segment_iterable.hpp"
#include "utils/ignore_unused_variable.hpp"

namespace opossum {

ColumnLikeTableScanImpl::ColumnLikeTableScanImpl(const std::shared_ptr<const Table>& in_table, const ColumnID column_id,
                                                 const PredicateCondition predicate_condition,
                                                 const pmr_string& pattern)
    : AbstractDereferencedColumnTableScanImpl{in_table, column_id, predicate_condition},
      _matcher{pattern},
      _invert_results(predicate_condition == PredicateCondition::NotLike) {}

std::string ColumnLikeTableScanImpl::description() const { return "ColumnLike"; }

void ColumnLikeTableScanImpl::_scan_non_reference_segment(const BaseSegment& segment, const ChunkID chunk_id,
                                                          PosList& matches,
                                                          const std::shared_ptr<const PosList>& position_filter) const {
  // Select optimized or generic scanning implementation based on segment type
  if (const auto* dictionary_segment = dynamic_cast<const BaseDictionarySegment*>(&segment)) {
    _scan_dictionary_segment(*dictionary_segment, chunk_id, matches, position_filter);
  } else {
    _scan_generic_segment(segment, chunk_id, matches, position_filter);
  }
}

void ColumnLikeTableScanImpl::_scan_generic_segment(const BaseSegment& segment, const ChunkID chunk_id,
                                                    PosList& matches,
                                                    const std::shared_ptr<const PosList>& position_filter) const {
  segment_with_iterators_filtered(segment, position_filter, [&](auto it, [[maybe_unused]] const auto end) {
    // Don't instantiate this for this for DictionarySegments and ReferenceSegments to save compile time.
    // DictionarySegments are handled in _scan_dictionary_segment()
    // ReferenceSegments are handled via position_filter
    if constexpr (!is_dictionary_segment_iterable_v<typename decltype(it)::IterableType> &&
                  !is_reference_segment_iterable_v<typename decltype(it)::IterableType>) {
      using ColumnDataType = typename decltype(it)::ValueType;

      if constexpr (std::is_same_v<ColumnDataType, pmr_string>) {
        _matcher.resolve(_invert_results, [&](const auto& resolved_matcher) {
          const auto functor = [&](const auto& position) { return resolved_matcher(position.value()); };
          _scan_with_iterators<true>(functor, it, end, chunk_id, matches);
        });
      } else {
        Fail("Can only handle strings");
      }
    } else {
      Fail("Dictionary and ReferenceSegments have their own code paths and should be handled there");
    }
  });
}

void ColumnLikeTableScanImpl::_scan_dictionary_segment(const BaseDictionarySegment& segment, const ChunkID chunk_id,
                                                       PosList& matches,
                                                       const std::shared_ptr<const PosList>& position_filter) const {
  std::pair<size_t, std::vector<bool>> result;

  if (segment.encoding_type() == EncodingType::Dictionary) {
    const auto& typed_segment = static_cast<const DictionarySegment<pmr_string>&>(segment);
    result = _find_matches_in_dictionary(*typed_segment.dictionary());
  } else {
    const auto& typed_segment = static_cast<const FixedStringDictionarySegment<pmr_string>&>(segment);
    result = _find_matches_in_dictionary(*typed_segment.dictionary());
  }

  const auto& match_count = result.first;
  const auto& dictionary_matches = result.second;

  auto attribute_vector_iterable = create_iterable_from_attribute_vector(segment);

  // LIKE matches all rows, but we still need to check for NULL
  if (match_count == dictionary_matches.size()) {
    attribute_vector_iterable.with_iterators(position_filter, [&](auto it, auto end) {
      static const auto always_true = [](const auto&) { return true; };
      _scan_with_iterators<true>(always_true, it, end, chunk_id, matches);
    });

    return;
  }

  // LIKE matches no rows
  if (match_count == 0u) {
    return;
  }

  const auto dictionary_lookup = [&dictionary_matches](const auto& position) {
    return dictionary_matches[position.value()];
  };

  attribute_vector_iterable.with_iterators(position_filter, [&](auto it, auto end) {
    _scan_with_iterators<true>(dictionary_lookup, it, end, chunk_id, matches);
  });
}

std::pair<size_t, std::vector<bool>> ColumnLikeTableScanImpl::_find_matches_in_dictionary(
    const pmr_vector<pmr_string>& dictionary) const {
  auto result = std::pair<size_t, std::vector<bool>>{};

  auto& count = result.first;
  auto& dictionary_matches = result.second;

  count = 0u;
  dictionary_matches.reserve(dictionary.size());

  _matcher.resolve(_invert_results, [&](const auto& matcher) {
    for (const auto& value : dictionary) {
      const auto matches = matcher(value);
      count += static_cast<size_t>(matches);
      dictionary_matches.push_back(matches);
    }
  });

  return result;
}

}  // namespace opossum
<commit_msg>Fix performance regression in JOB (#1848)<commit_after>#include "column_like_table_scan_impl.hpp"

#include <algorithm>
#include <array>
#include <map>
#include <memory>
#include <regex>
#include <sstream>
#include <string>
#include <utility>
#include <vector>

#include "storage/create_iterable_from_segment.hpp"
#include "storage/resolve_encoded_segment_type.hpp"
#include "storage/segment_iterables/create_iterable_from_attribute_vector.hpp"
#include "storage/segment_iterate.hpp"
#include "storage/value_segment.hpp"
#include "storage/value_segment/value_segment_iterable.hpp"
#include "utils/ignore_unused_variable.hpp"

namespace opossum {

ColumnLikeTableScanImpl::ColumnLikeTableScanImpl(const std::shared_ptr<const Table>& in_table, const ColumnID column_id,
                                                 const PredicateCondition predicate_condition,
                                                 const pmr_string& pattern)
    : AbstractDereferencedColumnTableScanImpl{in_table, column_id, predicate_condition},
      _matcher{pattern},
      _invert_results(predicate_condition == PredicateCondition::NotLike) {}

std::string ColumnLikeTableScanImpl::description() const { return "ColumnLike"; }

void ColumnLikeTableScanImpl::_scan_non_reference_segment(const BaseSegment& segment, const ChunkID chunk_id,
                                                          PosList& matches,
                                                          const std::shared_ptr<const PosList>& position_filter) const {
  // For dictionary segments where the number of unique values is not higher than the number of (potentially filtered)
  // input rows, use an optimized implementation.
  if (const auto* dictionary_segment = dynamic_cast<const BaseDictionarySegment*>(&segment);
      dictionary_segment &&
      (!position_filter || dictionary_segment->unique_values_count() <= position_filter->size())) {
    _scan_dictionary_segment(*dictionary_segment, chunk_id, matches, position_filter);
  } else {
    _scan_generic_segment(segment, chunk_id, matches, position_filter);
  }
}

void ColumnLikeTableScanImpl::_scan_generic_segment(const BaseSegment& segment, const ChunkID chunk_id,
                                                    PosList& matches,
                                                    const std::shared_ptr<const PosList>& position_filter) const {
  segment_with_iterators_filtered(segment, position_filter, [&](auto it, [[maybe_unused]] const auto end) {
    // Don't instantiate this for ReferenceSegments to save compile time as ReferenceSegments are handled
    // via position_filter
    if constexpr (!is_reference_segment_iterable_v<typename decltype(it)::IterableType>) {
      using ColumnDataType = typename decltype(it)::ValueType;

      if constexpr (std::is_same_v<ColumnDataType, pmr_string>) {
        _matcher.resolve(_invert_results, [&](const auto& resolved_matcher) {
          const auto functor = [&](const auto& position) { return resolved_matcher(position.value()); };
          _scan_with_iterators<true>(functor, it, end, chunk_id, matches);
        });
      } else {
        Fail("Can only handle strings");
      }
    } else {
      Fail("ReferenceSegments have their own code paths and should be handled there");
    }
  });
}

void ColumnLikeTableScanImpl::_scan_dictionary_segment(const BaseDictionarySegment& segment, const ChunkID chunk_id,
                                                       PosList& matches,
                                                       const std::shared_ptr<const PosList>& position_filter) const {
  // First, build a bitmap containing 1s/0s for matching/non-matching dictionary values. Second, iterate over the
  // attribute vector and check against the bitmap. If too many input rows have already been removed (are not part of
  // position_filter), this optimization is detrimental. See caller for that case.
  std::pair<size_t, std::vector<bool>> result;

  if (segment.encoding_type() == EncodingType::Dictionary) {
    const auto& typed_segment = static_cast<const DictionarySegment<pmr_string>&>(segment);
    result = _find_matches_in_dictionary(*typed_segment.dictionary());
  } else {
    const auto& typed_segment = static_cast<const FixedStringDictionarySegment<pmr_string>&>(segment);
    result = _find_matches_in_dictionary(*typed_segment.dictionary());
  }

  const auto& match_count = result.first;
  const auto& dictionary_matches = result.second;

  auto attribute_vector_iterable = create_iterable_from_attribute_vector(segment);

  // LIKE matches all rows, but we still need to check for NULL
  if (match_count == dictionary_matches.size()) {
    attribute_vector_iterable.with_iterators(position_filter, [&](auto it, auto end) {
      static const auto always_true = [](const auto&) { return true; };
      _scan_with_iterators<true>(always_true, it, end, chunk_id, matches);
    });

    return;
  }

  // LIKE matches no rows
  if (match_count == 0u) {
    return;
  }

  const auto dictionary_lookup = [&dictionary_matches](const auto& position) {
    return dictionary_matches[position.value()];
  };

  attribute_vector_iterable.with_iterators(position_filter, [&](auto it, auto end) {
    _scan_with_iterators<true>(dictionary_lookup, it, end, chunk_id, matches);
  });
}

std::pair<size_t, std::vector<bool>> ColumnLikeTableScanImpl::_find_matches_in_dictionary(
    const pmr_vector<pmr_string>& dictionary) const {
  auto result = std::pair<size_t, std::vector<bool>>{};

  auto& count = result.first;
  auto& dictionary_matches = result.second;

  count = 0u;
  dictionary_matches.reserve(dictionary.size());

  _matcher.resolve(_invert_results, [&](const auto& matcher) {
    for (const auto& value : dictionary) {
      const auto matches = matcher(value);
      count += static_cast<size_t>(matches);
      dictionary_matches.push_back(matches);
    }
  });

  return result;
}

}  // namespace opossum
<|endoftext|>