<commit_before>/*

Copyright (c) 2013, Steven Siloti
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 author nor the names of its
      contributors may be used to endorse or promote products derived
      from this software without specific prior written permission.

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

*/

#include <libtorrent/hasher.hpp>
#include <libtorrent/kademlia/item.hpp>
#include <libtorrent/bencode.hpp>

#include "ed25519.h"

#ifdef TORRENT_DEBUG
#include "libtorrent/lazy_entry.hpp"
#endif

namespace libtorrent { namespace dht
{

namespace
{
	enum { canonical_length = 1200 };
	int canonical_string(std::pair<char const*, int> v, boost::uint64_t seq
		, std::pair<char const*, int> salt, char out[canonical_length])
	{
		// v must be valid bencoding!
#ifdef TORRENT_DEBUG
		lazy_entry e;
		error_code ec;
		TORRENT_ASSERT(lazy_bdecode(v.first, v.first + v.second, e, ec) == 0);
#endif
		char* ptr = out;

		int left = canonical_length - (ptr - out);
		if (salt.second > 0)
		{
			ptr += snprintf(ptr, left, "4:salt%d:", salt.second);
			left = canonical_length - (ptr - out);
			memcpy(ptr, salt.first, (std::min)(salt.second, left));
			ptr += (std::min)(salt.second, left);
			left = canonical_length - (ptr - out);
		}
		ptr += snprintf(ptr, canonical_length - (ptr - out)
			, "3:seqi%" PRId64 "e1:v", seq);
		left = canonical_length - (ptr - out);
		memcpy(ptr, v.first, (std::min)(v.second, left));
		ptr += (std::min)(v.second, left);
		TORRENT_ASSERT((ptr - out) <= canonical_length);
		return ptr - out;
	}
}

sha1_hash item_target_id(
	std::pair<char const*, int> v
	, std::pair<char const*, int> salt
	, char const* pk)
{
	hasher h;
	if (pk)
	{
		h.update(pk, item_pk_len);
		if (salt.second > 0) h.update(salt.first, salt.second);
	}
	else
	{
		h.update(v.first, v.second);
	}
	return h.final();
}

bool verify_mutable_item(
	std::pair<char const*, int> v,
	std::pair<char const*, int> salt,
	boost::uint64_t seq,
	char const* pk,
	char const* sig)
{
#ifdef TORRENT_USE_VALGRIND
	VALGRIND_CHECK_MEM_IS_DEFINED(v.first, v.second);
	VALGRIND_CHECK_MEM_IS_DEFINED(pk, item_pk_len);
	VALGRIND_CHECK_MEM_IS_DEFINED(sig, item_sig_len);
#endif

	char str[canonical_length];
	int len = canonical_string(v, seq, salt, str);

	return ed25519_verify((unsigned char const*)sig,
		(unsigned char const*)str,
		len,
		(unsigned char const*)pk) == 1;
}

void sign_mutable_item(
	std::pair<char const*, int> v,
	std::pair<char const*, int> salt,
	boost::uint64_t seq,
	char const* pk,
	char const* sk,
	char* sig)
{
#ifdef TORRENT_USE_VALGRIND
	VALGRIND_CHECK_MEM_IS_DEFINED(v.first, v.second);
	VALGRIND_CHECK_MEM_IS_DEFINED(sk, item_sk_len);
	VALGRIND_CHECK_MEM_IS_DEFINED(pk, item_pk_len);
#endif

	char str[canonical_length];
	int len = canonical_string(v, seq, salt, str);

	ed25519_sign((unsigned char*)sig,
		(unsigned char const*)str,
		len,
		(unsigned char const*)pk,
		(unsigned char const*)sk
	);
}

sha1_hash mutable_item_cas(std::pair<char const*, int> v
	, std::pair<char const*, int> salt
	, boost::uint64_t seq)
{
	char str[canonical_length];
	int len = canonical_string(v, seq, salt, str);
	return hasher(str, len).final();
}

item::item(entry const& v
	, std::pair<char const*, int> salt
	, boost::uint64_t seq, char const* pk, char const* sk)
{
	assign(v, salt, seq, pk, sk);
}

item::item(lazy_entry const* v, std::pair<char const*, int> salt
	, boost::uint64_t seq, char const* pk, char const* sig)
{
	if (!assign(v, salt, seq, pk, sig))
		throw invalid_item();
}

void item::assign(entry const& v, std::pair<char const*, int> salt
	, boost::uint64_t seq, char const* pk, char const* sk)
{
	m_value = v;
	if (pk && sk)
	{
		char buffer[1000];
		int bsize = bencode(buffer, v);
		TORRENT_ASSERT(bsize <= 1000);
		sign_mutable_item(std::make_pair(buffer, bsize)
			, salt, seq, pk, sk, m_sig);
		memcpy(m_pk, pk, item_pk_len);
		m_seq = seq;
		m_mutable = true;
	}
	else
		m_mutable = false;
}

bool item::assign(lazy_entry const* v
	, std::pair<char const*, int> salt
	, boost::uint64_t seq, char const* pk, char const* sig)
{
	TORRENT_ASSERT(v->data_section().second <= 1000);
	if (pk && sig)
	{
		if (!verify_mutable_item(v->data_section(), salt, seq, pk, sig))
			return false;
		memcpy(m_pk, pk, item_pk_len);
		memcpy(m_sig, sig, item_sig_len);
		if (salt.second > 0)
			m_salt.assign(salt.first, salt.second);
		m_seq = seq;
		m_mutable = true;
	}
	else
		m_mutable = false;

	m_value = *v;
	return true;
}

sha1_hash item::cas()
{
	TORRENT_ASSERT(m_mutable);
	char buffer[1000];
	int bsize = bencode(buffer, m_value);
	return mutable_item_cas(std::make_pair(buffer, bsize)
		, std::pair<char const*, int>(m_salt.c_str(), m_salt.size()), m_seq);
}

} } // namespace libtorrent::dht
<commit_msg>fix valgrind build<commit_after>/*

Copyright (c) 2013, Steven Siloti
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 author nor the names of its
      contributors may be used to endorse or promote products derived
      from this software without specific prior written permission.

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

*/

#include <libtorrent/hasher.hpp>
#include <libtorrent/kademlia/item.hpp>
#include <libtorrent/bencode.hpp>

#include "ed25519.h"

#ifdef TORRENT_DEBUG
#include "libtorrent/lazy_entry.hpp"
#endif

#ifdef TORRENT_USE_VALGRIND
#include <valgrind/memcheck.h>
#endif

namespace libtorrent { namespace dht
{

namespace
{
	enum { canonical_length = 1200 };
	int canonical_string(std::pair<char const*, int> v, boost::uint64_t seq
		, std::pair<char const*, int> salt, char out[canonical_length])
	{
		// v must be valid bencoding!
#ifdef TORRENT_DEBUG
		lazy_entry e;
		error_code ec;
		TORRENT_ASSERT(lazy_bdecode(v.first, v.first + v.second, e, ec) == 0);
#endif
		char* ptr = out;

		int left = canonical_length - (ptr - out);
		if (salt.second > 0)
		{
			ptr += snprintf(ptr, left, "4:salt%d:", salt.second);
			left = canonical_length - (ptr - out);
			memcpy(ptr, salt.first, (std::min)(salt.second, left));
			ptr += (std::min)(salt.second, left);
			left = canonical_length - (ptr - out);
		}
		ptr += snprintf(ptr, canonical_length - (ptr - out)
			, "3:seqi%" PRId64 "e1:v", seq);
		left = canonical_length - (ptr - out);
		memcpy(ptr, v.first, (std::min)(v.second, left));
		ptr += (std::min)(v.second, left);
		TORRENT_ASSERT((ptr - out) <= canonical_length);
		return ptr - out;
	}
}

sha1_hash item_target_id(
	std::pair<char const*, int> v
	, std::pair<char const*, int> salt
	, char const* pk)
{
	hasher h;
	if (pk)
	{
		h.update(pk, item_pk_len);
		if (salt.second > 0) h.update(salt.first, salt.second);
	}
	else
	{
		h.update(v.first, v.second);
	}
	return h.final();
}

bool verify_mutable_item(
	std::pair<char const*, int> v,
	std::pair<char const*, int> salt,
	boost::uint64_t seq,
	char const* pk,
	char const* sig)
{
#ifdef TORRENT_USE_VALGRIND
	VALGRIND_CHECK_MEM_IS_DEFINED(v.first, v.second);
	VALGRIND_CHECK_MEM_IS_DEFINED(pk, item_pk_len);
	VALGRIND_CHECK_MEM_IS_DEFINED(sig, item_sig_len);
#endif

	char str[canonical_length];
	int len = canonical_string(v, seq, salt, str);

	return ed25519_verify((unsigned char const*)sig,
		(unsigned char const*)str,
		len,
		(unsigned char const*)pk) == 1;
}

void sign_mutable_item(
	std::pair<char const*, int> v,
	std::pair<char const*, int> salt,
	boost::uint64_t seq,
	char const* pk,
	char const* sk,
	char* sig)
{
#ifdef TORRENT_USE_VALGRIND
	VALGRIND_CHECK_MEM_IS_DEFINED(v.first, v.second);
	VALGRIND_CHECK_MEM_IS_DEFINED(sk, item_sk_len);
	VALGRIND_CHECK_MEM_IS_DEFINED(pk, item_pk_len);
#endif

	char str[canonical_length];
	int len = canonical_string(v, seq, salt, str);

	ed25519_sign((unsigned char*)sig,
		(unsigned char const*)str,
		len,
		(unsigned char const*)pk,
		(unsigned char const*)sk
	);
}

sha1_hash mutable_item_cas(std::pair<char const*, int> v
	, std::pair<char const*, int> salt
	, boost::uint64_t seq)
{
	char str[canonical_length];
	int len = canonical_string(v, seq, salt, str);
	return hasher(str, len).final();
}

item::item(entry const& v
	, std::pair<char const*, int> salt
	, boost::uint64_t seq, char const* pk, char const* sk)
{
	assign(v, salt, seq, pk, sk);
}

item::item(lazy_entry const* v, std::pair<char const*, int> salt
	, boost::uint64_t seq, char const* pk, char const* sig)
{
	if (!assign(v, salt, seq, pk, sig))
		throw invalid_item();
}

void item::assign(entry const& v, std::pair<char const*, int> salt
	, boost::uint64_t seq, char const* pk, char const* sk)
{
	m_value = v;
	if (pk && sk)
	{
		char buffer[1000];
		int bsize = bencode(buffer, v);
		TORRENT_ASSERT(bsize <= 1000);
		sign_mutable_item(std::make_pair(buffer, bsize)
			, salt, seq, pk, sk, m_sig);
		memcpy(m_pk, pk, item_pk_len);
		m_seq = seq;
		m_mutable = true;
	}
	else
		m_mutable = false;
}

bool item::assign(lazy_entry const* v
	, std::pair<char const*, int> salt
	, boost::uint64_t seq, char const* pk, char const* sig)
{
	TORRENT_ASSERT(v->data_section().second <= 1000);
	if (pk && sig)
	{
		if (!verify_mutable_item(v->data_section(), salt, seq, pk, sig))
			return false;
		memcpy(m_pk, pk, item_pk_len);
		memcpy(m_sig, sig, item_sig_len);
		if (salt.second > 0)
			m_salt.assign(salt.first, salt.second);
		m_seq = seq;
		m_mutable = true;
	}
	else
		m_mutable = false;

	m_value = *v;
	return true;
}

sha1_hash item::cas()
{
	TORRENT_ASSERT(m_mutable);
	char buffer[1000];
	int bsize = bencode(buffer, m_value);
	return mutable_item_cas(std::make_pair(buffer, bsize)
		, std::pair<char const*, int>(m_salt.c_str(), m_salt.size()), m_seq);
}

} } // namespace libtorrent::dht
<|endoftext|>


<commit_before>/*

Copyright (c) 2013, Steven Siloti
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 author nor the names of its
      contributors may be used to endorse or promote products derived
      from this software without specific prior written permission.

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

*/

#include <libtorrent/hasher.hpp>
#include <libtorrent/kademlia/item.hpp>
#include <libtorrent/bencode.hpp>
#include <libtorrent/ed25519.hpp>

#ifdef TORRENT_DEBUG
#include "libtorrent/bdecode.hpp"
#endif

#ifdef TORRENT_USE_VALGRIND
#include <valgrind/memcheck.h>
#endif

