<commit_before>/*
 * Copyright (C) 2013-2016 Alexander Saprykin <xelfium@gmail.com>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301  USA.
 */

#ifndef PLIBSYS_TESTS_STATIC
#  define BOOST_TEST_DYN_LINK
#endif

#define BOOST_TEST_MODULE puthread_test

#include "plibsys.h"

#ifdef PLIBSYS_TESTS_STATIC
#  include <boost/test/included/unit_test.hpp>
#else
#  include <boost/test/unit_test.hpp>
#endif

static pint thread_wakes_1 = 0;
static pint thread_wakes_2 = 0;
static pint thread_to_wakes = 100;
static volatile pboolean is_threads_working = TRUE;

static P_HANDLE thread1_id = (P_HANDLE) NULL;
static P_HANDLE thread2_id = (P_HANDLE) NULL;

static PUThreadKey *tls_key = NULL;
static volatile pint free_counter = 0;

extern "C" ppointer pmem_alloc (psize nbytes)
{
	P_UNUSED (nbytes);
	return (ppointer) NULL;
}

extern "C" ppointer pmem_realloc (ppointer block, psize nbytes)
{
	P_UNUSED (block);
	P_UNUSED (nbytes);
	return (ppointer) NULL;
}

extern "C" void pmem_free (ppointer block)
{
	P_UNUSED (block);
}

static void free_with_check (ppointer mem)
{
	p_free (mem);
	p_atomic_int_inc (&free_counter);
}

static void * test_thread_func (void *data)
{
	pint *counter =  static_cast < pint * > (data);

	if ((*counter) == 1)
		thread1_id = p_uthread_current_id ();
	else
		thread2_id = p_uthread_current_id ();

	p_uthread_set_local (tls_key, (ppointer) p_uthread_current_id ());

	*counter = 0;

	while (is_threads_working == TRUE) {
		p_uthread_sleep (10);
		++(*counter);
		p_uthread_yield ();

		if (p_uthread_get_local (tls_key) != (ppointer) p_uthread_current_id ())
			p_uthread_exit (-1);
	}

	p_uthread_exit (*counter);
}

static void * test_thread_nonjoinable_func (void *data)
{
	pint *counter =  static_cast < pint * > (data);

	is_threads_working = TRUE;

	for (int i = thread_to_wakes; i > 0; --i) {
		p_uthread_sleep (10);
		++(*counter);
		p_uthread_yield ();
	}

	is_threads_working = FALSE;

	p_uthread_exit (0);
}

static void * test_thread_tls_func (void *data)
{
	pint self_thread_free = *((pint *) data);

	pint *tls_value = (pint *) p_malloc0 (sizeof (pint));
	*tls_value = 0;
	p_uthread_set_local (tls_key, (ppointer) tls_value);

	pint prev_tls = 0;
	pint counter  = 0;

	while (is_threads_working == TRUE) {
		p_uthread_sleep (10);

		pint *last_tls = (pint *) p_uthread_get_local (tls_key);

		if ((*last_tls) != prev_tls)
			p_uthread_exit (-1);

		pint *tls_new_value = (pint *) p_malloc0 (sizeof (pint));

		*tls_new_value = (*last_tls) + 1;
		prev_tls       = (*last_tls) + 1;

		p_uthread_replace_local (tls_key, (ppointer) tls_new_value);

		if (self_thread_free)
			p_free (last_tls);

		++counter;

		p_uthread_yield ();
	}

	p_uthread_exit (counter);
}

BOOST_AUTO_TEST_SUITE (BOOST_TEST_MODULE)

BOOST_AUTO_TEST_CASE (puthread_nomem_test)
{
	p_libsys_init ();

	PUThreadKey *thread_key = p_uthread_local_new (p_free);
	BOOST_CHECK (thread_key != NULL);

	PMemVTable vtable;

	vtable.free	= pmem_free;
	vtable.malloc	= pmem_alloc;
	vtable.realloc	= pmem_realloc;

	BOOST_CHECK (p_mem_set_vtable (&vtable) == TRUE);

	BOOST_CHECK (p_uthread_create ((PUThreadFunc) test_thread_func,
				       (ppointer) &thread_wakes_1,
				       TRUE) == NULL);

	BOOST_CHECK (p_uthread_create_full ((PUThreadFunc) test_thread_func,
					    (ppointer) &thread_wakes_2,
					    TRUE,
					    P_UTHREAD_PRIORITY_NORMAL) == NULL);

	BOOST_CHECK (p_uthread_local_new (NULL) == NULL);

	p_uthread_set_local (thread_key, PINT_TO_POINTER (10));
	BOOST_CHECK (p_uthread_get_local (thread_key) == NULL);

	vtable.malloc	= (ppointer (*)(psize)) malloc;
	vtable.realloc	= (ppointer (*)(ppointer, psize)) realloc;
	vtable.free	= (void (*)(ppointer)) free;

	BOOST_CHECK (p_mem_set_vtable (&vtable) == TRUE);

	p_uthread_local_free (thread_key);

	p_libsys_shutdown ();
}

BOOST_AUTO_TEST_CASE (puthread_bad_input_test)
{
	p_libsys_init ();

	BOOST_CHECK (p_uthread_create (NULL, NULL, false) == NULL);
	BOOST_CHECK (p_uthread_create_full (NULL, NULL, false, P_UTHREAD_PRIORITY_NORMAL) == NULL);
	BOOST_CHECK (p_uthread_join (NULL) == -1);
	BOOST_CHECK (p_uthread_set_priority (NULL, P_UTHREAD_PRIORITY_NORMAL));
	BOOST_CHECK (p_uthread_get_local (NULL) == NULL);
	p_uthread_set_local (NULL, NULL);
	p_uthread_replace_local (NULL, NULL);
	p_uthread_free (NULL);
	p_uthread_local_free (NULL);

	p_libsys_shutdown ();
}

BOOST_AUTO_TEST_CASE (puthread_general_test)
{
	p_libsys_init ();

	thread_wakes_1 = 1;
	thread_wakes_2 = 2;

	tls_key = p_uthread_local_new (NULL);
	BOOST_CHECK (tls_key != NULL);

	PUThread *thr1 = p_uthread_create ((PUThreadFunc) test_thread_func,
					   (ppointer) &thread_wakes_1,
					   TRUE);

	PUThread *thr2 = p_uthread_create_full ((PUThreadFunc) test_thread_func,
						(ppointer) &thread_wakes_2,
						TRUE,
						P_UTHREAD_PRIORITY_NORMAL);

	BOOST_CHECK (p_uthread_set_priority (thr1, P_UTHREAD_PRIORITY_NORMAL) == 0);

	BOOST_REQUIRE (thr1 != NULL);
	BOOST_REQUIRE (thr2 != NULL);

	p_uthread_sleep (5000);

	is_threads_working = FALSE;

	BOOST_CHECK (p_uthread_join (thr1) == thread_wakes_1);
	BOOST_CHECK (p_uthread_join (thr2) == thread_wakes_2);

	BOOST_REQUIRE (thread1_id != thread2_id);
	BOOST_CHECK (thread1_id != p_uthread_current_id () &&
		     thread2_id != p_uthread_current_id ());

	p_uthread_local_free (tls_key);

	p_libsys_shutdown ();
}

BOOST_AUTO_TEST_CASE (puthread_nonjoinable_test)
{
	p_libsys_init ();

	thread_wakes_1 = 0;

	PUThread *thr1 = p_uthread_create ((PUThreadFunc) test_thread_nonjoinable_func,
					   (ppointer) &thread_wakes_1,
					   FALSE);

	BOOST_REQUIRE (thr1 != NULL);

	p_uthread_sleep (3000);

	BOOST_CHECK (p_uthread_join (thr1) == -1);

	while (is_threads_working == TRUE)
		p_uthread_sleep (10);

	BOOST_CHECK (thread_wakes_1 == thread_to_wakes);

	p_libsys_shutdown ();
}

BOOST_AUTO_TEST_CASE (puthread_tls_test)
{
	p_libsys_init ();

	/* With destroy notification */
	tls_key = p_uthread_local_new (free_with_check);

	is_threads_working = TRUE;

	pint self_thread_free = 0;

	PUThread *thr1 = p_uthread_create ((PUThreadFunc) test_thread_tls_func,
					   (ppointer) &self_thread_free,
					   TRUE);

	PUThread *thr2 = p_uthread_create ((PUThreadFunc) test_thread_tls_func,
					   (ppointer) &self_thread_free,
					   TRUE);

	BOOST_REQUIRE (thr1 != NULL);
	BOOST_REQUIRE (thr2 != NULL);

	p_uthread_sleep (5000);

	is_threads_working = FALSE;

	pint total_counter = 0;

	total_counter += p_uthread_join (thr1);
	total_counter += p_uthread_join (thr2);

#ifndef P_OS_WIN
	total_counter += 2;
#endif

	BOOST_CHECK (total_counter == free_counter);

	p_uthread_local_free (tls_key);

	/* Without destroy notification */
	tls_key = p_uthread_local_new (NULL);

	free_counter       = 0;
	is_threads_working = TRUE;
	self_thread_free   = 1;

	thr1 = p_uthread_create ((PUThreadFunc) test_thread_tls_func,
				 (ppointer) &self_thread_free,
				 TRUE);

	thr2 = p_uthread_create ((PUThreadFunc) test_thread_tls_func,
				 (ppointer) &self_thread_free,
				 TRUE);

	BOOST_REQUIRE (thr1 != NULL);
	BOOST_REQUIRE (thr2 != NULL);

	p_uthread_sleep (5000);

	is_threads_working = FALSE;

	total_counter = 0;

	total_counter += p_uthread_join (thr1);
	total_counter += p_uthread_join (thr2);

#ifndef P_OS_WIN
	total_counter += 2;
#endif

	BOOST_CHECK (total_counter > 0);
	BOOST_CHECK (free_counter == 0);

	p_uthread_local_free (tls_key);

	p_libsys_shutdown ();
}

BOOST_AUTO_TEST_SUITE_END()
<commit_msg>tests: Remove Windows-specific improper actions in thread tests<commit_after>/*
 * Copyright (C) 2013-2016 Alexander Saprykin <xelfium@gmail.com>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301  USA.
 */

#ifndef PLIBSYS_TESTS_STATIC
#  define BOOST_TEST_DYN_LINK
#endif

#define BOOST_TEST_MODULE puthread_test

#include "plibsys.h"

#ifdef PLIBSYS_TESTS_STATIC
#  include <boost/test/included/unit_test.hpp>
#else
#  include <boost/test/unit_test.hpp>
#endif

static pint thread_wakes_1 = 0;
static pint thread_wakes_2 = 0;
static pint thread_to_wakes = 100;
static volatile pboolean is_threads_working = TRUE;

static P_HANDLE thread1_id = (P_HANDLE) NULL;
static P_HANDLE thread2_id = (P_HANDLE) NULL;

static PUThreadKey *tls_key = NULL;
static volatile pint free_counter = 0;

extern "C" ppointer pmem_alloc (psize nbytes)
{
	P_UNUSED (nbytes);
	return (ppointer) NULL;
}

extern "C" ppointer pmem_realloc (ppointer block, psize nbytes)
{
	P_UNUSED (block);
	P_UNUSED (nbytes);
	return (ppointer) NULL;
}

extern "C" void pmem_free (ppointer block)
{
	P_UNUSED (block);
}

static void free_with_check (ppointer mem)
{
	p_free (mem);
	p_atomic_int_inc (&free_counter);
}

