<commit_before>/*! \file MemoryChecker.cpp
	\date Wednesday March 17, 2010
	\author Gregory Diamos <gregory.diamos@gatech.edu>
	\brief The source file for the MemoryChecker class.
*/

#ifndef MEMORY_CHECKER_CPP_INCLUDED
#define MEMORY_CHECKER_CPP_INCLUDED

// Ocelot includes
#include <ocelot/trace/interface/MemoryChecker.h>
#include <ocelot/trace/interface/TraceEvent.h>
#include <ocelot/executive/interface/EmulatedKernel.h>
#include <ocelot/executive/interface/Device.h>

// hydrazine includes
#include <hydrazine/implementation/Exception.h>

namespace trace
{
	MemoryChecker::Allocation::Allocation( bool v, ir::PTXU64 b, ir::PTXU64 e )
		: valid( v ), base( b ), extent( e )
	{

	}

	static std::string prefix( unsigned int thread, const ir::Dim3& dim,
		const TraceEvent& e )
	{
		const unsigned int cta = e.blockId.x + e.blockId.y * dim.x
			+ dim.x * dim.y * e.blockId.z;

		std::stringstream stream;
		stream << "[PC " << e.PC << "] ";
		stream << "[thread " << thread << "] ";
		stream << "[cta " << cta << "] ";
		stream << e.instruction->toString() << " - ";

		return stream.str();
	}

	static void alignmentError( const executive::EmulatedKernel* kernel,
		const ir::Dim3& dim, const TraceEvent& e, unsigned int thread,
		ir::PTXU64 address, unsigned int size )
	{
		std::stringstream stream;
		stream << prefix( thread, dim, e );
		stream << "Memory access " << (void*)address
			<< " is not aligned to the access size ( " << size << " bytes )";
		stream << "\n";
		stream << "Near " << kernel->location( e.PC ) << "\n";
		throw hydrazine::Exception( stream.str() );
	}

	template< unsigned int size >
	static void checkAlignment( const executive::EmulatedKernel* kernel,
		const ir::Dim3& dim, const TraceEvent& e )
	{
		TraceEvent::U64Vector::const_iterator
			address = e.memory_addresses.begin();
		unsigned int threads = e.active.size();
		for( unsigned int thread = 0; thread < threads; ++thread )
		{
			if( !e.active[ thread ] ) continue;
			if( *address & ( size - 1 ) )
			{
				alignmentError( kernel, dim, e, thread, *address, size );
			}
			++address;
		}
	}

	void MemoryChecker::_checkAlignment( const TraceEvent& e )
	{
		switch(e.memory_size)
		{
			case 1: return;
			case 2: checkAlignment< 2 >( _kernel, _dim, e ); break;
			case 4: checkAlignment< 4 >( _kernel, _dim, e ); break;
			case 8: checkAlignment< 8 >( _kernel, _dim, e ); break;
			case 16: checkAlignment< 16 >( _kernel, _dim, e ); break;
			case 32: checkAlignment< 32 >( _kernel, _dim, e ); break;
			default: break;
		}
	}

	static void memoryError( const std::string& space, const ir::Dim3& dim,
		unsigned int thread, ir::PTXU64 address, unsigned int size,
		const TraceEvent& e, const executive::EmulatedKernel* kernel,
		const MemoryChecker::Allocation& allocation )
	{
		std::stringstream stream;
		stream << prefix( thread, dim, e );
		stream << space << " memory access " << (void*) address
			<< " (" << size << " bytes) is beyond allocated block size "
			<< allocation.extent;
		stream << "\n";
		stream << "Near " << kernel->location( e.PC ) << "\n";
		throw hydrazine::Exception( stream.str() );
	}

	static void globalMemoryError(const executive::Device* device,
		const ir::Dim3& dim, unsigned int thread, ir::PTXU64 address,
		unsigned int size, const TraceEvent& event,
		const executive::EmulatedKernel* kernel)
	{
		std::stringstream stream;
		stream << prefix( thread, dim, event );
		stream << "Global memory access " << (void*)address
			<< " is not within any allocated or mapped range.\n\n";
		stream << "Nearby Device Allocations\n";
		stream << device->nearbyAllocationsToString( (void*)address );
		stream << "\n";
		stream << "Near " << kernel->location( event.PC ) << "\n";
		throw hydrazine::Exception( stream.str() );
	}

	static void checkLocalAccess( const std::string& space, const ir::Dim3& dim,
		const MemoryChecker::Allocation& allocation, const TraceEvent& event,
		const executive::EmulatedKernel* kernel )
	{
		TraceEvent::U64Vector::const_iterator
			address = event.memory_addresses.begin();

		unsigned int threads = event.active.size();
		for( unsigned int thread = 0; thread < threads; ++thread )
		{
			if( !event.active[ thread ] ) continue;
			if( allocation.base > *address
				|| *address >= allocation.base + allocation.extent )
			{
				memoryError( space, dim, thread,
					*address, event.memory_size, event, kernel, allocation );
			}
			++address;
		}
	}

	void MemoryChecker::_checkValidity( const TraceEvent& e )
	{
		switch( e.instruction->addressSpace )
		{
			case ir::PTXInstruction::Global:
			{
				TraceEvent::U64Vector::const_iterator
					address = e.memory_addresses.begin();

				unsigned int threads = e.active.size();
				for( unsigned int thread = 0; thread < threads; ++thread )
				{
					if( !e.active[ thread ] ) continue;
					if( _cache.base > *address
						|| *address >= _cache.base + _cache.extent
						|| !_cache.valid )
					{
						const executive::Device::MemoryAllocation* allocation =
							_device->getMemoryAllocation( (void*)*address,
								executive::Device::AnyAllocation );
						if( allocation == 0 )
						{
							globalMemoryError( _device, _dim,
								thread, *address, e.memory_size, e, _kernel );
						}
						_cache.base = ( ir::PTXU64 ) allocation->pointer();
						_cache.extent = allocation->size();
						if( *address >= _cache.base + _cache.extent )
						{
							globalMemoryError( _device, _dim,
								thread, *address, e.memory_size, e, _kernel );
						}
					}
					++address;
				}
				break;
			}
			case ir::PTXInstruction::Local: checkLocalAccess( "Local", _dim,
				_local, e, _kernel ); break;
			case ir::PTXInstruction::Param: checkLocalAccess( "Parameter", _dim,
				_parameter, e, _kernel ); break;
			case ir::PTXInstruction::Shared: checkLocalAccess( "Shared", _dim,
				_shared, e, _kernel ); break;
			case ir::PTXInstruction::Const: checkLocalAccess( "Constant", _dim,
				_constant, e, _kernel ); break;
			default: break;
		}
	}

	void MemoryChecker::_checkInitialized( const TraceEvent& e )
	{
		// TODO: implement this
	}

	MemoryChecker::MemoryChecker() : _cache( false ), _parameter( true ),
		_shared( true ), _local( true ), _constant( true )
	{

	}

	void MemoryChecker::initialize( const executive::ExecutableKernel& kernel )
	{
		_dim = kernel.blockDim();

		_device = kernel.device;

		_cache.valid = false;

		_parameter.base = 0;
		_parameter.extent = kernel.parameterMemorySize();

		_constant.base = 0;
		_constant.extent = kernel.constMemorySize();

		_shared.base = 0;
		_shared.extent = kernel.totalSharedMemorySize();

		_local.base = 0;
		_local.extent = kernel.localMemorySize();

		_kernel = static_cast< const executive::EmulatedKernel* >( &kernel );
	}

	void MemoryChecker::event(const TraceEvent& event)
	{
		const bool isMemoryOperation =
			event.instruction->opcode == ir::PTXInstruction::Ld
			|| event.instruction->opcode == ir::PTXInstruction::St
			|| event.instruction->opcode == ir::PTXInstruction::Atom;

		if( !isMemoryOperation ) return;

		_checkAlignment( event );
		_checkValidity( event );
		_checkInitialized( event );
	}

	void MemoryChecker::finish()
	{

	}
}

#endif

<commit_msg>BUG: Memory checker should ignore the top 32-bits of shared accesses.  These are actually application bugs, but we are not treating them as such until 2.x<commit_after>/*! \file MemoryChecker.cpp
	\date Wednesday March 17, 2010
	\author Gregory Diamos <gregory.diamos@gatech.edu>
	\brief The source file for the MemoryChecker class.
*/

#ifndef MEMORY_CHECKER_CPP_INCLUDED
#define MEMORY_CHECKER_CPP_INCLUDED

// Ocelot includes
#include <ocelot/trace/interface/MemoryChecker.h>
#include <ocelot/trace/interface/TraceEvent.h>
#include <ocelot/executive/interface/EmulatedKernel.h>
#include <ocelot/executive/interface/Device.h>

// hydrazine includes
#include <hydrazine/implementation/Exception.h>

namespace trace
{
	MemoryChecker::Allocation::Allocation( bool v, ir::PTXU64 b, ir::PTXU64 e )
		: valid( v ), base( b ), extent( e )
	{

	}

	static std::string prefix( unsigned int thread, const ir::Dim3& dim,
		const TraceEvent& e )
	{
		const unsigned int cta = e.blockId.x + e.blockId.y * dim.x
			+ dim.x * dim.y * e.blockId.z;

		std::stringstream stream;
		stream << "[PC " << e.PC << "] ";
		stream << "[thread " << thread << "] ";
		stream << "[cta " << cta << "] ";
		stream << e.instruction->toString() << " - ";

		return stream.str();
	}

	static void alignmentError( const executive::EmulatedKernel* kernel,
		const ir::Dim3& dim, const TraceEvent& e, unsigned int thread,
		ir::PTXU64 address, unsigned int size )
	{
		std::stringstream stream;
		stream << prefix( thread, dim, e );
		stream << "Memory access " << (void*)address
			<< " is not aligned to the access size ( " << size << " bytes )";
		stream << "\n";
		stream << "Near " << kernel->location( e.PC ) << "\n";
		throw hydrazine::Exception( stream.str() );
	}

	template< unsigned int size >
	static void checkAlignment( const executive::EmulatedKernel* kernel,
		const ir::Dim3& dim, const TraceEvent& e )
	{
		TraceEvent::U64Vector::const_iterator
			address = e.memory_addresses.begin();
		unsigned int threads = e.active.size();
		for( unsigned int thread = 0; thread < threads; ++thread )
		{
			if( !e.active[ thread ] ) continue;
			if( *address & ( size - 1 ) )
			{
				alignmentError( kernel, dim, e, thread, *address, size );
			}
			++address;
		}
	}

	void MemoryChecker::_checkAlignment( const TraceEvent& e )
	{
		switch(e.memory_size)
		{
			case 1: return;
			case 2: checkAlignment< 2 >( _kernel, _dim, e ); break;
			case 4: checkAlignment< 4 >( _kernel, _dim, e ); break;
			case 8: checkAlignment< 8 >( _kernel, _dim, e ); break;
			case 16: checkAlignment< 16 >( _kernel, _dim, e ); break;
			case 32: checkAlignment< 32 >( _kernel, _dim, e ); break;
			default: break;
		}
	}

	static void memoryError( const std::string& space, const ir::Dim3& dim,
		unsigned int thread, ir::PTXU64 address, unsigned int size,
		const TraceEvent& e, const executive::EmulatedKernel* kernel,
		const MemoryChecker::Allocation& allocation )
	{
		std::stringstream stream;
		stream << prefix( thread, dim, e );
		stream << space << " memory access " << (void*) address
			<< " (" << size << " bytes) is beyond allocated block size "
			<< allocation.extent;
		stream << "\n";
		stream << "Near " << kernel->location( e.PC ) << "\n";
		throw hydrazine::Exception( stream.str() );
	}

	static void globalMemoryError(const executive::Device* device,
		const ir::Dim3& dim, unsigned int thread, ir::PTXU64 address,
		unsigned int size, const TraceEvent& event,
		const executive::EmulatedKernel* kernel)
	{
		std::stringstream stream;
		stream << prefix( thread, dim, event );
		stream << "Global memory access " << (void*)address
			<< " is not within any allocated or mapped range.\n\n";
		stream << "Nearby Device Allocations\n";
		stream << device->nearbyAllocationsToString( (void*)address );
		stream << "\n";
		stream << "Near " << kernel->location( event.PC ) << "\n";
		throw hydrazine::Exception( stream.str() );
	}

