<commit_before>/****************************************************************************
 *
 *   Copyright (c) 2017  Intel Corporation. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in
 *    the documentation and/or other materials provided with the
 *    distribution.
 * 3. Neither the name PX4 nor the names of its contributors may be
 *    used to endorse or promote products derived from this software
 *    without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
 * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 *
 ****************************************************************************/
#include "ArmAuthorization.h"

#include <string.h>
#include <unistd.h>

#include <px4_platform_common/defines.h>
#include <px4_platform_common/px4_config.h>
#include <lib/parameters/param.h>
#include <systemlib/mavlink_log.h>
#include <uORB/Publication.hpp>
#include <uORB/topics/vehicle_command.h>
#include <uORB/topics/vehicle_command_ack.h>

static orb_advert_t *mavlink_log_pub;
static int command_ack_sub = -1;

static param_t param_arm_parameters;

static hrt_abstime auth_timeout;
static hrt_abstime auth_req_time;

static enum {
	ARM_AUTH_IDLE = 0,
	ARM_AUTH_WAITING_AUTH,
	ARM_AUTH_WAITING_AUTH_WITH_ACK,
	ARM_AUTH_MISSION_APPROVED
} state = ARM_AUTH_IDLE;

union {
	struct {
		uint8_t authorizer_system_id;
		union {
			uint16_t auth_method_arm_timeout_msec;
			uint16_t auth_method_two_arm_timeout_msec;
		} auth_method_param;
		uint8_t authentication_method;
	} __attribute__((packed)) struct_value;
	int32_t param_value;
} arm_parameters;

static uint8_t *system_id;

static uint8_t _auth_method_arm_req_check();
static uint8_t _auth_method_two_arm_check();

static uint8_t (*arm_check_method[ARM_AUTH_METHOD_LAST])() = {
	_auth_method_arm_req_check,
	_auth_method_two_arm_check,
};

static void arm_auth_request_msg_send()
{
	vehicle_command_s vcmd{};
	vcmd.timestamp = hrt_absolute_time();
	vcmd.command = vehicle_command_s::VEHICLE_CMD_ARM_AUTHORIZATION_REQUEST;
	vcmd.target_system = arm_parameters.struct_value.authorizer_system_id;

	uORB::Publication<vehicle_command_s> vcmd_pub{ORB_ID(vehicle_command)};
	vcmd_pub.publish(vcmd);
}

static uint8_t _auth_method_arm_req_check()
{
	switch (state) {
	case ARM_AUTH_IDLE:
		/* no authentication in process? handle bellow */
		break;

	case ARM_AUTH_MISSION_APPROVED:
		return vehicle_command_ack_s::VEHICLE_RESULT_ACCEPTED;

	default:
		return vehicle_command_ack_s::VEHICLE_RESULT_DENIED;
	}

	/* handling ARM_AUTH_IDLE */
	arm_auth_request_msg_send();

	hrt_abstime now = hrt_absolute_time();
	auth_req_time = now;
	auth_timeout = now + (arm_parameters.struct_value.auth_method_param.auth_method_arm_timeout_msec * 1000);
	state = ARM_AUTH_WAITING_AUTH;

	while (now < auth_timeout) {
		arm_auth_update(now);

		if (state != ARM_AUTH_WAITING_AUTH && state != ARM_AUTH_WAITING_AUTH_WITH_ACK) {
			break;
		}

		/* 0.5ms */
		px4_usleep(500);
		now = hrt_absolute_time();
	}

	switch (state) {
	case ARM_AUTH_WAITING_AUTH:
	case ARM_AUTH_WAITING_AUTH_WITH_ACK:
		state = ARM_AUTH_IDLE;
		mavlink_log_critical(mavlink_log_pub, "Arm auth: No response");
		break;

	default:
		break;
	}

	return state == ARM_AUTH_MISSION_APPROVED ?
	       vehicle_command_ack_s::VEHICLE_RESULT_ACCEPTED : vehicle_command_ack_s::VEHICLE_RESULT_DENIED;
}

static uint8_t _auth_method_two_arm_check()
{
	switch (state) {
	case ARM_AUTH_IDLE:
		/* no authentication in process? handle bellow */
		break;

	case ARM_AUTH_MISSION_APPROVED:
		return vehicle_command_ack_s::VEHICLE_RESULT_ACCEPTED;

	case ARM_AUTH_WAITING_AUTH:
	case ARM_AUTH_WAITING_AUTH_WITH_ACK:
		return vehicle_command_ack_s::VEHICLE_RESULT_TEMPORARILY_REJECTED;

	default:
		return vehicle_command_ack_s::VEHICLE_RESULT_DENIED;
	}

	/* handling ARM_AUTH_IDLE */
	arm_auth_request_msg_send();

	hrt_abstime now = hrt_absolute_time();
	auth_req_time = now;
	auth_timeout = now + (arm_parameters.struct_value.auth_method_param.auth_method_arm_timeout_msec * 1000);
	state = ARM_AUTH_WAITING_AUTH;

	mavlink_log_info(mavlink_log_pub, "Arm auth: Requesting authorization...");

	return vehicle_command_ack_s::VEHICLE_RESULT_TEMPORARILY_REJECTED;
}

uint8_t arm_auth_check()
{
	if (arm_parameters.struct_value.authentication_method < ARM_AUTH_METHOD_LAST) {
		return arm_check_method[arm_parameters.struct_value.authentication_method]();
	}

	return vehicle_command_ack_s::VEHICLE_RESULT_DENIED;
}

void arm_auth_update(hrt_abstime now, bool param_update)
{
	if (param_update) {
		param_get(param_arm_parameters, &arm_parameters.param_value);
	}

	switch (state) {
	case ARM_AUTH_WAITING_AUTH:
	case ARM_AUTH_WAITING_AUTH_WITH_ACK:
		/* handle bellow */
		break;

	case ARM_AUTH_MISSION_APPROVED:
		if (now > auth_timeout) {
			state = ARM_AUTH_IDLE;
		}

		return;

	case ARM_AUTH_IDLE:
	default:
		return;
	}

	/*
	 * handling ARM_AUTH_WAITING_AUTH, ARM_AUTH_WAITING_AUTH_WITH_ACK
	 */
	vehicle_command_ack_s command_ack;
	bool updated = false;

	orb_check(command_ack_sub, &updated);

	if (updated) {
		orb_copy(ORB_ID(vehicle_command_ack), command_ack_sub, &command_ack);
	}

	if (updated
	    && command_ack.command == vehicle_command_s::VEHICLE_CMD_ARM_AUTHORIZATION_REQUEST
	    && command_ack.target_system == *system_id
	    && command_ack.timestamp > auth_req_time) {
		switch (command_ack.result) {
		case vehicle_command_ack_s::VEHICLE_RESULT_IN_PROGRESS:
			state = ARM_AUTH_WAITING_AUTH_WITH_ACK;
			break;

		case vehicle_command_ack_s::VEHICLE_RESULT_ACCEPTED:
			mavlink_log_info(mavlink_log_pub,
					 "Arm auth: Authorized for the next %u seconds",
					 command_ack.result_param2);
			state = ARM_AUTH_MISSION_APPROVED;
			auth_timeout = now + (command_ack.result_param2 * 1000000);
			return;

		case vehicle_command_ack_s::VEHICLE_RESULT_TEMPORARILY_REJECTED:
			mavlink_log_critical(mavlink_log_pub, "Arm auth: Temporarily rejected");
			state = ARM_AUTH_IDLE;
			return;

		case vehicle_command_ack_s::VEHICLE_RESULT_DENIED:
		default:
			switch (command_ack.result_param1) {
			case vehicle_command_ack_s::ARM_AUTH_DENIED_REASON_NONE:
				/* Authorizer will send reason to ground station */
				break;

			case vehicle_command_ack_s::ARM_AUTH_DENIED_REASON_INVALID_WAYPOINT:
				mavlink_log_critical(mavlink_log_pub, "Arm auth: Denied, waypoint %i have a invalid value", command_ack.result_param2);
				break;

			case vehicle_command_ack_s::ARM_AUTH_DENIED_REASON_TIMEOUT:
				mavlink_log_critical(mavlink_log_pub, "Arm auth: Denied by timeout in authorizer");
				break;

			case vehicle_command_ack_s::ARM_AUTH_DENIED_REASON_AIRSPACE_IN_USE:
				mavlink_log_critical(mavlink_log_pub, "Arm auth: Denied because airspace is in use");
				break;

			case vehicle_command_ack_s::ARM_AUTH_DENIED_REASON_BAD_WEATHER:
				mavlink_log_critical(mavlink_log_pub, "Arm auth: Denied because of bad weather");
				break;

			case vehicle_command_ack_s::ARM_AUTH_DENIED_REASON_GENERIC:
			default:
				mavlink_log_critical(mavlink_log_pub, "Arm auth: Denied");
			}

			state = ARM_AUTH_IDLE;
			return;
		}
	}

	if (now > auth_timeout) {
		mavlink_log_critical(mavlink_log_pub, "Arm auth: No response");
		state = ARM_AUTH_IDLE;
	}
}

void arm_auth_init(orb_advert_t *mav_log_pub, uint8_t *sys_id)
{
	system_id = sys_id;
	param_arm_parameters = param_find("COM_ARM_AUTH");
	command_ack_sub = orb_subscribe(ORB_ID(vehicle_command_ack));
	mavlink_log_pub = mav_log_pub;
}

enum arm_auth_methods arm_auth_method_get()
{
	return (enum arm_auth_methods) arm_parameters.struct_value.authentication_method;
}
<commit_msg>arm_auth: use ack reception timestamp to compute authorization timeout<commit_after>/****************************************************************************
 *
 *   Copyright (c) 2017  Intel Corporation. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in
 *    the documentation and/or other materials provided with the
 *    distribution.
 * 3. Neither the name PX4 nor the names of its contributors may be
 *    used to endorse or promote products derived from this software
 *    without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
 * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 *
 ****************************************************************************/
#include "ArmAuthorization.h"

#include <string.h>
#include <unistd.h>

#include <px4_platform_common/defines.h>
#include <px4_platform_common/px4_config.h>
#include <lib/parameters/param.h>
#include <systemlib/mavlink_log.h>
#include <uORB/Publication.hpp>
#include <uORB/topics/vehicle_command.h>
#include <uORB/topics/vehicle_command_ack.h>

static orb_advert_t *mavlink_log_pub;
static int command_ack_sub = -1;

static param_t param_arm_parameters;

static hrt_abstime auth_timeout;
static hrt_abstime auth_req_time;

static enum {
	ARM_AUTH_IDLE = 0,
	ARM_AUTH_WAITING_AUTH,
	ARM_AUTH_WAITING_AUTH_WITH_ACK,
	ARM_AUTH_MISSION_APPROVED
} state = ARM_AUTH_IDLE;

union {
	struct {
		uint8_t authorizer_system_id;
		union {
			uint16_t auth_method_arm_timeout_msec;
			uint16_t auth_method_two_arm_timeout_msec;
		} auth_method_param;
		uint8_t authentication_method;
	} __attribute__((packed)) struct_value;
	int32_t param_value;
} arm_parameters;

static uint8_t *system_id;

static uint8_t _auth_method_arm_req_check();
static uint8_t _auth_method_two_arm_check();

static uint8_t (*arm_check_method[ARM_AUTH_METHOD_LAST])() = {
	_auth_method_arm_req_check,
	_auth_method_two_arm_check,
};

static void arm_auth_request_msg_send()
{
	vehicle_command_s vcmd{};
	vcmd.timestamp = hrt_absolute_time();
	vcmd.command = vehicle_command_s::VEHICLE_CMD_ARM_AUTHORIZATION_REQUEST;
	vcmd.target_system = arm_parameters.struct_value.authorizer_system_id;

	uORB::Publication<vehicle_command_s> vcmd_pub{ORB_ID(vehicle_command)};
	vcmd_pub.publish(vcmd);
}

