<commit_before>#include "winptyprocess.h"
#include <QFile>
#include <QFileInfo>
#include <sstream>
#include <QCoreApplication>
#include <windows.h>
#include <QDir>

#define DEBUG_VAR_LEGACY "WINPTYDBG"
#define DEBUG_VAR_ACTUAL "WINPTY_DEBUG"
#define SHOW_CONSOLE_VAR "WINPTY_SHOW_CONSOLE"
#define WINPTY_AGENT_NAME "winpty-agent.exe"
#define WINPTY_DLL_NAME "winpty32.dll"

//#define WINPTY_DLL "winpty.dll"

static HMODULE hWinPtyDLL = NULL;

/* Gets the error code from the error object. */
WINPTY_API winpty_result_t (*winpty_error_code)(winpty_error_ptr_t err);

/* Returns a textual representation of the error.  The string is freed when
 * the error is freed. */
WINPTY_API LPCWSTR (*winpty_error_msg)(winpty_error_ptr_t err);

/* Free the error object.  Every error returned from the winpty API must be
 * freed. */
WINPTY_API void (*winpty_error_free)(winpty_error_ptr_t err);

WINPTY_API winpty_config_t *
(*winpty_config_new)(UINT64 agentFlags, winpty_error_ptr_t *err /*OPTIONAL*/);

/* Free the cfg object after passing it to winpty_open. */
WINPTY_API void (*winpty_config_free)(winpty_config_t *cfg);

WINPTY_API void
(*winpty_config_set_initial_size)(winpty_config_t *cfg, int cols, int rows);

/* Set the mouse mode to one of the WINPTY_MOUSE_MODE_xxx constants. */
WINPTY_API void
(*winpty_config_set_mouse_mode)(winpty_config_t *cfg, int mouseMode);

/* Amount of time to wait for the agent to startup and to wait for any given
 * agent RPC request.  Must be greater than 0.  Can be INFINITE. */
WINPTY_API void
(*winpty_config_set_agent_timeout)(winpty_config_t *cfg, DWORD timeoutMs);

WINPTY_API winpty_t *
(*winpty_open)(const winpty_config_t *cfg,
            winpty_error_ptr_t *err /*OPTIONAL*/);

WINPTY_API HANDLE (*winpty_agent_process)(winpty_t *wp);
WINPTY_API LPCWSTR (*winpty_conin_name)(winpty_t *wp);
WINPTY_API LPCWSTR (*winpty_conout_name)(winpty_t *wp);
WINPTY_API LPCWSTR (*winpty_conerr_name)(winpty_t *wp);
WINPTY_API winpty_spawn_config_t *
(*winpty_spawn_config_new)(UINT64 spawnFlags,
                        LPCWSTR appname /*OPTIONAL*/,
                        LPCWSTR cmdline /*OPTIONAL*/,
                        LPCWSTR cwd /*OPTIONAL*/,
                        LPCWSTR env /*OPTIONAL*/,
                        winpty_error_ptr_t *err /*OPTIONAL*/);
WINPTY_API void (*winpty_spawn_config_free)(winpty_spawn_config_t *cfg);
WINPTY_API BOOL
(*winpty_spawn)(winpty_t *wp,
             const winpty_spawn_config_t *cfg,
             HANDLE *process_handle /*OPTIONAL*/,
             HANDLE *thread_handle /*OPTIONAL*/,
             DWORD *create_process_error /*OPTIONAL*/,
             winpty_error_ptr_t *err /*OPTIONAL*/);
WINPTY_API BOOL
(*winpty_set_size)(winpty_t *wp, int cols, int rows,
                winpty_error_ptr_t *err /*OPTIONAL*/);
WINPTY_API int
(*winpty_get_console_process_list)(winpty_t *wp, int *processList, const int processCount,
                                winpty_error_ptr_t *err /*OPTIONAL*/);
WINPTY_API void (*winpty_free)(winpty_t *wp);

static bool winpty_init()
{
    int i;
    static struct
    {
    char	    *name;
    FARPROC	    *ptr;
    } winpty_entry[] =
    {
    {"winpty_conerr_name", (FARPROC*)&winpty_conerr_name},
    {"winpty_config_free", (FARPROC*)&winpty_config_free},
    {"winpty_config_new", (FARPROC*)&winpty_config_new},
    {"winpty_config_set_mouse_mode",
                      (FARPROC*)&winpty_config_set_mouse_mode},
    {"winpty_config_set_initial_size",
                    (FARPROC*)&winpty_config_set_initial_size},
    {"winpty_conin_name", (FARPROC*)&winpty_conin_name},
    {"winpty_conout_name", (FARPROC*)&winpty_conout_name},
    {"winpty_error_free", (FARPROC*)&winpty_error_free},
    {"winpty_free", (FARPROC*)&winpty_free},
    {"winpty_open", (FARPROC*)&winpty_open},
    {"winpty_spawn", (FARPROC*)&winpty_spawn},
    {"winpty_spawn_config_free", (FARPROC*)&winpty_spawn_config_free},
    {"winpty_spawn_config_new", (FARPROC*)&winpty_spawn_config_new},
    {"winpty_error_msg", (FARPROC*)&winpty_error_msg},
    {"winpty_set_size", (FARPROC*)&winpty_set_size},
    {"winpty_agent_process", (FARPROC*)&winpty_agent_process},
    {"winpty_get_console_process_list", (FARPROC*)&winpty_get_console_process_list},
    {NULL, NULL}
    };

    // No need to initialize twice.
    if (hWinPtyDLL)
        return true;
    // Load winpty.dll, prefer using the 'winptydll' option, fall back to just
    // winpty.dll.
    if (!hWinPtyDLL)
        hWinPtyDLL = LoadLibraryA(WINPTY_DLL_NAME);

    if (!hWinPtyDLL)
    {
        return false;
    }
    for (i = 0; winpty_entry[i].name != NULL
         && winpty_entry[i].ptr != NULL; ++i)
    {
        if ((*winpty_entry[i].ptr = (FARPROC)GetProcAddress(hWinPtyDLL,
                                                            winpty_entry[i].name)) == NULL)
        {
            hWinPtyDLL = NULL;
            return false;
        }
    }

    return true;
}

QString castErrorToString(winpty_error_ptr_t error_ptr)
{
    return QString::fromStdWString(winpty_error_msg(error_ptr));
}

WinPtyProcess::WinPtyProcess()
    : IPtyProcess()
    , m_ptyHandler(0)
    , m_innerHandle(0)
    , m_inSocket(0)
    , m_outSocket(0)
{
    m_initPty = winpty_init();
}

WinPtyProcess::~WinPtyProcess()
{
    kill();
}

bool WinPtyProcess::startProcess(const QString &shellPath, const QStringList &arguments, const QString &workingDirectory, QStringList environment, qint16 rows, qint16 cols)
{
//    if (!isAvailable())
//    {
//        m_lastError = QString("WinPty Error: winpty-agent.exe or winpty.dll not found!");
//        return false;
//    }

    //already running
    if (m_ptyHandler)
        return false;

    QFileInfo fi(shellPath);
    if (fi.isRelative() || !QFile::exists(shellPath))
    {
        //todo add auto-find executable in PATH env var
        m_lastError = QString("WinPty Error: shell file path must be absolute");
        return false;
    }

    m_shellPath = QDir::toNativeSeparators(shellPath);
    m_size = QPair<qint16, qint16>(cols, rows);

#ifdef PTYQT_DEBUG
    if (m_trace)
    {
        environment.append(QString("%1=1").arg(DEBUG_VAR_LEGACY));
        environment.append(QString("%1=trace").arg(DEBUG_VAR_ACTUAL));
        environment.append(QString("%1=1").arg(SHOW_CONSOLE_VAR));
        SetEnvironmentVariable(DEBUG_VAR_LEGACY, "1");
        SetEnvironmentVariable(DEBUG_VAR_ACTUAL, "trace");
        SetEnvironmentVariable(SHOW_CONSOLE_VAR, "1");
    }
#endif

    //env
    std::wstringstream envBlock;
    foreach (QString line, environment)
    {
        envBlock << line.toStdWString() << L'\0';
    }
    std::wstring env = envBlock.str();

    //create start config
    winpty_error_ptr_t errorPtr = 0;
    winpty_config_t* startConfig = winpty_config_new(0, &errorPtr);
    if (startConfig == 0)
    {
        m_lastError = QString("WinPty Error: create start config -> %1").arg(castErrorToString(errorPtr));
        return false;
    }
    winpty_error_free(errorPtr);

    //set params
    winpty_config_set_initial_size(startConfig, cols, rows);
    winpty_config_set_mouse_mode(startConfig, WINPTY_MOUSE_MODE_AUTO);
    //winpty_config_set_agent_timeout();

    //start agent
    m_ptyHandler = winpty_open(startConfig, &errorPtr);
    winpty_config_free(startConfig); //start config is local var, free it after use

    if (m_ptyHandler == 0)
    {
        m_lastError = QString("WinPty Error: start agent -> %1").arg(castErrorToString(errorPtr));
        return false;
    }
    winpty_error_free(errorPtr);

    //create spawn config
    winpty_spawn_config_t* spawnConfig = winpty_spawn_config_new(WINPTY_SPAWN_FLAG_AUTO_SHUTDOWN, m_shellPath.toStdWString().c_str(),
                                                                 //commandLine.toStdWString().c_str(), cwd.toStdWString().c_str(),
                                                                 NULL, workingDirectory.toStdWString().c_str(),
                                                                 env.c_str(),
                                                                 &errorPtr);

    if (spawnConfig == 0)
    {
        m_lastError = QString("WinPty Error: create spawn config -> %1").arg(castErrorToString(errorPtr));
        return false;
    }
    winpty_error_free(errorPtr);

    //spawn the new process
    BOOL spawnSuccess = winpty_spawn(m_ptyHandler, spawnConfig, &m_innerHandle, 0, 0, &errorPtr);
    winpty_spawn_config_free(spawnConfig); //spawn config is local var, free it after use
    if (!spawnSuccess)
    {
        m_lastError = QString("WinPty Error: start terminal process -> %1").arg(castErrorToString(errorPtr));
        return false;
    }
    winpty_error_free(errorPtr);

    m_pid = (int)GetProcessId(m_innerHandle);

    //get pipe names
    LPCWSTR conInPipeName = winpty_conin_name(m_ptyHandler);
    m_conInName = QString::fromStdWString(std::wstring(conInPipeName));
    m_inSocket = new QLocalSocket();
    m_inSocket->connectToServer(m_conInName, QIODevice::WriteOnly);
    m_inSocket->waitForConnected();

    LPCWSTR conOutPipeName = winpty_conout_name(m_ptyHandler);
    m_conOutName = QString::fromStdWString(std::wstring(conOutPipeName));
    m_outSocket = new QLocalSocket();
    m_outSocket->connectToServer(m_conOutName, QIODevice::ReadOnly);
    m_outSocket->waitForConnected();

    if (m_inSocket->state() != QLocalSocket::ConnectedState && m_outSocket->state() != QLocalSocket::ConnectedState)
    {
        m_lastError = QString("WinPty Error: Unable to connect local sockets -> %1 / %2").arg(m_inSocket->errorString()).arg(m_outSocket->errorString());
        m_inSocket->deleteLater();
        m_outSocket->deleteLater();
        m_inSocket = 0;
        m_outSocket = 0;
        return false;
    }

    connect(m_outSocket,SIGNAL(disconnected()),this,SLOT(disconnected()));

    return true;
}

bool WinPtyProcess::resize(qint16 cols, qint16 rows)
{
    if (m_ptyHandler == 0)
    {
        return false;
    }

    bool res = winpty_set_size(m_ptyHandler, cols, rows, 0);

    if (res)
    {
        m_size = QPair<qint16, qint16>(cols, rows);
    }

    return res;
}

bool WinPtyProcess::kill()
{
    bool exitCode = false;
    if (m_innerHandle != 0 && m_ptyHandler != 0)
    {
        //disconnect all signals (readyRead, ...)
        m_inSocket->disconnect();
        m_outSocket->disconnect();

        //disconnect for server
        m_inSocket->disconnectFromServer();
        m_outSocket->disconnectFromServer();

        m_inSocket->deleteLater();
        m_outSocket->deleteLater();

        m_inSocket = 0;
        m_outSocket = 0;

        winpty_free(m_ptyHandler);
        exitCode = CloseHandle(m_innerHandle);

        m_ptyHandler = 0;
        m_innerHandle = 0;
        m_conInName = QString();
        m_conOutName = QString();
        m_pid = 0;
    }
    return exitCode;
}

IPtyProcess::PtyType WinPtyProcess::type()
{
    return IPtyProcess::WinPty;
}

QString WinPtyProcess::dumpDebugInfo()
{
#ifdef PTYQT_DEBUG
    return QString("PID: %1, ConIn: %2, ConOut: %3, Type: %4, Cols: %5, Rows: %6, IsRunning: %7, Shell: %8")
            .arg(m_pid).arg(m_conInName).arg(m_conOutName).arg(type())
            .arg(m_size.first).arg(m_size.second).arg(m_ptyHandler != nullptr)
            .arg(m_shellPath);
#else
    return QString("Nothing...");
#endif
}

QIODevice *WinPtyProcess::notifier()
{
    return m_outSocket;
}

