<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>/*
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 2 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU Library General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 *
 * InterfacePicker.cpp
 * Chooses an interface to listen on
 * Copyright (C) 2005-2009 Simon Newton
 */

#ifdef LLA_USE_GETIFADDRS
  #include <ifaddrs.h>
  #include <linux/types.h>
  #include <linux/if_packet.h>
#endif

#include <arpa/inet.h>
#include <errno.h>
#include <net/if.h>
#include <net/if_dl.h>
#include <string.h>
#include <sys/ioctl.h>
#include <algorithm>

#include <lla/Logging.h>
#include <lla/network/InterfacePicker.h>

using namespace lla::network;
using std::string;
using std::vector;

Interface::Interface() {
  ip_address.s_addr = 0;
  bcast_address.s_addr = 0;
  memset(hw_address, 0, MAC_LENGTH);
}

Interface::Interface(const Interface &other) {
  name = other.name;
  ip_address = other.ip_address;
  bcast_address = other.bcast_address;
  memcpy(hw_address, other.hw_address, MAC_LENGTH);
}

Interface& Interface::operator=(const Interface &other) {
  if (this != &other) {
    name = other.name;
    ip_address = other.ip_address;
    bcast_address = other.bcast_address;
    memcpy(hw_address, other.hw_address, MAC_LENGTH);
  }
  return *this;
}

/*
 * Select an interface to use
 * @param interface, the interface to populate
 * @param preferred_ip the ip address of the local interface we'd prefer to use
 * @return true if we found an interface, false otherwise
 */
bool InterfacePicker::ChooseInterface(Interface &interface,
                                      const string &preferred_ip) const {
  struct in_addr wanted_ip;
  bool use_preferred = false;
  vector<Interface> interfaces = GetInterfaces();

  if (!interfaces.size()) {
    LLA_INFO << "No interfaces found";
    return false;
  }

  if (!preferred_ip.empty()) {
    if (inet_aton(preferred_ip.data(), &wanted_ip)) {
      use_preferred = true;
    } else {
      LLA_WARN << "Could not convert address " << preferred_ip;
    }
  }

  if (use_preferred) {
    vector<Interface>::const_iterator iter;
    for (iter = interfaces.begin(); iter != interfaces.end(); ++iter) {
      if ((*iter).ip_address.s_addr == wanted_ip.s_addr) {
        interface = *iter;
        return true;
      }
    }
  }
  interface = interfaces[0];
  return true;
}

vector<Interface> InterfacePicker::GetInterfaces() const {
  vector<Interface> interfaces;
  string last_dl_iface_name;
  uint8_t hwlen = 0;
  char *hwaddr = NULL;

  // create socket to get iface config
  int sd = socket(PF_INET, SOCK_DGRAM, 0);

  if (sd < 0) {
    LLA_WARN << "Could not create socket " << strerror(errno);
    return interfaces;
  }

  // use ioctl to get a listing of interfaces
  char *buffer; // holds the iface data
  unsigned int lastlen = 0; // the amount of data returned by the last ioctl
  unsigned int len = INITIAL_IFACE_COUNT;

  while (true) {
    struct ifconf ifc;
    ifc.ifc_len = len * sizeof(struct ifreq);
    buffer = new char[ifc.ifc_len];
    ifc.ifc_buf = buffer;

    if (ioctl(sd, SIOCGIFCONF, &ifc) < 0) {
      if (errno != EINVAL || lastlen != 0) {
        LLA_WARN << "ioctl error " << strerror(errno);
        delete[] buffer;
        return interfaces;
      }
    } else {
      if(ifc.ifc_len == lastlen) {
        lastlen = ifc.ifc_len;
        break;
      }
      lastlen = ifc.ifc_len;
    }
    len += IFACE_COUNT_INC;
    delete[] buffer;
  }

  // loop through each iface
  for (char *ptr = buffer; ptr < buffer + lastlen;) {
    struct ifreq *iface = (struct ifreq*) ptr;
    unsigned int iface_len = sizeof(struct sockaddr);

#ifdef HAVE_SOCKADDR_SA_LEN
    iface_len = std::max(iface_len, (unsigned int) iface->ifr_addr.sa_len);
#else
#ifdef IPV6
    if (iface->ifr_addr.sa_family == AF_INET6)
      iface_len = sizeof(struct sockaddr_in6);
#endif
#endif

    ptr += sizeof(iface->ifr_name) + iface_len;

#ifdef HAVE_SOCKADDR_DL_STRUCT
    if (iface->ifr_addr.sa_family == AF_LINK) {
      struct sockaddr_dl *sdl = (struct sockaddr_dl*) &iface->ifr_addr;
      last_dl_iface_name.assign(sdl->sdl_data, sdl->sdl_nlen);
      hwaddr = sdl->sdl_data + sdl->sdl_nlen;
      hwlen = sdl->sdl_alen;
    }
#endif

    // look for AF_INET interfaces only
    if (iface->ifr_addr.sa_family != AF_INET) {
      LLA_DEBUG << "skipping " << iface->ifr_name <<
        " because it's not af_inet";
      continue;
    }

    struct ifreq ifrcopy = *iface;
    if (ioctl(sd, SIOCGIFFLAGS, &ifrcopy) < 0) {
      LLA_WARN << "ioctl error for " << iface->ifr_name << ":"
        << strerror(errno);
      continue;
    }

    if (!(ifrcopy.ifr_flags & IFF_UP)) {
      LLA_DEBUG << "skipping " << iface->ifr_name << " because it's down";
      continue;
    }

    if (ifrcopy.ifr_flags & IFF_LOOPBACK) {
      LLA_DEBUG << "skipping " << iface->ifr_name <<
        " because it's a loopback";
      continue;
    }

    Interface interface;
    interface.name = iface->ifr_name;
    if (interface.name == last_dl_iface_name && hwaddr) {
      memcpy(interface.hw_address, hwaddr,
             std::min(hwlen, (uint8_t) MAC_LENGTH));
    }
    struct sockaddr_in *sin = (struct sockaddr_in *) &iface->ifr_addr;
    interface.ip_address = sin->sin_addr;

    // fetch bcast address
#ifdef SIOCGIFBRDADDR
    if (ifrcopy.ifr_flags & IFF_BROADCAST) {
      if (ioctl(sd, SIOCGIFBRDADDR, &ifrcopy) < 0) {
        LLA_WARN << "ioctl error " << strerror(errno);
      } else {
        sin = (struct sockaddr_in *) &ifrcopy.ifr_broadaddr;
        interface.bcast_address = sin->sin_addr;
      }
    }
#endif

    // fetch hardware address
#ifdef SIOCGIFHWADDR
    if (ifrcopy.ifr_flags & SIOCGIFHWADDR) {
      if (ioctl(sd, SIOCGIFHWADDR, &ifrcopy) < 0) {
        LLA_WARN << "ioctl error" << strerror(errno);
      } else {
        memcpy(interface.hw_address, ifrcopy.ifr_hwaddr.sa_data, MAC_LENGTH);
      }
    }
#endif

    /* ok, if that all failed we should prob try and use sysctl to work out the bcast
     * and hware addresses
     * i'll leave that for another day
     */
    interfaces.push_back(interface);
  }
  close(sd);
  delete[] buffer;
  return interfaces;
}
<commit_msg> * make the include conditional<commit_after>/*
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 2 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU Library General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 *
 * InterfacePicker.cpp
 * Chooses an interface to listen on
 * Copyright (C) 2005-2009 Simon Newton
 */

#ifdef LLA_USE_GETIFADDRS
  #include <ifaddrs.h>
  #include <linux/types.h>
  #include <linux/if_packet.h>
#endif

#include <arpa/inet.h>
#include <errno.h>
#include <net/if.h>
#ifdef HAVE_SOCKADDR_DL_STRUCT
#include <net/if_dl.h>
#endif
#include <string.h>
#include <sys/ioctl.h>
#include <algorithm>

#include <lla/Logging.h>
#include <lla/network/InterfacePicker.h>

using namespace lla::network;
using std::string;
using std::vector;

Interface::Interface() {
  ip_address.s_addr = 0;
  bcast_address.s_addr = 0;
  memset(hw_address, 0, MAC_LENGTH);
}

Interface::Interface(const Interface &other) {
  name = other.name;
  ip_address = other.ip_address;
  bcast_address = other.bcast_address;
  memcpy(hw_address, other.hw_address, MAC_LENGTH);
}