	static void checkLocalAccess( const std::string& space, const ir::Dim3& dim,
		const MemoryChecker::Allocation& allocation, const TraceEvent& event,
		const executive::EmulatedKernel* kernel )
	{
		TraceEvent::U64Vector::const_iterator
			address = event.memory_addresses.begin();

		unsigned int threads = event.active.size();
		for( unsigned int thread = 0; thread < threads; ++thread )
		{
			if( !event.active[ thread ] ) continue;
			if( allocation.base > *address
				|| *address >= allocation.base + allocation.extent )
			{
				memoryError( space, dim, thread,
					*address, event.memory_size, event, kernel, allocation );
			}
			++address;
		}
	}

	void MemoryChecker::_checkValidity( const TraceEvent& e )
	{
		switch( e.instruction->addressSpace )
		{
			case ir::PTXInstruction::Global:
			{
				TraceEvent::U64Vector::const_iterator
					address = e.memory_addresses.begin();

				unsigned int threads = e.active.size();
				for( unsigned int thread = 0; thread < threads; ++thread )
				{
					if( !e.active[ thread ] ) continue;
					if( _cache.base > *address
						|| *address >= _cache.base + _cache.extent
						|| !_cache.valid )
					{
						const executive::Device::MemoryAllocation* allocation =
							_device->getMemoryAllocation( (void*)*address,
								executive::Device::AnyAllocation );
						if( allocation == 0 )
						{
							globalMemoryError( _device, _dim,
								thread, *address, e.memory_size, e, _kernel );
						}
						_cache.base = ( ir::PTXU64 ) allocation->pointer();
						_cache.extent = allocation->size();
						if( *address >= _cache.base + _cache.extent )
						{
							globalMemoryError( _device, _dim,
								thread, *address, e.memory_size, e, _kernel );
						}
					}
					++address;
				}
				break;
			}
			case ir::PTXInstruction::Local: checkLocalAccess( "Local", _dim,
				_local, e, _kernel ); break;
			case ir::PTXInstruction::Param: checkLocalAccess( "Parameter", _dim,
				_parameter, e, _kernel ); break;
			case ir::PTXInstruction::Shared: {
				TraceEvent::U64Vector::const_iterator
					address = e.memory_addresses.begin();

				unsigned int threads = e.active.size();
				for( unsigned int thread = 0; thread < threads; ++thread )
				{
					if( !e.active[ thread ] ) continue;

					ir::PTXU64 a = *address & 0xffffffff;
					if( _shared.base > a
						|| a >= _shared.base + _shared.extent )
					{
						memoryError( "Shared", _dim, thread,
							a, e.memory_size, e, _kernel, _shared );
					}
					++address;
				}
			}; break;
			case ir::PTXInstruction::Const: checkLocalAccess( "Constant", _dim,
				_constant, e, _kernel ); break;
			default: break;
		}
	}

	void MemoryChecker::_checkInitialized( const TraceEvent& e )
	{
		// TODO: implement this
	}

	MemoryChecker::MemoryChecker() : _cache( false ), _parameter( true ),
		_shared( true ), _local( true ), _constant( true )
	{

	}

	void MemoryChecker::initialize( const executive::ExecutableKernel& kernel )
	{
		_dim = kernel.blockDim();

		_device = kernel.device;

		_cache.valid = false;

		_parameter.base = 0;
		_parameter.extent = kernel.parameterMemorySize();

		_constant.base = 0;
		_constant.extent = kernel.constMemorySize();

		_shared.base = 0;
		_shared.extent = kernel.totalSharedMemorySize();

		_local.base = 0;
		_local.extent = kernel.localMemorySize();

		_kernel = static_cast< const executive::EmulatedKernel* >( &kernel );
	}

	void MemoryChecker::event(const TraceEvent& event)
	{
		const bool isMemoryOperation =
			event.instruction->opcode == ir::PTXInstruction::Ld
			|| event.instruction->opcode == ir::PTXInstruction::St
			|| event.instruction->opcode == ir::PTXInstruction::Atom;

		if( !isMemoryOperation ) return;

		_checkAlignment( event );
		_checkValidity( event );
		_checkInitialized( event );
	}

	void MemoryChecker::finish()
	{

	}
}

#endif

<|endoftext|>


<commit_before>/* Copyright 2021 David M. Rogers
 *
 * This file is part of Alpaka.
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
 */

#include <alpaka/test/KernelExecutionFixture.hpp>
#include <alpaka/test/acc/TestAccs.hpp>
#include <alpaka/test/queue/Queue.hpp>
#include <alpaka/warp/Traits.hpp>

#include <catch2/catch.hpp>

#include <cstdint>

//#############################################################################
class ShflSingleThreadWarpTestKernel
{
public:
    //-------------------------------------------------------------------------
    ALPAKA_NO_HOST_ACC_WARNING
    template<typename TAcc>
    ALPAKA_FN_ACC auto operator()(TAcc const& acc, bool* success) const -> void
    {
        std::int32_t const warpExtent = alpaka::warp::getSize(acc);
        ALPAKA_CHECK(*success, warpExtent == 1);

        ALPAKA_CHECK(*success, alpaka::warp::shfl(acc, 12, 0) == 12);
        ALPAKA_CHECK(*success, alpaka::warp::shfl(acc, 42, -1) == 42);
        float ans = alpaka::warp::shfl(acc, 3.3f, 0);
        ALPAKA_CHECK(*success, alpaka::math::abs(acc, ans - 3.3f) < 1e-8f);
    }
};

//#############################################################################
class ShflMultipleThreadWarpTestKernel
{
public:
    //-----------------------------------------------------------------------------
    ALPAKA_NO_HOST_ACC_WARNING
    template<typename TAcc>
    ALPAKA_FN_ACC auto operator()(TAcc const& acc, bool* success) const -> void
    {
        auto const localThreadIdx = alpaka::getIdx<alpaka::Block, alpaka::Threads>(acc);
        auto const blockExtent = alpaka::getWorkDiv<alpaka::Block, alpaka::Threads>(acc);
        std::int32_t const warpExtent = alpaka::warp::getSize(acc);
        // Test relies on having a single warp per thread block
        ALPAKA_CHECK(*success, static_cast<std::int32_t>(blockExtent.prod()) == warpExtent);
        auto const threadIdxInWarp = std::int32_t(alpaka::mapIdx<1u>(localThreadIdx, blockExtent)[0]);

        ALPAKA_CHECK(*success, warpExtent > 1);

        ALPAKA_CHECK(*success, alpaka::warp::shfl(acc, 42, 0) == 42);
        ALPAKA_CHECK(*success, alpaka::warp::shfl(acc, threadIdxInWarp, 0) == 0);
        ALPAKA_CHECK(*success, alpaka::warp::shfl(acc, threadIdxInWarp, 1) == 1);
        // Note the CUDA and HIP API-s differ on lane wrapping, but both agree it should not segfault
        // https://github.com/ROCm-Developer-Tools/HIP-CPU/issues/14
        ALPAKA_CHECK(*success, alpaka::warp::shfl(acc, 5, -1) == 5);

        // Test various widths
        for(int width = 1; width < warpExtent; width *= 2)
        {
            for(int idx = 0; idx < width; idx++)
            {
                int off = width * (threadIdxInWarp / width);
                ALPAKA_CHECK(*success, alpaka::warp::shfl(acc, threadIdxInWarp, idx, width) == idx + off);
                float ans = alpaka::warp::shfl(acc, 4.0f - float(threadIdxInWarp), idx, width);
                float expect = 4.0f - float(idx + off);
                ALPAKA_CHECK(*success, alpaka::math::abs(acc, ans - expect) < 1e-8f);
            }
        }

        // Some threads quit the kernel to test that the warp operations
        // properly operate on the active threads only
        if(threadIdxInWarp >= warpExtent / 2)
            return;

        for(int idx = 0; idx < warpExtent / 2; idx++)
        {
            ALPAKA_CHECK(*success, alpaka::warp::shfl(acc, threadIdxInWarp, idx) == idx);
            float ans = alpaka::warp::shfl(acc, 4.0f - float(threadIdxInWarp), idx);
            float expect = 4.0f - float(idx);
            ALPAKA_CHECK(*success, alpaka::math::abs(acc, ans - expect) < 1e-8f);
        }
    }
};

//-----------------------------------------------------------------------------
TEMPLATE_LIST_TEST_CASE("shfl", "[warp]", alpaka::test::TestAccs)
{
    using Acc = TestType;
    using Dev = alpaka::Dev<Acc>;
    using Pltf = alpaka::Pltf<Dev>;
    using Dim = alpaka::Dim<Acc>;
    using Idx = alpaka::Idx<Acc>;

    Dev const dev(alpaka::getDevByIdx<Pltf>(0u));
    auto const warpExtent = alpaka::getWarpSize(dev);
    if(warpExtent == 1)
    {
        Idx const gridThreadExtentPerDim = 4;
        alpaka::test::KernelExecutionFixture<Acc> fixture(alpaka::Vec<Dim, Idx>::all(gridThreadExtentPerDim));
        ShflSingleThreadWarpTestKernel kernel;
        REQUIRE(fixture(kernel));
    }
    else
    {
        // Work around gcc 7.5 trying and failing to offload for OpenMP 4.0
#if BOOST_COMP_GNUC && (BOOST_COMP_GNUC == BOOST_VERSION_NUMBER(7, 5, 0)) && defined ALPAKA_ACC_ANY_BT_OMP5_ENABLED
        return;
#else
        using ExecutionFixture = alpaka::test::KernelExecutionFixture<Acc>;
        auto const gridBlockExtent = alpaka::Vec<Dim, Idx>::all(2);
        // Enforce one warp per thread block
        auto blockThreadExtent = alpaka::Vec<Dim, Idx>::ones();
        blockThreadExtent[0] = static_cast<Idx>(warpExtent);
        auto const threadElementExtent = alpaka::Vec<Dim, Idx>::ones();
        auto workDiv = typename ExecutionFixture::WorkDiv{gridBlockExtent, blockThreadExtent, threadElementExtent};
        auto fixture = ExecutionFixture{workDiv};
        ShflMultipleThreadWarpTestKernel kernel;
        REQUIRE(fixture(kernel));
#endif
    }
}
<commit_msg>remove magic number<commit_after>/* Copyright 2021 David M. Rogers
 *
 * This file is part of Alpaka.
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
 */

#include <alpaka/test/KernelExecutionFixture.hpp>
#include <alpaka/test/acc/TestAccs.hpp>
#include <alpaka/test/queue/Queue.hpp>
#include <alpaka/warp/Traits.hpp>

#include <catch2/catch.hpp>

#include <cstdint>
#include <limits>

//#############################################################################
class ShflSingleThreadWarpTestKernel
{
public:
    //-------------------------------------------------------------------------
    ALPAKA_NO_HOST_ACC_WARNING
    template<typename TAcc>
    ALPAKA_FN_ACC auto operator()(TAcc const& acc, bool* success) const -> void
    {
        std::int32_t const warpExtent = alpaka::warp::getSize(acc);
        ALPAKA_CHECK(*success, warpExtent == 1);

        ALPAKA_CHECK(*success, alpaka::warp::shfl(acc, 12, 0) == 12);
        ALPAKA_CHECK(*success, alpaka::warp::shfl(acc, 42, -1) == 42);
        float ans = alpaka::warp::shfl(acc, 3.3f, 0);
        ALPAKA_CHECK(*success, alpaka::math::abs(acc, ans - 3.3f) < 1e-8f);
    }
};

