<commit_before>// Copyright (2015) Gustav

#include "finans/core/commandline.h"

#include "gtest/gtest.h"
#include "gmock/gmock.h"

using namespace testing;

struct CommandlineTest : public Test {
  std::ostringstream output;
  std::ostringstream error;
};

#define GTEST(x) TEST_F(CommandlineTest, x)

/*
void main(int argc, char* argv[])
{
  enum MyEnum
  {
    MyVal, MyVal2
  };

  std::string compiler;
  int i;
  int op = 2;
  std::vector<std::string> strings;
  //MyEnum v;
  bool ok = argparse::Parser::ParseComplete ==
    argparse::Parser("description")
    ("compiler", compiler)
    ("int", i)
    ("-op", op)
    .add<std::vector<std::string>, std::string>("-strings", strings, argparse::Extra().count(argparse::Count::MoreThanOne).metavar("string"), argparse::PushBackVector<std::string>) // todo: is this beautifiable?
    //("-enum", &v, Convert<MyEnum>("MyVal", MyEnum::MyVal)("MyVal2", MyEnum::MyVal2) )
    .parseArgs(argc, argv);
  if (ok == false) return;
  std::cout << compiler << " " << i << " " << op << std::endl;
  BOOST_FOREACH(const std::string& s, strings)
  {
    std::cout << s << " " << std::endl;
  }
}
*/

GTEST(TestEmpty) {
  const bool ok = argparse::Parser::ParseComplete ==
    argparse::Parser("description")
    .ParseArgs(argparse::Arguments("app.exe", {}), output, error);
  EXPECT_EQ(true, ok);
}

GTEST(TestError) {
  const bool ok = argparse::Parser::ParseComplete ==
    argparse::Parser("description")
    .ParseArgs(argparse::Arguments("app.exe", { "hello", "world" }), output, error);
  EXPECT_EQ(false, ok);
}

GTEST(TestOptionalDefault) {
  int op = 2;
  const bool ok = argparse::Parser::ParseComplete ==
    argparse::Parser("description")
    ("-op", op)
    .ParseArgs(argparse::Arguments("app.exe", {}), output, error);
  EXPECT_EQ(true, ok);
  EXPECT_EQ(2, op);
}

GTEST(TestOptionalValue) {
  int op = 2;
  const bool ok = argparse::Parser::ParseComplete ==
    argparse::Parser("description")
    ("-op", op)
    .ParseArgs(argparse::Arguments("app.exe", {"-op", "42"}), output, error);
  EXPECT_EQ(true, ok);
  EXPECT_EQ(42, op);
}

GTEST(TestPositionalValue) {
  int op = 2;
  const bool ok = argparse::Parser::ParseComplete ==
    argparse::Parser("description")
    ("op", op)
    .ParseArgs(argparse::Arguments("app.exe", { "42" }), output, error);
  EXPECT_EQ(true, ok);
  EXPECT_EQ(42, op);
}

GTEST(TestPositionalValueErr) {
  int op = 42;
  const bool ok = argparse::Parser::ParseComplete ==
    argparse::Parser("description")
    ("op", op)
    .ParseArgs(argparse::Arguments("app.exe", {}), output, error);
  EXPECT_EQ(false, ok);
  EXPECT_EQ(42, op); // not touched
}

GTEST(TestStdVector) {
  std::vector<std::string> strings;
  const bool ok = argparse::Parser::ParseComplete ==
    argparse::Parser("description")
    .AddGreedy("-strings", strings, "string")
    .ParseArgs(argparse::Arguments("app.exe", {"-strings", "cat", "dog", "fish"}), output, error);
  EXPECT_EQ(true, ok);
  EXPECT_THAT(strings, ElementsAre("cat", "dog", "fish"));
}

GTEST(TestStdVectorInts) {
  std::vector<int> ints;
  const bool ok = argparse::Parser::ParseComplete ==
    argparse::Parser("description")
    .AddGreedy("-ints", ints, "string")
    .ParseArgs(argparse::Arguments("app.exe", { "-ints", "2", "3", "-5", "4" }), output, error);
  EXPECT_EQ(true, ok);
  EXPECT_THAT(ints, ElementsAre(2, 3, -5, 4));
}

GTEST(TestNonGreedyVector) {
  std::vector<std::string> strings;
  const bool ok = argparse::Parser::ParseComplete ==
    argparse::Parser("description")
    ("-s", strings)
    .ParseArgs(argparse::Arguments("app.exe", { "-s", "cat", "-s", "dog", "-s", "fish" }), output, error);
  EXPECT_EQ(true, ok);
  EXPECT_THAT(strings, ElementsAre("cat", "dog", "fish"));
}

enum class Day
{
  TODAY, YESTERDAY, TOMORROW
};

ARGPARSE_DEFINE_ENUM(Day, "day", ("Today", Day::TODAY)("Tomorrow", Day::TOMORROW)("Yesterday", Day::YESTERDAY) )

GTEST(TestEnum) {
  Day op = Day::TOMORROW;
  const bool ok = argparse::Parser::ParseComplete ==
    argparse::Parser("description")
    ("op", op)
    .ParseArgs(argparse::Arguments("app.exe", { "tod" }), output, error);
  EXPECT_EQ(true, ok);
  EXPECT_EQ(Day::TODAY, op);
}

GTEST(TestCommaOp) {
  int op = 2;
  const bool ok = argparse::Parser::ParseComplete ==
    argparse::Parser("description")
    ("-int,-i", op)
    .ParseArgs(argparse::Arguments("app.exe", { "-int", "42" }), output, error);
  EXPECT_EQ(true, ok);
  EXPECT_EQ(42, op);
}
<commit_msg>commented away failing tests<commit_after>// Copyright (2015) Gustav

#include "finans/core/commandline.h"

#include "gtest/gtest.h"
#include "gmock/gmock.h"

using namespace testing;

struct CommandlineTest : public Test {
  std::ostringstream output;
  std::ostringstream error;

  argparse::Parser parser;
  std::string animal;
  std::string another;

  CommandlineTest() : parser("description") {
    parser("pos", animal)("-op", another);
  }
};

#define GTEST(x) TEST_F(CommandlineTest, x)

/*
void main(int argc, char* argv[])
{
  enum MyEnum
  {
    MyVal, MyVal2
  };

  std::string compiler;
  int i;
  int op = 2;
  std::vector<std::string> strings;
  //MyEnum v;
  bool ok = argparse::Parser::ParseComplete ==
    argparse::Parser("description")
    ("compiler", compiler)
    ("int", i)
    ("-op", op)
    .add<std::vector<std::string>, std::string>("-strings", strings, argparse::Extra().count(argparse::Count::MoreThanOne).metavar("string"), argparse::PushBackVector<std::string>) // todo: is this beautifiable?
    //("-enum", &v, Convert<MyEnum>("MyVal", MyEnum::MyVal)("MyVal2", MyEnum::MyVal2) )
    .parseArgs(argc, argv);
  if (ok == false) return;
  std::cout << compiler << " " << i << " " << op << std::endl;
  BOOST_FOREACH(const std::string& s, strings)
  {
    std::cout << s << " " << std::endl;
  }
}
*/

GTEST(TestEmpty) {
  const bool ok = argparse::Parser::ParseComplete ==
    argparse::Parser("description")
    .ParseArgs(argparse::Arguments("app.exe", {}), output, error);
  EXPECT_EQ(true, ok);
}

GTEST(TestError) {
  const bool ok = argparse::Parser::ParseComplete ==
    argparse::Parser("description")
    .ParseArgs(argparse::Arguments("app.exe", { "hello", "world" }), output, error);
  EXPECT_EQ(false, ok);
}

GTEST(TestOptionalDefault) {
  int op = 2;
  const bool ok = argparse::Parser::ParseComplete ==
    argparse::Parser("description")
    ("-op", op)
    .ParseArgs(argparse::Arguments("app.exe", {}), output, error);
  EXPECT_EQ(true, ok);
  EXPECT_EQ(2, op);
}

GTEST(TestOptionalValue) {
  int op = 2;
  const bool ok = argparse::Parser::ParseComplete ==
    argparse::Parser("description")
    ("-op", op)
    .ParseArgs(argparse::Arguments("app.exe", {"-op", "42"}), output, error);
  EXPECT_EQ(true, ok);
  EXPECT_EQ(42, op);
}

GTEST(TestPositionalValue) {
  int op = 2;
  const bool ok = argparse::Parser::ParseComplete ==
    argparse::Parser("description")
    ("op", op)
    .ParseArgs(argparse::Arguments("app.exe", { "42" }), output, error);
  EXPECT_EQ(true, ok);
  EXPECT_EQ(42, op);
}

GTEST(TestPositionalValueErr) {
  int op = 42;
  const bool ok = argparse::Parser::ParseComplete ==
    argparse::Parser("description")
    ("op", op)
    .ParseArgs(argparse::Arguments("app.exe", {}), output, error);
  EXPECT_EQ(false, ok);
  EXPECT_EQ(42, op); // not touched
}

GTEST(TestStdVector) {
  std::vector<std::string> strings;
  const bool ok = argparse::Parser::ParseComplete ==
    argparse::Parser("description")
    .AddGreedy("-strings", strings, "string")
    .ParseArgs(argparse::Arguments("app.exe", {"-strings", "cat", "dog", "fish"}), output, error);
  EXPECT_EQ(true, ok);
  EXPECT_THAT(strings, ElementsAre("cat", "dog", "fish"));
}

GTEST(TestStdVectorInts) {
  std::vector<int> ints;
  const bool ok = argparse::Parser::ParseComplete ==
    argparse::Parser("description")
    .AddGreedy("-ints", ints, "string")
    .ParseArgs(argparse::Arguments("app.exe", { "-ints", "2", "3", "-5", "4" }), output, error);
  EXPECT_EQ(true, ok);
  EXPECT_THAT(ints, ElementsAre(2, 3, -5, 4));
}

GTEST(TestNonGreedyVector) {
  std::vector<std::string> strings;
  const bool ok = argparse::Parser::ParseComplete ==
    argparse::Parser("description")
    ("-s", strings)
    .ParseArgs(argparse::Arguments("app.exe", { "-s", "cat", "-s", "dog", "-s", "fish" }), output, error);
  EXPECT_EQ(true, ok);
  EXPECT_THAT(strings, ElementsAre("cat", "dog", "fish"));
}

enum class Day
{
  TODAY, YESTERDAY, TOMORROW
};

ARGPARSE_DEFINE_ENUM(Day, "day", ("Today", Day::TODAY)("Tomorrow", Day::TOMORROW)("Yesterday", Day::YESTERDAY) )

GTEST(TestEnum) {
  Day op = Day::TOMORROW;
  const bool ok = argparse::Parser::ParseComplete ==
    argparse::Parser("description")
    ("op", op)
    .ParseArgs(argparse::Arguments("app.exe", { "tod" }), output, error);
  EXPECT_EQ(true, ok);
  EXPECT_EQ(Day::TODAY, op);
}

GTEST(TestCommaOp) {
  int op = 2;
  const bool ok = argparse::Parser::ParseComplete ==
    argparse::Parser("description")
    ("-int,-i", op)
    .ParseArgs(argparse::Arguments("app.exe", { "-int", "42" }), output, error);
  EXPECT_EQ(true, ok);
  EXPECT_EQ(42, op);
}

GTEST(TestPrecedencePos) {
  const bool ok = argparse::Parser::ParseComplete ==
    parser.ParseArgs(argparse::Arguments("app.exe", {"dog"}), output, error);
  EXPECT_EQ(true, ok);
  EXPECT_EQ("dog", animal);
  EXPECT_EQ("", another);
}

/*
// currently failing. fix this
GTEST(TestPrecedencePosOp) {
  const bool ok = argparse::Parser::ParseComplete ==
    parser.ParseArgs(argparse::Arguments("app.exe", { "-dog", "-op", "cat" }), output, error);
  EXPECT_EQ(true, ok);
  EXPECT_EQ("-dog", animal);
  EXPECT_EQ("cat", another);
}
*/

// should optional be allowed before positional? How does help work with positional?
/*
// currently failing. fix this
GTEST(TestPrecedenceOpPos) {
  const bool ok = argparse::Parser::ParseComplete ==
    parser.ParseArgs(argparse::Arguments("app.exe", { "-op", "cat", "dog" }), output, error);
  EXPECT_EQ(true, ok);
  EXPECT_EQ("dog", animal);
  EXPECT_EQ("cat", another);
}
*/<|endoftext|>


