<commit_before>/*
 * TTBlue Class that maintains a table of symbols
 * Copyright © 2008, Timothy Place
 *
 * License: This code is licensed under the terms of the "New BSD License"
 * http://creativecommons.org/licenses/BSD/
 */

#include "TTSymbolTable.h"
#include "TTMutex.h"
#include "TTValue.h"

#if defined( TT_PLATFORM_MAC ) || defined ( TT_PLATFORM_IPHONE )
//#include <ext/hash_map>
//using namespace __gnu_cxx;
#include "boost/unordered_map.hpp"
using namespace boost;
#elif TT_PLATFORM_LINUX
#include <map>
#else
#include <hash_map>
using namespace stdext;	// Visual Studio 2008 puts the hash_map in this namespace
#endif

/** A simple helper class used by TTSymbolTable for comparing hash_map keys.  */
#if defined( TT_PLATFORM_WIN )
class TTStringCompare : public stdext::hash_compare<const TTCString> {
public:
	bool operator()(const TTCString s1, const TTCString s2) const
	{
		return !strcmp(s1, s2);
	}

	std::size_t operator()(const TTCString s)
	{
		return stdext::hash_value(s);
	}
};
#elif defined( TT_PLATFORM_MAC ) || defined ( TT_PLATFORM_IPHONE )
class TTStringCompare {
public:
	bool operator()(const char* s1, const char* s2) const
	{
		return !strcmp(s1, s2);
	}
};
#endif

/** A type that represents the key as a C-String and the value as a pointer to the matching TTSymbol object. */
typedef pair<const char*, TTSymbolPtr>										TTSymbolTablePair;

/** A hash_map type used by TTSymbolTable. */
#ifdef TT_PLATFORM_WIN
typedef hash_map<TTString, TTSymbolPtr>										TTSymbolTableHash;
#elif TT_PLATFORM_LINUX
typedef map<const char*, TTSymbolPtr>										TTSymbolTableHash;
#else
typedef unordered_map<const char*, TTSymbolPtr, hash<const char*>, TTStringCompare>	TTSymbolTableHash;
#endif

/** An iterator for the STL hash_map used by TTSymbolTable. */
typedef TTSymbolTableHash::const_iterator									TTSymbolTableIter;

static TTMutex*				sMutex = NULL;
TTFOUNDATION_EXPORT TTSymbolTable*		ttSymbolTable = NULL;

#define mSYMBOLTABLE ((TTSymbolTableHash*)(mSymbolTable))

/****************************************************************************************************/

TTSymbolTable::TTSymbolTable()
{
	if (!sMutex)
		sMutex = new TTMutex(true);
	mSymbolTable = (TTPtr) new TTSymbolTableHash;
	mSYMBOLTABLE->insert(TTSymbolTablePair("", new TTSymbol("", 0)));
}

TTSymbolTable::~TTSymbolTable()
{
	TTSymbolTableIter	iter;

	for (iter = mSYMBOLTABLE->begin(); iter != mSYMBOLTABLE->end(); iter++)
		delete TTSymbolPtr(iter->second);
	mSYMBOLTABLE->clear();
	delete mSYMBOLTABLE;
	// TODO: we should reference count symbol tables and then free the mutex here, yes?
}

TTSymbol* TTSymbolTable::lookup(const char* aString)
{
	TTSymbolTableIter	iter;

	sMutex->lock();

	iter = mSYMBOLTABLE->find(aString);
	if (iter == mSYMBOLTABLE->end()) {
		// The symbol wasn't found in the table, so we need to create and add it.
		// TTLogMessage("Adding symbol: %s  With Address: %x", aString, aString);
		TTSymbolPtr	newSymbol = new TTSymbol(aString, mSYMBOLTABLE->size());
		mSYMBOLTABLE->insert(TTSymbolTablePair(newSymbol->getCString(), newSymbol));
		sMutex->unlock();
		return newSymbol;
	}
	else {
		// The symbol was found, so we return it.
		sMutex->unlock();
		return iter->second;
	}
}

TTSymbol* TTSymbolTable::lookup(const TTString& aString)
{
	return lookup(aString.c_str());
}

TTSymbol* TTSymbolTable::lookup(const int& aNumberToBeConvertedToAString)
{
	char	cString[16];

	snprintf(cString, 16, "%d", aNumberToBeConvertedToAString);
	return lookup(cString);
}

void TTSymbolTable::dump(TTValue& allSymbols)
{
	TTSymbolTableIter	iter;

	TTLogMessage("---- DUMPING SYMBOL TABLE -- BEGIN ----\n");
	allSymbols.clear();
	for (iter = mSYMBOLTABLE->begin(); iter != mSYMBOLTABLE->end(); iter++) {
		allSymbols.append(TTSymbolPtr(iter->second));
		TTLogMessage("KEY:%s   VALUE:%s\n", iter->first, TTSymbolPtr(iter->second)->getCString());
	}
	TTLogMessage("---- DUMPING SYMBOL TABLE -- END ----\n");
}
<commit_msg>TTSymbolTable: fixes for the unordered_map not working correctly with the previous C-String to Pointer mapping -- now we do std::string to pointer mapping, which is the common/optimized case for unordered_map.<commit_after>/*
 * TTBlue Class that maintains a table of symbols
 * Copyright © 2008, Timothy Place
 *
 * License: This code is licensed under the terms of the "New BSD License"
 * http://creativecommons.org/licenses/BSD/
 */

#include "TTSymbolTable.h"
#include "TTMutex.h"
#include "TTValue.h"

#if defined( TT_PLATFORM_MAC ) || defined ( TT_PLATFORM_IPHONE )
//#include <ext/hash_map>
//using namespace __gnu_cxx;
#include "boost/unordered_map.hpp"
using namespace boost;
#elif TT_PLATFORM_LINUX
#include <map>
#else
#include <hash_map>
using namespace stdext;	// Visual Studio 2008 puts the hash_map in this namespace
#endif

/** A simple helper class used by TTSymbolTable for comparing hash_map keys.  */
#if defined( TT_PLATFORM_WIN )
class TTStringCompare : public stdext::hash_compare<const TTCString> {
public:
	bool operator()(const TTCString s1, const TTCString s2) const
	{
		return !strcmp(s1, s2);
	}

	std::size_t operator()(const TTCString s)
	{
		return stdext::hash_value(s);
	}
};
//#elif defined( TT_PLATFORM_MAC ) || defined ( TT_PLATFORM_IPHONE )
//class TTStringCompare {
//public:
//	bool operator()(const char* s1, const char* s2) const
//	{
//		return !strcmp(s1, s2);
//	}
//};
#endif

/** A type that represents the key as a C-String and the value as a pointer to the matching TTSymbol object. */
typedef pair<const char*, TTSymbolPtr>				TTSymbolTablePair;

/** A hash_map type used by TTSymbolTable. */
#ifdef TT_PLATFORM_WIN
typedef hash_map<TTString, TTSymbolPtr>				TTSymbolTableHash;
#elif TT_PLATFORM_LINUX
typedef map<const char*, TTSymbolPtr>				TTSymbolTableHash;
#else
//typedef unordered_map<const char*, TTSymbolPtr, hash<const char*>, TTStringCompare>	TTSymbolTableHash;
//typedef unordered_map<const char*, TTSymbolPtr>		TTSymbolTableHash;
typedef unordered_map<std::string, TTSymbolPtr>		TTSymbolTableHash;
#endif

/** An iterator for the STL hash_map used by TTSymbolTable. */
typedef TTSymbolTableHash::const_iterator			TTSymbolTableIter;

static TTMutex*				sMutex = NULL;
TTFOUNDATION_EXPORT TTSymbolTable*		ttSymbolTable = NULL;

#define mSYMBOLTABLE ((TTSymbolTableHash*)(mSymbolTable))

/****************************************************************************************************/

TTSymbolTable::TTSymbolTable()
{
	if (!sMutex)
		sMutex = new TTMutex(true);
	mSymbolTable = (TTPtr) new TTSymbolTableHash;
	mSYMBOLTABLE->insert(TTSymbolTablePair("", new TTSymbol("", 0)));
}

TTSymbolTable::~TTSymbolTable()
{
	TTSymbolTableIter	iter;

	for (iter = mSYMBOLTABLE->begin(); iter != mSYMBOLTABLE->end(); iter++)
		delete TTSymbolPtr(iter->second);
	mSYMBOLTABLE->clear();
	delete mSYMBOLTABLE;
	// TODO: we should reference count symbol tables and then free the mutex here, yes?
}

TTSymbol* TTSymbolTable::lookup(const char* aString)
{
#ifdef TT_PLATFORM_WIN
	TTSymbolTableIter	iter;

	sMutex->lock();

	iter = mSYMBOLTABLE->find(aString);
	if (iter == mSYMBOLTABLE->end()) {
		// The symbol wasn't found in the table, so we need to create and add it.
		// TTLogMessage("Adding symbol: %s  With Address: %x", aString, aString);
		TTSymbolPtr	newSymbol = new TTSymbol(aString, mSYMBOLTABLE->size());
		mSYMBOLTABLE->insert(TTSymbolTablePair(newSymbol->getCString(), newSymbol));
		sMutex->unlock();
		return newSymbol;
	}
	else {
		// The symbol was found, so we return it.
		sMutex->unlock();
		return iter->second;
	}
#else
	const TTString s(aString);
	return lookup(s);
#endif
}

TTSymbol* TTSymbolTable::lookup(const TTString& aString)
{
#ifdef TT_PLATFORM_WIN
	return lookup(aString.c_str());
#else
	TTSymbolTableIter	iter;

	sMutex->lock();

	iter = mSYMBOLTABLE->find(aString);
	if (iter == mSYMBOLTABLE->end()) {
		// The symbol wasn't found in the table, so we need to create and add it.
		// TTLogMessage("Adding symbol: %s  With Address: %x", aString, aString);
		TTSymbolPtr	newSymbol = new TTSymbol(aString, mSYMBOLTABLE->size());
		mSYMBOLTABLE->insert(TTSymbolTablePair(newSymbol->getCString(), newSymbol));
		sMutex->unlock();
		return newSymbol;
	}
	else {
		// The symbol was found, so we return it.
		sMutex->unlock();
		return iter->second;
	}
#endif
}

TTSymbol* TTSymbolTable::lookup(const int& aNumberToBeConvertedToAString)
{
#ifdef TT_PLATFORM_WIN
	char	cString[16];

	snprintf(cString, 16, "%d", aNumberToBeConvertedToAString);
	return lookup(cString);
#else
	char	cString[16];

	snprintf(cString, 16, "%d", aNumberToBeConvertedToAString);

	TTString s(cString);
	return lookup(s);
#endif
}

void TTSymbolTable::dump(TTValue& allSymbols)
{
	TTSymbolTableIter	iter;

	TTLogMessage("---- DUMPING SYMBOL TABLE -- BEGIN ----\n");
	allSymbols.clear();
	for (iter = mSYMBOLTABLE->begin(); iter != mSYMBOLTABLE->end(); iter++) {
		allSymbols.append(TTSymbolPtr(iter->second));
		TTLogMessage("KEY:%s   VALUE:%s\n", iter->first, TTSymbolPtr(iter->second)->getCString());
	}
	TTLogMessage("---- DUMPING SYMBOL TABLE -- END ----\n");
}
<|endoftext|>


<commit_before>//=======================================================================
// Copyright (c) 2014-2016 Baptiste Wicht
// Distributed under the terms of the MIT License.
// (See accompanying file LICENSE or copy at
//  http://opensource.org/licenses/MIT)
//=======================================================================

#pragma once

//Get the implementations
#include "etl/impl/conv.hpp"

namespace etl {

/*!
 * \brief A basic configurable convolution expr
 * \tparam T The value type
 * \tparam D The dimensions of convolution
 * \tparam TT The convolution type
 * \tparam Impl The implementation class
 */
template <typename T, std::size_t D, conv_type TT, typename Impl, std::size_t C4 = 0>
struct basic_conv_expr : impl_expr<basic_conv_expr<T, D, TT, Impl, C4>> {
    static_assert(D > 0, "0D convolution is not valid");

    using value_type = T;                                   ///< The type of value of the expression
    using this_type  = basic_conv_expr<T, D, TT, Impl, C4>; ///< The type of this expression

