<commit_before>/*************************************************************************
 *
 *  $RCSfile: msci.hxx,v $
 *
 *  $Revision: 1.3 $
 *
 *  last change: $Author: dbo $ $Date: 2001-08-01 10:09:58 $
 *
 *  The Contents of this file are made available subject to the terms of
 *  either of the following licenses
 *
 *         - GNU Lesser General Public License Version 2.1
 *         - Sun Industry Standards Source License Version 1.1
 *
 *  Sun Microsystems Inc., October, 2000
 *
 *  GNU Lesser General Public License Version 2.1
 *  =============================================
 *  Copyright 2000 by Sun Microsystems, Inc.
 *  901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public
 *  License version 2.1, as published by the Free Software Foundation.
 *
 *  This library is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *  Lesser General Public License for more details.
 *
 *  You should have received a copy of the GNU Lesser General Public
 *  License along with this library; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *  MA  02111-1307  USA
 *
 *
 *  Sun Industry Standards Source License Version 1.1
 *  =================================================
 *  The contents of this file are subject to the Sun Industry Standards
 *  Source License Version 1.1 (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.openoffice.org/license.html.
 *
 *  Software provided under this License is provided on an "AS IS" basis,
 *  WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
 *  WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
 *  MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
 *  See the License for the specific provisions governing your rights and
 *  obligations concerning the Software.
 *
 *  The Initial Developer of the Original Code is: Sun Microsystems, Inc.
 *
 *  Copyright: 2000 by Sun Microsystems, Inc.
 *
 *  All Rights Reserved.
 *
 *  Contributor(s): _______________________________________
 *
 *
 ************************************************************************/

#include <windows.h>

#ifndef _RTL_USTRING_HXX_
#include <rtl/ustring.hxx>
#endif

#define MSVC_ExceptionCode 0xe06d7363

class type_info;
typedef struct _uno_Any uno_Any;
typedef struct _uno_Mapping uno_Mapping;

namespace CPPU_CURRENT_NAMESPACE
{

//==================================================================================================
type_info * msci_getRTTI(
    ::rtl::OUString const & rUNOname ) throw ();

//==================================================================================================
sal_Int32 msci_filterCppException(
    LPEXCEPTION_POINTERS pPointers, uno_Any * pUnoExc, uno_Mapping * pCpp2Uno );

//==================================================================================================
void msci_raiseException(
    uno_Any * pUnoExc, uno_Mapping * pUno2Cpp );

}

