<commit_before>#include "GVAccess.h"

GVAccess::GVAccess (QObject *parent/* = NULL*/)
: QObject (parent)
, mutex(QMutex::Recursive)
, bLoggedIn(false)
, timeout(20)
{
}//GVAccess::GVAccess

GVAccess::~GVAccess ()
{
}//GVAccess::~GVAccess

QString
GVAccess::getNameForWork (GVAccess_Work whatwork)
{
    QString strResult = QString ("%1: %2");
    const char *func = NULL;

    switch (whatwork)
    {
    case GVAW_aboutBlank:
        func = "aboutBlank";
        break;
    case GVAW_logout:
        func = "logout";
        break;
    case GVAW_getRegisteredPhones:
        func = "getRegisteredPhones";
        break;
    case GVAW_dialCallback:
        func = "dialCallback";
        break;
    case GVAW_dialOut:
        func = "dialOut";
        break;
    case GVAW_login:
        func = "login";
        break;
    case GVAW_getInbox:
        func = "getInbox";
        break;
    case GVAW_sendSMS:
        func = "sendSMS";
        break;
    case GVAW_playVmail:
        func = "playVmail";
        break;
    default:
        func = "unknown";
        break;
    }

    strResult = strResult.arg(whatwork).arg(func);

    return (strResult);
}//GVWebPage::getNameForWork

bool
GVAccess::enqueueWork (GVAccess_Work whatwork, const QVariantList &params,
                       QObject      *receiver, const char         *method)
{
    if ((NULL == receiver) || (NULL == method))
    {
        qWarning ("GVAccess: Invalid slot");
        return (false);
    }

    QString msg;
    GVAccess_WorkItem workItem;
    workItem.whatwork = whatwork;
    workItem.receiver = receiver;
    workItem.method   = method;

    bool bValid = true;
    switch (whatwork)
    {
    case GVAW_aboutBlank:
    case GVAW_logout:
    case GVAW_getRegisteredPhones:
        // No params needed here
        if (0 != params.size ())
        {
            msg = "GVAccess: Invalid parameter count";
            bValid = false;
        }
        break;

    // No enum values that need only one parameter!!

    case GVAW_login:                // user and password
    case GVAW_sendSMS:              // Number, text
    case GVAW_playVmail:            // Voicemail link, destination filename
        if (2 != params.size ())
        {
            msg = "GVAccess: Invalid parameter count";
            bValid = false;
        }
        break;

    case GVAW_dialOut:              // Destination, context, callout
        if (3 != params.size ())
        {
            msg = "GVAccess: Invalid parameter count";
            bValid = false;
        }
        break;

    case GVAW_dialCallback:         // Destination, context, callback and type
    case GVAW_getInbox:             // type, start page, page count, last update
        if (4 != params.size ())
        {
            msg = "GVAccess: Invalid parameter count";
            bValid = false;
        }
        break;

    default:
        msg = "GVAccess: Invalid work code";
        bValid = false;
        break;
    }

    if (!bValid)
    {
        qWarning () << msg;
        return (false);
    }

    workItem.arrParams = params;

    QMutexLocker locker(&mutex);
    workList.push_back (workItem);

    qDebug() << "GVAccess: Enqueued " << getNameForWork (whatwork);

    // If there is no current work in progress...
    doNextWork ();// ... this takes care of when some work is in progress

    qDebug() << "GVAccess: Exit enqueueWork. The work we came in for was "
             << getNameForWork (whatwork);
    // We've come this far. Always return true because enqueue has succeeded.
    return (true);
}//GVAccess::enqueueWork

void
GVAccess::doNextWork ()
{
    QMutexLocker locker(&mutex);

    do // Begin cleanup block (not a loop)
    {
        if (0 == workList.size ())
        {
            qDebug ("GVAccess: No work to be done. Sleep now.");
            break;
        }
        if (GVAW_Nothing != workCurrent.whatwork)
        {
            qDebug () << QString ("GVAccess: Work %1 in progress. Wait for it "
                                  "to finish.")
                            .arg (getNameForWork (workCurrent.whatwork));
            break;
        }

        workCurrent = workList.takeFirst ();
        qDebug () << "GVAccess: Starting work "
                  << getNameForWork (workCurrent.whatwork);
        switch (workCurrent.whatwork)
        {
        case GVAW_aboutBlank:
            aboutBlank ();
            break;
        case GVAW_login:
            login ();
            break;
        case GVAW_logout:
            logout ();
            break;
        case GVAW_dialCallback:
        case GVAW_dialOut:
            dialCallback (workCurrent.whatwork == GVAW_dialCallback);
            break;
        case GVAW_getRegisteredPhones:
            getRegisteredPhones ();
            break;
        case GVAW_getInbox:
            getInbox ();
            break;
        case GVAW_sendSMS:
            sendSMS ();
            break;
        case GVAW_playVmail:
            playVmail ();
            break;
        default:
            qWarning ("Invalid work specified. Moving on to next work.");
            workCurrent.init ();
            continue;
        }

        break;
    } while (1); // End cleanup block (not a loop)
}//GVAccess::doNextWork

void
GVAccess::completeCurrentWork (GVAccess_Work whatwork, bool bOk)
{
    QMutexLocker locker(&mutex);
    if (whatwork != workCurrent.whatwork)
    {
        qWarning () << "GVAccess: Cannot complete the work because it is not "
                       "current! current = "
                    << getNameForWork (workCurrent.whatwork)
                    << ". requested = " << getNameForWork (whatwork);
        return;
    }

    do // Begin cleanup block (not a loop)
    {
        if (GVAW_Nothing == workCurrent.whatwork)
        {
            qWarning ("GVAccess: Completing null work!");
            break;
        }

        QObject::connect (
            this, SIGNAL (workCompleted (bool, const QVariantList &)),
            workCurrent.receiver, workCurrent.method);

        qDebug() << "GVAccess: Invoking callback for work "
                 << getNameForWork(whatwork);
        emit workCompleted (bOk, workCurrent.arrParams);

        QObject::disconnect (
            this, SIGNAL (workCompleted (bool, const QVariantList &)),
            workCurrent.receiver, workCurrent.method);

        qDebug() << "GVAccess: Completed work " << getNameForWork(whatwork);
    } while (0); // End cleanup block (not a loop)

    // Init MUST be done after the workCompleted emit to prevent races
    // and to let the stack unwind.
    workCurrent.init ();
    doNextWork ();
}//GVAccess::completeCurrentWork

bool
GVAccess::cancelWork()
{
    QMutexLocker locker(&mutex);
    qDebug() << "GVAccess: Request for cancel current. current work is "
             << getNameForWork (workCurrent.whatwork);
    return cancelWork (workCurrent.whatwork);
}//GVAccess::cancelWork

bool
GVAccess::cancelWork (GVAccess_Work whatwork)
{
    bool rv = false;
    QMutexLocker locker(&mutex);
    qDebug() << "GVAccess: Request for cancel. work to cancel:"
             << getNameForWork (whatwork);
    do // Begin cleanup block (not a loop)
    {
        if (whatwork == workCurrent.whatwork)
        {
            qDebug("Work to cancel was the current work");

            workCurrent.bCancel = true;

            if (NULL != workCurrent.cancel)
            {
                qDebug("Current work had a cancel callback. Invoking it.");
                (this->*(workCurrent.cancel)) ();
            }
            else
            {
                qDebug("Current work had no cancel callback. Moving on.");
                workCurrent.init ();
                doNextWork ();
            }

            rv = true;
            break;
        }

        qDebug("Work to cancel was NOT the current work. Looking for it...");
        bool bFound = false;
        for (int i = 0; i < workList.size (); i++)
        {
            if (whatwork == workList[i].whatwork)
            {
                qDebug() << "Found the work to cancel at index" << i;
                bFound = true;
                GVAccess_WorkItem item = workList.takeAt (i);
                if (NULL != item.cancel)
                {
                    qDebug("Work had a cancel callback. Invoking it.");
                    (this->*(workCurrent.cancel)) ();
                } else {
                    qDebug("Work had NO cancel callback. Moving on.");
                }

                rv = true;
                break;
            }
        }
        if (!bFound) {
            qWarning ("Did not find the work to cancel.");
        }
    } while (0); // End cleanup block (not a loop)

    return (rv);
}//GVAccess::cancelWork

void
GVAccess::simplify_number (QString &strNumber, bool bAddIntPrefix /*= true*/)
{
    strNumber.remove(QChar (' ')).remove(QChar ('(')).remove(QChar (')'));
    strNumber.remove(QChar ('-'));

    do // Begin cleanup block (not a loop)
    {
        if (!bAddIntPrefix) {
            break;
        }

        if (strNumber.startsWith ("+")) {
            break;
        }

        if (strNumber.length () < 10) {
            break;
        }

        if (!strNumber.contains (QRegExp("^\\d*$"))) {
            // Not numbers. Dont touch it! (anymore!!)
            break;
        }

        if ((strNumber.length () == 11) && (strNumber.startsWith ('1')))
        {
            strNumber = "+" + strNumber;
            break;
        }

        strNumber = "+1" + strNumber;
    } while (0); // End cleanup block (not a loop)
}//GVAccess::simplify_number

bool
GVAccess::isNumberValid (const QString &strNumber)
{
    QString strTemp = strNumber;
    simplify_number (strTemp);
    strTemp.remove ('+');
    strTemp.remove (QRegExp ("\\d"));

    return (strTemp.size () == 0);
}//GVAccess::isNumberValid

void
GVAccess::beautify_number (QString &strNumber)
{
    do { // Begin cleanup block (not a loop)
        if (!GVAccess::isNumberValid (strNumber))   break;

        QString strTemp = strNumber;
        GVAccess::simplify_number (strTemp);

        if (!strTemp.startsWith ("+1"))   break;
        if (strTemp.size () < 10)         break;

        // +1aaabbbcccc -> +1 aaa bbb cccc
        // 012345678901
        strNumber = "+1 "
                  + strTemp.mid (2, 3)
                  + " "
                  + strTemp.mid (5, 3)
                  + " "
                  + strTemp.mid (8);
    } while (0); // End cleanup block (not a loop)
}//GVAccess::beautify_number

QNetworkRequest
GVAccess::createRequest (QString         strUrl    ,
                         QStringPairList arrPairs  ,
                         QByteArray     &byPostData)
{
    QStringList arrParams;
    foreach (QStringPair pairParam, arrPairs)
    {
        arrParams += QString("%1=%2")
                        .arg(pairParam.first)
                        .arg(pairParam.second);
    }
    byPostData = arrParams.join ("&").toAscii ();

    QUrl url (strUrl);
    QNetworkRequest request(url);
    request.setHeader (QNetworkRequest::ContentTypeHeader,
                       "application/x-www-form-urlencoded");

    return (request);
}//GVAccess::createRequest

QNetworkReply *
GVAccess::postRequest (QNetworkAccessManager   *mgr     ,
                       QString                  strUrl  ,
                       QStringPairList          arrPairs,
                       QString                  strUA   ,
                       QObject                 *receiver,
                       const char              *method  )
{
    QByteArray byPostData;
    QNetworkRequest request = createRequest (strUrl, arrPairs, byPostData);
    if (0 != strUA.size ())
    {
        request.setRawHeader ("User-Agent", strUA.toAscii ());
    }

    QObject::connect (mgr     , SIGNAL (finished (QNetworkReply *)),
                      receiver, method);
    QNetworkReply *reply = mgr->post (request, byPostData);
    return (reply);
}//GVAccess::postRequest

void
GVAccess::dialCanFinish ()
{
    QMutexLocker locker(&mutex);
    if (GVAW_dialCallback == workCurrent.whatwork)
    {
        qDebug ("GVAccess: call in progress can finish. Completing");
        completeCurrentWork (GVAW_dialCallback, true);
    }
    else
    {
        qWarning ("GVAccess: Cannot complete a call that is not in progress");
    }
}//GVAccess::dialCanFinish

void
GVAccess::setView (QWidget * /*view*/)
{
}//GVAccess::setView