    static constexpr const bool is_gpu = is_cufft_enabled || is_cudnn_enabled; ///< Indicates if the expression runs on GPU

    /*!
     * \brief The result type for given sub types
     * \tparam A The left hand side epxpression type
     * \tparam B The right hand side epxpression type
     */
    template <typename A, typename B>
    using result_type = detail::expr_result_t<this_type, A, B>;

    /*!
     * \brief Validate the convolutiond dimensions
     * \param a The input matrix
     * \þaram b The kernel matrix
     * \þaram c The output matrix
     */
    template <typename A, typename B, typename C, cpp_enable_if(all_fast<A,B,C>::value)>
    static void check(const A& a, const B& b, const C& c) {
        cpp_unused(a);
        cpp_unused(b);
        cpp_unused(c);

        Impl::template check<A,B,C>();
    }

    /*!
     * \brief Validate the convolutiond dimensions
     * \param a The input matrix
     * \þaram b The kernel matrix
     * \þaram c The output matrix
     */
    template <typename A, typename B, typename C, cpp_disable_if(all_fast<A,B,C>::value)>
    static void check(const A& a, const B& b, const C& c) {
        Impl::check(a, b, c);
    }

    /*!
     * \brief Apply the expression
     * \param a The left hand side
     * \param b The right hand side
     * \param c The expression where to store the results
     */
    template <typename A, typename B, typename C>
    static void apply(A&& a, B&& b, C&& c) {
        static_assert(all_etl_expr<A, B, C>::value, "Convolution only supported for ETL expressions");

        check(a, b, c);

        Impl::apply(
            make_temporary(std::forward<A>(a)),
            make_temporary(std::forward<B>(b)),
            std::forward<C>(c));
    }

    /*!
     * \brief Returns a textual representation of the operation
     * \return a textual representation of the operation
     */
    static constexpr const char* desc() noexcept {
        return Impl::desc();
    }

    /*!
     * \brief Returns the DDth dimension of the expression
     * \return the DDth dimension of the expression
     */
    template <typename A, typename B, std::size_t DD>
    static constexpr std::size_t dim() {
        return Impl::template dim<DD, A, B>();
    }

    /*!
     * \brief Returns the dth dimension of the expression
     * \param a The left hand side
     * \param b The right hand side
     * \param d The dimension to get
     * \return the dth dimension of the expression
     */
    template <typename A, typename B>
    static std::size_t dim(const A& a, const B& b, std::size_t d) {
        return Impl::dim(d, a, b);
    }

    /*!
     * \brief Returns the size of the expression
     * \param a The left hand side
     * \param b The right hand side
     * \return the size of the expression
     */
    template <typename A, typename B>
    static std::size_t size(const A& a, const B& b) {
        std::size_t acc = 1;
        for (std::size_t i = 0; i < dimensions(); ++i) {
            acc *= this_type::dim(a, b, i);
        }
        return acc;
    }

    /*!
     * \brief Returns the multiplicative sum of the dimensions at the given indices
     * \return the multiplicative sum of the dimensions at the given indices
     */
    template <typename A, typename B, std::size_t... I>
    static constexpr std::size_t size_mul(const std::index_sequence<I...>& /*seq*/) {
        return mul_all<this_type::dim<A, B, I>()...>::value;
    }

    /*!
     * \brief Returns the size of the expression
     * \return the size of the expression
     */
    template <typename A, typename B>
    static constexpr std::size_t size() {
        return size_mul<A, B>(std::make_index_sequence<dimensions()>());
    }

    /*!
     * \brief Returns the storage order of the expression.
     * \return the storage order of the expression
     */
    template <typename A, typename B>
    static constexpr etl::order order() {
        return etl::order::RowMajor;
    }

    /*!
     * \brief Returns the number of dimensions of the expression
     * \return the number of dimensions of the expression
     */
    static constexpr std::size_t dimensions() {
        return is_multi(TT) ? D + 1 : D;
    }
};

//1D convolution

/*!
 * \brief Expression for 1D valid convolution
 */
template <typename T>
using conv1_valid_expr = basic_conv_expr<T, 1, conv_type::VALID, detail::conv1_valid_impl>;

/*!
 * \brief Expression for 1D same convolution
 */
template <typename T>
using conv1_same_expr = basic_conv_expr<T, 1, conv_type::SAME, detail::conv1_same_impl>;

/*!
 * \brief Expression for 1D full convolution
 */
template <typename T>
using conv1_full_expr = basic_conv_expr<T, 1, conv_type::FULL, detail::conv1_full_impl>;

//2D convolutions

/*!
 * \brief Expression for 2D valid convolution
 */
template<typename T, size_t S1 = 0, size_t S2 = 0, size_t P1 = 0, size_t P2 = 0>
using conv2_valid_expr = basic_conv_expr<T, 2, conv_type::VALID, detail::conv2_valid_impl<S1, S2, P1, P2>>;

/*!
 * \brief Expression for 2D valid convolution
 */
template<typename T, size_t S1 = 0, size_t S2 = 0, size_t P1 = 0, size_t P2 = 0>
using conv2_valid_flipped_expr = basic_conv_expr<T, 2, conv_type::VALID, detail::conv2_valid_flipped_impl<S1, S2, P1, P2>>;

/*!
 * \brief Expression for 4D valid convolution
 */
template <typename T>
using conv4_valid_expr = basic_conv_expr<T, 4, conv_type::VALID, detail::conv4_valid_impl, 1>;

/*!
 * \brief Expression for 4D valid convolution
 */
template <typename T>
using conv4_valid_filter_expr = basic_conv_expr<T, 4, conv_type::VALID, detail::conv4_valid_filter_impl, 2>;

/*!
 * \brief Expression for 4D valid convolution
 */
template <typename T>
using conv4_valid_filter_flipped_expr = basic_conv_expr<T, 4, conv_type::VALID, detail::conv4_valid_filter_flipped_impl, 2>;

/*!
 * \brief Expression for 4D valid convolution
 */
template <typename T>
using conv4_full_expr = basic_conv_expr<T, 4, conv_type::FULL, detail::conv4_full_impl, 1>;

/*!
 * \brief Expression for 4D valid convolution
 */
template <typename T>
using conv4_valid_flipped_expr = basic_conv_expr<T, 4, conv_type::VALID, detail::conv4_valid_flipped_impl, 1>;

/*!
 * \brief Expression for 4D valid convolution
 */
template <typename T>
using conv4_full_flipped_expr = basic_conv_expr<T, 4, conv_type::FULL, detail::conv4_full_flipped_impl, 1>;

/*!
 * \brief Expression for 2D valid convolution, with multiple kernels
 */
template <typename T>
using conv2_valid_multi_expr = basic_conv_expr<T, 2, conv_type::VALID_MULTI, detail::conv2_valid_multi_impl>;

/*!
 * \brief Expression for 2D valid convolution, with multiple flipped kernels
 */
template <typename T>
using conv2_valid_multi_flipped_expr = basic_conv_expr<T, 2, conv_type::VALID_MULTI, detail::conv2_valid_multi_flipped_impl>;

/*!
 * \brief Expression for 2D same convolution, with multiple kernels
 */
template <typename T>
using conv2_same_multi_expr = basic_conv_expr<T, 2, conv_type::SAME_MULTI, detail::conv2_same_multi_impl>;

/*!
 * \brief Expression for 2D same convolution, with multiple flipped kernels
 */
template <typename T>
using conv2_same_multi_flipped_expr = basic_conv_expr<T, 2, conv_type::SAME_MULTI, detail::conv2_same_multi_flipped_impl>;

/*!
 * \brief Expression for 2D full convolution, with multiple kernels
 */
template <typename T>
using conv2_full_multi_expr = basic_conv_expr<T, 2, conv_type::FULL_MULTI, detail::conv2_full_multi_impl>;

/*!
 * \brief Expression for 2D full convolution, with multiple flipped kernels
 */
template <typename T>
using conv2_full_multi_flipped_expr = basic_conv_expr<T, 2, conv_type::FULL_MULTI, detail::conv2_full_multi_flipped_impl>;

/*!
 * \brief Expression for 2D same convolution
 */
template <typename T>
using conv2_same_expr = basic_conv_expr<T, 2, conv_type::SAME, detail::conv2_same_impl>;

/*!
 * \brief Expression for 2D same convolution
 */
template <typename T>
using conv2_same_flipped_expr = basic_conv_expr<T, 2, conv_type::SAME, detail::conv2_same_flipped_impl>;

/*!
 * \brief Expression for 2D full convolution
 */
template <typename T>
using conv2_full_expr = basic_conv_expr<T, 2, conv_type::FULL, detail::conv2_full_impl>;

/*!
 * \brief Expression for 2D full convolution
 */
template <typename T>
using conv2_full_flipped_expr = basic_conv_expr<T, 2, conv_type::FULL, detail::conv2_full_flipped_impl>;

//>2D convolutions

/*!
 * \brief Expression for >2D valid convolution
 */
template <typename T, std::size_t D>
using conv_deep_valid_expr = basic_conv_expr<T, D, conv_type::VALID, detail::conv_deep_valid_impl>;

/*!
 * \brief Expression for >2D same convolution
 */
template <typename T, std::size_t D>
using conv_deep_same_expr = basic_conv_expr<T, D, conv_type::SAME, detail::conv_deep_same_impl>;

/*!
 * \brief Expression for >2D full convolution
 */
template <typename T, std::size_t D>
using conv_deep_full_expr = basic_conv_expr<T, D, conv_type::FULL, detail::conv_deep_full_impl>;

} //end of namespace etl
<commit_msg>Cleanup<commit_after>//=======================================================================
// Copyright (c) 2014-2016 Baptiste Wicht
// Distributed under the terms of the MIT License.
// (See accompanying file LICENSE or copy at
//  http://opensource.org/licenses/MIT)
//=======================================================================

#pragma once

//Get the implementations
#include "etl/impl/conv.hpp"

namespace etl {

/*!
 * \brief A basic configurable convolution expr
 * \tparam T The value type
 * \tparam D The dimensions of convolution
 * \tparam TT The convolution type
 * \tparam Impl The implementation class
 */
template <typename T, std::size_t D, conv_type TT, typename Impl>
struct basic_conv_expr : impl_expr<basic_conv_expr<T, D, TT, Impl>> {
    static_assert(D > 0, "0D convolution is not valid");

    using value_type = T;                                   ///< The type of value of the expression
    using this_type  = basic_conv_expr<T, D, TT, Impl>; ///< The type of this expression

    static constexpr const bool is_gpu = is_cufft_enabled || is_cudnn_enabled; ///< Indicates if the expression runs on GPU

    /*!
     * \brief The result type for given sub types
     * \tparam A The left hand side epxpression type
     * \tparam B The right hand side epxpression type
     */
    template <typename A, typename B>
    using result_type = detail::expr_result_t<this_type, A, B>;

    /*!
     * \brief Validate the convolutiond dimensions
     * \param a The input matrix
     * \þaram b The kernel matrix
     * \þaram c The output matrix
     */
    template <typename A, typename B, typename C, cpp_enable_if(all_fast<A,B,C>::value)>
    static void check(const A& a, const B& b, const C& c) {
        cpp_unused(a);
        cpp_unused(b);
        cpp_unused(c);

        Impl::template check<A,B,C>();
    }

    /*!
     * \brief Validate the convolutiond dimensions
     * \param a The input matrix
     * \þaram b The kernel matrix
     * \þaram c The output matrix
     */
    template <typename A, typename B, typename C, cpp_disable_if(all_fast<A,B,C>::value)>
    static void check(const A& a, const B& b, const C& c) {
        Impl::check(a, b, c);
    }

    /*!
     * \brief Apply the expression
     * \param a The left hand side
     * \param b The right hand side
     * \param c The expression where to store the results
     */
    template <typename A, typename B, typename C>
    static void apply(A&& a, B&& b, C&& c) {
        static_assert(all_etl_expr<A, B, C>::value, "Convolution only supported for ETL expressions");

        check(a, b, c);

        Impl::apply(
            make_temporary(std::forward<A>(a)),
            make_temporary(std::forward<B>(b)),
            std::forward<C>(c));
    }