<commit_msg>INTEGRATION: CWS unopkg (1.3.100); FILE MERGED 2003/09/26 12:58:00 dbo 1.3.100.1: #112449# fixing msci bridge rethrow<commit_after>/*************************************************************************
 *
 *  $RCSfile: msci.hxx,v $
 *
 *  $Revision: 1.4 $
 *
 *  last change: $Author: vg $ $Date: 2003-10-06 13:15:52 $
 *
 *  The Contents of this file are made available subject to the terms of
 *  either of the following licenses
 *
 *         - GNU Lesser General Public License Version 2.1
 *         - Sun Industry Standards Source License Version 1.1
 *
 *  Sun Microsystems Inc., October, 2000
 *
 *  GNU Lesser General Public License Version 2.1
 *  =============================================
 *  Copyright 2000 by Sun Microsystems, Inc.
 *  901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public
 *  License version 2.1, as published by the Free Software Foundation.
 *
 *  This library is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *  Lesser General Public License for more details.
 *
 *  You should have received a copy of the GNU Lesser General Public
 *  License along with this library; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *  MA  02111-1307  USA
 *
 *
 *  Sun Industry Standards Source License Version 1.1
 *  =================================================
 *  The contents of this file are subject to the Sun Industry Standards
 *  Source License Version 1.1 (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.openoffice.org/license.html.
 *
 *  Software provided under this License is provided on an "AS IS" basis,
 *  WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
 *  WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
 *  MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
 *  See the License for the specific provisions governing your rights and
 *  obligations concerning the Software.
 *
 *  The Initial Developer of the Original Code is: Sun Microsystems, Inc.
 *
 *  Copyright: 2000 by Sun Microsystems, Inc.
 *
 *  All Rights Reserved.
 *
 *  Contributor(s): _______________________________________
 *
 *
 ************************************************************************/

#include <windows.h>
#include "rtl/ustring.hxx"

class type_info;
typedef struct _uno_Any uno_Any;
typedef struct _uno_Mapping uno_Mapping;

namespace CPPU_CURRENT_NAMESPACE
{

const long MSVC_ExceptionCode = 0xe06d7363;
const long MSVC_magic_number = 0x19930520L;

//==============================================================================
type_info * msci_getRTTI( ::rtl::OUString const & rUNOname );

//==============================================================================
int msci_filterCppException(
    EXCEPTION_POINTERS * pPointers, uno_Any * pUnoExc, uno_Mapping * pCpp2Uno );

//==============================================================================
void msci_raiseException(
    uno_Any * pUnoExc, uno_Mapping * pUno2Cpp );

}

<|endoftext|>


<commit_before>// Load transforms and build RGB volumes from images

#include "boost/filesystem.hpp"

#include "itkRGBPixel.h"
#include "itkVectorResampleImageFilter.h"

// my files
#include "Stack.hpp"
#include "StackInitializers.hpp"
#include "RegistrationBuilder.hpp"
#include "StackAligner.hpp"
#include "StackIOHelpers.hpp"
#include "IOHelpers.hpp"
#include "StackTransforms.hpp"
#include "Dirs.hpp"
#include "Parameters.hpp"
#include "Profiling.hpp"

void checkUsage(int argc, char const *argv[]) {
  if( argc < 3 )
  {
    cerr << "\nUsage: " << endl;
    cerr << argv[0] << " dataSet outputDir (loResDSRatio hiResDSRatio roi)\n\n";
    exit(EXIT_FAILURE);
  }
}

int main(int argc, char const *argv[]) {
	// Verify the number of parameters in the command line
	checkUsage(argc, argv);

	// Process command line arguments
  Dirs::SetDataSet(argv[1]);
  Dirs::SetOutputDirName(argv[2]);

  // set region of interest
  string roi;
  if(argc >=6) roi = argv[5];
  else         roi = "whole_heart";

  // get file names
  vector< string > LoResFilePaths, HiResFilePaths;
  LoResFilePaths = getFilePaths(Dirs::BlockDir(), Dirs::SliceFile());
  HiResFilePaths = getFilePaths(Dirs::SliceDir(), Dirs::SliceFile());

  // initialise stack with correct spacings, sizes, transforms etc
  typedef itk::RGBPixel< unsigned char > PixelType;
  typedef Stack< PixelType, itk::VectorResampleImageFilter, itk::VectorLinearInterpolateImageFunction > StackType;
  StackType::SliceVectorType LoResImages = readImages< StackType >(LoResFilePaths);
  StackType::SliceVectorType HiResImages = readImages< StackType >(HiResFilePaths);
  boost::shared_ptr< StackType > LoResStack = InitializeLoResStack<StackType>(LoResImages, roi);
  boost::shared_ptr< StackType > HiResStack = InitializeHiResStack<StackType>(HiResImages, roi);

  HiResStack->SetDefaultPixelValue( 255 );

  // Load transforms from files
  // get downsample ratios
  string LoResDownsampleRatio, HiResDownsampleRatio;
  if( argc >= 5 )
  {
    LoResDownsampleRatio = argv[3];
    HiResDownsampleRatio = argv[4];
  }
  else
  {
    boost::shared_ptr<YAML::Node> downsample_ratios = config(Dirs::GetDataSet() + "/downsample_ratios.yml");
    (*downsample_ratios)["LoRes"] >> LoResDownsampleRatio;
    (*downsample_ratios)["HiRes"] >> HiResDownsampleRatio;
  }

  // read transforms from directories labeled by both ds ratios
  using namespace boost::filesystem;
  string LoResTransformsDir = Dirs::ResultsDir() + "LoResTransforms_" + LoResDownsampleRatio + "_" + HiResDownsampleRatio;
  string HiResTransformsDir = Dirs::ResultsDir() + "HiResTransforms_" + LoResDownsampleRatio + "_" + HiResDownsampleRatio;

  Load(*LoResStack, LoResFilePaths, LoResTransformsDir);
  Load(*HiResStack, HiResFilePaths, HiResTransformsDir);

  // move stack origins to ROI
  itk::Vector< double, 2 > translation = StackTransforms::GetLoResTranslation(roi) - StackTransforms::GetLoResTranslation("whole_heart");
  StackTransforms::Translate(*LoResStack, translation);
  StackTransforms::Translate(*HiResStack, translation);

  // generate images
  LoResStack->updateVolumes();
  HiResStack->updateVolumes();

  // Write bmps
  using namespace boost::filesystem;
  create_directory( Dirs::ColourDir() );

  writeImage< StackType::VolumeType >( LoResStack->GetVolume(), (path( Dirs::ColourDir() ) / "LoRes.mha").string());
  writeImage< StackType::VolumeType >( HiResStack->GetVolume(), (path( Dirs::ColourDir() ) / "HiRes.mha").string());

  return EXIT_SUCCESS;
}
<commit_msg>Tidied up string initialisation.<commit_after>// Load transforms and build RGB volumes from images

#include "boost/filesystem.hpp"

#include "itkRGBPixel.h"
#include "itkVectorResampleImageFilter.h"

// my files
#include "Stack.hpp"
#include "StackInitializers.hpp"
#include "RegistrationBuilder.hpp"
#include "StackAligner.hpp"
#include "StackIOHelpers.hpp"
#include "IOHelpers.hpp"
#include "StackTransforms.hpp"
#include "Dirs.hpp"
#include "Parameters.hpp"
#include "Profiling.hpp"

void checkUsage(int argc, char const *argv[]) {
  if( argc < 3 )
  {
    cerr << "\nUsage: " << endl;
    cerr << argv[0] << " dataSet outputDir (loResDSRatio hiResDSRatio roi)\n\n";
    exit(EXIT_FAILURE);
  }
}

int main(int argc, char const *argv[]) {
	// Verify the number of parameters in the command line
	checkUsage(argc, argv);

	// Process command line arguments
  Dirs::SetDataSet(argv[1]);
  Dirs::SetOutputDirName(argv[2]);

  // set region of interest
  string roi = argc >=6 ? argv[5] : "whole_heart";

  // get file names
  vector< string > LoResFilePaths, HiResFilePaths;
  LoResFilePaths = getFilePaths(Dirs::BlockDir(), Dirs::SliceFile());
  HiResFilePaths = getFilePaths(Dirs::SliceDir(), Dirs::SliceFile());

  // initialise stack with correct spacings, sizes, transforms etc
  typedef itk::RGBPixel< unsigned char > PixelType;
  typedef Stack< PixelType, itk::VectorResampleImageFilter, itk::VectorLinearInterpolateImageFunction > StackType;
  StackType::SliceVectorType LoResImages = readImages< StackType >(LoResFilePaths);
  StackType::SliceVectorType HiResImages = readImages< StackType >(HiResFilePaths);
  boost::shared_ptr< StackType > LoResStack = InitializeLoResStack<StackType>(LoResImages, roi);
  boost::shared_ptr< StackType > HiResStack = InitializeHiResStack<StackType>(HiResImages, roi);

  HiResStack->SetDefaultPixelValue( 255 );

  // Load transforms from files
  // get downsample ratios
  string LoResDownsampleRatio, HiResDownsampleRatio;
  if( argc >= 5 )
  {
    LoResDownsampleRatio = argv[3];
    HiResDownsampleRatio = argv[4];
  }
  else
  {
    boost::shared_ptr<YAML::Node> downsample_ratios = config(Dirs::GetDataSet() + "/downsample_ratios.yml");
    (*downsample_ratios)["LoRes"] >> LoResDownsampleRatio;
    (*downsample_ratios)["HiRes"] >> HiResDownsampleRatio;
  }

  // read transforms from directories labeled by both ds ratios
  using namespace boost::filesystem;
  string LoResTransformsDir = Dirs::ResultsDir() + "LoResTransforms_" + LoResDownsampleRatio + "_" + HiResDownsampleRatio;
  string HiResTransformsDir = Dirs::ResultsDir() + "HiResTransforms_" + LoResDownsampleRatio + "_" + HiResDownsampleRatio;

  Load(*LoResStack, LoResFilePaths, LoResTransformsDir);
  Load(*HiResStack, HiResFilePaths, HiResTransformsDir);

  // move stack origins to ROI
  itk::Vector< double, 2 > translation = StackTransforms::GetLoResTranslation(roi) - StackTransforms::GetLoResTranslation("whole_heart");
  StackTransforms::Translate(*LoResStack, translation);
  StackTransforms::Translate(*HiResStack, translation);

  // generate images
  LoResStack->updateVolumes();
  HiResStack->updateVolumes();

  // Write bmps
  using namespace boost::filesystem;
  create_directory( Dirs::ColourDir() );

  writeImage< StackType::VolumeType >( LoResStack->GetVolume(), (path( Dirs::ColourDir() ) / "LoRes.mha").string());
  writeImage< StackType::VolumeType >( HiResStack->GetVolume(), (path( Dirs::ColourDir() ) / "HiRes.mha").string());

  return EXIT_SUCCESS;
}
<|endoftext|>


<commit_before>#include "responseserializer.h"
#include "responsedata.h"
#include <sstream>

std::string ApiMock::ResponseSerializer::statusCodeDescription(HTTP_RESPONSE_CODE responseCode) {
	switch (responseCode) {
	case HTTP_CONTINUE:							return "Continue";
	case HTTP_SWITCHING_PROTOCOLS:				return "Switching Protocols";
	case HTTP_OK:								return "OK";
	case HTTP_CREATED:							return "Created";
	case HTTP_ACCEPTED:							return "Accepted";
	case HTTP_NON_AUTHORATIVE_INFO:				return "Non-Authoritative Information";
	case HTTP_NO_CONTENT:						return "No Content";
	case HTTP_RESET_CONTENT:					return "Reset Content";
	case HTTP_PARTIAL_CONTENT:					return "Partial Content";
	case HTTP_MULTIPLE_CHOICES:					return "Multiple Choices";
	case HTTP_MOVED_PERMANENTLY:				return "Moved Permanently";
	case HTTP_FOUND:							return "Found";
	case HTTP_SEE_OTHER:						return "See Other";
	case HTTP_NOT_MODIFIED:						return "Not Modified";
	case HTTP_USE_PROXY:						return "Use Proxy";
	case HTTP_TEMPORARY_REDIRECT:				return "Temporary Redirect";
	case HTTP_BAD_REQUEST:						return "Bad Request";
	case HTTP_UNAUTHORIZED:						return "Unauthorized";
	case HTTP_FORBIDDEN:						return "Forbidden";
	case HTTP_NOT_FOUND:						return "Not Found";
	case HTTP_METHOD_NOT_ALLOWED:				return "Method Not Allowed";
	case HTTP_NOT_ACCEPTABLE:					return "Not Acceptable";
	case HTTP_PROXY_AUTH_REQUIRED:				return "Proxy Authentication Required";
	case HTTP_REQUEST_TIMEOUT:					return "Request Timeout";
	case HTTP_CONFLICT:							return "Conflict";
	case HTTP_GONE:								return "Gone";
	case HTTP_LENGTH_REQUIRED:					return "Length Required";
	case HTTP_PRECONDITION_FAILED:				return "Precondition Failed";
	case HTTP_REQUEST_ENTITY_TOO_LARGE:			return "Request Entity Too Large";
	case HTTP_REQUEST_URI_TOO_LONG:				return "Request-URI Too Long";
	case HTTP_UNSUPPORTED_MEDIA_TYPE:			return "Unsupported Media Type";
	case HTTP_REQUREST_RANGE_NOT_SATISFIABLE:	return "Requested Range Not Satisfiable";
	case HTTP_EXPECTATION_FAILED:				return "Expectation Failed";
	case HTTP_INTERNAL_SERVER_ERROR:			return "Internal Server Error";
	case HTTP_NOT_IMPLEMENTED:					return "Not Implemented";
	case HTTP_BAD_GATEWAY:						return "Bad Gateway";
	case HTTP_SERVICE_UNAVAILABLE:				return "Service Unavailable";
	case HTTP_GATEWAY_TIMEOUT:					return "Gateway Timeout";
	case HTTP_VERSION_NOT_SUPPORTED:			return "Version Not Supported";
	default:									return "";

	}
}

std::string ApiMock::ResponseSerializer::serialize(ResponseData response) {
	const std::string CRLF = "\r\n";
	std::stringstream ss;

	return ss.str();
}<commit_msg>Implement a simple response serializer<commit_after>#include "responseserializer.h"
#include "responsedata.h"
#include <sstream>

std::string ApiMock::ResponseSerializer::statusCodeDescription(HTTP_RESPONSE_CODE responseCode) {
	switch (responseCode) {
	case HTTP_CONTINUE:							return "Continue";
	case HTTP_SWITCHING_PROTOCOLS:				return "Switching Protocols";
	case HTTP_OK:								return "OK";
	case HTTP_CREATED:							return "Created";
	case HTTP_ACCEPTED:							return "Accepted";
	case HTTP_NON_AUTHORATIVE_INFO:				return "Non-Authoritative Information";
	case HTTP_NO_CONTENT:						return "No Content";
	case HTTP_RESET_CONTENT:					return "Reset Content";
	case HTTP_PARTIAL_CONTENT:					return "Partial Content";
	case HTTP_MULTIPLE_CHOICES:					return "Multiple Choices";
	case HTTP_MOVED_PERMANENTLY:				return "Moved Permanently";
	case HTTP_FOUND:							return "Found";
	case HTTP_SEE_OTHER:						return "See Other";
	case HTTP_NOT_MODIFIED:						return "Not Modified";
	case HTTP_USE_PROXY:						return "Use Proxy";
	case HTTP_TEMPORARY_REDIRECT:				return "Temporary Redirect";
	case HTTP_BAD_REQUEST:						return "Bad Request";
	case HTTP_UNAUTHORIZED:						return "Unauthorized";
	case HTTP_FORBIDDEN:						return "Forbidden";
	case HTTP_NOT_FOUND:						return "Not Found";
	case HTTP_METHOD_NOT_ALLOWED:				return "Method Not Allowed";
	case HTTP_NOT_ACCEPTABLE:					return "Not Acceptable";
	case HTTP_PROXY_AUTH_REQUIRED:				return "Proxy Authentication Required";
	case HTTP_REQUEST_TIMEOUT:					return "Request Timeout";
	case HTTP_CONFLICT:							return "Conflict";
	case HTTP_GONE:								return "Gone";
	case HTTP_LENGTH_REQUIRED:					return "Length Required";
	case HTTP_PRECONDITION_FAILED:				return "Precondition Failed";
	case HTTP_REQUEST_ENTITY_TOO_LARGE:			return "Request Entity Too Large";
	case HTTP_REQUEST_URI_TOO_LONG:				return "Request-URI Too Long";
	case HTTP_UNSUPPORTED_MEDIA_TYPE:			return "Unsupported Media Type";
	case HTTP_REQUREST_RANGE_NOT_SATISFIABLE:	return "Requested Range Not Satisfiable";
	case HTTP_EXPECTATION_FAILED:				return "Expectation Failed";
	case HTTP_INTERNAL_SERVER_ERROR:			return "Internal Server Error";
	case HTTP_NOT_IMPLEMENTED:					return "Not Implemented";
	case HTTP_BAD_GATEWAY:						return "Bad Gateway";
	case HTTP_SERVICE_UNAVAILABLE:				return "Service Unavailable";
	case HTTP_GATEWAY_TIMEOUT:					return "Gateway Timeout";
	case HTTP_VERSION_NOT_SUPPORTED:			return "Version Not Supported";
	default:									return "";

	}
}

std::string ApiMock::ResponseSerializer::serialize(ResponseData response) {
	const std::string CRLF = "\r\n";
	std::stringstream ss;

	// Status line
	ss << "HTTP/1.1 ";
	ss << std::to_string(response.statusCode) << " " << statusCodeDescription(response.statusCode);
	ss << CRLF;

	// Response headers
	for (auto header : response.headers)
		ss << header.first << ": " << header.second << CRLF;

	// Body
	ss << CRLF;
	ss << response.body;

	auto r = ss.str();
	return r;
}<|endoftext|>


<commit_before>/*

Copyright (c) 2003, Arvid Norberg
All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:

    * Redistributions of source code must retain the above copyright
      notice, this list of conditions and the following disclaimer.
    * Redistributions in binary form must reproduce the above copyright
      notice, this list of conditions and the following disclaimer in
      the documentation and/or other materials provided with the distribution.
    * Neither the name of the author nor the names of its
      contributors may be used to endorse or promote products derived
      from this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.

*/

#include "libtorrent/pch.hpp"

#include <vector>
#include <iostream>
#include <cctype>
#include <iomanip>
#include <sstream>
#include <algorithm>

#include "libtorrent/config.hpp"
#include "libtorrent/gzip.hpp"

#ifdef _MSC_VER
#pragma warning(push, 1)
#endif

#include <boost/bind.hpp>

#ifdef _MSC_VER
#pragma warning(pop)
#endif

#include "libtorrent/tracker_manager.hpp"
#include "libtorrent/http_tracker_connection.hpp"
#include "libtorrent/http_connection.hpp"
#include "libtorrent/entry.hpp"
#include "libtorrent/bencode.hpp"
#include "libtorrent/torrent.hpp"
#include "libtorrent/io.hpp"
#include "libtorrent/socket.hpp"

using namespace libtorrent;
using boost::bind;

namespace libtorrent
{

	http_tracker_connection::http_tracker_connection(
		io_service& ios
		, connection_queue& cc
		, tracker_manager& man
		, tracker_request const& req
		, address bind_infc
		, boost::weak_ptr<request_callback> c
		, session_settings const& stn
		, proxy_settings const& ps
		, std::string const& auth)
		: tracker_connection(man, req, ios, bind_infc, c)
		, m_man(man)
	{
		// TODO: authentication
		std::string url = req.url;

		if (req.kind == tracker_request::scrape_request)
		{
			// find and replace "announce" with "scrape"
			// in request

			std::size_t pos = url.find("announce");
			if (pos == std::string::npos)
			{
				fail(-1, ("scrape is not available on url: '"
					+ req.url +"'").c_str());
				return;
			}
			url.replace(pos, 8, "scrape");
		}

		// if request-string already contains
		// some parameters, append an ampersand instead
		// of a question mark
		size_t arguments_start = url.find('?');
		if (arguments_start != std::string::npos)
			url += "&";
		else
			url += "?";

		url += "info_hash=";
		url += escape_string(
			reinterpret_cast<const char*>(req.info_hash.begin()), 20);

		if (req.kind == tracker_request::announce_request)
		{
			url += "&peer_id=";
			url += escape_string(
				reinterpret_cast<const char*>(req.pid.begin()), 20);

			url += "&port=";
			url += boost::lexical_cast<std::string>(req.listen_port);

			url += "&uploaded=";
			url += boost::lexical_cast<std::string>(req.uploaded);

			url += "&downloaded=";
			url += boost::lexical_cast<std::string>(req.downloaded);

			url += "&left=";
			url += boost::lexical_cast<std::string>(req.left);

			if (req.event != tracker_request::none)
			{
				const char* event_string[] = {"completed", "started", "stopped"};
				url += "&event=";
				url += event_string[req.event - 1];
			}

			url += "&key=";
			std::stringstream key_string;
			key_string << std::hex << req.key;
			url += key_string.str();

			url += "&compact=1";

			url += "&numwant=";
			url += boost::lexical_cast<std::string>(
				(std::min)(req.num_want, 999));

			if (stn.announce_ip != address())
			{
				url += "&ip=";
				url += stn.announce_ip.to_string();
			}

#ifndef TORRENT_DISABLE_ENCRYPTION
			url += "&supportcrypto=1";
#endif
			url += "&ipv6=";
			url += req.ipv6;

			// extension that tells the tracker that
			// we don't need any peer_id's in the response
			url += "&no_peer_id=1";
		}

		m_tracker_connection.reset(new http_connection(ios, cc
			, boost::bind(&http_tracker_connection::on_response, self(), _1, _2, _3, _4)));

		int timeout = req.event==tracker_request::stopped
			?stn.stop_tracker_timeout
			:stn.tracker_completion_timeout;

		m_tracker_connection->get(url, seconds(timeout)
			, 1, &ps, 5, stn.user_agent, bind_infc);

#if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING)

		boost::shared_ptr<request_callback> cb = requester();
		if (cb)
		{
			cb->debug_log("==> TRACKER_REQUEST [ url: " + url + " ]");
		}
#endif
	}

	void http_tracker_connection::close()
	{
		if (m_tracker_connection)
		{
			m_tracker_connection->close();
			m_tracker_connection.reset();
		}
		tracker_connection::close();
	}

	void http_tracker_connection::on_response(error_code const& ec
		, http_parser const& parser, char const* data, int size)
	{
		// keep this alive
		boost::intrusive_ptr<http_tracker_connection> me(this);

		if (ec && ec != asio::error::eof)
		{
			fail(-1, ec.message().c_str());
			return;
		}

		if (!parser.header_finished())
		{
			fail(-1, "premature end of file");
			return;
		}

		if (parser.status_code() != 200)
		{
			fail(parser.status_code(), parser.message().c_str());
			return;
		}

		if (ec && ec != asio::error::eof)
		{
			fail(parser.status_code(), ec.message().c_str());
			return;
		}

		// handle tracker response
		entry e = bdecode(data, data + size);

		if (e.type() != entry::undefined_t)
		{
			parse(parser.status_code(), e);
		}
		else
		{
			std::string error_str("invalid bencoding of tracker response: \"");
			for (char const* i = data, *end(data + size); i != end; ++i)
			{
				if (std::isprint(*i)) error_str += *i;
				else error_str += "0x" + boost::lexical_cast<std::string>((unsigned int)*i) + " ";
			}
			error_str += "\"";
			fail(parser.status_code(), error_str.c_str());
		}
		close();
	}

	bool http_tracker_connection::extract_peer_info(const entry& info, peer_entry& ret)
	{
		// extract peer id (if any)
		if (info.type() != entry::dictionary_t)
		{
			fail(-1, "invalid response from tracker (invalid peer entry)");
			return false;
		}
		entry const* i = info.find_key("peer id");
		if (i != 0)
		{
			if (i->type() != entry::string_t || i->string().length() != 20)
			{
				fail(-1, "invalid response from tracker (invalid peer id)");
				return false;
			}
			std::copy(i->string().begin(), i->string().end(), ret.pid.begin());
		}
		else
		{
			// if there's no peer_id, just initialize it to a bunch of zeroes
			std::fill_n(ret.pid.begin(), 20, 0);
		}

		// extract ip
		i = info.find_key("ip");
		if (i == 0 || i->type() != entry::string_t)
		{
			fail(-1, "invalid response from tracker");
			return false;
		}
		ret.ip = i->string();

		// extract port
		i = info.find_key("port");
		if (i == 0 || i->type() != entry::int_t)
		{
			fail(-1, "invalid response from tracker");
			return false;
		}
		ret.port = (unsigned short)i->integer();

		return true;
	}

	void http_tracker_connection::parse(int status_code, entry const& e)
	{
		boost::shared_ptr<request_callback> cb = requester();
		if (!cb) return;

		// parse the response
		entry const* failure = e.find_key("failure reason");
		if (failure && failure->type() == entry::string_t)
		{
			fail(status_code, failure->string().c_str());
			return;
		}

		entry const* warning = e.find_key("warning message");
		if (warning && warning->type() == entry::string_t)
		{
			cb->tracker_warning(tracker_req(), warning->string());
		}

		std::vector<peer_entry> peer_list;

		if (tracker_req().kind == tracker_request::scrape_request)
		{
			std::string ih = tracker_req().info_hash.to_string();

			entry const* files = e.find_key("files");
			if (files == 0 || files->type() != entry::dictionary_t)
			{
				fail(-1, "invalid or missing 'files' entry in scrape response");
				return;
			}

			entry const* scrape_data = files->find_key(ih);
			if (scrape_data == 0 || scrape_data->type() != entry::dictionary_t)
			{
				fail(-1, "missing or invalid info-hash entry in scrape response");
				return;
			}
			entry const* complete = scrape_data->find_key("complete");
			entry const* incomplete = scrape_data->find_key("incomplete");
			entry const* downloaded = scrape_data->find_key("downloaded");
			if (complete == 0 || incomplete == 0 || downloaded == 0
				|| complete->type() != entry::int_t
				|| incomplete->type() != entry::int_t
				|| downloaded->type() != entry::int_t)
			{
				fail(-1, "missing 'complete' or 'incomplete' entries in scrape response");
				return;
			}
			cb->tracker_scrape_response(tracker_req(), int(complete->integer())
				, int(incomplete->integer()), int(downloaded->integer()));
			return;
		}

		entry const* interval = e.find_key("interval");
		if (interval == 0 || interval->type() != entry::int_t)
		{
			fail(-1, "missing or invalid 'interval' entry in tracker response");
			return;
		}

		entry const* peers_ent = e.find_key("peers");
		if (peers_ent == 0)
		{
			fail(-1, "missing 'peers' entry in tracker response");
			return;
		}

		if (peers_ent->type() == entry::string_t)
		{
			std::string const& peers = peers_ent->string();
			for (std::string::const_iterator i = peers.begin();
				i != peers.end();)
			{
				if (std::distance(i, peers.end()) < 6) break;

				peer_entry p;
				p.pid.clear();
				p.ip = detail::read_v4_address(i).to_string();
				p.port = detail::read_uint16(i);
				peer_list.push_back(p);
			}
		}
		else if (peers_ent->type() == entry::list_t)
		{
			entry::list_type const& l = peers_ent->list();
			for(entry::list_type::const_iterator i = l.begin(); i != l.end(); ++i)
			{
				peer_entry p;
				if (!extract_peer_info(*i, p)) return;
				peer_list.push_back(p);
			}
		}
		else
		{
			fail(-1, "invalid 'peers' entry in tracker response");
			return;
		}

		entry const* ipv6_peers = e.find_key("peers6");
		if (ipv6_peers && ipv6_peers->type() == entry::string_t)
		{
			std::string const& peers = ipv6_peers->string();
			for (std::string::const_iterator i = peers.begin();
				i != peers.end();)
			{
				if (std::distance(i, peers.end()) < 18) break;

				peer_entry p;
				p.pid.clear();
				p.ip = detail::read_v6_address(i).to_string();
				p.port = detail::read_uint16(i);
				peer_list.push_back(p);
			}
		}

		// look for optional scrape info
		int complete = -1;
		int incomplete = -1;
		address external_ip;

		entry const* ip_ent = e.find_key("external ip");
		if (ip_ent && ip_ent->type() == entry::string_t)
		{
			std::string const& ip = ip_ent->string();
			char const* p = &ip[0];
			if (ip.size() == address_v4::bytes_type::static_size)
				external_ip = detail::read_v4_address(p);
			else if (ip.size() == address_v6::bytes_type::static_size)
				external_ip = detail::read_v6_address(p);
		}

		entry const* complete_ent = e.find_key("complete");
		if (complete_ent && complete_ent->type() == entry::int_t)
			complete = int(complete_ent->integer());

		entry const* incomplete_ent = e.find_key("incomplete");
		if (incomplete_ent && incomplete_ent->type() == entry::int_t)
			incomplete = int(incomplete_ent->integer());

		cb->tracker_response(tracker_req(), peer_list, interval->integer(), complete
			, incomplete, external_ip);
	}

}

<commit_msg>fixed exception issue when tracker sends invalid response<commit_after>/*

Copyright (c) 2003, Arvid Norberg
All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:

    * Redistributions of source code must retain the above copyright
      notice, this list of conditions and the following disclaimer.
    * Redistributions in binary form must reproduce the above copyright
      notice, this list of conditions and the following disclaimer in
      the documentation and/or other materials provided with the distribution.
    * Neither the name of the author nor the names of its
      contributors may be used to endorse or promote products derived
      from this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.

*/

#include "libtorrent/pch.hpp"

#include <vector>
#include <iostream>
#include <cctype>
#include <iomanip>
#include <sstream>
#include <algorithm>

#include "libtorrent/config.hpp"
#include "libtorrent/gzip.hpp"

#ifdef _MSC_VER
#pragma warning(push, 1)
#endif

#include <boost/bind.hpp>

#ifdef _MSC_VER
#pragma warning(pop)
#endif

#include "libtorrent/tracker_manager.hpp"
#include "libtorrent/http_tracker_connection.hpp"
#include "libtorrent/http_connection.hpp"
#include "libtorrent/entry.hpp"
#include "libtorrent/bencode.hpp"
#include "libtorrent/torrent.hpp"
#include "libtorrent/io.hpp"
#include "libtorrent/socket.hpp"

using namespace libtorrent;
using boost::bind;

namespace libtorrent
{

	http_tracker_connection::http_tracker_connection(
		io_service& ios
		, connection_queue& cc
		, tracker_manager& man
		, tracker_request const& req
		, address bind_infc
		, boost::weak_ptr<request_callback> c
		, session_settings const& stn
		, proxy_settings const& ps
		, std::string const& auth)
		: tracker_connection(man, req, ios, bind_infc, c)
		, m_man(man)
	{
		// TODO: authentication
		std::string url = req.url;

		if (req.kind == tracker_request::scrape_request)
		{
			// find and replace "announce" with "scrape"
			// in request

			std::size_t pos = url.find("announce");
			if (pos == std::string::npos)
			{
				fail(-1, ("scrape is not available on url: '"
					+ req.url +"'").c_str());
				return;
			}
			url.replace(pos, 8, "scrape");
		}

		// if request-string already contains
		// some parameters, append an ampersand instead
		// of a question mark
		size_t arguments_start = url.find('?');
		if (arguments_start != std::string::npos)
			url += "&";
		else
			url += "?";

		url += "info_hash=";
		url += escape_string(
			reinterpret_cast<const char*>(req.info_hash.begin()), 20);

		if (req.kind == tracker_request::announce_request)
		{
			url += "&peer_id=";
			url += escape_string(
				reinterpret_cast<const char*>(req.pid.begin()), 20);

			url += "&port=";
			url += boost::lexical_cast<std::string>(req.listen_port);

			url += "&uploaded=";
			url += boost::lexical_cast<std::string>(req.uploaded);

			url += "&downloaded=";
			url += boost::lexical_cast<std::string>(req.downloaded);

			url += "&left=";
			url += boost::lexical_cast<std::string>(req.left);

			if (req.event != tracker_request::none)
			{
				const char* event_string[] = {"completed", "started", "stopped"};
				url += "&event=";
				url += event_string[req.event - 1];
			}

			url += "&key=";
			std::stringstream key_string;
			key_string << std::hex << req.key;
			url += key_string.str();

			url += "&compact=1";

			url += "&numwant=";
			url += boost::lexical_cast<std::string>(
				(std::min)(req.num_want, 999));

			if (stn.announce_ip != address())
			{
				url += "&ip=";
				url += stn.announce_ip.to_string();
			}

#ifndef TORRENT_DISABLE_ENCRYPTION
			url += "&supportcrypto=1";
#endif
			url += "&ipv6=";
			url += req.ipv6;

			// extension that tells the tracker that
			// we don't need any peer_id's in the response
			url += "&no_peer_id=1";
		}

		m_tracker_connection.reset(new http_connection(ios, cc
			, boost::bind(&http_tracker_connection::on_response, self(), _1, _2, _3, _4)));

		int timeout = req.event==tracker_request::stopped
			?stn.stop_tracker_timeout
			:stn.tracker_completion_timeout;

		m_tracker_connection->get(url, seconds(timeout)
			, 1, &ps, 5, stn.user_agent, bind_infc);

#if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING)

		boost::shared_ptr<request_callback> cb = requester();
		if (cb)
		{
			cb->debug_log("==> TRACKER_REQUEST [ url: " + url + " ]");
		}
#endif
	}

	void http_tracker_connection::close()
	{
		if (m_tracker_connection)
		{
			m_tracker_connection->close();
			m_tracker_connection.reset();
		}
		tracker_connection::close();
	}

	void http_tracker_connection::on_response(error_code const& ec
		, http_parser const& parser, char const* data, int size)
	{
		// keep this alive
		boost::intrusive_ptr<http_tracker_connection> me(this);

		if (ec && ec != asio::error::eof)
		{
			fail(-1, ec.message().c_str());
			return;
		}

		if (!parser.header_finished())
		{
			fail(-1, "premature end of file");
			return;
		}

		if (parser.status_code() != 200)
		{
			fail(parser.status_code(), parser.message().c_str());
			return;
		}

		if (ec && ec != asio::error::eof)
		{
			fail(parser.status_code(), ec.message().c_str());
			return;
		}

		// handle tracker response
		entry e;
#ifndef BOOST_NO_EXCEPTIONS
		try {
#endif
		e = bdecode(data, data + size);
#ifndef BOOST_NO_EXCEPTIONS
		} catch (std::exception&) {}
#endif

		if (e.type() != entry::undefined_t)
		{
			parse(parser.status_code(), e);
		}
		else
		{
			std::string error_str("invalid bencoding of tracker response: \"");
			for (char const* i = data, *end(data + size); i != end; ++i)
			{
				if (std::isprint(*i)) error_str += *i;
				else error_str += "0x" + boost::lexical_cast<std::string>((unsigned int)*i) + " ";
			}
			error_str += "\"";
			fail(parser.status_code(), error_str.c_str());
		}
		close();
	}

	bool http_tracker_connection::extract_peer_info(const entry& info, peer_entry& ret)
	{
		// extract peer id (if any)
		if (info.type() != entry::dictionary_t)
		{
			fail(-1, "invalid response from tracker (invalid peer entry)");
			return false;
		}
		entry const* i = info.find_key("peer id");
		if (i != 0)
		{
			if (i->type() != entry::string_t || i->string().length() != 20)
			{
				fail(-1, "invalid response from tracker (invalid peer id)");
				return false;
			}
			std::copy(i->string().begin(), i->string().end(), ret.pid.begin());
		}
		else
		{
			// if there's no peer_id, just initialize it to a bunch of zeroes
			std::fill_n(ret.pid.begin(), 20, 0);
		}

		// extract ip
		i = info.find_key("ip");
		if (i == 0 || i->type() != entry::string_t)
		{
			fail(-1, "invalid response from tracker");
			return false;
		}
		ret.ip = i->string();

		// extract port
		i = info.find_key("port");
		if (i == 0 || i->type() != entry::int_t)
		{
			fail(-1, "invalid response from tracker");
			return false;
		}
		ret.port = (unsigned short)i->integer();

		return true;
	}

	void http_tracker_connection::parse(int status_code, entry const& e)
	{
		boost::shared_ptr<request_callback> cb = requester();
		if (!cb) return;

		// parse the response
		entry const* failure = e.find_key("failure reason");
		if (failure && failure->type() == entry::string_t)
		{
			fail(status_code, failure->string().c_str());
			return;
		}

		entry const* warning = e.find_key("warning message");
		if (warning && warning->type() == entry::string_t)
		{
			cb->tracker_warning(tracker_req(), warning->string());
		}

		std::vector<peer_entry> peer_list;

		if (tracker_req().kind == tracker_request::scrape_request)
		{
			std::string ih = tracker_req().info_hash.to_string();

			entry const* files = e.find_key("files");
			if (files == 0 || files->type() != entry::dictionary_t)
			{
				fail(-1, "invalid or missing 'files' entry in scrape response");
				return;
			}

			entry const* scrape_data = files->find_key(ih);
			if (scrape_data == 0 || scrape_data->type() != entry::dictionary_t)
			{
				fail(-1, "missing or invalid info-hash entry in scrape response");
				return;
			}
			entry const* complete = scrape_data->find_key("complete");
			entry const* incomplete = scrape_data->find_key("incomplete");
			entry const* downloaded = scrape_data->find_key("downloaded");
			if (complete == 0 || incomplete == 0 || downloaded == 0
				|| complete->type() != entry::int_t
				|| incomplete->type() != entry::int_t
				|| downloaded->type() != entry::int_t)
			{
				fail(-1, "missing 'complete' or 'incomplete' entries in scrape response");
				return;
			}
			cb->tracker_scrape_response(tracker_req(), int(complete->integer())
				, int(incomplete->integer()), int(downloaded->integer()));
			return;
		}

		entry const* interval = e.find_key("interval");
		if (interval == 0 || interval->type() != entry::int_t)
		{
			fail(-1, "missing or invalid 'interval' entry in tracker response");
			return;
		}

		entry const* peers_ent = e.find_key("peers");
		if (peers_ent == 0)
		{
			fail(-1, "missing 'peers' entry in tracker response");
			return;
		}

		if (peers_ent->type() == entry::string_t)
		{
			std::string const& peers = peers_ent->string();
			for (std::string::const_iterator i = peers.begin();
				i != peers.end();)
			{
				if (std::distance(i, peers.end()) < 6) break;

				peer_entry p;
				p.pid.clear();
				p.ip = detail::read_v4_address(i).to_string();
				p.port = detail::read_uint16(i);
				peer_list.push_back(p);
			}
		}
		else if (peers_ent->type() == entry::list_t)
		{
			entry::list_type const& l = peers_ent->list();
			for(entry::list_type::const_iterator i = l.begin(); i != l.end(); ++i)
			{
				peer_entry p;
				if (!extract_peer_info(*i, p)) return;
				peer_list.push_back(p);
			}
		}
		else
		{
			fail(-1, "invalid 'peers' entry in tracker response");
			return;
		}

		entry const* ipv6_peers = e.find_key("peers6");
		if (ipv6_peers && ipv6_peers->type() == entry::string_t)
		{
			std::string const& peers = ipv6_peers->string();
			for (std::string::const_iterator i = peers.begin();
				i != peers.end();)
			{
				if (std::distance(i, peers.end()) < 18) break;

				peer_entry p;
				p.pid.clear();
				p.ip = detail::read_v6_address(i).to_string();
				p.port = detail::read_uint16(i);
				peer_list.push_back(p);
			}
		}

		// look for optional scrape info
		int complete = -1;
		int incomplete = -1;
		address external_ip;

		entry const* ip_ent = e.find_key("external ip");
		if (ip_ent && ip_ent->type() == entry::string_t)
		{
			std::string const& ip = ip_ent->string();
			char const* p = &ip[0];
			if (ip.size() == address_v4::bytes_type::static_size)
				external_ip = detail::read_v4_address(p);
			else if (ip.size() == address_v6::bytes_type::static_size)
				external_ip = detail::read_v6_address(p);
		}

		entry const* complete_ent = e.find_key("complete");
		if (complete_ent && complete_ent->type() == entry::int_t)
			complete = int(complete_ent->integer());

		entry const* incomplete_ent = e.find_key("incomplete");
		if (incomplete_ent && incomplete_ent->type() == entry::int_t)
			incomplete = int(incomplete_ent->integer());

		cb->tracker_response(tracker_req(), peer_list, interval->integer(), complete
			, incomplete, external_ip);
	}

}

<|endoftext|>


<commit_before>/******************************************************************************
 * The MIT License (MIT)
 *
 * Copyright (c) 2019-2021 Baldur Karlsson
 *
 * 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 "RGPInterop.h"
#include <QApplication>
#include <QTcpServer>
#include <QTcpSocket>

bool RGPInterop::RGPSupportsInterop(const QString &RGPPath)
{
  uint32_t majorVersion = 0;
  uint32_t minorVersion = 0;

  const char *searchString = "RGPVersion=";
  const int searchStringLength = (int)strlen(searchString);

  // look for an embedded string in the exe
  QFile f(RGPPath);
  if(f.open(QIODevice::ReadOnly))
  {
    QByteArray contents = f.readAll();

    int search = 0;
    do
    {
      int needle = contents.indexOf("RGPVersion=", search);

      if(needle == -1)
        break;

      search = needle + searchStringLength;

      // bail if there isn't enough room for the string plus X.Y
      if(contents.size() - needle < searchStringLength + 3)
        break;

      // get the major version number
      const char *major = contents.data() + search;

      const char *sep = major;

      // find the separator
      while(*sep >= '0' && *sep <= '9')
        sep++;

      // get the minor version number
      const char *minor = sep + 1;

      const char *end = minor;

      // find the end
      while(*end >= '0' && *end <= '9')
        end++;

      // convert the strings to integers
      QByteArray majorStr(major, sep - major);
      QByteArray minorStr(minor, end - minor);

      bool ok = false;
      majorVersion = majorStr.toUInt(&ok);

      if(!ok)
      {
        majorVersion = 0;
        continue;
      }

      minorVersion = minorStr.toUInt(&ok);

      if(!ok)
      {
        majorVersion = minorVersion = 0;
        continue;
      }

      // found the version
      break;

    } while(search >= 0);
  }

  // interop supported in RGP V1.2 and higher
  if(majorVersion > 1 || (majorVersion == 1 && minorVersion > 1))
  {
    return true;
  }

  return false;
}

template <>
rdcstr DoStringise(const RGPCommand &el)
{
  BEGIN_ENUM_STRINGISE(RGPCommand);
  {
    STRINGISE_ENUM_CLASS_NAMED(Initialize, "initialize");
    STRINGISE_ENUM_CLASS_NAMED(SetEvent, "set_event");
    STRINGISE_ENUM_CLASS_NAMED(Terminate, "terminate");
  }
  END_ENUM_STRINGISE();
}

RGPInterop::RGPInterop(ICaptureContext &ctx) : m_Ctx(ctx)
{
  m_Server = new QTcpServer(NULL);
  m_Server->listen(QHostAddress::Any, Port);

  QObject::connect(m_Server, &QTcpServer::newConnection, [this]() {
    if(m_Socket == NULL)
    {
      m_Socket = m_Server->nextPendingConnection();
      ConnectionEstablished();
    }
    else
    {
      // close any other connections while we already have one
      delete m_Server->nextPendingConnection();
    }
  });
}

RGPInterop::~RGPInterop()
{
  RGPInteropTerminate terminate;
  QString encoded = EncodeCommand(RGPCommand::Terminate, terminate.toParams(m_Version));

  if(m_Socket)
  {
    m_Socket->write(encoded.trimmed().toUtf8().data());
    m_Socket->waitForBytesWritten();
  }

  m_Server->close();
  delete m_Server;
}

void RGPInterop::InitializeRGP()
{
  RGPInteropInit init;

  init.interop_version = 1;
  init.interop_name = lit("RenderDoc");

  QString encoded = EncodeCommand(RGPCommand::Initialize, init.toParams(m_Version));

  if(m_Socket)
  {
    m_Socket->write(encoded.trimmed().toUtf8().data());
  }
}

bool RGPInterop::HasRGPEvent(uint32_t eventId)
{
  if(m_Version == 0)
    return false;

  if(m_Socket == NULL)
    return false;

  return m_Event2RGP[eventId].interoplinearid != 0;
}

bool RGPInterop::SelectRGPEvent(uint32_t eventId)
{
  if(m_Version == 0)
    return false;

  RGPInteropEvent ev = m_Event2RGP[eventId];

  if(ev.interoplinearid == 0)
    return false;

  QString encoded = EncodeCommand(RGPCommand::SetEvent, ev.toParams(m_Version));

  if(m_Socket)
  {
    m_Socket->write(encoded.trimmed().toUtf8().data());
    return true;
  }

  return false;
}

void RGPInterop::EventSelected(RGPInteropEvent event)
{
  uint32_t eventId = m_RGP2Event[event.interoplinearid];

  if(eventId == 0)
  {
    qWarning() << "RGP Event " << event.interoplinearid << event.cmdbufid << event.eventname
               << " did not correspond to a known eventId";
    return;
  }

  const ActionDescription *action = m_Ctx.GetAction(eventId);

  const SDFile &file = m_Ctx.GetStructuredFile();

  if(action && QString(file.chunks[action->events.back().chunkIndex]->name) != event.eventname)
    qWarning() << "Action name mismatch. Expected " << event.eventname << " but got "
               << QString(file.chunks[action->events.back().chunkIndex]->name);

  m_Ctx.SetEventID({}, eventId, eventId);

  BringToForeground(m_Ctx.GetMainWindow()->Widget());
}

void RGPInterop::ConnectionEstablished()
{
  QObject::connect(m_Socket, &QAbstractSocket::disconnected, [this]() {
    m_Socket->deleteLater();
    m_Socket = NULL;
  });

  // initial handshake and protocol version
  InitializeRGP();

  // TODO: negotiate mapping version
  uint32_t version = 1;
  CreateMapping(version);

  // add a handler that appends all data to the read buffer and processes each time more comes in.
  QObject::connect(m_Socket, &QIODevice::readyRead, [this]() {
    // append all available data
    m_ReadBuffer += m_Socket->readAll();

    // process the read buffer
    ProcessReadBuffer();
  });
}

void RGPInterop::CreateMapping(const rdcarray<ActionDescription> &actions)
{
  const SDFile &file = m_Ctx.GetStructuredFile();

  for(const ActionDescription &action : actions)
  {
    for(const APIEvent &ev : action.events)
    {
      if(ev.chunkIndex == 0 || ev.chunkIndex == APIEvent::NoChunk ||
         ev.chunkIndex >= file.chunks.size())
        continue;

      const SDChunk *chunk = file.chunks[ev.chunkIndex];

      if(m_EventNames.contains(chunk->name, Qt::CaseSensitive))
      {
        m_Event2RGP[ev.eventId].interoplinearid = (uint32_t)m_RGP2Event.size();
        rdcstr n = chunk->name;
        if(n.contains(':'))
          n.erase(0, n.find_last_of(":") + 1);
        n += "(";
        bool first = true;
        for(size_t i = 0; i < chunk->NumChildren(); i++)
        {
          const SDObject *o = chunk->GetChild(i);
          if(o->type.flags & SDTypeFlags::Important)
          {
            if(first)
              n += ", ";
            first = false;
            n += ToStr(o->AsUInt32());
          }
        }
        n += ")";

        m_Event2RGP[ev.eventId].eventname = n;

        m_RGP2Event.push_back(ev.eventId);
      }
    }

    // if we have children, step into them first before going to our next sibling
    if(!action.children.empty())
      CreateMapping(action.children);
  }
}

void RGPInterop::CreateMapping(uint32_t version)
{
  m_Version = version;

  if(m_Ctx.APIProps().pipelineType == GraphicsAPI::Vulkan)
  {
    if(version == 1)
    {
      m_EventNames << lit("vkCmdDispatch") << lit("vkCmdDraw") << lit("vkCmdDrawIndexed");
    }
  }
  else if(m_Ctx.APIProps().pipelineType == GraphicsAPI::D3D12)
  {
    // these names must match those in DoStringise(const D3D12Chunk &el) for the chunks

    if(version == 1)
    {
      m_EventNames << lit("ID3D12GraphicsCommandList::Dispatch")
                   << lit("ID3D12GraphicsCommandList::DrawInstanced")
                   << lit("ID3D12GraphicsCommandList::DrawIndexedInstanced");
    }
  }

  // if we don't have any event names, this API doesn't have a mapping or this was an unrecognised
  // version.
  if(m_EventNames.isEmpty())
    return;

  m_Event2RGP.resize(m_Ctx.GetLastAction()->eventId + 1);

  // linearId 0 is invalid, so map to eventId 0.
  // the first real event will be linearId 1
  m_RGP2Event.push_back(0);

  CreateMapping(m_Ctx.CurRootActions());
}

QString RGPInterop::EncodeCommand(RGPCommand command, QVariantList params)
{
  QString ret;

  QString cmd = ToQStr(command);

  ret += lit("command=%1\n").arg(cmd);

  // iterate params in pair, name and value
  for(int i = 0; i + 1 < params.count(); i += 2)
    ret += QFormatStr("%1.%2=%3\n").arg(cmd).arg(params[i].toString()).arg(params[i + 1].toString());

  ret += lit("endcommand=%1\n").arg(cmd);

  return ret;
}

bool RGPInterop::DecodeCommand(QString command)
{
  QStringList lines = command.trimmed().split(QLatin1Char('\n'));

  if(lines[0].indexOf(lit("command=")) != 0 || lines.last().indexOf(lit("endcommand=")) != 0)
  {
    qWarning() << "Malformed RGP command:\n" << command;
    return false;
  }

  QString commandName = lines[0].split(QLatin1Char('='))[1];

  if(lines.last().split(QLatin1Char('='))[1] != commandName)
  {
    qWarning() << "Mismatch between command and endcommand:\n" << command;
    return false;
  }

  lines.pop_front();
  lines.pop_back();

  QVariantList params;

  QString prefix = commandName + lit(".");

  for(QString &param : lines)
  {
    int eq = param.indexOf(QLatin1Char('='));

    if(eq < 0)
    {
      qWarning() << "Malformed param: " << param;
      continue;
    }

    QString key = param.left(eq);
    QString value = param.mid(eq + 1);

    if(!key.startsWith(prefix))
    {
      qWarning() << "Malformed param key for" << commandName << ": " << key;
      continue;
    }

    key = key.mid(prefix.count());

    params << key << value;
  }

  if(commandName == ToQStr(RGPCommand::SetEvent))
  {
    RGPInteropEvent ev;
    ev.fromParams(m_Version, params);

    EventSelected(ev);

    return true;
  }
  else if(commandName == ToQStr(RGPCommand::Initialize))
  {
    RGPInteropInit init;
    init.fromParams(m_Version, params);

    // TODO: decode the params here. This will contain the interop
    // version and the name of the tool connected to RenderDoc

    return true;
  }
  else if(commandName == ToQStr(RGPCommand::Terminate))
  {
    // RGP has shut down so disconnect the socket etc
    emit m_Socket->disconnected();
    return true;
  }
  else
  {
    qWarning() << "Unrecognised command: " << commandName;
  }

  return false;
}

void RGPInterop::ProcessReadBuffer()
{
  // we might have partial data, so wait until we have a full command
  do
  {
    int idx = m_ReadBuffer.indexOf("endcommand=");

    // if we don't have endcommand= yet, we don't have a full command
    if(idx < 0)
      return;

    idx = m_ReadBuffer.indexOf('\n', idx);

    // also break if we don't have the full line yet including newline.
    if(idx < 0)
      return;

    // extract the command and decode as UTF-8
    QString command = QString::fromUtf8(m_ReadBuffer.data(), idx + 1);

    // remove the command from our buffer, to retain any partial subsequent command we might have
    m_ReadBuffer.remove(0, idx + 1);

    // process this command
    DecodeCommand(command);

    // loop again - we might have read multiple commands
  } while(true);
}
<commit_msg>Fix parameter generation for RGP event names<commit_after>/******************************************************************************
 * The MIT License (MIT)
 *
 * Copyright (c) 2019-2021 Baldur Karlsson
 *
 * 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 "RGPInterop.h"
#include <QApplication>
#include <QTcpServer>
#include <QTcpSocket>

bool RGPInterop::RGPSupportsInterop(const QString &RGPPath)
{
  uint32_t majorVersion = 0;
  uint32_t minorVersion = 0;

  const char *searchString = "RGPVersion=";
  const int searchStringLength = (int)strlen(searchString);

  // look for an embedded string in the exe
  QFile f(RGPPath);
  if(f.open(QIODevice::ReadOnly))
  {
    QByteArray contents = f.readAll();

    int search = 0;
    do
    {
      int needle = contents.indexOf("RGPVersion=", search);

      if(needle == -1)
        break;

      search = needle + searchStringLength;

      // bail if there isn't enough room for the string plus X.Y
      if(contents.size() - needle < searchStringLength + 3)
        break;

      // get the major version number
      const char *major = contents.data() + search;

      const char *sep = major;

      // find the separator
      while(*sep >= '0' && *sep <= '9')
        sep++;

      // get the minor version number
      const char *minor = sep + 1;

      const char *end = minor;

      // find the end
      while(*end >= '0' && *end <= '9')
        end++;

      // convert the strings to integers
      QByteArray majorStr(major, sep - major);
      QByteArray minorStr(minor, end - minor);

      bool ok = false;
      majorVersion = majorStr.toUInt(&ok);

      if(!ok)
      {
        majorVersion = 0;
        continue;
      }

      minorVersion = minorStr.toUInt(&ok);

      if(!ok)
      {
        majorVersion = minorVersion = 0;
        continue;
      }

      // found the version
      break;

    } while(search >= 0);
  }

  // interop supported in RGP V1.2 and higher
  if(majorVersion > 1 || (majorVersion == 1 && minorVersion > 1))
  {
    return true;
  }

  return false;
}

template <>
rdcstr DoStringise(const RGPCommand &el)
{
  BEGIN_ENUM_STRINGISE(RGPCommand);
  {
    STRINGISE_ENUM_CLASS_NAMED(Initialize, "initialize");
    STRINGISE_ENUM_CLASS_NAMED(SetEvent, "set_event");
    STRINGISE_ENUM_CLASS_NAMED(Terminate, "terminate");
  }
  END_ENUM_STRINGISE();
}

RGPInterop::RGPInterop(ICaptureContext &ctx) : m_Ctx(ctx)
{
  m_Server = new QTcpServer(NULL);
  m_Server->listen(QHostAddress::Any, Port);

  QObject::connect(m_Server, &QTcpServer::newConnection, [this]() {
    if(m_Socket == NULL)
    {
      m_Socket = m_Server->nextPendingConnection();
      ConnectionEstablished();
    }
    else
    {
      // close any other connections while we already have one
      delete m_Server->nextPendingConnection();
    }
  });
}

RGPInterop::~RGPInterop()
{
  RGPInteropTerminate terminate;
  QString encoded = EncodeCommand(RGPCommand::Terminate, terminate.toParams(m_Version));

  if(m_Socket)
  {
    m_Socket->write(encoded.trimmed().toUtf8().data());
    m_Socket->waitForBytesWritten();
  }

  m_Server->close();
  delete m_Server;
}

void RGPInterop::InitializeRGP()
{
  RGPInteropInit init;

  init.interop_version = 1;
  init.interop_name = lit("RenderDoc");

  QString encoded = EncodeCommand(RGPCommand::Initialize, init.toParams(m_Version));

  if(m_Socket)
  {
    m_Socket->write(encoded.trimmed().toUtf8().data());
  }
}

bool RGPInterop::HasRGPEvent(uint32_t eventId)
{
  if(m_Version == 0)
    return false;

  if(m_Socket == NULL)
    return false;

  return m_Event2RGP[eventId].interoplinearid != 0;
}

bool RGPInterop::SelectRGPEvent(uint32_t eventId)
{
  if(m_Version == 0)
    return false;

  RGPInteropEvent ev = m_Event2RGP[eventId];

  if(ev.interoplinearid == 0)
    return false;

  QString encoded = EncodeCommand(RGPCommand::SetEvent, ev.toParams(m_Version));

  if(m_Socket)
  {
    m_Socket->write(encoded.trimmed().toUtf8().data());
    return true;
  }

  return false;
}

void RGPInterop::EventSelected(RGPInteropEvent event)
{
  uint32_t eventId = m_RGP2Event[event.interoplinearid];

  if(eventId == 0)
  {
    qWarning() << "RGP Event " << event.interoplinearid << event.cmdbufid << event.eventname
               << " did not correspond to a known eventId";
    return;
  }

  const ActionDescription *action = m_Ctx.GetAction(eventId);

  const SDFile &file = m_Ctx.GetStructuredFile();

  if(action && QString(file.chunks[action->events.back().chunkIndex]->name) != event.eventname)
    qWarning() << "Action name mismatch. Expected " << event.eventname << " but got "
               << QString(file.chunks[action->events.back().chunkIndex]->name);

  m_Ctx.SetEventID({}, eventId, eventId);

  BringToForeground(m_Ctx.GetMainWindow()->Widget());
}

void RGPInterop::ConnectionEstablished()
{
  QObject::connect(m_Socket, &QAbstractSocket::disconnected, [this]() {
    m_Socket->deleteLater();
    m_Socket = NULL;
  });

  // initial handshake and protocol version
  InitializeRGP();

  // TODO: negotiate mapping version
  uint32_t version = 1;
  CreateMapping(version);

  // add a handler that appends all data to the read buffer and processes each time more comes in.
  QObject::connect(m_Socket, &QIODevice::readyRead, [this]() {
    // append all available data
    m_ReadBuffer += m_Socket->readAll();

    // process the read buffer
    ProcessReadBuffer();
  });
}

void RGPInterop::CreateMapping(const rdcarray<ActionDescription> &actions)
{
  const SDFile &file = m_Ctx.GetStructuredFile();

  for(const ActionDescription &action : actions)
  {
    for(const APIEvent &ev : action.events)
    {
      if(ev.chunkIndex == 0 || ev.chunkIndex == APIEvent::NoChunk ||
         ev.chunkIndex >= file.chunks.size())
        continue;

      const SDChunk *chunk = file.chunks[ev.chunkIndex];

      if(m_EventNames.contains(chunk->name, Qt::CaseSensitive))
      {
        m_Event2RGP[ev.eventId].interoplinearid = (uint32_t)m_RGP2Event.size();
        rdcstr n = chunk->name;
        if(n.contains(':'))
          n.erase(0, n.find_last_of(":") + 1);
        n += "(";
        bool first = true;
        for(size_t i = 0; i < chunk->NumChildren(); i++)
        {
          const SDObject *o = chunk->GetChild(i);
          if(o->type.flags & SDTypeFlags::Important)
          {
            if(!first)
              n += ", ";
            first = false;
            n += ToStr(o->AsUInt32());
          }
        }
        n += ")";

        m_Event2RGP[ev.eventId].eventname = n;

        m_RGP2Event.push_back(ev.eventId);
      }
    }

    // if we have children, step into them first before going to our next sibling
    if(!action.children.empty())
      CreateMapping(action.children);
  }
}

void RGPInterop::CreateMapping(uint32_t version)
{
  m_Version = version;

  if(m_Ctx.APIProps().pipelineType == GraphicsAPI::Vulkan)
  {
    if(version == 1)
    {
      m_EventNames << lit("vkCmdDispatch") << lit("vkCmdDraw") << lit("vkCmdDrawIndexed");
    }
  }
  else if(m_Ctx.APIProps().pipelineType == GraphicsAPI::D3D12)
  {
    // these names must match those in DoStringise(const D3D12Chunk &el) for the chunks

    if(version == 1)
    {
      m_EventNames << lit("ID3D12GraphicsCommandList::Dispatch")
                   << lit("ID3D12GraphicsCommandList::DrawInstanced")
                   << lit("ID3D12GraphicsCommandList::DrawIndexedInstanced");
    }
  }

  // if we don't have any event names, this API doesn't have a mapping or this was an unrecognised
  // version.
  if(m_EventNames.isEmpty())
    return;

  m_Event2RGP.resize(m_Ctx.GetLastAction()->eventId + 1);

  // linearId 0 is invalid, so map to eventId 0.
  // the first real event will be linearId 1
  m_RGP2Event.push_back(0);

  CreateMapping(m_Ctx.CurRootActions());
}

QString RGPInterop::EncodeCommand(RGPCommand command, QVariantList params)
{
  QString ret;

  QString cmd = ToQStr(command);

  ret += lit("command=%1\n").arg(cmd);

  // iterate params in pair, name and value
  for(int i = 0; i + 1 < params.count(); i += 2)
    ret += QFormatStr("%1.%2=%3\n").arg(cmd).arg(params[i].toString()).arg(params[i + 1].toString());

  ret += lit("endcommand=%1\n").arg(cmd);

  return ret;
}

bool RGPInterop::DecodeCommand(QString command)
{
  QStringList lines = command.trimmed().split(QLatin1Char('\n'));

  if(lines[0].indexOf(lit("command=")) != 0 || lines.last().indexOf(lit("endcommand=")) != 0)
  {
    qWarning() << "Malformed RGP command:\n" << command;
    return false;
  }

  QString commandName = lines[0].split(QLatin1Char('='))[1];

  if(lines.last().split(QLatin1Char('='))[1] != commandName)
  {
    qWarning() << "Mismatch between command and endcommand:\n" << command;
    return false;
  }

  lines.pop_front();
  lines.pop_back();

  QVariantList params;

  QString prefix = commandName + lit(".");

  for(QString &param : lines)
  {
    int eq = param.indexOf(QLatin1Char('='));

    if(eq < 0)
    {
      qWarning() << "Malformed param: " << param;
      continue;
    }

    QString key = param.left(eq);
    QString value = param.mid(eq + 1);

    if(!key.startsWith(prefix))
    {
      qWarning() << "Malformed param key for" << commandName << ": " << key;
      continue;
    }

    key = key.mid(prefix.count());

    params << key << value;
  }

  if(commandName == ToQStr(RGPCommand::SetEvent))
  {
    RGPInteropEvent ev;
    ev.fromParams(m_Version, params);

    EventSelected(ev);

    return true;
  }
  else if(commandName == ToQStr(RGPCommand::Initialize))
  {
    RGPInteropInit init;
    init.fromParams(m_Version, params);

    // TODO: decode the params here. This will contain the interop
    // version and the name of the tool connected to RenderDoc

    return true;
  }
  else if(commandName == ToQStr(RGPCommand::Terminate))
  {
    // RGP has shut down so disconnect the socket etc
    emit m_Socket->disconnected();
    return true;
  }
  else
  {
    qWarning() << "Unrecognised command: " << commandName;
  }

  return false;
}

void RGPInterop::ProcessReadBuffer()
{
  // we might have partial data, so wait until we have a full command
  do
  {
    int idx = m_ReadBuffer.indexOf("endcommand=");

    // if we don't have endcommand= yet, we don't have a full command
    if(idx < 0)
      return;

    idx = m_ReadBuffer.indexOf('\n', idx);

    // also break if we don't have the full line yet including newline.
    if(idx < 0)
      return;

    // extract the command and decode as UTF-8
    QString command = QString::fromUtf8(m_ReadBuffer.data(), idx + 1);

    // remove the command from our buffer, to retain any partial subsequent command we might have
    m_ReadBuffer.remove(0, idx + 1);

    // process this command
    DecodeCommand(command);

    // loop again - we might have read multiple commands
  } while(true);
}
<|endoftext|>


<commit_before>#include "resizeHandler.h"

#include <algorithm>

ResizeHandler::ResizeHandler(
		NodeElement* const resizingNode
		, ElementImpl* const elementImpl
		)
	: mResizingNode(resizingNode)
	, mElementImpl(elementImpl)
{
}

void ResizeHandler::resize(QRectF newContents, QPointF newPos) const
{
	newContents.moveTo(0, 0);

	sortChildrenIfNeeded();
	gripeIfMinimizesToChildrenContainer(newContents);

	if (!mResizingNode->isFolded()) {
		resizeAccordingToChildren(newContents, newPos);
	}

	normalizeSize(newContents);

	newContents.moveTo(newPos);
	mResizingNode->setGeometry(newContents);
	mResizingNode->storeGeometry();

	parentResizeCall();

	if (SettingsManager::value("ActivateGrid").toBool()) {
		mResizingNode->alignToGrid();
	}
}

qreal ResizeHandler::maxChildWidth() const
{
	qreal maxChildWidthValue = 0;

	foreach (const QGraphicsItem* const childItem, mResizingNode->childItems()) {
		const NodeElement* const curItem = dynamic_cast<const NodeElement* const>(childItem);
		if (!curItem) {
			continue;
		}

		maxChildWidthValue = std::max(maxChildWidthValue, curItem->contents().width());
	}
	if (maxChildWidthValue == 0) {
		maxChildWidthValue = mResizingNode->childrenBoundingRect().width();
	}

	return maxChildWidthValue;
}

void ResizeHandler::sortChildrenIfNeeded() const
{
	if (!mElementImpl->isSortingContainer()) {
		return;
	}

	int const sizeOfForestalling = mElementImpl->sizeOfForestalling();
	qreal curChildY = sizeOfForestalling + mTitlePadding;
	qreal maxChildWidthValue = maxChildWidth();

	foreach (QGraphicsItem* const childItem, mResizingNode->childItems()) {
		QGraphicsRectItem* const placeholder = mResizingNode->placeholder();

		if(placeholder != NULL && childItem == placeholder){
			QRectF const rect(sizeOfForestalling, curChildY,
				maxChildWidthValue, placeholder->rect().height());
			placeholder->setRect(rect);
			curChildY += placeholder->rect().height() + mChildSpacing;
		}

		NodeElement* const curItem = dynamic_cast<NodeElement* const>(childItem);
		if (!curItem) {
			continue;
		}

		qreal const necessaryWidth =
			mElementImpl->maximizesChildren()
			? maxChildWidthValue
			: curItem->contents().width();
		QRectF const rect(sizeOfForestalling, curChildY, necessaryWidth, curItem->contents().height());

		curItem->setGeometry(rect);
		curItem->storeGeometry();
		curChildY += curItem->contents().height() + mElementImpl->sizeOfChildrenForestalling() + mChildSpacing;
	}
}

void ResizeHandler::gripeIfMinimizesToChildrenContainer(QRectF& contents) const
{
	if (mElementImpl->minimizesToChildren()) {
		contents = QRectF();
	}
}

void ResizeHandler::parentResizeCall() const {
	NodeElement* const parItem = dynamic_cast<NodeElement* const>(mResizingNode->parentItem());
	if (parItem) {
		ResizeHandler handler(parItem, parItem->elementImpl());
		handler.resize(parItem->contents(), parItem->pos());
	}
}

void ResizeHandler::normalizeSize(QRectF& newContents) const {
	if (newContents.width() < mMinSize) {
		newContents.setWidth(mResizingNode->foldedContents().width());
	}

	if (newContents.height() < mMinSize) {
		newContents.setHeight(mResizingNode->foldedContents().height());
	}
}

void ResizeHandler::resizeAccordingToChildren(QRectF& newContents, QPointF& newPos) const {
	/*
	* AAAA!!! Who knows why is this code existed????!!!
	*
	foreach (QGraphicsItem *childItem, childItems()) {
		NodeElement* curItem = dynamic_cast<NodeElement*>(childItem);
		if (curItem && curItem->isPort() && newContents != mContents) {
			curItem->resizeChild(newContents, mContents);
		}
	}
	*/

	/// Vector of minimum negative XY child deflection from top left corner.
	QPointF const childDeflectionVector = childDeflection();

	moveChildren(-childDeflectionVector);
	//newPos += childDeflectionVector;

	expandByChildren(newContents);
}