//#############################################################################
class ShflMultipleThreadWarpTestKernel
{
public:
    //-----------------------------------------------------------------------------
    ALPAKA_NO_HOST_ACC_WARNING
    template<typename TAcc>
    ALPAKA_FN_ACC auto operator()(TAcc const& acc, bool* success) const -> void
    {
        auto const localThreadIdx = alpaka::getIdx<alpaka::Block, alpaka::Threads>(acc);
        auto const blockExtent = alpaka::getWorkDiv<alpaka::Block, alpaka::Threads>(acc);
        std::int32_t const warpExtent = alpaka::warp::getSize(acc);
        // Test relies on having a single warp per thread block
        ALPAKA_CHECK(*success, static_cast<std::int32_t>(blockExtent.prod()) == warpExtent);
        auto const threadIdxInWarp = std::int32_t(alpaka::mapIdx<1u>(localThreadIdx, blockExtent)[0]);

        ALPAKA_CHECK(*success, warpExtent > 1);

        ALPAKA_CHECK(*success, alpaka::warp::shfl(acc, 42, 0) == 42);
        ALPAKA_CHECK(*success, alpaka::warp::shfl(acc, threadIdxInWarp, 0) == 0);
        ALPAKA_CHECK(*success, alpaka::warp::shfl(acc, threadIdxInWarp, 1) == 1);
        // Note the CUDA and HIP API-s differ on lane wrapping, but both agree it should not segfault
        // https://github.com/ROCm-Developer-Tools/HIP-CPU/issues/14
        ALPAKA_CHECK(*success, alpaka::warp::shfl(acc, 5, -1) == 5);

        auto const epsilon = std::numeric_limits<float>::epsilon();

        // Test various widths
        for(int width = 1; width < warpExtent; width *= 2)
        {
            for(int idx = 0; idx < width; idx++)
            {
                int const off = width * (threadIdxInWarp / width);
                ALPAKA_CHECK(*success, alpaka::warp::shfl(acc, threadIdxInWarp, idx, width) == idx + off);
                float const ans = alpaka::warp::shfl(acc, 4.0f - float(threadIdxInWarp), idx, width);
                float const expect = 4.0f - float(idx + off);
                ALPAKA_CHECK(*success, alpaka::math::abs(acc, ans - expect) < epsilon);
            }
        }

        // Some threads quit the kernel to test that the warp operations
        // properly operate on the active threads only
        if(threadIdxInWarp >= warpExtent / 2)
            return;

        for(int idx = 0; idx < warpExtent / 2; idx++)
        {
            ALPAKA_CHECK(*success, alpaka::warp::shfl(acc, threadIdxInWarp, idx) == idx);
            float const ans = alpaka::warp::shfl(acc, 4.0f - float(threadIdxInWarp), idx);
            float const expect = 4.0f - float(idx);
            ALPAKA_CHECK(*success, alpaka::math::abs(acc, ans - expect) < epsilon);
        }
    }
};

//-----------------------------------------------------------------------------
TEMPLATE_LIST_TEST_CASE("shfl", "[warp]", alpaka::test::TestAccs)
{
    using Acc = TestType;
    using Dev = alpaka::Dev<Acc>;
    using Pltf = alpaka::Pltf<Dev>;
    using Dim = alpaka::Dim<Acc>;
    using Idx = alpaka::Idx<Acc>;

    Dev const dev(alpaka::getDevByIdx<Pltf>(0u));
    auto const warpExtent = alpaka::getWarpSize(dev);
    if(warpExtent == 1)
    {
        Idx const gridThreadExtentPerDim = 4;
        alpaka::test::KernelExecutionFixture<Acc> fixture(alpaka::Vec<Dim, Idx>::all(gridThreadExtentPerDim));
        ShflSingleThreadWarpTestKernel kernel;
        REQUIRE(fixture(kernel));
    }
    else
    {
        // Work around gcc 7.5 trying and failing to offload for OpenMP 4.0
#if BOOST_COMP_GNUC && (BOOST_COMP_GNUC == BOOST_VERSION_NUMBER(7, 5, 0)) && defined ALPAKA_ACC_ANY_BT_OMP5_ENABLED
        return;
#else
        using ExecutionFixture = alpaka::test::KernelExecutionFixture<Acc>;
        auto const gridBlockExtent = alpaka::Vec<Dim, Idx>::all(2);
        // Enforce one warp per thread block
        auto blockThreadExtent = alpaka::Vec<Dim, Idx>::ones();
        blockThreadExtent[0] = static_cast<Idx>(warpExtent);
        auto const threadElementExtent = alpaka::Vec<Dim, Idx>::ones();
        auto workDiv = typename ExecutionFixture::WorkDiv{gridBlockExtent, blockThreadExtent, threadElementExtent};
        auto fixture = ExecutionFixture{workDiv};
        ShflMultipleThreadWarpTestKernel kernel;
        REQUIRE(fixture(kernel));
#endif
    }
}
<|endoftext|>


<commit_before>//
// Created by lz on 1/25/17.
//

#include <catch.hpp>
#include <c10k/worker_thread.hpp>
#include <c10k/utils.hpp>
#include "test_common.hpp"
#include <cstdint>
#include <sstream>
#include <iostream>

struct ServerHandler: public c10k::Handler
{
    std::uint16_t len;
    std::vector<char> buffer;
    virtual void handle_init(const c10k::ConnectionPtr &conn) override
    {
        using namespace std::placeholders;
        using std::static_pointer_cast;
        conn->read_async_then((char*)&len, sizeof(len),
                              std::bind(&ServerHandler::read_buffer,
                                        static_pointer_cast<ServerHandler>(shared_from_this()), _1, _2, _3));
    }

    void read_buffer(const c10k::ConnectionPtr &conn, char *st, char *ed)
    {
        using namespace std::placeholders;
        buffer.reserve(len);
        conn->read_async_then(std::back_inserter(buffer), len,
                              std::bind(&ServerHandler::write_back,
                                        std::static_pointer_cast<ServerHandler>(shared_from_this()), _1, _2, _3));
    }

    void write_back(const c10k::ConnectionPtr &conn, char *st, char *ed)
    {
        using namespace std::placeholders;
        std::vector<char> wrt_buffer;
        wrt_buffer.reserve(2 + len);
        std::copy_n((char *)&len, 2, std::back_inserter(wrt_buffer));
        std::copy(buffer.begin(), buffer.end(), std::back_inserter(wrt_buffer));
        conn->write_async_then(wrt_buffer.begin(), wrt_buffer.end(),
                               std::bind(&ServerHandler::close_connection,
                                         std::static_pointer_cast<ServerHandler>(shared_from_this()), _1));
    }

    void close_connection(const c10k::ConnectionPtr &conn)
    {
        conn->close();
    }
};

std::atomic_bool check_ok {true};
std::stringstream ss;

struct ClientHandler: public c10k::Handler
{
    std::vector<char> gen_data()
    {
        std::vector<char> wrt_buffer;
        std::uint16_t len = std::rand() % 32768;
        wrt_buffer.reserve(2 + len);
        std::copy_n((char *)&len, 2, std::back_inserter(wrt_buffer));
        std::generate_n(std::back_inserter(wrt_buffer), len, []() {
            return std::rand() % 128;;
        });
        return wrt_buffer;
    }

    std::vector<char> send_data, recv_data;
    virtual void handle_init(const c10k::ConnectionPtr &conn) override
    {
        using namespace std::placeholders;
        send_data = gen_data();
        conn->write_async(send_data.cbegin(), send_data.cend());
        conn->read_async_then(std::back_inserter(recv_data), send_data.size(),
            std::bind(&ClientHandler::check_data,
                      std::static_pointer_cast<ClientHandler>(shared_from_this()), _1, _2, _3));
    }

    void check_data(const c10k::ConnectionPtr &conn, char *st, char *ed)
    {
        bool ok = true;
        ok &= send_data.size() == recv_data.size();
        if (ok)
            for (int i=0; i<send_data.size(); ++i) {
                ok &= send_data[i] == recv_data[i];
                if (send_data[i] != recv_data[i]) {
                    for (int j=i-5; j < i+5 && j<send_data.size(); ++j)
                        ss << "Pos[" << j << "]: send=" << send_data[j] << " recv=" << recv_data[j] << std::endl;
                    ss << "At pos " << i << " send=" << (int) send_data[i] << " recv=" << (int) recv_data[i] <<
                                   " size=" << recv_data.size() <<
                                   " fd=" << conn->getFD() << std::endl;
                }
            }
        if (check_ok.load() && !ok) {
            check_ok = ok;
            ss << "Err!" << "Send size="<< send_data.size() <<" recv size=" << recv_data.size() << std::endl;
        }
        conn->close();
    }
};

TEST_CASE("multiple WorkerThread test", "[worker_thread]")
{
    using namespace std::chrono_literals;
    using namespace c10k;
    using detail::call_must_ok;
    spdlog::set_level(spdlog::level::debug);
    auto server_logger = spdlog::stdout_color_mt("Server"), client_logger = spdlog::stdout_color_mt("Client");
    detail::WorkerThread<ServerHandler> worker(400, server_logger);

    std::thread server_t {std::ref(worker)};
    static constexpr int TEST_CNT = 600;

    std::thread main_t {[&]() {
        INFO("Main thread entered");
        int main_fd = create_socket();
        INFO("Main thread created");
        sockaddr_in addr = create_addr("127.0.0.1", 6503);
        call_must_ok(::bind, "Bind", main_fd, (sockaddr*)&addr, sizeof(addr));
        call_must_ok(::listen, "Listen", main_fd, 1024);
        INFO("Main thread binded");
        for (int i=0; i<TEST_CNT; ++i)
        {
            int new_sock = call_must_ok(accept, "Accept", main_fd, nullptr, nullptr);
            make_socket_nonblocking(new_sock);
            server_logger->info("new fd created = {}", new_sock);
            worker.add_new_connection(new_sock);
        }
        call_must_ok(::close, "close", main_fd);
    }};
    main_t.detach();
    INFO("Main thread detached");
    cur_sleep_for(1s);
    INFO("Start to create clientWorker");

    detail::WorkerThread<ClientHandler> clientWorker(400, client_logger);
    std::thread client_t {std::ref(clientWorker)};
    INFO("ClientWorker created");

    for (int i=0; i<TEST_CNT; ++i)
    {
        int cli_fd = create_socket(true);
        sockaddr_in addr = create_addr("127.0.0.1", 6503);
        call_must_ok(::connect, "Connect", cli_fd, (sockaddr*)&addr, sizeof(addr));
        INFO("New fd added" << i);
        make_socket_nonblocking(cli_fd);
        clientWorker.add_new_connection(cli_fd);
    }

    cur_sleep_for(2s);
    server_t.detach(); client_t.detach();
    worker.stop(); clientWorker.stop();
    cur_sleep_for(1s);
    INFO(ss.str());
    REQUIRE(check_ok);
}<commit_msg>Test: Detach server_t/client_t earlier<commit_after>//
// Created by lz on 1/25/17.
//

#include <catch.hpp>
#include <c10k/worker_thread.hpp>
#include <c10k/utils.hpp>
#include "test_common.hpp"
#include <cstdint>
#include <sstream>
#include <iostream>

struct ServerHandler: public c10k::Handler
{
    std::uint16_t len;
    std::vector<char> buffer;
    virtual void handle_init(const c10k::ConnectionPtr &conn) override
    {
        using namespace std::placeholders;
        using std::static_pointer_cast;
        conn->read_async_then((char*)&len, sizeof(len),
                              std::bind(&ServerHandler::read_buffer,
                                        static_pointer_cast<ServerHandler>(shared_from_this()), _1, _2, _3));
    }

    void read_buffer(const c10k::ConnectionPtr &conn, char *st, char *ed)
    {
        using namespace std::placeholders;
        buffer.reserve(len);
        conn->read_async_then(std::back_inserter(buffer), len,
                              std::bind(&ServerHandler::write_back,
                                        std::static_pointer_cast<ServerHandler>(shared_from_this()), _1, _2, _3));
    }

    void write_back(const c10k::ConnectionPtr &conn, char *st, char *ed)
    {
        using namespace std::placeholders;
        std::vector<char> wrt_buffer;
        wrt_buffer.reserve(2 + len);
        std::copy_n((char *)&len, 2, std::back_inserter(wrt_buffer));
        std::copy(buffer.begin(), buffer.end(), std::back_inserter(wrt_buffer));
        conn->write_async_then(wrt_buffer.begin(), wrt_buffer.end(),
                               std::bind(&ServerHandler::close_connection,
                                         std::static_pointer_cast<ServerHandler>(shared_from_this()), _1));
    }