    /*!
     * \brief Returns a textual representation of the operation
     * \return a textual representation of the operation
     */
    static constexpr const char* desc() noexcept {
        return Impl::desc();
    }

    /*!
     * \brief Returns the DDth dimension of the expression
     * \return the DDth dimension of the expression
     */
    template <typename A, typename B, std::size_t DD>
    static constexpr std::size_t dim() {
        return Impl::template dim<DD, A, B>();
    }

    /*!
     * \brief Returns the dth dimension of the expression
     * \param a The left hand side
     * \param b The right hand side
     * \param d The dimension to get
     * \return the dth dimension of the expression
     */
    template <typename A, typename B>
    static std::size_t dim(const A& a, const B& b, std::size_t d) {
        return Impl::dim(d, a, b);
    }

    /*!
     * \brief Returns the size of the expression
     * \param a The left hand side
     * \param b The right hand side
     * \return the size of the expression
     */
    template <typename A, typename B>
    static std::size_t size(const A& a, const B& b) {
        std::size_t acc = 1;
        for (std::size_t i = 0; i < dimensions(); ++i) {
            acc *= this_type::dim(a, b, i);
        }
        return acc;
    }

    /*!
     * \brief Returns the multiplicative sum of the dimensions at the given indices
     * \return the multiplicative sum of the dimensions at the given indices
     */
    template <typename A, typename B, std::size_t... I>
    static constexpr std::size_t size_mul(const std::index_sequence<I...>& /*seq*/) {
        return mul_all<this_type::dim<A, B, I>()...>::value;
    }

    /*!
     * \brief Returns the size of the expression
     * \return the size of the expression
     */
    template <typename A, typename B>
    static constexpr std::size_t size() {
        return size_mul<A, B>(std::make_index_sequence<dimensions()>());
    }

    /*!
     * \brief Returns the storage order of the expression.
     * \return the storage order of the expression
     */
    template <typename A, typename B>
    static constexpr etl::order order() {
        return etl::order::RowMajor;
    }

    /*!
     * \brief Returns the number of dimensions of the expression
     * \return the number of dimensions of the expression
     */
    static constexpr std::size_t dimensions() {
        return D;
    }
};

//1D convolution

/*!
 * \brief Expression for 1D valid convolution
 */
template <typename T>
using conv1_valid_expr = basic_conv_expr<T, 1, conv_type::VALID, detail::conv1_valid_impl>;

/*!
 * \brief Expression for 1D same convolution
 */
template <typename T>
using conv1_same_expr = basic_conv_expr<T, 1, conv_type::SAME, detail::conv1_same_impl>;

/*!
 * \brief Expression for 1D full convolution
 */
template <typename T>
using conv1_full_expr = basic_conv_expr<T, 1, conv_type::FULL, detail::conv1_full_impl>;

//2D convolutions

/*!
 * \brief Expression for 2D valid convolution
 */
template<typename T, size_t S1 = 0, size_t S2 = 0, size_t P1 = 0, size_t P2 = 0>
using conv2_valid_expr = basic_conv_expr<T, 2, conv_type::VALID, detail::conv2_valid_impl<S1, S2, P1, P2>>;

/*!
 * \brief Expression for 2D valid convolution
 */
template<typename T, size_t S1 = 0, size_t S2 = 0, size_t P1 = 0, size_t P2 = 0>
using conv2_valid_flipped_expr = basic_conv_expr<T, 2, conv_type::VALID, detail::conv2_valid_flipped_impl<S1, S2, P1, P2>>;

/*!
 * \brief Expression for 4D valid convolution
 */
template <typename T>
using conv4_valid_expr = basic_conv_expr<T, 4, conv_type::VALID, detail::conv4_valid_impl>;

/*!
 * \brief Expression for 4D valid convolution
 */
template <typename T>
using conv4_valid_filter_expr = basic_conv_expr<T, 4, conv_type::VALID, detail::conv4_valid_filter_impl>;

/*!
 * \brief Expression for 4D valid convolution
 */
template <typename T>
using conv4_valid_filter_flipped_expr = basic_conv_expr<T, 4, conv_type::VALID, detail::conv4_valid_filter_flipped_impl>;

/*!
 * \brief Expression for 4D valid convolution
 */
template <typename T>
using conv4_full_expr = basic_conv_expr<T, 4, conv_type::FULL, detail::conv4_full_impl>;

/*!
 * \brief Expression for 4D valid convolution
 */
template <typename T>
using conv4_valid_flipped_expr = basic_conv_expr<T, 4, conv_type::VALID, detail::conv4_valid_flipped_impl>;

/*!
 * \brief Expression for 4D valid convolution
 */
template <typename T>
using conv4_full_flipped_expr = basic_conv_expr<T, 4, conv_type::FULL, detail::conv4_full_flipped_impl>;

/*!
 * \brief Expression for 2D valid convolution, with multiple kernels
 */
template <typename T>
using conv2_valid_multi_expr = basic_conv_expr<T, 3, conv_type::VALID_MULTI, detail::conv2_valid_multi_impl>;

/*!
 * \brief Expression for 2D valid convolution, with multiple flipped kernels
 */
template <typename T>
using conv2_valid_multi_flipped_expr = basic_conv_expr<T, 3, conv_type::VALID_MULTI, detail::conv2_valid_multi_flipped_impl>;

/*!
 * \brief Expression for 2D same convolution, with multiple kernels
 */
template <typename T>
using conv2_same_multi_expr = basic_conv_expr<T, 3, conv_type::SAME_MULTI, detail::conv2_same_multi_impl>;

/*!
 * \brief Expression for 2D same convolution, with multiple flipped kernels
 */
template <typename T>
using conv2_same_multi_flipped_expr = basic_conv_expr<T, 3, conv_type::SAME_MULTI, detail::conv2_same_multi_flipped_impl>;

/*!
 * \brief Expression for 2D full convolution, with multiple kernels
 */
template <typename T>
using conv2_full_multi_expr = basic_conv_expr<T, 3, conv_type::FULL_MULTI, detail::conv2_full_multi_impl>;

/*!
 * \brief Expression for 2D full convolution, with multiple flipped kernels
 */
template <typename T>
using conv2_full_multi_flipped_expr = basic_conv_expr<T, 3, conv_type::FULL_MULTI, detail::conv2_full_multi_flipped_impl>;

/*!
 * \brief Expression for 2D same convolution
 */
template <typename T>
using conv2_same_expr = basic_conv_expr<T, 2, conv_type::SAME, detail::conv2_same_impl>;

/*!
 * \brief Expression for 2D same convolution
 */
template <typename T>
using conv2_same_flipped_expr = basic_conv_expr<T, 2, conv_type::SAME, detail::conv2_same_flipped_impl>;

/*!
 * \brief Expression for 2D full convolution
 */
template <typename T>
using conv2_full_expr = basic_conv_expr<T, 2, conv_type::FULL, detail::conv2_full_impl>;

/*!
 * \brief Expression for 2D full convolution
 */
template <typename T>
using conv2_full_flipped_expr = basic_conv_expr<T, 2, conv_type::FULL, detail::conv2_full_flipped_impl>;

//>2D convolutions

/*!
 * \brief Expression for >2D valid convolution
 */
template <typename T, std::size_t D>
using conv_deep_valid_expr = basic_conv_expr<T, D, conv_type::VALID, detail::conv_deep_valid_impl>;

/*!
 * \brief Expression for >2D same convolution
 */
template <typename T, std::size_t D>
using conv_deep_same_expr = basic_conv_expr<T, D, conv_type::SAME, detail::conv_deep_same_impl>;

/*!
 * \brief Expression for >2D full convolution
 */
template <typename T, std::size_t D>
using conv_deep_full_expr = basic_conv_expr<T, D, conv_type::FULL, detail::conv_deep_full_impl>;

} //end of namespace etl
<|endoftext|>


