<commit_before>/////////////////////////////////////////////////////////////////////////////////////////
#include "timer_queue_t.h"
#include "base_guard.h"
#include <iostream>

BASE_NAMESPACE_BEGIN_DECL

#define UNINT32_MAX  4294967296

#define SELECT_DELAY 5

/////////////////////////////////////////////////////////////////////////////////////////

template<class HANDLER, class FUNCTOR, class LOCK>
CTimerQueue_T<HANDLER, FUNCTOR, LOCK>::CTimerQueue_T(FUNCTOR* functor, size_t heap_size /* = 10240 */)
{
	heap_size_ = 0;

	alloc_heap(heap_size);

	used_num_ = 0;
	cur_heap_pos_ = 0;
	//ʼʱ
	start_time_ = CBaseTimeValue::get_time_value();
	prev_time_ = start_time_;

	functor_ = functor;

	for(uint8_t index = 0; index < RINGS_SIZE; index ++)
	{
		rings_[index].set_ring_id(index);
	}
}

template<class HANDLER, class FUNCTOR, class LOCK>
CTimerQueue_T<HANDLER, FUNCTOR, LOCK>::~CTimerQueue_T()
{
	clear();
}

template<class HANDLER, class FUNCTOR, class LOCK>
void CTimerQueue_T<HANDLER, FUNCTOR, LOCK>::clear()
{
	BASE_GUARD(LOCK, cf_mon, mutex_);

	for(uint32_t i = 0; i < heap_size_; i ++)
	{
		if(heap_[i] != NULL)
		{
			node_pool_.push_obj(heap_[i]);
			heap_[i] = NULL;
			freeTimers_.push_back(i);
		}
	}

	used_num_ = 0;
	cur_heap_pos_ = 0;
}

template<class HANDLER, class FUNCTOR, class LOCK>
bool CTimerQueue_T<HANDLER, FUNCTOR, LOCK>::full() const
{
	return used_num_ >= heap_size_ - 1;
}

template<class HANDLER, class FUNCTOR, class LOCK>
void CTimerQueue_T<HANDLER, FUNCTOR, LOCK>::alloc_heap(size_t size)
{
	heap_.resize(size + heap_size_);
	for(uint32_t i = 0; i < size; i ++)
	{
		heap_[heap_size_] = NULL;
		if(heap_size_  > 0)
			freeTimers_.push_back(heap_size_);

		heap_size_ ++;
	}
}

template<class HANDLER, class FUNCTOR, class LOCK>
uint32_t CTimerQueue_T<HANDLER, FUNCTOR, LOCK>::get_free_node()
{
	if(full())
	{
		alloc_heap(heap_size_ + 1);
	}

	uint32_t ret = freeTimers_.front();
	freeTimers_.pop_front();
	if(heap_[ret] != NULL)
		assert(0);

	return ret;
}

template<class HANDLER, class FUNCTOR, class LOCK>
FUNCTOR &CTimerQueue_T<HANDLER, FUNCTOR, LOCK>::upcall_functor()
{
	return *(this->functor_);
}

template<class HANDLER, class FUNCTOR, class LOCK>
uint32_t CTimerQueue_T<HANDLER, FUNCTOR, LOCK>::schedule(HANDLER handler,
																		   const void *act,
																		   uint32_t delay,
																		   uint32_t interval)
{
	BASE_GUARD_RETURN(LOCK, cf_mon, mutex_, 0);

	BaseTimerNode_T<HANDLER>* timer_obj = node_pool_.pop_obj();
	if(timer_obj != NULL)
	{
		uint32_t timer_id = get_free_node();

		CBaseTimeValue cur_timer = CBaseTimeValue::get_time_value();

		uint64_t distance = delay; //ֱԵǰʱΪ꣬һɨ20MS
		if(cur_timer > start_time_)
			distance = (cur_timer.msec() - start_time_.msec() + delay);// SELECT_DELAY;

		distance = distance % (UNINT32_MAX);

		timer_obj->set(handler, act, (uint32_t)(core_max(distance, 1)), interval, timer_id);

		heap_[timer_id] = timer_obj;

		used_num_ ++;

		insert_node(timer_obj);

		upcall_functor().registration(timer_obj->get_handler(), timer_id);

		return timer_id;
	}

	return 0;
}

template<class HANDLER, class FUNCTOR, class LOCK>
void CTimerQueue_T<HANDLER, FUNCTOR, LOCK>::cancel_timer(uint32_t timer_id, const void **act)
{
	BASE_GUARD(LOCK, cf_mon, mutex_);
	if(timer_id < heap_size_ && heap_[timer_id] != NULL)
	{
		BaseTimerNode_T<HANDLER>* timer_obj = heap_[timer_id];
		delete_node(timer_obj);

		heap_[timer_id] = NULL;
		if(used_num_ > 0)
			used_num_ --;

		freeTimers_.push_back(timer_id);

		*act = timer_obj->get_act();
		upcall_functor().cancel_timer(timer_obj->get_handler(), timer_id);

		node_pool_.push_obj(timer_obj);
	}
}

template<class HANDLER, class FUNCTOR, class LOCK>
uint32_t CTimerQueue_T<HANDLER, FUNCTOR, LOCK>::reset_timer(uint32_t timer_id, uint32_t delay, uint32_t interval /* = 0 */)
{
	BASE_GUARD_RETURN(LOCK, cf_mon, mutex_, 0);

	if(timer_id < heap_size_ && heap_[timer_id] != NULL)
	{
		BaseTimerNode_T<HANDLER>* timer_obj = heap_[timer_id];
		delete_node(timer_obj);

		timer_obj->set_internal(interval);

		CBaseTimeValue cur_timer = CBaseTimeValue::get_time_value();
		uint64_t distance = delay; // SELECT_DELAY; //ֱԵǰʱΪ꣬һɨ20MS
		if(cur_timer > start_time_)
			distance = (cur_timer.msec() - start_time_.msec() + delay); // SELECT_DELAY;

		distance = distance % (UNINT32_MAX);
		timer_obj->set_time_stamp(core_max(distance, 1));

		insert_node(timer_obj);

		return timer_id;
	}
	else
	{
		return 0;
	}
}

template<class HANDLER, class FUNCTOR, class LOCK>
uint32_t CTimerQueue_T<HANDLER, FUNCTOR, LOCK>::expire()
{
	BASE_GUARD_RETURN(LOCK, cf_mon, mutex_, 0);
	uint32_t ret = SELECT_DELAY;	//Ĭ20MS

	CBaseTimeValue cur_timer = CBaseTimeValue::get_time_value();

	if(cur_timer > prev_time_)
	{
		uint32_t scale = static_cast<uint32_t>((cur_timer.msec() - prev_time_.msec()));// SELECT_DELAY);
		if(scale > 0)
		{
			ret = revolver(scale);
			prev_time_ = cur_timer;
		}
	}

	return ret;
}

template<class HANDLER, class FUNCTOR, class LOCK>
uint32_t CTimerQueue_T<HANDLER, FUNCTOR, LOCK>::revolver(uint32_t scale)
{
	//std::cout << "pos, first = " << rings_[0].get_pos() << ", second = " << rings_[1].get_pos()
	//	<< ", third = " << rings_[2].get_pos() << ", fourth = " << rings_[3].get_pos() <<std::endl;

	uint32_t ret = SELECT_DELAY;

	uint8_t index = 0;
	uint32_t rewind_scale = scale;
	while(rewind_scale > 0)
	{
		index = 0;
		if(rings_[index].cycle(rewind_scale, this)) //ɨһ
		{
			index ++;
			uint32_t sc = 1;
			while(rings_[index].cycle(sc, this))//ɨһ̶ֻ֣ǰƽ1
			{
				sc = 1;
				index ++;
				if(index >= RINGS_SIZE)
				{
					start_time_ = CBaseTimeValue::get_time_value();
					break;
				}
			}
		}
	}

	return ret;
}

template<class HANDLER, class FUNCTOR, class LOCK>
void CTimerQueue_T<HANDLER, FUNCTOR, LOCK>::ring_event(uint8_t ring_id, uint32_t timer_id)
{
	if(heap_[timer_id] == NULL)
		return;

	BaseTimerNode_T<HANDLER>* timer_obj = heap_[timer_id];
	if(ring_id == 0)
	{
		//ʱ֪ͨ
		BaseTimerDispathInfo_T<HANDLER> info;
		if(timer_obj != NULL)
		{
			timer_obj->get_dispatch_info(info);
			this->dispatch_info(info, timer_id);

			node_pool_.push_obj(timer_obj);
		}

		heap_[timer_id] = NULL;
		if(used_num_ > 0)
			used_num_ --;

		freeTimers_.push_back(timer_id);
	}
	else if(ring_id < RINGS_SIZE)
	{
		//ƶRINGλã磬ڶӵĳԪжʱӳ䵽һϽ·ֲ
		insert_node(timer_obj);
	}
}

template<class HANDLER, class FUNCTOR, class LOCK>
void CTimerQueue_T<HANDLER, FUNCTOR, LOCK>::insert_node(BaseTimerNode_T<HANDLER>* node)
{
	uint32_t timer_id = node->get_timer_id();

	uint8_t poss[RINGS_SIZE] = {0};
	node->get_revolver_pos(poss[RINGS_SIZE - 1], poss[RINGS_SIZE - 2], poss[RINGS_SIZE - 3], poss[RINGS_SIZE - 4]);
	//cout << "timer id = "<< timer_id << ", first = " << (uint16_t)poss[RINGS_SIZE - 4] << ",second = " << (uint16_t)poss[RINGS_SIZE - 3]
	//<< ",third = " << (uint16_t)poss[RINGS_SIZE - 2] <<", fouth = " << (uint16_t)poss[RINGS_SIZE - 1] <<endl;
	uint8_t index = RINGS_SIZE - 1;
	while(!rings_[index].add_element(poss[index], timer_id))
	{
		if(index == 0)
			break ;

		index --;
	}
}

template<class HANDLER, class FUNCTOR, class LOCK>
void CTimerQueue_T<HANDLER, FUNCTOR, LOCK>::delete_node(BaseTimerNode_T<HANDLER>* node)
{
	uint32_t timer_id = node->get_timer_id();
	uint8_t poss[RINGS_SIZE] = {0};
	node->get_revolver_pos(poss[RINGS_SIZE - 1], poss[RINGS_SIZE - 2], poss[RINGS_SIZE - 3], poss[RINGS_SIZE - 4]);

	for(uint8_t index = 0; index < RINGS_SIZE; index ++) //ÿϽɾ
	{
		rings_[index].delete_element(poss[index], timer_id);
	}
}

template<class HANDLER, class FUNCTOR, class LOCK>
void CTimerQueue_T<HANDLER,  FUNCTOR, LOCK>::dispatch_info(BaseTimerDispathInfo_T<HANDLER>& info, uint32_t timer_id)
{
	upcall_functor().timer_out(info.handler_, info.act_, info.recurring_, timer_id);
}

#if _DEBUG
template<class HANDLER, class FUNCTOR, class LOCK>
void CTimerQueue_T<HANDLER,  FUNCTOR, LOCK>::set_ring_id()
{
	rings_[1].set_pos(255);
	rings_[2].set_pos(0);
	rings_[3].set_pos(0);
}
#endif

BASE_NAMESPACE_END_DECL
/////////////////////////////////////////////////////////////////////////////////////////

<commit_msg>修改epoll轮询时间<commit_after>/////////////////////////////////////////////////////////////////////////////////////////
#include "timer_queue_t.h"
#include "base_guard.h"
#include <iostream>

BASE_NAMESPACE_BEGIN_DECL

#define UNINT32_MAX  4294967296

#define SELECT_DELAY 1

/////////////////////////////////////////////////////////////////////////////////////////

