<commit_before>/*! \file */ // Copyright 2011-2020 Tyler Gilbert and Stratify Labs, Inc; see LICENSE.md for rights.
#ifndef SAPI_UX_COMPONENT_HPP
#define SAPI_UX_COMPONENT_HPP

#include "../api/WorkObject.hpp"
#include "../hal/Display.hpp"
#include "../var/String.hpp"
#include "../sgfx/Theme.hpp"
#include "Drawing.hpp"
#include "Event.hpp"

#define COMPONENT_SIGNATURE(a,b,c,d) ((a << 24) | (b << 16) | (c << 8) | (d))

namespace ux {

class EventLoop;

class Component : public Drawing {
public:

	Component(
			const var::String & name,
			u32 signature = 0) :
		m_name(name), m_signature(signature){
	}
	virtual ~Component();

	template<typename T> T * reinterpret(){
		return static_cast<T*>(this);
	}

	static u32 whatis_signature(){
		return 0;
	}

	enum sgfx::Theme::style theme_style() const {
		return m_theme_style;
	}

	enum sgfx::Theme::state theme_state() const {
		return m_theme_state;
	}

	bool is_antialias() const {
		return m_is_antialias;
	}

	Component& set_antialias(bool value = true){
		m_is_antialias = value;
		return *this;
	}

	bool is_visible() const {
		return m_is_visible;
	}

	bool is_enabled() const {
		return m_is_enabled;
	}

	const sgfx::Theme * theme() const;
	const hal::Display * display() const;
	hal::Display * display();

	//update the location of the component (allow animations)

	virtual void handle_event(const ux::Event & event){}

	const var::String & name() const {
		return m_name;
	}

	void apply_antialias_filter(const DrawingAttributes & attributes);
	void apply_antialias_filter(const DrawingScaledAttributes & attributes);

	void redraw(){
		if( is_ready_to_draw() ){
			draw(local_drawing_attributes());
			set_refresh_drawing_pending();
		}
	}

	sgfx::Region region() const {
		return m_reference_drawing_attributes.calculate_region_on_bitmap();
	}

	bool contains(const sgfx::Point & point){
		return sgfx::Region(
					m_reference_drawing_attributes.calculate_region_on_bitmap()
					).contains(point);
	}

	DrawingPoint translate_point(const sgfx::Point & point);

	void erase();

	void set_refresh_drawing_pending(){
		m_is_refresh_drawing_pending = true;
	}

	EventLoop * event_loop(){
		return m_event_loop;
	}

	const EventLoop * event_loop() const {
		return m_event_loop;
	}

	void set_drawing_area(const DrawingArea & drawing_area){
		m_reference_drawing_attributes.set_area(drawing_area);
	}

	void set_drawing_point(const DrawingPoint & drawing_point){
		m_reference_drawing_attributes.set_point(drawing_point);
	}

	void set_theme_style(enum sgfx::Theme::style value){
		m_theme_style = value;
	}

	void set_theme_state(enum sgfx::Theme::state value){
		m_theme_state = value;
	}

protected:

	bool m_is_visible = false;
	bool m_is_enabled = true;
	bool m_is_created = false;
	virtual void examine_visibility();

	virtual void touch_drawing_attributes(){}

	void set_refresh_region(const sgfx::Region & region){
		if( region.width() * region.height() == 0 ){
			m_refresh_region = m_local_bitmap.region();
		} else {
			m_refresh_region = region;
		}
	}

	bool is_refresh_drawing_pending() const {
		return m_is_refresh_drawing_pending;
	}

	void refresh_drawing();
	friend class Layout;
	friend class LayoutComponent;

	const DrawingAttributes & local_drawing_attributes() const {
		return m_local_drawing_attributes;
	}

	const DrawingAttributes& reference_drawing_attributes() const {
		return m_reference_drawing_attributes;
	}

	DrawingAttributes& reference_drawing_attributes(){
		return m_reference_drawing_attributes;
	}

	virtual void set_enabled_internal(bool value = true){
		if( m_is_enabled != value ){
			m_is_enabled = value;
			examine_visibility();
		}
	}

	virtual void set_visible_internal(bool value = true){
		if( m_is_visible != value ){
			m_is_visible = value;
			examine_visibility();
		}
	}

	void set_event_loop(EventLoop * event_loop){
		m_event_loop = event_loop;
	}

	bool is_ready_to_draw() const {
		return is_enabled() && is_visible();
	}

	u32 signature() const {
		return m_signature;
	}

private:

	var::String m_name;
	const u32 m_signature;
	//needs to know where on the display it is drawn
	DrawingAttributes m_reference_drawing_attributes;
	DrawingAttributes m_local_drawing_attributes;
	sgfx::Bitmap m_local_bitmap;
	enum sgfx::Theme::style m_theme_style = sgfx::Theme::style_brand_primary;
	enum sgfx::Theme::state m_theme_state = sgfx::Theme::state_default;
	bool m_is_antialias = true;
	bool m_is_refresh_drawing_pending;
	sgfx::Region m_refresh_region;

	//needs a palette to use while drawing
	EventLoop * m_event_loop = nullptr;

	void set_name(const var::String & name){
		m_name = name;
	}

};

template<class T, u32 signature_value> class ComponentAccess : public Component {
public:

	ComponentAccess(const var::String & name) :
		Component(name, signature_value){}

	T& set_enabled(bool value = true){
		Component::set_enabled_internal(value);
		return static_cast<T&>(*this);
	}

	T& set_drawing_area(const DrawingArea & value){
		Component::set_drawing_area(value);
		return static_cast<T&>(*this);
	}

	T& set_drawing_point(const DrawingPoint & value){
		Component::set_drawing_point(value);
		return static_cast<T&>(*this);
	}

	T& set_theme_style(enum sgfx::Theme::style value){
		Component::set_theme_style(value);
		return static_cast<T&>(*this);
	}

	T& set_theme_state(enum sgfx::Theme::state value){
		Component::set_theme_state(value);
		return static_cast<T&>(*this);
	}

	template<typename... Args> static T & create(
			Args... args
			){
		T * result = new T(args...);
		if( result == nullptr ){
			//assert here
			printf("failed!!!\n");
		}
		result->m_is_created = true;
		return *result;
	}

protected:

};

}

#endif // SAPI_UX_COMPONENT_HPP
<commit_msg>set_drawing_point() and set_drawing_area() easier to access<commit_after>/*! \file */ // Copyright 2011-2020 Tyler Gilbert and Stratify Labs, Inc; see LICENSE.md for rights.
#ifndef SAPI_UX_COMPONENT_HPP
#define SAPI_UX_COMPONENT_HPP

#include "../api/WorkObject.hpp"
#include "../hal/Display.hpp"
#include "../var/String.hpp"
#include "../sgfx/Theme.hpp"
#include "Drawing.hpp"
#include "Event.hpp"

#define COMPONENT_SIGNATURE(a,b,c,d) ((a << 24) | (b << 16) | (c << 8) | (d))

namespace ux {

class EventLoop;

class Component : public Drawing {
public:

	Component(
			const var::String & name,
			u32 signature = 0) :
		m_name(name), m_signature(signature){
		set_drawing_point(DrawingPoint(0,0));
		set_drawing_area(DrawingArea(1000,1000));
	}
	virtual ~Component();

	template<typename T> T * reinterpret(){
		return static_cast<T*>(this);
	}

	static u32 whatis_signature(){
		return 0;
	}

	enum sgfx::Theme::style theme_style() const {
		return m_theme_style;
	}

	enum sgfx::Theme::state theme_state() const {
		return m_theme_state;
	}

	bool is_antialias() const {
		return m_is_antialias;
	}

	Component& set_antialias(bool value = true){
		m_is_antialias = value;
		return *this;
	}

	bool is_visible() const {
		return m_is_visible;
	}

	bool is_enabled() const {
		return m_is_enabled;
	}

	const sgfx::Theme * theme() const;
	const hal::Display * display() const;
	hal::Display * display();

	//update the location of the component (allow animations)

	virtual void handle_event(const ux::Event & event){}

	const var::String & name() const {
		return m_name;
	}

	void apply_antialias_filter(const DrawingAttributes & attributes);
	void apply_antialias_filter(const DrawingScaledAttributes & attributes);

	void redraw(){
		if( is_ready_to_draw() ){
			draw(local_drawing_attributes());
			set_refresh_drawing_pending();
		}
	}

	sgfx::Region region() const {
		return m_reference_drawing_attributes.calculate_region_on_bitmap();
	}

	bool contains(const sgfx::Point & point){
		return sgfx::Region(
					m_reference_drawing_attributes.calculate_region_on_bitmap()
					).contains(point);
	}

	DrawingPoint translate_point(const sgfx::Point & point);

	void erase();

	void set_refresh_drawing_pending(){
		m_is_refresh_drawing_pending = true;
	}

	EventLoop * event_loop(){
		return m_event_loop;
	}

	const EventLoop * event_loop() const {
		return m_event_loop;
	}

	void set_drawing_area(const DrawingArea & drawing_area){
		m_reference_drawing_attributes.set_area(drawing_area);
	}

	void set_drawing_point(const DrawingPoint & drawing_point){
		m_reference_drawing_attributes.set_point(drawing_point);
	}

	void set_theme_style(enum sgfx::Theme::style value){
		m_theme_style = value;
	}

	void set_theme_state(enum sgfx::Theme::state value){
		m_theme_state = value;
	}

protected:

	bool m_is_visible = false;
	bool m_is_enabled = true;
	bool m_is_created = false;
	virtual void examine_visibility();

	virtual void touch_drawing_attributes(){}

	void set_refresh_region(const sgfx::Region & region){
		if( region.width() * region.height() == 0 ){
			m_refresh_region = m_local_bitmap.region();
		} else {
			m_refresh_region = region;
		}
	}

	bool is_refresh_drawing_pending() const {
		return m_is_refresh_drawing_pending;
	}

	void refresh_drawing();
	friend class Layout;
	friend class LayoutComponent;

	const DrawingAttributes & local_drawing_attributes() const {
		return m_local_drawing_attributes;
	}

	const DrawingAttributes& reference_drawing_attributes() const {
		return m_reference_drawing_attributes;
	}

	DrawingAttributes& reference_drawing_attributes(){
		return m_reference_drawing_attributes;
	}

	virtual void set_enabled_internal(bool value = true){
		if( m_is_enabled != value ){
			m_is_enabled = value;
			examine_visibility();
		}
	}

	virtual void set_visible_internal(bool value = true){
		if( m_is_visible != value ){
			m_is_visible = value;
			examine_visibility();
		}
	}

	void set_event_loop(EventLoop * event_loop){
		m_event_loop = event_loop;
	}

	bool is_ready_to_draw() const {
		return is_enabled() && is_visible();
	}

	u32 signature() const {
		return m_signature;
	}

private:

	var::String m_name;
	const u32 m_signature;
	//needs to know where on the display it is drawn
	DrawingAttributes m_reference_drawing_attributes;
	DrawingAttributes m_local_drawing_attributes;
	sgfx::Bitmap m_local_bitmap;
	enum sgfx::Theme::style m_theme_style = sgfx::Theme::style_brand_primary;
	enum sgfx::Theme::state m_theme_state = sgfx::Theme::state_default;
	bool m_is_antialias = true;
	bool m_is_refresh_drawing_pending;
	sgfx::Region m_refresh_region;

	//needs a palette to use while drawing
	EventLoop * m_event_loop = nullptr;

	void set_name(const var::String & name){
		m_name = name;
	}

};

template<class T, u32 signature_value> class ComponentAccess : public Component {
public:

	ComponentAccess(const var::String & name) :
		Component(name, signature_value){}

	T& set_enabled(bool value = true){
		Component::set_enabled_internal(value);
		return static_cast<T&>(*this);
	}

	T& set_drawing_area(const DrawingArea & value){
		Component::set_drawing_area(value);
		return static_cast<T&>(*this);
	}

	T& set_drawing_area(drawing_size_t width, drawing_size_t height){
		Component::set_drawing_area(DrawingArea(width,height));
		return static_cast<T&>(*this);
	}

	T& set_drawing_point(const DrawingPoint & value){
		Component::set_drawing_point(value);
		return static_cast<T&>(*this);
	}

	T& set_drawing_point(drawing_int_t x, drawing_int_t y){
		Component::set_drawing_point(DrawingPoint(x,y));
		return static_cast<T&>(*this);
	}

	T& set_theme_style(enum sgfx::Theme::style value){
		Component::set_theme_style(value);
		return static_cast<T&>(*this);
	}

	T& set_theme_state(enum sgfx::Theme::state value){
		Component::set_theme_state(value);
		return static_cast<T&>(*this);
	}

	template<typename... Args> static T & create(
			Args... args
			){
		T * result = new T(args...);
		if( result == nullptr ){
			//assert here
			printf("failed!!!\n");
		}
		result->m_is_created = true;
		return *result;
	}

protected:

};

}