QPointF ResizeHandler::childDeflection() const
{
	QPointF childDeflectionVector = QPointF(0, 0);
	int const sizeOfForestalling = mElementImpl->sizeOfForestalling();

	foreach (const QGraphicsItem* const childItem, mResizingNode->childItems()) {
		const NodeElement* const curItem = dynamic_cast<const NodeElement* const>(childItem);
		if (!curItem || curItem->isPort()) {
			continue;
		}

		childDeflectionVector.setX(
				std::min(curItem->pos().x() - sizeOfForestalling, childDeflectionVector.x())
				);
		childDeflectionVector.setY(
				std::min(curItem->pos().y() - sizeOfForestalling, childDeflectionVector.y())
				);
	}

	return childDeflectionVector;
}

void ResizeHandler::moveChildren(QPointF const &shift) const
{
	qreal const sizeOfForestalling = mElementImpl->sizeOfForestalling();

	foreach (QGraphicsItem* const childItem, mResizingNode->childItems()) {
		NodeElement* const curItem = dynamic_cast<NodeElement* const>(childItem);
		if (!curItem || !curItem->isPort()) {
			continue;
		}

		curItem->moveBy(shift.x(), shift.y());

		QPointF pos(
				std::max(curItem->pos().x(), sizeOfForestalling)
				, std::max(curItem->pos().y(), sizeOfForestalling)
			);
		///returns object to the parent area
		curItem->setPos(pos);
	}
}