<commit_before>/******************************************************************************
* Copyright (c) 2011, Michael P. Gerlek (mpg@flaxen.com)
*
* 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 Hobu, Inc. or Flaxen Geo Consulting 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 "AppSupport.hpp"

#include <boost/filesystem.hpp>
#include <boost/algorithm/string.hpp>

#include <pdal/FileUtils.hpp>
#include <pdal/Utils.hpp>
#include <pdal/PipelineManager.hpp>
#include <pdal/PipelineReader.hpp>
#include <pdal/StageFactory.hpp>

std::string AppSupport::inferReaderDriver(const std::string& filename, pdal::Options& options)
{
    std::string ext = boost::filesystem::extension(filename);

    pdal::Option& fn = options.getOptionByRef("filename");
    fn.setValue<std::string>(filename);

    // maybe this should live in StageFactory?
    std::map<std::string, std::string> drivers;
    drivers["las"] = "drivers.las.reader";
    drivers["laz"] = "drivers.las.reader";
    drivers["bin"] = "drivers.terrasolid.reader";
    drivers["qi"] = "drivers.qfit.reader";
    drivers["xml"] = "drivers.pipeline.reader";
    drivers["nitf"] = "drivers.nitf.reader";
    drivers["ntf"] = "drivers.nitf.reader";

    if (boost::algorithm::iequals(filename, "STDIN"))
    {
        return drivers["xml"];
    }

    if (ext == "") return "";
    ext = ext.substr(1, ext.length()-1);
    if (ext == "") return "";

    boost::to_lower(ext);
    std::string driver = drivers[ext];
    return driver; // will be "" if not found
}

std::string AppSupport::inferWriterDriver(const std::string& filename, pdal::Options& options)
{
    std::string ext = boost::filesystem::extension(filename);

    boost::to_lower(ext);

    if (boost::algorithm::iequals(ext,".laz"))
    {
        options.add("compression", true);
    }

    options.add<std::string>("filename", filename);

    // maybe this should live in StageFactory?
    std::map<std::string, std::string> drivers;
    drivers["las"] = "drivers.las.writer";
    drivers["laz"] = "drivers.las.writer";
    drivers["xyz"] = "drivers.text.writer";
    drivers["txt"] = "drivers.text.writer";
    drivers["pcd"] = "drivers.pcd.writer";

    if (boost::algorithm::iequals(filename, "STDOUT"))
    {
        return drivers["txt"];
    }

    if (ext == "") return drivers["txt"];
    ext = ext.substr(1, ext.length()-1);
    if (ext == "") return drivers["txt"];

    boost::to_lower(ext);
    std::string driver = drivers[ext];
    return driver; // will be "" if not found
}

pdal::Stage* AppSupport::makeReader(pdal::Options& options)
{
    const std::string inputFile = options.getValueOrThrow<std::string>("filename");

    if (!pdal::FileUtils::fileExists(inputFile))
    {
        throw app_runtime_error("file not found: " + inputFile);
    }

    pdal::StageFactory factory;
    std::string driver = factory.inferReaderDriver(inputFile, options);
    if (driver == "")
    {
        throw app_runtime_error("Cannot determine input file type of " + inputFile);
    }

    pdal::Stage* stage = factory.createReader(driver, options);
    if (!stage)
    {
        throw app_runtime_error("reader creation failed");
    }

    return stage;
}

pdal::Writer* AppSupport::makeWriter(pdal::Options& options, pdal::Stage& stage)
{
    const std::string outputFile = options.getValueOrThrow<std::string>("filename");

    pdal::StageFactory factory;
    std::string driver = factory.inferWriterDriver(outputFile, options);
    if (driver == "")
    {
        throw app_runtime_error("Cannot determine output file type of " + outputFile);
    }

    pdal::Writer* writer = factory.createWriter(driver, stage, options);
    if (!writer)
    {
        throw app_runtime_error("writer creation failed");
    }

    return writer;
}

PercentageCallback::PercentageCallback(double major, double minor)
    : m_lastMajorPerc(-1 * major)
    , m_lastMinorPerc(-1 * minor)
    , m_done(false)
{
    return;
}

void PercentageCallback::callback()
{
    if (m_done) return;

    double currPerc = getPercentComplete();

    if (pdal::Utils::compare_distance<double>(currPerc, 100.0))
    {
        std::cerr << "100" << std::endl;
        m_done = true;
    }
    else if (currPerc >= m_lastMajorPerc + 10.0)
    {
        std::cerr << (int)currPerc << std::flush;
        m_lastMajorPerc = currPerc;
        m_lastMinorPerc = currPerc;
    }
    else if (currPerc >= m_lastMinorPerc + 2.0)
    {
        std::cerr << '.' << std::flush;
        m_lastMinorPerc = currPerc;
    }

    return;
}

ShellScriptCallback::ShellScriptCallback(std::vector<std::string> const& command)
{
    double major(10.0);
    double minor(2.0);

    if (!command.size())
    {
        m_command = "";
    }
    else
    {
        m_command = command[0];

        if (command.size() == 3)
        {
            major = boost::lexical_cast<double>(command[1]);
            minor = boost::lexical_cast<double>(command[2]);
        }
        else if (command.size() == 2)
        {
            major = boost::lexical_cast<double>(command[1]);
        }
    }

    PercentageCallback(major, minor);

    return;
}

void ShellScriptCallback::callback()
{
    if (m_done) return;

    double currPerc = getPercentComplete();

    if (pdal::Utils::compare_distance<double>(currPerc, 100.0))
    {
        m_done = true;
    }
    else if (currPerc >= m_lastMajorPerc + 10.0)
    {
        std::string output;
        int stat = pdal::Utils::run_shell_command(m_command, output);
    }
    else if (currPerc >= m_lastMinorPerc + 2.0)
    {
        m_lastMinorPerc = currPerc;
    }

    return;
}

HeartbeatCallback::HeartbeatCallback()
{
    return;
}

void HeartbeatCallback::callback()
{
    std::cerr << '.';

    return;
}
<commit_msg>rename variables<commit_after>/******************************************************************************
* Copyright (c) 2011, Michael P. Gerlek (mpg@flaxen.com)
*
* 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 Hobu, Inc. or Flaxen Geo Consulting 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 "AppSupport.hpp"

#include <boost/filesystem.hpp>
#include <boost/algorithm/string.hpp>

#include <pdal/FileUtils.hpp>
#include <pdal/Utils.hpp>
#include <pdal/PipelineManager.hpp>
#include <pdal/PipelineReader.hpp>
#include <pdal/StageFactory.hpp>

std::string AppSupport::inferReaderDriver(const std::string& filename, pdal::Options& options)
{
    std::string ext = boost::filesystem::extension(filename);

    pdal::Option& fn = options.getOptionByRef("filename");
    fn.setValue<std::string>(filename);

    // maybe this should live in StageFactory?
    std::map<std::string, std::string> drivers;
    drivers["las"] = "drivers.las.reader";
    drivers["laz"] = "drivers.las.reader";
    drivers["bin"] = "drivers.terrasolid.reader";
    drivers["qi"] = "drivers.qfit.reader";
    drivers["xml"] = "drivers.pipeline.reader";
    drivers["nitf"] = "drivers.nitf.reader";
    drivers["ntf"] = "drivers.nitf.reader";

    if (boost::algorithm::iequals(filename, "STDIN"))
    {
        return drivers["xml"];
    }

    if (ext == "") return "";
    ext = ext.substr(1, ext.length()-1);
    if (ext == "") return "";

    boost::to_lower(ext);
    std::string driver = drivers[ext];
    return driver; // will be "" if not found
}

std::string AppSupport::inferWriterDriver(const std::string& filename, pdal::Options& options)
{
    std::string ext = boost::filesystem::extension(filename);

    boost::to_lower(ext);

    if (boost::algorithm::iequals(ext,".laz"))
    {
        options.add("compression", true);
    }

    options.add<std::string>("filename", filename);

    // maybe this should live in StageFactory?
    std::map<std::string, std::string> drivers;
    drivers["las"] = "drivers.las.writer";
    drivers["laz"] = "drivers.las.writer";
    drivers["xyz"] = "drivers.text.writer";
    drivers["txt"] = "drivers.text.writer";
    drivers["pcd"] = "drivers.pcd.writer";

    if (boost::algorithm::iequals(filename, "STDOUT"))
    {
        return drivers["txt"];
    }

    if (ext == "") return drivers["txt"];
    ext = ext.substr(1, ext.length()-1);
    if (ext == "") return drivers["txt"];

    boost::to_lower(ext);
    std::string driver = drivers[ext];
    return driver; // will be "" if not found
}

pdal::Stage* AppSupport::makeReader(pdal::Options& options)
{
    const std::string inputFile = options.getValueOrThrow<std::string>("filename");

    if (!pdal::FileUtils::fileExists(inputFile))
    {
        throw app_runtime_error("file not found: " + inputFile);
    }

    pdal::StageFactory factory;
    std::string driver = factory.inferReaderDriver(inputFile, options);
    if (driver == "")
    {
        throw app_runtime_error("Cannot determine input file type of " + inputFile);
    }

    pdal::Stage* stage = factory.createReader(driver, options);
    if (!stage)
    {
        throw app_runtime_error("reader creation failed");
    }

    return stage;
}

pdal::Writer* AppSupport::makeWriter(pdal::Options& options, pdal::Stage& stage)
{
    const std::string outputFile = options.getValueOrThrow<std::string>("filename");

    pdal::StageFactory factory;
    std::string driver = factory.inferWriterDriver(outputFile, options);
    if (driver == "")
    {
        throw app_runtime_error("Cannot determine output file type of " + outputFile);
    }

    pdal::Writer* writer = factory.createWriter(driver, stage, options);
    if (!writer)
    {
        throw app_runtime_error("writer creation failed");
    }

    return writer;
}

PercentageCallback::PercentageCallback(double major, double minor)
    : m_lastMajorPerc(-1 * major)
    , m_lastMinorPerc(-1 * minor)
    , m_done(false)
{
    return;
}

void PercentageCallback::callback()
{
    if (m_done) return;

    double currPerc = getPercentComplete();

    if (pdal::Utils::compare_distance<double>(currPerc, 100.0))
    {
        std::cerr << "100" << std::endl;
        m_done = true;
    }
    else if (currPerc >= m_lastMajorPerc + 10.0)
    {
        std::cerr << (int)currPerc << std::flush;
        m_lastMajorPerc = currPerc;
        m_lastMinorPerc = currPerc;
    }
    else if (currPerc >= m_lastMinorPerc + 2.0)
    {
        std::cerr << '.' << std::flush;
        m_lastMinorPerc = currPerc;
    }

    return;
}

ShellScriptCallback::ShellScriptCallback(std::vector<std::string> const& command)
{
    double major_tick(10.0);
    double minor_tick(2.0);

    if (!command.size())
    {
        m_command = "";
    }
    else
    {
        m_command = command[0];

        if (command.size() == 3)
        {
            major_tick = boost::lexical_cast<double>(command[1]);
            minor_tick = boost::lexical_cast<double>(command[2]);
        }
        else if (command.size() == 2)
        {
            major_tick = boost::lexical_cast<double>(command[1]);
        }
    }

    PercentageCallback(major_tick, minor_tick);

    return;
}

void ShellScriptCallback::callback()
{
    if (m_done) return;

    double currPerc = getPercentComplete();

    if (pdal::Utils::compare_distance<double>(currPerc, 100.0))
    {
        m_done = true;
    }
    else if (currPerc >= m_lastMajorPerc + 10.0)
    {
        std::string output;
        int stat = pdal::Utils::run_shell_command(m_command, output);
    }
    else if (currPerc >= m_lastMinorPerc + 2.0)
    {
        m_lastMinorPerc = currPerc;
    }

    return;
}

HeartbeatCallback::HeartbeatCallback()
{
    return;
}

void HeartbeatCallback::callback()
{
    std::cerr << '.';

    return;
}
<|endoftext|>


<commit_before>/*======================================================================
----------------------------------------------------------------------*/
/**
 * @file		iutest_port_c.inl
 * @brief		iris unit portable t@C
 *
 * @author		t.sirayanagi
 * @par			copyright
 * Copyright (C) 2012-2014, Takazumi Shirayanagi\n
 * This software is released under the new BSD License,
 * see LICENSE
*/
/*----------------------------------------------------------------------
======================================================================*/
#ifndef INCG_IRIS_IUTEST_PORT_C_INL_6D5DBD9D_C830_4415_957D_D38D69AEE35B_
#define INCG_IRIS_IUTEST_PORT_C_INL_6D5DBD9D_C830_4415_957D_D38D69AEE35B_

/* include ===========================================================*/
#include "../internal/iutest_port_c.h"

/* function ==========================================================*/

IUTEST_PRAGMA_CRT_SECURE_WARN_DISABLE_BEGIN()

IUTEST_C_INL_INLINE IUTEST_ATTRIBUTE_UNUSED_ const char * iuTestOS_GetEnv(const char* name)
{
#if defined(IUTEST_OS_WINDOWS_MOBILE) || defined(IUTEST_C_NO_GETENV)
	IUTEST_UNUSED_VAR(name);
	return NULL;
#elif defined(__BORLANDC__) || defined(__SunOS_5_8) || defined(__SunOS_5_9)
	const char* env = getenv(name);
	return (env != NULL && env[0] != '\0') ? env : NULL;
#else
	return getenv(name);
#endif
}

IUTEST_C_INL_INLINE IUTEST_ATTRIBUTE_UNUSED_ int iuTestOS_PutEnv(const char* expr)
{
#if defined(IUTEST_OS_WINDOWS_MOBILE) || defined(IUTEST_C_NO_PUTENV)
	IUTEST_UNUSED_VAR(expr);
	return -1;
#else
	return putenv((char*)expr);
#endif
}

IUTEST_C_INL_INLINE IUTEST_ATTRIBUTE_UNUSED_ iuBOOL iuTestOS_GetEnvironmentVariable(const char* name, char* value, size_t size)
{
#if defined(IUTEST_OS_WINDOWS) && !defined(IUTEST_OS_WINDOWS_MOBILE)
	if( !GetEnvironmentVariableA(name, value, size) ) return FALSE;
	return TRUE;
#else
	IUTEST_UNUSED_VAR(size);
	const char* env = iuTestOS_GetEnv(name);
	if( env == NULL ) return FALSE;
	iu_strcpy(value, env);
	return TRUE;
#endif
}

IUTEST_C_INL_INLINE IUTEST_ATTRIBUTE_UNUSED_ iuBOOL iuTestOS_GetEnvironmentInt(const char* name, int* value)
{
	char buf[128];
	iu_memset(buf, 0, sizeof(buf));
	if( value == NULL ) return FALSE;
	if( iuTestOS_GetEnvironmentVariable(name, buf, sizeof(buf)) )
	{
		*value = iuString_ToInt(buf);
		return TRUE;
	}
	return FALSE;
}

IUTEST_C_INL_INLINE IUTEST_ATTRIBUTE_UNUSED_ void iuAbort(void)
{
#if defined(IUTEST_OS_WINDOWS_MOBILE)
	DebugBreak();
	TerminateProcess(GetCurrentProcess(), 1);
#elif IUTEST_C_HAS_LIBC
	abort();
#else
	int* p = NULL;
	*p = 0;
#endif
}

IUTEST_C_INL_INLINE IUTEST_ATTRIBUTE_UNUSED_ void iuExit(int exit_code)
{
#if IUTEST_C_HAS_LIBC
	exit(exit_code);
#else
	IUTEST_UNUSED_VAR(exit_code);
	int* p = NULL;
	*p = 0;
#endif
}

IUTEST_PRAGMA_CRT_SECURE_WARN_DISABLE_END()

#if defined(IUTEST_OS_WINDOWS)

IUTEST_C_INL_INLINE IUTEST_ATTRIBUTE_UNUSED_ char* iuTestOS_AllocHResultString(HRESULT hr)
{
#if defined(IUTEST_OS_WINDOWS_MOBILE)
	return NULL;
#else
	LPSTR buf = NULL;
	FormatMessageA(
		FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
		NULL,
		hr,
		MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), /* ftHg [U[ */
		(LPSTR)&buf,
		0,
		NULL );
	return buf;
#endif
}

static IUTEST_ATTRIBUTE_UNUSED_ void iuTestOS_FreeHResultString(char* ptr)
{
	LocalFree(ptr);
}

#endif

