<commit_before>/*************************************************************************/
/*  stream_peer_tcp.cpp                                                  */
/*************************************************************************/
/*                       This file is part of:                           */
/*                           GODOT ENGINE                                */
/*                      https://godotengine.org                          */
/*************************************************************************/
/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur.                 */
/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md)    */
/*                                                                       */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the       */
/* "Software"), to deal in the Software without restriction, including   */
/* without limitation the rights to use, copy, modify, merge, publish,   */
/* distribute, sublicense, and/or sell copies of the Software, and to    */
/* permit persons to whom the Software is furnished to do so, subject to */
/* the following conditions:                                             */
/*                                                                       */
/* The above copyright notice and this permission notice shall be        */
/* included in all copies or substantial portions of the Software.       */
/*                                                                       */
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,       */
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF    */
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY  */
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,  */
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE     */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.                */
/*************************************************************************/

#include "stream_peer_tcp.h"

Error StreamPeerTCP::_poll_connection() {

	ERR_FAIL_COND_V(status != STATUS_CONNECTING || !_sock.is_valid() || !_sock->is_open(), FAILED);

	Error err = _sock->connect_to_host(peer_host, peer_port);

	if (err == OK) {
		status = STATUS_CONNECTED;
		return OK;
	} else if (err == ERR_BUSY) {
		// Still trying to connect
		return OK;
	}

	status = STATUS_ERROR;
	return ERR_CONNECTION_ERROR;
}

void StreamPeerTCP::accept_socket(Ref<NetSocket> p_sock, IP_Address p_host, uint16_t p_port) {

	_sock = p_sock;
	_sock->set_blocking_enabled(false);

	status = STATUS_CONNECTING;

	peer_host = p_host;
	peer_port = p_port;
}

Error StreamPeerTCP::connect_to_host(const IP_Address &p_host, uint16_t p_port) {

	ERR_FAIL_COND_V(!_sock.is_valid(), ERR_UNAVAILABLE);
	ERR_FAIL_COND_V(_sock->is_open(), ERR_ALREADY_IN_USE);
	ERR_FAIL_COND_V(!p_host.is_valid(), ERR_INVALID_PARAMETER);

	Error err;
	IP::Type ip_type = p_host.is_ipv4() ? IP::TYPE_IPV4 : IP::TYPE_IPV6;

	err = _sock->open(NetSocket::TYPE_TCP, ip_type);
	ERR_FAIL_COND_V(err != OK, FAILED);

	_sock->set_blocking_enabled(false);

	err = _sock->connect_to_host(p_host, p_port);

	if (err != OK) {
		if (err == ERR_BUSY) {
			status = STATUS_CONNECTING;
		} else {
			ERR_PRINT("Connection to remote host failed!");
			disconnect_from_host();
			return FAILED;
		}
	}

	status = STATUS_CONNECTED;
	peer_host = p_host;
	peer_port = p_port;

	return OK;
}

Error StreamPeerTCP::write(const uint8_t *p_data, int p_bytes, int &r_sent, bool p_block) {

	ERR_FAIL_COND_V(!_sock.is_valid(), ERR_UNAVAILABLE);

	if (status == STATUS_NONE || status == STATUS_ERROR) {

		return FAILED;
	}

	if (status != STATUS_CONNECTED) {

		if (_poll_connection() != OK) {

			return FAILED;
		}

		if (status != STATUS_CONNECTED) {
			r_sent = 0;
			return OK;
		}
	}

	if (!_sock->is_open())
		return FAILED;

	Error err;
	int data_to_send = p_bytes;
	const uint8_t *offset = p_data;
	int total_sent = 0;

	while (data_to_send) {

		int sent_amount = 0;
		err = _sock->send(offset, data_to_send, sent_amount);

		if (err != OK) {

			if (err != ERR_BUSY) {
				disconnect_from_host();
				return FAILED;
			}

			if (!p_block) {
				r_sent = total_sent;
				return OK;
			}

			// Block and wait for the socket to accept more data
			err = _sock->poll(NetSocket::POLL_TYPE_OUT, -1);
			if (err != OK) {
				disconnect_from_host();
				return FAILED;
			}
		} else {

			data_to_send -= sent_amount;
			offset += sent_amount;
			total_sent += sent_amount;
		}
	}

	r_sent = total_sent;

	return OK;
}

Error StreamPeerTCP::read(uint8_t *p_buffer, int p_bytes, int &r_received, bool p_block) {

	if (!is_connected_to_host()) {

		return FAILED;
	};

	if (status == STATUS_CONNECTING) {

		if (_poll_connection() != OK) {

			return FAILED;
		};

		if (status != STATUS_CONNECTED) {
			r_received = 0;
			return OK;
		};
	};

	Error err;
	int to_read = p_bytes;
	int total_read = 0;
	r_received = 0;

	while (to_read) {

		int read = 0;
		err = _sock->recv(p_buffer + total_read, to_read, read);

		if (err != OK) {

			if (err != ERR_BUSY) {
				disconnect_from_host();
				return FAILED;
			}

			if (!p_block) {
				r_received = total_read;
				return OK;
			}

			err = _sock->poll(NetSocket::POLL_TYPE_IN, -1);

			if (err != OK) {
				disconnect_from_host();
				return FAILED;
			}

		} else if (read == 0) {

			_sock->close();
			status = STATUS_NONE;
			peer_port = 0;
			peer_host = IP_Address();
			r_received = total_read;
			return ERR_FILE_EOF;

		} else {

			to_read -= read;
			total_read += read;
		}
	}

	r_received = total_read;

	return OK;
}

void StreamPeerTCP::set_no_delay(bool p_enabled) {

	ERR_FAIL_COND(!is_connected_to_host());
	_sock->set_tcp_no_delay_enabled(p_enabled);
}

bool StreamPeerTCP::is_connected_to_host() const {

	if (status == STATUS_NONE || status == STATUS_ERROR) {

		return false;
	}

	if (status != STATUS_CONNECTED) {
		return true;
	}

	return _sock.is_valid() && _sock->is_open();
}

StreamPeerTCP::Status StreamPeerTCP::get_status() {

	if (status == STATUS_CONNECTING) {
		_poll_connection();
	}

	return status;
}

void StreamPeerTCP::disconnect_from_host() {

	if (_sock.is_valid() && _sock->is_open())
		_sock->close();

	status = STATUS_NONE;
	peer_host = IP_Address();
	peer_port = 0;
}

Error StreamPeerTCP::put_data(const uint8_t *p_data, int p_bytes) {

	int total;
	return write(p_data, p_bytes, total, true);
}

Error StreamPeerTCP::put_partial_data(const uint8_t *p_data, int p_bytes, int &r_sent) {

	return write(p_data, p_bytes, r_sent, false);
}

Error StreamPeerTCP::get_data(uint8_t *p_buffer, int p_bytes) {

	int total;
	return read(p_buffer, p_bytes, total, true);
}

Error StreamPeerTCP::get_partial_data(uint8_t *p_buffer, int p_bytes, int &r_received) {

	return read(p_buffer, p_bytes, r_received, false);
}

int StreamPeerTCP::get_available_bytes() const {

	ERR_FAIL_COND_V(!_sock.is_valid(), -1);
	return _sock->get_available_bytes();
}

IP_Address StreamPeerTCP::get_connected_host() const {

	return peer_host;
}

uint16_t StreamPeerTCP::get_connected_port() const {

	return peer_port;
}

Error StreamPeerTCP::_connect(const String &p_address, int p_port) {

	IP_Address ip;
	if (p_address.is_valid_ip_address()) {
		ip = p_address;
	} else {
		ip = IP::get_singleton()->resolve_hostname(p_address);
		if (!ip.is_valid())
			return ERR_CANT_RESOLVE;
	}

	return connect_to_host(ip, p_port);
}

void StreamPeerTCP::_bind_methods() {

	ClassDB::bind_method(D_METHOD("connect_to_host", "host", "port"), &StreamPeerTCP::_connect);
	ClassDB::bind_method(D_METHOD("is_connected_to_host"), &StreamPeerTCP::is_connected_to_host);
	ClassDB::bind_method(D_METHOD("get_status"), &StreamPeerTCP::get_status);
	ClassDB::bind_method(D_METHOD("get_connected_host"), &StreamPeerTCP::get_connected_host);
	ClassDB::bind_method(D_METHOD("get_connected_port"), &StreamPeerTCP::get_connected_port);
	ClassDB::bind_method(D_METHOD("disconnect_from_host"), &StreamPeerTCP::disconnect_from_host);
	ClassDB::bind_method(D_METHOD("set_no_delay", "enabled"), &StreamPeerTCP::set_no_delay);

	BIND_ENUM_CONSTANT(STATUS_NONE);
	BIND_ENUM_CONSTANT(STATUS_CONNECTING);
	BIND_ENUM_CONSTANT(STATUS_CONNECTED);
	BIND_ENUM_CONSTANT(STATUS_ERROR);
}

StreamPeerTCP::StreamPeerTCP() {

	_sock = Ref<NetSocket>(NetSocket::create());
	status = STATUS_NONE;
	peer_host = IP_Address();
	peer_port = 0;
}

StreamPeerTCP::~StreamPeerTCP() {

	disconnect_from_host();
}
<commit_msg>Fix TCP connecting state not set correctly<commit_after>/*************************************************************************/
/*  stream_peer_tcp.cpp                                                  */
/*************************************************************************/
/*                       This file is part of:                           */
/*                           GODOT ENGINE                                */
/*                      https://godotengine.org                          */
/*************************************************************************/
/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur.                 */
/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md)    */
/*                                                                       */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the       */
/* "Software"), to deal in the Software without restriction, including   */
/* without limitation the rights to use, copy, modify, merge, publish,   */
/* distribute, sublicense, and/or sell copies of the Software, and to    */
/* permit persons to whom the Software is furnished to do so, subject to */
/* the following conditions:                                             */
/*                                                                       */
/* The above copyright notice and this permission notice shall be        */
/* included in all copies or substantial portions of the Software.       */
/*                                                                       */
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,       */
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF    */
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY  */
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,  */
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE     */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.                */
/*************************************************************************/

#include "stream_peer_tcp.h"

Error StreamPeerTCP::_poll_connection() {

	ERR_FAIL_COND_V(status != STATUS_CONNECTING || !_sock.is_valid() || !_sock->is_open(), FAILED);

	Error err = _sock->connect_to_host(peer_host, peer_port);

	if (err == OK) {
		status = STATUS_CONNECTED;
		return OK;
	} else if (err == ERR_BUSY) {
		// Still trying to connect
		return OK;
	}

	disconnect_from_host();
	status = STATUS_ERROR;
	return ERR_CONNECTION_ERROR;
}

void StreamPeerTCP::accept_socket(Ref<NetSocket> p_sock, IP_Address p_host, uint16_t p_port) {

	_sock = p_sock;
	_sock->set_blocking_enabled(false);

	status = STATUS_CONNECTING;

	peer_host = p_host;
	peer_port = p_port;
}

Error StreamPeerTCP::connect_to_host(const IP_Address &p_host, uint16_t p_port) {

	ERR_FAIL_COND_V(!_sock.is_valid(), ERR_UNAVAILABLE);
	ERR_FAIL_COND_V(_sock->is_open(), ERR_ALREADY_IN_USE);
	ERR_FAIL_COND_V(!p_host.is_valid(), ERR_INVALID_PARAMETER);

	Error err;
	IP::Type ip_type = p_host.is_ipv4() ? IP::TYPE_IPV4 : IP::TYPE_IPV6;

	err = _sock->open(NetSocket::TYPE_TCP, ip_type);
	ERR_FAIL_COND_V(err != OK, FAILED);

	_sock->set_blocking_enabled(false);

	err = _sock->connect_to_host(p_host, p_port);

	if (err == OK) {
		status = STATUS_CONNECTED;
	} else if (err == ERR_BUSY) {
		status = STATUS_CONNECTING;
	} else {
		ERR_PRINT("Connection to remote host failed!");
		disconnect_from_host();
		return FAILED;
	}

	peer_host = p_host;
	peer_port = p_port;

	return OK;
}

Error StreamPeerTCP::write(const uint8_t *p_data, int p_bytes, int &r_sent, bool p_block) {

	ERR_FAIL_COND_V(!_sock.is_valid(), ERR_UNAVAILABLE);

	if (status == STATUS_NONE || status == STATUS_ERROR) {

		return FAILED;
	}

	if (status != STATUS_CONNECTED) {

		if (_poll_connection() != OK) {

			return FAILED;
		}

		if (status != STATUS_CONNECTED) {
			r_sent = 0;
			return OK;
		}
	}

	if (!_sock->is_open())
		return FAILED;

	Error err;
	int data_to_send = p_bytes;
	const uint8_t *offset = p_data;
	int total_sent = 0;

	while (data_to_send) {

		int sent_amount = 0;
		err = _sock->send(offset, data_to_send, sent_amount);

		if (err != OK) {

			if (err != ERR_BUSY) {
				disconnect_from_host();
				return FAILED;
			}

			if (!p_block) {
				r_sent = total_sent;
				return OK;
			}

			// Block and wait for the socket to accept more data
			err = _sock->poll(NetSocket::POLL_TYPE_OUT, -1);
			if (err != OK) {
				disconnect_from_host();
				return FAILED;
			}
		} else {

			data_to_send -= sent_amount;
			offset += sent_amount;
			total_sent += sent_amount;
		}
	}

	r_sent = total_sent;

	return OK;
}