QByteArray WinPtyProcess::readAll()
{
    return m_outSocket->readAll();
}

qint64 WinPtyProcess::write(const QByteArray &byteArray)
{
    return m_inSocket->write(byteArray);
}

bool WinPtyProcess::isAvailable()
{
    m_initPty;
}

void WinPtyProcess::moveToThread(QThread *targetThread)
{
    m_inSocket->moveToThread(targetThread);
    m_outSocket->moveToThread(targetThread);
}

bool WinPtyProcess::hasProcessList() const
{
    int list[64];
    if (winpty_get_console_process_list) {
        int n = winpty_get_console_process_list(m_ptyHandler,list,64,0);
        return n >= 1;
    }
    return true;
}

void WinPtyProcess::disconnected()
{
    emit exited();
}
<commit_msg>terminal: fix winpty load for Q_OS_WIN64<commit_after>#include "winptyprocess.h"
#include <QFile>
#include <QFileInfo>
#include <sstream>
#include <QCoreApplication>
#include <windows.h>
#include <QDir>

#define DEBUG_VAR_LEGACY "WINPTYDBG"
#define DEBUG_VAR_ACTUAL "WINPTY_DEBUG"
#define SHOW_CONSOLE_VAR "WINPTY_SHOW_CONSOLE"
#define WINPTY_AGENT_NAME "winpty-agent.exe"
#ifdef Q_OS_WIN64
#define WINPTY_DLL_NAME "winpty64.dll"
#else
#define WINPTY_DLL_NAME "winpty32.dll"
#endif

//#define WINPTY_DLL "winpty.dll"

static HMODULE hWinPtyDLL = NULL;

/* Gets the error code from the error object. */
WINPTY_API winpty_result_t (*winpty_error_code)(winpty_error_ptr_t err);

/* Returns a textual representation of the error.  The string is freed when
 * the error is freed. */
WINPTY_API LPCWSTR (*winpty_error_msg)(winpty_error_ptr_t err);

/* Free the error object.  Every error returned from the winpty API must be
 * freed. */
WINPTY_API void (*winpty_error_free)(winpty_error_ptr_t err);

WINPTY_API winpty_config_t *
(*winpty_config_new)(UINT64 agentFlags, winpty_error_ptr_t *err /*OPTIONAL*/);

/* Free the cfg object after passing it to winpty_open. */
WINPTY_API void (*winpty_config_free)(winpty_config_t *cfg);

WINPTY_API void
(*winpty_config_set_initial_size)(winpty_config_t *cfg, int cols, int rows);

/* Set the mouse mode to one of the WINPTY_MOUSE_MODE_xxx constants. */
WINPTY_API void
(*winpty_config_set_mouse_mode)(winpty_config_t *cfg, int mouseMode);

/* Amount of time to wait for the agent to startup and to wait for any given
 * agent RPC request.  Must be greater than 0.  Can be INFINITE. */
WINPTY_API void
(*winpty_config_set_agent_timeout)(winpty_config_t *cfg, DWORD timeoutMs);

WINPTY_API winpty_t *
(*winpty_open)(const winpty_config_t *cfg,
            winpty_error_ptr_t *err /*OPTIONAL*/);

WINPTY_API HANDLE (*winpty_agent_process)(winpty_t *wp);
WINPTY_API LPCWSTR (*winpty_conin_name)(winpty_t *wp);
WINPTY_API LPCWSTR (*winpty_conout_name)(winpty_t *wp);
WINPTY_API LPCWSTR (*winpty_conerr_name)(winpty_t *wp);
WINPTY_API winpty_spawn_config_t *
(*winpty_spawn_config_new)(UINT64 spawnFlags,
                        LPCWSTR appname /*OPTIONAL*/,
                        LPCWSTR cmdline /*OPTIONAL*/,
                        LPCWSTR cwd /*OPTIONAL*/,
                        LPCWSTR env /*OPTIONAL*/,
                        winpty_error_ptr_t *err /*OPTIONAL*/);
WINPTY_API void (*winpty_spawn_config_free)(winpty_spawn_config_t *cfg);
WINPTY_API BOOL
(*winpty_spawn)(winpty_t *wp,
             const winpty_spawn_config_t *cfg,
             HANDLE *process_handle /*OPTIONAL*/,
             HANDLE *thread_handle /*OPTIONAL*/,
             DWORD *create_process_error /*OPTIONAL*/,
             winpty_error_ptr_t *err /*OPTIONAL*/);
WINPTY_API BOOL
(*winpty_set_size)(winpty_t *wp, int cols, int rows,
                winpty_error_ptr_t *err /*OPTIONAL*/);
WINPTY_API int
(*winpty_get_console_process_list)(winpty_t *wp, int *processList, const int processCount,
                                winpty_error_ptr_t *err /*OPTIONAL*/);
WINPTY_API void (*winpty_free)(winpty_t *wp);

static bool winpty_init()
{
    int i;
    static struct
    {
    char	    *name;
    FARPROC	    *ptr;
    } winpty_entry[] =
    {
    {"winpty_conerr_name", (FARPROC*)&winpty_conerr_name},
    {"winpty_config_free", (FARPROC*)&winpty_config_free},
    {"winpty_config_new", (FARPROC*)&winpty_config_new},
    {"winpty_config_set_mouse_mode",
                      (FARPROC*)&winpty_config_set_mouse_mode},
    {"winpty_config_set_initial_size",
                    (FARPROC*)&winpty_config_set_initial_size},
    {"winpty_conin_name", (FARPROC*)&winpty_conin_name},
    {"winpty_conout_name", (FARPROC*)&winpty_conout_name},
    {"winpty_error_free", (FARPROC*)&winpty_error_free},
    {"winpty_free", (FARPROC*)&winpty_free},
    {"winpty_open", (FARPROC*)&winpty_open},
    {"winpty_spawn", (FARPROC*)&winpty_spawn},
    {"winpty_spawn_config_free", (FARPROC*)&winpty_spawn_config_free},
    {"winpty_spawn_config_new", (FARPROC*)&winpty_spawn_config_new},
    {"winpty_error_msg", (FARPROC*)&winpty_error_msg},
    {"winpty_set_size", (FARPROC*)&winpty_set_size},
    {"winpty_agent_process", (FARPROC*)&winpty_agent_process},
    {"winpty_get_console_process_list", (FARPROC*)&winpty_get_console_process_list},
    {NULL, NULL}
    };

    // No need to initialize twice.
    if (hWinPtyDLL)
        return true;
    // Load winpty.dll, prefer using the 'winptydll' option, fall back to just
    // winpty.dll.
    if (!hWinPtyDLL)
        hWinPtyDLL = LoadLibraryA(WINPTY_DLL_NAME);

    if (!hWinPtyDLL)
    {
        return false;
    }
    for (i = 0; winpty_entry[i].name != NULL
         && winpty_entry[i].ptr != NULL; ++i)
    {
        if ((*winpty_entry[i].ptr = (FARPROC)GetProcAddress(hWinPtyDLL,
                                                            winpty_entry[i].name)) == NULL)
        {
            qDebug() << "GetProcAddress false" << winpty_entry[i].name;
       //     hWinPtyDLL = NULL;
       //     return false;
        }
    }

    return true;
}

QString castErrorToString(winpty_error_ptr_t error_ptr)
{
    return QString::fromStdWString(winpty_error_msg(error_ptr));
}

WinPtyProcess::WinPtyProcess()
    : IPtyProcess()
    , m_ptyHandler(0)
    , m_innerHandle(0)
    , m_inSocket(0)
    , m_outSocket(0)
{
    m_initPty = winpty_init();
}

WinPtyProcess::~WinPtyProcess()
{
    kill();
}

bool WinPtyProcess::startProcess(const QString &shellPath, const QStringList &arguments, const QString &workingDirectory, QStringList environment, qint16 rows, qint16 cols)
{
//    if (!isAvailable())
//    {
//        m_lastError = QString("WinPty Error: winpty-agent.exe or winpty.dll not found!");
//        return false;
//    }

    //already running
    if (m_ptyHandler)
        return false;

    QFileInfo fi(shellPath);
    if (fi.isRelative() || !QFile::exists(shellPath))
    {
        //todo add auto-find executable in PATH env var
        m_lastError = QString("WinPty Error: shell file path must be absolute");
        return false;
    }

    m_shellPath = QDir::toNativeSeparators(shellPath);
    m_size = QPair<qint16, qint16>(cols, rows);

#ifdef PTYQT_DEBUG
    if (m_trace)
    {
        environment.append(QString("%1=1").arg(DEBUG_VAR_LEGACY));
        environment.append(QString("%1=trace").arg(DEBUG_VAR_ACTUAL));
        environment.append(QString("%1=1").arg(SHOW_CONSOLE_VAR));
        SetEnvironmentVariable(DEBUG_VAR_LEGACY, "1");
        SetEnvironmentVariable(DEBUG_VAR_ACTUAL, "trace");
        SetEnvironmentVariable(SHOW_CONSOLE_VAR, "1");
    }
#endif

    //env
    std::wstringstream envBlock;
    foreach (QString line, environment)
    {
        envBlock << line.toStdWString() << L'\0';
    }
    std::wstring env = envBlock.str();

    //create start config
    winpty_error_ptr_t errorPtr = 0;
    winpty_config_t* startConfig = winpty_config_new(0, &errorPtr);
    if (startConfig == 0)
    {
        m_lastError = QString("WinPty Error: create start config -> %1").arg(castErrorToString(errorPtr));
        return false;
    }
    winpty_error_free(errorPtr);

    //set params
    winpty_config_set_initial_size(startConfig, cols, rows);
    winpty_config_set_mouse_mode(startConfig, WINPTY_MOUSE_MODE_AUTO);
    //winpty_config_set_agent_timeout();

    //start agent
    m_ptyHandler = winpty_open(startConfig, &errorPtr);
    winpty_config_free(startConfig); //start config is local var, free it after use

    if (m_ptyHandler == 0)
    {
        m_lastError = QString("WinPty Error: start agent -> %1").arg(castErrorToString(errorPtr));
        return false;
    }
    winpty_error_free(errorPtr);

    //create spawn config
    winpty_spawn_config_t* spawnConfig = winpty_spawn_config_new(WINPTY_SPAWN_FLAG_AUTO_SHUTDOWN, m_shellPath.toStdWString().c_str(),
                                                                 //commandLine.toStdWString().c_str(), cwd.toStdWString().c_str(),
                                                                 NULL, workingDirectory.toStdWString().c_str(),
                                                                 env.c_str(),
                                                                 &errorPtr);

    if (spawnConfig == 0)
    {
        m_lastError = QString("WinPty Error: create spawn config -> %1").arg(castErrorToString(errorPtr));
        return false;
    }
    winpty_error_free(errorPtr);

    //spawn the new process
    BOOL spawnSuccess = winpty_spawn(m_ptyHandler, spawnConfig, &m_innerHandle, 0, 0, &errorPtr);
    winpty_spawn_config_free(spawnConfig); //spawn config is local var, free it after use
    if (!spawnSuccess)
    {
        m_lastError = QString("WinPty Error: start terminal process -> %1").arg(castErrorToString(errorPtr));
        return false;
    }
    winpty_error_free(errorPtr);

    m_pid = (int)GetProcessId(m_innerHandle);

    //get pipe names
    LPCWSTR conInPipeName = winpty_conin_name(m_ptyHandler);
    m_conInName = QString::fromStdWString(std::wstring(conInPipeName));
    m_inSocket = new QLocalSocket();
    m_inSocket->connectToServer(m_conInName, QIODevice::WriteOnly);
    m_inSocket->waitForConnected();

    LPCWSTR conOutPipeName = winpty_conout_name(m_ptyHandler);
    m_conOutName = QString::fromStdWString(std::wstring(conOutPipeName));
    m_outSocket = new QLocalSocket();
    m_outSocket->connectToServer(m_conOutName, QIODevice::ReadOnly);
    m_outSocket->waitForConnected();

    if (m_inSocket->state() != QLocalSocket::ConnectedState && m_outSocket->state() != QLocalSocket::ConnectedState)
    {
        m_lastError = QString("WinPty Error: Unable to connect local sockets -> %1 / %2").arg(m_inSocket->errorString()).arg(m_outSocket->errorString());
        m_inSocket->deleteLater();
        m_outSocket->deleteLater();
        m_inSocket = 0;
        m_outSocket = 0;
        return false;
    }

    connect(m_outSocket,SIGNAL(disconnected()),this,SLOT(disconnected()));

    return true;
}

bool WinPtyProcess::resize(qint16 cols, qint16 rows)
{
    if (m_ptyHandler == 0)
    {
        return false;
    }

    bool res = winpty_set_size(m_ptyHandler, cols, rows, 0);

    if (res)
    {
        m_size = QPair<qint16, qint16>(cols, rows);
    }

    return res;
}

bool WinPtyProcess::kill()
{
    bool exitCode = false;
    if (m_innerHandle != 0 && m_ptyHandler != 0)
    {
        //disconnect all signals (readyRead, ...)
        m_inSocket->disconnect();
        m_outSocket->disconnect();

        //disconnect for server
        m_inSocket->disconnectFromServer();
        m_outSocket->disconnectFromServer();

        m_inSocket->deleteLater();
        m_outSocket->deleteLater();

        m_inSocket = 0;
        m_outSocket = 0;

        winpty_free(m_ptyHandler);
        exitCode = CloseHandle(m_innerHandle);

        m_ptyHandler = 0;
        m_innerHandle = 0;
        m_conInName = QString();
        m_conOutName = QString();
        m_pid = 0;
    }
    return exitCode;
}

