<commit_before>/*
 * Copyright(c) Sophist Solutions, Inc. 1990-2020.  All rights reserved
 */
#ifndef _Stroika_Foundation_Cache_BloomFilter_inl_
#define _Stroika_Foundation_Cache_BloomFilter_inl_ 1

/*
 ********************************************************************************
 ***************************** Implementation Details ***************************
 ********************************************************************************
 */
#include <cmath>

#include "../Characters/StringBuilder.h"
#include "../Debug/Assertions.h"
#include "../Execution/Exceptions.h"
#include "../Math/Common.h"

namespace Stroika::Foundation::Cache {

    /*
     ********************************************************************************
     ********************** Cache::BloomFilter<T>::Statistics ***********************
     ********************************************************************************
     */
    template <typename T>
    nonvirtual double BloomFilter<T>::Statistics::GetFractionFull () const
    {
        return static_cast<double> (fBitsSet) / static_cast<double> (fBitCount);
    }
    template <typename T>
    Characters::String BloomFilter<T>::Statistics::ToString () const
    {
        Characters::StringBuilder sb;
        sb += L"{";
        sb += L"fHashFunctions: " + Characters::ToString (fHashFunctions) + L", ";
        sb += L"fBitCount: " + Characters::ToString (fBitCount) + L", ";
        sb += L"fBitsSet: " + Characters::ToString (fBitsSet);
        sb += L"}";
        return sb.str ();
    }

    /*
     ********************************************************************************
     ****************************** Cache::BloomFilter ******************************
     ********************************************************************************
     */
    template <typename T>
    inline BloomFilter<T>::BloomFilter (const Containers::Sequence<HashFunctionType>& hashFunctions, size_t bitCount)
        : fHashFunctions_{hashFunctions.template As<vector<HashFunctionType>> ()}
    {
        Require (fHashFunctions_.size () >= 1);
        Require (bitCount >= 1);
        fBits_.resize (bitCount, false);
    }
    template <typename T>
    BloomFilter<T>::BloomFilter (size_t expectedMaxSetSize, const HashFunctionType& defaultHashFunction, double desiredFalsePositivityRate)
    {
        size_t bitCount        = OptimizeBitSize (expectedMaxSetSize, desiredFalsePositivityRate);
        size_t hashFunctionCnt = OptimizeNumberOfHashFunctions (expectedMaxSetSize, bitCount);
        fBits_.resize (bitCount, false);
        fHashFunctions_ = DeriveIndependentHashFunctions (defaultHashFunction, hashFunctionCnt).template As<vector<HashFunctionType>> ();
    }
    template <typename T>
    inline unsigned int BloomFilter<T>::OptimizeBitSize (size_t nElements, double desiredFalsePositiveProbability)
    {
        // based on https://en.wikipedia.org/wiki/Bloom_filter (approximate)
        return static_cast<unsigned int> (::ceil (-static_cast<double> (nElements) * log (desiredFalsePositiveProbability) / log (2) * log (2)));
    }
    template <typename T>
    inline unsigned int BloomFilter<T>::OptimizeNumberOfHashFunctions (size_t setSize, size_t bitSize)
    {
        // based on https://en.wikipedia.org/wiki/Bloom_filter - (m/n)*ln(2)
        return static_cast<unsigned int> (::ceil ((double (bitSize) / setSize) * log (2)));
    }
    template <typename T>
    inline double BloomFilter<T>::ProbabilityOfFalsePositive (size_t hashFunctionCount, size_t bitCount, size_t nElementsInsertedSoFar)
    {
        // From https://en.wikipedia.org/wiki/Bloom_filter
        return ::pow (1 - ::exp (-static_cast<double> (hashFunctionCount * nElementsInsertedSoFar) / bitCount), hashFunctionCount);
    }
    template <typename T>
    inline double BloomFilter<T>::ProbabilityOfFalsePositive (size_t nElementsInsertedSoFar) const
    {
        return ProbabilityOfFalsePositive (fHashFunctions_.size (), fBits_.size (), nElementsInsertedSoFar);
    }
    template <typename T>
    auto BloomFilter<T>::DeriveIndependentHashFunctions (const HashFunctionType& h, size_t repeatCount) -> Containers::Sequence<HashFunctionType>
    {
        Require (repeatCount >= 1);
        /**
         *  From https://en.wikipedia.org/wiki/Bloom_filter
         *
         *      The requirement of designing k different independent hash functions can be prohibitive
         *      for large k. For a good hash function with a wide output, there should be little if any
         *      correlation between different bit-fields of such a hash, so this type of hash can be
         *      used to generate multiple "different" hash functions by slicing its output into multiple
         *      bit fields. Alternatively, one can pass k different initial values (such as 0, 1, ..., k − 1)
         *      to a hash function that takes an initial value; or add (or append) these values to the key
         *
         *  This trick here - is something similar to the suggestions in the wiki article - deriving
         *  a hash function by combining a unique seed (by hashing a constant) and combining that with the
         *  has result of the original function.
         */
        Containers::Sequence<HashFunctionType> result{h};
        for (size_t i = 1; i < repeatCount; ++i) {
            HashResultType seed = Cryptography::Digest::Hash<HashResultType>{}(i);
            result += [=] (const T& t) { return Cryptography::Digest::HashValueCombine (h (t), seed); };
        }
        return result;
    }
    template <typename T>
    void BloomFilter<T>::Add (Configuration::ArgByValueType<T> elt)
    {
        size_t sz{fBits_.size ()};
        for (const HashFunctionType& f : fHashFunctions_) {
            auto v         = f (elt);
            fBits_[v % sz] = true;
        }
    }
    template <typename T>
    inline void BloomFilter<T>::clear ()
    {
        fBits_.clear ();
    }
    template <typename T>
    bool BloomFilter<T>::Contains (Configuration::ArgByValueType<T> elt) const
    {
        size_t sz{fBits_.size ()};
        for (const HashFunctionType& f : fHashFunctions_) {
            if (not fBits_[f (elt) % sz]) {
                return false;
            }
        }
        return true;
    }
    template <typename T>
    auto BloomFilter<T>::GetStatistics () const -> Statistics
    {
        size_t nTrue{};
        for (bool i : fBits_) {
            if (i) {
                nTrue++;
            }
        }
        return Statistics{fHashFunctions_.size (), fBits_.size (), nTrue};
    }

}

#endif /*_Stroika_Foundation_Cache_BloomFilter_inl_*/
<commit_msg>bloomfilter code cleanup<commit_after>/*
 * Copyright(c) Sophist Solutions, Inc. 1990-2020.  All rights reserved
 */
#ifndef _Stroika_Foundation_Cache_BloomFilter_inl_
#define _Stroika_Foundation_Cache_BloomFilter_inl_ 1

/*
 ********************************************************************************
 ***************************** Implementation Details ***************************
 ********************************************************************************
 */
#include <cmath>

#include "../Characters/StringBuilder.h"
#include "../Debug/Assertions.h"
#include "../Execution/Exceptions.h"
#include "../Math/Common.h"

namespace Stroika::Foundation::Cache {

    /*
     ********************************************************************************
     ********************** Cache::BloomFilter<T>::Statistics ***********************
     ********************************************************************************
     */
    template <typename T>
    nonvirtual double BloomFilter<T>::Statistics::GetFractionFull () const
    {
        return static_cast<double> (fBitsSet) / static_cast<double> (fBitCount);
    }
    template <typename T>
    Characters::String BloomFilter<T>::Statistics::ToString () const
    {
        Characters::StringBuilder sb;
        sb += L"{";
        sb += L"fHashFunctions: " + Characters::ToString (fHashFunctions) + L", ";
        sb += L"fBitCount: " + Characters::ToString (fBitCount) + L", ";
        sb += L"fBitsSet: " + Characters::ToString (fBitsSet);
        sb += L"}";
        return sb.str ();
    }

    /*
     ********************************************************************************
     ****************************** Cache::BloomFilter ******************************
     ********************************************************************************
     */
    template <typename T>
    inline BloomFilter<T>::BloomFilter (const Containers::Sequence<HashFunctionType>& hashFunctions, size_t bitCount)
        : fHashFunctions_{hashFunctions.template As<vector<HashFunctionType>> ()}
    {
        Require (fHashFunctions_.size () >= 1);
        Require (bitCount >= 1);
        fBits_.resize (bitCount, false);
    }
    template <typename T>
    BloomFilter<T>::BloomFilter (size_t expectedMaxSetSize, const HashFunctionType& defaultHashFunction, double desiredFalsePositivityRate)
    {
        size_t bitCount        = OptimizeBitSize (expectedMaxSetSize, desiredFalsePositivityRate);
        size_t hashFunctionCnt = OptimizeNumberOfHashFunctions (expectedMaxSetSize, bitCount);
        fBits_.resize (bitCount, false);
        fHashFunctions_ = DeriveIndependentHashFunctions (defaultHashFunction, hashFunctionCnt).template As<vector<HashFunctionType>> ();
    }
    template <typename T>
    inline unsigned int BloomFilter<T>::OptimizeBitSize (size_t nElements, double desiredFalsePositiveProbability)
    {
        // based on https://en.wikipedia.org/wiki/Bloom_filter (approximate)
        return static_cast<unsigned int> (::ceil (-static_cast<double> (nElements) * log (desiredFalsePositiveProbability) / log (2) * log (2)));
    }
    template <typename T>
    inline unsigned int BloomFilter<T>::OptimizeNumberOfHashFunctions (size_t setSize, size_t bitSize)
    {
        // based on https://en.wikipedia.org/wiki/Bloom_filter - (m/n)*ln(2)
        return static_cast<unsigned int> (::ceil ((double (bitSize) / setSize) * log (2)));
    }
    template <typename T>
    inline double BloomFilter<T>::ProbabilityOfFalsePositive (size_t hashFunctionCount, size_t bitCount, size_t nElementsInsertedSoFar)
    {
        // From https://en.wikipedia.org/wiki/Bloom_filter
        return ::pow (1 - ::exp (-static_cast<double> (hashFunctionCount * nElementsInsertedSoFar) / bitCount), hashFunctionCount);
    }
    template <typename T>
    inline double BloomFilter<T>::ProbabilityOfFalsePositive (size_t nElementsInsertedSoFar) const
    {
        return ProbabilityOfFalsePositive (fHashFunctions_.size (), fBits_.size (), nElementsInsertedSoFar);
    }
    template <typename T>
    auto BloomFilter<T>::DeriveIndependentHashFunctions (const HashFunctionType& h, size_t repeatCount) -> Containers::Sequence<HashFunctionType>
    {
        Require (repeatCount >= 1);
        /**
         *  From https://en.wikipedia.org/wiki/Bloom_filter
         *
         *      The requirement of designing k different independent hash functions can be prohibitive
         *      for large k. For a good hash function with a wide output, there should be little if any
         *      correlation between different bit-fields of such a hash, so this type of hash can be
         *      used to generate multiple "different" hash functions by slicing its output into multiple
         *      bit fields. Alternatively, one can pass k different initial values (such as 0, 1, ..., k − 1)
         *      to a hash function that takes an initial value; or add (or append) these values to the key
         *
         *  This trick here - is something similar to the suggestions in the wiki article - deriving
         *  a hash function by combining a unique seed (by hashing a constant) and combining that with the
         *  has result of the original function.
         */
        Containers::Sequence<HashFunctionType> result{h};
        for (size_t i = 1; i < repeatCount; ++i) {
            HashResultType seed = Cryptography::Digest::Hash<HashResultType>{}(i);
            result += [=] (const T& t) { return Cryptography::Digest::HashValueCombine (h (t), seed); };
        }
        return result;
    }
    template <typename T>
    void BloomFilter<T>::Add (Configuration::ArgByValueType<T> elt)
    {
        size_t sz{fBits_.size ()};
        for (const HashFunctionType& f : fHashFunctions_) {
            fBits_[f (elt) % sz] = true;
        }
    }
    template <typename T>
    inline void BloomFilter<T>::clear ()
    {
        fBits_.clear ();
    }
    template <typename T>
    bool BloomFilter<T>::Contains (Configuration::ArgByValueType<T> elt) const
    {
        size_t sz{fBits_.size ()};
        for (const HashFunctionType& f : fHashFunctions_) {
            if (not fBits_[f (elt) % sz]) {
                return false;
            }
        }
        return true;
    }
    template <typename T>
    auto BloomFilter<T>::GetStatistics () const -> Statistics
    {
        size_t nTrue{};
        for (bool i : fBits_) {
            if (i) {
                nTrue++;
            }
        }
        return Statistics{fHashFunctions_.size (), fBits_.size (), nTrue};
    }

}

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