static uint8_t _auth_method_arm_req_check()
{
	switch (state) {
	case ARM_AUTH_IDLE:
		/* no authentication in process? handle bellow */
		break;

	case ARM_AUTH_MISSION_APPROVED:
		return vehicle_command_ack_s::VEHICLE_RESULT_ACCEPTED;

	default:
		return vehicle_command_ack_s::VEHICLE_RESULT_DENIED;
	}

	/* handling ARM_AUTH_IDLE */
	arm_auth_request_msg_send();

	hrt_abstime now = hrt_absolute_time();
	auth_req_time = now;
	auth_timeout = now + (arm_parameters.struct_value.auth_method_param.auth_method_arm_timeout_msec * 1000);
	state = ARM_AUTH_WAITING_AUTH;

	while (now < auth_timeout) {
		arm_auth_update(now);

		if (state != ARM_AUTH_WAITING_AUTH && state != ARM_AUTH_WAITING_AUTH_WITH_ACK) {
			break;
		}

		/* 0.5ms */
		px4_usleep(500);
		now = hrt_absolute_time();
	}

	switch (state) {
	case ARM_AUTH_WAITING_AUTH:
	case ARM_AUTH_WAITING_AUTH_WITH_ACK:
		state = ARM_AUTH_IDLE;
		mavlink_log_critical(mavlink_log_pub, "Arm auth: No response");
		break;

	default:
		break;
	}

	return state == ARM_AUTH_MISSION_APPROVED ?
	       vehicle_command_ack_s::VEHICLE_RESULT_ACCEPTED : vehicle_command_ack_s::VEHICLE_RESULT_DENIED;
}

static uint8_t _auth_method_two_arm_check()
{
	switch (state) {
	case ARM_AUTH_IDLE:
		/* no authentication in process? handle bellow */
		break;

	case ARM_AUTH_MISSION_APPROVED:
		return vehicle_command_ack_s::VEHICLE_RESULT_ACCEPTED;

	case ARM_AUTH_WAITING_AUTH:
	case ARM_AUTH_WAITING_AUTH_WITH_ACK:
		return vehicle_command_ack_s::VEHICLE_RESULT_TEMPORARILY_REJECTED;

	default:
		return vehicle_command_ack_s::VEHICLE_RESULT_DENIED;
	}

	/* handling ARM_AUTH_IDLE */
	arm_auth_request_msg_send();

	hrt_abstime now = hrt_absolute_time();
	auth_req_time = now;
	auth_timeout = now + (arm_parameters.struct_value.auth_method_param.auth_method_arm_timeout_msec * 1000);
	state = ARM_AUTH_WAITING_AUTH;

	mavlink_log_info(mavlink_log_pub, "Arm auth: Requesting authorization...");

	return vehicle_command_ack_s::VEHICLE_RESULT_TEMPORARILY_REJECTED;
}

uint8_t arm_auth_check()
{
	if (arm_parameters.struct_value.authentication_method < ARM_AUTH_METHOD_LAST) {
		return arm_check_method[arm_parameters.struct_value.authentication_method]();
	}

	return vehicle_command_ack_s::VEHICLE_RESULT_DENIED;
}

void arm_auth_update(hrt_abstime now, bool param_update)
{
	if (param_update) {
		param_get(param_arm_parameters, &arm_parameters.param_value);
	}

	switch (state) {
	case ARM_AUTH_WAITING_AUTH:
	case ARM_AUTH_WAITING_AUTH_WITH_ACK:
		/* handle bellow */
		break;

	case ARM_AUTH_MISSION_APPROVED:
		if (now > auth_timeout) {
			state = ARM_AUTH_IDLE;
		}

		return;

	case ARM_AUTH_IDLE:
	default:
		return;
	}

	/*
	 * handling ARM_AUTH_WAITING_AUTH, ARM_AUTH_WAITING_AUTH_WITH_ACK
	 */
	vehicle_command_ack_s command_ack;
	bool updated = false;

	orb_check(command_ack_sub, &updated);

	if (updated) {
		orb_copy(ORB_ID(vehicle_command_ack), command_ack_sub, &command_ack);
	}

	if (updated
	    && command_ack.command == vehicle_command_s::VEHICLE_CMD_ARM_AUTHORIZATION_REQUEST
	    && command_ack.target_system == *system_id
	    && command_ack.timestamp > auth_req_time) {
		switch (command_ack.result) {
		case vehicle_command_ack_s::VEHICLE_RESULT_IN_PROGRESS:
			state = ARM_AUTH_WAITING_AUTH_WITH_ACK;
			break;

		case vehicle_command_ack_s::VEHICLE_RESULT_ACCEPTED:
			mavlink_log_info(mavlink_log_pub,
					 "Arm auth: Authorized for the next %u seconds",
					 command_ack.result_param2);
			state = ARM_AUTH_MISSION_APPROVED;
			auth_timeout = command_ack.timestamp + (command_ack.result_param2 * 1000000);
			return;

		case vehicle_command_ack_s::VEHICLE_RESULT_TEMPORARILY_REJECTED:
			mavlink_log_critical(mavlink_log_pub, "Arm auth: Temporarily rejected");
			state = ARM_AUTH_IDLE;
			return;

		case vehicle_command_ack_s::VEHICLE_RESULT_DENIED:
		default:
			switch (command_ack.result_param1) {
			case vehicle_command_ack_s::ARM_AUTH_DENIED_REASON_NONE:
				/* Authorizer will send reason to ground station */
				break;

			case vehicle_command_ack_s::ARM_AUTH_DENIED_REASON_INVALID_WAYPOINT:
				mavlink_log_critical(mavlink_log_pub, "Arm auth: Denied, waypoint %i have a invalid value", command_ack.result_param2);
				break;

			case vehicle_command_ack_s::ARM_AUTH_DENIED_REASON_TIMEOUT:
				mavlink_log_critical(mavlink_log_pub, "Arm auth: Denied by timeout in authorizer");
				break;

			case vehicle_command_ack_s::ARM_AUTH_DENIED_REASON_AIRSPACE_IN_USE:
				mavlink_log_critical(mavlink_log_pub, "Arm auth: Denied because airspace is in use");
				break;

			case vehicle_command_ack_s::ARM_AUTH_DENIED_REASON_BAD_WEATHER:
				mavlink_log_critical(mavlink_log_pub, "Arm auth: Denied because of bad weather");
				break;

			case vehicle_command_ack_s::ARM_AUTH_DENIED_REASON_GENERIC:
			default:
				mavlink_log_critical(mavlink_log_pub, "Arm auth: Denied");
			}

			state = ARM_AUTH_IDLE;
			return;
		}
	}

	if (now > auth_timeout) {
		mavlink_log_critical(mavlink_log_pub, "Arm auth: No response");
		state = ARM_AUTH_IDLE;
	}
}

void arm_auth_init(orb_advert_t *mav_log_pub, uint8_t *sys_id)
{
	system_id = sys_id;
	param_arm_parameters = param_find("COM_ARM_AUTH");
	command_ack_sub = orb_subscribe(ORB_ID(vehicle_command_ack));
	mavlink_log_pub = mav_log_pub;
}

enum arm_auth_methods arm_auth_method_get()
{
	return (enum arm_auth_methods) arm_parameters.struct_value.authentication_method;
}
<|endoftext|>


<commit_before>/**************************************************************************
**
** This file is part of Qt Creator
**
** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
**
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** Commercial Usage
**
** Licensees holding valid Qt Commercial licenses may use this file in
** accordance with the Qt Commercial License Agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Nokia.
**
** GNU Lesser General Public License Usage
**
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file.  Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** If you are unsure which license is appropriate for your use, please
** contact the sales department at http://qt.nokia.com/contact.
**
**************************************************************************/

#include "navigatortreeview.h"

#include "navigatorview.h"
#include "navigatortreemodel.h"
#include "navigatorwidget.h"

#include <nodeproperty.h>

#define _separator_line_color_ "#757575"

namespace QmlDesigner {

QSize IconCheckboxItemDelegate::sizeHint(const QStyleOptionViewItem &option,
                                         const QModelIndex &index) const
{
    Q_UNUSED(option);
    Q_UNUSED(index);
    return QSize(15,21);
}

void IconCheckboxItemDelegate::paint(QPainter *painter,
                                     const QStyleOptionViewItem &option, const QModelIndex &index) const
{
    painter->save();
    if (option.state & QStyle::State_Selected)
        painter->fillRect(option.rect, option.palette.highlight());
    bool isChecked= (m_TreeModel->itemFromIndex(index)->checkState() == Qt::Checked);

    if (m_TreeModel->isNodeInvisible( index ))
        painter->setOpacity(0.5);

    if (isChecked)
        painter->drawPixmap(option.rect.x()+2,option.rect.y()+1,onPix);
    else
        painter->drawPixmap(option.rect.x()+2,option.rect.y()+1,offPix);

    painter->restore();
}

void IdItemDelegate::paint(QPainter *painter,
               const QStyleOptionViewItem &option, const QModelIndex &index) const
{
    painter->save();

    if (option.state & QStyle::State_Selected)
        painter->fillRect(option.rect, option.palette.highlight());

    ModelNode node = m_TreeModel->nodeForIndex(index);

    QIcon icon=node.metaInfo().icon();
    if (icon.isNull()) icon = QIcon(":/ItemLibrary/images/default-icon.png");
    QPixmap pixmap = icon.pixmap(option.rect.width(),option.rect.height()-4);
    painter->drawPixmap(option.rect.x()+5,option.rect.y()+2,pixmap);

    QString myString = node.id();
    if (myString.isEmpty())
        myString = node.simplifiedTypeName();

    // Check text length does not exceed available space
    int extraSpace=12+pixmap.width();
    QFontMetrics metric(painter->fontMetrics());
    if (painter->fontMetrics().boundingRect(myString).width() > option.rect.width()-extraSpace)
    {
        QString origString(myString);
        int cutpoint=origString.length()/2;
        while (painter->fontMetrics().boundingRect(myString).width() > option.rect.width()-extraSpace)
        {
            cutpoint--;
            myString = origString.left(cutpoint)+QLatin1String("...")+origString.right(cutpoint);
        }
    }

    if (m_TreeModel->isNodeInvisible( index ))
        painter->setOpacity(0.5);
    painter->drawText(option.rect.bottomLeft()+QPoint(8+pixmap.width(),-4),myString);

    painter->restore();
}

void NavigatorTreeView::drawRow(QPainter *painter, const QStyleOptionViewItem &options, const QModelIndex &index) const
{
    painter->save();

    QTreeView::drawRow(painter,options,index);
    painter->setPen(QColor(_separator_line_color_));
    painter->drawLine(options.rect.bottomLeft(),options.rect.bottomRight());

    painter->restore();
}

}
<commit_msg>QmlDesigner.Navigator: Showing icons for the items' types<commit_after>/**************************************************************************
**
** This file is part of Qt Creator
**
** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
**
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** Commercial Usage
**
** Licensees holding valid Qt Commercial licenses may use this file in
** accordance with the Qt Commercial License Agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Nokia.
**
** GNU Lesser General Public License Usage
**
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file.  Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** If you are unsure which license is appropriate for your use, please
** contact the sales department at http://qt.nokia.com/contact.
**
**************************************************************************/

#include "navigatortreeview.h"

#include "navigatorview.h"
#include "navigatortreemodel.h"
#include "navigatorwidget.h"

#include <nodeproperty.h>
#include "metainfo.h"

#define _separator_line_color_ "#757575"

