<commit_before>/*
 * The Apache Software License, Version 1.1
 *
 *
 * Copyright (c) 1999 The Apache Software Foundation.  All rights
 * reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 *
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in
 *    the documentation and/or other materials provided with the
 *    distribution.
 *
 * 3. The end-user documentation included with the redistribution,
 *    if any, must include the following acknowledgment:
 *       "This product includes software developed by the
 *        Apache Software Foundation (http://www.apache.org/)."
 *    Alternately, this acknowledgment may appear in the software itself,
 *    if and wherever such third-party acknowledgments normally appear.
 *
 * 4. The names "Xalan" and "Apache Software Foundation" must
 *    not be used to endorse or promote products derived from this
 *    software without prior written permission. For written
 *    permission, please contact apache@apache.org.
 *
 * 5. Products derived from this software may not be called "Apache",
 *    nor may "Apache" appear in their name, without prior written
 *    permission of the Apache Software Foundation.
 *
 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED 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 APACHE SOFTWARE FOUNDATION OR
 * ITS 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.
 * ====================================================================
 *
 * This software consists of voluntary contributions made by many
 * individuals on behalf of the Apache Software Foundation and was
 * originally based on software copyright (c) 1999, International
 * Business Machines, Inc., http://www.ibm.com.  For more
 * information on the Apache Software Foundation, please see
 * <http://www.apache.org/>.
 */

#define TEST_XALAN_CPP

#include <util/PlatformUtils.hpp>

#if defined(TEST_XALAN_CPP)

#include <XalanTransformer/XalanTransformer.hpp>

#if defined(XALAN_OLD_STREAM_HEADERS)
#include <iostream.h>
#include <strstream.h>
#else
#include <iostream>
#include <strstream>
#endif

#if !defined(XALAN_NO_NAMESPACES)
using std::ostrstream;
using std::cout;
#endif

#else

#include <XalanTransformer/XalanCAPI.h>

#include <stdio.h>

#endif

static unsigned long xalan_output_handler(const void *data, unsigned long length, const void *handle)
{
	FILE *fp = (FILE*)handle;

	char* d = (char *)data;

	fwrite( d, sizeof( char ), length, stdout );

	return fwrite( d, sizeof( char ), length, fp );
}

static void xalan_flush_handler(const void *handle)
{
	FILE *fp = (FILE*)handle;

	fflush(fp);
}

int
main(
			int				/* argc */,
			const char*		/* argv[] */)
{
	const char* const		theXMLFileName = "d:\\xslt\\xsl-test\\perf\\basic\\basic-all_well.xml";
	const char* const 		theXSLFileName = "d:\\xslt\\xsl-test\\perf\\basic\\basic-all_well.xsl";
	const char* const		theOutFileName = "d:\\Transformer-Results\\basic-all_well.out";

	const char* const 		theXMLFileName2 = "d:\\xslt\\xsl-test\\perf\\basic\\miscfam.xml";
	const char* const		theXSLFileName2 = "d:\\xslt\\xsl-test\\perf\\basic\\miscfam.xsl";

	const char* const 		theXMLFileName3 = "d:\\xslt\\xsl-test\\conf\\embed\\embed01.xml";
	const char* const		theOutFileName3 = "d:\\Transformer-Results\\embed01.out";

	const char* const 		theXMLFileName4 = "d:\\xml-xalan\\c\\samples\\UseStylesheetParam\\foo.xml";
	const char* const 		theXSLFileName4 = "d:\\xml-xalan\\c\\samples\\UseStylesheetParam\\foo.xsl";

#if defined(TEST_XALAN_CPP)

	// Call the static initializer for Xerces.
	XMLPlatformUtils::Initialize();

    // Initialize Xalan.
    XalanTransformer::initialize();

	XalanTransformer xalan;

	const XalanCompiledStylesheet* const	css = xalan.compileStylesheet(theXSLFileName);

	for(int i=0; i<1; ++i)
	{

		if(xalan.transform(theXMLFileName, css, "d:\\transformer-results\\css.out"))
		{
			cout << xalan.getLastError();

			return 0;
		}

		if(xalan.transform(theXMLFileName3, theOutFileName3))
		{
			cout << xalan.getLastError();

			return 0;
		}

		if(xalan.transform(theXMLFileName, theXSLFileName, theOutFileName))
		{
			cout << xalan.getLastError();

			return 0;
		}

		ostrstream	theOutput;

		if(xalan.transform(theXMLFileName2, theXSLFileName2, &theOutput))
		{
			cout << xalan.getLastError();

			return 0;
		}

		theOutput << '\0';

		cout << theOutput.str();

		ostrstream	theOutput3;

		if(xalan.transform(theXMLFileName3, theOutput3))
		{
			cout << xalan.getLastError();

			return 0;
		}
/*
		if(xalan.transform(theXMLFileName, css, cout))
		{
			cout << xalan.getLastError();

			return 0;
		}
*/
		xalan.setStylesheetParam("param1", "'What is Up'");

		if(xalan.transform(theXMLFileName4, theXSLFileName4, &cout))
		{
			cout << xalan.getLastError();

			return 0;
		}

		if(xalan.transform(theXMLFileName4, theXSLFileName4, &cout))
		{
			cout << xalan.getLastError();

			return 0;
		}
	}

   // Terminate Xalan.
	XalanTransformer::terminate();

	// Call the static terminator for Xerces.
	XMLPlatformUtils::Terminate();

#else
	XalanInitialize();

	XalanHandle xalan = CreateXalanTransformer();
	XalanCSSHandle theXalanCSS2 = XalanCompileStylesheet(theXSLFileName2, xalan);
	XalanCSSHandle theXalanCSS4 = XalanCompileStylesheet(theXSLFileName4, xalan);

	for(int i=0; i<2; ++i)
	{
		if(XalanTransformToFile(theXMLFileName, theXSLFileName, theOutFileName, xalan))
		{
			puts("Error");
			puts(XalanGetLastError(xalan));
			return 0;
		}

		char* 		theOutput;

		if(XalanTransformToData(theXMLFileName2, theXSLFileName2, &theOutput, xalan))
		{
			puts("Error");
			puts(XalanGetLastError(xalan));
			return 0;
		}

		puts(theOutput);

		XalanFreeData(theOutput);

		if(XalanTransformToFile(theXMLFileName3, NULL, theOutFileName3, xalan))
		{
			puts("Error");
			puts(XalanGetLastError(xalan));
			return 0;
		}

		if(XalanTransformToData(theXMLFileName3, NULL, &theOutput, xalan))
		{
			puts("Error");
			puts(XalanGetLastError(xalan));
			return 0;
		}

		puts(theOutput);

		XalanFreeData(theOutput);

		if(XalanTransformToDataCSS(theXMLFileName2, theXalanCSS2, &theOutput, xalan))
		{
			puts("Error");
			puts(XalanGetLastError(xalan));
			return 0;
		}

		puts(theOutput);

		XalanFreeData(theOutput);

		FILE* fp =0;
		fp = fopen("c:\\temp\\test.out", "w");

		if(XalanTransformToHandlerCSS(theXMLFileName2, theXalanCSS2, xalan, fp, xalan_output_handler, xalan_flush_handler))
		{
			puts("Error");
			puts(XalanGetLastError(xalan));
			return 0;
		}

		fclose(fp);

		XalanSetStylesheetParam("param1", "'hi'", xalan);

		//if(xalan.transform(theXMLFileName4, theXSLFileName4, &cout))
		if(XalanTransformToDataCSS(theXMLFileName4, theXalanCSS4, &theOutput, xalan))
		{
			puts("Error");
			puts(XalanGetLastError(xalan));
			return 0;
		}

		puts(theOutput);

		XalanFreeData(theOutput);

	}

	DeleteXalanTransformer(xalan);

	XalanTerminate();
#endif

	return 0;
}<commit_msg>Changes to setStylesheetParam<commit_after>/*
 * The Apache Software License, Version 1.1
 *
 *
 * Copyright (c) 1999 The Apache Software Foundation.  All rights
 * reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 *
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in
 *    the documentation and/or other materials provided with the
 *    distribution.
 *
 * 3. The end-user documentation included with the redistribution,
 *    if any, must include the following acknowledgment:
 *       "This product includes software developed by the
 *        Apache Software Foundation (http://www.apache.org/)."
 *    Alternately, this acknowledgment may appear in the software itself,
 *    if and wherever such third-party acknowledgments normally appear.
 *
 * 4. The names "Xalan" and "Apache Software Foundation" must
 *    not be used to endorse or promote products derived from this
 *    software without prior written permission. For written
 *    permission, please contact apache@apache.org.
 *
 * 5. Products derived from this software may not be called "Apache",
 *    nor may "Apache" appear in their name, without prior written
 *    permission of the Apache Software Foundation.
 *
 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED 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 APACHE SOFTWARE FOUNDATION OR
 * ITS 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.
 * ====================================================================
 *
 * This software consists of voluntary contributions made by many
 * individuals on behalf of the Apache Software Foundation and was
 * originally based on software copyright (c) 1999, International
 * Business Machines, Inc., http://www.ibm.com.  For more
 * information on the Apache Software Foundation, please see
 * <http://www.apache.org/>.
 */

#define TEST_XALAN_CPP

#include <util/PlatformUtils.hpp>

#if defined(TEST_XALAN_CPP)

#include <XalanTransformer/XalanTransformer.hpp>

#if defined(XALAN_OLD_STREAM_HEADERS)
#include <iostream.h>
#include <strstream.h>
#else
#include <iostream>
#include <strstream>
#endif

#if !defined(XALAN_NO_NAMESPACES)
using std::ostrstream;
using std::cout;
#endif

#else

#include <XalanTransformer/XalanCAPI.h>

#include <stdio.h>

#endif

static unsigned long xalan_output_handler(const void *data, unsigned long length, const void *handle)
{
	FILE *fp = (FILE*)handle;

	char* d = (char *)data;

	fwrite( d, sizeof( char ), length, stdout );

	return fwrite( d, sizeof( char ), length, fp );
}

static void xalan_flush_handler(const void *handle)
{
	FILE *fp = (FILE*)handle;

	fflush(fp);
}