#endif // SAPI_UX_COMPONENT_HPP
<|endoftext|>


<commit_before>// windows-wlan-util.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"

// Struct containing useful network info
struct NetworkInfo {
	UCHAR ssid[32];
	UCHAR bssid[32];
	ULONG frequency;
	LONG rssi;
	ULONG quality;
};

// Get a WLAN handle, necessary for all other operations
HANDLE getWlanHandle() {
	// Result variable
	DWORD dwResult;

	// Maximum number of clients (?)
	DWORD dwMaxClient = 2;
	// Current version
	DWORD dwCurVersion;

	// Handle
	HANDLE hClient = NULL;
	// Open WLAN handle
	dwResult = WlanOpenHandle(dwMaxClient, NULL, &dwCurVersion, &hClient);

	if (dwResult != ERROR_SUCCESS) {
		return NULL;
	}
	else {
		return hClient;
	}
}

// Get a list of WLAN interfaces
PWLAN_INTERFACE_INFO_LIST getWlanInterfaces(HANDLE whandle) {
	PWLAN_INTERFACE_INFO_LIST ifList = NULL;
	DWORD dwResult;
	dwResult = WlanEnumInterfaces(whandle, NULL, &ifList);

	if (dwResult != ERROR_SUCCESS) {
		return NULL;
	}
	else {
		return ifList;
	}
}

// Initiate a scan of Wifi Networks on the given interface
boolean scanWifiNetworks(HANDLE hClient, GUID ifGuid) {
	DWORD dwResult;
	dwResult = WlanScan(hClient, &ifGuid, NULL, NULL, NULL);
	if (dwResult != ERROR_SUCCESS) {
		return false;
	}
	else {
		return true;
	}
}

// Get a list of Wifi Networks from the last scan
std::vector<NetworkInfo> getWifiNetworks(HANDLE hClient, GUID ifGuid) {
	// Return variable
	std::vector<NetworkInfo> ns;

	// Result variable
	DWORD dwResult;

	// List of interfaces
	PWLAN_INTERFACE_INFO_LIST ifList = NULL;
	// Interface info
	PWLAN_INTERFACE_INFO ifInfo = NULL;
	// Service list
	PWLAN_BSS_LIST bssList = NULL;
	// Network service
	PWLAN_BSS_ENTRY bssEntry = NULL;

	// Get a list of interfaces
	dwResult = WlanEnumInterfaces(hClient, NULL, &ifList);
	if (dwResult != ERROR_SUCCESS) {
		return ns;
	}
	else {
		// Retrieve a list of available networks
		dwResult = WlanGetNetworkBssList(hClient, &ifGuid, NULL, dot11_BSS_type_any, NULL, NULL, &bssList);
		if (dwResult != ERROR_SUCCESS) {
		}
		else {
			// For each network
			for (unsigned int j = 0; j < bssList->dwNumberOfItems; j++) {
				// Grab the network
				bssEntry = (WLAN_BSS_ENTRY *)&bssList->wlanBssEntries[j];

				// Network info struct
				NetworkInfo ni;
				// SSID
				for (int k = 0, l = bssEntry->dot11Ssid.uSSIDLength; k < 32; k++) {
					if (k < l) ni.ssid[k] = (int)bssEntry->dot11Ssid.ucSSID[k];
					else ni.ssid[k] = 0;
				}
				// Hardware MAC Address
				for (int k = 0, l = 6; k < 32; k++) {
					if (k < l) ni.bssid[k] = (int)bssEntry->dot11Bssid[k];
					else ni.bssid[k] = 0;
				}
				// Channel Frequency
				ni.frequency = bssEntry->ulChCenterFrequency;
				// Rssi
				ni.rssi = bssEntry->lRssi;
				// Signal quality
				ni.quality = bssEntry->uLinkQuality;

				// Add to the list
				ns.push_back(ni);
			}
		}
	}

	// Clean up
	if (bssList != NULL) {
		WlanFreeMemory(bssList);
		bssList = NULL;
	}
	if (ifList != NULL) {
		WlanFreeMemory(ifList);
		ifList = NULL;
	}

	// Finish
	return ns;
}

// Print usage
void usage(const char* name) {
	printf("Usage: %s <task> [interface number]\n", name);
}

// Tasks
const int TASK_USAGE = 0;
const int TASK_LIST_INTERFACES = 1;
const int TASK_SCAN_NETWORKS = 2;
const int TASK_LIST_NETWORKS = 3;

// Main program
int main(int argc, char** argv)
{
	// Parse arguments
	int task = 0;
	if (argc < 2) {
		usage(argv[0]);
		return 2;
	}
	// Interface number
	DWORD ifSelect = 0;

	// Task
	if (argc >= 2) {
		if (strncmp(argv[1], "if", 2) == 0) {
			task = TASK_LIST_INTERFACES;
		}
		else if (strncmp(argv[1], "scan", 4) == 0) {
			task = TASK_SCAN_NETWORKS;
		}
		else if (strncmp(argv[1], "list", 4) == 0) {
			task = TASK_LIST_NETWORKS;
		}
	}

	// Interface
	if (argc >= 3) {
		sscanf_s(argv[2], "%d", &ifSelect);
	}

	// Setup
	HANDLE whandle = getWlanHandle();
	std::string input;

	if (whandle == NULL) {
		printf("Error: Failed to open wlan handle.\n");
		return 1;
	}

	// Print usage and exit
	if (task == TASK_USAGE) {
		usage(argv[0]);
		return 2;
	}

	// Get interfaces
	PWLAN_INTERFACE_INFO_LIST ifList = NULL;
	ifList = getWlanInterfaces(whandle);

	if (ifList == NULL) {
		printf("Error: Failed to find wlan interfaces.\n");
		return 1;
	}

	// Print interfaces and exit
	if (task == TASK_LIST_INTERFACES) {
		for (DWORD i = 0; i < ifList->dwNumberOfItems; i++) {
			PWLAN_INTERFACE_INFO info = (WLAN_INTERFACE_INFO *)&ifList->InterfaceInfo[i];
			printf("% 2d  %ws\n", i, info->strInterfaceDescription);
		}
		WlanFreeMemory(ifList);
		return 0;
	}

	// Select the wlan interface
	GUID ifGuid;
	if (ifList->dwNumberOfItems == 0) {
		printf("Error: No wlan interfaces exist.\n");
		return 1;
	}
	else {
		if (ifSelect >= ifList->dwNumberOfItems) {
			printf("Warning: Interface %d does not exist. Defaulting to interface 0.\n", ifSelect);
			ifSelect = 0;
		}
		ifGuid = ((WLAN_INTERFACE_INFO *)&ifList->InterfaceInfo[ifSelect])->InterfaceGuid;
	}
	WlanFreeMemory(ifList);

	if (task == TASK_SCAN_NETWORKS) {
		// Scan for network
		scanWifiNetworks(whandle, ifGuid);
	}
	else if (task == TASK_LIST_NETWORKS) {
		// List available networks
		std::vector<NetworkInfo> networks = getWifiNetworks(whandle, ifGuid);

		for (auto itr = networks.begin(); itr != networks.end(); itr++) {
			// Rssi
			printf("%-4d    ", (*itr).rssi);
			// Quality
			printf("% 4d    ", (*itr).quality);
			// Bssid
			for (int i = 0; i < 6; i++) printf("%02x", (*itr).bssid[i]) && (i<5) && printf("-");
			printf("    ");
			// Ssid
			for (int i = 0; i < 32; i++) printf("%c", (*itr).ssid[i]);
			printf("\n");
		}
	}

	return 0;
}
<commit_msg>Cleaned up stray variables and output<commit_after>// windows-wlan-util.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"

// Struct containing useful network info
struct NetworkInfo {
	UCHAR ssid[32];
	UCHAR bssid[32];
	ULONG frequency;
	LONG rssi;
	ULONG quality;
};

// Get a WLAN handle, necessary for all other operations
HANDLE getWlanHandle() {
	// Result variable
	DWORD dwResult;

	// Maximum number of clients (?)
	DWORD dwMaxClient = 2;
	// Current version
	DWORD dwCurVersion;

	// Handle
	HANDLE hClient = NULL;
	// Open WLAN handle
	dwResult = WlanOpenHandle(dwMaxClient, NULL, &dwCurVersion, &hClient);

	if (dwResult != ERROR_SUCCESS) {
		return NULL;
	}
	else {
		return hClient;
	}
}

// Get a list of WLAN interfaces
PWLAN_INTERFACE_INFO_LIST getWlanInterfaces(HANDLE whandle) {
	PWLAN_INTERFACE_INFO_LIST ifList = NULL;
	DWORD dwResult;
	dwResult = WlanEnumInterfaces(whandle, NULL, &ifList);

	if (dwResult != ERROR_SUCCESS) {
		return NULL;
	}
	else {
		return ifList;
	}
}

// Initiate a scan of Wifi Networks on the given interface
boolean scanWifiNetworks(HANDLE hClient, GUID ifGuid) {
	DWORD dwResult;
	dwResult = WlanScan(hClient, &ifGuid, NULL, NULL, NULL);
	if (dwResult != ERROR_SUCCESS) {
		return false;
	}
	else {
		return true;
	}
}

// Get a list of Wifi Networks from the last scan
std::vector<NetworkInfo> getWifiNetworks(HANDLE hClient, GUID ifGuid) {
	// Return variable
	std::vector<NetworkInfo> ns;

	// Result variable
	DWORD dwResult;

	// List of interfaces
	PWLAN_INTERFACE_INFO_LIST ifList = NULL;
	// Interface info
	PWLAN_INTERFACE_INFO ifInfo = NULL;
	// Service list
	PWLAN_BSS_LIST bssList = NULL;
	// Network service
	PWLAN_BSS_ENTRY bssEntry = NULL;

	// Retrieve a list of available networks
	dwResult = WlanGetNetworkBssList(hClient, &ifGuid, NULL, dot11_BSS_type_any, NULL, NULL, &bssList);
	if (dwResult != ERROR_SUCCESS) {
	}
	else {
		// For each network
		for (unsigned int j = 0; j < bssList->dwNumberOfItems; j++) {
			// Grab the network
			bssEntry = (WLAN_BSS_ENTRY *)&bssList->wlanBssEntries[j];

			// Network info struct
			NetworkInfo ni;
			// SSID
			for (int k = 0, l = bssEntry->dot11Ssid.uSSIDLength; k < 32; k++) {
				if (k < l) ni.ssid[k] = (int)bssEntry->dot11Ssid.ucSSID[k];
				else ni.ssid[k] = 0;
			}
			// Hardware MAC Address
			for (int k = 0, l = 6; k < 32; k++) {
				if (k < l) ni.bssid[k] = (int)bssEntry->dot11Bssid[k];
				else ni.bssid[k] = 0;
			}
			// Channel Frequency
			ni.frequency = bssEntry->ulChCenterFrequency;
			// Rssi
			ni.rssi = bssEntry->lRssi;
			// Signal quality
			ni.quality = bssEntry->uLinkQuality;

			// Add to the list
			ns.push_back(ni);
		}
	}

	// Clean up
	if (bssList != NULL) {
		WlanFreeMemory(bssList);
		bssList = NULL;
	}

	// Finish
	return ns;
}

// Print usage
void usage(const char* name) {
	printf("Usage: %s <task> [interface number]\n", name);
}

// Tasks
const int TASK_USAGE = 0;
const int TASK_LIST_INTERFACES = 1;
const int TASK_SCAN_NETWORKS = 2;
const int TASK_LIST_NETWORKS = 3;