namespace libtorrent { namespace dht
{

namespace
{
	enum { canonical_length = 1200 };
	int canonical_string(std::pair<char const*, int> v, boost::uint64_t seq
		, std::pair<char const*, int> salt, char out[canonical_length])
	{
		// v must be valid bencoding!
#ifdef TORRENT_DEBUG
		bdecode_node e;
		error_code ec;
		TORRENT_ASSERT(bdecode(v.first, v.first + v.second, e, ec) == 0);
#endif
		char* ptr = out;

		int left = canonical_length - (ptr - out);
		if (salt.second > 0)
		{
			ptr += snprintf(ptr, left, "4:salt%d:", salt.second);
			left = canonical_length - (ptr - out);
			memcpy(ptr, salt.first, (std::min)(salt.second, left));
			ptr += (std::min)(salt.second, left);
			left = canonical_length - (ptr - out);
		}
		ptr += snprintf(ptr, canonical_length - (ptr - out)
			, "3:seqi%" PRId64 "e1:v", seq);
		left = canonical_length - (ptr - out);
		memcpy(ptr, v.first, (std::min)(v.second, left));
		ptr += (std::min)(v.second, left);
		TORRENT_ASSERT((ptr - out) <= canonical_length);
		return ptr - out;
	}
}

// calculate the target hash for an immutable item.
sha1_hash item_target_id(std::pair<char const*, int> v)
{
	hasher h;
	h.update(v.first, v.second);
	return h.final();
}

// calculate the target hash for a mutable item.
sha1_hash item_target_id(std::pair<char const*, int> salt
	, char const* pk)
{
	hasher h;
	h.update(pk, item_pk_len);
	if (salt.second > 0) h.update(salt.first, salt.second);
	return h.final();
}

bool verify_mutable_item(
	std::pair<char const*, int> v
	, std::pair<char const*, int> salt
	, boost::uint64_t seq
	, char const* pk
	, char const* sig)
{
#ifdef TORRENT_USE_VALGRIND
	VALGRIND_CHECK_MEM_IS_DEFINED(v.first, v.second);
	VALGRIND_CHECK_MEM_IS_DEFINED(pk, item_pk_len);
	VALGRIND_CHECK_MEM_IS_DEFINED(sig, item_sig_len);
#endif

	char str[canonical_length];
	int len = canonical_string(v, seq, salt, str);

	return ed25519_verify(reinterpret_cast<unsigned char const*>(sig)
		, reinterpret_cast<unsigned char const*>(str)
		, len
		, reinterpret_cast<unsigned char const*>(pk)) == 1;
}

// given the bencoded buffer ``v``, the salt (which is optional and may have
// a length of zero to be omitted), sequence number ``seq``, public key (32
// bytes ed25519 key) ``pk`` and a secret/private key ``sk`` (64 bytes ed25519
// key) a signature ``sig`` is produced. The ``sig`` pointer must point to
// at least 64 bytes of available space. This space is where the signature is
// written.
void sign_mutable_item(
	std::pair<char const*, int> v
	, std::pair<char const*, int> salt
	, boost::uint64_t seq
	, char const* pk
	, char const* sk
	, char* sig)
{
#ifdef TORRENT_USE_VALGRIND
	VALGRIND_CHECK_MEM_IS_DEFINED(v.first, v.second);
	VALGRIND_CHECK_MEM_IS_DEFINED(sk, item_sk_len);
	VALGRIND_CHECK_MEM_IS_DEFINED(pk, item_pk_len);
#endif

	char str[canonical_length];
	int len = canonical_string(v, seq, salt, str);

	ed25519_sign(reinterpret_cast<unsigned char*>(sig)
		, reinterpret_cast<unsigned char const*>(str)
		, len
		, reinterpret_cast<unsigned char const*>(pk)
		, reinterpret_cast<unsigned char const*>(sk)
	);
}

item::item(char const* pk, std::string const& salt)
	: m_salt(salt)
	, m_seq(0)
	, m_mutable(true)
{
	memcpy(m_pk.data(), pk, item_pk_len);
}

item::item(entry const& v
	, std::pair<char const*, int> salt
	, boost::uint64_t seq, char const* pk, char const* sk)
{
	assign(v, salt, seq, pk, sk);
}

void item::assign(entry const& v, std::pair<char const*, int> salt
	, boost::uint64_t seq, char const* pk, char const* sk)
{
	m_value = v;
	if (pk && sk)
	{
		char buffer[1000];
		int bsize = bencode(buffer, v);
		TORRENT_ASSERT(bsize <= 1000);
		sign_mutable_item(std::make_pair(buffer, bsize)
			, salt, seq, pk, sk, m_sig.c_array());
		m_salt.assign(salt.first, salt.second);
		memcpy(m_pk.c_array(), pk, item_pk_len);
		m_seq = seq;
		m_mutable = true;
	}
	else
		m_mutable = false;
}

bool item::assign(bdecode_node const& v
	, std::pair<char const*, int> salt
	, boost::uint64_t seq, char const* pk, char const* sig)
{
	TORRENT_ASSERT(v.data_section().second <= 1000);
	if (pk && sig)
	{
		if (!verify_mutable_item(v.data_section(), salt, seq, pk, sig))
			return false;
		memcpy(m_pk.c_array(), pk, item_pk_len);
		memcpy(m_sig.c_array(), sig, item_sig_len);
		if (salt.second > 0)
			m_salt.assign(salt.first, salt.second);
		else
			m_salt.clear();
		m_seq = seq;
		m_mutable = true;
	}
	else
		m_mutable = false;

	m_value = v;
	return true;
}

void item::assign(entry const& v, std::string salt, boost::uint64_t seq
	, char const* pk, char const* sig)
{
	memcpy(m_pk.c_array(), pk, item_pk_len);
	memcpy(m_sig.c_array(), sig, item_sig_len);
	m_salt = salt;
	m_seq = seq;
	m_mutable = true;
	m_value = v;
}

} } // namespace libtorrent::dht
<commit_msg>assert that the signature is valid when assigning a mutable value to an item<commit_after>/*

Copyright (c) 2013, Steven Siloti
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 author nor the names of its
      contributors may be used to endorse or promote products derived
      from this software without specific prior written permission.

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

*/

#include <libtorrent/hasher.hpp>
#include <libtorrent/kademlia/item.hpp>
#include <libtorrent/bencode.hpp>
#include <libtorrent/ed25519.hpp>

#ifdef TORRENT_DEBUG
#include "libtorrent/bdecode.hpp"
#endif

#ifdef TORRENT_USE_VALGRIND
#include <valgrind/memcheck.h>
#endif

namespace libtorrent { namespace dht
{

namespace
{
	enum { canonical_length = 1200 };
	int canonical_string(std::pair<char const*, int> v, boost::uint64_t seq
		, std::pair<char const*, int> salt, char out[canonical_length])
	{
		// v must be valid bencoding!
#ifdef TORRENT_DEBUG
		bdecode_node e;
		error_code ec;
		TORRENT_ASSERT(bdecode(v.first, v.first + v.second, e, ec) == 0);
#endif
		char* ptr = out;

		int left = canonical_length - (ptr - out);
		if (salt.second > 0)
		{
			ptr += snprintf(ptr, left, "4:salt%d:", salt.second);
			left = canonical_length - (ptr - out);
			memcpy(ptr, salt.first, (std::min)(salt.second, left));
			ptr += (std::min)(salt.second, left);
			left = canonical_length - (ptr - out);
		}
		ptr += snprintf(ptr, canonical_length - (ptr - out)
			, "3:seqi%" PRId64 "e1:v", seq);
		left = canonical_length - (ptr - out);
		memcpy(ptr, v.first, (std::min)(v.second, left));
		ptr += (std::min)(v.second, left);
		TORRENT_ASSERT((ptr - out) <= canonical_length);
		return ptr - out;
	}
}

// calculate the target hash for an immutable item.
sha1_hash item_target_id(std::pair<char const*, int> v)
{
	hasher h;
	h.update(v.first, v.second);
	return h.final();
}

// calculate the target hash for a mutable item.
sha1_hash item_target_id(std::pair<char const*, int> salt
	, char const* pk)
{
	hasher h;
	h.update(pk, item_pk_len);
	if (salt.second > 0) h.update(salt.first, salt.second);
	return h.final();
}

bool verify_mutable_item(
	std::pair<char const*, int> v
	, std::pair<char const*, int> salt
	, boost::uint64_t seq
	, char const* pk
	, char const* sig)
{
#ifdef TORRENT_USE_VALGRIND
	VALGRIND_CHECK_MEM_IS_DEFINED(v.first, v.second);
	VALGRIND_CHECK_MEM_IS_DEFINED(pk, item_pk_len);
	VALGRIND_CHECK_MEM_IS_DEFINED(sig, item_sig_len);
#endif

	char str[canonical_length];
	int len = canonical_string(v, seq, salt, str);

	return ed25519_verify(reinterpret_cast<unsigned char const*>(sig)
		, reinterpret_cast<unsigned char const*>(str)
		, len
		, reinterpret_cast<unsigned char const*>(pk)) == 1;
}

// given the bencoded buffer ``v``, the salt (which is optional and may have
// a length of zero to be omitted), sequence number ``seq``, public key (32
// bytes ed25519 key) ``pk`` and a secret/private key ``sk`` (64 bytes ed25519
// key) a signature ``sig`` is produced. The ``sig`` pointer must point to
// at least 64 bytes of available space. This space is where the signature is
// written.
void sign_mutable_item(
	std::pair<char const*, int> v
	, std::pair<char const*, int> salt
	, boost::uint64_t seq
	, char const* pk
	, char const* sk
	, char* sig)
{
#ifdef TORRENT_USE_VALGRIND
	VALGRIND_CHECK_MEM_IS_DEFINED(v.first, v.second);
	VALGRIND_CHECK_MEM_IS_DEFINED(sk, item_sk_len);
	VALGRIND_CHECK_MEM_IS_DEFINED(pk, item_pk_len);
#endif

	char str[canonical_length];
	int len = canonical_string(v, seq, salt, str);

	ed25519_sign(reinterpret_cast<unsigned char*>(sig)
		, reinterpret_cast<unsigned char const*>(str)
		, len
		, reinterpret_cast<unsigned char const*>(pk)
		, reinterpret_cast<unsigned char const*>(sk)
	);
}

item::item(char const* pk, std::string const& salt)
	: m_salt(salt)
	, m_seq(0)
	, m_mutable(true)
{
	memcpy(m_pk.data(), pk, item_pk_len);
}

item::item(entry const& v
	, std::pair<char const*, int> salt
	, boost::uint64_t seq, char const* pk, char const* sk)
{
	assign(v, salt, seq, pk, sk);
}

void item::assign(entry const& v, std::pair<char const*, int> salt
	, boost::uint64_t seq, char const* pk, char const* sk)
{
	m_value = v;
	if (pk && sk)
	{
		char buffer[1000];
		int bsize = bencode(buffer, v);
		TORRENT_ASSERT(bsize <= 1000);
		sign_mutable_item(std::make_pair(buffer, bsize)
			, salt, seq, pk, sk, m_sig.c_array());
		m_salt.assign(salt.first, salt.second);
		memcpy(m_pk.c_array(), pk, item_pk_len);
		m_seq = seq;
		m_mutable = true;
	}
	else
		m_mutable = false;
}

bool item::assign(bdecode_node const& v
	, std::pair<char const*, int> salt
	, boost::uint64_t seq, char const* pk, char const* sig)
{
	TORRENT_ASSERT(v.data_section().second <= 1000);
	if (pk && sig)
	{
		if (!verify_mutable_item(v.data_section(), salt, seq, pk, sig))
			return false;
		memcpy(m_pk.c_array(), pk, item_pk_len);
		memcpy(m_sig.c_array(), sig, item_sig_len);
		if (salt.second > 0)
			m_salt.assign(salt.first, salt.second);
		else
			m_salt.clear();
		m_seq = seq;
		m_mutable = true;
	}
	else
		m_mutable = false;

	m_value = v;
	return true;
}

void item::assign(entry const& v, std::string salt, boost::uint64_t seq
	, char const* pk, char const* sig)
{
#if TORRENT_USE_ASSERTS
	TORRENT_ASSERT(pk && sig);
	char buffer[1000];
	int bsize = bencode(buffer, v);
	TORRENT_ASSERT(bsize <= 1000);
	TORRENT_ASSERT(verify_mutable_item(
		std::make_pair(buffer, bsize)
		, std::make_pair(salt.data(), int(salt.size()))
		, seq, pk, sig));
#endif

	memcpy(m_pk.c_array(), pk, item_pk_len);
	memcpy(m_sig.c_array(), sig, item_sig_len);
	m_salt = salt;
	m_seq = seq;
	m_mutable = true;
	m_value = v;
}

} } // namespace libtorrent::dht
<|endoftext|>