void ResizeHandler::expandByChildren(QRectF& contents) const
{
	int const sizeOfForestalling = mElementImpl->sizeOfForestalling();

	foreach (const QGraphicsItem* const childItem, mResizingNode->childItems()) {
		QRectF curChildItemBoundingRect = childBoundingRect(childItem, contents);

		if (
			curChildItemBoundingRect.width() == 0
			||
			curChildItemBoundingRect.height() == 0
		) {
			continue;
		}

		// it seems to be more appropriate to use childItem->pos() but it causes
		// bad behaviour when dropping one element to another
		curChildItemBoundingRect.translate(childItem->scenePos() - mResizingNode->scenePos());

		contents.setLeft(
				std::min(curChildItemBoundingRect.left() - sizeOfForestalling
				       	, contents.left())
				);

		contents.setRight(
				std::max(curChildItemBoundingRect.right() + sizeOfForestalling
				       	, contents.right())
				);

		contents.setTop(
				std::min(curChildItemBoundingRect.top() - sizeOfForestalling
				       	, contents.top())
				);

		contents.setBottom(
				std::max(curChildItemBoundingRect.bottom() + sizeOfForestalling
				       	, contents.bottom())
				);
	}
}

QRectF ResizeHandler::childBoundingRect(const QGraphicsItem* const childItem, QRectF const &contents) const
{
	QRectF boundingRect;

	if (childItem == mResizingNode->placeholder()) {
		boundingRect = childItem->boundingRect();

		int const sizeOfForestalling = mElementImpl->sizeOfForestalling();
		boundingRect.setLeft(contents.left() + sizeOfForestalling);
		boundingRect.setRight(contents.right() - sizeOfForestalling);

		return boundingRect;
	}

	const NodeElement* const curItem = dynamic_cast<const NodeElement* const>(childItem);
	if (curItem && !curItem->isPort()) {
		boundingRect = curItem->contents();
	}

	return boundingRect;
}
<commit_msg>Changed std::max/min to qMax/qMin.<commit_after>#include "resizeHandler.h"