    void close_connection(const c10k::ConnectionPtr &conn)
    {
        conn->close();
    }
};

std::atomic_bool check_ok {true};
std::stringstream ss;

struct ClientHandler: public c10k::Handler
{
    std::vector<char> gen_data()
    {
        std::vector<char> wrt_buffer;
        std::uint16_t len = std::rand() % 32768;
        wrt_buffer.reserve(2 + len);
        std::copy_n((char *)&len, 2, std::back_inserter(wrt_buffer));
        std::generate_n(std::back_inserter(wrt_buffer), len, []() {
            return std::rand() % 128;;
        });
        return wrt_buffer;
    }

    std::vector<char> send_data, recv_data;
    virtual void handle_init(const c10k::ConnectionPtr &conn) override
    {
        using namespace std::placeholders;
        send_data = gen_data();
        conn->write_async(send_data.cbegin(), send_data.cend());
        conn->read_async_then(std::back_inserter(recv_data), send_data.size(),
            std::bind(&ClientHandler::check_data,
                      std::static_pointer_cast<ClientHandler>(shared_from_this()), _1, _2, _3));
    }

    void check_data(const c10k::ConnectionPtr &conn, char *st, char *ed)
    {
        bool ok = true;
        ok &= send_data.size() == recv_data.size();
        if (ok)
            for (int i=0; i<send_data.size(); ++i) {
                ok &= send_data[i] == recv_data[i];
                if (send_data[i] != recv_data[i]) {
                    for (int j=i-5; j < i+5 && j<send_data.size(); ++j)
                        ss << "Pos[" << j << "]: send=" << send_data[j] << " recv=" << recv_data[j] << std::endl;
                    ss << "At pos " << i << " send=" << (int) send_data[i] << " recv=" << (int) recv_data[i] <<
                                   " size=" << recv_data.size() <<
                                   " fd=" << conn->getFD() << std::endl;
                }
            }
        if (check_ok.load() && !ok) {
            check_ok = ok;
            ss << "Err!" << "Send size="<< send_data.size() <<" recv size=" << recv_data.size() << std::endl;
        }
        conn->close();
    }
};

TEST_CASE("multiple WorkerThread test", "[worker_thread]")
{
    using namespace std::chrono_literals;
    using namespace c10k;
    using detail::call_must_ok;
    spdlog::set_level(spdlog::level::debug);
    auto server_logger = spdlog::stdout_color_mt("Server"), client_logger = spdlog::stdout_color_mt("Client");
    detail::WorkerThread<ServerHandler> worker(400, server_logger);

    std::thread server_t {std::ref(worker)};
    static constexpr int TEST_CNT = 600;

    std::thread main_t {[&]() {
        INFO("Main thread entered");
        int main_fd = create_socket();
        INFO("Main thread created");
        sockaddr_in addr = create_addr("127.0.0.1", 6503);
        call_must_ok(::bind, "Bind", main_fd, (sockaddr*)&addr, sizeof(addr));
        call_must_ok(::listen, "Listen", main_fd, 1024);
        INFO("Main thread binded");
        for (int i=0; i<TEST_CNT; ++i)
        {
            int new_sock = call_must_ok(accept, "Accept", main_fd, nullptr, nullptr);
            make_socket_nonblocking(new_sock);
            server_logger->info("new fd created = {}", new_sock);
            worker.add_new_connection(new_sock);
        }
        call_must_ok(::close, "close", main_fd);
    }};
    main_t.detach();
    INFO("Main thread detached");
    cur_sleep_for(1s);
    INFO("Start to create clientWorker");

    detail::WorkerThread<ClientHandler> clientWorker(400, client_logger);
    std::thread client_t {std::ref(clientWorker)};
    INFO("ClientWorker created");

    for (int i=0; i<TEST_CNT; ++i)
    {
        int cli_fd = create_socket(true);
        sockaddr_in addr = create_addr("127.0.0.1", 6503);
        call_must_ok(::connect, "Connect", cli_fd, (sockaddr*)&addr, sizeof(addr));
        INFO("New fd added" << i);
        make_socket_nonblocking(cli_fd);
        clientWorker.add_new_connection(cli_fd);
    }

    server_t.detach(); client_t.detach();
    cur_sleep_for(2s);
    worker.stop(); clientWorker.stop();
    cur_sleep_for(1s);
    INFO(ss.str());
    REQUIRE(check_ok);
}<|endoftext|>


<commit_before>#include "libyaml_utils.h"
#include "logger.h"

// ---------------------------------------------------------------------------------
// ------------------------------- libyaml test code -------------------------------
// ---------------------------------------------------------------------------------
namespace
{
bool positionAnalysis(mode_type* add_to_me, const mode_type reference_character, const bool map_mode)
{
    if (reference_character ==  mode_type::MAP_TYPE)
    {
        if (map_mode)
        {
            *add_to_me =  mode_type::KEY_TYPE;
        }
        else
        {
            *add_to_me =  mode_type::VALUE_TYPE;
        }
        return !map_mode;
    }
    else if (reference_character ==  mode_type::SEQUENCE_TYPE)
    {
        *add_to_me =  mode_type::SEQUENCE_TYPE;
    }
    else
    {
        *add_to_me =  mode_type::UNKNOWN_TYPE;
    }

    return map_mode;
}

void addTag(YAML::Node* current_node, yaml_char_t* tag)
{
    if (tag)
    {
        std::string temp_tag_translator = ((char*)tag);

        current_node->SetTag(temp_tag_translator);
    }
    else if(current_node->Tag().empty())
    {
        current_node->SetTag("?");
    }
}

void addToNode
    (YAML::Node* addToMe, YAML::Node* add_me, std::stack<YAML::Node>* key_stack,
    const mode_type* tracking_current_type, yaml_char_t* tag)
{
    addTag(add_me, tag);
    if (*tracking_current_type ==  mode_type::SEQUENCE_TYPE)
    {
        addToMe->push_back(*add_me);
    }
    else if (*tracking_current_type ==  mode_type::KEY_TYPE)
    {
        key_stack->push(*add_me);
        (*addToMe)[*add_me];
    }
    else if (*tracking_current_type ==  mode_type::VALUE_TYPE)
    {
        (*addToMe)[key_stack->top()] = *add_me;
        key_stack->pop();
    }
}

bool endEventAddition
    (std::vector<YAML::Node>* libyaml_local_output, std::stack<mode_type>* mode_stack,
    std::stack<bool>* map_mode_stack, bool map_mode, std::stack<YAML::Node>* key_stack)
{

    if (libyaml_local_output->size() > 1)
    {
        mode_stack->pop();

        if (mode_stack->top() ==  mode_type::MAP_TYPE)
        {
            map_mode = map_mode_stack->top();
            map_mode_stack->pop();
        }
        mode_type temp_position_info;

        positionAnalysis(&temp_position_info, (mode_stack->top()), !map_mode);

        YAML::Node temp_node = libyaml_local_output->back();

        libyaml_local_output->pop_back();

        if (temp_node.size() <= 0)
        {
            TEST_PPRINT("interesting\n");
        }

        addToNode(&libyaml_local_output->back(), &temp_node, key_stack, &temp_position_info, nullptr);
    }
    return map_mode;
}

void restartVariables (std::stack<YAML::Node>* key_stack,
    std::stack<mode_type>* mode_stack, std::stack<bool>* map_mode_stack,
    std::vector<YAML::Node>* libyaml_local_output, std::vector<YAML::Node>* libyaml_final_output,
    bool* map_mode, std::map<std::string, YAML::Node>* anchor_map)
{
    while (!key_stack->empty())
    {
        key_stack->pop();
    }

    while (!mode_stack->empty())
    {
        mode_stack->pop();
    }
    mode_stack->push(mode_type::UNKNOWN_TYPE);

    while (!map_mode_stack->empty())
    {
        map_mode_stack->pop();
    }

    if (!libyaml_local_output->empty())
    {
        libyaml_final_output->push_back(libyaml_local_output->back());
    }

    libyaml_local_output->clear();

    *map_mode = true;

    anchor_map->clear();
}
}