IPtyProcess::PtyType WinPtyProcess::type()
{
    return IPtyProcess::WinPty;
}

QString WinPtyProcess::dumpDebugInfo()
{
#ifdef PTYQT_DEBUG
    return QString("PID: %1, ConIn: %2, ConOut: %3, Type: %4, Cols: %5, Rows: %6, IsRunning: %7, Shell: %8")
            .arg(m_pid).arg(m_conInName).arg(m_conOutName).arg(type())
            .arg(m_size.first).arg(m_size.second).arg(m_ptyHandler != nullptr)
            .arg(m_shellPath);
#else
    return QString("Nothing...");
#endif
}

QIODevice *WinPtyProcess::notifier()
{
    return m_outSocket;
}

QByteArray WinPtyProcess::readAll()
{
    return m_outSocket->readAll();
}

qint64 WinPtyProcess::write(const QByteArray &byteArray)
{
    return m_inSocket->write(byteArray);
}

bool WinPtyProcess::isAvailable()
{
    return m_initPty;
}

void WinPtyProcess::moveToThread(QThread *targetThread)
{
    m_inSocket->moveToThread(targetThread);
    m_outSocket->moveToThread(targetThread);
}

bool WinPtyProcess::hasProcessList() const
{
    int list[64];
    if (winpty_get_console_process_list) {
        int n = winpty_get_console_process_list(m_ptyHandler,list,64,0);
        return n >= 1;
    }
    return true;
}

void WinPtyProcess::disconnected()
{
    emit exited();
}
<|endoftext|>


<commit_before>#include "scientistservice.h"
#include <algorithm>
#include <string>

using namespace std;

struct ScientistComparison {
  bool operator() (Scientist a,Scientist b) { return (a.getName()<b.getName());}
};

ScientistService::ScientistService()
{

}

vector<Scientist> ScientistService::getScientist(/* TODO: parameters */)
{
    vector<Scientist> scientist;

    // scientist = sækja scientists frá dataaccess

    // TODO: business logic!

    // Sort by name:
    ScientistComparison cmp;
    std::sort(scientist.begin(), scientist.end(), cmp);

    return scientist;
}

void ScientistService::addScientist(string name, char gender, int age, int death)
{   //bætir scientist við listann
    Scientist scientist(name, gender, age, death);
    _scientists.push_back(scientist);

    //senda _scientists til dataaccess til að savea í skránna
}

void ScientistService::addScientist(string name, char gender, int age)
{   //sama og fyrir ofan, án death date.
    Scientist scientist(name, gender, age);
    _scientists.push_back(scientist);

    //senda _scientists til dataaccess til að savea í skránna
}

<commit_msg>smá breyting á function sem les inn í Scientist vector<commit_after>#include "scientistservice.h"
#include <algorithm>
#include <string>

using namespace std;

struct ScientistComparison {
  bool operator() (Scientist a,Scientist b) { return (a.getName()<b.getName());}
};

ScientistService::ScientistService()
{

}

vector<Scientist> ScientistService::getScientist(/* TODO: parameters */)
{
    vector<Scientist> scientist;

    // scientist = sækja scientists frá dataaccess

    // TODO: business logic!

    // Sort by name:
    ScientistComparison cmp;
    std::sort(scientist.begin(), scientist.end(), cmp);

    return scientist;
}

void ScientistService::addScientist(string name, char gender, int age, int death)
{   //bætir scientist við listann
    Scientist scientist(name, gender, age, death);
    _scientists.push_back(scientist);

    //senda _scientists til dataaccess til að savea í skránna
}

<|endoftext|>


<commit_before>#line 2 "sxc:Account/Roster.cxx"
// LICENSE/*{{{*/
/*
  sxc - Simple Xmpp Client
  Copyright (C) 2008 Dennis Felsing, Andreas Waidler

  Permission to use, copy, modify, and/or distribute this software for any
  purpose with or without fee is hereby granted, provided that the above
  copyright notice and this permission notice appear in all copies.

  THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
  WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
  MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
  ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
  WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
  ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
  OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 */
/*}}}*/

// INCLUDE/*{{{*/

#ifdef HAVE_CONFIG_H
# include <config.hxx>
#endif

#include <string>
#include <map>
#include <sstream>

#include <gloox/clientbase.h>
#include <gloox/jid.h>
#include <gloox/presence.h>
#include <gloox/iq.h>
#include <gloox/message.h>
#include <gloox/messagehandler.h>
#include <gloox/error.h>

#include <libsxc/generateString.hxx>
#include <libsxc/Exception/Exception.hxx>
#include <libsxc/Debug/Logger.hxx>
#include <libsxc/Error/Handler.hxx>

#include <Account/Roster.hxx>
#include <Account/RosterType.hxx>
#include <Contact/Contact.hxx>
#include <File/AbcOutput.hxx>
#include <Account/File/Info.hxx>
#include <File/createDir.hxx>
#include <Exit/Code.hxx>

/*}}}*/

namespace Account
{
  Roster::Roster(/*{{{*/
    gloox::Client &client,
    ::File::AbcOutput &out,
    File::Info &nfo,
    libsxc::Error::Handler &eh)
  : RosterListener()
  , _client(client)
  , _out(out)
  , _nfo(nfo)
  , _contacts()
  , _eh(eh)
  {
    // Asynchronous subscription request handling.
    _client.rosterManager()->registerRosterListener(this, false);
    _client.registerMessageHandler(this);
  }/*}}}*/
  Roster::~Roster()/*{{{*/
  {
    _client.rosterManager()->removeRosterListener();
    _client.removeMessageHandler(this);

    for(
    contactList::iterator entry = _contacts.begin();
    entry != _contacts.end();
    ++entry) {
      delete entry->second;
    }
  }/*}}}*/

  void Roster::sendMessage(const gloox::JID &jid, const std::string &message)/*{{{*/
  {
    _addContactLocal(jid);

    contactList::iterator contact = _getContact(jid.bare());
    if (_contacts.end() == contact)
      return; // FIXME: Throw exception, this is really unexpected.

    contact->second->sendMessage(message);
  }/*}}}*/

  void Roster::addContact(const gloox::JID &jid)/*{{{*/
  {
    _addContactLocal(jid);
    _addContactRemote(jid);
  }/*}}}*/
  void Roster::removeContact(const gloox::JID &jid) const/*{{{*/
  {
    _checkClient();

    LOG("Remove contact from the roster: \"" + jid.bare() + "\".");

    _client.rosterManager()->remove(jid);
    _client.rosterManager()->synchronize();
  }/*}}}*/

  void Roster::subscribe(/*{{{*/
    const gloox::JID &jid,
    const std::string &message) const
  {
    _checkClient();

    LOG(
      "Sending subscription request: (jid: \"" + jid.bare() +
      "\", message: \"" + message + "\").");

    const gloox::StringList groups;
    _client.rosterManager()->subscribe(jid, jid.bare(), groups, message);
    _client.rosterManager()->synchronize();
  }/*}}}*/
  void Roster::unsubscribe(/*{{{*/
    const gloox::JID &jid,
    const std::string &message) const
  {
    _checkClient();

    LOG(
      "Sending unsubscription request: (jid: \"" + jid.bare() +
      "\", message: \"" + message + "\").");

    _client.rosterManager()->unsubscribe(jid, message);
    _client.rosterManager()->synchronize();
  }/*}}}*/

  void Roster::acknowledgeSubscription(const gloox::JID &jid) const/*{{{*/
  {
    LOG(
      "Acknowledge subscription request: \"" + jid.bare() + "\".");

    _client.rosterManager()->ackSubscriptionRequest(jid, true);
  }/*}}}*/
  void Roster::declineSubscription(const gloox::JID &jid) const/*{{{*/
  {
    LOG(
      "Decline subscription request: \"" + jid.bare() + "\".");

    _client.rosterManager()->ackSubscriptionRequest(jid, false);
  }/*}}}*/

  void Roster::handleMessage(/*{{{*/
    const gloox::Message &msg,
    gloox::MessageSession *session)
  {
    _addContactLocal(msg.from()); // Local only.

    contactList::iterator contact = _getContact(msg.from().bare());
    if (_contacts.end() == contact)
      return;

    contact->second->handleMessage(msg, session);
  }/*}}}*/

  gloox::MessageSession *Roster::createMessageSession(/*{{{*/
    gloox::MessageHandler *handler,
    const gloox::JID &jid)
  {
    gloox::MessageSession *session = new gloox::MessageSession(&_client, jid);
    session->registerMessageHandler(handler);
    return session;
  }/*}}}*/
  void Roster::disposeMessageSession(gloox::MessageSession *session)/*{{{*/
  {
    // This deletes the session. Else the destructor of gloox::ClientBase would
    // handle this.
    _client.disposeMessageSession(session);
  }/*}}}*/

  const gloox::JID &Roster::getJid()/*{{{*/
  {
    return _client.jid();
  }/*}}}*/

  void Roster::handleItemAdded(const gloox::JID &jid)/*{{{*/
  {
    LOG("Item added to the roster: \"" + jid.bare() + "\".");

    _addContactLocal(jid);
  }/*}}}*/
  void Roster::handleItemSubscribed(const gloox::JID &jid)/*{{{*/
  {
    LOG("Item subscribed: \"" + jid.bare() + "\".");
  }/*}}}*/
  void Roster::handleItemRemoved(const gloox::JID &jid)/*{{{*/
  {
    LOG("Item removed from the roster: \"" + jid.bare() + "\".");

    contactList::iterator contact = _getContact(jid.bare());
    if (_contacts.end() == contact)
      return;
    delete contact->second;
    _contacts.erase(contact);

    // _account->print("Contact removed: \"" + jid.bare() + "\".");
  }/*}}}*/
  void Roster::handleItemUpdated(const gloox::JID &jid)/*{{{*/
  {
    LOG("Item updated: \"" + jid.bare() + "\".");
  }/*}}}*/
  void Roster::handleItemUnsubscribed(const gloox::JID &jid)/*{{{*/
  {
    LOG(
      "Item unsubscribed: \"" + jid.bare() + "\".");
  }/*}}}*/
  void Roster::handleRoster(const gloox::Roster &roster)/*{{{*/
  {
    LOG("Initial roster received from the server.");

    for(
    gloox::Roster::const_iterator entry = roster.begin();
    entry != roster.end();
    ++entry) {
      _addContactLocal(entry->first);

      contactList::iterator contact = _getContact(entry->first);
      if (_contacts.end() == contact)
        continue;

      contact->second->updateRoster(Remote);
    }
  }/*}}}*/
  void Roster::handleRosterPresence(/*{{{*/
    const gloox::RosterItem &item,
    const std::string &resource,
    gloox::Presence::PresenceType presence,
    const std::string &msg)
  {
    std::ostringstream ss;
    ss << "Status changed: (jid: \"" << item.jid()
       << "/" << resource << "\", presence: \""
       << libsxc::genPresenceString(presence) << "\" (" << presence
       << "), message: \"" << msg << "\").";
    LOG(ss.str());

    contactList::iterator contact = _getContact(item.jid());
    if (_contacts.end() == contact)
      return;
    contact->second->updatePresence(resource, presence, msg);
  }/*}}}*/
  void Roster::handleSelfPresence(/*{{{*/
    const gloox::RosterItem &item,
    const std::string &resource,
    gloox::Presence::PresenceType presence,
    const std::string &msg)
  {
    std::ostringstream ss;
    ss << "Self-status changed: (jid: \"" << item.name()
       << "\", resource: \"" << resource << "\", presence: "
       << presence << ", message: \"" << msg << "\").";
    LOG(ss.str());

    if (resource == _client.jid().resource()) {
      _nfo.setPresence(presence);
      _nfo.setMessage(msg);
    }
  }/*}}}*/
  bool Roster::handleSubscriptionRequest(/*{{{*/
    const gloox::JID &jid,
    const std::string &msg)
  {
    LOG(
      "Received subscription request: (jid: \"" + jid.bare() +
      "\", message: \"" + msg + "\").");

    contactList::iterator contact = _getContact(jid.bare());
    if (_contacts.end() == contact)
      return true;

    //_account->print(
    //  "Subscription request received: \"" + jid.bare() + "\"");

    return true;
  }/*}}}*/
  bool Roster::handleUnsubscriptionRequest(/*{{{*/
    const gloox::JID &jid,
    const std::string &msg)
  {
    LOG(
      "Received unsubscription request: (jid: \"" + jid.bare() +
      "\", message: \"" + msg + "\").");

    contactList::iterator contact = _getContact(jid.bare());
    if (_contacts.end() == contact)
      return true;

    //_account->print(
    //  "Unsubscription request received: \"" + jid.bare() + "\"");

    return true;
  }/*}}}*/
  void Roster::handleNonrosterPresence(const gloox::Presence &presence)/*{{{*/
  {
    std::ostringstream ss;
    ss << "Nonroster-Status changed: (type: \"" << presence.subtype()
       << "\", message: \"" << presence.status() << "\").";
    LOG(ss.str());
  }/*}}}*/
  void Roster::handleRosterError(const gloox::IQ &iq)/*{{{*/
  {
    const gloox::Error *error = iq.error();
    if (error) {
      _eh.print(
        "Roster error received: " +
        libsxc::genStanzaErrorString(error->error()));
    }

  }/*}}}*/