int
main(
			int				/* argc */,
			const char*		/* argv[] */)
{
	const char* const		theXMLFileName = "d:\\xslt\\xsl-test\\perf\\basic\\basic-all_well.xml";
	const char* const 		theXSLFileName = "d:\\xslt\\xsl-test\\perf\\basic\\basic-all_well.xsl";
	const char* const		theOutFileName = "d:\\Transformer-Results\\basic-all_well.out";

	const char* const 		theXMLFileName2 = "d:\\xslt\\xsl-test\\perf\\basic\\miscfam.xml";
	const char* const		theXSLFileName2 = "d:\\xslt\\xsl-test\\perf\\basic\\miscfam.xsl";

	const char* const 		theXMLFileName3 = "d:\\xslt\\xsl-test\\conf\\embed\\embed01.xml";
	const char* const		theOutFileName3 = "d:\\Transformer-Results\\embed01.out";

	const char* const 		theXMLFileName4 = "d:\\xml-xalan\\c\\samples\\UseStylesheetParam\\foo.xml";
	const char* const 		theXSLFileName4 = "d:\\xml-xalan\\c\\samples\\UseStylesheetParam\\foo.xsl";

#if defined(TEST_XALAN_CPP)

	// Call the static initializer for Xerces.
	XMLPlatformUtils::Initialize();

    // Initialize Xalan.
    XalanTransformer::initialize();

	XalanTransformer xalan;

	const XalanCompiledStylesheet* const	css = xalan.compileStylesheet(theXSLFileName);

	for(int i=0; i<1; ++i)
	{

		if(xalan.transform(theXMLFileName, css, "d:\\transformer-results\\css.out"))
		{
			cout << xalan.getLastError();

			return 0;
		}

		if(xalan.transform(theXMLFileName3, theOutFileName3))
		{
			cout << xalan.getLastError();

			return 0;
		}

		if(xalan.transform(theXMLFileName, theXSLFileName, theOutFileName))
		{
			cout << xalan.getLastError();

			return 0;
		}

		ostrstream	theOutput;

		if(xalan.transform(theXMLFileName2, theXSLFileName2, &theOutput))
		{
			cout << xalan.getLastError();

			return 0;
		}

		theOutput << '\0';

		cout << theOutput.str();

		ostrstream	theOutput3;

		if(xalan.transform(theXMLFileName3, theOutput3))
		{
			cout << xalan.getLastError();

			return 0;
		}
/*
		if(xalan.transform(theXMLFileName, css, cout))
		{
			cout << xalan.getLastError();

			return 0;
		}
*/
		xalan.setStylesheetParam(XalanDOMString("param1"),
								 XalanDOMString("'What is Up'"));

		if(xalan.transform(theXMLFileName4, theXSLFileName4, &cout))
		{
			cout << xalan.getLastError();

			return 0;
		}

		if(xalan.transform(theXMLFileName4, theXSLFileName4, &cout))
		{
			cout << xalan.getLastError();

			return 0;
		}
	}

   // Terminate Xalan.
	XalanTransformer::terminate();

	// Call the static terminator for Xerces.
	XMLPlatformUtils::Terminate();

#else
	XalanInitialize();

	XalanHandle xalan = CreateXalanTransformer();
	XalanCSSHandle theXalanCSS2 = XalanCompileStylesheet(theXSLFileName2, xalan);
	XalanCSSHandle theXalanCSS4 = XalanCompileStylesheet(theXSLFileName4, xalan);

	for(int i=0; i<2; ++i)
	{
		if(XalanTransformToFile(theXMLFileName, theXSLFileName, theOutFileName, xalan))
		{
			puts("Error");
			puts(XalanGetLastError(xalan));
			return 0;
		}

		char* 		theOutput;

		if(XalanTransformToData(theXMLFileName2, theXSLFileName2, &theOutput, xalan))
		{
			puts("Error");
			puts(XalanGetLastError(xalan));
			return 0;
		}

		puts(theOutput);

		XalanFreeData(theOutput);

		if(XalanTransformToFile(theXMLFileName3, NULL, theOutFileName3, xalan))
		{
			puts("Error");
			puts(XalanGetLastError(xalan));
			return 0;
		}

		if(XalanTransformToData(theXMLFileName3, NULL, &theOutput, xalan))
		{
			puts("Error");
			puts(XalanGetLastError(xalan));
			return 0;
		}

		puts(theOutput);

		XalanFreeData(theOutput);

		if(XalanTransformToDataCSS(theXMLFileName2, theXalanCSS2, &theOutput, xalan))
		{
			puts("Error");
			puts(XalanGetLastError(xalan));
			return 0;
		}

		puts(theOutput);

		XalanFreeData(theOutput);

		FILE* fp =0;
		fp = fopen("c:\\temp\\test.out", "w");

		if(XalanTransformToHandlerCSS(theXMLFileName2, theXalanCSS2, xalan, fp, xalan_output_handler, xalan_flush_handler))
		{
			puts("Error");
			puts(XalanGetLastError(xalan));
			return 0;
		}

		fclose(fp);

		XalanSetStylesheetParam("param1", "'hi'", xalan);

		//if(xalan.transform(theXMLFileName4, theXSLFileName4, &cout))
		if(XalanTransformToDataCSS(theXMLFileName4, theXalanCSS4, &theOutput, xalan))
		{
			puts("Error");
			puts(XalanGetLastError(xalan));
			return 0;
		}

		puts(theOutput);

		XalanFreeData(theOutput);

	}

	DeleteXalanTransformer(xalan);

	XalanTerminate();
#endif

	return 0;
}<|endoftext|>


<commit_before>#include "LinuxWindowCapture.h"

// remove the window title bar which we are not interested in
#define LINUX_WINDOW_TITLE_BAR_HEIGHT 22

LinuxWindowCapture::LinuxWindowCapture( const QString& windowName )
  : mWindowName( windowName ), mWinId( 0 )
{
  mTimer = new QTimer( this );
  connect( mTimer, SIGNAL( timeout() ), this, SLOT( Update() ) );
  mTimer->start( LINUX_UPDATE_WINDOW_DATA_INTERVAL );

  Update();
}

void LinuxWindowCapture::Update() {
  if( mWinId == 0 ) {
    mWinId = FindWindow( mWindowName );
  }

  if( mWinId && !WindowRect( mWinId, &mRect ) ) {
    // Window became invalid
    mWinId = 0;
  }
}

bool LinuxWindowCapture::WindowFound() {
  return mWinId != 0;
}

int LinuxWindowCapture::Width() {
  return mRect.width();
}

int LinuxWindowCapture::Height() {
  int height = mRect.height();
  return Fullscreen() ? height : std::max< int >( height - LINUX_WINDOW_TITLE_BAR_HEIGHT, 0 );
}

QPixmap LinuxWindowCapture::Capture( int x, int y, int w, int h ) {
    LOG("Capturing window: %d, %d, %d, %d", x,y,h,w);
    QPixmap pixmap = QPixmap::grabWindow(mWinId,
                                         x + mRect.x(),
                                         y + mRect.y() + ( Fullscreen() ? 0 : LINUX_WINDOW_TITLE_BAR_HEIGHT ),
                                         w,
                                         h );
  return pixmap;
}

bool LinuxWindowCapture::Fullscreen() {
  // this is not the most elegant solution, but I couldn't find a better way
  return mRect.x() == 0.0f && mRect.y() == 0.0f &&
    ( mRect.height() & LINUX_WINDOW_TITLE_BAR_HEIGHT ) != LINUX_WINDOW_TITLE_BAR_HEIGHT;
}

QList<Window> LinuxWindowCapture::listXWindowsRecursive(Display *disp, Window w)
{
    Window root;
    Window parent;
    Window *children;
    unsigned int childrenCount;

    QList<Window> windows;
    if(XQueryTree(disp, w, &root, &parent, &children, &childrenCount))
    {
        for(unsigned int i = 0; i < childrenCount; ++i)
        {
            windows << children[i];
            windows << listXWindowsRecursive(disp, children[i]);
        }
        XFree(children);
    }
    return windows;
}

int LinuxWindowCapture::FindWindow( const QString& name ) {
    int winId = 0;
    Display *disp = XOpenDisplay(NULL);
    Window rootWin = XDefaultRootWindow(disp);
    QList<Window> windows = listXWindowsRecursive(disp, rootWin);

    foreach(Window win, windows){
        char *n;
        XFetchName(disp, win, &n);
        QString found = QString::fromLocal8Bit(n);
        if(found == name){
            winId = win;
            //LOG("HS Window found");
            break;
        }
    }
    XCloseDisplay(disp);
  return winId;
}

bool LinuxWindowCapture::WindowRect( int windowId, QRect *rect ) {
    Display *disp = XOpenDisplay(NULL);
    QList<Window> windows = listXWindowsRecursive(disp, windowId);

    int numWindows = windows.length();
    if(numWindows > 0){
        int x,y;
        unsigned int h,w,border,depth;
        Window root;
        XGetGeometry(disp, windows.at(0), &root, &x, &y, &h, &w, &border, &depth);
        rect->setRect(x, y, w, h);
        //LOG("Windows geometry: %d, %d, %d, %d", x,y,h,w);
    }

    XCloseDisplay(disp);
  return numWindows > 0;
}
<commit_msg>correction in order of arguments for XGetGeometry(...)<commit_after>#include "LinuxWindowCapture.h"

// remove the window title bar which we are not interested in
#define LINUX_WINDOW_TITLE_BAR_HEIGHT 22

LinuxWindowCapture::LinuxWindowCapture( const QString& windowName )
  : mWindowName( windowName ), mWinId( 0 )
{
  mTimer = new QTimer( this );
  connect( mTimer, SIGNAL( timeout() ), this, SLOT( Update() ) );
  mTimer->start( LINUX_UPDATE_WINDOW_DATA_INTERVAL );

  Update();
}

void LinuxWindowCapture::Update() {
  if( mWinId == 0 ) {
    mWinId = FindWindow( mWindowName );
  }

  if( mWinId && !WindowRect( mWinId, &mRect ) ) {
    // Window became invalid
    mWinId = 0;
  }
}

bool LinuxWindowCapture::WindowFound() {
  return mWinId != 0;
}

int LinuxWindowCapture::Width() {
  return mRect.width();
}

int LinuxWindowCapture::Height() {
  int height = mRect.height();
  return Fullscreen() ? height : std::max< int >( height - LINUX_WINDOW_TITLE_BAR_HEIGHT, 0 );
}

QPixmap LinuxWindowCapture::Capture( int x, int y, int w, int h ) {
    LOG("Capturing window: %d, %d, %d, %d", x,y,h,w);
    QPixmap pixmap = QPixmap::grabWindow(mWinId,
                                         x + mRect.x(),
                                         y + mRect.y() + ( Fullscreen() ? 0 : LINUX_WINDOW_TITLE_BAR_HEIGHT ),
                                         w,
                                         h );
  return pixmap;
}