std::vector<YAML::Node>& libyaml_parsing::parseLibyaml
    (const uint8_t* input, size_t input_size, std::unique_ptr<std::string>* error_message_container)
{
    yaml_parser_t parser;
    yaml_event_t event;

    std::vector<YAML::Node> libyaml_local_output;

    std::vector<YAML::Node>* libyaml_final_output = new std::vector<YAML::Node>;

    std::stack<YAML::Node> key_stack;

    std::stack<mode_type> mode_stack;

    mode_stack.push(mode_type::UNKNOWN_TYPE);

    std::stack<bool> map_mode_stack;

    bool map_mode = true;

    std::map<std::string, YAML::Node> anchor_map;

    if (!yaml_parser_initialize(&parser))
    {
        TEST_PPRINT("ERROR: Failed to initialize\n");

        *error_message_container = std::unique_ptr<std::string>(new std::string("ERROR"));

        return *libyaml_final_output;
    }

    yaml_parser_set_input_string(&parser, input, input_size);

    while (true)
    {

        YAML::Node new_node;

        yaml_event_type_t type;

        mode_type tracking_current_type;

        if (!yaml_parser_parse(&parser, &event))
        {
            yaml_event_delete(&event);

            yaml_parser_delete(&parser);

            TEST_PPRINT("ERROR: Bad parsing\n");

            *error_message_container = std::unique_ptr<std::string>(new std::string("ERROR"));

            return *libyaml_final_output;
        }
        type = event.type;

        switch (type)
        {
            case YAML_STREAM_END_EVENT:

                TEST_PPRINT("STR-\n");

                break;
            case YAML_DOCUMENT_END_EVENT:

                TEST_PPRINT("DOC-\n");

                restartVariables(&key_stack, &mode_stack, &map_mode_stack, &libyaml_local_output,
                    libyaml_final_output, &map_mode, &anchor_map);

                break;
            case YAML_DOCUMENT_START_EVENT:

                TEST_PPRINT("DOC+\n");

                restartVariables(&key_stack, &mode_stack, &map_mode_stack, &libyaml_local_output,
                    libyaml_final_output, &map_mode, &anchor_map);

                break;

            case YAML_MAPPING_END_EVENT:

                TEST_PPRINT("MAP-\n");

                map_mode = endEventAddition(&libyaml_local_output, &mode_stack, &map_mode_stack, map_mode, &key_stack);

                break;
            case YAML_SEQUENCE_END_EVENT:

                TEST_PPRINT("SQU-\n");

                map_mode = endEventAddition(&libyaml_local_output, &mode_stack, &map_mode_stack, map_mode, &key_stack);

                break;
            case YAML_MAPPING_START_EVENT:

                TEST_PPRINT("MAP+\n");

                libyaml_local_output.push_back(YAML::Node(YAML::NodeType::Map));
                addTag(&libyaml_local_output.back(), event.data.sequence_start.tag);

                if (!mode_stack.empty())
                {
                    positionAnalysis(&tracking_current_type, mode_stack.top(), map_mode);
                }

                if (mode_stack.top() ==  mode_type::MAP_TYPE)
                {
                    map_mode_stack.push(!map_mode);
                }

                mode_stack.push(mode_type::MAP_TYPE);
                map_mode = true;

                if (event.data.mapping_start.anchor)
                {
                    TEST_PPRINT("ANCH-map+\n");
                    anchor_map[std::string((char*)event.data.mapping_start.anchor)] = libyaml_local_output.back();
                }

                break;
            case YAML_SEQUENCE_START_EVENT:

                TEST_PPRINT("SQU+\n");

                libyaml_local_output.push_back(YAML::Node(YAML::NodeType::Sequence));
                addTag(&libyaml_local_output.back(), event.data.sequence_start.tag);

                if (mode_stack.top() ==  mode_type::MAP_TYPE)
                {
                    map_mode_stack.push(!map_mode);
                }

                mode_stack.push(mode_type::SEQUENCE_TYPE);

                if (event.data.sequence_start.anchor)
                {
                    TEST_PPRINT("ANCH-squ+\n");

                    anchor_map[std::string((char*)event.data.sequence_start.anchor)] = libyaml_local_output.back();
                }

                break;

            case YAML_SCALAR_EVENT:
            {
                TEST_PPRINT("SCL\n");

                YAML::Node add_me(std::string((char*)event.data.scalar.value, event.data.scalar.length));
                addTag(&add_me, event.data.scalar.tag);

                if (event.data.scalar.anchor)
                {
                    TEST_PPRINT("ANCH-scl\n");
                    std::string temp_translator = ((char*)event.data.scalar.anchor);

                    if (event.data.scalar.value)
                    {

                        TEST_PPRINT("value\n");

                        if(event.data.scalar.length != 0)
                        {
                            anchor_map[temp_translator] = add_me;

                            map_mode = positionAnalysis(&tracking_current_type, mode_stack.top(), map_mode);

                            if (libyaml_local_output.empty())
                            {
                                libyaml_local_output.push_back(add_me);

                            }
                            else
                            {
                                addToNode(&libyaml_local_output.back(), &add_me, &key_stack, &tracking_current_type,
                                    event.data.scalar.tag);
                            }
                        }
                        else
                        {
                            TEST_PPRINT("empty\n");
                            if (mode_stack.top() ==  mode_type::SEQUENCE_TYPE)
                            {
                                TEST_PPRINT("sequence\n");
                                add_me = YAML::Node(YAML::NodeType::Null);

                                libyaml_local_output.back().push_back(add_me);

                                break;
                            }

                            mode_stack.pop();

                            if (!mode_stack.empty())
                            {
                                if (mode_stack.top() ==  mode_type::MAP_TYPE)
                                {
                                    TEST_PPRINT("map\n");
                                    map_mode = map_mode_stack.top();
                                    map_mode_stack.pop();
                                }
                                libyaml_local_output.pop_back();
                            }
                            else
                            {
                                libyaml_local_output.push_back(YAML::Node());
                            }
                        }
                    }
                }
                else
                {
                    TEST_PPRINT("normal\n");
                    map_mode = positionAnalysis(&tracking_current_type, mode_stack.top(), map_mode);

                    if (event.data.scalar.length <= 0 && !event.data.scalar.tag &&
                            event.data.scalar.style == YAML_PLAIN_SCALAR_STYLE)
                    {
                        TEST_PPRINT("Begin from nothing\n");
                        add_me = YAML::Node();
                    }

                    if (libyaml_local_output.empty())
                    {
                        libyaml_local_output.push_back(add_me);
                    }
                    else
                    {
                        addToNode(&libyaml_local_output.back(), &add_me, &key_stack, &tracking_current_type,
                            event.data.scalar.tag);
                    }
                }

                break;
            }
            case YAML_ALIAS_EVENT:
            {

                TEST_PPRINT("ALI\n");

                std::string temp_translator = ((char*) event.data.alias.anchor);

                if(anchor_map.find(temp_translator) != anchor_map.end())
                {
                    map_mode = positionAnalysis(&tracking_current_type, mode_stack.top(), map_mode);

                    addToNode(&libyaml_local_output.back(), &anchor_map[temp_translator],
                        &key_stack, &tracking_current_type, nullptr);
                }
                else
                {
                    yaml_event_delete(&event);

                    yaml_parser_delete(&parser);

                    TEST_PPRINT("ERROR: Missing anchor\n");

                    *error_message_container = std::unique_ptr<std::string>(new std::string("ERROR"));

                    return *libyaml_final_output;
                }
                break;
            }
            default:
                break;
        }

        yaml_event_delete(&event);

        if (type == YAML_STREAM_END_EVENT)
        {
            break;
        }

    }

    yaml_parser_delete(&parser);

    fflush(stdout);

    return *libyaml_final_output;
}<commit_msg>edge handle empty key<commit_after>#include "libyaml_utils.h"
#include "logger.h"

// ---------------------------------------------------------------------------------
// ------------------------------- libyaml test code -------------------------------
// ---------------------------------------------------------------------------------
namespace
{
bool positionAnalysis(mode_type* add_to_me, const mode_type reference_character, const bool map_mode)
{
    if (reference_character ==  mode_type::MAP_TYPE)
    {
        if (map_mode)
        {
            *add_to_me =  mode_type::KEY_TYPE;
        }
        else
        {
            *add_to_me =  mode_type::VALUE_TYPE;
        }
        return !map_mode;
    }
    else if (reference_character ==  mode_type::SEQUENCE_TYPE)
    {
        *add_to_me =  mode_type::SEQUENCE_TYPE;
    }
    else
    {
        *add_to_me =  mode_type::UNKNOWN_TYPE;
    }

    return map_mode;
}

void addTag(YAML::Node* current_node, yaml_char_t* tag)
{
    if (tag)
    {
        std::string temp_tag_translator = ((char*)tag);

        current_node->SetTag(temp_tag_translator);
    }
    else if(current_node->Tag().empty())
    {
        current_node->SetTag("?");
    }
}

void addToNode
    (YAML::Node* addToMe, YAML::Node* add_me, std::stack<YAML::Node>* key_stack,
    const mode_type* tracking_current_type, yaml_char_t* tag)
{
    addTag(add_me, tag);

    if (*tracking_current_type ==  mode_type::SEQUENCE_TYPE)
    {
        TEST_PPRINT("squ type\n")
        addToMe->push_back(*add_me);
    }
    else if (*tracking_current_type ==  mode_type::KEY_TYPE)
    {
        TEST_PPRINT("key type\n")
        key_stack->push(*add_me);
        (*addToMe)[*add_me];
    }
    else if (*tracking_current_type ==  mode_type::VALUE_TYPE)
    {
        TEST_PPRINT("map type\n")
        if (!key_stack->empty())
        {
            (*addToMe)[key_stack->top()] = *add_me;
            key_stack->pop();
        }
    }
    else
    {
        TEST_PPRINT("? type\n")
    }
}

bool endEventAddition
    (std::vector<YAML::Node>* libyaml_local_output, std::stack<mode_type>* mode_stack,
    std::stack<bool>* map_mode_stack, bool map_mode, std::stack<YAML::Node>* key_stack)
{

    if (libyaml_local_output->size() > 1)
    {
        mode_stack->pop();

        if (mode_stack->top() ==  mode_type::MAP_TYPE)
        {
            map_mode = map_mode_stack->top();
            map_mode_stack->pop();
        }
        mode_type temp_position_info;

        positionAnalysis(&temp_position_info, (mode_stack->top()), !map_mode);

        YAML::Node temp_node = libyaml_local_output->back();

        libyaml_local_output->pop_back();

        addToNode(&libyaml_local_output->back(), &temp_node, key_stack, &temp_position_info, nullptr);
    }
    return map_mode;
}

void restartVariables (std::stack<YAML::Node>* key_stack,
    std::stack<mode_type>* mode_stack, std::stack<bool>* map_mode_stack,
    std::vector<YAML::Node>* libyaml_local_output, std::vector<YAML::Node>* libyaml_final_output,
    bool* map_mode, std::map<std::string, YAML::Node>* anchor_map)
{
    while (!key_stack->empty())
    {
        key_stack->pop();
    }

    while (!mode_stack->empty())
    {
        mode_stack->pop();
    }
    mode_stack->push(mode_type::UNKNOWN_TYPE);

    while (!map_mode_stack->empty())
    {
        map_mode_stack->pop();
    }

    if (!libyaml_local_output->empty())
    {
        libyaml_final_output->push_back(libyaml_local_output->back());
    }

    libyaml_local_output->clear();

    *map_mode = true;

    anchor_map->clear();
}
}

std::vector<YAML::Node>& libyaml_parsing::parseLibyaml
    (const uint8_t* input, size_t input_size, std::unique_ptr<std::string>* error_message_container)
{
    yaml_parser_t parser;
    yaml_event_t event;

    std::vector<YAML::Node> libyaml_local_output;

    std::vector<YAML::Node>* libyaml_final_output = new std::vector<YAML::Node>;

    std::stack<YAML::Node> key_stack;

    std::stack<mode_type> mode_stack;

    mode_stack.push(mode_type::UNKNOWN_TYPE);

    std::stack<bool> map_mode_stack;

    bool map_mode = true;

    std::map<std::string, YAML::Node> anchor_map;

    if (!yaml_parser_initialize(&parser))
    {
        TEST_PPRINT("ERROR: Failed to initialize\n");

        *error_message_container = std::unique_ptr<std::string>(new std::string("ERROR"));

        return *libyaml_final_output;
    }

    yaml_parser_set_input_string(&parser, input, input_size);

    while (true)
    {

        YAML::Node new_node;

        yaml_event_type_t type;

        mode_type tracking_current_type;

        if (!yaml_parser_parse(&parser, &event))
        {
            yaml_event_delete(&event);

            yaml_parser_delete(&parser);

            TEST_PPRINT("ERROR: Bad parsing\n");

            *error_message_container = std::unique_ptr<std::string>(new std::string("ERROR"));

            return *libyaml_final_output;
        }
        type = event.type;

        switch (type)
        {
            case YAML_STREAM_END_EVENT:

                TEST_PPRINT("STR-\n");

                break;
            case YAML_DOCUMENT_END_EVENT:

                TEST_PPRINT("DOC-\n");

                restartVariables(&key_stack, &mode_stack, &map_mode_stack, &libyaml_local_output,
                    libyaml_final_output, &map_mode, &anchor_map);

                break;
            case YAML_DOCUMENT_START_EVENT:

                TEST_PPRINT("DOC+\n");

                restartVariables(&key_stack, &mode_stack, &map_mode_stack, &libyaml_local_output,
                    libyaml_final_output, &map_mode, &anchor_map);

                break;

            case YAML_MAPPING_END_EVENT:

                TEST_PPRINT("MAP-\n");

                map_mode = endEventAddition(&libyaml_local_output, &mode_stack, &map_mode_stack, map_mode, &key_stack);

                break;
            case YAML_SEQUENCE_END_EVENT:

                TEST_PPRINT("SQU-\n");

                map_mode = endEventAddition(&libyaml_local_output, &mode_stack, &map_mode_stack, map_mode, &key_stack);

                break;
            case YAML_MAPPING_START_EVENT:

                TEST_PPRINT("MAP+\n");

                libyaml_local_output.push_back(YAML::Node(YAML::NodeType::Map));
                addTag(&libyaml_local_output.back(), event.data.sequence_start.tag);

                if (!mode_stack.empty())
                {
                    positionAnalysis(&tracking_current_type, mode_stack.top(), map_mode);
                }

                if (mode_stack.top() ==  mode_type::MAP_TYPE)
                {
                    map_mode_stack.push(!map_mode);
                }

                mode_stack.push(mode_type::MAP_TYPE);
                map_mode = true;

                if (event.data.mapping_start.anchor)
                {
                    TEST_PPRINT("ANCH-map+\n");
                    anchor_map[std::string((char*)event.data.mapping_start.anchor)] = libyaml_local_output.back();
                }

                break;
            case YAML_SEQUENCE_START_EVENT:

                TEST_PPRINT("SQU+\n");

                libyaml_local_output.push_back(YAML::Node(YAML::NodeType::Sequence));
                addTag(&libyaml_local_output.back(), event.data.sequence_start.tag);

                if (mode_stack.top() ==  mode_type::MAP_TYPE)
                {
                    map_mode_stack.push(!map_mode);
                }

                mode_stack.push(mode_type::SEQUENCE_TYPE);

                if (event.data.sequence_start.anchor)
                {
                    TEST_PPRINT("ANCH-squ+\n");

                    anchor_map[std::string((char*)event.data.sequence_start.anchor)] = libyaml_local_output.back();
                }

                break;

            case YAML_SCALAR_EVENT:
            {
                TEST_PPRINT("SCL\n");

                YAML::Node add_me(std::string((char*)event.data.scalar.value, event.data.scalar.length));
                addTag(&add_me, event.data.scalar.tag);

                if (event.data.scalar.anchor)
                {
                    TEST_PPRINT("ANCH-scl\n");
                    std::string temp_translator = ((char*)event.data.scalar.anchor);

                    if (event.data.scalar.value)
                    {

                        TEST_PPRINT("value\n");

                        if(event.data.scalar.length != 0)
                        {
                            anchor_map[temp_translator] = add_me;

                            map_mode = positionAnalysis(&tracking_current_type, mode_stack.top(), map_mode);

                            if (libyaml_local_output.empty())
                            {
                                libyaml_local_output.push_back(add_me);

                            }
                            else
                            {
                                addToNode(&libyaml_local_output.back(), &add_me, &key_stack, &tracking_current_type,
                                    event.data.scalar.tag);
                            }
                        }
                        else
                        {
                            TEST_PPRINT("empty\n");
                            if (mode_stack.top() ==  mode_type::SEQUENCE_TYPE)
                            {
                                TEST_PPRINT("sequence\n");
                                add_me = YAML::Node(YAML::NodeType::Null);

                                libyaml_local_output.back().push_back(add_me);

                                break;
                            }

                            mode_stack.pop();

                            if (!mode_stack.empty())
                            {
                                if (mode_stack.top() ==  mode_type::MAP_TYPE)
                                {
                                    TEST_PPRINT("map\n");
                                    map_mode = map_mode_stack.top();
                                    map_mode_stack.pop();
                                }
                                libyaml_local_output.pop_back();
                            }
                            else
                            {
                                libyaml_local_output.push_back(YAML::Node());
                            }
                        }
                    }
                }
                else
                {
                    TEST_PPRINT("normal\n");
                    map_mode = positionAnalysis(&tracking_current_type, mode_stack.top(), map_mode);

                    if (event.data.scalar.length <= 0 && !event.data.scalar.tag &&
                            event.data.scalar.style == YAML_PLAIN_SCALAR_STYLE)
                    {
                        TEST_PPRINT("Begin from nothing\n");
                        add_me = YAML::Node();
                    }

                    if (libyaml_local_output.empty())
                    {
                        libyaml_local_output.push_back(add_me);
                    }
                    else
                    {
                        addToNode(&libyaml_local_output.back(), &add_me, &key_stack, &tracking_current_type,
                            event.data.scalar.tag);
                    }
                }

                break;
            }
            case YAML_ALIAS_EVENT:
            {

                TEST_PPRINT("ALI\n");

                std::string temp_translator = ((char*) event.data.alias.anchor);

                if(anchor_map.find(temp_translator) != anchor_map.end())
                {
                    map_mode = positionAnalysis(&tracking_current_type, mode_stack.top(), map_mode);

                    addToNode(&libyaml_local_output.back(), &anchor_map[temp_translator],
                        &key_stack, &tracking_current_type, nullptr);
                }
                else
                {
                    yaml_event_delete(&event);

                    yaml_parser_delete(&parser);

                    TEST_PPRINT("ERROR: Missing anchor\n");

                    *error_message_container = std::unique_ptr<std::string>(new std::string("ERROR"));

                    return *libyaml_final_output;
                }
                break;
            }
            default:
                break;
        }

        yaml_event_delete(&event);

        if (type == YAML_STREAM_END_EVENT)
        {
            break;
        }

    }

    yaml_parser_delete(&parser);

    fflush(stdout);

    return *libyaml_final_output;
}<|endoftext|>