template<class HANDLER, class FUNCTOR, class LOCK>
CTimerQueue_T<HANDLER, FUNCTOR, LOCK>::CTimerQueue_T(FUNCTOR* functor, size_t heap_size /* = 10240 */)
{
	heap_size_ = 0;

	alloc_heap(heap_size);

	used_num_ = 0;
	cur_heap_pos_ = 0;
	//ʼʱ
	start_time_ = CBaseTimeValue::get_time_value();
	prev_time_ = start_time_;

	functor_ = functor;

	for(uint8_t index = 0; index < RINGS_SIZE; index ++)
	{
		rings_[index].set_ring_id(index);
	}
}

template<class HANDLER, class FUNCTOR, class LOCK>
CTimerQueue_T<HANDLER, FUNCTOR, LOCK>::~CTimerQueue_T()
{
	clear();
}

template<class HANDLER, class FUNCTOR, class LOCK>
void CTimerQueue_T<HANDLER, FUNCTOR, LOCK>::clear()
{
	BASE_GUARD(LOCK, cf_mon, mutex_);

	for(uint32_t i = 0; i < heap_size_; i ++)
	{
		if(heap_[i] != NULL)
		{
			node_pool_.push_obj(heap_[i]);
			heap_[i] = NULL;
			freeTimers_.push_back(i);
		}
	}

	used_num_ = 0;
	cur_heap_pos_ = 0;
}

template<class HANDLER, class FUNCTOR, class LOCK>
bool CTimerQueue_T<HANDLER, FUNCTOR, LOCK>::full() const
{
	return used_num_ >= heap_size_ - 1;
}

template<class HANDLER, class FUNCTOR, class LOCK>
void CTimerQueue_T<HANDLER, FUNCTOR, LOCK>::alloc_heap(size_t size)
{
	heap_.resize(size + heap_size_);
	for(uint32_t i = 0; i < size; i ++)
	{
		heap_[heap_size_] = NULL;
		if(heap_size_  > 0)
			freeTimers_.push_back(heap_size_);

		heap_size_ ++;
	}
}

template<class HANDLER, class FUNCTOR, class LOCK>
uint32_t CTimerQueue_T<HANDLER, FUNCTOR, LOCK>::get_free_node()
{
	if(full())
	{
		alloc_heap(heap_size_ + 1);
	}

	uint32_t ret = freeTimers_.front();
	freeTimers_.pop_front();
	if(heap_[ret] != NULL)
		assert(0);

	return ret;
}

template<class HANDLER, class FUNCTOR, class LOCK>
FUNCTOR &CTimerQueue_T<HANDLER, FUNCTOR, LOCK>::upcall_functor()
{
	return *(this->functor_);
}

template<class HANDLER, class FUNCTOR, class LOCK>
uint32_t CTimerQueue_T<HANDLER, FUNCTOR, LOCK>::schedule(HANDLER handler,
																		   const void *act,
																		   uint32_t delay,
																		   uint32_t interval)
{
	BASE_GUARD_RETURN(LOCK, cf_mon, mutex_, 0);

	BaseTimerNode_T<HANDLER>* timer_obj = node_pool_.pop_obj();
	if(timer_obj != NULL)
	{
		uint32_t timer_id = get_free_node();

		CBaseTimeValue cur_timer = CBaseTimeValue::get_time_value();

		uint64_t distance = delay; //ֱԵǰʱΪ꣬һɨ20MS
		if(cur_timer > start_time_)
			distance = (cur_timer.msec() - start_time_.msec() + delay);// SELECT_DELAY;

		distance = distance % (UNINT32_MAX);

		timer_obj->set(handler, act, (uint32_t)(core_max(distance, 1)), interval, timer_id);

		heap_[timer_id] = timer_obj;

		used_num_ ++;

		insert_node(timer_obj);

		upcall_functor().registration(timer_obj->get_handler(), timer_id);

		return timer_id;
	}

	return 0;
}

template<class HANDLER, class FUNCTOR, class LOCK>
void CTimerQueue_T<HANDLER, FUNCTOR, LOCK>::cancel_timer(uint32_t timer_id, const void **act)
{
	BASE_GUARD(LOCK, cf_mon, mutex_);
	if(timer_id < heap_size_ && heap_[timer_id] != NULL)
	{
		BaseTimerNode_T<HANDLER>* timer_obj = heap_[timer_id];
		delete_node(timer_obj);

		heap_[timer_id] = NULL;
		if(used_num_ > 0)
			used_num_ --;

		freeTimers_.push_back(timer_id);

		*act = timer_obj->get_act();
		upcall_functor().cancel_timer(timer_obj->get_handler(), timer_id);

		node_pool_.push_obj(timer_obj);
	}
}

template<class HANDLER, class FUNCTOR, class LOCK>
uint32_t CTimerQueue_T<HANDLER, FUNCTOR, LOCK>::reset_timer(uint32_t timer_id, uint32_t delay, uint32_t interval /* = 0 */)
{
	BASE_GUARD_RETURN(LOCK, cf_mon, mutex_, 0);

	if(timer_id < heap_size_ && heap_[timer_id] != NULL)
	{
		BaseTimerNode_T<HANDLER>* timer_obj = heap_[timer_id];
		delete_node(timer_obj);

		timer_obj->set_internal(interval);

		CBaseTimeValue cur_timer = CBaseTimeValue::get_time_value();
		uint64_t distance = delay; // SELECT_DELAY; //ֱԵǰʱΪ꣬һɨ20MS
		if(cur_timer > start_time_)
			distance = (cur_timer.msec() - start_time_.msec() + delay); // SELECT_DELAY;

		distance = distance % (UNINT32_MAX);
		timer_obj->set_time_stamp(core_max(distance, 1));

		insert_node(timer_obj);

		return timer_id;
	}
	else
	{
		return 0;
	}
}

template<class HANDLER, class FUNCTOR, class LOCK>
uint32_t CTimerQueue_T<HANDLER, FUNCTOR, LOCK>::expire()
{
	BASE_GUARD_RETURN(LOCK, cf_mon, mutex_, 0);
	uint32_t ret = SELECT_DELAY;	//Ĭ20MS

	CBaseTimeValue cur_timer = CBaseTimeValue::get_time_value();

	if(cur_timer > prev_time_)
	{
		uint32_t scale = static_cast<uint32_t>((cur_timer.msec() - prev_time_.msec()));// SELECT_DELAY);
		if(scale > 0)
		{
			ret = revolver(scale);
			prev_time_ = cur_timer;
		}
	}

	return ret;
}

template<class HANDLER, class FUNCTOR, class LOCK>
uint32_t CTimerQueue_T<HANDLER, FUNCTOR, LOCK>::revolver(uint32_t scale)
{
	//std::cout << "pos, first = " << rings_[0].get_pos() << ", second = " << rings_[1].get_pos()
	//	<< ", third = " << rings_[2].get_pos() << ", fourth = " << rings_[3].get_pos() <<std::endl;

	uint32_t ret = SELECT_DELAY;

	uint8_t index = 0;
	uint32_t rewind_scale = scale;
	while(rewind_scale > 0)
	{
		index = 0;
		if(rings_[index].cycle(rewind_scale, this)) //ɨһ
		{
			index ++;
			uint32_t sc = 1;
			while(rings_[index].cycle(sc, this))//ɨһ̶ֻ֣ǰƽ1
			{
				sc = 1;
				index ++;
				if(index >= RINGS_SIZE)
				{
					start_time_ = CBaseTimeValue::get_time_value();
					break;
				}
			}
		}
	}

	return ret;
}

template<class HANDLER, class FUNCTOR, class LOCK>
void CTimerQueue_T<HANDLER, FUNCTOR, LOCK>::ring_event(uint8_t ring_id, uint32_t timer_id)
{
	if(heap_[timer_id] == NULL)
		return;

	BaseTimerNode_T<HANDLER>* timer_obj = heap_[timer_id];
	if(ring_id == 0)
	{
		//ʱ֪ͨ
		BaseTimerDispathInfo_T<HANDLER> info;
		if(timer_obj != NULL)
		{
			timer_obj->get_dispatch_info(info);
			this->dispatch_info(info, timer_id);

			node_pool_.push_obj(timer_obj);
		}

		heap_[timer_id] = NULL;
		if(used_num_ > 0)
			used_num_ --;

		freeTimers_.push_back(timer_id);
	}
	else if(ring_id < RINGS_SIZE)
	{
		//ƶRINGλã磬ڶӵĳԪжʱӳ䵽һϽ·ֲ
		insert_node(timer_obj);
	}
}

template<class HANDLER, class FUNCTOR, class LOCK>
void CTimerQueue_T<HANDLER, FUNCTOR, LOCK>::insert_node(BaseTimerNode_T<HANDLER>* node)
{
	uint32_t timer_id = node->get_timer_id();

	uint8_t poss[RINGS_SIZE] = {0};
	node->get_revolver_pos(poss[RINGS_SIZE - 1], poss[RINGS_SIZE - 2], poss[RINGS_SIZE - 3], poss[RINGS_SIZE - 4]);
	//cout << "timer id = "<< timer_id << ", first = " << (uint16_t)poss[RINGS_SIZE - 4] << ",second = " << (uint16_t)poss[RINGS_SIZE - 3]
	//<< ",third = " << (uint16_t)poss[RINGS_SIZE - 2] <<", fouth = " << (uint16_t)poss[RINGS_SIZE - 1] <<endl;
	uint8_t index = RINGS_SIZE - 1;
	while(!rings_[index].add_element(poss[index], timer_id))
	{
		if(index == 0)
			break ;

		index --;
	}
}

template<class HANDLER, class FUNCTOR, class LOCK>
void CTimerQueue_T<HANDLER, FUNCTOR, LOCK>::delete_node(BaseTimerNode_T<HANDLER>* node)
{
	uint32_t timer_id = node->get_timer_id();
	uint8_t poss[RINGS_SIZE] = {0};
	node->get_revolver_pos(poss[RINGS_SIZE - 1], poss[RINGS_SIZE - 2], poss[RINGS_SIZE - 3], poss[RINGS_SIZE - 4]);

	for(uint8_t index = 0; index < RINGS_SIZE; index ++) //ÿϽɾ
	{
		rings_[index].delete_element(poss[index], timer_id);
	}
}

template<class HANDLER, class FUNCTOR, class LOCK>
void CTimerQueue_T<HANDLER,  FUNCTOR, LOCK>::dispatch_info(BaseTimerDispathInfo_T<HANDLER>& info, uint32_t timer_id)
{
	upcall_functor().timer_out(info.handler_, info.act_, info.recurring_, timer_id);
}

#if _DEBUG
template<class HANDLER, class FUNCTOR, class LOCK>
void CTimerQueue_T<HANDLER,  FUNCTOR, LOCK>::set_ring_id()
{
	rings_[1].set_pos(255);
	rings_[2].set_pos(0);
	rings_[3].set_pos(0);
}
#endif

BASE_NAMESPACE_END_DECL
/////////////////////////////////////////////////////////////////////////////////////////

<|endoftext|>


<commit_before>/**
 * \file
 * \brief PendSV_Handler() for ARMv6-M and ARMv7-M
 *
 * \author Copyright (C) 2014-2016 Kamil Szczygiel http://www.distortec.com http://www.freddiechopin.info
 *
 * \par License
 * 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 "distortos/internal/scheduler/getScheduler.hpp"
#include "distortos/internal/scheduler/Scheduler.hpp"

#include "distortos/chip/CMSIS-proxy.h"

#ifdef CONFIG_CHECK_STACK_POINTER_RANGE_ENABLE

#include "distortos/FATAL_ERROR.h"

#endif	// def CONFIG_CHECK_STACK_POINTER_RANGE_ENABLE

namespace distortos
{

namespace
{

/*---------------------------------------------------------------------------------------------------------------------+
| local functions
+---------------------------------------------------------------------------------------------------------------------*/