<commit_before>/*
 Copyright (c) 2009-2010 Ilmar 'Ingaras' Kruis (seaeagle1@users.sourceforge.net)

   All rights reserved.

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

   - Redistributions of source code must retain the above copyright notice,
     this list of conditions and the following disclaimer.
   - Redistributions in binary form must reproduce the above copyright notice,
     this list of conditions and the following disclaimer in the documentation
     and/or other materials provided with the distribution.
   - Neither the name of the Mumble Developers 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 FOUNDATION OR
   CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
   EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
   PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
   PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
   LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
   NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
   SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/

#include "../mumble_plugin_win32.h"

static int fetch(float *avatar_pos, float *avatar_front, float *avatar_top, float *camera_pos, float *camera_front, float *camera_top, std::string &context, std::wstring &identity) {
	for (int i=0;i<3;i++)
		avatar_pos[i] = avatar_front[i] = avatar_top[i] = camera_pos[i] = camera_front[i] = camera_top[i] = 0.0f;

	bool ok;

	byte l[2];
	byte r,i;
	float o[3];
	BYTE *hPtr;
	float h;

	/*
		Position as represented by /loc command

		lx, ly = 8 * (byte)l;
		ox, oy, oz = (float)o;

		0 < ox < 160

		x = west
		y = north
		z = altitude

		r = region
		i = instance nr
	*/

	ok = peekProc((BYTE *) 0x010A18F0, o, 12) &&
	     peekProc((BYTE *) 0x010A18E8, l, 2) &&
	     peekProc((BYTE *) 0x010A18E4, &r, 1) &&
	     peekProc((BYTE *) 0x010A18EC, &i, 1) &&
	     peekProc((BYTE *)(pModule + 0x00D87EC0), &hPtr, 4);

	if (! ok)
		return false;

	ok = peekProc((BYTE *)(hPtr + 0x00000034), &h, 4);

	if (! ok)
		return false;

	// Use region as context since each region has its own coordinate system
	if (r == 1)
		context = "Eriador";
	else if (r == 2)
		context = "Rhovannion";
	else
		return true;

	// If we're in an instance, append the instance id
	if (i != 0)
		context += i;

	// Heading should be between 0 and 360
	if (h < 0 || h > 360)
		return true;

	// Limit coordinates to byte-values, otherwise we probably have a read error
	if (l[0] == 255 && l[1] == 255)
		return true;

	avatar_pos[0] = (float)l[0] * 160.0f + o[0];
	avatar_pos[1] = o[2];
	avatar_pos[2] = (float)l[1] * 160.0f + o[1];

	avatar_front[0] = sinf(h * M_PI / 180.0f);
	avatar_front[1] = 0.0f;
	avatar_front[2] = cosf(h * M_PI / 180.0f);

	avatar_top[0] = 0.0;
	avatar_top[1] = 1.0;
	avatar_top[2] = 0.0;

	// TODO: 3rd person camera support
	for (int i=0;i<3;i++) {
		camera_pos[i] = avatar_pos[i];
		camera_front[i] = avatar_front[i];
		camera_top[i] = avatar_top[i];
	}

	//qDebug("P %f %f %f -- %f %f %f -- h %f \n", avatar_pos[0], avatar_pos[1], avatar_pos[2], avatar_front[0], avatar_front[1], avatar_front[2], h);

	return true;
}

static int trylock(const std::multimap<std::wstring, unsigned long long int> &pids) {
	if (! initialize(pids, L"lotroclient.exe"))
		return false;

	float apos[3], afront[3], atop[3], cpos[3], cfront[3], ctop[3];
	std::string context;
	std::wstring identity;

	if (fetch(apos, afront, atop, cpos, cfront, ctop, context, identity)) {
		return true;
	} else {
		generic_unlock();
		return false;
	}
}

static const std::wstring longdesc() {
	return std::wstring(L"Supports Lord of the Rings Online (Codemasters Edition, Vol II Book 9 Patch1, v3.0.6.8015). Context support based on region and instance. No Identity support.");
}

static std::wstring description(L"Lord of the Rings Online (EU), Vol II Book 9 Patch1");
static std::wstring shortname(L"Lord of the Rings Online");

static int trylock1() {
	return trylock(std::multimap<std::wstring, unsigned long long int>());
}

static MumblePlugin lotroplug = {
	MUMBLE_PLUGIN_MAGIC,
	description,
	shortname,
	NULL,
	NULL,
	trylock1,
	generic_unlock,
	longdesc,
	fetch
};

static MumblePlugin2 lotroplug2 = {
	MUMBLE_PLUGIN_MAGIC_2,
	MUMBLE_PLUGIN_VERSION,
	trylock
};

extern "C" __declspec(dllexport) MumblePlugin *getMumblePlugin() {
	return &lotroplug;
}

extern "C" __declspec(dllexport) MumblePlugin2 *getMumblePlugin2() {
	return &lotroplug2;
}
<commit_msg>Update lotro to Vol 3, Book 1<commit_after>/*
 Copyright (c) 2009-2010 Ilmar 'Ingaras' Kruis (seaeagle1@users.sourceforge.net)

   All rights reserved.

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

   - Redistributions of source code must retain the above copyright notice,
     this list of conditions and the following disclaimer.
   - Redistributions in binary form must reproduce the above copyright notice,
     this list of conditions and the following disclaimer in the documentation
     and/or other materials provided with the distribution.
   - Neither the name of the Mumble Developers 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 FOUNDATION OR
   CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
   EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
   PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
   PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
   LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
   NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
   SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/

#include "../mumble_plugin_win32.h"
#include <QtCore/QtCore>

static int fetch(float *avatar_pos, float *avatar_front, float *avatar_top, float *camera_pos, float *camera_front, float *camera_top, std::string &context, std::wstring &identity) {
	for (int i=0;i<3;i++)
		avatar_pos[i] = avatar_front[i] = avatar_top[i] = camera_pos[i] = camera_front[i] = camera_top[i] = 0.0f;

	bool ok;

	byte l[2];
	byte r,i;
	float o[3];
	BYTE *hPtr;
	float h;
	BYTE *nPtr;
	BYTE *nPtr2;
	wchar_t* nPtr3;

	/*
		Position as represented by /loc command

		lx, ly = 8 * (byte)l;
		ox, oy, oz = (float)o;

		0 < ox < 160

		x = west
		y = north
		z = altitude

		r = region
		i = instance nr

		nPtr = pointer to character name (unique on a server)
	*/

	ok = peekProc((BYTE *) 0x010A9DC0, o, 12) &&
	     peekProc((BYTE *) 0x010A9DB8, l, 2) &&
	     peekProc((BYTE *) 0x010A9DB4, &r, 1) &&
	     peekProc((BYTE *) 0x010A9DBC, &i, 1) &&
	     peekProc((BYTE *)(pModule + 0x00DA0864), &hPtr, 4);

	if (! ok)
		return false;

	ok = peekProc((BYTE *)(hPtr  + 0x000007DC), &h, 4);

	if (! ok)
		return false;

	// Set identity
	//if(nPtr3 > 0)
	//	identity.assign(nPtr3);

	// Use region as context since each region has its own coordinate system
	if (r == 1)
		context = "Eriador";
	else if (r == 2)
		context = "Rhovannion";
	else
		return true;

	// If we're in an instance, append the instance id
	if (i != 0)
		context += i;

	// Heading should be between 0 and 360
	if (h < 0 || h > 360)
		return true;

	// Limit coordinates to byte-values, otherwise we probably have a read error
	if (l[0] == 255 && l[1] == 255)
		return true;

	avatar_pos[0] = (float)l[0] * 160.0f + o[0];
	avatar_pos[1] = o[2];
	avatar_pos[2] = (float)l[1] * 160.0f + o[1];

	avatar_front[0] = sinf(h * M_PI / 180.0f);
	avatar_front[1] = 0.0f;
	avatar_front[2] = cosf(h * M_PI / 180.0f);

	avatar_top[0] = 0.0;
	avatar_top[1] = 1.0;
	avatar_top[2] = 0.0;

	// TODO: 3rd person camera support
	for (int i=0;i<3;i++) {
		camera_pos[i] = avatar_pos[i];
		camera_front[i] = avatar_front[i];
		camera_top[i] = avatar_top[i];
	}

	//qDebug("I %s", identity);
	//qDebug("P %f %f %f -- %f %f %f -- h %f \n", avatar_pos[0], avatar_pos[1], avatar_pos[2], avatar_front[0], avatar_front[1], avatar_front[2], h);

	return true;
}

static int trylock(const std::multimap<std::wstring, unsigned long long int> &pids) {
	if (! initialize(pids, L"lotroclient.exe"))
		return false;

	float apos[3], afront[3], atop[3], cpos[3], cfront[3], ctop[3];
	std::string context;
	std::wstring identity;

	if (fetch(apos, afront, atop, cpos, cfront, ctop, context, identity)) {
		return true;
	} else {
		generic_unlock();
		return false;
	}
}

static const std::wstring longdesc() {
	return std::wstring(L"Supports Lord of the Rings Online (Codemasters Edition, Vol III Book 1, v3.1.0.8026). Context support based on region and instance. No Identity support.");
}

static std::wstring description(L"Lord of the Rings Online (EU), Vol III Book 1");
static std::wstring shortname(L"Lord of the Rings Online");

static int trylock1() {
	return trylock(std::multimap<std::wstring, unsigned long long int>());
}

static MumblePlugin lotroplug = {
	MUMBLE_PLUGIN_MAGIC,
	description,
	shortname,
	NULL,
	NULL,
	trylock1,
	generic_unlock,
	longdesc,
	fetch
};

static MumblePlugin2 lotroplug2 = {
	MUMBLE_PLUGIN_MAGIC_2,
	MUMBLE_PLUGIN_VERSION,
	trylock
};

extern "C" __declspec(dllexport) MumblePlugin *getMumblePlugin() {
	return &lotroplug;
}

extern "C" __declspec(dllexport) MumblePlugin2 *getMumblePlugin2() {
	return &lotroplug2;
}
<|endoftext|>


<commit_before>#include <nodelet/nodelet.h>
#include <pluginlib/class_list_macros.h>
#include "OpenniWrapperNode.h"
#include "OpenniWrapperNodelet.h"

  void OpenniWrapperNodelet::onInit()
 {

   NODELET_DEBUG("Initializing nodelet");
   inst_.reset(new OpenniWrapperNode(getNodeHandle(),getPrivateNodeHandle()));
   inst_->initializeOpenni();
 }

  OpenniWrapperNodelet::~OpenniWrapperNodelet()
  {
      inst_->terminateOpenni();
  }

  PLUGINLIB_DECLARE_CLASS(openni_wrapper,OpenniWrapperNodelet, OpenniWrapperNodelet, nodelet::Nodelet)
<commit_msg>new export class<commit_after>#include <nodelet/nodelet.h>
#include <pluginlib/class_list_macros.h>
#include "OpenniWrapperNode.h"
#include "OpenniWrapperNodelet.h"

  void OpenniWrapperNodelet::onInit()
 {

   NODELET_DEBUG("Initializing nodelet");
   inst_.reset(new OpenniWrapperNode(getNodeHandle(),getPrivateNodeHandle()));
   inst_->initializeOpenni();
 }

  OpenniWrapperNodelet::~OpenniWrapperNodelet()
  {
      inst_->terminateOpenni();
  }

  PLUGINLIB_EXPORT_CLASS(OpenniWrapperNodelet, nodelet::Nodelet)
<|endoftext|>


<commit_before>#include "input/input_state.h"
#include "input/keycodes.h"
#include "ui/ui_screen.h"
#include "ui/ui_context.h"
#include "ui/screen.h"
#include "i18n/i18n.h"
#include "gfx_es2/draw_buffer.h"

UIScreen::UIScreen()
	: Screen(), root_(0), recreateViews_(true), hatDown_(0) {
}

UIScreen::~UIScreen() {
	delete root_;
}

void UIScreen::DoRecreateViews() {
	if (recreateViews_) {
		delete root_;
		root_ = 0;
		CreateViews();
		if (root_ && root_->GetDefaultFocusView()) {
			root_->GetDefaultFocusView()->SetFocus();
		}
		recreateViews_ = false;
	}
}

void UIScreen::update(InputState &input) {
	DoRecreateViews();

	if (root_) {
		UpdateViewHierarchy(input, root_);
	}
}

void UIScreen::render() {
	DoRecreateViews();

	if (root_) {
		UI::LayoutViewHierarchy(*screenManager()->getUIContext(), root_);

		screenManager()->getUIContext()->Begin();
		DrawBackground(*screenManager()->getUIContext());
		root_->Draw(*screenManager()->getUIContext());
		screenManager()->getUIContext()->End();
		screenManager()->getUIContext()->Flush();
	}
}

void UIScreen::touch(const TouchInput &touch) {
	if (root_) {
		UI::TouchEvent(touch, root_);
	}
}

void UIScreen::key(const KeyInput &key) {
	if (root_) {
		UI::KeyEvent(key, root_);
	}
}