bool
GVAccess::setProxySettings (bool bEnable,
                            bool bUseSystemProxy,
                            const QString &host, int port,
                            bool bRequiresAuth,
                            const QString &user, const QString &pass)
{
    QNetworkProxy proxySettings;
    do // Begin cleanup block (not a loop)
    {
        if (!bEnable) {
            qDebug ("GVAccess: Clearing all proxy information");
            break;
        }

        if (bUseSystemProxy) {
            QNetworkProxy https;
            getSystemProxies (proxySettings, https);
            qDebug ("GVAccess: Using system proxy settings");
            break;
        }

        proxySettings.setHostName (host);
        proxySettings.setPort (port);
        proxySettings.setType (QNetworkProxy::HttpProxy);

        if (bRequiresAuth) {
            proxySettings.setUser (user);
            proxySettings.setPassword (pass);
        }

        qDebug ("GVAccess: Using user defined proxy settings.");
    } while (0); // End cleanup block (not a loop)
    QNetworkProxy::setApplicationProxy (proxySettings);

    return (true);
}//GVAccess::setProxySettings

bool
GVAccess::getSystemProxies (QNetworkProxy &http, QNetworkProxy &https)
{
    QNetworkProxyFactory::setUseSystemConfiguration (true);

    do { // Begin cleanup block (not a loop)
        QList<QNetworkProxy> netProxies =
        QNetworkProxyFactory::systemProxyForQuery (
        QNetworkProxyQuery(QUrl("http://www.google.com")));
        http = netProxies[0];
        if (QNetworkProxy::NoProxy != http.type ()) {
            qDebug () << "GVAccess: Got proxy: host = " << http.hostName ()
                      << ", port = " << http.port ();
            break;
        }

        // Otherwise Confirm it
#if defined(Q_WS_X11)
        QString strHttpProxy = getenv ("http_proxy");
        if (strHttpProxy.isEmpty ()) {
            break;
        }

        int colon = strHttpProxy.lastIndexOf (':');
        if (-1 != colon) {
            QString strHost = strHttpProxy.mid (0, colon);
            QString strPort = strHttpProxy.mid (colon);

            strHost.remove ("http://").remove ("https://");

            strPort.remove (':').remove ('/');
            int port = strPort.toInt ();

            qDebug () << "GVAccess: Found http proxy: "
                      << strHost << ":" << port;
            http.setHostName (strHost);
            http.setPort (port);
            http.setType (QNetworkProxy::HttpProxy);
        }
#endif
    } while (0); // End cleanup block (not a loop)

    do { // Begin cleanup block (not a loop)
        QList<QNetworkProxy> netProxies =
        QNetworkProxyFactory::systemProxyForQuery (
        QNetworkProxyQuery(QUrl("https://www.google.com")));
        https = netProxies[0];
        if (QNetworkProxy::NoProxy != https.type ()) {
            qDebug () << "GVAccess: Got proxy: host = " << https.hostName ()
                      << ", port = " << https.port ();
            break;
        }

        // Otherwise Confirm it
#if defined(Q_WS_X11)
        QString strHttpProxy = getenv ("https_proxy");
        if (strHttpProxy.isEmpty ()) {
            break;
        }

        int colon = strHttpProxy.lastIndexOf (':');
        if (-1 != colon) {
            QString strHost = strHttpProxy.mid (0, colon);
            QString strPort = strHttpProxy.mid (colon);

            strHost.remove ("http://").remove ("https://");

            strPort.remove (':').remove ('/');
            int port = strPort.toInt ();

            qDebug () << "GVAccess: Found http proxy: "
                      << strHost << ":" << port;
            https.setHostName (strHost);
            https.setPort (port);
            https.setType (QNetworkProxy::HttpProxy);
        }
#endif
    } while (0); // End cleanup block (not a loop)

    return (true);
}//GVAccess::getSystemProxies

void
GVAccess::setTimeout (int seconds /*= 20*/)
{
    timeout = seconds;
    qDebug() << "GVAccess: Timeout is now : " << timeout;
}//GVAccess::setTimeout
<commit_msg>minor fix<commit_after>#include "GVAccess.h"

GVAccess::GVAccess (QObject *parent/* = NULL*/)
: QObject (parent)
, mutex(QMutex::Recursive)
, bLoggedIn(false)
, timeout(20)
{
}//GVAccess::GVAccess

GVAccess::~GVAccess ()
{
}//GVAccess::~GVAccess

QString
GVAccess::getNameForWork (GVAccess_Work whatwork)
{
    QString strResult = QString ("%1: %2");
    const char *func = NULL;

    switch (whatwork)
    {
    case GVAW_aboutBlank:
        func = "aboutBlank";
        break;
    case GVAW_logout:
        func = "logout";
        break;
    case GVAW_getRegisteredPhones:
        func = "getRegisteredPhones";
        break;
    case GVAW_dialCallback:
        func = "dialCallback";
        break;
    case GVAW_dialOut:
        func = "dialOut";
        break;
    case GVAW_login:
        func = "login";
        break;
    case GVAW_getInbox:
        func = "getInbox";
        break;
    case GVAW_sendSMS:
        func = "sendSMS";
        break;
    case GVAW_playVmail:
        func = "playVmail";
        break;
    default:
        func = "unknown";
        break;
    }

    strResult = strResult.arg(whatwork).arg(func);

    return (strResult);
}//GVWebPage::getNameForWork

bool
GVAccess::enqueueWork (GVAccess_Work whatwork, const QVariantList &params,
                       QObject      *receiver, const char         *method)
{
    if ((NULL == receiver) || (NULL == method))
    {
        qWarning ("GVAccess: Invalid slot");
        return (false);
    }

    QString msg;
    GVAccess_WorkItem workItem;
    workItem.whatwork = whatwork;
    workItem.receiver = receiver;
    workItem.method   = method;

    bool bValid = true;
    switch (whatwork)
    {
    case GVAW_aboutBlank:
    case GVAW_logout:
    case GVAW_getRegisteredPhones:
        // No params needed here
        if (0 != params.size ())
        {
            msg = "GVAccess: Invalid parameter count";
            bValid = false;
        }
        break;

    // No enum values that need only one parameter!!

    case GVAW_login:                // user and password
    case GVAW_sendSMS:              // Number, text
    case GVAW_playVmail:            // Voicemail link, destination filename
        if (2 != params.size ())
        {
            msg = "GVAccess: Invalid parameter count";
            bValid = false;
        }
        break;

    case GVAW_dialOut:              // Destination, context, callout
        if (3 != params.size ())
        {
            msg = "GVAccess: Invalid parameter count";
            bValid = false;
        }
        break;

    case GVAW_dialCallback:         // Destination, context, callback and type
    case GVAW_getInbox:             // type, start page, page count, last update
        if (4 != params.size ())
        {
            msg = "GVAccess: Invalid parameter count";
            bValid = false;
        }
        break;

    default:
        msg = "GVAccess: Invalid work code";
        bValid = false;
        break;
    }

    if (!bValid)
    {
        qWarning () << msg;
        return (false);
    }

    workItem.arrParams = params;

    QMutexLocker locker(&mutex);
    workList.push_back (workItem);

    qDebug() << "GVAccess: Enqueued " << getNameForWork (whatwork);

    // If there is no current work in progress...
    doNextWork ();// ... this takes care of when some work is in progress

    qDebug() << "GVAccess: Exit enqueueWork. The work we came in for was "
             << getNameForWork (whatwork);
    // We've come this far. Always return true because enqueue has succeeded.
    return (true);
}//GVAccess::enqueueWork

void
GVAccess::doNextWork ()
{
    QMutexLocker locker(&mutex);

    do // Begin cleanup block (not a loop)
    {
        if (0 == workList.size ())
        {
            qDebug ("GVAccess: No work to be done. Sleep now.");
            break;
        }
        if (GVAW_Nothing != workCurrent.whatwork)
        {
            qDebug () << QString ("GVAccess: Work %1 in progress. Wait for it "
                                  "to finish.")
                            .arg (getNameForWork (workCurrent.whatwork));
            break;
        }

        workCurrent = workList.takeFirst ();
        qDebug () << "GVAccess: Starting work "
                  << getNameForWork (workCurrent.whatwork);
        switch (workCurrent.whatwork)
        {
        case GVAW_aboutBlank:
            aboutBlank ();
            break;
        case GVAW_login:
            login ();
            break;
        case GVAW_logout:
            logout ();
            break;
        case GVAW_dialCallback:
        case GVAW_dialOut:
            dialCallback (workCurrent.whatwork == GVAW_dialCallback);
            break;
        case GVAW_getRegisteredPhones:
            getRegisteredPhones ();
            break;
        case GVAW_getInbox:
            getInbox ();
            break;
        case GVAW_sendSMS:
            sendSMS ();
            break;
        case GVAW_playVmail:
            playVmail ();
            break;
        default:
            qWarning ("Invalid work specified. Moving on to next work.");
            workCurrent.init ();
            continue;
        }

        break;
    } while (1); // End cleanup block (not a loop)
}//GVAccess::doNextWork

void
GVAccess::completeCurrentWork (GVAccess_Work whatwork, bool bOk)
{
    QMutexLocker locker(&mutex);
    if (whatwork != workCurrent.whatwork)
    {
        qWarning () << "GVAccess: Cannot complete the work because it is not "
                       "current! current = "
                    << getNameForWork (workCurrent.whatwork)
                    << ". requested = " << getNameForWork (whatwork);
        return;
    }

    do // Begin cleanup block (not a loop)
    {
        if (GVAW_Nothing == workCurrent.whatwork)
        {
            qWarning ("GVAccess: Completing null work!");
            break;
        }

        QObject::connect (
            this, SIGNAL (workCompleted (bool, const QVariantList &)),
            workCurrent.receiver, workCurrent.method);

        qDebug() << "GVAccess: Invoking callback for work "
                 << getNameForWork(whatwork);
        emit workCompleted (bOk, workCurrent.arrParams);

        QObject::disconnect (
            this, SIGNAL (workCompleted (bool, const QVariantList &)),
            workCurrent.receiver, workCurrent.method);

        qDebug() << "GVAccess: Completed work " << getNameForWork(whatwork);
    } while (0); // End cleanup block (not a loop)

    // Init MUST be done after the workCompleted emit to prevent races
    // and to let the stack unwind.
    workCurrent.init ();
    doNextWork ();
}//GVAccess::completeCurrentWork

bool
GVAccess::cancelWork()
{
    QMutexLocker locker(&mutex);
    qDebug() << "GVAccess: Request for cancel current. current work is "
             << getNameForWork (workCurrent.whatwork);
    return cancelWork (workCurrent.whatwork);
}//GVAccess::cancelWork

bool
GVAccess::cancelWork (GVAccess_Work whatwork)
{
    bool rv = false;
    QMutexLocker locker(&mutex);
    qDebug() << "GVAccess: Request for cancel. work to cancel:"
             << getNameForWork (whatwork);
    do // Begin cleanup block (not a loop)
    {
        if (whatwork == workCurrent.whatwork)
        {
            qDebug("Work to cancel was the current work");

            workCurrent.bCancel = true;

            if (NULL != workCurrent.cancel)
            {
                qDebug("Current work had a cancel callback. Invoking it.");
                (this->*(workCurrent.cancel)) ();
            }
            else
            {
                qDebug("Current work had no cancel callback. Moving on.");
                workCurrent.init ();
                doNextWork ();
            }

            rv = true;
            break;
        }

        qDebug("Work to cancel was NOT the current work. Looking for it...");
        bool bFound = false;
        for (int i = 0; i < workList.size (); i++)
        {
            if (whatwork == workList[i].whatwork)
            {
                qDebug() << "Found the work to cancel at index" << i;
                bFound = true;
                GVAccess_WorkItem item = workList.takeAt (i);
                if (NULL != item.cancel)
                {
                    qDebug("Work had a cancel callback. Invoking it.");
                    (this->*(workCurrent.cancel)) ();
                } else {
                    qDebug("Work had NO cancel callback. Moving on.");
                }

                rv = true;
                break;
            }
        }
        if (!bFound) {
            qWarning ("Did not find the work to cancel.");
        }
    } while (0); // End cleanup block (not a loop)

    return (rv);
}//GVAccess::cancelWork

void
GVAccess::simplify_number (QString &strNumber, bool bAddIntPrefix /*= true*/)
{
    strNumber.remove(QChar (' ')).remove(QChar ('(')).remove(QChar (')'));
    strNumber.remove(QChar ('-'));

    do // Begin cleanup block (not a loop)
    {
        if (!bAddIntPrefix) {
            break;
        }

        if (strNumber.startsWith ("+")) {
            break;
        }

        if (strNumber.length () < 10) {
            break;
        }

        if (!strNumber.contains (QRegExp("^\\d*$"))) {
            // Not numbers. Dont touch it! (anymore!!)
            break;
        }

        if ((strNumber.length () == 11) && (strNumber.startsWith ('1')))
        {
            strNumber = "+" + strNumber;
            break;
        }

        strNumber = "+1" + strNumber;
    } while (0); // End cleanup block (not a loop)
}//GVAccess::simplify_number