#ifdef CONFIG_CHECK_STACK_POINTER_RANGE_ENABLE

/**
 * \brief Wrapper for check of stack pointer range
 *
 * If the check fails, FATAL_ERROR() is called.
 *
 * \param [in] stackPointer is the current thread's stack pointer value, including the frame which will be stacked
 */

void checkStackPointerWrapper(void* const stackPointer)
{
	if (internal::getScheduler().getCurrentThreadControlBlock().getStack().checkStackPointer(stackPointer) == false)
		FATAL_ERROR("Stack overflow detected!");
}

#endif	// def CONFIG_CHECK_STACK_POINTER_RANGE_ENABLE

/**
 * \brief Wrapper for void* distortos::internal::getScheduler().switchContext(void*)
 *
 * \param [in] stackPointer is the current value of current thread's stack pointer
 *
 * \return new thread's stack pointer
 */

void* schedulerSwitchContextWrapper(void* const stackPointer)
{
	return internal::getScheduler().switchContext(stackPointer);
}

}	// namespace

/*---------------------------------------------------------------------------------------------------------------------+
| global functions
+---------------------------------------------------------------------------------------------------------------------*/

/**
 * \brief PendSV_Handler() for ARMv6-M and ARMv7-M
 *
 * Performs the context switch.
 */

extern "C" __attribute__ ((naked)) void PendSV_Handler()
{
#if CONFIG_ARCHITECTURE_ARMV7_M_KERNEL_BASEPRI != 0

	constexpr auto basepriValue = CONFIG_ARCHITECTURE_ARMV7_M_KERNEL_BASEPRI << (8 - __NVIC_PRIO_BITS);
	static_assert(basepriValue > 0 && basepriValue <= UINT8_MAX,
			"Invalid CONFIG_ARCHITECTURE_ARMV7_M_KERNEL_BASEPRI value!");

#endif	// CONFIG_ARCHITECTURE_ARMV7_M_KERNEL_BASEPRI != 0

	asm volatile
	(
#if CONFIG_ARCHITECTURE_ARMV7_M_KERNEL_BASEPRI != 0
			"	mov			r0, %[basepriValue]					\n"
			"	msr			basepri, r0							\n"	// enable interrupt masking
#else	// CONFIG_ARCHITECTURE_ARMV7_M_KERNEL_BASEPRI == 0
			"	cpsid		i									\n"	// disable interrupts
#endif	// CONFIG_ARCHITECTURE_ARMV7_M_KERNEL_BASEPRI == 0
			"													\n"
#ifdef __ARM_ARCH_6M__
			"	mrs			r0, psp								\n"
#ifdef CONFIG_CHECK_STACK_POINTER_RANGE_ENABLE
			"	push		{r0, lr}							\n"
			"	sub			r0, r0, #0x20						\n"
			"	ldr			r1, =%[checkStackPointerWrapper]	\n"
			"	blx			r1									\n"
			"	pop			{r0, r1}							\n"
			"	mov			lr, r1								\n"
#endif	// def CONFIG_CHECK_STACK_POINTER_RANGE_ENABLE
			"	sub			r0, #0x10							\n"
			"	stmia		r0!, {r4-r7}						\n"	// save lower half of current thread's context
			"	mov			r4, r8								\n"
			"	mov			r5, r9								\n"
			"	mov			r6, r10								\n"
			"	mov			r7, r11								\n"
			"	sub			r0, #0x20							\n"
			"	stmia		r0!, {r4-r7}						\n"	// save upper half of current thread's context
			"	sub			r0, #0x10							\n"
			"	mov			r4, lr								\n"
			"													\n"
			"	ldr			r1, =%[schedulerSwitchContext]		\n"
			"	blx			r1									\n"	// switch context
			"													\n"
			"	mov			lr, r4								\n"
			"	ldmia		r0!, {r4-r7}						\n"	// load upper half of new thread's context
			"	mov			r8, r4								\n"
			"	mov			r9, r5								\n"
			"	mov			r10, r6								\n"
			"	mov			r11, r7								\n"
			"	ldmia		r0!, {r4-r7}						\n"	// load lower half of new thread's context
			"	msr			psp, r0								\n"
#else	// !def __ARM_ARCH_6M__
			"	mrs			r0, psp								\n"
#ifdef CONFIG_CHECK_STACK_POINTER_RANGE_ENABLE
			"	push		{r0, lr}							\n"
#if __FPU_PRESENT == 1 && __FPU_USED == 1
			"	tst			lr, #(1 << 4)						\n"	// was floating-point used by the thread?
			"	it			eq									\n"
			"	subeq		r0, r0, #0x40						\n"	// account for size of "floating-pont" context
			"	sub			r0, r0, #0x28						\n"
#else	// __FPU_PRESENT != 1 || __FPU_USED != 1
			"	sub			r0, r0, #0x20						\n"
#endif	// __FPU_PRESENT != 1 || __FPU_USED != 1
			"	bl			%[checkStackPointerWrapper]			\n"	// switch context
			"	pop			{r0, lr}							\n"
#endif	// def CONFIG_CHECK_STACK_POINTER_RANGE_ENABLE
#if __FPU_PRESENT == 1 && __FPU_USED == 1
			"	tst			lr, #(1 << 4)						\n"	// was floating-point used by the thread?
			"	it			eq									\n"
			"	vstmdbeq	r0!, {s16-s31}						\n"	// save "floating-point" context of current thread
			// save "regular" context of current thread (r12 is saved just to keep double-word alignment)
			"	stmdb		r0!, {r4-r12, lr}					\n"
#else	// __FPU_PRESENT != 1 || __FPU_USED != 1
			"	stmdb		r0!, {r4-r11}						\n"	// save context of current thread
			"	mov			r4, lr								\n"
#endif	// __FPU_PRESENT != 1 || __FPU_USED != 1
			"													\n"
			"	bl			%[schedulerSwitchContext]			\n"	// switch context
			"													\n"
#if __FPU_PRESENT == 1 && __FPU_USED == 1
			"	ldmia		r0!, {r4-r12, lr}					\n"	// load "regular" context of new thread
			"	tst			lr, #(1 << 4)						\n"	// was floating-point used by the thread?
			"	it			eq									\n"
			"	vldmiaeq	r0!, {s16-s31}						\n"	// load "floating-point" context of new thread
#else	// __FPU_PRESENT != 1 || __FPU_USED != 1
			"	mov			lr, r4								\n"
			"	ldmia		r0!, {r4-r11}						\n"	// load context of new thread
#endif	// __FPU_PRESENT != 1 || __FPU_USED != 1
			"	msr			psp, r0								\n"
#endif	// !def __ARM_ARCH_6M__
			"													\n"
#if CONFIG_ARCHITECTURE_ARMV7_M_KERNEL_BASEPRI != 0
			"	mov			r0, #0								\n"
			"	msr			basepri, r0							\n"	// disable interrupt masking
#else	// CONFIG_ARCHITECTURE_ARMV7_M_KERNEL_BASEPRI == 0
			"	cpsie		i									\n"	// enable interrupts
#endif	// CONFIG_ARCHITECTURE_ARMV7_M_KERNEL_BASEPRI == 0
			"													\n"
			"	bx			lr									\n"	// return to new thread

			::
#if CONFIG_ARCHITECTURE_ARMV7_M_KERNEL_BASEPRI != 0
				[basepriValue] "i" (basepriValue),
#endif	// CONFIG_ARCHITECTURE_ARMV7_M_KERNEL_BASEPRI != 0
#ifdef CONFIG_CHECK_STACK_POINTER_RANGE_ENABLE
				[checkStackPointerWrapper] "i" (checkStackPointerWrapper),
#endif	// def CONFIG_CHECK_STACK_POINTER_RANGE_ENABLE
				[schedulerSwitchContext] "i" (schedulerSwitchContextWrapper)
	);

	__builtin_unreachable();
}

}	// namespace distortos
<commit_msg>Remove wrong comment from PendSV_Handler() for ARMv6-M & ARMv7-M<commit_after>/**
 * \file
 * \brief PendSV_Handler() for ARMv6-M and ARMv7-M
 *
 * \author Copyright (C) 2014-2016 Kamil Szczygiel http://www.distortec.com http://www.freddiechopin.info
 *
 * \par License
 * 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 "distortos/internal/scheduler/getScheduler.hpp"
#include "distortos/internal/scheduler/Scheduler.hpp"

#include "distortos/chip/CMSIS-proxy.h"

#ifdef CONFIG_CHECK_STACK_POINTER_RANGE_ENABLE

#include "distortos/FATAL_ERROR.h"

#endif	// def CONFIG_CHECK_STACK_POINTER_RANGE_ENABLE

namespace distortos
{

namespace
{

/*---------------------------------------------------------------------------------------------------------------------+
| local functions
+---------------------------------------------------------------------------------------------------------------------*/

#ifdef CONFIG_CHECK_STACK_POINTER_RANGE_ENABLE

/**
 * \brief Wrapper for check of stack pointer range
 *
 * If the check fails, FATAL_ERROR() is called.
 *
 * \param [in] stackPointer is the current thread's stack pointer value, including the frame which will be stacked
 */

void checkStackPointerWrapper(void* const stackPointer)
{
	if (internal::getScheduler().getCurrentThreadControlBlock().getStack().checkStackPointer(stackPointer) == false)
		FATAL_ERROR("Stack overflow detected!");
}

#endif	// def CONFIG_CHECK_STACK_POINTER_RANGE_ENABLE

/**
 * \brief Wrapper for void* distortos::internal::getScheduler().switchContext(void*)
 *
 * \param [in] stackPointer is the current value of current thread's stack pointer
 *
 * \return new thread's stack pointer
 */

void* schedulerSwitchContextWrapper(void* const stackPointer)
{
	return internal::getScheduler().switchContext(stackPointer);
}

}	// namespace

/*---------------------------------------------------------------------------------------------------------------------+
| global functions
+---------------------------------------------------------------------------------------------------------------------*/

/**
 * \brief PendSV_Handler() for ARMv6-M and ARMv7-M
 *
 * Performs the context switch.
 */