static void * test_thread_func (void *data)
{
	pint *counter =  static_cast < pint * > (data);

	if ((*counter) == 1)
		thread1_id = p_uthread_current_id ();
	else
		thread2_id = p_uthread_current_id ();

	p_uthread_set_local (tls_key, (ppointer) p_uthread_current_id ());

	*counter = 0;

	while (is_threads_working == TRUE) {
		p_uthread_sleep (10);
		++(*counter);
		p_uthread_yield ();

		if (p_uthread_get_local (tls_key) != (ppointer) p_uthread_current_id ())
			p_uthread_exit (-1);
	}

	p_uthread_exit (*counter);
}

static void * test_thread_nonjoinable_func (void *data)
{
	pint *counter =  static_cast < pint * > (data);

	is_threads_working = TRUE;

	for (int i = thread_to_wakes; i > 0; --i) {
		p_uthread_sleep (10);
		++(*counter);
		p_uthread_yield ();
	}

	is_threads_working = FALSE;

	p_uthread_exit (0);
}

static void * test_thread_tls_func (void *data)
{
	pint self_thread_free = *((pint *) data);

	pint *tls_value = (pint *) p_malloc0 (sizeof (pint));
	*tls_value = 0;
	p_uthread_set_local (tls_key, (ppointer) tls_value);

	pint prev_tls = 0;
	pint counter  = 0;

	while (is_threads_working == TRUE) {
		p_uthread_sleep (10);

		pint *last_tls = (pint *) p_uthread_get_local (tls_key);

		if ((*last_tls) != prev_tls)
			p_uthread_exit (-1);

		pint *tls_new_value = (pint *) p_malloc0 (sizeof (pint));

		*tls_new_value = (*last_tls) + 1;
		prev_tls       = (*last_tls) + 1;

		p_uthread_replace_local (tls_key, (ppointer) tls_new_value);

		if (self_thread_free)
			p_free (last_tls);

		++counter;

		p_uthread_yield ();
	}

	p_uthread_exit (counter);
}

BOOST_AUTO_TEST_SUITE (BOOST_TEST_MODULE)

BOOST_AUTO_TEST_CASE (puthread_nomem_test)
{
	p_libsys_init ();

	PUThreadKey *thread_key = p_uthread_local_new (p_free);
	BOOST_CHECK (thread_key != NULL);

	PMemVTable vtable;

	vtable.free	= pmem_free;
	vtable.malloc	= pmem_alloc;
	vtable.realloc	= pmem_realloc;

	BOOST_CHECK (p_mem_set_vtable (&vtable) == TRUE);

	BOOST_CHECK (p_uthread_create ((PUThreadFunc) test_thread_func,
				       (ppointer) &thread_wakes_1,
				       TRUE) == NULL);

	BOOST_CHECK (p_uthread_create_full ((PUThreadFunc) test_thread_func,
					    (ppointer) &thread_wakes_2,
					    TRUE,
					    P_UTHREAD_PRIORITY_NORMAL) == NULL);

	BOOST_CHECK (p_uthread_local_new (NULL) == NULL);

	p_uthread_set_local (thread_key, PINT_TO_POINTER (10));
	BOOST_CHECK (p_uthread_get_local (thread_key) == NULL);

	vtable.malloc	= (ppointer (*)(psize)) malloc;
	vtable.realloc	= (ppointer (*)(ppointer, psize)) realloc;
	vtable.free	= (void (*)(ppointer)) free;

	BOOST_CHECK (p_mem_set_vtable (&vtable) == TRUE);

	p_uthread_local_free (thread_key);

	p_libsys_shutdown ();
}

BOOST_AUTO_TEST_CASE (puthread_bad_input_test)
{
	p_libsys_init ();

	BOOST_CHECK (p_uthread_create (NULL, NULL, false) == NULL);
	BOOST_CHECK (p_uthread_create_full (NULL, NULL, false, P_UTHREAD_PRIORITY_NORMAL) == NULL);
	BOOST_CHECK (p_uthread_join (NULL) == -1);
	BOOST_CHECK (p_uthread_set_priority (NULL, P_UTHREAD_PRIORITY_NORMAL));
	BOOST_CHECK (p_uthread_get_local (NULL) == NULL);
	p_uthread_set_local (NULL, NULL);
	p_uthread_replace_local (NULL, NULL);
	p_uthread_free (NULL);
	p_uthread_local_free (NULL);

	p_libsys_shutdown ();
}

BOOST_AUTO_TEST_CASE (puthread_general_test)
{
	p_libsys_init ();

	thread_wakes_1 = 1;
	thread_wakes_2 = 2;

	tls_key = p_uthread_local_new (NULL);
	BOOST_CHECK (tls_key != NULL);

	PUThread *thr1 = p_uthread_create ((PUThreadFunc) test_thread_func,
					   (ppointer) &thread_wakes_1,
					   TRUE);

	PUThread *thr2 = p_uthread_create_full ((PUThreadFunc) test_thread_func,
						(ppointer) &thread_wakes_2,
						TRUE,
						P_UTHREAD_PRIORITY_NORMAL);

	BOOST_CHECK (p_uthread_set_priority (thr1, P_UTHREAD_PRIORITY_NORMAL) == 0);

	BOOST_REQUIRE (thr1 != NULL);
	BOOST_REQUIRE (thr2 != NULL);

	p_uthread_sleep (5000);

	is_threads_working = FALSE;

	BOOST_CHECK (p_uthread_join (thr1) == thread_wakes_1);
	BOOST_CHECK (p_uthread_join (thr2) == thread_wakes_2);

	BOOST_REQUIRE (thread1_id != thread2_id);
	BOOST_CHECK (thread1_id != p_uthread_current_id () &&
		     thread2_id != p_uthread_current_id ());

	p_uthread_local_free (tls_key);

	p_libsys_shutdown ();
}

BOOST_AUTO_TEST_CASE (puthread_nonjoinable_test)
{
	p_libsys_init ();

	thread_wakes_1 = 0;

	PUThread *thr1 = p_uthread_create ((PUThreadFunc) test_thread_nonjoinable_func,
					   (ppointer) &thread_wakes_1,
					   FALSE);

	BOOST_REQUIRE (thr1 != NULL);

	p_uthread_sleep (3000);

	BOOST_CHECK (p_uthread_join (thr1) == -1);

	while (is_threads_working == TRUE)
		p_uthread_sleep (10);

	BOOST_CHECK (thread_wakes_1 == thread_to_wakes);

	p_libsys_shutdown ();
}

BOOST_AUTO_TEST_CASE (puthread_tls_test)
{
	p_libsys_init ();

	/* With destroy notification */
	tls_key = p_uthread_local_new (free_with_check);

	is_threads_working = TRUE;

	pint self_thread_free = 0;

	PUThread *thr1 = p_uthread_create ((PUThreadFunc) test_thread_tls_func,
					   (ppointer) &self_thread_free,
					   TRUE);

	PUThread *thr2 = p_uthread_create ((PUThreadFunc) test_thread_tls_func,
					   (ppointer) &self_thread_free,
					   TRUE);

	BOOST_REQUIRE (thr1 != NULL);
	BOOST_REQUIRE (thr2 != NULL);

	p_uthread_sleep (5000);

	is_threads_working = FALSE;

	pint total_counter = 0;

	total_counter += p_uthread_join (thr1);
	total_counter += p_uthread_join (thr2);

	BOOST_CHECK (total_counter == free_counter);

	p_uthread_local_free (tls_key);

	/* Without destroy notification */
	tls_key = p_uthread_local_new (NULL);

	free_counter       = 0;
	is_threads_working = TRUE;
	self_thread_free   = 1;

	thr1 = p_uthread_create ((PUThreadFunc) test_thread_tls_func,
				 (ppointer) &self_thread_free,
				 TRUE);

	thr2 = p_uthread_create ((PUThreadFunc) test_thread_tls_func,
				 (ppointer) &self_thread_free,
				 TRUE);

	BOOST_REQUIRE (thr1 != NULL);
	BOOST_REQUIRE (thr2 != NULL);

	p_uthread_sleep (5000);

	is_threads_working = FALSE;

	total_counter = 0;

	total_counter += p_uthread_join (thr1);
	total_counter += p_uthread_join (thr2);

	BOOST_CHECK (total_counter > 0);
	BOOST_CHECK (free_counter == 0);

	p_uthread_local_free (tls_key);

	p_libsys_shutdown ();
}

BOOST_AUTO_TEST_SUITE_END()
<|endoftext|>


<commit_before>#ifndef TEE_BUF_HPP
#define TEE_BUF_HPP

#include <string>
#include <ostream>
#include <streambuf>
#include <functional>

#define CreateOstreamTeeBuf(s, n, f) OstreamTeeBuf<decltype(s)> n(s, f)
#define BindStdStringAppend(s) std::bind<decltype(s)&(decltype(s)::*)(decltype(s)::const_pointer, size_t)>(&decltype(s)::append, &s, std::placeholders::_1, std::placeholders::_2)

template <class OstrT>
class OstreamTeeBuf: private std::basic_streambuf<typename OstrT::char_type> {
	typedef std::function<void(const typename OstrT::char_type* s, std::streamsize n)> TeeCallbackType;
private:
	OstrT &ostr;
	std::basic_streambuf<typename OstrT::char_type> *orig_buf;
	TeeCallbackType tee_callback;
	bool no_err;

	//Hacky hacky hacky...
	//Class tries to redirect all the output to original ostream/wcostream buffer
	//This is not intended behaviour of basic_streambuf descendant
	//We are expected to provide our own buffer and handle overflow and sync functions like a good descendant wood do
	//And only while behaving like proper basic_streambuf we are allowed to do whatever we want with data passed (like forwarding it to original buffer via public functions)
	//There is a perfect reason for this - we don't know how basic_streambuf will be used and by who
	//By conforming to the standard we are ensuring that whoever use it, if he also conforms to standard, will get expected results
	//But no... we will cut off some corners and just redirect protected members to it's equivalents of original buffer via hacky means
	//Actually it works and if we redirect all of the protected members we are pretty safe
	//Observations on behaviour of GCC's ostream implementaion show that it's enough to redirect only protected functions listed below (at least for this particular implementation)
	//(BTW, ostream calls these protected functions directly because they are friends with basic_streambuf)

	std::streamsize xsputn(const typename OstrT::char_type* s, std::streamsize n) {
		if (tee_callback) tee_callback(s, n);
		std::streamsize res=((OstreamTeeBuf<OstrT>*)orig_buf)->xsputn(s, n);
		return no_err?n:res;
	};

	typename std::char_traits<typename OstrT::char_type>::int_type overflow(typename std::char_traits<typename OstrT::char_type>::int_type c) {
		if (tee_callback) {
			typename OstrT::char_type cc=std::char_traits<typename OstrT::char_type>::to_char_type(c);
			tee_callback(&cc, 1);
		}
		typename std::char_traits<typename OstrT::char_type>::int_type res=((OstreamTeeBuf<OstrT>*)orig_buf)->overflow(c);
		return no_err?(c==std::char_traits<typename OstrT::char_type>::eof()?std::char_traits<typename OstrT::char_type>::not_eof(c):c):res;
	};

	int sync() {
		int res=((OstreamTeeBuf<OstrT>*)orig_buf)->sync();
		return no_err?0:res;
	};
public:
	OstreamTeeBuf(OstrT &ostr, TeeCallbackType tee_callback): ostr(ostr), orig_buf(ostr.rdbuf(this)), tee_callback(tee_callback), no_err(false) {};

	void Deactivate() {
		if (orig_buf) {
			ostr.rdbuf(orig_buf);
			orig_buf=NULL;
		}
	};

	void IgnoreOutputErrors(bool value) {
		no_err=value;
	};

	~OstreamTeeBuf() {
		Deactivate();
	};
};