Error StreamPeerTCP::read(uint8_t *p_buffer, int p_bytes, int &r_received, bool p_block) {

	if (!is_connected_to_host()) {

		return FAILED;
	}

	if (status == STATUS_CONNECTING) {

		if (_poll_connection() != OK) {

			return FAILED;
		}

		if (status != STATUS_CONNECTED) {
			r_received = 0;
			return OK;
		}
	}

	Error err;
	int to_read = p_bytes;
	int total_read = 0;
	r_received = 0;

	while (to_read) {

		int read = 0;
		err = _sock->recv(p_buffer + total_read, to_read, read);

		if (err != OK) {

			if (err != ERR_BUSY) {
				disconnect_from_host();
				return FAILED;
			}

			if (!p_block) {
				r_received = total_read;
				return OK;
			}

			err = _sock->poll(NetSocket::POLL_TYPE_IN, -1);

			if (err != OK) {
				disconnect_from_host();
				return FAILED;
			}

		} else if (read == 0) {

			disconnect_from_host();
			r_received = total_read;
			return ERR_FILE_EOF;

		} else {

			to_read -= read;
			total_read += read;
		}
	}

	r_received = total_read;

	return OK;
}

void StreamPeerTCP::set_no_delay(bool p_enabled) {

	ERR_FAIL_COND(!is_connected_to_host());
	_sock->set_tcp_no_delay_enabled(p_enabled);
}

bool StreamPeerTCP::is_connected_to_host() const {

	if (status == STATUS_NONE || status == STATUS_ERROR) {

		return false;
	}

	if (status != STATUS_CONNECTED) {
		return true;
	}

	return _sock.is_valid() && _sock->is_open();
}

StreamPeerTCP::Status StreamPeerTCP::get_status() {

	if (status == STATUS_CONNECTING) {
		_poll_connection();
	}

	return status;
}

void StreamPeerTCP::disconnect_from_host() {

	if (_sock.is_valid() && _sock->is_open())
		_sock->close();

	status = STATUS_NONE;
	peer_host = IP_Address();
	peer_port = 0;
}

Error StreamPeerTCP::put_data(const uint8_t *p_data, int p_bytes) {

	int total;
	return write(p_data, p_bytes, total, true);
}

Error StreamPeerTCP::put_partial_data(const uint8_t *p_data, int p_bytes, int &r_sent) {

	return write(p_data, p_bytes, r_sent, false);
}

Error StreamPeerTCP::get_data(uint8_t *p_buffer, int p_bytes) {

	int total;
	return read(p_buffer, p_bytes, total, true);
}

Error StreamPeerTCP::get_partial_data(uint8_t *p_buffer, int p_bytes, int &r_received) {

	return read(p_buffer, p_bytes, r_received, false);
}

int StreamPeerTCP::get_available_bytes() const {

	ERR_FAIL_COND_V(!_sock.is_valid(), -1);
	return _sock->get_available_bytes();
}

IP_Address StreamPeerTCP::get_connected_host() const {

	return peer_host;
}

uint16_t StreamPeerTCP::get_connected_port() const {

	return peer_port;
}

Error StreamPeerTCP::_connect(const String &p_address, int p_port) {

	IP_Address ip;
	if (p_address.is_valid_ip_address()) {
		ip = p_address;
	} else {
		ip = IP::get_singleton()->resolve_hostname(p_address);
		if (!ip.is_valid())
			return ERR_CANT_RESOLVE;
	}

	return connect_to_host(ip, p_port);
}

void StreamPeerTCP::_bind_methods() {

	ClassDB::bind_method(D_METHOD("connect_to_host", "host", "port"), &StreamPeerTCP::_connect);
	ClassDB::bind_method(D_METHOD("is_connected_to_host"), &StreamPeerTCP::is_connected_to_host);
	ClassDB::bind_method(D_METHOD("get_status"), &StreamPeerTCP::get_status);
	ClassDB::bind_method(D_METHOD("get_connected_host"), &StreamPeerTCP::get_connected_host);
	ClassDB::bind_method(D_METHOD("get_connected_port"), &StreamPeerTCP::get_connected_port);
	ClassDB::bind_method(D_METHOD("disconnect_from_host"), &StreamPeerTCP::disconnect_from_host);
	ClassDB::bind_method(D_METHOD("set_no_delay", "enabled"), &StreamPeerTCP::set_no_delay);

	BIND_ENUM_CONSTANT(STATUS_NONE);
	BIND_ENUM_CONSTANT(STATUS_CONNECTING);
	BIND_ENUM_CONSTANT(STATUS_CONNECTED);
	BIND_ENUM_CONSTANT(STATUS_ERROR);
}

StreamPeerTCP::StreamPeerTCP() {

	_sock = Ref<NetSocket>(NetSocket::create());
	status = STATUS_NONE;
	peer_host = IP_Address();
	peer_port = 0;
}

StreamPeerTCP::~StreamPeerTCP() {

	disconnect_from_host();
}
<|endoftext|>


<commit_before>#include "drakeMexUtil.h"
#include "CoordinateFrame.h"

using namespace std;

void mexFunction( int nlhs, mxArray *plhs[],int nrhs, const mxArray *prhs[] ) {
  if (nrhs==1) {
    destroyDrakeMexPointer<CoordinateFrame*>(prhs[0]);  // note: prhs[0] is the actual DrakeMexPointer object (not the CoordinateFrame object, as it would be in the non-static class methods)
    return;
  }

  if (nrhs<2) mexErrMsgIdAndTxt("Drake:CoordinateFrame:BadInputs","Usage: new(name,coordinates)");

  string name = mxGetStdString(prhs[0]);
  vector<string> coordinates = mxGetVectorOfStdStrings(prhs[1]);

  CoordinateFrame* frame = new CoordinateFrame(name,coordinates);

  plhs[0] = createDrakeMexPointer(frame,name,0,NULL,"","CoordinateFrame.");
}
<commit_msg>this will at least alert before the failure that i *think* justifies all the issues on drake006<commit_after>#include "drakeMexUtil.h"
#include "CoordinateFrame.h"

using namespace std;

void onExit(void) {
  if (mexIsLocked())
    cout << "the new.cpp mex file is being cleared from memory even though it is supposedly locked.  expect bad things to happen." << endl;
}

void mexFunction( int nlhs, mxArray *plhs[],int nrhs, const mxArray *prhs[] ) {
  mexAtExit(&onExit);

  if (nrhs==1) {
    destroyDrakeMexPointer<CoordinateFrame*>(prhs[0]);  // note: prhs[0] is the actual DrakeMexPointer object (not the CoordinateFrame object, as it would be in the non-static class methods)
    return;
  }

  if (nrhs<2) mexErrMsgIdAndTxt("Drake:CoordinateFrame:BadInputs","Usage: new(name,coordinates)");

  string name = mxGetStdString(prhs[0]);
  vector<string> coordinates = mxGetVectorOfStdStrings(prhs[1]);

  CoordinateFrame* frame = new CoordinateFrame(name,coordinates);

  plhs[0] = createDrakeMexPointer(frame,name,0,NULL,"","CoordinateFrame.");
}
<|endoftext|>


<commit_before>// -*- Mode: c++-mode; c-basic-offset: 2; indent-tabs-mode: t; tab-width: 2; -*-
//
// Copyright (C) 2004 Grzegorz Jaskiewicz <gj at pointblue.com.pl>
//
// gadurichtextformat.cpp
//
// 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., 59 Temple Place - Suite 330, Boston, MA
// 02111-1307, USA.

#include <kopetenotifyclient.h>
#include <kdebug.h>
#include <kopetemessage.h>

#include "gadurichtextformat.h"
#include "gadusession.h"

#include <qstring.h>
#include <qregexp.h>

GaduRichTextFormat::GaduRichTextFormat()
{
}

GaduRichTextFormat::~GaduRichTextFormat()
{
}