<commit_before>/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
 * This file is part of the LibreOffice project.
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
 *
 * This file incorporates work covered by the following license notice:
 *
 *   Licensed to the Apache Software Foundation (ASF) under one or more
 *   contributor license agreements. See the NOTICE file distributed
 *   with this work for additional information regarding copyright
 *   ownership. The ASF licenses this file to you 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 .
 */

#include <svtools/prnsetup.hxx>
#include <svtools/svtools.hrc>
#include <svtools/svtresid.hxx>
#include <vcl/print.hxx>

// =======================================================================

void ImplFillPrnDlgListBox( const Printer* pPrinter,
                            ListBox* pBox, PushButton* pPropBtn )
{
    ImplFreePrnDlgListBox( pBox );

    const std::vector<OUString>& rPrinters = Printer::GetPrinterQueues();
    unsigned int nCount = rPrinters.size();
    if ( nCount )
    {
        for( unsigned int i = 0; i < nCount; i++ )
            pBox->InsertEntry( rPrinters[i] );
        pBox->SelectEntry( pPrinter->GetName() );
    }

    pBox->Enable( nCount != 0 );
    pPropBtn->Show( pPrinter->HasSupport( SUPPORT_SETUPDIALOG ) );
}

// -----------------------------------------------------------------------

void ImplFreePrnDlgListBox( ListBox* pBox, sal_Bool bClear )
{
    if ( bClear )
        pBox->Clear();
}

// -----------------------------------------------------------------------

Printer* ImplPrnDlgListBoxSelect( ListBox* pBox, PushButton* pPropBtn,
                                  Printer* pPrinter, Printer* pTempPrinter )
{
    if ( pBox->GetSelectEntryPos() != LISTBOX_ENTRY_NOTFOUND )
    {
        const QueueInfo* pInfo = Printer::GetQueueInfo( pBox->GetSelectEntry(), true );
        if( pInfo)
        {
            if ( !pTempPrinter )
            {
                if ( (pPrinter->GetName() == pInfo->GetPrinterName()) &&
                     (pPrinter->GetDriverName() == pInfo->GetDriver()) )
                    pTempPrinter = new Printer( pPrinter->GetJobSetup() );
                else
                    pTempPrinter = new Printer( *pInfo );
            }
            else
            {
                if ( (pTempPrinter->GetName() != pInfo->GetPrinterName()) ||
                     (pTempPrinter->GetDriverName() != pInfo->GetDriver()) )
                {
                    delete pTempPrinter;
                    pTempPrinter = new Printer( *pInfo );
                }
            }

            pPropBtn->Enable( pTempPrinter->HasSupport( SUPPORT_SETUPDIALOG ) );
        }
        else
            pPropBtn->Disable();
    }
    else
        pPropBtn->Disable();

    return pTempPrinter;
}

// -----------------------------------------------------------------------

Printer* ImplPrnDlgUpdatePrinter( Printer* pPrinter, Printer* pTempPrinter )
{
    OUString aPrnName;
    if ( pTempPrinter )
        aPrnName = pTempPrinter->GetName();
    else
        aPrnName = pPrinter->GetName();

    if ( ! Printer::GetQueueInfo( aPrnName, false ) )
    {
        if ( pTempPrinter )
            delete pTempPrinter;
        pTempPrinter = new Printer;
    }

    return pTempPrinter;
}

// -----------------------------------------------------------------------

void ImplPrnDlgUpdateQueueInfo( ListBox* pBox, QueueInfo& rInfo )
{
    if ( pBox->GetSelectEntryPos() != LISTBOX_ENTRY_NOTFOUND )
    {
        const QueueInfo* pInfo = Printer::GetQueueInfo( pBox->GetSelectEntry(), true );
        if( pInfo )
            rInfo = *pInfo;
    }
}

// -----------------------------------------------------------------------

static void ImplPrnDlgAddString( XubString& rStr, const OUString& rAddStr )
{
    if ( rStr.Len() )
        rStr.AppendAscii( "; " );
    rStr += rAddStr;
}

// -----------------------------------------------------------------------

static void ImplPrnDlgAddResString( XubString& rStr, sal_uInt16 nResId )
{
    ImplPrnDlgAddString( rStr, SVT_RESSTR(nResId) );
}

// -----------------------------------------------------------------------

OUString ImplPrnDlgGetStatusText( const QueueInfo& rInfo )
{
    XubString   aStr;
    sal_uLong       nStatus = rInfo.GetStatus();

    // Default-Printer
    if ( !rInfo.GetPrinterName().isEmpty() &&
         (rInfo.GetPrinterName() == Printer::GetDefaultPrinterName()) )
        ImplPrnDlgAddResString( aStr, STR_SVT_PRNDLG_DEFPRINTER );

    // Status
    if ( nStatus & QUEUE_STATUS_READY )
        ImplPrnDlgAddResString( aStr, STR_SVT_PRNDLG_READY );
    if ( nStatus & QUEUE_STATUS_PAUSED )
        ImplPrnDlgAddResString( aStr, STR_SVT_PRNDLG_PAUSED );
    if ( nStatus & QUEUE_STATUS_PENDING_DELETION )
        ImplPrnDlgAddResString( aStr, STR_SVT_PRNDLG_PENDING );
    if ( nStatus & QUEUE_STATUS_BUSY )
        ImplPrnDlgAddResString( aStr, STR_SVT_PRNDLG_BUSY );
    if ( nStatus & QUEUE_STATUS_INITIALIZING )
        ImplPrnDlgAddResString( aStr, STR_SVT_PRNDLG_INITIALIZING );
    if ( nStatus & QUEUE_STATUS_WAITING )
        ImplPrnDlgAddResString( aStr, STR_SVT_PRNDLG_WAITING );
    if ( nStatus & QUEUE_STATUS_WARMING_UP )
        ImplPrnDlgAddResString( aStr, STR_SVT_PRNDLG_WARMING_UP );
    if ( nStatus & QUEUE_STATUS_PROCESSING )
        ImplPrnDlgAddResString( aStr, STR_SVT_PRNDLG_PROCESSING );
    if ( nStatus & QUEUE_STATUS_PRINTING )
        ImplPrnDlgAddResString( aStr, STR_SVT_PRNDLG_PRINTING );
    if ( nStatus & QUEUE_STATUS_OFFLINE )
        ImplPrnDlgAddResString( aStr, STR_SVT_PRNDLG_OFFLINE );
    if ( nStatus & QUEUE_STATUS_ERROR )
        ImplPrnDlgAddResString( aStr, STR_SVT_PRNDLG_ERROR );
    if ( nStatus & QUEUE_STATUS_SERVER_UNKNOWN )
        ImplPrnDlgAddResString( aStr, STR_SVT_PRNDLG_SERVER_UNKNOWN );
    if ( nStatus & QUEUE_STATUS_PAPER_JAM )
        ImplPrnDlgAddResString( aStr, STR_SVT_PRNDLG_PAPER_JAM );
    if ( nStatus & QUEUE_STATUS_PAPER_OUT )
        ImplPrnDlgAddResString( aStr, STR_SVT_PRNDLG_PAPER_OUT );
    if ( nStatus & QUEUE_STATUS_MANUAL_FEED )
        ImplPrnDlgAddResString( aStr, STR_SVT_PRNDLG_MANUAL_FEED );
    if ( nStatus & QUEUE_STATUS_PAPER_PROBLEM )
        ImplPrnDlgAddResString( aStr, STR_SVT_PRNDLG_PAPER_PROBLEM );
    if ( nStatus & QUEUE_STATUS_IO_ACTIVE )
        ImplPrnDlgAddResString( aStr, STR_SVT_PRNDLG_IO_ACTIVE );
    if ( nStatus & QUEUE_STATUS_OUTPUT_BIN_FULL )
        ImplPrnDlgAddResString( aStr, STR_SVT_PRNDLG_OUTPUT_BIN_FULL );
    if ( nStatus & QUEUE_STATUS_TONER_LOW )
        ImplPrnDlgAddResString( aStr, STR_SVT_PRNDLG_TONER_LOW );
    if ( nStatus & QUEUE_STATUS_NO_TONER )
        ImplPrnDlgAddResString( aStr, STR_SVT_PRNDLG_NO_TONER );
    if ( nStatus & QUEUE_STATUS_PAGE_PUNT )
        ImplPrnDlgAddResString( aStr, STR_SVT_PRNDLG_PAGE_PUNT );
    if ( nStatus & QUEUE_STATUS_USER_INTERVENTION )
        ImplPrnDlgAddResString( aStr, STR_SVT_PRNDLG_USER_INTERVENTION );
    if ( nStatus & QUEUE_STATUS_OUT_OF_MEMORY )
        ImplPrnDlgAddResString( aStr, STR_SVT_PRNDLG_OUT_OF_MEMORY );
    if ( nStatus & QUEUE_STATUS_DOOR_OPEN )
        ImplPrnDlgAddResString( aStr, STR_SVT_PRNDLG_DOOR_OPEN );
    if ( nStatus & QUEUE_STATUS_POWER_SAVE )
        ImplPrnDlgAddResString( aStr, STR_SVT_PRNDLG_POWER_SAVE );

    // Anzahl Jobs
    sal_uLong nJobs = rInfo.GetJobs();
    if ( nJobs && (nJobs != QUEUE_JOBS_DONTKNOW) )
    {
        XubString aJobStr( SVT_RESSTR( STR_SVT_PRNDLG_JOBCOUNT ) );
        OUString aJobs( OUString::number( nJobs ) );
        aJobStr.SearchAndReplaceAscii( "%d", aJobs );
        ImplPrnDlgAddString( aStr, aJobStr );
    }

    return aStr;
}