#endif //TEE_BUF_HPP
<commit_msg>Updated BindStdStringAppend macros<commit_after>#ifndef TEE_BUF_HPP
#define TEE_BUF_HPP

#include <string>
#include <ostream>
#include <streambuf>
#include <functional>

#define CreateOstreamTeeBuf(s, n, f) OstreamTeeBuf<decltype(s)> n(s, f)
#define BindStdStringAppend(s) std::bind<decltype(s)&(decltype(s)::*)(decltype(s)::const_pointer, decltype(s)::size_type)>(&decltype(s)::append, &s, std::placeholders::_1, std::placeholders::_2)

template <class OstrT>
class OstreamTeeBuf: private std::basic_streambuf<typename OstrT::char_type> {
	typedef std::function<void(const typename OstrT::char_type* s, std::streamsize n)> TeeCallbackType;
private:
	OstrT &ostr;
	std::basic_streambuf<typename OstrT::char_type> *orig_buf;
	TeeCallbackType tee_callback;
	bool no_err;

	//Hacky hacky hacky...
	//Class tries to redirect all the output to original ostream/wcostream buffer
	//This is not intended behaviour of basic_streambuf descendant
	//We are expected to provide our own buffer and handle overflow and sync functions like a good descendant wood do
	//And only while behaving like proper basic_streambuf we are allowed to do whatever we want with data passed (like forwarding it to original buffer via public functions)
	//There is a perfect reason for this - we don't know how basic_streambuf will be used and by who
	//By conforming to the standard we are ensuring that whoever use it, if he also conforms to standard, will get expected results
	//But no... we will cut off some corners and just redirect protected members to it's equivalents of original buffer via hacky means
	//Actually it works and if we redirect all of the protected members we are pretty safe
	//Observations on behaviour of GCC's ostream implementaion show that it's enough to redirect only protected functions listed below (at least for this particular implementation)
	//(BTW, ostream calls these protected functions directly because they are friends with basic_streambuf)

	std::streamsize xsputn(const typename OstrT::char_type* s, std::streamsize n) {
		if (tee_callback) tee_callback(s, n);
		std::streamsize res=((OstreamTeeBuf<OstrT>*)orig_buf)->xsputn(s, n);
		return no_err?n:res;
	};

	typename std::char_traits<typename OstrT::char_type>::int_type overflow(typename std::char_traits<typename OstrT::char_type>::int_type c) {
		if (tee_callback) {
			typename OstrT::char_type cc=std::char_traits<typename OstrT::char_type>::to_char_type(c);
			tee_callback(&cc, 1);
		}
		typename std::char_traits<typename OstrT::char_type>::int_type res=((OstreamTeeBuf<OstrT>*)orig_buf)->overflow(c);
		return no_err?(c==std::char_traits<typename OstrT::char_type>::eof()?std::char_traits<typename OstrT::char_type>::not_eof(c):c):res;
	};

	int sync() {
		int res=((OstreamTeeBuf<OstrT>*)orig_buf)->sync();
		return no_err?0:res;
	};
public:
	OstreamTeeBuf(OstrT &ostr, TeeCallbackType tee_callback): ostr(ostr), orig_buf(ostr.rdbuf(this)), tee_callback(tee_callback), no_err(false) {};

	void Deactivate() {
		if (orig_buf) {
			ostr.rdbuf(orig_buf);
			orig_buf=NULL;
		}
	};

	void IgnoreOutputErrors(bool value) {
		no_err=value;
	};

	~OstreamTeeBuf() {
		Deactivate();
	};
};

#endif //TEE_BUF_HPP
<|endoftext|>


<commit_before>// Copyright © 2014, German Neuroinformatics Node (G-Node)
//
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted under the terms of the BSD License. See
// LICENSE file in the root of the Project.
//
// Author: Christian Kellner <kellner@bio.lmu.de>

#ifndef NIX_VALUE_H
#define NIX_VALUE_H

#include <string>
#include <cstdint>
#include <stdexcept>
#include <iostream>

#include <nix/DataType.hpp>

namespace nix {

class Value {
private:
    DataType dtype;

    union {
        bool        v_bool;
        double      v_double;
        uint32_t    v_uint32;
        int32_t     v_int32;
        uint64_t    v_uint64;
        int64_t     v_int64;
        std::string v_string;
    };

public:
    double uncertainty;

    std::string reference;
    std::string filename;
    std::string encoder;
    std::string checksum;

    Value() : dtype(DataType::Nothing), v_bool(false) { }

    template<typename T>
    explicit Value(const T &value) : dtype(to_data_type<T>::value) {
        if (dtype == DataType::String) {
            new (&v_string) std::string();
        }

        set(value);
    }

    template<size_t N>
    explicit Value(const char (&value)[N]) : dtype(DataType::String) {
        new (&v_string) std::string();
        v_string = value;
    }

    Value(const Value &other) {
        assign_variant_from(other);
    }

    Value(Value &&other) : Value() {
        swap(other);
    }

    Value &operator=(Value other) {
        swap(other);
        return *this;
    }

    ~Value() {
        maybe_deallocte_string();
    }

    void set(bool   value);
    void set(int32_t value);
    void set(uint32_t value);
    void set(int64_t value);
    void set(uint64_t value);
    void set(double value);
    void set(const std::string &value);

    template<typename T>
    T get() const {
        T temp;
        get(temp);
        return temp;
    }

    void get(bool &out) const;
    void get(int32_t &value) const;
    void get(uint32_t &value) const;
    void get(int64_t &value) const;
    void get(uint64_t &value) const;
    void get(double &value) const;
    void get(std::string &value) const;

    DataType type() const {
        return dtype;
    }

    void swap(Value &other);

private:

    template<typename T>
    void swap_helper(Value &other) {
        T temp = get<T>();
        assign_variant_from(other);
        other.set(temp);
    }

    void assign_variant_from(const Value &other);
    void maybe_deallocte_string();

    inline void check_argument_type(DataType check) const {
        if (dtype != check) {
            throw std::invalid_argument("Incompatible DataType");
        }
    }
};

template<>
inline const char * Value::get<const char *>() const {
    check_argument_type(DataType::String);
    return v_string.c_str();
}

std::ostream& operator<<(std::ostream &out, const Value &value);
void swap(Value &a, Value &b);

} // namespace nix

#endif // NIX_VALUE_H
<commit_msg>Value: add ctors for [const] char *<commit_after>// Copyright © 2014, German Neuroinformatics Node (G-Node)
//
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted under the terms of the BSD License. See
// LICENSE file in the root of the Project.
//
// Author: Christian Kellner <kellner@bio.lmu.de>

#ifndef NIX_VALUE_H
#define NIX_VALUE_H

#include <string>
#include <cstdint>
#include <stdexcept>
#include <iostream>

#include <nix/DataType.hpp>

namespace nix {

class Value {
private:
    DataType dtype;

    union {
        bool        v_bool;
        double      v_double;
        uint32_t    v_uint32;
        int32_t     v_int32;
        uint64_t    v_uint64;
        int64_t     v_int64;
        std::string v_string;
    };

public:
    double uncertainty;

    std::string reference;
    std::string filename;
    std::string encoder;
    std::string checksum;

    Value() : dtype(DataType::Nothing), v_bool(false) { }

    Value(char *value) : dtype(DataType::String) {
        new (&v_string) std::string();
        v_string = value;
    }

    Value(const char *value) : dtype(DataType::String) {
        new (&v_string) std::string();
        v_string = value;
    }

    template<typename T>
    explicit Value(const T &value) : dtype(to_data_type<T>::value) {
        if (dtype == DataType::String) {
            new (&v_string) std::string();
        }

        set(value);
    }

    template<size_t N>
    explicit Value(const char (&value)[N]) : dtype(DataType::String) {
        new (&v_string) std::string();
        v_string = value;
    }

    Value(const Value &other) {
        assign_variant_from(other);
    }

    Value(Value &&other) : Value() {
        swap(other);
    }

    Value &operator=(Value other) {
        swap(other);
        return *this;
    }

    ~Value() {
        maybe_deallocte_string();
    }

    void set(bool   value);
    void set(int32_t value);
    void set(uint32_t value);
    void set(int64_t value);
    void set(uint64_t value);
    void set(double value);
    void set(const std::string &value);

    template<typename T>
    T get() const {
        T temp;
        get(temp);
        return temp;
    }

    void get(bool &out) const;
    void get(int32_t &value) const;
    void get(uint32_t &value) const;
    void get(int64_t &value) const;
    void get(uint64_t &value) const;
    void get(double &value) const;
    void get(std::string &value) const;

    DataType type() const {
        return dtype;
    }

    void swap(Value &other);

private:

    template<typename T>
    void swap_helper(Value &other) {
        T temp = get<T>();
        assign_variant_from(other);
        other.set(temp);
    }

    void assign_variant_from(const Value &other);
    void maybe_deallocte_string();

    inline void check_argument_type(DataType check) const {
        if (dtype != check) {
            throw std::invalid_argument("Incompatible DataType");
        }
    }
};

template<>
inline const char * Value::get<const char *>() const {
    check_argument_type(DataType::String);
    return v_string.c_str();
}

std::ostream& operator<<(std::ostream &out, const Value &value);
void swap(Value &a, Value &b);

} // namespace nix

#endif // NIX_VALUE_H
<|endoftext|>


<commit_before>/*
 * Copyright © 2013 Red Hat, Inc.
 *
 * Permission is hereby granted, free of charge, to any person obtaining a
 * copy of this software and associated documentation files (the "Software"),
 * to deal in the Software without restriction, including without limitation
 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
 * and/or sell copies of the Software, and to permit persons to whom the
 * Software is furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice (including the next
 * paragraph) shall be included in all copies or substantial portions of the
 * Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
 * DEALINGS IN THE SOFTWARE.
 *
 */

#if HAVE_CONFIG_H
#include <config.h>
#endif

#include <fstream>

#include <xorg/gtest/xorg-gtest.h>

#include "xit-server-input-test.h"
#include "device-interface.h"
#include "helpers.h"

using namespace xorg::testing;

class Xephyr24bppTest : public XITServerTest {
    virtual void SetUpConfigAndLog() {
        config.SetAutoAddDevices(true);
        config.AppendRawConfig(
            "Section \"ServerLayout\"\n"
            "	Identifier     \"X.org Configured\"\n"
            "	Screen        \"Screen0\"\n"
            "EndSection\n"
            "\n"
            "Section \"ServerFlags\"\n"
            "   Option \"Pixmap\" \"24\""
            "EndSection\n"
            "\n"
            "Section \"Device\"\n"
            "	Identifier  \"Card0\"\n"
            "	Driver      \"dummy\"\n"
            "EndSection\n"
            "\n"
            "Section \"Screen\"\n"
            "	Identifier \"Screen0\"\n"
            "	Device     \"Card0\"\n"
            "   SubSection \"Display\"\n"
            "       Depth     24"
            "   EndSubSection\n"
            "EndSection");

        config.WriteConfig();
    }
};

TEST_F(Xephyr24bppTest, CrashOn24bppHost)
{
    XORG_TESTCASE("Start Xephyr on a 24bpp host.\n"
                  "Verify Xephyr doesn't crash\n"
                  "https://bugzilla.redhat.com/show_bug.cgi?id=518960");

    ::Display *dpy = Display();
    int depth = DefaultDepth(dpy, 0);
    ASSERT_EQ(depth, 24);

    Process xephyr;
    setenv("DISPLAY", server.GetDisplayString().c_str(), 1);
    xephyr.Start("Xephyr", ":134", NULL);
    ASSERT_GT(xephyr.Pid(), 0);
    ASSERT_EQ(xephyr.GetState(), xorg::testing::Process::RUNNING);

    ::Display *ephdpy = NULL;

    int i = 0;
    while (i++ < 10 && !ephdpy) {
        ephdpy = XOpenDisplay(":134");
        if (!ephdpy)
            usleep(10000);
    }
    ASSERT_EQ(xephyr.GetState(), xorg::testing::Process::RUNNING);
    ASSERT_TRUE(ephdpy);

    xephyr.Terminate(1000);
}