extern "C" __attribute__ ((naked)) void PendSV_Handler()
{
#if CONFIG_ARCHITECTURE_ARMV7_M_KERNEL_BASEPRI != 0

	constexpr auto basepriValue = CONFIG_ARCHITECTURE_ARMV7_M_KERNEL_BASEPRI << (8 - __NVIC_PRIO_BITS);
	static_assert(basepriValue > 0 && basepriValue <= UINT8_MAX,
			"Invalid CONFIG_ARCHITECTURE_ARMV7_M_KERNEL_BASEPRI value!");

#endif	// CONFIG_ARCHITECTURE_ARMV7_M_KERNEL_BASEPRI != 0

	asm volatile
	(
#if CONFIG_ARCHITECTURE_ARMV7_M_KERNEL_BASEPRI != 0
			"	mov			r0, %[basepriValue]					\n"
			"	msr			basepri, r0							\n"	// enable interrupt masking
#else	// CONFIG_ARCHITECTURE_ARMV7_M_KERNEL_BASEPRI == 0
			"	cpsid		i									\n"	// disable interrupts
#endif	// CONFIG_ARCHITECTURE_ARMV7_M_KERNEL_BASEPRI == 0
			"													\n"
#ifdef __ARM_ARCH_6M__
			"	mrs			r0, psp								\n"
#ifdef CONFIG_CHECK_STACK_POINTER_RANGE_ENABLE
			"	push		{r0, lr}							\n"
			"	sub			r0, r0, #0x20						\n"
			"	ldr			r1, =%[checkStackPointerWrapper]	\n"
			"	blx			r1									\n"
			"	pop			{r0, r1}							\n"
			"	mov			lr, r1								\n"
#endif	// def CONFIG_CHECK_STACK_POINTER_RANGE_ENABLE
			"	sub			r0, #0x10							\n"
			"	stmia		r0!, {r4-r7}						\n"	// save lower half of current thread's context
			"	mov			r4, r8								\n"
			"	mov			r5, r9								\n"
			"	mov			r6, r10								\n"
			"	mov			r7, r11								\n"
			"	sub			r0, #0x20							\n"
			"	stmia		r0!, {r4-r7}						\n"	// save upper half of current thread's context
			"	sub			r0, #0x10							\n"
			"	mov			r4, lr								\n"
			"													\n"
			"	ldr			r1, =%[schedulerSwitchContext]		\n"
			"	blx			r1									\n"	// switch context
			"													\n"
			"	mov			lr, r4								\n"
			"	ldmia		r0!, {r4-r7}						\n"	// load upper half of new thread's context
			"	mov			r8, r4								\n"
			"	mov			r9, r5								\n"
			"	mov			r10, r6								\n"
			"	mov			r11, r7								\n"
			"	ldmia		r0!, {r4-r7}						\n"	// load lower half of new thread's context
			"	msr			psp, r0								\n"
#else	// !def __ARM_ARCH_6M__
			"	mrs			r0, psp								\n"
#ifdef CONFIG_CHECK_STACK_POINTER_RANGE_ENABLE
			"	push		{r0, lr}							\n"
#if __FPU_PRESENT == 1 && __FPU_USED == 1
			"	tst			lr, #(1 << 4)						\n"	// was floating-point used by the thread?
			"	it			eq									\n"
			"	subeq		r0, r0, #0x40						\n"	// account for size of "floating-pont" context
			"	sub			r0, r0, #0x28						\n"
#else	// __FPU_PRESENT != 1 || __FPU_USED != 1
			"	sub			r0, r0, #0x20						\n"
#endif	// __FPU_PRESENT != 1 || __FPU_USED != 1
			"	bl			%[checkStackPointerWrapper]			\n"
			"	pop			{r0, lr}							\n"
#endif	// def CONFIG_CHECK_STACK_POINTER_RANGE_ENABLE
#if __FPU_PRESENT == 1 && __FPU_USED == 1
			"	tst			lr, #(1 << 4)						\n"	// was floating-point used by the thread?
			"	it			eq									\n"
			"	vstmdbeq	r0!, {s16-s31}						\n"	// save "floating-point" context of current thread
			// save "regular" context of current thread (r12 is saved just to keep double-word alignment)
			"	stmdb		r0!, {r4-r12, lr}					\n"
#else	// __FPU_PRESENT != 1 || __FPU_USED != 1
			"	stmdb		r0!, {r4-r11}						\n"	// save context of current thread
			"	mov			r4, lr								\n"
#endif	// __FPU_PRESENT != 1 || __FPU_USED != 1
			"													\n"
			"	bl			%[schedulerSwitchContext]			\n"	// switch context
			"													\n"
#if __FPU_PRESENT == 1 && __FPU_USED == 1
			"	ldmia		r0!, {r4-r12, lr}					\n"	// load "regular" context of new thread
			"	tst			lr, #(1 << 4)						\n"	// was floating-point used by the thread?
			"	it			eq									\n"
			"	vldmiaeq	r0!, {s16-s31}						\n"	// load "floating-point" context of new thread
#else	// __FPU_PRESENT != 1 || __FPU_USED != 1
			"	mov			lr, r4								\n"
			"	ldmia		r0!, {r4-r11}						\n"	// load context of new thread
#endif	// __FPU_PRESENT != 1 || __FPU_USED != 1
			"	msr			psp, r0								\n"
#endif	// !def __ARM_ARCH_6M__
			"													\n"
#if CONFIG_ARCHITECTURE_ARMV7_M_KERNEL_BASEPRI != 0
			"	mov			r0, #0								\n"
			"	msr			basepri, r0							\n"	// disable interrupt masking
#else	// CONFIG_ARCHITECTURE_ARMV7_M_KERNEL_BASEPRI == 0
			"	cpsie		i									\n"	// enable interrupts
#endif	// CONFIG_ARCHITECTURE_ARMV7_M_KERNEL_BASEPRI == 0
			"													\n"
			"	bx			lr									\n"	// return to new thread

			::
#if CONFIG_ARCHITECTURE_ARMV7_M_KERNEL_BASEPRI != 0
				[basepriValue] "i" (basepriValue),
#endif	// CONFIG_ARCHITECTURE_ARMV7_M_KERNEL_BASEPRI != 0
#ifdef CONFIG_CHECK_STACK_POINTER_RANGE_ENABLE
				[checkStackPointerWrapper] "i" (checkStackPointerWrapper),
#endif	// def CONFIG_CHECK_STACK_POINTER_RANGE_ENABLE
				[schedulerSwitchContext] "i" (schedulerSwitchContextWrapper)
	);

	__builtin_unreachable();
}

}	// namespace distortos
<|endoftext|>


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

 Program:   ORFEO Toolbox
 Language:  C++
 Date:      $Date$
 Version:   $Revision$

 Copyright (c) Centre National d'Etudes Spatiales. All rights reserved.
 See OTBCopyright.txt for details.

 This software is distributed WITHOUT ANY WARRANTY; without even
 the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
 PURPOSE.  See the above copyright notices for more information.

 =========================================================================*/
#include "otbWrapperApplication.h"
#include "otbWrapperApplicationFactory.h"

#include "otbSarRadiometricCalibrationToImageFilter.h"

namespace otb
{
namespace Wrapper
{
class SarRadiometricCalibration : public Application
{
public:
  /** Standard class typedefs. */
  typedef SarRadiometricCalibration     Self;
  typedef Application                   Superclass;
  typedef itk::SmartPointer<Self>       Pointer;
  typedef itk::SmartPointer<const Self> ConstPointer;

  /** Standard macro */
  itkNewMacro(Self);

  itkTypeMacro(SarRadiometricCalibration, otb::Application);

  typedef otb::SarRadiometricCalibrationToImageFilter<ComplexFloatImageType,
                                                      FloatImageType>     CalibrationFilterType;

private:
  void DoInit()
  {
    SetName("SarRadiometricCalibration");
    SetDescription("Perform radiometric calibration of SAR images. Since OTB 5.2, following product types are supported. TerraSARX, Sentinel1 L1, Radarsat2.\n The application allow s one to read complex and non-complex(intensity) band images.");

    // Documentation
    SetDocName("SAR Radiometric calibration");
    SetDocLongDescription("This application performs radiometric calibration of SAR images. Since OTB 5.2, following product types are supported. TerraSARX, Sentinel1 L1, Radarsat2.\n The application allows one to read images with complex and non-complex pixel types(intensity band). For non-complex type, the application reads it as std::complex() with imaginary part set to zero. ");
    SetDocLimitations("None");
    SetDocAuthors("OTB-Team");
    SetDocSeeAlso(" ");

    AddDocTag(Tags::Calibration);
    AddDocTag(Tags::SAR);

    AddParameter(ParameterType_ComplexInputImage,  "in", "Input Image");
    SetParameterDescription("in", "Input complex image");

    AddParameter(ParameterType_OutputImage,  "out", "Output Image");
    SetParameterDescription("out", "Output calibrated image. This image contains the backscatter (sigmaNought) of the input image.");

    AddRAMParameter();

    AddParameter(ParameterType_Empty, "noise", "Disable Noise");
    SetParameterDescription("noise", "Flag to disable noise. For 5.2.0 release, the noise values are only read by TerraSARX product.");
    MandatoryOff("noise");

    AddParameter(ParameterType_Choice, "lut", "Lookup table sigma /gamma/ beta/ DN.");
    SetParameterDescription("lut", "Lookup table values are not available with all SAR products. The products that provide lookup table with metadata are: Sentinel1, Radarsat2.");
    AddChoice("lut.sigma", "Use sigma nought lookup");
    SetParameterDescription("lut.sigma","Use Sigma nought lookup value from product metadata");
    AddChoice("lut.gamma", "Use gamma nought lookup");
    SetParameterDescription("lut.gamma","Use Gamma nought lookup value from product metadata");
    AddChoice("lut.beta", "Use beta nought lookup");
    SetParameterDescription("lut.beta","Use Beta nought lookup value from product metadata");
    AddChoice("lut.dn", "Use DN value lookup");
    SetParameterDescription("lut.dn","Use DN value lookup value from product metadata");
    SetDefaultParameterInt("lut", 0);

    // Doc example parameter settings
    SetDocExampleParameterValue("in", "RSAT_imagery_HH.tif");
    SetDocExampleParameterValue("out", "SarRadiometricCalibration.tif" );
  }

  void DoUpdateParameters()
  {

  }

  void DoExecute()
  {
    // Get the input complex image
    ComplexFloatImageType*  floatComplexImage = GetParameterComplexFloatImage("in");

    // Set the filer input
    m_CalibrationFilter = CalibrationFilterType::New();
    m_CalibrationFilter->SetInput(floatComplexImage);

    if (IsParameterEnabled("noise"))
      {
      m_CalibrationFilter->SetEnableNoise(false);
      }

    short lut = 0;

    lut = GetParameterInt("lut");

    m_CalibrationFilter->SetLookupSelected(lut);

    // Set the output image
    SetParameterOutputImage("out", m_CalibrationFilter->GetOutput());

  }

  CalibrationFilterType::Pointer   m_CalibrationFilter;

};
}
}

OTB_APPLICATION_EXPORT(otb::Wrapper::SarRadiometricCalibration)
<commit_msg>DOC: small edits in SAR calibration app description<commit_after>/*=========================================================================

 Program:   ORFEO Toolbox
 Language:  C++
 Date:      $Date$
 Version:   $Revision$

 Copyright (c) Centre National d'Etudes Spatiales. All rights reserved.
 See OTBCopyright.txt for details.

 This software is distributed WITHOUT ANY WARRANTY; without even
 the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
 PURPOSE.  See the above copyright notices for more information.

 =========================================================================*/
#include "otbWrapperApplication.h"
#include "otbWrapperApplicationFactory.h"

#include "otbSarRadiometricCalibrationToImageFilter.h"

namespace otb
{
namespace Wrapper
{
class SarRadiometricCalibration : public Application
{
public:
  /** Standard class typedefs. */
  typedef SarRadiometricCalibration     Self;
  typedef Application                   Superclass;
  typedef itk::SmartPointer<Self>       Pointer;
  typedef itk::SmartPointer<const Self> ConstPointer;

  /** Standard macro */
  itkNewMacro(Self);

  itkTypeMacro(SarRadiometricCalibration, otb::Application);