// Main program
int main(int argc, char** argv)
{
	// Parse arguments
	int task = 0;
	if (argc < 2) {
		usage(argv[0]);
		return 2;
	}
	// Interface number
	DWORD ifSelect = 0;

	// Task
	if (argc >= 2) {
		if (strncmp(argv[1], "if", 2) == 0) {
			task = TASK_LIST_INTERFACES;
		}
		else if (strncmp(argv[1], "scan", 4) == 0) {
			task = TASK_SCAN_NETWORKS;
		}
		else if (strncmp(argv[1], "list", 4) == 0) {
			task = TASK_LIST_NETWORKS;
		}
	}

	// Interface
	if (argc >= 3) {
		sscanf_s(argv[2], "%d", &ifSelect);
	}

	// Setup
	HANDLE whandle = getWlanHandle();
	std::string input;

	if (whandle == NULL) {
		printf("Error: Failed to open wlan handle.\n");
		return 1;
	}

	// Print usage and exit
	if (task == TASK_USAGE) {
		usage(argv[0]);
		return 2;
	}

	// Get interfaces
	PWLAN_INTERFACE_INFO_LIST ifList = NULL;
	ifList = getWlanInterfaces(whandle);

	if (ifList == NULL) {
		printf("Error: Failed to find wlan interfaces.\n");
		return 1;
	}

	// Print interfaces and exit
	if (task == TASK_LIST_INTERFACES) {
		for (DWORD i = 0; i < ifList->dwNumberOfItems; i++) {
			PWLAN_INTERFACE_INFO info = (WLAN_INTERFACE_INFO *)&ifList->InterfaceInfo[i];
			printf("% 2d  %ws\n", i, info->strInterfaceDescription);
		}
		WlanFreeMemory(ifList);
		return 0;
	}

	// Select the wlan interface
	GUID ifGuid;
	if (ifList->dwNumberOfItems == 0) {
		printf("Error: No wlan interfaces exist.\n");
		return 1;
	}
	else {
		if (ifSelect >= ifList->dwNumberOfItems) {
			//printf("Warning: Interface %d does not exist. Defaulting to interface 0.\n", ifSelect);
			ifSelect = 0;
		}
		ifGuid = ((WLAN_INTERFACE_INFO *)&ifList->InterfaceInfo[ifSelect])->InterfaceGuid;
	}
	WlanFreeMemory(ifList);

	if (task == TASK_SCAN_NETWORKS) {
		// Scan for network
		scanWifiNetworks(whandle, ifGuid);
	}
	else if (task == TASK_LIST_NETWORKS) {
		// List available networks
		std::vector<NetworkInfo> networks = getWifiNetworks(whandle, ifGuid);

		for (auto itr = networks.begin(); itr != networks.end(); itr++) {
			// Rssi
			printf("% 4d  ", (*itr).rssi);
			// Quality
			printf("% 4d  ", (*itr).quality);
			// Bssid
			for (int i = 0; i < 6; i++) printf("%02x", (*itr).bssid[i]) && (i<5) && printf(":");
			printf("  ");
			// Ssid
			for (int i = 0; i < 32; i++) printf("%c", (*itr).ssid[i]);
			printf("\n");
		}
	}

	return 0;
}
<|endoftext|>


<commit_before>#pragma once

namespace gcl::mp::meta
{
    template <typename... Ts>
    struct join;
    template <typename first_type, typename second_type, typename... Ts>
    struct join<first_type, second_type, Ts...> {
        static_assert(sizeof...(Ts) not_eq 0);
        using type = typename join<typename join<first_type, second_type>::type, Ts...>::type;
    };
    template <typename T>
    struct join<T> {
        using type = T;
    };
    template <template <typename...> typename Type, typename... Ts, typename... Us>
    struct join<Type<Ts...>, Type<Us...>> {
        using type = Type<Ts..., Us...>;
    };

    template <typename... Ts>
    using join_t = typename join<Ts...>::type;
}

#include <tuple>

namespace gcl::mp::tests::meta
{
    using namespace gcl::mp::meta;
    static_assert(std::is_same_v<std::tuple<int, char, double>, join_t<std::tuple<int>, std::tuple<char, double>>>);
    static_assert(std::is_same_v<std::tuple<int, char, double>, join_t<std::tuple<int, char, double>>>);
    static_assert(
        std::is_same_v<std::tuple<int, char, double>, join_t<std::tuple<int>, std::tuple<char>, std::tuple<double>>>);
    static_assert(std::is_same_v<
                  std::tuple<int, char, double, float>,
                  join_t<std::tuple<int>, std::tuple<char>, std::tuple<double>, std::tuple<float>>>);
}<commit_msg>[mp::meta] : remote dependency to std::tuple for join_t<Ts...> ctc tests<commit_after>#pragma once

namespace gcl::mp::meta
{
    template <typename... Ts>
    struct join;
    template <typename first_type, typename second_type, typename... Ts>
    struct join<first_type, second_type, Ts...> {
        static_assert(sizeof...(Ts) not_eq 0);
        using type = typename join<typename join<first_type, second_type>::type, Ts...>::type;
    };
    template <typename T>
    struct join<T> {
        using type = T;
    };
    template <template <typename...> typename Type, typename... Ts, typename... Us>
    struct join<Type<Ts...>, Type<Us...>> {
        using type = Type<Ts..., Us...>;
    };

    template <typename... Ts>
    using join_t = typename join<Ts...>::type;
}

namespace gcl::mp::tests::meta
{
    template <typename ... Ts>
    struct type_seq {};

    using namespace gcl::mp::meta;
    static_assert(std::is_same_v<type_seq<int, char, double>, join_t<type_seq<int>, type_seq<char, double>>>);
    static_assert(std::is_same_v<type_seq<int, char, double>, join_t<type_seq<int, char, double>>>);
    static_assert(
        std::is_same_v<type_seq<int, char, double>, join_t<type_seq<int>, type_seq<char>, type_seq<double>>>);
    static_assert(std::is_same_v<
                  type_seq<int, char, double, float>,
                  join_t<type_seq<int>, type_seq<char>, type_seq<double>, type_seq<float>>>);
}<|endoftext|>


<commit_before>#ifndef SRC_SETTINGS_JSONFILE_SETTING_BACKEND_HPP_
#define SRC_SETTINGS_JSONFILE_SETTING_BACKEND_HPP_

#include <settings/settings.hpp>
#include <cereal/archives/json.hpp>

namespace fc
{

class json_file_setting_facade
{
public:
	typedef cereal::JSONInputArchive json_archive;

	/**
	 * @brief Creates a setting facade that reads values from
	 * stream using json format.
	 *
	 * @param stream The input stream containing the data in json syntax.
	 * @throw ::cereal::Exception if the given @p stream cannot be parsed
	 * by json parser, e.g. if syntax is wrong.
	 */
	json_file_setting_facade(std::istream& stream)
		: archive(stream)
	{
	}

	template<class data_t, class setter_t>
	void register_setting(
			setting_id id,
			data_t initial_v,
			setter_t setter) //todo add constraint
	{
		auto value = initial_v;
		try
		{
			//tries to read value from json parser.
			//the value remains unchanged if an error occurs.
			archive(cereal::make_nvp(id.key, value));
		}
		catch(const cereal::Exception& ex)
		{
			std::cerr << "json_file_setting_facade.register_setting():"
					" '"	<< ex.what() << "'" << std::endl;
		}
		setter(value);
	}

	/**
	 * \brief registers Setting together with region
	 *
	 * Region can be ignored in this case,
	 * as parameters from json file don't change after loading.
	 */
	template<class data_t, class setter_t, class region_t>
	void register_setting(
			setting_id id,
			data_t initial_v,
			setter_t setter,
			region_t& /*region*/) //todo add constraint
	{
		register_setting(id, initial_v, setter);
	}

	json_archive archive;
};

}  // namespace fc

#endif /* SRC_SETTINGS_JSONFILE_SETTING_BACKEND_HPP_ */
<commit_msg>make exception message more usable by hinting for probable cause of exception in jsonfile_setting_backend.hpp<commit_after>#ifndef SRC_SETTINGS_JSONFILE_SETTING_BACKEND_HPP_
#define SRC_SETTINGS_JSONFILE_SETTING_BACKEND_HPP_

#include <settings/settings.hpp>
#include <cereal/archives/json.hpp>

namespace fc
{

class json_file_setting_facade
{
public:
	typedef cereal::JSONInputArchive json_archive;

	/**
	 * @brief Creates a setting facade that reads values from
	 * stream using json format.
	 *
	 * @param stream The input stream containing the data in json syntax.
	 * @throw ::cereal::Exception if the given @p stream cannot be parsed
	 * by json parser, e.g. if syntax is wrong.
	 */
	json_file_setting_facade(std::istream& stream)
		try : archive(stream)
	{
	}
	catch (const ::cereal::Exception& ex)
	{
		throw ::cereal::Exception(std::string(ex.what())
				+ ". you should check for json syntax errors.");
	}

	template<class data_t, class setter_t>
	void register_setting(
			setting_id id,
			data_t initial_v,
			setter_t setter) //todo add constraint
	{
		auto value = initial_v;
		try
		{
			//tries to read value from json parser.
			//the value remains unchanged if an error occurs.
			archive(cereal::make_nvp(id.key, value));
		}
		catch(const cereal::Exception& ex)
		{
			std::cerr << "json_file_setting_facade.register_setting():"
					" '"	<< ex.what() << "'" << std::endl;
		}
		setter(value);
	}

	/**
	 * \brief registers Setting together with region
	 *
	 * Region can be ignored in this case,
	 * as parameters from json file don't change after loading.
	 */
	template<class data_t, class setter_t, class region_t>
	void register_setting(
			setting_id id,
			data_t initial_v,
			setter_t setter,
			region_t& /*region*/) //todo add constraint
	{
		register_setting(id, initial_v, setter);
	}

	json_archive archive;
};

}  // namespace fc

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


<commit_before>/* Copyright 2015 The TensorFlow Authors. All Rights Reserved.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
==============================================================================*/

#include "tensorflow/core/common_runtime/kernel_benchmark_testlib.h"

#include <vector>
#include "tensorflow/core/common_runtime/device.h"
#include "tensorflow/core/common_runtime/device_factory.h"
#include "tensorflow/core/common_runtime/executor_factory.h"
#include "tensorflow/core/common_runtime/local_device.h"
#include "tensorflow/core/framework/op.h"
#include "tensorflow/core/framework/op_kernel.h"
#include "tensorflow/core/framework/op_segment.h"
#include "tensorflow/core/framework/versions.pb.h"
#include "tensorflow/core/graph/graph.h"
#include "tensorflow/core/kernels/ops_util.h"
#include "tensorflow/core/lib/core/notification.h"
#include "tensorflow/core/lib/core/threadpool.h"
#include "tensorflow/core/lib/strings/str_util.h"
#include "tensorflow/core/platform/byte_order.h"
#include "tensorflow/core/platform/cpu_info.h"
#include "tensorflow/core/platform/logging.h"
#include "tensorflow/core/platform/test_benchmark.h"
#include "tensorflow/core/platform/types.h"
#include "tensorflow/core/public/session_options.h"
#include "tensorflow/core/public/version.h"
#include "tensorflow/core/util/device_name_utils.h"