namespace QmlDesigner {

QSize IconCheckboxItemDelegate::sizeHint(const QStyleOptionViewItem &option,
                                         const QModelIndex &index) const
{
    Q_UNUSED(option);
    Q_UNUSED(index);
    return QSize(15,21);
}

void IconCheckboxItemDelegate::paint(QPainter *painter,
                                     const QStyleOptionViewItem &option, const QModelIndex &index) const
{
    painter->save();
    if (option.state & QStyle::State_Selected)
        painter->fillRect(option.rect, option.palette.highlight());
    bool isChecked= (m_TreeModel->itemFromIndex(index)->checkState() == Qt::Checked);

    if (m_TreeModel->isNodeInvisible( index ))
        painter->setOpacity(0.5);

    if (isChecked)
        painter->drawPixmap(option.rect.x()+2,option.rect.y()+1,onPix);
    else
        painter->drawPixmap(option.rect.x()+2,option.rect.y()+1,offPix);

    painter->restore();
}

void IdItemDelegate::paint(QPainter *painter,
               const QStyleOptionViewItem &option, const QModelIndex &index) const
{
    painter->save();

    if (option.state & QStyle::State_Selected)
        painter->fillRect(option.rect, option.palette.highlight());

    ModelNode node = m_TreeModel->nodeForIndex(index);

    QIcon icon=node.metaInfo().icon();
    if (icon.isNull())
    {
        // if node has no own icon, search for it in the itemlibrary
        QList <ItemLibraryInfo> InfoList = node.metaInfo().metaInfo().itemLibraryRepresentations(node.metaInfo());
        foreach (const ItemLibraryInfo &entry, InfoList)
        {
            if (entry.typeName()==node.metaInfo().typeName()) {
                icon = entry.icon();
                break;
            }
        }

        // if the library was also empty, use the default icon
        if (icon.isNull()) icon = QIcon(":/ItemLibrary/images/default-icon.png");
    }

    QPixmap pixmap = icon.pixmap(option.rect.width(),option.rect.height()-4);
    painter->drawPixmap(option.rect.x()+5,option.rect.y()+2,pixmap);

    QString myString = node.id();
    if (myString.isEmpty())
        myString = node.simplifiedTypeName();

    // Check text length does not exceed available space
    int extraSpace=12+pixmap.width();
    QFontMetrics metric(painter->fontMetrics());
    if (painter->fontMetrics().boundingRect(myString).width() > option.rect.width()-extraSpace)
    {
        QString origString(myString);
        int cutpoint=origString.length()/2;
        while (painter->fontMetrics().boundingRect(myString).width() > option.rect.width()-extraSpace)
        {
            cutpoint--;
            myString = origString.left(cutpoint)+QLatin1String("...")+origString.right(cutpoint);
        }
    }

    if (m_TreeModel->isNodeInvisible( index ))
        painter->setOpacity(0.5);
    painter->drawText(option.rect.bottomLeft()+QPoint(8+pixmap.width(),-4),myString);

    painter->restore();
}

void NavigatorTreeView::drawRow(QPainter *painter, const QStyleOptionViewItem &options, const QModelIndex &index) const
{
    painter->save();

    QTreeView::drawRow(painter,options,index);
    painter->setPen(QColor(_separator_line_color_));
    painter->drawLine(options.rect.bottomLeft(),options.rect.bottomRight());

    painter->restore();
}

}
<|endoftext|>


<commit_before>//! @Alan @pezy
//!
//! Exercise 11.20:
//! Rewrite the word-counting program from § 11.1 (p. 421) to use insert instead
//! of subscripting. Which program do you think is easier to write and read?
//! Explain your reasoning.
//!

#include <iostream>
#include <map>
#include <string>

using std::string;

int main()
{
    std::map<string, size_t> word_count;
    string word;
    while (std::cin >> word) {
        auto ret = word_count.insert({word, 1});
        if (!ret.second) ++ret.first->second;
    }

    //! print the content of the map.
    for (const auto& w : word_count)
        std::cout << w.first << " " << w.second
                  << ((w.second > 1) ? " times" : " time") << std::endl;
}
<commit_msg>Update ex11_20.cpp<commit_after>//! @Alan @pezy
//!
//! Exercise 11.20:
//! Rewrite the word counting program from § 11.1 (p. 421) to use insert instead
//! of subscripting. Which program do you think is easier to write and read?
//! Explain your reasoning.
//!

#include <iostream>
#include <map>
#include <string>
#include <cstddef>

using namespace std;

int main()
{
   map<string, size_t> word_count;
   string word;
   while(cin>>word)
   {
       auto ret=word_count.insert({word, 1});
       if(!ret.second)
            ++ret.first->second;
   }

   //! print the content of the map
   for(const auto &w:word_count)
   {
       cout<<w.first<<" "<<w.second<<((w.second>1)?" times":" time")<<endl;
   }
}
<|endoftext|>


<commit_before>#include "EntityViewerTreeWidget.h"
#include "EditorApplication.h"

#include <Core/GameWorld.h>
#include <Core/GameWorldLayer.h>

EntityViewerTreeWidget::EntityViewerTreeWidget(QWidget* parent) : QTreeWidget(parent)
{

}

EntityViewerTreeWidget::~EntityViewerTreeWidget()
{

}

void EntityViewerTreeWidget::OnEngineInitialize()
{
	setColumnCount(1);

	m_gameWorlds = qEditorApp->GetEngineProxy().GetGameWorlds();

	PopulateTreeData();
}

void EntityViewerTreeWidget::PopulateTreeData()
{
	setHeaderLabel("Worlds");

	for (const auto& currentWorld : m_gameWorlds)
	{
		QTreeWidgetItem* worldTreeItem = new QTreeWidgetItem(QStringList(currentWorld->GetWorldName().c_str()));

		insertTopLevelItem(0, worldTreeItem);

		for (const auto& currentLayer : currentWorld->GetWorldLayers())
		{
			QTreeWidgetItem* worldLayerTreeItem = new QTreeWidgetItem(QStringList(currentLayer.second.GetLayerName().c_str()));

			worldTreeItem->insertChild(0, worldLayerTreeItem);

			auto currentLayerEntities = currentLayer.second.GetLayerEntities();
			const int numLayerEntities = static_cast<int>(currentLayerEntities.size());

			for (int i = 0; i < numLayerEntities; ++i)
			{
				QTreeWidgetItem* entityTreeItem = new QTreeWidgetItem(QStringList(currentLayerEntities[i]->GetDebugName().c_str()));

				worldLayerTreeItem->insertChild(i, entityTreeItem);
			}
		}
	}

}
<commit_msg>Disable the world and world layers widget items from being selectable<commit_after>#include "EntityViewerTreeWidget.h"
#include "EditorApplication.h"

#include <Core/GameWorld.h>
#include <Core/GameWorldLayer.h>

EntityViewerTreeWidget::EntityViewerTreeWidget(QWidget* parent) : QTreeWidget(parent)
{

}

EntityViewerTreeWidget::~EntityViewerTreeWidget()
{

}

void EntityViewerTreeWidget::OnEngineInitialize()
{
	setColumnCount(1);

	m_gameWorlds = qEditorApp->GetEngineProxy().GetGameWorlds();

	PopulateTreeData();
}

void EntityViewerTreeWidget::PopulateTreeData()
{
	setHeaderLabel("Worlds");

	for (const auto& currentWorld : m_gameWorlds)
	{
		QTreeWidgetItem* worldTreeItem = new QTreeWidgetItem(QStringList(currentWorld->GetWorldName().c_str()));

		worldTreeItem->setFlags(worldTreeItem->flags() & ~Qt::ItemIsSelectable);

		insertTopLevelItem(0, worldTreeItem);

		for (const auto& currentLayer : currentWorld->GetWorldLayers())
		{
			QTreeWidgetItem* worldLayerTreeItem = new QTreeWidgetItem(QStringList(currentLayer.second.GetLayerName().c_str()));

			worldLayerTreeItem->setFlags(worldLayerTreeItem->flags() & ~Qt::ItemIsSelectable);

			worldTreeItem->insertChild(0, worldLayerTreeItem);

			auto currentLayerEntities = currentLayer.second.GetLayerEntities();
			const int numLayerEntities = static_cast<int>(currentLayerEntities.size());

			for (int i = 0; i < numLayerEntities; ++i)
			{
				QTreeWidgetItem* entityTreeItem = new QTreeWidgetItem(QStringList(currentLayerEntities[i]->GetDebugName().c_str()));

				worldLayerTreeItem->insertChild(i, entityTreeItem);
			}
		}
	}

}
<|endoftext|>


<commit_before>//
// This file is part of the Marble Desktop Globe.
//
// This program is free software licensed under the GNU LGPL. You can
// find a copy of this license in LICENSE.txt in the top directory of
// the source code.
//
// Copyright 2004-2007 Torsten Rahn  <tackat@kde.org>
// Copyright 2007      Inge Wallin   <ingwa@kde.org>
// Copyright 2007      Thomas Zander <zander@kde.org>
// Copyright 2010      Bastian Holst <bastianholst@gmx.de>
//

// Self
#include "CurrentLocationWidget.h"

// Marble
#include "AdjustNavigation.h"
#include "MarbleLocale.h"
#include "MarbleMap.h"
#include "MarbleModel.h"
#include "MarbleWidget.h"
#include "GeoDataCoordinates.h"
#include "PositionProviderPlugin.h"
#include "PluginManager.h"
#include "gps/PositionTracking.h"
#include "routing/RoutingManager.h"

using namespace Marble;
// Ui
#include "ui_CurrentLocationWidget.h"

namespace Marble
{

class CurrentLocationWidgetPrivate
{
 public:
    Ui::CurrentLocationWidget      m_currentLocationUi;
    MarbleWidget                  *m_widget;
    AdjustNavigation *m_adjustNavigation;

    QList<PositionProviderPlugin*> m_positionProviderPlugins;
    GeoDataCoordinates             m_currentPosition;

    MarbleLocale*                  m_locale;