bool
GVAccess::isNumberValid (const QString &strNumber)
{
    QString strTemp = strNumber;
    simplify_number (strTemp);
    strTemp.remove ('+');
    strTemp.remove (QRegExp ("\\d"));

    return (strTemp.size () == 0);
}//GVAccess::isNumberValid

void
GVAccess::beautify_number (QString &strNumber)
{
    do { // Begin cleanup block (not a loop)
        if (!GVAccess::isNumberValid (strNumber))   break;

        QString strTemp = strNumber;
        GVAccess::simplify_number (strTemp);

        if (!strTemp.startsWith ("+1"))   break;
        if (strTemp.size () < 10)         break;

        // +1aaabbbcccc -> +1 aaa bbb cccc
        // 012345678901
        strNumber = "+1 "
                  + strTemp.mid (2, 3)
                  + " "
                  + strTemp.mid (5, 3)
                  + " "
                  + strTemp.mid (8);
    } while (0); // End cleanup block (not a loop)
}//GVAccess::beautify_number

QNetworkRequest
GVAccess::createRequest (QString         strUrl    ,
                         QStringPairList arrPairs  ,
                         QByteArray     &byPostData)
{
    QStringList arrParams;
    foreach (QStringPair pairParam, arrPairs)
    {
        arrParams += QString("%1=%2")
                        .arg(pairParam.first)
                        .arg(pairParam.second);
    }
    byPostData = arrParams.join ("&").toAscii ();

    QUrl url (strUrl);
    QNetworkRequest request(url);
    request.setHeader (QNetworkRequest::ContentTypeHeader,
                       "application/x-www-form-urlencoded");

    return (request);
}//GVAccess::createRequest

QNetworkReply *
GVAccess::postRequest (QNetworkAccessManager   *mgr     ,
                       QString                  strUrl  ,
                       QStringPairList          arrPairs,
                       QString                  strUA   ,
                       QObject                 *receiver,
                       const char              *method  )
{
    QByteArray byPostData;
    QNetworkRequest request = createRequest (strUrl, arrPairs, byPostData);
    if (0 != strUA.size ())
    {
        request.setRawHeader ("User-Agent", strUA.toAscii ());
    }

    QObject::connect (mgr     , SIGNAL (finished (QNetworkReply *)),
                      receiver, method);
    QNetworkReply *reply = mgr->post (request, byPostData);
    return (reply);
}//GVAccess::postRequest

void
GVAccess::dialCanFinish ()
{
    QMutexLocker locker(&mutex);
    if (GVAW_dialCallback == workCurrent.whatwork)
    {
        qDebug ("GVAccess: call in progress can finish. Completing");
        completeCurrentWork (GVAW_dialCallback, true);
    }
    else
    {
        qWarning ("GVAccess: Cannot complete a call that is not in progress");
    }
}//GVAccess::dialCanFinish

void
GVAccess::setView (QWidget * /*view*/)
{
}//GVAccess::setView

bool
GVAccess::setProxySettings (bool bEnable,
                            bool bUseSystemProxy,
                            const QString &host, int port,
                            bool bRequiresAuth,
                            const QString &user, const QString &pass)
{
    QNetworkProxy proxySettings;
    do // Begin cleanup block (not a loop)
    {
        if (!bEnable) {
            qDebug ("GVAccess: Clearing all proxy information");
            break;
        }

        if (bUseSystemProxy) {
            QNetworkProxy https;
            getSystemProxies (proxySettings, https);
            qDebug ("GVAccess: Using system proxy settings");
            break;
        }

        proxySettings.setHostName (host);
        proxySettings.setPort (port);
        proxySettings.setType (QNetworkProxy::HttpProxy);

        if (bRequiresAuth) {
            proxySettings.setUser (user);
            proxySettings.setPassword (pass);
        }

        qDebug ("GVAccess: Using user defined proxy settings.");
    } while (0); // End cleanup block (not a loop)
    QNetworkProxy::setApplicationProxy (proxySettings);

    return (true);
}//GVAccess::setProxySettings

bool
GVAccess::getSystemProxies (QNetworkProxy &http, QNetworkProxy &https)
{
#if !DIABLO_OS
    QNetworkProxyFactory::setUseSystemConfiguration (true);
#endif

    do { // Begin cleanup block (not a loop)
        QList<QNetworkProxy> netProxies =
        QNetworkProxyFactory::systemProxyForQuery (
        QNetworkProxyQuery(QUrl("http://www.google.com")));
        http = netProxies[0];
        if (QNetworkProxy::NoProxy != http.type ()) {
            qDebug () << "GVAccess: Got proxy: host = " << http.hostName ()
                      << ", port = " << http.port ();
            break;
        }

        // Otherwise Confirm it
#if defined(Q_WS_X11)
        QString strHttpProxy = getenv ("http_proxy");
        if (strHttpProxy.isEmpty ()) {
            break;
        }

        int colon = strHttpProxy.lastIndexOf (':');
        if (-1 != colon) {
            QString strHost = strHttpProxy.mid (0, colon);
            QString strPort = strHttpProxy.mid (colon);

            strHost.remove ("http://").remove ("https://");

            strPort.remove (':').remove ('/');
            int port = strPort.toInt ();

            qDebug () << "GVAccess: Found http proxy: "
                      << strHost << ":" << port;
            http.setHostName (strHost);
            http.setPort (port);
            http.setType (QNetworkProxy::HttpProxy);
        }
#endif
    } while (0); // End cleanup block (not a loop)

    do { // Begin cleanup block (not a loop)
        QList<QNetworkProxy> netProxies =
        QNetworkProxyFactory::systemProxyForQuery (
        QNetworkProxyQuery(QUrl("https://www.google.com")));
        https = netProxies[0];
        if (QNetworkProxy::NoProxy != https.type ()) {
            qDebug () << "GVAccess: Got proxy: host = " << https.hostName ()
                      << ", port = " << https.port ();
            break;
        }

        // Otherwise Confirm it
#if defined(Q_WS_X11)
        QString strHttpProxy = getenv ("https_proxy");
        if (strHttpProxy.isEmpty ()) {
            break;
        }

        int colon = strHttpProxy.lastIndexOf (':');
        if (-1 != colon) {
            QString strHost = strHttpProxy.mid (0, colon);
            QString strPort = strHttpProxy.mid (colon);

            strHost.remove ("http://").remove ("https://");

            strPort.remove (':').remove ('/');
            int port = strPort.toInt ();

            qDebug () << "GVAccess: Found http proxy: "
                      << strHost << ":" << port;
            https.setHostName (strHost);
            https.setPort (port);
            https.setType (QNetworkProxy::HttpProxy);
        }
#endif
    } while (0); // End cleanup block (not a loop)

    return (true);
}//GVAccess::getSystemProxies

void
GVAccess::setTimeout (int seconds /*= 20*/)
{
    timeout = seconds;
    qDebug() << "GVAccess: Timeout is now : " << timeout;
}//GVAccess::setTimeout
<|endoftext|>


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

#include "Precompiled.h"
#include "Context.h"
#include "BorderImage.h"
#include "InputEvents.h"
#include "ScrollBar.h"
#include "ScrollView.h"
#include "UIEvents.h"

#include "DebugNew.h"