namespace tensorflow {
namespace test {

// TODO(hongm): Convert `g` and `init` to using std::unique_ptr.
Benchmark::Benchmark(const string& device, Graph* g,
                     const SessionOptions* options, Graph* init,
                     Rendezvous* rendez, const char* executor_type) {
  SessionOptions default_options;
  if (!options) {
    options = &default_options;
  }

  testing::StopTiming();
  string t = absl::AsciiStrToUpper(device);
  // Allow NewDevice to allocate a new threadpool with different number of
  // threads for each new benchmark.
  LocalDevice::set_use_global_threadpool(false);
  device_ =
      DeviceFactory::NewDevice(t, *options, "/job:localhost/replica:0/task:0");
  CHECK(device_) << "Could not create a " << device << " device";

  pool_ =
      new thread::ThreadPool(options->env, "blocking", port::MaxParallelism());

  auto runner = [this](std::function<void()> closure) {
    pool_->Schedule(closure);
  };

  if (rendez == nullptr) {
    rendez_ = NewLocalRendezvous();
  } else {
    rendez_ = rendez;
  }

  const int graph_def_version = g->versions().producer();

  LocalExecutorParams params;
  params.device = device_.get();
  params.function_library = nullptr;
  params.create_kernel = [this, graph_def_version](const NodeDef& ndef,
                                                   OpKernel** kernel) {
    return CreateNonCachedKernel(device_.get(), nullptr, ndef,
                                 graph_def_version, kernel);
  };
  params.delete_kernel = [](OpKernel* kernel) {
    DeleteNonCachedKernel(kernel);
  };

  if (init) {
    std::unique_ptr<Executor> init_exec;
    TF_CHECK_OK(NewExecutor(executor_type, params, *init, &init_exec));
    Executor::Args args;
    args.rendezvous = rendez_;
    args.runner = runner;
    TF_CHECK_OK(init_exec->Run(args));
  }

  TF_CHECK_OK(NewExecutor(executor_type, params, *g, &exec_));
}

Benchmark::~Benchmark() {
  if (device_) {
    rendez_->Unref();
    // We delete `exec_` before `device_` because the `exec_` destructor may
    // run kernel destructors that may attempt to access state borrowed from
    // `device_`, such as the resource manager.
    exec_.reset();
    device_.reset();
    delete pool_;
  }
}

void Benchmark::Run(int iters) { RunWithArgs({}, {}, iters); }

string GetRendezvousKey(const Node* node) {
  string send_device;
  TF_CHECK_OK(GetNodeAttr(node->attrs(), "send_device", &send_device));
  string recv_device;
  TF_CHECK_OK(GetNodeAttr(node->attrs(), "recv_device", &recv_device));
  string tensor_name;
  TF_CHECK_OK(GetNodeAttr(node->attrs(), "tensor_name", &tensor_name));
  uint64 send_device_incarnation;
  TF_CHECK_OK(GetNodeAttr(node->attrs(), "send_device_incarnation",
                          reinterpret_cast<int64*>(&send_device_incarnation)));
  return Rendezvous::CreateKey(send_device, send_device_incarnation,
                               recv_device, tensor_name, FrameAndIter(0, 0));
}

void Benchmark::RunWithArgs(
    const std::vector<std::pair<const Node*, Tensor>>& inputs,
    const std::vector<const Node*>& outputs, int iters) {
  if (!device_ || iters == 0) {
    return;
  }
  // Gets inputs' and outputs' rendezvous keys.
  std::vector<std::pair<string, Tensor>> in;
  in.reserve(inputs.size());
  for (const auto& p : inputs) {
    in.push_back({GetRendezvousKey(p.first), p.second});
  }
  std::vector<string> out;
  out.reserve(outputs.size());
  for (const auto& n : outputs) {
    out.push_back(GetRendezvousKey(n));
  }
  Tensor unused;  // In benchmark, we don't care the return value.
  bool is_dead;

  // Warm up
  Executor::Args args;
  args.rendezvous = rendez_;
  args.runner = [this](std::function<void()> closure) {
    pool_->Schedule(closure);
  };
  static const int kWarmupRuns = 3;
  for (int i = 0; i < kWarmupRuns; ++i) {
    for (const auto& p : in) {
      Rendezvous::ParsedKey parsed;
      TF_CHECK_OK(Rendezvous::ParseKey(p.first, &parsed));
      TF_CHECK_OK(rendez_->Send(parsed, Rendezvous::Args(), p.second, false));
    }
    TF_CHECK_OK(exec_->Run(args));
    for (const string& key : out) {
      Rendezvous::ParsedKey parsed;
      TF_CHECK_OK(Rendezvous::ParseKey(key, &parsed));
      TF_CHECK_OK(rendez_->Recv(parsed, Rendezvous::Args(), &unused, &is_dead));
    }
  }
  TF_CHECK_OK(device_->Sync());
  VLOG(3) << kWarmupRuns << " warmup runs done.";

  testing::StartTiming();
  while (iters-- > 0) {
    for (const auto& p : in) {
      Rendezvous::ParsedKey parsed;
      TF_CHECK_OK(Rendezvous::ParseKey(p.first, &parsed));
      TF_CHECK_OK(rendez_->Send(parsed, Rendezvous::Args(), p.second, false));
    }
    TF_CHECK_OK(exec_->Run(args));
    for (const string& key : out) {
      Rendezvous::ParsedKey parsed;
      TF_CHECK_OK(Rendezvous::ParseKey(key, &parsed));
      TF_CHECK_OK(rendez_->Recv(parsed, Rendezvous::Args(), &unused, &is_dead));
    }
  }

  TF_CHECK_OK(device_->Sync());
  testing::StopTiming();
}

}  // end namespace test
}  // end namespace tensorflow
<commit_msg>Fix memory leak of Graph objects in test::benchmark.<commit_after>/* Copyright 2015 The TensorFlow Authors. All Rights Reserved.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
==============================================================================*/

#include "tensorflow/core/common_runtime/kernel_benchmark_testlib.h"

#include <vector>

#include "tensorflow/core/common_runtime/device.h"
#include "tensorflow/core/common_runtime/device_factory.h"
#include "tensorflow/core/common_runtime/executor_factory.h"
#include "tensorflow/core/common_runtime/local_device.h"
#include "tensorflow/core/framework/op.h"
#include "tensorflow/core/framework/op_kernel.h"
#include "tensorflow/core/framework/op_segment.h"
#include "tensorflow/core/framework/versions.pb.h"
#include "tensorflow/core/graph/graph.h"
#include "tensorflow/core/kernels/ops_util.h"
#include "tensorflow/core/lib/core/notification.h"
#include "tensorflow/core/lib/core/threadpool.h"
#include "tensorflow/core/lib/gtl/cleanup.h"
#include "tensorflow/core/lib/strings/str_util.h"
#include "tensorflow/core/platform/byte_order.h"
#include "tensorflow/core/platform/cpu_info.h"
#include "tensorflow/core/platform/logging.h"
#include "tensorflow/core/platform/test_benchmark.h"
#include "tensorflow/core/platform/types.h"
#include "tensorflow/core/public/session_options.h"
#include "tensorflow/core/public/version.h"
#include "tensorflow/core/util/device_name_utils.h"

namespace tensorflow {
namespace test {

// TODO(hongm): Convert `g` and `init` to using std::unique_ptr.
Benchmark::Benchmark(const string& device, Graph* g,
                     const SessionOptions* options, Graph* init,
                     Rendezvous* rendez, const char* executor_type) {
  auto cleanup = gtl::MakeCleanup([g, init]() {
    delete g;
    delete init;
  });

  SessionOptions default_options;
  if (!options) {
    options = &default_options;
  }

  testing::StopTiming();
  string t = absl::AsciiStrToUpper(device);
  // Allow NewDevice to allocate a new threadpool with different number of
  // threads for each new benchmark.
  LocalDevice::set_use_global_threadpool(false);
  device_ =
      DeviceFactory::NewDevice(t, *options, "/job:localhost/replica:0/task:0");
  CHECK(device_) << "Could not create a " << device << " device";

  pool_ =
      new thread::ThreadPool(options->env, "blocking", port::MaxParallelism());

  auto runner = [this](std::function<void()> closure) {
    pool_->Schedule(closure);
  };

  if (rendez == nullptr) {
    rendez_ = NewLocalRendezvous();
  } else {
    rendez_ = rendez;
  }

  const int graph_def_version = g->versions().producer();

  LocalExecutorParams params;
  params.device = device_.get();
  params.function_library = nullptr;
  params.create_kernel = [this, graph_def_version](const NodeDef& ndef,
                                                   OpKernel** kernel) {
    return CreateNonCachedKernel(device_.get(), nullptr, ndef,
                                 graph_def_version, kernel);
  };
  params.delete_kernel = [](OpKernel* kernel) {
    DeleteNonCachedKernel(kernel);
  };

  if (init) {
    std::unique_ptr<Executor> init_exec;
    TF_CHECK_OK(NewExecutor(executor_type, params, *init, &init_exec));
    Executor::Args args;
    args.rendezvous = rendez_;
    args.runner = runner;
    TF_CHECK_OK(init_exec->Run(args));
  }

  TF_CHECK_OK(NewExecutor(executor_type, params, *g, &exec_));
}

Benchmark::~Benchmark() {
  if (device_) {
    rendez_->Unref();
    // We delete `exec_` before `device_` because the `exec_` destructor may
    // run kernel destructors that may attempt to access state borrowed from
    // `device_`, such as the resource manager.
    exec_.reset();
    device_.reset();
    delete pool_;
  }
}

void Benchmark::Run(int iters) { RunWithArgs({}, {}, iters); }

string GetRendezvousKey(const Node* node) {
  string send_device;
  TF_CHECK_OK(GetNodeAttr(node->attrs(), "send_device", &send_device));
  string recv_device;
  TF_CHECK_OK(GetNodeAttr(node->attrs(), "recv_device", &recv_device));
  string tensor_name;
  TF_CHECK_OK(GetNodeAttr(node->attrs(), "tensor_name", &tensor_name));
  uint64 send_device_incarnation;
  TF_CHECK_OK(GetNodeAttr(node->attrs(), "send_device_incarnation",
                          reinterpret_cast<int64*>(&send_device_incarnation)));
  return Rendezvous::CreateKey(send_device, send_device_incarnation,
                               recv_device, tensor_name, FrameAndIter(0, 0));
}

void Benchmark::RunWithArgs(
    const std::vector<std::pair<const Node*, Tensor>>& inputs,
    const std::vector<const Node*>& outputs, int iters) {
  if (!device_ || iters == 0) {
    return;
  }
  // Gets inputs' and outputs' rendezvous keys.
  std::vector<std::pair<string, Tensor>> in;
  in.reserve(inputs.size());
  for (const auto& p : inputs) {
    in.push_back({GetRendezvousKey(p.first), p.second});
  }
  std::vector<string> out;
  out.reserve(outputs.size());
  for (const auto& n : outputs) {
    out.push_back(GetRendezvousKey(n));
  }
  Tensor unused;  // In benchmark, we don't care the return value.
  bool is_dead;

  // Warm up
  Executor::Args args;
  args.rendezvous = rendez_;
  args.runner = [this](std::function<void()> closure) {
    pool_->Schedule(closure);
  };
  static const int kWarmupRuns = 3;
  for (int i = 0; i < kWarmupRuns; ++i) {
    for (const auto& p : in) {
      Rendezvous::ParsedKey parsed;
      TF_CHECK_OK(Rendezvous::ParseKey(p.first, &parsed));
      TF_CHECK_OK(rendez_->Send(parsed, Rendezvous::Args(), p.second, false));
    }
    TF_CHECK_OK(exec_->Run(args));
    for (const string& key : out) {
      Rendezvous::ParsedKey parsed;
      TF_CHECK_OK(Rendezvous::ParseKey(key, &parsed));
      TF_CHECK_OK(rendez_->Recv(parsed, Rendezvous::Args(), &unused, &is_dead));
    }
  }
  TF_CHECK_OK(device_->Sync());
  VLOG(3) << kWarmupRuns << " warmup runs done.";

  testing::StartTiming();
  while (iters-- > 0) {
    for (const auto& p : in) {
      Rendezvous::ParsedKey parsed;
      TF_CHECK_OK(Rendezvous::ParseKey(p.first, &parsed));
      TF_CHECK_OK(rendez_->Send(parsed, Rendezvous::Args(), p.second, false));
    }
    TF_CHECK_OK(exec_->Run(args));
    for (const string& key : out) {
      Rendezvous::ParsedKey parsed;
      TF_CHECK_OK(Rendezvous::ParseKey(key, &parsed));
      TF_CHECK_OK(rendez_->Recv(parsed, Rendezvous::Args(), &unused, &is_dead));
    }
  }

  TF_CHECK_OK(device_->Sync());
  testing::StopTiming();
}

}  // end namespace test
}  // end namespace tensorflow
<|endoftext|>


<commit_before>#ifdef HAVE_EIGEN3

#include <shogun/mathematics/ajd/JADiagOrth.h>

#include <shogun/base/init.h>

#include <shogun/mathematics/Math.h>
#include <shogun/mathematics/eigen3.h>

using namespace Eigen;

typedef Matrix< float64_t, Dynamic, 1, ColMajor > EVector;
typedef Matrix< float64_t, Dynamic, Dynamic, ColMajor > EMatrix;

using namespace shogun;

double givens_stack(double *A, int M, int K, int p, int q);
void LeftRotStack(double *A, int M, int N, int K, int p, int q, double c, double s);
void RightRotStack(double *A, int M, int N, int K, int p, int q, double c, double s);
void LeftRotSimple(double *A, int m, int n, int p, int q, double c, double s);

SGMatrix<float64_t> CJADiagOrth::diagonalize(SGNDArray<float64_t> &C, SGMatrix<float64_t> V0,
						double eps, int itermax)
{
	int m = C.dims[0];
	int L = C.dims[2];

	SGMatrix<float64_t> V;
	if (V0.num_rows != 0)
	{
		V = V0.clone();
	}
	else
	{
		V = SGMatrix<float64_t>::create_identity_matrix(m,1);
	}

	bool more = true;
	int rots = 0;

	while (more)
	{
        more = false;

        for (int p = 0; p < m; p++)
        {
            for (int q = p+1; q < m; q++)
            {
                // computation of Givens angle
                double theta = givens_stack(C.array, m, L, p, q);

                // Givens update
                if (fabs(theta) > eps)
                {
                    double c = cos(theta);
                    double s = sin(theta);
                    LeftRotStack (C.array, m, m, L, p, q, c, s);
	                RightRotStack(C.array, m, m, L, p, q, c, s);
	                LeftRotSimple(V.matrix, m, m, p, q, c, s);
                    rots++;
                    more = true;
                }
            }
        }
	}

    return V;
}