  void Roster::_checkClient() const/*{{{*/
  {
    // FIXME: Better exception or none at all
    if (!gloox::StateConnected == _client.state())
      throw libsxc::Exception::Exception(
        "Connection ist not established.",
        Exit::InvalidUsage);
  }/*}}}*/
  void Roster::_addContactRemote(const gloox::JID &jid)/*{{{*/
  {
    LOG(
      "Add contact to the remote roster: \"" + jid.bare() + "\".");

    _checkClient();

    const gloox::StringList groups;
    _client.rosterManager()->add(jid, jid.bare(), groups);
    _client.rosterManager()->synchronize();

    contactList::iterator contact = _getContact(jid.bare());
    if (_contacts.end() == contact)
      return;

    contact->second->updateRoster(Remote);
  }/*}}}*/
  void Roster::_addContactLocal(const gloox::JID &jid)/*{{{*/
  {
    if (_contacts.end() != _getContact(jid.bare())) {
      LOG("Contact already in local roster, not adding: \"" + jid.bare() + "\"");
      return;
    }

    _out.write("Add contact: " + jid.bare());

    Contact::Contact *contact = new Contact::Contact(
      *this, _client.jid(), jid);
    contact->updateRoster(Local);

    ::File::createDir(_client.jid().bare() + "/" + jid.bare());
    _contacts.insert(std::make_pair(jid.bare(), contact));

  }/*}}}*/
  contactList::iterator Roster::_getContact(const std::string &jid)/*{{{*/
  {
    contactList::iterator contact = _contacts.find(jid);

    if (_contacts.end() == contact) {
      LOG("Item not found in local roster");
    }

    return contact;
  }/*}}}*/
}

// Use no tabs at all; two spaces indentation; max. eighty chars per line.
// vim: et ts=2 sw=2 sts=2 tw=80 fdm=marker
<commit_msg>Fix: Create contact directory before creating files<commit_after>#line 2 "sxc:Account/Roster.cxx"
// LICENSE/*{{{*/
/*
  sxc - Simple Xmpp Client
  Copyright (C) 2008 Dennis Felsing, Andreas Waidler

  Permission to use, copy, modify, and/or distribute this software for any
  purpose with or without fee is hereby granted, provided that the above
  copyright notice and this permission notice appear in all copies.

  THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
  WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
  MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
  ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
  WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
  ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
  OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 */
/*}}}*/

// INCLUDE/*{{{*/

#ifdef HAVE_CONFIG_H
# include <config.hxx>
#endif

#include <string>
#include <map>
#include <sstream>

#include <gloox/clientbase.h>
#include <gloox/jid.h>
#include <gloox/presence.h>
#include <gloox/iq.h>
#include <gloox/message.h>
#include <gloox/messagehandler.h>
#include <gloox/error.h>

#include <libsxc/generateString.hxx>
#include <libsxc/Exception/Exception.hxx>
#include <libsxc/Debug/Logger.hxx>
#include <libsxc/Error/Handler.hxx>

#include <Account/Roster.hxx>
#include <Account/RosterType.hxx>
#include <Contact/Contact.hxx>
#include <File/AbcOutput.hxx>
#include <Account/File/Info.hxx>
#include <File/createDir.hxx>
#include <Exit/Code.hxx>

/*}}}*/

namespace Account
{
  Roster::Roster(/*{{{*/
    gloox::Client &client,
    ::File::AbcOutput &out,
    File::Info &nfo,
    libsxc::Error::Handler &eh)
  : RosterListener()
  , _client(client)
  , _out(out)
  , _nfo(nfo)
  , _contacts()
  , _eh(eh)
  {
    // Asynchronous subscription request handling.
    _client.rosterManager()->registerRosterListener(this, false);
    _client.registerMessageHandler(this);
  }/*}}}*/
  Roster::~Roster()/*{{{*/
  {
    _client.rosterManager()->removeRosterListener();
    _client.removeMessageHandler(this);

    for(
    contactList::iterator entry = _contacts.begin();
    entry != _contacts.end();
    ++entry) {
      delete entry->second;
    }
  }/*}}}*/

  void Roster::sendMessage(const gloox::JID &jid, const std::string &message)/*{{{*/
  {
    _addContactLocal(jid);

    contactList::iterator contact = _getContact(jid.bare());
    if (_contacts.end() == contact)
      return; // FIXME: Throw exception, this is really unexpected.

    contact->second->sendMessage(message);
  }/*}}}*/

  void Roster::addContact(const gloox::JID &jid)/*{{{*/
  {
    _addContactLocal(jid);
    _addContactRemote(jid);
  }/*}}}*/
  void Roster::removeContact(const gloox::JID &jid) const/*{{{*/
  {
    _checkClient();

    LOG("Remove contact from the roster: \"" + jid.bare() + "\".");

    _client.rosterManager()->remove(jid);
    _client.rosterManager()->synchronize();
  }/*}}}*/

  void Roster::subscribe(/*{{{*/
    const gloox::JID &jid,
    const std::string &message) const
  {
    _checkClient();

    LOG(
      "Sending subscription request: (jid: \"" + jid.bare() +
      "\", message: \"" + message + "\").");

    const gloox::StringList groups;
    _client.rosterManager()->subscribe(jid, jid.bare(), groups, message);
    _client.rosterManager()->synchronize();
  }/*}}}*/
  void Roster::unsubscribe(/*{{{*/
    const gloox::JID &jid,
    const std::string &message) const
  {
    _checkClient();

    LOG(
      "Sending unsubscription request: (jid: \"" + jid.bare() +
      "\", message: \"" + message + "\").");

    _client.rosterManager()->unsubscribe(jid, message);
    _client.rosterManager()->synchronize();
  }/*}}}*/

  void Roster::acknowledgeSubscription(const gloox::JID &jid) const/*{{{*/
  {
    LOG(
      "Acknowledge subscription request: \"" + jid.bare() + "\".");

    _client.rosterManager()->ackSubscriptionRequest(jid, true);
  }/*}}}*/
  void Roster::declineSubscription(const gloox::JID &jid) const/*{{{*/
  {
    LOG(
      "Decline subscription request: \"" + jid.bare() + "\".");

    _client.rosterManager()->ackSubscriptionRequest(jid, false);
  }/*}}}*/

  void Roster::handleMessage(/*{{{*/
    const gloox::Message &msg,
    gloox::MessageSession *session)
  {
    _addContactLocal(msg.from()); // Local only.

    contactList::iterator contact = _getContact(msg.from().bare());
    if (_contacts.end() == contact)
      return;

    contact->second->handleMessage(msg, session);
  }/*}}}*/

  gloox::MessageSession *Roster::createMessageSession(/*{{{*/
    gloox::MessageHandler *handler,
    const gloox::JID &jid)
  {
    gloox::MessageSession *session = new gloox::MessageSession(&_client, jid);
    session->registerMessageHandler(handler);
    return session;
  }/*}}}*/
  void Roster::disposeMessageSession(gloox::MessageSession *session)/*{{{*/
  {
    // This deletes the session. Else the destructor of gloox::ClientBase would
    // handle this.
    _client.disposeMessageSession(session);
  }/*}}}*/

  const gloox::JID &Roster::getJid()/*{{{*/
  {
    return _client.jid();
  }/*}}}*/

  void Roster::handleItemAdded(const gloox::JID &jid)/*{{{*/
  {
    LOG("Item added to the roster: \"" + jid.bare() + "\".");

    _addContactLocal(jid);
  }/*}}}*/
  void Roster::handleItemSubscribed(const gloox::JID &jid)/*{{{*/
  {
    LOG("Item subscribed: \"" + jid.bare() + "\".");
  }/*}}}*/
  void Roster::handleItemRemoved(const gloox::JID &jid)/*{{{*/
  {
    LOG("Item removed from the roster: \"" + jid.bare() + "\".");

    contactList::iterator contact = _getContact(jid.bare());
    if (_contacts.end() == contact)
      return;
    delete contact->second;
    _contacts.erase(contact);

    // _account->print("Contact removed: \"" + jid.bare() + "\".");
  }/*}}}*/
  void Roster::handleItemUpdated(const gloox::JID &jid)/*{{{*/
  {
    LOG("Item updated: \"" + jid.bare() + "\".");
  }/*}}}*/
  void Roster::handleItemUnsubscribed(const gloox::JID &jid)/*{{{*/
  {
    LOG(
      "Item unsubscribed: \"" + jid.bare() + "\".");
  }/*}}}*/
  void Roster::handleRoster(const gloox::Roster &roster)/*{{{*/
  {
    LOG("Initial roster received from the server.");

    for(
    gloox::Roster::const_iterator entry = roster.begin();
    entry != roster.end();
    ++entry) {
      _addContactLocal(entry->first);

      contactList::iterator contact = _getContact(entry->first);
      if (_contacts.end() == contact)
        continue;

      contact->second->updateRoster(Remote);
    }
  }/*}}}*/
  void Roster::handleRosterPresence(/*{{{*/
    const gloox::RosterItem &item,
    const std::string &resource,
    gloox::Presence::PresenceType presence,
    const std::string &msg)
  {
    std::ostringstream ss;
    ss << "Status changed: (jid: \"" << item.jid()
       << "/" << resource << "\", presence: \""
       << libsxc::genPresenceString(presence) << "\" (" << presence
       << "), message: \"" << msg << "\").";
    LOG(ss.str());

    contactList::iterator contact = _getContact(item.jid());
    if (_contacts.end() == contact)
      return;
    contact->second->updatePresence(resource, presence, msg);
  }/*}}}*/
  void Roster::handleSelfPresence(/*{{{*/
    const gloox::RosterItem &item,
    const std::string &resource,
    gloox::Presence::PresenceType presence,
    const std::string &msg)
  {
    std::ostringstream ss;
    ss << "Self-status changed: (jid: \"" << item.name()
       << "\", resource: \"" << resource << "\", presence: "
       << presence << ", message: \"" << msg << "\").";
    LOG(ss.str());

    if (resource == _client.jid().resource()) {
      _nfo.setPresence(presence);
      _nfo.setMessage(msg);
    }
  }/*}}}*/
  bool Roster::handleSubscriptionRequest(/*{{{*/
    const gloox::JID &jid,
    const std::string &msg)
  {
    LOG(
      "Received subscription request: (jid: \"" + jid.bare() +
      "\", message: \"" + msg + "\").");

    contactList::iterator contact = _getContact(jid.bare());
    if (_contacts.end() == contact)
      return true;

    //_account->print(
    //  "Subscription request received: \"" + jid.bare() + "\"");

    return true;
  }/*}}}*/
  bool Roster::handleUnsubscriptionRequest(/*{{{*/
    const gloox::JID &jid,
    const std::string &msg)
  {
    LOG(
      "Received unsubscription request: (jid: \"" + jid.bare() +
      "\", message: \"" + msg + "\").");

    contactList::iterator contact = _getContact(jid.bare());
    if (_contacts.end() == contact)
      return true;

    //_account->print(
    //  "Unsubscription request received: \"" + jid.bare() + "\"");

    return true;
  }/*}}}*/
  void Roster::handleNonrosterPresence(const gloox::Presence &presence)/*{{{*/
  {
    std::ostringstream ss;
    ss << "Nonroster-Status changed: (type: \"" << presence.subtype()
       << "\", message: \"" << presence.status() << "\").";
    LOG(ss.str());
  }/*}}}*/
  void Roster::handleRosterError(const gloox::IQ &iq)/*{{{*/
  {
    const gloox::Error *error = iq.error();
    if (error) {
      _eh.print(
        "Roster error received: " +
        libsxc::genStanzaErrorString(error->error()));
    }

  }/*}}}*/

  void Roster::_checkClient() const/*{{{*/
  {
    // FIXME: Better exception or none at all
    if (!gloox::StateConnected == _client.state())
      throw libsxc::Exception::Exception(
        "Connection ist not established.",
        Exit::InvalidUsage);
  }/*}}}*/
  void Roster::_addContactRemote(const gloox::JID &jid)/*{{{*/
  {
    LOG(
      "Add contact to the remote roster: \"" + jid.bare() + "\".");

    _checkClient();

    const gloox::StringList groups;
    _client.rosterManager()->add(jid, jid.bare(), groups);
    _client.rosterManager()->synchronize();

    contactList::iterator contact = _getContact(jid.bare());
    if (_contacts.end() == contact)
      return;

    contact->second->updateRoster(Remote);
  }/*}}}*/
  void Roster::_addContactLocal(const gloox::JID &jid)/*{{{*/
  {
    if (_contacts.end() != _getContact(jid.bare())) {
      LOG("Contact already in local roster, not adding: \"" + jid.bare() + "\"");
      return;
    }

    _out.write("Add contact: " + jid.bare());

    ::File::createDir(_client.jid().bare() + "/" + jid.bare());

    Contact::Contact *contact = new Contact::Contact(
      *this, _client.jid(), jid);
    contact->updateRoster(Local);

    _contacts.insert(std::make_pair(jid.bare(), contact));

  }/*}}}*/
  contactList::iterator Roster::_getContact(const std::string &jid)/*{{{*/
  {
    contactList::iterator contact = _contacts.find(jid);

    if (_contacts.end() == contact) {
      LOG("Item not found in local roster");
    }

    return contact;
  }/*}}}*/
}