<commit_before>#include <cmath>

#include "ChunkUtils.h"
#include "VoxelFacing2D.h"
#include "VoxelFacing3D.h"
#include "VoxelUtils.h"

#include "components/debug/Debug.h"

NewInt2 VoxelUtils::originalVoxelToNewVoxel(const OriginalInt2 &voxel)
{
	return NewInt2(voxel.y, voxel.x);
}

OriginalInt2 VoxelUtils::newVoxelToOriginalVoxel(const NewInt2 &voxel)
{
	return VoxelUtils::originalVoxelToNewVoxel(voxel);
}

Double2 VoxelUtils::getTransformedVoxel(const Double2 &voxel)
{
	return Double2(voxel.y, voxel.x);
}

VoxelInt3 VoxelUtils::pointToVoxel(const VoxelDouble3 &point, double ceilingScale)
{
	return VoxelInt3(
		static_cast<SNInt>(std::floor(point.x)),
		static_cast<int>(std::floor(point.y / ceilingScale)),
		static_cast<WEInt>(std::floor(point.z)));
}

VoxelInt3 VoxelUtils::pointToVoxel(const VoxelDouble3 &point)
{
	constexpr double ceilingScale = 1.0;
	return VoxelUtils::pointToVoxel(point, ceilingScale);
}

VoxelInt2 VoxelUtils::pointToVoxel(const VoxelDouble2 &point)
{
	return VoxelInt2(
		static_cast<SNInt>(std::floor(point.x)),
		static_cast<WEInt>(std::floor(point.y)));
}

NewDouble3 VoxelUtils::chunkPointToNewPoint(const ChunkInt2 &chunk, const VoxelDouble3 &point)
{
	const NewDouble3 basePoint(
		static_cast<SNDouble>(chunk.x) * ChunkUtils::CHUNK_DIM,
		0.0,
		static_cast<WEDouble>(chunk.y) * ChunkUtils::CHUNK_DIM);
	return basePoint + point;
}

NewDouble2 VoxelUtils::chunkPointToNewPoint(const ChunkInt2 &chunk, const VoxelDouble2 &point)
{
	const NewDouble2 basePoint(
		static_cast<SNDouble>(chunk.x) * ChunkUtils::CHUNK_DIM,
		static_cast<WEDouble>(chunk.y) * ChunkUtils::CHUNK_DIM);
	return basePoint + point;
}

NewInt3 VoxelUtils::chunkVoxelToNewVoxel(const ChunkInt2 &chunk, const VoxelInt3 &voxel)
{
	const NewInt3 baseVoxel(chunk.x * ChunkUtils::CHUNK_DIM, 0, chunk.y * ChunkUtils::CHUNK_DIM);
	return baseVoxel + voxel;
}

NewDouble3 VoxelUtils::coordToNewPoint(const CoordDouble3 &coord)
{
	return VoxelUtils::chunkPointToNewPoint(coord.chunk, coord.point);
}

NewDouble2 VoxelUtils::coordToNewPoint(const CoordDouble2 &coord)
{
	return VoxelUtils::chunkPointToNewPoint(coord.chunk, coord.point);
}

NewInt3 VoxelUtils::coordToNewVoxel(const CoordInt3 &coord)
{
	return VoxelUtils::chunkVoxelToNewVoxel(coord.chunk, coord.voxel);
}

NewInt2 VoxelUtils::coordToNewVoxel(const CoordInt2 &coord)
{
	const NewInt3 voxel3D = VoxelUtils::chunkVoxelToNewVoxel(coord.chunk, VoxelInt3(coord.voxel.x, 0, coord.voxel.y));
	return NewInt2(voxel3D.x, voxel3D.z);
}

NewInt2 VoxelUtils::chunkVoxelToNewVoxel(const ChunkInt2 &chunk, const VoxelInt2 &voxel)
{
	return (chunk * ChunkUtils::CHUNK_DIM) + voxel;
}

CoordDouble3 VoxelUtils::newPointToCoord(const NewDouble3 &point)
{
	const ChunkInt2 chunk(
		static_cast<SNInt>(point.x) / ChunkUtils::CHUNK_DIM,
		static_cast<WEInt>(point.z) / ChunkUtils::CHUNK_DIM);
	const VoxelDouble3 voxel(
		std::fmod(point.x, static_cast<SNDouble>(ChunkUtils::CHUNK_DIM)),
		point.y,
		std::fmod(point.z, static_cast<WEDouble>(ChunkUtils::CHUNK_DIM)));
	return CoordDouble3(chunk, voxel);
}

CoordDouble2 VoxelUtils::newPointToCoord(const NewDouble2 &point)
{
	const ChunkInt2 chunk(
		static_cast<SNInt>(point.x) / ChunkUtils::CHUNK_DIM,
		static_cast<WEInt>(point.y) / ChunkUtils::CHUNK_DIM);
	const VoxelDouble2 voxel(
		std::fmod(point.x, static_cast<SNDouble>(ChunkUtils::CHUNK_DIM)),
		std::fmod(point.y, static_cast<WEDouble>(ChunkUtils::CHUNK_DIM)));
	return CoordDouble2(chunk, voxel);
}

CoordInt3 VoxelUtils::newVoxelToCoord(const NewInt3 &voxel)
{
	CoordInt3 coord(
		ChunkInt2(voxel.x / ChunkUtils::CHUNK_DIM, voxel.z / ChunkUtils::CHUNK_DIM),
		VoxelInt3(voxel.x % ChunkUtils::CHUNK_DIM, voxel.y, voxel.z % ChunkUtils::CHUNK_DIM));
	return coord;
}

CoordInt2 VoxelUtils::newVoxelToCoord(const NewInt2 &voxel)
{
	// @todo: need to handle voxel outside grid.
	// @todo: probably want (int)Floor() instead of modulo.

	CoordInt2 coord(
		ChunkInt2(voxel.x / ChunkUtils::CHUNK_DIM, voxel.y / ChunkUtils::CHUNK_DIM),
		VoxelInt2(voxel.x % ChunkUtils::CHUNK_DIM, voxel.y % ChunkUtils::CHUNK_DIM));
	return coord;
}

CoordInt2 VoxelUtils::levelVoxelToCoord(const LevelInt2 &voxel)
{
	// @todo: make sure it handles negative coordinates.
	return VoxelUtils::newVoxelToCoord(voxel);
}

ChunkInt2 VoxelUtils::newVoxelToChunk(const NewInt2 &voxel)
{
	const CoordInt2 chunkCoord = VoxelUtils::newVoxelToCoord(voxel);
	return chunkCoord.chunk;
}

VoxelInt2 VoxelUtils::wrapVoxelCoord(const VoxelInt2 &voxel)
{
	// @todo: handle negative numbers
	return VoxelInt2(voxel.x % ChunkUtils::CHUNK_DIM, voxel.y % ChunkUtils::CHUNK_DIM);
}

Double3 VoxelUtils::getVoxelCenter(const Int3 &voxel)
{
	return Double3(
		static_cast<double>(voxel.x) + 0.50,
		static_cast<double>(voxel.y) + 0.50,
		static_cast<double>(voxel.z) + 0.50);
}

Double2 VoxelUtils::getVoxelCenter(const Int2 &voxel)
{
	return Double2(
		static_cast<double>(voxel.x) + 0.50,
		static_cast<double>(voxel.y) + 0.50);
}

Double3 VoxelUtils::getNormal(VoxelFacing2D facing)
{
	if (facing == VoxelFacing2D::PositiveX)
	{
		return Double3::UnitX;
	}
	else if (facing == VoxelFacing2D::NegativeX)
	{
		return -Double3::UnitX;
	}
	else if (facing == VoxelFacing2D::PositiveZ)
	{
		return Double3::UnitZ;
	}
	else if (facing == VoxelFacing2D::NegativeZ)
	{
		return -Double3::UnitZ;
	}
	else
	{
		DebugUnhandledReturnMsg(Double3, std::to_string(static_cast<int>(facing)));
	}
}

VoxelFacing3D VoxelUtils::convertFaceTo3D(VoxelFacing2D facing)
{
	if (facing == VoxelFacing2D::PositiveX)
	{
		return VoxelFacing3D::PositiveX;
	}
	else if (facing == VoxelFacing2D::NegativeX)
	{
		return VoxelFacing3D::NegativeX;
	}
	else if (facing == VoxelFacing2D::PositiveZ)
	{
		return VoxelFacing3D::PositiveZ;
	}
	else if (facing == VoxelFacing2D::NegativeZ)
	{
		return VoxelFacing3D::NegativeZ;
	}
	else
	{
		DebugUnhandledReturnMsg(VoxelFacing3D, std::to_string(static_cast<int>(facing)));
	}
}

std::optional<VoxelFacing2D> VoxelUtils::tryConvertFaceTo2D(VoxelFacing3D facing)
{
	if (facing == VoxelFacing3D::PositiveX)
	{
		return VoxelFacing2D::PositiveX;
	}
	else if (facing == VoxelFacing3D::NegativeX)
	{
		return VoxelFacing2D::NegativeX;
	}
	else if (facing == VoxelFacing3D::PositiveZ)
	{
		return VoxelFacing2D::PositiveZ;
	}
	else if (facing == VoxelFacing3D::NegativeZ)
	{
		return VoxelFacing2D::NegativeZ;
	}
	else if ((facing == VoxelFacing3D::PositiveY) || (facing == VoxelFacing3D::NegativeY))
	{
		return std::nullopt;
	}
	else
	{
		DebugUnhandledReturnMsg(VoxelFacing2D, std::to_string(static_cast<int>(facing)));
	}
}

void VoxelUtils::getSurroundingVoxels(const VoxelInt3 &voxel, int distance, VoxelInt3 *outMinVoxel, VoxelInt3 *outMaxVoxel)
{
	DebugAssert(distance >= 0);
	*outMinVoxel = VoxelInt3(voxel.x - distance, voxel.y - distance, voxel.z - distance);
	*outMaxVoxel = VoxelInt3(voxel.x + distance, voxel.y + distance, voxel.z + distance);
}

void VoxelUtils::getSurroundingVoxels(const VoxelInt2 &voxel, int distance, VoxelInt2 *outMinVoxel, VoxelInt2 *outMaxVoxel)
{
	DebugAssert(distance >= 0);
	*outMinVoxel = VoxelInt2(voxel.x - distance, voxel.y - distance);
	*outMaxVoxel = VoxelInt2(voxel.x + distance, voxel.y + distance);
}
<commit_msg>Fixed some VoxelUtils conversion functions.<commit_after>#include <cmath>

#include "ChunkUtils.h"
#include "VoxelFacing2D.h"
#include "VoxelFacing3D.h"
#include "VoxelUtils.h"

#include "components/debug/Debug.h"

NewInt2 VoxelUtils::originalVoxelToNewVoxel(const OriginalInt2 &voxel)
{
	return NewInt2(voxel.y, voxel.x);
}

OriginalInt2 VoxelUtils::newVoxelToOriginalVoxel(const NewInt2 &voxel)
{
	return VoxelUtils::originalVoxelToNewVoxel(voxel);
}

Double2 VoxelUtils::getTransformedVoxel(const Double2 &voxel)
{
	return Double2(voxel.y, voxel.x);
}

VoxelInt3 VoxelUtils::pointToVoxel(const VoxelDouble3 &point, double ceilingScale)
{
	return VoxelInt3(
		static_cast<SNInt>(std::floor(point.x)),
		static_cast<int>(std::floor(point.y / ceilingScale)),
		static_cast<WEInt>(std::floor(point.z)));
}

VoxelInt3 VoxelUtils::pointToVoxel(const VoxelDouble3 &point)
{
	constexpr double ceilingScale = 1.0;
	return VoxelUtils::pointToVoxel(point, ceilingScale);
}

VoxelInt2 VoxelUtils::pointToVoxel(const VoxelDouble2 &point)
{
	return VoxelInt2(
		static_cast<SNInt>(std::floor(point.x)),
		static_cast<WEInt>(std::floor(point.y)));
}

NewDouble3 VoxelUtils::chunkPointToNewPoint(const ChunkInt2 &chunk, const VoxelDouble3 &point)
{
	const NewDouble3 basePoint(
		static_cast<SNDouble>(chunk.x) * ChunkUtils::CHUNK_DIM,
		0.0,
		static_cast<WEDouble>(chunk.y) * ChunkUtils::CHUNK_DIM);
	return basePoint + point;
}