Interface& Interface::operator=(const Interface &other) {
  if (this != &other) {
    name = other.name;
    ip_address = other.ip_address;
    bcast_address = other.bcast_address;
    memcpy(hw_address, other.hw_address, MAC_LENGTH);
  }
  return *this;
}

/*
 * Select an interface to use
 * @param interface, the interface to populate
 * @param preferred_ip the ip address of the local interface we'd prefer to use
 * @return true if we found an interface, false otherwise
 */
bool InterfacePicker::ChooseInterface(Interface &interface,
                                      const string &preferred_ip) const {
  struct in_addr wanted_ip;
  bool use_preferred = false;
  vector<Interface> interfaces = GetInterfaces();

  if (!interfaces.size()) {
    LLA_INFO << "No interfaces found";
    return false;
  }

  if (!preferred_ip.empty()) {
    if (inet_aton(preferred_ip.data(), &wanted_ip)) {
      use_preferred = true;
    } else {
      LLA_WARN << "Could not convert address " << preferred_ip;
    }
  }

  if (use_preferred) {
    vector<Interface>::const_iterator iter;
    for (iter = interfaces.begin(); iter != interfaces.end(); ++iter) {
      if ((*iter).ip_address.s_addr == wanted_ip.s_addr) {
        interface = *iter;
        return true;
      }
    }
  }
  interface = interfaces[0];
  return true;
}

vector<Interface> InterfacePicker::GetInterfaces() const {
  vector<Interface> interfaces;
  string last_dl_iface_name;
  uint8_t hwlen = 0;
  char *hwaddr = NULL;

  // create socket to get iface config
  int sd = socket(PF_INET, SOCK_DGRAM, 0);

  if (sd < 0) {
    LLA_WARN << "Could not create socket " << strerror(errno);
    return interfaces;
  }

  // use ioctl to get a listing of interfaces
  char *buffer; // holds the iface data
  unsigned int lastlen = 0; // the amount of data returned by the last ioctl
  unsigned int len = INITIAL_IFACE_COUNT;

  while (true) {
    struct ifconf ifc;
    ifc.ifc_len = len * sizeof(struct ifreq);
    buffer = new char[ifc.ifc_len];
    ifc.ifc_buf = buffer;

    if (ioctl(sd, SIOCGIFCONF, &ifc) < 0) {
      if (errno != EINVAL || lastlen != 0) {
        LLA_WARN << "ioctl error " << strerror(errno);
        delete[] buffer;
        return interfaces;
      }
    } else {
      if(ifc.ifc_len == lastlen) {
        lastlen = ifc.ifc_len;
        break;
      }
      lastlen = ifc.ifc_len;
    }
    len += IFACE_COUNT_INC;
    delete[] buffer;
  }

  // loop through each iface
  for (char *ptr = buffer; ptr < buffer + lastlen;) {
    struct ifreq *iface = (struct ifreq*) ptr;
    unsigned int iface_len = sizeof(struct sockaddr);

#ifdef HAVE_SOCKADDR_SA_LEN
    iface_len = std::max(iface_len, (unsigned int) iface->ifr_addr.sa_len);
#else
#ifdef IPV6
    if (iface->ifr_addr.sa_family == AF_INET6)
      iface_len = sizeof(struct sockaddr_in6);
#endif
#endif

    ptr += sizeof(iface->ifr_name) + iface_len;

#ifdef HAVE_SOCKADDR_DL_STRUCT
    if (iface->ifr_addr.sa_family == AF_LINK) {
      struct sockaddr_dl *sdl = (struct sockaddr_dl*) &iface->ifr_addr;
      last_dl_iface_name.assign(sdl->sdl_data, sdl->sdl_nlen);
      hwaddr = sdl->sdl_data + sdl->sdl_nlen;
      hwlen = sdl->sdl_alen;
    }
#endif

    // look for AF_INET interfaces only
    if (iface->ifr_addr.sa_family != AF_INET) {
      LLA_DEBUG << "skipping " << iface->ifr_name <<
        " because it's not af_inet";
      continue;
    }

    struct ifreq ifrcopy = *iface;
    if (ioctl(sd, SIOCGIFFLAGS, &ifrcopy) < 0) {
      LLA_WARN << "ioctl error for " << iface->ifr_name << ":"
        << strerror(errno);
      continue;
    }

    if (!(ifrcopy.ifr_flags & IFF_UP)) {
      LLA_DEBUG << "skipping " << iface->ifr_name << " because it's down";
      continue;
    }

    if (ifrcopy.ifr_flags & IFF_LOOPBACK) {
      LLA_DEBUG << "skipping " << iface->ifr_name <<
        " because it's a loopback";
      continue;
    }

    Interface interface;
    interface.name = iface->ifr_name;
    if (interface.name == last_dl_iface_name && hwaddr) {
      memcpy(interface.hw_address, hwaddr,
             std::min(hwlen, (uint8_t) MAC_LENGTH));
    }
    struct sockaddr_in *sin = (struct sockaddr_in *) &iface->ifr_addr;
    interface.ip_address = sin->sin_addr;

    // fetch bcast address
#ifdef SIOCGIFBRDADDR
    if (ifrcopy.ifr_flags & IFF_BROADCAST) {
      if (ioctl(sd, SIOCGIFBRDADDR, &ifrcopy) < 0) {
        LLA_WARN << "ioctl error " << strerror(errno);
      } else {
        sin = (struct sockaddr_in *) &ifrcopy.ifr_broadaddr;
        interface.bcast_address = sin->sin_addr;
      }
    }
#endif

    // fetch hardware address
#ifdef SIOCGIFHWADDR
    if (ifrcopy.ifr_flags & SIOCGIFHWADDR) {
      if (ioctl(sd, SIOCGIFHWADDR, &ifrcopy) < 0) {
        LLA_WARN << "ioctl error" << strerror(errno);
      } else {
        memcpy(interface.hw_address, ifrcopy.ifr_hwaddr.sa_data, MAC_LENGTH);
      }
    }
#endif

    /* ok, if that all failed we should prob try and use sysctl to work out the bcast
     * and hware addresses
     * i'll leave that for another day
     */
    interfaces.push_back(interface);
  }
  close(sd);
  delete[] buffer;
  return interfaces;
}
<|endoftext|>


<commit_before>//!@todo: swarm: implement logger_interface
//!@todo: thevoid: redirect json config.
//!@todo: files_t: Rotation condition.
//! Sample config:
/*!
Rotate by datetime:
"rotate": {
    "backups" 5,
    "pattern": "%(filename)s.log.%Y%M%d",
    "every": "d" [m, H, a, d, w, M, y]
}

Rotate both:
"rotate": {
    "backups" 5,
    "pattern": "%(filename)s.log.%N.%Y%M%d",
    "size": 1000000,
    "every": "d" [m, H, a, d, w, M, y]
}
*/

//!@todo: example: Make stdout/string example with demonstration of formatting other attribute.

//!@todo: benchmark: File logging comparing with boost::log.
//!@todo: benchmark: Socket logging with json.

//!@todo: files_t: Make file naming by pattern.
//!@todo: files_t: logrotate support - ability to handle signals to reopen current file (SIGHUP).

//!@todo: performance: Experiment with std::ostringstream or format library for performance check.
//!@todo: performance: Current naive implementation of timestamp formatter is suck and have large performance troubles. Fix it.

//!@todo: api: Make fallback logger. Make it configurable.
//!@todo: aux: Make internal exception class with attribute keeping, e.g. line, file or path.
//!@todo: api: Maybe squish repository_t::init and ::configure methods?
//!@todo: msgpack_t: Attribute mappings.
//!@todo: socket_t: Make asynchronous TCP backend.
<commit_msg>Subtask added.<commit_after>//!@todo: example: initialization from file.
//!@todo: swarm: implement logger_interface
//!@todo: thevoid: redirect json config.
//!@todo: files_t: Rotation condition.
//! Sample config:
/*!
Rotate by datetime:
"rotate": {
    "backups" 5,
    "pattern": "%(filename)s.log.%Y%M%d",
    "every": "d" [m, H, a, d, w, M, y]
}

Rotate both:
"rotate": {
    "backups" 5,
    "pattern": "%(filename)s.log.%N.%Y%M%d",
    "size": 1000000,
    "every": "d" [m, H, a, d, w, M, y]
}
*/