// Use no tabs at all; two spaces indentation; max. eighty chars per line.
// vim: et ts=2 sw=2 sts=2 tw=80 fdm=marker
<|endoftext|>


<commit_before>#include "module_thruster.h"
#include "thruster_form.h"
#include "module_uid.h"

Module_Thruster::Module_Thruster(QString id, Module_UID *uid)
    : RobotModule(id)
{
    this->uid=uid;

    setDefaultValue("i2cAddress", 0x01);
    setDefaultValue("channel", 1);
    setDefaultValue("multiplicator", 127);

    connect(this,SIGNAL(enabled(bool)), this, SLOT(gotEnabled(bool)));

    initController();
}

void Module_Thruster::initController()
{
    if (!getSettings().value("enabled").toBool())
        return;

    unsigned char sendValue[] = { 0x01 };
    unsigned char address = getSettings().value("i2cAddress").toInt();

    bool ret = uid->getUID()->I2C_WriteRegister(address,0x00,sendValue,0x01);
    if (!ret)
        setHealthToSick("UID reported error.");
    else
        setHealthToOk();
}

Module_Thruster::~Module_Thruster()
{
}

void Module_Thruster::terminate()
{
}

void Module_Thruster::reset()
{
    // TODO: what exactly does this do?
    initController();
}

void Module_Thruster::setSpeed(float speed)
{
    if (!getSettings().value("enabled").toBool())
        return;

    data["speed"] = speed;

    if (speed > 1)
        speed = 1;

    if (speed < -1)
        speed = -1;

    unsigned char sendValue[] = { (int)(speed * getSettings().value("multiplicator").toInt()) };
    unsigned char address = getSettings().value("i2cAddress").toInt();
    unsigned char channel = getSettings().value("channel").toInt();

    bool ret = uid->getUID()->I2C_WriteRegister(address,channel,sendValue,0x01);
    if (!ret)
        setHealthToSick("UID reported error.");
    else
        setHealthToOk();

}

QList<RobotModule*> Module_Thruster::getDependencies()
{
    QList<RobotModule*> ret;
    ret.append(uid);
    return ret;
}

QWidget* Module_Thruster::createView(QWidget* parent)
{
    return new Thruster_Form(this, parent);
}

void Module_Thruster::doHealthCheck()
{
    if (!getSettings().value("enabled").toBool())
        return;

    int address = getSettings().value("i2cAddress").toInt();
    if (uid->getUID()->I2C_Scan().contains(address))
        setHealthToOk();
    else
        setHealthToSick("Couldn't find i2c slave on bus.");
}

void Module_Thruster::gotEnabled(bool value)
{
    initController();
}
<commit_msg>improved health check for thruster<commit_after>#include "module_thruster.h"
#include "thruster_form.h"
#include "module_uid.h"

/* see http://www.robot-electronics.co.uk/htm/md22tech.htm for details */
#define REG_MODE 0x00
#define REG_CHAN1 0x01
#define REG_CHAN2 0x02
#define REG_ACCEL 0x03
/* Regs 4-6: unused */
#define REG_SWREV 0x07

// expected value from the "software revision" register
#define MAGIC_SWREV 7

Module_Thruster::Module_Thruster(QString id, Module_UID *uid)
    : RobotModule(id)
{
    this->uid=uid;

    setDefaultValue("i2cAddress", 0x01);
    setDefaultValue("channel", 1);
    setDefaultValue("multiplicator", 127);

    connect(this,SIGNAL(enabled(bool)), this, SLOT(gotEnabled(bool)));

    initController();
}

void Module_Thruster::initController()
{
    if (!getSettings().value("enabled").toBool())
        return;

    unsigned char sendValue[] = { 0x01 };
    unsigned char address = getSettings().value("i2cAddress").toInt();

    bool ret = uid->getUID()->I2C_WriteRegister(address,REG_MODE,sendValue,0x01);
    if (!ret)
        setHealthToSick("UID reported error.");
    else
        setHealthToOk();
}

Module_Thruster::~Module_Thruster()
{
}

void Module_Thruster::terminate()
{
}

void Module_Thruster::reset()
{
    // TODO: what exactly does this do?
    initController();
}

void Module_Thruster::setSpeed(float speed)
{
    if (!getSettings().value("enabled").toBool())
        return;

    data["speed"] = speed;

    if (speed > 1)
        speed = 1;

    if (speed < -1)
        speed = -1;

    unsigned char sendValue[] = { (int)(speed * getSettings().value("multiplicator").toInt()) };
    unsigned char address = getSettings().value("i2cAddress").toInt();
    unsigned char channel = getSettings().value("channel").toInt();

    if (channel != 1 && channel != 2) {
        setHealthToSick("thruster configured to an illegal channel.");
        return;
    }

    bool ret = uid->getUID()->I2C_WriteRegister(address,channel,sendValue,0x01);
    if (!ret)
        setHealthToSick("UID reported error.");
    else
        setHealthToOk();

}

QList<RobotModule*> Module_Thruster::getDependencies()
{
    QList<RobotModule*> ret;
    ret.append(uid);
    return ret;
}

QWidget* Module_Thruster::createView(QWidget* parent)
{
    return new Thruster_Form(this, parent);
}

void Module_Thruster::doHealthCheck()
{
    if (!getSettings().value("enabled").toBool())
        return;

    int address = getSettings().value("i2cAddress").toInt();
    unsigned char data[1];
    bool ret = uid->getUID()->I2C_ReadRegisters(address,REG_SWREV,1,data);
    if (!ret)
        setHealthToSick("UID reported error.");
    else if (data[0] != MAGIC_SWREV)
        setHealthToSick("sw revision register doesn't match magic value.");
    else
        setHealthToOk();
}

void Module_Thruster::gotEnabled(bool value)
{
    if (value)
        initController();
}
<|endoftext|>


<commit_before>#include <QVector3D>
#include "kernel.h"
#include "ilwisdata.h"
#include "geometries.h"
#include "coordinatesystem.h"
#include "geos/geom/Geometry.h"
#include "geos/geom/CoordinateSequence.h"
#include "drawers/drawerinterface.h"
#include "geometryhelper.h"
#include "tesselation/ilwistesselator.h"
#include "openglhelper.h"
#include "tesselation/tesselator.h"

using namespace Ilwis;
using namespace Geodrawer;

IlwisTesselator OpenGLHelper::_tesselator;

OpenGLHelper::OpenGLHelper()
{
}

quint32 OpenGLHelper::getVertices(const ICoordinateSystem& csyRoot,
                               const ICoordinateSystem& csyGeom,
                               const Ilwis::UPGeometry &geometry,
                               Raw objectid,
                               QVector<QVector3D> &points,
                               QVector<QVector3D>& normals,
                               std::vector<VertexIndex> &indices,
                               quint32& boundaryIndex)
{
    quint32 oldNumberOfVertices = points.size();
    IlwisTypes tp =  GeometryHelper::geometryType(geometry.get());

       switch( tp)     {
        case itPOLYGON:
            getPolygonVertices(csyRoot, csyGeom, geometry, objectid, points, normals, indices);
        case itLINE:
            getLineVertices(csyRoot, csyGeom,geometry, objectid, points, normals, indices); break;
        case itPOINT:
            getPointVertices(csyRoot, csyGeom,geometry, objectid, points, normals, indices); break;\
        default:
            break;
    }
    return points.size() - oldNumberOfVertices;

}

void OpenGLHelper::getPolygonVertices(const ICoordinateSystem& csyRoot,
                                      const ICoordinateSystem& csyGeom,
                                      const Ilwis::UPGeometry &geometry,
                                      Raw objectid,
                                      QVector<QVector3D> &points,
                                      QVector<QVector3D>& normals,
                                      std::vector<VertexIndex> &indices){
    int n = geometry->getNumGeometries();
    for(int  geom = 0; geom < n; ++geom ){
        const geos::geom::Geometry *subgeom = geometry->getGeometryN(geom);
        if (!subgeom)
            continue;
        _tesselator.tesselate(csyRoot,csyGeom, subgeom,objectid, points, indices);
    }
}

void OpenGLHelper::getLineVertices(const ICoordinateSystem& csyRoot,
                                   const ICoordinateSystem& csyGeom,
                                   const Ilwis::UPGeometry &geometry,
                                   Raw objectid,
                                   QVector<QVector3D> &points,
                                   QVector<QVector3D> &normals,
                                   std::vector<VertexIndex> &indices){

    int n = geometry->getNumGeometries();
    for(int  geom = 0; geom < n; ++geom ){
        const geos::geom::Geometry *subgeom = geometry->getGeometryN(geom);
        if (!subgeom)
            continue;
        auto *coords = subgeom->getCoordinates();
        quint32 oldend = points.size();
        indices.push_back(VertexIndex(oldend, coords->size(), itLINE, GL_LINE_STRIP, objectid));
        points.resize(oldend + coords->size());
        bool conversionNeeded = csyRoot != csyGeom;
        Coordinate crd;
        for(int i = 0; i < coords->size(); ++i){
            coords->getAt(i, crd);
            if ( conversionNeeded){
                crd = csyRoot->coord2coord(csyGeom, crd);
            }
            points[oldend + i] = QVector3D(crd.x, crd.y, crd.z);
        }
        delete coords;
    }

}

void OpenGLHelper::getPointVertices(const ICoordinateSystem& csyRoot,
                                    const ICoordinateSystem& csyGeom,
                                    const Ilwis::UPGeometry &geometry,
                                    Raw objectid, QVector<QVector3D> &points,
                                    QVector<QVector3D> &normals,
                                    std::vector<VertexIndex> &indices){

    int n = geometry->getNumGeometries();
    for(int  geom = 0; geom < n; ++geom ){
        const geos::geom::Geometry *subgeom = geometry->getGeometryN(geom);
        if (!subgeom)
            continue;
        const geos::geom::Coordinate *crd = subgeom->getCoordinate();
        indices.push_back(VertexIndex(points.size(),1,itPOINT,GL_POINTS,objectid));
        bool conversionNeeded = csyRoot != csyGeom;
        Coordinate coord = *crd;
        if ( conversionNeeded){
            coord = csyRoot->coord2coord(csyGeom, *crd);
        }
        points.push_back(QVector3D(coord.x, coord.y, coord.z));
    }
}
<commit_msg>changes to constructor of vertexindex<commit_after>#include <QVector3D>
#include "kernel.h"
#include "ilwisdata.h"
#include "geometries.h"
#include "coordinatesystem.h"
#include "geos/geom/Geometry.h"
#include "geos/geom/CoordinateSequence.h"
#include "drawers/drawerinterface.h"
#include "geometryhelper.h"
#include "tesselation/ilwistesselator.h"
#include "openglhelper.h"
#include "tesselation/tesselator.h"

using namespace Ilwis;
using namespace Geodrawer;

IlwisTesselator OpenGLHelper::_tesselator;

OpenGLHelper::OpenGLHelper()
{
}

quint32 OpenGLHelper::getVertices(const ICoordinateSystem& csyRoot,
                               const ICoordinateSystem& csyGeom,
                               const Ilwis::UPGeometry &geometry,
                               Raw objectid,
                               QVector<QVector3D> &points,
                               QVector<QVector3D>& normals,
                               std::vector<VertexIndex> &indices,
                               quint32& boundaryIndex)
{
    quint32 oldNumberOfVertices = points.size();
    IlwisTypes tp =  GeometryHelper::geometryType(geometry.get());

       switch( tp)     {
        case itPOLYGON:
            getPolygonVertices(csyRoot, csyGeom, geometry, objectid, points, normals, indices);
        case itLINE:
            getLineVertices(csyRoot, csyGeom,geometry, objectid, points, normals, indices); break;
        case itPOINT:
            getPointVertices(csyRoot, csyGeom,geometry, objectid, points, normals, indices); break;\
        default:
            break;
    }
    return points.size() - oldNumberOfVertices;

}

void OpenGLHelper::getPolygonVertices(const ICoordinateSystem& csyRoot,
                                      const ICoordinateSystem& csyGeom,
                                      const Ilwis::UPGeometry &geometry,
                                      Raw objectid,
                                      QVector<QVector3D> &points,
                                      QVector<QVector3D>& normals,
                                      std::vector<VertexIndex> &indices){
    int n = geometry->getNumGeometries();
    for(int  geom = 0; geom < n; ++geom ){
        const geos::geom::Geometry *subgeom = geometry->getGeometryN(geom);
        if (!subgeom)
            continue;
        _tesselator.tesselate(csyRoot,csyGeom, subgeom,objectid, points, indices);
    }
}