bool LinuxWindowCapture::Fullscreen() {
  // this is not the most elegant solution, but I couldn't find a better way
  return mRect.x() == 0.0f && mRect.y() == 0.0f &&
    ( mRect.height() & LINUX_WINDOW_TITLE_BAR_HEIGHT ) != LINUX_WINDOW_TITLE_BAR_HEIGHT;
}

QList<Window> LinuxWindowCapture::listXWindowsRecursive(Display *disp, Window w)
{
    Window root;
    Window parent;
    Window *children;
    unsigned int childrenCount;

    QList<Window> windows;
    if(XQueryTree(disp, w, &root, &parent, &children, &childrenCount))
    {
        for(unsigned int i = 0; i < childrenCount; ++i)
        {
            windows << children[i];
            windows << listXWindowsRecursive(disp, children[i]);
        }
        XFree(children);
    }
    return windows;
}

int LinuxWindowCapture::FindWindow( const QString& name ) {
    int winId = 0;
    Display *disp = XOpenDisplay(NULL);
    Window rootWin = XDefaultRootWindow(disp);
    QList<Window> windows = listXWindowsRecursive(disp, rootWin);

    foreach(Window win, windows){
        char *n;
        XFetchName(disp, win, &n);
        QString found = QString::fromLocal8Bit(n);
        if(found == name){
            winId = win;
            //LOG("HS Window found");
            break;
        }
    }
    XCloseDisplay(disp);
  return winId;
}

bool LinuxWindowCapture::WindowRect( int windowId, QRect *rect ) {
    Display *disp = XOpenDisplay(NULL);
    QList<Window> windows = listXWindowsRecursive(disp, windowId);

    int numWindows = windows.length();
    if(numWindows > 0){
        int x,y;
        unsigned int h,w,border,depth;
        Window root;
        XGetGeometry(disp, windows.at(0), &root, &x, &y, &w, &h, &border, &depth);
        rect->setRect(x, y, w, h);
        //LOG("Windows geometry: %d, %d, %d, %d", x,y,h,w);
    }

    XCloseDisplay(disp);
  return numWindows > 0;
}
<|endoftext|>


<commit_before>#include <sys/types.h>
#include <sys/socket.h>
#include <unistd.h>

/* Purpose: to figure out how to proxy a TCP connection
 *          using raw sockets.
 */

const short LISTEN_PORT = 4210;

typedef void * (*thread_func)(void*);

static pthread_mutex_t proxy_lock = PTHREAD_MUTEX_INITIALIZER;
static pthread_mutex_t proxy_cv = PTHREAD_COND_INITIALIZER;
static bool running = true;

/* from_sock and to_sock are both raw sockets. */
static int proxy_data(int from_sock, int to_sock)
{
    char buf[4096];
    int rc = read(from_sock, buf, sizeof(buf));
    if (rc > 0) {
        int bytes_written = write(to_sock, buf, rc);
        if (bytes_written != rc) {
            perror("proxy_data: write");
        }
        rc = bytes_written;
    } else if (rc == 0) {
        fprintf(stderr, "proxy_data: socket closed\n");
    } else {
        perror("proxy_data: read");
    }
    return rc;
}

void ProxyThread(struct sockets *sockets)
{
    int client_proxy_sock = sockets->client_proxy_sock;
    int server_proxy_sock = sockets->server_proxy_sock;

    fd_set readable;
    FD_ZERO(&readable);
    FD_SET(client_proxy_sock, &readable);
    FD_SET(server_proxy_sock, &readable);
    int nfds = max(proxy_sock, server_sock) + 1;

    while (running) {
        int rc = select(nfds, &readable, NULL, NULL, NULL);
        if (rc > 0) {
            if (FD_ISSET(client_proxy_sock, &readable)) {
                proxy_data(client_proxy_sock, server_proxy_sock);
                // TODO: error handling
            }
            if (FD_ISSET(server_proxy_sock, &readable)) {
                proxy_data(server_proxy_sock, client_proxy_sock);
                // TODO: error handling
            }
        }
    }
}

int main()
{
    int listen_sock = make_listening_socket(LISTEN_PORT + 1);
    assert(listen_sock >= 0);

    int proxy_sock = socket(PF_INET, SOCK_RAW, IPPROTO_TCP);
    handle_error(proxy_sock < 0, "making raw socket");

    struct sockaddr_in addr;
    memset(&addr, 0, sizeof(addr));
    addr.sin_family = AF_INET;
    addr.sin_port = htons(LISTEN_PORT);
    socklen_t addrlen = sizeof(addr);
    int rc = bind(proxy_sock, (struct sockaddr *) &addr, addrlen);
    handle_error(rc < 0, "binding raw socket");

}
<commit_msg>Tiny bit more progress, but I'm confused about how to use raw sockets now.<commit_after>#include <sys/types.h>
#include <sys/socket.h>
#include <unistd.h>

/* Purpose: to figure out how to proxy a TCP connection
 *          using raw sockets.
 */

const short LISTEN_PORT = 4210;

typedef void * (*thread_func)(void*);

static pthread_mutex_t proxy_lock = PTHREAD_MUTEX_INITIALIZER;
static pthread_mutex_t proxy_cv = PTHREAD_COND_INITIALIZER;
static bool running = true;

/* from_sock and to_sock are both raw sockets. */
static int proxy_data(int from_sock, int to_sock)
{
    char buf[4096];
    int rc = read(from_sock, buf, sizeof(buf));
    if (rc > 0) {
        int bytes_written = write(to_sock, buf, rc);
        if (bytes_written != rc) {
            perror("proxy_data: write");
        }
        rc = bytes_written;
    } else if (rc == 0) {
        fprintf(stderr, "proxy_data: socket closed\n");
    } else {
        perror("proxy_data: read");
    }
    return rc;
}

struct sockets {
    int client_proxy_sock;
    int server_proxy_sock;
};

void ProxyThread(struct sockets *sockets)
{
    int client_proxy_sock = sockets->client_proxy_sock;
    int server_proxy_sock = sockets->server_proxy_sock;

    fd_set readable;
    FD_ZERO(&readable);
    FD_SET(client_proxy_sock, &readable);
    FD_SET(server_proxy_sock, &readable);
    int nfds = max(proxy_sock, server_sock) + 1;

    while (running) {
        int rc = select(nfds, &readable, NULL, NULL, NULL);
        if (rc > 0) {
            if (FD_ISSET(client_proxy_sock, &readable)) {
                rc = proxy_data(client_proxy_sock, server_proxy_sock);
                if (rc > 0) {
                    FD_SET(client_proxy_sock, &readable);
                }
            }
            if (FD_ISSET(server_proxy_sock, &readable)) {
                proxy_data(server_proxy_sock, client_proxy_sock);
                if (rc > 0) {
                    FD_SET(client_proxy_sock, &readable);
                }
            }
            if (!FD_ISSET(client_proxy_sock, &readable) &&
                !FD_ISSET(server_proxy_sock, &readable)) {
                fprintf(stderr, "client and server proxy sockets closed; proxy thread exiting.\n");
                break;
            }
        } else {
            perror("select");
            break;
        }
    }
}

int main()
{
    int listen_sock = make_listening_socket(LISTEN_PORT + 1);
    assert(listen_sock >= 0);

    int proxy_sock = socket(PF_INET, SOCK_RAW, IPPROTO_TCP);
    handle_error(proxy_sock < 0, "making raw socket");

    struct sockaddr_in addr;
    memset(&addr, 0, sizeof(addr));
    addr.sin_family = AF_INET;
    addr.sin_port = htons(LISTEN_PORT);
    socklen_t addrlen = sizeof(addr);
    int rc = bind(proxy_sock, (struct sockaddr *) &addr, addrlen);
    handle_error(rc < 0, "binding raw socket");

    // TODO: figure out how to handle accept through the proxy sockets.
}
<|endoftext|>


<commit_before>#include <sys/types.h>
#include <sys/socket.h>
#include <unistd.h>

const short LISTEN_PORT = 4210;

typedef void * (*thread_func)(void*);

static pthread_mutex_t proxy_lock = PTHREAD_MUTEX_INITIALIZER;
static pthread_mutex_t proxy_cv = PTHREAD_COND_INITIALIZER;
static bool running = true;

void ProxyThread(struct sockets *sockets)
{
    int proxy_sock = sockets->proxy_sock;
    int server_sock = sockets->server_sock;

    char buf[4096];
    fd_set readable;
    FD_ZERO(&readable);
    FD_ZERO(&writeable);
    FD_SET(proxy_sock, &readable);
    FD_SET(proxy_sock, &writeable);

    while (running) {
        int rc = select(/* ... */);
    }
}

int main()
{
    int listen_sock = make_listening_socket(LISTEN_PORT + 1);
    assert(listen_sock >= 0);

    int proxy_sock = socket(PF_INET, SOCK_RAW, IPPROTO_TCP);
    handle_error(proxy_sock < 0, "making raw socket");

    struct sockaddr_in addr;
    memset(&addr, 0, sizeof(addr));
    addr.sin_family = AF_INET;
    addr.sin_port = htons(LISTEN_PORT);
    socklen_t addrlen = sizeof(addr);
    int rc = bind(proxy_sock, (struct sockaddr *) &addr, addrlen);
    handle_error(rc < 0, "binding raw socket");

}
<commit_msg>Some progress on the proxy thread.<commit_after>#include <sys/types.h>
#include <sys/socket.h>
#include <unistd.h>

/* Purpose: to figure out how to proxy a TCP connection
 *          using raw sockets.
 */

const short LISTEN_PORT = 4210;

typedef void * (*thread_func)(void*);

static pthread_mutex_t proxy_lock = PTHREAD_MUTEX_INITIALIZER;
static pthread_mutex_t proxy_cv = PTHREAD_COND_INITIALIZER;
static bool running = true;

/* from_sock and to_sock are both raw sockets. */
static int proxy_data(int from_sock, int to_sock)
{
    char buf[4096];
    int rc = read(from_sock, buf, sizeof(buf));
    if (rc > 0) {
        int bytes_written = write(to_sock, buf, rc);
        if (bytes_written != rc) {
            perror("proxy_data: write");
        }
        rc = bytes_written;
    } else if (rc == 0) {
        fprintf(stderr, "proxy_data: socket closed\n");
    } else {
        perror("proxy_data: read");
    }
    return rc;
}