// =======================================================================

PrinterSetupDialog::PrinterSetupDialog(Window* pParent)
    : ModalDialog(pParent, "PrinterSetupDialog",
        "svt/ui/printersetupdialog.ui")
{
    get(m_pLbName, "name");
    m_pLbName->SetStyle(m_pLbName->GetStyle() | WB_SORT);
    get(m_pBtnProperties, "properties");
    get(m_pBtnOptions, "options");
    get(m_pFiStatus, "status");
    get(m_pFiType, "type");
    get(m_pFiLocation, "location");
    get(m_pFiComment, "comment");

    // show options button only if link is set
    m_pBtnOptions->Hide();

    mpPrinter       = NULL;
    mpTempPrinter   = NULL;

    maStatusTimer.SetTimeout( IMPL_PRINTDLG_STATUS_UPDATE );
    maStatusTimer.SetTimeoutHdl( LINK( this, PrinterSetupDialog, ImplStatusHdl ) );
    m_pBtnProperties->SetClickHdl( LINK( this, PrinterSetupDialog, ImplPropertiesHdl ) );
    m_pLbName->SetSelectHdl( LINK( this, PrinterSetupDialog, ImplChangePrinterHdl ) );
}

// -----------------------------------------------------------------------

PrinterSetupDialog::~PrinterSetupDialog()
{
    ImplFreePrnDlgListBox(m_pLbName, sal_False);
    delete mpTempPrinter;
}

// -----------------------------------------------------------------------

void PrinterSetupDialog::SetOptionsHdl( const Link& rLink )
{
    m_pBtnOptions->SetClickHdl( rLink );
    m_pBtnOptions->Show( rLink.IsSet() );
}

void PrinterSetupDialog::ImplSetInfo()
{
    const QueueInfo* pInfo = Printer::GetQueueInfo(m_pLbName->GetSelectEntry(), true);
    if ( pInfo )
    {
        m_pFiType->SetText( pInfo->GetDriver() );
        m_pFiLocation->SetText( pInfo->GetLocation() );
        m_pFiComment->SetText( pInfo->GetComment() );
        m_pFiStatus->SetText( ImplPrnDlgGetStatusText( *pInfo ) );
    }
    else
    {
        OUString aTempStr;
        m_pFiType->SetText( aTempStr );
        m_pFiLocation->SetText( aTempStr );
        m_pFiComment->SetText( aTempStr );
        m_pFiStatus->SetText( aTempStr );
    }
}

// -----------------------------------------------------------------------

IMPL_LINK_NOARG(PrinterSetupDialog, ImplStatusHdl)
{
    QueueInfo aInfo;
    ImplPrnDlgUpdateQueueInfo(m_pLbName, aInfo);
    m_pFiStatus->SetText( ImplPrnDlgGetStatusText( aInfo ) );

    return 0;
}

// -----------------------------------------------------------------------

IMPL_LINK_NOARG(PrinterSetupDialog, ImplPropertiesHdl)
{
    if ( !mpTempPrinter )
        mpTempPrinter = new Printer( mpPrinter->GetJobSetup() );
    mpTempPrinter->Setup( this );

    return 0;
}

// -----------------------------------------------------------------------

IMPL_LINK_NOARG(PrinterSetupDialog, ImplChangePrinterHdl)
{
    mpTempPrinter = ImplPrnDlgListBoxSelect(m_pLbName, m_pBtnProperties,
                                             mpPrinter, mpTempPrinter );
    ImplSetInfo();
    return 0;
}

// -----------------------------------------------------------------------

long PrinterSetupDialog::Notify( NotifyEvent& rNEvt )
{
    if ( (rNEvt.GetType() == EVENT_GETFOCUS) && IsReallyVisible() )
        ImplStatusHdl( &maStatusTimer );

    return ModalDialog::Notify( rNEvt );
}

// -----------------------------------------------------------------------

void PrinterSetupDialog::DataChanged( const DataChangedEvent& rDCEvt )
{
    if ( rDCEvt.GetType() == DATACHANGED_PRINTER )
    {
        mpTempPrinter = ImplPrnDlgUpdatePrinter( mpPrinter, mpTempPrinter );
        Printer* pPrn;
        if ( mpTempPrinter )
            pPrn = mpTempPrinter;
        else
            pPrn = mpPrinter;
        ImplFillPrnDlgListBox(pPrn, m_pLbName, m_pBtnProperties);
        ImplSetInfo();
    }

    ModalDialog::DataChanged( rDCEvt );
}

// -----------------------------------------------------------------------

short PrinterSetupDialog::Execute()
{
    if ( !mpPrinter || mpPrinter->IsPrinting() || mpPrinter->IsJobActive() )
    {
        SAL_WARN( "svtools.dialogs", "PrinterSetupDialog::Execute() - No Printer or printer is printing" );
        return sal_False;
    }

    Printer::updatePrinters();

    ImplFillPrnDlgListBox(mpPrinter, m_pLbName, m_pBtnProperties);
    ImplSetInfo();
    maStatusTimer.Start();

    // Dialog starten
    short nRet = ModalDialog::Execute();

    // Wenn Dialog mit OK beendet wurde, dann die Daten updaten
    if ( nRet == sal_True )
    {
        if ( mpTempPrinter )
            mpPrinter->SetPrinterProps( mpTempPrinter );
    }

    maStatusTimer.Stop();

    return nRet;
}

/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
<commit_msg>make svtools XubString free<commit_after>/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
 * This file is part of the LibreOffice project.
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
 *
 * This file incorporates work covered by the following license notice:
 *
 *   Licensed to the Apache Software Foundation (ASF) under one or more
 *   contributor license agreements. See the NOTICE file distributed
 *   with this work for additional information regarding copyright
 *   ownership. The ASF licenses this file to you 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 .
 */

#include <svtools/prnsetup.hxx>
#include <svtools/svtools.hrc>
#include <svtools/svtresid.hxx>
#include <vcl/print.hxx>

// =======================================================================

void ImplFillPrnDlgListBox( const Printer* pPrinter,
                            ListBox* pBox, PushButton* pPropBtn )
{
    ImplFreePrnDlgListBox( pBox );

    const std::vector<OUString>& rPrinters = Printer::GetPrinterQueues();
    unsigned int nCount = rPrinters.size();
    if ( nCount )
    {
        for( unsigned int i = 0; i < nCount; i++ )
            pBox->InsertEntry( rPrinters[i] );
        pBox->SelectEntry( pPrinter->GetName() );
    }

    pBox->Enable( nCount != 0 );
    pPropBtn->Show( pPrinter->HasSupport( SUPPORT_SETUPDIALOG ) );
}

// -----------------------------------------------------------------------

void ImplFreePrnDlgListBox( ListBox* pBox, sal_Bool bClear )
{
    if ( bClear )
        pBox->Clear();
}

// -----------------------------------------------------------------------

Printer* ImplPrnDlgListBoxSelect( ListBox* pBox, PushButton* pPropBtn,
                                  Printer* pPrinter, Printer* pTempPrinter )
{
    if ( pBox->GetSelectEntryPos() != LISTBOX_ENTRY_NOTFOUND )
    {
        const QueueInfo* pInfo = Printer::GetQueueInfo( pBox->GetSelectEntry(), true );
        if( pInfo)
        {
            if ( !pTempPrinter )
            {
                if ( (pPrinter->GetName() == pInfo->GetPrinterName()) &&
                     (pPrinter->GetDriverName() == pInfo->GetDriver()) )
                    pTempPrinter = new Printer( pPrinter->GetJobSetup() );
                else
                    pTempPrinter = new Printer( *pInfo );
            }
            else
            {
                if ( (pTempPrinter->GetName() != pInfo->GetPrinterName()) ||
                     (pTempPrinter->GetDriverName() != pInfo->GetDriver()) )
                {
                    delete pTempPrinter;
                    pTempPrinter = new Printer( *pInfo );
                }
            }

            pPropBtn->Enable( pTempPrinter->HasSupport( SUPPORT_SETUPDIALOG ) );
        }
        else
            pPropBtn->Disable();
    }
    else
        pPropBtn->Disable();

    return pTempPrinter;
}

// -----------------------------------------------------------------------

Printer* ImplPrnDlgUpdatePrinter( Printer* pPrinter, Printer* pTempPrinter )
{
    OUString aPrnName;
    if ( pTempPrinter )
        aPrnName = pTempPrinter->GetName();
    else
        aPrnName = pPrinter->GetName();

    if ( ! Printer::GetQueueInfo( aPrnName, false ) )
    {
        if ( pTempPrinter )
            delete pTempPrinter;
        pTempPrinter = new Printer;
    }

    return pTempPrinter;
}

// -----------------------------------------------------------------------

void ImplPrnDlgUpdateQueueInfo( ListBox* pBox, QueueInfo& rInfo )
{
    if ( pBox->GetSelectEntryPos() != LISTBOX_ENTRY_NOTFOUND )
    {
        const QueueInfo* pInfo = Printer::GetQueueInfo( pBox->GetSelectEntry(), true );
        if( pInfo )
            rInfo = *pInfo;
    }
}

// -----------------------------------------------------------------------

static OUString ImplPrnDlgAddString(const OUString& rStr, const OUString& rAddStr)
{
    OUString aStr(rStr);
    if (!aStr.isEmpty())
        aStr += "; " ;
    return aStr + rAddStr;
}

// -----------------------------------------------------------------------

static OUString ImplPrnDlgAddResString(const OUString& rStr, sal_uInt16 nResId)
{
    return ImplPrnDlgAddString(rStr, SVT_RESSTR(nResId));
}

// -----------------------------------------------------------------------