#endif
<commit_msg>update r600<commit_after>/*======================================================================
----------------------------------------------------------------------*/
/**
 * @file		iutest_port_c.inl
 * @brief		iris unit portable t@C
 *
 * @author		t.sirayanagi
 * @par			copyright
 * Copyright (C) 2012-2014, Takazumi Shirayanagi\n
 * This software is released under the new BSD License,
 * see LICENSE
*/
/*----------------------------------------------------------------------
======================================================================*/
#ifndef INCG_IRIS_IUTEST_PORT_C_INL_6D5DBD9D_C830_4415_957D_D38D69AEE35B_
#define INCG_IRIS_IUTEST_PORT_C_INL_6D5DBD9D_C830_4415_957D_D38D69AEE35B_

/* include ===========================================================*/
#include "../internal/iutest_port_c.h"

/* function ==========================================================*/

IUTEST_PRAGMA_CRT_SECURE_WARN_DISABLE_BEGIN()

IUTEST_C_INL_INLINE IUTEST_ATTRIBUTE_UNUSED_ const char * iuTestOS_GetEnv(const char* name)
{
#if defined(IUTEST_OS_WINDOWS_MOBILE) || defined(IUTEST_C_NO_GETENV)
	IUTEST_UNUSED_VAR(name);
	return NULL;
#elif defined(__BORLANDC__) || defined(__SunOS_5_8) || defined(__SunOS_5_9)
	const char* env = getenv(name);
	return (env != NULL && env[0] != '\0') ? env : NULL;
#else
	return getenv(name);
#endif
}

IUTEST_C_INL_INLINE IUTEST_ATTRIBUTE_UNUSED_ int iuTestOS_PutEnv(const char* expr)
{
#if defined(IUTEST_OS_WINDOWS_MOBILE) || defined(IUTEST_C_NO_PUTENV)
	IUTEST_UNUSED_VAR(expr);
	return -1;
#else
	return putenv((char*)expr);
#endif
}

IUTEST_C_INL_INLINE IUTEST_ATTRIBUTE_UNUSED_ iuBOOL iuTestOS_GetEnvironmentVariable(const char* name, char* value, size_t size)
{
#if defined(IUTEST_OS_WINDOWS) && !defined(IUTEST_OS_WINDOWS_MOBILE)
	if( !GetEnvironmentVariableA(name, value, size) ) return FALSE;
	return TRUE;
#else
	IUTEST_UNUSED_VAR(size);
	const char* env = iuTestOS_GetEnv(name);
	if( env == NULL ) return FALSE;
	iu_strcpy(value, env);
	return TRUE;
#endif
}

IUTEST_C_INL_INLINE IUTEST_ATTRIBUTE_UNUSED_ iuBOOL iuTestOS_GetEnvironmentInt(const char* name, int* value)
{
	char buf[128];
	iu_memset(buf, 0, sizeof(buf));
	if( value == NULL ) return FALSE;
	if( iuTestOS_GetEnvironmentVariable(name, buf, sizeof(buf)) )
	{
		*value = iuString_ToInt(buf);
		return TRUE;
	}
	return FALSE;
}

IUTEST_C_INL_INLINE IUTEST_ATTRIBUTE_UNUSED_ void iuAbort(void)
{
#if defined(IUTEST_OS_WINDOWS_MOBILE)
	DebugBreak();
	TerminateProcess(GetCurrentProcess(), 1);
#elif IUTEST_C_HAS_LIBC
	abort();
#else
	int* p = NULL;
	*p = 0;
#endif
}

IUTEST_C_INL_INLINE IUTEST_ATTRIBUTE_UNUSED_ void iuExit(int exit_code)
{
#if IUTEST_C_HAS_LIBC
	exit(exit_code);
#else
	IUTEST_UNUSED_VAR(exit_code);
	int* p = NULL;
	*p = 0;
#endif
}

IUTEST_PRAGMA_CRT_SECURE_WARN_DISABLE_END()

#if defined(IUTEST_OS_WINDOWS)

IUTEST_C_INL_INLINE IUTEST_ATTRIBUTE_UNUSED_ char* iuTestOS_AllocHResultString(HRESULT hr)
{
#if defined(IUTEST_OS_WINDOWS_MOBILE)
	return NULL;
#else
	LPSTR buf = NULL;
	FormatMessageA(
		FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
		NULL,
		hr,
		MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), /* ftHg [U[ */
		(LPSTR)&buf,
		0,
		NULL );
	return buf;
#endif
}

IUTEST_C_INL_INLINE IUTEST_ATTRIBUTE_UNUSED_ void iuTestOS_FreeHResultString(char* ptr)
{
	LocalFree(ptr);
}

#endif

#endif
<|endoftext|>


<commit_before><commit_msg>Fix some composite matching bugs<commit_after><|endoftext|>


<commit_before>/** \brief Utility for deleting partial or entire MARC records based on an input list.
 *  \author Dr. Johannes Ruscheinski (johannes.ruscheinski@uni-tuebingen.de)
 *
 *  \copyright 2015 Universitätsbiblothek Tübingen.  All rights reserved.
 *
 *  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, see <http://www.gnu.org/licenses/>.
*/
#include <algorithm>
#include <iostream>
#include <stdexcept>
#include <unordered_set>
#include <vector>
#include <cstdio>
#include <cstdlib>
#include "MarcUtil.h"
#include "StringUtil.h"
#include "Subfields.h"
#include "util.h"

static void Usage() __attribute__((noreturn));

static void Usage() {
    std::cerr << "Usage: " << progname << " deletion_list input_marc output_marc\n";
    std::exit(EXIT_FAILURE);
}

void ExtractDeletionIds(FILE * const deletion_list, std::unordered_set<std::string> * const title_deletion_ids,
			std::unordered_set<std::string> * const local_deletion_ids)
{
    char line[100];
    while (std::fgets(line, sizeof(line), deletion_list) != NULL) {
	if (std::strlen(line) < 13)
	    Error("short line in deletion list file: \"" + std::string(line) + "\"!");
	if (line[11] == 'A')
	    title_deletion_ids->insert(line + 12);
	else if (line[11] == '9')
	    local_deletion_ids->insert(line + 12);
    }

    std::fclose(deletion_list);
}

int MatchLocalID(const std::unordered_set<std::string> &local_ids, const std::vector<DirectoryEntry> &dir_entries,
		 const std::vector<std::string> &field_data)
{
    for (size_t i(0); i < dir_entries.size(); ++i) {
	if (dir_entries[i].getTag() != "LOK")
	    continue;

	const Subfields subfields(field_data[i]);
	if (not subfields.hasSubfield('0'))
	    continue;

	const std::string subfield_contents(subfields.getFirstSubfieldValue('0'));
	if (not StringUtil::StartsWith(subfield_contents, "001 ")
	    or local_ids.find(subfield_contents.substr(4)) == local_ids.end())
	    continue;

	return i;
    }

    return -1;
}

class MatchTag {
    const std::string tag_to_match_;
public:
    explicit MatchTag(const std::string &tag_to_match): tag_to_match_(tag_to_match) { }
    bool operator()(const DirectoryEntry &dir_entry) const { return dir_entry.getTag() == tag_to_match_; }
};

void ProcessRecords(const std::unordered_set<std::string> &title_deletion_ids,
		    const std::unordered_set<std::string> &local_deletion_ids, FILE * const input,
		    FILE * const output)
{
    Leader *raw_leader;
    std::vector<DirectoryEntry> dir_entries;
    std::vector<std::string> field_data;
    std::string err_msg;
    unsigned total_record_count(0), deleted_record_count(0), modified_record_count(0);

    while (MarcUtil::ReadNextRecord(input, &raw_leader, &dir_entries, &field_data, &err_msg)) {
	++total_record_count;

	if (dir_entries[0].getTag() != "001")
	    Error("First field is not \"001\"!");

	ssize_t start_local_match;
	if (title_deletion_ids.find(field_data[0]) != title_deletion_ids.end()) {
	    MarcUtil::ComposeAndWriteRecord(output, dir_entries, field_data, raw_leader);

	    bool modified(false);
	    while ((start_local_match = MatchLocalID(local_deletion_ids, dir_entries, field_data)) != -1) {
		// We now expect a field "000" before the current "001" field:
		--start_local_match;
		if (start_local_match <= 0)
		    Error("weird data structure (1)!");
		const Subfields subfields(field_data[start_local_match]);
		if (not subfields.hasSubfield('0')
		    or StringUtil::StartsWith(subfields.getFirstSubfieldValue('0'), "000 "))
		    Error("missing or empty local field \"000\"!");

		// Now we need to find the index one past the end of the local record.  This would
		// be either the "000" field of the next local record or one past the end of the overall
		// MARC record.
		bool found_next_000(false);
		size_t end_local_match(start_local_match + 2);
		while (end_local_match < field_data.size()) {
		    const Subfields subfields(field_data[end_local_match]);
		    if (not subfields.hasSubfield('0'))
			Error("weird data (2)!");
		    if (StringUtil::StartsWith(subfields.getFirstSubfieldValue('0'), "000 ")) {
			found_next_000 = true;
			break;
		    }

		    ++end_local_match;
		}
		if (not found_next_000)
		    ++end_local_match;

		// Throw away the matched local data set:
		dir_entries.erase(dir_entries.begin() + start_local_match, dir_entries.begin() + end_local_match);

		modified = true;
	    }

	    if (not modified)
		MarcUtil::ComposeAndWriteRecord(output, dir_entries, field_data, raw_leader);
	    else {
		// Only keep records that still have at least one "LOK" tag:
		if (std::find_if(dir_entries.cbegin(), dir_entries.cend(), MatchTag("LOK")) == dir_entries.cend())
		    ++deleted_record_count;
		else {
		    ++modified_record_count;
		    MarcUtil::ComposeAndWriteRecord(output, dir_entries, field_data, raw_leader);
		}
	    }
	} else {
	    ++deleted_record_count;
	    std::cout << "Deleted record with ID " << field_data[0] << '\n';
	}
    }

    if (not err_msg.empty())
	Error(err_msg);
    std::cerr << "Read " << total_record_count << " records.\n";
    std::cerr << "Deleted " << deleted_record_count << " records.\n";
    std::cerr << "Modified " << modified_record_count << " records.\n";

    std::fclose(input);
    std::fclose(output);
}

int main(int argc, char *argv[]) {
    progname = argv[0];

    if (argc != 4)
	Usage();

    const std::string deletion_list_filename(argv[1]);
    FILE *deletion_list = std::fopen(deletion_list_filename.c_str(), "rb");
    if (deletion_list == NULL)
	Error("can't open \"" + deletion_list_filename + "\" for reading!");

    std::unordered_set<std::string> title_deletion_ids, local_deletion_ids;
    ExtractDeletionIds(deletion_list, &title_deletion_ids, &local_deletion_ids);

    const std::string marc_input_filename(argv[2]);
    FILE *marc_input = std::fopen(marc_input_filename.c_str(), "rb");
    if (marc_input == NULL)
	Error("can't open \"" + marc_input_filename + "\" for reading!");

    const std::string marc_output_filename(argv[3]);
    FILE *marc_output = std::fopen(marc_output_filename.c_str(), "wb");
    if (marc_output == NULL)
	Error("can't open \"" + marc_output_filename + "\" for writing!");

    try {
	ProcessRecords(title_deletion_ids, local_deletion_ids, marc_input, marc_output);
    } catch (const std::exception &e) {
	Error("Caught exception: " + std::string(e.what()));
    }
}
<commit_msg>Fixed a variety of bugs after I was able to test this with actual data.<commit_after>/** \brief Utility for deleting partial or entire MARC records based on an input list.
 *  \author Dr. Johannes Ruscheinski (johannes.ruscheinski@uni-tuebingen.de)
 *
 *  \copyright 2015 Universitätsbiblothek Tübingen.  All rights reserved.
 *
 *  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, see <http://www.gnu.org/licenses/>.
*/
#include <algorithm>
#include <iostream>
#include <stdexcept>
#include <unordered_set>
#include <vector>
#include <cstdio>
#include <cstdlib>
#include "MarcUtil.h"
#include "StringUtil.h"
#include "Subfields.h"
#include "util.h"

static void Usage() __attribute__((noreturn));

static void Usage() {
    std::cerr << "Usage: " << progname << " deletion_list input_marc output_marc\n";
    std::exit(EXIT_FAILURE);
}