/* Givens angle for the pair (p,q) of a stack of K M*M matrices */
double givens_stack(double *A, int M, int K, int p, int q)
{
    int k;
    double diff_on, sum_off, ton, toff;
    double *cm; // A cumulant matrix
    double G11 = 0.0;
    double G12 = 0.0;
    double G22 = 0.0;

    int M2 = M*M;
    int pp = p+p*M;
    int pq = p+q*M;
    int qp = q+p*M;
    int qq = q+q*M;

    for (k=0, cm=A; k<K; k++, cm+=M2)
    {
        diff_on = cm[pp] - cm[qq];
        sum_off = cm[pq] + cm[qp];

        G11 += diff_on * diff_on;
        G22 += sum_off * sum_off;
        G12 += diff_on * sum_off;
    }

    ton  = G11 - G22;
    toff = 2.0 * G12;

    return -0.5 * atan2 ( toff , ton+sqrt(ton*ton+toff*toff) );
}

/*
   Ak(mxn) --> R * Ak(mxn) where R rotates the (p,q) rows R =[ c -s ; s c ]
   and Ak is the k-th matrix in the stack
*/
void LeftRotStack(double *A, int M, int N, int K, int p, int q, double c, double s )
{
    int k, ix, iy, cpt;
    int MN = M*N;
    int kMN;
    double nx, ny;

    for (k=0, kMN=0; k<K; k++, kMN+=MN)
    {
        for (cpt=0, ix=p+kMN, iy=q+kMN; cpt<N; cpt++, ix+=M, iy+=M)
        {
            nx = A[ix];
            ny = A[iy];
            A[ix] = c*nx - s*ny;
            A[iy] = s*nx + c*ny;
        }
    }
}

/* Ak(mxn) --> Ak(mxn) x R where R rotates the (p,q) columns R =[ c s ; -s c ]
   and Ak is the k-th M*N matrix in the stack */
void RightRotStack(double *A, int M, int N, int K, int p, int q, double c, double s )
{
    int k, ix, iy, cpt, kMN;
    int pM = p*M;
    int qM = q*M;
    double nx, ny;

    for (k=0, kMN=0; k<K; k++, kMN+=M*N)
    {
        for (cpt=0, ix=pM+kMN, iy=qM+kMN; cpt<M; cpt++)
        {
            nx = A[ix];
            ny = A[iy];
            A[ix++] = c*nx - s*ny;
            A[iy++] = s*nx + c*ny;
        }
    }
}

/*
   A(mxn) --> R * A(mxn) where R=[ c -s ; s c ]   rotates the (p,q) rows of R
*/
void LeftRotSimple(double *A, int m, int n, int p, int q, double c, double s)
{
    int ix = p;
    int iy = q;
    double nx, ny;
    int j;

    for (j=0; j<n; j++, ix+=m, iy+=m)
    {
        nx = A[ix];
        ny = A[iy];
        A[ix] = c*nx - s*ny;
        A[iy] = s*nx + c*ny;
    }
}
#endif //HAVE_EIGEN3
<commit_msg>renamed JADiagOrth inner functions<commit_after>#ifdef HAVE_EIGEN3

#include <shogun/mathematics/ajd/JADiagOrth.h>

#include <shogun/base/init.h>

#include <shogun/mathematics/Math.h>
#include <shogun/mathematics/eigen3.h>

using namespace Eigen;

typedef Matrix< float64_t, Dynamic, 1, ColMajor > EVector;
typedef Matrix< float64_t, Dynamic, Dynamic, ColMajor > EMatrix;

using namespace shogun;

double givens_stack(double *A, int M, int K, int p, int q);
void left_rot_stack(double *A, int M, int N, int K, int p, int q, double c, double s);
void right_rot_stack(double *A, int M, int N, int K, int p, int q, double c, double s);
void left_rot_simple(double *A, int m, int n, int p, int q, double c, double s);

SGMatrix<float64_t> CJADiagOrth::diagonalize(SGNDArray<float64_t> &C, SGMatrix<float64_t> V0,
						double eps, int itermax)
{
	int m = C.dims[0];
	int L = C.dims[2];

	SGMatrix<float64_t> V;
	if (V0.num_rows != 0)
	{
		V = V0.clone();
	}
	else
	{
		V = SGMatrix<float64_t>::create_identity_matrix(m,1);
	}

	bool more = true;
	int rots = 0;

	while (more)
	{
        more = false;

        for (int p = 0; p < m; p++)
        {
            for (int q = p+1; q < m; q++)
            {
                // computation of Givens angle
                double theta = givens_stack(C.array, m, L, p, q);

                // Givens update
                if (fabs(theta) > eps)
                {
                    double c = cos(theta);
                    double s = sin(theta);
                    left_rot_stack (C.array, m, m, L, p, q, c, s);
	                right_rot_stack(C.array, m, m, L, p, q, c, s);
	                left_rot_simple(V.matrix, m, m, p, q, c, s);
                    rots++;
                    more = true;
                }
            }
        }
	}

    return V;
}

/* Givens angle for the pair (p,q) of a stack of K M*M matrices */
double givens_stack(double *A, int M, int K, int p, int q)
{
    int k;
    double diff_on, sum_off, ton, toff;
    double *cm; // A cumulant matrix
    double G11 = 0.0;
    double G12 = 0.0;
    double G22 = 0.0;

    int M2 = M*M;
    int pp = p+p*M;
    int pq = p+q*M;
    int qp = q+p*M;
    int qq = q+q*M;

    for (k=0, cm=A; k<K; k++, cm+=M2)
    {
        diff_on = cm[pp] - cm[qq];
        sum_off = cm[pq] + cm[qp];

        G11 += diff_on * diff_on;
        G22 += sum_off * sum_off;
        G12 += diff_on * sum_off;
    }

    ton  = G11 - G22;
    toff = 2.0 * G12;

    return -0.5 * atan2 ( toff , ton+sqrt(ton*ton+toff*toff) );
}

/*
   Ak(mxn) --> R * Ak(mxn) where R rotates the (p,q) rows R =[ c -s ; s c ]
   and Ak is the k-th matrix in the stack
*/
void left_rot_stack(double *A, int M, int N, int K, int p, int q, double c, double s )
{
    int k, ix, iy, cpt;
    int MN = M*N;
    int kMN;
    double nx, ny;

    for (k=0, kMN=0; k<K; k++, kMN+=MN)
    {
        for (cpt=0, ix=p+kMN, iy=q+kMN; cpt<N; cpt++, ix+=M, iy+=M)
        {
            nx = A[ix];
            ny = A[iy];
            A[ix] = c*nx - s*ny;
            A[iy] = s*nx + c*ny;
        }
    }
}

/* Ak(mxn) --> Ak(mxn) x R where R rotates the (p,q) columns R =[ c s ; -s c ]
   and Ak is the k-th M*N matrix in the stack */
void right_rot_stack(double *A, int M, int N, int K, int p, int q, double c, double s )
{
    int k, ix, iy, cpt, kMN;
    int pM = p*M;
    int qM = q*M;
    double nx, ny;

    for (k=0, kMN=0; k<K; k++, kMN+=M*N)
    {
        for (cpt=0, ix=pM+kMN, iy=qM+kMN; cpt<M; cpt++)
        {
            nx = A[ix];
            ny = A[iy];
            A[ix++] = c*nx - s*ny;
            A[iy++] = s*nx + c*ny;
        }
    }
}

/*
   A(mxn) --> R * A(mxn) where R=[ c -s ; s c ]   rotates the (p,q) rows of R
*/
void left_rot_simple(double *A, int m, int n, int p, int q, double c, double s)
{
    int ix = p;
    int iy = q;
    double nx, ny;
    int j;

    for (j=0; j<n; j++, ix+=m, iy+=m)
    {
        nx = A[ix];
        ny = A[iy];
        A[ix] = c*nx - s*ny;
        A[iy] = s*nx + c*ny;
    }
}
#endif //HAVE_EIGEN3
<|endoftext|>


<commit_before>#pragma once

#include "point_to_int64.hpp"

#include "../geometry/point2d.hpp"

namespace feature
{
  namespace pts
  {
    inline int64_t FromPoint(m2::PointD const & p)
    {
      return PointToInt64(p.x, p.y);
    }

    inline m2::PointD ToPoint(int64_t i)
    {
      CoordPointT const pt = Int64ToPoint(i);
      return m2::PointD(pt.first, pt.second);
    }
  }

  static int g_arrWorldScales[] = { 1, 3, 4, 6 };       // 6 = upper scale for world.mwm visibility
  static int g_arrCountryScales[] = { 7, 10, 14, 17 };  // 17 = scales::GetUpperScale()

  inline string GetTagForIndex(char const * prefix, int ind)
  {
    string str;
    str.reserve(strlen(prefix) + 1);
    str = prefix;

    static char arrChar[] = { '0', '1', '2', '3' };
    STATIC_ASSERT ( ARRAY_SIZE(arrChar) == ARRAY_SIZE(g_arrWorldScales) );
    STATIC_ASSERT ( ARRAY_SIZE(arrChar) == ARRAY_SIZE(g_arrCountryScales) );
    ASSERT ( ind >= 0 && ind < ARRAY_SIZE(arrChar), (ind) );

    str += arrChar[ind];
    return str;
  }
}
<commit_msg>Fixed geometry zoom levels for World file<commit_after>#pragma once

#include "point_to_int64.hpp"

#include "../geometry/point2d.hpp"

namespace feature
{
  namespace pts
  {
    inline int64_t FromPoint(m2::PointD const & p)
    {
      return PointToInt64(p.x, p.y);
    }

    inline m2::PointD ToPoint(int64_t i)
    {
      CoordPointT const pt = Int64ToPoint(i);
      return m2::PointD(pt.first, pt.second);
    }
  }

  static int g_arrWorldScales[] = { 2, 4, 5, 6 };       // 6 = upper scale for world.mwm visibility
  static int g_arrCountryScales[] = { 7, 10, 14, 17 };  // 17 = scales::GetUpperScale()

  inline string GetTagForIndex(char const * prefix, int ind)
  {
    string str;
    str.reserve(strlen(prefix) + 1);
    str = prefix;

    static char arrChar[] = { '0', '1', '2', '3' };
    STATIC_ASSERT ( ARRAY_SIZE(arrChar) == ARRAY_SIZE(g_arrWorldScales) );
    STATIC_ASSERT ( ARRAY_SIZE(arrChar) == ARRAY_SIZE(g_arrCountryScales) );
    ASSERT ( ind >= 0 && ind < ARRAY_SIZE(arrChar), (ind) );

    str += arrChar[ind];
    return str;
  }
}
<|endoftext|>


<commit_before>#include "ntuple_test.hxx"

TEST(RNTuple, RealWorld1)
{
   FileRaii fileGuard("test_ntuple_realworld1.root");

   // See https://github.com/olifre/root-io-bench/blob/master/benchmark.cpp
   auto modelWrite = RNTupleModel::Create();
   auto wrEvent   = modelWrite->MakeField<std::uint32_t>("event");
   auto wrSignal  = modelWrite->MakeField<bool>("signal");
   auto wrEnergy  = modelWrite->MakeField<double>("energy");
   auto wrTimes   = modelWrite->MakeField<std::vector<double>>("times");
   auto wrIndices = modelWrite->MakeField<std::vector<std::uint32_t>>("indices");

   TRandom3 rnd(42);
   double chksumWrite = 0.0;
   {
      auto ntuple = RNTupleWriter::Recreate(std::move(modelWrite), "myNTuple", fileGuard.GetPath());
      constexpr unsigned int nEvents = 60000;
      for (unsigned int i = 0; i < nEvents; ++i) {
         *wrEvent = i;
         *wrEnergy = rnd.Rndm() * 1000.;
         *wrSignal = i % 2;

         chksumWrite += double(*wrEvent);
         chksumWrite += double(*wrSignal);
         chksumWrite += *wrEnergy;

         auto nTimes = 1 + floor(rnd.Rndm() * 1000.);
         wrTimes->resize(nTimes);
         for (unsigned int n = 0; n < nTimes; ++n) {
            wrTimes->at(n) = 1 + rnd.Rndm()*1000. - 500.;
            chksumWrite += wrTimes->at(n);
         }

         auto nIndices = 1 + floor(rnd.Rndm() * 1000.);
         wrIndices->resize(nIndices);
         for (unsigned int n = 0; n < nIndices; ++n) {
            wrIndices->at(n) = 1 + floor(rnd.Rndm() * 1000.);
            chksumWrite += double(wrIndices->at(n));
         }

         ntuple->Fill();
      }
   }

   auto modelRead  = RNTupleModel::Create();
   auto rdEvent   = modelRead->MakeField<std::uint32_t>("event");
   auto rdSignal  = modelRead->MakeField<bool>("signal");
   auto rdEnergy  = modelRead->MakeField<double>("energy");
   auto rdTimes   = modelRead->MakeField<std::vector<double>>("times");
   auto rdIndices = modelRead->MakeField<std::vector<std::uint32_t>>("indices");

   double chksumRead = 0.0;
   auto ntuple = RNTupleReader::Open(std::move(modelRead), "myNTuple", fileGuard.GetPath());
   for (auto entryId : *ntuple) {
      ntuple->LoadEntry(entryId);
      chksumRead += double(*rdEvent) + double(*rdSignal) + *rdEnergy;
      for (auto t : *rdTimes) chksumRead += t;
      for (auto ind : *rdIndices) chksumRead += double(ind);
   }

   // The floating point arithmetic should have been executed in the same order for reading and writing,
   // thus we expect the checksums to be bitwise identical
   EXPECT_EQ(chksumRead, chksumWrite);
}