void ProxyThread(struct sockets *sockets)
{
    int client_proxy_sock = sockets->client_proxy_sock;
    int server_proxy_sock = sockets->server_proxy_sock;

    fd_set readable;
    FD_ZERO(&readable);
    FD_SET(client_proxy_sock, &readable);
    FD_SET(server_proxy_sock, &readable);
    int nfds = max(proxy_sock, server_sock) + 1;

    while (running) {
        int rc = select(nfds, &readable, NULL, NULL, NULL);
        if (rc > 0) {
            if (FD_ISSET(client_proxy_sock, &readable)) {
                proxy_data(client_proxy_sock, server_proxy_sock);
                // TODO: error handling
            }
            if (FD_ISSET(server_proxy_sock, &readable)) {
                proxy_data(server_proxy_sock, client_proxy_sock);
                // TODO: error handling
            }
        }
    }
}

int main()
{
    int listen_sock = make_listening_socket(LISTEN_PORT + 1);
    assert(listen_sock >= 0);

    int proxy_sock = socket(PF_INET, SOCK_RAW, IPPROTO_TCP);
    handle_error(proxy_sock < 0, "making raw socket");

    struct sockaddr_in addr;
    memset(&addr, 0, sizeof(addr));
    addr.sin_family = AF_INET;
    addr.sin_port = htons(LISTEN_PORT);
    socklen_t addrlen = sizeof(addr);
    int rc = bind(proxy_sock, (struct sockaddr *) &addr, addrlen);
    handle_error(rc < 0, "binding raw socket");

}
<|endoftext|>


<commit_before>#include "OrthographicCamera.h"

OrthographicCamera::OrthographicCamera()
  : Camera() {

}

OrthographicCamera::OrthographicCamera(const Point3D& position, const Vector3D& forward, const Vector3D& up, const uint32_t near, const uint32_t far)
  : Camera(position, forward, up, near, far) {

}

OrthographicCamera::~OrthographicCamera() {

}

const Triangle2D OrthographicCamera::projectToScreen(const Triangle3D& triangle3D) const {
  //TODO: actual projection
  return Triangle2D();
}

const float OrthographicCamera::getDepth(const Point3D& pixel_world, const Triangle3D& triangle) const {
  // Create line from camera position in camera_fwd direction
    // return line
  // Calculate intersection between this line and triangle/object
    // return intersection point
  // Calculate distance between two points
    // return distance
}
<commit_msg>Implemented getDepth function<commit_after>#include "OrthographicCamera.h"
#include <limits>
OrthographicCamera::OrthographicCamera()
  : Camera() {

}

OrthographicCamera::OrthographicCamera(const Point3D& position, const Vector3D& forward, const Vector3D& up, const uint32_t near, const uint32_t far)
  : Camera(position, forward, up, near, far) {

}

OrthographicCamera::~OrthographicCamera() {

}

const Triangle2D OrthographicCamera::projectToScreen(const Triangle3D& triangle3D) const {
  //TODO: actual projection
  return Triangle2D();
}

const float OrthographicCamera::getDepth(const Point3D& pixel_world, const Triangle3D& triangle) const {
  bool out_hit;
  const Point3D intersection_point = triangle.intersect(out_hit, pixel_world, this->m_forward);
  if (!out_hit) {
    return std::numeric_limits<float>::max();
  }

  return pixel_world.distance(intersection_point);
}
<|endoftext|>


<commit_before>#include "Players/Genetic_AI.h"

#include <iostream>
#include <fstream>
#include <vector>

#include "Moves/Move.h"
#include "Game/Board.h"
#include "Game/Clock.h"

#include "Exceptions/Checkmate_Exception.h"
#include "Exceptions/Game_Ending_Exception.h"
#include "Exceptions/End_Of_File_Exception.h"

#include "Utility.h"

int Genetic_AI::next_id = 0;

Genetic_AI::Genetic_AI() :
    genome(),
    id(next_id++)
{
}

// Sexual reproduction
Genetic_AI::Genetic_AI(const Genetic_AI& A, const Genetic_AI& B) :
    genome(A.genome, B.genome),
    id(next_id++)
{
}

Genetic_AI::~Genetic_AI()
{
}

Genetic_AI::Genetic_AI(const std::string& file_name)
{
    std::ifstream ifs(file_name);
    if( ! ifs)
    {
        throw std::runtime_error("Could not read: " + file_name);
    }

    read_from(ifs);
}

Genetic_AI::Genetic_AI(std::istream& is)
{
    read_from(is);
}

Genetic_AI::Genetic_AI(const std::string& file_name, int id_in) : id(id_in)
{
    std::ifstream ifs(file_name);
    if( ! ifs)
    {
        throw std::runtime_error("Could not read: " + file_name);
    }

    std::string line;
    while(std::getline(ifs, line))
    {
        if( ! String::starts_with(line, "ID:"))
        {
            continue;
        }

        auto param_value = String::split(line, ":", 1);
        if(id_in == std::stoi(param_value[1]))
        {
            genome.read_from(ifs);
            return;
        }
    }

    throw std::runtime_error("Could not locate ID " + std::to_string(id_in) + " inside file " + file_name);
}

void Genetic_AI::read_from(std::istream& is)
{
    std::string line;
    id = -1;
    while(std::getline(is, line))
    {
        if(line.empty())
        {
            continue;
        }

        if(String::starts_with(line, "ID:"))
        {
            id = std::stoi(String::split(line)[1]);
            break;
        }
        else
        {
            throw std::runtime_error("Invalid Genetic_AI line: " + line);
        }
    }

    if( ! is)
    {
        if(id > -1)
        {
            throw std::runtime_error("Incomplete Genetic_AI spec in file for ID " + std::to_string(id));
        }
        else
        {
            throw End_Of_File_Exception();
        }
    }

    if(id >= next_id)
    {
        next_id = id + 1;
    }

    genome.read_from(is);
}

const Complete_Move Genetic_AI::choose_move(const Board& board, const Clock& clock) const
{
    const auto& legal_moves = board.all_legal_moves();
    if(legal_moves.size() == 1)
    {
        return legal_moves.front(); // If there's only one legal move, take it.
    }

    auto positions_to_examine = genome.positions_to_examine(board, clock);
    std::string look_ahead_comment = "[" + std::to_string(positions_to_examine) + ",";
    auto result = search_game_tree(board,
                                   positions_to_examine,
                                   clock,
                                   0);
    look_ahead_comment += std::to_string(positions_to_examine) + "] ";
    board.add_commentary_to_next_move(look_ahead_comment + result.commentary);
    return result.move;
}

Game_Tree_Node_Result Genetic_AI::search_game_tree(const Board& board,
                                                   int& positions_to_examine,
                                                   const Clock& clock,
                                                   const int depth) const
{
    // Every call to search_game_tree() after the first
    // costs a position_to_examine.
    if(depth > 0 && positions_to_examine > 0)
    {
        --positions_to_examine;
    }

    auto perspective = board.whose_turn();

    std::string comments_on_all_moves; // only use when depth == 0

    std::vector<Game_Tree_Node_Result> results;

    // Moves worth examining further
    std::vector<std::tuple<Complete_Move, Board, double>> further_examine; // move, resulting board, score

    // Find moves worth examining
    for(const auto& move : board.all_legal_moves())
    {
        if(clock.time_left(clock.running_for()) < 0.0)
        {
            break;
        }

        auto next_board = board;

        try
        {
            next_board.submit_move(move);

            if(positions_to_examine <= 0 || ! genome.good_enough_to_examine(board, next_board, perspective))
            {
                // Record immediate result without looking ahead further
                results.push_back({move,
                                   genome.evaluate(next_board, perspective),
                                   perspective,
                                   depth,
                                   next_board.get_game_record().back()});
            }
            else
            {
                further_examine.push_back({move, next_board, genome.evaluate(next_board, perspective)});
            }
        }
        catch(const Checkmate_Exception&)
        {
            // Mate in one (try to pick the shortest path to checkmate)
            auto score = genome.evaluate(next_board, perspective);
            auto comment = next_board.get_game_record().back();
            if(depth == 0)
            {
                comment = comments_on_all_moves + " " + comment + " (" + std::to_string(score) + ")";
            }
            return {move,
                    score,
                    perspective,
                    depth,
                    comment};
        }
        catch(const Game_Ending_Exception&)
        {
            // Draw
            results.push_back({move,
                               genome.evaluate(next_board, perspective),
                               perspective,
                               depth,
                               next_board.get_game_record().back()});
        }
    }

    // Sort moves by score so higher scores get more moves for examination
    std::sort(further_examine.begin(),
              further_examine.end(),
              [](const auto& x, const auto& y)
              {
                  return std::get<double>(x) < std::get<double>(y);
              });

    // Look ahead through moves found above
    for(size_t i = 0; i < further_examine.size(); ++i)
    {
        int moves_left = further_examine.size() - i;
        int positions_for_this_move = positions_to_examine/moves_left;

        if(positions_for_this_move > 0)
        {
            positions_to_examine -= positions_for_this_move;

            results.push_back(search_game_tree(std::get<Board>(further_examine[i]),
                                               positions_for_this_move,
                                               clock,
                                               depth + 1));
            // Update last result with this node's data
            results.back().move = std::get<Complete_Move>(further_examine[i]);
            results.back().commentary = std::get<Board>(further_examine[i]).get_game_record().back()
                                        + " "
                                        + results.back().commentary;

            positions_to_examine += positions_for_this_move;
        }
        else
        {
            results.push_back({std::get<Complete_Move>(further_examine[i]),
                               std::get<double>(further_examine[i]),
                               perspective,
                               depth,
                               std::get<Board>(further_examine[i]).get_game_record().back()});
        }
    }

    // Consider all results and return best
    auto best_score = -Math::infinity;
    auto best_move = board.all_legal_moves().front();
    auto best_depth = 0;
    std::string comments_on_best_move;

    for(const auto& result : results)
    {
        auto score = result.score;
        if(result.perspective != perspective)
        {
            score = -score;
        }

        // Prefer ...
        if(score > best_score // ... better score
           || (score ==  Math::infinity && result.depth < best_depth) // shortest path to victory
           || (score == -Math::infinity && result.depth > best_depth)) // longest path to defeat
        {
            best_score = score;
            best_move = result.move;
            best_depth = result.depth;
            comments_on_best_move = result.commentary;
        }

        if(depth == 0)
        {
            // build comment on all current move possibilities
            comments_on_all_moves += " " + result.commentary + " (" + std::to_string(score) + ")";
        }
    }

    return {best_move,
            best_score,
            perspective,
            best_depth,
            (depth == 0 ? comments_on_all_moves : comments_on_best_move)};
}

void Genetic_AI::mutate()
{
    genome.mutate();
}