QString
GaduRichTextFormat::convertToHtml( const QString& msg, unsigned int formats, void* formatStructure)
{
	if ( formatStructure == NULL ) {
		kdDebug(14100) << "no rtf structure, plain message" << endl;
		return msg;
	}
	if ( formats == 0 ) {
		kdDebug(14100) << "rtf structure size 0 , plain message" << endl;
		return msg;
	}

	QString tmp;
	gg_msg_richtext_format *format;
	char *pointer = (char*) formatStructure;

	unsigned int i,j;
	int r, g, b;
	r = g = b = 0;
	bool opened = false;
	for ( i = 0, j = 0 ; i < formats ; ) {
		format = (gg_msg_richtext_format*) pointer;
		unsigned int position = format->position;
		char font = format->font;
		QString style;

		if ( position < j || position > msg.length() ) {
			break;
		}

		if ( font & GG_FONT_IMAGE ) {
			i += sizeof( gg_msg_richtext_image );
			pointer += sizeof( gg_msg_richtext_image );
			tmp += "[this should be a picture, not yet implemented]";
		}
		else {
			QString nb;

			nb = msg.mid( j, position - j );
			nb.replace( '\n', QString::fromLatin1( "
" ) );
			nb.replace( '\t', QString::fromLatin1( "    " ) );
			nb.replace( QRegExp( QString::fromLatin1( "\\s\\s" ) ), QString::fromLatin1( "  " ) );
			tmp += nb;

			j = position;

			// add message bit between formating
			if ( opened ) {
				tmp += formatClosingTag("span");
				opened = false;
			}
			// set font attributes
			if ( font & GG_FONT_BOLD ) {
				style += (" font-weight:bold; ");
			}
			if ( font & GG_FONT_ITALIC ) {
				style += (" font-style:italic; ");
			}
			if ( font & GG_FONT_UNDERLINE ) {
				style += (" text-decoration:underline; ");
			}
			// add color
			if ( font & GG_FONT_COLOR ) {
				pointer += sizeof( gg_msg_richtext_format );
				i += sizeof( gg_msg_richtext_format );
				gg_msg_richtext_color *color = (gg_msg_richtext_color*)( pointer );
				r = (int)color->red;
				g = (int)color->green;
				b = (int)color->blue;
			}
			style += QString(" color: rgb( %1, %2, %3 ); ").arg( r ).arg( g ).arg( b );

			tmp += formatOpeningTag( QString::fromLatin1("span"), QString::fromLatin1("style=\"%1\"").arg( style ) );
			opened = true;

		}

		// advance to next structure in row
		pointer += sizeof( gg_msg_richtext_format );
		i += sizeof( gg_msg_richtext_format );
	}

	tmp += msg.mid( j, msg.length() );
	if ( opened ) {
		tmp += formatClosingTag("span");
	}

	kdDebug(14100) << "----------\n" << tmp << "\n----------" << endl;

	return tmp;
}

QString
GaduRichTextFormat::formatOpeningTag( const QString& tag, const QString& attributes )
{
	QString res = "<" + tag;
	if(!attributes.isEmpty())
		res.append(" " + attributes);
	return res + ">";
}

QString
GaduRichTextFormat::formatClosingTag( const QString& tag )
{
	return "</" + tag + ">";
}

// the initial idea stolen from IRC plugin
KGaduMessage*
GaduRichTextFormat::convertToGaduMessage( const KopeteMessage& message )
{
	QString htmlString = message.escapedBody();

	KGaduMessage* output = new KGaduMessage;
	rtcs.blue  = rtcs.green = rtcs.red = 0;
	color = QColor();
	int position = 0;

	rtf.resize( sizeof( gg_msg_richtext) );
	output->rtf.resize(0);

	// test first if there is any HTML formating in it
	if( htmlString.find( QString::fromLatin1(" -1 ){
		QRegExp findTags( QString::fromLatin1("(.*)") );
		findTags.setMinimal( true );
		int pos = 0;
		int lastpos = 0;

		while ( pos >= 0 ){
			pos = findTags.search( htmlString );
			if ( pos > -1 ) {
				QString styleHTML = findTags.cap(1);
				QString replacement = findTags.cap(2);
				QStringList styleAttrs = QStringList::split( ';', styleHTML );
				rtfs.font = 0;

				if ( pos != lastpos ) {
					QString tmp = htmlString.mid( lastpos, pos-lastpos );
					color.setRgb( 0, 0, 0 );
					rtfs.font = GG_FONT_COLOR;
					if ( insertRtf( position ) == false ) {
						delete output;
						return NULL;
					}
					tmp = unescapeGaduMessage( tmp );
					output->message += tmp;
					position += tmp.length();
					kdDebug(14100) << "text between without encoding I reckon \"" << tmp << "\"" << endl;
				}

				lastpos = pos + replacement.length();
				kdDebug(14100) << "\nposition : " << pos << endl;
				kdDebug(14100)  <<"--------------\nstyle: "  << endl;
				for( QStringList::Iterator attrPair = styleAttrs.begin(); attrPair != styleAttrs.end(); ++attrPair ) {
					QString attribute = (*attrPair).section(':',0,0);
					QString value = (*attrPair).section(':',1);
					parseAttributes( attribute, value );
				}

				if ( insertRtf( position ) == false ) {
					delete output;
					return NULL;
				}

				QRegExp rx( QString::fromLatin1(".*" ).arg( styleHTML ) );
				rx.setMinimal( true );
				htmlString.replace( rx, replacement );
				replacement = unescapeGaduMessage( replacement );
				kdDebug(14100) << " message: \"" <<replacement <<"\"\n---------------" << endl;
				output->message += replacement;
				position += replacement.length();
			}
			else {
				QString tmp = htmlString.mid( lastpos, htmlString.length() - lastpos );
				if ( tmp.length() ) {
					color.setRgb( 0, 0, 0 );
					rtfs.font = GG_FONT_COLOR;
					if ( insertRtf( position ) == false ) {
						delete output;
						return NULL;
					}
					tmp = unescapeGaduMessage( tmp );
					output->message += tmp;
					position += tmp.length();
					kdDebug(14100) << "end left :\"" << tmp << "\"" <<endl;
				}
			}
		}
		output->rtf = rtf;
		// this is sick, but that's the way libgadu is designed
		// here I am adding network header !, should sit in libgadu IMO
		header = (gg_msg_richtext*) output->rtf.data();
		header->length = output->rtf.size() - sizeof( gg_msg_richtext );
		header->flag = 2;
	}
	else {
		output->message = message.escapedBody();
		output->message = unescapeGaduMessage( output->message );
	}

	return output;

}

void
GaduRichTextFormat::parseAttributes( QString attribute, QString value )
{
	if( attribute == QString::fromLatin1("color") ) {
		color.setNamedColor( value );
		kdDebug(14100) << "color detected, value: \"" <<  value << "\"  " << endl;
	}
	if( attribute == QString::fromLatin1("font-weight") && value == QString::fromLatin1("600") ) {
		kdDebug(14100) << " font bold " << endl;
		rtfs.font |= GG_FONT_BOLD;
	}
	if( attribute == QString::fromLatin1("text-decoration")  && value == QString::fromLatin1("underline") ) {
		kdDebug(14100) << " font underline "  << endl;
		rtfs.font |= GG_FONT_UNDERLINE ;
	}
	if( attribute == QString::fromLatin1("font-style")  && value == QString::fromLatin1("italic") ) {
		kdDebug(14100) << " font italic "  << endl;
		rtfs.font |= GG_FONT_ITALIC;
	}
}

QString
GaduRichTextFormat::unescapeGaduMessage( QString& ns )
{
	QString s;
	s = KopeteMessage::unescape( ns );
	s.replace( QString::fromAscii( "\n" ), QString::fromAscii( "\r\n" ) );
	return s;
}

bool
GaduRichTextFormat::insertRtf( uint position)
{
	if ( color.red() != rtcs.red || color.blue() != rtcs.blue || color.green() != rtcs.green ) {
		rtcs.red   = color.red();
		rtcs.green = color.green();
		rtcs.blue  = color.blue();
		rtfs.font |= GG_FONT_COLOR;
	}

	if ( rtfs.font ) {
		// append font description
		rtfs.position = position;
		uint csize = rtf.size();
		if ( rtf.resize( csize + sizeof( gg_msg_richtext_format ) ) == FALSE ) {
			kdDebug( 14100 ) << "problem allocating memory, message cannot be sent" << endl;
			return false;
		};
		memcpy( rtf.data()  + csize, &rtfs, sizeof( rtfs ) );
		// append color description, if color has changed
		if ( rtfs.font & GG_FONT_COLOR ) {
			csize = rtf.size();
			if ( rtf.resize( csize + sizeof( gg_msg_richtext_color ) ) == FALSE ) {
				kdDebug( 14100 ) << "problem allocating memory, message cannot be sent" << endl;
				return false;
			};
			memcpy( rtf.data() + csize, &rtcs, sizeof( rtcs ) );
		}
	}
	return true;
}
<commit_msg>Replace html with text correctly, we have to remember that QString::replace does multiple replaces! this used to break things up<commit_after>// -*- Mode: c++-mode; c-basic-offset: 2; indent-tabs-mode: t; tab-width: 2; -*-
//
// Copyright (C) 2004 Grzegorz Jaskiewicz <gj at pointblue.com.pl>
//
// gadurichtextformat.cpp
//
// 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., 59 Temple Place - Suite 330, Boston, MA
// 02111-1307, USA.

#include <kopetenotifyclient.h>
#include <kdebug.h>
#include <kopetemessage.h>

#include "gadurichtextformat.h"
#include "gadusession.h"

#include <qstring.h>
#include <qregexp.h>

GaduRichTextFormat::GaduRichTextFormat()
{
}

GaduRichTextFormat::~GaduRichTextFormat()
{
}

QString
GaduRichTextFormat::convertToHtml( const QString& msg, unsigned int formats, void* formatStructure)
{
	if ( formatStructure == NULL ) {
		kdDebug(14100) << "no rtf structure, plain message" << endl;
		return msg;
	}
	if ( formats == 0 ) {
		kdDebug(14100) << "rtf structure size 0 , plain message" << endl;
		return msg;
	}

	QString tmp;
	gg_msg_richtext_format *format;
	char *pointer = (char*) formatStructure;

	unsigned int i,j;
	int r, g, b;
	r = g = b = 0;
	bool opened = false;
	for ( i = 0, j = 0 ; i < formats ; ) {
		format = (gg_msg_richtext_format*) pointer;
		unsigned int position = format->position;
		char font = format->font;
		QString style;

		if ( position < j || position > msg.length() ) {
			break;
		}

		if ( font & GG_FONT_IMAGE ) {
			i += sizeof( gg_msg_richtext_image );
			pointer += sizeof( gg_msg_richtext_image );
			tmp += "[this should be a picture, not yet implemented]";
		}
		else {
			QString nb;

			nb = msg.mid( j, position - j );
			nb.replace( '\n', QString::fromLatin1( "
" ) );
			nb.replace( '\t', QString::fromLatin1( "    " ) );
			nb.replace( QRegExp( QString::fromLatin1( "\\s\\s" ) ), QString::fromLatin1( "  " ) );
			tmp += nb;

			j = position;

			// add message bit between formating
			if ( opened ) {
				tmp += formatClosingTag("span");
				opened = false;
			}
			// set font attributes
			if ( font & GG_FONT_BOLD ) {
				style += (" font-weight:bold; ");
			}
			if ( font & GG_FONT_ITALIC ) {
				style += (" font-style:italic; ");
			}
			if ( font & GG_FONT_UNDERLINE ) {
				style += (" text-decoration:underline; ");
			}
			// add color
			if ( font & GG_FONT_COLOR ) {
				pointer += sizeof( gg_msg_richtext_format );
				i += sizeof( gg_msg_richtext_format );
				gg_msg_richtext_color *color = (gg_msg_richtext_color*)( pointer );
				r = (int)color->red;
				g = (int)color->green;
				b = (int)color->blue;
			}
			style += QString(" color: rgb( %1, %2, %3 ); ").arg( r ).arg( g ).arg( b );

			tmp += formatOpeningTag( QString::fromLatin1("span"), QString::fromLatin1("style=\"%1\"").arg( style ) );
			opened = true;

		}

		// advance to next structure in row
		pointer += sizeof( gg_msg_richtext_format );
		i += sizeof( gg_msg_richtext_format );
	}

	tmp += msg.mid( j, msg.length() );
	if ( opened ) {
		tmp += formatClosingTag("span");
	}

	kdDebug(14100) << "----------\n" << tmp << "\n----------" << endl;

	return tmp;
}

QString
GaduRichTextFormat::formatOpeningTag( const QString& tag, const QString& attributes )
{
	QString res = "<" + tag;
	if(!attributes.isEmpty())
		res.append(" " + attributes);
	return res + ">";
}

QString
GaduRichTextFormat::formatClosingTag( const QString& tag )
{
	return "</" + tag + ">";
}

// the initial idea stolen from IRC plugin
KGaduMessage*
GaduRichTextFormat::convertToGaduMessage( const KopeteMessage& message )
{
	QString htmlString = message.escapedBody();
kdDebug(14100) << "-------------------------\n" << htmlString << "\n------------------"<<endl;
	KGaduMessage* output = new KGaduMessage;
	rtcs.blue  = rtcs.green = rtcs.red = 0;
	color = QColor();
	int position = 0;

	rtf.resize( sizeof( gg_msg_richtext) );
	output->rtf.resize(0);

	// test first if there is any HTML formating in it
	if( htmlString.find( QString::fromLatin1(" -1 ) {
		QRegExp findTags( QString::fromLatin1("(.*)") );
		findTags.setMinimal( true );
		int pos = 0;
		int lastpos = 0;

		while ( pos >= 0 ){
			pos = findTags.search( htmlString );

			kdDebug( 14100 ) << "pos: " << pos <<", lastpos: " << lastpos << endl;
			if ( pos != lastpos ) {
				QString tmp;
				if ( pos < 0 ) {
					tmp = htmlString.mid( lastpos );
				}
				else {
					tmp = htmlString.mid( lastpos, pos - lastpos );
				}
				if ( !tmp.isEmpty() ) {
					color.setRgb( 0, 0, 0 );
//					rtfs.font = GG_FONT_COLOR;
					if ( insertRtf( position ) == false ) {
						delete output;
						return NULL;
					}
					tmp = unescapeGaduMessage( tmp );
					output->message += tmp;
					position += tmp.length();
					kdDebug(14100) << "text between without encoding I reckon \"" << tmp << "\"" << endl;
				}
			}

			if ( pos > -1 ) {
				QString styleHTML = findTags.cap(1);
				QString replacement = findTags.cap(2);
				QStringList styleAttrs = QStringList::split( ';', styleHTML );
				rtfs.font = 0;

				lastpos = pos + replacement.length();

				kdDebug(14100) << "\nposition : " << pos << endl;
				kdDebug(14100)  <<"--------------\nstyle: "  << endl;
				for( QStringList::Iterator attrPair = styleAttrs.begin(); attrPair != styleAttrs.end(); ++attrPair ) {
					QString attribute = (*attrPair).section(':',0,0);
					QString value = (*attrPair).section(':',1);
					parseAttributes( attribute, value );
				}

				if ( insertRtf( position ) == false ) {
					delete output;
					return NULL;
				}

				QRegExp rx( QString::fromLatin1("%2" ).arg( styleHTML ).arg( replacement ) );
				rx.setMinimal( true );
				htmlString.replace( rx, replacement );
				replacement = unescapeGaduMessage( replacement );
				kdDebug(14100) << " message: \"" <<replacement <<"\"\n---------------" << endl;
				output->message += replacement;
				position += replacement.length();
			}

		}
		output->rtf = rtf;
		// this is sick, but that's the way libgadu is designed
		// here I am adding network header !, should sit in libgadu IMO
		header = (gg_msg_richtext*) output->rtf.data();
		header->length = output->rtf.size() - sizeof( gg_msg_richtext );
		header->flag = 2;
	}
	else {
		output->message = message.escapedBody();
		output->message = unescapeGaduMessage( output->message );
	}

	return output;

}

void
GaduRichTextFormat::parseAttributes( QString attribute, QString value )
{
	if( attribute == QString::fromLatin1("color") ) {
		color.setNamedColor( value );
		kdDebug(14100) << "color detected, value: \"" <<  value << "\"  " << endl;
	}
	if( attribute == QString::fromLatin1("font-weight") && value == QString::fromLatin1("600") ) {
		kdDebug(14100) << " font bold " << endl;
		rtfs.font |= GG_FONT_BOLD;
	}
	if( attribute == QString::fromLatin1("text-decoration")  && value == QString::fromLatin1("underline") ) {
		kdDebug(14100) << " font underline "  << endl;
		rtfs.font |= GG_FONT_UNDERLINE ;
	}
	if( attribute == QString::fromLatin1("font-style")  && value == QString::fromLatin1("italic") ) {
		kdDebug(14100) << " font italic "  << endl;
		rtfs.font |= GG_FONT_ITALIC;
	}
}

QString
GaduRichTextFormat::unescapeGaduMessage( QString& ns )
{
	QString s;
	s = KopeteMessage::unescape( ns );
	s.replace( QString::fromAscii( "\n" ), QString::fromAscii( "\r\n" ) );
	return s;
}

bool
GaduRichTextFormat::insertRtf( uint position)
{
	if ( color.red() != rtcs.red || color.blue() != rtcs.blue || color.green() != rtcs.green ) {
		rtcs.red   = color.red();
		rtcs.green = color.green();
		rtcs.blue  = color.blue();
		rtfs.font |= GG_FONT_COLOR;
	}

	if ( rtfs.font ) {
		// append font description
		rtfs.position = position;
		uint csize = rtf.size();
		if ( rtf.resize( csize + sizeof( gg_msg_richtext_format ) ) == FALSE ) {
			kdDebug( 14100 ) << "problem allocating memory, message cannot be sent" << endl;
			return false;
		};
		memcpy( rtf.data()  + csize, &rtfs, sizeof( rtfs ) );
		// append color description, if color has changed
		if ( rtfs.font & GG_FONT_COLOR ) {
			csize = rtf.size();
			if ( rtf.resize( csize + sizeof( gg_msg_richtext_color ) ) == FALSE ) {
				kdDebug( 14100 ) << "problem allocating memory, message cannot be sent" << endl;
				return false;
			};
			memcpy( rtf.data() + csize, &rtcs, sizeof( rtcs ) );
		}
	}
	return true;
}
<|endoftext|>


<commit_before>// Copyright (c) 2011 The LevelDB Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file. See the AUTHORS file for names of contributors.

#include <assert.h>
#include <stdio.h>
#include <stdlib.h>

#include "leveldb/cache.h"
#include "port/port.h"
#include "util/hash.h"
#include "util/mutexlock.h"

namespace leveldb {

Cache::~Cache() {
}

namespace {

// LRU cache implementation

// An entry is a variable length heap-allocated structure.  Entries
// are kept in a circular doubly linked list ordered by access time.
struct LRUHandle {
  void* value;
  void (*deleter)(const Slice&, void* value);
  LRUHandle* next_hash;
  LRUHandle* next;
  LRUHandle* prev;
  size_t charge;      // TODO(opt): Only allow uint32_t?
  size_t key_length;
  uint32_t refs;
  uint32_t hash;      // Hash of key(); used for fast sharding and comparisons
  char key_data[1];   // Beginning of key

  Slice key() const {
    // For cheaper lookups, we allow a temporary Handle object
    // to store a pointer to a key in "value".
    if (next == this) {
      return *(reinterpret_cast<Slice*>(value));
    } else {
      return Slice(key_data, key_length);
    }
  }
};

// We provide our own simple hash table since it removes a whole bunch
// of porting hacks and is also faster than some of the built-in hash
// table implementations in some of the compiler/runtime combinations
// we have tested.  E.g., readrandom speeds up by ~5% over the g++
// 4.4.3's builtin hashtable.
class HandleTable {
 public:
  HandleTable() : length_(0), elems_(0), list_(NULL) { Resize(); }
  ~HandleTable() { delete[] list_; }

  LRUHandle* Lookup(const Slice& key, uint32_t hash) {
    return *FindPointer(key, hash);
  }

  LRUHandle* Insert(LRUHandle* h) {
    LRUHandle** ptr = FindPointer(h->key(), h->hash);
    LRUHandle* old = *ptr;
    h->next_hash = (old == NULL ? NULL : old->next_hash);
    *ptr = h;
    if (old == NULL) {
      ++elems_;
      if (elems_ > length_) {
        // Since each cache entry is fairly large, we aim for a small
        // average linked list length (<= 1).
        Resize();
      }
    }
    return old;
  }

  LRUHandle* Remove(const Slice& key, uint32_t hash) {
    LRUHandle** ptr = FindPointer(key, hash);
    LRUHandle* result = *ptr;
    if (result != NULL) {
      *ptr = result->next_hash;
      --elems_;
    }
    return result;
  }

 private:
  // The table consists of an array of buckets where each bucket is
  // a linked list of cache entries that hash into the bucket.
  uint32_t length_;
  uint32_t elems_;
  LRUHandle** list_;

  // Return a pointer to slot that points to a cache entry that
  // matches key/hash.  If there is no such cache entry, return a
  // pointer to the trailing slot in the corresponding linked list.
  LRUHandle** FindPointer(const Slice& key, uint32_t hash) {
    LRUHandle** ptr = &list_[hash & (length_ - 1)];
    while (*ptr != NULL &&
           ((*ptr)->hash != hash || key != (*ptr)->key())) {
      ptr = &(*ptr)->next_hash;
    }
    return ptr;
  }

  void Resize() {
    uint32_t new_length = 4;
    while (new_length < elems_) {
      new_length *= 2;
    }
    LRUHandle** new_list = new LRUHandle*[new_length];
    memset(new_list, 0, sizeof(new_list[0]) * new_length);
    uint32_t count = 0;
    for (uint32_t i = 0; i < length_; i++) {
      LRUHandle* h = list_[i];
      while (h != NULL) {
        LRUHandle* next = h->next_hash;
        /*Slice key =*/ h->key();  // eliminate unused var warning, but allow for side-effects
        uint32_t hash = h->hash;
        LRUHandle** ptr = &new_list[hash & (new_length - 1)];
        h->next_hash = *ptr;
        *ptr = h;
        h = next;
        count++;
      }
    }
    assert(elems_ == count);
    delete[] list_;
    list_ = new_list;
    length_ = new_length;
  }
};

// A single shard of sharded cache.
class LRUCache : public Cache {
 public:
  LRUCache();
  ~LRUCache();

  static inline uint32_t HashSlice(const Slice& s) {
    return Hash(s.data(), s.size(), 0);
  }
  // Separate from constructor so caller can easily make an array of LRUCache
  void SetCapacity(size_t capacity) { capacity_ = capacity; }

  size_t GetCapacity() const {return(capacity_);};
  size_t GetUsage() const {return(usage_);};

  // Cache methods to allow direct use for single shard
  virtual Cache::Handle* Insert(const Slice& key,
                        void* value, size_t charge,
                        void (*deleter)(const Slice& key, void* value))
        {return(Insert(key, HashSlice(key), value, charge, deleter));};

  virtual Cache::Handle* Lookup(const Slice& key)
        {return(Lookup(key, HashSlice(key)));};

  virtual void Release(Cache::Handle* handle);
  virtual void Erase(const Slice& key)
       {Erase(key, HashSlice(key));};
  virtual void* Value(Handle* handle) {
    return reinterpret_cast<LRUHandle*>(handle)->value;
  }

  virtual uint64_t NewId() {
    return (++last_id_);
  }

  virtual size_t EntryOverheadSize() {return(sizeof(LRUHandle));};

  // Like Cache methods, but with an extra "hash" parameter.
  Cache::Handle* Insert(const Slice& key, uint32_t hash,
                        void* value, size_t charge,
                        void (*deleter)(const Slice& key, void* value));
  Cache::Handle* Lookup(const Slice& key, uint32_t hash);

  void Erase(const Slice& key, uint32_t hash);

    virtual void Addref(Cache::Handle* handle);

 private:
  void LRU_Remove(LRUHandle* e);
  void LRU_Append(LRUHandle* e);
  void Unref(LRUHandle* e);

  // Initialized before use.
  size_t capacity_;

  // mutex_ protects the following state.
  port::Spin spin_;
  size_t usage_;
  uint64_t last_id_;

  // Dummy head of LRU list.
  // lru.prev is newest entry, lru.next is oldest entry.
  LRUHandle lru_;

  HandleTable table_;
};

LRUCache::LRUCache()
    : usage_(0),
      last_id_(0) {
  // Make empty circular linked list
  lru_.next = &lru_;
  lru_.prev = &lru_;
}

LRUCache::~LRUCache() {
  for (LRUHandle* e = lru_.next; e != &lru_; ) {
    LRUHandle* next = e->next;

    assert(e->refs == 1);  // Error if caller has an unreleased handle
    // must allow for 2 refs given overlapped files
    //  being double ref'd intentionally ... ruins this assert :-(
//    assert(e->refs == 1 || e->refs == 2);  // Error if caller has an unreleased handle
    Unref(e);
    e = next;
  }
}

void LRUCache::Unref(LRUHandle* e) {
  assert(e->refs > 0);
  e->refs--;
  if (e->refs <= 0) {
    usage_ -= e->charge;
    (*e->deleter)(e->key(), e->value);
    free(e);
  }
}

void LRUCache::LRU_Remove(LRUHandle* e) {
  e->next->prev = e->prev;
  e->prev->next = e->next;
}

void LRUCache::LRU_Append(LRUHandle* e) {
  // Make "e" newest entry by inserting just before lru_
  e->next = &lru_;
  e->prev = lru_.prev;
  e->prev->next = e;
  e->next->prev = e;
}

Cache::Handle* LRUCache::Lookup(const Slice& key, uint32_t hash) {
  SpinLock l(&spin_);
  LRUHandle* e = table_.Lookup(key, hash);
  if (e != NULL) {
    e->refs++;
    LRU_Remove(e);
    LRU_Append(e);
  }
  return reinterpret_cast<Cache::Handle*>(e);
}

void LRUCache::Release(Cache::Handle* handle) {
  SpinLock l(&spin_);
  Unref(reinterpret_cast<LRUHandle*>(handle));
}

void LRUCache::Addref(Cache::Handle* handle) {
  SpinLock l(&spin_);
  LRUHandle * e;

  e=reinterpret_cast<LRUHandle*>(handle);
  if (NULL!=e && 1 <= e->refs)
      ++e->refs;
}

Cache::Handle* LRUCache::Insert(
    const Slice& key, uint32_t hash, void* value, size_t charge,
    void (*deleter)(const Slice& key, void* value)) {
  SpinLock l(&spin_);

  LRUHandle* e = reinterpret_cast<LRUHandle*>(
      malloc(sizeof(LRUHandle)-1 + key.size()));
  e->value = value;
  e->deleter = deleter;
  e->charge = charge;
  e->key_length = key.size();
  e->hash = hash;
  e->refs = 2;  // One from LRUCache, one for the returned handle
  memcpy(e->key_data, key.data(), key.size());
  LRU_Append(e);
  usage_ += charge;

  LRUHandle* old = table_.Insert(e);
  if (old != NULL) {
    LRU_Remove(old);
    Unref(old);
  }

  // Riak - matthewv: code added to remove old only if it was not active.
  //  Had scenarios where file cache would be largely or totally drained
  //  because an active object does NOT reduce usage_ upon delete.  So
  //  the previous while loop would basically delete everything.
  LRUHandle * next, * cursor;

  for (cursor=lru_.next; usage_ > capacity_ && cursor != &lru_; cursor=next)
  {
      // take next pointer before potentially destroying cursor
      next=cursor->next;

      // only delete cursor if it will actually destruct and
      //   return value to usage_
      if (cursor->refs <= 1)
      {
          LRU_Remove(cursor);
          table_.Remove(cursor->key(), cursor->hash);
          Unref(cursor);
      }   // if
  }   // for

  return reinterpret_cast<Cache::Handle*>(e);
}

void LRUCache::Erase(const Slice& key, uint32_t hash) {
  SpinLock l(&spin_);
  LRUHandle* e = table_.Remove(key, hash);
  if (e != NULL) {
    LRU_Remove(e);
    Unref(e);
  }
}

static const int kNumShardBits = 4;
static const int kNumShards = 1 << kNumShardBits;

class ShardedLRUCache : public Cache {
 private:
  LRUCache shard_[kNumShards];
  port::Spin id_spin_;
  uint64_t last_id_;

  static inline uint32_t HashSlice(const Slice& s) {
    return Hash(s.data(), s.size(), 0);
  }

  static uint32_t Shard(uint32_t hash) {
    return hash >> (32 - kNumShardBits);
  }

 public:
  explicit ShardedLRUCache(size_t capacity)
      : last_id_(0) {
    const size_t per_shard = (capacity + (kNumShards - 1)) / kNumShards;
    for (int s = 0; s < kNumShards; s++) {
      shard_[s].SetCapacity(per_shard);
    }
  }
  virtual ~ShardedLRUCache() { }
  virtual Handle* Insert(const Slice& key, void* value, size_t charge,
                         void (*deleter)(const Slice& key, void* value)) {
    const uint32_t hash = HashSlice(key);
    return shard_[Shard(hash)].Insert(key, hash, value, charge, deleter);
  }
  virtual Handle* Lookup(const Slice& key) {
    const uint32_t hash = HashSlice(key);
    return shard_[Shard(hash)].Lookup(key, hash);
  }
  virtual void Addref(Handle* handle) {
    LRUHandle* h = reinterpret_cast<LRUHandle*>(handle);
    shard_[Shard(h->hash)].Addref(handle);
  }
  virtual void Release(Handle* handle) {
    LRUHandle* h = reinterpret_cast<LRUHandle*>(handle);
    shard_[Shard(h->hash)].Release(handle);
  }
  virtual void Erase(const Slice& key) {
    const uint32_t hash = HashSlice(key);
    shard_[Shard(hash)].Erase(key, hash);
  }
  virtual void* Value(Handle* handle) {
    return reinterpret_cast<LRUHandle*>(handle)->value;
  }
  virtual uint64_t NewId() {
    SpinLock l(&id_spin_);
    return ++(last_id_);
  }
  virtual size_t EntryOverheadSize() {return(sizeof(LRUHandle));};
};

}  // end anonymous namespace

Cache* NewLRUCache(size_t capacity) {
  return new ShardedLRUCache(capacity);
}

Cache* NewLRUCache2(size_t capacity) {
    LRUCache * cache;
    cache=new LRUCache();
    cache->SetCapacity(capacity);
    return cache;
}

}  // namespace leveldb
<commit_msg>remove dead / commented code<commit_after>// Copyright (c) 2011 The LevelDB Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file. See the AUTHORS file for names of contributors.

#include <assert.h>
#include <stdio.h>
#include <stdlib.h>

#include "leveldb/cache.h"
#include "port/port.h"
#include "util/hash.h"
#include "util/mutexlock.h"

namespace leveldb {

Cache::~Cache() {
}

namespace {

// LRU cache implementation

// An entry is a variable length heap-allocated structure.  Entries
// are kept in a circular doubly linked list ordered by access time.
struct LRUHandle {
  void* value;
  void (*deleter)(const Slice&, void* value);
  LRUHandle* next_hash;
  LRUHandle* next;
  LRUHandle* prev;
  size_t charge;      // TODO(opt): Only allow uint32_t?
  size_t key_length;
  uint32_t refs;
  uint32_t hash;      // Hash of key(); used for fast sharding and comparisons
  char key_data[1];   // Beginning of key

  Slice key() const {
    // For cheaper lookups, we allow a temporary Handle object
    // to store a pointer to a key in "value".
    if (next == this) {
      return *(reinterpret_cast<Slice*>(value));
    } else {
      return Slice(key_data, key_length);
    }
  }
};

// We provide our own simple hash table since it removes a whole bunch
// of porting hacks and is also faster than some of the built-in hash
// table implementations in some of the compiler/runtime combinations
// we have tested.  E.g., readrandom speeds up by ~5% over the g++
// 4.4.3's builtin hashtable.
class HandleTable {
 public:
  HandleTable() : length_(0), elems_(0), list_(NULL) { Resize(); }
  ~HandleTable() { delete[] list_; }

  LRUHandle* Lookup(const Slice& key, uint32_t hash) {
    return *FindPointer(key, hash);
  }

  LRUHandle* Insert(LRUHandle* h) {
    LRUHandle** ptr = FindPointer(h->key(), h->hash);
    LRUHandle* old = *ptr;
    h->next_hash = (old == NULL ? NULL : old->next_hash);
    *ptr = h;
    if (old == NULL) {
      ++elems_;
      if (elems_ > length_) {
        // Since each cache entry is fairly large, we aim for a small
        // average linked list length (<= 1).
        Resize();
      }
    }
    return old;
  }

  LRUHandle* Remove(const Slice& key, uint32_t hash) {
    LRUHandle** ptr = FindPointer(key, hash);
    LRUHandle* result = *ptr;
    if (result != NULL) {
      *ptr = result->next_hash;
      --elems_;
    }
    return result;
  }

 private:
  // The table consists of an array of buckets where each bucket is
  // a linked list of cache entries that hash into the bucket.
  uint32_t length_;
  uint32_t elems_;
  LRUHandle** list_;

  // Return a pointer to slot that points to a cache entry that
  // matches key/hash.  If there is no such cache entry, return a
  // pointer to the trailing slot in the corresponding linked list.
  LRUHandle** FindPointer(const Slice& key, uint32_t hash) {
    LRUHandle** ptr = &list_[hash & (length_ - 1)];
    while (*ptr != NULL &&
           ((*ptr)->hash != hash || key != (*ptr)->key())) {
      ptr = &(*ptr)->next_hash;
    }
    return ptr;
  }

  void Resize() {
    uint32_t new_length = 4;
    while (new_length < elems_) {
      new_length *= 2;
    }
    LRUHandle** new_list = new LRUHandle*[new_length];
    memset(new_list, 0, sizeof(new_list[0]) * new_length);
    uint32_t count = 0;
    for (uint32_t i = 0; i < length_; i++) {
      LRUHandle* h = list_[i];
      while (h != NULL) {
        LRUHandle* next = h->next_hash;
        /*Slice key =*/ h->key();  // eliminate unused var warning, but allow for side-effects
        uint32_t hash = h->hash;
        LRUHandle** ptr = &new_list[hash & (new_length - 1)];
        h->next_hash = *ptr;
        *ptr = h;
        h = next;
        count++;
      }
    }
    assert(elems_ == count);
    delete[] list_;
    list_ = new_list;
    length_ = new_length;
  }
};

// A single shard of sharded cache.
class LRUCache : public Cache {
 public:
  LRUCache();
  ~LRUCache();

  static inline uint32_t HashSlice(const Slice& s) {
    return Hash(s.data(), s.size(), 0);
  }
  // Separate from constructor so caller can easily make an array of LRUCache
  void SetCapacity(size_t capacity) { capacity_ = capacity; }

  size_t GetCapacity() const {return(capacity_);};
  size_t GetUsage() const {return(usage_);};

  // Cache methods to allow direct use for single shard
  virtual Cache::Handle* Insert(const Slice& key,
                        void* value, size_t charge,
                        void (*deleter)(const Slice& key, void* value))
        {return(Insert(key, HashSlice(key), value, charge, deleter));};

  virtual Cache::Handle* Lookup(const Slice& key)
        {return(Lookup(key, HashSlice(key)));};

  virtual void Release(Cache::Handle* handle);
  virtual void Erase(const Slice& key)
       {Erase(key, HashSlice(key));};
  virtual void* Value(Handle* handle) {
    return reinterpret_cast<LRUHandle*>(handle)->value;
  }

  virtual uint64_t NewId() {
    return (++last_id_);
  }

  virtual size_t EntryOverheadSize() {return(sizeof(LRUHandle));};

  // Like Cache methods, but with an extra "hash" parameter.
  Cache::Handle* Insert(const Slice& key, uint32_t hash,
                        void* value, size_t charge,
                        void (*deleter)(const Slice& key, void* value));
  Cache::Handle* Lookup(const Slice& key, uint32_t hash);

  void Erase(const Slice& key, uint32_t hash);

    virtual void Addref(Cache::Handle* handle);

 private:
  void LRU_Remove(LRUHandle* e);
  void LRU_Append(LRUHandle* e);
  void Unref(LRUHandle* e);

  // Initialized before use.
  size_t capacity_;

  // mutex_ protects the following state.
  port::Spin spin_;
  size_t usage_;
  uint64_t last_id_;

  // Dummy head of LRU list.
  // lru.prev is newest entry, lru.next is oldest entry.
  LRUHandle lru_;

  HandleTable table_;
};

LRUCache::LRUCache()
    : usage_(0),
      last_id_(0) {
  // Make empty circular linked list
  lru_.next = &lru_;
  lru_.prev = &lru_;
}

LRUCache::~LRUCache() {
  for (LRUHandle* e = lru_.next; e != &lru_; ) {
    LRUHandle* next = e->next;

    assert(e->refs == 1);  // Error if caller has an unreleased handle

    Unref(e);
    e = next;
  }
}

void LRUCache::Unref(LRUHandle* e) {
  assert(e->refs > 0);
  e->refs--;
  if (e->refs <= 0) {
    usage_ -= e->charge;
    (*e->deleter)(e->key(), e->value);
    free(e);
  }
}

void LRUCache::LRU_Remove(LRUHandle* e) {
  e->next->prev = e->prev;
  e->prev->next = e->next;
}

void LRUCache::LRU_Append(LRUHandle* e) {
  // Make "e" newest entry by inserting just before lru_
  e->next = &lru_;
  e->prev = lru_.prev;
  e->prev->next = e;
  e->next->prev = e;
}

Cache::Handle* LRUCache::Lookup(const Slice& key, uint32_t hash) {
  SpinLock l(&spin_);
  LRUHandle* e = table_.Lookup(key, hash);
  if (e != NULL) {
    e->refs++;
    LRU_Remove(e);
    LRU_Append(e);
  }
  return reinterpret_cast<Cache::Handle*>(e);
}

void LRUCache::Release(Cache::Handle* handle) {
  SpinLock l(&spin_);
  Unref(reinterpret_cast<LRUHandle*>(handle));
}

void LRUCache::Addref(Cache::Handle* handle) {
  SpinLock l(&spin_);
  LRUHandle * e;

  e=reinterpret_cast<LRUHandle*>(handle);
  if (NULL!=e && 1 <= e->refs)
      ++e->refs;
}

Cache::Handle* LRUCache::Insert(
    const Slice& key, uint32_t hash, void* value, size_t charge,
    void (*deleter)(const Slice& key, void* value)) {
  SpinLock l(&spin_);

  LRUHandle* e = reinterpret_cast<LRUHandle*>(
      malloc(sizeof(LRUHandle)-1 + key.size()));
  e->value = value;
  e->deleter = deleter;
  e->charge = charge;
  e->key_length = key.size();
  e->hash = hash;
  e->refs = 2;  // One from LRUCache, one for the returned handle
  memcpy(e->key_data, key.data(), key.size());
  LRU_Append(e);
  usage_ += charge;

  LRUHandle* old = table_.Insert(e);
  if (old != NULL) {
    LRU_Remove(old);
    Unref(old);
  }

  // Riak - matthewv: code added to remove old only if it was not active.
  //  Had scenarios where file cache would be largely or totally drained
  //  because an active object does NOT reduce usage_ upon delete.  So
  //  the previous while loop would basically delete everything.
  LRUHandle * next, * cursor;

  for (cursor=lru_.next; usage_ > capacity_ && cursor != &lru_; cursor=next)
  {
      // take next pointer before potentially destroying cursor
      next=cursor->next;

      // only delete cursor if it will actually destruct and
      //   return value to usage_
      if (cursor->refs <= 1)
      {
          LRU_Remove(cursor);
          table_.Remove(cursor->key(), cursor->hash);
          Unref(cursor);
      }   // if
  }   // for

  return reinterpret_cast<Cache::Handle*>(e);
}

void LRUCache::Erase(const Slice& key, uint32_t hash) {
  SpinLock l(&spin_);
  LRUHandle* e = table_.Remove(key, hash);
  if (e != NULL) {
    LRU_Remove(e);
    Unref(e);
  }
}

static const int kNumShardBits = 4;
static const int kNumShards = 1 << kNumShardBits;

class ShardedLRUCache : public Cache {
 private:
  LRUCache shard_[kNumShards];
  port::Spin id_spin_;
  uint64_t last_id_;

  static inline uint32_t HashSlice(const Slice& s) {
    return Hash(s.data(), s.size(), 0);
  }

  static uint32_t Shard(uint32_t hash) {
    return hash >> (32 - kNumShardBits);
  }

 public:
  explicit ShardedLRUCache(size_t capacity)
      : last_id_(0) {
    const size_t per_shard = (capacity + (kNumShards - 1)) / kNumShards;
    for (int s = 0; s < kNumShards; s++) {
      shard_[s].SetCapacity(per_shard);
    }
  }
  virtual ~ShardedLRUCache() { }
  virtual Handle* Insert(const Slice& key, void* value, size_t charge,
                         void (*deleter)(const Slice& key, void* value)) {
    const uint32_t hash = HashSlice(key);
    return shard_[Shard(hash)].Insert(key, hash, value, charge, deleter);
  }
  virtual Handle* Lookup(const Slice& key) {
    const uint32_t hash = HashSlice(key);
    return shard_[Shard(hash)].Lookup(key, hash);
  }
  virtual void Addref(Handle* handle) {
    LRUHandle* h = reinterpret_cast<LRUHandle*>(handle);
    shard_[Shard(h->hash)].Addref(handle);
  }
  virtual void Release(Handle* handle) {
    LRUHandle* h = reinterpret_cast<LRUHandle*>(handle);
    shard_[Shard(h->hash)].Release(handle);
  }
  virtual void Erase(const Slice& key) {
    const uint32_t hash = HashSlice(key);
    shard_[Shard(hash)].Erase(key, hash);
  }
  virtual void* Value(Handle* handle) {
    return reinterpret_cast<LRUHandle*>(handle)->value;
  }
  virtual uint64_t NewId() {
    SpinLock l(&id_spin_);
    return ++(last_id_);
  }
  virtual size_t EntryOverheadSize() {return(sizeof(LRUHandle));};
};

}  // end anonymous namespace

Cache* NewLRUCache(size_t capacity) {
  return new ShardedLRUCache(capacity);
}

Cache* NewLRUCache2(size_t capacity) {
    LRUCache * cache;
    cache=new LRUCache();
    cache->SetCapacity(capacity);
    return cache;
}

}  // namespace leveldb
<|endoftext|>


<commit_before>#include <ros/ros.h>

#include <kobuki_control/kobuki_control.h>

//#define ODOM
#define VICON
//#define DB

#define rad2deg(x) ((x)*(180.0)/M_PI)
#define deg2rad(x) ((x)*M_PI/180.0)

ros::Publisher vel_pub;
ros::ServiceClient db_client;

double distance(double x0, double y0, double x1, double y1) {
	return sqrt((x1-x0)*(x1-x0)+(y1-y0)*(y1-y0));
}

// calculate z-axis rotation from Odom_Quaternion(z, w) -180~+180
double quaternion_to_enler(double z, double w) {
    double sqw, sqz;
    sqw = w*w;
    sqz = z*z;
    return atan2(2.0*(z*w),(-sqz + sqw));
}

//forward speed linear[m/s] rotational_speed angular[rad/s]
void pub_vel(double linear, double angular) {
    geometry_msgs::Twist vel;
    vel.linear.x = linear;
    vel.angular.z = angular;

    //publish the message
    vel_pub.publish(vel);
    return;
}

void vicon_sysCallback(const tms_msg_ss::vicon_data::ConstPtr& msg) {
	if (msg->subjectName == "kobuki") {
		//大域変数を更新
		v_pos_x = msg->translation.x;
		v_pos_y = msg->translation.y;
	    v_ori_th = rad2deg(msg->eulerXYZ[2] - deg2rad(90));
	}
}

void odomCallback(const nav_msgs::Odometry::ConstPtr& msg) {
    double z, w;//quaternion
    double temp_th;
	//大域変数を更新
	pos_x = msg->pose.pose.position.x + x;
	pos_y = msg->pose.pose.position.y + y;

	z = msg->pose.pose.orientation.z;
	w = msg->pose.pose.orientation.w;
    temp_th = quaternion_to_enler(z, w);
    ori_th = rad2deg(temp_th) + th;
}

bool control_base(double goal_dis, double goal_ang) {
	//移動前のオドメトリ情報を格納
	double ini_pos_x, ini_pos_y, ini_ori_th;
	double var_pos_x, var_pos_y, var_ori_th;//ini_th->quaternion to euler

//initialize variables
#ifdef ODOM
	ini_pos_x = pos_x;
	ini_pos_y = pos_y;
	ini_ori_th = ori_th;

	var_pos_x = pos_x;
	var_pos_y = pos_y;
	var_ori_th = ori_th;
#endif

#ifdef VICON
	ini_pos_x = v_pos_x;
	ini_pos_y = v_pos_y;
	ini_ori_th = v_ori_th;

	var_pos_x = v_pos_x;
	var_pos_y = v_pos_y;
	var_ori_th = v_ori_th;
#endif

#ifdef DB
	tms_msg_db::TmsdbGetData srv;
	srv.request.tmsdb.id = 2005; // ID : kobuki
	if (db_client.call(srv)) {
		ini_pos_x = srv.response.tmsdb[0].x;
		ini_pos_y = srv.response.tmsdb[0].y;
		ini_ori_th = srv.response.tmsdb[0].ry;

		var_pos_x = srv.response.tmsdb[0].x;
		var_pos_y = srv.response.tmsdb[0].y;
		var_ori_th = srv.response.tmsdb[0].ry;
	} else {
		ROS_ERROR("Failed to call service tms db get kobuki's data\n");
	}
#endif

	if (goal_ang > 0) { // rotate +
		while (1) {
			// 180度の境界線を越えるとき
			if (ini_ori_th+goal_ang > 180) {
				if ((ini_ori_th <= var_ori_th && var_ori_th <= 180)
						|| (-180 <= var_ori_th && var_ori_th < ini_ori_th+goal_ang-360)) {
//				if ((-180-ini_ori_th <= var_ori_th && var_ori_th < goal_ang-360)
//						|| (0 <= var_ori_th && var_ori_th <= 180-goal_ang)) {
					pub_vel(0.0, 0.523596);// 30deg/s
#ifdef ODOM
					var_ori_th = ori_th;
#endif
#ifdef VICON
					var_ori_th = v_ori_th;
#endif
#ifdef DB
					if (db_client.call(srv)) {
						var_ori_th = srv.response.tmsdb[0].ry;
					} else {
						ROS_ERROR("Failed to call service tms db get kobuki's data\n");
					}
#endif
				} else {
					pub_vel(0.0, 0.0);
					break;
				}
			} else {
				if (fabs(var_ori_th - ini_ori_th) < fabs(goal_ang)){
					// 1.+回転
					pub_vel(0.0, 0.523596); // 30deg/s
#ifdef ODOM
					var_ori_th = ori_th;
#endif
#ifdef VICON
					var_ori_th = v_ori_th;
#endif
#ifdef DB
					if (db_client.call(srv)) {
						var_ori_th = srv.response.tmsdb[0].ry;
					} else {
						ROS_ERROR("Failed to call service tms db get kobuki's data\n");
					}
#endif
				} else {
					pub_vel(0.0, 0.0);
					break;
				}
			}
		}
	} else if (goal_ang < 0) { // rotate -
		while (1) {
			// 180度の境界線を越えるとき
			if(ini_ori_th+goal_ang < -180) {
				if ((-180 <= var_ori_th && var_ori_th <= ini_ori_th)
						|| (360+goal_ang+ini_ori_th < var_ori_th && var_ori_th <= 180)) {
//				if ((-180-ini_ori_th <= var_ori_th && var_ori_th <= 0)
//						|| (goal_ang+360 < var_ori_th && var_ori_th <= 180-ini_ori_th)) {
					pub_vel(0.0, -0.523596);//-(PI/2m)/s
#ifdef ODOM
					var_ori_th = ori_th;
#endif
#ifdef VICON
					var_ori_th = v_ori_th;
#endif
#ifdef DB
					if (db_client.call(srv)) {
						var_ori_th = srv.response.tmsdb[0].ry;
					} else {
						ROS_ERROR("Failed to call service tms db get kobuki's data\n");
					}
#endif
				} else {
					pub_vel(0.0, 0.0);
					break;
				}
			} else {
				if (fabs(var_ori_th - ini_ori_th) < fabs(goal_ang)) {
					// 1.+回転
					pub_vel(0.0, -0.523596); // -(PI/2m)/s
#ifdef ODOM
					var_ori_th = ori_th;
#endif
#ifdef VICON
					var_ori_th = v_ori_th;
#endif
#ifdef DB
					if (db_client.call(srv)) {
						var_ori_th = srv.response.tmsdb[0].ry;
					} else {
						ROS_ERROR("Failed to call service tms db get kobuki's data\n");
					}
#endif
				} else {
					pub_vel(0.0, 0.0);
					break;
				}
			}
		}
	}

	if (goal_dis > 0) {
		while (1) {
	        if (distance(ini_pos_x, ini_pos_y, var_pos_x, var_pos_y) <  goal_dis) { // 単位：mm
	        	// 2.直進
				pub_vel(0.15, 0.0); // 0.25m/s
#ifdef ODOM
				var_pos_x = pos_x;
				var_pos_y = pos_y;
#endif
#ifdef VICON
				var_pos_x = v_pos_x;
				var_pos_y = v_pos_y;
#endif
#ifdef DB
						if (db_client.call(srv)) {
							var_pos_x = srv.response.tmsdb[0].x;
							var_pos_y = srv.response.tmsdb[0].y;
						} else {
							ROS_ERROR("Failed to call service tms db get kobuki's data\n");
						}
#endif
			} else {
				pub_vel(0.0, 0.0);
				break;
			}
		}
	}
	return true;
}

bool callback(tms_msg_rc::rc_robot_control::Request  &req,
		tms_msg_rc::rc_robot_control::Response &res) {
	switch (req.cmd) {
	case 0:
		///// control robot base1(絶対座標)
		// エラーチェック
		if (req.arg.size() != 3 || req.arg[0] < 0 || req.arg[0] > 8000
				|| req.arg[1] < 0 || req.arg[1] > 4500
				|| req.arg[2] < -180 || req.arg[2] > 180) {
			ROS_ERROR("case0 : An illegal arguments' type.\n");
			res.result = 0; //false
			return true;
		}

		// 現在地取得
		double current_x, current_y, current_th;
#ifdef ODOM
		current_x = pos_x;
		current_y = pos_y;
		current_th = ori_th;
		ROS_INFO("current_x=%fmm, current_y=%fmm, current_th=%fdeg\n", current_x, current_y, current_th);
#endif
#ifdef VICON
		current_x = v_pos_x;
		current_y = v_pos_y;
		current_th = v_ori_th;
		ROS_INFO("current_x=%fmm, current_y=%fmm, current_th=%fdeg\n", current_x, current_y, current_th);
#endif
#ifdef DB
		tms_msg_db::TmsdbGetData srv;
		srv.request.tmsdb.id = 2005; // ID : kobuki
		if (db_client.call(srv)) {
			current_x = srv.response.tmsdb[0].x;
			current_y = srv.response.tmsdb[0].y;
			current_th = srv.response.tmsdb[0].ry;
		} else {
			ROS_ERROR("Failed to call service tms db get kobuki's data\n");
			return false;
		}
		ROS_INFO("current_x=%fmm, current_y=%fmm, current_th=%fdeg\n", current_x, current_y, current_th);
#endif
		double goal_distance, goal_theta;
		goal_distance = distance(current_x, current_y, req.arg[0], req.arg[1]);
		goal_theta = req.arg[2] - current_th;
		if (goal_theta > 180.0) goal_theta = goal_theta - 360.0;
		else if (goal_theta < -180.0) goal_theta = goal_theta + 360.0;

		ROS_INFO("goal_dis=%fmm, goal_arg=%fdeg\n", goal_distance, goal_theta);
		if(control_base(goal_distance, goal_theta)) {
			ROS_INFO("Finish control_base");
			sleep(2);
		}
		res.result = 1;
		break;

	case 1:
		///// control robot base2(相対座標)
		// エラーチェック
		if (req.arg.size() != 2 || req.arg[0] < 0 || req.arg[0] > 9179
				|| req.arg[1] < -180 || req.arg[1] > 180) {
			ROS_ERROR("case0 : An illegal arguments' type.\n");
			res.result = 0; //false
			return true;}
		ROS_INFO("goal_dis=%fmm, goal_arg=%fdeg\n", req.arg[0], req.arg[1]);
		if (control_base((double)req.arg[0], (double)req.arg[1])) {
			ROS_INFO("Finish control_base");
			sleep(2);
		}
		res.result = 1;
		break;

	default :
		ROS_ERROR("An illegal command : %d\n", req.cmd);
		res.result = 0;
		return true;
	}
	sleep(1.0);
	return true;
}

int main(int argc, char **argv) {
	ros::init(argc, argv, "kobuki_control");
	ros::NodeHandle n;

	db_client = n.serviceClient<tms_msg_db::TmsdbGetData>("/tms_db_reader/dbreader");

#ifdef ODOM
	// kobukiの初期位置を格納
	tms_msg_db::TmsdbGetData srv;
	srv.request.tmsdb.id = 2005; // ID : kobuki
	if (db_client.call(srv)) {
		x = srv.response.tmsdb[0].x;
		y = srv.response.tmsdb[0].y;
		th = srv.response.tmsdb[0].ry;
	} else {
		ROS_ERROR("Failed to call service tms db get kobuki's data\n");
		return false;
	}
	ROS_INFO("kobuki's initial pos = [%fmm, %fmm, %fdeg]\n", x, y, th);
#endif

	ros::ServiceServer service = n.advertiseService("kobuki_control", callback);
	ROS_INFO("Ready to activate kobuki_control_node\n");

	ros::AsyncSpinner spinner(3);
	spinner.start();

	//現在地取得方法(vicon or odom)
	ros::Subscriber vicon_sub = n.subscribe("vicon_stream/output", 10, vicon_sysCallback);
	ros::Subscriber odom_sub = n.subscribe("odom", 10, odomCallback);//Odometry情報取得

	vel_pub = n.advertise<geometry_msgs::Twist>("mobile_base/commands/velocity",1); //kobukiに速度を送る
	ros::waitForShutdown();

	return 0;
}
<commit_msg>fix a bug<commit_after>#include <ros/ros.h>

#include <kobuki_control/kobuki_control.h>

//#define ODOM
#define VICON
//#define DB

#define rad2deg(x) ((x)*(180.0)/M_PI)
#define deg2rad(x) ((x)*M_PI/180.0)

ros::Publisher vel_pub;
ros::ServiceClient db_client;

double distance(double x0, double y0, double x1, double y1) {
	return sqrt((x1-x0)*(x1-x0)+(y1-y0)*(y1-y0));
}

// 小数第N位切り捨て
double floor2(double input, int N)
{
    double output;

    output = input * pow(10.0, (N-1));
    output = (double)(int)(output);

    return output * pow(10.0, 1-N);
}

// calculate z-axis rotation from Odom_Quaternion(z, w) -180~+180
double quaternion_to_enler(double z, double w) {
    double sqw, sqz;
    sqw = w*w;
    sqz = z*z;
    return atan2(2.0*(z*w),(-sqz + sqw));
}

//forward speed linear[m/s] rotational_speed angular[rad/s]
void pub_vel(double linear, double angular) {
    geometry_msgs::Twist vel;
    vel.linear.x = linear;
    vel.angular.z = angular;

    //publish the message
    vel_pub.publish(vel);
    return;
}

void vicon_sysCallback(const tms_msg_ss::vicon_data::ConstPtr& msg) {
	if (msg->subjectName == "kobuki") {
		//大域変数を更新
		v_pos_x = msg->translation.x;
		v_pos_y = msg->translation.y;
	    v_ori_th = floor2(rad2deg(msg->eulerXYZ[2]), 2);
	}
}

void odomCallback(const nav_msgs::Odometry::ConstPtr& msg) {
    double z, w;//quaternion
    double temp_th;
	//大域変数を更新
	pos_x = msg->pose.pose.position.x + x;
	pos_y = msg->pose.pose.position.y + y;

	z = msg->pose.pose.orientation.z;
	w = msg->pose.pose.orientation.w;
    temp_th = quaternion_to_enler(z, w);
    ori_th = rad2deg(temp_th) + th;
}

// command 0: rotate only
// command 1: go straight only
// command 2: rotate and go straight
bool control_base(int command, double goal_dis, double goal_ang) {
	//移動前のオドメトリ情報を格納
	double ini_pos_x, ini_pos_y, ini_ori_th;
	double var_pos_x, var_pos_y, var_ori_th;//ini_th->quaternion to euler

//initialize variables
#ifdef ODOM
	ini_pos_x = pos_x;
	ini_pos_y = pos_y;
	ini_ori_th = ori_th;

	var_pos_x = pos_x;
	var_pos_y = pos_y;
	var_ori_th = ori_th;
#endif

#ifdef VICON
	ini_pos_x = v_pos_x;
	ini_pos_y = v_pos_y;
	ini_ori_th = v_ori_th;

	var_pos_x = v_pos_x;
	var_pos_y = v_pos_y;
	var_ori_th = v_ori_th;
#endif

#ifdef DB
	tms_msg_db::TmsdbGetData srv;
	srv.request.tmsdb.id = 2005; // ID : kobuki
	if (db_client.call(srv)) {
		ini_pos_x = srv.response.tmsdb[0].x;
		ini_pos_y = srv.response.tmsdb[0].y;
		ini_ori_th = srv.response.tmsdb[0].ry;

		var_pos_x = srv.response.tmsdb[0].x;
		var_pos_y = srv.response.tmsdb[0].y;
		var_ori_th = srv.response.tmsdb[0].ry;
	} else {
		ROS_ERROR("Failed to call service tms db get kobuki's data\n");
	}
#endif

	if (command == 0 || command == 2) {
		if (goal_ang > 0) { // rotate +
			while (1) {
				// 180度の境界線を越えるとき
				if (ini_ori_th+goal_ang > 180) {
					if ((ini_ori_th <= var_ori_th && var_ori_th <= 180)
							|| (-180 <= var_ori_th && var_ori_th < ini_ori_th+goal_ang-360)) {
						pub_vel(0.0, 0.523596);// 30deg/s
#ifdef ODOM
						var_ori_th = ori_th;
#endif
#ifdef VICON
						var_ori_th = v_ori_th;
#endif
#ifdef DB
						if (db_client.call(srv)) {
							var_ori_th = srv.response.tmsdb[0].ry;
						} else {
							ROS_ERROR("Failed to call service tms db get kobuki's data\n");
						}
#endif
					} else {
						pub_vel(0.0, 0.0);
						break;
					}
				} else {
					if (fabs(var_ori_th - ini_ori_th) < fabs(goal_ang)){
						// 1.+回転
						pub_vel(0.0, 0.523596); // 30deg/s
#ifdef ODOM
						var_ori_th = ori_th;
#endif
#ifdef VICON
						var_ori_th = v_ori_th;
#endif
#ifdef DB
						if (db_client.call(srv)) {
							var_ori_th = srv.response.tmsdb[0].ry;
						} else {
							ROS_ERROR("Failed to call service tms db get kobuki's data\n");
						}
#endif
					} else {
						pub_vel(0.0, 0.0);
						break;
					}
				}
			}
		} else if (goal_ang < 0) { // rotate -
			while (1) {
				// 180度の境界線を越えるとき
				if(ini_ori_th+goal_ang < -180) {
					if ((-180 <= var_ori_th && var_ori_th <= ini_ori_th)
							|| (360+goal_ang+ini_ori_th < var_ori_th && var_ori_th <= 180)) {
						pub_vel(0.0, -0.523596);//-(PI/2m)/s
#ifdef ODOM
						var_ori_th = ori_th;
#endif
#ifdef VICON
						var_ori_th = v_ori_th;
#endif
#ifdef DB
						if (db_client.call(srv)) {
							var_ori_th = srv.response.tmsdb[0].ry;
						} else {
							ROS_ERROR("Failed to call service tms db get kobuki's data\n");
						}
#endif
					} else {
						pub_vel(0.0, 0.0);
						break;
					}
				} else {
					if (fabs(var_ori_th - ini_ori_th) < fabs(goal_ang)) {
						// 1.+回転
						pub_vel(0.0, -0.523596); // -(PI/2m)/s
	#ifdef ODOM
						var_ori_th = ori_th;
	#endif
	#ifdef VICON
						var_ori_th = v_ori_th;
	#endif
	#ifdef DB
						if (db_client.call(srv)) {
							var_ori_th = srv.response.tmsdb[0].ry;
						} else {
							ROS_ERROR("Failed to call service tms db get kobuki's data\n");
						}
	#endif
					} else {
						pub_vel(0.0, 0.0);
						break;
					}
				}
			}
		}
	}

	if (command == 1 || command  == 2) {
		if (goal_dis > 0) {
			while (1) {
		        if (distance(ini_pos_x, ini_pos_y, var_pos_x, var_pos_y) <  goal_dis) { // 単位：mm
		        	// 2.直進
					pub_vel(0.15, 0.0); // 0.25m/s
#ifdef ODOM
					var_pos_x = pos_x;
					var_pos_y = pos_y;
#endif
#ifdef VICON
					var_pos_x = v_pos_x;
					var_pos_y = v_pos_y;
#endif
#ifdef DB
							if (db_client.call(srv)) {
								var_pos_x = srv.response.tmsdb[0].x;
								var_pos_y = srv.response.tmsdb[0].y;
							} else {
								ROS_ERROR("Failed to call service tms db get kobuki's data\n");
							}
#endif
				} else {
					pub_vel(0.0, 0.0);
					break;
				}
			}
		}
	}
	return true;
}

bool callback(tms_msg_rc::rc_robot_control::Request  &req,
		tms_msg_rc::rc_robot_control::Response &res) {
	int command = 0;
	switch (req.cmd) {
	case 0:
		///// control robot base1(絶対座標)
		// エラーチェック
		if (req.arg.size() != 3 || req.arg[0] < 0 || req.arg[0] > 8000
				|| req.arg[1] < 0 || req.arg[1] > 4500
				|| req.arg[2] < -180 || req.arg[2] > 180) {
			ROS_ERROR("case0 : An illegal arguments' type.\n");
			res.result = 0; //false
			return true;
		}

		// 現在地取得
		double current_x, current_y, current_th;
#ifdef ODOM
		current_x = pos_x;
		current_y = pos_y;
		current_th = ori_th;
		ROS_INFO("current_x=%fmm, current_y=%fmm, current_th=%fdeg\n", current_x, current_y, current_th);
#endif
#ifdef VICON
		current_x = v_pos_x;
		current_y = v_pos_y;
		current_th = v_ori_th;
		ROS_INFO("current_x=%fmm, current_y=%fmm, current_th=%fdeg\n", current_x, current_y, current_th);
#endif
#ifdef DB
		tms_msg_db::TmsdbGetData srv;
		srv.request.tmsdb.id = 2005; // ID : kobuki
		if (db_client.call(srv)) {
			current_x = srv.response.tmsdb[0].x;
			current_y = srv.response.tmsdb[0].y;
			current_th = srv.response.tmsdb[0].ry;
		} else {
			ROS_ERROR("Failed to call service tms db get kobuki's data\n");
			return false;
		}
		ROS_INFO("current_x=%fmm, current_y=%fmm, current_th=%fdeg\n", current_x, current_y, current_th);
#endif
		double goal_distance, goal_theta;
		goal_distance = distance(current_x, current_y, req.arg[0], req.arg[1]);
		goal_theta = req.arg[2] - current_th;
		if (goal_theta > 180.0) goal_theta = goal_theta - 360.0;
		else if (goal_theta < -180.0) goal_theta = goal_theta + 360.0;

		if (goal_distance >= 5 && goal_theta < 2) command = 1;
		else if (goal_distance >= 5 && goal_theta >= 2) command = 2;

		ROS_INFO("command:%d: goal_dis=%fmm, goal_arg=%fdeg", command, goal_distance, goal_theta);
		if(control_base(command, goal_distance, goal_theta)) {
			ROS_INFO("Finish control_base");
		}
		res.result = 1;
		break;

	case 1:
		///// control robot base2(相対座標)
		// エラーチェック
		if (req.arg.size() != 2 || req.arg[0] < 0 || req.arg[0] > 9179
				|| req.arg[1] < -180 || req.arg[1] > 180) {
			ROS_ERROR("case0 : An illegal arguments' type.\n");
			res.result = 0; //false
			return true;}

		if (goal_distance >= 5 && goal_theta < 2) command = 1;
		else if (goal_distance >= 5 && goal_theta >= 2) command = 2;

		ROS_INFO("command:%d: goal_dis=%fmm, goal_arg=%fdeg", command, req.arg[0], req.arg[1]);
		if (control_base(command, (double)req.arg[0], (double)req.arg[1])) {
			ROS_INFO("Finish control_base");
		}
		res.result = 1;
		break;

	default :
		ROS_ERROR("An illegal command : %d\n", req.cmd);
		res.result = 0;
		return true;
	}
	sleep(1.0);
	return true;
}

int main(int argc, char **argv) {
	ros::init(argc, argv, "kobuki_control");
	ros::NodeHandle n;

	db_client = n.serviceClient<tms_msg_db::TmsdbGetData>("/tms_db_reader/dbreader");

#ifdef ODOM
	// kobukiの初期位置を格納
	tms_msg_db::TmsdbGetData srv;
	srv.request.tmsdb.id = 2005; // ID : kobuki
	if (db_client.call(srv)) {
		x = srv.response.tmsdb[0].x;
		y = srv.response.tmsdb[0].y;
		th = srv.response.tmsdb[0].ry;
	} else {
		ROS_ERROR("Failed to call service tms db get kobuki's data\n");
		return false;
	}
	ROS_INFO("kobuki's initial pos = [%fmm, %fmm, %fdeg]\n", x, y, th);
#endif

	ros::ServiceServer service = n.advertiseService("kobuki_control", callback);
	ROS_INFO("Ready to activate kobuki_control_node\n");

	ros::AsyncSpinner spinner(3);
	spinner.start();

	//現在地取得方法(vicon or odom)
	ros::Subscriber vicon_sub = n.subscribe("vicon_stream/output", 10, vicon_sysCallback);
	ros::Subscriber odom_sub = n.subscribe("odom", 10, odomCallback);//Odometry情報取得

	vel_pub = n.advertise<geometry_msgs::Twist>("mobile_base/commands/velocity",1); //kobukiに速度を送る
	ros::waitForShutdown();

	return 0;
}
<|endoftext|>


<commit_before>// Copyright (c) 2016 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.

#include "modaloverlay.h"
#include "ui_modaloverlay.h"

#include "guiutil.h"

#include "chainparams.h"

#include <QResizeEvent>
#include <QPropertyAnimation>

ModalOverlay::ModalOverlay(QWidget *parent) :
QWidget(parent),
ui(new Ui::ModalOverlay),
bestHeaderHeight(0),
bestHeaderDate(QDateTime()),
layerIsVisible(false),
userClosed(false)
{
    ui->setupUi(this);
    connect(ui->closeButton, SIGNAL(clicked()), this, SLOT(closeClicked()));
    if (parent) {
        parent->installEventFilter(this);
        raise();
    }

    blockProcessTime.clear();
    setVisible(false);
}

ModalOverlay::~ModalOverlay()
{
    delete ui;
}

bool ModalOverlay::eventFilter(QObject * obj, QEvent * ev) {
    if (obj == parent()) {
        if (ev->type() == QEvent::Resize) {
            QResizeEvent * rev = static_cast<QResizeEvent*>(ev);
            resize(rev->size());
            if (!layerIsVisible)
                setGeometry(0, height(), width(), height());

        }
        else if (ev->type() == QEvent::ChildAdded) {
            raise();
        }
    }
    return QWidget::eventFilter(obj, ev);
}

//! Tracks parent widget changes
bool ModalOverlay::event(QEvent* ev) {
    if (ev->type() == QEvent::ParentAboutToChange) {
        if (parent()) parent()->removeEventFilter(this);
    }
    else if (ev->type() == QEvent::ParentChange) {
        if (parent()) {
            parent()->installEventFilter(this);
            raise();
        }
    }
    return QWidget::event(ev);
}

void ModalOverlay::setKnownBestHeight(int count, const QDateTime& blockDate)
{
    if (count > bestHeaderHeight) {
        bestHeaderHeight = count;
        bestHeaderDate = blockDate;
    }
}

void ModalOverlay::tipUpdate(int count, const QDateTime& blockDate, double nVerificationProgress)
{
    QDateTime currentDate = QDateTime::currentDateTime();

    // keep a vector of samples of verification progress at height
    blockProcessTime.push_front(qMakePair(currentDate.toMSecsSinceEpoch(), nVerificationProgress));

    // show progress speed if we have more then one sample
    if (blockProcessTime.size() >= 2)
    {
        double progressStart = blockProcessTime[0].second;
        double progressDelta = 0;
        double progressPerHour = 0;
        qint64 timeDelta = 0;
        qint64 remainingMSecs = 0;
        double remainingProgress = 1.0 - nVerificationProgress;
        for (int i = 1; i < blockProcessTime.size(); i++)
        {
            QPair<qint64, double> sample = blockProcessTime[i];

            // take first sample after 500 seconds or last available one
            if (sample.first < (currentDate.toMSecsSinceEpoch() - 500 * 1000) || i == blockProcessTime.size() - 1) {
                progressDelta = progressStart-sample.second;
                timeDelta = blockProcessTime[0].first - sample.first;
                progressPerHour = progressDelta/(double)timeDelta*1000*3600;
                remainingMSecs = (progressDelta > 0) ? remainingProgress / progressDelta * timeDelta : -1;
                break;
            }
        }
        // show progress increase per hour
        ui->progressIncreasePerH->setText(QString::number(progressPerHour*100, 'f', 2)+"%");

        if(remainingMSecs >= 0) {
            ui->expectedTimeLeft->setText(GUIUtil::formatNiceTimeOffset(remainingMSecs / 1000.0));
        } else {
            ui->expectedTimeLeft->setText(QObject::tr("unknown"));
        }

        static const int MAX_SAMPLES = 5000;
        if (blockProcessTime.count() > MAX_SAMPLES)
            blockProcessTime.remove(MAX_SAMPLES, blockProcessTime.count()-MAX_SAMPLES);
    }

    // show the last block date
    ui->newestBlockDate->setText(blockDate.toString());

    // show the percentage done according to nVerificationProgress
    ui->percentageProgress->setText(QString::number(nVerificationProgress*100, 'f', 2)+"%");
    ui->progressBar->setValue(nVerificationProgress*100);

    if (!bestHeaderDate.isValid())
        // not syncing
        return;

    // estimate the number of headers left based on nPowTargetSpacing
    // and check if the gui is not aware of the best header (happens rarely)
    int estimateNumHeadersLeft = bestHeaderDate.secsTo(currentDate) / Params().GetConsensus().nPowTargetSpacing;
    bool hasBestHeader = bestHeaderHeight >= count;

    // show remaining number of blocks
    if (estimateNumHeadersLeft < HEADER_HEIGHT_DELTA_SYNC && hasBestHeader) {
        ui->numberOfBlocksLeft->setText(QString::number(bestHeaderHeight - count));
    } else {
        ui->numberOfBlocksLeft->setText(tr("Unknown. Syncing Headers (%1)...").arg(bestHeaderHeight));
        ui->expectedTimeLeft->setText(tr("Unknown..."));
    }
}

void ModalOverlay::toggleVisibility()
{
    showHide(layerIsVisible, true);
    if (!layerIsVisible)
        userClosed = true;
}

void ModalOverlay::showHide(bool hide, bool userRequested)
{
    if ( (layerIsVisible && !hide) || (!layerIsVisible && hide) || (!hide && userClosed && !userRequested))
        return;

    if (!isVisible() && !hide)
        setVisible(true);

    setGeometry(0, hide ? 0 : height(), width(), height());

    QPropertyAnimation* animation = new QPropertyAnimation(this, "pos");
    animation->setDuration(300);
    animation->setStartValue(QPoint(0, hide ? 0 : this->height()));
    animation->setEndValue(QPoint(0, hide ? this->height() : 0));
    animation->setEasingCurve(QEasingCurve::OutQuad);
    animation->start(QAbstractAnimation::DeleteWhenStopped);
    layerIsVisible = !hide;
}

void ModalOverlay::closeClicked()
{
    showHide(true);
    userClosed = true;
}<commit_msg>Refactor tipUpdate as per style guide<commit_after>// Copyright (c) 2016 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.

#include "modaloverlay.h"
#include "ui_modaloverlay.h"

#include "guiutil.h"

#include "chainparams.h"

#include <QResizeEvent>
#include <QPropertyAnimation>

ModalOverlay::ModalOverlay(QWidget *parent) :
QWidget(parent),
ui(new Ui::ModalOverlay),
bestHeaderHeight(0),
bestHeaderDate(QDateTime()),
layerIsVisible(false),
userClosed(false)
{
    ui->setupUi(this);
    connect(ui->closeButton, SIGNAL(clicked()), this, SLOT(closeClicked()));
    if (parent) {
        parent->installEventFilter(this);
        raise();
    }

    blockProcessTime.clear();
    setVisible(false);
}

ModalOverlay::~ModalOverlay()
{
    delete ui;
}

bool ModalOverlay::eventFilter(QObject * obj, QEvent * ev) {
    if (obj == parent()) {
        if (ev->type() == QEvent::Resize) {
            QResizeEvent * rev = static_cast<QResizeEvent*>(ev);
            resize(rev->size());
            if (!layerIsVisible)
                setGeometry(0, height(), width(), height());

        }
        else if (ev->type() == QEvent::ChildAdded) {
            raise();
        }
    }
    return QWidget::eventFilter(obj, ev);
}

//! Tracks parent widget changes
bool ModalOverlay::event(QEvent* ev) {
    if (ev->type() == QEvent::ParentAboutToChange) {
        if (parent()) parent()->removeEventFilter(this);
    }
    else if (ev->type() == QEvent::ParentChange) {
        if (parent()) {
            parent()->installEventFilter(this);
            raise();
        }
    }
    return QWidget::event(ev);
}

void ModalOverlay::setKnownBestHeight(int count, const QDateTime& blockDate)
{
    if (count > bestHeaderHeight) {
        bestHeaderHeight = count;
        bestHeaderDate = blockDate;
    }
}

void ModalOverlay::tipUpdate(int count, const QDateTime& blockDate, double nVerificationProgress)
{
    QDateTime currentDate = QDateTime::currentDateTime();

    // keep a vector of samples of verification progress at height
    blockProcessTime.push_front(qMakePair(currentDate.toMSecsSinceEpoch(), nVerificationProgress));

    // show progress speed if we have more then one sample
    if (blockProcessTime.size() >= 2) {
        double progressDelta = 0;
        double progressPerHour = 0;
        qint64 timeDelta = 0;
        qint64 remainingMSecs = 0;
        double remainingProgress = 1.0 - nVerificationProgress;
        for (int i = 1; i < blockProcessTime.size(); i++) {
            QPair<qint64, double> sample = blockProcessTime[i];

            // take first sample after 500 seconds or last available one
            if (sample.first < (currentDate.toMSecsSinceEpoch() - 500 * 1000) || i == blockProcessTime.size() - 1) {
                progressDelta = blockProcessTime[0].second - sample.second;
                timeDelta = blockProcessTime[0].first - sample.first;
                progressPerHour = progressDelta / (double) timeDelta * 1000 * 3600;
                remainingMSecs = (progressDelta > 0) ? remainingProgress / progressDelta * timeDelta : -1;
                break;
            }
        }
        // show progress increase per hour
        ui->progressIncreasePerH->setText(QString::number(progressPerHour * 100, 'f', 2)+"%");

        // show expected remaining time
        if(remainingMSecs >= 0) {
            ui->expectedTimeLeft->setText(GUIUtil::formatNiceTimeOffset(remainingMSecs / 1000.0));
        } else {
            ui->expectedTimeLeft->setText(QObject::tr("unknown"));
        }

        static const int MAX_SAMPLES = 5000;
        if (blockProcessTime.count() > MAX_SAMPLES) {
            blockProcessTime.remove(MAX_SAMPLES, blockProcessTime.count() - MAX_SAMPLES);
        }
    }

    // show the last block date
    ui->newestBlockDate->setText(blockDate.toString());

    // show the percentage done according to nVerificationProgress
    ui->percentageProgress->setText(QString::number(nVerificationProgress*100, 'f', 2)+"%");
    ui->progressBar->setValue(nVerificationProgress*100);

    if (!bestHeaderDate.isValid())
        // not syncing
        return;

    // estimate the number of headers left based on nPowTargetSpacing
    // and check if the gui is not aware of the best header (happens rarely)
    int estimateNumHeadersLeft = bestHeaderDate.secsTo(currentDate) / Params().GetConsensus().nPowTargetSpacing;
    bool hasBestHeader = bestHeaderHeight >= count;

    // show remaining number of blocks
    if (estimateNumHeadersLeft < HEADER_HEIGHT_DELTA_SYNC && hasBestHeader) {
        ui->numberOfBlocksLeft->setText(QString::number(bestHeaderHeight - count));
    } else {
        ui->numberOfBlocksLeft->setText(tr("Unknown. Syncing Headers (%1)...").arg(bestHeaderHeight));
        ui->expectedTimeLeft->setText(tr("Unknown..."));
    }
}

void ModalOverlay::toggleVisibility()
{
    showHide(layerIsVisible, true);
    if (!layerIsVisible)
        userClosed = true;
}

void ModalOverlay::showHide(bool hide, bool userRequested)
{
    if ( (layerIsVisible && !hide) || (!layerIsVisible && hide) || (!hide && userClosed && !userRequested))
        return;

    if (!isVisible() && !hide)
        setVisible(true);

    setGeometry(0, hide ? 0 : height(), width(), height());

    QPropertyAnimation* animation = new QPropertyAnimation(this, "pos");
    animation->setDuration(300);
    animation->setStartValue(QPoint(0, hide ? 0 : this->height()));
    animation->setEndValue(QPoint(0, hide ? this->height() : 0));
    animation->setEasingCurve(QEasingCurve::OutQuad);
    animation->start(QAbstractAnimation::DeleteWhenStopped);
    layerIsVisible = !hide;
}

void ModalOverlay::closeClicked()
{
    showHide(true);
    userClosed = true;
}
<|endoftext|>


<commit_before>////////////////////////////////////////////////////////////////////////////////
/// DISCLAIMER
///
/// Copyright 2014-2016 ArangoDB GmbH, Cologne, Germany
/// Copyright 2004-2014 triAGENS GmbH, Cologne, Germany
///
/// 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.
///
/// Copyright holder is ArangoDB GmbH, Cologne, Germany
///
/// @author Dr. Frank Celler
////////////////////////////////////////////////////////////////////////////////

#include "random.h"

#include "Basics/threads.h"

////////////////////////////////////////////////////////////////////////////////
/// @brief already initialized
////////////////////////////////////////////////////////////////////////////////

static bool Initialized = false;

////////////////////////////////////////////////////////////////////////////////
/// @brief generates a seed
////////////////////////////////////////////////////////////////////////////////

static unsigned long SeedRandom(void) {
  unsigned long seed;

#ifdef TRI_HAVE_GETTIMEOFDAY
  struct timeval tv;

  /* ignore result */ gettimeofday(&tv, 0);

  seed = (unsigned long)(tv.tv_sec);
  seed ^= (unsigned long)(tv.tv_usec);
#else
  seed = (unsigned long)time(0);
#endif

  seed ^= (unsigned long)((uint32_t) TRI_CurrentProcessId() << 8);
  seed ^= (unsigned long)((uint32_t) TRI_CurrentProcessId() << 16);
  seed ^= (unsigned long)((uint32_t) TRI_CurrentProcessId() << 24);
  seed ^= (unsigned long)((uint32_t) TRI_CurrentThreadId());

  return seed;
}

////////////////////////////////////////////////////////////////////////////////
/// @brief generates a 16 bit random unsigned integer
////////////////////////////////////////////////////////////////////////////////

uint16_t TRI_UInt16Random(void) {
#if RAND_MAX == 2147483647

  return TRI_random() & 0xFFFF;

#else

  uint32_t l1;
  uint32_t l2;

  l1 = TRI_random();
  l2 = TRI_random();

  return ((l1 & 0xFF) << 8) | (l2 & 0xFF);

#endif
}

////////////////////////////////////////////////////////////////////////////////
/// @brief generates a 32 bit random unsigned integer
////////////////////////////////////////////////////////////////////////////////

uint32_t TRI_UInt32Random(void) {
#if RAND_MAX == 2147483647

  uint32_t l1;
  uint32_t l2;

  l1 = (uint32_t)TRI_random();
  l2 = (uint32_t)TRI_random();

  return ((l1 & 0xFFFF) << 16) | (l2 & 0xFFFF);

#else

#ifdef _WIN32
  unsigned int number;
  auto err = rand_s(&number);
  if (err == 0) {
    return number;
  }
#endif

  uint32_t l1;
  uint32_t l2;
  uint32_t l3;
  uint32_t l4;

  l1 = TRI_random();
  l2 = TRI_random();
  l3 = TRI_random();
  l4 = TRI_random();

  return ((l1 & 0xFF) << 24) | ((l2 & 0xFF) << 16) | ((l3 & 0xFF) << 8) |
         (l4 & 0xFF);
#endif
}

////////////////////////////////////////////////////////////////////////////////
/// @brief initializes the random components
////////////////////////////////////////////////////////////////////////////////

void TRI_InitializeRandom(void) {
  if (Initialized) {
    return;
  }

  TRI_srandom(SeedRandom());

  Initialized = true;
}

////////////////////////////////////////////////////////////////////////////////
/// @brief shuts down the random components
////////////////////////////////////////////////////////////////////////////////

void TRI_ShutdownRandom(void) {
  if (!Initialized) {
    return;
  }

  Initialized = false;
}
<commit_msg>attempt to fix warning with clang on Mac<commit_after>////////////////////////////////////////////////////////////////////////////////
/// DISCLAIMER
///
/// Copyright 2014-2016 ArangoDB GmbH, Cologne, Germany
/// Copyright 2004-2014 triAGENS GmbH, Cologne, Germany
///
/// 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.
///
/// Copyright holder is ArangoDB GmbH, Cologne, Germany
///
/// @author Dr. Frank Celler
////////////////////////////////////////////////////////////////////////////////

#include "random.h"

#include "Basics/threads.h"

////////////////////////////////////////////////////////////////////////////////
/// @brief already initialized
////////////////////////////////////////////////////////////////////////////////

static bool Initialized = false;

////////////////////////////////////////////////////////////////////////////////
/// @brief generates a seed
////////////////////////////////////////////////////////////////////////////////

static unsigned long SeedRandom(void) {
  unsigned long seed;

#ifdef TRI_HAVE_GETTIMEOFDAY
  struct timeval tv;

  /* ignore result */ gettimeofday(&tv, 0);

  seed = static_cast<decltype(seed)>(tv.tv_sec);
  seed ^= static_cast<decltype(seed)>(tv.tv_usec);
#else
  seed = static_cast<decltype(seed)>(time(0));
#endif

  seed ^= static_cast<decltype(seed)>((uint32_t) TRI_CurrentProcessId() << 8);
  seed ^= static_cast<decltype(seed)>((uint32_t) TRI_CurrentProcessId() << 16);
  seed ^= static_cast<decltype(seed)>((uint32_t) TRI_CurrentProcessId() << 24);
  seed ^= static_cast<decltype(seed)>(static_cast<std::conditional<std::is_pointer<TRI_tid_t>::value, uintptr_t, uint32_t>::type>(TRI_CurrentThreadId()));

  return seed;
}

////////////////////////////////////////////////////////////////////////////////
/// @brief generates a 16 bit random unsigned integer
////////////////////////////////////////////////////////////////////////////////

uint16_t TRI_UInt16Random(void) {
#if RAND_MAX == 2147483647

  return TRI_random() & 0xFFFF;

#else

  uint32_t l1;
  uint32_t l2;

  l1 = TRI_random();
  l2 = TRI_random();

  return ((l1 & 0xFF) << 8) | (l2 & 0xFF);

#endif
}

////////////////////////////////////////////////////////////////////////////////
/// @brief generates a 32 bit random unsigned integer
////////////////////////////////////////////////////////////////////////////////

uint32_t TRI_UInt32Random(void) {
#if RAND_MAX == 2147483647

  uint32_t l1;
  uint32_t l2;

  l1 = (uint32_t)TRI_random();
  l2 = (uint32_t)TRI_random();

  return ((l1 & 0xFFFF) << 16) | (l2 & 0xFFFF);

#else

#ifdef _WIN32
  unsigned int number;
  auto err = rand_s(&number);
  if (err == 0) {
    return number;
  }
#endif

  uint32_t l1;
  uint32_t l2;
  uint32_t l3;
  uint32_t l4;

  l1 = TRI_random();
  l2 = TRI_random();
  l3 = TRI_random();
  l4 = TRI_random();

  return ((l1 & 0xFF) << 24) | ((l2 & 0xFF) << 16) | ((l3 & 0xFF) << 8) |
         (l4 & 0xFF);
#endif
}

////////////////////////////////////////////////////////////////////////////////
/// @brief initializes the random components
////////////////////////////////////////////////////////////////////////////////

void TRI_InitializeRandom(void) {
  if (Initialized) {
    return;
  }

  TRI_srandom(SeedRandom());

  Initialized = true;
}

////////////////////////////////////////////////////////////////////////////////
/// @brief shuts down the random components
////////////////////////////////////////////////////////////////////////////////

void TRI_ShutdownRandom(void) {
  if (!Initialized) {
    return;
  }

  Initialized = false;
}
<|endoftext|>