#if !defined(_MSC_VER) || defined(R__ENABLE_BROKEN_WIN_TESTS)
TEST(RNTuple, LargeFile)
{
   FileRaii fileGuard("test_large_file.root");

   auto modelWrite = RNTupleModel::Create();
   auto& wrEnergy  = *modelWrite->MakeField<double>("energy");

   TRandom3 rnd(42);
   double chksumWrite = 0.0;
   {
      RNTupleWriteOptions options;
      options.SetCompression(0);
      auto ntuple = RNTupleWriter::Recreate(std::move(modelWrite), "myNTuple", fileGuard.GetPath(), options);
      constexpr unsigned long nEvents = 1024 * 1024 * 256; // Exceed 2GB file size
      for (unsigned int i = 0; i < nEvents; ++i) {
         wrEnergy = rnd.Rndm();
         chksumWrite += wrEnergy;
         ntuple->Fill();
      }
   }
   FILE *file = fopen(fileGuard.GetPath().c_str(), "rb");
   ASSERT_TRUE(file != nullptr);
   EXPECT_EQ(0, fseek(file, 0, SEEK_END));
   EXPECT_GT(ftell(file), 2048LL * 1024LL * 1024LL);
   fclose(file);

   auto ntuple = RNTupleReader::Open("myNTuple", fileGuard.GetPath());
   auto rdEnergy  = ntuple->GetView<double>("energy");
   double chksumRead = 0.0;

   for (auto i : ntuple->GetEntryRange()) {
      chksumRead += rdEnergy(i);
   }

   EXPECT_EQ(chksumRead, chksumWrite);
   auto f = TFile::Open(fileGuard.GetPath().c_str(), "READ");
   EXPECT_TRUE(f != nullptr);
   delete f;
}
#endif
<commit_msg>[ntuple] add unit test for random access reading<commit_after>#include "ntuple_test.hxx"

TEST(RNTuple, RealWorld1)
{
   FileRaii fileGuard("test_ntuple_realworld1.root");

   // See https://github.com/olifre/root-io-bench/blob/master/benchmark.cpp
   auto modelWrite = RNTupleModel::Create();
   auto wrEvent   = modelWrite->MakeField<std::uint32_t>("event");
   auto wrSignal  = modelWrite->MakeField<bool>("signal");
   auto wrEnergy  = modelWrite->MakeField<double>("energy");
   auto wrTimes   = modelWrite->MakeField<std::vector<double>>("times");
   auto wrIndices = modelWrite->MakeField<std::vector<std::uint32_t>>("indices");

   TRandom3 rnd(42);
   double chksumWrite = 0.0;
   {
      auto ntuple = RNTupleWriter::Recreate(std::move(modelWrite), "myNTuple", fileGuard.GetPath());
      constexpr unsigned int nEvents = 60000;
      for (unsigned int i = 0; i < nEvents; ++i) {
         *wrEvent = i;
         *wrEnergy = rnd.Rndm() * 1000.;
         *wrSignal = i % 2;

         chksumWrite += double(*wrEvent);
         chksumWrite += double(*wrSignal);
         chksumWrite += *wrEnergy;

         auto nTimes = 1 + floor(rnd.Rndm() * 1000.);
         wrTimes->resize(nTimes);
         for (unsigned int n = 0; n < nTimes; ++n) {
            wrTimes->at(n) = 1 + rnd.Rndm()*1000. - 500.;
            chksumWrite += wrTimes->at(n);
         }

         auto nIndices = 1 + floor(rnd.Rndm() * 1000.);
         wrIndices->resize(nIndices);
         for (unsigned int n = 0; n < nIndices; ++n) {
            wrIndices->at(n) = 1 + floor(rnd.Rndm() * 1000.);
            chksumWrite += double(wrIndices->at(n));
         }

         ntuple->Fill();
      }
   }

   auto modelRead  = RNTupleModel::Create();
   auto rdEvent   = modelRead->MakeField<std::uint32_t>("event");
   auto rdSignal  = modelRead->MakeField<bool>("signal");
   auto rdEnergy  = modelRead->MakeField<double>("energy");
   auto rdTimes   = modelRead->MakeField<std::vector<double>>("times");
   auto rdIndices = modelRead->MakeField<std::vector<std::uint32_t>>("indices");

   double chksumRead = 0.0;
   auto ntuple = RNTupleReader::Open(std::move(modelRead), "myNTuple", fileGuard.GetPath());
   for (auto entryId : *ntuple) {
      ntuple->LoadEntry(entryId);
      chksumRead += double(*rdEvent) + double(*rdSignal) + *rdEnergy;
      for (auto t : *rdTimes) chksumRead += t;
      for (auto ind : *rdIndices) chksumRead += double(ind);
   }

   // The floating point arithmetic should have been executed in the same order for reading and writing,
   // thus we expect the checksums to be bitwise identical
   EXPECT_EQ(chksumRead, chksumWrite);
}

// Stress test the asynchronous cluster pool by a deliberately unfavourable read pattern
TEST(RNTuple, RandomAccess)
{
   FileRaii fileGuard("test_ntuple_random_access.root");

   auto modelWrite = RNTupleModel::Create();
   auto wrValue   = modelWrite->MakeField<std::int32_t>("value", 42);

   constexpr unsigned int nEvents = 1000000;
   {
      RNTupleWriteOptions options;
      options.SetCompression(0);
      auto ntuple = RNTupleWriter::Recreate(std::move(modelWrite), "myNTuple", fileGuard.GetPath(), options);
      for (unsigned int i = 0; i < nEvents; ++i)
         ntuple->Fill();
   }

   RNTupleReadOptions options;
   options.SetClusterCache(RNTupleReadOptions::EClusterCache::kOn);
   auto ntuple = RNTupleReader::Open("myNTuple", fileGuard.GetPath(), options);
   EXPECT_GT(ntuple->GetDescriptor().GetNClusters(), 10);

   auto viewValue = ntuple->GetView<std::int32_t>("value");

   std::int32_t sum = 0;
   constexpr unsigned int nSamples = 1000;
   TRandom3 rnd(42);
   for (unsigned int i = 0; i < 1000; ++i) {
      auto entryId = floor(rnd.Rndm() * (nEvents - 1));
      sum += viewValue(entryId);
   }
   EXPECT_EQ(42 * nSamples, sum);
}

#if !defined(_MSC_VER) || defined(R__ENABLE_BROKEN_WIN_TESTS)
TEST(RNTuple, LargeFile)
{
   FileRaii fileGuard("test_large_file.root");

   auto modelWrite = RNTupleModel::Create();
   auto& wrEnergy  = *modelWrite->MakeField<double>("energy");

   TRandom3 rnd(42);
   double chksumWrite = 0.0;
   {
      RNTupleWriteOptions options;
      options.SetCompression(0);
      auto ntuple = RNTupleWriter::Recreate(std::move(modelWrite), "myNTuple", fileGuard.GetPath(), options);
      constexpr unsigned long nEvents = 1024 * 1024 * 256; // Exceed 2GB file size
      for (unsigned int i = 0; i < nEvents; ++i) {
         wrEnergy = rnd.Rndm();
         chksumWrite += wrEnergy;
         ntuple->Fill();
      }
   }
   FILE *file = fopen(fileGuard.GetPath().c_str(), "rb");
   ASSERT_TRUE(file != nullptr);
   EXPECT_EQ(0, fseek(file, 0, SEEK_END));
   EXPECT_GT(ftell(file), 2048LL * 1024LL * 1024LL);
   fclose(file);

   auto ntuple = RNTupleReader::Open("myNTuple", fileGuard.GetPath());
   auto rdEnergy  = ntuple->GetView<double>("energy");
   double chksumRead = 0.0;

   for (auto i : ntuple->GetEntryRange()) {
      chksumRead += rdEnergy(i);
   }

   EXPECT_EQ(chksumRead, chksumWrite);
   auto f = TFile::Open(fileGuard.GetPath().c_str(), "READ");
   EXPECT_TRUE(f != nullptr);
   delete f;
}
#endif
<|endoftext|>


<commit_before>// RUN: %clang_cl_asan -O0 %s -Fe%t
// RUN: not %run %t 2>&1 | FileCheck %s

#include <windows.h>

HANDLE done;

DWORD CALLBACK work_item(LPVOID) {
  int subscript = -1;
  volatile char stack_buffer[42];
  stack_buffer[subscript] = 42;
// CHECK: AddressSanitizer: stack-buffer-underflow on address [[ADDR:0x[0-9a-f]+]]
// CHECK: WRITE of size 1 at [[ADDR]] thread T1
// CHECK:   {{#0 .* work_item.*queue_user_work_item_report.cc}}:[[@LINE-3]]
// CHECK: Address [[ADDR]] is located in stack of thread T1 at offset {{.*}} in frame
// CHECK:   work_item
  SetEvent(done);
  return 0;
}

int main(int argc, char **argv) {
  done = CreateEvent(0, false, false, "job is done");
  if (!done)
    return 1;
// CHECK-NOT: Thread T1 created
  QueueUserWorkItem(&work_item, nullptr, 0);
  if (WAIT_OBJECT_0 != WaitForSingleObject(done, 10 * 1000))
    return 2;
}
<commit_msg>Remove stale CHECK lines that should have been included in r277478<commit_after>// RUN: %clang_cl_asan -O0 %s -Fe%t
// RUN: not %run %t 2>&1 | FileCheck %s

#include <windows.h>

HANDLE done;

DWORD CALLBACK work_item(LPVOID) {
  int subscript = -1;
  volatile char stack_buffer[42];
  stack_buffer[subscript] = 42;
// CHECK: AddressSanitizer: stack-buffer-underflow on address [[ADDR:0x[0-9a-f]+]]
// CHECK: WRITE of size 1 at [[ADDR]] thread T1
// CHECK:   {{#0 .* work_item.*queue_user_work_item_report.cc}}:[[@LINE-3]]
  SetEvent(done);
  return 0;
}

int main(int argc, char **argv) {
  done = CreateEvent(0, false, false, "job is done");
  if (!done)
    return 1;
// CHECK-NOT: Thread T1 created
  QueueUserWorkItem(&work_item, nullptr, 0);
  if (WAIT_OBJECT_0 != WaitForSingleObject(done, 10 * 1000))
    return 2;
}
<|endoftext|>


<commit_before>/*****************************************************************************
 * EPGChannels.cpp: EPGChannels
 ****************************************************************************
 * Copyright © 2009-2010 VideoLAN
 *
 * Authors: Adrien Maglo <magsoft@videolan.org>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software Foundation, Inc.,
 * 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
 *****************************************************************************/

#include "EPGChannels.hpp"
#include "EPGView.hpp"

#include <QPainter>
#include <QFont>
#include <QPaintEvent>

EPGChannels::EPGChannels( QWidget *parent, EPGView *m_epgView )
    : QWidget( parent ), m_epgView( m_epgView ), m_offset( 0 )
{
    setContentsMargins( 0, 0, 0, 0 );
}

void EPGChannels::setOffset( int offset )
{
    m_offset = offset;
    update();
}

void EPGChannels::addChannel( QString channelName )
{
    if ( !channelList.contains( channelName ) )
    {
        channelList << channelName;
        channelList.sort();
        update();
    }
}

void EPGChannels::removeChannel( QString channelName )
{
    if ( channelList.removeOne( channelName ) ) update();
}

void EPGChannels::paintEvent( QPaintEvent *event )
{
    Q_UNUSED( event );

    QPainter p( this );

    /* Draw the top and the bottom lines. */
    p.drawLine( 0, 0, width() - 1, 0 );

    unsigned int i=0;
    foreach( QString text, channelList )
    {
        /* try to remove the " [Program xxx]" end */
        int i_idx_channel = text.lastIndexOf(" [Program ");
        if (i_idx_channel > 0)
            text = text.left( i_idx_channel );

        p.drawText( 0, - m_offset + ( i++ + 0.5 ) * TRACKS_HEIGHT - 4,
                    width(), 20, Qt::AlignLeft, text );

        int i_width = fontMetrics().width( text );
        if( width() < i_width )
            setMinimumWidth( i_width );
    }
}
<commit_msg>Qt: epgchannels: split string on bracket.<commit_after>/*****************************************************************************
 * EPGChannels.cpp: EPGChannels
 ****************************************************************************
 * Copyright © 2009-2010 VideoLAN
 *
 * Authors: Adrien Maglo <magsoft@videolan.org>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software Foundation, Inc.,
 * 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
 *****************************************************************************/