#include <algorithm>

ResizeHandler::ResizeHandler(
		NodeElement* const resizingNode
		, ElementImpl* const elementImpl
		)
	: mResizingNode(resizingNode)
	, mElementImpl(elementImpl)
{
}

void ResizeHandler::resize(QRectF newContents, QPointF newPos) const
{
	newContents.moveTo(0, 0);

	sortChildrenIfNeeded();
	gripeIfMinimizesToChildrenContainer(newContents);

	if (!mResizingNode->isFolded()) {
		resizeAccordingToChildren(newContents, newPos);
	}

	normalizeSize(newContents);

	newContents.moveTo(newPos);
	mResizingNode->setGeometry(newContents);
	mResizingNode->storeGeometry();

	parentResizeCall();

	if (SettingsManager::value("ActivateGrid").toBool()) {
		mResizingNode->alignToGrid();
	}
}

qreal ResizeHandler::maxChildWidth() const
{
	qreal maxChildWidthValue = 0;

	foreach (const QGraphicsItem* const childItem, mResizingNode->childItems()) {
		const NodeElement* const curItem = dynamic_cast<const NodeElement* const>(childItem);
		if (!curItem) {
			continue;
		}

		maxChildWidthValue = qMax(maxChildWidthValue, curItem->contents().width());
	}
	if (maxChildWidthValue == 0) {
		maxChildWidthValue = mResizingNode->childrenBoundingRect().width();
	}

	return maxChildWidthValue;
}