NewDouble2 VoxelUtils::chunkPointToNewPoint(const ChunkInt2 &chunk, const VoxelDouble2 &point)
{
	const NewDouble2 basePoint(
		static_cast<SNDouble>(chunk.x) * ChunkUtils::CHUNK_DIM,
		static_cast<WEDouble>(chunk.y) * ChunkUtils::CHUNK_DIM);
	return basePoint + point;
}

NewInt3 VoxelUtils::chunkVoxelToNewVoxel(const ChunkInt2 &chunk, const VoxelInt3 &voxel)
{
	const NewInt3 baseVoxel(chunk.x * ChunkUtils::CHUNK_DIM, 0, chunk.y * ChunkUtils::CHUNK_DIM);
	return baseVoxel + voxel;
}

NewDouble3 VoxelUtils::coordToNewPoint(const CoordDouble3 &coord)
{
	return VoxelUtils::chunkPointToNewPoint(coord.chunk, coord.point);
}

NewDouble2 VoxelUtils::coordToNewPoint(const CoordDouble2 &coord)
{
	return VoxelUtils::chunkPointToNewPoint(coord.chunk, coord.point);
}

NewInt3 VoxelUtils::coordToNewVoxel(const CoordInt3 &coord)
{
	return VoxelUtils::chunkVoxelToNewVoxel(coord.chunk, coord.voxel);
}

NewInt2 VoxelUtils::coordToNewVoxel(const CoordInt2 &coord)
{
	const NewInt3 voxel3D = VoxelUtils::chunkVoxelToNewVoxel(coord.chunk, VoxelInt3(coord.voxel.x, 0, coord.voxel.y));
	return NewInt2(voxel3D.x, voxel3D.z);
}

NewInt2 VoxelUtils::chunkVoxelToNewVoxel(const ChunkInt2 &chunk, const VoxelInt2 &voxel)
{
	return (chunk * ChunkUtils::CHUNK_DIM) + voxel;
}

CoordDouble3 VoxelUtils::newPointToCoord(const NewDouble3 &point)
{
	const ChunkInt2 chunk(
		static_cast<SNInt>(point.x) / ChunkUtils::CHUNK_DIM,
		static_cast<WEInt>(point.z) / ChunkUtils::CHUNK_DIM);
	const VoxelDouble3 voxel(
		std::fmod(point.x, static_cast<SNDouble>(ChunkUtils::CHUNK_DIM)),
		point.y,
		std::fmod(point.z, static_cast<WEDouble>(ChunkUtils::CHUNK_DIM)));
	return CoordDouble3(chunk, voxel);
}

CoordDouble2 VoxelUtils::newPointToCoord(const NewDouble2 &point)
{
	const ChunkInt2 chunk(
		static_cast<SNInt>(point.x) / ChunkUtils::CHUNK_DIM,
		static_cast<WEInt>(point.y) / ChunkUtils::CHUNK_DIM);
	const VoxelDouble2 voxel(
		std::fmod(point.x, static_cast<SNDouble>(ChunkUtils::CHUNK_DIM)),
		std::fmod(point.y, static_cast<WEDouble>(ChunkUtils::CHUNK_DIM)));
	return CoordDouble2(chunk, voxel);
}

CoordInt3 VoxelUtils::newVoxelToCoord(const NewInt3 &voxel)
{
	constexpr int chunkDim = ChunkUtils::CHUNK_DIM;
	const ChunkInt2 newChunk(
		((voxel.x >= 0) ? voxel.x : (voxel.x - (chunkDim - 1))) / chunkDim,
		((voxel.y >= 0) ? voxel.y : (voxel.y - (chunkDim - 1))) / chunkDim);
	const VoxelInt3 newVoxel(
		(voxel.x >= 0) ? (voxel.x % chunkDim) : (chunkDim - (-voxel.x % chunkDim)),
		(voxel.y >= 0) ? (voxel.y % chunkDim) : (chunkDim - (-voxel.y % chunkDim)),
		(voxel.z >= 0) ? (voxel.z % chunkDim) : (chunkDim - (-voxel.z % chunkDim)));
	return CoordInt3(newChunk, newVoxel);
}

CoordInt2 VoxelUtils::newVoxelToCoord(const NewInt2 &voxel)
{
	constexpr int chunkDim = ChunkUtils::CHUNK_DIM;
	const ChunkInt2 newChunk(
		((voxel.x >= 0) ? voxel.x : (voxel.x - (chunkDim - 1))) / chunkDim,
		((voxel.y >= 0) ? voxel.y : (voxel.y - (chunkDim - 1))) / chunkDim);
	const VoxelInt2 newVoxel(
		(voxel.x >= 0) ? (voxel.x % chunkDim) : (chunkDim - (-voxel.x % chunkDim)),
		(voxel.y >= 0) ? (voxel.y % chunkDim) : (chunkDim - (-voxel.y % chunkDim)));
	return CoordInt2(newChunk, newVoxel);
}

CoordInt2 VoxelUtils::levelVoxelToCoord(const LevelInt2 &voxel)
{
	// @todo: make sure it handles negative coordinates.
	return VoxelUtils::newVoxelToCoord(voxel);
}

ChunkInt2 VoxelUtils::newVoxelToChunk(const NewInt2 &voxel)
{
	const CoordInt2 chunkCoord = VoxelUtils::newVoxelToCoord(voxel);
	return chunkCoord.chunk;
}

VoxelInt2 VoxelUtils::wrapVoxelCoord(const VoxelInt2 &voxel)
{
	// @todo: handle negative numbers
	return VoxelInt2(voxel.x % ChunkUtils::CHUNK_DIM, voxel.y % ChunkUtils::CHUNK_DIM);
}

Double3 VoxelUtils::getVoxelCenter(const Int3 &voxel)
{
	return Double3(
		static_cast<double>(voxel.x) + 0.50,
		static_cast<double>(voxel.y) + 0.50,
		static_cast<double>(voxel.z) + 0.50);
}

Double2 VoxelUtils::getVoxelCenter(const Int2 &voxel)
{
	return Double2(
		static_cast<double>(voxel.x) + 0.50,
		static_cast<double>(voxel.y) + 0.50);
}

Double3 VoxelUtils::getNormal(VoxelFacing2D facing)
{
	if (facing == VoxelFacing2D::PositiveX)
	{
		return Double3::UnitX;
	}
	else if (facing == VoxelFacing2D::NegativeX)
	{
		return -Double3::UnitX;
	}
	else if (facing == VoxelFacing2D::PositiveZ)
	{
		return Double3::UnitZ;
	}
	else if (facing == VoxelFacing2D::NegativeZ)
	{
		return -Double3::UnitZ;
	}
	else
	{
		DebugUnhandledReturnMsg(Double3, std::to_string(static_cast<int>(facing)));
	}
}

VoxelFacing3D VoxelUtils::convertFaceTo3D(VoxelFacing2D facing)
{
	if (facing == VoxelFacing2D::PositiveX)
	{
		return VoxelFacing3D::PositiveX;
	}
	else if (facing == VoxelFacing2D::NegativeX)
	{
		return VoxelFacing3D::NegativeX;
	}
	else if (facing == VoxelFacing2D::PositiveZ)
	{
		return VoxelFacing3D::PositiveZ;
	}
	else if (facing == VoxelFacing2D::NegativeZ)
	{
		return VoxelFacing3D::NegativeZ;
	}
	else
	{
		DebugUnhandledReturnMsg(VoxelFacing3D, std::to_string(static_cast<int>(facing)));
	}
}

std::optional<VoxelFacing2D> VoxelUtils::tryConvertFaceTo2D(VoxelFacing3D facing)
{
	if (facing == VoxelFacing3D::PositiveX)
	{
		return VoxelFacing2D::PositiveX;
	}
	else if (facing == VoxelFacing3D::NegativeX)
	{
		return VoxelFacing2D::NegativeX;
	}
	else if (facing == VoxelFacing3D::PositiveZ)
	{
		return VoxelFacing2D::PositiveZ;
	}
	else if (facing == VoxelFacing3D::NegativeZ)
	{
		return VoxelFacing2D::NegativeZ;
	}
	else if ((facing == VoxelFacing3D::PositiveY) || (facing == VoxelFacing3D::NegativeY))
	{
		return std::nullopt;
	}
	else
	{
		DebugUnhandledReturnMsg(VoxelFacing2D, std::to_string(static_cast<int>(facing)));
	}
}

void VoxelUtils::getSurroundingVoxels(const VoxelInt3 &voxel, int distance, VoxelInt3 *outMinVoxel, VoxelInt3 *outMaxVoxel)
{
	DebugAssert(distance >= 0);
	*outMinVoxel = VoxelInt3(voxel.x - distance, voxel.y - distance, voxel.z - distance);
	*outMaxVoxel = VoxelInt3(voxel.x + distance, voxel.y + distance, voxel.z + distance);
}

void VoxelUtils::getSurroundingVoxels(const VoxelInt2 &voxel, int distance, VoxelInt2 *outMinVoxel, VoxelInt2 *outMaxVoxel)
{
	DebugAssert(distance >= 0);
	*outMinVoxel = VoxelInt2(voxel.x - distance, voxel.y - distance);
	*outMaxVoxel = VoxelInt2(voxel.x + distance, voxel.y + distance);
}
<|endoftext|>


<commit_before>#include <sstream>
#include <string>
#include <libHierGA/HierGA.hpp>
#include "1maxFitness.hpp"

using namespace std;

OneMaxFitness::OneMaxFitness() : ObjectiveFunction() {}

float OneMaxFitness::checkFitness(Genome * genome) {
	unsigned total = 0;
	Genome flattened = genome->flattenGenome();

	for (unsigned int i = 0; i < 32 && i < genome->genomeLength(); i++)
		total += flattened.getIndex<int>(i);

	return total;
}

OneMaxToString::OneMaxToString(
	HierarchicalToString::mode printMode
) : HierarchicalToString(printMode) {}

std::string OneMaxToString::stringifySegment(std::vector<Gene*> genes) {
	stringstream ss;

	for (unsigned int i = 0; i < genes.size(); i++)
		ss << genes[i]->getValue<int>();

	return ss.str();
}
<commit_msg>[1max Fitness]: Fixed bug<commit_after>#include <sstream>
#include <string>
#include <libHierGA/HierGA.hpp>
#include "1maxFitness.hpp"

using namespace std;

OneMaxFitness::OneMaxFitness() : ObjectiveFunction() {}

float OneMaxFitness::checkFitness(Genome * genome) {
	unsigned total = 0;
	Genome flattened = genome->flattenGenome();

	for (unsigned int i = 0; i < flattened.genomeLength(); i++)
		total += flattened.getIndex<int>(i);

	return total;
}

OneMaxToString::OneMaxToString(
	HierarchicalToString::mode printMode
) : HierarchicalToString(printMode) {}

std::string OneMaxToString::stringifySegment(std::vector<Gene*> genes) {
	stringstream ss;

	for (unsigned int i = 0; i < genes.size(); i++)
		ss << genes[i]->getValue<int>();

	return ss.str();
}
<|endoftext|>


<commit_before>/*!
 * \file bezier_util.hpp
 * \brief file bezier_util.hpp
 *
 * Copyright 2019 by Intel.
 *
 * Contact: kevin.rogovin@intel.com
 *
 * This Source Code Form is subject to the
 * terms of the Mozilla Public License, v. 2.0.
 * If a copy of the MPL was not distributed with
 * this file, You can obtain one at
 * http://mozilla.org/MPL/2.0/.
 *
 * \author Kevin Rogovin <kevin.rogovin@intel.com>
 *
 */

#pragma once

#include <fastuidraw/util/util.hpp>
#include <fastuidraw/util/c_array.hpp>
#include <fastuidraw/util/vecN.hpp>

namespace fastuidraw
{
  namespace detail
  {
    template<typename T>
    class DefaultIntermediateType
    {};

    template<>
    class DefaultIntermediateType<int>
    {
    public:
      typedef int64_t int_type;
      typedef float float_type;
    };

    template<>
    class DefaultIntermediateType<float>
    {
    public:
      typedef float int_type;
      typedef float float_type;
    };

    template<>
    class DefaultIntermediateType<double>
    {
    public:
      typedef double int_type;
      typedef double float_type;
    };