<commit_before>/*
 * Copyright(c) Sophist Solutions, Inc. 1990-2016.  All rights reserved
 */
#include    "../StroikaPreComp.h"

#if     qPlatform_AIX
#include    <sys/stat.h>
#endif

#include    "Process.h"

using   namespace   Stroika::Foundation;
using   namespace   Stroika::Foundation::Configuration;
using   namespace   Stroika::Foundation::Execution;

// Comment this in to turn on aggressive noisy DbgTrace in this module
//#define   USE_NOISY_TRACE_IN_THIS_MODULE_       1

/*
 ********************************************************************************
 ********************** Execution::IsProcessRunning *****************************
 ********************************************************************************
 */

bool    Execution::IsProcessRunning (pid_t pid)
{
#if     USE_NOISY_TRACE_IN_THIS_MODULE_
    Debug::TraceContextBumper traceCtx ("Stroika::Foundation::Execution::IsProcessRunning");
    DbgTrace (L"(pid=%d)", pid);
#endif
#if     qPlatform_AIX
    // sadly getpgid doesnt appear to work on AIX --LGP 2015-11-13
    // From http://stackoverflow.com/questions/9152979/check-if-process-exists-given-its-pid
    struct stat sts;
    char    buf[1024];
    snprintf (buf, NEltsOf(buf), "/proc/%d", pid);
    if (::stat (buf, &sts) == -1 && errno == ENOENT) {
        // process doesn't exist
        return true;
    }
    else {
        return true;
    }
#elif     qPlatform_POSIX
    // http://stackoverflow.com/questions/9152979/check-if-process-exists-given-its-pid
    // http://linux.die.net/man/2/getpgid
    // if not owner, trick of kill (pid, 0) returns error EPERM
    pid_t   tmp { ::getpgid (pid) };
#if     USE_NOISY_TRACE_IN_THIS_MODULE_
    DbgTrace (L"getpgid (pid=%d) -> %d, with ernno=%d", pid, tmp, errno);
#endif
    return tmp > 0;
#else
    AssertNotImplemented ();
    return false;
#endif
}
<commit_msg>probably fixed Execution::IsProcessRunning() for AIX<commit_after>/*
 * Copyright(c) Sophist Solutions, Inc. 1990-2016.  All rights reserved
 */
#include    "../StroikaPreComp.h"

#if     qPlatform_AIX
#include    <sys/stat.h>
#endif

#include    "Process.h"

using   namespace   Stroika::Foundation;
using   namespace   Stroika::Foundation::Configuration;
using   namespace   Stroika::Foundation::Execution;

// Comment this in to turn on aggressive noisy DbgTrace in this module
//#define   USE_NOISY_TRACE_IN_THIS_MODULE_       1

/*
 ********************************************************************************
 ********************** Execution::IsProcessRunning *****************************
 ********************************************************************************
 */

bool    Execution::IsProcessRunning (pid_t pid)
{
#if     USE_NOISY_TRACE_IN_THIS_MODULE_
    Debug::TraceContextBumper traceCtx ("Stroika::Foundation::Execution::IsProcessRunning");
    DbgTrace (L"(pid=%d)", pid);
#endif
#if     qPlatform_AIX
    // sadly getpgid doesnt appear to work on AIX --LGP 2015-11-13
    // From http://stackoverflow.com/questions/9152979/check-if-process-exists-given-its-pid
    struct stat sts;
    char    buf[1024];
    snprintf (buf, NEltsOf(buf), "/proc/%d", pid);
    if (::stat (buf, &sts) == -1 && errno == ENOENT) {
        // process doesn't exist
        return false;
    }
    else {
        return true;
    }
#elif     qPlatform_POSIX
    // http://stackoverflow.com/questions/9152979/check-if-process-exists-given-its-pid
    // http://linux.die.net/man/2/getpgid
    // if not owner, trick of kill (pid, 0) returns error EPERM
    pid_t   tmp { ::getpgid (pid) };
#if     USE_NOISY_TRACE_IN_THIS_MODULE_
    DbgTrace (L"getpgid (pid=%d) -> %d, with ernno=%d", pid, tmp, errno);
#endif
    return tmp > 0;
#else
    AssertNotImplemented ();
    return false;
#endif
}
<|endoftext|>


<commit_before>/*
 * Copyright(c) Sophist Solutions, Inc. 1990-2011.  All rights reserved
 */
#include	"../StroikaPreComp.h"

#include	<map>

#include	"../Debug/Trace.h"
#include	"CriticalSection.h"

#include	"Signals.h"

using	namespace	Stroika::Foundation;
using	namespace	Stroika::Foundation::Execution;

namespace	{
	CriticalSection	sCritSection_;

	map<SignalIDType,set<SignalHandlerType>>	sHandlers_;

	bool	IsSigIgnore_ (const set<SignalHandlerType>& sigSet)
		{
			return sigSet.size () == 1 and *sigSet.begin () == SignalHandlerRegistry::kIGNORED;
		}

	void	MyHandler_ (int signal)
		{
			Debug::TraceContextBumper trcCtx (TSTR ("Stroika::Foundation::Execution::Signals::{}::MyHandler_"));
			DbgTrace ("(signal = %d)", signal);
			set<SignalHandlerType>	handlers;
			{
				AutoCriticalSection critSec (sCritSection_);
				map<SignalIDType,set<SignalHandlerType>>::const_iterator i = sHandlers_.find (signal);
				Assert (i != sHandlers_.end ());
				handlers = i->second;
			}
			for (set<SignalHandlerType>::const_iterator i = handlers.begin (); i != handlers.end (); ++i) {
				if (*i != SignalHandlerRegistry::kIGNORED) {
					(*i) (signal);
				}
			}
		}
}

/*
 ********************************************************************************
 ******************** Execution::SignalHandlerRegistry **************************
 ********************************************************************************
 */

const	SignalHandlerType	SignalHandlerRegistry::kIGNORED	=	SIG_IGN;

SignalHandlerRegistry&	SignalHandlerRegistry::Get ()
{
	static	SignalHandlerRegistry	sThe_;
	return sThe_;
}

SignalHandlerRegistry::SignalHandlerRegistry ()
{
}

set<SignalIDType>	SignalHandlerRegistry::GetHandledSignals () const
{
	set<SignalIDType>	result;
	{
		AutoCriticalSection critSec (sCritSection_);
		for (map<SignalIDType,set<SignalHandlerType>>::const_iterator i = sHandlers_.begin (); i != sHandlers_.end (); ++i) {
			result.insert (i->first);
		}
	}
	return result;
}

set<SignalHandlerType>	SignalHandlerRegistry::GetSignalHandlers (SignalIDType signal) const
{
	AutoCriticalSection critSec (sCritSection_);
	map<SignalIDType,set<SignalHandlerType>>::const_iterator i = sHandlers_.find (signal);
	if (i == sHandlers_.end ()) {
		return set<SignalHandlerType> ();
	}
	else {
		return i->second;
	}
}

void	SignalHandlerRegistry::SetSignalHandlers (SignalIDType signal)
{
	SetSignalHandlers (signal, set<SignalHandlerType> ());
}

void	SignalHandlerRegistry::SetSignalHandlers (SignalIDType signal, SignalHandlerType handler)
{
	SetSignalHandlers (signal, set<SignalHandlerType> (&handler, &handler + 1));
}

void	SignalHandlerRegistry::SetSignalHandlers (SignalIDType signal, const set<SignalHandlerType>& handlers)
{
	Debug::TraceContextBumper trcCtx (TSTR ("Stroika::Foundation::Execution::Signals::{}::SetSignalHandlers"));
	DbgTrace ("(signal = %d, handlers.size (), ....)", signal, handlers.size ());
	AutoCriticalSection critSec (sCritSection_);
	map<SignalIDType,set<SignalHandlerType>>::iterator i = sHandlers_.find (signal);
	if (i == sHandlers_.end ()) {
		if (not handlers.empty ()) {
			sHandlers_.insert (map<SignalIDType,set<SignalHandlerType>>::value_type (signal, handlers));
		}
	}
	else {
		i->second = handlers;
	}
	if (handlers.empty ()) {
		// nothing todo - empty list treated as not in sHandlers_ list
		(void)::signal (signal, SIG_DFL);
	}
	else if (IsSigIgnore_ (handlers)) {
		(void)::signal (signal, SIG_IGN);
	}
	else {
		(void)::signal (signal, MyHandler_);
	}
}

void	SignalHandlerRegistry::AddSignalHandler (SignalIDType signal, SignalHandlerType handler)
{
	set<SignalHandlerType>	s	=	GetSignalHandlers (signal);
	s.insert (handler);
	SetSignalHandlers (signal, s);
}

void	SignalHandlerRegistry::RemoveSignalHandler (SignalIDType signal, SignalHandlerType handler)
{
	set<SignalHandlerType>	s	=	GetSignalHandlers (signal);
	Require (s.find (handler) != s.end ());
	s.erase (handler);
	SetSignalHandlers (signal, s);
}

/*
 ********************************************************************************
 **************************** Execution::SendSignal *****************************
 ********************************************************************************
 */
void	Execution::SendSignal (Thread::NativeHandleType h, SignalIDType signal)
{
	Debug::TraceContextBumper trcCtx (TSTR ("Stroika::Foundation::Execution::Signals::Execution::SendSignal"));
	DbgTrace ("(signal = %d)", signal);
	#if		qPlatform_POSIX
		Verify (pthread_kill (h, signal));
	#else
		AssertNotImplemented ();
	#endif
}
<commit_msg>fixed POSIX signal debugmessage and assertion<commit_after>/*
 * Copyright(c) Sophist Solutions, Inc. 1990-2011.  All rights reserved
 */