void UIDialogScreen::key(const KeyInput &key) {
	if ((key.flags & KEY_DOWN) && UI::IsEscapeKeyCode(key.keyCode)) {
		if (finished_) {
			ELOG("Screen already finished");
		} else {
			finished_ = true;
			screenManager()->finishDialog(this, DR_BACK);
		}
	} else {
		UIScreen::key(key);
	}
}

void UIScreen::axis(const AxisInput &axis) {
	// Simple translation of hat to keys for Shield and other modern pads.
	// TODO: Use some variant of keymap?
	int flags = 0;
	if (axis.axisId == JOYSTICK_AXIS_HAT_X) {
		if (axis.value < -0.7f)
			flags |= PAD_BUTTON_LEFT;
		if (axis.value > 0.7f)
			flags |= PAD_BUTTON_RIGHT;
	}
	if (axis.axisId == JOYSTICK_AXIS_HAT_Y) {
		if (axis.value < -0.7f)
			flags |= PAD_BUTTON_UP;
		if (axis.value > 0.7f)
			flags |= PAD_BUTTON_DOWN;
	}

	// Yeah yeah, this should be table driven..
	int pressed = flags & ~hatDown_;
	int released = ~flags & hatDown_;
	if (pressed & PAD_BUTTON_LEFT) key(KeyInput(DEVICE_ID_KEYBOARD, NKCODE_DPAD_LEFT, KEY_DOWN));
	if (pressed & PAD_BUTTON_RIGHT) key(KeyInput(DEVICE_ID_KEYBOARD, NKCODE_DPAD_RIGHT, KEY_DOWN));
	if (pressed & PAD_BUTTON_UP) key(KeyInput(DEVICE_ID_KEYBOARD, NKCODE_DPAD_UP, KEY_DOWN));
	if (pressed & PAD_BUTTON_DOWN) key(KeyInput(DEVICE_ID_KEYBOARD, NKCODE_DPAD_DOWN, KEY_DOWN));
	if (released & PAD_BUTTON_LEFT) key(KeyInput(DEVICE_ID_KEYBOARD, NKCODE_DPAD_LEFT, KEY_UP));
	if (released & PAD_BUTTON_RIGHT) key(KeyInput(DEVICE_ID_KEYBOARD, NKCODE_DPAD_RIGHT, KEY_UP));
	if (released & PAD_BUTTON_UP) key(KeyInput(DEVICE_ID_KEYBOARD, NKCODE_DPAD_UP, KEY_UP));
	if (released & PAD_BUTTON_DOWN) key(KeyInput(DEVICE_ID_KEYBOARD, NKCODE_DPAD_DOWN, KEY_UP));
	hatDown_ = flags;
	if (root_) {
		UI::AxisEvent(axis, root_);
	}
}

UI::EventReturn UIScreen::OnBack(UI::EventParams &e) {
	screenManager()->finishDialog(this, DR_BACK);
	return UI::EVENT_DONE;
}

UI::EventReturn UIScreen::OnOK(UI::EventParams &e) {
	screenManager()->finishDialog(this, DR_OK);
	return UI::EVENT_DONE;
}

UI::EventReturn UIScreen::OnCancel(UI::EventParams &e) {
	screenManager()->finishDialog(this, DR_CANCEL);
	return UI::EVENT_DONE;
}

PopupScreen::PopupScreen(std::string title, std::string button1, std::string button2)
	: box_(0), title_(title) {
	I18NCategory *d = GetI18NCategory("Dialog");
	if (!button1.empty())
		button1_ = d->T(button1.c_str());
	if (!button2.empty())
		button2_ = d->T(button2.c_str());
}

void PopupScreen::touch(const TouchInput &touch) {
	if (!box_ || (touch.flags & TOUCH_DOWN) == 0 || touch.id != 0) {
		UIDialogScreen::touch(touch);
		return;
	}

	if (!box_->GetBounds().Contains(touch.x, touch.y))
		screenManager()->finishDialog(this, DR_BACK);

	UIDialogScreen::touch(touch);
}

void PopupScreen::CreateViews() {
	using namespace UI;

	UIContext &dc = *screenManager()->getUIContext();

	root_ = new AnchorLayout(new LayoutParams(FILL_PARENT, FILL_PARENT));

	float yres = screenManager()->getUIContext()->GetBounds().h;

	box_ = new LinearLayout(ORIENT_VERTICAL,
		new AnchorLayoutParams(550, FillVertical() ? yres - 30 : WRAP_CONTENT, dc.GetBounds().centerX(), dc.GetBounds().centerY(), NONE, NONE, true));

	root_->Add(box_);
	box_->SetBG(UI::Drawable(0xFF303030));
	box_->SetHasDropShadow(true);

	View *title = new PopupHeader(title_);
	box_->Add(title);

	CreatePopupContents(box_);

	if (ShowButtons() && !button1_.empty()) {
		// And the two buttons at the bottom.
		LinearLayout *buttonRow = new LinearLayout(ORIENT_HORIZONTAL, new LinearLayoutParams(200, WRAP_CONTENT));
		buttonRow->SetSpacing(0);
		Margins buttonMargins(5, 5);

		// Adjust button order to the platform default.
#if defined(_WIN32)
		buttonRow->Add(new Button(button1_, new LinearLayoutParams(1.0f, buttonMargins)))->OnClick.Handle(this, &PopupScreen::OnOK);
		if (!button2_.empty())
			buttonRow->Add(new Button(button2_, new LinearLayoutParams(1.0f, buttonMargins)))->OnClick.Handle(this, &PopupScreen::OnCancel);
#else
		if (!button2_.empty())
			buttonRow->Add(new Button(button2_, new LinearLayoutParams(1.0f)))->OnClick.Handle(this, &PopupScreen::OnCancel);
		buttonRow->Add(new Button(button1_, new LinearLayoutParams(1.0f)))->OnClick.Handle(this, &PopupScreen::OnOK);
#endif

		box_->Add(buttonRow);
	}
}

void MessagePopupScreen::CreatePopupContents(UI::ViewGroup *parent) {
	parent->Add(new UI::TextView(message_));
}

UI::EventReturn PopupScreen::OnOK(UI::EventParams &e) {
	OnCompleted(DR_OK);
	screenManager()->finishDialog(this, DR_OK);
	return UI::EVENT_DONE;
}

UI::EventReturn PopupScreen::OnCancel(UI::EventParams &e) {
	OnCompleted(DR_CANCEL);
	screenManager()->finishDialog(this, DR_CANCEL);
	return UI::EVENT_DONE;
}

void ListPopupScreen::CreatePopupContents(UI::ViewGroup *parent) {
	using namespace UI;

	listView_ = parent->Add(new ListView(&adaptor_)); //, new LinearLayoutParams(1.0)));
	listView_->SetMaxHeight(screenManager()->getUIContext()->GetBounds().h - 140);
	listView_->OnChoice.Handle(this, &ListPopupScreen::OnListChoice);
}

UI::EventReturn ListPopupScreen::OnListChoice(UI::EventParams &e) {
	adaptor_.SetSelected(e.a);
	if (callback_)
		callback_(adaptor_.GetSelected());
	screenManager()->finishDialog(this, DR_OK);
	OnCompleted(DR_OK);
	OnChoice.Dispatch(e);
	return UI::EVENT_DONE;
}

namespace UI {

UI::EventReturn PopupMultiChoice::HandleClick(UI::EventParams &e) {
	std::vector<std::string> choices;
	for (int i = 0; i < numChoices_; i++) {
		choices.push_back(category_ ? category_->T(choices_[i]) : choices_[i]);
	}

	Screen *popupScreen = new ListPopupScreen(text_, choices, *value_ - minVal_,
		std::bind(&PopupMultiChoice::ChoiceCallback, this, placeholder::_1));
	screenManager_->push(popupScreen);
	return UI::EVENT_DONE;
}

void PopupMultiChoice::UpdateText() {
	// Clamp the value to be safe.
	if (*value_ < minVal_ || *value_ > minVal_ + numChoices_ - 1) {
		valueText_ = "(invalid choice)";  // Shouldn't happen. Should be no need to translate this.
	} else {
		valueText_ = category_ ? category_->T(choices_[*value_ - minVal_]) : choices_[*value_ - minVal_];
	}
}

void PopupMultiChoice::ChoiceCallback(int num) {
	if (num != -1) {
		*value_ = num + minVal_;
		UpdateText();

		UI::EventParams e;
		e.v = this;
		e.a = num;
		OnChoice.Trigger(e);
	}
}

void PopupMultiChoice::Draw(UIContext &dc) {
	Style style = dc.theme->itemStyle;
	if (!IsEnabled()) {
		style = dc.theme->itemDisabledStyle;
	}
	Choice::Draw(dc);
	int paddingX = 12;
	dc.SetFontStyle(dc.theme->uiFont);
	dc.DrawText(valueText_.c_str(), bounds_.x2() - paddingX, bounds_.centerY(), style.fgColor, ALIGN_RIGHT | ALIGN_VCENTER);
}

PopupSliderChoice::PopupSliderChoice(int *value, int minValue, int maxValue, const std::string &text, ScreenManager *screenManager, LayoutParams *layoutParams)
	: Choice(text, "", false, layoutParams), value_(value), minValue_(minValue), maxValue_(maxValue), screenManager_(screenManager) {
	OnClick.Handle(this, &PopupSliderChoice::HandleClick);
}

PopupSliderChoiceFloat::PopupSliderChoiceFloat(float *value, float minValue, float maxValue, const std::string &text, ScreenManager *screenManager, LayoutParams *layoutParams)
	: Choice(text, "", false, layoutParams), value_(value), minValue_(minValue), maxValue_(maxValue), screenManager_(screenManager) {
	OnClick.Handle(this, &PopupSliderChoiceFloat::HandleClick);
}

EventReturn PopupSliderChoice::HandleClick(EventParams &e) {
	SliderPopupScreen *popupScreen = new SliderPopupScreen(value_, minValue_, maxValue_, text_);
	popupScreen->OnChange.Handle(this, &PopupSliderChoice::HandleChange);
	screenManager_->push(popupScreen);
	return EVENT_DONE;
}

EventReturn PopupSliderChoice::HandleChange(EventParams &e) {
	e.v = this;
	OnChange.Trigger(e);
	return EVENT_DONE;
}

void PopupSliderChoice::Draw(UIContext &dc) {
	Style style = dc.theme->itemStyle;
	if (!IsEnabled()) {
		style = dc.theme->itemDisabledStyle;
	}
	Choice::Draw(dc);
	char temp[32];
	sprintf(temp, "%i", *value_);
	dc.SetFontStyle(dc.theme->uiFont);
	dc.DrawText(temp, bounds_.x2() - 12, bounds_.centerY(), style.fgColor, ALIGN_RIGHT | ALIGN_VCENTER);
}

EventReturn PopupSliderChoiceFloat::HandleClick(EventParams &e) {
	SliderFloatPopupScreen *popupScreen = new SliderFloatPopupScreen(value_, minValue_, maxValue_, text_);
	popupScreen->OnChange.Handle(this, &PopupSliderChoiceFloat::HandleChange);
	screenManager_->push(popupScreen);
	return EVENT_DONE;
}

EventReturn PopupSliderChoiceFloat::HandleChange(EventParams &e) {
	e.v = this;
	OnChange.Trigger(e);
	return EVENT_DONE;
}

void PopupSliderChoiceFloat::Draw(UIContext &dc) {
	Style style = dc.theme->itemStyle;
	if (!IsEnabled()) {
		style = dc.theme->itemDisabledStyle;
	}
	Choice::Draw(dc);
	char temp[32];
	sprintf(temp, "%2.2f", *value_);
	dc.SetFontStyle(dc.theme->uiFont);
	dc.DrawText(temp, bounds_.x2() - 12, bounds_.centerY(), style.fgColor, ALIGN_RIGHT | ALIGN_VCENTER);
}

EventReturn SliderPopupScreen::OnDecrease(EventParams &params) {
	sliderValue_--;
	slider_->Clamp();
	return EVENT_DONE;
}

EventReturn SliderPopupScreen::OnIncrease(EventParams &params) {
	sliderValue_++;
	slider_->Clamp();
	return EVENT_DONE;
}

void SliderPopupScreen::CreatePopupContents(UI::ViewGroup *parent) {
	using namespace UI;
	sliderValue_ = *value_;
	LinearLayout *lin = parent->Add(new LinearLayout(ORIENT_HORIZONTAL, new LinearLayoutParams(UI::Margins(10, 5))));
	slider_ = new Slider(&sliderValue_, minValue_, maxValue_, new LinearLayoutParams(1.0f));
	lin->Add(slider_);
	lin->Add(new Button(" - "))->OnClick.Handle(this, &SliderPopupScreen::OnDecrease);
	lin->Add(new Button(" + "))->OnClick.Handle(this, &SliderPopupScreen::OnIncrease);

	UI::SetFocusedView(slider_);
}

void SliderFloatPopupScreen::CreatePopupContents(UI::ViewGroup *parent) {
	using namespace UI;
	sliderValue_ = *value_;
	slider_ = parent->Add(new SliderFloat(&sliderValue_, minValue_, maxValue_, new LinearLayoutParams(UI::Margins(10, 5))));
	UI::SetFocusedView(slider_);
}

void SliderPopupScreen::OnCompleted(DialogResult result) {
	if (result == DR_OK) {
		*value_ = sliderValue_;
		EventParams e;
		e.v = 0;
		e.a = *value_;
		OnChange.Trigger(e);
	}
}

void SliderFloatPopupScreen::OnCompleted(DialogResult result) {
	if (result == DR_OK) {
		*value_ = sliderValue_;
		EventParams e;
		e.v = 0;
		e.a = (int)*value_;
		e.f = *value_;
		OnChange.Trigger(e);
	}
}

}  // namespace UI
<commit_msg>Focus the contents of popup screens<commit_after>#include "input/input_state.h"
#include "input/keycodes.h"
#include "ui/ui_screen.h"
#include "ui/ui_context.h"
#include "ui/screen.h"
#include "i18n/i18n.h"
#include "gfx_es2/draw_buffer.h"