void ResizeHandler::sortChildrenIfNeeded() const
{
	if (!mElementImpl->isSortingContainer()) {
		return;
	}

	int const sizeOfForestalling = mElementImpl->sizeOfForestalling();
	qreal curChildY = sizeOfForestalling + mTitlePadding;
	qreal maxChildWidthValue = maxChildWidth();

	foreach (QGraphicsItem* const childItem, mResizingNode->childItems()) {
		QGraphicsRectItem* const placeholder = mResizingNode->placeholder();

		if(placeholder != NULL && childItem == placeholder){
			QRectF const rect(sizeOfForestalling, curChildY,
				maxChildWidthValue, placeholder->rect().height());
			placeholder->setRect(rect);
			curChildY += placeholder->rect().height() + mChildSpacing;
		}

		NodeElement* const curItem = dynamic_cast<NodeElement* const>(childItem);
		if (!curItem) {
			continue;
		}

		qreal const necessaryWidth =
			mElementImpl->maximizesChildren()
			? maxChildWidthValue
			: curItem->contents().width();
		QRectF const rect(sizeOfForestalling, curChildY, necessaryWidth, curItem->contents().height());

		curItem->setGeometry(rect);
		curItem->storeGeometry();
		curChildY += curItem->contents().height() + mElementImpl->sizeOfChildrenForestalling() + mChildSpacing;
	}
}