#include	"../StroikaPreComp.h"

#include	<map>

#include	"../Debug/Trace.h"
#include	"CriticalSection.h"

#include	"Signals.h"

using	namespace	Stroika::Foundation;
using	namespace	Stroika::Foundation::Execution;

namespace	{
	CriticalSection	sCritSection_;

	map<SignalIDType,set<SignalHandlerType>>	sHandlers_;

	bool	IsSigIgnore_ (const set<SignalHandlerType>& sigSet)
		{
			return sigSet.size () == 1 and *sigSet.begin () == SignalHandlerRegistry::kIGNORED;
		}

	void	MyHandler_ (int signal)
		{
			Debug::TraceContextBumper trcCtx (TSTR ("Stroika::Foundation::Execution::Signals::{}::MyHandler_"));
			DbgTrace ("(signal = %d)", signal);
			set<SignalHandlerType>	handlers;
			{
				AutoCriticalSection critSec (sCritSection_);
				map<SignalIDType,set<SignalHandlerType>>::const_iterator i = sHandlers_.find (signal);
				Assert (i != sHandlers_.end ());
				handlers = i->second;
			}
			for (set<SignalHandlerType>::const_iterator i = handlers.begin (); i != handlers.end (); ++i) {
				if (*i != SignalHandlerRegistry::kIGNORED) {
					(*i) (signal);
				}
			}
		}
}

/*
 ********************************************************************************
 ******************** Execution::SignalHandlerRegistry **************************
 ********************************************************************************
 */

const	SignalHandlerType	SignalHandlerRegistry::kIGNORED	=	SIG_IGN;

SignalHandlerRegistry&	SignalHandlerRegistry::Get ()
{
	static	SignalHandlerRegistry	sThe_;
	return sThe_;
}

SignalHandlerRegistry::SignalHandlerRegistry ()
{
}

set<SignalIDType>	SignalHandlerRegistry::GetHandledSignals () const
{
	set<SignalIDType>	result;
	{
		AutoCriticalSection critSec (sCritSection_);
		for (map<SignalIDType,set<SignalHandlerType>>::const_iterator i = sHandlers_.begin (); i != sHandlers_.end (); ++i) {
			result.insert (i->first);
		}
	}
	return result;
}

set<SignalHandlerType>	SignalHandlerRegistry::GetSignalHandlers (SignalIDType signal) const
{
	AutoCriticalSection critSec (sCritSection_);
	map<SignalIDType,set<SignalHandlerType>>::const_iterator i = sHandlers_.find (signal);
	if (i == sHandlers_.end ()) {
		return set<SignalHandlerType> ();
	}
	else {
		return i->second;
	}
}

void	SignalHandlerRegistry::SetSignalHandlers (SignalIDType signal)
{
	SetSignalHandlers (signal, set<SignalHandlerType> ());
}

void	SignalHandlerRegistry::SetSignalHandlers (SignalIDType signal, SignalHandlerType handler)
{
	SetSignalHandlers (signal, set<SignalHandlerType> (&handler, &handler + 1));
}

void	SignalHandlerRegistry::SetSignalHandlers (SignalIDType signal, const set<SignalHandlerType>& handlers)
{
	Debug::TraceContextBumper trcCtx (TSTR ("Stroika::Foundation::Execution::Signals::{}::SetSignalHandlers"));
	DbgTrace ("(signal = %d, handlers.size () = %d, ....)", signal, handlers.size ());
	AutoCriticalSection critSec (sCritSection_);
	map<SignalIDType,set<SignalHandlerType>>::iterator i = sHandlers_.find (signal);
	if (i == sHandlers_.end ()) {
		if (not handlers.empty ()) {
			sHandlers_.insert (map<SignalIDType,set<SignalHandlerType>>::value_type (signal, handlers));
		}
	}
	else {
		i->second = handlers;
	}
	if (handlers.empty ()) {
		// nothing todo - empty list treated as not in sHandlers_ list
		(void)::signal (signal, SIG_DFL);
	}
	else if (IsSigIgnore_ (handlers)) {
		(void)::signal (signal, SIG_IGN);
	}
	else {
		(void)::signal (signal, MyHandler_);
	}
}

void	SignalHandlerRegistry::AddSignalHandler (SignalIDType signal, SignalHandlerType handler)
{
	set<SignalHandlerType>	s	=	GetSignalHandlers (signal);
	s.insert (handler);
	SetSignalHandlers (signal, s);
}

void	SignalHandlerRegistry::RemoveSignalHandler (SignalIDType signal, SignalHandlerType handler)
{
	set<SignalHandlerType>	s	=	GetSignalHandlers (signal);
	Require (s.find (handler) != s.end ());
	s.erase (handler);
	SetSignalHandlers (signal, s);
}

/*
 ********************************************************************************
 **************************** Execution::SendSignal *****************************
 ********************************************************************************
 */
void	Execution::SendSignal (Thread::NativeHandleType h, SignalIDType signal)
{
	Debug::TraceContextBumper trcCtx (TSTR ("Stroika::Foundation::Execution::Signals::Execution::SendSignal"));
	DbgTrace ("(signal = %d)", signal);
	#if		qPlatform_POSIX
		Verify (pthread_kill (h, signal) == 0);
	#else
		AssertNotImplemented ();
	#endif
}
<|endoftext|>


<commit_before>#include "openrasp_file.h"

static const char* mode_to_type(char *mode)
{
    if (strchr(mode, '+') > mode)
    {
        return "writeFile";
    }
    else if (strchr(mode, 'r') != nullptr)
    {
        return "readFile";
    }
    else
    {
        return "writeFile";
    }
}

static void check_file_operation(const char* type, char *filename, int filename_len, zend_bool use_include_path TSRMLS_DC)
{
    char resolved_path_buff[MAXPATHLEN];
    char *real_path = nullptr;
    real_path = php_resolve_path(filename, filename_len, use_include_path ? PG(include_path) : NULL TSRMLS_CC);
    if (real_path)
    {
        zval *params;
        MAKE_STD_ZVAL(params);
        array_init(params);
        zval *path = NULL;
        MAKE_STD_ZVAL(path);
        ZVAL_STRING(path, filename, 1);
        zval *realpath = NULL;
        MAKE_STD_ZVAL(realpath);
        ZVAL_STRING(realpath, real_path, 1);
        add_assoc_zval(params, "path", path);
        add_assoc_zval(params, "realpath", realpath);
        check(type, params TSRMLS_CC);
    }
}

void hook_file(INTERNAL_FUNCTION_PARAMETERS)
{
    char *filename;
	int filename_len;
	long flags = 0;
    zend_bool use_include_path;
	zval *zcontext = NULL;

	if (openrasp_check_type_ignored(ZEND_STRL("readFile") TSRMLS_CC)
    || zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "p|lr!", &filename, &filename_len, &flags, &zcontext) == FAILURE) {
		return;
	}
    use_include_path = flags & PHP_FILE_USE_INCLUDE_PATH;
    check_file_operation("readFile", filename, filename_len, use_include_path TSRMLS_CC);
}

void hook_readfile(INTERNAL_FUNCTION_PARAMETERS)
{
    char *filename;
	int filename_len;
	zend_bool use_include_path = 0;
	zval *zcontext = NULL;

	if (openrasp_check_type_ignored(ZEND_STRL("readFile") TSRMLS_CC)
    || zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "p|br!", &filename, &filename_len, &use_include_path, &zcontext) == FAILURE) {
		return;
	}
    check_file_operation("readFile", filename, filename_len, use_include_path TSRMLS_CC);
}

void hook_file_get_contents(INTERNAL_FUNCTION_PARAMETERS)
{
    char *filename;
	int filename_len;
	zend_bool use_include_path = 0;
	long offset = -1;
	long maxlen = PHP_STREAM_COPY_ALL;
	zval *zcontext = NULL;

	if (openrasp_check_type_ignored(ZEND_STRL("readFile") TSRMLS_CC)
    || zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "p|br!ll", &filename, &filename_len, &use_include_path, &zcontext, &offset, &maxlen) == FAILURE) {
		return;
	}
    check_file_operation("readFile", filename, filename_len, use_include_path TSRMLS_CC);
}
void hook_file_put_contents(INTERNAL_FUNCTION_PARAMETERS)
{
    zval **path, **data, **flags;
    char resolved_path_buff[MAXPATHLEN];
    int argc = MIN(3, ZEND_NUM_ARGS());
    if (!openrasp_check_type_ignored(ZEND_STRL("writeFile") TSRMLS_CC) &&
        argc > 1 &&
        zend_get_parameters_ex(argc, &path, &data, &flags) == SUCCESS &&
        Z_TYPE_PP(path) == IS_STRING)
    {
        if (!openrasp_check_type_ignored(ZEND_STRL("webshell") TSRMLS_CC)
            && openrasp_zval_in_request(*path TSRMLS_CC)
            && openrasp_zval_in_request(*data TSRMLS_CC))
            {
                zval *attack_params = NULL;
                MAKE_STD_ZVAL(attack_params);
                ZVAL_STRING(attack_params, "", 1);
                zval *plugin_message = NULL;
                MAKE_STD_ZVAL(plugin_message);
                ZVAL_STRING(plugin_message, _("File dropper backdoor"), 1);
                openrasp_buildin_php_risk_handle(1, "webshell", 100, attack_params, plugin_message TSRMLS_CC);
            }
        char *real_path = nullptr;
        char *include_path = nullptr;
        if (argc == 3 && Z_TYPE_PP(flags) == IS_LONG && (Z_LVAL_PP(flags) & PHP_FILE_USE_INCLUDE_PATH))
        {
            include_path = PG(include_path);
        }
        else
        {
            include_path = NULL;
        }
        real_path = php_resolve_path(Z_STRVAL_PP(path), Z_STRLEN_PP(path), include_path TSRMLS_CC);
        zval *params;
        MAKE_STD_ZVAL(params);
        array_init(params);
        add_assoc_zval(params, "path", *path);
        Z_ADDREF_P(*path);
        if (real_path)
        {
            add_assoc_string(params, "realpath", real_path, 1);
        }
        else
        {
            zval *realpath;
            MAKE_STD_ZVAL(realpath);
            ZVAL_STRING(realpath, Z_STRVAL_PP(path), 1);
            add_assoc_zval(params, "realpath", realpath);
        }
        check("writeFile", params TSRMLS_CC);
    }

}
void hook_fopen(INTERNAL_FUNCTION_PARAMETERS)
{
    char *filename, *mode;
	int filename_len, mode_len;
	zend_bool use_include_path = 0;
	zval *zcontext = NULL;

	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ps|br", &filename, &filename_len, &mode, &mode_len, &use_include_path, &zcontext) == FAILURE) {
		return;
	}
    const char *type = mode_to_type(mode);
    if (!openrasp_check_type_ignored(type, strlen(type) TSRMLS_CC))
    {
        check_file_operation(type, filename, filename_len, use_include_path TSRMLS_CC);
    }
}