    void adjustPositionTrackingStatus( PositionProviderStatus status );
    void changePositionProvider( const QString &provider );
    void centerOnCurrentLocation();
    void updateRecenterComboBox( int centerMode );
    void updateAutoZoomCheckBox( bool autoZoom );

};

CurrentLocationWidget::CurrentLocationWidget( QWidget *parent, Qt::WindowFlags f )
    : QWidget( parent, f ),
      d( new CurrentLocationWidgetPrivate() )
{
    d->m_currentLocationUi.setupUi( this );

    d->m_locale = MarbleGlobal::getInstance()->locale();

    connect( d->m_currentLocationUi.recenterComboBox, SIGNAL ( highlighted( int ) ),
            this, SLOT( setRecenterMode( int ) ) );

    connect( d->m_currentLocationUi.autoZoomCheckBox, SIGNAL( clicked( bool ) ),
             this, SLOT( setAutoZoom( bool ) ) );
}

CurrentLocationWidget::~CurrentLocationWidget()
{
    delete d;
}

void CurrentLocationWidget::setMarbleWidget( MarbleWidget *widget )
{
    d->m_widget = widget;

    d->m_adjustNavigation = new AdjustNavigation( d->m_widget, this );
    d->m_widget->map()->model()->routingManager()->setAdjustNavigation( d->m_adjustNavigation );

    PluginManager* pluginManager = d->m_widget->model()->pluginManager();
    d->m_positionProviderPlugins = pluginManager->createPositionProviderPlugins();
    foreach( const PositionProviderPlugin *plugin, d->m_positionProviderPlugins ) {
        d->m_currentLocationUi.positionTrackingComboBox->addItem( plugin->guiString() );
    }
    if ( d->m_positionProviderPlugins.isEmpty() ) {
        d->m_currentLocationUi.positionTrackingComboBox->setEnabled( false );
        QString html = "
No Position Tracking Plugin installed.
";
        d->m_currentLocationUi.locationLabel->setText( html );
        d->m_currentLocationUi.locationLabel->setEnabled ( true );
    }

    //disconnect CurrentLocation Signals
    disconnect( d->m_widget->model()->positionTracking(),
             SIGNAL( gpsLocation( GeoDataCoordinates, qreal ) ),
             this, SLOT( receiveGpsCoordinates( GeoDataCoordinates, qreal ) ) );
    disconnect( d->m_currentLocationUi.positionTrackingComboBox, SIGNAL( currentIndexChanged( QString ) ),
             this, SLOT( changePositionProvider( QString ) ) );
    disconnect( d->m_currentLocationUi.locationLabel, SIGNAL( linkActivated( QString ) ),
             this, SLOT( centerOnCurrentLocation() ) );
    disconnect( d->m_widget->model()->positionTracking(),
             SIGNAL( statusChanged( PositionProviderStatus) ),this,
             SLOT( adjustPositionTrackingStatus( PositionProviderStatus) ) );

    disconnect( d->m_adjustNavigation, SIGNAL( recenterModeChanged( int ) ),
             this, SLOT( updateRecenterComboBox( int ) ) );
    disconnect( d->m_adjustNavigation, SIGNAL( autoZoomToggled( bool ) ),
             this, SLOT( updateAutoZoomCheckBox( bool ) ) );

    //connect CurrentLoctaion signals
    connect( d->m_widget->model()->positionTracking(),
             SIGNAL( gpsLocation( GeoDataCoordinates, qreal ) ),
             this, SLOT( receiveGpsCoordinates( GeoDataCoordinates, qreal ) ) );
    connect( d->m_currentLocationUi.positionTrackingComboBox, SIGNAL( currentIndexChanged( QString ) ),
             this, SLOT( changePositionProvider( QString ) ) );
    connect( d->m_currentLocationUi.locationLabel, SIGNAL( linkActivated( QString ) ),
             this, SLOT( centerOnCurrentLocation() ) );
    connect( d->m_widget->model()->positionTracking(),
             SIGNAL( statusChanged( PositionProviderStatus) ), this,
             SLOT( adjustPositionTrackingStatus( PositionProviderStatus) ) );

    connect( d->m_adjustNavigation, SIGNAL( recenterModeChanged( int ) ),
             this, SLOT( updateRecenterComboBox( int ) ) );
    connect( d->m_adjustNavigation, SIGNAL( autoZoomToggled( bool ) ),
             this, SLOT( updateAutoZoomCheckBox( bool ) ) );
}

void CurrentLocationWidgetPrivate::adjustPositionTrackingStatus( PositionProviderStatus status )
{
    if ( status == PositionProviderStatusAvailable ) {
        m_currentLocationUi.recenterLabel->setEnabled( true );
        m_currentLocationUi.recenterComboBox->setEnabled( true );
        m_currentLocationUi.autoZoomCheckBox->setEnabled( true );
        return;
    }

    QString html = "
";

    switch ( status ) {
        case PositionProviderStatusUnavailable:
        html += QObject::tr( "Waiting for current location information..." );
            break;
        case PositionProviderStatusAcquiring:
            html += QObject::tr( "Initializing current location service..." );
            break;
        case PositionProviderStatusAvailable:
            Q_ASSERT( false );
            break;
        case PositionProviderStatusError:
            html += QObject::tr( "Error when determining current location: " );
            html += m_widget->model()->positionTracking()->error();
            break;
    }

    html += "
";
    m_currentLocationUi.locationLabel->setEnabled( true );
    m_currentLocationUi.locationLabel->setText( html );
}

void CurrentLocationWidget::receiveGpsCoordinates( const GeoDataCoordinates &position, qreal speed )
{
    d->m_currentPosition = position;
    QString unitString;
    QString speedString;
    QString distanceUnitString;
    QString distanceString;
    qreal unitSpeed = 0.0;
    qreal distance = 0.0;

    QString html = "";
    html += "
";
    html += "
Longitude	%1
";
    html += "
Latitude	%2
";
    html += "
Altitude	%3
";
    html += "
Speed	%4
";
    html += "
";
    html += "";

    switch ( d->m_locale->measureSystem() ) {
        case Metric:
        //kilometers per hour
        unitString = tr("km/h");
        unitSpeed = speed * HOUR2SEC * METER2KM;
        distanceUnitString = tr("m");
        distance = position.altitude();
        break;

        case Imperial:
        //miles per hour
        unitString = tr("m/h");
        unitSpeed = speed * HOUR2SEC * METER2KM * KM2MI;
        distanceUnitString = tr("ft");
        distance = position.altitude() * M2FT;
        break;
    }
    // TODO read this value from the incoming signal
    speedString = QLocale::system().toString( unitSpeed, 'f', 1);
    distanceString = QString( "%1 %2" ).arg( distance, 0, 'f', 1, QChar(' ') ).arg( distanceUnitString );

    html = html.arg( position.lonToString() ).arg( position.latToString() );
    html = html.arg( distanceString ).arg( speedString + ' ' + unitString );
    d->m_currentLocationUi.locationLabel->setText( html );
}

void CurrentLocationWidgetPrivate::changePositionProvider( const QString &provider )
{
    if ( provider == QObject::tr("Disabled") ) {
        m_currentLocationUi.locationLabel->setEnabled( false );
        m_widget->map()->setShowGps( false );
        m_widget->model()->positionTracking()->setPositionProviderPlugin( 0 );
        m_currentLocationUi.recenterLabel->setEnabled( false );
        m_currentLocationUi.recenterComboBox->setEnabled( false );
        m_currentLocationUi.autoZoomCheckBox->setEnabled( false );
        m_widget->update();
    }
    else {
        foreach( PositionProviderPlugin* plugin, m_positionProviderPlugins ) {
            if ( plugin->guiString() == provider ) {
                m_currentLocationUi.locationLabel->setEnabled( true );
                PositionProviderPlugin* instance = plugin->newInstance();
                PositionTracking *tracking = m_widget->model()->positionTracking();
                tracking->setPositionProviderPlugin( instance );
                m_widget->map()->setShowGps( true );
                m_widget->update();
                return;
            }
        }
    }
}

void CurrentLocationWidget::setRecenterMode( int centerMode )
{
    d->m_adjustNavigation->setRecenter( centerMode );
}

void CurrentLocationWidget::setAutoZoom( bool autoZoom )
{
    d->m_adjustNavigation->setAutoZoom( autoZoom );
}

void CurrentLocationWidgetPrivate::updateAutoZoomCheckBox( bool autoZoom )
{
    m_currentLocationUi.autoZoomCheckBox->setChecked( autoZoom );
}

void CurrentLocationWidgetPrivate::updateRecenterComboBox( int centerMode )
{
    m_currentLocationUi.recenterComboBox->setCurrentIndex( centerMode );
}

void CurrentLocationWidgetPrivate::centerOnCurrentLocation()
{
    m_widget->centerOn(m_currentPosition, true);
}

}

#include "CurrentLocationWidget.moc"
<commit_msg>use more forwarders of MarbleWidget directly<commit_after>//
// This file is part of the Marble Desktop Globe.
//
// This program is free software licensed under the GNU LGPL. You can
// find a copy of this license in LICENSE.txt in the top directory of
// the source code.
//
// Copyright 2004-2007 Torsten Rahn  <tackat@kde.org>
// Copyright 2007      Inge Wallin   <ingwa@kde.org>
// Copyright 2007      Thomas Zander <zander@kde.org>
// Copyright 2010      Bastian Holst <bastianholst@gmx.de>
//

// Self
#include "CurrentLocationWidget.h"

// Marble
#include "AdjustNavigation.h"
#include "MarbleLocale.h"
#include "MarbleModel.h"
#include "MarbleWidget.h"
#include "GeoDataCoordinates.h"
#include "PositionProviderPlugin.h"
#include "PluginManager.h"
#include "gps/PositionTracking.h"
#include "routing/RoutingManager.h"

using namespace Marble;
// Ui
#include "ui_CurrentLocationWidget.h"

namespace Marble
{

class CurrentLocationWidgetPrivate
{
 public:
    Ui::CurrentLocationWidget      m_currentLocationUi;
    MarbleWidget                  *m_widget;
    AdjustNavigation *m_adjustNavigation;

    QList<PositionProviderPlugin*> m_positionProviderPlugins;
    GeoDataCoordinates             m_currentPosition;

    MarbleLocale*                  m_locale;

    void adjustPositionTrackingStatus( PositionProviderStatus status );
    void changePositionProvider( const QString &provider );
    void centerOnCurrentLocation();
    void updateRecenterComboBox( int centerMode );
    void updateAutoZoomCheckBox( bool autoZoom );

};

CurrentLocationWidget::CurrentLocationWidget( QWidget *parent, Qt::WindowFlags f )
    : QWidget( parent, f ),
      d( new CurrentLocationWidgetPrivate() )
{
    d->m_currentLocationUi.setupUi( this );

    d->m_locale = MarbleGlobal::getInstance()->locale();

    connect( d->m_currentLocationUi.recenterComboBox, SIGNAL ( highlighted( int ) ),
            this, SLOT( setRecenterMode( int ) ) );

    connect( d->m_currentLocationUi.autoZoomCheckBox, SIGNAL( clicked( bool ) ),
             this, SLOT( setAutoZoom( bool ) ) );
}

CurrentLocationWidget::~CurrentLocationWidget()
{
    delete d;
}

void CurrentLocationWidget::setMarbleWidget( MarbleWidget *widget )
{
    d->m_widget = widget;

    d->m_adjustNavigation = new AdjustNavigation( d->m_widget, this );
    d->m_widget->model()->routingManager()->setAdjustNavigation( d->m_adjustNavigation );

    PluginManager* pluginManager = d->m_widget->model()->pluginManager();
    d->m_positionProviderPlugins = pluginManager->createPositionProviderPlugins();
    foreach( const PositionProviderPlugin *plugin, d->m_positionProviderPlugins ) {
        d->m_currentLocationUi.positionTrackingComboBox->addItem( plugin->guiString() );
    }
    if ( d->m_positionProviderPlugins.isEmpty() ) {
        d->m_currentLocationUi.positionTrackingComboBox->setEnabled( false );
        QString html = "
No Position Tracking Plugin installed.
";
        d->m_currentLocationUi.locationLabel->setText( html );
        d->m_currentLocationUi.locationLabel->setEnabled ( true );
    }

    //disconnect CurrentLocation Signals
    disconnect( d->m_widget->model()->positionTracking(),
             SIGNAL( gpsLocation( GeoDataCoordinates, qreal ) ),
             this, SLOT( receiveGpsCoordinates( GeoDataCoordinates, qreal ) ) );
    disconnect( d->m_currentLocationUi.positionTrackingComboBox, SIGNAL( currentIndexChanged( QString ) ),
             this, SLOT( changePositionProvider( QString ) ) );
    disconnect( d->m_currentLocationUi.locationLabel, SIGNAL( linkActivated( QString ) ),
             this, SLOT( centerOnCurrentLocation() ) );
    disconnect( d->m_widget->model()->positionTracking(),
             SIGNAL( statusChanged( PositionProviderStatus) ),this,
             SLOT( adjustPositionTrackingStatus( PositionProviderStatus) ) );

    disconnect( d->m_adjustNavigation, SIGNAL( recenterModeChanged( int ) ),
             this, SLOT( updateRecenterComboBox( int ) ) );
    disconnect( d->m_adjustNavigation, SIGNAL( autoZoomToggled( bool ) ),
             this, SLOT( updateAutoZoomCheckBox( bool ) ) );

    //connect CurrentLoctaion signals
    connect( d->m_widget->model()->positionTracking(),
             SIGNAL( gpsLocation( GeoDataCoordinates, qreal ) ),
             this, SLOT( receiveGpsCoordinates( GeoDataCoordinates, qreal ) ) );
    connect( d->m_currentLocationUi.positionTrackingComboBox, SIGNAL( currentIndexChanged( QString ) ),
             this, SLOT( changePositionProvider( QString ) ) );
    connect( d->m_currentLocationUi.locationLabel, SIGNAL( linkActivated( QString ) ),
             this, SLOT( centerOnCurrentLocation() ) );
    connect( d->m_widget->model()->positionTracking(),
             SIGNAL( statusChanged( PositionProviderStatus) ), this,
             SLOT( adjustPositionTrackingStatus( PositionProviderStatus) ) );

    connect( d->m_adjustNavigation, SIGNAL( recenterModeChanged( int ) ),
             this, SLOT( updateRecenterComboBox( int ) ) );
    connect( d->m_adjustNavigation, SIGNAL( autoZoomToggled( bool ) ),
             this, SLOT( updateAutoZoomCheckBox( bool ) ) );
}

void CurrentLocationWidgetPrivate::adjustPositionTrackingStatus( PositionProviderStatus status )
{
    if ( status == PositionProviderStatusAvailable ) {
        m_currentLocationUi.recenterLabel->setEnabled( true );
        m_currentLocationUi.recenterComboBox->setEnabled( true );
        m_currentLocationUi.autoZoomCheckBox->setEnabled( true );
        return;
    }

    QString html = "
";

    switch ( status ) {
        case PositionProviderStatusUnavailable:
        html += QObject::tr( "Waiting for current location information..." );
            break;
        case PositionProviderStatusAcquiring:
            html += QObject::tr( "Initializing current location service..." );
            break;
        case PositionProviderStatusAvailable:
            Q_ASSERT( false );
            break;
        case PositionProviderStatusError:
            html += QObject::tr( "Error when determining current location: " );
            html += m_widget->model()->positionTracking()->error();
            break;
    }

    html += "
";
    m_currentLocationUi.locationLabel->setEnabled( true );
    m_currentLocationUi.locationLabel->setText( html );
}

void CurrentLocationWidget::receiveGpsCoordinates( const GeoDataCoordinates &position, qreal speed )
{
    d->m_currentPosition = position;
    QString unitString;
    QString speedString;
    QString distanceUnitString;
    QString distanceString;
    qreal unitSpeed = 0.0;
    qreal distance = 0.0;

    QString html = "";
    html += "
";
    html += "
Longitude	%1
";
    html += "
Latitude	%2
";
    html += "
Altitude	%3
";
    html += "
Speed	%4
";
    html += "
";
    html += "";

    switch ( d->m_locale->measureSystem() ) {
        case Metric:
        //kilometers per hour
        unitString = tr("km/h");
        unitSpeed = speed * HOUR2SEC * METER2KM;
        distanceUnitString = tr("m");
        distance = position.altitude();
        break;

        case Imperial:
        //miles per hour
        unitString = tr("m/h");
        unitSpeed = speed * HOUR2SEC * METER2KM * KM2MI;
        distanceUnitString = tr("ft");
        distance = position.altitude() * M2FT;
        break;
    }
    // TODO read this value from the incoming signal
    speedString = QLocale::system().toString( unitSpeed, 'f', 1);
    distanceString = QString( "%1 %2" ).arg( distance, 0, 'f', 1, QChar(' ') ).arg( distanceUnitString );

    html = html.arg( position.lonToString() ).arg( position.latToString() );
    html = html.arg( distanceString ).arg( speedString + ' ' + unitString );
    d->m_currentLocationUi.locationLabel->setText( html );
}

void CurrentLocationWidgetPrivate::changePositionProvider( const QString &provider )
{
    if ( provider == QObject::tr("Disabled") ) {
        m_currentLocationUi.locationLabel->setEnabled( false );
        m_widget->setShowGps( false );
        m_widget->model()->positionTracking()->setPositionProviderPlugin( 0 );
        m_currentLocationUi.recenterLabel->setEnabled( false );
        m_currentLocationUi.recenterComboBox->setEnabled( false );
        m_currentLocationUi.autoZoomCheckBox->setEnabled( false );
        m_widget->update();
    }
    else {
        foreach( PositionProviderPlugin* plugin, m_positionProviderPlugins ) {
            if ( plugin->guiString() == provider ) {
                m_currentLocationUi.locationLabel->setEnabled( true );
                PositionProviderPlugin* instance = plugin->newInstance();
                PositionTracking *tracking = m_widget->model()->positionTracking();
                tracking->setPositionProviderPlugin( instance );
                m_widget->setShowGps( true );
                m_widget->update();
                return;
            }
        }
    }
}

void CurrentLocationWidget::setRecenterMode( int centerMode )
{
    d->m_adjustNavigation->setRecenter( centerMode );
}

void CurrentLocationWidget::setAutoZoom( bool autoZoom )
{
    d->m_adjustNavigation->setAutoZoom( autoZoom );
}

void CurrentLocationWidgetPrivate::updateAutoZoomCheckBox( bool autoZoom )
{
    m_currentLocationUi.autoZoomCheckBox->setChecked( autoZoom );
}

void CurrentLocationWidgetPrivate::updateRecenterComboBox( int centerMode )
{
    m_currentLocationUi.recenterComboBox->setCurrentIndex( centerMode );
}

void CurrentLocationWidgetPrivate::centerOnCurrentLocation()
{
    m_widget->centerOn(m_currentPosition, true);
}

}