UIScreen::UIScreen()
	: Screen(), root_(0), recreateViews_(true), hatDown_(0) {
}

UIScreen::~UIScreen() {
	delete root_;
}

void UIScreen::DoRecreateViews() {
	if (recreateViews_) {
		delete root_;
		root_ = 0;
		CreateViews();
		if (root_ && root_->GetDefaultFocusView()) {
			root_->GetDefaultFocusView()->SetFocus();
		}
		recreateViews_ = false;
	}
}

void UIScreen::update(InputState &input) {
	DoRecreateViews();

	if (root_) {
		UpdateViewHierarchy(input, root_);
	}
}

void UIScreen::render() {
	DoRecreateViews();

	if (root_) {
		UI::LayoutViewHierarchy(*screenManager()->getUIContext(), root_);

		screenManager()->getUIContext()->Begin();
		DrawBackground(*screenManager()->getUIContext());
		root_->Draw(*screenManager()->getUIContext());
		screenManager()->getUIContext()->End();
		screenManager()->getUIContext()->Flush();
	}
}

void UIScreen::touch(const TouchInput &touch) {
	if (root_) {
		UI::TouchEvent(touch, root_);
	}
}

void UIScreen::key(const KeyInput &key) {
	if (root_) {
		UI::KeyEvent(key, root_);
	}
}

void UIDialogScreen::key(const KeyInput &key) {
	if ((key.flags & KEY_DOWN) && UI::IsEscapeKeyCode(key.keyCode)) {
		if (finished_) {
			ELOG("Screen already finished");
		} else {
			finished_ = true;
			screenManager()->finishDialog(this, DR_BACK);
		}
	} else {
		UIScreen::key(key);
	}
}

void UIScreen::axis(const AxisInput &axis) {
	// Simple translation of hat to keys for Shield and other modern pads.
	// TODO: Use some variant of keymap?
	int flags = 0;
	if (axis.axisId == JOYSTICK_AXIS_HAT_X) {
		if (axis.value < -0.7f)
			flags |= PAD_BUTTON_LEFT;
		if (axis.value > 0.7f)
			flags |= PAD_BUTTON_RIGHT;
	}
	if (axis.axisId == JOYSTICK_AXIS_HAT_Y) {
		if (axis.value < -0.7f)
			flags |= PAD_BUTTON_UP;
		if (axis.value > 0.7f)
			flags |= PAD_BUTTON_DOWN;
	}

	// Yeah yeah, this should be table driven..
	int pressed = flags & ~hatDown_;
	int released = ~flags & hatDown_;
	if (pressed & PAD_BUTTON_LEFT) key(KeyInput(DEVICE_ID_KEYBOARD, NKCODE_DPAD_LEFT, KEY_DOWN));
	if (pressed & PAD_BUTTON_RIGHT) key(KeyInput(DEVICE_ID_KEYBOARD, NKCODE_DPAD_RIGHT, KEY_DOWN));
	if (pressed & PAD_BUTTON_UP) key(KeyInput(DEVICE_ID_KEYBOARD, NKCODE_DPAD_UP, KEY_DOWN));
	if (pressed & PAD_BUTTON_DOWN) key(KeyInput(DEVICE_ID_KEYBOARD, NKCODE_DPAD_DOWN, KEY_DOWN));
	if (released & PAD_BUTTON_LEFT) key(KeyInput(DEVICE_ID_KEYBOARD, NKCODE_DPAD_LEFT, KEY_UP));
	if (released & PAD_BUTTON_RIGHT) key(KeyInput(DEVICE_ID_KEYBOARD, NKCODE_DPAD_RIGHT, KEY_UP));
	if (released & PAD_BUTTON_UP) key(KeyInput(DEVICE_ID_KEYBOARD, NKCODE_DPAD_UP, KEY_UP));
	if (released & PAD_BUTTON_DOWN) key(KeyInput(DEVICE_ID_KEYBOARD, NKCODE_DPAD_DOWN, KEY_UP));
	hatDown_ = flags;
	if (root_) {
		UI::AxisEvent(axis, root_);
	}
}

UI::EventReturn UIScreen::OnBack(UI::EventParams &e) {
	screenManager()->finishDialog(this, DR_BACK);
	return UI::EVENT_DONE;
}

UI::EventReturn UIScreen::OnOK(UI::EventParams &e) {
	screenManager()->finishDialog(this, DR_OK);
	return UI::EVENT_DONE;
}

UI::EventReturn UIScreen::OnCancel(UI::EventParams &e) {
	screenManager()->finishDialog(this, DR_CANCEL);
	return UI::EVENT_DONE;
}

PopupScreen::PopupScreen(std::string title, std::string button1, std::string button2)
	: box_(0), title_(title) {
	I18NCategory *d = GetI18NCategory("Dialog");
	if (!button1.empty())
		button1_ = d->T(button1.c_str());
	if (!button2.empty())
		button2_ = d->T(button2.c_str());
}

void PopupScreen::touch(const TouchInput &touch) {
	if (!box_ || (touch.flags & TOUCH_DOWN) == 0 || touch.id != 0) {
		UIDialogScreen::touch(touch);
		return;
	}

	if (!box_->GetBounds().Contains(touch.x, touch.y))
		screenManager()->finishDialog(this, DR_BACK);

	UIDialogScreen::touch(touch);
}

void PopupScreen::CreateViews() {
	using namespace UI;

	UIContext &dc = *screenManager()->getUIContext();

	root_ = new AnchorLayout(new LayoutParams(FILL_PARENT, FILL_PARENT));

	float yres = screenManager()->getUIContext()->GetBounds().h;

	box_ = new LinearLayout(ORIENT_VERTICAL,
		new AnchorLayoutParams(550, FillVertical() ? yres - 30 : WRAP_CONTENT, dc.GetBounds().centerX(), dc.GetBounds().centerY(), NONE, NONE, true));

	root_->Add(box_);
	box_->SetBG(UI::Drawable(0xFF303030));
	box_->SetHasDropShadow(true);

	View *title = new PopupHeader(title_);
	box_->Add(title);

	CreatePopupContents(box_);
	root_->SetDefaultFocusView(box_);

	if (ShowButtons() && !button1_.empty()) {
		// And the two buttons at the bottom.
		LinearLayout *buttonRow = new LinearLayout(ORIENT_HORIZONTAL, new LinearLayoutParams(200, WRAP_CONTENT));
		buttonRow->SetSpacing(0);
		Margins buttonMargins(5, 5);

		// Adjust button order to the platform default.
#if defined(_WIN32)
		buttonRow->Add(new Button(button1_, new LinearLayoutParams(1.0f, buttonMargins)))->OnClick.Handle(this, &PopupScreen::OnOK);
		if (!button2_.empty())
			buttonRow->Add(new Button(button2_, new LinearLayoutParams(1.0f, buttonMargins)))->OnClick.Handle(this, &PopupScreen::OnCancel);
#else
		if (!button2_.empty())
			buttonRow->Add(new Button(button2_, new LinearLayoutParams(1.0f)))->OnClick.Handle(this, &PopupScreen::OnCancel);
		buttonRow->Add(new Button(button1_, new LinearLayoutParams(1.0f)))->OnClick.Handle(this, &PopupScreen::OnOK);
#endif

		box_->Add(buttonRow);
	}
}

void MessagePopupScreen::CreatePopupContents(UI::ViewGroup *parent) {
	parent->Add(new UI::TextView(message_));
}

UI::EventReturn PopupScreen::OnOK(UI::EventParams &e) {
	OnCompleted(DR_OK);
	screenManager()->finishDialog(this, DR_OK);
	return UI::EVENT_DONE;
}

UI::EventReturn PopupScreen::OnCancel(UI::EventParams &e) {
	OnCompleted(DR_CANCEL);
	screenManager()->finishDialog(this, DR_CANCEL);
	return UI::EVENT_DONE;
}

void ListPopupScreen::CreatePopupContents(UI::ViewGroup *parent) {
	using namespace UI;

	listView_ = parent->Add(new ListView(&adaptor_)); //, new LinearLayoutParams(1.0)));
	listView_->SetMaxHeight(screenManager()->getUIContext()->GetBounds().h - 140);
	listView_->OnChoice.Handle(this, &ListPopupScreen::OnListChoice);
}

UI::EventReturn ListPopupScreen::OnListChoice(UI::EventParams &e) {
	adaptor_.SetSelected(e.a);
	if (callback_)
		callback_(adaptor_.GetSelected());
	screenManager()->finishDialog(this, DR_OK);
	OnCompleted(DR_OK);
	OnChoice.Dispatch(e);
	return UI::EVENT_DONE;
}