  typedef otb::SarRadiometricCalibrationToImageFilter<ComplexFloatImageType,
                                                      FloatImageType>     CalibrationFilterType;

private:
  void DoInit()
  {
    SetName("SarRadiometricCalibration");
    SetDescription("Perform radiometric calibration of SAR images. Following sensors are supported: TerraSAR-X, Sentinel1 and Radarsat-2.Both Single Look Complex(SLC) and detected products are supported as input.\n");

    // Documentation
    SetDocName("SAR Radiometric calibration");
    SetDocLongDescription("The objective of SAR calibration is to provide imagery in which the pixel values can be directly related to the radar backscatter of the scene. This application allows to compute Sigma Naught (Radiometric Calibration) for TerraSAR-X, Sentinel1 L1 and Radarsat-2 sensors. Metadata are automatically retrieved from image products.The application supports complex and non-complex images (SLC or detected products).\n");
    SetDocLimitations("None");
    SetDocAuthors("OTB-Team");
    SetDocSeeAlso(" ");

    AddDocTag(Tags::Calibration);
    AddDocTag(Tags::SAR);

    AddParameter(ParameterType_ComplexInputImage,  "in", "Input Image");
    SetParameterDescription("in", "Input complex image");

    AddParameter(ParameterType_OutputImage,  "out", "Output Image");
    SetParameterDescription("out", "Output calibrated image. This image contains the backscatter (sigmaNought) of the input image.");

    AddRAMParameter();

    AddParameter(ParameterType_Empty, "noise", "Disable Noise");
    SetParameterDescription("noise", "Flag to disable noise. For 5.2.0 release, the noise values are only read by TerraSARX product.");
    MandatoryOff("noise");

    AddParameter(ParameterType_Choice, "lut", "Lookup table sigma /gamma/ beta/ DN.");
    SetParameterDescription("lut", "Lookup table values are not available with all SAR products. Products that provide lookup table with metadata are: Sentinel1, Radarsat2.");
    AddChoice("lut.sigma", "Use sigma nought lookup");
    SetParameterDescription("lut.sigma","Use Sigma nought lookup value from product metadata");
    AddChoice("lut.gamma", "Use gamma nought lookup");
    SetParameterDescription("lut.gamma","Use Gamma nought lookup value from product metadata");
    AddChoice("lut.beta", "Use beta nought lookup");
    SetParameterDescription("lut.beta","Use Beta nought lookup value from product metadata");
    AddChoice("lut.dn", "Use DN value lookup");
    SetParameterDescription("lut.dn","Use DN value lookup value from product metadata");
    SetDefaultParameterInt("lut", 0);

    // Doc example parameter settings
    SetDocExampleParameterValue("in", "RSAT_imagery_HH.tif");
    SetDocExampleParameterValue("out", "SarRadiometricCalibration.tif" );
  }

  void DoUpdateParameters()
  {

  }

  void DoExecute()
  {
    // Get the input complex image
    ComplexFloatImageType*  floatComplexImage = GetParameterComplexFloatImage("in");

    // Set the filer input
    m_CalibrationFilter = CalibrationFilterType::New();
    m_CalibrationFilter->SetInput(floatComplexImage);

    if (IsParameterEnabled("noise"))
      {
      m_CalibrationFilter->SetEnableNoise(false);
      }

    short lut = 0;

    lut = GetParameterInt("lut");

    m_CalibrationFilter->SetLookupSelected(lut);

    // Set the output image
    SetParameterOutputImage("out", m_CalibrationFilter->GetOutput());

  }

  CalibrationFilterType::Pointer   m_CalibrationFilter;

};
}
}

OTB_APPLICATION_EXPORT(otb::Wrapper::SarRadiometricCalibration)
<|endoftext|>


<commit_before>// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "chrome/browser/ui/gtk/tab_contents/chrome_web_contents_view_delegate_gtk.h"

#include <map>

#include "base/lazy_instance.h"
#include "chrome/browser/browser_shutdown.h"
#include "chrome/browser/tab_contents/web_drag_bookmark_handler_gtk.h"
#include "chrome/browser/ui/gtk/constrained_window_gtk.h"
#include "chrome/browser/ui/gtk/tab_contents/render_view_context_menu_gtk.h"
#include "chrome/browser/ui/tab_contents/chrome_web_contents_view_delegate.h"
#include "content/public/browser/render_process_host.h"
#include "content/public/browser/render_view_host.h"
#include "content/public/browser/render_widget_host_view.h"
#include "content/public/browser/web_contents.h"
#include "content/public/browser/web_contents_view.h"
#include "ui/base/gtk/focus_store_gtk.h"
#include "ui/base/gtk/gtk_floating_container.h"

namespace {

const char kViewDelegateUserDataKey[] = "ChromeWebContentsViewDelegateGtk";

class ViewDelegateUserData : public base::SupportsUserData::Data {
 public:
  explicit ViewDelegateUserData(ChromeWebContentsViewDelegateGtk* view_delegate)
      : view_delegate_(view_delegate) {}
  virtual ~ViewDelegateUserData() {}
  ChromeWebContentsViewDelegateGtk* view_delegate() { return view_delegate_; }

 private:
  ChromeWebContentsViewDelegateGtk* view_delegate_;  // unowned
};

}  // namespace

ChromeWebContentsViewDelegateGtk* ChromeWebContentsViewDelegateGtk::GetFor(
    content::WebContents* web_contents) {
  ViewDelegateUserData* user_data = static_cast<ViewDelegateUserData*>(
      web_contents->GetUserData(&kViewDelegateUserDataKey));

  return user_data ? user_data->view_delegate() : NULL;
}

ChromeWebContentsViewDelegateGtk::ChromeWebContentsViewDelegateGtk(
    content::WebContents* web_contents)
    : floating_(gtk_floating_container_new()),
      constrained_window_(NULL),
      web_contents_(web_contents),
      expanded_container_(NULL),
      focus_store_(NULL) {
  gtk_widget_set_name(floating_.get(), "chrome-tab-contents-view");
  g_signal_connect(floating_.get(), "set-floating-position",
                   G_CALLBACK(OnSetFloatingPositionThunk), this);

  // Stash this in the WebContents.
  web_contents->SetUserData(&kViewDelegateUserDataKey,
                            new ViewDelegateUserData(this));
}

ChromeWebContentsViewDelegateGtk::~ChromeWebContentsViewDelegateGtk() {
  floating_.Destroy();
}

void ChromeWebContentsViewDelegateGtk::AttachConstrainedWindow(
    ConstrainedWindowGtk* constrained_window) {
  DCHECK(constrained_window_ == NULL);

  constrained_window_ = constrained_window;
  gtk_floating_container_add_floating(GTK_FLOATING_CONTAINER(floating_.get()),
                                      constrained_window->widget());
}

void ChromeWebContentsViewDelegateGtk::RemoveConstrainedWindow(
    ConstrainedWindowGtk* constrained_window) {
  DCHECK(constrained_window == constrained_window_);

  constrained_window_ = NULL;
  gtk_container_remove(GTK_CONTAINER(floating_.get()),
                       constrained_window->widget());
}

void ChromeWebContentsViewDelegateGtk::Initialize(
    GtkWidget* expanded_container, ui::FocusStoreGtk* focus_store) {
  expanded_container_ = expanded_container;
  focus_store_ = focus_store;
  // We install a chrome specific handler to intercept bookmark drags for the
  // bookmark manager/extension API.
  bookmark_handler_gtk_.reset(new WebDragBookmarkHandlerGtk);

  gtk_container_add(GTK_CONTAINER(floating_.get()), expanded_container);
  gtk_widget_show(floating_.get());
}

gfx::NativeView ChromeWebContentsViewDelegateGtk::GetNativeView() const {
  return floating_.get();
}

void ChromeWebContentsViewDelegateGtk::Focus() {
  if (!constrained_window_) {
    GtkWidget* widget = web_contents_->GetView()->GetContentNativeView();
    if (widget)
      gtk_widget_grab_focus(widget);
  }
}

gboolean ChromeWebContentsViewDelegateGtk::OnNativeViewFocusEvent(
    GtkWidget* widget,
    GtkDirectionType type,
    gboolean* return_value) {
  // If we are showing a constrained window, don't allow the native view to take
  // focus.
  if (constrained_window_) {
    // If we return false, it will revert to the default handler, which will
    // take focus. We don't want that. But if we return true, the event will
    // stop being propagated, leaving focus wherever it is currently. That is
    // also bad. So we return false to let the default handler run, but take
    // focus first so as to trick it into thinking the view was already focused
    // and allowing the event to propagate.
    gtk_widget_grab_focus(widget);
    *return_value = FALSE;
    return TRUE;
  }

  // Let the default WebContentsViewGtk::OnFocus() behaviour run.
  return FALSE;
}

void ChromeWebContentsViewDelegateGtk::ShowContextMenu(
    const content::ContextMenuParams& params,
    content::ContextMenuSourceType type) {
  // Find out the RenderWidgetHostView that corresponds to the render widget on
  // which this context menu is showed, so that we can retrieve the last mouse
  // down event on the render widget and use it as the timestamp of the
  // activation event to show the context menu.
  content::RenderWidgetHostView* view = NULL;
  if (params.custom_context.render_widget_id !=
      content::CustomContextMenuContext::kCurrentRenderWidget) {
    content::RenderWidgetHost* host =
        web_contents_->GetRenderProcessHost()->GetRenderWidgetHostByID(
            params.custom_context.render_widget_id);
    if (!host) {
      NOTREACHED();
      return;
    }
    view = host->GetView();
  } else {
    view = web_contents_->GetRenderWidgetHostView();
  }

  context_menu_.reset(
      new RenderViewContextMenuGtk(web_contents_, params, view));
  context_menu_->Init();

  gfx::Rect bounds;
  web_contents_->GetView()->GetContainerBounds(&bounds);
  gfx::Point point = bounds.origin();
  point.Offset(params.x, params.y);
  context_menu_->Popup(point);
}

content::WebDragDestDelegate*
    ChromeWebContentsViewDelegateGtk::GetDragDestDelegate() {
  return bookmark_handler_gtk_.get();
}

void ChromeWebContentsViewDelegateGtk::OnSetFloatingPosition(
    GtkWidget* floating_container, GtkAllocation* allocation) {
  if (!constrained_window_)
    return;

  // Place each WebContentsModalDialog in the center of the view.
  GtkWidget* widget = constrained_window_->widget();
  DCHECK(gtk_widget_get_parent(widget) == floating_.get());

  GtkRequisition requisition;
  gtk_widget_size_request(widget, &requisition);

  GValue value = { 0, };
  g_value_init(&value, G_TYPE_INT);

  int child_x = std::max((allocation->width - requisition.width) / 2, 0);
  g_value_set_int(&value, child_x);
  gtk_container_child_set_property(GTK_CONTAINER(floating_container),
                                   widget, "x", &value);

  int child_y = std::max((allocation->height - requisition.height) / 2, 0);
  g_value_set_int(&value, child_y);
  gtk_container_child_set_property(GTK_CONTAINER(floating_container),
                                   widget, "y", &value);
  g_value_unset(&value);
}

namespace chrome {

content::WebContentsViewDelegate* CreateWebContentsViewDelegate(
    content::WebContents* web_contents) {
  return new ChromeWebContentsViewDelegateGtk(web_contents);
}

}  // namespace chrome
<commit_msg>Don't show empty popup menus on Gtk.<commit_after>// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "chrome/browser/ui/gtk/tab_contents/chrome_web_contents_view_delegate_gtk.h"

#include <map>

#include "base/lazy_instance.h"
#include "chrome/browser/browser_shutdown.h"
#include "chrome/browser/tab_contents/web_drag_bookmark_handler_gtk.h"
#include "chrome/browser/ui/gtk/constrained_window_gtk.h"
#include "chrome/browser/ui/gtk/tab_contents/render_view_context_menu_gtk.h"
#include "chrome/browser/ui/tab_contents/chrome_web_contents_view_delegate.h"
#include "content/public/browser/render_process_host.h"
#include "content/public/browser/render_view_host.h"
#include "content/public/browser/render_widget_host_view.h"
#include "content/public/browser/web_contents.h"
#include "content/public/browser/web_contents_view.h"
#include "ui/base/gtk/focus_store_gtk.h"
#include "ui/base/gtk/gtk_floating_container.h"

namespace {

const char kViewDelegateUserDataKey[] = "ChromeWebContentsViewDelegateGtk";

class ViewDelegateUserData : public base::SupportsUserData::Data {
 public:
  explicit ViewDelegateUserData(ChromeWebContentsViewDelegateGtk* view_delegate)
      : view_delegate_(view_delegate) {}
  virtual ~ViewDelegateUserData() {}
  ChromeWebContentsViewDelegateGtk* view_delegate() { return view_delegate_; }