int main(int argc, char **argv) {
    testing::InitGoogleTest(&argc, argv);
    return RUN_ALL_TESTS();
}
<commit_msg>server/Xephyr: test for 8bpp crash<commit_after>/*
 * Copyright © 2013 Red Hat, Inc.
 *
 * Permission is hereby granted, free of charge, to any person obtaining a
 * copy of this software and associated documentation files (the "Software"),
 * to deal in the Software without restriction, including without limitation
 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
 * and/or sell copies of the Software, and to permit persons to whom the
 * Software is furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice (including the next
 * paragraph) shall be included in all copies or substantial portions of the
 * Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
 * DEALINGS IN THE SOFTWARE.
 *
 */

#if HAVE_CONFIG_H
#include <config.h>
#endif

#include <fstream>

#include <xorg/gtest/xorg-gtest.h>

#include "xit-server-input-test.h"
#include "device-interface.h"
#include "helpers.h"

using namespace xorg::testing;

class Xephyr24bppTest : public XITServerTest {
    virtual void SetUpConfigAndLog() {
        config.SetAutoAddDevices(true);
        config.AppendRawConfig(
            "Section \"ServerLayout\"\n"
            "	Identifier     \"X.org Configured\"\n"
            "	Screen        \"Screen0\"\n"
            "EndSection\n"
            "\n"
            "Section \"ServerFlags\"\n"
            "   Option \"Pixmap\" \"24\""
            "EndSection\n"
            "\n"
            "Section \"Device\"\n"
            "	Identifier  \"Card0\"\n"
            "	Driver      \"dummy\"\n"
            "EndSection\n"
            "\n"
            "Section \"Screen\"\n"
            "	Identifier \"Screen0\"\n"
            "	Device     \"Card0\"\n"
            "   SubSection \"Display\"\n"
            "       Depth     24"
            "   EndSubSection\n"
            "EndSection");

        config.WriteConfig();
    }
};

TEST_F(Xephyr24bppTest, CrashOn24bppHost)
{
    XORG_TESTCASE("Start Xephyr on a 24bpp host.\n"
                  "Verify Xephyr doesn't crash\n"
                  "https://bugzilla.redhat.com/show_bug.cgi?id=518960");

    ::Display *dpy = Display();
    int depth = DefaultDepth(dpy, 0);
    ASSERT_EQ(depth, 24);

    Process xephyr;
    setenv("DISPLAY", server.GetDisplayString().c_str(), 1);
    xephyr.Start("Xephyr", ":134", NULL);
    ASSERT_GT(xephyr.Pid(), 0);
    ASSERT_EQ(xephyr.GetState(), xorg::testing::Process::RUNNING);

    ::Display *ephdpy = NULL;

    int i = 0;
    while (i++ < 10 && !ephdpy) {
        ephdpy = XOpenDisplay(":134");
        if (!ephdpy)
            usleep(10000);
    }
    ASSERT_EQ(xephyr.GetState(), xorg::testing::Process::RUNNING);
    ASSERT_TRUE(ephdpy);

    xephyr.Terminate(1000);
}

class Xephyr8bppTest : public XITServerTest {
    virtual void SetUpConfigAndLog() {
        config.AddDefaultScreenWithDriver();
        config.WriteConfig();
    }
};

TEST_F(Xephyr8bppTest, No8bppCrash)
{
    XORG_TESTCASE("Start 8-bit Xephyr.\n"
                  "Verify Xephyr doesn't crash\n"
                  "https://bugzilla.redhat.com/show_bug.cgi?id=518960");

    ::Display *dpy = Display();
    int depth = DefaultDepth(dpy, 0);
    ASSERT_GT(depth, 8);

    Process xephyr;
    setenv("DISPLAY", server.GetDisplayString().c_str(), 1);
    xephyr.Start("Xephyr", "-screen", "320x220x8", ":134", NULL);
    ASSERT_GT(xephyr.Pid(), 0);
    ASSERT_EQ(xephyr.GetState(), xorg::testing::Process::RUNNING);

    ::Display *ephdpy = NULL;

    int i = 0;
    while (i++ < 10 && !ephdpy) {
        ephdpy = XOpenDisplay(":134");
        if (!ephdpy)
            usleep(10000);
    }
    ASSERT_EQ(xephyr.GetState(), xorg::testing::Process::RUNNING);
    ASSERT_TRUE(ephdpy);

    xephyr.Terminate(1000);
}

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


<commit_before>#include "stdafx.h"
#include "frame.h"
#include "dimensions.h"

static vk::CommandBuffer create_command_buffer(vk::Device device, vk::CommandPool command_pool, const std::vector<vk::DescriptorSet>& descriptor_sets, vk::RenderPass render_pass, pipeline pipeline, vk::Framebuffer framebuffer, buffer buf)
{
    auto command_buffer = device.allocateCommandBuffers(
        vk::CommandBufferAllocateInfo()
        .setCommandPool(command_pool)
        .setLevel(vk::CommandBufferLevel::ePrimary)
        .setCommandBufferCount(1)
    )[0];

    command_buffer.begin(vk::CommandBufferBeginInfo()
        .setFlags(vk::CommandBufferUsageFlagBits::eSimultaneousUse));

    auto clear_value = vk::ClearValue()
        .setColor(vk::ClearColorValue().setFloat32({0.f, 1.f, 1.f, 1.f}));

    vk::Rect2D render_area;
    render_area.extent.width = WIDTH;
    render_area.extent.height = HEIGHT;

    command_buffer.beginRenderPass(
        vk::RenderPassBeginInfo()
        .setRenderPass(render_pass)
        .setClearValueCount(1)
        .setPClearValues(&clear_value)
        .setRenderArea(render_area)
        .setFramebuffer(framebuffer),
        vk::SubpassContents::eInline
    );

    command_buffer.bindPipeline(vk::PipelineBindPoint::eGraphics, pipeline.pl);

    command_buffer.bindDescriptorSets(vk::PipelineBindPoint::eGraphics, pipeline.layout, 0, descriptor_sets, {});

    command_buffer.bindVertexBuffers(0, {buf.buf}, {0});

    command_buffer.draw(6, 1, 0, 0);

    command_buffer.endRenderPass();

    command_buffer.end();

    return command_buffer;
}

frame::frame(
    vk::PhysicalDevice physical_device,
    vk::Device device,
    vk::CommandPool command_pool,
    vk::DescriptorPool descriptor_pool,
    vk::Image image,
    vk::RenderPass render_pass,
    pipeline pipeline,
    buffer vertex_buffer)
    : uniform_buffer(physical_device, device, vk::BufferUsageFlagBits::eUniformBuffer, sizeof(uniform_data))
{
    this->image = image;

    image_view = device.createImageView(
        vk::ImageViewCreateInfo()
        .setFormat(vk::Format::eB8G8R8A8Unorm)
        .setViewType(vk::ImageViewType::e2D)
        .setImage(image)
        .setSubresourceRange(
            vk::ImageSubresourceRange()
            .setAspectMask(vk::ImageAspectFlagBits::eColor)
            .setLevelCount(VK_REMAINING_MIP_LEVELS)
            .setLayerCount(1)
        )
    );

    framebuffer = device.createFramebuffer(
        vk::FramebufferCreateInfo()
        .setRenderPass(render_pass)
        .setAttachmentCount(1)
        .setPAttachments(&image_view)
        .setWidth(WIDTH)
        .setHeight(HEIGHT)
        .setLayers(1)
    );

    rendered_fence = device.createFence(vk::FenceCreateInfo(vk::FenceCreateFlagBits::eSignaled));

    auto descriptor_sets = device.allocateDescriptorSets(
        vk::DescriptorSetAllocateInfo()
        .setDescriptorPool(descriptor_pool)
        .setDescriptorSetCount(1)
        .setPSetLayouts(&pipeline.set_layout)
    );

    auto buffer_info = vk::DescriptorBufferInfo()
        .setBuffer(uniform_buffer.buf)
        .setRange(uniform_buffer.allocation_size);

    auto write_descriptor_set = vk::WriteDescriptorSet()
        .setDescriptorType(vk::DescriptorType::eUniformBuffer)
        .setDescriptorCount(1)
        .setDstSet(descriptor_sets[0])
        .setPBufferInfo(&buffer_info);

    device.updateDescriptorSets({write_descriptor_set}, {});

    command_buffer = create_command_buffer(device, command_pool, descriptor_sets, render_pass, pipeline, framebuffer, vertex_buffer);
}

void frame::destroy(vk::Device device) const
{
    uniform_buffer.destroy(device);
    device.destroyFramebuffer(framebuffer);
    device.destroyImageView(image_view);
    device.destroyImage(image);
    device.destroyFence(rendered_fence);
}
<commit_msg>Don't destroy swapchain images (we are not allowed to)<commit_after>#include "stdafx.h"
#include "frame.h"
#include "dimensions.h"

static vk::CommandBuffer create_command_buffer(vk::Device device, vk::CommandPool command_pool, const std::vector<vk::DescriptorSet>& descriptor_sets, vk::RenderPass render_pass, pipeline pipeline, vk::Framebuffer framebuffer, buffer buf)
{
    auto command_buffer = device.allocateCommandBuffers(
        vk::CommandBufferAllocateInfo()
        .setCommandPool(command_pool)
        .setLevel(vk::CommandBufferLevel::ePrimary)
        .setCommandBufferCount(1)
    )[0];

    command_buffer.begin(vk::CommandBufferBeginInfo()
        .setFlags(vk::CommandBufferUsageFlagBits::eSimultaneousUse));

    auto clear_value = vk::ClearValue()
        .setColor(vk::ClearColorValue().setFloat32({0.f, 1.f, 1.f, 1.f}));

    vk::Rect2D render_area;
    render_area.extent.width = WIDTH;
    render_area.extent.height = HEIGHT;

    command_buffer.beginRenderPass(
        vk::RenderPassBeginInfo()
        .setRenderPass(render_pass)
        .setClearValueCount(1)
        .setPClearValues(&clear_value)
        .setRenderArea(render_area)
        .setFramebuffer(framebuffer),
        vk::SubpassContents::eInline
    );

    command_buffer.bindPipeline(vk::PipelineBindPoint::eGraphics, pipeline.pl);

    command_buffer.bindDescriptorSets(vk::PipelineBindPoint::eGraphics, pipeline.layout, 0, descriptor_sets, {});

    command_buffer.bindVertexBuffers(0, {buf.buf}, {0});

    command_buffer.draw(6, 1, 0, 0);

    command_buffer.endRenderPass();

    command_buffer.end();

    return command_buffer;
}