namespace UI {

UI::EventReturn PopupMultiChoice::HandleClick(UI::EventParams &e) {
	std::vector<std::string> choices;
	for (int i = 0; i < numChoices_; i++) {
		choices.push_back(category_ ? category_->T(choices_[i]) : choices_[i]);
	}

	Screen *popupScreen = new ListPopupScreen(text_, choices, *value_ - minVal_,
		std::bind(&PopupMultiChoice::ChoiceCallback, this, placeholder::_1));
	screenManager_->push(popupScreen);
	return UI::EVENT_DONE;
}

void PopupMultiChoice::UpdateText() {
	// Clamp the value to be safe.
	if (*value_ < minVal_ || *value_ > minVal_ + numChoices_ - 1) {
		valueText_ = "(invalid choice)";  // Shouldn't happen. Should be no need to translate this.
	} else {
		valueText_ = category_ ? category_->T(choices_[*value_ - minVal_]) : choices_[*value_ - minVal_];
	}
}

void PopupMultiChoice::ChoiceCallback(int num) {
	if (num != -1) {
		*value_ = num + minVal_;
		UpdateText();

		UI::EventParams e;
		e.v = this;
		e.a = num;
		OnChoice.Trigger(e);
	}
}

void PopupMultiChoice::Draw(UIContext &dc) {
	Style style = dc.theme->itemStyle;
	if (!IsEnabled()) {
		style = dc.theme->itemDisabledStyle;
	}
	Choice::Draw(dc);
	int paddingX = 12;
	dc.SetFontStyle(dc.theme->uiFont);
	dc.DrawText(valueText_.c_str(), bounds_.x2() - paddingX, bounds_.centerY(), style.fgColor, ALIGN_RIGHT | ALIGN_VCENTER);
}

PopupSliderChoice::PopupSliderChoice(int *value, int minValue, int maxValue, const std::string &text, ScreenManager *screenManager, LayoutParams *layoutParams)
	: Choice(text, "", false, layoutParams), value_(value), minValue_(minValue), maxValue_(maxValue), screenManager_(screenManager) {
	OnClick.Handle(this, &PopupSliderChoice::HandleClick);
}

PopupSliderChoiceFloat::PopupSliderChoiceFloat(float *value, float minValue, float maxValue, const std::string &text, ScreenManager *screenManager, LayoutParams *layoutParams)
	: Choice(text, "", false, layoutParams), value_(value), minValue_(minValue), maxValue_(maxValue), screenManager_(screenManager) {
	OnClick.Handle(this, &PopupSliderChoiceFloat::HandleClick);
}

EventReturn PopupSliderChoice::HandleClick(EventParams &e) {
	SliderPopupScreen *popupScreen = new SliderPopupScreen(value_, minValue_, maxValue_, text_);
	popupScreen->OnChange.Handle(this, &PopupSliderChoice::HandleChange);
	screenManager_->push(popupScreen);
	return EVENT_DONE;
}

EventReturn PopupSliderChoice::HandleChange(EventParams &e) {
	e.v = this;
	OnChange.Trigger(e);
	return EVENT_DONE;
}

void PopupSliderChoice::Draw(UIContext &dc) {
	Style style = dc.theme->itemStyle;
	if (!IsEnabled()) {
		style = dc.theme->itemDisabledStyle;
	}
	Choice::Draw(dc);
	char temp[32];
	sprintf(temp, "%i", *value_);
	dc.SetFontStyle(dc.theme->uiFont);
	dc.DrawText(temp, bounds_.x2() - 12, bounds_.centerY(), style.fgColor, ALIGN_RIGHT | ALIGN_VCENTER);
}

EventReturn PopupSliderChoiceFloat::HandleClick(EventParams &e) {
	SliderFloatPopupScreen *popupScreen = new SliderFloatPopupScreen(value_, minValue_, maxValue_, text_);
	popupScreen->OnChange.Handle(this, &PopupSliderChoiceFloat::HandleChange);
	screenManager_->push(popupScreen);
	return EVENT_DONE;
}

EventReturn PopupSliderChoiceFloat::HandleChange(EventParams &e) {
	e.v = this;
	OnChange.Trigger(e);
	return EVENT_DONE;
}

void PopupSliderChoiceFloat::Draw(UIContext &dc) {
	Style style = dc.theme->itemStyle;
	if (!IsEnabled()) {
		style = dc.theme->itemDisabledStyle;
	}
	Choice::Draw(dc);
	char temp[32];
	sprintf(temp, "%2.2f", *value_);
	dc.SetFontStyle(dc.theme->uiFont);
	dc.DrawText(temp, bounds_.x2() - 12, bounds_.centerY(), style.fgColor, ALIGN_RIGHT | ALIGN_VCENTER);
}

EventReturn SliderPopupScreen::OnDecrease(EventParams &params) {
	sliderValue_--;
	slider_->Clamp();
	return EVENT_DONE;
}

EventReturn SliderPopupScreen::OnIncrease(EventParams &params) {
	sliderValue_++;
	slider_->Clamp();
	return EVENT_DONE;
}

void SliderPopupScreen::CreatePopupContents(UI::ViewGroup *parent) {
	using namespace UI;
	sliderValue_ = *value_;
	LinearLayout *lin = parent->Add(new LinearLayout(ORIENT_HORIZONTAL, new LinearLayoutParams(UI::Margins(10, 5))));
	slider_ = new Slider(&sliderValue_, minValue_, maxValue_, new LinearLayoutParams(1.0f));
	lin->Add(slider_);
	lin->Add(new Button(" - "))->OnClick.Handle(this, &SliderPopupScreen::OnDecrease);
	lin->Add(new Button(" + "))->OnClick.Handle(this, &SliderPopupScreen::OnIncrease);

	UI::SetFocusedView(slider_);
}

void SliderFloatPopupScreen::CreatePopupContents(UI::ViewGroup *parent) {
	using namespace UI;
	sliderValue_ = *value_;
	slider_ = parent->Add(new SliderFloat(&sliderValue_, minValue_, maxValue_, new LinearLayoutParams(UI::Margins(10, 5))));
	UI::SetFocusedView(slider_);
}

void SliderPopupScreen::OnCompleted(DialogResult result) {
	if (result == DR_OK) {
		*value_ = sliderValue_;
		EventParams e;
		e.v = 0;
		e.a = *value_;
		OnChange.Trigger(e);
	}
}

void SliderFloatPopupScreen::OnCompleted(DialogResult result) {
	if (result == DR_OK) {
		*value_ = sliderValue_;
		EventParams e;
		e.v = 0;
		e.a = (int)*value_;
		e.f = *value_;
		OnChange.Trigger(e);
	}
}

}  // namespace UI
<|endoftext|>


<commit_before>// Copyright (c) 2020 by Robert Bosch GmbH. All rights reserved.
//
// 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 "iceoryx_posh/iceoryx_posh_types.hpp"
#include "iceoryx_posh/internal/popo/ports/publisher_port_roudi.hpp"
#include "iceoryx_posh/internal/popo/ports/publisher_port_user.hpp"
#include "iceoryx_posh/internal/popo/ports/subscriber_port_multi_producer.hpp"
#include "iceoryx_posh/internal/popo/ports/subscriber_port_single_producer.hpp"
#include "iceoryx_posh/internal/popo/ports/subscriber_port_user.hpp"
#include "iceoryx_posh/mepoo/mepoo_config.hpp"
#include "iceoryx_utils/cxx/generic_raii.hpp"
#include "iceoryx_utils/error_handling/error_handling.hpp"
#include "iceoryx_utils/internal/concurrent/smart_lock.hpp"
#include "test.hpp"

#include <chrono>
#include <sstream>
#include <thread>

using namespace ::testing;
using namespace iox::popo;
using namespace iox::capro;
using namespace iox::cxx;
using namespace iox::mepoo;
using namespace iox::posix;
using ::testing::Return;

struct DummySample
{
    uint64_t m_dummy{42};
};

static const ServiceDescription TEST_SERVICE_DESCRIPTION("x", "y", "z");
static const iox::ProcessName_t TEST_SUBSCRIBER_APP_NAME("mySubscriberApp");
static const iox::ProcessName_t TEST_PUBLISHER_APP_NAME("myPublisherApp");

static constexpr uint32_t NUMBER_OF_PUBLISHERS = 27u;
static constexpr uint32_t ITERATIONS = 1000u;

static constexpr uint32_t NUM_CHUNKS_IN_POOL = NUMBER_OF_PUBLISHERS * ITERATIONS;
static constexpr uint32_t SMALL_CHUNK = 128u;
static constexpr uint32_t CHUNK_META_INFO_SIZE = 256u;
static constexpr size_t MEMORY_SIZE = NUM_CHUNKS_IN_POOL * (SMALL_CHUNK + CHUNK_META_INFO_SIZE);
alignas(64) static uint8_t g_memory[MEMORY_SIZE];

class PortUser_IntegrationTest : public Test
{
  public:
    PortUser_IntegrationTest()
    {
        m_mempoolConfig.addMemPool({SMALL_CHUNK, NUM_CHUNKS_IN_POOL});
        m_memoryManager.configureMemoryManager(m_mempoolConfig, &m_memoryAllocator, &m_memoryAllocator);
    }

    ~PortUser_IntegrationTest()
    {
    }

    void SetUp()
    {
        for (uint32_t i = 0; i < NUMBER_OF_PUBLISHERS; i++)
        {
            std::stringstream publisherAppName;
            publisherAppName << TEST_PUBLISHER_APP_NAME << i;

            iox::cxx::string<100> processName(TruncateToCapacity, publisherAppName.str().c_str());

            m_publisherPortDataVector.emplace_back(TEST_SERVICE_DESCRIPTION, processName, &m_memoryManager);
            m_publisherPortUserVector.emplace_back(&m_publisherPortDataVector.back());
            m_publisherPortRouDiVector.emplace_back(&m_publisherPortDataVector.back());
        }
    }

    void TearDown()
    {
        for (uint32_t i = 0; i < NUMBER_OF_PUBLISHERS; i++)
        {
            m_publisherPortUserVector[i].stopOffer();
            static_cast<void>(m_publisherPortRouDiVector[i].getCaProMessage());
        }

        m_subscriberPortUserSingleProducer.unsubscribe();
        m_subscriberPortUserMultiProducer.unsubscribe();

        static_cast<void>(m_subscriberPortRouDiSingleProducer.getCaProMessage());
        static_cast<void>(m_subscriberPortRouDiMultiProducer.getCaProMessage());
    }

    GenericRAII m_uniqueRouDiId{[] { iox::popo::internal::setUniqueRouDiId(0); },
                                [] { iox::popo::internal::unsetUniqueRouDiId(); }};

    uint64_t m_receiveCounter{0};
    std::atomic<uint64_t> m_sendCounter{0};
    std::atomic<uint64_t> m_publisherRunFinished{0};

    // Memory objects
    Allocator m_memoryAllocator{g_memory, MEMORY_SIZE};
    MePooConfig m_mempoolConfig;
    MemoryManager m_memoryManager;

    using ConcurrentCaproMessageVector_t = iox::concurrent::smart_lock<vector<CaproMessage, 1>>;
    ConcurrentCaproMessageVector_t m_concurrentCaproMessageExchange;
    ConcurrentCaproMessageVector_t m_concurrentCaproMessageRx;

    // subscriber port for single producer
    SubscriberPortData m_subscriberPortDataSingleProducer{
        TEST_SERVICE_DESCRIPTION, TEST_SUBSCRIBER_APP_NAME, VariantQueueTypes::SoFi_SingleProducerSingleConsumer};
    SubscriberPortUser m_subscriberPortUserSingleProducer{&m_subscriberPortDataSingleProducer};
    SubscriberPortSingleProducer m_subscriberPortRouDiSingleProducer{&m_subscriberPortDataSingleProducer};

    // subscriber port for multi producer
    SubscriberPortData m_subscriberPortDataMultiProducer{
        TEST_SERVICE_DESCRIPTION, TEST_SUBSCRIBER_APP_NAME, VariantQueueTypes::SoFi_MultiProducerSingleConsumer};
    SubscriberPortUser m_subscriberPortUserMultiProducer{&m_subscriberPortDataMultiProducer};
    SubscriberPortMultiProducer m_subscriberPortRouDiMultiProducer{&m_subscriberPortDataMultiProducer};

    // publisher port
    vector<PublisherPortData, NUMBER_OF_PUBLISHERS> m_publisherPortDataVector;
    vector<PublisherPortUser, NUMBER_OF_PUBLISHERS> m_publisherPortUserVector;
    vector<PublisherPortRouDi, NUMBER_OF_PUBLISHERS> m_publisherPortRouDiVector;

    inline CaproMessage waitForCaproMessage(const ConcurrentCaproMessageVector_t& concurrentCaproMessageVector,
                                            const CaproMessageType& caproMessageType)
    {
        bool finished{false};
        CaproMessage caproMessage;

        // Wait until the expected CaPro message has arrived in the shared message vector between subscriber and the
        // first publisher thread
        do
        {
            // Add delay to allow other thread accessing the shared resource
            std::this_thread::sleep_for(std::chrono::microseconds(10));
            {
                auto guardedVector = concurrentCaproMessageVector.GetScopeGuard();
                if (guardedVector->size() != 0)
                {
                    caproMessage = guardedVector->back();

                    if (caproMessage.m_type == caproMessageType)
                    {
                        guardedVector->pop_back();
                        finished = true;
                    }
                }
            }
        } while (!finished);

        return caproMessage;
    }

    template <typename SubscriberPortProducerType>
    void subscriberThread(uint32_t numberOfPublishers,
                          SubscriberPortProducerType& subscriberPortRouDi,
                          SubscriberPortUser& subscriberPortUser)
    {
        bool finished{false};

        // Wait for publisher to be ready
        auto caproMessage = waitForCaproMessage(m_concurrentCaproMessageExchange, CaproMessageType::OFFER);

        // Subscribe to publisher
        subscriberPortUser.subscribe();
        auto maybeCaproMessage = subscriberPortRouDi.getCaProMessage();
        if (maybeCaproMessage.has_value())
        {
            caproMessage = maybeCaproMessage.value();
            m_concurrentCaproMessageExchange->push_back(caproMessage);
        }
        else
        {
            // Error shall never occur
            FAIL() << "Error in subscriber SUB CaPro message!";
        }

        // Wait for subscription ACK from publisher
        caproMessage = waitForCaproMessage(m_concurrentCaproMessageExchange, CaproMessageType::ACK);

        // Let RouDi change state to finish subscription
        static_cast<void>(subscriberPortRouDi.dispatchCaProMessage(caproMessage));

        // Subscription done and ready to receive samples
        while (!finished)
        {
            // Try to receive chunk
            subscriberPortUser.getChunk()
                .and_then([&](optional<const ChunkHeader*>& maybeChunkHeader) {
                    if (maybeChunkHeader.has_value())
                    {
                        auto chunkHeader = maybeChunkHeader.value();
                        m_receiveCounter++;
                        subscriberPortUser.releaseChunk(chunkHeader);
                    }
                    else
                    {
                        // Nothing received -> check if publisher(s) still running
                        if (m_publisherRunFinished.load(std::memory_order_relaxed) == numberOfPublishers)
                        {
                            finished = true;
                        }
                    }
                })
                .or_else([](ChunkReceiveError error) {
                    // Errors shall never occur
                    FAIL() << "Error in getChunk(): " << static_cast<uint32_t>(error);
                });
        }
    }