void ExtractDeletionIds(FILE * const deletion_list, std::unordered_set<std::string> * const title_deletion_ids,
			std::unordered_set<std::string> * const local_deletion_ids)
{
    unsigned line_no(0);
    char line[100];
    while (std::fgets(line, sizeof(line), deletion_list) != NULL) {
	++line_no;
	size_t line_length(std::strlen(line));
	if (line_length < 13)
	    Error("short line in deletion list file: \"" + std::string(line) + "\"!");
	if (line[line_length - 1] == '\n') {
	    line[line_length - 1] = '\0';
	    --line_length;
	}
	if (line[11] == 'A')
	    title_deletion_ids->insert(line + 12); // extract PPN
	else if (line[11] == '9') {
	    if (line_length != 25)
		Error("unexpected line length for local entry on line " + std::to_string(line_no) + "!");
	    local_deletion_ids->insert(std::string(line).substr(12, 9)); // extract ELN
	}
    }

    std::fclose(deletion_list);
}

int MatchLocalID(const std::unordered_set<std::string> &local_ids, const std::vector<DirectoryEntry> &dir_entries,
		 const std::vector<std::string> &field_data)
{
    for (size_t i(0); i < dir_entries.size(); ++i) {
	if (dir_entries[i].getTag() != "LOK")
	    continue;

	const Subfields subfields(field_data[i]);
	if (not subfields.hasSubfield('0'))
	    continue;

	const std::string subfield_contents(subfields.getFirstSubfieldValue('0'));
	if (not StringUtil::StartsWith(subfield_contents, "001 ")
	    or local_ids.find(subfield_contents.substr(4)) == local_ids.end())
	    continue;

	return i;
    }

    return -1;
}

class MatchTag {
    const std::string tag_to_match_;
public:
    explicit MatchTag(const std::string &tag_to_match): tag_to_match_(tag_to_match) { }
    bool operator()(const DirectoryEntry &dir_entry) const { return dir_entry.getTag() == tag_to_match_; }
};

void ProcessRecords(const std::unordered_set<std::string> &title_deletion_ids,
		    const std::unordered_set<std::string> &local_deletion_ids, FILE * const input,
		    FILE * const output)
{
    Leader *raw_leader;
    std::vector<DirectoryEntry> dir_entries;
    std::vector<std::string> field_data;
    std::string err_msg;
    unsigned total_record_count(0), deleted_record_count(0), modified_record_count(0);

    while (MarcUtil::ReadNextRecord(input, &raw_leader, &dir_entries, &field_data, &err_msg)) {
	++total_record_count;

	if (dir_entries[0].getTag() != "001")
	    Error("First field is not \"001\"!");

	ssize_t start_local_match;
	if (title_deletion_ids.find(field_data[0]) != title_deletion_ids.end()) {
	    ++deleted_record_count;
	    std::cout << "Deleted record with ID " << field_data[0] << '\n';
	} else { // Look for local data sets that may need to be deleted.
	    MarcUtil::ComposeAndWriteRecord(output, dir_entries, field_data, raw_leader);

	    bool modified(false);
	    while ((start_local_match = MatchLocalID(local_deletion_ids, dir_entries, field_data)) != -1) {
		// We now expect a field "000" before the current "001" field:
		--start_local_match;
		if (start_local_match <= 0)
		    Error("weird data structure (1)!");
		const Subfields subfields(field_data[start_local_match]);
		if (not subfields.hasSubfield('0')
		    or not StringUtil::StartsWith(subfields.getFirstSubfieldValue('0'), "000 "))
		    Error("missing or empty local field \"000\"! (EPN: "
			  + field_data[start_local_match + 1].substr(8) + ", PPN: " + field_data[0] + ")");

		// Now we need to find the index one past the end of the local record.  This would
		// be either the "000" field of the next local record or one past the end of the overall
		// MARC record.
		bool found_next_000(false);
		size_t end_local_match(start_local_match + 2);
		while (end_local_match < field_data.size()) {
		    const Subfields subfields(field_data[end_local_match]);
		    if (not subfields.hasSubfield('0'))
			Error("weird data (2)!");
		    if (StringUtil::StartsWith(subfields.getFirstSubfieldValue('0'), "000 ")) {
			found_next_000 = true;
			break;
		    }

		    ++end_local_match;
		}
		if (not found_next_000)
		    ++end_local_match;

		// Throw away the matched local data set:
		dir_entries.erase(dir_entries.begin() + start_local_match, dir_entries.begin() + end_local_match);

		modified = true;
	    }

	    if (not modified)
		MarcUtil::ComposeAndWriteRecord(output, dir_entries, field_data, raw_leader);
	    else {
		// Only keep records that still have at least one "LOK" tag:
		if (std::find_if(dir_entries.cbegin(), dir_entries.cend(), MatchTag("LOK")) == dir_entries.cend())
		    ++deleted_record_count;
		else {
		    ++modified_record_count;
		    MarcUtil::ComposeAndWriteRecord(output, dir_entries, field_data, raw_leader);
		}
	    }
	}
    }

    if (not err_msg.empty())
	Error(err_msg);
    std::cerr << "Read " << total_record_count << " records.\n";
    std::cerr << "Deleted " << deleted_record_count << " records.\n";
    std::cerr << "Modified " << modified_record_count << " records.\n";

    std::fclose(input);
    std::fclose(output);
}

int main(int argc, char *argv[]) {
    progname = argv[0];

    if (argc != 4)
	Usage();

    const std::string deletion_list_filename(argv[1]);
    FILE *deletion_list = std::fopen(deletion_list_filename.c_str(), "rb");
    if (deletion_list == NULL)
	Error("can't open \"" + deletion_list_filename + "\" for reading!");

    std::unordered_set<std::string> title_deletion_ids, local_deletion_ids;
    ExtractDeletionIds(deletion_list, &title_deletion_ids, &local_deletion_ids);

    const std::string marc_input_filename(argv[2]);
    FILE *marc_input = std::fopen(marc_input_filename.c_str(), "rb");
    if (marc_input == NULL)
	Error("can't open \"" + marc_input_filename + "\" for reading!");

    const std::string marc_output_filename(argv[3]);
    FILE *marc_output = std::fopen(marc_output_filename.c_str(), "wb");
    if (marc_output == NULL)
	Error("can't open \"" + marc_output_filename + "\" for writing!");

    try {
	ProcessRecords(title_deletion_ids, local_deletion_ids, marc_input, marc_output);
    } catch (const std::exception &e) {
	Error("Caught exception: " + std::string(e.what()));
    }
}
<|endoftext|>


<commit_before>/* Copyright 2013 Yahoo! Inc.                                         */
/* See LICENSE in the root of the distribution for licensing details. */

#ifndef DONT_MULTI_INCLUDE_MDBM_UTIL_HH
#define DONT_MULTI_INCLUDE_MDBM_UTIL_HH

#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <stdint.h>
#include <pthread.h>

#include <execinfo.h>
extern "C" {
  /* Obtain a backtrace and print it to stdout. */
  inline void print_trace(void) {
    void *array[10];
    size_t size = backtrace (array, 10);
    char **strings = backtrace_symbols (array, size);
    printf ("Obtained %d stack frames.\n", (int)size);
    for (size_t i = 0; i < size; i++) { fprintf (stderr, "  @-->%s\n", strings[i]); }
    free (strings);
  }

  // Intel (and later model AMD) Fetch Time-StampCounter
  // WANRING:  This value may be affected by speedstep and may vary randomly across cores.
  __inline__ uint64_t rdtsc(void) {
    uint32_t lo, hi;
    __asm__ __volatile__ (      // serialize
    "xorl %%eax,%%eax \n        cpuid"
    ::: "%rax", "%rbx", "%rcx", "%rdx");
    /* We cannot use "=A", since this would use %rax on x86_64 and return only the lower 32bits of the TSC */
    __asm__ __volatile__ ("rdtsc" : "=a" (lo), "=d" (hi));
    return (uint64_t)hi << 32 | lo;
  }
}

#include <map>
#include <string>

class AccumTSCRecord {
public:
  volatile uint64_t total;
  volatile uint64_t count;
  std::string       label;

  AccumTSCRecord() : total(0), count(0), label("<unknown>") {}
};

class AccumTSC {
public:
  typedef std::map<std::string, AccumTSCRecord*> AccumulatorMap;
  AccumulatorMap records;
  AccumTSC() { }
  ~AccumTSC() {
    // G++ seems to be creating and destroying these with great abandon, even though
    // the macro that makes them declares them (function) static
    AccumulatorMap::iterator iter;
    for (iter = records.begin(); iter != records.end(); ++iter) {
      AccumTSCRecord* rec = iter->second;
      fprintf(stderr, "TSC pid:%d [%-29s] Time % 12lld for % 9lld avg:% 7lld\n", getpid(), rec->label.c_str(), (long long)rec->total, (long long)rec->count, rec->count ? ((long long)rec->total) / (long long)rec->count : 0);
    }
  }
  AccumTSCRecord* GetRecord(const char* label) {
    static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
    AccumTSCRecord *rec = NULL;
    //fprintf(stderr, "Fetching accumulator for [%s]\n", label);
    pthread_mutex_lock(&mutex);
    AccumulatorMap::iterator iter = records.find(label);
    if (iter != records.end()) {
      rec = records[label];
    } else {
      rec = new AccumTSCRecord;
      rec->label = label;
      records[label] = rec;
    }
    pthread_mutex_unlock(&mutex);
    return rec;
  }
  static void Increment(AccumTSCRecord *rec, uint64_t time) {
    __sync_fetch_and_add(&rec->count, 1);
    __sync_fetch_and_add(&rec->total, time);
    //fprintf(stderr, "Time %lld for %lld [%s]\n", (long long)total, (long long)count, label);
  }
};

static AccumTSC Accumulators;

class AutoTSC {
public:
  uint64_t        start;
  const char     *label;
  AccumTSCRecord *rec;
  AutoTSC(const char* lbl, AccumTSCRecord* rec) : rec(rec) {
    label = lbl;
    start = rdtsc();
  }
  ~AutoTSC() {
    uint64_t delta = rdtsc() - start;
    Accumulators.Increment(rec, delta);
    //fprintf(stderr, "Time %lld for [%s]\n", (long long)delta, label);
  }
};

// profiling via Intel TimeStampCounters, function-static and scoped-automatic variables
#if 0
#  define AUTO_TSC(desc)                                           \
     static AccumTSCRecord* record = Accumulators.GetRecord(desc); \
     AutoTSC TSCAuto(desc, record);
#else
#  define AUTO_TSC(desc)
#endif

// branch hinting macros
#define likely(x)       __builtin_expect(!!(x), 1)
#define unlikely(x)     __builtin_expect(!!(x), 0)

// cache prefetching macros
#define prefetch(x) __builtin_prefetch(x)

//#define CHECKPOINTV(msg, ...) fprintf(stderr, "%d %s:%d::%s() "msg"\n", getpid(), __FILE__, __LINE__, __PRETTY_FUNCTION__,__VA_ARGS__);
#define CHECKPOINTV(msg, ...)

//#define TRACE_LOCKS
#define PRINT_LOCK_TRACE(msg) {                                                      \
    char buf[512];                                                                   \
    snprintf(buf, 512,                                                               \
        "rec:%p pid:%d self:" OWNER_FMT " %s count:%u owner:" OWNER_FMT " idx:%d\n", \
        rec, getpid(), get_thread_id(), msg, rec->count,                             \
        rec->owner, index);                                                          \
    fprintf(stderr, buf);                                                            \
  }

#endif /* DONT_MULTI_INCLUDE_MDBM_UTIL_HH */
<commit_msg>Fix a typo: WANRING -> WARNING<commit_after>/* Copyright 2013 Yahoo! Inc.                                         */
/* See LICENSE in the root of the distribution for licensing details. */

#ifndef DONT_MULTI_INCLUDE_MDBM_UTIL_HH
#define DONT_MULTI_INCLUDE_MDBM_UTIL_HH

#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <stdint.h>
#include <pthread.h>