//!@todo: example: Make stdout/string example with demonstration of formatting other attribute.

//!@todo: benchmark: File logging comparing with boost::log.
//!@todo: benchmark: Socket logging with json.

//!@todo: files_t: Make file naming by pattern.
//!@todo: files_t: logrotate support - ability to handle signals to reopen current file (SIGHUP).

//!@todo: performance: Experiment with std::ostringstream or format library for performance check.
//!@todo: performance: Current naive implementation of timestamp formatter is suck and have large performance troubles. Fix it.

//!@todo: api: Make fallback logger. Make it configurable.
//!@todo: aux: Make internal exception class with attribute keeping, e.g. line, file or path.
//!@todo: api: Maybe squish repository_t::init and ::configure methods?
//!@todo: msgpack_t: Attribute mappings.
//!@todo: socket_t: Make asynchronous TCP backend.
<|endoftext|>


<commit_before>#include "InstructionLexer.hpp"

#include <iostream>
#include <vector>
#include <utility>
#include <functinal>
#include <regex>

#include "boost/tokenizer.hpp"
#include "boost/range/algorithm.hpp"

Tokens InstructionLexer::parseInstructions(const std::string& line)
{
    boost::tokenizer<boost::char_separator<char>> lineTokenizer{line, boost::char_separator<char>{"\n"}};
    Tokens tokens;
    for (const auto&line : lineTokenizer)
    {
      if (line.at(0) != ' ')
      {
	  throw UnknownInstruction("Invalid line: " + line);
      }
      boost::copy(parseLine(line), std::back_inserter(tokens));
    }
    return tokens;
}

Tokens InstructionLexer::parseLine(const std::string& line)
{
    boost::tokenizer<boost::char_separator<char>> instructionTokenizer{line, boost::char_separator<char>{", "}};
    Tokens tokens;
    for (const auto&token : instructionTokenizer)
    {
      boost::copy(parseInstruction(token), std::back_inserter(tokens));
    }
    return tokens;
}

const auto alwaysZeroValue = [](const std::string&) -> Token::ValueType
{
  return 0;
};

const auto convertToUnsigned = [](const std::string& text) -> Token::ValueType
{
  try
  {
    return std::stoi(text);
  }
  catch (const std::exception &)
  {
    return 0;
  }
};

Tokens InstructionLexer::parseInstruction(const std::string& instruction)
{
  const auto trimmedInstruction = trimWhitespacesOnFront(instruction);
  if (trimmedInstruction.empty())
  {
    return{};
  }
  using TextToTokens = std::vector<std::tuple<std::regex, TokenType, std::function<Token::ValueType(const std::string&)>>>;
  const TextToTokens acceptableInstructions{{std::regex{"out"}, TokenType::Out, alwaysZeroValue},
                                            {std::regex{"\\(0\\)"}, TokenType::ZeroWithBrackets, alwaysZeroValue},
                                            {std::regex{"ld"}, TokenType::Ld, alwaysZeroValue},
                                            {std::regex{"a"}, TokenType::A, alwaysZeroValue},
                                            {std::regex{"[0-9]{1,2}|1[0-9]{1,2}|2[0-4][0-9]|25[0-5]"}, TokenType::Number8Bit, convertToUnsigned}};
  const auto noArgumentInstructionPosition = std::find_if(acceptableInstructions.begin(), acceptableInstructions.end(), [&](const auto& tokenMap)
      {
        return std::regex_match(trimmedInstruction, std::get<0>(tokenMap));
      });
  if (noArgumentInstructionPosition != acceptableInstructions.end())
  {
    return {{std::get<1>(*noArgumentInstructionPosition), std::get<2>(*noArgumentInstructionPosition)(trimmedInstruction)}};
  }
  throw UnknownInstruction{"Unknown instruction: " + instruction};
}

std::string InstructionLexer::trimWhitespacesOnFront(const std::string& instruction)
{
  const auto firstRelevantCharPosition = instruction.find_first_not_of(" \t");
  if (firstRelevantCharPosition != std::string::npos)
  {
    return instruction.substr(firstRelevantCharPosition);
  }
  return {};
}
<commit_msg>Change include to functinal<commit_after>#include "InstructionLexer.hpp"

#include <iostream>
#include <vector>
#include <utility>
#include <functional>
#include <regex>

#include "boost/tokenizer.hpp"
#include "boost/range/algorithm.hpp"

Tokens InstructionLexer::parseInstructions(const std::string& line)
{
    boost::tokenizer<boost::char_separator<char>> lineTokenizer{line, boost::char_separator<char>{"\n"}};
    Tokens tokens;
    for (const auto&line : lineTokenizer)
    {
      if (line.at(0) != ' ')
      {
	  throw UnknownInstruction("Invalid line: " + line);
      }
      boost::copy(parseLine(line), std::back_inserter(tokens));
    }
    return tokens;
}

Tokens InstructionLexer::parseLine(const std::string& line)
{
    boost::tokenizer<boost::char_separator<char>> instructionTokenizer{line, boost::char_separator<char>{", "}};
    Tokens tokens;
    for (const auto&token : instructionTokenizer)
    {
      boost::copy(parseInstruction(token), std::back_inserter(tokens));
    }
    return tokens;
}

const auto alwaysZeroValue = [](const std::string&) -> Token::ValueType
{
  return 0;
};

const auto convertToUnsigned = [](const std::string& text) -> Token::ValueType
{
  try
  {
    return std::stoi(text);
  }
  catch (const std::exception &)
  {
    return 0;
  }
};

Tokens InstructionLexer::parseInstruction(const std::string& instruction)
{
  const auto trimmedInstruction = trimWhitespacesOnFront(instruction);
  if (trimmedInstruction.empty())
  {
    return{};
  }
  using TextToTokens = std::vector<std::tuple<std::regex, TokenType, std::function<Token::ValueType(const std::string&)>>>;
  const TextToTokens acceptableInstructions{{std::regex{"out"}, TokenType::Out, alwaysZeroValue},
                                            {std::regex{"\\(0\\)"}, TokenType::ZeroWithBrackets, alwaysZeroValue},
                                            {std::regex{"ld"}, TokenType::Ld, alwaysZeroValue},
                                            {std::regex{"a"}, TokenType::A, alwaysZeroValue},
                                            {std::regex{"[0-9]{1,2}|1[0-9]{1,2}|2[0-4][0-9]|25[0-5]"}, TokenType::Number8Bit, convertToUnsigned}};
  const auto noArgumentInstructionPosition = std::find_if(acceptableInstructions.begin(), acceptableInstructions.end(), [&](const auto& tokenMap)
      {
        return std::regex_match(trimmedInstruction, std::get<0>(tokenMap));
      });
  if (noArgumentInstructionPosition != acceptableInstructions.end())
  {
    return {{std::get<1>(*noArgumentInstructionPosition), std::get<2>(*noArgumentInstructionPosition)(trimmedInstruction)}};
  }
  throw UnknownInstruction{"Unknown instruction: " + instruction};
}

std::string InstructionLexer::trimWhitespacesOnFront(const std::string& instruction)
{
  const auto firstRelevantCharPosition = instruction.find_first_not_of(" \t");
  if (firstRelevantCharPosition != std::string::npos)
  {
    return instruction.substr(firstRelevantCharPosition);
  }
  return {};
}
<|endoftext|>


<commit_before>/*
 * Copyright (c) Facebook, Inc. and its affiliates.
 *
 * This source code is licensed under the MIT license found in the
 * LICENSE file in the root directory of this source tree.
 */

#ifdef __ANDROID__

#include <android/log.h>

// Provide a prototype to silence missing prototype warning in release
// mode.
extern "C" void react_native_assert_fail(
    const char *func,
    const char *file,
    int line,
    const char *expr);

extern "C" void react_native_assert_fail(
    const char *func,
    const char *file,
    int line,
    const char *expr) {
  // Print as an error so it shows up in logcat before crash....
  __android_log_print(
      ANDROID_LOG_ERROR,
      "ReactNative",
      "%s:%d: function %s: assertion failed (%s)",
      file,
      line,
      func,
      expr);
  // Print as a fatal so it crashes and shows up in uploaded logs
  __android_log_print(
      ANDROID_LOG_FATAL,
      "ReactNative",
      "%s:%d: function %s: assertion failed (%s)",
      file,
      line,
      func,
      expr);
}