frame::frame(
    vk::PhysicalDevice physical_device,
    vk::Device device,
    vk::CommandPool command_pool,
    vk::DescriptorPool descriptor_pool,
    vk::Image image,
    vk::RenderPass render_pass,
    pipeline pipeline,
    buffer vertex_buffer)
    : uniform_buffer(physical_device, device, vk::BufferUsageFlagBits::eUniformBuffer, sizeof(uniform_data))
{
    this->image = image;

    image_view = device.createImageView(
        vk::ImageViewCreateInfo()
        .setFormat(vk::Format::eB8G8R8A8Unorm)
        .setViewType(vk::ImageViewType::e2D)
        .setImage(image)
        .setSubresourceRange(
            vk::ImageSubresourceRange()
            .setAspectMask(vk::ImageAspectFlagBits::eColor)
            .setLevelCount(VK_REMAINING_MIP_LEVELS)
            .setLayerCount(1)
        )
    );

    framebuffer = device.createFramebuffer(
        vk::FramebufferCreateInfo()
        .setRenderPass(render_pass)
        .setAttachmentCount(1)
        .setPAttachments(&image_view)
        .setWidth(WIDTH)
        .setHeight(HEIGHT)
        .setLayers(1)
    );

    rendered_fence = device.createFence(vk::FenceCreateInfo(vk::FenceCreateFlagBits::eSignaled));

    auto descriptor_sets = device.allocateDescriptorSets(
        vk::DescriptorSetAllocateInfo()
        .setDescriptorPool(descriptor_pool)
        .setDescriptorSetCount(1)
        .setPSetLayouts(&pipeline.set_layout)
    );

    auto buffer_info = vk::DescriptorBufferInfo()
        .setBuffer(uniform_buffer.buf)
        .setRange(uniform_buffer.allocation_size);

    auto write_descriptor_set = vk::WriteDescriptorSet()
        .setDescriptorType(vk::DescriptorType::eUniformBuffer)
        .setDescriptorCount(1)
        .setDstSet(descriptor_sets[0])
        .setPBufferInfo(&buffer_info);

    device.updateDescriptorSets({write_descriptor_set}, {});

    command_buffer = create_command_buffer(device, command_pool, descriptor_sets, render_pass, pipeline, framebuffer, vertex_buffer);
}

void frame::destroy(vk::Device device) const
{
    uniform_buffer.destroy(device);
    device.destroyFramebuffer(framebuffer);
    device.destroyImageView(image_view);
    device.destroyFence(rendered_fence);
}
<|endoftext|>


<commit_before>#include <iostream>
#include "stack thread safe.hpp"

constexpr int NUM_WORKERS = 4;

void consume(std::threadsafe::stack<int> &stack){
	for (int i = 0;i < 3;i++){
		int n;
		stack.wait_pop(n);
		stack.push(n*2);
	}
}

int main(){
	std::threadsafe::stack<int> stack;
	stack.push(1);

	std::thread threads[NUM_WORKERS];

	for (int i = 0;i < NUM_WORKERS;i++){
		threads[i] = std::thread(consume,std::ref(stack));
	}

	for (int i = 0;i < NUM_WORKERS;i++){
		threads[i].join();
	}

	int n;
	stack.wait_pop(n);
	std::cout << n << std::endl;
}
<commit_msg>A bit of makeup to stack.scpp<commit_after>#include <iostream>
#include "stack thread safe.hpp"

constexpr int NUM_WORKERS = 4;

void consume(std::threadsafe::stack<int> &stack){
	for (int i = 0;i < 3;i++){
		int n;
		stack.wait_pop(n);
		stack.push(n*2);
	}
}

int main(){
	std::threadsafe::stack<int> stack;
	stack.push(1);

	std::thread threads[NUM_WORKERS];

	for (int i = 0;i < NUM_WORKERS;i++)
		threads[i] = std::thread(consume,std::ref(stack));

	for (int i = 0;i < NUM_WORKERS;i++)
		threads[i].join();

	int n;
	stack.wait_pop(n);
	std::cout << n << std::endl;
}
<|endoftext|>


<commit_before>

#include <tclap/CmdLine.h>
#include <iostream>
#include <string>

using namespace TCLAP;
using namespace std;

bool _boolTestB;
bool _boolTestA;
string _stringTest;

void parseOptions(int argc, char** argv);

int main(int argc, char** argv)
{

	parseOptions(argc,argv);

	cout << "for string we got : " << _stringTest<< endl
		 << "for bool B we got : " << _boolTestB << endl
		 << "for bool A we got : " << _boolTestA << endl;

}

void parseOptions(int argc, char** argv)
{
	try {

	CmdLine cmd("this is a message", ' ', "0.99" );

	//
	// Define arguments
	//

	SwitchArg btest("B","sB", "exist Test B", false);
	SwitchArg atest("A","sA", "exist Test A", false);

	ValueArg<string> stest("s", "Bs", "string test", true, "homer",
					       "string");
	cmd.add( stest );
	cmd.add( btest );
	cmd.add( atest );

	//
	// Parse the command line.
	//
	cmd.parse(argc,argv);

	//
	// Set variables
	//
	_stringTest = stest.getValue();
	_boolTestB = btest.getValue();
	_boolTestA = atest.getValue();

	} catch ( ArgException e )
	{ cout << "ERROR: " << e.error() << " " << e.argId() << endl; }
}

<commit_msg>shows how to alter output<commit_after>

#include <tclap/CmdLine.h>
#include <iostream>
#include <string>

using namespace TCLAP;
using namespace std;

// This exemplifies how the CmdLine class can be overridden to provide
// user defined output.
class MyCmdLine : public CmdLine
{
	public:

        MyCmdLine(const std::string& name,
                const std::string& message,
                const std::string& version = "none" )
		: CmdLine(name,message,version) { }

		MyCmdLine(const std::string& message,
	            const char delimiter = ' ',
	             const std::string& version = "none" )
		: CmdLine(message,delimiter,version) { }

		virtual void failure(const ArgException& e)
		{
			cerr << "My special failure message for: " << endl
			     << e.what() << endl;
			exit(1);
		}
};

bool _boolTestB;
bool _boolTestA;
string _stringTest;

void parseOptions(int argc, char** argv);

int main(int argc, char** argv)
{

	parseOptions(argc,argv);

	cout << "for string we got : " << _stringTest<< endl
		 << "for bool B we got : " << _boolTestB << endl
		 << "for bool A we got : " << _boolTestA << endl;

}

void parseOptions(int argc, char** argv)
{
	try {

	MyCmdLine cmd("this is a message", ' ', "0.99" );

	//
	// Define arguments
	//

	SwitchArg btest("B","sB", "exist Test B", false);
	SwitchArg atest("A","sA", "exist Test A", false);

	ValueArg<string> stest("s", "Bs", "string test", true, "homer",
					       "string");
	cmd.add( stest );
	cmd.add( btest );
	cmd.add( atest );

	//
	// Parse the command line.
	//
	cmd.parse(argc,argv);

	//
	// Set variables
	//
	_stringTest = stest.getValue();
	_boolTestB = btest.getValue();
	_boolTestA = atest.getValue();

	} catch ( ArgException e )
	{ cout << "ERROR: " << e.error() << " " << e.argId() << endl; }
}

<|endoftext|>


<commit_before>/* +------------------------------------------------------------------------+
   |                     Mobile Robot Programming Toolkit (MRPT)            |
   |                          http://www.mrpt.org/                          |
   |                                                                        |
   | Copyright (c) 2005-2018, Individual contributors, see AUTHORS file     |
   | See: http://www.mrpt.org/Authors - All rights reserved.                |
   | Released under BSD License. See details in http://www.mrpt.org/License |
   +------------------------------------------------------------------------+ */

#include <mrpt/comms/nodelets.h>
#include <mrpt/poses/CPose3D.h>
#include <cstdio>  // printf()
#include <thread>
#include <chrono>
#include <iostream>

bool nodelets_test_passed_ok = false;

// Test payload:
const mrpt::poses::CPose3D p_tx(1.0, 2.0, 3.0, 0.2, 0.4, 0.6);

auto dir = mrpt::comms::TopicDirectory::create();

void thread_publisher()
{
	using namespace mrpt::comms;
	using namespace std;

	try
	{
#ifdef NODELETS_TEST_VERBOSE
		printf("[publisher] Started\n");
#endif

		for (int i = 0; i < 5; i++)
		{
			std::this_thread::sleep_for(100ms);
			dir->getTopic("/foo/bar")->publish(p_tx);
		}

#ifdef NODELETS_TEST_VERBOSE
		printf("[publisher] Finish\n");
#endif
	}
	catch (std::exception& e)
	{
		cerr << e.what() << endl;
	}
	catch (...)
	{
		printf("[thread_publisher] Runtime error!\n");
	}
}

void thread_subscriber()
{
	using namespace mrpt::comms;
	using namespace std;

	try
	{
#ifdef NODELETS_TEST_VERBOSE
		printf("[subscriber] Connecting\n");
#endif

#ifdef NODELETS_TEST_VERBOSE
		printf("[subscriber] Connected. Waiting for a message...\n");
#endif

		auto sub = dir->getTopic("/foo/bar")
					   ->createSubscriber(
						   std::function<void(const mrpt::poses::CPose3D&)>(
							   [](const mrpt::poses::CPose3D& p_rx) -> void {
#ifdef NODELETS_TEST_VERBOSE
								   std::cout << "rx CPose3D" << p_rx.asString()
											 << std::endl;
#endif
								   nodelets_test_passed_ok = (p_rx == p_tx);
							   }));

#ifdef NODELETS_TEST_VERBOSE
		printf("[subscriber] Finish\n");
#endif
	}
	catch (std::exception& e)
	{
		cerr << e.what() << endl;
	}
	catch (...)
	{
		cerr << "[thread_subscriber] Runtime error!" << endl;
		;
	}
}

void NodeletsTest()
{
	using namespace std::chrono_literals;

	std::thread(thread_publisher).detach();
	std::thread(thread_subscriber).detach();
	std::this_thread::sleep_for(1000ms);
}
<commit_msg>fix and extend example<commit_after>/* +------------------------------------------------------------------------+
   |                     Mobile Robot Programming Toolkit (MRPT)            |
   |                          http://www.mrpt.org/                          |
   |                                                                        |
   | Copyright (c) 2005-2018, Individual contributors, see AUTHORS file     |
   | See: http://www.mrpt.org/Authors - All rights reserved.                |
   | Released under BSD License. See details in http://www.mrpt.org/License |
   +------------------------------------------------------------------------+ */

#include <mrpt/comms/nodelets.h>
#include <mrpt/poses/CPose3D.h>
#include <cstdio>  // printf()
#include <thread>
#include <chrono>
#include <iostream>

bool nodelets_test_passed_ok = false;

// Test payload:
const mrpt::poses::CPose3D p_tx(1.0, 2.0, 3.0, 0.2, 0.4, 0.6);

auto dir = mrpt::comms::TopicDirectory::create();

void thread_publisher()
{
	using namespace mrpt::comms;
	using namespace std;

	try
	{
#ifdef NODELETS_TEST_VERBOSE
		printf("[publisher] Started\n");
#endif

		for (int i = 0; i < 5; i++)
		{
			std::this_thread::sleep_for(100ms);
			dir->getTopic("/robot/odom")->publish(p_tx);
		}

#ifdef NODELETS_TEST_VERBOSE
		printf("[publisher] Finish\n");
#endif
	}
	catch (std::exception& e)
	{
		cerr << e.what() << endl;
	}
	catch (...)
	{
		printf("[thread_publisher] Runtime error!\n");
	}
}

void onNewMsg(const mrpt::poses::CPose3D& p)
{
#ifdef NODELETS_TEST_VERBOSE
	std::cout << "sub2: rx CPose3D" << p.asString() << std::endl;
#endif
}