    template<typename InputType,
             typename IntermediateType = typename DefaultIntermediateType<InputType>::int_type,
             typename IntermediateFloatType = typename DefaultIntermediateType<InputType>::float_type,
             typename OutputType = InputType>
    vecN<vecN<OutputType, 2>, 3>
    quadratic_from_cubicT(c_array<const vecN<InputType, 2> > pts)
    {
      FASTUIDRAWassert(pts.size() == 4);

      IntermediateType det;
      vecN<IntermediateType, 2> p0(pts[0]), p1(pts[1]), p2(pts[2]), p3(pts[3]);
      vecN<IntermediateType, 2> d10(p1 - p0), d32(p3 - p2);
      vecN<IntermediateType, 2> Jd32(d32.y(), -d32.x());
      vecN<IntermediateType, 2> Jd10(d10.y(), -d10.x());
      vecN<IntermediateFloatType, 2> C;

      det = d10.x() * d32.y() - d10.y() * d32.x();
      if (det == IntermediateType(0))
        {
          C = IntermediateFloatType(0.5) * ( vecN<IntermediateFloatType, 2>(p1 + p2));
        }
      else
        {
          /* Compute where the lines [p0, p1] and [p2, p3]
           * intersect. If the intersection point goes
           * to far beyond p1 or p3, take the average
           * of clamping it going out upto 3 times the
           * length of [p0, p1] or [p2, p3].
           */
          vecN<IntermediateFloatType, 2> Cs, Ct;
          IntermediateFloatType s, t;

          s = IntermediateFloatType(dot(Jd32, p3 - p0)) / IntermediateFloatType(det);
          t = IntermediateFloatType(dot(Jd10, p0 - p3)) / IntermediateFloatType(det);

          s = t_max(IntermediateFloatType(-3.0), t_min(s, IntermediateFloatType(3.0)));
          t = t_max(IntermediateFloatType(-3.0), t_min(t, IntermediateFloatType(3.0)));

          Cs = vecN<IntermediateFloatType, 2>(p0) + s * vecN<IntermediateFloatType, 2>(d10);
          Ct = vecN<IntermediateFloatType, 2>(p3) - t * vecN<IntermediateFloatType, 2>(d32);

          C = IntermediateFloatType(0.5) * (Cs + Ct);
        }

      vecN<vecN<OutputType, 2>, 3> return_value;
      return_value[0] = vecN<OutputType, 2>(pts[0]);
      return_value[1] = vecN<OutputType, 2>(C);
      return_value[2] = vecN<OutputType, 2>(pts[3]);

      return return_value;
    }

    template<typename InputType,
             typename IntermediateType = typename DefaultIntermediateType<InputType>::int_type,
             typename IntermediateFloatType = typename DefaultIntermediateType<InputType>::float_type,
             typename OutputType = InputType>
    vecN<vecN<OutputType, 2>, 3>
    quadratic_from_cubicT(const vecN<vecN<InputType, 2>, 4> &pts)
    {
      c_array<const vecN<InputType, 2> > q(pts.c_ptr(), 4);
      return quadratic_from_cubicT<InputType, IntermediateType, IntermediateFloatType, OutputType>(q);
    }

    template<typename InputType,
             typename IntermediateType = typename DefaultIntermediateType<InputType>::int_type,
             typename OutputType = InputType>
    vecN<vecN<vecN<OutputType, 2>, 4>, 2>
    split_cubicT(c_array<const vecN<InputType, 2> > pts)
    {
      FASTUIDRAWassert(pts.size() == 4);

      vecN<vecN<vecN<OutputType, 2>, 4>, 2> return_value;
      vecN<IntermediateType, 2> p0(pts[0]), p1(pts[1]), p2(pts[2]), p3(pts[3]);
      vecN<IntermediateType, 2> p01, p23, pA, pB, pC;
      const IntermediateType two(2), three(3), four(4), eight(8);

      p01 = (p0 + p1) / two;
      p23 = (p2 + p3) / two;
      pA = (p0 + two * p1 + p2) / four;
      pB = (p1 + two * p2 + p3) / four;
      pC = (p0 + three * p1 + three * p2 + p3) / eight;

      vecN<OutputType, 2> q0(pts[0]), q01(p01), qA(pA), qC(pC);
      vecN<OutputType, 2> qB(pB), q23(p23), q3(pts[3]);

      return_value[0] = vecN<vecN<OutputType, 2>, 4>(q0, q01, qA, qC);
      return_value[1] = vecN<vecN<OutputType, 2>, 4>(qC, qB, q23, q3);

      return return_value;
    }

    template<typename InputType,
             typename IntermediateType = typename DefaultIntermediateType<InputType>::int_type,
             typename OutputType = InputType>
    vecN<vecN<vecN<OutputType, 2>, 4>, 2>
    split_cubicT(const vecN<vecN<InputType, 2>, 4> &pts)
    {
      c_array<const vecN<InputType, 2> > q(pts.c_ptr(), 4);
      return split_cubicT<InputType, IntermediateType, OutputType>(q);
    }
  }
}
<commit_msg>fastuidraw/private/bezier_util: add arc-to-quadratic approximations + rework cubic-to-quadratic approximations<commit_after>/*!
 * \file bezier_util.hpp
 * \brief file bezier_util.hpp
 *
 * Copyright 2019 by Intel.
 *
 * Contact: kevin.rogovin@intel.com
 *
 * This Source Code Form is subject to the
 * terms of the Mozilla Public License, v. 2.0.
 * If a copy of the MPL was not distributed with
 * this file, You can obtain one at
 * http://mozilla.org/MPL/2.0/.
 *
 * \author Kevin Rogovin <kevin.rogovin@intel.com>
 *
 */

#pragma once

#include <fastuidraw/util/util.hpp>
#include <fastuidraw/util/c_array.hpp>
#include <fastuidraw/util/vecN.hpp>
#include <fastuidraw/util/math.hpp>

namespace fastuidraw
{
  namespace detail
  {
    template<typename T>
    class DefaultIntermediateType
    {};

    template<>
    class DefaultIntermediateType<int>
    {
    public:
      typedef int64_t int_type;
      typedef float float_type;
    };

    template<>
    class DefaultIntermediateType<float>
    {
    public:
      typedef float int_type;
      typedef float float_type;
    };

    template<>
    class DefaultIntermediateType<double>
    {
    public:
      typedef double int_type;
      typedef double float_type;
    };

    template<typename InputType,
             typename IntermediateType = typename DefaultIntermediateType<InputType>::int_type,
             typename IntermediateFloatType = typename DefaultIntermediateType<InputType>::float_type,
             typename OutputType = InputType>
    vecN<vecN<OutputType, 2>, 3>
    quadratic_from_cubicT(c_array<const vecN<InputType, 2> > pts)
    {
      FASTUIDRAWassert(pts.size() == 4);

      IntermediateType det;
      vecN<IntermediateType, 2> p0(pts[0]), p1(pts[1]), p2(pts[2]), p3(pts[3]);
      vecN<IntermediateType, 2> d10(p1 - p0), d32(p3 - p2);
      vecN<IntermediateType, 2> Jd32(d32.y(), -d32.x());
      vecN<IntermediateType, 2> Jd10(d10.y(), -d10.x());
      vecN<IntermediateFloatType, 2> C;

      det = d10.x() * d32.y() - d10.y() * d32.x();
      if (det == IntermediateType(0))
        {
          C = IntermediateFloatType(0.5) * ( vecN<IntermediateFloatType, 2>(p1 + p2));
        }
      else
        {
          IntermediateFloatType three(3), four(4);
          vecN<IntermediateFloatType, 2> q0(pts[0]), q1(pts[1]), q2(pts[2]), q3(pts[3]);

          C = (three * q2 - q3 + three * q1 - q0) / four;
        }

      vecN<vecN<OutputType, 2>, 3> return_value;
      return_value[0] = vecN<OutputType, 2>(pts[0]);
      return_value[1] = vecN<OutputType, 2>(C);
      return_value[2] = vecN<OutputType, 2>(pts[3]);

      return return_value;
    }

    template<typename InputType,
             typename IntermediateType = typename DefaultIntermediateType<InputType>::int_type,
             typename IntermediateFloatType = typename DefaultIntermediateType<InputType>::float_type,
             typename OutputType = InputType>
    vecN<vecN<OutputType, 2>, 3>
    quadratic_from_cubicT(const vecN<vecN<InputType, 2>, 4> &pts)
    {
      c_array<const vecN<InputType, 2> > q(pts.c_ptr(), 4);
      return quadratic_from_cubicT<InputType, IntermediateType, IntermediateFloatType, OutputType>(q);
    }

    template<typename InputType,
             typename IntermediateType = typename DefaultIntermediateType<InputType>::int_type,
             typename OutputType = InputType>
    vecN<vecN<vecN<OutputType, 2>, 4>, 2>
    split_cubicT(c_array<const vecN<InputType, 2> > pts)
    {
      FASTUIDRAWassert(pts.size() == 4);

      vecN<vecN<vecN<OutputType, 2>, 4>, 2> return_value;
      vecN<IntermediateType, 2> p0(pts[0]), p1(pts[1]), p2(pts[2]), p3(pts[3]);
      vecN<IntermediateType, 2> p01, p23, pA, pB, pC;
      const IntermediateType two(2), three(3), four(4), eight(8);

      p01 = (p0 + p1) / two;
      p23 = (p2 + p3) / two;
      pA = (p0 + two * p1 + p2) / four;
      pB = (p1 + two * p2 + p3) / four;
      pC = (p0 + three * p1 + three * p2 + p3) / eight;

      vecN<OutputType, 2> q0(pts[0]), q01(p01), qA(pA), qC(pC);
      vecN<OutputType, 2> qB(pB), q23(p23), q3(pts[3]);

      return_value[0] = vecN<vecN<OutputType, 2>, 4>(q0, q01, qA, qC);
      return_value[1] = vecN<vecN<OutputType, 2>, 4>(qC, qB, q23, q3);

      return return_value;
    }

    template<typename InputType,
             typename IntermediateType = typename DefaultIntermediateType<InputType>::int_type,
             typename OutputType = InputType>
    vecN<vecN<vecN<OutputType, 2>, 4>, 2>
    split_cubicT(const vecN<vecN<InputType, 2>, 4> &pts)
    {
      c_array<const vecN<InputType, 2> > q(pts.c_ptr(), 4);
      return split_cubicT<InputType, IntermediateType, OutputType>(q);
    }

    inline
    float
    compute_quadratic_cubic_approximate_error(fastuidraw::c_array<const fastuidraw::vec2> p)
    {
      /* taking the comptuation from http://caffeineowl.com/graphics/2d/vectorial/cubic2quad01.html,
       * letting q1 = (3p2 - p3 + 3p1 - p0) / 4, the error between the quadratic [p0, q1, p2] and
       * the cube [p0, p1, p2, p3] is given by ||p3 - 3p2 + 3p1 - p0 || sqrt(3) / 36. We split
       * the cubic until that error is achieved and then approximate by q.
       */
      const float error_coeff(0.04811252243f);
      fastuidraw::vec2 error_vec(p[3] - 3.0f * p[2] + 3.0f * p[1] - p[0]);
      float error(error_coeff * error_vec.magnitude());
      return error;
    }

    template<typename Builder>
    void
    add_cubic_adaptive(int max_recursion, Builder *B,
                       c_array<const vec2> p, float tol)
    {
      FASTUIDRAWassert(p.size() == 4);
      if (max_recursion == 0 || compute_quadratic_cubic_approximate_error(p) < tol)
        {
          vec2 q1;
          q1 = (3.0f * p[2] - p[3] + 3.0f * p[1] - p[0]) * 0.25f;
          B->quadratic_to(q1, p[3]);
        }
      else
        {
          /* split the cubic */
          vecN<vecN<vec2, 4>, 2> split;

          split = split_cubicT<float>(p);
          add_cubic_adaptive(max_recursion - 1, B, split[0], tol);
          add_cubic_adaptive(max_recursion - 1, B, split[1], tol);
        }
    }

    template<typename Builder>
    void
    add_arc_as_single_cubic(int max_recursion, Builder *B, float tol,
                            vec2 from_pt, vec2 to_pt, float angle)
    {
      vec2 vp(to_pt - from_pt);
      vec2 jp(-vp.y(), vp.x());
      float d(t_tan(angle * 0.25f));
      vec2 c0, c1;

      vp *= ((1.0f - d * d) / 3.0f);
      jp *= (2.0f * d / 3.0f);
      c0 = from_pt + vp - jp;
      c1 = to_pt - vp - jp;

      add_cubic_adaptive(max_recursion, B,
                         vecN<vec2, 4>(from_pt, c0, c1, to_pt),
                         tol);
    }