OUString ImplPrnDlgGetStatusText( const QueueInfo& rInfo )
{
    OUString aStr;
    sal_uLong nStatus = rInfo.GetStatus();

    // Default-Printer
    if ( !rInfo.GetPrinterName().isEmpty() &&
         (rInfo.GetPrinterName() == Printer::GetDefaultPrinterName()) )
        aStr = ImplPrnDlgAddResString( aStr, STR_SVT_PRNDLG_DEFPRINTER );

    // Status
    if ( nStatus & QUEUE_STATUS_READY )
        aStr = ImplPrnDlgAddResString( aStr, STR_SVT_PRNDLG_READY );
    if ( nStatus & QUEUE_STATUS_PAUSED )
        aStr = ImplPrnDlgAddResString( aStr, STR_SVT_PRNDLG_PAUSED );
    if ( nStatus & QUEUE_STATUS_PENDING_DELETION )
        aStr = ImplPrnDlgAddResString( aStr, STR_SVT_PRNDLG_PENDING );
    if ( nStatus & QUEUE_STATUS_BUSY )
        aStr = ImplPrnDlgAddResString( aStr, STR_SVT_PRNDLG_BUSY );
    if ( nStatus & QUEUE_STATUS_INITIALIZING )
        aStr = ImplPrnDlgAddResString( aStr, STR_SVT_PRNDLG_INITIALIZING );
    if ( nStatus & QUEUE_STATUS_WAITING )
        aStr = ImplPrnDlgAddResString( aStr, STR_SVT_PRNDLG_WAITING );
    if ( nStatus & QUEUE_STATUS_WARMING_UP )
        aStr = ImplPrnDlgAddResString( aStr, STR_SVT_PRNDLG_WARMING_UP );
    if ( nStatus & QUEUE_STATUS_PROCESSING )
        aStr = ImplPrnDlgAddResString( aStr, STR_SVT_PRNDLG_PROCESSING );
    if ( nStatus & QUEUE_STATUS_PRINTING )
        aStr = ImplPrnDlgAddResString( aStr, STR_SVT_PRNDLG_PRINTING );
    if ( nStatus & QUEUE_STATUS_OFFLINE )
        aStr = ImplPrnDlgAddResString( aStr, STR_SVT_PRNDLG_OFFLINE );
    if ( nStatus & QUEUE_STATUS_ERROR )
        aStr = ImplPrnDlgAddResString( aStr, STR_SVT_PRNDLG_ERROR );
    if ( nStatus & QUEUE_STATUS_SERVER_UNKNOWN )
        aStr = ImplPrnDlgAddResString( aStr, STR_SVT_PRNDLG_SERVER_UNKNOWN );
    if ( nStatus & QUEUE_STATUS_PAPER_JAM )
        aStr = ImplPrnDlgAddResString( aStr, STR_SVT_PRNDLG_PAPER_JAM );
    if ( nStatus & QUEUE_STATUS_PAPER_OUT )
        aStr = ImplPrnDlgAddResString( aStr, STR_SVT_PRNDLG_PAPER_OUT );
    if ( nStatus & QUEUE_STATUS_MANUAL_FEED )
        aStr = ImplPrnDlgAddResString( aStr, STR_SVT_PRNDLG_MANUAL_FEED );
    if ( nStatus & QUEUE_STATUS_PAPER_PROBLEM )
        aStr = ImplPrnDlgAddResString( aStr, STR_SVT_PRNDLG_PAPER_PROBLEM );
    if ( nStatus & QUEUE_STATUS_IO_ACTIVE )
        aStr = ImplPrnDlgAddResString( aStr, STR_SVT_PRNDLG_IO_ACTIVE );
    if ( nStatus & QUEUE_STATUS_OUTPUT_BIN_FULL )
        aStr = ImplPrnDlgAddResString( aStr, STR_SVT_PRNDLG_OUTPUT_BIN_FULL );
    if ( nStatus & QUEUE_STATUS_TONER_LOW )
        aStr = ImplPrnDlgAddResString( aStr, STR_SVT_PRNDLG_TONER_LOW );
    if ( nStatus & QUEUE_STATUS_NO_TONER )
        aStr = ImplPrnDlgAddResString( aStr, STR_SVT_PRNDLG_NO_TONER );
    if ( nStatus & QUEUE_STATUS_PAGE_PUNT )
        aStr = ImplPrnDlgAddResString( aStr, STR_SVT_PRNDLG_PAGE_PUNT );
    if ( nStatus & QUEUE_STATUS_USER_INTERVENTION )
        aStr = ImplPrnDlgAddResString( aStr, STR_SVT_PRNDLG_USER_INTERVENTION );
    if ( nStatus & QUEUE_STATUS_OUT_OF_MEMORY )
        aStr = ImplPrnDlgAddResString( aStr, STR_SVT_PRNDLG_OUT_OF_MEMORY );
    if ( nStatus & QUEUE_STATUS_DOOR_OPEN )
        aStr = ImplPrnDlgAddResString( aStr, STR_SVT_PRNDLG_DOOR_OPEN );
    if ( nStatus & QUEUE_STATUS_POWER_SAVE )
        aStr = ImplPrnDlgAddResString( aStr, STR_SVT_PRNDLG_POWER_SAVE );

    // Anzahl Jobs
    sal_uLong nJobs = rInfo.GetJobs();
    if ( nJobs && (nJobs != QUEUE_JOBS_DONTKNOW) )
    {
        OUString aJobStr( SVT_RESSTR( STR_SVT_PRNDLG_JOBCOUNT ) );
        OUString aJobs( OUString::number( nJobs ) );
        aStr = ImplPrnDlgAddString(aStr, aJobStr.replaceAll("%d", aJobs));
    }

    return aStr;
}

// =======================================================================

PrinterSetupDialog::PrinterSetupDialog(Window* pParent)
    : ModalDialog(pParent, "PrinterSetupDialog",
        "svt/ui/printersetupdialog.ui")
{
    get(m_pLbName, "name");
    m_pLbName->SetStyle(m_pLbName->GetStyle() | WB_SORT);
    get(m_pBtnProperties, "properties");
    get(m_pBtnOptions, "options");
    get(m_pFiStatus, "status");
    get(m_pFiType, "type");
    get(m_pFiLocation, "location");
    get(m_pFiComment, "comment");

    // show options button only if link is set
    m_pBtnOptions->Hide();

    mpPrinter       = NULL;
    mpTempPrinter   = NULL;

    maStatusTimer.SetTimeout( IMPL_PRINTDLG_STATUS_UPDATE );
    maStatusTimer.SetTimeoutHdl( LINK( this, PrinterSetupDialog, ImplStatusHdl ) );
    m_pBtnProperties->SetClickHdl( LINK( this, PrinterSetupDialog, ImplPropertiesHdl ) );
    m_pLbName->SetSelectHdl( LINK( this, PrinterSetupDialog, ImplChangePrinterHdl ) );
}

// -----------------------------------------------------------------------

PrinterSetupDialog::~PrinterSetupDialog()
{
    ImplFreePrnDlgListBox(m_pLbName, sal_False);
    delete mpTempPrinter;
}

// -----------------------------------------------------------------------

void PrinterSetupDialog::SetOptionsHdl( const Link& rLink )
{
    m_pBtnOptions->SetClickHdl( rLink );
    m_pBtnOptions->Show( rLink.IsSet() );
}

void PrinterSetupDialog::ImplSetInfo()
{
    const QueueInfo* pInfo = Printer::GetQueueInfo(m_pLbName->GetSelectEntry(), true);
    if ( pInfo )
    {
        m_pFiType->SetText( pInfo->GetDriver() );
        m_pFiLocation->SetText( pInfo->GetLocation() );
        m_pFiComment->SetText( pInfo->GetComment() );
        m_pFiStatus->SetText( ImplPrnDlgGetStatusText( *pInfo ) );
    }
    else
    {
        OUString aTempStr;
        m_pFiType->SetText( aTempStr );
        m_pFiLocation->SetText( aTempStr );
        m_pFiComment->SetText( aTempStr );
        m_pFiStatus->SetText( aTempStr );
    }
}

// -----------------------------------------------------------------------

IMPL_LINK_NOARG(PrinterSetupDialog, ImplStatusHdl)
{
    QueueInfo aInfo;
    ImplPrnDlgUpdateQueueInfo(m_pLbName, aInfo);
    m_pFiStatus->SetText( ImplPrnDlgGetStatusText( aInfo ) );

    return 0;
}

// -----------------------------------------------------------------------

IMPL_LINK_NOARG(PrinterSetupDialog, ImplPropertiesHdl)
{
    if ( !mpTempPrinter )
        mpTempPrinter = new Printer( mpPrinter->GetJobSetup() );
    mpTempPrinter->Setup( this );

    return 0;
}

// -----------------------------------------------------------------------

IMPL_LINK_NOARG(PrinterSetupDialog, ImplChangePrinterHdl)
{
    mpTempPrinter = ImplPrnDlgListBoxSelect(m_pLbName, m_pBtnProperties,
                                             mpPrinter, mpTempPrinter );
    ImplSetInfo();
    return 0;
}

// -----------------------------------------------------------------------

long PrinterSetupDialog::Notify( NotifyEvent& rNEvt )
{
    if ( (rNEvt.GetType() == EVENT_GETFOCUS) && IsReallyVisible() )
        ImplStatusHdl( &maStatusTimer );

    return ModalDialog::Notify( rNEvt );
}

// -----------------------------------------------------------------------

void PrinterSetupDialog::DataChanged( const DataChangedEvent& rDCEvt )
{
    if ( rDCEvt.GetType() == DATACHANGED_PRINTER )
    {
        mpTempPrinter = ImplPrnDlgUpdatePrinter( mpPrinter, mpTempPrinter );
        Printer* pPrn;
        if ( mpTempPrinter )
            pPrn = mpTempPrinter;
        else
            pPrn = mpPrinter;
        ImplFillPrnDlgListBox(pPrn, m_pLbName, m_pBtnProperties);
        ImplSetInfo();
    }

    ModalDialog::DataChanged( rDCEvt );
}

// -----------------------------------------------------------------------

short PrinterSetupDialog::Execute()
{
    if ( !mpPrinter || mpPrinter->IsPrinting() || mpPrinter->IsJobActive() )
    {
        SAL_WARN( "svtools.dialogs", "PrinterSetupDialog::Execute() - No Printer or printer is printing" );
        return sal_False;
    }

    Printer::updatePrinters();

    ImplFillPrnDlgListBox(mpPrinter, m_pLbName, m_pBtnProperties);
    ImplSetInfo();
    maStatusTimer.Start();

    // Dialog starten
    short nRet = ModalDialog::Execute();

    // Wenn Dialog mit OK beendet wurde, dann die Daten updaten
    if ( nRet == sal_True )
    {
        if ( mpTempPrinter )
            mpPrinter->SetPrinterProps( mpTempPrinter );
    }

    maStatusTimer.Stop();

    return nRet;
}

/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
<|endoftext|>


<commit_before>/***********************************************************************************************************************
*                                                                                *
* SPLASH build system v0.2                                                                                *
*                                                                                *
* Copyright (c) 2016 Andrew D. Zonenberg                                                                               *
* All rights reserved.                                                                                *
*                                                                                *
* Redistribution and use in Object and binary forms, with or without modification, are permitted provided that the     *
* following conditions are met:                                                                                *
*                                                                                *
*    * Redistributions of Object code must retain the above copyright notice, this list of conditions, and the         *
*      following disclaimer.                                                                                *
*                                                                                *
*    * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the       *
*      following disclaimer in the documentation and/or other materials provided with the distribution.                *
*                                                                                *
*    * Neither the name of the author nor the names of any contributors may be used to endorse or promote products     *
*      derived from this software without specific prior written permission.                                           *
*                                                                                *
* THIS SOFTWARE IS PROVIDED BY THE AUTHORS "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 AUTHORS BE HELD 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 "splashcore.h"

using namespace std;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Construction / destruction

CPPObjectNode::CPPObjectNode(
	BuildGraph* graph,
	std::string arch,
	std::string config,
	std::string fname,
	std::string path,
	std::string toolchain)
{
/*
		$cc -M -MG
	 */
}

CPPObjectNode::~CPPObjectNode()
{
}

<commit_msg>Added debug log message<commit_after>/***********************************************************************************************************************
*                                                                                *
* SPLASH build system v0.2                                                                                *
*                                                                                *
* Copyright (c) 2016 Andrew D. Zonenberg                                                                               *
* All rights reserved.                                                                                *
*                                                                                *
* Redistribution and use in Object and binary forms, with or without modification, are permitted provided that the     *
* following conditions are met:                                                                                *
*                                                                                *
*    * Redistributions of Object code must retain the above copyright notice, this list of conditions, and the         *
*      following disclaimer.                                                                                *
*                                                                                *
*    * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the       *
*      following disclaimer in the documentation and/or other materials provided with the distribution.                *
*                                                                                *
*    * Neither the name of the author nor the names of any contributors may be used to endorse or promote products     *
*      derived from this software without specific prior written permission.                                           *
*                                                                                *
* THIS SOFTWARE IS PROVIDED BY THE AUTHORS "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 AUTHORS BE HELD 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 "splashcore.h"

using namespace std;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Construction / destruction

CPPObjectNode::CPPObjectNode(
	BuildGraph* graph,
	std::string arch,
	std::string config,
	std::string fname,
	std::string path,
	std::string toolchain)
{
	LogDebug("Creating CPPObjectNode %s\n", fname.c_str());
/*
	$cc -M -MG
 */
}

CPPObjectNode::~CPPObjectNode()
{
}

<|endoftext|>