void thread_subscriber()
{
	using namespace mrpt::comms;
	using namespace std;

	try
	{
#ifdef NODELETS_TEST_VERBOSE
		printf("[subscriber] Connecting\n");
#endif

#ifdef NODELETS_TEST_VERBOSE
		printf("[subscriber] Connected. Waiting for a message...\n");
#endif

		// Create a subscriber with a lambda:
		auto sub1 = dir->getTopic("/robot/odom")
					   ->createSubscriber(
						   std::function<void(const mrpt::poses::CPose3D&)>(
							   [](const mrpt::poses::CPose3D& p_rx) -> void {
#ifdef NODELETS_TEST_VERBOSE
								   std::cout << "sub1: rx CPose3D"
											 << p_rx.asString() << std::endl;
#endif
								   nodelets_test_passed_ok = (p_rx == p_tx);
							   }));

		// Create a subscriber with a regular function:
		auto sub2 = dir->getTopic("/robot/odom")
					   ->createSubscriber(
						   std::function<void(const mrpt::poses::CPose3D&)>(
							   &onNewMsg));

		// wait for messages to arrive.
		// The nodelet is up and live until "sub" gets out of scope.
		std::this_thread::sleep_for(1000ms);

#ifdef NODELETS_TEST_VERBOSE
		printf("[subscriber] Finish\n");
#endif
	}
	catch (std::exception& e)
	{
		cerr << e.what() << endl;
	}
	catch (...)
	{
		cerr << "[thread_subscriber] Runtime error!" << endl;
		;
	}
}

void NodeletsTest()
{
	using namespace std::chrono_literals;

	std::thread(thread_publisher).detach();
	std::thread(thread_subscriber).detach();
	std::this_thread::sleep_for(1000ms);
}
<|endoftext|>


<commit_before>/*****************************************************************************
*   Number Plate Recognition using SVM and Neural Networks
******************************************************************************
*/

// Main entry code OpenCV

#include <cv.h>
#include <highgui.h>
#include <cvaux.h>
#include <ml.h>

#include <iostream>
#include <vector>

#include "DetectRegions.h"
#include "OCR.h"

using namespace std;
using namespace cv;

string getFilename(string s) {

    char sep = '/';
    char sepExt='.';

    #ifdef _WIN32
        sep = '\\';
    #endif

    size_t i = s.rfind(sep, s.length( ));
    if (i != string::npos) {
        string fn= (s.substr(i+1, s.length( ) - i));
        size_t j = fn.rfind(sepExt, fn.length( ));
        if (i != string::npos) {
            return fn.substr(0,j);
        }else{
            return fn;
        }
    }else{
        return "";
    }
}

int main ( int argc, char** argv )
{
    cout << "OpenCV Automatic Number Plate Recognition\n";
    char* filename;
    Mat input_image;

    //Check if user specify image to process
    if(argc >= 2 )
    {
        filename= argv[1];
        //load image  in gray level
        input_image=imread(filename,1);
    }else{
        printf("Use:\n\t%s image\n",argv[0]);
        return 0;
    }

    string filename_whithoutExt=getFilename(filename);
    cout << "working with file: "<< filename_whithoutExt << "\n";
    //Detect posibles plate regions
    DetectRegions detectRegions;
    detectRegions.setFilename(filename_whithoutExt);
    detectRegions.saveRegions=false;
    detectRegions.showSteps=false;
    vector<Plate> posible_regions= detectRegions.run( input_image );

    //SVM for each plate region to get valid car plates
    //Read file storage.
    FileStorage fs;
    fs.open("SVM.xml", FileStorage::READ);
    Mat SVM_TrainingData;
    Mat SVM_Classes;
    fs["TrainingData"] >> SVM_TrainingData;
    fs["classes"] >> SVM_Classes;
    //Set SVM params
    CvSVMParams SVM_params;
    SVM_params.svm_type = CvSVM::C_SVC;
    SVM_params.kernel_type = CvSVM::LINEAR; //CvSVM::LINEAR;
    SVM_params.degree = 0;
    SVM_params.gamma = 1;
    SVM_params.coef0 = 0;
    SVM_params.C = 1;
    SVM_params.nu = 0;
    SVM_params.p = 0;
    SVM_params.term_crit = cvTermCriteria(CV_TERMCRIT_ITER, 1000, 0.01);
    //Train SVM
    CvSVM svmClassifier(SVM_TrainingData, SVM_Classes, Mat(), Mat(), SVM_params);

    //For each possible plate, classify with svm if it's a plate or no
    vector<Plate> plates;
    for(int i=0; i< posible_regions.size(); i++)
    {
        Mat img=posible_regions[i].plateImg;
        Mat p= img.reshape(1, 1);
        p.convertTo(p, CV_32FC1);

        int response = (int)svmClassifier.predict( p );
        if(response==1)
            plates.push_back(posible_regions[i]);
    }

    cout << "Num plates detected: " << plates.size() << "\n";
    //For each plate detected, recognize it with OCR
    OCR ocr("OCR.xml");
    ocr.saveSegments=true;
    ocr.DEBUG=false;
    ocr.filename=filename_whithoutExt;
    for(int i=0; i< plates.size(); i++){
        Plate plate=plates[i];

        string plateNumber=ocr.run(&plate);
        string licensePlate=plate.str();
        cout << "================================================\n";
        cout << "License plate number: "<< licensePlate << "\n";
        cout << "================================================\n";
        rectangle(input_image, plate.position, Scalar(0,0,200));
        putText(input_image, licensePlate, Point(plate.position.x, plate.position.y), CV_FONT_HERSHEY_SIMPLEX, 1, Scalar(0,0,200),2);
        if(false){
            imshow("Plate Detected seg", plate.plateImg);
            cvWaitKey(0);
        }

    }
        imshow("Plate Detected", input_image);
       for(;;)
       {
       int c;
       c = cvWaitKey(10);
       if( (char) c == 27)
       break;
       }
    return 0;
}
<commit_msg>main plate recorder<commit_after>/*****************************************************************************
*   Number Plate Recognition using SVM and Neural Networks
******************************************************************************
*/

// Main entry code OpenCV

#include <cv.h>
#include <highgui.h>
#include <cvaux.h>
#include <ml.h>

#include <iostream>
#include <vector>

#include "DetectRegions.h"
#include "OCR.h"

using namespace std;
using namespace cv;

string getFilename(string s) {

    char sep = '/';
    char sepExt='.';

    #ifdef _WIN32
        sep = '\\';
    #endif

    size_t i = s.rfind(sep, s.length( ));
    if (i != string::npos) {
        string fn= (s.substr(i+1, s.length( ) - i));
        size_t j = fn.rfind(sepExt, fn.length( ));
        if (i != string::npos) {
            return fn.substr(0,j);
        }else{
            return fn;
        }
    }else{
        return "";
    }
}

int main ( int argc, char** argv )
{
    cout << "OpenCV Automatic Number Plate Recognition\n";
    char* filename;
    Mat input_image;

    //Check if user specify image to process
    if(argc >= 2 )
    {
        filename= argv[1];
        //load image  in gray level
        input_image=imread(filename,1);
    }else{
        printf("Use:\n\t%s image\n",argv[0]);
        return 0;
    }

    string filename_whithoutExt=getFilename(filename);
    cout << "working with file: "<< filename_whithoutExt << "\n";
    //Detect posibles plate regions
    DetectRegions detectRegions;
    detectRegions.setFilename(filename_whithoutExt);
    detectRegions.saveRegions=false;
    detectRegions.showSteps=false;
    vector<Plate> posible_regions= detectRegions.run( input_image );

    //SVM for each plate region to get valid car plates
    //Read file storage.
    FileStorage fs;
    fs.open("SVM.xml", FileStorage::READ);
    Mat SVM_TrainingData;
    Mat SVM_Classes;
    fs["TrainingData"] >> SVM_TrainingData;
    fs["classes"] >> SVM_Classes;
    //Set SVM params
    CvSVMParams SVM_params;
    SVM_params.svm_type = CvSVM::C_SVC;
    SVM_params.kernel_type = CvSVM::LINEAR; //CvSVM::LINEAR;
    SVM_params.degree = 0;
    SVM_params.gamma = 1;
    SVM_params.coef0 = 0;
    SVM_params.C = 1;
    SVM_params.nu = 0;
    SVM_params.p = 0;
    SVM_params.term_crit = cvTermCriteria(CV_TERMCRIT_ITER, 1000, 0.01);
    //Train SVM
    CvSVM svmClassifier(SVM_TrainingData, SVM_Classes, Mat(), Mat(), SVM_params);

    //For each possible plate, classify with svm if it's a plate or no
    vector<Plate> plates;
    for(int i=0; i< posible_regions.size(); i++) {
        Mat img=posible_regions[i].plateImg;
        Mat p= img.reshape(1, 1);
        p.convertTo(p, CV_32FC1);

        int response = (int)svmClassifier.predict( p );
        if(response==1)
            plates.push_back(posible_regions[i]);
    }

    cout << "Num plates detected: " << plates.size() << "\n";
    //For each plate detected, recognize it with OCR
    OCR ocr("OCR.xml");
    ocr.saveSegments=true;
    ocr.DEBUG=false;
    ocr.filename=filename_whithoutExt;
    for(int i=0; i< plates.size(); i++) {
        Plate plate=plates[i];

        string plateNumber=ocr.run(&plate);
        string licensePlate=plate.str();
        cout << "================================================\n";
        cout << "License plate number: "<< licensePlate << "\n";
        cout << "================================================\n";
        rectangle(input_image, plate.position, Scalar(0,0,200));
        putText(input_image, licensePlate, Point(plate.position.x, plate.position.y), CV_FONT_HERSHEY_SIMPLEX, 1, Scalar(0,0,200),2);
        if(false){
            imshow("Plate Detected seg", plate.plateImg);
            cvWaitKey(0);
        }

    }
        imshow("Plate Detected", input_image);
       for(;;)
       {
       int c;
       c = cvWaitKey(10);
       if( (char) c == 27)
       break;
       }
    return 0;
}
<|endoftext|>


<commit_before>/*=========================================================================

  Program:   Visualization Toolkit
  Module:    vtkBooleanStructuredPoints.cc
  Language:  C++
  Date:      $Date$
  Version:   $Revision$

Copyright (c) 1993-1995 Ken Martin, Will Schroeder, Bill Lorensen.

This software is copyrighted by Ken Martin, Will Schroeder and Bill Lorensen.
The following terms apply to all files associated with the software unless
explicitly disclaimed in individual files. This copyright specifically does
not apply to the related textbook "The Visualization Toolkit" ISBN
013199837-4 published by Prentice Hall which is covered by its own copyright.

The authors hereby grant permission to use, copy, and distribute this
software and its documentation for any purpose, provided that existing
copyright notices are retained in all copies and that this notice is included
verbatim in any distributions. Additionally, the authors grant permission to
modify this software and its documentation for any purpose, provided that
such modifications are not distributed without the explicit consent of the
authors and that existing copyright notices are retained in all copies. Some
of the algorithms implemented by this software are patented, observe all
applicable patent law.

IN NO EVENT SHALL THE AUTHORS OR DISTRIBUTORS BE LIABLE TO ANY PARTY FOR
DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
OF THE USE OF THIS SOFTWARE, ITS DOCUMENTATION, OR ANY DERIVATIVES THEREOF,
EVEN IF THE AUTHORS HAVE BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

THE AUTHORS AND DISTRIBUTORS SPECIFICALLY DISCLAIM ANY WARRANTIES, INCLUDING,
BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
PARTICULAR PURPOSE, AND NON-INFRINGEMENT.  THIS SOFTWARE IS PROVIDED ON AN
"AS IS" BASIS, AND THE AUTHORS AND DISTRIBUTORS HAVE NO OBLIGATION TO PROVIDE
MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.

=========================================================================*/
#include "vtkBooleanStructuredPoints.hh"