namespace Urho3D
{

static const float STEP_FACTOR = 300.0f;

OBJECTTYPESTATIC(ScrollView);

ScrollView::ScrollView(Context* context) :
    UIElement(context),
    viewPosition_(IntVector2::ZERO),
    viewSize_(IntVector2::ZERO),
    pageStep_(1.0f)
{
    clipChildren_ = true;
    active_ = true;
    focusMode_ = FM_FOCUSABLE_DEFOCUSABLE;

    horizontalScrollBar_ = CreateChild<ScrollBar>();
    horizontalScrollBar_->SetInternal(true);
    horizontalScrollBar_->SetAlignment(HA_LEFT, VA_BOTTOM);
    horizontalScrollBar_->SetOrientation(O_HORIZONTAL);
    verticalScrollBar_ = CreateChild<ScrollBar>();
    verticalScrollBar_->SetInternal(true);
    verticalScrollBar_->SetAlignment(HA_RIGHT, VA_TOP);
    verticalScrollBar_->SetOrientation(O_VERTICAL);
    scrollPanel_ = CreateChild<BorderImage>();
    scrollPanel_->SetInternal(true);
    scrollPanel_->SetActive(true);
    scrollPanel_->SetClipChildren(true);
    scrollPanel_->SetPriority(-1);

    SubscribeToEvent(horizontalScrollBar_, E_SCROLLBARCHANGED, HANDLER(ScrollView, HandleScrollBarChanged));
    SubscribeToEvent(horizontalScrollBar_, E_VISIBLECHANGED, HANDLER(ScrollView, HandleScrollBarVisibleChanged));
    SubscribeToEvent(verticalScrollBar_, E_SCROLLBARCHANGED, HANDLER(ScrollView, HandleScrollBarChanged));
    SubscribeToEvent(verticalScrollBar_, E_VISIBLECHANGED, HANDLER(ScrollView, HandleScrollBarVisibleChanged));
}

ScrollView::~ScrollView()
{
}

void ScrollView::RegisterObject(Context* context)
{
    context->RegisterFactory<ScrollView>();

    REF_ACCESSOR_ATTRIBUTE(ScrollView, VAR_INTVECTOR2, "View Position", GetViewPosition, SetViewPosition, IntVector2, IntVector2::ZERO, AM_FILE);
    ACCESSOR_ATTRIBUTE(ScrollView, VAR_FLOAT, "Scroll Step", GetScrollStep, SetScrollStep, float, 0.1f, AM_FILE);
    ACCESSOR_ATTRIBUTE(ScrollView, VAR_FLOAT, "Page Step", GetPageStep, SetPageStep, float, 1.0f, AM_FILE);
    COPY_BASE_ATTRIBUTES(ScrollView, UIElement);
}

void ScrollView::ApplyAttributes()
{
    UIElement::ApplyAttributes();

    // Set the scrollbar orientations again and perform size update now that the style is known
    horizontalScrollBar_->SetOrientation(O_HORIZONTAL);
    verticalScrollBar_->SetOrientation(O_VERTICAL);

    OnResize();
}

void ScrollView::OnWheel(int delta, int buttons, int qualifiers)
{
    if (delta > 0)
        verticalScrollBar_->StepBack();
    if (delta < 0)
        verticalScrollBar_->StepForward();
}

void ScrollView::OnKey(int key, int buttons, int qualifiers)
{
    switch (key)
    {
    case KEY_LEFT:
        if (horizontalScrollBar_->IsVisible())
        {
            if (qualifiers & QUAL_CTRL)
                horizontalScrollBar_->SetValue(0.0f);
            else
                horizontalScrollBar_->StepBack();
        }
        break;

    case KEY_RIGHT:
        if (horizontalScrollBar_->IsVisible())
        {
            if (qualifiers & QUAL_CTRL)
                horizontalScrollBar_->SetValue(horizontalScrollBar_->GetRange());
            else
                horizontalScrollBar_->StepForward();
        }
        break;

    case KEY_UP:
        if (verticalScrollBar_->IsVisible())
        {
            if (qualifiers & QUAL_CTRL)
                verticalScrollBar_->SetValue(0.0f);
            else
                verticalScrollBar_->StepBack();
        }
        break;

    case KEY_DOWN:
        if (verticalScrollBar_->IsVisible())
        {
            if (qualifiers & QUAL_CTRL)
                verticalScrollBar_->SetValue(verticalScrollBar_->GetRange());
            else
                verticalScrollBar_->StepForward();
        }
        break;

    case KEY_PAGEUP:
        if (verticalScrollBar_->IsVisible())
            verticalScrollBar_->ChangeValue(-pageStep_);
        break;

    case KEY_PAGEDOWN:
        if (verticalScrollBar_->IsVisible())
            verticalScrollBar_->ChangeValue(pageStep_);
        break;

    case KEY_HOME:
        if (verticalScrollBar_->IsVisible())
            verticalScrollBar_->SetValue(0.0f);
        break;

    case KEY_END:
        if (verticalScrollBar_->IsVisible())
            verticalScrollBar_->SetValue(verticalScrollBar_->GetRange());
        break;
    }
}

void ScrollView::OnResize()
{
    IntVector2 panelSize = GetSize();
    if (verticalScrollBar_->IsVisible())
        panelSize.x_ -= verticalScrollBar_->GetWidth();
    if (horizontalScrollBar_->IsVisible())
        panelSize.y_ -= horizontalScrollBar_->GetHeight();

    scrollPanel_->SetSize(panelSize);
    horizontalScrollBar_->SetWidth(scrollPanel_->GetWidth());
    verticalScrollBar_->SetHeight(scrollPanel_->GetHeight());

    UpdateViewSize();
}

void ScrollView::SetContentElement(UIElement* element)
{
    if (element == contentElement_)
        return;

    if (contentElement_)
    {
        scrollPanel_->RemoveChild(contentElement_);
        UnsubscribeFromEvent(contentElement_, E_RESIZED);
    }
    contentElement_ = element;
    if (contentElement_)
    {
        scrollPanel_->AddChild(contentElement_);
        SubscribeToEvent(contentElement_, E_RESIZED, HANDLER(ScrollView, HandleElementResized));
    }

    UpdateViewSize();
}

void ScrollView::SetViewPosition(const IntVector2& position)
{
    UpdateView(position);
    UpdateScrollBars();
}

void ScrollView::SetViewPosition(int x, int y)
{
    SetViewPosition(IntVector2(x, y));
}

void ScrollView::SetScrollBarsVisible(bool horizontal, bool vertical)
{
    horizontalScrollBar_->SetVisible(horizontal);
    verticalScrollBar_->SetVisible(vertical);
}

void ScrollView::SetScrollStep(float step)
{
    horizontalScrollBar_->SetScrollStep(step);
    verticalScrollBar_->SetScrollStep(step);
}

void ScrollView::SetPageStep(float step)
{
    pageStep_ = Max(step, 0.0f);
}

float ScrollView::GetScrollStep() const
{
    return horizontalScrollBar_->GetScrollStep();
}

void ScrollView::UpdateViewSize()
{
    IntVector2 size(IntVector2::ZERO);
    if (contentElement_)
        size = contentElement_->GetSize();
    IntRect panelBorder = scrollPanel_->GetClipBorder();

    viewSize_.x_ = Max(size.x_, scrollPanel_->GetWidth() - panelBorder.left_ - panelBorder.right_);
    viewSize_.y_ = Max(size.y_, scrollPanel_->GetHeight() - panelBorder.top_ - panelBorder.bottom_);
    UpdateView(viewPosition_);
    UpdateScrollBars();
}

void ScrollView::UpdateScrollBars()
{
    ignoreEvents_ = true;

    IntVector2 size = scrollPanel_->GetSize();
    IntRect panelBorder = scrollPanel_->GetClipBorder();
    size.x_ -= panelBorder.left_ + panelBorder.right_;
    size.y_ -= panelBorder.top_ + panelBorder.bottom_;

    if (horizontalScrollBar_ && size.x_ > 0 && viewSize_.x_ > 0)
    {
        horizontalScrollBar_->SetRange((float)viewSize_.x_ / (float)size.x_ - 1.0f);
        horizontalScrollBar_->SetValue((float)viewPosition_.x_ / (float)size.x_);
        horizontalScrollBar_->SetStepFactor(STEP_FACTOR / (float)size.x_);
    }
    if (verticalScrollBar_ && size.y_ > 0 && viewSize_.y_ > 0)
    {
        verticalScrollBar_->SetRange((float)viewSize_.y_ / (float)size.y_ - 1.0f);
        verticalScrollBar_->SetValue((float)viewPosition_.y_ / (float)size.y_);
        verticalScrollBar_->SetStepFactor(STEP_FACTOR / (float)size.y_);
    }

    ignoreEvents_ = false;
}

void ScrollView::UpdateView(const IntVector2& position)
{
    IntVector2 oldPosition = viewPosition_;
    IntRect panelBorder = scrollPanel_->GetClipBorder();

    viewPosition_.x_ = Clamp(position.x_, 0, viewSize_.x_);
    viewPosition_.y_ = Clamp(position.y_, 0, viewSize_.y_);
    scrollPanel_->SetChildOffset(IntVector2(-viewPosition_.x_ + panelBorder.left_, -viewPosition_.y_ + panelBorder.top_));

    if (viewPosition_ != oldPosition)
    {
        using namespace ViewChanged;

        VariantMap eventData;
        eventData[P_ELEMENT] = (void*)this;
        eventData[P_X] = viewPosition_.x_;
        eventData[P_Y] = viewPosition_.y_;
        SendEvent(E_VIEWCHANGED, eventData);
    }
}

void ScrollView::HandleScrollBarChanged(StringHash eventType, VariantMap& eventData)
{
    IntVector2 size = scrollPanel_->GetSize();
    IntRect panelBorder = scrollPanel_->GetClipBorder();
    size.x_ -= panelBorder.left_ + panelBorder.right_;
    size.y_ -= panelBorder.top_ + panelBorder.bottom_;

    if (!ignoreEvents_)
    {
        UpdateView(IntVector2(
            (int)(horizontalScrollBar_->GetValue() * (float)size.x_),
            (int)(verticalScrollBar_->GetValue() * (float)size.y_)
        ));
    }
}

void ScrollView::HandleScrollBarVisibleChanged(StringHash eventType, VariantMap& eventData)
{
    // Need to recalculate panel size when scrollbar visibility changes
    OnResize();
}

void ScrollView::HandleElementResized(StringHash eventType, VariantMap& eventData)
{
    UpdateViewSize();
}

}
<commit_msg>Fixed scroll view positioning bug.<commit_after>//
// Urho3D Engine
// Copyright (c) 2008-2012 Lasse rni
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
//

#include "Precompiled.h"
#include "Context.h"
#include "BorderImage.h"
#include "InputEvents.h"
#include "ScrollBar.h"
#include "ScrollView.h"
#include "UIEvents.h"

#include "DebugNew.h"

namespace Urho3D
{

static const float STEP_FACTOR = 300.0f;

OBJECTTYPESTATIC(ScrollView);

ScrollView::ScrollView(Context* context) :
    UIElement(context),
    viewPosition_(IntVector2::ZERO),
    viewSize_(IntVector2::ZERO),
    pageStep_(1.0f)
{
    clipChildren_ = true;
    active_ = true;
    focusMode_ = FM_FOCUSABLE_DEFOCUSABLE;

    horizontalScrollBar_ = CreateChild<ScrollBar>();
    horizontalScrollBar_->SetInternal(true);
    horizontalScrollBar_->SetAlignment(HA_LEFT, VA_BOTTOM);
    horizontalScrollBar_->SetOrientation(O_HORIZONTAL);
    verticalScrollBar_ = CreateChild<ScrollBar>();
    verticalScrollBar_->SetInternal(true);
    verticalScrollBar_->SetAlignment(HA_RIGHT, VA_TOP);
    verticalScrollBar_->SetOrientation(O_VERTICAL);
    scrollPanel_ = CreateChild<BorderImage>();
    scrollPanel_->SetInternal(true);
    scrollPanel_->SetActive(true);
    scrollPanel_->SetClipChildren(true);
    scrollPanel_->SetPriority(-1);

    SubscribeToEvent(horizontalScrollBar_, E_SCROLLBARCHANGED, HANDLER(ScrollView, HandleScrollBarChanged));
    SubscribeToEvent(horizontalScrollBar_, E_VISIBLECHANGED, HANDLER(ScrollView, HandleScrollBarVisibleChanged));
    SubscribeToEvent(verticalScrollBar_, E_SCROLLBARCHANGED, HANDLER(ScrollView, HandleScrollBarChanged));
    SubscribeToEvent(verticalScrollBar_, E_VISIBLECHANGED, HANDLER(ScrollView, HandleScrollBarVisibleChanged));
}

ScrollView::~ScrollView()
{
}

void ScrollView::RegisterObject(Context* context)
{
    context->RegisterFactory<ScrollView>();

    REF_ACCESSOR_ATTRIBUTE(ScrollView, VAR_INTVECTOR2, "View Position", GetViewPosition, SetViewPosition, IntVector2, IntVector2::ZERO, AM_FILE);
    ACCESSOR_ATTRIBUTE(ScrollView, VAR_FLOAT, "Scroll Step", GetScrollStep, SetScrollStep, float, 0.1f, AM_FILE);
    ACCESSOR_ATTRIBUTE(ScrollView, VAR_FLOAT, "Page Step", GetPageStep, SetPageStep, float, 1.0f, AM_FILE);
    COPY_BASE_ATTRIBUTES(ScrollView, UIElement);
}

void ScrollView::ApplyAttributes()
{
    UIElement::ApplyAttributes();

    // Set the scrollbar orientations again and perform size update now that the style is known
    horizontalScrollBar_->SetOrientation(O_HORIZONTAL);
    verticalScrollBar_->SetOrientation(O_VERTICAL);

    OnResize();
}

void ScrollView::OnWheel(int delta, int buttons, int qualifiers)
{
    if (delta > 0)
        verticalScrollBar_->StepBack();
    if (delta < 0)
        verticalScrollBar_->StepForward();
}

void ScrollView::OnKey(int key, int buttons, int qualifiers)
{
    switch (key)
    {
    case KEY_LEFT:
        if (horizontalScrollBar_->IsVisible())
        {
            if (qualifiers & QUAL_CTRL)
                horizontalScrollBar_->SetValue(0.0f);
            else
                horizontalScrollBar_->StepBack();
        }
        break;

    case KEY_RIGHT:
        if (horizontalScrollBar_->IsVisible())
        {
            if (qualifiers & QUAL_CTRL)
                horizontalScrollBar_->SetValue(horizontalScrollBar_->GetRange());
            else
                horizontalScrollBar_->StepForward();
        }
        break;

    case KEY_UP:
        if (verticalScrollBar_->IsVisible())
        {
            if (qualifiers & QUAL_CTRL)
                verticalScrollBar_->SetValue(0.0f);
            else
                verticalScrollBar_->StepBack();
        }
        break;

    case KEY_DOWN:
        if (verticalScrollBar_->IsVisible())
        {
            if (qualifiers & QUAL_CTRL)
                verticalScrollBar_->SetValue(verticalScrollBar_->GetRange());
            else
                verticalScrollBar_->StepForward();
        }
        break;

    case KEY_PAGEUP:
        if (verticalScrollBar_->IsVisible())
            verticalScrollBar_->ChangeValue(-pageStep_);
        break;

    case KEY_PAGEDOWN:
        if (verticalScrollBar_->IsVisible())
            verticalScrollBar_->ChangeValue(pageStep_);
        break;

    case KEY_HOME:
        if (verticalScrollBar_->IsVisible())
            verticalScrollBar_->SetValue(0.0f);
        break;

    case KEY_END:
        if (verticalScrollBar_->IsVisible())
            verticalScrollBar_->SetValue(verticalScrollBar_->GetRange());
        break;
    }
}

void ScrollView::OnResize()
{
    IntVector2 panelSize = GetSize();
    if (verticalScrollBar_->IsVisible())
        panelSize.x_ -= verticalScrollBar_->GetWidth();
    if (horizontalScrollBar_->IsVisible())
        panelSize.y_ -= horizontalScrollBar_->GetHeight();

    scrollPanel_->SetSize(panelSize);
    horizontalScrollBar_->SetWidth(scrollPanel_->GetWidth());
    verticalScrollBar_->SetHeight(scrollPanel_->GetHeight());

    UpdateViewSize();
}

void ScrollView::SetContentElement(UIElement* element)
{
    if (element == contentElement_)
        return;

    if (contentElement_)
    {
        scrollPanel_->RemoveChild(contentElement_);
        UnsubscribeFromEvent(contentElement_, E_RESIZED);
    }
    contentElement_ = element;
    if (contentElement_)
    {
        scrollPanel_->AddChild(contentElement_);
        SubscribeToEvent(contentElement_, E_RESIZED, HANDLER(ScrollView, HandleElementResized));
    }

    UpdateViewSize();
}

void ScrollView::SetViewPosition(const IntVector2& position)
{
    UpdateView(position);
    UpdateScrollBars();
}

void ScrollView::SetViewPosition(int x, int y)
{
    SetViewPosition(IntVector2(x, y));
}

void ScrollView::SetScrollBarsVisible(bool horizontal, bool vertical)
{
    horizontalScrollBar_->SetVisible(horizontal);
    verticalScrollBar_->SetVisible(vertical);
}

void ScrollView::SetScrollStep(float step)
{
    horizontalScrollBar_->SetScrollStep(step);
    verticalScrollBar_->SetScrollStep(step);
}

void ScrollView::SetPageStep(float step)
{
    pageStep_ = Max(step, 0.0f);
}

float ScrollView::GetScrollStep() const
{
    return horizontalScrollBar_->GetScrollStep();
}

void ScrollView::UpdateViewSize()
{
    IntVector2 size(IntVector2::ZERO);
    if (contentElement_)
        size = contentElement_->GetSize();
    IntRect panelBorder = scrollPanel_->GetClipBorder();

    viewSize_.x_ = Max(size.x_, scrollPanel_->GetWidth() - panelBorder.left_ - panelBorder.right_);
    viewSize_.y_ = Max(size.y_, scrollPanel_->GetHeight() - panelBorder.top_ - panelBorder.bottom_);
    UpdateView(viewPosition_);
    UpdateScrollBars();
}

void ScrollView::UpdateScrollBars()
{
    ignoreEvents_ = true;

    IntVector2 size = scrollPanel_->GetSize();
    IntRect panelBorder = scrollPanel_->GetClipBorder();
    size.x_ -= panelBorder.left_ + panelBorder.right_;
    size.y_ -= panelBorder.top_ + panelBorder.bottom_;

    if (horizontalScrollBar_ && size.x_ > 0 && viewSize_.x_ > 0)
    {
        horizontalScrollBar_->SetRange((float)viewSize_.x_ / (float)size.x_ - 1.0f);
        horizontalScrollBar_->SetValue((float)viewPosition_.x_ / (float)size.x_);
        horizontalScrollBar_->SetStepFactor(STEP_FACTOR / (float)size.x_);
    }
    if (verticalScrollBar_ && size.y_ > 0 && viewSize_.y_ > 0)
    {
        verticalScrollBar_->SetRange((float)viewSize_.y_ / (float)size.y_ - 1.0f);
        verticalScrollBar_->SetValue((float)viewPosition_.y_ / (float)size.y_);
        verticalScrollBar_->SetStepFactor(STEP_FACTOR / (float)size.y_);
    }

    ignoreEvents_ = false;
}

void ScrollView::UpdateView(const IntVector2& position)
{
    IntVector2 oldPosition = viewPosition_;
    IntRect panelBorder = scrollPanel_->GetClipBorder();
    IntVector2 panelSize(scrollPanel_->GetWidth() - panelBorder.left_ - panelBorder.right_, scrollPanel_->GetHeight() -
        panelBorder.top_ - panelBorder.bottom_);

    viewPosition_.x_ = Clamp(position.x_, 0, viewSize_.x_ - panelSize.x_);
    viewPosition_.y_ = Clamp(position.y_, 0, viewSize_.y_ - panelSize.y_);
    scrollPanel_->SetChildOffset(IntVector2(-viewPosition_.x_ + panelBorder.left_, -viewPosition_.y_ + panelBorder.top_));

    if (viewPosition_ != oldPosition)
    {
        using namespace ViewChanged;

        VariantMap eventData;
        eventData[P_ELEMENT] = (void*)this;
        eventData[P_X] = viewPosition_.x_;
        eventData[P_Y] = viewPosition_.y_;
        SendEvent(E_VIEWCHANGED, eventData);
    }
}

void ScrollView::HandleScrollBarChanged(StringHash eventType, VariantMap& eventData)
{
    IntVector2 size = scrollPanel_->GetSize();
    IntRect panelBorder = scrollPanel_->GetClipBorder();
    size.x_ -= panelBorder.left_ + panelBorder.right_;
    size.y_ -= panelBorder.top_ + panelBorder.bottom_;

    if (!ignoreEvents_)
    {
        UpdateView(IntVector2(
            (int)(horizontalScrollBar_->GetValue() * (float)size.x_),
            (int)(verticalScrollBar_->GetValue() * (float)size.y_)
        ));
    }
}

void ScrollView::HandleScrollBarVisibleChanged(StringHash eventType, VariantMap& eventData)
{
    // Need to recalculate panel size when scrollbar visibility changes
    OnResize();
}

void ScrollView::HandleElementResized(StringHash eventType, VariantMap& eventData)
{
    UpdateViewSize();
}

}
<|endoftext|>