#include "CurrentLocationWidget.moc"
<|endoftext|>


<commit_before>
#include "slicer.hpp"

bool point_match( MBCartVect pnt1, MBCartVect pnt2)
{
  bool ans = false;
  double tolerance = 1e-6;

  MBCartVect diff = pnt2-pnt1;

  if (diff.length() < tolerance) ans = true;

  return ans;
}

MBErrorCode get_sets_by_category( MBInterface *mbi, MBRange &entsets, char* category)
{

  MBErrorCode result = MB_SUCCESS;

  //get the name tag
  MBTag category_tag;
  result = mbi->tag_get_handle(CATEGORY_TAG_NAME, category_tag);
  ERR_CHECK(result);

  const void *dum = &(category[0]);

  result = mbi->get_entities_by_type_and_tag(0, MBENTITYSET, &category_tag, &dum, 1, entsets);
  ERR_CHECK(result);

  return result;

}

MBErrorCode get_surfaces( MBInterface* mbi, MBRange &surfs)
{

  MBErrorCode result = MB_SUCCESS;

  char category[CATEGORY_TAG_SIZE] = "Surface";

  result = get_sets_by_category( mbi, surfs, category);

  std::cout << "There are " << surfs.size() << " surfaces in this model." << std::endl;

  return result;

}

MBErrorCode get_all_volumes( MBInterface *mbi, MBRange &vols)
{

  MBErrorCode result = MB_SUCCESS;

  char category[CATEGORY_TAG_SIZE] = "Volume";

  result = get_sets_by_category( mbi, vols, category);

  std::cout << "There are " << vols.size() << " volumes in this model." << std::endl;

  return result;
}

MBErrorCode create_surface_intersections( MBInterface *mbi, MBRange surfs, int axis, double coord,   std::map<MBEntityHandle,std::vector<Loop> > &intersection_map)
{

  MBErrorCode result;

  MBRange::iterator i;
  for ( i = surfs.begin(); i !=surfs.end(); i++)
    {
      //get the surface triangles
      std::vector<MBEntityHandle> surf_tris;
      result = mbi->get_entities_by_type( *i, MBTRI, surf_tris);
      ERR_CHECK(result);

      //now create surface intersection
      std::vector<Loop> surf_intersections;
      result = surface_intersections( mbi, surf_tris, axis, coord, surf_intersections);
      ERR_CHECK(result);

      intersection_map[*i] = surf_intersections;
      surf_intersections.clear();

    }

  return result;
}

MBErrorCode surface_intersections(MBInterface *mbi, std::vector<MBEntityHandle> tris, int axis, double coord, std::vector<Loop> &surf_intersections)
{

  MBErrorCode result;

  std::vector<Line> intersect_lines;

  std::vector<MBEntityHandle>::iterator i;
  for ( i = tris.begin(); i != tris.end(); i++)
    {
      Line line; bool intersect;
      result = intersection( mbi, axis, coord, *i, line, intersect);
      ERR_CHECK(result);

      if(intersect) intersect_lines.push_back(line);
    }

  std::vector<Loop> all_surf_intersections;

  //now it is time to order these
  unsigned int index = 0; //index for intersection lines
  //arbitrarily start a new intersection loop
  Loop curr_loop;

  while (intersect_lines.size() != 0) {

    curr_loop.points.clear();
    curr_loop.points.push_back( intersect_lines.back().begin );
    curr_loop.points.push_back( intersect_lines.back().end );
    intersect_lines.pop_back();

    while (index < intersect_lines.size() )
      {

	Line this_line = intersect_lines[index];

	if ( point_match( this_line.begin, curr_loop.points.front() ) )
	  {
	    //insert the line into the current loop
	    curr_loop.points.insert(curr_loop.points.begin(), this_line.end );
	    //delete the current matched line from intersect_lines
	    intersect_lines.erase(intersect_lines.begin()+index);
	    index = 0;
	  }
	else if ( point_match( this_line.begin, curr_loop.points.back() ) )
	  {
	    curr_loop.points.push_back( this_line.end );
	    intersect_lines.erase(intersect_lines.begin()+index);
	    index = 0;
	  }
	else if ( point_match( this_line.end, curr_loop.points.front() ) )
	  {
	    curr_loop.points.insert(curr_loop.points.begin(), this_line.begin );
	    intersect_lines.erase(intersect_lines.begin()+index);
	    index = 0;
	  }
	else if ( point_match( this_line.end, curr_loop.points.back() ) )
	  {
	    curr_loop.points.push_back( this_line.begin );
	    intersect_lines.erase(intersect_lines.begin()+index);
	    index = 0;
	  }
	else
	  {
	    index++;
	  }
      }

    all_surf_intersections.push_back(curr_loop);

  }

  surf_intersections = all_surf_intersections;

  return result;

}

MBErrorCode intersection( MBInterface *mbi,  int axis, double coord, MBEntityHandle tri, Line &tri_intersection, bool &intersect)
{
  MBErrorCode result;
  //get the triangle vertices
  std::vector<MBEntityHandle> verts;

  result = mbi->get_adjacencies( &tri, 1, 0, false, verts);
  ERR_CHECK(result);

  MBCartVect tri_coords[3];
  result = mbi->get_coords( &(verts[0]), 1, tri_coords[0].array() );
  ERR_CHECK(result);
  result = mbi->get_coords( &(verts[1]), 1, tri_coords[1].array() );
  ERR_CHECK(result);
  result = mbi->get_coords( &(verts[2]), 1, tri_coords[2].array() );
  ERR_CHECK(result);

  triangle_plane_intersect(axis, coord, tri_coords, tri_intersection);

  intersect = tri_intersection.full;

  return result;

}

void triangle_plane_intersect( int axis, double coord, MBCartVect *coords, Line &line_out)
{

  //check to see how many triangle edges cross the coordinate
  int count = 0; int nlines = 0;
  MBCartVect p0,p1,p2,p3;

  //expecting three points for the triangle
  for( unsigned int i = 0 ; i < 3; i++)
    p3[i] = copysign(1.0, coords[i][axis] - coord);
  /*
  if (p3[0] * p3[1] < 0) count += 1;
  if (p3[1] * p3[2] < 0) count += 1;
  if (p3[2] * p3[0] < 0) count += 1;

  //count up how many line points we'll get from this triangle
  if (count ==2)
    nlines += 1;
  else if (count == 3)
    nlines += 2;
  */

  if (p3[0] * p3[1] < 0 )
    {
      p0 = coords[0];
      p1 = coords[1];
      get_intersection(p0, p1, axis, coord, line_out);
    }
  if (p3[1] * p3[2] < 0 )
    {
      p0 = coords[1];
      p1 = coords[2];
      get_intersection(p0, p1, axis, coord, line_out);
    }
  if (p3[2] * p3[0] < 0 )
    {
      p0 = coords[2];
      p1 = coords[0];
      get_intersection(p0, p1, axis, coord, line_out);
    }

}

void get_intersection( MBCartVect pnt0, MBCartVect pnt1, int axis, double coord, Line &line )
{

  MBCartVect vec = pnt1-pnt0;

  double t = (coord - pnt0[axis])/vec[axis];

  MBCartVect pnt_out = pnt0 + t*vec;

  line.add_pnt(pnt_out);

}
<commit_msg>Started the slice_faceted_model function.<commit_after>
#include "slicer.hpp"

bool point_match( MBCartVect pnt1, MBCartVect pnt2)
{
  bool ans = false;
  double tolerance = 1e-6;

  MBCartVect diff = pnt2-pnt1;

  if (diff.length() < tolerance) ans = true;

  return ans;
}

MBErrorCode get_sets_by_category( MBInterface *mbi, MBRange &entsets, char* category)
{

  MBErrorCode result = MB_SUCCESS;

  //get the name tag
  MBTag category_tag;
  result = mbi->tag_get_handle(CATEGORY_TAG_NAME, category_tag);
  ERR_CHECK(result);

  const void *dum = &(category[0]);

  result = mbi->get_entities_by_type_and_tag(0, MBENTITYSET, &category_tag, &dum, 1, entsets);
  ERR_CHECK(result);

  return result;

}

MBErrorCode get_surfaces( MBInterface* mbi, MBRange &surfs)
{

  MBErrorCode result = MB_SUCCESS;

  char category[CATEGORY_TAG_SIZE] = "Surface";

  result = get_sets_by_category( mbi, surfs, category);

  std::cout << "There are " << surfs.size() << " surfaces in this model." << std::endl;

  return result;

}

MBErrorCode get_all_volumes( MBInterface *mbi, MBRange &vols)
{

  MBErrorCode result = MB_SUCCESS;

  char category[CATEGORY_TAG_SIZE] = "Volume";

  result = get_sets_by_category( mbi, vols, category);

  std::cout << "There are " << vols.size() << " volumes in this model." << std::endl;

  return result;
}