// Description:
// Construct with sample resolution of (50,50,50) and automatic
// computation of sample bounds. Initial boolean operation is union.
vtkBooleanStructuredPoints::vtkBooleanStructuredPoints()
{
  this->SampleDimensions[0] = 50;
  this->SampleDimensions[1] = 50;
  this->SampleDimensions[2] = 50;

  this->ModelBounds[0] = 0.0;
  this->ModelBounds[1] = 0.0;
  this->ModelBounds[2] = 0.0;
  this->ModelBounds[3] = 0.0;
  this->ModelBounds[4] = 0.0;
  this->ModelBounds[5] = 0.0;

  this->OperationType = VTK_UNION_OPERATOR;
  // this->Operator = this->Union;
  this->Output = new vtkStructuredPoints;
  this->Output->SetSource(this);
}

// Description:
// Add another structured point set to the list of objects to boolean.
void vtkBooleanStructuredPoints::AddInput(vtkStructuredPoints *sp)
{
  if ( ! this->InputList.IsItemPresent(sp) )
    {
    this->Modified();
    this->InputList.AddItem(sp);
    }
}

// Description:
// Remove an object from the list of objects to boolean.
void vtkBooleanStructuredPoints::RemoveInput(vtkStructuredPoints *sp)
{
  if ( this->InputList.IsItemPresent(sp) )
    {
    this->Modified();
    this->InputList.RemoveItem(sp);
    }
}

void vtkBooleanStructuredPoints::Update()
{
  unsigned long int mtime, dsMtime;
  vtkDataSet *ds;

  // make sure input is available
  if ( this->InputList.GetNumberOfItems() < 1 )
    {
    vtkErrorMacro(<< "No input...can't execute!");
    return;
    }

  // prevent chasing our tail
  if (this->Updating) return;

  this->Updating = 1;
  for (mtime=0, this->InputList.InitTraversal(); ds = this->InputList.GetNextItem(); )
    {
    ds->Update();
    dsMtime = ds->GetMTime();
    if ( dsMtime > mtime ) mtime = dsMtime;
    }
  this->Updating = 0;

  if (mtime > this->ExecuteTime || this->GetMTime() > this->ExecuteTime ||
  this->GetDataReleased() )
    {
    if ( this->StartMethod ) (*this->StartMethod)(this->StartMethodArg);
    this->Output->Initialize(); //clear output
    this->Execute();
    this->ExecuteTime.Modified();
    this->SetDataReleased(0);
    if ( this->EndMethod ) (*this->EndMethod)(this->EndMethodArg);
    }

  for (this->InputList.InitTraversal(); ds = this->InputList.GetNextItem(); )
    if ( ds->ShouldIReleaseData() ) ds->ReleaseData();
}

// Initialize object prior to performing Boolean operations
void vtkBooleanStructuredPoints::InitializeBoolean()
{
  vtkScalars *inScalars=NULL;
  vtkScalars *newScalars;
  vtkStructuredPoints *sp;
  float *bounds;
  int numPts;
  int i, j;
  vtkStructuredPoints *output = this->GetOutput();
  float tempf[3];

  output->SetDimensions(this->SampleDimensions);
  numPts = output->GetNumberOfPoints();

  // If ModelBounds unset, use input, else punt
  if ( this->ModelBounds[0] >= this->ModelBounds[1] ||
  this->ModelBounds[2] >= this->ModelBounds[3] ||
  this->ModelBounds[4] >= this->ModelBounds[5] )
    {
    if ( this->InputList.GetNumberOfItems() > 0 )
      {
       this->ModelBounds[0] = this->ModelBounds[2] = this->ModelBounds[4] = VTK_LARGE_FLOAT;
       this->ModelBounds[1] = this->ModelBounds[3] = this->ModelBounds[5] = -VTK_LARGE_FLOAT;
      for ( this->InputList.InitTraversal(); sp = this->InputList.GetNextItem(); )
        {
        bounds = sp->GetBounds();
        for (j=0; j < 3; j++)
          {
          if ( bounds[2*j] < this->ModelBounds[2*j] )
            this->ModelBounds[2*j] = bounds[2*j];

          if ( bounds[2*j+1] > this->ModelBounds[2*j+1] )
            this->ModelBounds[2*j+1] = bounds[2*j+1];
          }
        }
      }
    else
      {
      this->ModelBounds[0] = this->ModelBounds[2] = this->ModelBounds[4] = 0.0;
      this->ModelBounds[1] = this->ModelBounds[3] = this->ModelBounds[5] = 1000.0;
      }
    }

  // Update origin and aspect ratio
  for (i=0; i<3; i++)
    {
    tempf[i] = this->ModelBounds[2*i];
    }
  output->SetOrigin(tempf);
  for (i=0; i<3; i++)
    {
    tempf[i] = (this->ModelBounds[2*i+1] - this->ModelBounds[2*i])
      / (this->SampleDimensions[i] - 1);
    }
  output->SetAspectRatio(tempf);

  // Create output scalar (same type as input)
  if ( this->InputList.GetNumberOfItems() > 0 )
    {
    this->InputList.InitTraversal(); sp = this->InputList.GetNextItem();
    inScalars = sp->GetPointData()->GetScalars();
    }

  if ( inScalars != NULL )
    {
    newScalars = inScalars->MakeObject(numPts); //copy
    }
  else
    {
    newScalars = new vtkFloatScalars(numPts);
    }
  output->GetPointData()->SetScalars(newScalars);
  newScalars->Delete();
}

// Perform Boolean operations on input volumes
void vtkBooleanStructuredPoints::Execute()
{
  vtkStructuredPoints *sp;

  this->InitializeBoolean();

  for ( this->InputList.InitTraversal(); sp = this->InputList.GetNextItem(); )
    {
    this->Append(sp);
    }
}

// Description:
// Perform Boolean operations by appending to current output data.
void vtkBooleanStructuredPoints::Append(vtkStructuredPoints *sp)
{
  vtkScalars *currentScalars, *inScalars;
  float *inBounds;
  float *destBounds;
  int i,j,k;
  float *in_aspect;
  float inX,inY,inZ;
  int inI,inJ,inK;
  int inKval,inJval;
  int destKval,destJval;
  int *inDimensions;
  vtkStructuredPoints *output = (vtkStructuredPoints *)this->Output;
  float *aspectRatio = output->GetAspectRatio();

  if ((currentScalars = this->Output->GetPointData()->GetScalars()) == NULL )
    {
    this->InitializeBoolean();
    currentScalars = this->Output->GetPointData()->GetScalars();
    }

  inScalars = sp->GetPointData()->GetScalars();

  inBounds = sp->GetBounds();
  destBounds = this->GetModelBounds();
  in_aspect = sp->GetAspectRatio();
  inDimensions = sp->GetDimensions();

  // now perform operation on data
  switch (this->OperationType)
    {
    case VTK_UNION_OPERATOR :
      {
      // for each cell
      for (k = 0; k < this->SampleDimensions[2]; k++)
	{
	inZ = destBounds[4] + k*aspectRatio[2];
	inK = int ((float)(inZ - inBounds[4])/in_aspect[2]);
	if ((inK >= 0)&&(inK < inDimensions[2]))
	  {
	  inKval = inK*inDimensions[0]*inDimensions[1];
	  destKval = k*this->SampleDimensions[0]*this->SampleDimensions[1];
	  for (j = 0; j < this->SampleDimensions[1]; j++)
	    {
	    inY = destBounds[2] + j*aspectRatio[1];
	    inJ = (int) ((float)(inY - inBounds[2])/in_aspect[1]);
	    if ((inJ >= 0)&&(inJ < inDimensions[1]))
	      {
	      inJval = inJ*inDimensions[0];
	      destJval = j*this->SampleDimensions[0];
	      for (i = 0; i < this->SampleDimensions[0]; i++)
		{
		inX = destBounds[0] + i*aspectRatio[0];
		inI = (int) ((float)(inX - inBounds[0])/in_aspect[0]);
		if ((inI >= 0)&&(inI < inDimensions[0]))
		  {
		  if (inScalars->GetScalar(inKval+inJval+inI))
		    {
		    currentScalars->SetScalar(destKval + destJval+i,1);
		    }
		  }
		}
	      }
	    }
	  }
	}
      }
      break;
    }
}

// Description:
// Set the i-j-k dimensions on which to perform boolean operation.
void vtkBooleanStructuredPoints::SetSampleDimensions(int i, int j, int k)
{
  int dim[3];

  dim[0] = i;
  dim[1] = j;
  dim[2] = k;

  this->SetSampleDimensions(dim);
}

void vtkBooleanStructuredPoints::SetSampleDimensions(int dim[3])
{
  int i;

  vtkDebugMacro(<< " setting SampleDimensions to (" << dim[0] << "," << dim[1] << "," << dim[2] << ")");

  if ( dim[0] != this->SampleDimensions[0] || dim[1] != SampleDimensions[1] ||
  dim[2] != SampleDimensions[2] )
    {
    if ( dim[0]<0 || dim[1]<0 || dim[2]<0 )
      {
      vtkErrorMacro (<< "Bad Sample Dimensions, retaining previous values");
      return;
      }

    for ( i=0; i<3; i++) this->SampleDimensions[i] = dim[i];

    this->Modified();
    }
}

// Description:
// Set the size of the volume on which to perform the sampling.
void vtkBooleanStructuredPoints::SetModelBounds(float *bounds)
{
  vtkBooleanStructuredPoints::SetModelBounds(bounds[0], bounds[1], bounds[2], bounds[3], bounds[4], bounds[5]);
}

void vtkBooleanStructuredPoints::SetModelBounds(float xmin, float xmax, float ymin, float ymax, float zmin, float zmax)
{
  vtkStructuredPoints *output = this->GetOutput();

  if (this->ModelBounds[0] != xmin || this->ModelBounds[1] != xmax ||
  this->ModelBounds[2] != ymin || this->ModelBounds[3] != ymax ||
  this->ModelBounds[4] != zmin || this->ModelBounds[5] != zmax )
    {
    float length;

    this->Modified();
    this->ModelBounds[0] = xmin;
    this->ModelBounds[1] = xmax;
    this->ModelBounds[2] = ymin;
    this->ModelBounds[3] = ymax;
    this->ModelBounds[4] = zmin;
    this->ModelBounds[5] = zmax;

    output->SetOrigin(xmin,ymin,zmin);

    if ( (length = xmax - xmin) == 0.0 ) length = 1.0;
    output->SetAspectRatio(1.0,(ymax - ymin) / length,(zmax - zmin) / length);
    }
}

void vtkBooleanStructuredPoints::PrintSelf(ostream& os, vtkIndent indent)
{
  vtkFilter::PrintSelf(os,indent);

  os << indent << "Input DataSets:\n";
  this->InputList.PrintSelf(os,indent.GetNextIndent());
}

<commit_msg>fixed up some warnings<commit_after>/*=========================================================================

  Program:   Visualization Toolkit
  Module:    vtkBooleanStructuredPoints.cc
  Language:  C++
  Date:      $Date$
  Version:   $Revision$

Copyright (c) 1993-1995 Ken Martin, Will Schroeder, Bill Lorensen.

This software is copyrighted by Ken Martin, Will Schroeder and Bill Lorensen.
The following terms apply to all files associated with the software unless
explicitly disclaimed in individual files. This copyright specifically does
not apply to the related textbook "The Visualization Toolkit" ISBN
013199837-4 published by Prentice Hall which is covered by its own copyright.

The authors hereby grant permission to use, copy, and distribute this
software and its documentation for any purpose, provided that existing
copyright notices are retained in all copies and that this notice is included
verbatim in any distributions. Additionally, the authors grant permission to
modify this software and its documentation for any purpose, provided that
such modifications are not distributed without the explicit consent of the
authors and that existing copyright notices are retained in all copies. Some
of the algorithms implemented by this software are patented, observe all
applicable patent law.

IN NO EVENT SHALL THE AUTHORS OR DISTRIBUTORS BE LIABLE TO ANY PARTY FOR
DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
OF THE USE OF THIS SOFTWARE, ITS DOCUMENTATION, OR ANY DERIVATIVES THEREOF,
EVEN IF THE AUTHORS HAVE BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

THE AUTHORS AND DISTRIBUTORS SPECIFICALLY DISCLAIM ANY WARRANTIES, INCLUDING,
BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
PARTICULAR PURPOSE, AND NON-INFRINGEMENT.  THIS SOFTWARE IS PROVIDED ON AN
"AS IS" BASIS, AND THE AUTHORS AND DISTRIBUTORS HAVE NO OBLIGATION TO PROVIDE
MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.

=========================================================================*/
#include "vtkBooleanStructuredPoints.hh"