 private:
  ChromeWebContentsViewDelegateGtk* view_delegate_;  // unowned
};

}  // namespace

ChromeWebContentsViewDelegateGtk* ChromeWebContentsViewDelegateGtk::GetFor(
    content::WebContents* web_contents) {
  ViewDelegateUserData* user_data = static_cast<ViewDelegateUserData*>(
      web_contents->GetUserData(&kViewDelegateUserDataKey));

  return user_data ? user_data->view_delegate() : NULL;
}

ChromeWebContentsViewDelegateGtk::ChromeWebContentsViewDelegateGtk(
    content::WebContents* web_contents)
    : floating_(gtk_floating_container_new()),
      constrained_window_(NULL),
      web_contents_(web_contents),
      expanded_container_(NULL),
      focus_store_(NULL) {
  gtk_widget_set_name(floating_.get(), "chrome-tab-contents-view");
  g_signal_connect(floating_.get(), "set-floating-position",
                   G_CALLBACK(OnSetFloatingPositionThunk), this);

  // Stash this in the WebContents.
  web_contents->SetUserData(&kViewDelegateUserDataKey,
                            new ViewDelegateUserData(this));
}

ChromeWebContentsViewDelegateGtk::~ChromeWebContentsViewDelegateGtk() {
  floating_.Destroy();
}

void ChromeWebContentsViewDelegateGtk::AttachConstrainedWindow(
    ConstrainedWindowGtk* constrained_window) {
  DCHECK(constrained_window_ == NULL);

  constrained_window_ = constrained_window;
  gtk_floating_container_add_floating(GTK_FLOATING_CONTAINER(floating_.get()),
                                      constrained_window->widget());
}

void ChromeWebContentsViewDelegateGtk::RemoveConstrainedWindow(
    ConstrainedWindowGtk* constrained_window) {
  DCHECK(constrained_window == constrained_window_);

  constrained_window_ = NULL;
  gtk_container_remove(GTK_CONTAINER(floating_.get()),
                       constrained_window->widget());
}

void ChromeWebContentsViewDelegateGtk::Initialize(
    GtkWidget* expanded_container, ui::FocusStoreGtk* focus_store) {
  expanded_container_ = expanded_container;
  focus_store_ = focus_store;
  // We install a chrome specific handler to intercept bookmark drags for the
  // bookmark manager/extension API.
  bookmark_handler_gtk_.reset(new WebDragBookmarkHandlerGtk);

  gtk_container_add(GTK_CONTAINER(floating_.get()), expanded_container);
  gtk_widget_show(floating_.get());
}

gfx::NativeView ChromeWebContentsViewDelegateGtk::GetNativeView() const {
  return floating_.get();
}

void ChromeWebContentsViewDelegateGtk::Focus() {
  if (!constrained_window_) {
    GtkWidget* widget = web_contents_->GetView()->GetContentNativeView();
    if (widget)
      gtk_widget_grab_focus(widget);
  }
}

gboolean ChromeWebContentsViewDelegateGtk::OnNativeViewFocusEvent(
    GtkWidget* widget,
    GtkDirectionType type,
    gboolean* return_value) {
  // If we are showing a constrained window, don't allow the native view to take
  // focus.
  if (constrained_window_) {
    // If we return false, it will revert to the default handler, which will
    // take focus. We don't want that. But if we return true, the event will
    // stop being propagated, leaving focus wherever it is currently. That is
    // also bad. So we return false to let the default handler run, but take
    // focus first so as to trick it into thinking the view was already focused
    // and allowing the event to propagate.
    gtk_widget_grab_focus(widget);
    *return_value = FALSE;
    return TRUE;
  }

  // Let the default WebContentsViewGtk::OnFocus() behaviour run.
  return FALSE;
}

void ChromeWebContentsViewDelegateGtk::ShowContextMenu(
    const content::ContextMenuParams& params,
    content::ContextMenuSourceType type) {
  // Find out the RenderWidgetHostView that corresponds to the render widget on
  // which this context menu is showed, so that we can retrieve the last mouse
  // down event on the render widget and use it as the timestamp of the
  // activation event to show the context menu.
  content::RenderWidgetHostView* view = NULL;
  if (params.custom_context.render_widget_id !=
      content::CustomContextMenuContext::kCurrentRenderWidget) {
    content::RenderWidgetHost* host =
        web_contents_->GetRenderProcessHost()->GetRenderWidgetHostByID(
            params.custom_context.render_widget_id);
    if (!host) {
      NOTREACHED();
      return;
    }
    view = host->GetView();
  } else {
    view = web_contents_->GetRenderWidgetHostView();
  }

  context_menu_.reset(
      new RenderViewContextMenuGtk(web_contents_, params, view));
  context_menu_->Init();

  // Don't show empty menus.
  if (context_menu_->menu_model().GetItemCount() == 0)
    return;

  gfx::Rect bounds;
  web_contents_->GetView()->GetContainerBounds(&bounds);
  gfx::Point point = bounds.origin();
  point.Offset(params.x, params.y);
  context_menu_->Popup(point);
}

content::WebDragDestDelegate*
    ChromeWebContentsViewDelegateGtk::GetDragDestDelegate() {
  return bookmark_handler_gtk_.get();
}

void ChromeWebContentsViewDelegateGtk::OnSetFloatingPosition(
    GtkWidget* floating_container, GtkAllocation* allocation) {
  if (!constrained_window_)
    return;

  // Place each WebContentsModalDialog in the center of the view.
  GtkWidget* widget = constrained_window_->widget();
  DCHECK(gtk_widget_get_parent(widget) == floating_.get());

  GtkRequisition requisition;
  gtk_widget_size_request(widget, &requisition);

  GValue value = { 0, };
  g_value_init(&value, G_TYPE_INT);

  int child_x = std::max((allocation->width - requisition.width) / 2, 0);
  g_value_set_int(&value, child_x);
  gtk_container_child_set_property(GTK_CONTAINER(floating_container),
                                   widget, "x", &value);

  int child_y = std::max((allocation->height - requisition.height) / 2, 0);
  g_value_set_int(&value, child_y);
  gtk_container_child_set_property(GTK_CONTAINER(floating_container),
                                   widget, "y", &value);
  g_value_unset(&value);
}

namespace chrome {

content::WebContentsViewDelegate* CreateWebContentsViewDelegate(
    content::WebContents* web_contents) {
  return new ChromeWebContentsViewDelegateGtk(web_contents);
}

}  // namespace chrome
<|endoftext|>


<commit_before>#include <cutehmi/dataacquisition/Schema.hpp>
#include <cutehmi/dataacquisition/Exception.hpp>

#include "../../../cutehmi.dirs.hpp"

#include <QFile>
#include <QSqlRecord>

namespace cutehmi {
namespace dataacquisition {

Schema::Schema(QObject * parent):
	shareddatabase::DataObject(parent),
	m(new Members)
{
}

QString Schema::name() const
{
	return m->name;
}

void Schema::setName(const QString & name)
{
	if (m->name != name) {
		m->name = name;
		emit nameChanged();
	}
}

QString Schema::user() const
{
	return m->user;
}

void Schema::setUser(const QString & user)
{
	if (m->user != user) {
		m->user = user;
		emit userChanged();
	}
}

void Schema::create()
{
	worker([this](QSqlDatabase & db) {

		bool warning = false;
		bool error = false;

		if (db.driverName() == "QPSQL") {
			QSqlQuery query(db);
			try {
				CUTEHMI_DEBUG("Creating schema...");

				QString queryString = readScript(POSTGRESQL_SCRIPTS_SUBDIR, "create.sql").arg(name());
				CUTEHMI_DEBUG("SQL query:\n```\n" << queryString + "\n```");

				if (!query.exec(queryString))
					error = true;
				pushError(query.lastError(), query.lastQuery());
				query.finish();
			} catch (const Exception & e) {
				CUTEHMI_CRITICAL(e.what());
				error = true;
			}

			if (!user().isEmpty()) {
				CUTEHMI_DEBUG("Setting schema owner...");

				const char * alterSchemaQuery = R"SQL(
					ALTER SCHEMA %1 OWNER TO %2;
				)SQL";

				if (!query.exec(QString(alterSchemaQuery).arg(name(), user())))
					warning = true;

				pushError(query.lastError(), query.lastQuery());
				query.finish();
			}
		} else if (db.driverName() == "QSQLITE") {
			QSqlQuery query(db);
			try {
				CUTEHMI_DEBUG("Creating schema...");

				QString queryString = readScript(SQLITE_SCRIPTS_SUBDIR, "create.sql").arg(name());
				QStringList queryList = queryString.split(';');
				queryList.removeLast();	// Remove empty query.
				for (auto queryIt = queryList.begin(); queryIt != queryList.end(); ++queryIt) {
					CUTEHMI_DEBUG("SQL query:\n```\n" << *queryIt + "\n```");

					if (!query.exec(*queryIt))
						error = true;
					pushError(query.lastError(), query.lastQuery());
					query.finish();
				}
			} catch (const Exception & e) {
				CUTEHMI_CRITICAL(e.what());
				error = true;
			}
		} else {
			emit errored(CUTEHMI_ERROR(tr("Driver '%1' is not supported.").arg(db.driverName())));
			error = true;
		}

		if (error)
			Notification::Critical(tr("Failed to create '%1' schema.").arg(name()));
		else if (warning)
			Notification::Warning(tr("Created '%1' schema although the operation wasn't clean.").arg(name()));
		else
			Notification::Info(tr("Successfully created '%1' schema.").arg(name()));

		if (error)
			emit created(false);
		else
			emit created(true);
	})->work();
}

void Schema::drop()
{
	worker([this](QSqlDatabase & db) {

		bool warning = false;
		bool error = false;

		if (db.driverName() == "QPSQL") {
			QSqlQuery query(db);
			try {
				CUTEHMI_DEBUG("Dropping schema...");

				QString queryString = readScript(POSTGRESQL_SCRIPTS_SUBDIR, "drop.sql").arg(name());
				CUTEHMI_DEBUG("SQL query:\n```\n" << queryString + "\n```");

				if (!query.exec(queryString))
					error = true;
				pushError(query.lastError(), query.lastQuery());
				query.finish();
			} catch (const Exception & e) {
				CUTEHMI_CRITICAL(e.what());
				error = true;
			}
		} else if (db.driverName() == "QSQLITE") {
			QSqlQuery query(db);
			try {
				CUTEHMI_DEBUG("Dropping schema...");

				QString queryString = readScript(SQLITE_SCRIPTS_SUBDIR, "drop.sql").arg(name());
				QStringList queryList = queryString.split(';');
				queryList.removeLast();	// Remove empty query.
				for (auto queryIt = queryList.begin(); queryIt != queryList.end(); ++queryIt) {
					CUTEHMI_DEBUG("SQL query:\n```\n" << *queryIt + "\n```");

					if (!query.exec(*queryIt))
						warning = true;
					pushError(query.lastError(), query.lastQuery());
					query.finish();
				}
			} catch (const Exception & e) {
				CUTEHMI_CRITICAL(e.what());
				error = true;
			}
		} else {
			emit errored(CUTEHMI_ERROR(tr("Driver '%1' is not supported.").arg(db.driverName())));
			error = true;
		}

		if (error)
			Notification::Critical(tr("Failed to drop '%1' schema.").arg(name()));
		else if (warning)
			Notification::Warning(tr("Dropped '%1' schema although the operation wasn't clean.").arg(name()));
		else
			Notification::Info(tr("Dropped '%1' schema.").arg(name()));

		if (error)
			emit dropped(false);
		else
			emit dropped(true);
	})->work();
}

void Schema::validate()
{
	worker([this](QSqlDatabase & db) {
		if (db.driverName() == "QPSQL") {
			QSqlQuery query(db);

			bool result = true;

			result &= validatePostgresTable("tag", query);

			result &= validatePostgresTable("history_int", query);
			result &= validatePostgresTable("history_bool", query);
			result &= validatePostgresTable("history_real", query);

			result &= validatePostgresTable("event_int", query);
			result &= validatePostgresTable("event_bool", query);
			result &= validatePostgresTable("event_real", query);

			result &= validatePostgresTable("recency_int", query);
			result &= validatePostgresTable("recency_bool", query);
			result &= validatePostgresTable("recency_real", query);

			emit validated(result);
		} else if (db.driverName() == "QSQLITE") {
			QSqlQuery query(db);

			bool result = true;

			result &= validateSqliteTable("tag", query);

			result &= validateSqliteTable("history_int", query);
			result &= validateSqliteTable("history_bool", query);
			result &= validateSqliteTable("history_real", query);

			result &= validateSqliteTable("event_int", query);
			result &= validateSqliteTable("event_bool", query);
			result &= validateSqliteTable("event_real", query);

			result &= validateSqliteTable("recency_int", query);
			result &= validateSqliteTable("recency_bool", query);
			result &= validateSqliteTable("recency_real", query);

			emit validated(result);
		} else {
			emit errored(CUTEHMI_ERROR(tr("Driver '%1' is not supported.").arg(db.driverName())));
			emit validated(false);
		}
	})->work();
}

bool Schema::validatePostgresTable(const QString & tableName, QSqlQuery & query)
{
	bool result = true;

	CUTEHMI_DEBUG("Checking if '" << tableName << "' table exists...");
	const char * tableExistsQuery = R"SQL(
		SELECT EXISTS (
			SELECT FROM information_schema.tables
			WHERE table_schema = '%1' AND table_name = '%2'
		);
	)SQL";
	query.exec(QString(tableExistsQuery).arg(name(), tableName));
	pushError(query.lastError(), query.lastQuery());
	int existsIndex = query.record().indexOf("exists");
	if (query.first())
		if (!query.value(existsIndex).toBool()) {
			emit errored(CUTEHMI_ERROR(QObject::tr("Table '%1' does not exist in schema '%2'.").arg(tableName, name())));
			result = false;
		}
	query.finish();