#include <execinfo.h>
extern "C" {
  /* Obtain a backtrace and print it to stdout. */
  inline void print_trace(void) {
    void *array[10];
    size_t size = backtrace (array, 10);
    char **strings = backtrace_symbols (array, size);
    printf ("Obtained %d stack frames.\n", (int)size);
    for (size_t i = 0; i < size; i++) { fprintf (stderr, "  @-->%s\n", strings[i]); }
    free (strings);
  }

  // Intel (and later model AMD) Fetch Time-StampCounter
  // WARNING:  This value may be affected by speedstep and may vary randomly across cores.
  __inline__ uint64_t rdtsc(void) {
    uint32_t lo, hi;
    __asm__ __volatile__ (      // serialize
    "xorl %%eax,%%eax \n        cpuid"
    ::: "%rax", "%rbx", "%rcx", "%rdx");
    /* We cannot use "=A", since this would use %rax on x86_64 and return only the lower 32bits of the TSC */
    __asm__ __volatile__ ("rdtsc" : "=a" (lo), "=d" (hi));
    return (uint64_t)hi << 32 | lo;
  }
}

#include <map>
#include <string>

class AccumTSCRecord {
public:
  volatile uint64_t total;
  volatile uint64_t count;
  std::string       label;

  AccumTSCRecord() : total(0), count(0), label("<unknown>") {}
};

class AccumTSC {
public:
  typedef std::map<std::string, AccumTSCRecord*> AccumulatorMap;
  AccumulatorMap records;
  AccumTSC() { }
  ~AccumTSC() {
    // G++ seems to be creating and destroying these with great abandon, even though
    // the macro that makes them declares them (function) static
    AccumulatorMap::iterator iter;
    for (iter = records.begin(); iter != records.end(); ++iter) {
      AccumTSCRecord* rec = iter->second;
      fprintf(stderr, "TSC pid:%d [%-29s] Time % 12lld for % 9lld avg:% 7lld\n", getpid(), rec->label.c_str(), (long long)rec->total, (long long)rec->count, rec->count ? ((long long)rec->total) / (long long)rec->count : 0);
    }
  }
  AccumTSCRecord* GetRecord(const char* label) {
    static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
    AccumTSCRecord *rec = NULL;
    //fprintf(stderr, "Fetching accumulator for [%s]\n", label);
    pthread_mutex_lock(&mutex);
    AccumulatorMap::iterator iter = records.find(label);
    if (iter != records.end()) {
      rec = records[label];
    } else {
      rec = new AccumTSCRecord;
      rec->label = label;
      records[label] = rec;
    }
    pthread_mutex_unlock(&mutex);
    return rec;
  }
  static void Increment(AccumTSCRecord *rec, uint64_t time) {
    __sync_fetch_and_add(&rec->count, 1);
    __sync_fetch_and_add(&rec->total, time);
    //fprintf(stderr, "Time %lld for %lld [%s]\n", (long long)total, (long long)count, label);
  }
};

static AccumTSC Accumulators;

class AutoTSC {
public:
  uint64_t        start;
  const char     *label;
  AccumTSCRecord *rec;
  AutoTSC(const char* lbl, AccumTSCRecord* rec) : rec(rec) {
    label = lbl;
    start = rdtsc();
  }
  ~AutoTSC() {
    uint64_t delta = rdtsc() - start;
    Accumulators.Increment(rec, delta);
    //fprintf(stderr, "Time %lld for [%s]\n", (long long)delta, label);
  }
};

// profiling via Intel TimeStampCounters, function-static and scoped-automatic variables
#if 0
#  define AUTO_TSC(desc)                                           \
     static AccumTSCRecord* record = Accumulators.GetRecord(desc); \
     AutoTSC TSCAuto(desc, record);
#else
#  define AUTO_TSC(desc)
#endif

// branch hinting macros
#define likely(x)       __builtin_expect(!!(x), 1)
#define unlikely(x)     __builtin_expect(!!(x), 0)

// cache prefetching macros
#define prefetch(x) __builtin_prefetch(x)

//#define CHECKPOINTV(msg, ...) fprintf(stderr, "%d %s:%d::%s() "msg"\n", getpid(), __FILE__, __LINE__, __PRETTY_FUNCTION__,__VA_ARGS__);
#define CHECKPOINTV(msg, ...)

//#define TRACE_LOCKS
#define PRINT_LOCK_TRACE(msg) {                                                      \
    char buf[512];                                                                   \
    snprintf(buf, 512,                                                               \
        "rec:%p pid:%d self:" OWNER_FMT " %s count:%u owner:" OWNER_FMT " idx:%d\n", \
        rec, getpid(), get_thread_id(), msg, rec->count,                             \
        rec->owner, index);                                                          \
    fprintf(stderr, buf);                                                            \
  }

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


<commit_before>/*
 * #%L
 * %%
 * Copyright (C) 2011 - 2015 BMW Car IT GmbH
 * %%
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 * #L%
 */
#include "joynr/ClassDeserializer.h"
#include "joynr/SerializerRegistry.h"
#include "joynr/IDeserializer.h"
namespace joynr
{

/**
 * @brief deserialize not knowing the type
 * @param object
 * @return Variant
 */
Variant deserialize(IObject& o)
{
    // The object must have fields
    if (!o.hasNextField()) {
        throw std::invalid_argument("Object contains no fields");
    }

    // The first field has to contain the typename
    IField& field = o.nextField();
    if (field.name() != "_typeName") {
        throw std::invalid_argument("First field of object should be _typeName");
    }

    // Create an object of the correct type
    std::string typeName(field.value());
    std::unique_ptr<IClassDeserializer> deserializer =
            SerializerRegistry::getDeserializer(typeName);

    // Deserialize
    return deserializer->deserializeVariant(o);
}

Variant convertVariant(IValue &value)
{
    if (value.isObject()) {
        return deserialize(value);
    } else if (value.isArray()) {
        return Variant::make<std::vector<Variant>>(
                convertArray<Variant>(value, convertVariant));
    } else {
        // This covers all non-object values
        // i.e values without a _typename entry
        return value.getVariant();
    }
}

std::string convertString(IValue &value)
{
    return static_cast<std::string>(value);
}

bool convertBool(IValue &value)
{
    return value.getBool();
}
} // namespace joynr
<commit_msg>[C++] Use removeEscapeFromSpecialChars in ClassDeserializer<commit_after>/*
 * #%L
 * %%
 * Copyright (C) 2011 - 2015 BMW Car IT GmbH
 * %%
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 * #L%
 */
#include "joynr/ClassDeserializer.h"
#include "joynr/SerializerRegistry.h"
#include "joynr/IDeserializer.h"
#include "joynr/Util.h"
namespace joynr
{

/**
 * @brief deserialize not knowing the type
 * @param object
 * @return Variant
 */
Variant deserialize(IObject& o)
{
    // The object must have fields
    if (!o.hasNextField()) {
        throw std::invalid_argument("Object contains no fields");
    }

    // The first field has to contain the typename
    IField& field = o.nextField();
    if (field.name() != "_typeName") {
        throw std::invalid_argument("First field of object should be _typeName");
    }

    // Create an object of the correct type
    std::string typeName(field.value());
    std::unique_ptr<IClassDeserializer> deserializer =
            SerializerRegistry::getDeserializer(typeName);

    // Deserialize
    return deserializer->deserializeVariant(o);
}

Variant convertVariant(IValue &value)
{
    if (value.isObject()) {
        return deserialize(value);
    } else if (value.isArray()) {
        return Variant::make<std::vector<Variant>>(
                convertArray<Variant>(value, convertVariant));
    } else {
        // This covers all non-object values
        // i.e values without a _typename entry
        return value.getVariant();
    }
}

std::string convertString(IValue &value)
{
    return removeEscapeFromSpecialChars(static_cast<std::string>(value));
}

bool convertBool(IValue &value)
{
    return value.getBool();
}
} // namespace joynr
<|endoftext|>


<commit_before>/* This software is released under the BSD License.
 |
 | Copyright (c) 2009, Kevin P. Barry [the resourcerver project]
 | 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  Resourcerver  Project  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.
 +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/

extern "C" {
#include "api-label-check.h"
}

extern "C" {
#include "param.h"
}

#include <regex.h> /* regular expressions */

#include "protocol/constants.hpp"

static regex_t entity_expression = regex_t(), address_expression = regex_t();
static int entity_initialized = 0, address_initialized = 0;

int initialize_label_check()
{
	//TODO: add logging point here

	if (!entity_initialized)
	{
	regfree(&entity_expression);
	entity_initialized = regcomp(&entity_expression, "^[" PARAM_ENTITY_FILTER "]*$",
	  REG_EXTENDED | REG_NOSUB) == 0;
	}

	if (!address_initialized)
	{
	regfree(&address_expression);
	address_initialized = regcomp(&address_expression, "^[" PARAM_ADDRESS_FILTER "]*$",
	  REG_EXTENDED | REG_NOSUB) == 0;
	}

	return entity_initialized && address_initialized;
}

void cleanup_label_check()
{
	regfree(&entity_expression);
	regfree(&address_expression);
	entity_initialized  = false;
	address_initialized = false;
}

//TODO: add logging points for exceeded limits

result check_entity_label(text_info lLabel)
{
	if (!lLabel) return true;
	if (strlen(lLabel) > PARAM_ENTITY_LIMIT) return false;
	return (entity_initialized || initialize_label_check()) &&
	  regexec(&entity_expression, lLabel, 0, NULL, 0x00) == 0;
}

result check_address_label(text_info lLabel)
{
	if (!lLabel) return true;
	if (strlen(lLabel) > PARAM_SCOPE_LIMIT) return false;
	if ( !(address_initialized || initialize_label_check()) ||
	     regexec(&address_expression, lLabel, 0, NULL, 0x00) != 0 )
	return false;

	int target = -1, address = 0, current_address = 0;
	const char *current = lLabel;
	bool checking_address = false;

	if (current) while (*current)
	{
	if (*current == client_scope_char)
	 {
	if (target > address) return false;
	checking_address = true;
	target = current - lLabel;
	 }

	else if (*current == address_scope_char)
	 {
	if (address > target) return false;
	checking_address = false;
	current_address  = 0;
	address = current - lLabel;
	 }

	else if (checking_address && ++current_address > PARAM_ADDRESS_LIMIT) return false;

	current++;
	}

	return target < 0 || target > address;
}

result check_next_to_address(text_info lLabel)
{
	if (!lLabel) return false;

	const char *current = lLabel;

	if (current) while (*current)
	{
	if      (*current == client_scope_char)  return false;
	else if (*current == address_scope_char) return true;
	current++;
	}

	return true;
}