<commit_before>#include <ros/ros.h>
#include <nav_msgs/Odometry.h>
#include <geometry_msgs/Twist.h>
#include <tf2_msgs/TFMessage.h>
#include <std_msgs/String.h>
#include <string>

#include <sys/mman.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <pthread.h>
#include <string.h>
#include <errno.h>

#include <time.h>

#include "drive_command.h"

/*
Inspect ros output on local machine for sanity-checking topics.
this is useful in the absence of being able to access ROS command-line tools
from the Beam.
*/

#define SHM_CMD 0
#define SHM_STAT 1
#define SLEEP_MILLISECONDS 250

void rostopic_list(int argc, char **argv)
{
    ros::init(argc, argv, "rostopic_list");
    printf("List of ROS Topic Available: \n");
    ros::master::V_TopicInfo ti;
    if(ros::master::getTopics(ti))
    {
        for(ros::master::V_TopicInfo::iterator it = ti.begin(); it != ti.end(); it++)
        {
            printf("%s\n", it->name.c_str());
        }
    }
}

/* cmd_vel singled out for subscription  (instead of odom, tf) because it's the one client-side input command.
Feel free to add support for /odom and /tf. Ideally, we can just have the build install the generic ros-tools
onto the beam, but given the limited local ROS capabilities we need on the Beam itself, checking the most
important statuses might be enough for now.
*/
void check_cmd_vel(const geometry_msgs::Twist::ConstPtr& msg)
{
    ROS_INFO("received cmd_vel:");
    ROS_INFO("   ang_vel: %f", msg->angular.z);
    ROS_INFO("   lin_vel: %f", msg->linear.x);
}

void subscribe_cmd_vel(int argc, char **argv)
{
    ros::init(argc, argv, "inspector");
    ros::NodeHandle node;
    ROS_INFO("Subscribing to /beam/cmd_vel topic...");

    ros::Subscriber cmd_vel_checker = node.subscribe("/beam/cmd_vel", 10, check_cmd_vel);

    ros::spin();
}

/*
 * Feel free to add more information to these printouts.
 */
void print_cmd(drive_command &cmd)
{
    printf("[CMD] {magic=%d, lin_vel=%d, ang_vel=%d, crc=%X}\n",
            cmd.magic, cmd.lin_vel, cmd.ang_vel, cmd.crc);

}

void print_stat(drive_status &stat)
{
    printf("[STAT] {magic=%d, encoder_1=%d, encoder_2=%d, crc=%X}\n",
            stat.magic, stat.encoder_1, stat.encoder_2, stat.crc);
}

/* poll the shared memory, and output whether it's currently a drive command (write)
   or a drive status command (read) */
void tail_shm(int shm_mode)
{
    struct drive_shm *shm;

    ROS_INFO("Polling shared memory on %s...", DRIVE_SHM_NAME);

    int fd = shm_open(DRIVE_SHM_NAME, O_RDWR, 0);

    if (fd < 0)
    {
        ROS_ERROR("shm_open: %s", strerror(errno));
        exit(EXIT_FAILURE);
    }

    shm = (struct drive_shm *)mmap(NULL, sizeof(*shm), PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);

    if (close(fd) < 0)
        ROS_WARN("close: %s", strerror(errno));

    if (shm == MAP_FAILED) {
        ROS_ERROR("mmap: %s", strerror(errno));
        exit(EXIT_FAILURE);
    }

    struct timespec tv;
    int sleep_nanoseconds = SLEEP_MILLISECONDS * 1000000;
    tv.tv_sec = 0;
    tv.tv_nsec = sleep_nanoseconds;

    while (true)
    {

        if (shm == NULL)
        {
            continue;
        }

        //we're doing ad-hoc read-only from shm, so forget about locks.
        if (shm_mode == SHM_CMD)
        {
            print_cmd(shm->cmd);
        }
        else if (shm_mode == SHM_STAT)
        {
            print_stat(shm->stat);
        }

        nanosleep(&tv, &tv);

    }
}

void print_usage()
{
    printf("Usage: inspector [ cmd_vel | list_topics | shm $LOCATION ] \n");
}

/* Two inspection modes: 1) rostopic debugging, 2) Shared Memory debugging
     * for shared memory, it is necessary to provide the
 */
int main(int argc, char **argv)
{
    if (argc < 2)
    {
        print_usage();
        exit(EXIT_SUCCESS);
    }

    std::string mode = argv[1];

    if (mode == "--usage" || mode == "--help")
    {
        printf("Usage: inspector [ cmd_vel | list_topics | shm [cmd | stat]] \n");
        //printf("    * cmd_vel - echo velocity data on /cmd_vel topic \n");
        //printf("    * list_topics - see all ROS topics on beam\n");
        //printf("    * shm [ cmd | stat ] - inspect shared memory, either for drive command (cmd) or status (stat)\n");
        exit(EXIT_SUCCESS);
    }
    else if (mode == "cmd_vel")
    {
        subscribe_cmd_vel(argc, argv);
    }
    else if (mode == "list_topics")
    {
        rostopic_list(argc, argv);
    }
    else if (mode == "shm")
    {
        if (argc != 3)
        {
            printf(" shm example: 'inspector shm cmd'\n");
            print_usage();
            exit(EXIT_SUCCESS);
        }

        std::string shm_mode = argv[2];

        printf("about to tail shm\n");
        if (shm_mode == "cmd")
        {
            tail_shm(SHM_CMD);
        }
        else if (shm_mode == "stat")
        {
            tail_shm(SHM_STAT);
        }
        else
        {
            printf(" error - shm arg must be either 'cmd' or 'stat'\n");
            print_usage();
            exit(EXIT_SUCCESS);
        }
    }
    else
    {
        print_usage();
    }

    return 0;
}
<commit_msg>Cleaning unnecessarily lines.<commit_after>#include <ros/ros.h>
#include <nav_msgs/Odometry.h>
#include <geometry_msgs/Twist.h>
#include <tf2_msgs/TFMessage.h>
#include <std_msgs/String.h>
#include <string>

#include <sys/mman.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <pthread.h>
#include <string.h>
#include <errno.h>

#include <time.h>

#include "drive_command.h"

/*
Inspect ros output on local machine for sanity-checking topics.
this is useful in the absence of being able to access ROS command-line tools
from the Beam.
*/

#define SHM_CMD 0
#define SHM_STAT 1
#define SLEEP_MILLISECONDS 250

void rostopic_list(int argc, char **argv)
{
    ros::init(argc, argv, "rostopic_list");
    printf("List of ROS Topic Available: \n");
    ros::master::V_TopicInfo ti;
    if(ros::master::getTopics(ti))
    {
        for(ros::master::V_TopicInfo::iterator it = ti.begin(); it != ti.end(); it++)
        {
            printf("%s\n", it->name.c_str());
        }
    }
}

/* cmd_vel singled out for subscription  (instead of odom, tf) because it's the one client-side input command.
Feel free to add support for /odom and /tf. Ideally, we can just have the build install the generic ros-tools
onto the beam, but given the limited local ROS capabilities we need on the Beam itself, checking the most
important statuses might be enough for now.
*/
void check_cmd_vel(const geometry_msgs::Twist::ConstPtr& msg)
{
    ROS_INFO("received cmd_vel:");
    ROS_INFO("   ang_vel: %f", msg->angular.z);
    ROS_INFO("   lin_vel: %f", msg->linear.x);
}

void subscribe_cmd_vel(int argc, char **argv)
{
    ros::init(argc, argv, "inspector");
    ros::NodeHandle node;
    ROS_INFO("Subscribing to /beam/cmd_vel topic...");

    ros::Subscriber cmd_vel_checker = node.subscribe("/beam/cmd_vel", 10, check_cmd_vel);

    ros::spin();
}

/*
 * Feel free to add more information to these printouts.
 */
void print_cmd(drive_command &cmd)
{
    printf("[CMD] {magic=%d, lin_vel=%d, ang_vel=%d, crc=%X}\n",
            cmd.magic, cmd.lin_vel, cmd.ang_vel, cmd.crc);

}