    void publisherThread(uint32_t publisherThreadIndex,
                         PublisherPortRouDi& publisherPortRouDi,
                         PublisherPortUser& publisherPortUser)
    {
        CaproMessage caproMessage;

        // Publisher offers its service
        publisherPortUser.offer();

        // Let RouDi change state and send OFFER to subscriber
        auto maybeCaproMessage = publisherPortRouDi.getCaProMessage();

        if (publisherThreadIndex == 0)
        {
            // First publisher thread will sync with subscriber
            if (maybeCaproMessage.has_value())
            {
                caproMessage = maybeCaproMessage.value();
                m_concurrentCaproMessageExchange->push_back(caproMessage);
            }
            else
            {
                // Error shall never occur
                FAIL() << "Error in publisher OFFER CaPro message!";
            }

            // Wait for subscriber to subscribe
            caproMessage = waitForCaproMessage(m_concurrentCaproMessageExchange, CaproMessageType::SUB);
            m_concurrentCaproMessageRx->push_back(caproMessage);

            // Send ACK to subscriber
            maybeCaproMessage = publisherPortRouDi.dispatchCaProMessage(m_concurrentCaproMessageRx->back());
            if (maybeCaproMessage.has_value())
            {
                caproMessage = maybeCaproMessage.value();
                m_concurrentCaproMessageExchange->push_back(caproMessage);
            }
            else
            {
                // Error shall never occur
                FAIL() << "Error in publisher ACK CaPro message!";
            }
        }
        else
        {
            // All other publisher threads wait for the first thread to be synced with subscriber (indicated by
            // receiving a SUB message) to continue
            CaproMessage caproMessageRouDi(CaproMessageType::UNSUB, TEST_SERVICE_DESCRIPTION);
            do
            {
                std::this_thread::sleep_for(std::chrono::microseconds(10));

                if (m_concurrentCaproMessageRx->size() != 0)
                {
                    caproMessageRouDi = m_concurrentCaproMessageRx->back();
                }

            } while (caproMessageRouDi.m_type != CaproMessageType::SUB);

            static_cast<void>(publisherPortRouDi.dispatchCaProMessage(caproMessageRouDi));
        }

        // Subscriber is ready to receive -> start sending samples
        for (size_t i = 0; i < ITERATIONS; i++)
        {
            publisherPortUser.allocateChunk(sizeof(DummySample))
                .and_then([&](ChunkHeader* chunkHeader) {
                    auto sample = chunkHeader->payload();
                    new (sample) DummySample();
                    static_cast<DummySample*>(sample)->m_dummy = i;
                    publisherPortUser.sendChunk(chunkHeader);
                    m_sendCounter++;
                })
                .or_else([](AllocationError error) {
                    // Errors shall never occur
                    FAIL() << "Error in allocateChunk(): " << static_cast<uint32_t>(error);
                });

            /// Add some jitter to make thread breathe
            std::this_thread::sleep_for(std::chrono::microseconds(rand() % 750));
        }

        // Signal the subscriber thread we're done
        m_publisherRunFinished++;
    }
};

TEST_F(PortUser_IntegrationTest, SingleProducer)
{
    std::thread subscribingThread(std::bind(&PortUser_IntegrationTest::subscriberThread<SubscriberPortSingleProducer>,
                                            this,
                                            1,
                                            std::ref(PortUser_IntegrationTest::m_subscriberPortRouDiSingleProducer),
                                            std::ref(PortUser_IntegrationTest::m_subscriberPortUserSingleProducer)));
    std::thread publishingThread(std::bind(&PortUser_IntegrationTest::publisherThread,
                                           this,
                                           0,
                                           std::ref(PortUser_IntegrationTest::m_publisherPortRouDiVector.front()),
                                           std::ref(PortUser_IntegrationTest::m_publisherPortUserVector.front())));

    if (subscribingThread.joinable())
    {
        subscribingThread.join();
    }

    if (publishingThread.joinable())
    {
        publishingThread.join();
    }

    EXPECT_EQ(m_sendCounter.load(std::memory_order_relaxed), m_receiveCounter);
    EXPECT_EQ(PortUser_IntegrationTest::m_subscriberPortUserMultiProducer.hasLostChunks(), false);
}

TEST_F(PortUser_IntegrationTest, MultiProducer)
{
    std::thread subscribingThread(std::bind(&PortUser_IntegrationTest::subscriberThread<SubscriberPortMultiProducer>,
                                            this,
                                            NUMBER_OF_PUBLISHERS,
                                            std::ref(PortUser_IntegrationTest::m_subscriberPortRouDiMultiProducer),
                                            std::ref(PortUser_IntegrationTest::m_subscriberPortUserMultiProducer)));

    vector<std::thread, NUMBER_OF_PUBLISHERS> publisherThreadVector;
    for (uint32_t i = 0; i < NUMBER_OF_PUBLISHERS; i++)
    {
        publisherThreadVector.emplace_back(std::bind(&PortUser_IntegrationTest::publisherThread,
                                                     this,
                                                     i,
                                                     std::ref(PortUser_IntegrationTest::m_publisherPortRouDiVector[i]),
                                                     std::ref(PortUser_IntegrationTest::m_publisherPortUserVector[i])));
    }

    if (subscribingThread.joinable())
    {
        subscribingThread.join();
    }

    for (uint32_t i = 0; i < NUMBER_OF_PUBLISHERS; i++)
    {
        if (publisherThreadVector[i].joinable())
        {
            publisherThreadVector[i].join();
        }
    }

    EXPECT_EQ(m_sendCounter.load(std::memory_order_relaxed), m_receiveCounter);
    EXPECT_EQ(PortUser_IntegrationTest::m_subscriberPortUserMultiProducer.hasLostChunks(), false);
}
<commit_msg>iox-#25: Add constexpr for some numbers<commit_after>// Copyright (c) 2020 by Robert Bosch GmbH. All rights reserved.
//
// 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 "iceoryx_posh/iceoryx_posh_types.hpp"
#include "iceoryx_posh/internal/popo/ports/publisher_port_roudi.hpp"
#include "iceoryx_posh/internal/popo/ports/publisher_port_user.hpp"
#include "iceoryx_posh/internal/popo/ports/subscriber_port_multi_producer.hpp"
#include "iceoryx_posh/internal/popo/ports/subscriber_port_single_producer.hpp"
#include "iceoryx_posh/internal/popo/ports/subscriber_port_user.hpp"
#include "iceoryx_posh/mepoo/mepoo_config.hpp"
#include "iceoryx_utils/cxx/generic_raii.hpp"
#include "iceoryx_utils/error_handling/error_handling.hpp"
#include "iceoryx_utils/internal/concurrent/smart_lock.hpp"
#include "test.hpp"

#include <chrono>
#include <sstream>
#include <thread>

using namespace ::testing;
using namespace iox::popo;
using namespace iox::capro;
using namespace iox::cxx;
using namespace iox::mepoo;
using namespace iox::posix;
using ::testing::Return;

struct DummySample
{
    uint64_t m_dummy{42};
};

static const ServiceDescription TEST_SERVICE_DESCRIPTION("x", "y", "z");
static const iox::ProcessName_t TEST_SUBSCRIBER_APP_NAME("mySubscriberApp");
static const iox::ProcessName_t TEST_PUBLISHER_APP_NAME("myPublisherApp");

static constexpr uint32_t NUMBER_OF_PUBLISHERS = 27u;
static constexpr uint32_t ITERATIONS = 1000u;

static constexpr uint32_t NUM_CHUNKS_IN_POOL = NUMBER_OF_PUBLISHERS * ITERATIONS;
static constexpr uint32_t SMALL_CHUNK = 128u;
static constexpr uint32_t CHUNK_META_INFO_SIZE = 256u;
static constexpr size_t MEMORY_SIZE = NUM_CHUNKS_IN_POOL * (SMALL_CHUNK + CHUNK_META_INFO_SIZE);
alignas(64) static uint8_t g_memory[MEMORY_SIZE];

class PortUser_IntegrationTest : public Test
{
  public:
    PortUser_IntegrationTest()
    {
        m_mempoolConfig.addMemPool({SMALL_CHUNK, NUM_CHUNKS_IN_POOL});
        m_memoryManager.configureMemoryManager(m_mempoolConfig, &m_memoryAllocator, &m_memoryAllocator);
    }

    ~PortUser_IntegrationTest()
    {
    }

    void SetUp()
    {
        for (uint32_t i = 0; i < NUMBER_OF_PUBLISHERS; i++)
        {
            std::stringstream publisherAppName;
            publisherAppName << TEST_PUBLISHER_APP_NAME << i;

            iox::cxx::string<100> processName(TruncateToCapacity, publisherAppName.str().c_str());

            m_publisherPortDataVector.emplace_back(TEST_SERVICE_DESCRIPTION, processName, &m_memoryManager);
            m_publisherPortUserVector.emplace_back(&m_publisherPortDataVector.back());
            m_publisherPortRouDiVector.emplace_back(&m_publisherPortDataVector.back());
        }
    }

    void TearDown()
    {
        for (uint32_t i = 0; i < NUMBER_OF_PUBLISHERS; i++)
        {
            m_publisherPortUserVector[i].stopOffer();
            static_cast<void>(m_publisherPortRouDiVector[i].getCaProMessage());
        }

        m_subscriberPortUserSingleProducer.unsubscribe();
        m_subscriberPortUserMultiProducer.unsubscribe();

        static_cast<void>(m_subscriberPortRouDiSingleProducer.getCaProMessage());
        static_cast<void>(m_subscriberPortRouDiMultiProducer.getCaProMessage());
    }

    GenericRAII m_uniqueRouDiId{[] { iox::popo::internal::setUniqueRouDiId(0); },
                                [] { iox::popo::internal::unsetUniqueRouDiId(); }};

    uint64_t m_receiveCounter{0};
    std::atomic<uint64_t> m_sendCounter{0};
    std::atomic<uint64_t> m_publisherRunFinished{0};

    // Memory objects
    Allocator m_memoryAllocator{g_memory, MEMORY_SIZE};
    MePooConfig m_mempoolConfig;
    MemoryManager m_memoryManager;

    using ConcurrentCaproMessageVector_t = iox::concurrent::smart_lock<vector<CaproMessage, 1>>;
    ConcurrentCaproMessageVector_t m_concurrentCaproMessageExchange;
    ConcurrentCaproMessageVector_t m_concurrentCaproMessageRx;

    // subscriber port for single producer
    SubscriberPortData m_subscriberPortDataSingleProducer{
        TEST_SERVICE_DESCRIPTION, TEST_SUBSCRIBER_APP_NAME, VariantQueueTypes::SoFi_SingleProducerSingleConsumer};
    SubscriberPortUser m_subscriberPortUserSingleProducer{&m_subscriberPortDataSingleProducer};
    SubscriberPortSingleProducer m_subscriberPortRouDiSingleProducer{&m_subscriberPortDataSingleProducer};

    // subscriber port for multi producer
    SubscriberPortData m_subscriberPortDataMultiProducer{
        TEST_SERVICE_DESCRIPTION, TEST_SUBSCRIBER_APP_NAME, VariantQueueTypes::SoFi_MultiProducerSingleConsumer};
    SubscriberPortUser m_subscriberPortUserMultiProducer{&m_subscriberPortDataMultiProducer};
    SubscriberPortMultiProducer m_subscriberPortRouDiMultiProducer{&m_subscriberPortDataMultiProducer};

    // publisher port
    vector<PublisherPortData, NUMBER_OF_PUBLISHERS> m_publisherPortDataVector;
    vector<PublisherPortUser, NUMBER_OF_PUBLISHERS> m_publisherPortUserVector;
    vector<PublisherPortRouDi, NUMBER_OF_PUBLISHERS> m_publisherPortRouDiVector;

    inline CaproMessage waitForCaproMessage(const ConcurrentCaproMessageVector_t& concurrentCaproMessageVector,
                                            const CaproMessageType& caproMessageType)
    {
        bool finished{false};
        CaproMessage caproMessage;

        // Wait until the expected CaPro message has arrived in the shared message vector between subscriber and the
        // first publisher thread
        do
        {
            // Add delay to allow other thread accessing the shared resource
            std::this_thread::sleep_for(std::chrono::microseconds(10));
            {
                auto guardedVector = concurrentCaproMessageVector.GetScopeGuard();
                if (guardedVector->size() != 0)
                {
                    caproMessage = guardedVector->back();

                    if (caproMessage.m_type == caproMessageType)
                    {
                        guardedVector->pop_back();
                        finished = true;
                    }
                }
            }
        } while (!finished);

        return caproMessage;
    }