void hook_splfileobject___construct_ex(INTERNAL_FUNCTION_PARAMETERS)
{
    char *filename, *mode;
	int filename_len, mode_len;
	zend_bool use_include_path = 0;
	zval *zcontext = NULL;

	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "p|sbr", &filename, &filename_len, &mode, &mode_len, &use_include_path, &zcontext) == FAILURE) {
		return;
	}
    const char *type = mode_to_type(mode);
    if (!openrasp_check_type_ignored(type, strlen(type) TSRMLS_CC))
    {
        check_file_operation(type, filename, filename_len, use_include_path TSRMLS_CC);
    }
}

void hook_copy(INTERNAL_FUNCTION_PARAMETERS)
{
    zval **source, **dest;
    int argc = MIN(2, ZEND_NUM_ARGS());
    if (!openrasp_check_type_ignored(ZEND_STRL("writeFile") TSRMLS_CC) &&
        argc > 1 &&
        zend_get_parameters_ex(argc, &source, &dest) == SUCCESS &&
        Z_TYPE_PP(source) == IS_STRING &&
        Z_TYPE_PP(dest) == IS_STRING)
    {
        zval *params;
        MAKE_STD_ZVAL(params);
        array_init(params);
        add_assoc_zval(params, "path", *dest);
        Z_ADDREF_P(*dest);
        add_assoc_zval(params, "realpath", *dest);
        Z_ADDREF_P(*dest);
        check("writeFile", params TSRMLS_CC);
    }
}<commit_msg>openrasp_file.cc zend_parse_params p->s<commit_after>#include "openrasp_file.h"

static const char* mode_to_type(char *mode)
{
    if (strchr(mode, '+') > mode)
    {
        return "writeFile";
    }
    else if (strchr(mode, 'r') != nullptr)
    {
        return "readFile";
    }
    else
    {
        return "writeFile";
    }
}

static void check_file_operation(const char* type, char *filename, int filename_len, zend_bool use_include_path TSRMLS_DC)
{
    char resolved_path_buff[MAXPATHLEN];
    char *real_path = nullptr;
    real_path = php_resolve_path(filename, filename_len, use_include_path ? PG(include_path) : NULL TSRMLS_CC);
    if (real_path)
    {
        zval *params;
        MAKE_STD_ZVAL(params);
        array_init(params);
        zval *path = NULL;
        MAKE_STD_ZVAL(path);
        ZVAL_STRING(path, filename, 1);
        zval *realpath = NULL;
        MAKE_STD_ZVAL(realpath);
        ZVAL_STRING(realpath, real_path, 1);
        add_assoc_zval(params, "path", path);
        add_assoc_zval(params, "realpath", realpath);
        check(type, params TSRMLS_CC);
    }
}

void hook_file(INTERNAL_FUNCTION_PARAMETERS)
{
    char *filename;
	int filename_len;
	long flags = 0;
    zend_bool use_include_path;
	zval *zcontext = NULL;

	if (openrasp_check_type_ignored(ZEND_STRL("readFile") TSRMLS_CC)
    || zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|lr!", &filename, &filename_len, &flags, &zcontext) == FAILURE) {
		return;
	}
    use_include_path = flags & PHP_FILE_USE_INCLUDE_PATH;
    check_file_operation("readFile", filename, filename_len, use_include_path TSRMLS_CC);
}

void hook_readfile(INTERNAL_FUNCTION_PARAMETERS)
{
    char *filename;
	int filename_len;
	zend_bool use_include_path = 0;
	zval *zcontext = NULL;

	if (openrasp_check_type_ignored(ZEND_STRL("readFile") TSRMLS_CC)
    || zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|br!", &filename, &filename_len, &use_include_path, &zcontext) == FAILURE) {
		return;
	}
    check_file_operation("readFile", filename, filename_len, use_include_path TSRMLS_CC);
}

void hook_file_get_contents(INTERNAL_FUNCTION_PARAMETERS)
{
    char *filename;
	int filename_len;
	zend_bool use_include_path = 0;
	long offset = -1;
	long maxlen = PHP_STREAM_COPY_ALL;
	zval *zcontext = NULL;

	if (openrasp_check_type_ignored(ZEND_STRL("readFile") TSRMLS_CC)
    || zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|br!ll", &filename, &filename_len, &use_include_path, &zcontext, &offset, &maxlen) == FAILURE) {
		return;
	}
    check_file_operation("readFile", filename, filename_len, use_include_path TSRMLS_CC);
}
void hook_file_put_contents(INTERNAL_FUNCTION_PARAMETERS)
{
    zval **path, **data, **flags;
    char resolved_path_buff[MAXPATHLEN];
    int argc = MIN(3, ZEND_NUM_ARGS());
    if (!openrasp_check_type_ignored(ZEND_STRL("writeFile") TSRMLS_CC) &&
        argc > 1 &&
        zend_get_parameters_ex(argc, &path, &data, &flags) == SUCCESS &&
        Z_TYPE_PP(path) == IS_STRING)
    {
        if (!openrasp_check_type_ignored(ZEND_STRL("webshell") TSRMLS_CC)
            && openrasp_zval_in_request(*path TSRMLS_CC)
            && openrasp_zval_in_request(*data TSRMLS_CC))
            {
                zval *attack_params = NULL;
                MAKE_STD_ZVAL(attack_params);
                ZVAL_STRING(attack_params, "", 1);
                zval *plugin_message = NULL;
                MAKE_STD_ZVAL(plugin_message);
                ZVAL_STRING(plugin_message, _("File dropper backdoor"), 1);
                openrasp_buildin_php_risk_handle(1, "webshell", 100, attack_params, plugin_message TSRMLS_CC);
            }
        char *real_path = nullptr;
        char *include_path = nullptr;
        if (argc == 3 && Z_TYPE_PP(flags) == IS_LONG && (Z_LVAL_PP(flags) & PHP_FILE_USE_INCLUDE_PATH))
        {
            include_path = PG(include_path);
        }
        else
        {
            include_path = NULL;
        }
        real_path = php_resolve_path(Z_STRVAL_PP(path), Z_STRLEN_PP(path), include_path TSRMLS_CC);
        zval *params;
        MAKE_STD_ZVAL(params);
        array_init(params);
        add_assoc_zval(params, "path", *path);
        Z_ADDREF_P(*path);
        if (real_path)
        {
            add_assoc_string(params, "realpath", real_path, 1);
        }
        else
        {
            zval *realpath;
            MAKE_STD_ZVAL(realpath);
            ZVAL_STRING(realpath, Z_STRVAL_PP(path), 1);
            add_assoc_zval(params, "realpath", realpath);
        }
        check("writeFile", params TSRMLS_CC);
    }

}
void hook_fopen(INTERNAL_FUNCTION_PARAMETERS)
{
    char *filename, *mode;
	int filename_len, mode_len;
	zend_bool use_include_path = 0;
	zval *zcontext = NULL;

	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss|br", &filename, &filename_len, &mode, &mode_len, &use_include_path, &zcontext) == FAILURE) {
		return;
	}
    const char *type = mode_to_type(mode);
    if (!openrasp_check_type_ignored(type, strlen(type) TSRMLS_CC))
    {
        check_file_operation(type, filename, filename_len, use_include_path TSRMLS_CC);
    }
}

void hook_splfileobject___construct_ex(INTERNAL_FUNCTION_PARAMETERS)
{
    char *filename, *mode;
	int filename_len, mode_len;
	zend_bool use_include_path = 0;
	zval *zcontext = NULL;

	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|sbr", &filename, &filename_len, &mode, &mode_len, &use_include_path, &zcontext) == FAILURE) {
		return;
	}
    const char *type = mode_to_type(mode);
    if (!openrasp_check_type_ignored(type, strlen(type) TSRMLS_CC))
    {
        check_file_operation(type, filename, filename_len, use_include_path TSRMLS_CC);
    }
}

void hook_copy(INTERNAL_FUNCTION_PARAMETERS)
{
    zval **source, **dest;
    int argc = MIN(2, ZEND_NUM_ARGS());
    if (!openrasp_check_type_ignored(ZEND_STRL("writeFile") TSRMLS_CC) &&
        argc > 1 &&
        zend_get_parameters_ex(argc, &source, &dest) == SUCCESS &&
        Z_TYPE_PP(source) == IS_STRING &&
        Z_TYPE_PP(dest) == IS_STRING)
    {
        zval *params;
        MAKE_STD_ZVAL(params);
        array_init(params);
        add_assoc_zval(params, "path", *dest);
        Z_ADDREF_P(*dest);
        add_assoc_zval(params, "realpath", *dest);
        Z_ADDREF_P(*dest);
        check("writeFile", params TSRMLS_CC);
    }
}<|endoftext|>


<commit_before>//===- unittest/AST/RecursiveASTMatcherTest.cpp ---------------------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//

#include "clang/AST/ASTConsumer.h"
#include "clang/AST/RecursiveASTVisitor.h"
#include "clang/Frontend/FrontendAction.h"
#include "clang/Frontend/CompilerInstance.h"
#include "clang/Tooling/Tooling.h"
#include "gtest/gtest.h"

namespace clang {

/// \brief Base class for sipmle RecursiveASTVisitor based tests.
///
/// This is a drop-in replacement for RecursiveASTVisitor itself, with the
/// additional capability of running it over a snippet of code.
///
/// Visits template instantiations by default.
///
/// FIXME: Put into a common location.
template <typename T>
class TestVisitor : public clang::RecursiveASTVisitor<T> {
public:
  /// \brief Runs the current AST visitor over the given code.
  bool runOver(StringRef Code) {
    return tooling::runToolOnCode(new TestAction(this), Code);
  }

  bool shouldVisitTemplateInstantiations() const {
    return true;
  }

protected:
  clang::ASTContext *Context;
  clang::SourceManager *SM;

private:
  class FindConsumer : public clang::ASTConsumer {
  public:
    FindConsumer(TestVisitor *Visitor) : Visitor(Visitor) {}

    virtual void HandleTranslationUnit(clang::ASTContext &Context) {
      Visitor->TraverseDecl(Context.getTranslationUnitDecl());
    }

  private:
    TestVisitor *Visitor;
  };

  class TestAction : public clang::ASTFrontendAction {
  public:
    TestAction(TestVisitor *Visitor) : Visitor(Visitor) {}

    virtual clang::ASTConsumer* CreateASTConsumer(
        clang::CompilerInstance& compiler, llvm::StringRef dummy) {
      Visitor->SM = &compiler.getSourceManager();
      Visitor->Context = &compiler.getASTContext();
      /// TestConsumer will be deleted by the framework calling us.
      return new FindConsumer(Visitor);
    }

  private:
    TestVisitor *Visitor;
  };
};

/// \brief A RecursiveASTVisitor for testing the RecursiveASTVisitor itself.
///
/// Allows simple creation of test visitors running matches on only a small
/// subset of the Visit* methods.
template <typename T>
class ExpectedLocationVisitor : public TestVisitor<T> {
public:
  ExpectedLocationVisitor()
    : ExpectedLine(0), ExpectedColumn(0), Found(false) {}