    template<typename Builder>
    void
    add_arc_as_cubics(int max_recursion, Builder *B, float tol,
                      vec2 start_pt, vec2 end_pt, vec2 center,
                      float radius, float start_angle, float angle)
    {
      /* One way to approximate an arc with a cubic-bezier is as
       * follows (taken from GLyphy which is likely take its
       * computations from Cairo).
       *
       *   D = tan(angle / 4)
       *   p0 = start of arc
       *   p3 = end of arc
       *   vp = p3 - p1
       *   jp = J(vp)
       *   A = (1 - D^2) / 3
       *   B = (2 * D) / 3
       *   p1 = p0 + A * vp - B * jp
       *   p2 = p1 - A * vp - B * jp
       *
       * and the error between the arc and [p0, p1, p2, p3] is given by
       *
       *   error <= |vp| * |D|^5 / 54(1 + D^2)
       *
       * Now, |angle| < 2 * PI, implies |angle| / 4 < PI / 4 thus |D| < 1, giving
       *
       *   error <= |vp| * |D|^5 / 27
       *
       * thus we need:
       *
       *  |tan(|angle| / 4)|^5 < (27 * tol) / |vp|
       *
       * since, tan() is increasing function,
       *
       *   |angle| < 4 * pow(atan((27 * tol) / |vp|), 0.20f)
       *
       */

      vec2 vp(end_pt - start_pt);
      vec2 jp(-vp.y(), vp.x());
      float mag_vp(vp.magnitude());
      float goal, angle_max;

      if (mag_vp < tol)
        {
          B->line_to(end_pt);
          return;
        }

      /* half the tolerance for the cubic to quadratic and half
       * the tolerance for arc to cubic.
       */
      tol *= 0.5f;

      goal = t_min(1.0f, (27.0f * tol) / vp.magnitude());
      angle_max = t_min(FASTUIDRAW_PI, 4.0f * std::pow(fastuidraw::t_atan(goal), 0.20f));

      float angle_remaining(angle);
      float current_angle(start_angle);
      float angle_direction(t_sign(angle));
      float angle_advance(angle_max * angle_direction);
      vec2 last_pt(start_pt);

      while (t_abs(angle_remaining) > angle_max)
        {
          float next_angle(current_angle + angle_advance);
          float cos_next_angle(t_cos(next_angle));
          float sin_next_angle(t_sin(next_angle));
          vec2 next_delta, next_pt;

          next_pt.x() = center.x() + cos_next_angle * radius;
          next_pt.y() = center.y() + sin_next_angle * radius;
          add_arc_as_single_cubic(max_recursion, B, tol, last_pt, next_pt, angle_advance);

          current_angle += angle_advance;
          angle_remaining -= angle_advance;
          last_pt = next_pt;
        }

      add_arc_as_single_cubic(max_recursion, B, tol, last_pt, end_pt, angle_remaining);
    }

  }
}
<|endoftext|>


<commit_before>#ifndef BART_SRC_FRAMEWORK_TESTS_FRAMEWORK_MOCK_HPP_
#define BART_SRC_FRAMEWORK_TESTS_FRAMEWORK_MOCK_HPP_

#include "framework/framework_i.hpp"
#include "test_helpers/gmock_wrapper.h"

namespace bart::framework {

class FrameworkMock : public FrameworkI {
  MOCK_METHOD(void, SolveSystem, (), (override));
  MOCK_METHOD(system::System*, system, (), (const, override));
  MOCK_METHOD(void, OutputResults, (std::ostream& output_stream), (override));
  MOCK_METHOD(void, OutputMasterFile, (std::ostream& output_stream, const std::vector<std::string>& filenames,
      const int process_id), (override));
};

} // namespace bart::framework

#endif //BART_SRC_FRAMEWORK_TESTS_FRAMEWORK_MOCK_HPP_
<commit_msg>Added missing public declaration from framework mock.<commit_after>#ifndef BART_SRC_FRAMEWORK_TESTS_FRAMEWORK_MOCK_HPP_
#define BART_SRC_FRAMEWORK_TESTS_FRAMEWORK_MOCK_HPP_

#include "framework/framework_i.hpp"
#include "test_helpers/gmock_wrapper.h"

namespace bart::framework {

class FrameworkMock : public FrameworkI {
 public:
  MOCK_METHOD(void, SolveSystem, (), (override));
  MOCK_METHOD(system::System*, system, (), (const, override));
  MOCK_METHOD(void, OutputResults, (std::ostream& output_stream), (override));
  MOCK_METHOD(void, OutputMasterFile, (std::ostream& output_stream, const std::vector<std::string>& filenames,
      const int process_id), (override));
};

} // namespace bart::framework

#endif //BART_SRC_FRAMEWORK_TESTS_FRAMEWORK_MOCK_HPP_
<|endoftext|>


<commit_before>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: ScriptElement.cxx,v $
 *
 *  $Revision: 1.9 $
 *
 *  last change: $Author: obo $ $Date: 2006-09-16 12:30:47 $
 *
 *  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_scripting.hxx"

#include "ScriptElement.hxx"
#include <util/util.hxx>

using namespace ::rtl;
using namespace ::com::sun::star;
using namespace ::com::sun::star::uno;

typedef ::std::vector < ::std::pair < ::rtl::OUString, bool > >  dependencies_vec;
typedef ::std::vector < ::std::pair < ::rtl::OUString, ::rtl::OUString > > deliveries_vec;