void OpenGLHelper::getLineVertices(const ICoordinateSystem& csyRoot,
                                   const ICoordinateSystem& csyGeom,
                                   const Ilwis::UPGeometry &geometry,
                                   Raw objectid,
                                   QVector<QVector3D> &points,
                                   QVector<QVector3D> &normals,
                                   std::vector<VertexIndex> &indices){

    int n = geometry->getNumGeometries();
    for(int  geom = 0; geom < n; ++geom ){
        const geos::geom::Geometry *subgeom = geometry->getGeometryN(geom);
        if (!subgeom)
            continue;
        auto *coords = subgeom->getCoordinates();
        quint32 oldend = points.size();
        indices.push_back(VertexIndex(oldend, coords->size(), GL_LINE_STRIP, objectid));
        points.resize(oldend + coords->size());
        bool conversionNeeded = csyRoot != csyGeom;
        Coordinate crd;
        for(int i = 0; i < coords->size(); ++i){
            coords->getAt(i, crd);
            if ( conversionNeeded){
                crd = csyRoot->coord2coord(csyGeom, crd);
            }
            points[oldend + i] = QVector3D(crd.x, crd.y, crd.z);
        }
        delete coords;
    }

}

void OpenGLHelper::getPointVertices(const ICoordinateSystem& csyRoot,
                                    const ICoordinateSystem& csyGeom,
                                    const Ilwis::UPGeometry &geometry,
                                    Raw objectid, QVector<QVector3D> &points,
                                    QVector<QVector3D> &normals,
                                    std::vector<VertexIndex> &indices){

    int n = geometry->getNumGeometries();
    for(int  geom = 0; geom < n; ++geom ){
        const geos::geom::Geometry *subgeom = geometry->getGeometryN(geom);
        if (!subgeom)
            continue;
        const geos::geom::Coordinate *crd = subgeom->getCoordinate();
        indices.push_back(VertexIndex(points.size(),1,GL_POINTS,objectid));
        bool conversionNeeded = csyRoot != csyGeom;
        Coordinate coord = *crd;
        if ( conversionNeeded){
            coord = csyRoot->coord2coord(csyGeom, *crd);
        }
        points.push_back(QVector3D(coord.x, coord.y, coord.z));
    }
}
<|endoftext|>


<commit_before>#include "vtkDICOMSequence.h"
#include "vtkDICOMSequenceItem.h"

#include <assert.h>

void vtkDICOMSequence::AddItem(const vtkDICOMSequenceItem& item)
{
  // if value is not a sequence, make it into a sequence
  if (this->V == 0 || this->V->Type != VTK_DICOM_ITEM)
    {
    this->AllocateSequenceData(vtkDICOMVR::SQ, 2);
    this->V->NumberOfValues = 0;
    this->V->VL = 0xffffffff;
    }

  vtkDICOMSequenceItem *ptr =
    static_cast<const ValueT<vtkDICOMSequenceItem> *>(this->V)->Data;

  unsigned int n = this->V->NumberOfValues;
  unsigned int nn = 0;
  // reallocate if n is a power of two
  if (n > 1 && ((n - 1) & n) == 0)
    {
    nn = 2*n;
    }
  // reallocate if not unique reference, or not yet growable
  else if (this->V->ReferenceCount > 1 || this->V->VL != 0xffffffff)
    {
    // get next power of two that is greater than n
    nn = 1;
    do { nn <<= 1; } while (nn <= n);
    // mark as growable for next time
    this->V->VL = 0xffffffff;
    }
  // reallocate the array
  if (nn != 0)
    {
    Value *v = this->V;
    v->ReferenceCount++;
    const vtkDICOMSequenceItem *cptr = ptr;
    ptr = this->AllocateSequenceData(vtkDICOMVR::SQ, nn);
    this->V->NumberOfValues = n;
    for (unsigned int i = 0; i < n; i++)
      {
      ptr[i] = cptr[i];
      }
    if (--(v->ReferenceCount) == 0)
      {
      vtkDICOMValue::FreeValue(v);
      }
    }

  // add the item
  ptr[this->V->NumberOfValues++] = item;
}

void vtkDICOMSequence::SetItem(int i, const vtkDICOMSequenceItem& item)
{
  assert(this->V != 0 && this->V->Type == VTK_DICOM_ITEM);
  assert(i >= 0 && static_cast<unsigned int>(i) < this->V->NumberOfValues);

  vtkDICOMSequenceItem *ptr =
    static_cast<const ValueT<vtkDICOMSequenceItem> *>(this->V)->Data;

  // reallocate the array if we aren't the sole owner
  if (this->V->ReferenceCount > 1)
    {
    unsigned int n = this->V->NumberOfValues;
    const vtkDICOMSequenceItem *cptr = ptr;
    ptr = this->AllocateSequenceData(vtkDICOMVR::SQ, n);
    for (unsigned int i = 0; i < n; i++)
      {
      ptr[i] = cptr[i];
      }
    }

  ptr[i] = item;
}
<commit_msg>COMP: Fix shadowed variable warning in vtkDICOMSequence.<commit_after>#include "vtkDICOMSequence.h"
#include "vtkDICOMSequenceItem.h"

#include <assert.h>

void vtkDICOMSequence::AddItem(const vtkDICOMSequenceItem& item)
{
  // if value is not a sequence, make it into a sequence
  if (this->V == 0 || this->V->Type != VTK_DICOM_ITEM)
    {
    this->AllocateSequenceData(vtkDICOMVR::SQ, 2);
    this->V->NumberOfValues = 0;
    this->V->VL = 0xffffffff;
    }

  vtkDICOMSequenceItem *ptr =
    static_cast<const ValueT<vtkDICOMSequenceItem> *>(this->V)->Data;

  unsigned int n = this->V->NumberOfValues;
  unsigned int nn = 0;
  // reallocate if n is a power of two
  if (n > 1 && ((n - 1) & n) == 0)
    {
    nn = 2*n;
    }
  // reallocate if not unique reference, or not yet growable
  else if (this->V->ReferenceCount > 1 || this->V->VL != 0xffffffff)
    {
    // get next power of two that is greater than n
    nn = 1;
    do { nn <<= 1; } while (nn <= n);
    // mark as growable for next time
    this->V->VL = 0xffffffff;
    }
  // reallocate the array
  if (nn != 0)
    {
    Value *v = this->V;
    v->ReferenceCount++;
    const vtkDICOMSequenceItem *cptr = ptr;
    ptr = this->AllocateSequenceData(vtkDICOMVR::SQ, nn);
    this->V->NumberOfValues = n;
    for (unsigned int i = 0; i < n; i++)
      {
      ptr[i] = cptr[i];
      }
    if (--(v->ReferenceCount) == 0)
      {
      vtkDICOMValue::FreeValue(v);
      }
    }

  // add the item
  ptr[this->V->NumberOfValues++] = item;
}

void vtkDICOMSequence::SetItem(int i, const vtkDICOMSequenceItem& item)
{
  assert(this->V != 0 && this->V->Type == VTK_DICOM_ITEM);
  assert(i >= 0 && static_cast<unsigned int>(i) < this->V->NumberOfValues);

  vtkDICOMSequenceItem *ptr =
    static_cast<const ValueT<vtkDICOMSequenceItem> *>(this->V)->Data;

  // reallocate the array if we aren't the sole owner
  if (this->V->ReferenceCount > 1)
    {
    unsigned int m = this->V->NumberOfValues;
    const vtkDICOMSequenceItem *cptr = ptr;
    ptr = this->AllocateSequenceData(vtkDICOMVR::SQ, m);
    for (unsigned int j = 0; j < m; j++)
      {
      ptr[j] = cptr[j];
      }
    }

  ptr[i] = item;
}
<|endoftext|>


<commit_before>// BentleyOttmann.cpp
// Copyright (c) 2009, Dan Heeks
// This program is released under the BSD license. See the file COPYING for details.

#include "stdafx.h"

//This algorithm takes an array of polygon segments and computes the intersection points

class MyLine
{
public:
	gp_Pnt A;
	gp_Pnt B;
	double addedAt;
	MyLine(gp_Pnt A,gp_Pnt B){this->A = A; this->B = B;}
	MyLine(){}
	void Reverse() {gp_Pnt tmp = A; A = B; B = tmp;}
	double GetY()
	{
		double dy = B.Y() - A.Y();
		double dx = B.X() - A.X();

		double t = (addedAt - A.X()) / dx;
		return A.Y() + t * dy;
	}

	double GetY(double ax)
	{
		double dy = B.Y() - A.Y();
		double dx = B.X() - A.X();

		double t = (ax - A.X()) / dx;
		return A.Y() + t * dy;
	}
};

class Intersection
{
public:
	MyLine* line;
	double X,Y;
	Intersection(MyLine* line, double X, double Y){this->line = line; this->X = X; this->Y = Y;}
};

double currentX=0;

class LineCmp
{
public:
	MyLine line;
	double ofst;

	LineCmp(MyLine* line, double ofst){this->line = *line; this->ofst = ofst;}

	double GetY()
	{
		return line.GetY() + ofst;
	}

	double GetY(double ax)
	{
		return line.GetY(ax) + ofst;
	}

};

//fast storage for the global tolerance paramater
double tol=0;

//Determine if two doubles are the same within tolerance
inline bool MyIsEqual(double a, double b)
{
	if(a > b - tol && a < b + tol)
		return true;
	return false;
}

enum EventType
{
	AddType,
	RemoveType,
	AddRemoveType,
	IntersectionType
};

//By using an std::pair and this comparison function. We can get std::map to group operations in the red black tree
//while taking into account geometric tolerance. the first and second parameters have already been perturbed by the
//tolerance value.
class IsLessThan
{
public:
	bool operator()(std::pair<double,double> a, std::pair<double,double> b)
	{
		return a.second < b.first;
	}

	bool operator()(std::pair<LineCmp,LineCmp> a, std::pair<LineCmp,LineCmp> b)
	{
		return a.second.GetY() < b.first.GetY();
	}

	bool operator()(std::pair<LineCmp,LineCmp> a, std::pair<LineCmp,LineCmp> b, double ax)
	{
		return a.second.GetY(ax) < b.first.GetY(ax);
	}

};

class IntResult
{
public:
	bool exists;
	double atX;
	IntResult(bool exists, double atX){this->exists = exists; this->atX = atX;}
};

IntResult Intersects(MyLine* line1, MyLine* line2)
{
	//Checks if these lines intersect somewhere besides the start and end points
	if(line1->A.IsEqual(line2->A,tol) || line1->B.IsEqual(line2->B,tol))
		return IntResult(false,0);

	double ua = (line2->B.X()-line2->A.X())*(line1->A.Y()-line2->A.Y()) - (line2->B.Y()-line2->A.Y())*(line1->A.X()-line2->A.X());
	ua /= (line2->B.Y()-line2->A.Y())*(line1->B.X()-line1->A.X())-(line2->B.X()-line2->A.X())*(line1->B.Y()-line1->A.Y());
	double ub = (line1->B.X()-line1->A.X())*(line1->A.Y()-line2->A.Y()) - (line1->B.Y()-line1->A.Y())*(line1->A.X()-line2->A.X());
	ub /= (line2->B.Y()-line2->A.Y())*(line1->B.X()-line1->A.X())-(line2->B.X()-line2->A.X())*(line1->B.Y()-line1->A.Y());

	if(ua > 0 && ua < 1 && ub > 0 && ub < 1)
	{
		double atX = line1->A.X() + ua * (line1->B.X() - line1->A.X());
		return IntResult(true,atX);
	}
	return IntResult(false,0);
}

//Storage for the event table
std::map<std::pair<double,double>,std::vector<std::list<MyLine*> >,IsLessThan> eventtable;

//Put a new event into the table
void InsertEvent(EventType type, double x, MyLine* line)
{
	//Find an existing list, or a place to insert it
	std::pair<double,double> pos(x-tol,x+tol);
	if(eventtable[pos].size() == 0)
		eventtable[pos].resize(4);

	eventtable[pos][type].push_back(line);
}