  ~ExpectedLocationVisitor() {
    EXPECT_TRUE(Found)
      << "Expected \"" << ExpectedMatch << "\" at " << ExpectedLine
      << ":" << ExpectedColumn << PartialMatches;
  }

  /// \brief Expect 'Match' to occur at the given 'Line' and 'Column'.
  void ExpectMatch(Twine Match, unsigned Line, unsigned Column) {
    ExpectedMatch = Match.str();
    ExpectedLine = Line;
    ExpectedColumn = Column;
  }

protected:
  /// \brief Convenience method to simplify writing test visitors.
  ///
  /// Sets 'Found' to true if 'Name' and 'Location' match the expected
  /// values. If only a partial match is found, record the information
  /// to produce nice error output when a test fails.
  ///
  /// Implementations are required to call this with appropriate values
  /// for 'Name' during visitation.
  void Match(StringRef Name, SourceLocation Location) {
    FullSourceLoc FullLocation = this->Context->getFullLoc(Location);
    if (Name == ExpectedMatch &&
        FullLocation.isValid() &&
        FullLocation.getSpellingLineNumber() == ExpectedLine &&
        FullLocation.getSpellingColumnNumber() == ExpectedColumn) {
      Found = true;
    } else if (Name == ExpectedMatch ||
               (FullLocation.isValid() &&
                FullLocation.getSpellingLineNumber() == ExpectedLine &&
                FullLocation.getSpellingColumnNumber() == ExpectedColumn)) {
      // If we did not match, record information about partial matches.
      llvm::raw_string_ostream Stream(PartialMatches);
      Stream << ", partial match: \"" << Name << "\" at ";
      Location.print(Stream, *this->SM);
    }
  }

  std::string ExpectedMatch;
  unsigned ExpectedLine;
  unsigned ExpectedColumn;
  std::string PartialMatches;
  bool Found;
};

class TypeLocVisitor : public ExpectedLocationVisitor<TypeLocVisitor> {
public:
  bool VisitTypeLoc(TypeLoc TypeLocation) {
    Match(TypeLocation.getType().getAsString(), TypeLocation.getBeginLoc());
    return true;
  }
};

class DeclRefExprVisitor : public ExpectedLocationVisitor<DeclRefExprVisitor> {
public:
  bool VisitDeclRefExpr(DeclRefExpr *Reference) {
    Match(Reference->getNameInfo().getAsString(), Reference->getLocation());
    return true;
  }
};

class CXXMemberCallVisitor
  : public ExpectedLocationVisitor<CXXMemberCallVisitor> {
public:
  bool VisitCXXMemberCallExpr(CXXMemberCallExpr *Call) {
    Match(Call->getMethodDecl()->getQualifiedNameAsString(),
          Call->getLocStart());
    return true;
  }
};

TEST(RecursiveASTVisitor, VisitsBaseClassDeclarations) {
  TypeLocVisitor Visitor;
  Visitor.ExpectMatch("class X", 1, 30);
  EXPECT_TRUE(Visitor.runOver("class X {}; class Y : public X {};"));
}

TEST(RecursiveASTVisitor, VisitsBaseClassTemplateArguments) {
  DeclRefExprVisitor Visitor;
  Visitor.ExpectMatch("x", 2, 3);
  EXPECT_TRUE(Visitor.runOver(
    "void x(); template <void (*T)()> class X {};\nX<x> y;"));
}

TEST(RecursiveASTVisitor, VisitsCallExpr) {
  DeclRefExprVisitor Visitor;
  Visitor.ExpectMatch("x", 1, 22);
  EXPECT_TRUE(Visitor.runOver(
    "void x(); void y() { x(); }"));
}

TEST(RecursiveASTVisitor, VisitsCallInTemplateInstantiation) {
  CXXMemberCallVisitor Visitor;
  Visitor.ExpectMatch("Y::x", 3, 3);
  EXPECT_TRUE(Visitor.runOver(
    "struct Y { void x(); };\n"
    "template<typename T> void y(T t) {\n"
    "  t.x();\n"
    "}\n"
    "void foo() { y<Y>(Y()); }"));
}

/* FIXME:
TEST(RecursiveASTVisitor, VisitsCallInNestedTemplateInstantiation) {
  CXXMemberCallVisitor Visitor;
  Visitor.ExpectMatch("Y::x", 4, 5);
  EXPECT_TRUE(Visitor.runOver(
    "struct Y { void x(); };\n"
    "template<typename T> struct Z {\n"
    "  template<typename U> static void f() {\n"
    "    T().x();\n"
    "  }\n"
    "};\n"
    "void foo() { Z<Y>::f<int>(); }"));
}
*/

/* FIXME: According to Richard Smith this is a bug in the AST.
TEST(RecursiveASTVisitor, VisitsBaseClassTemplateArgumentsInInstantiation) {
  DeclRefExprVisitor Visitor;
  Visitor.ExpectMatch("x", 3, 43);
  EXPECT_TRUE(Visitor.runOver(
    "template <typename T> void x();\n"
    "template <void (*T)()> class X {};\n"
    "template <typename T> class Y : public X< x<T> > {};\n"
    "Y<int> y;"));
}
*/

} // end namespace clang

<commit_msg>No need to put the SourceManager in with the ASTContext, as the ASTContext already contains the SourceManager.<commit_after>//===- unittest/AST/RecursiveASTMatcherTest.cpp ---------------------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//

#include "clang/AST/ASTConsumer.h"
#include "clang/AST/RecursiveASTVisitor.h"
#include "clang/Frontend/FrontendAction.h"
#include "clang/Frontend/CompilerInstance.h"
#include "clang/Tooling/Tooling.h"
#include "gtest/gtest.h"

namespace clang {

/// \brief Base class for sipmle RecursiveASTVisitor based tests.
///
/// This is a drop-in replacement for RecursiveASTVisitor itself, with the
/// additional capability of running it over a snippet of code.
///
/// Visits template instantiations by default.
///
/// FIXME: Put into a common location.
template <typename T>
class TestVisitor : public clang::RecursiveASTVisitor<T> {
public:
  /// \brief Runs the current AST visitor over the given code.
  bool runOver(StringRef Code) {
    return tooling::runToolOnCode(new TestAction(this), Code);
  }

  bool shouldVisitTemplateInstantiations() const {
    return true;
  }

protected:
  clang::ASTContext *Context;

private:
  class FindConsumer : public clang::ASTConsumer {
  public:
    FindConsumer(TestVisitor *Visitor) : Visitor(Visitor) {}

    virtual void HandleTranslationUnit(clang::ASTContext &Context) {
      Visitor->TraverseDecl(Context.getTranslationUnitDecl());
    }

  private:
    TestVisitor *Visitor;
  };

  class TestAction : public clang::ASTFrontendAction {
  public:
    TestAction(TestVisitor *Visitor) : Visitor(Visitor) {}

    virtual clang::ASTConsumer* CreateASTConsumer(
        clang::CompilerInstance& compiler, llvm::StringRef dummy) {
      Visitor->Context = &compiler.getASTContext();
      /// TestConsumer will be deleted by the framework calling us.
      return new FindConsumer(Visitor);
    }

  private:
    TestVisitor *Visitor;
  };
};

/// \brief A RecursiveASTVisitor for testing the RecursiveASTVisitor itself.
///
/// Allows simple creation of test visitors running matches on only a small
/// subset of the Visit* methods.
template <typename T>
class ExpectedLocationVisitor : public TestVisitor<T> {
public:
  ExpectedLocationVisitor()
    : ExpectedLine(0), ExpectedColumn(0), Found(false) {}

  ~ExpectedLocationVisitor() {
    EXPECT_TRUE(Found)
      << "Expected \"" << ExpectedMatch << "\" at " << ExpectedLine
      << ":" << ExpectedColumn << PartialMatches;
  }

  /// \brief Expect 'Match' to occur at the given 'Line' and 'Column'.
  void ExpectMatch(Twine Match, unsigned Line, unsigned Column) {
    ExpectedMatch = Match.str();
    ExpectedLine = Line;
    ExpectedColumn = Column;
  }

protected:
  /// \brief Convenience method to simplify writing test visitors.
  ///
  /// Sets 'Found' to true if 'Name' and 'Location' match the expected
  /// values. If only a partial match is found, record the information
  /// to produce nice error output when a test fails.
  ///
  /// Implementations are required to call this with appropriate values
  /// for 'Name' during visitation.
  void Match(StringRef Name, SourceLocation Location) {
    FullSourceLoc FullLocation = this->Context->getFullLoc(Location);
    if (Name == ExpectedMatch &&
        FullLocation.isValid() &&
        FullLocation.getSpellingLineNumber() == ExpectedLine &&
        FullLocation.getSpellingColumnNumber() == ExpectedColumn) {
      Found = true;
    } else if (Name == ExpectedMatch ||
               (FullLocation.isValid() &&
                FullLocation.getSpellingLineNumber() == ExpectedLine &&
                FullLocation.getSpellingColumnNumber() == ExpectedColumn)) {
      // If we did not match, record information about partial matches.
      llvm::raw_string_ostream Stream(PartialMatches);
      Stream << ", partial match: \"" << Name << "\" at ";
      Location.print(Stream, this->Context->getSourceManager());
    }
  }

  std::string ExpectedMatch;
  unsigned ExpectedLine;
  unsigned ExpectedColumn;
  std::string PartialMatches;
  bool Found;
};

class TypeLocVisitor : public ExpectedLocationVisitor<TypeLocVisitor> {
public:
  bool VisitTypeLoc(TypeLoc TypeLocation) {
    Match(TypeLocation.getType().getAsString(), TypeLocation.getBeginLoc());
    return true;
  }
};

class DeclRefExprVisitor : public ExpectedLocationVisitor<DeclRefExprVisitor> {
public:
  bool VisitDeclRefExpr(DeclRefExpr *Reference) {
    Match(Reference->getNameInfo().getAsString(), Reference->getLocation());
    return true;
  }
};

class CXXMemberCallVisitor
  : public ExpectedLocationVisitor<CXXMemberCallVisitor> {
public:
  bool VisitCXXMemberCallExpr(CXXMemberCallExpr *Call) {
    Match(Call->getMethodDecl()->getQualifiedNameAsString(),
          Call->getLocStart());
    return true;
  }
};

TEST(RecursiveASTVisitor, VisitsBaseClassDeclarations) {
  TypeLocVisitor Visitor;
  Visitor.ExpectMatch("class X", 1, 30);
  EXPECT_TRUE(Visitor.runOver("class X {}; class Y : public X {};"));
}

TEST(RecursiveASTVisitor, VisitsBaseClassTemplateArguments) {
  DeclRefExprVisitor Visitor;
  Visitor.ExpectMatch("x", 2, 3);
  EXPECT_TRUE(Visitor.runOver(
    "void x(); template <void (*T)()> class X {};\nX<x> y;"));
}

TEST(RecursiveASTVisitor, VisitsCallExpr) {
  DeclRefExprVisitor Visitor;
  Visitor.ExpectMatch("x", 1, 22);
  EXPECT_TRUE(Visitor.runOver(
    "void x(); void y() { x(); }"));
}

TEST(RecursiveASTVisitor, VisitsCallInTemplateInstantiation) {
  CXXMemberCallVisitor Visitor;
  Visitor.ExpectMatch("Y::x", 3, 3);
  EXPECT_TRUE(Visitor.runOver(
    "struct Y { void x(); };\n"
    "template<typename T> void y(T t) {\n"
    "  t.x();\n"
    "}\n"
    "void foo() { y<Y>(Y()); }"));
}

/* FIXME:
TEST(RecursiveASTVisitor, VisitsCallInNestedTemplateInstantiation) {
  CXXMemberCallVisitor Visitor;
  Visitor.ExpectMatch("Y::x", 4, 5);
  EXPECT_TRUE(Visitor.runOver(
    "struct Y { void x(); };\n"
    "template<typename T> struct Z {\n"
    "  template<typename U> static void f() {\n"
    "    T().x();\n"
    "  }\n"
    "};\n"
    "void foo() { Z<Y>::f<int>(); }"));
}
*/

/* FIXME: According to Richard Smith this is a bug in the AST.
TEST(RecursiveASTVisitor, VisitsBaseClassTemplateArgumentsInInstantiation) {
  DeclRefExprVisitor Visitor;
  Visitor.ExpectMatch("x", 3, 43);
  EXPECT_TRUE(Visitor.runOver(
    "template <typename T> void x();\n"
    "template <void (*T)()> class X {};\n"
    "template <typename T> class Y : public X< x<T> > {};\n"
    "Y<int> y;"));
}
*/

} // end namespace clang