MBErrorCode slice_faceted_model( MBInterface *mbi, std::string filename, int axis, double coord)
{
  MBErrorCode result;
  std::map<MBEntityHandle,std::vector<Loop> > intersection_map;

  result = mbi->load_file( filename.c_str() );
  ERR_CHECK(result);

  MBRange surfaces;
  result = get_surfaces( mbi, surfaces );
  ERR_CHECK(result);

  result = create_surface_intersections( mbi, surfaces, axis, coord, intersection_map);

  MBRange volumes;
  result = get_all_volumes( mbi, volumes );
  ERR_CHECK(result);

  return MB_SUCCESS;

}

MBErrorCode create_surface_intersections( MBInterface *mbi, MBRange surfs, int axis, double coord, std::map<MBEntityHandle,std::vector<Loop> > &intersection_map)
{

  MBErrorCode result;

  MBRange::iterator i;
  for ( i = surfs.begin(); i !=surfs.end(); i++)
    {
      //get the surface triangles
      std::vector<MBEntityHandle> surf_tris;
      result = mbi->get_entities_by_type( *i, MBTRI, surf_tris);
      ERR_CHECK(result);

      //now create surface intersection
      std::vector<Loop> surf_intersections;
      result = surface_intersections( mbi, surf_tris, axis, coord, surf_intersections);
      ERR_CHECK(result);

      intersection_map[*i] = surf_intersections;
      surf_intersections.clear();

    }

  return result;
}

MBErrorCode surface_intersections(MBInterface *mbi, std::vector<MBEntityHandle> tris, int axis, double coord, std::vector<Loop> &surf_intersections)
{

  MBErrorCode result;

  std::vector<Line> intersect_lines;

  std::vector<MBEntityHandle>::iterator i;
  for ( i = tris.begin(); i != tris.end(); i++)
    {
      Line line; bool intersect;
      result = intersection( mbi, axis, coord, *i, line, intersect);
      ERR_CHECK(result);

      if(intersect) intersect_lines.push_back(line);
    }

  std::vector<Loop> all_surf_intersections;

  //now it is time to order these
  unsigned int index = 0; //index for intersection lines
  //arbitrarily start a new intersection loop
  Loop curr_loop;

  while (intersect_lines.size() != 0) {

    curr_loop.points.clear();
    curr_loop.points.push_back( intersect_lines.back().begin );
    curr_loop.points.push_back( intersect_lines.back().end );
    intersect_lines.pop_back();

    while (index < intersect_lines.size() )
      {

	Line this_line = intersect_lines[index];

	if ( point_match( this_line.begin, curr_loop.points.front() ) )
	  {
	    //insert the line into the current loop
	    curr_loop.points.insert(curr_loop.points.begin(), this_line.end );
	    //delete the current matched line from intersect_lines
	    intersect_lines.erase(intersect_lines.begin()+index);
	    index = 0;
	  }
	else if ( point_match( this_line.begin, curr_loop.points.back() ) )
	  {
	    curr_loop.points.push_back( this_line.end );
	    intersect_lines.erase(intersect_lines.begin()+index);
	    index = 0;
	  }
	else if ( point_match( this_line.end, curr_loop.points.front() ) )
	  {
	    curr_loop.points.insert(curr_loop.points.begin(), this_line.begin );
	    intersect_lines.erase(intersect_lines.begin()+index);
	    index = 0;
	  }
	else if ( point_match( this_line.end, curr_loop.points.back() ) )
	  {
	    curr_loop.points.push_back( this_line.begin );
	    intersect_lines.erase(intersect_lines.begin()+index);
	    index = 0;
	  }
	else
	  {
	    index++;
	  }
      }

    all_surf_intersections.push_back(curr_loop);

  }

  surf_intersections = all_surf_intersections;

  return result;

}

MBErrorCode intersection( MBInterface *mbi,  int axis, double coord, MBEntityHandle tri, Line &tri_intersection, bool &intersect)
{
  MBErrorCode result;
  //get the triangle vertices
  std::vector<MBEntityHandle> verts;

  result = mbi->get_adjacencies( &tri, 1, 0, false, verts);
  ERR_CHECK(result);

  MBCartVect tri_coords[3];
  result = mbi->get_coords( &(verts[0]), 1, tri_coords[0].array() );
  ERR_CHECK(result);
  result = mbi->get_coords( &(verts[1]), 1, tri_coords[1].array() );
  ERR_CHECK(result);
  result = mbi->get_coords( &(verts[2]), 1, tri_coords[2].array() );
  ERR_CHECK(result);

  triangle_plane_intersect(axis, coord, tri_coords, tri_intersection);

  intersect = tri_intersection.full;

  return result;

}

void triangle_plane_intersect( int axis, double coord, MBCartVect *coords, Line &line_out)
{

  //check to see how many triangle edges cross the coordinate
  int count = 0; int nlines = 0;
  MBCartVect p0,p1,p2,p3;

  //expecting three points for the triangle
  for( unsigned int i = 0 ; i < 3; i++)
    p3[i] = copysign(1.0, coords[i][axis] - coord);
  /*
  if (p3[0] * p3[1] < 0) count += 1;
  if (p3[1] * p3[2] < 0) count += 1;
  if (p3[2] * p3[0] < 0) count += 1;

  //count up how many line points we'll get from this triangle
  if (count ==2)
    nlines += 1;
  else if (count == 3)
    nlines += 2;
  */

  if (p3[0] * p3[1] < 0 )
    {
      p0 = coords[0];
      p1 = coords[1];
      get_intersection(p0, p1, axis, coord, line_out);
    }
  if (p3[1] * p3[2] < 0 )
    {
      p0 = coords[1];
      p1 = coords[2];
      get_intersection(p0, p1, axis, coord, line_out);
    }
  if (p3[2] * p3[0] < 0 )
    {
      p0 = coords[2];
      p1 = coords[0];
      get_intersection(p0, p1, axis, coord, line_out);
    }

}

void get_intersection( MBCartVect pnt0, MBCartVect pnt1, int axis, double coord, Line &line )
{

  MBCartVect vec = pnt1-pnt0;

  double t = (coord - pnt0[axis])/vec[axis];

  MBCartVect pnt_out = pnt0 + t*vec;

  line.add_pnt(pnt_out);

}
<|endoftext|>


<commit_before>//
// Copyright (c) 2019 The nanoFramework project contributors
// Portions Copyright (c) Microsoft Corporation.  All rights reserved.
// See LICENSE file in the project root for full license information.
//
#include <ch.h>
#include <hal.h>
#include <cmsis_os.h>

#include <targetPAL.h>
#include "win_dev_gpio_native_target.h"

//volatile uint16_t lastPadValue;

#define GPIO_MAX_PIN  		256
#define TOTAL_GPIO_PORTS   ((GPIO_MAX_PIN + 15) / 16)

// Double linkedlist to hold the state of each Input pin
struct gpio_input_state : public HAL_DblLinkedNode<gpio_input_state>
{
	GPIO_PIN pinNumber;                      // Pin number
	virtual_timer_t debounceTimer;			 // debounce timer for this Pin
	GPIO_INTERRUPT_SERVICE_ROUTINE isrPtr;   // Ptr to user ISR or null
	uint32_t debounceMs;                     // debounce Millsecs, no debonce=0
	uint8_t  mode;                           // Interrupt mode
	void *   param;                          // Param to user isr call
	bool     expected;                       // Expected state for debounce handler
	bool     waitingDebounce;	    		 // True if waiting for debounce timer to complete
};

static HAL_DblLinkedList<gpio_input_state>  gpioInputList; // Double Linked list for GPIO input status
static uint16_t pinReserved[TOTAL_GPIO_PORTS];        //  reserved - 1 bit per pin

// this is an utility function to get a ChibiOS PAL IoLine from our "encoded" pin number
static ioline_t GetIoLine(int16_t pinNumber)
{
	stm32_gpio_t* port = GPIO_PORT(pinNumber);
	int16_t pad = pinNumber % 16;

	return PAL_LINE(port, pad);

}

bool  IsValidGpioPin(GPIO_PIN pinNumber)
{
	return (pinNumber <= GPIO_MAX_PIN);
}

static void debounceTimer_Callback(void* arg)
{
	gpio_input_state* pState = (gpio_input_state*)arg;
	if (pState->isrPtr)
	{
		// get current pin state
		bool actual = palReadLine(GetIoLine(pState->pinNumber));
		if (actual == pState->expected)
		{
			pState->isrPtr(pState->pinNumber, actual, pState->param);
			if (pState->mode == GPIO_INT_EDGE_BOTH)
			{
				// both edges
				pState->expected ^= 1; // update expected state
			}
		}
	}

	pState->waitingDebounce = false;
}

static void GpioEventCallback(void *arg)
{
	NATIVE_INTERRUPT_START

	chSysLockFromISR();

	gpio_input_state * pGpio = (gpio_input_state *)arg;

	// Ignore any pin changes during debounce
	if (pGpio->waitingDebounce)
	{
		chSysUnlockFromISR();
		return;
	}

	// check if there is a debounce time set
	if (pGpio->debounceMs > 0)
	{
		// Set flag we are waiting for debounce on this pin
		pGpio->waitingDebounce = true;

		// setup timer
		chVTSetI(&pGpio->debounceTimer, TIME_MS2I(pGpio->debounceMs), debounceTimer_Callback, pGpio);
	}
	else
	{
		// get IoLine from pin number
		ioline_t ioLine = GetIoLine(pGpio->pinNumber);

		pGpio->isrPtr(pGpio->pinNumber, palReadLine(ioLine), pGpio->param);
	}

	chSysUnlockFromISR();

	NATIVE_INTERRUPT_END
}

// Get pointer to gpio_input_state for Gpio pin
// return NULL if not found
gpio_input_state * GetInputState(GPIO_PIN pinNumber)
{
	gpio_input_state * ptr = gpioInputList.FirstNode();
	while (ptr->Next() != NULL)
	{
		if (ptr->pinNumber == pinNumber) return ptr;
		ptr = ptr->Next();
	}
	return NULL;
}

// Allocate a new gpio_input_state and add to end of list
// if already exist then just return current ptr
gpio_input_state * AllocateGpioInputState(GPIO_PIN pinNumber)
{
	gpio_input_state * ptr = GetInputState(pinNumber);

	if (ptr == NULL)
	{
		ptr = (gpio_input_state *)platform_malloc(sizeof(gpio_input_state));

		// sanity check
		if(ptr != NULL)
		{
			memset(ptr, 0, sizeof(gpio_input_state));
			ptr->pinNumber = pinNumber;

    		chVTObjectInit(&ptr->debounceTimer);

			gpioInputList.LinkAtBack(ptr);
		}
	}

	return ptr;
}

void UnlinkInputState(gpio_input_state * pState)
{
	chVTReset(&pState->debounceTimer);

	// disable the EXT interrupt channel
	// it's OK to do always this, no matter if it's enabled or not
	palDisableLineEvent(GetIoLine(pState->pinNumber));

	pState->Unlink();
	platform_free(pState);
}

// Delete gpio_input_state from List and tidy up ( Timer & ISR handler )
void DeleteInputState(GPIO_PIN pinNumber)
{
	gpio_input_state * pState = GetInputState(pinNumber);
	if (pState)
	{
		UnlinkInputState(pState);
	}
}

bool   CPU_GPIO_Initialize()
{
	// Initialise Double linked list for input pin states
	gpioInputList.Initialize();

	// Make sure all pins are not reserved
	memset(pinReserved, 0, sizeof(pinReserved));

	return true;
}

bool   CPU_GPIO_Uninitialize()
{
	NANOCLR_FOREACH_NODE(gpio_input_state, pGpio, gpioInputList)
	{
		UnlinkInputState(pGpio);
	}
	NANOCLR_FOREACH_NODE_END();

	return true;
}

// Set/reset reserved state of pin
bool   CPU_GPIO_ReservePin(GPIO_PIN pinNumber, bool fReserve)
{
	// Check if valid pin number
	if (!IsValidGpioPin(pinNumber)) return false;

	int port = pinNumber >> 4, bit = 1 << (pinNumber & 0x0F);
	bool ret = true;
	GLOBAL_LOCK();

	if (fReserve)
	{
		if (pinReserved[port] & bit)
		{
			ret = false; // already reserved
		}
		else
		{
			pinReserved[port] |= bit;
		}
	}
	else
	{
		pinReserved[port] &= ~bit;
	}

	GLOBAL_UNLOCK();
	return ret;
}