	return result;
}

bool Schema::validateSqliteTable(const QString & tableName, QSqlQuery & query)
{
	bool result = true;

	CUTEHMI_DEBUG("Checking if '" << tableName << "' table exists...");
	const char * tableExistsQuery = R"SQL(
		SELECT name FROM sqlite_master WHERE type='table' AND name='%1.%2';
	)SQL";
	query.exec(QString(tableExistsQuery).arg(name(), tableName));
	pushError(query.lastError(), query.lastQuery());
	if (!query.first()) {
		emit errored(CUTEHMI_ERROR(QObject::tr("Table '%1' does not exist in schema '%2'.").arg(tableName, name())));
		result = false;
	}
	query.finish();

	return result;
}

QString Schema::readScript(const QString & dbms, const QString & scriptName) const
{
	QFile file(QString(CUTEHMI_DIRS_TOOL_RELATIVE_PATH) + "/" + SQL_SCRIPTS_SUBDIR + "/" + dbms + "/" + scriptName);
	if (!file.open(QIODevice::ReadOnly | QIODevice::Text))
		throw Exception(QString("Could not open file '%1'").arg(file.fileName()));
	return QTextStream(& file).readAll();
}

}
}

//(c)C: Copyright © 2020-2022, Michał Policht <michal@policht.pl>, Yuri Chornoivan <yurchor@ukr.net>. All rights reserved.
//(c)C: SPDX-License-Identifier: LGPL-3.0-or-later OR MIT
//(c)C: This file is a part of CuteHMI.
//(c)C: CuteHMI is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
//(c)C: CuteHMI is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more details.
//(c)C: You should have received a copy of the GNU Lesser General Public License along with CuteHMI.  If not, see <https://www.gnu.org/licenses/>.
//(c)C: Additionally, this file is licensed under terms of MIT license as expressed below.
//(c)C: Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
//(c)C: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
//(c)C: THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
<commit_msg>Add debug messages for validating schema<commit_after>#include <cutehmi/dataacquisition/Schema.hpp>
#include <cutehmi/dataacquisition/Exception.hpp>

#include "../../../cutehmi.dirs.hpp"

#include <QFile>
#include <QSqlRecord>

namespace cutehmi {
namespace dataacquisition {

Schema::Schema(QObject * parent):
	shareddatabase::DataObject(parent),
	m(new Members)
{
}

QString Schema::name() const
{
	return m->name;
}

void Schema::setName(const QString & name)
{
	if (m->name != name) {
		m->name = name;
		emit nameChanged();
	}
}

QString Schema::user() const
{
	return m->user;
}

void Schema::setUser(const QString & user)
{
	if (m->user != user) {
		m->user = user;
		emit userChanged();
	}
}

void Schema::create()
{
	worker([this](QSqlDatabase & db) {

		bool warning = false;
		bool error = false;

		if (db.driverName() == "QPSQL") {
			CUTEHMI_DEBUG("Creating schema...");

			QSqlQuery query(db);
			try {
				QString queryString = readScript(POSTGRESQL_SCRIPTS_SUBDIR, "create.sql").arg(name());
				CUTEHMI_DEBUG("SQL query:\n```\n" << queryString + "\n```");

				if (!query.exec(queryString))
					error = true;
				pushError(query.lastError(), query.lastQuery());
				query.finish();
			} catch (const Exception & e) {
				CUTEHMI_CRITICAL(e.what());
				error = true;
			}

			if (!user().isEmpty()) {
				CUTEHMI_DEBUG("Setting schema owner...");

				const char * alterSchemaQuery = R"SQL(
					ALTER SCHEMA %1 OWNER TO %2;
				)SQL";

				if (!query.exec(QString(alterSchemaQuery).arg(name(), user())))
					warning = true;

				pushError(query.lastError(), query.lastQuery());
				query.finish();
			}
		} else if (db.driverName() == "QSQLITE") {
			CUTEHMI_DEBUG("Creating schema...");

			QSqlQuery query(db);
			try {
				QString queryString = readScript(SQLITE_SCRIPTS_SUBDIR, "create.sql").arg(name());
				QStringList queryList = queryString.split(';');
				queryList.removeLast();	// Remove empty query.
				for (auto queryIt = queryList.begin(); queryIt != queryList.end(); ++queryIt) {
					CUTEHMI_DEBUG("SQL query:\n```\n" << *queryIt + "\n```");

					if (!query.exec(*queryIt))
						error = true;
					pushError(query.lastError(), query.lastQuery());
					query.finish();
				}
			} catch (const Exception & e) {
				CUTEHMI_CRITICAL(e.what());
				error = true;
			}
		} else {
			emit errored(CUTEHMI_ERROR(tr("Driver '%1' is not supported.").arg(db.driverName())));
			error = true;
		}

		if (error)
			Notification::Critical(tr("Failed to create '%1' schema.").arg(name()));
		else if (warning)
			Notification::Warning(tr("Created '%1' schema although the operation wasn't clean.").arg(name()));
		else
			Notification::Info(tr("Successfully created '%1' schema.").arg(name()));

		if (error)
			emit created(false);
		else
			emit created(true);
	})->work();
}

void Schema::drop()
{
	worker([this](QSqlDatabase & db) {

		bool warning = false;
		bool error = false;

		if (db.driverName() == "QPSQL") {
			CUTEHMI_DEBUG("Dropping schema...");

			QSqlQuery query(db);
			try {
				QString queryString = readScript(POSTGRESQL_SCRIPTS_SUBDIR, "drop.sql").arg(name());
				CUTEHMI_DEBUG("SQL query:\n```\n" << queryString + "\n```");

				if (!query.exec(queryString))
					error = true;
				pushError(query.lastError(), query.lastQuery());
				query.finish();
			} catch (const Exception & e) {
				CUTEHMI_CRITICAL(e.what());
				error = true;
			}
		} else if (db.driverName() == "QSQLITE") {
			CUTEHMI_DEBUG("Dropping schema...");

			QSqlQuery query(db);
			try {
				QString queryString = readScript(SQLITE_SCRIPTS_SUBDIR, "drop.sql").arg(name());
				QStringList queryList = queryString.split(';');
				queryList.removeLast();	// Remove empty query.
				for (auto queryIt = queryList.begin(); queryIt != queryList.end(); ++queryIt) {
					CUTEHMI_DEBUG("SQL query:\n```\n" << *queryIt + "\n```");

					if (!query.exec(*queryIt))
						warning = true;
					pushError(query.lastError(), query.lastQuery());
					query.finish();
				}
			} catch (const Exception & e) {
				CUTEHMI_CRITICAL(e.what());
				error = true;
			}
		} else {
			emit errored(CUTEHMI_ERROR(tr("Driver '%1' is not supported.").arg(db.driverName())));
			error = true;
		}

		if (error)
			Notification::Critical(tr("Failed to drop '%1' schema.").arg(name()));
		else if (warning)
			Notification::Warning(tr("Dropped '%1' schema although the operation wasn't clean.").arg(name()));
		else
			Notification::Info(tr("Dropped '%1' schema.").arg(name()));

		if (error)
			emit dropped(false);
		else
			emit dropped(true);
	})->work();
}

void Schema::validate()
{
	worker([this](QSqlDatabase & db) {
		if (db.driverName() == "QPSQL") {
			CUTEHMI_DEBUG("Validating schema...");

			QSqlQuery query(db);

			bool result = true;

			result &= validatePostgresTable("tag", query);

			result &= validatePostgresTable("history_int", query);
			result &= validatePostgresTable("history_bool", query);
			result &= validatePostgresTable("history_real", query);

			result &= validatePostgresTable("event_int", query);
			result &= validatePostgresTable("event_bool", query);
			result &= validatePostgresTable("event_real", query);

			result &= validatePostgresTable("recency_int", query);
			result &= validatePostgresTable("recency_bool", query);
			result &= validatePostgresTable("recency_real", query);

			emit validated(result);
		} else if (db.driverName() == "QSQLITE") {
			CUTEHMI_DEBUG("Validating schema...");

			QSqlQuery query(db);

			bool result = true;

			result &= validateSqliteTable("tag", query);

			result &= validateSqliteTable("history_int", query);
			result &= validateSqliteTable("history_bool", query);
			result &= validateSqliteTable("history_real", query);

			result &= validateSqliteTable("event_int", query);
			result &= validateSqliteTable("event_bool", query);
			result &= validateSqliteTable("event_real", query);

			result &= validateSqliteTable("recency_int", query);
			result &= validateSqliteTable("recency_bool", query);
			result &= validateSqliteTable("recency_real", query);

			emit validated(result);
		} else {
			emit errored(CUTEHMI_ERROR(tr("Driver '%1' is not supported.").arg(db.driverName())));
			emit validated(false);
		}
	})->work();
}

bool Schema::validatePostgresTable(const QString & tableName, QSqlQuery & query)
{
	bool result = true;

	CUTEHMI_DEBUG("Checking if '" << tableName << "' table exists...");
	const char * tableExistsQuery = R"SQL(
		SELECT EXISTS (
			SELECT FROM information_schema.tables
			WHERE table_schema = '%1' AND table_name = '%2'
		);
	)SQL";
	query.exec(QString(tableExistsQuery).arg(name(), tableName));
	pushError(query.lastError(), query.lastQuery());
	int existsIndex = query.record().indexOf("exists");
	if (query.first())
		if (!query.value(existsIndex).toBool()) {
			emit errored(CUTEHMI_ERROR(QObject::tr("Table '%1' does not exist in schema '%2'.").arg(tableName, name())));
			result = false;
		}
	query.finish();

	return result;
}