#include "EPGChannels.hpp"
#include "EPGView.hpp"

#include <QPainter>
#include <QFont>
#include <QPaintEvent>

EPGChannels::EPGChannels( QWidget *parent, EPGView *m_epgView )
    : QWidget( parent ), m_epgView( m_epgView ), m_offset( 0 )
{
    setContentsMargins( 0, 0, 0, 0 );
}

void EPGChannels::setOffset( int offset )
{
    m_offset = offset;
    update();
}

void EPGChannels::addChannel( QString channelName )
{
    if ( !channelList.contains( channelName ) )
    {
        channelList << channelName;
        channelList.sort();
        update();
    }
}

void EPGChannels::removeChannel( QString channelName )
{
    if ( channelList.removeOne( channelName ) ) update();
}

void EPGChannels::paintEvent( QPaintEvent *event )
{
    Q_UNUSED( event );

    QPainter p( this );

    /* Draw the top and the bottom lines. */
    p.drawLine( 0, 0, width() - 1, 0 );

    unsigned int i=0;
    foreach( QString text, channelList )
    {
        /* try to remove the " [Program xxx]" end */
        int i_idx_channel = text.lastIndexOf(" [");
        if (i_idx_channel > 0)
            text = text.left( i_idx_channel );

        p.drawText( 0, - m_offset + ( i++ + 0.5 ) * TRACKS_HEIGHT - 4,
                    width(), 20, Qt::AlignLeft, text );

        int i_width = fontMetrics().width( text );
        if( width() < i_width )
            setMinimumWidth( i_width );
    }
}
<|endoftext|>


<commit_before>// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
#include <vespa/vespalib/testkit/testapp.h>
#include <vespa/vespalib/stllike/string.h>
#include <vespa/document/base/documentid.h>
#include <vespa/vespalib/util/threadstackexecutor.h>
#include <vespa/searchcore/proton/server/executor_thread_service.h>
#include <vespa/searchlib/common/lambdatask.h>
#include <vespa/searchcore/proton/reference/i_gid_to_lid_change_listener.h>
#include <vespa/searchcore/proton/reference/gid_to_lid_change_handler.h>
#include <map>
#include <vespa/log/log.h>
LOG_SETUP("gid_to_lid_change_handler_test");

using document::GlobalId;
using document::DocumentId;
using search::makeLambdaTask;
using search::SerialNum;

namespace proton {

namespace {

GlobalId toGid(vespalib::stringref docId) {
    return DocumentId(docId).getGlobalId();
}

vespalib::string doc1("id:test:music::1");

}

class ListenerStats {
    using lock_guard = std::lock_guard<std::mutex>;
    std::mutex _lock;
    uint32_t  _putChanges;
    uint32_t  _removeChanges;
    uint32_t  _createdListeners;
    uint32_t  _registeredListeners;
    uint32_t  _destroyedListeners;

public:
    ListenerStats()
        : _lock(),
          _putChanges(0u),
          _removeChanges(0u),
          _createdListeners(0u),
          _registeredListeners(0u),
          _destroyedListeners(0u)
    {
    }

    ~ListenerStats()
    {
        EXPECT_EQUAL(_createdListeners, _destroyedListeners);
    }

    void notifyPutDone() {
        lock_guard guard(_lock);
        ++_putChanges;
    }
    void notifyRemove() {
        lock_guard guard(_lock);
        ++_removeChanges;
    }
    void markCreatedListener()    { lock_guard guard(_lock); ++_createdListeners; }
    void markRegisteredListener() { lock_guard guard(_lock); ++_registeredListeners; }
    void markDestroyedListener()  { lock_guard guard(_lock); ++_destroyedListeners; }

    uint32_t getCreatedListeners() const { return _createdListeners; }
    uint32_t getRegisteredListeners() const { return _registeredListeners; }
    uint32_t getDestroyedListeners() const { return _destroyedListeners; }

    void assertListeners(uint32_t expCreatedListeners,
                         uint32_t expRegisteredListeners,
                         uint32_t expDestroyedListeners)
    {
        EXPECT_EQUAL(expCreatedListeners, getCreatedListeners());
        EXPECT_EQUAL(expRegisteredListeners, getRegisteredListeners());
        EXPECT_EQUAL(expDestroyedListeners, getDestroyedListeners());
    }
    void assertChanges(uint32_t expPutChanges, uint32_t expRemoveChanges)
    {
        EXPECT_EQUAL(expPutChanges, _putChanges);
        EXPECT_EQUAL(expRemoveChanges, _removeChanges);
    }
};

class MyListener : public IGidToLidChangeListener
{
    ListenerStats         &_stats;
    vespalib::string  _name;
    vespalib::string  _docTypeName;
public:
    MyListener(ListenerStats &stats,
               const vespalib::string &name,
               const vespalib::string &docTypeName)
        : IGidToLidChangeListener(),
          _stats(stats),
          _name(name),
          _docTypeName(docTypeName)
    {
        _stats.markCreatedListener();
    }
    virtual ~MyListener() { _stats.markDestroyedListener(); }
    virtual void notifyPutDone(GlobalId, uint32_t) override { _stats.notifyPutDone(); }
    virtual void notifyRemove(GlobalId) override { _stats.notifyRemove(); }
    virtual void notifyRegistered() override { _stats.markRegisteredListener(); }
    virtual const vespalib::string &getName() const override { return _name; }
    virtual const vespalib::string &getDocTypeName() const override { return _docTypeName; }
};

struct Fixture
{
    std::vector<std::shared_ptr<ListenerStats>> _statss;
    std::shared_ptr<GidToLidChangeHandler> _handler;

    Fixture()
        : _statss(),
          _handler(std::make_shared<GidToLidChangeHandler>())
    {
    }

    ~Fixture()
    {
        close();
    }

    void close()
    {
        _handler->close();
    }

    ListenerStats &addStats() {
        _statss.push_back(std::make_shared<ListenerStats>());
        return *_statss.back();
    }

    void addListener(std::unique_ptr<IGidToLidChangeListener> listener) {
        _handler->addListener(std::move(listener));
    }

    void notifyPutDone(GlobalId gid, uint32_t lid, SerialNum serialNum) {
        _handler->notifyPutDone(gid, lid, serialNum);
    }

    void notifyRemove(GlobalId gid, SerialNum serialNum) {
        _handler->notifyRemove(gid, serialNum);
    }

    void notifyRemoveDone(GlobalId gid, SerialNum serialNum) {
        _handler->notifyRemoveDone(gid, serialNum);
    }

    void removeListeners(const vespalib::string &docTypeName,
                         const std::set<vespalib::string> &keepNames) {
        _handler->removeListeners(docTypeName, keepNames);
    }

};

TEST_F("Test that we can register a listener", Fixture)
{
    auto &stats = f.addStats();
    auto listener = std::make_unique<MyListener>(stats, "test", "testdoc");
    TEST_DO(stats.assertListeners(1, 0, 0));
    f.addListener(std::move(listener));
    TEST_DO(stats.assertListeners(1, 1, 0));
    f.notifyPutDone(toGid(doc1), 10, 10);
    TEST_DO(stats.assertChanges(1, 0));
    f.removeListeners("testdoc", {});
    TEST_DO(stats.assertListeners(1, 1, 1));
}

TEST_F("Test that we can register multiple listeners", Fixture)
{
    auto &stats1 = f.addStats();
    auto &stats2 = f.addStats();
    auto &stats3 = f.addStats();
    auto listener1 = std::make_unique<MyListener>(stats1, "test1", "testdoc");
    auto listener2 = std::make_unique<MyListener>(stats2, "test2", "testdoc");
    auto listener3 = std::make_unique<MyListener>(stats3, "test3", "testdoc2");
    TEST_DO(stats1.assertListeners(1, 0, 0));
    TEST_DO(stats2.assertListeners(1, 0, 0));
    TEST_DO(stats3.assertListeners(1, 0, 0));
    f.addListener(std::move(listener1));
    f.addListener(std::move(listener2));
    f.addListener(std::move(listener3));
    TEST_DO(stats1.assertListeners(1, 1, 0));
    TEST_DO(stats2.assertListeners(1, 1, 0));
    TEST_DO(stats3.assertListeners(1, 1, 0));
    f.notifyPutDone(toGid(doc1), 10, 10);
    TEST_DO(stats1.assertChanges(1, 0));
    TEST_DO(stats2.assertChanges(1, 0));
    TEST_DO(stats3.assertChanges(1, 0));
    f.removeListeners("testdoc", {"test1"});
    TEST_DO(stats1.assertListeners(1, 1, 0));
    TEST_DO(stats2.assertListeners(1, 1, 1));
    TEST_DO(stats3.assertListeners(1, 1, 0));
    f.removeListeners("testdoc", {});
    TEST_DO(stats1.assertListeners(1, 1, 1));
    TEST_DO(stats2.assertListeners(1, 1, 1));
    TEST_DO(stats3.assertListeners(1, 1, 0));
    f.removeListeners("testdoc2", {"test3"});
    TEST_DO(stats1.assertListeners(1, 1, 1));
    TEST_DO(stats2.assertListeners(1, 1, 1));
    TEST_DO(stats3.assertListeners(1, 1, 0));
    f.removeListeners("testdoc2", {"foo"});
    TEST_DO(stats1.assertListeners(1, 1, 1));
    TEST_DO(stats2.assertListeners(1, 1, 1));
    TEST_DO(stats3.assertListeners(1, 1, 1));
}

TEST_F("Test that we keep old listener when registering duplicate", Fixture)
{
    auto &stats = f.addStats();
    auto listener = std::make_unique<MyListener>(stats, "test1", "testdoc");
    TEST_DO(stats.assertListeners(1, 0, 0));
    f.addListener(std::move(listener));
    TEST_DO(stats.assertListeners(1, 1, 0));
    listener = std::make_unique<MyListener>(stats, "test1", "testdoc");
    TEST_DO(stats.assertListeners(2, 1, 0));
    f.addListener(std::move(listener));
    TEST_DO(stats.assertListeners(2, 1, 1));
}

TEST_F("Test that put is ignored if we have a pending remove", Fixture)
{
    auto &stats = f.addStats();
    auto listener = std::make_unique<MyListener>(stats, "test", "testdoc");
    f.addListener(std::move(listener));
    f.notifyRemove(toGid(doc1), 20);
    TEST_DO(stats.assertChanges(0, 1));
    f.notifyPutDone(toGid(doc1), 10, 10);
    TEST_DO(stats.assertChanges(0, 1));
    f.notifyRemoveDone(toGid(doc1), 20);
    TEST_DO(stats.assertChanges(0, 1));
    f.notifyPutDone(toGid(doc1), 11, 30);
    TEST_DO(stats.assertChanges(1, 1));
    f.removeListeners("testdoc", {});
}

TEST_F("Test that pending removes are merged", Fixture)
{
    auto &stats = f.addStats();
    auto listener = std::make_unique<MyListener>(stats, "test", "testdoc");
    f.addListener(std::move(listener));
    f.notifyRemove(toGid(doc1), 20);
    TEST_DO(stats.assertChanges(0, 1));
    f.notifyRemove(toGid(doc1), 40);
    TEST_DO(stats.assertChanges(0, 1));
    f.notifyPutDone(toGid(doc1), 10, 10);
    TEST_DO(stats.assertChanges(0, 1));
    f.notifyRemoveDone(toGid(doc1), 20);
    TEST_DO(stats.assertChanges(0, 1));
    f.notifyPutDone(toGid(doc1), 11, 30);
    TEST_DO(stats.assertChanges(0, 1));
    f.notifyRemoveDone(toGid(doc1), 40);
    TEST_DO(stats.assertChanges(0, 1));
    f.notifyPutDone(toGid(doc1), 12, 50);
    TEST_DO(stats.assertChanges(1, 1));
    f.removeListeners("testdoc", {});
}

TEST_F("Test that out of order notifyRemoveDone is handled", Fixture)
{
    auto &stats = f.addStats();
    auto listener = std::make_unique<MyListener>(stats, "test", "testdoc");
    f.addListener(std::move(listener));
    f.notifyRemove(toGid(doc1), 20);
    TEST_DO(stats.assertChanges(0, 1));
    f.notifyRemove(toGid(doc1), 40);
    TEST_DO(stats.assertChanges(0, 1));
    f.notifyRemoveDone(toGid(doc1), 40);
    TEST_DO(stats.assertChanges(0, 1));
    f.notifyRemoveDone(toGid(doc1), 20);
    TEST_DO(stats.assertChanges(0, 1));
    f.notifyPutDone(toGid(doc1), 12, 50);
    TEST_DO(stats.assertChanges(1, 1));
    f.removeListeners("testdoc", {});
}

TEST_F("Test that out of order notifyPutDone is handled", Fixture)
{
    auto &stats = f.addStats();
    auto listener = std::make_unique<MyListener>(stats, "test", "testdoc");
    f.addListener(std::move(listener));
    f.notifyRemove(toGid(doc1), 20);
    TEST_DO(stats.assertChanges(0, 1));
    f.notifyPutDone(toGid(doc1), 12, 50);
    TEST_DO(stats.assertChanges(1, 1));
    f.notifyRemoveDone(toGid(doc1), 20);
    TEST_DO(stats.assertChanges(1, 1));
    f.removeListeners("testdoc", {});
}

}