void Intersections(std::vector<MyLine> &lines)
{
	tol = wxGetApp().m_geom_tol;

	//first pass: build lists ordered by x coordinate
	for(size_t i=0; i < lines.size(); i++)
	{
		//We must do a binary search on the list, as we want to enfore a geom_tol
		if(MyIsEqual(lines[i].A.X(),lines[i].B.X()))
		{
			InsertEvent(AddRemoveType,lines[i].A.X(),&lines[i]); //For vertical lines
		}
		else
		{
			if(lines[i].A.X() > lines[i].B.X())
				lines[i].Reverse();
			InsertEvent(AddType,lines[i].A.X(),&lines[i]);
			InsertEvent(RemoveType,lines[i].B.X(),&lines[i]);
		}
	}

	//Storage for the sweepline
	std::map<std::pair<double,double>,std::set<MyLine*>,IsLessThan> sweepline;
	IsLessThan ILT;

	//Storage for the located intersections
	std::vector<Intersection> intersections;

	//Storage for the already intersected code
	std::map<MyLine*,std::set<MyLine*> > intersected;

	//Go through the event points in order
	std::map<std::pair<double,double>,std::vector<std::list<MyLine*> >,IsLessThan >::iterator it;
	for(it = eventtable.begin(); it != eventtable.end(); ++it)
	{
		std::list<MyLine*>::iterator it2;
		MyLine* tline=0;
		currentX = (*it).first.first + tol;

		for(it2 = (*it).second[IntersectionType].begin(); it2 != (*it).second[IntersectionType].end(); ++it2)
		{
			//Remove these items from the list and re-add them
			tline = *it2;
			double xSave = currentX;
			currentX = tline->addedAt;
			double currentY = tline->GetY();
			std::pair<double,double> loc(currentY-tol,currentY+tol);
			sweepline[loc].erase(sweepline[loc].find(tline));
			currentX = xSave;
			tline->addedAt = currentX;
			currentY = tline->GetY();
			loc = std::pair<double,double>(currentY-tol,currentY+tol);
			sweepline[loc].insert(tline);
		}

		for(it2 = (*it).second[AddType].begin(); it2 != (*it).second[AddType].end(); ++it2)
		{
			//Add these new items to the sweepline
			tline = *it2;
			tline->addedAt = currentX;
			//No numerical problems here, because if A.X and B.X were within tol. Line would be
			//in a different list
			double currentY = tline->GetY();
			std::pair<double,double> loc(currentY-tol,currentY+tol);
			sweepline[loc].insert(tline);
		}

		//try to break apart coincident point sets.
		std::map<std::pair<double,double>,std::set<MyLine*>,IsLessThan>::iterator it3;
		for(it3 = sweepline.begin(); it3 != sweepline.end(); it3++)
		{
			std::set<MyLine*> lines = (*it3).second;
			if(lines.size() <= 1)
				continue;
			std::pair<double,double> baseloc = (*it3).first;
			std::set<MyLine*>::iterator it4;
			for(it4 = lines.begin(); it4 != lines.end();)
			{
				MyLine* tline = *it4;
				double currentY = tline->GetY(currentX);
				std::pair<double,double> newloc(currentY-tol,currentY+tol);
				if(ILT(newloc,baseloc) || ILT(baseloc,newloc))
				{
					std::set<MyLine*>::iterator it5 = it4;
					++it4;
					double oldx = currentX;
					currentX = tline->addedAt;
					(*it3).second.erase(tline);
					currentX = oldx;
					tline->addedAt = currentX;
					sweepline[newloc].insert(tline);
					continue;
				}
				++it4;
			}
		}

		//TODO: all sets in sweepline represent intersections
		for(it3 = sweepline.begin(); it3 != sweepline.end(); it3++)
		{
			std::set<MyLine*> lines = (*it3).second;
			if(lines.size() <= 1)
				continue;
			//All the elements of lines are intersecting at this X
			std::set<MyLine*>::iterator it4;
			for(it4 = lines.begin(); it4 != lines.end(); ++it4)
			{
				tline = *it4;
				intersections.push_back(Intersection(tline,currentX,tline->GetY(currentX)));
			}
		}

		for(it2 = (*it).second[AddRemoveType].begin(); it2 != (*it).second[AddRemoveType].end(); ++it2)
		{
			//TODO: These intersect with all things between y1 and y2
		}

		for(it2 = (*it).second[RemoveType].begin(); it2 != (*it).second[RemoveType].end(); ++it2)
		{
			//Remove these from the sweepline
			tline = *it2;
			double xSave = currentX;
			currentX = tline->addedAt;
			double currentY = tline->GetY();
			std::pair<double,double> loc(currentY-tol,currentY+tol);
			sweepline[loc].erase(sweepline[loc].find(tline));
			currentX = xSave;
		}

		//TODO::Run intersection tests for between all adjacent sets. Then add these to the event tree
		for(it3 = sweepline.begin(); it3 != sweepline.end();)
		{
			std::set<MyLine*> lines = (*it3++).second;
			if(it3 == sweepline.end())
				break;
			std::set<MyLine*> nlines = (*it3).second;

			//Compare all lines in lines to each other and to all lines in nlines
			std::set<MyLine*>::iterator it4;
			for(it4 = lines.begin(); it4 != lines.end(); ++it4)
			{
				std::set<MyLine*>::iterator it5;
				for(it5 = nlines.begin(); it5 != nlines.end(); ++it5)
				{
					//Do the comparisons
					if(intersected[*it4].find(*it5) != intersected[*it4].end())
						continue;
					IntResult ir = Intersects(*it4,*it5);
					if(ir.exists && ir.atX > currentX + tol)
					{
						InsertEvent(IntersectionType,ir.atX,*it4);
						InsertEvent(IntersectionType,ir.atX,*it5);
						intersected[*it4].insert(*it5);
						intersected[*it5].insert(*it4);
					}
				}
				//TODO: I don't think it is necessary to compute the intersection of things within a group
				//as they are alread scheduled for regrouping
				/*
				it5 = it4;
				for(it5++; it5 != lines.end(); ++it5)
				{
					//Do the comparisons
					IntResult ir = Intersects(*it4,*it5);
					if(ir.exists)
					{
						InsertEvent(IntersectionType,ir.atX,*it4);
						InsertEvent(IntersectionType,ir.atX,*it5);
					}
				} */

			}
		}
	}
}

void Test()
{
	std::vector<MyLine> lines;
	lines.push_back(MyLine(gp_Pnt(0,0,0),gp_Pnt(5,5,0)));
	lines.push_back(MyLine(gp_Pnt(0,0,0),gp_Pnt(2,5,0)));
	lines.push_back(MyLine(gp_Pnt(0,1,0),gp_Pnt(4,1,0)));
//	lines.push_back(MyLine(gp_Pnt(1,1,0),gp_Pnt(1,2,0)));
	Intersections(lines);
}<commit_msg>BentleyOttmann should be working now. Although buggy.<commit_after>// BentleyOttmann.cpp
// Copyright (c) 2009, Dan Heeks
// This program is released under the BSD license. See the file COPYING for details.

#include "stdafx.h"

//This algorithm takes an array of polygon segments and computes the intersection points
//using a modified Bentley-Ottmann algorithm. There are several problems with the text book
//approach. Such as, not supporting vertical lines. Coincident points, or points with the same
//X coordinate. The usual way to alleviate these problems is to skew the data in someway which
//prevents the algorithm from breaking. We take a different approach and make the algorithm work
//will the ill-conditioned data. There is a cost to this. I'm not totally sure what it is.
//It is something like instead of being (n+k)log n. we are (n+k+m)log n+m. where m is the number
//of ill conditioned points. This means there is a worst case complexity of this algorithm which is higher
//than n^2.

//TODO: I wanted to have these "fuzzy trees" which would insert items into new lists depending on there being within
//tolerance of the other elements. This seemed to break the stl::map for some unknown reason. Instead, the index
//values are rounded to some multiple of tol. This guarantees that 2 items within the list are within tol. But items
//from an immediately adjacent list, could have members within tol of some items. This is not checked for, and should be

//TODO: The minimal x-step is dependant on the slope of the lines in question. Otherwise it is possible to take a step
//small enough to leave lines still intersecting. There may be another way to handle this.

class MyLine
{
public:
	gp_Pnt A;
	gp_Pnt B;
	double addedAt;
	MyLine(gp_Pnt A,gp_Pnt B){this->A = A; this->B = B;}
	MyLine(){}
	void Reverse() {gp_Pnt tmp = A; A = B; B = tmp;}
	double GetY()
	{
		double dy = B.Y() - A.Y();
		double dx = B.X() - A.X();

		double t = (addedAt - A.X()) / dx;
		return A.Y() + t * dy;
	}

	double GetY(double ax)
	{
		double dy = B.Y() - A.Y();
		double dx = B.X() - A.X();

		double t = (ax - A.X()) / dx;
		return A.Y() + t * dy;
	}
};

class Intersection
{
public:
	MyLine* line;
	double X,Y;
	Intersection(MyLine* line, double X, double Y){this->line = line; this->X = X; this->Y = Y;}
};

double currentX=0;

class LineCmp
{
public:
	MyLine line;
	double ofst;

	LineCmp(MyLine* line, double ofst){this->line = *line; this->ofst = ofst;}

	double GetY()
	{
		return line.GetY() + ofst;
	}

	double GetY(double ax)
	{
		return line.GetY(ax) + ofst;
	}

};

//fast storage for the global tolerance paramater
double tol=0;

//Determine if two doubles are the same within tolerance
inline bool MyIsEqual(double a, double b)
{
	if(a > b - tol && a < b + tol)
		return true;
	return false;
}

enum EventType
{
	AddType,
	RemoveType,
	AddRemoveType,
	IntersectionType
};

double MyRound(double d)
{
	return floor(d/tol) * tol;
}

//By using an std::pair and this comparison function. We can get std::map to group operations in the red black tree
//while taking into account geometric tolerance. the first and second parameters have already been perturbed by the
//tolerance value.
class IsLessThan
{
public:
	bool operator()(std::pair<double,double> a, std::pair<double,double> b)
	{
		return a.second < b.first;
	}

	bool operator()(std::pair<LineCmp,LineCmp> a, std::pair<LineCmp,LineCmp> b)
	{
		return a.second.GetY() < b.first.GetY();
	}

	bool operator()(std::pair<LineCmp,LineCmp> a, std::pair<LineCmp,LineCmp> b, double ax)
	{
		return a.second.GetY(ax) < b.first.GetY(ax);
	}

};

class IntResult
{
public:
	bool exists;
	double atX;
	IntResult(bool exists, double atX){this->exists = exists; this->atX = atX;}
};

IntResult Intersects(MyLine* line1, MyLine* line2)
{
	//Checks if these lines intersect somewhere besides the start and end points
	if(line1->A.IsEqual(line2->A,tol) || line1->B.IsEqual(line2->B,tol))
		return IntResult(false,0);

	double ua = (line2->B.X()-line2->A.X())*(line1->A.Y()-line2->A.Y()) - (line2->B.Y()-line2->A.Y())*(line1->A.X()-line2->A.X());
	ua /= (line2->B.Y()-line2->A.Y())*(line1->B.X()-line1->A.X())-(line2->B.X()-line2->A.X())*(line1->B.Y()-line1->A.Y());
	double ub = (line1->B.X()-line1->A.X())*(line1->A.Y()-line2->A.Y()) - (line1->B.Y()-line1->A.Y())*(line1->A.X()-line2->A.X());
	ub /= (line2->B.Y()-line2->A.Y())*(line1->B.X()-line1->A.X())-(line2->B.X()-line2->A.X())*(line1->B.Y()-line1->A.Y());

	if(ua > 0 && ua < 1 && ub > 0 && ub < 1)
	{
		double atX = line1->A.X() + ua * (line1->B.X() - line1->A.X());
		return IntResult(true,atX);
	}
	return IntResult(false,0);
}

//Storage for the event table
std::map<double,std::vector<std::list<MyLine*> > > eventtable;

//Put a new event into the table
void InsertEvent(EventType type, double x, MyLine* line)
{
	//Find an existing list, or a place to insert it
	double  pos = MyRound(x);
	if(eventtable[pos].size() == 0)
		eventtable[pos].resize(4);

	eventtable[pos][type].push_back(line);
}