#endif // __ANDROID__
<commit_msg>Let react_native_assert really abort the app<commit_after>/*
 * Copyright (c) Facebook, Inc. and its affiliates.
 *
 * This source code is licensed under the MIT license found in the
 * LICENSE file in the root directory of this source tree.
 */

#ifdef __ANDROID__

#include <android/log.h>

// Provide a prototype to silence missing prototype warning in release
// mode.
extern "C" void react_native_assert_fail(
    const char *func,
    const char *file,
    int line,
    const char *expr);

extern "C" void react_native_assert_fail(
    const char *func,
    const char *file,
    int line,
    const char *expr) {
  // Print as an error so it shows up in logcat before crash...
  __android_log_print(
      ANDROID_LOG_ERROR,
      "ReactNative",
      "%s:%d: function %s: assertion failed (%s)",
      file,
      line,
      func,
      expr);
  // ...and trigger an abort so it crashes and shows up in uploaded logs.
  __android_log_assert(
      nullptr,
      "ReactNative",
      "%s:%d: function %s: assertion failed (%s)",
      file,
      line,
      func,
      expr);
}

#endif // __ANDROID__
<|endoftext|>


<commit_before>/***************************************************
  This is a library for our I2C LED Backpacks

  Designed specifically to work with the Adafruit LED Matrix backpacks
  ----> http://www.adafruit.com/products/
  ----> http://www.adafruit.com/products/

  These displays use I2C to communicate, 2 pins are required to
  interface. There are multiple selectable I2C addresses. For backpacks
  with 2 Address Select pins: 0x70, 0x71, 0x72 or 0x73. For backpacks
  with 3 Address Select pins: 0x70 thru 0x77

  Adafruit invests time and resources providing this open source code,
  please support Adafruit and open-source hardware by purchasing
  products from Adafruit!

  Written by Limor Fried/Ladyada for Adafruit Industries.
  BSD license, all text above must be included in any redistribution
 ****************************************************/

#include "BCG_LED_Library.h"
#include "Adafruit_GFX.h"

static const uint8_t numbertable[] = {
	0x3F, /* 0 */
	0x06, /* 1 */
	0x5B, /* 2 */
	0x4F, /* 3 */
	0x66, /* 4 */
	0x6D, /* 5 */
	0x7D, /* 6 */
	0x07, /* 7 */
	0x7F, /* 8 */
	0x6F, /* 9 */
	0x77, /* a */
	0x7C, /* b */
	0x39, /* C */
	0x5E, /* d */
	0x79, /* E */
	0x71, /* F */
};

void Adafruit_LEDBackpack::setBrightness(uint8_t b) {
  if (b > 15) b = 15;
  Wire.beginTransmission(i2c_addr);
  Wire.write(0xE0 | b);
  Wire.endTransmission();
}

void Adafruit_LEDBackpack::blinkRate(uint8_t b) {
  Wire.beginTransmission(i2c_addr);
  if (b > 3) b = 0; // turn off if not sure

  Wire.write(HT16K33_BLINK_CMD | HT16K33_BLINK_DISPLAYON | (b << 1));
  Wire.endTransmission();
}

Adafruit_LEDBackpack::Adafruit_LEDBackpack(void) {
}

void Adafruit_LEDBackpack::begin(uint8_t _addr = 0x70) {
  i2c_addr = _addr;

  Wire.begin();

  Wire.beginTransmission(i2c_addr);
  Wire.write(0x21);  // turn on oscillator
  Wire.endTransmission();
  blinkRate(HT16K33_BLINK_OFF);

  setBrightness(15); // max brightness
}

void Adafruit_LEDBackpack::writeDisplay(void) {
  Wire.beginTransmission(i2c_addr);
  Wire.write((uint8_t)0x00); // start at address $00

  for (uint8_t i=0; i<8; i++) {
    Wire.write(displaybuffer[i] & 0xFF);
    Wire.write(displaybuffer[i] >> 8);
  }
  Wire.endTransmission();
}

void Adafruit_LEDBackpack::clear(void) {
  for (uint8_t i=0; i<8; i++) {
    displaybuffer[i] = 0;
  }
}

Adafruit_8x8matrix::Adafruit_8x8matrix(void) : Adafruit_GFX(8, 8) {
}

void Adafruit_8x8matrix::drawPixel(int16_t x, int16_t y, uint16_t color) {
  if ((y < 0) || (y >= 8)) return;
  if ((x < 0) || (x >= 8)) return;

 // check rotation, move pixel around if necessary
  switch (getRotation()) {
  case 1:
    swap(x, y);
    x = 8 - x - 1;
    break;
  case 2:
    x = 8 - x - 1;
    y = 8 - y - 1;
    break;
  case 3:
    swap(x, y);
    y = 8 - y - 1;
    break;
  }

  // wrap around the x
  x += 7;
  x %= 8;

  if (color) {
    displaybuffer[y] |= 1 << x;
  } else {
    displaybuffer[y] &= ~(1 << x);
  }
}

Adafruit_BicolorMatrix::Adafruit_BicolorMatrix(void) : Adafruit_GFX(8, 8) {
}

void Adafruit_BicolorMatrix::drawPixel(int16_t x, int16_t y, uint16_t color) {
  if ((y < 0) || (y >= 8)) return;
  if ((x < 0) || (x >= 8)) return;

  switch (getRotation()) {
  case 1:
    swap(x, y);
    x = 8 - x - 1;
    break;
  case 2:
    x = 8 - x - 1;
    y = 8 - y - 1;
    break;
  case 3:
    swap(x, y);
    y = 8 - y - 1;
    break;
  }

  if (color == LED_GREEN) {
    displaybuffer[y] |= 1 << x;
  } else if (color == LED_RED) {
    displaybuffer[y] |= 1 << (x+8);
  } else if (color == LED_YELLOW) {
    displaybuffer[y] |= (1 << (x+8)) | (1 << x);
  } else if (color == LED_OFF) {
    displaybuffer[y] &= ~(1 << x) & ~(1 << (x+8));
  }
}

Adafruit_7segment::Adafruit_7segment(void) {
  position = 0;
}

void Adafruit_7segment::print(unsigned long n, int base)
{
  if (base == 0) write(n);
  else printNumber(n, base);
}

void Adafruit_7segment::print(char c, int base)
{
  print((long) c, base);
}

void Adafruit_7segment::print(unsigned char b, int base)
{
  print((unsigned long) b, base);
}

void Adafruit_7segment::print(int n, int base)
{
  print((long) n, base);
}

void Adafruit_7segment::print(unsigned int n, int base)
{
  print((unsigned long) n, base);
}

void  Adafruit_7segment::println(void) {
  position = 0;
}

void  Adafruit_7segment::println(char c, int base)
{
  print(c, base);
  println();
}

void  Adafruit_7segment::println(unsigned char b, int base)
{
  print(b, base);
  println();
}

void  Adafruit_7segment::println(int n, int base)
{
  print(n, base);
  println();
}

void  Adafruit_7segment::println(unsigned int n, int base)
{
  print(n, base);
  println();
}

void  Adafruit_7segment::println(long n, int base)
{
  print(n, base);
  println();
}

void  Adafruit_7segment::println(unsigned long n, int base)
{
  print(n, base);
  println();
}

void  Adafruit_7segment::println(double n, int digits)
{
  print(n, digits);
  println();
}

void  Adafruit_7segment::print(double n, int digits)
{
  printFloat(n, digits);
}

size_t Adafruit_7segment::write(uint8_t c) {

  uint8_t r = 0;

  if (c == '\n') position = 0;
  if (c == '\r') position = 0;

  if ((c >= '0') && (c <= '9')) {
    writeDigitNum(position, c-'0');
    r = 1;
  }

  position++;
  if (position == 2) position++;

  return r;
}

void Adafruit_7segment::writeDigitRaw(uint8_t d, uint8_t bitmask) {
  if (d > 4) return;
  displaybuffer[d] = bitmask;
}

void Adafruit_7segment::drawColon(boolean state) {
  if (state)
    displaybuffer[2] = 0xFF;
  else
    displaybuffer[2] = 0;
}

void Adafruit_7segment::writeDigitNum(uint8_t d, uint8_t num, boolean dot) {
  if (d > 4) return;

  writeDigitRaw(d, numbertable[num] | (dot << 7));
}