<|endoftext|>


<commit_before>/*=========================================================================
 *
 *  Copyright Insight Software Consortium
 *
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 *
 *         http://www.apache.org/licenses/LICENSE-2.0.txt
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 *
 *=========================================================================*/
#include "itkMultiThreaderBase.h"
#include "itkMedianImageFilter.h"

int
main(int argc, char * argv[])
{
  if (argc != 2)
  {
    std::cerr << "Usage: " << std::endl;
    std::cerr << argv[0];
    std::cerr << " <NumberOfThreads>";
    std::cerr << std::endl;
    return EXIT_FAILURE;
  }

  const auto numberOfThreads = std::atoi(argv[1]);

  itk::MultiThreaderBase::SetGlobalDefaultNumberOfThreads(numberOfThreads);

  constexpr unsigned int Dimension = 2;
  using PixelType = float;
  using ImageType = itk::Image<PixelType, Dimension>;
  using FilterType = itk::MedianImageFilter<ImageType, ImageType>;
  FilterType::Pointer filter = FilterType::New();

  const auto filterDefaultThreads = filter->GetMultiThreader()->GetGlobalDefaultNumberOfThreads();
  std::cout << "Filter's default number of threads: " << filterDefaultThreads << std::endl;

  if (filterDefaultThreads != numberOfThreads)
  {
    std::cerr << "Filter does not have expected default number of threads." << std::endl;
    return EXIT_FAILURE;
  }

  return EXIT_SUCCESS;
}
<commit_msg>ENH: Make type sign match for comparison<commit_after>/*=========================================================================
 *
 *  Copyright Insight Software Consortium
 *
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 *
 *         http://www.apache.org/licenses/LICENSE-2.0.txt
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 *
 *=========================================================================*/
#include "itkMultiThreaderBase.h"
#include "itkMedianImageFilter.h"

int
main(int argc, char * argv[])
{
  if (argc != 2)
  {
    std::cerr << "Usage: " << std::endl;
    std::cerr << argv[0];
    std::cerr << " <NumberOfThreads>";
    std::cerr << std::endl;
    return EXIT_FAILURE;
  }

  const auto numberOfThreads = static_cast<unsigned int>(std::atoi(argv[1]));

  itk::MultiThreaderBase::SetGlobalDefaultNumberOfThreads(numberOfThreads);

  constexpr unsigned int Dimension = 2;
  using PixelType = float;
  using ImageType = itk::Image<PixelType, Dimension>;
  using FilterType = itk::MedianImageFilter<ImageType, ImageType>;
  FilterType::Pointer filter = FilterType::New();

  const auto filterDefaultThreads = filter->GetMultiThreader()->GetGlobalDefaultNumberOfThreads();
  std::cout << "Filter's default number of threads: " << filterDefaultThreads << std::endl;

  if (filterDefaultThreads != numberOfThreads)
  {
    std::cerr << "Filter does not have expected default number of threads." << std::endl;
    return EXIT_FAILURE;
  }

  return EXIT_SUCCESS;
}
<|endoftext|>


<commit_before>/**************************************************************************
**
** This file is part of Qt Creator
**
** Copyright (c) 2012 Nokia Corporation and/or its subsidiary(-ies).
**
** Contact: Nokia Corporation (qt-info@nokia.com)
**
**
** GNU Lesser General Public License Usage
**
** This file may be used under the terms of the GNU Lesser General Public
** License version 2.1 as published by the Free Software Foundation and
** appearing in the file LICENSE.LGPL included in the packaging of this file.
** Please review the following information to ensure the GNU Lesser General
** Public License version 2.1 requirements will be met:
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** Other Usage
**
** Alternatively, this file may be used in accordance with the terms and
** conditions contained in a signed written agreement between you and Nokia.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
**
**************************************************************************/

#include "profilemanagerconfigwidget.h"

#include "profile.h"

#include <utils/detailswidget.h>

#include <QHBoxLayout>
#include <QFileDialog>
#include <QGridLayout>
#include <QLabel>
#include <QToolButton>
#include <QScrollArea>
#include <QSizePolicy>
#include <QStyle>

namespace ProjectExplorer {
namespace Internal {

ProfileManagerConfigWidget::ProfileManagerConfigWidget(Profile *p, QWidget *parent) :
    ProfileConfigWidget(parent),
    m_layout(new QGridLayout),
    m_iconButton(new QToolButton),
    m_profile(p)
{
    m_layout->setMargin(0);
    m_layout->setSpacing(6);

    QVBoxLayout *top = new QVBoxLayout(this);
    top->setMargin(0);

    QScrollArea *scroll = new QScrollArea;
    scroll->setFrameShape(QFrame::NoFrame);
    scroll->setWidgetResizable(true);
    scroll->setFocusPolicy(Qt::NoFocus);
    top->addWidget(scroll);

    Utils::DetailsWidget *details = new Utils::DetailsWidget;
    details->setState(Utils::DetailsWidget::NoSummary);
    scroll->setWidget(details);

    QWidget *widget = new QWidget;
    details->setWidget(widget);

    QHBoxLayout *masterLayout = new QHBoxLayout(widget);
    masterLayout->setSpacing(12);

    QVBoxLayout *iconLayout = new QVBoxLayout;
    iconLayout->addWidget(m_iconButton);
    iconLayout->addStretch();

    masterLayout->addLayout(iconLayout);
    masterLayout->addLayout(m_layout);

    discard();

    connect(m_iconButton, SIGNAL(clicked()), this, SLOT(setIcon()));
}

QString ProfileManagerConfigWidget::displayName() const
{
    return tr("Profiles");
}

void ProfileManagerConfigWidget::apply()
{
    foreach (ProfileConfigWidget *w, m_widgets)
        w->apply();
    m_profile->setIconPath(m_iconPath);
}

void ProfileManagerConfigWidget::discard()
{
    foreach (ProfileConfigWidget *w, m_widgets)
        w->discard();
    m_iconButton->setIcon(m_profile->icon());
    m_iconPath = m_profile->iconPath();
}

bool ProfileManagerConfigWidget::isDirty() const
{
    foreach (ProfileConfigWidget *w, m_widgets)
        if (w->isDirty())
            return true;
    return m_profile->iconPath() != m_iconPath;
}

void ProfileManagerConfigWidget::addConfigWidget(ProjectExplorer::ProfileConfigWidget *widget)
{
    Q_ASSERT(widget);
    Q_ASSERT(!m_widgets.contains(widget));

    connect(widget, SIGNAL(dirty()), this, SIGNAL(dirty()));
    int row = m_layout->rowCount();
    m_layout->addWidget(new QLabel(widget->displayName()), row, 0,
                        Qt::Alignment(style()->styleHint(QStyle::SH_FormLayoutLabelAlignment)));
    m_layout->addWidget(widget, row, 1);
    if (widget->buttonWidget())
        m_layout->addWidget(widget->buttonWidget(), row, 2);
    m_widgets.append(widget);
}

void ProfileManagerConfigWidget::makeReadOnly()
{
    foreach (ProfileConfigWidget *w, m_widgets)
        w->makeReadOnly();
    m_iconButton->setEnabled(false);
}

void ProfileManagerConfigWidget::setIcon()
{
    const QString path = QFileDialog::getOpenFileName(0, tr("Select Icon"), m_iconPath, tr("Images (*.png *.xpm *.jpg)"));
    if (path.isEmpty())
        return;

    const QIcon icon = QIcon(path);
    if (icon.isNull())
        return;

    m_iconButton->setIcon(icon);
    m_iconPath = path;
    emit dirty();
}

} // namespace Internal
} // namespace ProjectExplorer
<commit_msg>projectexplorer: improve spacing in profile selection dialog<commit_after>/**************************************************************************
**
** This file is part of Qt Creator
**
** Copyright (c) 2012 Nokia Corporation and/or its subsidiary(-ies).
**
** Contact: Nokia Corporation (qt-info@nokia.com)
**
**
** GNU Lesser General Public License Usage
**
** This file may be used under the terms of the GNU Lesser General Public
** License version 2.1 as published by the Free Software Foundation and
** appearing in the file LICENSE.LGPL included in the packaging of this file.
** Please review the following information to ensure the GNU Lesser General
** Public License version 2.1 requirements will be met:
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** Other Usage
**
** Alternatively, this file may be used in accordance with the terms and
** conditions contained in a signed written agreement between you and Nokia.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
**
**************************************************************************/

#include "profilemanagerconfigwidget.h"

#include "profile.h"

#include <utils/detailswidget.h>

#include <QHBoxLayout>
#include <QFileDialog>
#include <QGridLayout>
#include <QLabel>
#include <QToolButton>
#include <QScrollArea>
#include <QSizePolicy>
#include <QStyle>