TEST_MAIN()
{
    TEST_RUN_ALL();
}
<commit_msg>Use a new fixture for the last 4 tests to reduce amount of duplicated code.<commit_after>// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
#include <vespa/vespalib/testkit/testapp.h>
#include <vespa/vespalib/stllike/string.h>
#include <vespa/document/base/documentid.h>
#include <vespa/vespalib/util/threadstackexecutor.h>
#include <vespa/searchcore/proton/server/executor_thread_service.h>
#include <vespa/searchlib/common/lambdatask.h>
#include <vespa/searchcore/proton/reference/i_gid_to_lid_change_listener.h>
#include <vespa/searchcore/proton/reference/gid_to_lid_change_handler.h>
#include <map>
#include <vespa/log/log.h>
LOG_SETUP("gid_to_lid_change_handler_test");

using document::GlobalId;
using document::DocumentId;
using search::makeLambdaTask;
using search::SerialNum;

namespace proton {

namespace {

GlobalId toGid(vespalib::stringref docId) {
    return DocumentId(docId).getGlobalId();
}

vespalib::string doc1("id:test:music::1");

}

class ListenerStats {
    using lock_guard = std::lock_guard<std::mutex>;
    std::mutex _lock;
    uint32_t  _putChanges;
    uint32_t  _removeChanges;
    uint32_t  _createdListeners;
    uint32_t  _registeredListeners;
    uint32_t  _destroyedListeners;

public:
    ListenerStats()
        : _lock(),
          _putChanges(0u),
          _removeChanges(0u),
          _createdListeners(0u),
          _registeredListeners(0u),
          _destroyedListeners(0u)
    {
    }

    ~ListenerStats()
    {
        EXPECT_EQUAL(_createdListeners, _destroyedListeners);
    }

    void notifyPutDone() {
        lock_guard guard(_lock);
        ++_putChanges;
    }
    void notifyRemove() {
        lock_guard guard(_lock);
        ++_removeChanges;
    }
    void markCreatedListener()    { lock_guard guard(_lock); ++_createdListeners; }
    void markRegisteredListener() { lock_guard guard(_lock); ++_registeredListeners; }
    void markDestroyedListener()  { lock_guard guard(_lock); ++_destroyedListeners; }

    uint32_t getCreatedListeners() const { return _createdListeners; }
    uint32_t getRegisteredListeners() const { return _registeredListeners; }
    uint32_t getDestroyedListeners() const { return _destroyedListeners; }

    void assertListeners(uint32_t expCreatedListeners,
                         uint32_t expRegisteredListeners,
                         uint32_t expDestroyedListeners)
    {
        EXPECT_EQUAL(expCreatedListeners, getCreatedListeners());
        EXPECT_EQUAL(expRegisteredListeners, getRegisteredListeners());
        EXPECT_EQUAL(expDestroyedListeners, getDestroyedListeners());
    }
    void assertChanges(uint32_t expPutChanges, uint32_t expRemoveChanges)
    {
        EXPECT_EQUAL(expPutChanges, _putChanges);
        EXPECT_EQUAL(expRemoveChanges, _removeChanges);
    }
};

class MyListener : public IGidToLidChangeListener
{
    ListenerStats         &_stats;
    vespalib::string  _name;
    vespalib::string  _docTypeName;
public:
    MyListener(ListenerStats &stats,
               const vespalib::string &name,
               const vespalib::string &docTypeName)
        : IGidToLidChangeListener(),
          _stats(stats),
          _name(name),
          _docTypeName(docTypeName)
    {
        _stats.markCreatedListener();
    }
    virtual ~MyListener() { _stats.markDestroyedListener(); }
    virtual void notifyPutDone(GlobalId, uint32_t) override { _stats.notifyPutDone(); }
    virtual void notifyRemove(GlobalId) override { _stats.notifyRemove(); }
    virtual void notifyRegistered() override { _stats.markRegisteredListener(); }
    virtual const vespalib::string &getName() const override { return _name; }
    virtual const vespalib::string &getDocTypeName() const override { return _docTypeName; }
};

struct Fixture
{
    std::vector<std::shared_ptr<ListenerStats>> _statss;
    std::shared_ptr<GidToLidChangeHandler> _handler;

    Fixture()
        : _statss(),
          _handler(std::make_shared<GidToLidChangeHandler>())
    {
    }

    ~Fixture()
    {
        close();
    }

    void close()
    {
        _handler->close();
    }

    ListenerStats &addStats() {
        _statss.push_back(std::make_shared<ListenerStats>());
        return *_statss.back();
    }

    void addListener(std::unique_ptr<IGidToLidChangeListener> listener) {
        _handler->addListener(std::move(listener));
    }

    void notifyPutDone(GlobalId gid, uint32_t lid, SerialNum serialNum) {
        _handler->notifyPutDone(gid, lid, serialNum);
    }

    void notifyRemove(GlobalId gid, SerialNum serialNum) {
        _handler->notifyRemove(gid, serialNum);
    }

    void notifyRemoveDone(GlobalId gid, SerialNum serialNum) {
        _handler->notifyRemoveDone(gid, serialNum);
    }

    void removeListeners(const vespalib::string &docTypeName,
                         const std::set<vespalib::string> &keepNames) {
        _handler->removeListeners(docTypeName, keepNames);
    }

};

TEST_F("Test that we can register a listener", Fixture)
{
    auto &stats = f.addStats();
    auto listener = std::make_unique<MyListener>(stats, "test", "testdoc");
    TEST_DO(stats.assertListeners(1, 0, 0));
    f.addListener(std::move(listener));
    TEST_DO(stats.assertListeners(1, 1, 0));
    f.notifyPutDone(toGid(doc1), 10, 10);
    TEST_DO(stats.assertChanges(1, 0));
    f.removeListeners("testdoc", {});
    TEST_DO(stats.assertListeners(1, 1, 1));
}

TEST_F("Test that we can register multiple listeners", Fixture)
{
    auto &stats1 = f.addStats();
    auto &stats2 = f.addStats();
    auto &stats3 = f.addStats();
    auto listener1 = std::make_unique<MyListener>(stats1, "test1", "testdoc");
    auto listener2 = std::make_unique<MyListener>(stats2, "test2", "testdoc");
    auto listener3 = std::make_unique<MyListener>(stats3, "test3", "testdoc2");
    TEST_DO(stats1.assertListeners(1, 0, 0));
    TEST_DO(stats2.assertListeners(1, 0, 0));
    TEST_DO(stats3.assertListeners(1, 0, 0));
    f.addListener(std::move(listener1));
    f.addListener(std::move(listener2));
    f.addListener(std::move(listener3));
    TEST_DO(stats1.assertListeners(1, 1, 0));
    TEST_DO(stats2.assertListeners(1, 1, 0));
    TEST_DO(stats3.assertListeners(1, 1, 0));
    f.notifyPutDone(toGid(doc1), 10, 10);
    TEST_DO(stats1.assertChanges(1, 0));
    TEST_DO(stats2.assertChanges(1, 0));
    TEST_DO(stats3.assertChanges(1, 0));
    f.removeListeners("testdoc", {"test1"});
    TEST_DO(stats1.assertListeners(1, 1, 0));
    TEST_DO(stats2.assertListeners(1, 1, 1));
    TEST_DO(stats3.assertListeners(1, 1, 0));
    f.removeListeners("testdoc", {});
    TEST_DO(stats1.assertListeners(1, 1, 1));
    TEST_DO(stats2.assertListeners(1, 1, 1));
    TEST_DO(stats3.assertListeners(1, 1, 0));
    f.removeListeners("testdoc2", {"test3"});
    TEST_DO(stats1.assertListeners(1, 1, 1));
    TEST_DO(stats2.assertListeners(1, 1, 1));
    TEST_DO(stats3.assertListeners(1, 1, 0));
    f.removeListeners("testdoc2", {"foo"});
    TEST_DO(stats1.assertListeners(1, 1, 1));
    TEST_DO(stats2.assertListeners(1, 1, 1));
    TEST_DO(stats3.assertListeners(1, 1, 1));
}

TEST_F("Test that we keep old listener when registering duplicate", Fixture)
{
    auto &stats = f.addStats();
    auto listener = std::make_unique<MyListener>(stats, "test1", "testdoc");
    TEST_DO(stats.assertListeners(1, 0, 0));
    f.addListener(std::move(listener));
    TEST_DO(stats.assertListeners(1, 1, 0));
    listener = std::make_unique<MyListener>(stats, "test1", "testdoc");
    TEST_DO(stats.assertListeners(2, 1, 0));
    f.addListener(std::move(listener));
    TEST_DO(stats.assertListeners(2, 1, 1));
}

class StatsFixture : public Fixture
{
    ListenerStats &_stats;

public:
    StatsFixture()
        : Fixture(),
          _stats(addStats())
    {
        addListener(std::make_unique<MyListener>(_stats, "test", "testdoc"));
    }

    ~StatsFixture()
    {
        removeListeners("testdoc", {});
    }

    void assertChanges(uint32_t expPutChanges, uint32_t expRemoveChanges)
    {
        TEST_DO(_stats.assertChanges(expPutChanges, expRemoveChanges));
    }
};

TEST_F("Test that put is ignored if we have a pending remove", StatsFixture)
{
    f.notifyRemove(toGid(doc1), 20);
    TEST_DO(f.assertChanges(0, 1));
    f.notifyPutDone(toGid(doc1), 10, 10);
    TEST_DO(f.assertChanges(0, 1));
    f.notifyRemoveDone(toGid(doc1), 20);
    TEST_DO(f.assertChanges(0, 1));
    f.notifyPutDone(toGid(doc1), 11, 30);
    TEST_DO(f.assertChanges(1, 1));
}

TEST_F("Test that pending removes are merged", StatsFixture)
{
    f.notifyRemove(toGid(doc1), 20);
    TEST_DO(f.assertChanges(0, 1));
    f.notifyRemove(toGid(doc1), 40);
    TEST_DO(f.assertChanges(0, 1));
    f.notifyPutDone(toGid(doc1), 10, 10);
    TEST_DO(f.assertChanges(0, 1));
    f.notifyRemoveDone(toGid(doc1), 20);
    TEST_DO(f.assertChanges(0, 1));
    f.notifyPutDone(toGid(doc1), 11, 30);
    TEST_DO(f.assertChanges(0, 1));
    f.notifyRemoveDone(toGid(doc1), 40);
    TEST_DO(f.assertChanges(0, 1));
    f.notifyPutDone(toGid(doc1), 12, 50);
    TEST_DO(f.assertChanges(1, 1));
}

TEST_F("Test that out of order notifyRemoveDone is handled", StatsFixture)
{
     f.notifyRemove(toGid(doc1), 20);
    TEST_DO(f.assertChanges(0, 1));
    f.notifyRemove(toGid(doc1), 40);
    TEST_DO(f.assertChanges(0, 1));
    f.notifyRemoveDone(toGid(doc1), 40);
    TEST_DO(f.assertChanges(0, 1));
    f.notifyRemoveDone(toGid(doc1), 20);
    TEST_DO(f.assertChanges(0, 1));
    f.notifyPutDone(toGid(doc1), 12, 50);
    TEST_DO(f.assertChanges(1, 1));
}

TEST_F("Test that out of order notifyPutDone is handled", StatsFixture)
{
     f.notifyRemove(toGid(doc1), 20);
    TEST_DO(f.assertChanges(0, 1));
    f.notifyPutDone(toGid(doc1), 12, 50);
    TEST_DO(f.assertChanges(1, 1));
    f.notifyRemoveDone(toGid(doc1), 20);
    TEST_DO(f.assertChanges(1, 1));
}

}

TEST_MAIN()
{
    TEST_RUN_ALL();
}
<|endoftext|>