void ResizeHandler::gripeIfMinimizesToChildrenContainer(QRectF& contents) const
{
	if (mElementImpl->minimizesToChildren()) {
		contents = QRectF();
	}
}

void ResizeHandler::parentResizeCall() const
{
	NodeElement* const parItem = dynamic_cast<NodeElement* const>(mResizingNode->parentItem());
	if (parItem) {
		ResizeHandler handler(parItem, parItem->elementImpl());
		handler.resize(parItem->contents(), parItem->pos());
	}
}

void ResizeHandler::normalizeSize(QRectF& newContents) const
{
	if (newContents.width() < mMinSize) {
		newContents.setWidth(mResizingNode->foldedContents().width());
	}

	if (newContents.height() < mMinSize) {
		newContents.setHeight(mResizingNode->foldedContents().height());
	}
}

void ResizeHandler::resizeAccordingToChildren(QRectF& newContents, QPointF& newPos) const
{
	/*
	* AAAA!!! Who knows why is this code existed????!!!
	*
	foreach (QGraphicsItem *childItem, childItems()) {
		NodeElement* curItem = dynamic_cast<NodeElement*>(childItem);
		if (curItem && curItem->isPort() && newContents != mContents) {
			curItem->resizeChild(newContents, mContents);
		}
	}
	*/

	/// Vector of minimum negative XY child deflection from top left corner.
	QPointF const childDeflectionVector = childDeflection();

	moveChildren(-childDeflectionVector);
	//newPos += childDeflectionVector;

	expandByChildren(newContents);
}