namespace ProjectExplorer {
namespace Internal {

ProfileManagerConfigWidget::ProfileManagerConfigWidget(Profile *p, QWidget *parent) :
    ProfileConfigWidget(parent),
    m_layout(new QGridLayout),
    m_iconButton(new QToolButton),
    m_profile(p)
{
    m_layout->setMargin(0);
    m_layout->setSpacing(6);
    m_layout->setContentsMargins(0, 0, 0, 0);

    QVBoxLayout *top = new QVBoxLayout(this);
    top->setMargin(0);

    QScrollArea *scroll = new QScrollArea;
    scroll->setFrameShape(QFrame::NoFrame);
    scroll->setWidgetResizable(true);
    scroll->setFocusPolicy(Qt::NoFocus);
    top->addWidget(scroll);

    Utils::DetailsWidget *details = new Utils::DetailsWidget;
    details->setState(Utils::DetailsWidget::NoSummary);
    scroll->setWidget(details);

    QWidget *widget = new QWidget;
    details->setWidget(widget);

    QVBoxLayout *iconLayout = new QVBoxLayout;
    iconLayout->addWidget(m_iconButton);
    iconLayout->addStretch();

    QHBoxLayout *spacer = new QHBoxLayout;
    spacer->addItem(new QSpacerItem(1, 1, QSizePolicy::Fixed, QSizePolicy::MinimumExpanding));

    QGridLayout *masterLayout = new QGridLayout(widget);
    masterLayout->setMargin(0);
    masterLayout->setContentsMargins(6, 0, 6, 0);
    masterLayout->addLayout(iconLayout, 0, 0);
    masterLayout->addLayout(m_layout, 0, 1);
    masterLayout->addLayout(spacer, 1, 0);

    discard();

    connect(m_iconButton, SIGNAL(clicked()), this, SLOT(setIcon()));
}

QString ProfileManagerConfigWidget::displayName() const
{
    return tr("Profiles");
}

void ProfileManagerConfigWidget::apply()
{
    foreach (ProfileConfigWidget *w, m_widgets)
        w->apply();
    m_profile->setIconPath(m_iconPath);
}

void ProfileManagerConfigWidget::discard()
{
    foreach (ProfileConfigWidget *w, m_widgets)
        w->discard();
    m_iconButton->setIcon(m_profile->icon());
    m_iconPath = m_profile->iconPath();
}

bool ProfileManagerConfigWidget::isDirty() const
{
    foreach (ProfileConfigWidget *w, m_widgets)
        if (w->isDirty())
            return true;
    return m_profile->iconPath() != m_iconPath;
}

void ProfileManagerConfigWidget::addConfigWidget(ProjectExplorer::ProfileConfigWidget *widget)
{
    Q_ASSERT(widget);
    Q_ASSERT(!m_widgets.contains(widget));

    connect(widget, SIGNAL(dirty()), this, SIGNAL(dirty()));
    int row = m_layout->rowCount();
    m_layout->addWidget(new QLabel(widget->displayName()), row, 0,
                        Qt::Alignment(style()->styleHint(QStyle::SH_FormLayoutLabelAlignment)));
    m_layout->addWidget(widget, row, 1);
    if (widget->buttonWidget())
        m_layout->addWidget(widget->buttonWidget(), row, 2);
    m_widgets.append(widget);
}

void ProfileManagerConfigWidget::makeReadOnly()
{
    foreach (ProfileConfigWidget *w, m_widgets)
        w->makeReadOnly();
    m_iconButton->setEnabled(false);
}

void ProfileManagerConfigWidget::setIcon()
{
    const QString path = QFileDialog::getOpenFileName(0, tr("Select Icon"), m_iconPath, tr("Images (*.png *.xpm *.jpg)"));
    if (path.isEmpty())
        return;

    const QIcon icon = QIcon(path);
    if (icon.isNull())
        return;

    m_iconButton->setIcon(icon);
    m_iconPath = path;
    emit dirty();
}

} // namespace Internal
} // namespace ProjectExplorer
<|endoftext|>


<commit_before>/****************************************************************************
**
** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of Qt Creator.
**
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Digia.  For licensing terms and
** conditions see http://qt.digia.com/licensing.  For further information
** use the contact form at http://qt.digia.com/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file.  Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Digia gives you certain additional
** rights.  These rights are described in the Digia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
****************************************************************************/

#include "debugview.h"
#include "debugviewwidget.h"

#include <qmldesignerplugin.h>
#include <designersettings.h>

#include <bindingproperty.h>
#include <nodeabstractproperty.h>
#include <variantproperty.h>