// Description:
// Construct with sample resolution of (50,50,50) and automatic
// computation of sample bounds. Initial boolean operation is union.
vtkBooleanStructuredPoints::vtkBooleanStructuredPoints()
{
  this->SampleDimensions[0] = 50;
  this->SampleDimensions[1] = 50;
  this->SampleDimensions[2] = 50;

  this->ModelBounds[0] = 0.0;
  this->ModelBounds[1] = 0.0;
  this->ModelBounds[2] = 0.0;
  this->ModelBounds[3] = 0.0;
  this->ModelBounds[4] = 0.0;
  this->ModelBounds[5] = 0.0;

  this->OperationType = VTK_UNION_OPERATOR;
  // this->Operator = this->Union;
  this->Output = new vtkStructuredPoints;
  this->Output->SetSource(this);
}

// Description:
// Add another structured point set to the list of objects to boolean.
void vtkBooleanStructuredPoints::AddInput(vtkStructuredPoints *sp)
{
  if ( ! this->InputList.IsItemPresent(sp) )
    {
    this->Modified();
    this->InputList.AddItem(sp);
    }
}

// Description:
// Remove an object from the list of objects to boolean.
void vtkBooleanStructuredPoints::RemoveInput(vtkStructuredPoints *sp)
{
  if ( this->InputList.IsItemPresent(sp) )
    {
    this->Modified();
    this->InputList.RemoveItem(sp);
    }
}

void vtkBooleanStructuredPoints::Update()
{
  unsigned long int mtime, dsMtime;
  vtkDataSet *ds;

  // make sure input is available
  if ( this->InputList.GetNumberOfItems() < 1 )
    {
    vtkErrorMacro(<< "No input...can't execute!");
    return;
    }

  // prevent chasing our tail
  if (this->Updating) return;

  this->Updating = 1;
  for (mtime=0, this->InputList.InitTraversal();
       (ds = this->InputList.GetNextItem()); )
    {
    ds->Update();
    dsMtime = ds->GetMTime();
    if ( dsMtime > mtime ) mtime = dsMtime;
    }
  this->Updating = 0;

  if (mtime > this->ExecuteTime || this->GetMTime() > this->ExecuteTime ||
  this->GetDataReleased() )
    {
    if ( this->StartMethod ) (*this->StartMethod)(this->StartMethodArg);
    this->Output->Initialize(); //clear output
    this->Execute();
    this->ExecuteTime.Modified();
    this->SetDataReleased(0);
    if ( this->EndMethod ) (*this->EndMethod)(this->EndMethodArg);
    }

  for (this->InputList.InitTraversal(); (ds = this->InputList.GetNextItem()); )
    if ( ds->ShouldIReleaseData() ) ds->ReleaseData();
}

// Initialize object prior to performing Boolean operations
void vtkBooleanStructuredPoints::InitializeBoolean()
{
  vtkScalars *inScalars=NULL;
  vtkScalars *newScalars;
  vtkStructuredPoints *sp;
  float *bounds;
  int numPts;
  int i, j;
  vtkStructuredPoints *output = this->GetOutput();
  float tempf[3];

  output->SetDimensions(this->SampleDimensions);
  numPts = output->GetNumberOfPoints();

  // If ModelBounds unset, use input, else punt
  if ( this->ModelBounds[0] >= this->ModelBounds[1] ||
  this->ModelBounds[2] >= this->ModelBounds[3] ||
  this->ModelBounds[4] >= this->ModelBounds[5] )
    {
    if ( this->InputList.GetNumberOfItems() > 0 )
      {
       this->ModelBounds[0] = this->ModelBounds[2] =
	 this->ModelBounds[4] = VTK_LARGE_FLOAT;
       this->ModelBounds[1] = this->ModelBounds[3] =
	 this->ModelBounds[5] = -VTK_LARGE_FLOAT;
      for (this->InputList.InitTraversal();
	   (sp = this->InputList.GetNextItem()); )
        {
        bounds = sp->GetBounds();
        for (j=0; j < 3; j++)
          {
          if ( bounds[2*j] < this->ModelBounds[2*j] )
            this->ModelBounds[2*j] = bounds[2*j];

          if ( bounds[2*j+1] > this->ModelBounds[2*j+1] )
            this->ModelBounds[2*j+1] = bounds[2*j+1];
          }
        }
      }
    else
      {
      this->ModelBounds[0] = this->ModelBounds[2] = this->ModelBounds[4] = 0.0;
      this->ModelBounds[1] = this->ModelBounds[3] = this->ModelBounds[5] = 1000.0;
      }
    }

  // Update origin and aspect ratio
  for (i=0; i<3; i++)
    {
    tempf[i] = this->ModelBounds[2*i];
    }
  output->SetOrigin(tempf);
  for (i=0; i<3; i++)
    {
    tempf[i] = (this->ModelBounds[2*i+1] - this->ModelBounds[2*i])
      / (this->SampleDimensions[i] - 1);
    }
  output->SetAspectRatio(tempf);

  // Create output scalar (same type as input)
  if ( this->InputList.GetNumberOfItems() > 0 )
    {
    this->InputList.InitTraversal(); sp = this->InputList.GetNextItem();
    inScalars = sp->GetPointData()->GetScalars();
    }

  if ( inScalars != NULL )
    {
    newScalars = inScalars->MakeObject(numPts); //copy
    }
  else
    {
    newScalars = new vtkFloatScalars(numPts);
    }
  output->GetPointData()->SetScalars(newScalars);
  newScalars->Delete();
}

// Perform Boolean operations on input volumes
void vtkBooleanStructuredPoints::Execute()
{
  vtkStructuredPoints *sp;

  this->InitializeBoolean();

  for (this->InputList.InitTraversal(); (sp = this->InputList.GetNextItem()); )
    {
    this->Append(sp);
    }
}

// Description:
// Perform Boolean operations by appending to current output data.
void vtkBooleanStructuredPoints::Append(vtkStructuredPoints *sp)
{
  vtkScalars *currentScalars, *inScalars;
  float *inBounds;
  float *destBounds;
  int i,j,k;
  float *in_aspect;
  float inX,inY,inZ;
  int inI,inJ,inK;
  int inKval,inJval;
  int destKval,destJval;
  int *inDimensions;
  vtkStructuredPoints *output = (vtkStructuredPoints *)this->Output;
  float *aspectRatio = output->GetAspectRatio();

  if ((currentScalars = this->Output->GetPointData()->GetScalars()) == NULL )
    {
    this->InitializeBoolean();
    currentScalars = this->Output->GetPointData()->GetScalars();
    }

  inScalars = sp->GetPointData()->GetScalars();

  inBounds = sp->GetBounds();
  destBounds = this->GetModelBounds();
  in_aspect = sp->GetAspectRatio();
  inDimensions = sp->GetDimensions();

  // now perform operation on data
  switch (this->OperationType)
    {
    case VTK_UNION_OPERATOR :
      {
      // for each cell
      for (k = 0; k < this->SampleDimensions[2]; k++)
	{
	inZ = destBounds[4] + k*aspectRatio[2];
	inK = int ((float)(inZ - inBounds[4])/in_aspect[2]);
	if ((inK >= 0)&&(inK < inDimensions[2]))
	  {
	  inKval = inK*inDimensions[0]*inDimensions[1];
	  destKval = k*this->SampleDimensions[0]*this->SampleDimensions[1];
	  for (j = 0; j < this->SampleDimensions[1]; j++)
	    {
	    inY = destBounds[2] + j*aspectRatio[1];
	    inJ = (int) ((float)(inY - inBounds[2])/in_aspect[1]);
	    if ((inJ >= 0)&&(inJ < inDimensions[1]))
	      {
	      inJval = inJ*inDimensions[0];
	      destJval = j*this->SampleDimensions[0];
	      for (i = 0; i < this->SampleDimensions[0]; i++)
		{
		inX = destBounds[0] + i*aspectRatio[0];
		inI = (int) ((float)(inX - inBounds[0])/in_aspect[0]);
		if ((inI >= 0)&&(inI < inDimensions[0]))
		  {
		  if (inScalars->GetScalar(inKval+inJval+inI))
		    {
		    currentScalars->SetScalar(destKval + destJval+i,1);
		    }
		  }
		}
	      }
	    }
	  }
	}
      }
      break;
    }
}

// Description:
// Set the i-j-k dimensions on which to perform boolean operation.
void vtkBooleanStructuredPoints::SetSampleDimensions(int i, int j, int k)
{
  int dim[3];

  dim[0] = i;
  dim[1] = j;
  dim[2] = k;

  this->SetSampleDimensions(dim);
}

void vtkBooleanStructuredPoints::SetSampleDimensions(int dim[3])
{
  int i;

  vtkDebugMacro(<< " setting SampleDimensions to (" << dim[0] << "," << dim[1] << "," << dim[2] << ")");

  if ( dim[0] != this->SampleDimensions[0] || dim[1] != SampleDimensions[1] ||
  dim[2] != SampleDimensions[2] )
    {
    if ( dim[0]<0 || dim[1]<0 || dim[2]<0 )
      {
      vtkErrorMacro (<< "Bad Sample Dimensions, retaining previous values");
      return;
      }

    for ( i=0; i<3; i++) this->SampleDimensions[i] = dim[i];

    this->Modified();
    }
}

// Description:
// Set the size of the volume on which to perform the sampling.
void vtkBooleanStructuredPoints::SetModelBounds(float *bounds)
{
  vtkBooleanStructuredPoints::SetModelBounds(bounds[0], bounds[1], bounds[2], bounds[3], bounds[4], bounds[5]);
}

void vtkBooleanStructuredPoints::SetModelBounds(float xmin, float xmax, float ymin, float ymax, float zmin, float zmax)
{
  vtkStructuredPoints *output = this->GetOutput();

  if (this->ModelBounds[0] != xmin || this->ModelBounds[1] != xmax ||
  this->ModelBounds[2] != ymin || this->ModelBounds[3] != ymax ||
  this->ModelBounds[4] != zmin || this->ModelBounds[5] != zmax )
    {
    float length;

    this->Modified();
    this->ModelBounds[0] = xmin;
    this->ModelBounds[1] = xmax;
    this->ModelBounds[2] = ymin;
    this->ModelBounds[3] = ymax;
    this->ModelBounds[4] = zmin;
    this->ModelBounds[5] = zmax;

    output->SetOrigin(xmin,ymin,zmin);

    if ( (length = xmax - xmin) == 0.0 ) length = 1.0;
    output->SetAspectRatio(1.0,(ymax - ymin) / length,(zmax - zmin) / length);
    }
}

void vtkBooleanStructuredPoints::PrintSelf(ostream& os, vtkIndent indent)
{
  vtkFilter::PrintSelf(os,indent);

  os << indent << "Input DataSets:\n";
  this->InputList.PrintSelf(os,indent.GetNextIndent());
}

<|endoftext|>