void Intersections(std::vector<MyLine> &lines)
{
	tol = wxGetApp().m_geom_tol;
	eventtable.clear();

	//first pass: build lists ordered by x coordinate
	for(size_t i=0; i < lines.size(); i++)
	{
		//We must do a binary search on the list, as we want to enfore a geom_tol
		if(MyIsEqual(lines[i].A.X(),lines[i].B.X()))
		{
			InsertEvent(AddRemoveType,lines[i].A.X(),&lines[i]); //For vertical lines
		}
		else
		{
			if(lines[i].A.X() > lines[i].B.X())
				lines[i].Reverse();
			InsertEvent(AddType,lines[i].A.X(),&lines[i]);
			InsertEvent(RemoveType,lines[i].B.X(),&lines[i]);
		}
	}

	//Storage for the sweepline
	std::map<double,std::set<MyLine*> > sweepline;
	IsLessThan ILT;

	//Storage for the located intersections
	std::vector<Intersection> intersections;

	//Storage for the already intersected code
	std::map<MyLine*,std::set<MyLine*> > intersected;

	//Go through the event points in order
	std::map<double,std::vector<std::list<MyLine*> > >::iterator it;
	for(it = eventtable.begin(); it != eventtable.end(); ++it)
	{
		std::list<MyLine*>::iterator it2;
		MyLine* tline=0;
		currentX = (*it).first;

		for(it2 = (*it).second[IntersectionType].begin(); it2 != (*it).second[IntersectionType].end(); ++it2)
		{
			//Remove these items from the list and re-add them
			tline = *it2;
			double xSave = currentX;
			currentX = tline->addedAt;
			double currentY = tline->GetY();
			double loc = MyRound(currentY);
			sweepline[loc].erase(sweepline[loc].find(tline));
			if(sweepline[loc].size() == 0)
				sweepline.erase(sweepline.find(loc));
			currentX = xSave;
			tline->addedAt = currentX;
			currentY = tline->GetY();
			loc = MyRound(currentY);
			sweepline[loc].insert(tline);
		}

		for(it2 = (*it).second[AddType].begin(); it2 != (*it).second[AddType].end(); ++it2)
		{
			//Add these new items to the sweepline
			tline = *it2;
			tline->addedAt = currentX;
			//No numerical problems here, because if A.X and B.X were within tol. Line would be
			//in a different list
			double currentY = tline->GetY();
			double loc = MyRound(currentY);
			sweepline[loc].insert(tline);
		}

		//try to break apart coincident point sets.
		//TODO: should erase the list in sweepline if it is empty
		std::map<double,std::set<MyLine*> >::iterator it3;
		for(it3 = sweepline.begin(); it3 != sweepline.end(); it3++)
		{
			std::set<MyLine*> lines = (*it3).second;
			if(lines.size() <= 1)
				continue;
			double baseloc = (*it3).first;
			std::set<MyLine*>::iterator it4;
			for(it4 = lines.begin(); it4 != lines.end();)
			{
				MyLine* tline = *it4;
				double currentY = tline->GetY(currentX);
				double newloc = MyRound(currentY);
				if(newloc!=baseloc)
				{
					std::set<MyLine*>::iterator it5 = it4;
					++it4;
					double oldx = currentX;
					currentX = tline->addedAt;
					(*it3).second.erase(tline);
					currentX = oldx;
					tline->addedAt = currentX;
					sweepline[newloc].insert(tline);
					continue;
				}
				++it4;
			}
		}

		//TODO: all sets in sweepline represent intersections
		for(it3 = sweepline.begin(); it3 != sweepline.end(); it3++)
		{
			std::set<MyLine*> lines = (*it3).second;
			if(lines.size() <= 1)
				continue;
			//All the elements of lines are intersecting at this X
			std::set<MyLine*>::iterator it4;
			for(it4 = lines.begin(); it4 != lines.end(); ++it4)
			{
				tline = *it4;
				intersections.push_back(Intersection(tline,currentX,tline->GetY(currentX)));
			}
		}

		for(it2 = (*it).second[AddRemoveType].begin(); it2 != (*it).second[AddRemoveType].end(); ++it2)
		{
			//TODO: These intersect with all things between y1 and y2
		}

		for(it2 = (*it).second[RemoveType].begin(); it2 != (*it).second[RemoveType].end(); ++it2)
		{
			//Remove these from the sweepline
			tline = *it2;
			double xSave = currentX;
			currentX = tline->addedAt;
			double currentY = tline->GetY();
			double loc = MyRound(currentY);
			sweepline[loc].erase(sweepline[loc].find(tline));
			if(sweepline[loc].size() == 0)
				sweepline.erase(sweepline.find(loc));
			currentX = xSave;
		}

		//TODO::Run intersection tests for between all adjacent sets. Then add these to the event tree
		for(it3 = sweepline.begin(); it3 != sweepline.end();)
		{
			std::set<MyLine*> lines = (*it3++).second;
			if(it3 == sweepline.end())
				break;
			std::set<MyLine*> nlines = (*it3).second;

			//Compare all lines in lines to each other and to all lines in nlines
			std::set<MyLine*>::iterator it4;
			for(it4 = lines.begin(); it4 != lines.end(); ++it4)
			{
				std::set<MyLine*>::iterator it5;
				for(it5 = nlines.begin(); it5 != nlines.end(); ++it5)
				{
					//Do the comparisons
					if(intersected[*it4].find(*it5) != intersected[*it4].end())
						continue;
					IntResult ir = Intersects(*it4,*it5);
					if(ir.exists && ir.atX > currentX + tol)
					{
						InsertEvent(IntersectionType,ir.atX,*it4);
						InsertEvent(IntersectionType,ir.atX,*it5);
						intersected[*it4].insert(*it5);
						intersected[*it5].insert(*it4);
					}
				}
				//TODO: I don't think it is necessary to compute the intersection of things within a group
				//as they are alread scheduled for regrouping
				/*
				it5 = it4;
				for(it5++; it5 != lines.end(); ++it5)
				{
					//Do the comparisons
					IntResult ir = Intersects(*it4,*it5);
					if(ir.exists)
					{
						InsertEvent(IntersectionType,ir.atX,*it4);
						InsertEvent(IntersectionType,ir.atX,*it5);
					}
				} */

			}
		}
	}
}

void Test()
{
	std::vector<MyLine> lines;
	lines.push_back(MyLine(gp_Pnt(0,0,0),gp_Pnt(5,5,0)));
	lines.push_back(MyLine(gp_Pnt(0,0,0),gp_Pnt(2,5,0)));
	lines.push_back(MyLine(gp_Pnt(0,1,0),gp_Pnt(4,1,0)));
//	lines.push_back(MyLine(gp_Pnt(1,1,0),gp_Pnt(1,2,0)));
	Intersections(lines);
}<|endoftext|>


<commit_before>
#include <stdio.h>
#include <backcurl/BackCurl.h>
/************************************ Test Scope ******************************************/

void simpleGetOption(bcl::Request &req) {
    bcl::setOpts(req, CURLOPT_URL , "http://www.google.com",
                 CURLOPT_FOLLOWLOCATION, 1L,
                 CURLOPT_WRITEFUNCTION, &bcl::writeMemoryCallback,
                 CURLOPT_WRITEDATA, req.dataPtr,
                 CURLOPT_USERAGENT, "libcurl-agent/1.0",
                 CURLOPT_RANGE, "0-200000"
                );
}

int countUI = 0;

void doSync() {
    bcl::execute<std::string>(simpleGetOption, [&](bcl::Response & resp) {
        std::string ret =  std::string(resp.getBody<std::string>()->c_str());
        printf("Sync === %s\n", ret.c_str());
    });

}

void doFuture() {
    bcl::FutureResponse frp;

    frp = bcl::execFuture<std::string>(simpleGetOption);
    bool uiRunning = true;
    while (uiRunning)  {
        if (bcl::hasRequestedAndReady(frp)) {
            bcl::Response r = frp.get();
            printf("The data content is = %s\n", r.getBody<std::string>()->c_str());
            printf("Got Http Status code = %ld\n", r.code);
            printf("Got Content Type = %s\n", r.contentType.c_str());
            printf("Total Time Consume = %f\n", r.totalTime);
            printf("has Error = %s\n", !r.error.empty() ? "Yes" : "No");

            // Exit App
            uiRunning = false;
        }
        printf("\r Future Sync ==%s ----%d", "Drawing Graphiccccc with count elapsed ", countUI++);

    }

    if (!bcl::isProcessing(frp)) printf("no data process now, no more coming data\n\n" );

}

void doGuiWork() {
    printf("\r %s --- %d", "Drawing thousand Pieces of Color with count elapsed ", countUI++);

}

void doUpdate() {
    bcl::LoopBackFire();
}

void doRunOnUI () {
    bool gui_running = true;
    std::cout << "Game is running thread: ";

    bcl::executeOnUI<std::string>([](bcl::Request & req) -> void {
        bcl::setOpts(req, CURLOPT_URL , "http://www.google.com",
        CURLOPT_FOLLOWLOCATION, 1L,
        CURLOPT_WRITEFUNCTION, &bcl::writeMemoryCallback,
        CURLOPT_WRITEDATA, req.dataPtr,
        CURLOPT_USERAGENT, "libcurl-agent/1.0",
        CURLOPT_RANGE, "0-200000"
                    );
    }, [&](bcl::Response & resp) {
        printf("On UI === %s\n", resp.getBody<std::string>()->c_str());
        printf("Done , stop gui running with count ui %d\n", countUI );
        std::this_thread::sleep_for(std::chrono::milliseconds(500));
        gui_running = false;
    });

    while (gui_running) {
        doGuiWork();
        doUpdate();
        std::this_thread::sleep_for(std::chrono::milliseconds(1000 / 16));
    }
}

// ** compile by g++ --std=c++11 main.cpp -lbackcurl -lcurl -pthread ** /

int main()
{
    bcl::init();

    doSync();

    doFuture();

    doRunOnUI();

    bcl::cleanUp();

    return 1;
}<commit_msg>testing<commit_after>
#include <stdio.h>
#include <backcurl/BackCurl.h>
#include <sys/stat.h>
#include <fcntl.h>
/************************************ Test Scope ******************************************/

void simpleGetOption(bcl::Request &req) {
    bcl::setOpts(req, CURLOPT_URL , "http://www.google.com",
                 CURLOPT_FOLLOWLOCATION, 1L,
                 CURLOPT_WRITEFUNCTION, &bcl::writeMemoryCallback,
                 CURLOPT_WRITEDATA, req.dataPtr,
                 CURLOPT_USERAGENT, "libcurl-agent/1.0",
                 CURLOPT_RANGE, "0-200000"
                );
}

int countUI = 0;

void doSync() {
    bcl::execute<std::string>(simpleGetOption, [&](bcl::Response & resp) {
        std::string ret =  std::string(resp.getBody<std::string>()->c_str());
        printf("Sync === %s\n", ret.c_str());
    });

}

void doFuture() {
    bcl::FutureResponse frp;

    frp = bcl::execFuture<std::string>(simpleGetOption);
    bool uiRunning = true;
    while (uiRunning)  {
        if (bcl::hasRequestedAndReady(frp)) {
            bcl::Response r = frp.get();
            printf("The data content is = %s\n", r.getBody<std::string>()->c_str());
            printf("Got Http Status code = %ld\n", r.code);
            printf("Got Content Type = %s\n", r.contentType.c_str());
            printf("Total Time Consume = %f\n", r.totalTime);
            printf("has Error = %s\n", !r.error.empty() ? "Yes" : "No");

            // Exit App
            uiRunning = false;
        }
        printf("\r Future Sync ==%s ----%d", "Drawing Graphiccccc with count elapsed ", countUI++);

    }

    if (!bcl::isProcessing(frp)) printf("no data process now, no more coming data\n\n" );

}

void doGuiWork() {
    printf("\r %s --- %d", "Drawing thousand Pieces of Color with count elapsed ", countUI++);

}

void doUpdate() {
    bcl::LoopBackFire();
}

void doRunOnUI () {
    bool gui_running = true;
    std::cout << "Game is running thread: ";

    bcl::executeOnUI<std::string>([](bcl::Request & req) -> void {
        bcl::setOpts(req, CURLOPT_URL , "http://www.google.com",
        CURLOPT_FOLLOWLOCATION, 1L,
        CURLOPT_WRITEFUNCTION, &bcl::writeMemoryCallback,
        CURLOPT_WRITEDATA, req.dataPtr,
        CURLOPT_USERAGENT, "libcurl-agent/1.0",
        CURLOPT_RANGE, "0-200000"
                    );
    }, [&](bcl::Response & resp) {
        printf("On UI === %s\n", resp.getBody<std::string>()->c_str());
        printf("Done , stop gui running with count ui %d\n", countUI );
        std::this_thread::sleep_for(std::chrono::milliseconds(500));
        gui_running = false;
    });

    while (gui_running) {
        doGuiWork();
        doUpdate();
        std::this_thread::sleep_for(std::chrono::milliseconds(1000 / 16));
    }
}

// File image upload and download
struct MyFileAgent {
    FILE *fd;
    struct stat file_info;
};

size_t write_data(void *ptr, size_t size, size_t nmemb, void *userData) {
    MyFileAgent* fAgent = (MyFileAgent*)userData;
    size_t written = fwrite((FILE*)ptr, size, nmemb, fAgent->fd);
    return written;
}

void doFileDownload() {
    const char *url = "http://wallpapercave.com/wp/LmOgKXz.jpg";
    char outfilename[] = "/Users/taymindis/Desktop/husky_dog_wallpaper.jpg";
    bcl::execute<MyFileAgent>([&](bcl::Request & req) -> void {
        MyFileAgent* fAgent = (MyFileAgent*)req.dataPtr;
        fAgent->fd = fopen(outfilename, "wb"); /* open file to upload */
        bcl::setOpts(req, CURLOPT_URL,url,
        CURLOPT_WRITEDATA, fAgent->fd,
        CURLOPT_WRITEFUNCTION, write_data,
        CURLOPT_FOLLOWLOCATION, 1L
                    );
    }, [&](bcl::Response & resp) {
        printf("On UI === %s\n", resp.contentType.c_str());
        fclose(resp.getBody<MyFileAgent>()->fd);
    });

}

// void doFileUpload() {
//     double speed_upload, total_time;
//     bcl::executeAsync<MyFileAgent>([&file_info](bcl::Request & req) -> void {
//          MyFileAgent* fAgent = (MyFileAgent*)req.dataPtr;
//          fAgent->fd = fopen("debugit", "rb"); /* open file to upload */
//         if (!fAgent->fd)
//             return; /* can't continue */

//         /* to get the file size */
//         if (fstat(fileno(fAgent->fd), &fAgent->file_info) != 0)
//             return; /* can't continue */

//         bcl::setOpts(req, CURLOPT_URL , "http://www.dropbox.com/....",
//         CURLOPT_UPLOAD, 1L
//         CURLOPT_READDATA, req.dataPtr,
//         CURLOPT_INFILESIZE_LARGE, (curl_off_t)fAgent->file_info.st_size,
//         CURLOPT_VERBOSE, 1L
//                     );
//     }, [&speed_upload, &fd](bcl::Response & resp) -> void {
//         curl_easy_getinfo(resp.curl, CURLINFO_SPEED_UPLOAD, speed_upload);
//         fprintf(stderr, "Speed: %.3f bytes/sec during %.3f seconds\n",
//         speed_upload, resp.total_time);
//         fclose(resp.getBody<MyFileAgent>()->fd);
//     });
// }

// ** compile by g++ --std=c++11 main.cpp -lbackcurl -lcurl -pthread ** /

int main()
{
    bcl::init();

    // doSync();

    // doFuture();

    // doRunOnUI();

    doFileDownload();
    bcl::cleanUp();

    return 1;
}<|endoftext|>