    template <typename SubscriberPortProducerType>
    void subscriberThread(uint32_t numberOfPublishers,
                          SubscriberPortProducerType& subscriberPortRouDi,
                          SubscriberPortUser& subscriberPortUser)
    {
        bool finished{false};

        // Wait for publisher to be ready
        auto caproMessage = waitForCaproMessage(m_concurrentCaproMessageExchange, CaproMessageType::OFFER);

        // Subscribe to publisher
        subscriberPortUser.subscribe();
        auto maybeCaproMessage = subscriberPortRouDi.getCaProMessage();
        if (maybeCaproMessage.has_value())
        {
            caproMessage = maybeCaproMessage.value();
            m_concurrentCaproMessageExchange->push_back(caproMessage);
        }
        else
        {
            // Error shall never occur
            FAIL() << "Error in subscriber SUB CaPro message!";
        }

        // Wait for subscription ACK from publisher
        caproMessage = waitForCaproMessage(m_concurrentCaproMessageExchange, CaproMessageType::ACK);

        // Let RouDi change state to finish subscription
        static_cast<void>(subscriberPortRouDi.dispatchCaProMessage(caproMessage));

        // Subscription done and ready to receive samples
        while (!finished)
        {
            // Try to receive chunk
            subscriberPortUser.getChunk()
                .and_then([&](optional<const ChunkHeader*>& maybeChunkHeader) {
                    if (maybeChunkHeader.has_value())
                    {
                        auto chunkHeader = maybeChunkHeader.value();
                        m_receiveCounter++;
                        subscriberPortUser.releaseChunk(chunkHeader);
                    }
                    else
                    {
                        // Nothing received -> check if publisher(s) still running
                        if (m_publisherRunFinished.load(std::memory_order_relaxed) == numberOfPublishers)
                        {
                            finished = true;
                        }
                    }
                })
                .or_else([](ChunkReceiveError error) {
                    // Errors shall never occur
                    FAIL() << "Error in getChunk(): " << static_cast<uint32_t>(error);
                });
        }
    }

    void publisherThread(uint32_t publisherThreadIndex,
                         PublisherPortRouDi& publisherPortRouDi,
                         PublisherPortUser& publisherPortUser)
    {
        CaproMessage caproMessage;

        // Publisher offers its service
        publisherPortUser.offer();

        // Let RouDi change state and send OFFER to subscriber
        auto maybeCaproMessage = publisherPortRouDi.getCaProMessage();

        if (publisherThreadIndex == 0)
        {
            // First publisher thread will sync with subscriber
            if (maybeCaproMessage.has_value())
            {
                caproMessage = maybeCaproMessage.value();
                m_concurrentCaproMessageExchange->push_back(caproMessage);
            }
            else
            {
                // Error shall never occur
                FAIL() << "Error in publisher OFFER CaPro message!";
            }

            // Wait for subscriber to subscribe
            caproMessage = waitForCaproMessage(m_concurrentCaproMessageExchange, CaproMessageType::SUB);
            m_concurrentCaproMessageRx->push_back(caproMessage);

            // Send ACK to subscriber
            maybeCaproMessage = publisherPortRouDi.dispatchCaProMessage(m_concurrentCaproMessageRx->back());
            if (maybeCaproMessage.has_value())
            {
                caproMessage = maybeCaproMessage.value();
                m_concurrentCaproMessageExchange->push_back(caproMessage);
            }
            else
            {
                // Error shall never occur
                FAIL() << "Error in publisher ACK CaPro message!";
            }
        }
        else
        {
            // All other publisher threads wait for the first thread to be synced with subscriber (indicated by
            // receiving a SUB message) to continue
            CaproMessage caproMessageRouDi(CaproMessageType::UNSUB, TEST_SERVICE_DESCRIPTION);
            do
            {
                std::this_thread::sleep_for(std::chrono::microseconds(10));

                if (m_concurrentCaproMessageRx->size() != 0)
                {
                    caproMessageRouDi = m_concurrentCaproMessageRx->back();
                }

            } while (caproMessageRouDi.m_type != CaproMessageType::SUB);

            static_cast<void>(publisherPortRouDi.dispatchCaProMessage(caproMessageRouDi));
        }

        // Subscriber is ready to receive -> start sending samples
        for (size_t i = 0; i < ITERATIONS; i++)
        {
            publisherPortUser.allocateChunk(sizeof(DummySample))
                .and_then([&](ChunkHeader* chunkHeader) {
                    auto sample = chunkHeader->payload();
                    new (sample) DummySample();
                    static_cast<DummySample*>(sample)->m_dummy = i;
                    publisherPortUser.sendChunk(chunkHeader);
                    m_sendCounter++;
                })
                .or_else([](AllocationError error) {
                    // Errors shall never occur
                    FAIL() << "Error in allocateChunk(): " << static_cast<uint32_t>(error);
                });

            /// Add some jitter to make thread breathe
            std::this_thread::sleep_for(std::chrono::microseconds(rand() % 750));
        }

        // Signal the subscriber thread we're done
        m_publisherRunFinished++;
    }
};

TEST_F(PortUser_IntegrationTest, SingleProducer)
{
    constexpr uint32_t NUMBER_OF_PUBLISHERS_SINGLE_PRODUCER = 1u;
    constexpr uint32_t INDEX_OF_PUBLISHER_SINGLE_PRODUCER = 0u;

    std::thread subscribingThread(std::bind(&PortUser_IntegrationTest::subscriberThread<SubscriberPortSingleProducer>,
                                            this,
                                            NUMBER_OF_PUBLISHERS_SINGLE_PRODUCER,
                                            std::ref(PortUser_IntegrationTest::m_subscriberPortRouDiSingleProducer),
                                            std::ref(PortUser_IntegrationTest::m_subscriberPortUserSingleProducer)));
    std::thread publishingThread(std::bind(&PortUser_IntegrationTest::publisherThread,
                                           this,
                                           INDEX_OF_PUBLISHER_SINGLE_PRODUCER,
                                           std::ref(PortUser_IntegrationTest::m_publisherPortRouDiVector.front()),
                                           std::ref(PortUser_IntegrationTest::m_publisherPortUserVector.front())));

    if (subscribingThread.joinable())
    {
        subscribingThread.join();
    }

    if (publishingThread.joinable())
    {
        publishingThread.join();
    }

    EXPECT_EQ(m_sendCounter.load(std::memory_order_relaxed), m_receiveCounter);
    EXPECT_EQ(PortUser_IntegrationTest::m_subscriberPortUserMultiProducer.hasLostChunks(), false);
}

TEST_F(PortUser_IntegrationTest, MultiProducer)
{
    std::thread subscribingThread(std::bind(&PortUser_IntegrationTest::subscriberThread<SubscriberPortMultiProducer>,
                                            this,
                                            NUMBER_OF_PUBLISHERS,
                                            std::ref(PortUser_IntegrationTest::m_subscriberPortRouDiMultiProducer),
                                            std::ref(PortUser_IntegrationTest::m_subscriberPortUserMultiProducer)));

    vector<std::thread, NUMBER_OF_PUBLISHERS> publisherThreadVector;
    for (uint32_t i = 0; i < NUMBER_OF_PUBLISHERS; i++)
    {
        publisherThreadVector.emplace_back(std::bind(&PortUser_IntegrationTest::publisherThread,
                                                     this,
                                                     i,
                                                     std::ref(PortUser_IntegrationTest::m_publisherPortRouDiVector[i]),
                                                     std::ref(PortUser_IntegrationTest::m_publisherPortUserVector[i])));
    }

    if (subscribingThread.joinable())
    {
        subscribingThread.join();
    }

    for (uint32_t i = 0; i < NUMBER_OF_PUBLISHERS; i++)
    {
        if (publisherThreadVector[i].joinable())
        {
            publisherThreadVector[i].join();
        }
    }

    EXPECT_EQ(m_sendCounter.load(std::memory_order_relaxed), m_receiveCounter);
    EXPECT_EQ(PortUser_IntegrationTest::m_subscriberPortUserMultiProducer.hasLostChunks(), false);
}
<|endoftext|>


<commit_before>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: propertysethelper.cxx,v $
 *
 *  $Revision: 1.3 $
 *
 *  last change: $Author: rt $ $Date: 2005-09-08 19:25:24 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    This library is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *    Lesser General Public License for more details.
 *
 *    You should have received a copy of the GNU Lesser General Public
 *    License along with this library; if not, write to the Free Software
 *    Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/

#include "propertysethelper.hxx"

#ifndef _COM_SUN_STAR_LANG_XTYPEPROVIDER_HPP_
#include <com/sun/star/lang/XTypeProvider.hpp>
#endif

#include <cppuhelper/typeprovider.hxx>

//..........................................................................
namespace extensions {
    namespace apihelper {
//..........................................................................
        namespace uno   = com::sun::star::uno;
        namespace lang  = com::sun::star::lang;
        namespace beans = com::sun::star::beans;
//..........................................................................
PropertySetHelper::PropertySetHelper()
: BroadcasterBase()
, cppu::OWeakObject()
, cppu::OPropertySetHelper( BroadcasterBase::getBroadcastHelper() )
, m_pHelper(0)
{
}

//..........................................................................
PropertySetHelper::~PropertySetHelper()
{
    delete m_pHelper;
}

//..........................................................................
// XInterface
uno::Any SAL_CALL PropertySetHelper::queryInterface( uno::Type const & rType ) throw (uno::RuntimeException)
{
    uno::Any aResult = cppu::OPropertySetHelper::queryInterface(rType);
    if (!aResult.hasValue())
        aResult = OWeakObject::queryInterface(rType);
    return aResult;
}

void SAL_CALL PropertySetHelper::acquire() throw ()
{
    OWeakObject::acquire();
}

void SAL_CALL PropertySetHelper::release() throw ()
{
    if (m_refCount == 1)
        this->disposing();

    OWeakObject::release();
}

//..........................................................................
// XTypeProvider
uno::Sequence< uno::Type > SAL_CALL PropertySetHelper::getTypes() throw (uno::RuntimeException)
{
    // could be static instance
    cppu::OTypeCollection aTypes(
        ::getCppuType( static_cast< uno::Reference< beans::XPropertySet > const * >(0) ),
        ::getCppuType( static_cast< uno::Reference< beans::XMultiPropertySet > const * >(0) ),
        ::getCppuType( static_cast< uno::Reference< beans::XFastPropertySet > const * >(0) ),
        ::getCppuType( static_cast< uno::Reference< lang::XTypeProvider > const * >(0) ) );

    return aTypes.getTypes();
}

//..........................................................................
// cppu::OPropertySetHelper
uno::Reference< beans::XPropertySetInfo > SAL_CALL PropertySetHelper::getPropertySetInfo(  )
    throw (uno::RuntimeException)
{
    return createPropertySetInfo(getInfoHelper());
}

//..........................................................................
cppu::IPropertyArrayHelper & SAL_CALL PropertySetHelper::getInfoHelper()
{
    osl::MutexGuard aGuard( getBroadcastMutex() );
    if (!m_pHelper)
        m_pHelper = newInfoHelper();

    OSL_ENSURE(m_pHelper,"Derived class did not create new PropertyInfoHelper");
    if (!m_pHelper)
        throw uno::RuntimeException(rtl::OUString::createFromAscii("No PropertyArrayHelper available"),*this);

    return *m_pHelper;
}

//..........................................................................
sal_Bool SAL_CALL PropertySetHelper::convertFastPropertyValue(
    uno::Any & rConvertedValue, uno::Any & rOldValue, sal_Int32 nHandle, const uno::Any& rValue )
        throw (lang::IllegalArgumentException)
{
    this->getFastPropertyValue(rOldValue, nHandle);
    rConvertedValue = rValue;
    return rValue.isExtractableTo( rOldValue.getValueType() );
}

//..........................................................................
void SAL_CALL ReadOnlyPropertySetHelper::setFastPropertyValue_NoBroadcast(
    sal_Int32 nHandle, const uno::Any& rValue )
        throw (uno::Exception)
{
    OSL_ENSURE(false, "Attempt to set value in read-only property set");
    throw beans::PropertyVetoException(rtl::OUString::createFromAscii("Attempt to set value in Read-Only property set"),*this);
}

//..........................................................................
sal_Bool SAL_CALL ReadOnlyPropertySetHelper::convertFastPropertyValue(
    uno::Any & rConvertedValue, uno::Any & rOldValue, sal_Int32 nHandle, const uno::Any& rValue )
        throw (lang::IllegalArgumentException)
{
    OSL_ENSURE(false, "Attempt to convert value in read-only property set");
    return false;
}
//..........................................................................
//..........................................................................
    }   // namespace apihelper
}   // namespace extensions
//..........................................................................

<commit_msg>INTEGRATION: CWS pchfix02 (1.3.186); FILE MERGED 2006/09/01 17:26:28 kaib 1.3.186.1: #i68856# Added header markers and pch files<commit_after>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: propertysethelper.cxx,v $
 *
 *  $Revision: 1.4 $
 *
 *  last change: $Author: obo $ $Date: 2006-09-16 12:58:28 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    This library is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *    Lesser General Public License for more details.
 *
 *    You should have received a copy of the GNU Lesser General Public
 *    License along with this library; if not, write to the Free Software
 *    Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/

// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_extensions.hxx"

#include "propertysethelper.hxx"

#ifndef _COM_SUN_STAR_LANG_XTYPEPROVIDER_HPP_
#include <com/sun/star/lang/XTypeProvider.hpp>
#endif

#include <cppuhelper/typeprovider.hxx>

//..........................................................................
namespace extensions {
    namespace apihelper {
//..........................................................................
        namespace uno   = com::sun::star::uno;
        namespace lang  = com::sun::star::lang;
        namespace beans = com::sun::star::beans;
//..........................................................................
PropertySetHelper::PropertySetHelper()
: BroadcasterBase()
, cppu::OWeakObject()
, cppu::OPropertySetHelper( BroadcasterBase::getBroadcastHelper() )
, m_pHelper(0)
{
}

//..........................................................................
PropertySetHelper::~PropertySetHelper()
{
    delete m_pHelper;
}

//..........................................................................
// XInterface
uno::Any SAL_CALL PropertySetHelper::queryInterface( uno::Type const & rType ) throw (uno::RuntimeException)
{
    uno::Any aResult = cppu::OPropertySetHelper::queryInterface(rType);
    if (!aResult.hasValue())
        aResult = OWeakObject::queryInterface(rType);
    return aResult;
}

void SAL_CALL PropertySetHelper::acquire() throw ()
{
    OWeakObject::acquire();
}

void SAL_CALL PropertySetHelper::release() throw ()
{
    if (m_refCount == 1)
        this->disposing();

    OWeakObject::release();
}

//..........................................................................
// XTypeProvider
uno::Sequence< uno::Type > SAL_CALL PropertySetHelper::getTypes() throw (uno::RuntimeException)
{
    // could be static instance
    cppu::OTypeCollection aTypes(
        ::getCppuType( static_cast< uno::Reference< beans::XPropertySet > const * >(0) ),
        ::getCppuType( static_cast< uno::Reference< beans::XMultiPropertySet > const * >(0) ),
        ::getCppuType( static_cast< uno::Reference< beans::XFastPropertySet > const * >(0) ),
        ::getCppuType( static_cast< uno::Reference< lang::XTypeProvider > const * >(0) ) );

    return aTypes.getTypes();
}

//..........................................................................
// cppu::OPropertySetHelper
uno::Reference< beans::XPropertySetInfo > SAL_CALL PropertySetHelper::getPropertySetInfo(  )
    throw (uno::RuntimeException)
{
    return createPropertySetInfo(getInfoHelper());
}

//..........................................................................
cppu::IPropertyArrayHelper & SAL_CALL PropertySetHelper::getInfoHelper()
{
    osl::MutexGuard aGuard( getBroadcastMutex() );
    if (!m_pHelper)
        m_pHelper = newInfoHelper();

    OSL_ENSURE(m_pHelper,"Derived class did not create new PropertyInfoHelper");
    if (!m_pHelper)
        throw uno::RuntimeException(rtl::OUString::createFromAscii("No PropertyArrayHelper available"),*this);

    return *m_pHelper;
}

//..........................................................................
sal_Bool SAL_CALL PropertySetHelper::convertFastPropertyValue(
    uno::Any & rConvertedValue, uno::Any & rOldValue, sal_Int32 nHandle, const uno::Any& rValue )
        throw (lang::IllegalArgumentException)
{
    this->getFastPropertyValue(rOldValue, nHandle);
    rConvertedValue = rValue;
    return rValue.isExtractableTo( rOldValue.getValueType() );
}

//..........................................................................
void SAL_CALL ReadOnlyPropertySetHelper::setFastPropertyValue_NoBroadcast(
    sal_Int32 nHandle, const uno::Any& rValue )
        throw (uno::Exception)
{
    OSL_ENSURE(false, "Attempt to set value in read-only property set");
    throw beans::PropertyVetoException(rtl::OUString::createFromAscii("Attempt to set value in Read-Only property set"),*this);
}

//..........................................................................
sal_Bool SAL_CALL ReadOnlyPropertySetHelper::convertFastPropertyValue(
    uno::Any & rConvertedValue, uno::Any & rOldValue, sal_Int32 nHandle, const uno::Any& rValue )
        throw (lang::IllegalArgumentException)
{
    OSL_ENSURE(false, "Attempt to convert value in read-only property set");
    return false;
}
//..........................................................................
//..........................................................................
    }   // namespace apihelper
}   // namespace extensions
//..........................................................................

<|endoftext|>


<commit_before>template <size_t maxSets>
inline DescriptorSetPool<maxSets>::DescriptorSetPool(Renderer& renderer) : _renderer(renderer) {}

template <size_t maxSets>
inline DescriptorSetPool<maxSets>::~DescriptorSetPool() {
    descriptorPool.destroy();
}

template <size_t maxSets>
inline bool DescriptorSetPool<maxSets>::init() {
    if (static_cast<VkDescriptorPool>(descriptorPool) == VK_NULL_HANDLE) {
        API::Builder::DescriptorPool descriptorPoolBuilder(_renderer.getDevice());

        // Use VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT to individually free descritors sets
        descriptorPoolBuilder.setFlags(0);

        descriptorPoolBuilder.setMaxSets(42); // TODO: Replace this arbitrary number

        std::vector<VkDescriptorPoolSize> poolSizes{ // TODO: Replace this initialization
            {
                /* poolSize.type            */ VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC,
                /* poolSize.descriptorCount */ 42
            },
            {
                /* poolSize.type            */ VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,
                /* poolSize.descriptorCount */ 42
            }
        };
        descriptorPoolBuilder.setPoolSizes(poolSizes);

        VkResult result{VK_SUCCESS};
        if (!descriptorPoolBuilder.build(descriptorPool, &result)) {
            LUG_LOG.error("DescriptorSetPool: Can't create the descriptor pool: {}", result);
            return false;
        }
    }
    return true;
}

template <size_t maxSets>
inline std::tuple<bool, const DescriptorSet*> DescriptorSetPool<maxSets>::allocate(size_t hash, const API::DescriptorSetLayout& descriptorSetLayout) {
    auto it = _descriptorSetsInUse.find(hash);
    if (it == _descriptorSetsInUse.end()) {
        DescriptorSet* descriptorSet = allocateNewDescriptorSet(descriptorSetLayout);

        if (!descriptorSet) {
            return std::make_tuple(false, nullptr);
        }

        descriptorSet->setHash(hash);
        _descriptorSetsInUse[hash] = descriptorSet;

        return std::make_tuple(true, descriptorSet);
    }

    it->second->_referenceCount += 1;
    return std::make_tuple(false, it->second);
}

template <size_t maxSets>
inline void DescriptorSetPool<maxSets>::free(const DescriptorSet* descriptorSet) {
    if (!descriptorSet) {
        return;
    }

    const_cast<DescriptorSet*>(descriptorSet)->_referenceCount -= 1;

    const auto it = _descriptorSetsInUse.find(descriptorSet->getHash());
    if (descriptorSet->_referenceCount == 0) {
        if (it != _descriptorSetsInUse.end() && it->second == descriptorSet) {
            _descriptorSetsInUse.erase(descriptorSet->getHash());
        } else {
            _freeDescriptorSets[_freeDescriptorSetsCount++] = const_cast<DescriptorSet*>(descriptorSet);
        }
    }
}

template <size_t maxSets>
inline DescriptorSet* DescriptorSetPool<maxSets>::allocateNewDescriptorSet(const API::DescriptorSetLayout& descriptorSetLayout) {
    if (_freeDescriptorSetsCount) {
        DescriptorSet* tmp = _freeDescriptorSets[_freeDescriptorSetsCount];

        _freeDescriptorSets[_freeDescriptorSetsCount--] = nullptr;
        tmp->_referenceCount += 1;

        return tmp;
    } else if (_descriptorSetsCount < maxSets) {
        API::Builder::DescriptorSet descriptorSetBuilder(_renderer.getDevice(), descriptorPool);
        descriptorSetBuilder.setDescriptorSetLayouts({static_cast<VkDescriptorSetLayout>(descriptorSetLayout)});

        API::DescriptorSet descriptorSet;
        VkResult result{VK_SUCCESS};
        if (!descriptorSetBuilder.build(_descriptorSets[_descriptorSetsCount]._descriptorSet, &result)) {
            LUG_LOG.error("DescriptorSetPool: Can't create descriptor set: {}", result);
            return nullptr;
        }

        return &_descriptorSets[_descriptorSetsCount++];
    } else {
        LUG_LOG.error("DescriptorSetPool: Can't create descriptor set: Maximum number of sets reached");
    }

    return nullptr;
}
<commit_msg>Fix a fail of reference counting in DescriptorSetPool<commit_after>template <size_t maxSets>
inline DescriptorSetPool<maxSets>::DescriptorSetPool(Renderer& renderer) : _renderer(renderer) {}

template <size_t maxSets>
inline DescriptorSetPool<maxSets>::~DescriptorSetPool() {
    descriptorPool.destroy();
}

template <size_t maxSets>
inline bool DescriptorSetPool<maxSets>::init() {
    if (static_cast<VkDescriptorPool>(descriptorPool) == VK_NULL_HANDLE) {
        API::Builder::DescriptorPool descriptorPoolBuilder(_renderer.getDevice());

        // Use VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT to individually free descritors sets
        descriptorPoolBuilder.setFlags(0);

        descriptorPoolBuilder.setMaxSets(42); // TODO: Replace this arbitrary number

        std::vector<VkDescriptorPoolSize> poolSizes{ // TODO: Replace this initialization
            {
                /* poolSize.type            */ VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC,
                /* poolSize.descriptorCount */ 42
            },
            {
                /* poolSize.type            */ VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,
                /* poolSize.descriptorCount */ 42
            }
        };
        descriptorPoolBuilder.setPoolSizes(poolSizes);

        VkResult result{VK_SUCCESS};
        if (!descriptorPoolBuilder.build(descriptorPool, &result)) {
            LUG_LOG.error("DescriptorSetPool: Can't create the descriptor pool: {}", result);
            return false;
        }
    }
    return true;
}

template <size_t maxSets>
inline std::tuple<bool, const DescriptorSet*> DescriptorSetPool<maxSets>::allocate(size_t hash, const API::DescriptorSetLayout& descriptorSetLayout) {
    auto it = _descriptorSetsInUse.find(hash);
    if (it == _descriptorSetsInUse.end()) {
        DescriptorSet* descriptorSet = allocateNewDescriptorSet(descriptorSetLayout);

        if (!descriptorSet) {
            return std::make_tuple(false, nullptr);
        }

        descriptorSet->setHash(hash);
        descriptorSet->_referenceCount += 1;

        _descriptorSetsInUse[hash] = descriptorSet;

        return std::make_tuple(true, descriptorSet);
    }

    it->second->_referenceCount += 1;
    return std::make_tuple(false, it->second);
}

template <size_t maxSets>
inline void DescriptorSetPool<maxSets>::free(const DescriptorSet* descriptorSet) {
    if (!descriptorSet) {
        return;
    }

    const_cast<DescriptorSet*>(descriptorSet)->_referenceCount -= 1;

    const auto it = _descriptorSetsInUse.find(descriptorSet->getHash());
    if (descriptorSet->_referenceCount == 0) {
        if (it != _descriptorSetsInUse.end() && it->second == descriptorSet) {
            _descriptorSetsInUse.erase(descriptorSet->getHash());
        } else {
            _freeDescriptorSets[_freeDescriptorSetsCount++] = const_cast<DescriptorSet*>(descriptorSet);
        }
    }
}

template <size_t maxSets>
inline DescriptorSet* DescriptorSetPool<maxSets>::allocateNewDescriptorSet(const API::DescriptorSetLayout& descriptorSetLayout) {
    if (_freeDescriptorSetsCount) {
        DescriptorSet* tmp = _freeDescriptorSets[_freeDescriptorSetsCount];

        _freeDescriptorSets[_freeDescriptorSetsCount--] = nullptr;

        return tmp;
    } else if (_descriptorSetsCount < maxSets) {
        API::Builder::DescriptorSet descriptorSetBuilder(_renderer.getDevice(), descriptorPool);
        descriptorSetBuilder.setDescriptorSetLayouts({static_cast<VkDescriptorSetLayout>(descriptorSetLayout)});

        VkResult result{VK_SUCCESS};
        if (!descriptorSetBuilder.build(_descriptorSets[_descriptorSetsCount]._descriptorSet, &result)) {
            LUG_LOG.error("DescriptorSetPool: Can't create descriptor set: {}", result);
            return nullptr;
        }

        return &_descriptorSets[_descriptorSetsCount++];
    } else {
        LUG_LOG.error("DescriptorSetPool: Can't create descriptor set: Maximum number of sets reached");
    }

    return nullptr;
}
<|endoftext|>