// Return if Pin is reserved
bool CPU_GPIO_PinIsBusy(GPIO_PIN pinNumber)
{
	// Check if valid pin number
	if (!IsValidGpioPin(pinNumber)) return false;

	int port = pinNumber >> 4, sh = pinNumber & 0x0F;
	return (pinReserved[port] >> sh) & 1;
}

// Return maximum number of pins
int32_t CPU_GPIO_GetPinCount()
{
	return GPIO_MAX_PIN;
}

// Get current state of pin
GpioPinValue CPU_GPIO_GetPinState(GPIO_PIN pin)
{
	return (GpioPinValue)palReadLine(GetIoLine(pin));
}

// Set Pin state
void CPU_GPIO_SetPinState(GPIO_PIN pin, GpioPinValue PinState)
{
	palWriteLine(GetIoLine(pin), (int)PinState);
}

bool CPU_GPIO_EnableInputPin(GPIO_PIN pinNumber, CLR_UINT64 debounceTimeMilliseconds, GPIO_INTERRUPT_SERVICE_ROUTINE pin_ISR, void* isr_Param, GPIO_INT_EDGE intEdge, GpioPinDriveMode driveMode)
{
	gpio_input_state * pState;

	// Check Input drive mode
	if (driveMode >= (int)GpioPinDriveMode_Output)
	{
		return false;
	}

	// Set as Input GPIO_INT_EDGE intEdge, GPIO_RESISTOR ResistorState
	if (!CPU_GPIO_SetDriveMode(pinNumber, driveMode))
	{
		return false;
	}
	pState = AllocateGpioInputState(pinNumber);

	// Link ISR ptr supplied and not already set up
	// CPU_GPIO_EnableInputPin could be called a 2nd time with changed parameters
	if ((pin_ISR != NULL) && (pState->isrPtr == NULL))
	{
		// there are callbacks registered and...
		// the drive mode is input so need to setup the interrupt

		// get IoLine from pin number
		ioline_t ioLine = GetIoLine(pinNumber);

		palEnableLineEvent(ioLine, PAL_EVENT_MODE_BOTH_EDGES);
		palSetLineCallback(ioLine, GpioEventCallback, pState);
	}

	pState->isrPtr = pin_ISR;
	pState->mode = intEdge;
	pState->param = (void *)isr_Param;
	pState->debounceMs = (uint32_t)(debounceTimeMilliseconds);

	switch (intEdge)
	{
		case GPIO_INT_EDGE_LOW:
		case GPIO_INT_LEVEL_LOW:
			pState->expected = PAL_LOW;
			break;

		case GPIO_INT_EDGE_HIGH:
		case GPIO_INT_LEVEL_HIGH:
			pState->expected = PAL_HIGH;
			break;

		case GPIO_INT_EDGE_BOTH:
			pState->expected = !CPU_GPIO_GetPinState(pinNumber);  // expected NOT current state
			break;

		default:
			break;
	}

	return true;
}

// Enable an output pin
//
// pinNumber    -   Gpio pin number
// InitialState -   Initial state of pin
// driveMode    -   Drive mode and resistors
// return       -   True if succesful, false invalid pin, pin not putput, invalid drive mode for ouptput
//
bool  CPU_GPIO_EnableOutputPin(GPIO_PIN pinNumber, GpioPinValue InitialState, GpioPinDriveMode driveMode)
{
	// check not an output drive mode
	if (driveMode < (int)GpioPinDriveMode_Output) return false;

	// If this is currently an input pin then clean up
	DeleteInputState(pinNumber);

	if (CPU_GPIO_SetDriveMode(pinNumber, driveMode) == false) return false;

	CPU_GPIO_SetPinState(pinNumber, InitialState);

	return true;
}

void CPU_GPIO_DisablePin(GPIO_PIN pinNumber, GpioPinDriveMode driveMode, uint32_t alternateFunction)
{
	DeleteInputState(pinNumber);

	GLOBAL_LOCK();

	CPU_GPIO_SetDriveMode(pinNumber, driveMode);

	// get IoLine from pin number
	ioline_t ioLine = GetIoLine(pinNumber);
	palSetLineMode(ioLine, PAL_MODE_ALTERNATE(alternateFunction));

	GLOBAL_UNLOCK();

	CPU_GPIO_ReservePin(pinNumber, false);
}

// Validate pin and set drive mode
// return true if ok
bool CPU_GPIO_SetDriveMode(GPIO_PIN pinNumber, GpioPinDriveMode driveMode)
{
	// get IoLine from pin number
	ioline_t ioLine = GetIoLine(pinNumber);

	switch (driveMode)
	{
		case GpioPinDriveMode_Input:
			palSetLineMode(ioLine, PAL_MODE_INPUT);
			break;

		case GpioPinDriveMode_InputPullDown:
			palSetLineMode(ioLine, PAL_MODE_INPUT_PULLDOWN);
			break;

		case GpioPinDriveMode_InputPullUp:
			palSetLineMode(ioLine, PAL_MODE_INPUT_PULLUP);
			break;

		case GpioPinDriveMode_Output:
			palSetLineMode(ioLine, PAL_MODE_OUTPUT_PUSHPULL);
			break;

		case GpioPinDriveMode_OutputOpenDrain:
			palSetLineMode(ioLine, PAL_MODE_OUTPUT_OPENDRAIN);
			break;

		default:
			// all other modes are NOT supported
			return false;
	}

	return true;
}

bool CPU_GPIO_DriveModeSupported(GPIO_PIN pinNumber, GpioPinDriveMode driveMode)
{
	(void)pinNumber;

	bool driveModeSupported = false;

	// check if the requested drive mode is support by ChibiOS config
	if ((driveMode == GpioPinDriveMode_Input) ||
		(driveMode == GpioPinDriveMode_InputPullDown) ||
		(driveMode == GpioPinDriveMode_InputPullUp) ||
		(driveMode == GpioPinDriveMode_Output) ||
		(driveMode == GpioPinDriveMode_OutputOpenDrain))
	{
		driveModeSupported = true;
	}

	return driveModeSupported;
}

uint32_t CPU_GPIO_GetPinDebounce(GPIO_PIN pinNumber)
{
	gpio_input_state * ptr = GetInputState(pinNumber);
	if (ptr)
	{
		return ptr->debounceMs;
	}

	return 0;
}