void Adafruit_7segment::print(long n, int base)
{
  printNumber(n, base);
}

void Adafruit_7segment::printNumber(long n, uint8_t base)
{
    printFloat(n, 0, base);
}

void Adafruit_7segment::printFloat(double n, uint8_t fracDigits, uint8_t base)
{
  uint8_t numericDigits = 4;   // available digits on display
  boolean isNegative = false;  // true if the number is negative

  // is the number negative?
  if(n < 0) {
    isNegative = true;  // need to draw sign later
    --numericDigits;    // the sign will take up one digit
    n *= -1;            // pretend the number is positive
  }

  // calculate the factor required to shift all fractional digits
  // into the integer part of the number
  double toIntFactor = 1.0;
  for(int i = 0; i < fracDigits; ++i) toIntFactor *= base;

  // create integer containing digits to display by applying
  // shifting factor and rounding adjustment
  uint32_t displayNumber = n * toIntFactor + 0.5;

  // calculate upper bound on displayNumber given
  // available digits on display
  uint32_t tooBig = 1;
  for(int i = 0; i < numericDigits; ++i) tooBig *= base;

  // if displayNumber is too large, try fewer fractional digits
  while(displayNumber >= tooBig) {
    --fracDigits;
    toIntFactor /= base;
    displayNumber = n * toIntFactor + 0.5;
  }

  // did toIntFactor shift the decimal off the display?
  if (toIntFactor < 1) {
    printError();
  } else {
    // otherwise, display the number
    int8_t displayPos = 4;

    if (displayNumber)  //if displayNumber is not 0
    {
      for(uint8_t i = 0; displayNumber; ++i) {
        boolean displayDecimal = (fracDigits != 0 && i == fracDigits);
        writeDigitNum(displayPos--, displayNumber % base, displayDecimal);
        if(displayPos == 2) writeDigitRaw(displayPos--, 0x00);
        displayNumber /= base;
      }
    }
    else {
      writeDigitNum(displayPos--, 0, false);
    }

    // display negative sign if negative
    if(isNegative) writeDigitRaw(displayPos--, 0x40);

    // clear remaining display positions
    while(displayPos >= 0) writeDigitRaw(displayPos--, 0x00);
  }
}

void Adafruit_7segment::printError(void) {
  for(uint8_t i = 0; i < SEVENSEG_DIGITS; ++i) {
    writeDigitRaw(i, (i == 2 ? 0x00 : 0x40));
  }
}
<commit_msg>Update BCG_LED_Library.cpp<commit_after>/***************************************************
  This is a library for our I2C LED Backpacks

  Designed specifically to work with the Adafruit LED Matrix backpacks
  ----> http://www.adafruit.com/products/
  ----> http://www.adafruit.com/products/

  These displays use I2C to communicate, 2 pins are required to
  interface. There are multiple selectable I2C addresses. For backpacks
  with 2 Address Select pins: 0x70, 0x71, 0x72 or 0x73. For backpacks
  with 3 Address Select pins: 0x70 thru 0x77

  Adafruit invests time and resources providing this open source code,
  please support Adafruit and open-source hardware by purchasing
  products from Adafruit!

  Written by Limor Fried/Ladyada for Adafruit Industries.
  BSD license, all text above must be included in any redistribution
 ****************************************************/

#include "BCG_LED_Library.h"
#include "Adafruit_GFX/Adafruit_GFX.h"

static const uint8_t numbertable[] = {
	0x3F, /* 0 */
	0x06, /* 1 */
	0x5B, /* 2 */
	0x4F, /* 3 */
	0x66, /* 4 */
	0x6D, /* 5 */
	0x7D, /* 6 */
	0x07, /* 7 */
	0x7F, /* 8 */
	0x6F, /* 9 */
	0x77, /* a */
	0x7C, /* b */
	0x39, /* C */
	0x5E, /* d */
	0x79, /* E */
	0x71, /* F */
};

void Adafruit_LEDBackpack::setBrightness(uint8_t b) {
  if (b > 15) b = 15;
  Wire.beginTransmission(i2c_addr);
  Wire.write(0xE0 | b);
  Wire.endTransmission();
}

void Adafruit_LEDBackpack::blinkRate(uint8_t b) {
  Wire.beginTransmission(i2c_addr);
  if (b > 3) b = 0; // turn off if not sure

  Wire.write(HT16K33_BLINK_CMD | HT16K33_BLINK_DISPLAYON | (b << 1));
  Wire.endTransmission();
}

Adafruit_LEDBackpack::Adafruit_LEDBackpack(void) {
}

void Adafruit_LEDBackpack::begin(uint8_t _addr = 0x70) {
  i2c_addr = _addr;

  Wire.begin();

  Wire.beginTransmission(i2c_addr);
  Wire.write(0x21);  // turn on oscillator
  Wire.endTransmission();
  blinkRate(HT16K33_BLINK_OFF);

  setBrightness(15); // max brightness
}

void Adafruit_LEDBackpack::writeDisplay(void) {
  Wire.beginTransmission(i2c_addr);
  Wire.write((uint8_t)0x00); // start at address $00

  for (uint8_t i=0; i<8; i++) {
    Wire.write(displaybuffer[i] & 0xFF);
    Wire.write(displaybuffer[i] >> 8);
  }
  Wire.endTransmission();
}

void Adafruit_LEDBackpack::clear(void) {
  for (uint8_t i=0; i<8; i++) {
    displaybuffer[i] = 0;
  }
}

Adafruit_8x8matrix::Adafruit_8x8matrix(void) : Adafruit_GFX(8, 8) {
}

void Adafruit_8x8matrix::drawPixel(int16_t x, int16_t y, uint16_t color) {
  if ((y < 0) || (y >= 8)) return;
  if ((x < 0) || (x >= 8)) return;

 // check rotation, move pixel around if necessary
  switch (getRotation()) {
  case 1:
    swap(x, y);
    x = 8 - x - 1;
    break;
  case 2:
    x = 8 - x - 1;
    y = 8 - y - 1;
    break;
  case 3:
    swap(x, y);
    y = 8 - y - 1;
    break;
  }

  // wrap around the x
  x += 7;
  x %= 8;

  if (color) {
    displaybuffer[y] |= 1 << x;
  } else {
    displaybuffer[y] &= ~(1 << x);
  }
}

Adafruit_BicolorMatrix::Adafruit_BicolorMatrix(void) : Adafruit_GFX(8, 8) {
}

void Adafruit_BicolorMatrix::drawPixel(int16_t x, int16_t y, uint16_t color) {
  if ((y < 0) || (y >= 8)) return;
  if ((x < 0) || (x >= 8)) return;

  switch (getRotation()) {
  case 1:
    swap(x, y);
    x = 8 - x - 1;
    break;
  case 2:
    x = 8 - x - 1;
    y = 8 - y - 1;
    break;
  case 3:
    swap(x, y);
    y = 8 - y - 1;
    break;
  }

  if (color == LED_GREEN) {
    displaybuffer[y] |= 1 << x;
  } else if (color == LED_RED) {
    displaybuffer[y] |= 1 << (x+8);
  } else if (color == LED_YELLOW) {
    displaybuffer[y] |= (1 << (x+8)) | (1 << x);
  } else if (color == LED_OFF) {
    displaybuffer[y] &= ~(1 << x) & ~(1 << (x+8));
  }
}

Adafruit_7segment::Adafruit_7segment(void) {
  position = 0;
}

void Adafruit_7segment::print(unsigned long n, int base)
{
  if (base == 0) write(n);
  else printNumber(n, base);
}

void Adafruit_7segment::print(char c, int base)
{
  print((long) c, base);
}

void Adafruit_7segment::print(unsigned char b, int base)
{
  print((unsigned long) b, base);
}

void Adafruit_7segment::print(int n, int base)
{
  print((long) n, base);
}

void Adafruit_7segment::print(unsigned int n, int base)
{
  print((unsigned long) n, base);
}

void  Adafruit_7segment::println(void) {
  position = 0;
}

void  Adafruit_7segment::println(char c, int base)
{
  print(c, base);
  println();
}

void  Adafruit_7segment::println(unsigned char b, int base)
{
  print(b, base);
  println();
}

void  Adafruit_7segment::println(int n, int base)
{
  print(n, base);
  println();
}