void print_stat(drive_status &stat)
{
    printf("[STAT] {magic=%d, encoder_1=%d, encoder_2=%d, crc=%X}\n",
            stat.magic, stat.encoder_1, stat.encoder_2, stat.crc);
}

/* poll the shared memory, and output whether it's currently a drive command (write)
   or a drive status command (read) */
void tail_shm(int shm_mode)
{
    struct drive_shm *shm;

    ROS_INFO("Polling shared memory on %s...", DRIVE_SHM_NAME);

    int fd = shm_open(DRIVE_SHM_NAME, O_RDWR, 0);

    if (fd < 0)
    {
        ROS_ERROR("shm_open: %s", strerror(errno));
        exit(EXIT_FAILURE);
    }

    shm = (struct drive_shm *)mmap(NULL, sizeof(*shm), PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);

    if (close(fd) < 0)
        ROS_WARN("close: %s", strerror(errno));

    if (shm == MAP_FAILED) {
        ROS_ERROR("mmap: %s", strerror(errno));
        exit(EXIT_FAILURE);
    }

    struct timespec tv;
    int sleep_nanoseconds = SLEEP_MILLISECONDS * 1000000;
    tv.tv_sec = 0;
    tv.tv_nsec = sleep_nanoseconds;

    while (true)
    {

        if (shm == NULL)
        {
            continue;
        }

        //we're doing ad-hoc read-only from shm, so forget about locks.
        if (shm_mode == SHM_CMD)
        {
            print_cmd(shm->cmd);
        }
        else if (shm_mode == SHM_STAT)
        {
            print_stat(shm->stat);
        }

        nanosleep(&tv, &tv);

    }
}

void print_usage()
{
    printf("Usage: inspector [ cmd_vel | list_topics | shm $LOCATION ] \n");
}

int main(int argc, char **argv)
{
    if (argc < 2)
    {
        print_usage();
        exit(EXIT_SUCCESS);
    }

    std::string mode = argv[1];

    if (mode == "--usage" || mode == "--help")
    {
        printf("Usage: inspector [ cmd_vel | list_topics | shm [cmd | stat]] \n");
        exit(EXIT_SUCCESS);
    }
    else if (mode == "cmd_vel")
    {
        subscribe_cmd_vel(argc, argv);
    }
    else if (mode == "list_topics")
    {
        rostopic_list(argc, argv);
    }
    else if (mode == "shm")
    {
        if (argc != 3)
        {
            printf(" shm example: 'inspector shm cmd'\n");
            print_usage();
            exit(EXIT_SUCCESS);
        }

        std::string shm_mode = argv[2];

        printf("about to tail shm\n");
        if (shm_mode == "cmd")
        {
            tail_shm(SHM_CMD);
        }
        else if (shm_mode == "stat")
        {
            tail_shm(SHM_STAT);
        }
        else
        {
            printf(" error - shm arg must be either 'cmd' or 'stat'\n");
            print_usage();
            exit(EXIT_SUCCESS);
        }
    }
    else
    {
        print_usage();
    }

    return 0;
}
<|endoftext|>


<commit_before>/*
 * File:   activationFunctions.cpp
 * Author: janvojt
 *
 * Created on July 1, 2014, 10:20 PM
 */

#include "activationFunctions.h"

#include <math.h>

void sigmoidFunction(double *inputPtr, double *targetPtr, int layerSize) {
    for (int i = 0; i < layerSize; i++) {
        *targetPtr = 1 / (1 + exp(-*inputPtr));
        inputPtr++;
        targetPtr++;
    }
}

void dSigmoidFunction(double* inputPtr, double* targetPtr, int layerSize) {
    for (int i = 0; i < layerSize; i++) {
        *targetPtr = exp(*inputPtr) / pow(1 + exp(*inputPtr), 2);
        inputPtr++;
        targetPtr++;
    }
}

void gSigmoidFunction(double* inputPtr, double* targetPtr, int layerSize) {
    for (int i = 0; i < layerSize; i++) {
        *targetPtr = *inputPtr * (1 - *inputPtr);
        inputPtr++;
        targetPtr++;
    }
}

void identityFunction(double *inputPtr, double *targetPtr, int layerSize) {
    for (int i = 0; i < layerSize; i++) {
        *targetPtr = *inputPtr;
        inputPtr++;
        targetPtr++;
    }
}

void dIdentityFunction(double* inputPtr, double* targetPtr, int layerSize) {
    for (int i = 0; i < layerSize; i++) {
        *targetPtr = 1;
        inputPtr++;
        targetPtr++;
    }
}

void hyperbolicTangentFunction(double* inputPtr, double* targetPtr, int layerSize) {
    for (int i = 0; i < layerSize; i++) {
        double ex = exp(2 * *inputPtr);
        *targetPtr = (ex - 1) / (ex + 1);
        inputPtr++;
        targetPtr++;
    }
}

void dHyperbolicTangentFunction(double* inputPtr, double* targetPtr, int layerSize) {
    for (int i = 0; i < layerSize; i++) {
        *targetPtr = 4 / pow(exp(*inputPtr) - exp(-*inputPtr), 2);
        inputPtr++;
        targetPtr++;
    }
}
<commit_msg>Fixed hyperbolic tangent function.<commit_after>/*
 * File:   activationFunctions.cpp
 * Author: janvojt
 *
 * Created on July 1, 2014, 10:20 PM
 */

#include "activationFunctions.h"

#include <math.h>

void sigmoidFunction(double *inputPtr, double *targetPtr, int layerSize) {
    for (int i = 0; i < layerSize; i++) {
        *targetPtr = 1 / (1 + exp(-*inputPtr));
        inputPtr++;
        targetPtr++;
    }
}

void dSigmoidFunction(double* inputPtr, double* targetPtr, int layerSize) {
    for (int i = 0; i < layerSize; i++) {
        *targetPtr = exp(*inputPtr) / pow(1 + exp(*inputPtr), 2);
        inputPtr++;
        targetPtr++;
    }
}

void gSigmoidFunction(double* inputPtr, double* targetPtr, int layerSize) {
    for (int i = 0; i < layerSize; i++) {
        *targetPtr = *inputPtr * (1 - *inputPtr);
        inputPtr++;
        targetPtr++;
    }
}

void identityFunction(double *inputPtr, double *targetPtr, int layerSize) {
    for (int i = 0; i < layerSize; i++) {
        *targetPtr = *inputPtr;
        inputPtr++;
        targetPtr++;
    }
}

void dIdentityFunction(double* inputPtr, double* targetPtr, int layerSize) {
    for (int i = 0; i < layerSize; i++) {
        *targetPtr = 1;
        inputPtr++;
        targetPtr++;
    }
}

void hyperbolicTangentFunction(double* inputPtr, double* targetPtr, int layerSize) {
    for (int i = 0; i < layerSize; i++) {
        *targetPtr = tanh(*inputPtr);
        inputPtr++;
        targetPtr++;
    }
}

void dHyperbolicTangentFunction(double* inputPtr, double* targetPtr, int layerSize) {
    for (int i = 0; i < layerSize; i++) {
        *targetPtr = 1 - (*inputPtr * *inputPtr);
        inputPtr++;
        targetPtr++;
    }
}
<|endoftext|>


<commit_before>////////////////////////////////////////////////////////////////////////////////
/// @brief simple http client
///
/// @file
///
/// DISCLAIMER
///
/// Copyright 2010-2011 triagens GmbH, Cologne, Germany
///
/// Licensed under the Apache License, Version 2.0 (the "License");
/// you may not use this file except in compliance with the License.
/// You may obtain a copy of the License at
///
///     http://www.apache.org/licenses/LICENSE-2.0
///
/// Unless required by applicable law or agreed to in writing, software
/// distributed under the License is distributed on an "AS IS" BASIS,
/// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
/// See the License for the specific language governing permissions and
/// limitations under the License.
///
/// Copyright holder is triAGENS GmbH, Cologne, Germany
///
/// @author Dr. Frank Celler
/// @author Achim Brandt
/// @author Copyright 2009, triagens GmbH, Cologne, Germany
////////////////////////////////////////////////////////////////////////////////

#include "SimpleHttpClient.h"

#include <stdio.h>
#include <string>
#include <errno.h>

#include "Basics/StringUtils.h"
#include "Logger/Logger.h"

#include "GeneralClientConnection.h"
#include "SimpleHttpResult.h"

using namespace triagens::basics;
using namespace triagens::rest;
using namespace std;

namespace triagens {
  namespace httpclient {

    // -----------------------------------------------------------------------------
    // constructors and destructors
    // -----------------------------------------------------------------------------

    SimpleHttpClient::SimpleHttpClient (GeneralClientConnection* connection, double requestTimeout, bool warn) :
      SimpleClient(connection, requestTimeout, warn), _result(0), _maxPacketSize(64 * 1024 * 1024) {
    }

    SimpleHttpClient::~SimpleHttpClient () {
    }

    // -----------------------------------------------------------------------------
    // public methods
    // -----------------------------------------------------------------------------

    SimpleHttpResult* SimpleHttpClient::request (rest::HttpRequest::HttpRequestType method,
            const string& location,
            const char* body,
            size_t bodyLength,
            const map<string, string>& headerFields) {

      assert(_result == 0);

      _result = new SimpleHttpResult;
      _errorMessage = "";

      // set body to all connections
      setRequest(method, location, body, bodyLength, headerFields);

      double endTime = now() + _requestTimeout;
      double remainingTime = _requestTimeout;

      while (isWorking() && remainingTime > 0.0) {
        switch (_state) {
          case (IN_CONNECT): {
            handleConnect();
            break;
          }

          case (IN_WRITE): {
            size_t bytesWritten = 0;

            if (! _connection->handleWrite(remainingTime, (void*) (_writeBuffer.c_str() + _written), _writeBuffer.length() - _written, &bytesWritten)) {
              setErrorMessage("::send() failed", errno);
              close();
            }
            else {
              _written += bytesWritten;
              if (_written == _writeBuffer.length())  {
                _state = IN_READ_HEADER;
              }
            }
            break;
          }

          case (IN_READ_HEADER):
          case (IN_READ_BODY):
          case (IN_READ_CHUNKED_HEADER):
          case (IN_READ_CHUNKED_BODY): {
            if (_connection->handleRead(remainingTime, _readBuffer)) {
              switch (_state) {
                case (IN_READ_HEADER):
                  readHeader();
                  break;
                case (IN_READ_BODY):
                  readBody();
                  break;
                case (IN_READ_CHUNKED_HEADER):
                  readChunkedHeader();
                  break;
                case (IN_READ_CHUNKED_BODY):
                  readChunkedBody();
                  break;
                default:
                  break;
              }
            }
            else {
              setErrorMessage("gesockopt() failed", errno);
              close();
            }
            break;
          }
          default:
            break;
        }

        remainingTime = endTime - now();
      }

      if (isWorking() && _errorMessage == "" ) {
        setErrorMessage("Request timeout reached");
      }

      // set result type in getResult()
      SimpleHttpResult* result = getResult();

      _result = 0;

      return result;
    }

    // -----------------------------------------------------------------------------
    // private methods
    // -----------------------------------------------------------------------------

    void SimpleHttpClient::reset () {
      SimpleClient::reset();
      if (_result) {
        _result->clear();
      }
    }

    ////////////////////////////////////////////////////////////////////////////////
    /// @brief sets username and password
    ////////////////////////////////////////////////////////////////////////////////

    void SimpleHttpClient::setUserNamePassword (
            const string& prefix,
            const string& username,
            const string& password) {

      string value = triagens::basics::StringUtils::encodeBase64(username + ":" + password);

      _pathToBasicAuth.push_back(make_pair(prefix, value));
    }

    SimpleHttpResult* SimpleHttpClient::getResult () {
      switch (_state) {
        case (IN_CONNECT):
          _result->setResultType(SimpleHttpResult::COULD_NOT_CONNECT);
          break;

        case (IN_WRITE):
          _result->setResultType(SimpleHttpResult::WRITE_ERROR);
          break;

        case (IN_READ_HEADER):
        case (IN_READ_BODY):
        case (IN_READ_CHUNKED_HEADER):
        case (IN_READ_CHUNKED_BODY):
          _result->setResultType(SimpleHttpResult::READ_ERROR);
          break;

        case (FINISHED):
          _result->setResultType(SimpleHttpResult::COMPLETE);
          break;

        default :
          _result->setResultType(SimpleHttpResult::COULD_NOT_CONNECT);
      }

      return _result;
    }