namespace scripting_impl
{

//*************************************************************************
/**
    Construct a ScriptElement from a ScriptData object

    @param sII
    the ScriptDataObject
*/
ScriptElement::ScriptElement( ScriptData & sII ) :
        XMLElement( OUSTR( "parcel" ) ),
        m_sII( sII )
{
    OSL_TRACE( "ScriptElement ctor called\n" );

    addAttribute( OUSTR( "language" ), sII.language );
    addAttribute( OUSTR( "xmlns:parcel" ), OUSTR( "scripting.dtd" ) );
    XMLElement* xScriptElt = new XMLElement( OUSTR( "script" ) );
    xScriptElt->addAttribute( OUSTR( "language" ), sII.language );
    Reference < xml::sax::XAttributeList > xal( xScriptElt );
    addSubElement( xal );

    strpair_map::const_iterator mp_it = sII.locales.begin();
    strpair_map::const_iterator mp_itend = sII.locales.end();

    for( ; mp_it != mp_itend; ++mp_it )
    {
        XMLElement* xel = new XMLElement( OUSTR( "locale" ) );
        xel->addAttribute( OUSTR( "lang" ), mp_it->first );

        {
            XMLElement* subxel = new XMLElement( OUSTR( "displayname" ) );
            subxel->addAttribute( OUSTR( "value" ), mp_it->second.first );
            Reference < xml::sax::XAttributeList > subxattl( subxel );
            xel->addSubElement( subxattl );
        }
        {
            XMLElement* subxel = new XMLElement( OUSTR( "description" ),
                                     mp_it->second.second );
            Reference< xml::sax::XAttributeList > subxattl( subxel );
            xel->addSubElement( subxattl );
        }

        Reference < xml::sax::XAttributeList > xal( xel );
        xScriptElt->addSubElement( xal );
    }

    {
        XMLElement* xel = new XMLElement( OUSTR( "functionname" ) );
        xel->addAttribute( OUSTR( "value" ), sII.functionname );
        Reference < xml::sax::XAttributeList > xal( xel );
        xScriptElt->addSubElement( xal );
    }

    {
        XMLElement* xel = new XMLElement( OUSTR( "logicalname" ) );
        xel->addAttribute( OUSTR( "value" ), sII.logicalname );
        Reference < xml::sax::XAttributeList > xal( xel );
        xScriptElt->addSubElement( xal );
    }

    props_vec::const_iterator vp_it = sII.languagedepprops.begin();
    props_vec::const_iterator vp_itend = sII.languagedepprops.end();

    if ( vp_it != vp_itend )
    {
        XMLElement* xel = new XMLElement( OUSTR( "languagedepprops" ) );

        for( ; vp_it != vp_itend ; ++vp_it )
        {
            XMLElement* subxel =  new XMLElement( OUSTR( "prop" ) );
            subxel->addAttribute( OUSTR( "name" ), vp_it->first );
            subxel->addAttribute( OUSTR( "value" ), vp_it->second );
            Reference < xml::sax::XAttributeList > subxattl( subxel );
            xel->addSubElement( subxattl );
        }

        Reference < xml::sax::XAttributeList > xal( xel );
        xScriptElt->addSubElement( xal );
    }

    filesets_map::const_iterator fm_it = sII.filesets.begin();
    filesets_map::const_iterator fm_itend = sII.filesets.end();

    for( ; fm_it != fm_itend; ++fm_it )
    {
        XMLElement* xel = new XMLElement( OUSTR( "fileset" ) );
        xel->addAttribute( OUSTR( "name" ), fm_it->first );

        vp_it = fm_it->second.first.begin();
        vp_itend = fm_it->second.first.end();

        for( ; vp_it != vp_itend; ++vp_it )
        {
            XMLElement* subxel = new XMLElement( OUSTR( "prop" ) );
            subxel->addAttribute( OUSTR( "name" ), vp_it->first );
            subxel->addAttribute( OUSTR("value"), vp_it->second );
            Reference < xml::sax::XAttributeList > subxattl( subxel );
            xel->addSubElement( subxattl );
       }

       strpairvec_map::const_iterator sm_it = fm_it->second.second.begin();
       strpairvec_map::const_iterator sm_itend = fm_it->second.second.end();

       if( sm_it != sm_itend )
       {
           // was there a purpose for contstructing this
           // XMLElement* subxel = new XMLElement( OUSTR( "file" ) );
           xel->addAttribute( OUSTR( "name" ), sm_it->first );

       }
    }
}

//*************************************************************************
ScriptElement::~ScriptElement() SAL_THROW(())
{
}

} // namespace scripting_impl
<commit_msg>INTEGRATION: CWS changefileheader (1.9.72); FILE MERGED 2008/03/31 13:36:03 rt 1.9.72.1: #i87441# Change license header to LPGL v3.<commit_after>/*************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2008 by Sun Microsystems, Inc.
 *
 * OpenOffice.org - a multi-platform office productivity suite
 *
 * $RCSfile: ScriptElement.cxx,v $
 * $Revision: 1.10 $
 *
 * This file is part of OpenOffice.org.
 *
 * OpenOffice.org is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License version 3
 * only, as published by the Free Software Foundation.
 *
 * OpenOffice.org 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 version 3 for more details
 * (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU Lesser General Public License
 * version 3 along with OpenOffice.org.  If not, see
 * <http://www.openoffice.org/license.html>
 * for a copy of the LGPLv3 License.
 *
 ************************************************************************/

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

#include "ScriptElement.hxx"
#include <util/util.hxx>

using namespace ::rtl;
using namespace ::com::sun::star;
using namespace ::com::sun::star::uno;

typedef ::std::vector < ::std::pair < ::rtl::OUString, bool > >  dependencies_vec;
typedef ::std::vector < ::std::pair < ::rtl::OUString, ::rtl::OUString > > deliveries_vec;

namespace scripting_impl
{

//*************************************************************************
/**
    Construct a ScriptElement from a ScriptData object

    @param sII
    the ScriptDataObject
*/
ScriptElement::ScriptElement( ScriptData & sII ) :
        XMLElement( OUSTR( "parcel" ) ),
        m_sII( sII )
{
    OSL_TRACE( "ScriptElement ctor called\n" );

    addAttribute( OUSTR( "language" ), sII.language );
    addAttribute( OUSTR( "xmlns:parcel" ), OUSTR( "scripting.dtd" ) );
    XMLElement* xScriptElt = new XMLElement( OUSTR( "script" ) );
    xScriptElt->addAttribute( OUSTR( "language" ), sII.language );
    Reference < xml::sax::XAttributeList > xal( xScriptElt );
    addSubElement( xal );

    strpair_map::const_iterator mp_it = sII.locales.begin();
    strpair_map::const_iterator mp_itend = sII.locales.end();

    for( ; mp_it != mp_itend; ++mp_it )
    {
        XMLElement* xel = new XMLElement( OUSTR( "locale" ) );
        xel->addAttribute( OUSTR( "lang" ), mp_it->first );

        {
            XMLElement* subxel = new XMLElement( OUSTR( "displayname" ) );
            subxel->addAttribute( OUSTR( "value" ), mp_it->second.first );
            Reference < xml::sax::XAttributeList > subxattl( subxel );
            xel->addSubElement( subxattl );
        }
        {
            XMLElement* subxel = new XMLElement( OUSTR( "description" ),
                                     mp_it->second.second );
            Reference< xml::sax::XAttributeList > subxattl( subxel );
            xel->addSubElement( subxattl );
        }

        Reference < xml::sax::XAttributeList > xal( xel );
        xScriptElt->addSubElement( xal );
    }

    {
        XMLElement* xel = new XMLElement( OUSTR( "functionname" ) );
        xel->addAttribute( OUSTR( "value" ), sII.functionname );
        Reference < xml::sax::XAttributeList > xal( xel );
        xScriptElt->addSubElement( xal );
    }

    {
        XMLElement* xel = new XMLElement( OUSTR( "logicalname" ) );
        xel->addAttribute( OUSTR( "value" ), sII.logicalname );
        Reference < xml::sax::XAttributeList > xal( xel );
        xScriptElt->addSubElement( xal );
    }

    props_vec::const_iterator vp_it = sII.languagedepprops.begin();
    props_vec::const_iterator vp_itend = sII.languagedepprops.end();

    if ( vp_it != vp_itend )
    {
        XMLElement* xel = new XMLElement( OUSTR( "languagedepprops" ) );

        for( ; vp_it != vp_itend ; ++vp_it )
        {
            XMLElement* subxel =  new XMLElement( OUSTR( "prop" ) );
            subxel->addAttribute( OUSTR( "name" ), vp_it->first );
            subxel->addAttribute( OUSTR( "value" ), vp_it->second );
            Reference < xml::sax::XAttributeList > subxattl( subxel );
            xel->addSubElement( subxattl );
        }

        Reference < xml::sax::XAttributeList > xal( xel );
        xScriptElt->addSubElement( xal );
    }

    filesets_map::const_iterator fm_it = sII.filesets.begin();
    filesets_map::const_iterator fm_itend = sII.filesets.end();

    for( ; fm_it != fm_itend; ++fm_it )
    {
        XMLElement* xel = new XMLElement( OUSTR( "fileset" ) );
        xel->addAttribute( OUSTR( "name" ), fm_it->first );

        vp_it = fm_it->second.first.begin();
        vp_itend = fm_it->second.first.end();

        for( ; vp_it != vp_itend; ++vp_it )
        {
            XMLElement* subxel = new XMLElement( OUSTR( "prop" ) );
            subxel->addAttribute( OUSTR( "name" ), vp_it->first );
            subxel->addAttribute( OUSTR("value"), vp_it->second );
            Reference < xml::sax::XAttributeList > subxattl( subxel );
            xel->addSubElement( subxattl );
       }

       strpairvec_map::const_iterator sm_it = fm_it->second.second.begin();
       strpairvec_map::const_iterator sm_itend = fm_it->second.second.end();

       if( sm_it != sm_itend )
       {
           // was there a purpose for contstructing this
           // XMLElement* subxel = new XMLElement( OUSTR( "file" ) );
           xel->addAttribute( OUSTR( "name" ), sm_it->first );

       }
    }
}

//*************************************************************************
ScriptElement::~ScriptElement() SAL_THROW(())
{
}

} // namespace scripting_impl
<|endoftext|>


<commit_before>//      sites.hpp
//
//      Copyright 2011 Florian Weber <florian.weber@sfz-bw.de>
//
//      This program is free software; you can redistribute it and/or modify
//      it under the terms of the GNU Affero General Public License as published by
//      the Free Software Foundation; either version 3 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 Affero General Public License for more details.
//
//      You should have received a copy of the GNU Affero 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 SITES_HPP
#define SITES_HPP

#include "page.hpp"
#include "settings.hpp"
#include "id.hpp"

///recreates all posts and the mainpage:
int create_all(settings &S);

///recreates all posts, that are shown on the mainpage and the mainpage:
int create_latest(settings &S);

///recreates the post with the ID id; if the post is shown on the mainpage
///create_latest() will be called:
int create(settings &S,ID id);

///create RSS-feed:
int create_rss(settings &S);

///create RSS-feeds for every tag, if this is configured
int create_tag_rss(settings &S);

///create RSS-feeds for all given tags:
int create_tag_rss(settings &S, deque<string> tags);

///create a new posting; the content has to stand within the given file
int import(settings &S,string filename);

///add a comment for a post; the command has to be in the given file
///WARNING: This won't search for security problems. Do this part in PHP
///or your language of choice:
int comment(settings &S,ID id,string filename);

///edit a post with the ID id:
int edit(settings &S, ID id);

///edit the comments of the post with the ID id:
int edit_comment(settings &S, ID id);

///list all existing entries:
int list_entries(settings &S);

list<blogentry*> search(settings &S,string phrase);

void print_search(settings &S,string phrase);

void print_html_search(settings &S,string phrase);

#endif /* SITES_HPP */
<commit_msg>updated macro<commit_after>//      sites.hpp
//
//      Copyright 2011 Florian Weber <florian.weber@sfz-bw.de>
//
//      This program is free software; you can redistribute it and/or modify
//      it under the terms of the GNU Affero General Public License as published by
//      the Free Software Foundation; either version 3 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 Affero General Public License for more details.
//
//      You should have received a copy of the GNU Affero 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 __ACTIONS_HPP__
#define __ACTIONS_HPP__

#include "page.hpp"
#include "settings.hpp"
#include "id.hpp"

///recreates all posts and the mainpage:
int create_all(settings &S);

///recreates all posts, that are shown on the mainpage and the mainpage:
int create_latest(settings &S);

///recreates the post with the ID id; if the post is shown on the mainpage
///create_latest() will be called:
int create(settings &S,ID id);

///create RSS-feed:
int create_rss(settings &S);

///create RSS-feeds for every tag, if this is configured
int create_tag_rss(settings &S);

///create RSS-feeds for all given tags:
int create_tag_rss(settings &S, deque<string> tags);

///create a new posting; the content has to stand within the given file
int import(settings &S,string filename);

///add a comment for a post; the command has to be in the given file
///WARNING: This won't search for security problems. Do this part in PHP
///or your language of choice:
int comment(settings &S,ID id,string filename);

///edit a post with the ID id:
int edit(settings &S, ID id);

///edit the comments of the post with the ID id:
int edit_comment(settings &S, ID id);

///list all existing entries:
int list_entries(settings &S);

list<blogentry*> search(settings &S,string phrase);

void print_search(settings &S,string phrase);

void print_html_search(settings &S,string phrase);

#endif /* __ACTIONS_HPP__ */
<|endoftext|>


<commit_before>#include "inc\address.h"
#include <sstream>

address::address()
   :m_address(0), m_port(0)
{
}

address::address(const uchar_t & a, const uchar_t & b, const uchar_t & c, const uchar_t & d, const uint16_t & port)
   :m_address(0), m_port(port)
{
   m_address = (a << 24) | (b << 16) | (c << 8) | d;
}

address::address(const uint32_t & addr, const uint16_t & port)
   :m_address(addr), m_port(port)
{
}

const uint32_t & address::getAddress() const
{
   return m_address;
}

const uint16_t & address::getPort() const
{
   return m_port;
}

std::string address::toString(const bool & includePort) const
{
   std::stringstream ss;
   uint16_t d = m_address >> 24;
   uint16_t c = (m_address - (d << 24)) >> 16;
   uint16_t b = (m_address - (d << 24) - (c << 16)) >> 8;
   uint16_t a = m_address - (d << 24) - (c << 16) - (b << 8);
   ss << a << '.' << b << '.' << c << '.' << d;
   return ss.str();
}
<commit_msg>CMake files has been updated<commit_after>#include "inc/address.h"
#include <sstream>

address::address()
   :m_address(0), m_port(0)
{
}

address::address(const uchar_t & a, const uchar_t & b, const uchar_t & c, const uchar_t & d, const uint16_t & port)
   :m_address(0), m_port(port)
{
   m_address = (a << 24) | (b << 16) | (c << 8) | d;
}

address::address(const uint32_t & addr, const uint16_t & port)
   :m_address(addr), m_port(port)
{
}

const uint32_t & address::getAddress() const
{
   return m_address;
}

const uint16_t & address::getPort() const
{
   return m_port;
}

std::string address::toString(const bool & includePort) const
{
   std::stringstream ss;
   uint16_t d = m_address >> 24;
   uint16_t c = (m_address - (d << 24)) >> 16;
   uint16_t b = (m_address - (d << 24) - (c << 16)) >> 8;
   uint16_t a = m_address - (d << 24) - (c << 16) - (b << 8);
   ss << a << '.' << b << '.' << c << '.' << d;
   return ss.str();
}
<|endoftext|>


<commit_before><commit_msg>INTEGRATION: CWS toolbars2 (1.27.42); FILE MERGED 2004/08/09 07:48:33 cd 1.27.42.1: #i32219# Adaption for framework based status bar<commit_after><|endoftext|>


<commit_before><commit_msg>INTEGRATION: CWS fwk16 (1.3.62); FILE MERGED 2005/06/06 10:38:20 pb 1.3.62.1: fix: #i43989# hide 'More Info' button<commit_after><|endoftext|>


<commit_before>/*
Copyright (c) 2012 Carsten Burstedde, Donna Calhoun
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.

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

#include "amr_forestclaw.H"
#include "amr_utils.H"
#include "amr_mol.H"

/* -----------------------------------------------------
   Store data for use by the function that evaluates
   the right hand side needed by MOL solver.
   -----------------------------------------------------*/
static fclaw2d_f_rhs_data_fort_t *s_f_rhs_data = NULL;

// ----------------------------------------------------------
// Vectorize all patch data at a given level
// ----------------------------------------------------------
static
void cb_vectorize_patch_data(fclaw2d_domain_t *domain,
                             fclaw2d_patch_t *this_patch,
                             int this_block_idx,
                             int this_patch_idx,
                             void *user)
{
    ClawPatch *cp = get_clawpatch(this_patch);
    double *curr_data = cp->current_data_ptr();

    fclaw_level_mol_data_t *mol_data = (fclaw_level_mol_data_t*) user;
    int size = mol_data->patch_size;
    int count = mol_data->count;
    mol_data->patches[count] = this_patch;
    mol_data->block_indices[count] = this_block_idx;
    mol_data->patch_indices[count] = this_patch_idx;

    // Copy patch data to  vector.
    for (int i = 0; i < size; i++)
    {
        mol_data->patch_data[count*size + i] = curr_data[i];
    }
    mol_data->count++;
}

static
fclaw_level_mol_data_t* vectorize_patch_data(fclaw2d_domain_t *domain,
                                               int a_level)
{
    int num_patches_at_level = num_patches(domain,a_level);

    const amr_options_t *gparms = get_domain_parms(domain);
    int mx = gparms->mx;
    int my = gparms->my;
    int mbc = gparms->mbc;
    int meqn = gparms->meqn;

    fclaw_level_mol_data_t *mol_data  = new fclaw_level_mol_data_t;
    mol_data->patches = new fclaw2d_patch_t*[num_patches_at_level];
    int neqn = (mx+2*mbc)*(my+2*mbc)*meqn;
    mol_data->patch_size = neqn;
    mol_data->patch_data = new double[num_patches_at_level*neqn];
    mol_data->patch_indices = new int[num_patches_at_level];
    mol_data->block_indices = new int[num_patches_at_level];
    mol_data->level = a_level;

    // Store patches in newly created vector mol_data->patch_data
    mol_data->count = 0;
    fclaw2d_domain_iterate_level(domain, a_level,
                                 cb_vectorize_patch_data,
                                 (void *) mol_data);
    return mol_data;
}

// ----------------------------------------------------------
// Restore vectorized data to patches in tree.
// ----------------------------------------------------------
static
    void restore_patch_data(fclaw2d_domain_t *domain,
                            int a_level,
                            fclaw_level_mol_data_t *mol_data)
{
    int count = mol_data->count; // total number of patches.
    int patch_size = mol_data->patch_size;
    for (int i = 0; i < count; i++)
    {
        fclaw2d_patch_t *this_patch = mol_data->patches[i];
        ClawPatch *cp = get_clawpatch(this_patch);
        double *cp_data = cp->current_data_ptr();
        double *patch_data = &mol_data->patch_data_restore[i*patch_size];
        for (int j = 0; j < patch_size; j++)
        {
            cp_data[j] = patch_data[j];
        }
    }
}

// Evaluate the right hand side, after first restoring
// q to the tree, and getting boundary conditions.
void fclaw_mol_rhs(const double& t_inner,
                   double *q, double *rhs)
{
    // ------------------------------------------------------------
    // Get data that was stored in static variables so we can put
    // everything back on the grid
    // ------------------------------------------------------------

    // Copy mol data back to domain level.  Use statically defined variables.
    fclaw2d_domain_t *domain = s_f_rhs_data->domain;
    fclaw2d_level_time_data_t *time_data = s_f_rhs_data->time_data;
    fclaw_level_mol_data_t *mol_data = s_f_rhs_data->mol_data;

    // The q pointer may not be the same one that is currently in
    // mol_data->patch_data, so we restore the q that is passed in.
    mol_data->patch_data_restore = q;

    // Things that are needed from the above
    const amr_options_t *gparms = get_domain_parms(domain);

    // From time_data
    double t_level = time_data->t_level;
    double t_initial = time_data->t_initial;
    double dt_coarse = time_data->dt_coarse;
    int level = mol_data->level;

    int count = mol_data->count; // Total number of patches at this level.
    int size = mol_data->patch_size;

    // ------------------------------------------------------------
    // Restore data, do a boundary exchange and call RHS function
    // ------------------------------------------------------------
    restore_patch_data(domain,level,mol_data);

    level_exchange(domain,level);
    set_phys_bc(domain,level, t_inner);

    // Set ghost cell values at newly updated data on level 'level'.
    if (t_inner > t_level)
    {
        // level_exchange(domain,level);

        if (!time_data->is_coarsest && gparms->subcycle)
        {
            double alpha = (t_inner - t_initial)/dt_coarse;
            printf("%d %16.8e %16.8e %16.8e\n",level,t_initial,t_inner,alpha);
            exchange_with_coarse(domain, level, t_inner, alpha);
        }
    }

    for(int i = 0; i < count; i++)
    {
        fclaw2d_patch_t *this_patch = mol_data->patches[i];
        int this_patch_idx = mol_data->patch_indices[i];
        int this_block_idx = mol_data->block_indices[i];

        // This is the user defined routine.  The value of
        // this function pointer is set in main.
        fclaw2d_domain_data_t *ddata = get_domain_data(domain);
        fclaw2d_mol_rhs_patch_t f_mol_rhs_patch_ptr = ddata->f_mol_rhs_patch;
        f_mol_rhs_patch_ptr(domain,this_patch,this_block_idx,
                            this_patch_idx,t_inner,&rhs[i*size]);
    }
}

/* ----------------------------------------------------------------------
   Take an MOL step of 'dt'.

   This needs two function pointers :

         void (*fclaw_mol_rhs_patch_t)(fclaw2d_domain_t *domain,
                                       fclaw2d_patch_t *this_patch,
                                       int this_block_idx,
                                       int this_patch_idx,
                                       double t,
                                       double *rhs);

   This function evaluates the right hand side on patch 'this_patch'.
   Both the patch data and the right hand side can be passed to a
   Fortran routine which evaluates the right hand grid.

         void (*fclaw_mol_solver_t)(int neqn,double q[],
                                    double t, double dt);

   This function is an interface to a routine 'amr_<solver>', which calls
   an existing ODE solver.  See 'amr_rkc.cpp', and 'amr_feuler.cpp' for
   examples.

   These function pointers are stored in domain->ddata.
----------------------------------------------------------------------- */
void fclaw_mol_step(fclaw2d_domain_t *domain,
                    int level,
                    fclaw2d_level_time_data_t *time_data)
{
    double t_level = time_data->t_level;
    double dt = time_data->dt;

    fclaw_level_mol_data_t *mol_data = vectorize_patch_data(domain,level);

    int count = mol_data->count;   // Number of patches at 'level'
    int size = mol_data->patch_size;
    int neqn = size*count;

    // Set static data that is needed by 'f_exp' below.
    s_f_rhs_data = new fclaw2d_f_rhs_data_fort_t;
    s_f_rhs_data->domain = domain;
    s_f_rhs_data->mol_data = mol_data;
    s_f_rhs_data->time_data = time_data;

    // -------------------------------------------------------------
    // Call time step method and solve to time t. The function below
    // is an interface to the actual solver.
    // -------------------------------------------------------------
    double *q = mol_data->patch_data;
    fclaw2d_domain_data *ddata = get_domain_data(domain);
    fclaw_mol_solver_t f_mol_solver_ptr = ddata->f_mol_solver;
    f_mol_solver_ptr(neqn,q,t_level,dt);

    // -------------------------------------------------------------
    // Return patch data to the tree
    // -------------------------------------------------------------
    restore_patch_data(domain,level,mol_data);

    delete [] mol_data->patches;
    delete [] mol_data->patch_data;

    delete s_f_rhs_data;
}
<commit_msg>Included comments about where "iterate_level_complete' might go.<commit_after>/*
Copyright (c) 2012 Carsten Burstedde, Donna Calhoun
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.

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

#include "amr_forestclaw.H"
#include "amr_utils.H"
#include "amr_mol.H"

/* -----------------------------------------------------
   Store data for use by the function that evaluates
   the right hand side needed by MOL solver.
   -----------------------------------------------------*/
static fclaw2d_f_rhs_data_fort_t *s_f_rhs_data = NULL;

// ----------------------------------------------------------
// Vectorize all patch data at a given level
// ----------------------------------------------------------
static
void cb_vectorize_patch_data(fclaw2d_domain_t *domain,
                             fclaw2d_patch_t *this_patch,
                             int this_block_idx,
                             int this_patch_idx,
                             void *user)
{
    ClawPatch *cp = get_clawpatch(this_patch);
    double *curr_data = cp->current_data_ptr();

    fclaw_level_mol_data_t *mol_data = (fclaw_level_mol_data_t*) user;
    int size = mol_data->patch_size;
    int count = mol_data->count;
    mol_data->patches[count] = this_patch;
    mol_data->block_indices[count] = this_block_idx;
    mol_data->patch_indices[count] = this_patch_idx;

    // Copy patch data to  vector.
    for (int i = 0; i < size; i++)
    {
        mol_data->patch_data[count*size + i] = curr_data[i];
    }
    mol_data->count++;
}

static
fclaw_level_mol_data_t* vectorize_patch_data(fclaw2d_domain_t *domain,
                                               int a_level)
{
    int include_shadow = 0;
    int num_patches_at_level = num_patches(domain,a_level,include_shadow);

    const amr_options_t *gparms = get_domain_parms(domain);
    int mx = gparms->mx;
    int my = gparms->my;
    int mbc = gparms->mbc;
    int meqn = gparms->meqn;

    fclaw_level_mol_data_t *mol_data  = new fclaw_level_mol_data_t;
    mol_data->patches = new fclaw2d_patch_t*[num_patches_at_level];
    int neqn = (mx+2*mbc)*(my+2*mbc)*meqn;
    mol_data->patch_size = neqn;
    mol_data->patch_data = new double[num_patches_at_level*neqn];
    mol_data->patch_indices = new int[num_patches_at_level];
    mol_data->block_indices = new int[num_patches_at_level];
    mol_data->level = a_level;

    // This should be a 'domain_iterate_level_complete' - that is, we want
    // to iterate over 'shadow' patches here.
    // Store all patches at this level in newly created vector
    // mol_data->patch_data
    mol_data->count = 0;
    fclaw2d_domain_iterate_level(domain, a_level,
                                 cb_vectorize_patch_data,
                                 (void *) mol_data);
    return mol_data;
}

// ----------------------------------------------------------
// Restore vectorized data to patches in tree.
// ----------------------------------------------------------
static
    void restore_patch_data(fclaw2d_domain_t *domain,
                            int a_level,
                            fclaw_level_mol_data_t *mol_data)
{
    int count = mol_data->count; // total number of patches.
    int patch_size = mol_data->patch_size;
    for (int i = 0; i < count; i++)
    {
        fclaw2d_patch_t *this_patch = mol_data->patches[i];
        ClawPatch *cp = get_clawpatch(this_patch);
        double *cp_data = cp->current_data_ptr();
        double *patch_data = &mol_data->patch_data_restore[i*patch_size];
        for (int j = 0; j < patch_size; j++)
        {
            cp_data[j] = patch_data[j];
        }
    }
}

/* -------------------------------------------------------------
   Evaluate the right hand side, after first restoring
   q to the tree, and getting boundary conditions
   -------------------------------------------------------------- */
void fclaw2d_mol_rhs(const double& t_inner, double *q, double *rhs)
{
    // ------------------------------------------------------------
    // Get data that was stored in static variables so we can put
    // everything back on the grid
    // ------------------------------------------------------------

    // Copy mol data back to domain level.  Use statically defined variables.
    fclaw2d_domain_t *domain = s_f_rhs_data->domain;
    fclaw2d_level_time_data_t *time_data = s_f_rhs_data->time_data;
    fclaw_level_mol_data_t *mol_data = s_f_rhs_data->mol_data;

    // The q pointer may not be the same one that is currently in
    // mol_data->patch_data, so we restore the q that is passed in.
    mol_data->patch_data_restore = q;

    // Things that are needed from the above
    const amr_options_t *gparms = get_domain_parms(domain);

    // From time_data
    double t_level = time_data->t_level;
    double t_initial = time_data->t_initial;
    double dt_coarse = time_data->dt_coarse;
    int level = mol_data->level;

    int count = mol_data->count; // Total number of patches at this level.
    int size = mol_data->patch_size;

    // ------------------------------------------------------------
    // Restore data, do a boundary exchange and call RHS function
    // ------------------------------------------------------------
    restore_patch_data(domain,level,mol_data);

    level_exchange(domain,level);
    set_phys_bc(domain,level, t_inner);

    // Set ghost cell values at newly updated data on level 'level'.
    if (t_inner > t_level)
    {
        // level_exchange(domain,level);

        if (!time_data->is_coarsest && gparms->subcycle)
        {
            double alpha = (t_inner - t_initial)/dt_coarse;
            printf("%d %16.8e %16.8e %16.8e\n",level,t_initial,t_inner,alpha);
            exchange_with_coarse(domain, level, t_inner, alpha);
        }
    }

    for(int i = 0; i < count; i++)
    {
        fclaw2d_patch_t *this_patch = mol_data->patches[i];
        int this_patch_idx = mol_data->patch_indices[i];
        int this_block_idx = mol_data->block_indices[i];

        // This is the user defined routine.  The value of
        // this function pointer is set in main.
        fclaw2d_domain_data_t *ddata = get_domain_data(domain);
        fclaw2d_mol_rhs_patch_t f_mol_rhs_patch_ptr = ddata->f_mol_rhs_patch;
        f_mol_rhs_patch_ptr(domain,this_patch,this_block_idx,
                            this_patch_idx,t_inner,&rhs[i*size]);
    }
}

/* ----------------------------------------------------------------------
   Take an MOL step of 'dt'.

   This needs two function pointers :

         void (*fclaw_mol_rhs_patch_t)(fclaw2d_domain_t *domain,
                                       fclaw2d_patch_t *this_patch,
                                       int this_block_idx,
                                       int this_patch_idx,
                                       double t,
                                       double *rhs);

   This function evaluates the right hand side on patch 'this_patch'.
   Both the patch data and the right hand side can be passed to a
   Fortran routine which evaluates the right hand grid.

         void (*fclaw_mol_solver_t)(int neqn,double q[],
                                    double t, double dt);

   This function is an interface to a routine 'amr_<solver>', which calls
   an existing ODE solver.  See 'amr_rkc.cpp', and 'amr_feuler.cpp' for
   examples.

   These function pointers are stored in domain->ddata.
----------------------------------------------------------------------- */
void fclaw_mol_step(fclaw2d_domain_t *domain,
                    int level,
                    fclaw2d_level_time_data_t *time_data)
{
    double t_level = time_data->t_level;
    double dt = time_data->dt;

    fclaw_level_mol_data_t *mol_data = vectorize_patch_data(domain,level);

    int count = mol_data->count;   // Number of patches at 'level'
    int size = mol_data->patch_size;
    int neqn = size*count;

    // Set static data that is needed by 'f_exp' below.
    s_f_rhs_data = new fclaw2d_f_rhs_data_fort_t;
    s_f_rhs_data->domain = domain;
    s_f_rhs_data->mol_data = mol_data;
    s_f_rhs_data->time_data = time_data;

    // -------------------------------------------------------------
    // Call time step method and solve to time t. The function below
    // is an interface to the actual solver.
    // -------------------------------------------------------------
    double *q = mol_data->patch_data;
    fclaw2d_domain_data *ddata = get_domain_data(domain);
    fclaw_mol_solver_t f_mol_solver_ptr = ddata->f_mol_solver;
    f_mol_solver_ptr(neqn,q,t_level,dt);

    // -------------------------------------------------------------
    // Return patch data to the tree
    // -------------------------------------------------------------
    restore_patch_data(domain,level,mol_data);

    delete [] mol_data->patches;
    delete [] mol_data->patch_data;

    delete s_f_rhs_data;
}
<|endoftext|>


<commit_before><commit_msg>fix spelling<commit_after><|endoftext|>