void  Adafruit_7segment::println(unsigned int n, int base)
{
  print(n, base);
  println();
}

void  Adafruit_7segment::println(long n, int base)
{
  print(n, base);
  println();
}

void  Adafruit_7segment::println(unsigned long n, int base)
{
  print(n, base);
  println();
}

void  Adafruit_7segment::println(double n, int digits)
{
  print(n, digits);
  println();
}

void  Adafruit_7segment::print(double n, int digits)
{
  printFloat(n, digits);
}

size_t Adafruit_7segment::write(uint8_t c) {

  uint8_t r = 0;

  if (c == '\n') position = 0;
  if (c == '\r') position = 0;

  if ((c >= '0') && (c <= '9')) {
    writeDigitNum(position, c-'0');
    r = 1;
  }

  position++;
  if (position == 2) position++;

  return r;
}

void Adafruit_7segment::writeDigitRaw(uint8_t d, uint8_t bitmask) {
  if (d > 4) return;
  displaybuffer[d] = bitmask;
}

void Adafruit_7segment::drawColon(boolean state) {
  if (state)
    displaybuffer[2] = 0xFF;
  else
    displaybuffer[2] = 0;
}

void Adafruit_7segment::writeDigitNum(uint8_t d, uint8_t num, boolean dot) {
  if (d > 4) return;

  writeDigitRaw(d, numbertable[num] | (dot << 7));
}

void Adafruit_7segment::print(long n, int base)
{
  printNumber(n, base);
}

void Adafruit_7segment::printNumber(long n, uint8_t base)
{
    printFloat(n, 0, base);
}

void Adafruit_7segment::printFloat(double n, uint8_t fracDigits, uint8_t base)
{
  uint8_t numericDigits = 4;   // available digits on display
  boolean isNegative = false;  // true if the number is negative

  // is the number negative?
  if(n < 0) {
    isNegative = true;  // need to draw sign later
    --numericDigits;    // the sign will take up one digit
    n *= -1;            // pretend the number is positive
  }

  // calculate the factor required to shift all fractional digits
  // into the integer part of the number
  double toIntFactor = 1.0;
  for(int i = 0; i < fracDigits; ++i) toIntFactor *= base;

  // create integer containing digits to display by applying
  // shifting factor and rounding adjustment
  uint32_t displayNumber = n * toIntFactor + 0.5;

  // calculate upper bound on displayNumber given
  // available digits on display
  uint32_t tooBig = 1;
  for(int i = 0; i < numericDigits; ++i) tooBig *= base;

  // if displayNumber is too large, try fewer fractional digits
  while(displayNumber >= tooBig) {
    --fracDigits;
    toIntFactor /= base;
    displayNumber = n * toIntFactor + 0.5;
  }

  // did toIntFactor shift the decimal off the display?
  if (toIntFactor < 1) {
    printError();
  } else {
    // otherwise, display the number
    int8_t displayPos = 4;

    if (displayNumber)  //if displayNumber is not 0
    {
      for(uint8_t i = 0; displayNumber; ++i) {
        boolean displayDecimal = (fracDigits != 0 && i == fracDigits);
        writeDigitNum(displayPos--, displayNumber % base, displayDecimal);
        if(displayPos == 2) writeDigitRaw(displayPos--, 0x00);
        displayNumber /= base;
      }
    }
    else {
      writeDigitNum(displayPos--, 0, false);
    }

    // display negative sign if negative
    if(isNegative) writeDigitRaw(displayPos--, 0x40);

    // clear remaining display positions
    while(displayPos >= 0) writeDigitRaw(displayPos--, 0x00);
  }
}

void Adafruit_7segment::printError(void) {
  for(uint8_t i = 0; i < SEVENSEG_DIGITS; ++i) {
    writeDigitRaw(i, (i == 2 ? 0x00 : 0x40));
  }
}
<|endoftext|>


<commit_before>/*
 *  yosys -- Yosys Open SYnthesis Suite
 *
 *  Copyright (C) 2012  Clifford Wolf <clifford@clifford.at>
 *  Copyright (C) 2019  The Symbiflow Authors
 *
 *  Permission to use, copy, modify, and/or distribute this software for any
 *  purpose with or without fee is hereby granted, provided that the above
 *  copyright notice and this permission notice appear in all copies.
 *
 *  THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 *  WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 *  MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
 *  ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 *  WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 *  ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 *  OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 *
 *  ---
 *
 *   XDC commands + FASM backend.
 *
 *   This plugin operates on the existing design and modifies its structure
 *   based on the content of the XDC (Xilinx Design Constraints) file.
 *   Since the XDC file consists of Tcl commands it is read using Yosys's
 *   tcl command and processed by the new XDC commands imported to the
 *   Tcl interpreter.
 */

#include "kernel/register.h"
#include "kernel/rtlil.h"
#include "kernel/log.h"
#include "../bank_tiles.h"

USING_YOSYS_NAMESPACE
PRIVATE_NAMESPACE_BEGIN

struct WriteFasm : public Backend {
	WriteFasm() : Backend("fasm", "Write out FASM features") {}

	void help() YS_OVERRIDE {
		//   |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
		log("\n");
		log("    write_fasm filename\n");
		log("\n");
		log("Write out a file with vref FASM features\n");
		log("\n");
	}

	void execute(std::ostream *&f, std::string filename,  std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE {
		size_t argidx = 1;
		extra_args(f, filename, args, argidx);
		process_vref(f, design);
	}

	void process_vref(std::ostream *&f, RTLIL::Design* design) {
		RTLIL::Module* top_module(design->top_module());
		if (top_module == nullptr) {
			log("write_fasm: No top module detected\n");
			return;
		}
		// Return if no BANK module exists as this means there are no cells
		if (!design->has(ID(BANK))) {
			return;
		}

		BankTilesMap bank_tiles(get_bank_tiles());
		if (bank_tiles.size()) {
			// Generate a fasm feature associated with the INTERNAL_VREF value per bank
			// e.g. VREF value of 0.675 for bank 34 is associated with tile HCLK_IOI3_X113Y26
			// hence we need to emit the following fasm feature: HCLK_IOI3_X113Y26.VREF.V_675_MV
			for (auto cell : top_module->cells()) {
				if (cell->type != ID(BANK)) continue;
				int bank_number(cell->getParam(ID(NUMBER)).as_int());
				int bank_vref(cell->getParam(ID(INTERNAL_VREF)).as_int());
				*f << "HCLK_IOI3_" << bank_tiles[bank_number] <<".VREF.V_" << bank_vref << "_MV\n";
			}
		}
	}
} WriteFasm;

PRIVATE_NAMESPACE_END
<commit_msg>FASM: Add additional error checking<commit_after>/*
 *  yosys -- Yosys Open SYnthesis Suite
 *
 *  Copyright (C) 2012  Clifford Wolf <clifford@clifford.at>
 *  Copyright (C) 2019  The Symbiflow Authors
 *
 *  Permission to use, copy, modify, and/or distribute this software for any
 *  purpose with or without fee is hereby granted, provided that the above
 *  copyright notice and this permission notice appear in all copies.
 *
 *  THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 *  WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 *  MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
 *  ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 *  WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 *  ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 *  OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 *
 *  ---
 *
 *   FASM backend
 *
 *   This plugin writes out the design's fasm features based on the parameter
 *   annotations on the design cells.
 */

#include "kernel/register.h"
#include "kernel/rtlil.h"
#include "kernel/log.h"
#include "../bank_tiles.h"

USING_YOSYS_NAMESPACE
PRIVATE_NAMESPACE_BEGIN

struct WriteFasm : public Backend {
	WriteFasm() : Backend("fasm", "Write out FASM features") {}

	void help() YS_OVERRIDE {
		//   |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
		log("\n");
		log("    write_fasm filename\n");
		log("\n");
		log("Write out a file with vref FASM features\n");
		log("\n");
	}