result check_next_to_client(text_info lLabel)
{
	if (!lLabel) return false;
	if (!strlen(lLabel)) return true;

	const char *current = lLabel;

	if (current) while (*current)
	{
	if      (*current == client_scope_char)  return true;
	else if (*current == address_scope_char) return false;
	current++;
	}

	return false;
}
<commit_msg>gamma.3 - fixed include in api-label-check<commit_after>/* This software is released under the BSD License.
 |
 | Copyright (c) 2009, Kevin P. Barry [the resourcerver project]
 | 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  Resourcerver  Project  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.
 +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/

extern "C" {
#include "api-label-check.h"
}

extern "C" {
#include "param.h"
}

#include <regex.h> //regular expressions
#include <string.h> //'strlen', etc.

#include "protocol/constants.hpp"

static regex_t entity_expression = regex_t(), address_expression = regex_t();
static int entity_initialized = 0, address_initialized = 0;

int initialize_label_check()
{
	//TODO: add logging point here

	if (!entity_initialized)
	{
	regfree(&entity_expression);
	entity_initialized = regcomp(&entity_expression, "^[" PARAM_ENTITY_FILTER "]*$",
	  REG_EXTENDED | REG_NOSUB) == 0;
	}

	if (!address_initialized)
	{
	regfree(&address_expression);
	address_initialized = regcomp(&address_expression, "^[" PARAM_ADDRESS_FILTER "]*$",
	  REG_EXTENDED | REG_NOSUB) == 0;
	}

	return entity_initialized && address_initialized;
}

void cleanup_label_check()
{
	regfree(&entity_expression);
	regfree(&address_expression);
	entity_initialized  = false;
	address_initialized = false;
}

//TODO: add logging points for exceeded limits

result check_entity_label(text_info lLabel)
{
	if (!lLabel) return true;
	if (strlen(lLabel) > PARAM_ENTITY_LIMIT) return false;
	return (entity_initialized || initialize_label_check()) &&
	  regexec(&entity_expression, lLabel, 0, NULL, 0x00) == 0;
}

result check_address_label(text_info lLabel)
{
	if (!lLabel) return true;
	if (strlen(lLabel) > PARAM_SCOPE_LIMIT) return false;
	if ( !(address_initialized || initialize_label_check()) ||
	     regexec(&address_expression, lLabel, 0, NULL, 0x00) != 0 )
	return false;

	int target = -1, address = 0, current_address = 0;
	const char *current = lLabel;
	bool checking_address = false;

	if (current) while (*current)
	{
	if (*current == client_scope_char)
	 {
	if (target > address) return false;
	checking_address = true;
	target = current - lLabel;
	 }

	else if (*current == address_scope_char)
	 {
	if (address > target) return false;
	checking_address = false;
	current_address  = 0;
	address = current - lLabel;
	 }

	else if (checking_address && ++current_address > PARAM_ADDRESS_LIMIT) return false;

	current++;
	}

	return target < 0 || target > address;
}

result check_next_to_address(text_info lLabel)
{
	if (!lLabel) return false;

	const char *current = lLabel;

	if (current) while (*current)
	{
	if      (*current == client_scope_char)  return false;
	else if (*current == address_scope_char) return true;
	current++;
	}

	return true;
}

result check_next_to_client(text_info lLabel)
{
	if (!lLabel) return false;
	if (!strlen(lLabel)) return true;

	const char *current = lLabel;

	if (current) while (*current)
	{
	if      (*current == client_scope_char)  return true;
	else if (*current == address_scope_char) return false;
	current++;
	}

	return false;
}
<|endoftext|>


<commit_before>/* bzflag
 * Copyright (c) 1993 - 2004 Tim Riker
 *
 * This package is free software;  you can redistribute it and/or
 * modify it under the terms of the license found in the file
 * named COPYING that should have accompanied this file.
 *
 * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
 * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
 */

#include "common.h"
#include "math.h"
#include "PlayerState.h"
#include "Pack.h"
#include "Protocol.h"
#include "StateDatabase.h"

// the full scale of a int16_t  (less 1.0 for safety)
const float smallScale     = 32766.0f;

// 2 cm resolution  (range: +/- 655.34 meters)
const float smallMaxDist   = 0.02f * smallScale;

// 1 cm/sec resolution  (range: +/- 327.66 meters/sec)
const float smallMaxVel    = 0.01f * smallScale;

// 0.001 radians/sec resolution  (range: +/- 32.766 rads/sec)
const float smallMaxAngVel = 0.001f * smallScale;

PlayerState::PlayerState()
: order(0), status(DeadStatus), azimuth(0.0f), angVel(0.0f)
{
  pos[0] = pos[1] = pos[2] = 0.0f;
  velocity[0] = velocity[0] = velocity[2] = 0.0f;
}

void*	PlayerState::pack(void* buf, uint16_t& code)
{
  order++;
  buf = nboPackInt(buf, int32_t(order));
  buf = nboPackShort(buf, int16_t(status));

  if ((BZDB.eval(StateDatabase::BZDB_NOSMALLPACKETS) > 0.0f) ||
      (fabsf (pos[0]) >= smallMaxDist)      ||
      (fabsf (pos[1]) >= smallMaxDist)      ||
      (fabsf (pos[2]) >= smallMaxDist)      ||
      (fabsf (velocity[0]) >= smallMaxVel)  ||
      (fabsf (velocity[1]) >= smallMaxVel)  ||
      (fabsf (velocity[2]) >= smallMaxVel)  ||
      (fabsf (angVel) >= smallMaxAngVel)) {

    code = MsgPlayerUpdate;

    buf = nboPackVector(buf, pos);
    buf = nboPackVector(buf, velocity);
    buf = nboPackFloat(buf, azimuth);
    buf = nboPackFloat(buf, angVel);
  }
  else {

    code = MsgPlayerUpdateSmall;

    int16_t posShort[3], velShort[3], aziShort, angVelShort;

    for (int i=0; i<3; i++) {
      posShort[i] = (int16_t) ((pos[i] * smallScale) / smallMaxDist);
      velShort[i] = (int16_t) ((velocity[i] * smallScale) / smallMaxVel);
    }

    // put the angle between -M_PI and +M_PI
    float angle = fmodf (azimuth, M_PI * 2.0f);
    if (angle > M_PI) {
      angle -= (M_PI * 2.0f);
    }
    else if (angle < -M_PI) {
      angle += (M_PI * 2.0f);
    }
    aziShort = (int16_t) ((angle * smallScale) / M_PI);
    angVelShort = (int16_t) ((angVel * smallScale) / smallMaxAngVel);

    buf = nboPackShort(buf, posShort[0]);
    buf = nboPackShort(buf, posShort[1]);
    buf = nboPackShort(buf, posShort[2]);
    buf = nboPackShort(buf, velShort[0]);
    buf = nboPackShort(buf, velShort[1]);
    buf = nboPackShort(buf, velShort[2]);
    buf = nboPackShort(buf, aziShort);
    buf = nboPackShort(buf, angVelShort);
  }
  return buf;
}

void*	PlayerState::unpack(void* buf, uint16_t code)
{
  int32_t inOrder;
  int16_t inStatus;
  buf = nboUnpackInt(buf, inOrder);
  buf = nboUnpackShort(buf, inStatus);
  order = int(inOrder);
  status = short(inStatus);

  if (code == MsgPlayerUpdate) {
    buf = nboUnpackVector(buf, pos);
    buf = nboUnpackVector(buf, velocity);
    buf = nboUnpackFloat(buf, azimuth);
    buf = nboUnpackFloat(buf, angVel);
  }
  else {
    int16_t posShort[3], velShort[3], aziShort, angVelShort;

    buf = nboUnpackShort(buf, posShort[0]);
    buf = nboUnpackShort(buf, posShort[1]);
    buf = nboUnpackShort(buf, posShort[2]);
    buf = nboUnpackShort(buf, velShort[0]);
    buf = nboUnpackShort(buf, velShort[1]);
    buf = nboUnpackShort(buf, velShort[2]);
    buf = nboUnpackShort(buf, aziShort);
    buf = nboUnpackShort(buf, angVelShort);

    for (int i=0; i<3; i++) {
      pos[i] = ((float)posShort[i] * smallMaxDist) / smallScale;
      velocity[i] = ((float)velShort[i] * smallMaxVel) / smallScale;
    }
    azimuth = ((float)aziShort * M_PI) / smallScale;
    angVel = ((float)angVelShort * smallMaxAngVel) / smallScale;
  }
  return buf;
}

// Local Variables: ***
// mode:C++ ***
// tab-width: 8 ***
// c-basic-offset: 2 ***
// indent-tabs-mode: t ***
// End: ***
// ex: shiftwidth=2 tabstop=8
<commit_msg>today's lesson, multiplication<commit_after>/* bzflag
 * Copyright (c) 1993 - 2004 Tim Riker
 *
 * This package is free software;  you can redistribute it and/or
 * modify it under the terms of the license found in the file
 * named COPYING that should have accompanied this file.
 *
 * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
 * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
 */

#include "common.h"
#include "math.h"
#include "PlayerState.h"
#include "Pack.h"
#include "Protocol.h"
#include "StateDatabase.h"

// the full scale of a int16_t  (less 1.0 for safety)
const float smallScale     = 32766.0f;

// 2 cm resolution  (range: +/- 655.32 meters)
const float smallMaxDist   = 0.02f * smallScale;

// 1 cm/sec resolution  (range: +/- 327.66 meters/sec)
const float smallMaxVel    = 0.01f * smallScale;

// 0.001 radians/sec resolution  (range: +/- 32.766 rads/sec)
const float smallMaxAngVel = 0.001f * smallScale;

PlayerState::PlayerState()
: order(0), status(DeadStatus), azimuth(0.0f), angVel(0.0f)
{
  pos[0] = pos[1] = pos[2] = 0.0f;
  velocity[0] = velocity[0] = velocity[2] = 0.0f;
}

void*	PlayerState::pack(void* buf, uint16_t& code)
{
  order++;
  buf = nboPackInt(buf, int32_t(order));
  buf = nboPackShort(buf, int16_t(status));

  if ((BZDB.eval(StateDatabase::BZDB_NOSMALLPACKETS) > 0.0f) ||
      (fabsf (pos[0]) >= smallMaxDist)      ||
      (fabsf (pos[1]) >= smallMaxDist)      ||
      (fabsf (pos[2]) >= smallMaxDist)      ||
      (fabsf (velocity[0]) >= smallMaxVel)  ||
      (fabsf (velocity[1]) >= smallMaxVel)  ||
      (fabsf (velocity[2]) >= smallMaxVel)  ||
      (fabsf (angVel) >= smallMaxAngVel)) {

    code = MsgPlayerUpdate;

    buf = nboPackVector(buf, pos);
    buf = nboPackVector(buf, velocity);
    buf = nboPackFloat(buf, azimuth);
    buf = nboPackFloat(buf, angVel);
  }
  else {

    code = MsgPlayerUpdateSmall;

    int16_t posShort[3], velShort[3], aziShort, angVelShort;

    for (int i=0; i<3; i++) {
      posShort[i] = (int16_t) ((pos[i] * smallScale) / smallMaxDist);
      velShort[i] = (int16_t) ((velocity[i] * smallScale) / smallMaxVel);
    }

    // put the angle between -M_PI and +M_PI
    float angle = fmodf (azimuth, M_PI * 2.0f);
    if (angle > M_PI) {
      angle -= (M_PI * 2.0f);
    }
    else if (angle < -M_PI) {
      angle += (M_PI * 2.0f);
    }
    aziShort = (int16_t) ((angle * smallScale) / M_PI);
    angVelShort = (int16_t) ((angVel * smallScale) / smallMaxAngVel);

    buf = nboPackShort(buf, posShort[0]);
    buf = nboPackShort(buf, posShort[1]);
    buf = nboPackShort(buf, posShort[2]);
    buf = nboPackShort(buf, velShort[0]);
    buf = nboPackShort(buf, velShort[1]);
    buf = nboPackShort(buf, velShort[2]);
    buf = nboPackShort(buf, aziShort);
    buf = nboPackShort(buf, angVelShort);
  }
  return buf;
}

void*	PlayerState::unpack(void* buf, uint16_t code)
{
  int32_t inOrder;
  int16_t inStatus;
  buf = nboUnpackInt(buf, inOrder);
  buf = nboUnpackShort(buf, inStatus);
  order = int(inOrder);
  status = short(inStatus);

  if (code == MsgPlayerUpdate) {
    buf = nboUnpackVector(buf, pos);
    buf = nboUnpackVector(buf, velocity);
    buf = nboUnpackFloat(buf, azimuth);
    buf = nboUnpackFloat(buf, angVel);
  }
  else {
    int16_t posShort[3], velShort[3], aziShort, angVelShort;

    buf = nboUnpackShort(buf, posShort[0]);
    buf = nboUnpackShort(buf, posShort[1]);
    buf = nboUnpackShort(buf, posShort[2]);
    buf = nboUnpackShort(buf, velShort[0]);
    buf = nboUnpackShort(buf, velShort[1]);
    buf = nboUnpackShort(buf, velShort[2]);
    buf = nboUnpackShort(buf, aziShort);
    buf = nboUnpackShort(buf, angVelShort);

    for (int i=0; i<3; i++) {
      pos[i] = ((float)posShort[i] * smallMaxDist) / smallScale;
      velocity[i] = ((float)velShort[i] * smallMaxVel) / smallScale;
    }
    azimuth = ((float)aziShort * M_PI) / smallScale;
    angVel = ((float)angVelShort * smallMaxAngVel) / smallScale;
  }
  return buf;
}

// Local Variables: ***
// mode:C++ ***
// tab-width: 8 ***
// c-basic-offset: 2 ***
// indent-tabs-mode: t ***
// End: ***
// ex: shiftwidth=2 tabstop=8
<|endoftext|>