bool CPU_GPIO_SetPinDebounce(GPIO_PIN pinNumber, CLR_UINT64 debounceTimeMilliseconds)
{
	gpio_input_state * ptr = GetInputState(pinNumber);
	if (ptr)
	{
		ptr->debounceMs = (uint32_t)(debounceTimeMilliseconds);
		return true;
	}
	return false;
}
<commit_msg>Double interrupt lock with GPIO (#1612)<commit_after>//
// Copyright (c) 2019 The nanoFramework project contributors
// Portions Copyright (c) Microsoft Corporation.  All rights reserved.
// See LICENSE file in the project root for full license information.
//
#include <ch.h>
#include <hal.h>
#include <cmsis_os.h>

#include <targetPAL.h>
#include "win_dev_gpio_native_target.h"

//volatile uint16_t lastPadValue;

#define GPIO_MAX_PIN  		256
#define TOTAL_GPIO_PORTS   ((GPIO_MAX_PIN + 15) / 16)

// Double linkedlist to hold the state of each Input pin
struct gpio_input_state : public HAL_DblLinkedNode<gpio_input_state>
{
	GPIO_PIN pinNumber;                      // Pin number
	virtual_timer_t debounceTimer;			 // debounce timer for this Pin
	GPIO_INTERRUPT_SERVICE_ROUTINE isrPtr;   // Ptr to user ISR or null
	uint32_t debounceMs;                     // debounce Millsecs, no debonce=0
	uint8_t  mode;                           // Interrupt mode
	void *   param;                          // Param to user isr call
	bool     expected;                       // Expected state for debounce handler
	bool     waitingDebounce;	    		 // True if waiting for debounce timer to complete
};

static HAL_DblLinkedList<gpio_input_state>  gpioInputList; // Double Linked list for GPIO input status
static uint16_t pinReserved[TOTAL_GPIO_PORTS];        //  reserved - 1 bit per pin

// this is an utility function to get a ChibiOS PAL IoLine from our "encoded" pin number
static ioline_t GetIoLine(int16_t pinNumber)
{
	stm32_gpio_t* port = GPIO_PORT(pinNumber);
	int16_t pad = pinNumber % 16;

	return PAL_LINE(port, pad);

}

bool  IsValidGpioPin(GPIO_PIN pinNumber)
{
	return (pinNumber <= GPIO_MAX_PIN);
}

static void debounceTimer_Callback(void* arg)
{
	gpio_input_state* pState = (gpio_input_state*)arg;
	if (pState->isrPtr)
	{
		// get current pin state
		bool actual = palReadLine(GetIoLine(pState->pinNumber));
		if (actual == pState->expected)
		{
			pState->isrPtr(pState->pinNumber, actual, pState->param);
			if (pState->mode == GPIO_INT_EDGE_BOTH)
			{
				// both edges
				pState->expected ^= 1; // update expected state
			}
		}
	}

	pState->waitingDebounce = false;
}

static void GpioEventCallback(void *arg)
{
	NATIVE_INTERRUPT_START

	chSysLockFromISR();

	gpio_input_state * pGpio = (gpio_input_state *)arg;

	// Ignore any pin changes during debounce
	if (pGpio->waitingDebounce)
	{
		chSysUnlockFromISR();
		return;
	}

	// check if there is a debounce time set
	if (pGpio->debounceMs > 0)
	{
		// Set flag we are waiting for debounce on this pin
		pGpio->waitingDebounce = true;

		// setup timer
		chVTSetI(&pGpio->debounceTimer, TIME_MS2I(pGpio->debounceMs), debounceTimer_Callback, pGpio);
	}
	else
	{
		// get IoLine from pin number
		ioline_t ioLine = GetIoLine(pGpio->pinNumber);

		chSysUnlockFromISR();
		pGpio->isrPtr(pGpio->pinNumber, palReadLine(ioLine), pGpio->param);
		chSysLockFromISR();
	}

	chSysUnlockFromISR();

	NATIVE_INTERRUPT_END
}

// Get pointer to gpio_input_state for Gpio pin
// return NULL if not found
gpio_input_state * GetInputState(GPIO_PIN pinNumber)
{
	gpio_input_state * ptr = gpioInputList.FirstNode();
	while (ptr->Next() != NULL)
	{
		if (ptr->pinNumber == pinNumber) return ptr;
		ptr = ptr->Next();
	}
	return NULL;
}

// Allocate a new gpio_input_state and add to end of list
// if already exist then just return current ptr
gpio_input_state * AllocateGpioInputState(GPIO_PIN pinNumber)
{
	gpio_input_state * ptr = GetInputState(pinNumber);

	if (ptr == NULL)
	{
		ptr = (gpio_input_state *)platform_malloc(sizeof(gpio_input_state));

		// sanity check
		if(ptr != NULL)
		{
			memset(ptr, 0, sizeof(gpio_input_state));
			ptr->pinNumber = pinNumber;

    		chVTObjectInit(&ptr->debounceTimer);

			gpioInputList.LinkAtBack(ptr);
		}
	}

	return ptr;
}

void UnlinkInputState(gpio_input_state * pState)
{
	chVTReset(&pState->debounceTimer);

	// disable the EXT interrupt channel
	// it's OK to do always this, no matter if it's enabled or not
	palDisableLineEvent(GetIoLine(pState->pinNumber));

	pState->Unlink();
	platform_free(pState);
}

// Delete gpio_input_state from List and tidy up ( Timer & ISR handler )
void DeleteInputState(GPIO_PIN pinNumber)
{
	gpio_input_state * pState = GetInputState(pinNumber);
	if (pState)
	{
		UnlinkInputState(pState);
	}
}

bool   CPU_GPIO_Initialize()
{
	// Initialise Double linked list for input pin states
	gpioInputList.Initialize();

	// Make sure all pins are not reserved
	memset(pinReserved, 0, sizeof(pinReserved));

	return true;
}

bool   CPU_GPIO_Uninitialize()
{
	NANOCLR_FOREACH_NODE(gpio_input_state, pGpio, gpioInputList)
	{
		UnlinkInputState(pGpio);
	}
	NANOCLR_FOREACH_NODE_END();

	return true;
}

// Set/reset reserved state of pin
bool   CPU_GPIO_ReservePin(GPIO_PIN pinNumber, bool fReserve)
{
	// Check if valid pin number
	if (!IsValidGpioPin(pinNumber)) return false;

	int port = pinNumber >> 4, bit = 1 << (pinNumber & 0x0F);
	bool ret = true;
	GLOBAL_LOCK();

	if (fReserve)
	{
		if (pinReserved[port] & bit)
		{
			ret = false; // already reserved
		}
		else
		{
			pinReserved[port] |= bit;
		}
	}
	else
	{
		pinReserved[port] &= ~bit;
	}

	GLOBAL_UNLOCK();
	return ret;
}

// Return if Pin is reserved
bool CPU_GPIO_PinIsBusy(GPIO_PIN pinNumber)
{
	// Check if valid pin number
	if (!IsValidGpioPin(pinNumber)) return false;

	int port = pinNumber >> 4, sh = pinNumber & 0x0F;
	return (pinReserved[port] >> sh) & 1;
}

// Return maximum number of pins
int32_t CPU_GPIO_GetPinCount()
{
	return GPIO_MAX_PIN;
}

// Get current state of pin
GpioPinValue CPU_GPIO_GetPinState(GPIO_PIN pin)
{
	return (GpioPinValue)palReadLine(GetIoLine(pin));
}

// Set Pin state
void CPU_GPIO_SetPinState(GPIO_PIN pin, GpioPinValue PinState)
{
	palWriteLine(GetIoLine(pin), (int)PinState);
}

bool CPU_GPIO_EnableInputPin(GPIO_PIN pinNumber, CLR_UINT64 debounceTimeMilliseconds, GPIO_INTERRUPT_SERVICE_ROUTINE pin_ISR, void* isr_Param, GPIO_INT_EDGE intEdge, GpioPinDriveMode driveMode)
{
	gpio_input_state * pState;

	// Check Input drive mode
	if (driveMode >= (int)GpioPinDriveMode_Output)
	{
		return false;
	}

	// Set as Input GPIO_INT_EDGE intEdge, GPIO_RESISTOR ResistorState
	if (!CPU_GPIO_SetDriveMode(pinNumber, driveMode))
	{
		return false;
	}
	pState = AllocateGpioInputState(pinNumber);

	// Link ISR ptr supplied and not already set up
	// CPU_GPIO_EnableInputPin could be called a 2nd time with changed parameters
	if ((pin_ISR != NULL) && (pState->isrPtr == NULL))
	{
		// there are callbacks registered and...
		// the drive mode is input so need to setup the interrupt

		// get IoLine from pin number
		ioline_t ioLine = GetIoLine(pinNumber);

		palEnableLineEvent(ioLine, PAL_EVENT_MODE_BOTH_EDGES);
		palSetLineCallback(ioLine, GpioEventCallback, pState);
	}

	pState->isrPtr = pin_ISR;
	pState->mode = intEdge;
	pState->param = (void *)isr_Param;
	pState->debounceMs = (uint32_t)(debounceTimeMilliseconds);

	switch (intEdge)
	{
		case GPIO_INT_EDGE_LOW:
		case GPIO_INT_LEVEL_LOW:
			pState->expected = PAL_LOW;
			break;

		case GPIO_INT_EDGE_HIGH:
		case GPIO_INT_LEVEL_HIGH:
			pState->expected = PAL_HIGH;
			break;

		case GPIO_INT_EDGE_BOTH:
			pState->expected = !CPU_GPIO_GetPinState(pinNumber);  // expected NOT current state
			break;

		default:
			break;
	}

	return true;
}

// Enable an output pin
//
// pinNumber    -   Gpio pin number
// InitialState -   Initial state of pin
// driveMode    -   Drive mode and resistors
// return       -   True if succesful, false invalid pin, pin not putput, invalid drive mode for ouptput
//
bool  CPU_GPIO_EnableOutputPin(GPIO_PIN pinNumber, GpioPinValue InitialState, GpioPinDriveMode driveMode)
{
	// check not an output drive mode
	if (driveMode < (int)GpioPinDriveMode_Output) return false;

	// If this is currently an input pin then clean up
	DeleteInputState(pinNumber);

	if (CPU_GPIO_SetDriveMode(pinNumber, driveMode) == false) return false;

	CPU_GPIO_SetPinState(pinNumber, InitialState);

	return true;
}

void CPU_GPIO_DisablePin(GPIO_PIN pinNumber, GpioPinDriveMode driveMode, uint32_t alternateFunction)
{
	DeleteInputState(pinNumber);

	GLOBAL_LOCK();

	CPU_GPIO_SetDriveMode(pinNumber, driveMode);

	// get IoLine from pin number
	ioline_t ioLine = GetIoLine(pinNumber);
	palSetLineMode(ioLine, PAL_MODE_ALTERNATE(alternateFunction));

	GLOBAL_UNLOCK();

	CPU_GPIO_ReservePin(pinNumber, false);
}

// Validate pin and set drive mode
// return true if ok
bool CPU_GPIO_SetDriveMode(GPIO_PIN pinNumber, GpioPinDriveMode driveMode)
{
	// get IoLine from pin number
	ioline_t ioLine = GetIoLine(pinNumber);

	switch (driveMode)
	{
		case GpioPinDriveMode_Input:
			palSetLineMode(ioLine, PAL_MODE_INPUT);
			break;

		case GpioPinDriveMode_InputPullDown:
			palSetLineMode(ioLine, PAL_MODE_INPUT_PULLDOWN);
			break;

		case GpioPinDriveMode_InputPullUp:
			palSetLineMode(ioLine, PAL_MODE_INPUT_PULLUP);
			break;

		case GpioPinDriveMode_Output:
			palSetLineMode(ioLine, PAL_MODE_OUTPUT_PUSHPULL);
			break;

		case GpioPinDriveMode_OutputOpenDrain:
			palSetLineMode(ioLine, PAL_MODE_OUTPUT_OPENDRAIN);
			break;

		default:
			// all other modes are NOT supported
			return false;
	}

	return true;
}

bool CPU_GPIO_DriveModeSupported(GPIO_PIN pinNumber, GpioPinDriveMode driveMode)
{
	(void)pinNumber;

	bool driveModeSupported = false;

	// check if the requested drive mode is support by ChibiOS config
	if ((driveMode == GpioPinDriveMode_Input) ||
		(driveMode == GpioPinDriveMode_InputPullDown) ||
		(driveMode == GpioPinDriveMode_InputPullUp) ||
		(driveMode == GpioPinDriveMode_Output) ||
		(driveMode == GpioPinDriveMode_OutputOpenDrain))
	{
		driveModeSupported = true;
	}

	return driveModeSupported;
}

uint32_t CPU_GPIO_GetPinDebounce(GPIO_PIN pinNumber)
{
	gpio_input_state * ptr = GetInputState(pinNumber);
	if (ptr)
	{
		return ptr->debounceMs;
	}

	return 0;
}

bool CPU_GPIO_SetPinDebounce(GPIO_PIN pinNumber, CLR_UINT64 debounceTimeMilliseconds)
{
	gpio_input_state * ptr = GetInputState(pinNumber);
	if (ptr)
	{
		ptr->debounceMs = (uint32_t)(debounceTimeMilliseconds);
		return true;
	}
	return false;
}
<|endoftext|>


<commit_before>//----------------------------------------------------------------------------
/// \file  string.cpp
//----------------------------------------------------------------------------
/// \brief Implementation of general purpose functions for string processing
//----------------------------------------------------------------------------
// Copyright (c) 2010 Serge Aleynikov <saleyn@gmail.com>
// Created: 2010-05-06
//----------------------------------------------------------------------------
/*
***** BEGIN LICENSE BLOCK *****

This file is part of the utxx open-source project.

Copyright (C) 2010 Serge Aleynikov <saleyn@gmail.com>

This library 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 2.1 of the License, or (at your option) any later version.

This library 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.

You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA

***** END LICENSE BLOCK *****
*/

#include <utxx/string.hpp>

namespace utxx {

std::string to_bin_string(const char* buf, size_t sz,
                          bool hex, bool readable, bool eol)
{
    std::stringstream out;
    const char* begin = buf, *end = buf + sz;
    bool printable = readable;
    if (!hex && readable)
        for(const char* p = begin; p != end; ++p)
            if ((*p < ' ' && *p != '\n' && *p != '\r' && *p != '\t') ||
                *p == 127 || *p == 255) {
                printable = false;
                break;
            }
    out << "<<" << (printable ? "\"" : "");
    for(const char* p = begin; p != end; ++p) {
        out << (p == begin || printable ? "" : ",");
        if (printable)
            switch (*p) {
                case '\n': out << "\\n";
                case '\r': out << "\\r";
                case '\t': out << "\\t";
                default:   out << *p;
            }
        else {
            if (hex) out << std::hex;
            out << (int)*(uint8_t*)p;
        }
    }
    out << (printable ? "\"" : "") << ">>";
    if (eol) out << std::endl;
    return out.str();
}

bool wildcard_match(const char* a_input, const char* a_pattern)
{
    const char* ip = nullptr, *pp = nullptr;

    while (*a_input && *a_pattern != '*') {
        if ((*a_pattern != *a_input) && (*a_pattern != '?'))
            return false;
        a_pattern++;
        a_input++;
    }

    while (*a_input) {
        if (*a_pattern == '*') {
            if (!*++a_pattern)
                return true;
            pp = a_pattern;
            ip = a_input+1;
        } else if ((*a_pattern == *a_input) || (*a_pattern == '?')) {
            a_pattern++;
            a_input++;
        } else {
            a_pattern = pp;
            a_input = ip++;
        }
    }

    while (*a_pattern == '*') a_pattern++;

    return !*a_pattern;
}

} // namespace utxx
<commit_msg>Fix to_bin_string printing<commit_after>//----------------------------------------------------------------------------
/// \file  string.cpp
//----------------------------------------------------------------------------
/// \brief Implementation of general purpose functions for string processing
//----------------------------------------------------------------------------
// Copyright (c) 2010 Serge Aleynikov <saleyn@gmail.com>
// Created: 2010-05-06
//----------------------------------------------------------------------------
/*
***** BEGIN LICENSE BLOCK *****

This file is part of the utxx open-source project.

Copyright (C) 2010 Serge Aleynikov <saleyn@gmail.com>

This library 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 2.1 of the License, or (at your option) any later version.

This library 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.

You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA

***** END LICENSE BLOCK *****
*/

#include <utxx/string.hpp>

namespace utxx {

std::string to_bin_string(const char* buf, size_t sz,
                          bool hex, bool readable, bool eol)
{
    std::stringstream out;
    const char* begin = buf, *end = buf + sz;
    bool printable = readable;
    if (!hex && readable)
        for(const char* p = begin; p != end; ++p)
            if ((*p < ' ' && *p != '\n' && *p != '\r' && *p != '\t') ||
                *p == 127 || *p == 255) {
                printable = false;
                break;
            }
    out << "<<" << (printable ? "\"" : "");
    for(const char* p = begin; p != end; ++p) {
        out << (p == begin || printable ? "" : ",");
        if (printable)
            switch (*p) {
                case '\n': out << "\\n"; break;
                case '\r': out << "\\r"; break;
                case '\t': out << "\\t"; break;
                default:   out << *p;    break;
            }
        else {
            if (hex) out << std::hex;
            out << (int)*(uint8_t*)p;
        }
    }
    out << (printable ? "\"" : "") << ">>";
    if (eol) out << std::endl;
    return out.str();
}

bool wildcard_match(const char* a_input, const char* a_pattern)
{
    const char* ip = nullptr, *pp = nullptr;

    while (*a_input && *a_pattern != '*') {
        if ((*a_pattern != *a_input) && (*a_pattern != '?'))
            return false;
        a_pattern++;
        a_input++;
    }

    while (*a_input) {
        if (*a_pattern == '*') {
            if (!*++a_pattern)
                return true;
            pp = a_pattern;
            ip = a_input+1;
        } else if ((*a_pattern == *a_input) || (*a_pattern == '?')) {
            a_pattern++;
            a_input++;
        } else {
            a_pattern = pp;
            a_input = ip++;
        }
    }

    while (*a_pattern == '*') a_pattern++;

    return !*a_pattern;
}

} // namespace utxx
<|endoftext|>