	void execute(std::ostream *&f, std::string filename,  std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE {
		size_t argidx = 1;
		extra_args(f, filename, args, argidx);
		process_vref(f, design);
	}

	void process_vref(std::ostream *&f, RTLIL::Design* design) {
		RTLIL::Module* top_module(design->top_module());
		if (top_module == nullptr) {
			log("write_fasm: No top module detected.\n");
			return;
		}
		// Return if no BANK module exists as this means there are no cells
		if (!design->has(ID(BANK))) {
			return;
		}

		BankTilesMap bank_tiles(get_bank_tiles());
		// Generate a fasm feature associated with the INTERNAL_VREF value per bank
		// e.g. VREF value of 0.675 for bank 34 is associated with tile HCLK_IOI3_X113Y26
		// hence we need to emit the following fasm feature: HCLK_IOI3_X113Y26.VREF.V_675_MV
		for (auto cell : top_module->cells()) {
			if (cell->type != ID(BANK)) continue;
			if (bank_tiles.size() == 0) {
				log("write_fasm: No bank tiles available on the target part.\n");
				return;
			}
			int bank_number(cell->getParam(ID(NUMBER)).as_int());
			if (bank_tiles.count(bank_number) == 0) {
				log("write_fasm: No IO bank number %d on the target part.\n", bank_number);
				return;
			}
			int bank_vref(cell->getParam(ID(INTERNAL_VREF)).as_int());
			*f << "HCLK_IOI3_" << bank_tiles[bank_number] <<".VREF.V_" << bank_vref << "_MV\n";
		}
	}
} WriteFasm;

PRIVATE_NAMESPACE_END
<|endoftext|>


<commit_before>#ifndef BUW_Scene_HPP
#define BUW_Scene_HPP
#include <iostream>
#include <string>
#include "color.hpp"
#include "shape.hpp"
#include "ray.hpp"
#include "material.hpp"
#include "camera.hpp"
#include "light_source.hpp"
#include "renderer.hpp"
#include <map>
#include <vector>

struct Scene
{
	Scene(): ambient(), cam(), render(0.0, 0.0, ""){};
	Scene(Color const& ambient_color, Camera const& camera, Renderer const& renderer): ambient(ambient_color), cam(camera), render(renderer){};
	std::map<std::string, Material> material;
	std::vector<Shape> shapes; // shared pointer
	std::vector<Light_source> lights;
	Color ambient;
	Camera cam;
	Renderer render;

};

#endif // #ifndef BUW_SCENE_HPP<commit_msg>Shapes in der Scene sind Shared Pointer<commit_after>#ifndef BUW_Scene_HPP
#define BUW_Scene_HPP
#include <iostream>
#include <string>
#include "color.hpp"
#include "shape.hpp"
#include "ray.hpp"
#include "material.hpp"
#include "camera.hpp"
#include "light_source.hpp"
#include "renderer.hpp"
#include <map>
#include <vector>
#include <memory>

struct Scene
{
	Scene(): ambient(), cam(), render(0.0, 0.0, ""){};
	Scene(Color const& ambient_color, Camera const& camera, Renderer const& renderer): ambient(ambient_color), cam(camera), render(renderer){};
	std::map<std::string, Material> material;
	std::vector<shared_ptr Shape> shapes;
	std::vector<Light_source> lights;
	Color ambient;
	Camera cam;
	Renderer render;

};

#endif // #ifndef BUW_SCENE_HPP<|endoftext|>


<commit_before>// Copyright (c) 2015, Matthew Malensek.
// Distributed under the BSD 2-Clause License (see LICENSE.txt for details)

#include "EjectOSD.h"

#include <Dbt.h>

#include "../HotkeyInfo.h"
#include "../Monitor.h"
#include "../NotifyIcon.h"
#include "../Skin/OSDComponent.h"
#include "../Skin/Skin.h"
#include "../Skin/SkinManager.h"

EjectOSD::EjectOSD() :
OSD(L"3RVX-EjectDispatcher"),
_mWnd(L"3RVX-EjectOSD", L"3RVX-EjectOSD") {

    SkinManager *skin = SkinManager::Instance();
    _mWnd.BackgroundImage(skin->EjectOSD()->background);
    _mWnd.EnableGlass(skin->EjectOSD()->mask);
    _mWnd.Update();

    OSD::InitMeterWnd(_mWnd);

    //TODO: this needs to be differentiated from the volume OSD.
    if (_settings->NotifyIconEnabled()) {
        _iconImages = skin->VolumeIconset();
        if (_iconImages.size() > 0) {
            _icon = new NotifyIcon(Window::Handle(), L"Eject", _iconImages[0]);
        }
    }

    _menu = CreatePopupMenu();
    //_menuThread = std::thread();
    UpdateDriveMenu();

}

void EjectOSD::UpdateDriveMenu() {
    DWORD drives = GetLogicalDrives();
    /* Get the most significant bit of the drive bitset */
    DWORD msb = (DWORD) log2(drives);
    for (DWORD i = 0; i < msb; ++i, drives >>= 1) {
        if (drives & 0x1) {
            wchar_t letter = (wchar_t) i + 65;
            wchar_t drivePath[] = L" :\\";
            drivePath[0] = letter;
            UINT type = GetDriveType(drivePath);
        }
    }
}

void EjectOSD::EjectDrive(std::wstring driveLetter) {
    std::wstring name = L"\\\\.\\" + driveLetter + L":";
    CLOG(L"Ejecting %s", name.c_str());

    HANDLE dev = CreateFile(
        name.c_str(),
        GENERIC_READ | GENERIC_WRITE,
        FILE_SHARE_READ | FILE_SHARE_WRITE,
        NULL,
        OPEN_EXISTING,
        NULL,
        NULL);

    if (dev == INVALID_HANDLE_VALUE) {
        CLOG(L"Failed to get device handle");
        return;
    }

    DWORD bytesReturned = 0;

    DeviceIoControl(dev, FSCTL_LOCK_VOLUME,
        NULL, NULL, NULL, NULL, &bytesReturned, NULL);

    PREVENT_MEDIA_REMOVAL pmr = { 0 };
    pmr.PreventMediaRemoval = FALSE;
    DeviceIoControl(dev, IOCTL_STORAGE_MEDIA_REMOVAL,
        &pmr, sizeof(PREVENT_MEDIA_REMOVAL), NULL, 0, &bytesReturned, NULL);

    DeviceIoControl(dev, FSCTL_DISMOUNT_VOLUME,
        NULL, NULL, NULL, NULL, &bytesReturned, NULL);

    BOOL ejected = FALSE;
    ejected = DeviceIoControl(dev, IOCTL_STORAGE_EJECT_MEDIA,
        NULL, NULL, NULL, NULL, &bytesReturned, NULL);

    if (ejected != FALSE) {
        std::wstring rootPath = driveLetter + L":\\";
        if (GetDriveType(rootPath.c_str()) != DRIVE_CDROM) {
            int driveBit = (int) pow(2, (driveLetter.at(0) - 65));
            _ignoreDrives |= driveBit;
            CLOG(L"Added drive bit %d to ignore list", driveBit);
        }
        if (OSD::Enabled()) {
            HideOthers(Eject);
            _mWnd.Show();
        }
    }

    CloseHandle(dev);
}

void EjectOSD::Hide() {
    _mWnd.Hide(false);
}

void EjectOSD::ProcessHotkeys(HotkeyInfo &hki) {
    switch (hki.action) {
    case HotkeyInfo::EjectDrive:
        if (hki.args.size() > 0) {
            EjectDrive(hki.args[0]);
        }
        break;

    case HotkeyInfo::EjectLastDisk:
        if (_latestDrive != 0) {
            wchar_t letter = MaskToDriveLetter(_latestDrive);
            std::wstring lStr(1, letter);
            EjectDrive(lStr);
            _latestDrive = 0;
        }

        break;
    }
}

LRESULT
EjectOSD::WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) {
    if (message == WM_DEVICECHANGE && wParam == DBT_DEVICEREMOVECOMPLETE) {
        PDEV_BROADCAST_HDR lpdb = (PDEV_BROADCAST_HDR) lParam;
        if (lpdb->dbch_devicetype == DBT_DEVTYP_VOLUME) {
            PDEV_BROADCAST_VOLUME lpdbv = (PDEV_BROADCAST_VOLUME) lpdb;

            DWORD driveMask = lpdbv->dbcv_unitmask;
            CLOG(L"Eject notification received for drive %c:",
                MaskToDriveLetter(driveMask));

            if (driveMask & _ignoreDrives) {
                CLOG(L"Drive already ejected by a hotkey; not displaying OSD.");
                _ignoreDrives ^= driveMask;
            } else if (OSD::Enabled()) {
                HideOthers(Eject);
                _mWnd.Show();
            }

            if (_latestDrive == driveMask) {
                _latestDrive = 0;
            }
        }
    }

    if (message == WM_DEVICECHANGE && wParam == DBT_DEVICEARRIVAL) {
        PDEV_BROADCAST_HDR lpdb = (PDEV_BROADCAST_HDR) lParam;
        if (lpdb->dbch_devicetype == DBT_DEVTYP_VOLUME) {
            PDEV_BROADCAST_VOLUME lpdbv = (PDEV_BROADCAST_VOLUME) lpdb;

            if (lpdbv->dbcv_flags != DBTF_NET) {
                _latestDrive = lpdbv->dbcv_unitmask;

                CLOG(L"Media inserted in drive %c:",
                    MaskToDriveLetter(_latestDrive));
            }
        }
    }

    return DefWindowProc(hWnd, message, wParam, lParam);
}

DWORD EjectOSD::DriveLetterToMask(wchar_t letter) {
    if (letter < 65 || letter > 90) {
        return 0;
    }

    return (DWORD) pow(2, (letter - 65));
}

wchar_t EjectOSD::MaskToDriveLetter(DWORD mask) {
    return (wchar_t) (log2(mask) + 65);
}

void EjectOSD::OnDisplayChange() {
    InitMeterWnd(_mWnd);
}
<commit_msg>Simplify drive detection<commit_after>// Copyright (c) 2015, Matthew Malensek.
// Distributed under the BSD 2-Clause License (see LICENSE.txt for details)

#include "EjectOSD.h"

#include <Dbt.h>

#include "../DiskInfo.h"
#include "../HotkeyInfo.h"
#include "../Monitor.h"
#include "../NotifyIcon.h"
#include "../Skin/OSDComponent.h"
#include "../Skin/Skin.h"
#include "../Skin/SkinManager.h"

EjectOSD::EjectOSD() :
OSD(L"3RVX-EjectDispatcher"),
_mWnd(L"3RVX-EjectOSD", L"3RVX-EjectOSD") {

    SkinManager *skin = SkinManager::Instance();
    _mWnd.BackgroundImage(skin->EjectOSD()->background);
    _mWnd.EnableGlass(skin->EjectOSD()->mask);
    _mWnd.Update();

    OSD::InitMeterWnd(_mWnd);

    //TODO: this needs to be differentiated from the volume OSD.
    if (_settings->NotifyIconEnabled()) {
        _iconImages = skin->VolumeIconset();
        if (_iconImages.size() > 0) {
            _icon = new NotifyIcon(Window::Handle(), L"Eject", _iconImages[0]);
        }
    }

    _menu = CreatePopupMenu();
    //_menuThread = std::thread();
    UpdateDriveMenu();

}

void EjectOSD::UpdateDriveMenu() {
    DWORD drives = GetLogicalDrives();
    /* Get the most significant bit of the drive bitset */
    DWORD msb = (DWORD) log2(drives);
    for (DWORD i = 0; i < msb; ++i, drives >>= 1) {
        if (drives & 0x1) {
            wchar_t letter = (wchar_t) i + 65;
            wchar_t drivePath[] = L" :\\";
            drivePath[0] = letter;
            UINT type = GetDriveType(drivePath);

            DiskInfo di(letter);
            wchar_t driveName[256] = { 0 };
            int result = GetVolumeInformation(drivePath, driveName, 256,
                NULL, NULL, NULL, NULL, NULL);
            CLOG(L"Drive: %c - %s [%d]", letter, driveName, result);
        }
    }
}

void EjectOSD::EjectDrive(std::wstring driveLetter) {
    std::wstring name = L"\\\\.\\" + driveLetter + L":";
    CLOG(L"Ejecting %s", name.c_str());

    HANDLE dev = CreateFile(
        name.c_str(),
        GENERIC_READ | GENERIC_WRITE,
        FILE_SHARE_READ | FILE_SHARE_WRITE,
        NULL,
        OPEN_EXISTING,
        NULL,
        NULL);

    if (dev == INVALID_HANDLE_VALUE) {
        CLOG(L"Failed to get device handle");
        return;
    }

    DWORD bytesReturned = 0;

    DeviceIoControl(dev, FSCTL_LOCK_VOLUME,
        NULL, NULL, NULL, NULL, &bytesReturned, NULL);

    PREVENT_MEDIA_REMOVAL pmr = { 0 };
    pmr.PreventMediaRemoval = FALSE;
    DeviceIoControl(dev, IOCTL_STORAGE_MEDIA_REMOVAL,
        &pmr, sizeof(PREVENT_MEDIA_REMOVAL), NULL, 0, &bytesReturned, NULL);

    DeviceIoControl(dev, FSCTL_DISMOUNT_VOLUME,
        NULL, NULL, NULL, NULL, &bytesReturned, NULL);

    BOOL ejected = FALSE;
    ejected = DeviceIoControl(dev, IOCTL_STORAGE_EJECT_MEDIA,
        NULL, NULL, NULL, NULL, &bytesReturned, NULL);

    if (ejected != FALSE) {
        std::wstring rootPath = driveLetter + L":\\";
        if (GetDriveType(rootPath.c_str()) != DRIVE_CDROM) {
            int driveBit = (int) pow(2, (driveLetter.at(0) - 65));
            _ignoreDrives |= driveBit;
            CLOG(L"Added drive bit %d to ignore list", driveBit);
        }
        if (OSD::Enabled()) {
            HideOthers(Eject);
            _mWnd.Show();
        }
    }

    CloseHandle(dev);
}

void EjectOSD::Hide() {
    _mWnd.Hide(false);
}

void EjectOSD::ProcessHotkeys(HotkeyInfo &hki) {
    switch (hki.action) {
    case HotkeyInfo::EjectDrive:
        if (hki.args.size() > 0) {
            EjectDrive(hki.args[0]);
        }
        break;

    case HotkeyInfo::EjectLastDisk:
        if (_latestDrive != 0) {
            wchar_t letter = MaskToDriveLetter(_latestDrive);
            std::wstring lStr(1, letter);
            EjectDrive(lStr);
            _latestDrive = 0;
        }

        break;
    }
}

LRESULT
EjectOSD::WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) {
    if (message == WM_DEVICECHANGE && wParam == DBT_DEVICEREMOVECOMPLETE) {
        PDEV_BROADCAST_HDR lpdb = (PDEV_BROADCAST_HDR) lParam;
        if (lpdb->dbch_devicetype == DBT_DEVTYP_VOLUME) {
            PDEV_BROADCAST_VOLUME lpdbv = (PDEV_BROADCAST_VOLUME) lpdb;

            DWORD driveMask = lpdbv->dbcv_unitmask;
            CLOG(L"Eject notification received for drive %c:",
                MaskToDriveLetter(driveMask));

            if (driveMask & _ignoreDrives) {
                CLOG(L"Drive already ejected by a hotkey; not displaying OSD.");
                _ignoreDrives ^= driveMask;
            } else if (OSD::Enabled()) {
                HideOthers(Eject);
                _mWnd.Show();
            }

            if (_latestDrive == driveMask) {
                _latestDrive = 0;
            }
        }
    }

    if (message == WM_DEVICECHANGE && wParam == DBT_DEVICEARRIVAL) {
        PDEV_BROADCAST_HDR lpdb = (PDEV_BROADCAST_HDR) lParam;
        if (lpdb->dbch_devicetype == DBT_DEVTYP_VOLUME) {
            PDEV_BROADCAST_VOLUME lpdbv = (PDEV_BROADCAST_VOLUME) lpdb;

            if (lpdbv->dbcv_flags != DBTF_NET) {
                _latestDrive = lpdbv->dbcv_unitmask;

                CLOG(L"Media inserted in drive %c:",
                    MaskToDriveLetter(_latestDrive));
            }
        }
    }

    return DefWindowProc(hWnd, message, wParam, lParam);
}

DWORD EjectOSD::DriveLetterToMask(wchar_t letter) {
    if (letter < 65 || letter > 90) {
        return 0;
    }

    return (DWORD) pow(2, (letter - 65));
}

wchar_t EjectOSD::MaskToDriveLetter(DWORD mask) {
    return (wchar_t) (log2(mask) + 65);
}

void EjectOSD::OnDisplayChange() {
    InitMeterWnd(_mWnd);
}
<|endoftext|>