void Genetic_AI::print_genome(const std::string& file_name) const
{
    if(file_name.empty())
    {
        print_genome(std::cout);
    }
    else
    {
        auto dest = std::ofstream(file_name, std::ofstream::app);
        print_genome(dest);
    }
}

void Genetic_AI::print_genome(std::ostream& os) const
{
    os << "ID: " << get_id() << std::endl;
    genome.print(os);
    os << "END" << std::endl << std::endl;
}

std::string Genetic_AI::name() const
{
    return "Genetic AI " + std::to_string(get_id());
}

int Genetic_AI::get_id() const
{
    return id;
}

bool Genetic_AI::operator<(const Genetic_AI& other) const
{
    return get_id() < other.get_id();
}

bool Genetic_AI::operator==(const Genetic_AI& other) const
{
    return get_id() == other.get_id();
}
<commit_msg>Add time elapsed to pick move to game commentary<commit_after>#include "Players/Genetic_AI.h"

#include <iostream>
#include <fstream>
#include <vector>

#include "Moves/Move.h"
#include "Game/Board.h"
#include "Game/Clock.h"

#include "Exceptions/Checkmate_Exception.h"
#include "Exceptions/Game_Ending_Exception.h"
#include "Exceptions/End_Of_File_Exception.h"

#include "Utility.h"

int Genetic_AI::next_id = 0;

Genetic_AI::Genetic_AI() :
    genome(),
    id(next_id++)
{
}

// Sexual reproduction
Genetic_AI::Genetic_AI(const Genetic_AI& A, const Genetic_AI& B) :
    genome(A.genome, B.genome),
    id(next_id++)
{
}

Genetic_AI::~Genetic_AI()
{
}

Genetic_AI::Genetic_AI(const std::string& file_name)
{
    std::ifstream ifs(file_name);
    if( ! ifs)
    {
        throw std::runtime_error("Could not read: " + file_name);
    }

    read_from(ifs);
}

Genetic_AI::Genetic_AI(std::istream& is)
{
    read_from(is);
}

Genetic_AI::Genetic_AI(const std::string& file_name, int id_in) : id(id_in)
{
    std::ifstream ifs(file_name);
    if( ! ifs)
    {
        throw std::runtime_error("Could not read: " + file_name);
    }

    std::string line;
    while(std::getline(ifs, line))
    {
        if( ! String::starts_with(line, "ID:"))
        {
            continue;
        }

        auto param_value = String::split(line, ":", 1);
        if(id_in == std::stoi(param_value[1]))
        {
            genome.read_from(ifs);
            return;
        }
    }

    throw std::runtime_error("Could not locate ID " + std::to_string(id_in) + " inside file " + file_name);
}

void Genetic_AI::read_from(std::istream& is)
{
    std::string line;
    id = -1;
    while(std::getline(is, line))
    {
        if(line.empty())
        {
            continue;
        }

        if(String::starts_with(line, "ID:"))
        {
            id = std::stoi(String::split(line)[1]);
            break;
        }
        else
        {
            throw std::runtime_error("Invalid Genetic_AI line: " + line);
        }
    }

    if( ! is)
    {
        if(id > -1)
        {
            throw std::runtime_error("Incomplete Genetic_AI spec in file for ID " + std::to_string(id));
        }
        else
        {
            throw End_Of_File_Exception();
        }
    }

    if(id >= next_id)
    {
        next_id = id + 1;
    }

    genome.read_from(is);
}

const Complete_Move Genetic_AI::choose_move(const Board& board, const Clock& clock) const
{
    const auto& legal_moves = board.all_legal_moves();
    if(legal_moves.size() == 1)
    {
        return legal_moves.front(); // If there's only one legal move, take it.
    }

    auto positions_to_examine = genome.positions_to_examine(board, clock);
    std::string look_ahead_comment = "[" + std::to_string(positions_to_examine) + ",";
    auto time_at_start = clock.time_left(board.whose_turn());
    auto result = search_game_tree(board,
                                   positions_to_examine,
                                   clock,
                                   0);
    look_ahead_comment += std::to_string(positions_to_examine) + "] ";
    auto time_used = time_at_start - clock.time_left(board.whose_turn());
    board.add_commentary_to_next_move(look_ahead_comment
                                      + " "
                                      + std::to_string(time_used)
                                      + " "
                                      + result.commentary);
    return result.move;
}

Game_Tree_Node_Result Genetic_AI::search_game_tree(const Board& board,
                                                   int& positions_to_examine,
                                                   const Clock& clock,
                                                   const int depth) const
{
    // Every call to search_game_tree() after the first
    // costs a position_to_examine.
    if(depth > 0 && positions_to_examine > 0)
    {
        --positions_to_examine;
    }

    auto perspective = board.whose_turn();

    std::string comments_on_all_moves; // only use when depth == 0

    std::vector<Game_Tree_Node_Result> results;

    // Moves worth examining further
    std::vector<std::tuple<Complete_Move, Board, double>> further_examine; // move, resulting board, score

    // Find moves worth examining
    for(const auto& move : board.all_legal_moves())
    {
        if(clock.time_left(clock.running_for()) < 0.0)
        {
            break;
        }

        auto next_board = board;

        try
        {
            next_board.submit_move(move);

            if(positions_to_examine <= 0 || ! genome.good_enough_to_examine(board, next_board, perspective))
            {
                // Record immediate result without looking ahead further
                results.push_back({move,
                                   genome.evaluate(next_board, perspective),
                                   perspective,
                                   depth,
                                   next_board.get_game_record().back()});
            }
            else
            {
                further_examine.push_back({move, next_board, genome.evaluate(next_board, perspective)});
            }
        }
        catch(const Checkmate_Exception&)
        {
            // Mate in one (try to pick the shortest path to checkmate)
            auto score = genome.evaluate(next_board, perspective);
            auto comment = next_board.get_game_record().back();
            if(depth == 0)
            {
                comment = comments_on_all_moves + " " + comment + " (" + std::to_string(score) + ")";
            }
            return {move,
                    score,
                    perspective,
                    depth,
                    comment};
        }
        catch(const Game_Ending_Exception&)
        {
            // Draw
            results.push_back({move,
                               genome.evaluate(next_board, perspective),
                               perspective,
                               depth,
                               next_board.get_game_record().back()});
        }
    }

    // Sort moves by score so higher scores get more moves for examination
    std::sort(further_examine.begin(),
              further_examine.end(),
              [](const auto& x, const auto& y)
              {
                  return std::get<double>(x) < std::get<double>(y);
              });

    // Look ahead through moves found above
    for(size_t i = 0; i < further_examine.size(); ++i)
    {
        int moves_left = further_examine.size() - i;
        int positions_for_this_move = positions_to_examine/moves_left;

        if(positions_for_this_move > 0)
        {
            positions_to_examine -= positions_for_this_move;

            results.push_back(search_game_tree(std::get<Board>(further_examine[i]),
                                               positions_for_this_move,
                                               clock,
                                               depth + 1));
            // Update last result with this node's data
            results.back().move = std::get<Complete_Move>(further_examine[i]);
            results.back().commentary = std::get<Board>(further_examine[i]).get_game_record().back()
                                        + " "
                                        + results.back().commentary;

            positions_to_examine += positions_for_this_move;
        }
        else
        {
            results.push_back({std::get<Complete_Move>(further_examine[i]),
                               std::get<double>(further_examine[i]),
                               perspective,
                               depth,
                               std::get<Board>(further_examine[i]).get_game_record().back()});
        }
    }

    // Consider all results and return best
    auto best_score = -Math::infinity;
    auto best_move = board.all_legal_moves().front();
    auto best_depth = 0;
    std::string comments_on_best_move;

    for(const auto& result : results)
    {
        auto score = result.score;
        if(result.perspective != perspective)
        {
            score = -score;
        }

        // Prefer ...
        if(score > best_score // ... better score
           || (score ==  Math::infinity && result.depth < best_depth) // shortest path to victory
           || (score == -Math::infinity && result.depth > best_depth)) // longest path to defeat
        {
            best_score = score;
            best_move = result.move;
            best_depth = result.depth;
            comments_on_best_move = result.commentary;
        }

        if(depth == 0)
        {
            // build comment on all current move possibilities
            comments_on_all_moves += " " + result.commentary + " (" + std::to_string(score) + ")";
        }
    }

    return {best_move,
            best_score,
            perspective,
            best_depth,
            (depth == 0 ? comments_on_all_moves : comments_on_best_move)};
}

void Genetic_AI::mutate()
{
    genome.mutate();
}

void Genetic_AI::print_genome(const std::string& file_name) const
{
    if(file_name.empty())
    {
        print_genome(std::cout);
    }
    else
    {
        auto dest = std::ofstream(file_name, std::ofstream::app);
        print_genome(dest);
    }
}

void Genetic_AI::print_genome(std::ostream& os) const
{
    os << "ID: " << get_id() << std::endl;
    genome.print(os);
    os << "END" << std::endl << std::endl;
}

std::string Genetic_AI::name() const
{
    return "Genetic AI " + std::to_string(get_id());
}

int Genetic_AI::get_id() const
{
    return id;
}

bool Genetic_AI::operator<(const Genetic_AI& other) const
{
    return get_id() < other.get_id();
}

bool Genetic_AI::operator==(const Genetic_AI& other) const
{
    return get_id() == other.get_id();
}
<|endoftext|>


<commit_before>#include "view.h"
#include "shader.h"

#include <SDL.h>
#include "gl.h"
#include <glm/gtx/transform.hpp>

#include <stdexcept>

namespace te
{
    const static GLfloat Z = 100;

    static void checkViewport(const FloatRect& viewport)
    {
        if (viewport.x < 0 ||
            viewport.y < 0 ||
            viewport.w > 1 ||
            viewport.y > 1)
        {
            throw std::runtime_error("View: Viewport must be in range [0,1].");
        }
    }

    View::View()
        : View(FloatRect(0,0,0,0))
    {}

    View::View(const FloatRect& lens)
        : mLens(lens)
        , mViewport(0, 0, 1, 1)
    {}

    FloatRect View::getLens() const
    {
        return mLens;
    }

    void View::reset(const FloatRect& lens)
    {
        mLens = lens;
    }

    void View::setViewport(const FloatRect& viewport)
    {
        checkViewport(viewport);
        mViewport = viewport;
    }

    View::Lock View::activate(const View& view, const std::shared_ptr<Shader>& pShader, SDL_Window& window)
    {
        int width = 0, height = 0;
        SDL_GetWindowSize(&window, &width, &height);
        return activate(view, pShader, width, height);
    }