    void SimpleHttpClient::setRequest (rest::HttpRequest::HttpRequestType method,
            const string& location,
            const char* body,
            size_t bodyLength,
            const map<string, string>& headerFields) {

      if (_state == DEAD) {
        _connection->resetNumConnectRetries();
      }

      ///////////////////// fill the write buffer //////////////////////////////
      _writeBuffer.clear();

      HttpRequest::appendMethod(method, &_writeBuffer);

      string l = location;
      if (location.length() == 0 || location[0] != '/') {
        l = "/" + location;
      }

      _writeBuffer.appendText(l);
      _writeBuffer.appendText(" HTTP/1.1\r\n");

      _writeBuffer.appendText("Host: ");
      _writeBuffer.appendText(_connection->getEndpoint()->getHostString());
      _writeBuffer.appendText("\r\n");
      _writeBuffer.appendText("Connection: Keep-Alive\r\n");
      _writeBuffer.appendText("User-Agent: VOC-Client/1.0\r\n");

      // do basic authorization
      if (_pathToBasicAuth.size() > 0) {
        string foundPrefix;
        string foundValue;
        std::vector< std::pair<std::string, std::string> >::iterator i = _pathToBasicAuth.begin();
        for (; i != _pathToBasicAuth.end(); ++i) {
          string f = i->first;
          if (l.find(f) == 0) {
            // f is prefix of l
            if (f.length() > foundPrefix.length()) {
              foundPrefix = f;
              foundValue = i->second;
            }
          }
        }
        if (foundValue.length() > 0) {
          _writeBuffer.appendText("Authorization: Basic ");
          _writeBuffer.appendText(foundValue);
          _writeBuffer.appendText("\r\n");
        }
      }

      for (map<string, string>::const_iterator i = headerFields.begin(); i != headerFields.end(); ++i) {
        // TODO: check Header name and value
        _writeBuffer.appendText(i->first);
        _writeBuffer.appendText(": ");
        _writeBuffer.appendText(i->second);
        _writeBuffer.appendText("\r\n");
      }

      _writeBuffer.appendText("Content-Length: ");
      _writeBuffer.appendInteger(bodyLength);
      _writeBuffer.appendText("\r\n\r\n");
      _writeBuffer.appendText(body, bodyLength);

      LOGGER_TRACE << "Request: " << _writeBuffer.c_str();

      //////////////////////////////////////////////////////////////////////////

      if (_state != FINISHED) {
        // close connection to reset all read and write buffers
        close();
      }

      if (_connection->isConnected()) {
        // we are connected, start with writing
        _state = IN_WRITE;
        _written = 0;
      }
      else {
        // connect to server
        _state = IN_CONNECT;
      }
    }

    // -----------------------------------------------------------------------------
    // private methods
    // -----------------------------------------------------------------------------

    bool SimpleHttpClient::readHeader () {
      char* pos = (char*) memchr(_readBuffer.c_str(), '\n', _readBuffer.length());

      while (pos) {
        // size_t is unsigned, should never get < 0
        assert(pos >= _readBuffer.c_str());

        size_t len = pos - _readBuffer.c_str();
        string line(_readBuffer.c_str(), len);
        _readBuffer.erase_front(len + 1);

        //printf("found header line %s\n", line.c_str());

        if (line == "\r" || line == "") {
          // end of header found
          if (_result->isChunked()) {
            _state = IN_READ_CHUNKED_HEADER;
            return readChunkedHeader();
          }
          else if (_result->getContentLength()) {

            if (_result->getContentLength() > _maxPacketSize) {
              setErrorMessage("Content-Length > max packet size found", true);

              // reset connection
              close();

              return false;
            }

            _state = IN_READ_BODY;
            return readBody();
          }
          else {
            _result->setResultType(SimpleHttpResult::COMPLETE);
            _state = FINISHED;
          }
          break;
        }
        else {
          _result->addHeaderField(line);
        }

        pos = (char*) memchr(_readBuffer.c_str(), '\n', _readBuffer.length());
      }
      return true;
    }

    bool SimpleHttpClient::readBody () {
      if (_readBuffer.length() >= _result->getContentLength()) {
        _result->getBody().write(_readBuffer.c_str(), _result->getContentLength());
        _readBuffer.erase_front(_result->getContentLength());
        _result->setResultType(SimpleHttpResult::COMPLETE);
        _state = FINISHED;
      }

      return true;
    }

    bool SimpleHttpClient::readChunkedHeader () {
      char* pos = (char*) memchr(_readBuffer.c_str(), '\n', _readBuffer.length());

      while (pos) {
        // got a line
        size_t len = pos - _readBuffer.c_str();
        string line(_readBuffer.c_str(), len);
        _readBuffer.erase_front(len + 1);

        string trimmed = StringUtils::trim(line);

        if (trimmed == "\r" || trimmed == "") {
          // ignore empty lines
          pos = (char*) memchr(_readBuffer.c_str(), '\n', _readBuffer.length());
          continue;
        }

        uint32_t contentLength;
        sscanf(trimmed.c_str(), "%x", &contentLength);

        if (contentLength == 0) {
          // OK: last content length found

          _result->setResultType(SimpleHttpResult::COMPLETE);

          _state = FINISHED;

          return true;
        }

        if (contentLength > _maxPacketSize) {
          // failed: too many bytes

          setErrorMessage("Content-Length > max packet size found!", true);

          // reset connection
          close();

          return false;
        }

        _state = IN_READ_CHUNKED_BODY;
        _nextChunkedSize = contentLength;

        return readChunkedBody();
      }

      return true;
    }

    bool SimpleHttpClient::readChunkedBody () {

      if (_readBuffer.length() >= _nextChunkedSize) {

        _result->getBody().write(_readBuffer.c_str(), (size_t) _nextChunkedSize);
        _readBuffer.erase_front((size_t) _nextChunkedSize);
        _state = IN_READ_CHUNKED_HEADER;
        return readChunkedHeader();
      }

      return true;
    }

  }

}
<commit_msg>do not send a content-length header on GET/HEAD/DELETE requests<commit_after>////////////////////////////////////////////////////////////////////////////////
/// @brief simple http client
///
/// @file
///
/// DISCLAIMER
///
/// Copyright 2010-2011 triagens GmbH, Cologne, Germany
///
/// Licensed under the Apache License, Version 2.0 (the "License");
/// you may not use this file except in compliance with the License.
/// You may obtain a copy of the License at
///
///     http://www.apache.org/licenses/LICENSE-2.0
///
/// Unless required by applicable law or agreed to in writing, software
/// distributed under the License is distributed on an "AS IS" BASIS,
/// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
/// See the License for the specific language governing permissions and
/// limitations under the License.
///
/// Copyright holder is triAGENS GmbH, Cologne, Germany
///
/// @author Dr. Frank Celler
/// @author Achim Brandt
/// @author Copyright 2009, triagens GmbH, Cologne, Germany
////////////////////////////////////////////////////////////////////////////////

#include "SimpleHttpClient.h"

#include <stdio.h>
#include <string>
#include <errno.h>

#include "Basics/StringUtils.h"
#include "Logger/Logger.h"

#include "GeneralClientConnection.h"
#include "SimpleHttpResult.h"

using namespace triagens::basics;
using namespace triagens::rest;
using namespace std;

namespace triagens {
  namespace httpclient {

    // -----------------------------------------------------------------------------
    // constructors and destructors
    // -----------------------------------------------------------------------------

    SimpleHttpClient::SimpleHttpClient (GeneralClientConnection* connection, double requestTimeout, bool warn) :
      SimpleClient(connection, requestTimeout, warn), _result(0), _maxPacketSize(64 * 1024 * 1024) {
    }

    SimpleHttpClient::~SimpleHttpClient () {
    }

    // -----------------------------------------------------------------------------
    // public methods
    // -----------------------------------------------------------------------------

    SimpleHttpResult* SimpleHttpClient::request (rest::HttpRequest::HttpRequestType method,
            const string& location,
            const char* body,
            size_t bodyLength,
            const map<string, string>& headerFields) {

      assert(_result == 0);

      _result = new SimpleHttpResult;
      _errorMessage = "";

      // set body to all connections
      setRequest(method, location, body, bodyLength, headerFields);

      double endTime = now() + _requestTimeout;
      double remainingTime = _requestTimeout;

      while (isWorking() && remainingTime > 0.0) {
        switch (_state) {
          case (IN_CONNECT): {
            handleConnect();
            break;
          }

          case (IN_WRITE): {
            size_t bytesWritten = 0;

            if (! _connection->handleWrite(remainingTime, (void*) (_writeBuffer.c_str() + _written), _writeBuffer.length() - _written, &bytesWritten)) {
              setErrorMessage("::send() failed", errno);
              close();
            }
            else {
              _written += bytesWritten;
              if (_written == _writeBuffer.length())  {
                _state = IN_READ_HEADER;
              }
            }
            break;
          }

          case (IN_READ_HEADER):
          case (IN_READ_BODY):
          case (IN_READ_CHUNKED_HEADER):
          case (IN_READ_CHUNKED_BODY): {
            if (_connection->handleRead(remainingTime, _readBuffer)) {
              switch (_state) {
                case (IN_READ_HEADER):
                  readHeader();
                  break;
                case (IN_READ_BODY):
                  readBody();
                  break;
                case (IN_READ_CHUNKED_HEADER):
                  readChunkedHeader();
                  break;
                case (IN_READ_CHUNKED_BODY):
                  readChunkedBody();
                  break;
                default:
                  break;
              }
            }
            else {
              setErrorMessage("gesockopt() failed", errno);
              close();
            }
            break;
          }
          default:
            break;
        }

        remainingTime = endTime - now();
      }

      if (isWorking() && _errorMessage == "" ) {
        setErrorMessage("Request timeout reached");
      }

      // set result type in getResult()
      SimpleHttpResult* result = getResult();

      _result = 0;

      return result;
    }

    // -----------------------------------------------------------------------------
    // private methods
    // -----------------------------------------------------------------------------

    void SimpleHttpClient::reset () {
      SimpleClient::reset();
      if (_result) {
        _result->clear();
      }
    }

    ////////////////////////////////////////////////////////////////////////////////
    /// @brief sets username and password
    ////////////////////////////////////////////////////////////////////////////////

    void SimpleHttpClient::setUserNamePassword (
            const string& prefix,
            const string& username,
            const string& password) {

      string value = triagens::basics::StringUtils::encodeBase64(username + ":" + password);

      _pathToBasicAuth.push_back(make_pair(prefix, value));
    }

    SimpleHttpResult* SimpleHttpClient::getResult () {
      switch (_state) {
        case (IN_CONNECT):
          _result->setResultType(SimpleHttpResult::COULD_NOT_CONNECT);
          break;

        case (IN_WRITE):
          _result->setResultType(SimpleHttpResult::WRITE_ERROR);
          break;

        case (IN_READ_HEADER):
        case (IN_READ_BODY):
        case (IN_READ_CHUNKED_HEADER):
        case (IN_READ_CHUNKED_BODY):
          _result->setResultType(SimpleHttpResult::READ_ERROR);
          break;

        case (FINISHED):
          _result->setResultType(SimpleHttpResult::COMPLETE);
          break;

        default :
          _result->setResultType(SimpleHttpResult::COULD_NOT_CONNECT);
      }

      return _result;
    }