namespace   {
const QLatin1String lineBreak = QLatin1String("
");

bool isDebugViewEnabled()
{
    return (QmlDesigner::QmlDesignerPlugin::instance()->settings().enableDebugView);
}

bool isDebugViewShown()
{
    return (QmlDesigner::QmlDesignerPlugin::instance()->settings().showDebugView);
}

}

namespace QmlDesigner {

namespace  Internal {

DebugView::DebugView(QObject *parent) : QmlModelView(parent),
    m_debugViewWidget(new DebugViewWidget)
{
}

DebugView::~DebugView()
{
}

void DebugView::modelAttached(Model *model)
{
    log(tr("Model attached"), tr("FileName %1").arg(model->fileUrl().toLocalFile()));
    m_debugViewWidget->setDebugViewEnabled(isDebugViewEnabled());
    qDebug() << "enabled: " << isDebugViewEnabled();
    QmlModelView::modelAttached(model);
}

void DebugView::modelAboutToBeDetached(Model *model)
{
    log(tr("Model detached"), tr("FileName %1").arg(model->fileUrl().toLocalFile()));
    QmlModelView::modelAboutToBeDetached(model);
}

void DebugView::importsChanged(const QList<Import> &addedImports, const QList<Import> &removedImports)
{
    if (isDebugViewEnabled()) {
        QString message;
        message += tr("Added imports:") += lineBreak;
        foreach (const Import &import, addedImports) {
            message += import.toString() += lineBreak;
        }

        message += tr("Removed imports:") += lineBreak;
        foreach (const Import &import, removedImports) {
            message += import.toString() += lineBreak;
        }

        log(tr("Imports changed:"), message);
    }
}

void DebugView::nodeCreated(const ModelNode &createdNode)
{
    if (isDebugViewEnabled()) {
        QTextStream message;
        QString string;
        message.setString(&string);
        message << createdNode;
        log(tr("Node created:"), message.readAll());
    }
}

void DebugView::nodeAboutToBeRemoved(const ModelNode &removedNode)
{
    if (isDebugViewEnabled()) {
        QTextStream message;
        QString string;
        message.setString(&string);
        message << removedNode;
        log(tr("Node removed:"), message.readAll());
    }
}

void DebugView::nodeReparented(const ModelNode &node, const NodeAbstractProperty &newPropertyParent,
                               const NodeAbstractProperty &oldPropertyParent, AbstractView::PropertyChangeFlags propertyChange)
{
    if (isDebugViewEnabled()) {
        QTextStream message;
        QString string;
        message.setString(&string);
        message << node;
        message << tr("New parent property:");
        message << lineBreak;
        message << newPropertyParent;
        message << tr("Old parent property:");
        message << lineBreak;
        message << oldPropertyParent;
        message << tr("PropertyChangeFlag");
        message << lineBreak;
        message << propertyChange;
        log(tr("Node reparanted:"), message.readAll());
    }
}

void DebugView::nodeIdChanged(const ModelNode &node, const QString &newId, const QString &oldId)
{
    if (isDebugViewEnabled()) {
        QTextStream message;
        QString string;
        message.setString(&string);
        message << node;
        message << tr("New Id: ") << newId << lineBreak;
        message << tr("Old Id: ") << oldId << lineBreak;
        log(tr("Node id changed:"), string);
    }
}

void DebugView::propertiesAboutToBeRemoved(const QList<AbstractProperty> & /*propertyList*/)
{
}

void DebugView::variantPropertiesChanged(const QList<VariantProperty> &propertyList,
                                         AbstractView::PropertyChangeFlags /*propertyChange*/)
{
    if (isDebugViewEnabled()) {
        QTextStream message;
        QString string;
        message.setString(&string);
        foreach (const VariantProperty &property, propertyList) {
            message << property;
        }
        log(tr("VariantProperties changed:"), string);
    }
}

void DebugView::bindingPropertiesChanged(const QList<BindingProperty> &propertyList,
                                         AbstractView::PropertyChangeFlags /*propertyChange*/)
{
    if (isDebugViewEnabled()) {
        QTextStream message;
        QString string;
        message.setString(&string);
        foreach (const BindingProperty &property, propertyList) {
            message << property;
        }
        log(tr("BindingProperties changed:"), string);
    }
}

void DebugView::rootNodeTypeChanged(const QString &type, int majorVersion, int minorVersion)
{
    if (isDebugViewEnabled()) {
        QString message;
        message += type;
        message += QLatin1String(" ");
        message += QString::number(majorVersion);
        message += QLatin1String(" ");
        message += QString::number(minorVersion);
        log(tr("Node id changed:"), message);
    }
}

void DebugView::selectedNodesChanged(const QList<ModelNode> & /*selectedNodeList*/,
                                     const QList<ModelNode> & /*lastSelectedNodeList*/)
{
}

void DebugView::scriptFunctionsChanged(const ModelNode & /*node*/, const QStringList & /*scriptFunctionList*/)
{
}

void DebugView::propertiesRemoved(const QList<AbstractProperty> &propertyList)
{
    if (isDebugViewEnabled()) {
        QTextStream message;
        QString string;
        message.setString(&string);
        foreach (const AbstractProperty &property, propertyList) {
            message << property;
        }
        log(tr("Properties removed:"), string);
    }
}

void DebugView::auxiliaryDataChanged(const ModelNode &node, const PropertyName &name, const QVariant &data)
{
    if (isDebugViewEnabled()) {
        QTextStream message;
        QString string;
        message.setString(&string);

        message << node;
        message << name;
        message << data.toString();

        log(tr("Auxiliary Data Changed:"), string);
    }
}

void DebugView::rewriterBeginTransaction()
{
    if (isDebugViewEnabled())
        log(tr("Begin rewriter transaction"), QString(), true);
}

void DebugView::rewriterEndTransaction()
{
    if (isDebugViewEnabled())
        log(tr("End rewriter transaction"), QString(), true);
}

WidgetInfo DebugView::widgetInfo()
{
    return createWidgetInfo(m_debugViewWidget.data(), "DebugView", WidgetInfo::LeftPane, 0, tr("Debug View"));
}

bool DebugView::hasWidget() const
{
    if (isDebugViewShown())
        return true;

    return false;
}

void DebugView::instancePropertyChange(const QList<QPair<ModelNode, PropertyName> > &propertyList)
{
    if (isDebugViewEnabled()) {
        QTextStream message;
        QString string;
        message.setString(&string);

        typedef QPair<ModelNode, PropertyName> Pair;

        foreach (const Pair &pair, propertyList) {
            message << pair.first;
            message << lineBreak;
            message << pair.second;
        }

        logInstance(tr("Instance property change"), string);
    }
}

void DebugView::instancesCompleted(const QVector<ModelNode> &completedNodeList)
{
    if (isDebugViewEnabled()) {
        QTextStream message;
        QString string;
        message.setString(&string);

        foreach (const ModelNode &modelNode, completedNodeList) {
            message << modelNode;
        }

        logInstance(tr("Instance Completed"), string);
    }
}

void DebugView::instanceInformationsChange(const QMultiHash<ModelNode, InformationName> &informationChangeHash)
{
    if (isDebugViewEnabled()) {
        QTextStream message;
        QString string;
        message.setString(&string);

        foreach (const ModelNode &modelNode, informationChangeHash.keys()) {
            message << modelNode;
            message << informationChangeHash.value(modelNode);
        }

        logInstance(tr("Instance Completed"), string);
    }

}

void DebugView::instancesRenderImageChanged(const QVector<ModelNode> & /*nodeList*/)
{
}

void DebugView::instancesPreviewImageChanged(const QVector<ModelNode> & /*nodeList*/)
{
}

void DebugView::instancesChildrenChanged(const QVector<ModelNode> & /*nodeList*/)
{
}

void DebugView::customNotification(const AbstractView *view, const QString &identifier, const QList<ModelNode> &nodeList, const QList<QVariant> &data)
{
    if (isDebugViewEnabled()) {
        QTextStream message;
        QString string;
        message.setString(&string);

        message << view;
        message << identifier;
        foreach (const ModelNode &node, nodeList) {
            message << node;
        }

        foreach (const QVariant &variant, data) {
            message << variant.toString();
        }

        log(tr("Custom Notification:"), string);
    }
}

void DebugView::nodeSourceChanged(const ModelNode &modelNode, const QString &newNodeSource)
{
    if (isDebugViewEnabled()) {
        QTextStream message;
        QString string;
        message.setString(&string);

        message << modelNode;
        message << newNodeSource;

        log(tr("Node Source Changed:"), string);
    }
}

void DebugView::log(const QString &title, const QString &message, bool highlight)
{
    m_debugViewWidget->addLogMessage(title, message, highlight);
}

void DebugView::logInstance(const QString &title, const QString &message, bool highlight)
{
    m_debugViewWidget->addLogInstanceMessage(title, message, highlight);
}

} // namesapce Internal

} // namespace QmlDesigner
<commit_msg>QmlDesigner: QLatin1Fix<commit_after>/****************************************************************************
**
** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of Qt Creator.
**
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Digia.  For licensing terms and
** conditions see http://qt.digia.com/licensing.  For further information
** use the contact form at http://qt.digia.com/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file.  Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Digia gives you certain additional
** rights.  These rights are described in the Digia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
****************************************************************************/

#include "debugview.h"
#include "debugviewwidget.h"

#include <qmldesignerplugin.h>
#include <designersettings.h>

#include <bindingproperty.h>
#include <nodeabstractproperty.h>
#include <variantproperty.h>

namespace   {
const QLatin1String lineBreak = QLatin1String("
");

bool isDebugViewEnabled()
{
    return (QmlDesigner::QmlDesignerPlugin::instance()->settings().enableDebugView);
}

bool isDebugViewShown()
{
    return (QmlDesigner::QmlDesignerPlugin::instance()->settings().showDebugView);
}

}

namespace QmlDesigner {

namespace  Internal {

DebugView::DebugView(QObject *parent) : QmlModelView(parent),
    m_debugViewWidget(new DebugViewWidget)
{
}

DebugView::~DebugView()
{
}

void DebugView::modelAttached(Model *model)
{
    log(tr("Model attached"), tr("FileName %1").arg(model->fileUrl().toLocalFile()));
    m_debugViewWidget->setDebugViewEnabled(isDebugViewEnabled());
    qDebug() << "enabled: " << isDebugViewEnabled();
    QmlModelView::modelAttached(model);
}

void DebugView::modelAboutToBeDetached(Model *model)
{
    log(tr("Model detached"), tr("FileName %1").arg(model->fileUrl().toLocalFile()));
    QmlModelView::modelAboutToBeDetached(model);
}

void DebugView::importsChanged(const QList<Import> &addedImports, const QList<Import> &removedImports)
{
    if (isDebugViewEnabled()) {
        QString message;
        message += tr("Added imports:") += lineBreak;
        foreach (const Import &import, addedImports) {
            message += import.toString() += lineBreak;
        }

        message += tr("Removed imports:") += lineBreak;
        foreach (const Import &import, removedImports) {
            message += import.toString() += lineBreak;
        }

        log(tr("Imports changed:"), message);
    }
}

void DebugView::nodeCreated(const ModelNode &createdNode)
{
    if (isDebugViewEnabled()) {
        QTextStream message;
        QString string;
        message.setString(&string);
        message << createdNode;
        log(tr("Node created:"), message.readAll());
    }
}

void DebugView::nodeAboutToBeRemoved(const ModelNode &removedNode)
{
    if (isDebugViewEnabled()) {
        QTextStream message;
        QString string;
        message.setString(&string);
        message << removedNode;
        log(tr("Node removed:"), message.readAll());
    }
}

void DebugView::nodeReparented(const ModelNode &node, const NodeAbstractProperty &newPropertyParent,
                               const NodeAbstractProperty &oldPropertyParent, AbstractView::PropertyChangeFlags propertyChange)
{
    if (isDebugViewEnabled()) {
        QTextStream message;
        QString string;
        message.setString(&string);
        message << node;
        message << tr("New parent property:");
        message << lineBreak;
        message << newPropertyParent;
        message << tr("Old parent property:");
        message << lineBreak;
        message << oldPropertyParent;
        message << tr("PropertyChangeFlag");
        message << lineBreak;
        message << propertyChange;
        log(tr("Node reparanted:"), message.readAll());
    }
}

void DebugView::nodeIdChanged(const ModelNode &node, const QString &newId, const QString &oldId)
{
    if (isDebugViewEnabled()) {
        QTextStream message;
        QString string;
        message.setString(&string);
        message << node;
        message << tr("New Id: ") << newId << lineBreak;
        message << tr("Old Id: ") << oldId << lineBreak;
        log(tr("Node id changed:"), string);
    }
}

void DebugView::propertiesAboutToBeRemoved(const QList<AbstractProperty> & /*propertyList*/)
{
}

void DebugView::variantPropertiesChanged(const QList<VariantProperty> &propertyList,
                                         AbstractView::PropertyChangeFlags /*propertyChange*/)
{
    if (isDebugViewEnabled()) {
        QTextStream message;
        QString string;
        message.setString(&string);
        foreach (const VariantProperty &property, propertyList) {
            message << property;
        }
        log(tr("VariantProperties changed:"), string);
    }
}

void DebugView::bindingPropertiesChanged(const QList<BindingProperty> &propertyList,
                                         AbstractView::PropertyChangeFlags /*propertyChange*/)
{
    if (isDebugViewEnabled()) {
        QTextStream message;
        QString string;
        message.setString(&string);
        foreach (const BindingProperty &property, propertyList) {
            message << property;
        }
        log(tr("BindingProperties changed:"), string);
    }
}

void DebugView::rootNodeTypeChanged(const QString &type, int majorVersion, int minorVersion)
{
    if (isDebugViewEnabled()) {
        QString message;
        message += type;
        message += QLatin1String(" ");
        message += QString::number(majorVersion);
        message += QLatin1String(" ");
        message += QString::number(minorVersion);
        log(tr("Node id changed:"), message);
    }
}

void DebugView::selectedNodesChanged(const QList<ModelNode> & /*selectedNodeList*/,
                                     const QList<ModelNode> & /*lastSelectedNodeList*/)
{
}

void DebugView::scriptFunctionsChanged(const ModelNode & /*node*/, const QStringList & /*scriptFunctionList*/)
{
}

void DebugView::propertiesRemoved(const QList<AbstractProperty> &propertyList)
{
    if (isDebugViewEnabled()) {
        QTextStream message;
        QString string;
        message.setString(&string);
        foreach (const AbstractProperty &property, propertyList) {
            message << property;
        }
        log(tr("Properties removed:"), string);
    }
}

void DebugView::auxiliaryDataChanged(const ModelNode &node, const PropertyName &name, const QVariant &data)
{
    if (isDebugViewEnabled()) {
        QTextStream message;
        QString string;
        message.setString(&string);

        message << node;
        message << name;
        message << data.toString();

        log(tr("Auxiliary Data Changed:"), string);
    }
}

void DebugView::rewriterBeginTransaction()
{
    if (isDebugViewEnabled())
        log(tr("Begin rewriter transaction"), QString(), true);
}

void DebugView::rewriterEndTransaction()
{
    if (isDebugViewEnabled())
        log(tr("End rewriter transaction"), QString(), true);
}

WidgetInfo DebugView::widgetInfo()
{
    return createWidgetInfo(m_debugViewWidget.data(), QLatin1String("DebugView"), WidgetInfo::LeftPane, 0, tr("Debug View"));
}

bool DebugView::hasWidget() const
{
    if (isDebugViewShown())
        return true;

    return false;
}

void DebugView::instancePropertyChange(const QList<QPair<ModelNode, PropertyName> > &propertyList)
{
    if (isDebugViewEnabled()) {
        QTextStream message;
        QString string;
        message.setString(&string);

        typedef QPair<ModelNode, PropertyName> Pair;

        foreach (const Pair &pair, propertyList) {
            message << pair.first;
            message << lineBreak;
            message << pair.second;
        }

        logInstance(tr("Instance property change"), string);
    }
}

void DebugView::instancesCompleted(const QVector<ModelNode> &completedNodeList)
{
    if (isDebugViewEnabled()) {
        QTextStream message;
        QString string;
        message.setString(&string);

        foreach (const ModelNode &modelNode, completedNodeList) {
            message << modelNode;
        }

        logInstance(tr("Instance Completed"), string);
    }
}

void DebugView::instanceInformationsChange(const QMultiHash<ModelNode, InformationName> &informationChangeHash)
{
    if (isDebugViewEnabled()) {
        QTextStream message;
        QString string;
        message.setString(&string);

        foreach (const ModelNode &modelNode, informationChangeHash.keys()) {
            message << modelNode;
            message << informationChangeHash.value(modelNode);
        }

        logInstance(tr("Instance Completed"), string);
    }

}

void DebugView::instancesRenderImageChanged(const QVector<ModelNode> & /*nodeList*/)
{
}

void DebugView::instancesPreviewImageChanged(const QVector<ModelNode> & /*nodeList*/)
{
}

void DebugView::instancesChildrenChanged(const QVector<ModelNode> & /*nodeList*/)
{
}

void DebugView::customNotification(const AbstractView *view, const QString &identifier, const QList<ModelNode> &nodeList, const QList<QVariant> &data)
{
    if (isDebugViewEnabled()) {
        QTextStream message;
        QString string;
        message.setString(&string);

        message << view;
        message << identifier;
        foreach (const ModelNode &node, nodeList) {
            message << node;
        }

        foreach (const QVariant &variant, data) {
            message << variant.toString();
        }

        log(tr("Custom Notification:"), string);
    }
}

void DebugView::nodeSourceChanged(const ModelNode &modelNode, const QString &newNodeSource)
{
    if (isDebugViewEnabled()) {
        QTextStream message;
        QString string;
        message.setString(&string);

        message << modelNode;
        message << newNodeSource;

        log(tr("Node Source Changed:"), string);
    }
}

void DebugView::log(const QString &title, const QString &message, bool highlight)
{
    m_debugViewWidget->addLogMessage(title, message, highlight);
}

void DebugView::logInstance(const QString &title, const QString &message, bool highlight)
{
    m_debugViewWidget->addLogInstanceMessage(title, message, highlight);
}

} // namesapce Internal

} // namespace QmlDesigner
<|endoftext|>