    View::Lock View::activate(const View& view, const std::shared_ptr<Shader>& pShader, int width, int height)
    {
        GLint originalViewport[4];
        glGetIntegerv(GL_VIEWPORT, originalViewport);

        FloatRect viewport = view.mViewport;
        glViewport((int)(viewport.x * width),
                   (int)(height - (height * (viewport.h + viewport.y))),
                   (int)(viewport.w * width),
                   (int)(viewport.h * height));

        glm::mat4 originalProjection = pShader->getProjection();
        pShader->setProjection(glm::ortho<GLfloat>(view.mLens.x, view.mLens.x + view.mLens.w, view.mLens.y + view.mLens.h, view.mLens.y, -Z, Z));

        return View::Lock(pShader, originalProjection, { originalViewport[0],
                                                         originalViewport[1],
                                                         originalViewport[2],
                                                         originalViewport[3] });
    }

    View::Lock::Lock(const std::shared_ptr<Shader>& pShader,
                     const glm::mat4& originalProjection,
                     const IntRect& originalViewport)
        : mpShader(pShader)
        , mProjection(originalProjection)
        , mViewport(originalViewport)
    {
        assert(pShader);
    }

    View::Lock& View::Lock::operator=(Lock&& o)
    {
        mpShader = o.mpShader;
        mProjection = o.mProjection;
        mViewport = o.mViewport;

        o.mpShader = nullptr;

        return *this;
    }

    View::Lock::Lock(Lock&& o)
        : mpShader(o.mpShader)
        , mProjection(o.mProjection)
        , mViewport(o.mViewport)
    {
        o.mpShader = nullptr;
    }

    View::Lock::~Lock()
    {
        // Null mpShader indicates moved lock
        if (mpShader) {
            // Restore lens and viewport
            mpShader->setProjection(mProjection);
            glViewport(mViewport.x, mViewport.y, mViewport.w, mViewport.h);
        }
    }
}
<commit_msg>Check for null reference<commit_after>#include "view.h"
#include "shader.h"

#include <SDL.h>
#include "gl.h"
#include <glm/gtx/transform.hpp>

#include <stdexcept>

namespace te
{
    const static GLfloat Z = 100;

    static void checkViewport(const FloatRect& viewport)
    {
        if (viewport.x < 0 ||
            viewport.y < 0 ||
            viewport.w > 1 ||
            viewport.y > 1)
        {
            throw std::runtime_error("View: Viewport must be in range [0,1].");
        }
    }

    View::View()
        : View(FloatRect(0,0,0,0))
    {}

    View::View(const FloatRect& lens)
        : mLens(lens)
        , mViewport(0, 0, 1, 1)
    {}

    FloatRect View::getLens() const
    {
        return mLens;
    }

    void View::reset(const FloatRect& lens)
    {
        mLens = lens;
    }

    void View::setViewport(const FloatRect& viewport)
    {
        checkViewport(viewport);
        mViewport = viewport;
    }

    View::Lock View::activate(const View& view, const std::shared_ptr<Shader>& pShader, SDL_Window& window)
    {
        if (!pShader) { throw std::runtime_error("View::activate: Shader required."); }

        int width = 0, height = 0;
        SDL_GetWindowSize(&window, &width, &height);
        return activate(view, pShader, width, height);
    }

    View::Lock View::activate(const View& view, const std::shared_ptr<Shader>& pShader, int width, int height)
    {
        if (!pShader) { throw std::runtime_error("View::activate: Shader required."); }

        GLint originalViewport[4];
        glGetIntegerv(GL_VIEWPORT, originalViewport);

        FloatRect viewport = view.mViewport;
        glViewport((int)(viewport.x * width),
                   (int)(height - (height * (viewport.h + viewport.y))),
                   (int)(viewport.w * width),
                   (int)(viewport.h * height));

        glm::mat4 originalProjection = pShader->getProjection();
        pShader->setProjection(glm::ortho<GLfloat>(view.mLens.x, view.mLens.x + view.mLens.w, view.mLens.y + view.mLens.h, view.mLens.y, -Z, Z));

        return View::Lock(pShader, originalProjection, { originalViewport[0],
                                                         originalViewport[1],
                                                         originalViewport[2],
                                                         originalViewport[3] });
    }

    View::Lock::Lock(const std::shared_ptr<Shader>& pShader,
                     const glm::mat4& originalProjection,
                     const IntRect& originalViewport)
        : mpShader(pShader)
        , mProjection(originalProjection)
        , mViewport(originalViewport)
    {
        assert(pShader);
    }

    View::Lock& View::Lock::operator=(Lock&& o)
    {
        mpShader = o.mpShader;
        mProjection = o.mProjection;
        mViewport = o.mViewport;

        o.mpShader = nullptr;

        return *this;
    }

    View::Lock::Lock(Lock&& o)
        : mpShader(o.mpShader)
        , mProjection(o.mProjection)
        , mViewport(o.mViewport)
    {
        o.mpShader = nullptr;
    }

    View::Lock::~Lock()
    {
        // Null mpShader indicates moved lock
        if (mpShader) {
            // Restore lens and viewport
            mpShader->setProjection(mProjection);
            glViewport(mViewport.x, mViewport.y, mViewport.w, mViewport.h);
        }
    }
}
<|endoftext|>


<commit_before>/******************************************************************************
 *                       ____    _    _____                                   *
 *                      / ___|  / \  |  ___|    C++                           *
 *                     | |     / _ \ | |_       Actor                         *
 *                     | |___ / ___ \|  _|      Framework                     *
 *                      \____/_/   \_|_|                                      *
 *                                                                            *
 * Copyright (C) 2011 - 2017                                                  *
 * Dominik Charousset <dominik.charousset (at) haw-hamburg.de>                *
 *                                                                            *
 * Distributed under the terms and conditions of the BSD 3-Clause License or  *
 * (at your option) under the terms and conditions of the Boost Software      *
 * License 1.0. See accompanying files LICENSE and LICENSE_ALTERNATIVE.       *
 *                                                                            *
 * If you did not receive a copy of the license files, see                    *
 * http://opensource.org/licenses/BSD-3-Clause and                            *
 * http://www.boost.org/LICENSE_1_0.txt.                                      *
 ******************************************************************************/

#include "caf/config.hpp"

#define CAF_SUITE blocking_actor
#include "caf/test/unit_test.hpp"

#include "caf/all.hpp"

using namespace caf;

namespace {

struct fixture {
  actor_system_config cfg;
  actor_system system;
  scoped_actor self;

  fixture() : system(cfg), self(system) {
    // nop
  }
};

} // namespace <anonymous>

CAF_TEST_FIXTURE_SCOPE(blocking_actor_tests, fixture)

CAF_TEST(catch_all) {
  self->send(self, 42);
  self->receive(
    [](float) {
      CAF_FAIL("received unexpected float");
    },
    others >> [](message_view& x) -> result<message> {
      CAF_CHECK_EQUAL(to_string(x.content()), "(42)");
      return sec::unexpected_message;
    }
  );
  self->receive(
    [](const error& err) {
      CAF_CHECK_EQUAL(err, sec::unexpected_message);
    }
  );
}

CAF_TEST(behavior_ref) {
  behavior bhvr{
    [](int i) {
      CAF_CHECK_EQUAL(i, 42);
    }
  };
  self->send(self, 42);
  self->receive(bhvr);
}

CAF_TEST(timeout_in_scoped_actor) {
  bool timeout_called = false;
  scoped_actor self{system};
  self->receive(
    after(std::chrono::milliseconds(20)) >> [&] {
      timeout_called = true;
    }
  );
  CAF_CHECK(timeout_called);
}

CAF_TEST_FIXTURE_SCOPE_END()
<commit_msg>Add unit test for scoped_actor skip problem<commit_after>/******************************************************************************
 *                       ____    _    _____                                   *
 *                      / ___|  / \  |  ___|    C++                           *
 *                     | |     / _ \ | |_       Actor                         *
 *                     | |___ / ___ \|  _|      Framework                     *
 *                      \____/_/   \_|_|                                      *
 *                                                                            *
 * Copyright (C) 2011 - 2017                                                  *
 * Dominik Charousset <dominik.charousset (at) haw-hamburg.de>                *
 *                                                                            *
 * Distributed under the terms and conditions of the BSD 3-Clause License or  *
 * (at your option) under the terms and conditions of the Boost Software      *
 * License 1.0. See accompanying files LICENSE and LICENSE_ALTERNATIVE.       *
 *                                                                            *
 * If you did not receive a copy of the license files, see                    *
 * http://opensource.org/licenses/BSD-3-Clause and                            *
 * http://www.boost.org/LICENSE_1_0.txt.                                      *
 ******************************************************************************/

#include "caf/config.hpp"

#define CAF_SUITE blocking_actor
#include "caf/test/unit_test.hpp"

#include "caf/all.hpp"

using namespace caf;

namespace {

struct fixture {
  actor_system_config cfg;
  actor_system system;
  scoped_actor self;

  fixture() : system(cfg), self(system) {
    // nop
  }
};

} // namespace <anonymous>

CAF_TEST_FIXTURE_SCOPE(blocking_actor_tests, fixture)

CAF_TEST(catch_all) {
  self->send(self, 42);
  self->receive(
    [](float) {
      CAF_FAIL("received unexpected float");
    },
    others >> [](message_view& x) -> result<message> {
      CAF_CHECK_EQUAL(to_string(x.content()), "(42)");
      return sec::unexpected_message;
    }
  );
  self->receive(
    [](const error& err) {
      CAF_CHECK_EQUAL(err, sec::unexpected_message);
    }
  );
}

CAF_TEST(behavior_ref) {
  behavior bhvr{
    [](int i) {
      CAF_CHECK_EQUAL(i, 42);
    }
  };
  self->send(self, 42);
  self->receive(bhvr);
}

CAF_TEST(timeout_in_scoped_actor) {
  bool timeout_called = false;
  scoped_actor self{system};
  self->receive(
    after(std::chrono::milliseconds(20)) >> [&] {
      timeout_called = true;
    }
  );
  CAF_CHECK(timeout_called);
}

// -- scoped_actors using skip -------------------------------------------------

using msg_t = int;
// send_order_t contains messages which are send to an actor in the same order
// as in vector
using send_order_t = std::vector<msg_t>;
// sequence_t contains a number of messages for processing by an actor with
// the information to skip the current message for later processing
using sequence_t = std::vector<std::pair<msg_t, bool>>;
using check_order_t = std::pair<send_order_t, sequence_t>;