    void SimpleHttpClient::setRequest (rest::HttpRequest::HttpRequestType method,
            const string& location,
            const char* body,
            size_t bodyLength,
            const map<string, string>& headerFields) {

      if (_state == DEAD) {
        _connection->resetNumConnectRetries();
      }

      ///////////////////// fill the write buffer //////////////////////////////
      _writeBuffer.clear();

      HttpRequest::appendMethod(method, &_writeBuffer);

      string l = location;
      if (location.length() == 0 || location[0] != '/') {
        l = "/" + location;
      }

      _writeBuffer.appendText(l);
      _writeBuffer.appendText(" HTTP/1.1\r\n");

      _writeBuffer.appendText("Host: ");
      _writeBuffer.appendText(_connection->getEndpoint()->getHostString());
      _writeBuffer.appendText("\r\n");
      _writeBuffer.appendText("Connection: Keep-Alive\r\n");
      _writeBuffer.appendText("User-Agent: VOC-Client/1.0\r\n");

      // do basic authorization
      if (_pathToBasicAuth.size() > 0) {
        string foundPrefix;
        string foundValue;
        std::vector< std::pair<std::string, std::string> >::iterator i = _pathToBasicAuth.begin();
        for (; i != _pathToBasicAuth.end(); ++i) {
          string f = i->first;
          if (l.find(f) == 0) {
            // f is prefix of l
            if (f.length() > foundPrefix.length()) {
              foundPrefix = f;
              foundValue = i->second;
            }
          }
        }
        if (foundValue.length() > 0) {
          _writeBuffer.appendText("Authorization: Basic ");
          _writeBuffer.appendText(foundValue);
          _writeBuffer.appendText("\r\n");
        }
      }

      for (map<string, string>::const_iterator i = headerFields.begin(); i != headerFields.end(); ++i) {
        // TODO: check Header name and value
        _writeBuffer.appendText(i->first);
        _writeBuffer.appendText(": ");
        _writeBuffer.appendText(i->second);
        _writeBuffer.appendText("\r\n");
      }

      if (method == HttpRequest::HTTP_REQUEST_GET ||
          method == HttpRequest::HTTP_REQUEST_HEAD ||
          method == HttpRequest::HTTP_REQUEST_DELETE) {
        // don't use a content-length for these request types
        _writeBuffer.appendText("\r\n");
      }
      else {
        // use a content-length for these request types
        _writeBuffer.appendText("Content-Length: ");
        _writeBuffer.appendInteger(bodyLength);
        _writeBuffer.appendText("\r\n\r\n");
      }

      _writeBuffer.appendText(body, bodyLength);

      LOGGER_TRACE << "Request: " << _writeBuffer.c_str();

      //////////////////////////////////////////////////////////////////////////

      if (_state != FINISHED) {
        // close connection to reset all read and write buffers
        close();
      }

      if (_connection->isConnected()) {
        // we are connected, start with writing
        _state = IN_WRITE;
        _written = 0;
      }
      else {
        // connect to server
        _state = IN_CONNECT;
      }
    }

    // -----------------------------------------------------------------------------
    // private methods
    // -----------------------------------------------------------------------------

    bool SimpleHttpClient::readHeader () {
      char* pos = (char*) memchr(_readBuffer.c_str(), '\n', _readBuffer.length());

      while (pos) {
        // size_t is unsigned, should never get < 0
        assert(pos >= _readBuffer.c_str());

        size_t len = pos - _readBuffer.c_str();
        string line(_readBuffer.c_str(), len);
        _readBuffer.erase_front(len + 1);

        //printf("found header line %s\n", line.c_str());

        if (line == "\r" || line == "") {
          // end of header found
          if (_result->isChunked()) {
            _state = IN_READ_CHUNKED_HEADER;
            return readChunkedHeader();
          }
          else if (_result->getContentLength()) {

            if (_result->getContentLength() > _maxPacketSize) {
              setErrorMessage("Content-Length > max packet size found", true);

              // reset connection
              close();

              return false;
            }

            _state = IN_READ_BODY;
            return readBody();
          }
          else {
            _result->setResultType(SimpleHttpResult::COMPLETE);
            _state = FINISHED;
          }
          break;
        }
        else {
          _result->addHeaderField(line);
        }

        pos = (char*) memchr(_readBuffer.c_str(), '\n', _readBuffer.length());
      }
      return true;
    }

    bool SimpleHttpClient::readBody () {
      if (_readBuffer.length() >= _result->getContentLength()) {
        _result->getBody().write(_readBuffer.c_str(), _result->getContentLength());
        _readBuffer.erase_front(_result->getContentLength());
        _result->setResultType(SimpleHttpResult::COMPLETE);
        _state = FINISHED;
      }

      return true;
    }

    bool SimpleHttpClient::readChunkedHeader () {
      char* pos = (char*) memchr(_readBuffer.c_str(), '\n', _readBuffer.length());

      while (pos) {
        // got a line
        size_t len = pos - _readBuffer.c_str();
        string line(_readBuffer.c_str(), len);
        _readBuffer.erase_front(len + 1);

        string trimmed = StringUtils::trim(line);

        if (trimmed == "\r" || trimmed == "") {
          // ignore empty lines
          pos = (char*) memchr(_readBuffer.c_str(), '\n', _readBuffer.length());
          continue;
        }

        uint32_t contentLength;
        sscanf(trimmed.c_str(), "%x", &contentLength);

        if (contentLength == 0) {
          // OK: last content length found

          _result->setResultType(SimpleHttpResult::COMPLETE);

          _state = FINISHED;

          return true;
        }

        if (contentLength > _maxPacketSize) {
          // failed: too many bytes

          setErrorMessage("Content-Length > max packet size found!", true);

          // reset connection
          close();

          return false;
        }

        _state = IN_READ_CHUNKED_BODY;
        _nextChunkedSize = contentLength;

        return readChunkedBody();
      }

      return true;
    }

    bool SimpleHttpClient::readChunkedBody () {

      if (_readBuffer.length() >= _nextChunkedSize) {

        _result->getBody().write(_readBuffer.c_str(), (size_t) _nextChunkedSize);
        _readBuffer.erase_front((size_t) _nextChunkedSize);
        _state = IN_READ_CHUNKED_HEADER;
        return readChunkedHeader();
      }

      return true;
    }

  }

}
<|endoftext|>


<commit_before>/*
** Author(s):
**  - Herve Cuche <hcuche@aldebaran-robotics.com>
**
** Copyright (C) 2012 Aldebaran Robotics
*/

#include <iostream>
#include "src/transport_socket_p.hpp"

namespace qi
{
  TransportSocketPrivate::TransportSocketPrivate(TransportSocket *socket)
    : tcd(NULL)
    , connected(false)
    , status(0)
    , readHdr(true)
    , msg(0)
    , self(socket)
  {
  }

  TransportSocketPrivate::~TransportSocketPrivate()
  {
  }

// if msecs < 0 no timeout
  bool TransportSocketPrivate::waitForConnected(int msecs)
  {
    // no timeout
    if (msecs < 0)
    {
      while (!isConnected() && status == 0)
        ;
      return true;
    }

    while ((!isConnected() && status == 0) && msecs > 0)
    {
      qi::os::msleep(1);
      msecs--;
    }
    return isConnected();
  }

  bool TransportSocketPrivate::waitForDisconnected(int msecs)
  {
    // no timeout
    if (msecs < 0)
    {
      while (isConnected())
        ;
      return true;
    }

    while (isConnected() && msecs > 0)
    {
      qi::os::msleep(1);
      msecs--;
    }

    return !isConnected();
  }

  bool TransportSocketPrivate::waitForId(int id, int msecs)
  {
    if (!isConnected())
    {
      qiLogError("qimessaging.TransportSocket") << "socket is not connected.";
      return false;
    }

    std::map<unsigned int, qi::Message*>::iterator it;
    {
      {
        boost::mutex::scoped_lock l(mtx);
        it = msgSend.find(id);
        if (it != msgSend.end())
          return true;
        if (!isConnected())
          return false;
        if (msecs > 0)
          cond.timed_wait(l, boost::posix_time::milliseconds(msecs));
        else
          cond.wait(l);
        it = msgSend.find(id);
        if (it != msgSend.end())
          return true;
      }
    }
    return false;
  }

  bool TransportSocketPrivate::read(int id, qi::Message *msg)
  {
    if (!isConnected())
    {
      qiLogError("qimessaging.TransportSocket") << "socket is not connected.";
      return false;
    }

    std::map<unsigned int, qi::Message*>::iterator it;
    {
      boost::mutex::scoped_lock l(mtx);
      it = msgSend.find(id);
      if (it != msgSend.end())
      {
        *msg = *it->second;
        delete it->second;
        msgSend.erase(it);
        return true;
      }
    }

    qiLogError("qimessaging.TransportSocket") << "message #" << id
                                              << " could not be found.";

    return false;
  }

  void TransportSocketPrivate::addCallbacks(TransportSocketInterface *delegate)
  {
    if (delegate)
    {
      boost::mutex::scoped_lock l(mtxCallback);
      tcd.push_back(delegate);
    }
    else
      qiLogError("") << "Trying to set invalid callback on TransportSoket.";
  }

  void TransportSocketPrivate::removeCallbacks(TransportSocketInterface *delegate)
  {
    if (delegate)
    {
      boost::mutex::scoped_lock l(mtxCallback);
      std::vector<TransportSocketInterface *>::iterator it;
      for (it = tcd.begin(); it != tcd.end(); ++it)
      {
        if (*it == delegate)
        {
          tcd.erase(it);
          break;
        }
      }
    }
    else
      qiLogError("") << "Trying to erase invalid callback on TransportSoket.";
  }

  bool TransportSocketPrivate::isConnected() const
  {
    return connected;
  }
}
<commit_msg>Fix warning.<commit_after>/*
** Author(s):
**  - Herve Cuche <hcuche@aldebaran-robotics.com>
**
** Copyright (C) 2012 Aldebaran Robotics
*/

#include <iostream>
#include "src/transport_socket_p.hpp"

namespace qi
{
  TransportSocketPrivate::TransportSocketPrivate(TransportSocket *socket)
    : tcd()
    , connected(false)
    , status(0)
    , readHdr(true)
    , msg(0)
    , self(socket)
  {
  }

  TransportSocketPrivate::~TransportSocketPrivate()
  {
  }

// if msecs < 0 no timeout
  bool TransportSocketPrivate::waitForConnected(int msecs)
  {
    // no timeout
    if (msecs < 0)
    {
      while (!isConnected() && status == 0)
        ;
      return true;
    }

    while ((!isConnected() && status == 0) && msecs > 0)
    {
      qi::os::msleep(1);
      msecs--;
    }
    return isConnected();
  }

  bool TransportSocketPrivate::waitForDisconnected(int msecs)
  {
    // no timeout
    if (msecs < 0)
    {
      while (isConnected())
        ;
      return true;
    }

    while (isConnected() && msecs > 0)
    {
      qi::os::msleep(1);
      msecs--;
    }

    return !isConnected();
  }

  bool TransportSocketPrivate::waitForId(int id, int msecs)
  {
    if (!isConnected())
    {
      qiLogError("qimessaging.TransportSocket") << "socket is not connected.";
      return false;
    }

    std::map<unsigned int, qi::Message*>::iterator it;
    {
      {
        boost::mutex::scoped_lock l(mtx);
        it = msgSend.find(id);
        if (it != msgSend.end())
          return true;
        if (!isConnected())
          return false;
        if (msecs > 0)
          cond.timed_wait(l, boost::posix_time::milliseconds(msecs));
        else
          cond.wait(l);
        it = msgSend.find(id);
        if (it != msgSend.end())
          return true;
      }
    }
    return false;
  }

  bool TransportSocketPrivate::read(int id, qi::Message *msg)
  {
    if (!isConnected())
    {
      qiLogError("qimessaging.TransportSocket") << "socket is not connected.";
      return false;
    }

    std::map<unsigned int, qi::Message*>::iterator it;
    {
      boost::mutex::scoped_lock l(mtx);
      it = msgSend.find(id);
      if (it != msgSend.end())
      {
        *msg = *it->second;
        delete it->second;
        msgSend.erase(it);
        return true;
      }
    }

    qiLogError("qimessaging.TransportSocket") << "message #" << id
                                              << " could not be found.";

    return false;
  }

  void TransportSocketPrivate::addCallbacks(TransportSocketInterface *delegate)
  {
    if (delegate)
    {
      boost::mutex::scoped_lock l(mtxCallback);
      tcd.push_back(delegate);
    }
    else
      qiLogError("") << "Trying to set invalid callback on TransportSoket.";
  }

  void TransportSocketPrivate::removeCallbacks(TransportSocketInterface *delegate)
  {
    if (delegate)
    {
      boost::mutex::scoped_lock l(mtxCallback);
      std::vector<TransportSocketInterface *>::iterator it;
      for (it = tcd.begin(); it != tcd.end(); ++it)
      {
        if (*it == delegate)
        {
          tcd.erase(it);
          break;
        }
      }
    }
    else
      qiLogError("") << "Trying to erase invalid callback on TransportSoket.";
  }

  bool TransportSocketPrivate::isConnected() const
  {
    return connected;
  }
}
<|endoftext|>