QPointF ResizeHandler::childDeflection() const
{
	QPointF childDeflectionVector = QPointF(0, 0);
	int const sizeOfForestalling = mElementImpl->sizeOfForestalling();

	foreach (const QGraphicsItem* const childItem, mResizingNode->childItems()) {
		const NodeElement* const curItem = dynamic_cast<const NodeElement* const>(childItem);
		if (!curItem || curItem->isPort()) {
			continue;
		}

		childDeflectionVector.setX(
				qMin(curItem->pos().x() - sizeOfForestalling, childDeflectionVector.x())
				);
		childDeflectionVector.setY(
				qMin(curItem->pos().y() - sizeOfForestalling, childDeflectionVector.y())
				);
	}

	return childDeflectionVector;
}

void ResizeHandler::moveChildren(QPointF const &shift) const
{
	qreal const sizeOfForestalling = mElementImpl->sizeOfForestalling();

	foreach (QGraphicsItem* const childItem, mResizingNode->childItems()) {
		NodeElement* const curItem = dynamic_cast<NodeElement* const>(childItem);
		if (!curItem || !curItem->isPort()) {
			continue;
		}

		curItem->moveBy(shift.x(), shift.y());

		QPointF pos(
				qMax(curItem->pos().x(), sizeOfForestalling)
				, qMax(curItem->pos().y(), sizeOfForestalling)
			);
		///returns object to the parent area
		curItem->setPos(pos);
	}
}

void ResizeHandler::expandByChildren(QRectF& contents) const
{
	int const sizeOfForestalling = mElementImpl->sizeOfForestalling();

	foreach (const QGraphicsItem* const childItem, mResizingNode->childItems()) {
		QRectF curChildItemBoundingRect = childBoundingRect(childItem, contents);

		if (
			curChildItemBoundingRect.width() == 0
			||
			curChildItemBoundingRect.height() == 0
		) {
			continue;
		}

		// it seems to be more appropriate to use childItem->pos() but it causes
		// bad behaviour when dropping one element to another
		curChildItemBoundingRect.translate(childItem->scenePos() - mResizingNode->scenePos());

		contents.setLeft(
				qMin(curChildItemBoundingRect.left() - sizeOfForestalling
				       	, contents.left())
				);

		contents.setRight(
				qMax(curChildItemBoundingRect.right() + sizeOfForestalling
				       	, contents.right())
				);

		contents.setTop(
				qMin(curChildItemBoundingRect.top() - sizeOfForestalling
				       	, contents.top())
				);

		contents.setBottom(
				qMax(curChildItemBoundingRect.bottom() + sizeOfForestalling
				       	, contents.bottom())
				);
	}
}

QRectF ResizeHandler::childBoundingRect(const QGraphicsItem* const childItem, QRectF const &contents) const
{
	QRectF boundingRect;

	if (childItem == mResizingNode->placeholder()) {
		boundingRect = childItem->boundingRect();

		int const sizeOfForestalling = mElementImpl->sizeOfForestalling();
		boundingRect.setLeft(contents.left() + sizeOfForestalling);
		boundingRect.setRight(contents.right() - sizeOfForestalling);

		return boundingRect;
	}

	const NodeElement* const curItem = dynamic_cast<const NodeElement* const>(childItem);
	if (curItem && !curItem->isPort()) {
		boundingRect = curItem->contents();
	}

	return boundingRect;
}
<|endoftext|>


<commit_before>/*
 * %injeqt copyright begin%
 * Copyright 2014 Rafał Malinowski (rafal.przemyslaw.malinowski@gmail.com)
 * %injeqt copyright end%
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 */

#include "factory-method.h"

#include "extract-interfaces.h"

#include <cassert>

namespace injeqt { namespace internal {

factory_method::factory_method()
{
}

factory_method::factory_method(QMetaMethod meta_method) :
	_object_type{meta_method.enclosingMetaObject()},
	_result_type{QMetaType::metaObjectForType(meta_method.returnType())},
	_meta_method{std::move(meta_method)}
{
	assert(meta_method.methodType() == QMetaMethod::Method || meta_method.methodType() == QMetaMethod::Slot);
	assert(meta_method.parameterCount() == 0);
	assert(meta_method.enclosingMetaObject() != nullptr);

}

bool factory_method::is_empty() const
{
	return !_meta_method.isValid();
}

const type & factory_method::object_type() const
{
	assert(!is_empty());

	return _object_type;
}

const type & factory_method::result_type() const
{
	assert(!is_empty());

	return _result_type;
}

const QMetaMethod & factory_method::meta_method() const
{
	return _meta_method;
}

std::unique_ptr<QObject> factory_method::invoke(QObject *on) const
{
	assert(!is_empty());
	assert(on != nullptr);
	assert(meta_method().enclosingMetaObject() == on->metaObject());

	QObject *result = nullptr;
	_meta_method.invoke(on, QReturnArgument<QObject *>((_result_type.name() + "*").c_str(), result)); // TODO: check for false result
	return std::unique_ptr<QObject>{result};
}

bool operator == (const factory_method &x, const factory_method &y)
{
	if (x.object_type() != y.object_type())
		return false;

	if (x.result_type() != y.result_type())
		return false;

	return true;
}

bool operator != (const factory_method &x, const factory_method &y)
{
	return !(x == y);
}

factory_method make_factory_method(const type &t, const type &f)
{
	assert(!t.is_empty());
	assert(!t.is_qobject());
	assert(!f.is_empty());
	assert(!f.is_qobject());

	auto meta_object = f.meta_object();
	auto method_count = meta_object->methodCount();
	auto factory_methods = std::vector<factory_method>{};

	for (decltype(method_count) i = 0; i < method_count; i++)
	{
		auto method = meta_object->method(i);
		if (method.parameterCount() != 0)
			continue;
		auto return_type_meta_object = QMetaType::metaObjectForType(method.returnType());
		if (!return_type_meta_object)
			continue;
		auto return_type = type{return_type_meta_object};
		auto interfaces = extract_interfaces(return_type);
		if (interfaces.contains(t))
			factory_methods.emplace_back(method);
	}

	if (factory_methods.empty())
		return factory_method{};
	else if (factory_methods.size() > 1)
		return factory_method{};
	else
		return factory_methods.front();
}

}}
<commit_msg>simplify make_factory_method<commit_after>/*
 * %injeqt copyright begin%
 * Copyright 2014 Rafał Malinowski (rafal.przemyslaw.malinowski@gmail.com)
 * %injeqt copyright end%
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 */

#include "factory-method.h"

#include "extract-interfaces.h"

#include <cassert>

namespace injeqt { namespace internal {

factory_method::factory_method()
{
}

factory_method::factory_method(QMetaMethod meta_method) :
	_object_type{meta_method.enclosingMetaObject()},
	_result_type{QMetaType::metaObjectForType(meta_method.returnType())},
	_meta_method{std::move(meta_method)}
{
	assert(meta_method.methodType() == QMetaMethod::Method || meta_method.methodType() == QMetaMethod::Slot);
	assert(meta_method.parameterCount() == 0);
	assert(meta_method.enclosingMetaObject() != nullptr);

}

bool factory_method::is_empty() const
{
	return !_meta_method.isValid();
}

const type & factory_method::object_type() const
{
	assert(!is_empty());

	return _object_type;
}

const type & factory_method::result_type() const
{
	assert(!is_empty());

	return _result_type;
}

const QMetaMethod & factory_method::meta_method() const
{
	return _meta_method;
}

std::unique_ptr<QObject> factory_method::invoke(QObject *on) const
{
	assert(!is_empty());
	assert(on != nullptr);
	assert(meta_method().enclosingMetaObject() == on->metaObject());

	QObject *result = nullptr;
	_meta_method.invoke(on, QReturnArgument<QObject *>((_result_type.name() + "*").c_str(), result)); // TODO: check for false result
	return std::unique_ptr<QObject>{result};
}

bool operator == (const factory_method &x, const factory_method &y)
{
	if (x.object_type() != y.object_type())
		return false;

	if (x.result_type() != y.result_type())
		return false;

	return true;
}

bool operator != (const factory_method &x, const factory_method &y)
{
	return !(x == y);
}

factory_method make_factory_method(const type &t, const type &f)
{
	assert(!t.is_empty());
	assert(!t.is_qobject());
	assert(!f.is_empty());
	assert(!f.is_qobject());

	auto meta_object = f.meta_object();
	auto method_count = meta_object->methodCount();
	auto factory_methods = std::vector<factory_method>{};

	for (decltype(method_count) i = 0; i < method_count; i++)
	{
		auto method = meta_object->method(i);
		if (method.parameterCount() != 0)
			continue;
		auto return_type_meta_object = QMetaType::metaObjectForType(method.returnType());
		if (!return_type_meta_object)
			continue;
		auto return_type = type{return_type_meta_object};
		auto interfaces = extract_interfaces(return_type);
		if (interfaces.contains(t))
			factory_methods.emplace_back(method);
	}

	if (factory_methods.size() == 1)
		return factory_methods.front();
	else
		return factory_method{};
}

}}
<|endoftext|>