behavior check_order_behavior_factory(local_actor* self,
                                      sequence_t::const_iterator* seq_it_ptr) {
  return {
    [=](int i) -> result<void> {
      auto& seq_it = *seq_it_ptr;
      CAF_CHECK_EQUAL(i, seq_it->first);
      if (seq_it->second) {
        CAF_MESSAGE("current: " << i << "; awaiting: " << seq_it->first
                                << "; inbox size: " << self->mailbox().count()
                                << " SKIPPED");
        ++seq_it;
        return skip();
      } else {
        CAF_MESSAGE("current: " << i << "; awaiting: " << seq_it->first
                                << "; inbox size: " << self->mailbox().count()
                                << " OK");
        ++seq_it;
        return unit;
      }
    }
  };
}

void check_order_event_based_actor(const check_order_t& corder) {
  actor_system_config cfg;
  actor_system system{cfg};
  auto& send_order = corder.first;
  auto& sequence = corder.second;
  auto seq_it = sequence.cbegin();
  {
    auto tmp = system.spawn(
      [=](event_based_actor* self) mutable {
        self->set_default_handler(skip);
        for(auto i : send_order) {
          self->send(self, i);
        }
        self->become(
          check_order_behavior_factory(self, &seq_it));
      }
    );

  }
  system.await_all_actors_done();
}

void check_order_scoped_actor(const check_order_t& corder) {
  actor_system_config cfg;
  actor_system system{cfg};
  auto& send_order = corder.first;
  auto& sequence = corder.second;
  auto seq_it = begin(sequence);
  scoped_actor self{system};
  auto check_order_behavior =
    check_order_behavior_factory(actor_cast<local_actor*>(self), &seq_it);
  for(auto i : send_order) {
    self->send(self, i);
  }
  while (seq_it != end(sequence)) {
    self->receive(check_order_behavior);
  }
}

CAF_TEST(skip_message) {
  check_order_t a = {
    {0, 1, 2, 3}, //recv_order = 0,1,2,3
    {{0, false}, {1, false}, {2, false}, {3, false}}
  };
  check_order_t b = {
    {3, 2, 1, 0}, //recv_order = 0,1,2,3
    {{3, true}, {2, true}, {1, true}, {0, false},
    {3, true}, {2, true}, {1, false},
    {3, true}, {2, false},
    {3, false}}
  };
  check_order_t c = {
    {1, 0, 2}, //recv_order = 0,1,2
    {{1, true}, {0, false},
    {1, false},
    {2, false}}
  };
  check_order_t d = {
    {3, 1, 2, 0}, //recv_order = 0,1,2,3
    {{3, true}, {1, true}, {2, true}, {0, false},
    {3, true}, {1, false},
    {3, true}, {2, false},
    {3, false}}
  };
  check_order_event_based_actor(a);
  check_order_event_based_actor(b);
  check_order_event_based_actor(c);
  check_order_event_based_actor(d);
  check_order_scoped_actor(a);
  check_order_scoped_actor(b);
  check_order_scoped_actor(c);
  check_order_scoped_actor(d);
}

CAF_TEST_FIXTURE_SCOPE_END()
<|endoftext|>


<commit_before>/*
**
** Copyright (C) 2010, 2012 Aldebaran Robotics
**  See COPYING for the license
*/

#include <qimessaging/genericvalue.hpp>
#include <qimessaging/genericobject.hpp>
#include <qimessaging/genericvaluespecialized.hpp>

namespace qi
{

std::pair<GenericValue, bool> GenericValue::convert(Type* targetType) const
{
  /* Can have false-negative (same effective type, different Type instances
   * but we do not care, correct check (by comparing info() result
   * is more expensive than the dummy conversion that will happen.
  */
  if (type == targetType)
  {
    return std::make_pair(*this, false);
  }

  GenericValue result;
  Type::Kind skind = type->kind();
  Type::Kind dkind = targetType->kind();
  if (skind == dkind)
  {
    switch(skind)
    {
    case Type::Float:
      result.type = targetType;
      result.value = targetType->initializeStorage();
      static_cast<TypeFloat*>(targetType)->set(&result.value,
        static_cast<TypeFloat*>(type)->get(value));
      return std::make_pair(result, true);
    case Type::Int:
      result.type = targetType;
      result.value = targetType->initializeStorage();
      static_cast<TypeInt*>(targetType)->set(&result.value,
        static_cast<TypeInt*>(type)->get(value));
      return std::make_pair(result, true);
    case Type::String:
      result.type = targetType;
      result.value = targetType->initializeStorage();
      static_cast<TypeString*>(targetType)->set(&result.value,
        static_cast<TypeString*>(type)->getString(value));
      return std::make_pair(result, true);
    case Type::List:
    {
      result.type = targetType;
      GenericList lsrc = asList();
      TypeList* targetListType = static_cast<TypeList*>(targetType);
      Type* srcElemType = lsrc.elementType();
      void* storage = targetType->initializeStorage();
      Type* dstElemType = targetListType->elementType(storage);
      bool needConvert = (srcElemType->info() != dstElemType->info());
      GenericList lresult;
      lresult.type = targetListType;
      lresult.value = storage;
      GenericListIterator i = lsrc.begin();
      GenericListIterator iend = lsrc.end();
      for (; i!= iend; ++i)
      {
        GenericValue val = *i;
        if (!needConvert)
          lresult.pushBack(val);
        else
        {
          std::pair<GenericValue,bool> c = val.convert(dstElemType);
          lresult.pushBack(c.first);
          if (c.second)
            c.first.destroy();
        }
      }
      return std::make_pair(lresult, true);
    }
    break;
  case Type::Map:
    {
      result.type = targetType;
      GenericMap msrc = asMap();

      TypeMap* targetMapType = static_cast<TypeMap*>(targetType);
      TypeMap* srcMapType = static_cast<TypeMap*>(type);

      Type* srcKeyType = srcMapType->keyType(value);
      Type* srcElementType = srcMapType->elementType(value);

      GenericMap mresult;
      mresult.type = targetType;
      mresult.value = targetMapType->initializeStorage();
      Type* targetKeyType = targetMapType->keyType(mresult.value);
      Type* targetElementType = targetMapType->elementType(mresult.value);

      bool sameKey = srcKeyType->info() == targetKeyType->info();
      bool sameElem = srcElementType->info() == targetElementType->info();

      GenericMapIterator i = msrc.begin();
      GenericMapIterator iend = msrc.end();
      for (; i != iend; ++i)
      {
        std::pair<GenericValue, GenericValue> kv = *i;
        std::pair<GenericValue, bool> ck, cv;
        if (!sameKey)
          ck = kv.first.convert(targetKeyType);
        if (!sameElem)
          cv = kv.second.convert(targetElementType);
        mresult.insert(sameKey?kv.first:ck.first, sameElem?kv.second:cv.first);
        if (!sameKey && ck.second)
          ck.first.destroy();
        if (!sameElem && cv.second)
          cv.first.destroy();
      }
      return std::make_pair(mresult, true);
    }
    break;
  case Type::Pointer:
    {
      Type* srcPointedType = static_cast<TypePointer*>(type)->pointedType();
      Type* dstPointedType = static_cast<TypePointer*>(targetType)->pointedType();
      // We only try to handle conversion for pointer to objects
      if (srcPointedType->kind() != Type::Object || dstPointedType->kind() != Type::Object)
      {
        // However, we need the full check for exact match here
        if (type->info() == targetType->info())
          return std::make_pair(*this, false);
        else
          return std::make_pair(GenericValue(), false);
      }
      GenericValue pointedSrc = static_cast<TypePointer*>(type)->dereference(value);
      std::pair<GenericValue, bool> pointedDstPair = pointedSrc.convert(dstPointedType);
      if (!pointedDstPair.first.type)
        return std::make_pair(GenericValue(), false);
      if (pointedDstPair.second)
        qiLogError("qi.meta") << "assertion error, allocated converted reference";
      // We must re-reference
      GenericValue pointedDst = pointedDstPair.first;
      void* ptr = pointedDst.type->ptrFromStorage(&pointedDst.value);
      result.type = targetType;
      result.value = targetType->initializeStorage(&ptr);
      return std::make_pair(result, false);
    }
    break;
  case Type::Tuple:
    {
      TypeTuple* tsrc = static_cast<TypeTuple*>(type);
      TypeTuple* tdst = static_cast<TypeTuple*>(targetType);
      std::vector<void*> sourceData = tsrc->get(value);
      std::vector<Type*> srcTypes = tsrc->memberTypes(value);
      std::vector<Type*> dstTypes = tdst->memberTypes(0);
      if (dstTypes.size() != sourceData.size())
      {
        qiLogWarning("qi.meta") << "Conversion failure: tuple size mismatch";
        return std::make_pair(GenericValue(), false);
      }

      std::vector<void*> targetData;
      std::vector<bool> mustDestroy;
      for (unsigned i=0; i<dstTypes.size(); ++i)
      {
        std::pair<GenericValue, bool> conv = GenericValue(srcTypes[i], sourceData[i]).convert(dstTypes[i]);
        if (!conv.first.type)
        {
          qiLogWarning("qi.meta") << "Conversion failure in tuple member between "
            << srcTypes[i]->infoString() << " and " << dstTypes[i]->infoString();
          return std::make_pair(GenericValue(), false);
        }
        targetData.push_back(conv.first.value);
        mustDestroy.push_back(conv.second);
      }
      void* dst = tdst->initializeStorage();
      tdst->set(&dst, targetData);
      for (unsigned i=0; i<mustDestroy.size(); ++i)
      {
        if (mustDestroy[i])
          dstTypes[i]->destroy(targetData[i]);
      }
      result.type = targetType;
      result.value = dst;
      return std::make_pair(result, true);
    }
  default:
    break;
  } // switch
  } // skind == dkind
  if (skind == Type::Float && dkind == Type::Int)
  {
    result.type = targetType;
    result.value = targetType->initializeStorage();
    static_cast<TypeInt*>(targetType)->set(&result.value,
      static_cast<TypeFloat*>(type)->get(value));
    return std::make_pair(result, true);
  }
  else if (skind == Type::Int && dkind == Type::Float)
  {
    result.type = targetType;
    result.value = targetType->initializeStorage();
    static_cast<TypeFloat*>(targetType)->set(&result.value,
      static_cast<TypeInt*>(type)->get(value));
    return std::make_pair(result, true);
  }

  static Type* genericValueType = typeOf<GenericValue>();
  static Type* genericObjectType = typeOf<GenericObject>();
  if (targetType->info() == genericValueType->info())
  {
    // Target is metavalue: special case
    GenericValue res;
    res.type = targetType;
    res.value = new GenericValue(*this);
    return std::make_pair(res, false);
  }
  if (type->info() == genericValueType->info())
  { // Source is metavalue: special case
    GenericValue* metaval = (GenericValue*)value;
    return metaval->convert(targetType);
  }
  if (type->info() == genericObjectType->info())
  {
    GenericObject* obj = (GenericObject*)value;
    GenericValue v;
    v.type = obj->type;
    v.value = obj->value;
    return v.convert(targetType);
  }
  if (skind == Type::Object)
  {
    // Try inheritance
    ObjectType* osrc = static_cast<ObjectType*>(type);
    qiLogDebug("qi.meta") << "inheritance check "
    << osrc <<" " << (osrc?osrc->inherits(targetType):false);
    int inheritOffset = 0;
    if (osrc && (inheritOffset =  osrc->inherits(targetType)) != -1)
    {
      // We return a Value that point to the same data as this.
      result.type = targetType;
      result.value = (void*)((long)value + inheritOffset);
      return std::make_pair(result, false);
    }
  }
  if (type->info() == targetType->info())
  {
    return std::make_pair(*this, false);
  }

  return std::make_pair(GenericValue(), false);
}

GenericValue GenericValue::convertCopy(Type* targetType) const
{
  std::pair<GenericValue, bool> res = convert(targetType);
  if (res.second)
    return res.first;
  else
    return res.first.clone();
}

}