bool Schema::validateSqliteTable(const QString & tableName, QSqlQuery & query)
{
	bool result = true;

	CUTEHMI_DEBUG("Checking if '" << tableName << "' table exists...");
	const char * tableExistsQuery = R"SQL(
		SELECT name FROM sqlite_master WHERE type='table' AND name='%1.%2';
	)SQL";
	query.exec(QString(tableExistsQuery).arg(name(), tableName));
	pushError(query.lastError(), query.lastQuery());
	if (!query.first()) {
		emit errored(CUTEHMI_ERROR(QObject::tr("Table '%1' does not exist in schema '%2'.").arg(tableName, name())));
		result = false;
	}
	query.finish();

	return result;
}

QString Schema::readScript(const QString & dbms, const QString & scriptName) const
{
	QFile file(QString(CUTEHMI_DIRS_TOOL_RELATIVE_PATH) + "/" + SQL_SCRIPTS_SUBDIR + "/" + dbms + "/" + scriptName);
	if (!file.open(QIODevice::ReadOnly | QIODevice::Text))
		throw Exception(QString("Could not open file '%1'").arg(file.fileName()));
	return QTextStream(& file).readAll();
}

}
}

//(c)C: Copyright © 2020-2022, Michał Policht <michal@policht.pl>, Yuri Chornoivan <yurchor@ukr.net>. All rights reserved.
//(c)C: SPDX-License-Identifier: LGPL-3.0-or-later OR MIT
//(c)C: This file is a part of CuteHMI.
//(c)C: CuteHMI is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
//(c)C: CuteHMI is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more details.
//(c)C: You should have received a copy of the GNU Lesser General Public License along with CuteHMI.  If not, see <https://www.gnu.org/licenses/>.
//(c)C: Additionally, this file is licensed under terms of MIT license as expressed below.
//(c)C: Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
//(c)C: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
//(c)C: THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
<|endoftext|>


<commit_before>/*****************************************************************************/
/**
 *  @file   LabColor.cpp
 *  @author Naohisa Sakamoto
 */
/*----------------------------------------------------------------------------
 *
 *  Copyright (c) Visualization Laboratory, Kyoto University.
 *  All rights reserved.
 *  See http://www.viz.media.kyoto-u.ac.jp/kvs/copyright/ for details.
 *
 *  $Id$
 */
/*****************************************************************************/
#include "LabColor.h"
#include "XYZColor.h"
#include "MshColor.h"

namespace
{

//const kvs::Vec3 ReferenceWhite( 1.0, 1.0, 1.0 );
//const kvs::Vec3 ReferenceWhite( 0.964221, 1.0, 0.825211 ); // D50
const kvs::Vec3 ReferenceWhite( 0.95047, 1.0, 1.08883 ); // D65

kvs::Real32 f( const kvs::Real32 t )
{
    if ( t > 0.008856 ) { return std::pow( t, 1.0 / 3.0 ); }
    else { return 7.787037 * t + 16.0 / 116.0; }
}

kvs::Real32 finv( const kvs::Real32 t )
{
    if ( t > 0.008856 ) { return std::pow( t, 3.0 ); }
    else { return ( t - 16.0 / 116.0 ) / 7.787037; }
}

kvs::LabColor XYZ2Lab( const kvs::XYZColor& xyz )
{
    const kvs::Real32 Xn = ReferenceWhite.x();
    const kvs::Real32 Yn = ReferenceWhite.y();
    const kvs::Real32 Zn = ReferenceWhite.z();

    const kvs::Real32 X = xyz.x();
    const kvs::Real32 Y = xyz.y();
    const kvs::Real32 Z = xyz.z();

    const kvs::Real32 l = 116.0 * ( f( Y / Yn ) - 16.0 / 116.0 );
    const kvs::Real32 a = 500.0 * ( f( X / Xn ) - f( Y / Yn ) );
    const kvs::Real32 b = 200.0 * ( f( Y / Yn ) - f( Z / Zn ) );
    return kvs::LabColor( l, a, b );
}

kvs::XYZColor Lab2XYZ( const kvs::LabColor& lab )
{
    const kvs::Real32 Xn = ReferenceWhite.x();
    const kvs::Real32 Yn = ReferenceWhite.y();
    const kvs::Real32 Zn = ReferenceWhite.z();

    const kvs::Real32 l = lab.l();
    const kvs::Real32 a = lab.a();
    const kvs::Real32 b = lab.b();

    const kvs::Real32 y = ( l + 16.0 ) / 116.0;
    const kvs::Real32 x = a / 500.0 + y;
    const kvs::Real32 z = y - b / 200.0;

    const kvs::Real32 X = Xn * finv( x );
    const kvs::Real32 Y = Yn * finv( y );
    const kvs::Real32 Z = Zn * finv( z );
    return kvs::XYZColor( X, Y, Z );
}

}

namespace kvs
{

LabColor::LabColor( kvs::Real32 l, kvs::Real32 a, kvs::Real32 b ):
    m_l( l ),
    m_a( a ),
    m_b( b )
{
}

LabColor::LabColor( const kvs::Vec3& lab ):
    m_l( lab[0] ),
    m_a( lab[1] ),
    m_b( lab[2] )
{
}

LabColor::LabColor( const kvs::LabColor& lab ):
    m_l( lab.l() ),
    m_a( lab.a() ),
    m_b( lab.b() )
{
}

LabColor::LabColor( const kvs::XYZColor& xyz )
{
    *this = ::XYZ2Lab( xyz );
}

kvs::XYZColor LabColor::toXYZColor() const
{
    return ::Lab2XYZ( *this );
}

kvs::MshColor LabColor::toMshColor() const
{
    return kvs::MshColor( *this );
}

kvs::LabColor& LabColor::operator += ( const kvs::LabColor& lab )
{
    m_l += lab.l();
    m_a += lab.a();
    m_b += lab.b();
    return *this;
}

kvs::LabColor& LabColor::operator -= ( const kvs::LabColor& lab )
{
    m_l -= lab.l();
    m_a -= lab.a();
    m_b -= lab.b();
    return *this;
}

kvs::LabColor& LabColor::operator = ( const kvs::LabColor& lab )
{
    m_l = lab.l();
    m_a = lab.a();
    m_b = lab.b();
    return *this;
}

kvs::LabColor& LabColor::operator = ( const kvs::XYZColor& xyz )
{
    *this = ::XYZ2Lab( xyz );
    return *this;
}

kvs::LabColor operator + ( const kvs::LabColor& a, const kvs::LabColor& b )
{
    kvs::LabColor ret( a ); ret += b;
    return ret;
}

bool operator == ( const kvs::LabColor& a, const kvs::LabColor& b )
{
    return
        kvs::Math::Equal( a.l(), b.l() ) &&
        kvs::Math::Equal( a.a(), b.a() ) &&
        kvs::Math::Equal( a.b(), b.b() );
}

} // end of namespace kvs
<commit_msg>modified.<commit_after>/*****************************************************************************/
/**
 *  @file   LabColor.cpp
 *  @author Naohisa Sakamoto
 */
/*----------------------------------------------------------------------------
 *
 *  Copyright (c) Visualization Laboratory, Kyoto University.
 *  All rights reserved.
 *  See http://www.viz.media.kyoto-u.ac.jp/kvs/copyright/ for details.
 *
 *  $Id$
 */
/*****************************************************************************/
#include "LabColor.h"
#include "XYZColor.h"
#include "MshColor.h"

namespace
{

//const kvs::Vec3 ReferenceWhite( 1.0, 1.0, 1.0 );
//const kvs::Vec3 ReferenceWhite( 0.964221, 1.0, 0.825211 ); // D50
const kvs::Vec3 ReferenceWhite( 0.95047, 1.0, 1.08883 ); // D65

kvs::Real32 f( const kvs::Real32 t )
{
    if ( t > 0.008856 ) { return std::pow( t, 1.0f / 3.0f ); }
    else { return 7.787037 * t + 16.0 / 116.0; }
}

kvs::Real32 finv( const kvs::Real32 t )
{
    if ( t > 0.008856 ) { return std::pow( t, 3.0f ); }
    else { return ( t - 16.0 / 116.0 ) / 7.787037; }
}

kvs::LabColor XYZ2Lab( const kvs::XYZColor& xyz )
{
    const kvs::Real32 Xn = ReferenceWhite.x();
    const kvs::Real32 Yn = ReferenceWhite.y();
    const kvs::Real32 Zn = ReferenceWhite.z();

    const kvs::Real32 X = xyz.x();
    const kvs::Real32 Y = xyz.y();
    const kvs::Real32 Z = xyz.z();

    const kvs::Real32 l = 116.0 * ( f( Y / Yn ) - 16.0 / 116.0 );
    const kvs::Real32 a = 500.0 * ( f( X / Xn ) - f( Y / Yn ) );
    const kvs::Real32 b = 200.0 * ( f( Y / Yn ) - f( Z / Zn ) );
    return kvs::LabColor( l, a, b );
}

kvs::XYZColor Lab2XYZ( const kvs::LabColor& lab )
{
    const kvs::Real32 Xn = ReferenceWhite.x();
    const kvs::Real32 Yn = ReferenceWhite.y();
    const kvs::Real32 Zn = ReferenceWhite.z();

    const kvs::Real32 l = lab.l();
    const kvs::Real32 a = lab.a();
    const kvs::Real32 b = lab.b();

    const kvs::Real32 y = ( l + 16.0 ) / 116.0;
    const kvs::Real32 x = a / 500.0 + y;
    const kvs::Real32 z = y - b / 200.0;

    const kvs::Real32 X = Xn * finv( x );
    const kvs::Real32 Y = Yn * finv( y );
    const kvs::Real32 Z = Zn * finv( z );
    return kvs::XYZColor( X, Y, Z );
}

}

namespace kvs
{

LabColor::LabColor( kvs::Real32 l, kvs::Real32 a, kvs::Real32 b ):
    m_l( l ),
    m_a( a ),
    m_b( b )
{
}

LabColor::LabColor( const kvs::Vec3& lab ):
    m_l( lab[0] ),
    m_a( lab[1] ),
    m_b( lab[2] )
{
}

LabColor::LabColor( const kvs::LabColor& lab ):
    m_l( lab.l() ),
    m_a( lab.a() ),
    m_b( lab.b() )
{
}

LabColor::LabColor( const kvs::XYZColor& xyz )
{
    *this = ::XYZ2Lab( xyz );
}

kvs::XYZColor LabColor::toXYZColor() const
{
    return ::Lab2XYZ( *this );
}

kvs::MshColor LabColor::toMshColor() const
{
    return kvs::MshColor( *this );
}

kvs::LabColor& LabColor::operator += ( const kvs::LabColor& lab )
{
    m_l += lab.l();
    m_a += lab.a();
    m_b += lab.b();
    return *this;
}

kvs::LabColor& LabColor::operator -= ( const kvs::LabColor& lab )
{
    m_l -= lab.l();
    m_a -= lab.a();
    m_b -= lab.b();
    return *this;
}

kvs::LabColor& LabColor::operator = ( const kvs::LabColor& lab )
{
    m_l = lab.l();
    m_a = lab.a();
    m_b = lab.b();
    return *this;
}

kvs::LabColor& LabColor::operator = ( const kvs::XYZColor& xyz )
{
    *this = ::XYZ2Lab( xyz );
    return *this;
}

kvs::LabColor operator + ( const kvs::LabColor& a, const kvs::LabColor& b )
{
    kvs::LabColor ret( a ); ret += b;
    return ret;
}

bool operator == ( const kvs::LabColor& a, const kvs::LabColor& b )
{
    return
        kvs::Math::Equal( a.l(), b.l() ) &&
        kvs::Math::Equal( a.a(), b.a() ) &&
        kvs::Math::Equal( a.b(), b.b() );
}

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