QI_TYPE_REGISTER(qi::GenericValue);
<commit_msg>GenericValue::convert: Detect sub-conversion failures.<commit_after>/*
**
** Copyright (C) 2010, 2012 Aldebaran Robotics
**  See COPYING for the license
*/

#include <qimessaging/genericvalue.hpp>
#include <qimessaging/genericobject.hpp>
#include <qimessaging/genericvaluespecialized.hpp>

namespace qi
{

std::pair<GenericValue, bool> GenericValue::convert(Type* targetType) const
{
  /* Can have false-negative (same effective type, different Type instances
   * but we do not care, correct check (by comparing info() result
   * is more expensive than the dummy conversion that will happen.
  */
  if (type == targetType)
  {
    return std::make_pair(*this, false);
  }

  GenericValue result;
  Type::Kind skind = type->kind();
  Type::Kind dkind = targetType->kind();
  if (skind == dkind)
  {
    switch(skind)
    {
    case Type::Float:
      result.type = targetType;
      result.value = targetType->initializeStorage();
      static_cast<TypeFloat*>(targetType)->set(&result.value,
        static_cast<TypeFloat*>(type)->get(value));
      return std::make_pair(result, true);
    case Type::Int:
      result.type = targetType;
      result.value = targetType->initializeStorage();
      static_cast<TypeInt*>(targetType)->set(&result.value,
        static_cast<TypeInt*>(type)->get(value));
      return std::make_pair(result, true);
    case Type::String:
      result.type = targetType;
      result.value = targetType->initializeStorage();
      static_cast<TypeString*>(targetType)->set(&result.value,
        static_cast<TypeString*>(type)->getString(value));
      return std::make_pair(result, true);
    case Type::List:
    {
      result.type = targetType;
      GenericList lsrc = asList();
      TypeList* targetListType = static_cast<TypeList*>(targetType);
      Type* srcElemType = lsrc.elementType();
      void* storage = targetType->initializeStorage();
      Type* dstElemType = targetListType->elementType(storage);
      bool needConvert = (srcElemType->info() != dstElemType->info());
      GenericList lresult;
      lresult.type = targetListType;
      lresult.value = storage;
      GenericListIterator i = lsrc.begin();
      GenericListIterator iend = lsrc.end();
      for (; i!= iend; ++i)
      {
        GenericValue val = *i;
        if (!needConvert)
          lresult.pushBack(val);
        else
        {
          std::pair<GenericValue,bool> c = val.convert(dstElemType);
          lresult.pushBack(c.first);
          if (c.second)
            c.first.destroy();
        }
      }
      return std::make_pair(lresult, true);
    }
    break;
  case Type::Map:
    {
      result.type = targetType;
      GenericMap msrc = asMap();

      TypeMap* targetMapType = static_cast<TypeMap*>(targetType);
      TypeMap* srcMapType = static_cast<TypeMap*>(type);

      Type* srcKeyType = srcMapType->keyType(value);
      Type* srcElementType = srcMapType->elementType(value);

      GenericMap mresult;
      mresult.type = targetType;
      mresult.value = targetMapType->initializeStorage();
      Type* targetKeyType = targetMapType->keyType(mresult.value);
      Type* targetElementType = targetMapType->elementType(mresult.value);

      bool sameKey = srcKeyType->info() == targetKeyType->info();
      bool sameElem = srcElementType->info() == targetElementType->info();

      GenericMapIterator i = msrc.begin();
      GenericMapIterator iend = msrc.end();
      for (; i != iend; ++i)
      {
        std::pair<GenericValue, GenericValue> kv = *i;
        std::pair<GenericValue, bool> ck, cv;
        if (!sameKey)
        {
          ck = kv.first.convert(targetKeyType);
          if (!ck.first.type)
            return std::make_pair(GenericValue(), false);
        }
        if (!sameElem)
        {
          cv = kv.second.convert(targetElementType);
          if (!cv.first.type)
            return std::make_pair(GenericValue(), false);
        }
        mresult.insert(sameKey?kv.first:ck.first, sameElem?kv.second:cv.first);
        if (!sameKey && ck.second)
          ck.first.destroy();
        if (!sameElem && cv.second)
          cv.first.destroy();
      }
      return std::make_pair(mresult, true);
    }
    break;
  case Type::Pointer:
    {
      Type* srcPointedType = static_cast<TypePointer*>(type)->pointedType();
      Type* dstPointedType = static_cast<TypePointer*>(targetType)->pointedType();
      // We only try to handle conversion for pointer to objects
      if (srcPointedType->kind() != Type::Object || dstPointedType->kind() != Type::Object)
      {
        // However, we need the full check for exact match here
        if (type->info() == targetType->info())
          return std::make_pair(*this, false);
        else
          return std::make_pair(GenericValue(), false);
      }
      GenericValue pointedSrc = static_cast<TypePointer*>(type)->dereference(value);
      std::pair<GenericValue, bool> pointedDstPair = pointedSrc.convert(dstPointedType);
      if (!pointedDstPair.first.type)
        return std::make_pair(GenericValue(), false);
      if (pointedDstPair.second)
        qiLogError("qi.meta") << "assertion error, allocated converted reference";
      // We must re-reference
      GenericValue pointedDst = pointedDstPair.first;
      void* ptr = pointedDst.type->ptrFromStorage(&pointedDst.value);
      result.type = targetType;
      result.value = targetType->initializeStorage(&ptr);
      return std::make_pair(result, false);
    }
    break;
  case Type::Tuple:
    {
      TypeTuple* tsrc = static_cast<TypeTuple*>(type);
      TypeTuple* tdst = static_cast<TypeTuple*>(targetType);
      std::vector<void*> sourceData = tsrc->get(value);
      std::vector<Type*> srcTypes = tsrc->memberTypes(value);
      std::vector<Type*> dstTypes = tdst->memberTypes(0);
      if (dstTypes.size() != sourceData.size())
      {
        qiLogWarning("qi.meta") << "Conversion failure: tuple size mismatch";
        return std::make_pair(GenericValue(), false);
      }

      std::vector<void*> targetData;
      std::vector<bool> mustDestroy;
      for (unsigned i=0; i<dstTypes.size(); ++i)
      {
        std::pair<GenericValue, bool> conv = GenericValue(srcTypes[i], sourceData[i]).convert(dstTypes[i]);
        if (!conv.first.type)
        {
          qiLogWarning("qi.meta") << "Conversion failure in tuple member between "
            << srcTypes[i]->infoString() << " and " << dstTypes[i]->infoString();
          return std::make_pair(GenericValue(), false);
        }
        targetData.push_back(conv.first.value);
        mustDestroy.push_back(conv.second);
      }
      void* dst = tdst->initializeStorage();
      tdst->set(&dst, targetData);
      for (unsigned i=0; i<mustDestroy.size(); ++i)
      {
        if (mustDestroy[i])
          dstTypes[i]->destroy(targetData[i]);
      }
      result.type = targetType;
      result.value = dst;
      return std::make_pair(result, true);
    }
  default:
    break;
  } // switch
  } // skind == dkind
  if (skind == Type::Float && dkind == Type::Int)
  {
    result.type = targetType;
    result.value = targetType->initializeStorage();
    static_cast<TypeInt*>(targetType)->set(&result.value,
      static_cast<TypeFloat*>(type)->get(value));
    return std::make_pair(result, true);
  }
  else if (skind == Type::Int && dkind == Type::Float)
  {
    result.type = targetType;
    result.value = targetType->initializeStorage();
    static_cast<TypeFloat*>(targetType)->set(&result.value,
      static_cast<TypeInt*>(type)->get(value));
    return std::make_pair(result, true);
  }

  static Type* genericValueType = typeOf<GenericValue>();
  static Type* genericObjectType = typeOf<GenericObject>();
  if (targetType->info() == genericValueType->info())
  {
    // Target is metavalue: special case
    GenericValue res;
    res.type = targetType;
    res.value = new GenericValue(*this);
    return std::make_pair(res, false);
  }
  if (type->info() == genericValueType->info())
  { // Source is metavalue: special case
    GenericValue* metaval = (GenericValue*)value;
    return metaval->convert(targetType);
  }
  if (type->info() == genericObjectType->info())
  {
    GenericObject* obj = (GenericObject*)value;
    GenericValue v;
    v.type = obj->type;
    v.value = obj->value;
    return v.convert(targetType);
  }
  if (skind == Type::Object)
  {
    // Try inheritance
    ObjectType* osrc = static_cast<ObjectType*>(type);
    qiLogDebug("qi.meta") << "inheritance check "
    << osrc <<" " << (osrc?osrc->inherits(targetType):false);
    int inheritOffset = 0;
    if (osrc && (inheritOffset =  osrc->inherits(targetType)) != -1)
    {
      // We return a Value that point to the same data as this.
      result.type = targetType;
      result.value = (void*)((long)value + inheritOffset);
      return std::make_pair(result, false);
    }
  }
  if (type->info() == targetType->info())
  {
    return std::make_pair(*this, false);
  }

  return std::make_pair(GenericValue(), false);
}

GenericValue GenericValue::convertCopy(Type* targetType) const
{
  std::pair<GenericValue, bool> res = convert(targetType);
  if (res.second)
    return res.first;
  else
    return res.first.clone();
}

}

QI_TYPE_REGISTER(qi::GenericValue);
<|endoftext|>