<commit_before>/*
 * Copyright (C) 2008-2014 The QXmpp developers
 *
 * Author:
 *  Jeremy Lainé
 *
 * Source:
 *  https://github.com/qxmpp-project/qxmpp
 *
 * This file is a part of QXmpp library.
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 */

#include <QObject>
#include "QXmppVCardIq.h"
#include "util.h"

class tst_QXmppVCardIq : public QObject
{
    Q_OBJECT

private slots:
    void testAddress_data();
    void testAddress();
    void testEmail_data();
    void testEmail();
    void testPhone_data();
    void testPhone();
    void testVCard();
};

void tst_QXmppVCardIq::testAddress_data()
{
    QTest::addColumn<QByteArray>("xml");
    QTest::addColumn<int>("type");
    QTest::addColumn<QString>("country");
    QTest::addColumn<QString>("locality");
    QTest::addColumn<QString>("postcode");
    QTest::addColumn<QString>("region");
    QTest::addColumn<QString>("street");

    QTest::newRow("none") << QByteArray("<ADR/>") << int(QXmppVCardAddress::None) << "" << "" << "" << "" << "";
    QTest::newRow("HOME") << QByteArray("<ADR><HOME/></ADR>") << int(QXmppVCardAddress::Home) << "" << "" << "" << "" << "";
    QTest::newRow("WORK") << QByteArray("<ADR><WORK/></ADR>") << int(QXmppVCardAddress::Work) << "" << "" << "" << "" << "";
    QTest::newRow("POSTAL") << QByteArray("<ADR><POSTAL/></ADR>") << int(QXmppVCardAddress::Postal) << "" << "" << "" << "" << "";
    QTest::newRow("PREF") << QByteArray("<ADR><PREF/></ADR>") << int(QXmppVCardAddress::Preferred) << "" << "" << "" << "" << "";

    QTest::newRow("country") << QByteArray("<ADR><CTRY>France</CTRY></ADR>") << int(QXmppVCardAddress::None) << "France" << "" << "" << "" << "";
    QTest::newRow("locality") << QByteArray("<ADR><LOCALITY>Paris</LOCALITY></ADR>") << int(QXmppVCardAddress::None) << "" << "Paris" << "" << "" << "";
    QTest::newRow("postcode") << QByteArray("<ADR><PCODE>75008</PCODE></ADR>") << int(QXmppVCardAddress::None) << "" << "" << "75008" << "" << "";
    QTest::newRow("region") << QByteArray("<ADR><REGION>Ile de France</REGION></ADR>") << int(QXmppVCardAddress::None) << "" << "" << "" << "Ile de France" << "";
    QTest::newRow("street") << QByteArray("<ADR><STREET>55 rue du faubourg Saint-Honoré</STREET></ADR>") << int(QXmppVCardAddress::None) << "" << "" << "" << "" << QString::fromUtf8("55 rue du faubourg Saint-Honoré");
}

void tst_QXmppVCardIq::testAddress()
{
    QFETCH(QByteArray, xml);
    QFETCH(int, type);
    QFETCH(QString, country);
    QFETCH(QString, locality);
    QFETCH(QString, postcode);
    QFETCH(QString, region);
    QFETCH(QString, street);

    QXmppVCardAddress address;
    parsePacket(address, xml);
    QCOMPARE(int(address.type()), type);
    QCOMPARE(address.country(), country);
    QCOMPARE(address.locality(), locality);
    QCOMPARE(address.postcode(), postcode);
    QCOMPARE(address.region(), region);
    QCOMPARE(address.street(), street);
    serializePacket(address, xml);
}

void tst_QXmppVCardIq::testEmail_data()
{
    QTest::addColumn<QByteArray>("xml");
    QTest::addColumn<int>("type");

    QTest::newRow("none") << QByteArray("<EMAIL><USERID>foo.bar@example.com</USERID></EMAIL>") << int(QXmppVCardEmail::None);
    QTest::newRow("HOME") << QByteArray("<EMAIL><HOME/><USERID>foo.bar@example.com</USERID></EMAIL>") << int(QXmppVCardEmail::Home);
    QTest::newRow("WORK") << QByteArray("<EMAIL><WORK/><USERID>foo.bar@example.com</USERID></EMAIL>") << int(QXmppVCardEmail::Work);
    QTest::newRow("INTERNET") << QByteArray("<EMAIL><INTERNET/><USERID>foo.bar@example.com</USERID></EMAIL>") << int(QXmppVCardEmail::Internet);
    QTest::newRow("X400") << QByteArray("<EMAIL><X400/><USERID>foo.bar@example.com</USERID></EMAIL>") << int(QXmppVCardEmail::X400);
    QTest::newRow("PREF") << QByteArray("<EMAIL><PREF/><USERID>foo.bar@example.com</USERID></EMAIL>") << int(QXmppVCardEmail::Preferred);
    QTest::newRow("all") << QByteArray("<EMAIL><HOME/><WORK/><INTERNET/><PREF/><X400/><USERID>foo.bar@example.com</USERID></EMAIL>") << int(QXmppVCardEmail::Home | QXmppVCardEmail::Work | QXmppVCardEmail::Internet | QXmppVCardEmail::Preferred | QXmppVCardEmail::X400);
}

void tst_QXmppVCardIq::testEmail()
{
    QFETCH(QByteArray, xml);
    QFETCH(int, type);

    QXmppVCardEmail email;
    parsePacket(email, xml);
    QCOMPARE(email.address(), QLatin1String("foo.bar@example.com"));
    QCOMPARE(int(email.type()), type);
    serializePacket(email, xml);
}

void tst_QXmppVCardIq::testPhone_data()
{
    QTest::addColumn<QByteArray>("xml");
    QTest::addColumn<int>("type");

    QTest::newRow("none") << QByteArray("<PHONE><NUMBER>12345</NUMBER></PHONE>") << int(QXmppVCardPhone::None);
    QTest::newRow("HOME") << QByteArray("<PHONE><HOME/><NUMBER>12345</NUMBER></PHONE>") << int(QXmppVCardPhone::Home);
    QTest::newRow("WORK") << QByteArray("<PHONE><WORK/><NUMBER>12345</NUMBER></PHONE>") << int(QXmppVCardPhone::Work);
    QTest::newRow("VOICE") << QByteArray("<PHONE><VOICE/><NUMBER>12345</NUMBER></PHONE>") << int(QXmppVCardPhone::Voice);
    QTest::newRow("FAX") << QByteArray("<PHONE><FAX/><NUMBER>12345</NUMBER></PHONE>") << int(QXmppVCardPhone::Fax);
    QTest::newRow("PAGER") << QByteArray("<PHONE><PAGER/><NUMBER>12345</NUMBER></PHONE>") << int(QXmppVCardPhone::Pager);
    QTest::newRow("MSG") << QByteArray("<PHONE><MSG/><NUMBER>12345</NUMBER></PHONE>") << int(QXmppVCardPhone::Messaging);
    QTest::newRow("CELL") << QByteArray("<PHONE><CELL/><NUMBER>12345</NUMBER></PHONE>") << int(QXmppVCardPhone::Cell);
    QTest::newRow("VIDEO") << QByteArray("<PHONE><VIDEO/><NUMBER>12345</NUMBER></PHONE>") << int(QXmppVCardPhone::Video);
    QTest::newRow("BBS") << QByteArray("<PHONE><BBS/><NUMBER>12345</NUMBER></PHONE>") << int(QXmppVCardPhone::BBS);
    QTest::newRow("MODEM") << QByteArray("<PHONE><MODEM/><NUMBER>12345</NUMBER></PHONE>") << int(QXmppVCardPhone::Modem);
    QTest::newRow("IDSN") << QByteArray("<PHONE><ISDN/><NUMBER>12345</NUMBER></PHONE>") << int(QXmppVCardPhone::ISDN);
    QTest::newRow("PCS") << QByteArray("<PHONE><PCS/><NUMBER>12345</NUMBER></PHONE>") << int(QXmppVCardPhone::PCS);
    QTest::newRow("PREF") << QByteArray("<PHONE><PREF/><NUMBER>12345</NUMBER></PHONE>") << int(QXmppVCardPhone::Preferred);
}

void tst_QXmppVCardIq::testPhone()
{
    QFETCH(QByteArray, xml);
    QFETCH(int, type);

    QXmppVCardPhone phone;
    parsePacket(phone, xml);
    QCOMPARE(phone.number(), QLatin1String("12345"));
    QCOMPARE(int(phone.type()), type);
    serializePacket(phone, xml);
}

void tst_QXmppVCardIq::testVCard()
{
    const QByteArray xml(
        "<iq id=\"vcard1\" type=\"set\">"
        "<vCard xmlns=\"vcard-temp\">"
        "<ADR><CTRY>France</CTRY></ADR>"
        "<BDAY>1983-09-14</BDAY>"
        "<DESC>I like XMPP.</DESC>"
        "<EMAIL><INTERNET/><USERID>foo.bar@example.com</USERID></EMAIL>"
        "<FN>Foo Bar!</FN>"
        "<NICKNAME>FooBar</NICKNAME>"
        "<N><GIVEN>Foo</GIVEN><FAMILY>Wiz</FAMILY><MIDDLE>Baz</MIDDLE></N>"
        "<PHONE><HOME/><NUMBER>12345</NUMBER></PHONE>"
        "<PHONE><WORK/><NUMBER>67890</NUMBER></PHONE>"
        "<PHOTO>"
            "<TYPE>image/png</TYPE>"
            "<BINVAL>"
            "iVBORw0KGgoAAAANSUhEUgAAAAgAAAAICAIAAABLbSncAAAAAXNSR0IArs4c6QAAAAlwSFlzAAA"
            "UIgAAFCIBjw1HyAAAAAd0SU1FB9oIHQInNvuJovgAAAAiSURBVAjXY2TQ+s/AwMDAwPD/GiMDlP"
            "WfgYGBiQEHGJwSAK2BBQ1f3uvpAAAAAElFTkSuQmCC"
            "</BINVAL>"
        "</PHOTO>"
        "<URL>https://github.com/qxmpp-project/qxmpp/</URL>"
        "<ORG>"
            "<ORGNAME>QXmpp foundation</ORGNAME>"
            "<ORGUNIT>Main QXmpp dev unit</ORGUNIT>"
        "</ORG>"
        "<TITLE>Executive Director</TITLE>"
        "<ROLE>Patron Saint</ROLE>"
        "</vCard>"
        "</iq>");

    QXmppVCardIq vcard;
    parsePacket(vcard, xml);
    QCOMPARE(vcard.addresses().size(), 1);
    QCOMPARE(vcard.addresses()[0].country(), QLatin1String("France"));
    QCOMPARE(int(vcard.addresses()[0].type()), int(QXmppVCardEmail::None));
    QCOMPARE(vcard.birthday(), QDate(1983, 9, 14));
    QCOMPARE(vcard.description(), QLatin1String("I like XMPP."));
    QCOMPARE(vcard.email(), QLatin1String("foo.bar@example.com"));
    QCOMPARE(vcard.emails().size(), 1);
    QCOMPARE(vcard.emails()[0].address(), QLatin1String("foo.bar@example.com"));
    QCOMPARE(int(vcard.emails()[0].type()), int(QXmppVCardEmail::Internet));
    QCOMPARE(vcard.nickName(), QLatin1String("FooBar"));
    QCOMPARE(vcard.fullName(), QLatin1String("Foo Bar!"));
    QCOMPARE(vcard.firstName(), QLatin1String("Foo"));
    QCOMPARE(vcard.middleName(), QLatin1String("Baz"));
    QCOMPARE(vcard.lastName(), QLatin1String("Wiz"));
    QCOMPARE(vcard.phones().size(), 2);
    QCOMPARE(vcard.phones()[0].number(), QLatin1String("12345"));
    QCOMPARE(int(vcard.phones()[0].type()), int(QXmppVCardEmail::Home));
    QCOMPARE(vcard.phones()[1].number(), QLatin1String("67890"));
    QCOMPARE(int(vcard.phones()[1].type()), int(QXmppVCardEmail::Work));
    QCOMPARE(vcard.photo(), QByteArray::fromBase64(
        "iVBORw0KGgoAAAANSUhEUgAAAAgAAAAICAIAAABLbSncAAAAAXNSR0IArs4c6QAAAAlwSFlzAAA"
        "UIgAAFCIBjw1HyAAAAAd0SU1FB9oIHQInNvuJovgAAAAiSURBVAjXY2TQ+s/AwMDAwPD/GiMDlP"
        "WfgYGBiQEHGJwSAK2BBQ1f3uvpAAAAAElFTkSuQmCC"));
    QCOMPARE(vcard.photoType(), QLatin1String("image/png"));
    QCOMPARE(vcard.url(), QLatin1String("https://github.com/qxmpp-project/qxmpp/"));

    const QXmppVCardOrganization &orgInfo = vcard.organization();
    QCOMPARE(orgInfo.organization(), QLatin1String("QXmpp foundation"));
    QCOMPARE(orgInfo.unit(), QLatin1String("Main QXmpp dev unit"));
    QCOMPARE(orgInfo.title(), QLatin1String("Executive Director"));
    QCOMPARE(orgInfo.role(), QLatin1String("Patron Saint"));

    serializePacket(vcard, xml);
}

QTEST_MAIN(tst_QXmppVCardIq)
#include "tst_qxmppvcardiq.moc"
<commit_msg>Covered eq operators for QXmppVCardAddress with tests.<commit_after>/*
 * Copyright (C) 2008-2014 The QXmpp developers
 *
 * Author:
 *  Jeremy Lainé
 *
 * Source:
 *  https://github.com/qxmpp-project/qxmpp
 *
 * This file is a part of QXmpp library.
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 */

#include <QObject>
#include "QXmppVCardIq.h"
#include "util.h"

class tst_QXmppVCardIq : public QObject
{
    Q_OBJECT

private slots:
    void testAddress_data();
    void testAddress();
    void testEmail_data();
    void testEmail();
    void testPhone_data();
    void testPhone();
    void testVCard();
};

void tst_QXmppVCardIq::testAddress_data()
{
    QTest::addColumn<QByteArray>("xml");
    QTest::addColumn<int>("type");
    QTest::addColumn<QString>("country");
    QTest::addColumn<QString>("locality");
    QTest::addColumn<QString>("postcode");
    QTest::addColumn<QString>("region");
    QTest::addColumn<QString>("street");
    QTest::addColumn<bool>("equalsEmpty");

    QTest::newRow("none") << QByteArray("<ADR/>") << int(QXmppVCardAddress::None) << "" << "" << "" << "" << "" << true;
    QTest::newRow("HOME") << QByteArray("<ADR><HOME/></ADR>") << int(QXmppVCardAddress::Home) << "" << "" << "" << "" << "" << false;
    QTest::newRow("WORK") << QByteArray("<ADR><WORK/></ADR>") << int(QXmppVCardAddress::Work) << "" << "" << "" << "" << "" << false;
    QTest::newRow("POSTAL") << QByteArray("<ADR><POSTAL/></ADR>") << int(QXmppVCardAddress::Postal) << "" << "" << "" << "" << "" << false;
    QTest::newRow("PREF") << QByteArray("<ADR><PREF/></ADR>") << int(QXmppVCardAddress::Preferred) << "" << "" << "" << "" << "" << false;

    QTest::newRow("country") << QByteArray("<ADR><CTRY>France</CTRY></ADR>") << int(QXmppVCardAddress::None) << "France" << "" << "" << "" << "" << false;
    QTest::newRow("locality") << QByteArray("<ADR><LOCALITY>Paris</LOCALITY></ADR>") << int(QXmppVCardAddress::None) << "" << "Paris" << "" << "" << "" << false;
    QTest::newRow("postcode") << QByteArray("<ADR><PCODE>75008</PCODE></ADR>") << int(QXmppVCardAddress::None) << "" << "" << "75008" << "" << "" << false;
    QTest::newRow("region") << QByteArray("<ADR><REGION>Ile de France</REGION></ADR>") << int(QXmppVCardAddress::None) << "" << "" << "" << "Ile de France" << "" << false;
    QTest::newRow("street") << QByteArray("<ADR><STREET>55 rue du faubourg Saint-Honoré</STREET></ADR>") << int(QXmppVCardAddress::None) << "" << "" << "" << "" << QString::fromUtf8("55 rue du faubourg Saint-Honoré") << false;
}

void tst_QXmppVCardIq::testAddress()
{
    QFETCH(QByteArray, xml);
    QFETCH(int, type);
    QFETCH(QString, country);
    QFETCH(QString, locality);
    QFETCH(QString, postcode);
    QFETCH(QString, region);
    QFETCH(QString, street);
    QFETCH(bool, equalsEmpty);

    QXmppVCardAddress address;
    parsePacket(address, xml);
    QCOMPARE(int(address.type()), type);
    QCOMPARE(address.country(), country);
    QCOMPARE(address.locality(), locality);
    QCOMPARE(address.postcode(), postcode);
    QCOMPARE(address.region(), region);
    QCOMPARE(address.street(), street);
    serializePacket(address, xml);

    QXmppVCardAddress addressCopy = address;
    QVERIFY2(addressCopy == address, "QXmppVCardAddres::operator==() fails");
    QVERIFY2(!(addressCopy != address), "QXmppVCardAddres::operator!=() fails");

    QXmppVCardAddress emptyAddress;
    QCOMPARE(emptyAddress == address, equalsEmpty);
    QCOMPARE(emptyAddress != address, !equalsEmpty);
}

void tst_QXmppVCardIq::testEmail_data()
{
    QTest::addColumn<QByteArray>("xml");
    QTest::addColumn<int>("type");

    QTest::newRow("none") << QByteArray("<EMAIL><USERID>foo.bar@example.com</USERID></EMAIL>") << int(QXmppVCardEmail::None);
    QTest::newRow("HOME") << QByteArray("<EMAIL><HOME/><USERID>foo.bar@example.com</USERID></EMAIL>") << int(QXmppVCardEmail::Home);
    QTest::newRow("WORK") << QByteArray("<EMAIL><WORK/><USERID>foo.bar@example.com</USERID></EMAIL>") << int(QXmppVCardEmail::Work);
    QTest::newRow("INTERNET") << QByteArray("<EMAIL><INTERNET/><USERID>foo.bar@example.com</USERID></EMAIL>") << int(QXmppVCardEmail::Internet);
    QTest::newRow("X400") << QByteArray("<EMAIL><X400/><USERID>foo.bar@example.com</USERID></EMAIL>") << int(QXmppVCardEmail::X400);
    QTest::newRow("PREF") << QByteArray("<EMAIL><PREF/><USERID>foo.bar@example.com</USERID></EMAIL>") << int(QXmppVCardEmail::Preferred);
    QTest::newRow("all") << QByteArray("<EMAIL><HOME/><WORK/><INTERNET/><PREF/><X400/><USERID>foo.bar@example.com</USERID></EMAIL>") << int(QXmppVCardEmail::Home | QXmppVCardEmail::Work | QXmppVCardEmail::Internet | QXmppVCardEmail::Preferred | QXmppVCardEmail::X400);
}

void tst_QXmppVCardIq::testEmail()
{
    QFETCH(QByteArray, xml);
    QFETCH(int, type);

    QXmppVCardEmail email;
    parsePacket(email, xml);
    QCOMPARE(email.address(), QLatin1String("foo.bar@example.com"));
    QCOMPARE(int(email.type()), type);
    serializePacket(email, xml);
}

void tst_QXmppVCardIq::testPhone_data()
{
    QTest::addColumn<QByteArray>("xml");
    QTest::addColumn<int>("type");

    QTest::newRow("none") << QByteArray("<PHONE><NUMBER>12345</NUMBER></PHONE>") << int(QXmppVCardPhone::None);
    QTest::newRow("HOME") << QByteArray("<PHONE><HOME/><NUMBER>12345</NUMBER></PHONE>") << int(QXmppVCardPhone::Home);
    QTest::newRow("WORK") << QByteArray("<PHONE><WORK/><NUMBER>12345</NUMBER></PHONE>") << int(QXmppVCardPhone::Work);
    QTest::newRow("VOICE") << QByteArray("<PHONE><VOICE/><NUMBER>12345</NUMBER></PHONE>") << int(QXmppVCardPhone::Voice);
    QTest::newRow("FAX") << QByteArray("<PHONE><FAX/><NUMBER>12345</NUMBER></PHONE>") << int(QXmppVCardPhone::Fax);
    QTest::newRow("PAGER") << QByteArray("<PHONE><PAGER/><NUMBER>12345</NUMBER></PHONE>") << int(QXmppVCardPhone::Pager);
    QTest::newRow("MSG") << QByteArray("<PHONE><MSG/><NUMBER>12345</NUMBER></PHONE>") << int(QXmppVCardPhone::Messaging);
    QTest::newRow("CELL") << QByteArray("<PHONE><CELL/><NUMBER>12345</NUMBER></PHONE>") << int(QXmppVCardPhone::Cell);
    QTest::newRow("VIDEO") << QByteArray("<PHONE><VIDEO/><NUMBER>12345</NUMBER></PHONE>") << int(QXmppVCardPhone::Video);
    QTest::newRow("BBS") << QByteArray("<PHONE><BBS/><NUMBER>12345</NUMBER></PHONE>") << int(QXmppVCardPhone::BBS);
    QTest::newRow("MODEM") << QByteArray("<PHONE><MODEM/><NUMBER>12345</NUMBER></PHONE>") << int(QXmppVCardPhone::Modem);
    QTest::newRow("IDSN") << QByteArray("<PHONE><ISDN/><NUMBER>12345</NUMBER></PHONE>") << int(QXmppVCardPhone::ISDN);
    QTest::newRow("PCS") << QByteArray("<PHONE><PCS/><NUMBER>12345</NUMBER></PHONE>") << int(QXmppVCardPhone::PCS);
    QTest::newRow("PREF") << QByteArray("<PHONE><PREF/><NUMBER>12345</NUMBER></PHONE>") << int(QXmppVCardPhone::Preferred);
}

void tst_QXmppVCardIq::testPhone()
{
    QFETCH(QByteArray, xml);
    QFETCH(int, type);

    QXmppVCardPhone phone;
    parsePacket(phone, xml);
    QCOMPARE(phone.number(), QLatin1String("12345"));
    QCOMPARE(int(phone.type()), type);
    serializePacket(phone, xml);
}

void tst_QXmppVCardIq::testVCard()
{
    const QByteArray xml(
        "<iq id=\"vcard1\" type=\"set\">"
        "<vCard xmlns=\"vcard-temp\">"
        "<ADR><CTRY>France</CTRY></ADR>"
        "<BDAY>1983-09-14</BDAY>"
        "<DESC>I like XMPP.</DESC>"
        "<EMAIL><INTERNET/><USERID>foo.bar@example.com</USERID></EMAIL>"
        "<FN>Foo Bar!</FN>"
        "<NICKNAME>FooBar</NICKNAME>"
        "<N><GIVEN>Foo</GIVEN><FAMILY>Wiz</FAMILY><MIDDLE>Baz</MIDDLE></N>"
        "<PHONE><HOME/><NUMBER>12345</NUMBER></PHONE>"
        "<PHONE><WORK/><NUMBER>67890</NUMBER></PHONE>"
        "<PHOTO>"
            "<TYPE>image/png</TYPE>"
            "<BINVAL>"
            "iVBORw0KGgoAAAANSUhEUgAAAAgAAAAICAIAAABLbSncAAAAAXNSR0IArs4c6QAAAAlwSFlzAAA"
            "UIgAAFCIBjw1HyAAAAAd0SU1FB9oIHQInNvuJovgAAAAiSURBVAjXY2TQ+s/AwMDAwPD/GiMDlP"
            "WfgYGBiQEHGJwSAK2BBQ1f3uvpAAAAAElFTkSuQmCC"
            "</BINVAL>"
        "</PHOTO>"
        "<URL>https://github.com/qxmpp-project/qxmpp/</URL>"
        "<ORG>"
            "<ORGNAME>QXmpp foundation</ORGNAME>"
            "<ORGUNIT>Main QXmpp dev unit</ORGUNIT>"
        "</ORG>"
        "<TITLE>Executive Director</TITLE>"
        "<ROLE>Patron Saint</ROLE>"
        "</vCard>"
        "</iq>");

    QXmppVCardIq vcard;
    parsePacket(vcard, xml);
    QCOMPARE(vcard.addresses().size(), 1);
    QCOMPARE(vcard.addresses()[0].country(), QLatin1String("France"));
    QCOMPARE(int(vcard.addresses()[0].type()), int(QXmppVCardEmail::None));
    QCOMPARE(vcard.birthday(), QDate(1983, 9, 14));
    QCOMPARE(vcard.description(), QLatin1String("I like XMPP."));
    QCOMPARE(vcard.email(), QLatin1String("foo.bar@example.com"));
    QCOMPARE(vcard.emails().size(), 1);
    QCOMPARE(vcard.emails()[0].address(), QLatin1String("foo.bar@example.com"));
    QCOMPARE(int(vcard.emails()[0].type()), int(QXmppVCardEmail::Internet));
    QCOMPARE(vcard.nickName(), QLatin1String("FooBar"));
    QCOMPARE(vcard.fullName(), QLatin1String("Foo Bar!"));
    QCOMPARE(vcard.firstName(), QLatin1String("Foo"));
    QCOMPARE(vcard.middleName(), QLatin1String("Baz"));
    QCOMPARE(vcard.lastName(), QLatin1String("Wiz"));
    QCOMPARE(vcard.phones().size(), 2);
    QCOMPARE(vcard.phones()[0].number(), QLatin1String("12345"));
    QCOMPARE(int(vcard.phones()[0].type()), int(QXmppVCardEmail::Home));
    QCOMPARE(vcard.phones()[1].number(), QLatin1String("67890"));
    QCOMPARE(int(vcard.phones()[1].type()), int(QXmppVCardEmail::Work));
    QCOMPARE(vcard.photo(), QByteArray::fromBase64(
        "iVBORw0KGgoAAAANSUhEUgAAAAgAAAAICAIAAABLbSncAAAAAXNSR0IArs4c6QAAAAlwSFlzAAA"
        "UIgAAFCIBjw1HyAAAAAd0SU1FB9oIHQInNvuJovgAAAAiSURBVAjXY2TQ+s/AwMDAwPD/GiMDlP"
        "WfgYGBiQEHGJwSAK2BBQ1f3uvpAAAAAElFTkSuQmCC"));
    QCOMPARE(vcard.photoType(), QLatin1String("image/png"));
    QCOMPARE(vcard.url(), QLatin1String("https://github.com/qxmpp-project/qxmpp/"));

    const QXmppVCardOrganization &orgInfo = vcard.organization();
    QCOMPARE(orgInfo.organization(), QLatin1String("QXmpp foundation"));
    QCOMPARE(orgInfo.unit(), QLatin1String("Main QXmpp dev unit"));
    QCOMPARE(orgInfo.title(), QLatin1String("Executive Director"));
    QCOMPARE(orgInfo.role(), QLatin1String("Patron Saint"));

    serializePacket(vcard, xml);
}

QTEST_MAIN(tst_QXmppVCardIq)
#include "tst_qxmppvcardiq.moc"
<|endoftext|>


<commit_before>//===- CodeGenTarget.cpp - CodeGen Target Class Wrapper ---------*- C++ -*-===//
//
//                     The LLVM Compiler Infrastructure
//
// This file was developed by the LLVM research group and is distributed under
// the University of Illinois Open Source License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This class wrap target description classes used by the various code
// generation TableGen backends.  This makes it easier to access the data and
// provides a single place that needs to check it for validity.  All of these
// classes throw exceptions on error conditions.
//
//===----------------------------------------------------------------------===//

#include "CodeGenTarget.h"
#include "Record.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/Support/CommandLine.h"
#include <set>
using namespace llvm;

static cl::opt<unsigned>
AsmWriterNum("asmwriternum", cl::init(0),
             cl::desc("Make -gen-asm-writer emit assembly writer #N"));

/// getValueType - Return the MCV::ValueType that the specified TableGen record
/// corresponds to.
MVT::ValueType llvm::getValueType(Record *Rec) {
  return (MVT::ValueType)Rec->getValueAsInt("Value");
}

std::string llvm::getName(MVT::ValueType T) {
  switch (T) {
  case MVT::Other: return "UNKNOWN";
  case MVT::i1:    return "i1";
  case MVT::i8:    return "i8";
  case MVT::i16:   return "i16";
  case MVT::i32:   return "i32";
  case MVT::i64:   return "i64";
  case MVT::i128:  return "i128";
  case MVT::f32:   return "f32";
  case MVT::f64:   return "f64";
  case MVT::f80:   return "f80";
  case MVT::f128:  return "f128";
  case MVT::isVoid:return "void";
  default: assert(0 && "ILLEGAL VALUE TYPE!"); return "";
  }
}

std::string llvm::getEnumName(MVT::ValueType T) {
  switch (T) {
  case MVT::Other: return "Other";
  case MVT::i1:    return "i1";
  case MVT::i8:    return "i8";
  case MVT::i16:   return "i16";
  case MVT::i32:   return "i32";
  case MVT::i64:   return "i64";
  case MVT::i128:  return "i128";
  case MVT::f32:   return "f32";
  case MVT::f64:   return "f64";
  case MVT::f80:   return "f80";
  case MVT::f128:  return "f128";
  case MVT::isVoid:return "isVoid";
  default: assert(0 && "ILLEGAL VALUE TYPE!"); return "";
  }
}

std::ostream &llvm::operator<<(std::ostream &OS, MVT::ValueType T) {
  return OS << getName(T);
}

/// getTarget - Return the current instance of the Target class.
///
CodeGenTarget::CodeGenTarget() : PointerType(MVT::Other) {
  std::vector<Record*> Targets = Records.getAllDerivedDefinitions("Target");
  if (Targets.size() == 0)
    throw std::string("ERROR: No 'Target' subclasses defined!");
  if (Targets.size() != 1)
    throw std::string("ERROR: Multiple subclasses of Target defined!");
  TargetRec = Targets[0];

  // Read in all of the CalleeSavedRegisters...
  ListInit *LI = TargetRec->getValueAsListInit("CalleeSavedRegisters");
  for (unsigned i = 0, e = LI->getSize(); i != e; ++i)
    if (DefInit *DI = dynamic_cast<DefInit*>(LI->getElement(i)))
      CalleeSavedRegisters.push_back(DI->getDef());
    else
      throw "Target: " + TargetRec->getName() +
            " expected register definition in CalleeSavedRegisters list!";

  PointerType = getValueType(TargetRec->getValueAsDef("PointerType"));
}

const std::string &CodeGenTarget::getName() const {
  return TargetRec->getName();
}

Record *CodeGenTarget::getInstructionSet() const {
  return TargetRec->getValueAsDef("InstructionSet");
}

/// getAsmWriter - Return the AssemblyWriter definition for this target.
///
Record *CodeGenTarget::getAsmWriter() const {
  ListInit *LI = TargetRec->getValueAsListInit("AssemblyWriters");
  if (AsmWriterNum >= LI->getSize())
    throw "Target does not have an AsmWriter #" + utostr(AsmWriterNum) + "!";
  DefInit *DI = dynamic_cast<DefInit*>(LI->getElement(AsmWriterNum));
  if (!DI) throw std::string("AssemblyWriter list should be a list of defs!");
  return DI->getDef();
}

void CodeGenTarget::ReadRegisters() const {
  std::vector<Record*> Regs = Records.getAllDerivedDefinitions("Register");
  if (Regs.empty())
    throw std::string("No 'Register' subclasses defined!");

  Registers.reserve(Regs.size());
  Registers.assign(Regs.begin(), Regs.end());
}

CodeGenRegister::CodeGenRegister(Record *R) : TheDef(R) {
  DeclaredSpillSize = R->getValueAsInt("SpillSize");
  DeclaredSpillAlignment = R->getValueAsInt("SpillAlignment");
}

const std::string &CodeGenRegister::getName() const {
  return TheDef->getName();
}

void CodeGenTarget::ReadRegisterClasses() const {
  std::vector<Record*> RegClasses =
    Records.getAllDerivedDefinitions("RegisterClass");
  if (RegClasses.empty())
    throw std::string("No 'RegisterClass' subclasses defined!");

  RegisterClasses.reserve(RegClasses.size());
  RegisterClasses.assign(RegClasses.begin(), RegClasses.end());
}

CodeGenRegisterClass::CodeGenRegisterClass(Record *R) : TheDef(R) {
  // Rename anonymous register classes.
  if (R->getName().size() > 9 && R->getName()[9] == '.') {
    static unsigned AnonCounter = 0;
    R->setName("AnonRegClass_"+utostr(AnonCounter++));
  }

  Namespace = R->getValueAsString("Namespace");
  SpillSize = R->getValueAsInt("Size");
  SpillAlignment = R->getValueAsInt("Alignment");
  VT = getValueType(R->getValueAsDef("RegType"));

  MethodBodies = R->getValueAsCode("MethodBodies");
  MethodProtos = R->getValueAsCode("MethodProtos");

  ListInit *RegList = R->getValueAsListInit("MemberList");
  for (unsigned i = 0, e = RegList->getSize(); i != e; ++i) {
    DefInit *RegDef = dynamic_cast<DefInit*>(RegList->getElement(i));
    if (!RegDef) throw "Register class member is not a record!";
    Record *Reg = RegDef->getDef();

    if (!Reg->isSubClassOf("Register"))
      throw "Register Class member '" + Reg->getName() +
            "' does not derive from the Register class!";
    Elements.push_back(Reg);
  }
}

const std::string &CodeGenRegisterClass::getName() const {
  return TheDef->getName();
}

void CodeGenTarget::ReadLegalValueTypes() const {
  const std::vector<CodeGenRegisterClass> &RCs = getRegisterClasses();
  for (unsigned i = 0, e = RCs.size(); i != e; ++i)
    LegalValueTypes.push_back(RCs[i].VT);
}

void CodeGenTarget::ReadInstructions() const {
  std::vector<Record*> Insts = Records.getAllDerivedDefinitions("Instruction");

  if (Insts.empty())
    throw std::string("No 'Instruction' subclasses defined!");

  std::string InstFormatName =
    getAsmWriter()->getValueAsString("InstFormatName");

  for (unsigned i = 0, e = Insts.size(); i != e; ++i) {
    std::string AsmStr = Insts[i]->getValueAsString(InstFormatName);
    Instructions.insert(std::make_pair(Insts[i]->getName(),
                                       CodeGenInstruction(Insts[i], AsmStr)));
  }
}

/// getPHIInstruction - Return the designated PHI instruction.
///
const CodeGenInstruction &CodeGenTarget::getPHIInstruction() const {
  Record *PHI = getInstructionSet()->getValueAsDef("PHIInst");
  std::map<std::string, CodeGenInstruction>::const_iterator I =
    getInstructions().find(PHI->getName());
  if (I == Instructions.end())
    throw "Could not find PHI instruction named '" + PHI->getName() + "'!";
  return I->second;
}

/// getInstructionsByEnumValue - Return all of the instructions defined by the
/// target, ordered by their enum value.
void CodeGenTarget::
getInstructionsByEnumValue(std::vector<const CodeGenInstruction*>
                                                 &NumberedInstructions) {

  // Print out the rest of the instructions now.
  unsigned i = 0;
  const CodeGenInstruction *PHI = &getPHIInstruction();
  NumberedInstructions.push_back(PHI);
  for (inst_iterator II = inst_begin(), E = inst_end(); II != E; ++II)
    if (&II->second != PHI)
      NumberedInstructions.push_back(&II->second);
}

/// isLittleEndianEncoding - Return whether this target encodes its instruction
/// in little-endian format, i.e. bits laid out in the order [0..n]
///
bool CodeGenTarget::isLittleEndianEncoding() const {
  return getInstructionSet()->getValueAsBit("isLittleEndianEncoding");
}

CodeGenInstruction::CodeGenInstruction(Record *R, const std::string &AsmStr)
  : TheDef(R), AsmString(AsmStr) {
  Name      = R->getValueAsString("Name");
  Namespace = R->getValueAsString("Namespace");

  isReturn     = R->getValueAsBit("isReturn");
  isBranch     = R->getValueAsBit("isBranch");
  isBarrier    = R->getValueAsBit("isBarrier");
  isCall       = R->getValueAsBit("isCall");
  isLoad       = R->getValueAsBit("isLoad");
  isStore      = R->getValueAsBit("isStore");
  isTwoAddress = R->getValueAsBit("isTwoAddress");
  isConvertibleToThreeAddress = R->getValueAsBit("isConvertibleToThreeAddress");
  isCommutable = R->getValueAsBit("isCommutable");
  isTerminator = R->getValueAsBit("isTerminator");
  hasDelaySlot = R->getValueAsBit("hasDelaySlot");
  usesCustomDAGSchedInserter = R->getValueAsBit("usesCustomDAGSchedInserter");
  hasVariableNumberOfOperands = false;

  DagInit *DI;
  try {
    DI = R->getValueAsDag("OperandList");
  } catch (...) {
    // Error getting operand list, just ignore it (sparcv9).
    AsmString.clear();
    OperandList.clear();
    return;
  }

  unsigned MIOperandNo = 0;
  std::set<std::string> OperandNames;
  for (unsigned i = 0, e = DI->getNumArgs(); i != e; ++i) {
    DefInit *Arg = dynamic_cast<DefInit*>(DI->getArg(i));
    if (!Arg)
      throw "Illegal operand for the '" + R->getName() + "' instruction!";

    Record *Rec = Arg->getDef();
    MVT::ValueType Ty;
    std::string PrintMethod = "printOperand";
    unsigned NumOps = 1;
    if (Rec->isSubClassOf("RegisterClass")) {
      Ty = getValueType(Rec->getValueAsDef("RegType"));
    } else if (Rec->isSubClassOf("Operand")) {
      Ty = getValueType(Rec->getValueAsDef("Type"));
      PrintMethod = Rec->getValueAsString("PrintMethod");
      NumOps = Rec->getValueAsInt("NumMIOperands");
    } else if (Rec->getName() == "variable_ops") {
      hasVariableNumberOfOperands = true;
      continue;
    } else
      throw "Unknown operand class '" + Rec->getName() +
            "' in instruction '" + R->getName() + "' instruction!";

    // Check that the operand has a name and that it's unique.
    if (DI->getArgName(i).empty())
      throw "In instruction '" + R->getName() + "', operand #" + utostr(i) +
        " has no name!";
    if (!OperandNames.insert(DI->getArgName(i)).second)
      throw "In instruction '" + R->getName() + "', operand #" + utostr(i) +
        " has the same name as a previous operand!";

    OperandList.push_back(OperandInfo(Rec, Ty, DI->getArgName(i),
                                      PrintMethod, MIOperandNo, NumOps));
    MIOperandNo += NumOps;
  }
}

/// getOperandNamed - Return the index of the operand with the specified
/// non-empty name.  If the instruction does not have an operand with the
/// specified name, throw an exception.
///
unsigned CodeGenInstruction::getOperandNamed(const std::string &Name) const {
  assert(!Name.empty() && "Cannot search for operand with no name!");
  for (unsigned i = 0, e = OperandList.size(); i != e; ++i)
    if (OperandList[i].Name == Name) return i;
  throw "Instruction '" + TheDef->getName() +
        "' does not have an operand named '$" + Name + "'!";
}
<commit_msg>Do not let getLegalValueTypes return a list with duplicates in it<commit_after>//===- CodeGenTarget.cpp - CodeGen Target Class Wrapper ---------*- C++ -*-===//
//
//                     The LLVM Compiler Infrastructure
//
// This file was developed by the LLVM research group and is distributed under
// the University of Illinois Open Source License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This class wrap target description classes used by the various code
// generation TableGen backends.  This makes it easier to access the data and
// provides a single place that needs to check it for validity.  All of these
// classes throw exceptions on error conditions.
//
//===----------------------------------------------------------------------===//

#include "CodeGenTarget.h"
#include "Record.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/Support/CommandLine.h"
#include <set>
#include <algorithm>
using namespace llvm;

static cl::opt<unsigned>
AsmWriterNum("asmwriternum", cl::init(0),
             cl::desc("Make -gen-asm-writer emit assembly writer #N"));

/// getValueType - Return the MCV::ValueType that the specified TableGen record
/// corresponds to.
MVT::ValueType llvm::getValueType(Record *Rec) {
  return (MVT::ValueType)Rec->getValueAsInt("Value");
}

std::string llvm::getName(MVT::ValueType T) {
  switch (T) {
  case MVT::Other: return "UNKNOWN";
  case MVT::i1:    return "i1";
  case MVT::i8:    return "i8";
  case MVT::i16:   return "i16";
  case MVT::i32:   return "i32";
  case MVT::i64:   return "i64";
  case MVT::i128:  return "i128";
  case MVT::f32:   return "f32";
  case MVT::f64:   return "f64";
  case MVT::f80:   return "f80";
  case MVT::f128:  return "f128";
  case MVT::isVoid:return "void";
  default: assert(0 && "ILLEGAL VALUE TYPE!"); return "";
  }
}

std::string llvm::getEnumName(MVT::ValueType T) {
  switch (T) {
  case MVT::Other: return "Other";
  case MVT::i1:    return "i1";
  case MVT::i8:    return "i8";
  case MVT::i16:   return "i16";
  case MVT::i32:   return "i32";
  case MVT::i64:   return "i64";
  case MVT::i128:  return "i128";
  case MVT::f32:   return "f32";
  case MVT::f64:   return "f64";
  case MVT::f80:   return "f80";
  case MVT::f128:  return "f128";
  case MVT::isVoid:return "isVoid";
  default: assert(0 && "ILLEGAL VALUE TYPE!"); return "";
  }
}

std::ostream &llvm::operator<<(std::ostream &OS, MVT::ValueType T) {
  return OS << getName(T);
}

/// getTarget - Return the current instance of the Target class.
///
CodeGenTarget::CodeGenTarget() : PointerType(MVT::Other) {
  std::vector<Record*> Targets = Records.getAllDerivedDefinitions("Target");
  if (Targets.size() == 0)
    throw std::string("ERROR: No 'Target' subclasses defined!");
  if (Targets.size() != 1)
    throw std::string("ERROR: Multiple subclasses of Target defined!");
  TargetRec = Targets[0];

  // Read in all of the CalleeSavedRegisters...
  ListInit *LI = TargetRec->getValueAsListInit("CalleeSavedRegisters");
  for (unsigned i = 0, e = LI->getSize(); i != e; ++i)
    if (DefInit *DI = dynamic_cast<DefInit*>(LI->getElement(i)))
      CalleeSavedRegisters.push_back(DI->getDef());
    else
      throw "Target: " + TargetRec->getName() +
            " expected register definition in CalleeSavedRegisters list!";

  PointerType = getValueType(TargetRec->getValueAsDef("PointerType"));
}

const std::string &CodeGenTarget::getName() const {
  return TargetRec->getName();
}

Record *CodeGenTarget::getInstructionSet() const {
  return TargetRec->getValueAsDef("InstructionSet");
}

/// getAsmWriter - Return the AssemblyWriter definition for this target.
///
Record *CodeGenTarget::getAsmWriter() const {
  ListInit *LI = TargetRec->getValueAsListInit("AssemblyWriters");
  if (AsmWriterNum >= LI->getSize())
    throw "Target does not have an AsmWriter #" + utostr(AsmWriterNum) + "!";
  DefInit *DI = dynamic_cast<DefInit*>(LI->getElement(AsmWriterNum));
  if (!DI) throw std::string("AssemblyWriter list should be a list of defs!");
  return DI->getDef();
}

void CodeGenTarget::ReadRegisters() const {
  std::vector<Record*> Regs = Records.getAllDerivedDefinitions("Register");
  if (Regs.empty())
    throw std::string("No 'Register' subclasses defined!");

  Registers.reserve(Regs.size());
  Registers.assign(Regs.begin(), Regs.end());
}

CodeGenRegister::CodeGenRegister(Record *R) : TheDef(R) {
  DeclaredSpillSize = R->getValueAsInt("SpillSize");
  DeclaredSpillAlignment = R->getValueAsInt("SpillAlignment");
}

const std::string &CodeGenRegister::getName() const {
  return TheDef->getName();
}

void CodeGenTarget::ReadRegisterClasses() const {
  std::vector<Record*> RegClasses =
    Records.getAllDerivedDefinitions("RegisterClass");
  if (RegClasses.empty())
    throw std::string("No 'RegisterClass' subclasses defined!");

  RegisterClasses.reserve(RegClasses.size());
  RegisterClasses.assign(RegClasses.begin(), RegClasses.end());
}

CodeGenRegisterClass::CodeGenRegisterClass(Record *R) : TheDef(R) {
  // Rename anonymous register classes.
  if (R->getName().size() > 9 && R->getName()[9] == '.') {
    static unsigned AnonCounter = 0;
    R->setName("AnonRegClass_"+utostr(AnonCounter++));
  }

  Namespace = R->getValueAsString("Namespace");
  SpillSize = R->getValueAsInt("Size");
  SpillAlignment = R->getValueAsInt("Alignment");
  VT = getValueType(R->getValueAsDef("RegType"));

  MethodBodies = R->getValueAsCode("MethodBodies");
  MethodProtos = R->getValueAsCode("MethodProtos");

  ListInit *RegList = R->getValueAsListInit("MemberList");
  for (unsigned i = 0, e = RegList->getSize(); i != e; ++i) {
    DefInit *RegDef = dynamic_cast<DefInit*>(RegList->getElement(i));
    if (!RegDef) throw "Register class member is not a record!";
    Record *Reg = RegDef->getDef();

    if (!Reg->isSubClassOf("Register"))
      throw "Register Class member '" + Reg->getName() +
            "' does not derive from the Register class!";
    Elements.push_back(Reg);
  }
}

const std::string &CodeGenRegisterClass::getName() const {
  return TheDef->getName();
}

void CodeGenTarget::ReadLegalValueTypes() const {
  const std::vector<CodeGenRegisterClass> &RCs = getRegisterClasses();
  for (unsigned i = 0, e = RCs.size(); i != e; ++i)
    LegalValueTypes.push_back(RCs[i].VT);

  // Remove duplicates.
  std::sort(LegalValueTypes.begin(), LegalValueTypes.end());
  LegalValueTypes.erase(std::unique(LegalValueTypes.begin(),
                                    LegalValueTypes.end()),
                        LegalValueTypes.end());
}

void CodeGenTarget::ReadInstructions() const {
  std::vector<Record*> Insts = Records.getAllDerivedDefinitions("Instruction");

  if (Insts.empty())
    throw std::string("No 'Instruction' subclasses defined!");

  std::string InstFormatName =
    getAsmWriter()->getValueAsString("InstFormatName");

  for (unsigned i = 0, e = Insts.size(); i != e; ++i) {
    std::string AsmStr = Insts[i]->getValueAsString(InstFormatName);
    Instructions.insert(std::make_pair(Insts[i]->getName(),
                                       CodeGenInstruction(Insts[i], AsmStr)));
  }
}

/// getPHIInstruction - Return the designated PHI instruction.
///
const CodeGenInstruction &CodeGenTarget::getPHIInstruction() const {
  Record *PHI = getInstructionSet()->getValueAsDef("PHIInst");
  std::map<std::string, CodeGenInstruction>::const_iterator I =
    getInstructions().find(PHI->getName());
  if (I == Instructions.end())
    throw "Could not find PHI instruction named '" + PHI->getName() + "'!";
  return I->second;
}

/// getInstructionsByEnumValue - Return all of the instructions defined by the
/// target, ordered by their enum value.
void CodeGenTarget::
getInstructionsByEnumValue(std::vector<const CodeGenInstruction*>
                                                 &NumberedInstructions) {

  // Print out the rest of the instructions now.
  unsigned i = 0;
  const CodeGenInstruction *PHI = &getPHIInstruction();
  NumberedInstructions.push_back(PHI);
  for (inst_iterator II = inst_begin(), E = inst_end(); II != E; ++II)
    if (&II->second != PHI)
      NumberedInstructions.push_back(&II->second);
}

/// isLittleEndianEncoding - Return whether this target encodes its instruction
/// in little-endian format, i.e. bits laid out in the order [0..n]
///
bool CodeGenTarget::isLittleEndianEncoding() const {
  return getInstructionSet()->getValueAsBit("isLittleEndianEncoding");
}

CodeGenInstruction::CodeGenInstruction(Record *R, const std::string &AsmStr)
  : TheDef(R), AsmString(AsmStr) {
  Name      = R->getValueAsString("Name");
  Namespace = R->getValueAsString("Namespace");

  isReturn     = R->getValueAsBit("isReturn");
  isBranch     = R->getValueAsBit("isBranch");
  isBarrier    = R->getValueAsBit("isBarrier");
  isCall       = R->getValueAsBit("isCall");
  isLoad       = R->getValueAsBit("isLoad");
  isStore      = R->getValueAsBit("isStore");
  isTwoAddress = R->getValueAsBit("isTwoAddress");
  isConvertibleToThreeAddress = R->getValueAsBit("isConvertibleToThreeAddress");
  isCommutable = R->getValueAsBit("isCommutable");
  isTerminator = R->getValueAsBit("isTerminator");
  hasDelaySlot = R->getValueAsBit("hasDelaySlot");
  usesCustomDAGSchedInserter = R->getValueAsBit("usesCustomDAGSchedInserter");
  hasVariableNumberOfOperands = false;

  DagInit *DI;
  try {
    DI = R->getValueAsDag("OperandList");
  } catch (...) {
    // Error getting operand list, just ignore it (sparcv9).
    AsmString.clear();
    OperandList.clear();
    return;
  }

  unsigned MIOperandNo = 0;
  std::set<std::string> OperandNames;
  for (unsigned i = 0, e = DI->getNumArgs(); i != e; ++i) {
    DefInit *Arg = dynamic_cast<DefInit*>(DI->getArg(i));
    if (!Arg)
      throw "Illegal operand for the '" + R->getName() + "' instruction!";

    Record *Rec = Arg->getDef();
    MVT::ValueType Ty;
    std::string PrintMethod = "printOperand";
    unsigned NumOps = 1;
    if (Rec->isSubClassOf("RegisterClass")) {
      Ty = getValueType(Rec->getValueAsDef("RegType"));
    } else if (Rec->isSubClassOf("Operand")) {
      Ty = getValueType(Rec->getValueAsDef("Type"));
      PrintMethod = Rec->getValueAsString("PrintMethod");
      NumOps = Rec->getValueAsInt("NumMIOperands");
    } else if (Rec->getName() == "variable_ops") {
      hasVariableNumberOfOperands = true;
      continue;
    } else
      throw "Unknown operand class '" + Rec->getName() +
            "' in instruction '" + R->getName() + "' instruction!";

    // Check that the operand has a name and that it's unique.
    if (DI->getArgName(i).empty())
      throw "In instruction '" + R->getName() + "', operand #" + utostr(i) +
        " has no name!";
    if (!OperandNames.insert(DI->getArgName(i)).second)
      throw "In instruction '" + R->getName() + "', operand #" + utostr(i) +
        " has the same name as a previous operand!";

    OperandList.push_back(OperandInfo(Rec, Ty, DI->getArgName(i),
                                      PrintMethod, MIOperandNo, NumOps));
    MIOperandNo += NumOps;
  }
}

/// getOperandNamed - Return the index of the operand with the specified
/// non-empty name.  If the instruction does not have an operand with the
/// specified name, throw an exception.
///
unsigned CodeGenInstruction::getOperandNamed(const std::string &Name) const {
  assert(!Name.empty() && "Cannot search for operand with no name!");
  for (unsigned i = 0, e = OperandList.size(); i != e; ++i)
    if (OperandList[i].Name == Name) return i;
  throw "Instruction '" + TheDef->getName() +
        "' does not have an operand named '$" + Name + "'!";
}
<|endoftext|>


<commit_before>#include "MPC.h"
#include <cppad/cppad.hpp>
#include <cppad/ipopt/solve.hpp>
#include "Eigen-3.3/Eigen/Core"

using CppAD::AD;

size_t N = 15;
double dt = 0.05;

// This value assumes the model presented in the classroom is used.
//
// It was obtained by measuring the radius formed by running the vehicle in the
// simulator around in a circle with a constant steering angle and velocity on a
// flat terrain.
//
// Lf was tuned until the the radius formed by the simulating the model
// presented in the classroom matched the previous radius.
//
// This is the length from front to CoG that has a similar radius.
const double Lf = 2.67;

double ref_v = 60;

size_t x_start = 0;
size_t y_start = x_start + N;
size_t psi_start = y_start + N;
size_t v_start = psi_start + N;
size_t cte_start = v_start + N;
size_t epsi_start = cte_start + N;
size_t delta_start = epsi_start + N;
size_t a_start = delta_start + N - 1;

class FG_eval {
 public:
  // Fitted polynomial coefficients
  Eigen::VectorXd coeffs;
  FG_eval(Eigen::VectorXd coeffs) { this->coeffs = coeffs; }

  typedef CPPAD_TESTVECTOR(AD<double>) ADvector;
  void operator()(ADvector& fg, const ADvector& vars) {
    // `fg` a vector of the cost constraints, `vars` is a vector of variable values (state & actuators)
    // NOTE: You'll probably go back and forth between this function and
    // the Solver function below.

    // The cost is stored is the first element of `fg`.
    // Any additions to the cost should be added to `fg[0]`.
    fg[0] = 0;

    // Reference State Cost
    // The part of the cost based on the reference state.
    for (int t = 0; t < N; t++) {
      fg[0] += 0.5 * CppAD::pow(vars[cte_start + t], 2);
      fg[0] += 5 * CppAD::pow(vars[epsi_start + t], 2);
      fg[0] += CppAD::pow(vars[v_start + t] - ref_v, 2);
      //fg[0] += 0.01 * CppAD::pow(t * vars[v_start + t] * vars[psi_start + t], 2);
    }

    // Minimize the use of actuators.
    for (int t = 0; t < N - 1; t++) {
      fg[0] += 5000 * CppAD::pow(vars[delta_start + t], 2);
      fg[0] += CppAD::pow(vars[a_start + t], 2);
    }

    // Minimize the value gap between sequential actuations.
    for (int t = 0; t < N - 2; t++) {
      fg[0] += 5000 * CppAD::pow(vars[delta_start + t + 1] - vars[delta_start + t], 2);
      fg[0] += CppAD::pow(vars[a_start + t + 1] - vars[a_start + t], 2);
    }

    //
    // Setup Constraints
    //

    // Initial constraints
    //
    // We add 1 to each of the starting indices due to cost being located at
    // index 0 of `fg`.
    // This bumps up the position of all the other values.
    fg[1 + x_start] = vars[x_start];
    fg[1 + y_start] = vars[y_start];
    fg[1 + psi_start] = vars[psi_start];
    fg[1 + v_start] = vars[v_start];
    fg[1 + cte_start] = vars[cte_start];
    fg[1 + epsi_start] = vars[epsi_start];

    // The rest of the constraints
    for (int t = 1; t < N; t++) {
      // The state at time t+1
      AD<double> x1 = vars[x_start + t];
      AD<double> y1 = vars[y_start + t];
      AD<double> psi1 = vars[psi_start + t];
      AD<double> v1 = vars[v_start + t];
      AD<double> cte1 = vars[cte_start + t];
      AD<double> epsi1 = vars[epsi_start + t];

      // The state at time t.
      AD<double> x0 = vars[x_start + t - 1];
      AD<double> y0 = vars[y_start + t - 1];
      AD<double> psi0 = vars[psi_start + t - 1];
      AD<double> v0 = vars[v_start + t - 1];
      AD<double> cte0 = vars[cte_start + t - 1];
      AD<double> epsi0 = vars[epsi_start + t - 1];

      // Only consider the actuation at time t.
      AD<double> delta0 = vars[delta_start + t - 1];
      AD<double> a0 = vars[a_start + t - 1];

      AD<double> f0 = coeffs[0] + coeffs[1] * x0 + coeffs[2] * x0 * x0 + coeffs[3] * x0 * x0 * x0;
      AD<double> psides0 = CppAD::atan(coeffs[1] + (2 * coeffs[2] * x0) + (3 * coeffs[3] * (x0*x0)));

      // Here's `x` to get you started.
      // The idea here is to constraint this value to be 0.
      //
      // Recall the equations for the model:
      // x_[t+1] = x[t] + v[t] * cos(psi[t]) * dt
      // y_[t+1] = y[t] + v[t] * sin(psi[t]) * dt
      // psi_[t+1] = psi[t] + v[t] / Lf * delta[t] * dt
      // v_[t+1] = v[t] + a[t] * dt
      // cte[t+1] = f(x[t]) - y[t] + v[t] * sin(epsi[t]) * dt
      // epsi[t+1] = psi[t] - psides[t] + v[t] * delta[t] / Lf * dt
      AD<double> psi1c = psi0 + (v0 / Lf * delta0 * dt);
      fg[1 + x_start + t] = x1 - (x0 + (v0 * CppAD::cos(psi0) * dt));
      fg[1 + y_start + t] = y1 - (y0 + (v0 * CppAD::sin(psi0) * dt));
      fg[1 + psi_start + t] = psi1 - psi1c;
      fg[1 + v_start + t] = v1 - (v0 + (a0 * dt));
      fg[1 + cte_start + t] = cte1 - (f0 - y0 + (v0 * CppAD::sin(epsi0) * dt));
      fg[1 + epsi_start + t] = epsi1 - psi1c;
    }
  }
};

//
// MPC class definition implementation.
//
MPC::MPC() {}
MPC::~MPC() {}

vector<double> MPC::Solve(Eigen::VectorXd state, Eigen::VectorXd coeffs) {
  typedef CPPAD_TESTVECTOR(double) Dvector;

  double x = state[0];
  double y = state[1];
  double psi = state[2];
  double v = state[3];
  double cte = state[4];
  double epsi = state[5];

  // Set the number of model variables
  size_t n_vars = (6 * N) + (2 * (N - 1));
  // Set the number of constraints
  size_t n_constraints = 6 * N;

  // Initial value of the independent variables.
  // SHOULD BE 0 besides initial state.
  Dvector vars(n_vars);
  for (int i = 0; i < n_vars; i++) {
    vars[i] = 0;
  }
  // Set the initial variable values
  vars[x_start] = x;
  vars[y_start] = y;
  vars[psi_start] = psi;
  vars[v_start] = v;
  vars[cte_start] = cte;
  vars[epsi_start] = epsi;

  Dvector vars_lowerbound(n_vars);
  Dvector vars_upperbound(n_vars);
  // Set all non-actuators upper and lowerlimits
  // to the max negative and positive values.
  for (int i = 0; i < delta_start; i++) {
    vars_lowerbound[i] = -1.0e19;
    vars_upperbound[i] = 1.0e19;
  }

  // The upper and lower limits of delta are set to -25 and 25
  // degrees (values in radians).
  for (int i = delta_start; i < a_start; i++) {
    vars_lowerbound[i] = -0.436332;
    vars_upperbound[i] = 0.436332;
  }

  // Acceleration/decceleration upper and lower limits.
  for (int i = a_start; i < n_vars; i++) {
    vars_lowerbound[i] = -1.0;
    vars_upperbound[i] = 1.0;
  }

  // Lower and upper limits for the constraints
  // Should be 0 besides initial state.
  Dvector constraints_lowerbound(n_constraints);
  Dvector constraints_upperbound(n_constraints);
  for (int i = 0; i < n_constraints; i++) {
    constraints_lowerbound[i] = 0;
    constraints_upperbound[i] = 0;
  }
  constraints_lowerbound[x_start] = x;
  constraints_lowerbound[y_start] = y;
  constraints_lowerbound[psi_start] = psi;
  constraints_lowerbound[v_start] = v;
  constraints_lowerbound[cte_start] = cte;
  constraints_lowerbound[epsi_start] = epsi;

  constraints_upperbound[x_start] = x;
  constraints_upperbound[y_start] = y;
  constraints_upperbound[psi_start] = psi;
  constraints_upperbound[v_start] = v;
  constraints_upperbound[cte_start] = cte;
  constraints_upperbound[epsi_start] = epsi;

  // object that computes objective and constraints
  FG_eval fg_eval(coeffs);

  //
  // NOTE: You don't have to worry about these options
  //
  // options for IPOPT solver
  std::string options;
  // Uncomment this if you'd like more print information
  options += "Integer print_level  0\n";
  // NOTE: Setting sparse to true allows the solver to take advantage
  // of sparse routines, this makes the computation MUCH FASTER. If you
  // can uncomment 1 of these and see if it makes a difference or not but
  // if you uncomment both the computation time should go up in orders of
  // magnitude.
  options += "Sparse  true        forward\n";
  options += "Sparse  true        reverse\n";
  // NOTE: Currently the solver has a maximum time limit of 0.5 seconds.
  // Change this as you see fit.
  options += "Numeric max_cpu_time          0.5\n";

  // place to return solution
  CppAD::ipopt::solve_result<Dvector> solution;

  // solve the problem
  CppAD::ipopt::solve<Dvector, FG_eval>(
      options, vars, vars_lowerbound, vars_upperbound, constraints_lowerbound,
      constraints_upperbound, fg_eval, solution);

  // Cost
  auto cost = solution.obj_value;
  std::cout << "Cost " << cost << std::endl;

  // We'll return the following values:
  // 0 -> the immediate steering value (in Radians)
  // 1 -> the immediate throttle value
  // 2 -> amount of coordinate values (N)
  // 3 ... 3+N -> X coordinate values
  // 3+N+1 ... 3+N+1+N -> Y coordinate values
  vector<double> result;
  result.push_back(solution.x[delta_start]);
  result.push_back(solution.x[a_start]);
  result.push_back(N);
  for (int i = 0; i < N; ++i)
  {
    result.push_back(solution.x[x_start + i]);
  }
  for (int i = 0; i < N; ++i)
  {
    result.push_back(solution.x[y_start + i]);
  }
  return result;
}
<commit_msg>P5 - still drives well at 60 mph<commit_after>#include "MPC.h"
#include <cppad/cppad.hpp>
#include <cppad/ipopt/solve.hpp>
#include "Eigen-3.3/Eigen/Core"

using CppAD::AD;

size_t N = 15;
double dt = 0.05;

// This value assumes the model presented in the classroom is used.
//
// It was obtained by measuring the radius formed by running the vehicle in the
// simulator around in a circle with a constant steering angle and velocity on a
// flat terrain.
//
// Lf was tuned until the the radius formed by the simulating the model
// presented in the classroom matched the previous radius.
//
// This is the length from front to CoG that has a similar radius.
const double Lf = 2.67;

double ref_v = 60;

size_t x_start = 0;
size_t y_start = x_start + N;
size_t psi_start = y_start + N;
size_t v_start = psi_start + N;
size_t cte_start = v_start + N;
size_t epsi_start = cte_start + N;
size_t delta_start = epsi_start + N;
size_t a_start = delta_start + N - 1;

class FG_eval {
 public:
  // Fitted polynomial coefficients
  Eigen::VectorXd coeffs;
  FG_eval(Eigen::VectorXd coeffs) { this->coeffs = coeffs; }

  typedef CPPAD_TESTVECTOR(AD<double>) ADvector;
  void operator()(ADvector& fg, const ADvector& vars) {
    // `fg` a vector of the cost constraints, `vars` is a vector of variable values (state & actuators)
    // NOTE: You'll probably go back and forth between this function and
    // the Solver function below.

    // The cost is stored is the first element of `fg`.
    // Any additions to the cost should be added to `fg[0]`.
    fg[0] = 0;

    // Reference State Cost
    // The part of the cost based on the reference state.
    for (int t = 0; t < N; t++) {
      fg[0] += 0.5 * CppAD::pow(vars[cte_start + t], 2);
      fg[0] += 5 * CppAD::pow(vars[epsi_start + t], 2);
      fg[0] += CppAD::pow(vars[v_start + t] - ref_v, 2);
      //fg[0] += 0.01 * CppAD::pow(t * vars[v_start + t] * vars[psi_start + t], 2);
    }

    // Minimize the use of actuators.
    for (int t = 0; t < N - 1; t++) {
      fg[0] += 5000 * CppAD::pow(vars[delta_start + t], 2);
      fg[0] += CppAD::pow(vars[a_start + t], 2);
    }

    // Minimize the value gap between sequential actuations.
    for (int t = 0; t < N - 2; t++) {
      fg[0] += 500 * CppAD::pow(vars[delta_start + t + 1] - vars[delta_start + t], 2);
      fg[0] += CppAD::pow(vars[a_start + t + 1] - vars[a_start + t], 2);
    }

    //
    // Setup Constraints
    //

    // Initial constraints
    //
    // We add 1 to each of the starting indices due to cost being located at
    // index 0 of `fg`.
    // This bumps up the position of all the other values.
    fg[1 + x_start] = vars[x_start];
    fg[1 + y_start] = vars[y_start];
    fg[1 + psi_start] = vars[psi_start];
    fg[1 + v_start] = vars[v_start];
    fg[1 + cte_start] = vars[cte_start];
    fg[1 + epsi_start] = vars[epsi_start];

    // The rest of the constraints
    for (int t = 1; t < N; t++) {
      // The state at time t+1
      AD<double> x1 = vars[x_start + t];
      AD<double> y1 = vars[y_start + t];
      AD<double> psi1 = vars[psi_start + t];
      AD<double> v1 = vars[v_start + t];
      AD<double> cte1 = vars[cte_start + t];
      AD<double> epsi1 = vars[epsi_start + t];

      // The state at time t.
      AD<double> x0 = vars[x_start + t - 1];
      AD<double> y0 = vars[y_start + t - 1];
      AD<double> psi0 = vars[psi_start + t - 1];
      AD<double> v0 = vars[v_start + t - 1];
      AD<double> cte0 = vars[cte_start + t - 1];
      AD<double> epsi0 = vars[epsi_start + t - 1];

      // Only consider the actuation at time t.
      AD<double> delta0 = vars[delta_start + t - 1];
      AD<double> a0 = vars[a_start + t - 1];

      AD<double> f0 = coeffs[0] + coeffs[1] * x0 + coeffs[2] * x0 * x0 + coeffs[3] * x0 * x0 * x0;
      AD<double> psides0 = CppAD::atan(coeffs[1] + (2 * coeffs[2] * x0) + (3 * coeffs[3] * (x0*x0)));

      // Here's `x` to get you started.
      // The idea here is to constraint this value to be 0.
      //
      // Recall the equations for the model:
      // x_[t+1] = x[t] + v[t] * cos(psi[t]) * dt
      // y_[t+1] = y[t] + v[t] * sin(psi[t]) * dt
      // psi_[t+1] = psi[t] + v[t] / Lf * delta[t] * dt
      // v_[t+1] = v[t] + a[t] * dt
      // cte[t+1] = f(x[t]) - y[t] + v[t] * sin(epsi[t]) * dt
      // epsi[t+1] = psi[t] - psides[t] + v[t] * delta[t] / Lf * dt
      AD<double> psi1c = psi0 + (v0 / Lf * delta0 * dt);
      fg[1 + x_start + t] = x1 - (x0 + (v0 * CppAD::cos(psi0) * dt));
      fg[1 + y_start + t] = y1 - (y0 + (v0 * CppAD::sin(psi0) * dt));
      fg[1 + psi_start + t] = psi1 - psi1c;
      fg[1 + v_start + t] = v1 - (v0 + (a0 * dt));
      fg[1 + cte_start + t] = cte1 - (f0 - y0 + (v0 * CppAD::sin(epsi0) * dt));
      fg[1 + epsi_start + t] = epsi1 - psi1c;
    }
  }
};

//
// MPC class definition implementation.
//
MPC::MPC() {}
MPC::~MPC() {}

vector<double> MPC::Solve(Eigen::VectorXd state, Eigen::VectorXd coeffs) {
  typedef CPPAD_TESTVECTOR(double) Dvector;

  double x = state[0];
  double y = state[1];
  double psi = state[2];
  double v = state[3];
  double cte = state[4];
  double epsi = state[5];

  // Set the number of model variables
  size_t n_vars = (6 * N) + (2 * (N - 1));
  // Set the number of constraints
  size_t n_constraints = 6 * N;

  // Initial value of the independent variables.
  // SHOULD BE 0 besides initial state.
  Dvector vars(n_vars);
  for (int i = 0; i < n_vars; i++) {
    vars[i] = 0;
  }
  // Set the initial variable values
  vars[x_start] = x;
  vars[y_start] = y;
  vars[psi_start] = psi;
  vars[v_start] = v;
  vars[cte_start] = cte;
  vars[epsi_start] = epsi;

  Dvector vars_lowerbound(n_vars);
  Dvector vars_upperbound(n_vars);
  // Set all non-actuators upper and lowerlimits
  // to the max negative and positive values.
  for (int i = 0; i < delta_start; i++) {
    vars_lowerbound[i] = -1.0e19;
    vars_upperbound[i] = 1.0e19;
  }

  // The upper and lower limits of delta are set to -25 and 25
  // degrees (values in radians).
  for (int i = delta_start; i < a_start; i++) {
    vars_lowerbound[i] = -0.436332;
    vars_upperbound[i] = 0.436332;
  }

  // Acceleration/decceleration upper and lower limits.
  for (int i = a_start; i < n_vars; i++) {
    vars_lowerbound[i] = -1.0;
    vars_upperbound[i] = 1.0;
  }

  // Lower and upper limits for the constraints
  // Should be 0 besides initial state.
  Dvector constraints_lowerbound(n_constraints);
  Dvector constraints_upperbound(n_constraints);
  for (int i = 0; i < n_constraints; i++) {
    constraints_lowerbound[i] = 0;
    constraints_upperbound[i] = 0;
  }
  constraints_lowerbound[x_start] = x;
  constraints_lowerbound[y_start] = y;
  constraints_lowerbound[psi_start] = psi;
  constraints_lowerbound[v_start] = v;
  constraints_lowerbound[cte_start] = cte;
  constraints_lowerbound[epsi_start] = epsi;

  constraints_upperbound[x_start] = x;
  constraints_upperbound[y_start] = y;
  constraints_upperbound[psi_start] = psi;
  constraints_upperbound[v_start] = v;
  constraints_upperbound[cte_start] = cte;
  constraints_upperbound[epsi_start] = epsi;

  // object that computes objective and constraints
  FG_eval fg_eval(coeffs);

  //
  // NOTE: You don't have to worry about these options
  //
  // options for IPOPT solver
  std::string options;
  // Uncomment this if you'd like more print information
  options += "Integer print_level  0\n";
  // NOTE: Setting sparse to true allows the solver to take advantage
  // of sparse routines, this makes the computation MUCH FASTER. If you
  // can uncomment 1 of these and see if it makes a difference or not but
  // if you uncomment both the computation time should go up in orders of
  // magnitude.
  options += "Sparse  true        forward\n";
  options += "Sparse  true        reverse\n";
  // NOTE: Currently the solver has a maximum time limit of 0.5 seconds.
  // Change this as you see fit.
  options += "Numeric max_cpu_time          0.5\n";

  // place to return solution
  CppAD::ipopt::solve_result<Dvector> solution;

  // solve the problem
  CppAD::ipopt::solve<Dvector, FG_eval>(
      options, vars, vars_lowerbound, vars_upperbound, constraints_lowerbound,
      constraints_upperbound, fg_eval, solution);

  // Cost
  auto cost = solution.obj_value;
  std::cout << "Cost " << cost << std::endl;

  // We'll return the following values:
  // 0 -> the immediate steering value (in Radians)
  // 1 -> the immediate throttle value
  // 2 -> amount of coordinate values (N)
  // 3 ... 3+N -> X coordinate values
  // 3+N+1 ... 3+N+1+N -> Y coordinate values
  vector<double> result;
  result.push_back(solution.x[delta_start]);
  result.push_back(solution.x[a_start]);
  result.push_back(N);
  for (int i = 0; i < N; ++i)
  {
    result.push_back(solution.x[x_start + i]);
  }
  for (int i = 0; i < N; ++i)
  {
    result.push_back(solution.x[y_start + i]);
  }
  return result;
}
<|endoftext|>


<commit_before>#include "Halide.h"
#include <cstdio>
#include <algorithm>
#include "benchmark.h"

using namespace Halide;

// 32-bit windows defines powf as a macro, which won't work for us.
#ifdef _WIN32
extern "C" __declspec(dllexport) float pow_ref(float x, float y) {
    return pow(x, y);
}
#else
extern "C" float pow_ref(float x, float y) {
    return powf(x, y);
}
#endif

HalideExtern_2(float, pow_ref, float, float);

int main(int argc, char **argv) {
    Func f, g, h;
    Var x, y;

    f(x, y) = pow_ref((x+1)/512.0f, (y+1)/512.0f);
    g(x, y) = pow((x+1)/512.0f, (y+1)/512.0f);
    h(x, y) = fast_pow((x+1)/512.0f, (y+1)/512.0f);
    f.vectorize(x, 8);
    g.vectorize(x, 8);
    h.vectorize(x, 8);

    Image<float> correct_result(2048, 768);
    Image<float> fast_result(2048, 768);
    Image<float> faster_result(2048, 768);

    f.realize(correct_result);
    g.realize(fast_result);
    h.realize(faster_result);

    const int trials = 5;
    const int iterations = 5;

    // All profiling runs are done into the same buffer, to avoid
    // cache weirdness.
    Image<float> timing_scratch(400, 400);
    double t1 = 1e3 * benchmark(trials, iterations, [&]() { f.realize(timing_scratch); });
    double t2 = 1e3 * benchmark(trials, iterations, [&]() { g.realize(timing_scratch); });
    double t3 = 1e3 * benchmark(trials, iterations, [&]() { h.realize(timing_scratch); });

    RDom r(correct_result);
    Func fast_error, faster_error;
    Expr fast_delta = correct_result(r.x, r.y) - fast_result(r.x, r.y);
    Expr faster_delta = correct_result(r.x, r.y) - faster_result(r.x, r.y);
    fast_error() += cast<double>(fast_delta * fast_delta);
    faster_error() += cast<double>(faster_delta * faster_delta);

    Image<double> fast_err = fast_error.realize();
    Image<double> faster_err = faster_error.realize();

    int timing_N = timing_scratch.width() * timing_scratch.height();
    int correctness_N = fast_result.width() * fast_result.height();
    fast_err(0) = sqrt(fast_err(0)/correctness_N);
    faster_err(0) = sqrt(faster_err(0)/correctness_N);

    printf("powf: %f ns per pixel\n"
           "Halide's pow: %f ns per pixel (rms error = %0.10f)\n"
           "Halide's fast_pow: %f ns per pixel (rms error = %0.10f)\n",
           1000000*t1 / timing_N,
           1000000*t2 / timing_N, fast_err(0),
           1000000*t3 / timing_N, faster_err(0));

    if (fast_err(0) > 0.000001) {
        printf("Error for pow too large\n");
        return -1;
    }

    if (faster_err(0) > 0.0001) {
        printf("Error for fast_pow too large\n");
        return -1;
    }

    if (t1 < t2) {
        printf("powf is faster than Halide's pow\n");
        return -1;
    }

    if (t2 < t3) {
        printf("pow is faster than fast_pow\n");
        return -1;
    }

    printf("Success!\n");

    return 0;
}
<commit_msg>Our pows are so fast the test was bandwidth limited<commit_after>#include "Halide.h"
#include <cstdio>
#include <algorithm>
#include "benchmark.h"

using namespace Halide;

// 32-bit windows defines powf as a macro, which won't work for us.
#ifdef _WIN32
extern "C" __declspec(dllexport) float pow_ref(float x, float y) {
    return pow(x, y);
}
#else
extern "C" float pow_ref(float x, float y) {
    return powf(x, y);
}
#endif

HalideExtern_2(float, pow_ref, float, float);

int main(int argc, char **argv) {
    Func f, g, h;
    Var x, y;

    Param<int> pows_per_pixel;

    RDom s(0, pows_per_pixel);
    f(x, y) = sum(pow_ref((x+1)/512.0f, (y+1+s)/512.0f));
    g(x, y) = sum(pow((x+1)/512.0f, (y+1+s)/512.0f));
    h(x, y) = sum(fast_pow((x+1)/512.0f, (y+1+s)/512.0f));
    f.vectorize(x, 8);
    g.vectorize(x, 8);
    h.vectorize(x, 8);

    Image<float> correct_result(2048, 768);
    Image<float> fast_result(2048, 768);
    Image<float> faster_result(2048, 768);

    pows_per_pixel.set(1);

    f.realize(correct_result);
    g.realize(fast_result);
    h.realize(faster_result);

    const int trials = 5;
    const int iterations = 5;
    pows_per_pixel.set(10);

    // All profiling runs are done into the same buffer, to avoid
    // cache weirdness.
    Image<float> timing_scratch(256, 256);
    double t1 = 1e3 * benchmark(trials, iterations, [&]() { f.realize(timing_scratch); });
    double t2 = 1e3 * benchmark(trials, iterations, [&]() { g.realize(timing_scratch); });
    double t3 = 1e3 * benchmark(trials, iterations, [&]() { h.realize(timing_scratch); });

    RDom r(correct_result);
    Func fast_error, faster_error;
    Expr fast_delta = correct_result(r.x, r.y) - fast_result(r.x, r.y);
    Expr faster_delta = correct_result(r.x, r.y) - faster_result(r.x, r.y);
    fast_error() += cast<double>(fast_delta * fast_delta);
    faster_error() += cast<double>(faster_delta * faster_delta);

    Image<double> fast_err = fast_error.realize();
    Image<double> faster_err = faster_error.realize();

    int timing_N = timing_scratch.width() * timing_scratch.height() * 10;
    int correctness_N = fast_result.width() * fast_result.height();
    fast_err(0) = sqrt(fast_err(0)/correctness_N);
    faster_err(0) = sqrt(faster_err(0)/correctness_N);

    printf("powf: %f ns per pixel\n"
           "Halide's pow: %f ns per pixel (rms error = %0.10f)\n"
           "Halide's fast_pow: %f ns per pixel (rms error = %0.10f)\n",
           1000000*t1 / timing_N,
           1000000*t2 / timing_N, fast_err(0),
           1000000*t3 / timing_N, faster_err(0));

    if (fast_err(0) > 0.000001) {
        printf("Error for pow too large\n");
        return -1;
    }

    if (faster_err(0) > 0.0001) {
        printf("Error for fast_pow too large\n");
        return -1;
    }

    if (t1 < t2) {
        printf("powf is faster than Halide's pow\n");
        return -1;
    }

    if (t2 < t3) {
        printf("pow is faster than fast_pow\n");
        return -1;
    }

    printf("Success!\n");

    return 0;
}
<|endoftext|>


<commit_before>#include <celero/Celero.h>

#include <annis/query.h>
#include <annis/annosearch/exactannokeysearch.h>
#include <annis/annosearch/exactannovaluesearch.h>
#include <annis/annosearch/regexannosearch.h>

#include <annis/operators/pointing.h>
#include <annis/operators/precedence.h>

using namespace annis;

CELERO_MAIN

class GUMFixture : public celero::TestFixture
{
    public:
        GUMFixture()
        {
        }

        /*
        virtual std::vector<std::pair<int64_t, uint64_t>> getExperimentValues() const override
        {
            std::vector<std::pair<int64_t, uint64_t>> problemSpace;
            problemSpace.push_back(std::make_pair(1, uint64_t(0)));

            return problemSpace;
        }
        */

        /// Before each run, build a vector of random integers.
        virtual void setUp(int64_t experimentValue)
        {
          char* testDataEnv = std::getenv("ANNIS4_TEST_DATA");
          std::string dataDir("data");
          if (testDataEnv != NULL) {
            dataDir = testDataEnv;
          }
          db.load(dataDir + "/GUM", true);
        }

        DB db;

        std::shared_ptr<Query> query_PosDepPos(QueryConfig config)
        {
          std::shared_ptr<Query> query = std::make_shared<Query>(db, config);

          query->addNode(std::make_shared<ExactAnnoKeySearch>(db, "pos"));
          query->addNode(std::make_shared<ExactAnnoKeySearch>(db, "pos"));

          Annotation edgeAnno = {db.strings.add("func"), 0, db.strings.add("dep")};
          query->addOperator(std::make_shared<Pointing>(db.edges, db.strings, "", "dep", edgeAnno), 0, 1);
          return query;
        }

        std::shared_ptr<Query> query_UsedTo(QueryConfig config)
        {
          std::shared_ptr<Query> query = std::make_shared<Query>(db, config);

          query->addNode(std::make_shared<RegexAnnoSearch>(db, "pos", "NN.*"));
          query->addNode(std::make_shared<ExactAnnoValueSearch>(db, "annis4_internal", "tok", "used"));
          query->addNode(std::make_shared<ExactAnnoValueSearch>(db, "annis4_internal", "tok", "to"));

          query->addOperator(std::make_shared<Precedence>(db, db.edges), 0, 1);
          query->addOperator(std::make_shared<Precedence>(db, db.edges), 1, 2);

          return query;
        }

};

BASELINE_F(PosDepPos, N1, GUMFixture, 10, 100)
{
  QueryConfig config;
  config.numOfParallelTasks = 1;
  std::shared_ptr<Query> query = query_PosDepPos(config);
  int counter=0;
  while(query->next()) {
    counter++;
  }
}

BENCHMARK_F(PosDepPos, N2, GUMFixture, 10, 100)
{
  QueryConfig config;
  config.numOfParallelTasks = 2;
  std::shared_ptr<Query> query = query_PosDepPos(config);
  int counter=0;
  while(query->next()) {
    counter++;
  }
}

BENCHMARK_F(PosDepPos, N3, GUMFixture, 10, 100)
{
  QueryConfig config;
  config.numOfParallelTasks = 3;
  std::shared_ptr<Query> query = query_PosDepPos(config);
  int counter=0;
  while(query->next()) {
    counter++;
  }
}

BENCHMARK_F(PosDepPos, N4, GUMFixture, 10, 100)
{
  QueryConfig config;
  config.numOfParallelTasks = 4;
  std::shared_ptr<Query> query = query_PosDepPos(config);
  int counter=0;
  while(query->next()) {
    counter++;
  }
}

BENCHMARK_F(PosDepPos, N5, GUMFixture, 10, 100)
{
  QueryConfig config;
  config.numOfParallelTasks = 5;
  std::shared_ptr<Query> query = query_PosDepPos(config);
  int counter=0;
  while(query->next()) {
    counter++;
  }
}

BENCHMARK_F(PosDepPos, N6, GUMFixture, 10, 100)
{
  QueryConfig config;
  config.numOfParallelTasks = 6;
  std::shared_ptr<Query> query = query_PosDepPos(config);
  int counter=0;
  while(query->next()) {
    counter++;
  }
}

BENCHMARK_F(PosDepPos, N7, GUMFixture, 10, 100)
{
  QueryConfig config;
  config.numOfParallelTasks = 7;
  std::shared_ptr<Query> query = query_PosDepPos(config);
  int counter=0;
  while(query->next()) {
    counter++;
  }
}

BENCHMARK_F(PosDepPos, N8, GUMFixture, 10, 100)
{
  QueryConfig config;
  config.numOfParallelTasks = 8;
  std::shared_ptr<Query> query = query_PosDepPos(config);
  int counter=0;
  while(query->next()) {
    counter++;
  }
}

BASELINE_F(UsedTo, N1, GUMFixture, 10, 100)
{
  QueryConfig config;
  config.numOfParallelTasks = 1;
  std::shared_ptr<Query> query = query_UsedTo(config);
  int counter=0;
  while(query->next()) {
    counter++;
  }
}

BENCHMARK_F(UsedTo, N2, GUMFixture, 10, 100)
{
  QueryConfig config;
  config.numOfParallelTasks = 2;
  std::shared_ptr<Query> query = query_UsedTo(config);
  int counter=0;
  while(query->next()) {
    counter++;
  }
}

BENCHMARK_F(UsedTo, N3, GUMFixture, 10, 100)
{
  QueryConfig config;
  config.numOfParallelTasks = 3;
  std::shared_ptr<Query> query = query_UsedTo(config);
  int counter=0;
  while(query->next()) {
    counter++;
  }
}

BENCHMARK_F(UsedTo, N4, GUMFixture, 10, 100)
{
  QueryConfig config;
  config.numOfParallelTasks = 4;
  std::shared_ptr<Query> query = query_UsedTo(config);
  int counter=0;
  while(query->next()) {
    counter++;
  }
}

BENCHMARK_F(UsedTo, N5, GUMFixture, 10, 100)
{
  QueryConfig config;
  config.numOfParallelTasks = 5;
  std::shared_ptr<Query> query = query_UsedTo(config);
  int counter=0;
  while(query->next()) {
    counter++;
  }
}

BENCHMARK_F(UsedTo, N6, GUMFixture, 10, 100)
{
  QueryConfig config;
  config.numOfParallelTasks = 6;
  std::shared_ptr<Query> query = query_UsedTo(config);
  int counter=0;
  while(query->next()) {
    counter++;
  }
}

BENCHMARK_F(UsedTo, N7, GUMFixture, 10, 100)
{
  QueryConfig config;
  config.numOfParallelTasks = 7;
  std::shared_ptr<Query> query = query_UsedTo(config);
  int counter=0;
  while(query->next()) {
    counter++;
  }
}

BENCHMARK_F(UsedTo, N8, GUMFixture, 10, 100)
{
  QueryConfig config;
  config.numOfParallelTasks = 8;
  std::shared_ptr<Query> query = query_UsedTo(config);
  int counter=0;
  while(query->next()) {
    counter++;
  }
}

BASELINE_F(CreateQuery, N1, GUMFixture, 10, 100)
{
  QueryConfig config;
  config.numOfParallelTasks = 1;
  std::shared_ptr<Query> query = query_UsedTo(config);
  query->getBestPlan();
}

BENCHMARK_F(CreateQuery, N2, GUMFixture, 10, 100)
{
  QueryConfig config;
  config.numOfParallelTasks = 2;
  std::shared_ptr<Query> query = query_UsedTo(config);
  query->getBestPlan();
}

BENCHMARK_F(CreateQuery, N3, GUMFixture, 10, 100)
{
  QueryConfig config;
  config.numOfParallelTasks = 3;
  std::shared_ptr<Query> query = query_UsedTo(config);
  query->getBestPlan();
}

BENCHMARK_F(CreateQuery, N4, GUMFixture, 10, 100)
{
  QueryConfig config;
  config.numOfParallelTasks = 4;
  std::shared_ptr<Query> query = query_UsedTo(config);
  query->getBestPlan();
}

BENCHMARK_F(CreateQuery, N5, GUMFixture, 10, 100)
{
  QueryConfig config;
  config.numOfParallelTasks = 5;
  std::shared_ptr<Query> query = query_UsedTo(config);
  query->getBestPlan();
}

BENCHMARK_F(CreateQuery, N6, GUMFixture, 10, 100)
{
  QueryConfig config;
  config.numOfParallelTasks = 6;
  std::shared_ptr<Query> query = query_UsedTo(config);
  query->getBestPlan();
}

BENCHMARK_F(CreateQuery, N7, GUMFixture, 10, 100)
{
  QueryConfig config;
  config.numOfParallelTasks = 7;
  std::shared_ptr<Query> query = query_UsedTo(config);
  query->getBestPlan();
}

BENCHMARK_F(CreateQueryCreateQuery, N8, GUMFixture, 10, 100)
{
  QueryConfig config;
  config.numOfParallelTasks = 8;
  std::shared_ptr<Query> query = query_UsedTo(config);
  query->getBestPlan();
}

BASELINE(CreateThreadPool, N1, 10, 1000)
{
  ThreadPool t(1);
}

BENCHMARK(CreateThreadPool, N2, 10, 1000)
{
  ThreadPool t(2);
}

BENCHMARK(CreateThreadPool, N3, 10, 1000)
{
  ThreadPool t(3);
}

BENCHMARK(CreateThreadPool, N4, 10, 1000)
{
  ThreadPool t(4);
}

BENCHMARK(CreateThreadPool, N5, 10, 1000)
{
  ThreadPool t(5);
}

BENCHMARK(CreateThreadPool, N6, 10, 1000)
{
  ThreadPool t(6);
}

BENCHMARK(CreateThreadPool, N7, 10, 1000)
{
  ThreadPool t(7);
}

BENCHMARK(CreateThreadPool, N8, 10, 1000)
{
  ThreadPool t(8);
}

<commit_msg>Fix benchmark group name.<commit_after>#include <celero/Celero.h>

#include <annis/query.h>
#include <annis/annosearch/exactannokeysearch.h>
#include <annis/annosearch/exactannovaluesearch.h>
#include <annis/annosearch/regexannosearch.h>

#include <annis/operators/pointing.h>
#include <annis/operators/precedence.h>

using namespace annis;

CELERO_MAIN

class GUMFixture : public celero::TestFixture
{
    public:
        GUMFixture()
        {
        }

        /*
        virtual std::vector<std::pair<int64_t, uint64_t>> getExperimentValues() const override
        {
            std::vector<std::pair<int64_t, uint64_t>> problemSpace;
            problemSpace.push_back(std::make_pair(1, uint64_t(0)));

            return problemSpace;
        }
        */

        /// Before each run, build a vector of random integers.
        virtual void setUp(int64_t experimentValue)
        {
          char* testDataEnv = std::getenv("ANNIS4_TEST_DATA");
          std::string dataDir("data");
          if (testDataEnv != NULL) {
            dataDir = testDataEnv;
          }
          db.load(dataDir + "/GUM", true);
        }

        DB db;

        std::shared_ptr<Query> query_PosDepPos(QueryConfig config)
        {
          std::shared_ptr<Query> query = std::make_shared<Query>(db, config);

          query->addNode(std::make_shared<ExactAnnoKeySearch>(db, "pos"));
          query->addNode(std::make_shared<ExactAnnoKeySearch>(db, "pos"));

          Annotation edgeAnno = {db.strings.add("func"), 0, db.strings.add("dep")};
          query->addOperator(std::make_shared<Pointing>(db.edges, db.strings, "", "dep", edgeAnno), 0, 1);
          return query;
        }

        std::shared_ptr<Query> query_UsedTo(QueryConfig config)
        {
          std::shared_ptr<Query> query = std::make_shared<Query>(db, config);

          query->addNode(std::make_shared<RegexAnnoSearch>(db, "pos", "NN.*"));
          query->addNode(std::make_shared<ExactAnnoValueSearch>(db, "annis4_internal", "tok", "used"));
          query->addNode(std::make_shared<ExactAnnoValueSearch>(db, "annis4_internal", "tok", "to"));

          query->addOperator(std::make_shared<Precedence>(db, db.edges), 0, 1);
          query->addOperator(std::make_shared<Precedence>(db, db.edges), 1, 2);

          return query;
        }

};

BASELINE_F(PosDepPos, N1, GUMFixture, 10, 100)
{
  QueryConfig config;
  config.numOfParallelTasks = 1;
  std::shared_ptr<Query> query = query_PosDepPos(config);
  int counter=0;
  while(query->next()) {
    counter++;
  }
}

BENCHMARK_F(PosDepPos, N2, GUMFixture, 10, 100)
{
  QueryConfig config;
  config.numOfParallelTasks = 2;
  std::shared_ptr<Query> query = query_PosDepPos(config);
  int counter=0;
  while(query->next()) {
    counter++;
  }
}

BENCHMARK_F(PosDepPos, N3, GUMFixture, 10, 100)
{
  QueryConfig config;
  config.numOfParallelTasks = 3;
  std::shared_ptr<Query> query = query_PosDepPos(config);
  int counter=0;
  while(query->next()) {
    counter++;
  }
}

BENCHMARK_F(PosDepPos, N4, GUMFixture, 10, 100)
{
  QueryConfig config;
  config.numOfParallelTasks = 4;
  std::shared_ptr<Query> query = query_PosDepPos(config);
  int counter=0;
  while(query->next()) {
    counter++;
  }
}

BENCHMARK_F(PosDepPos, N5, GUMFixture, 10, 100)
{
  QueryConfig config;
  config.numOfParallelTasks = 5;
  std::shared_ptr<Query> query = query_PosDepPos(config);
  int counter=0;
  while(query->next()) {
    counter++;
  }
}

BENCHMARK_F(PosDepPos, N6, GUMFixture, 10, 100)
{
  QueryConfig config;
  config.numOfParallelTasks = 6;
  std::shared_ptr<Query> query = query_PosDepPos(config);
  int counter=0;
  while(query->next()) {
    counter++;
  }
}

BENCHMARK_F(PosDepPos, N7, GUMFixture, 10, 100)
{
  QueryConfig config;
  config.numOfParallelTasks = 7;
  std::shared_ptr<Query> query = query_PosDepPos(config);
  int counter=0;
  while(query->next()) {
    counter++;
  }
}

BENCHMARK_F(PosDepPos, N8, GUMFixture, 10, 100)
{
  QueryConfig config;
  config.numOfParallelTasks = 8;
  std::shared_ptr<Query> query = query_PosDepPos(config);
  int counter=0;
  while(query->next()) {
    counter++;
  }
}

BASELINE_F(UsedTo, N1, GUMFixture, 10, 100)
{
  QueryConfig config;
  config.numOfParallelTasks = 1;
  std::shared_ptr<Query> query = query_UsedTo(config);
  int counter=0;
  while(query->next()) {
    counter++;
  }
}

BENCHMARK_F(UsedTo, N2, GUMFixture, 10, 100)
{
  QueryConfig config;
  config.numOfParallelTasks = 2;
  std::shared_ptr<Query> query = query_UsedTo(config);
  int counter=0;
  while(query->next()) {
    counter++;
  }
}

BENCHMARK_F(UsedTo, N3, GUMFixture, 10, 100)
{
  QueryConfig config;
  config.numOfParallelTasks = 3;
  std::shared_ptr<Query> query = query_UsedTo(config);
  int counter=0;
  while(query->next()) {
    counter++;
  }
}

BENCHMARK_F(UsedTo, N4, GUMFixture, 10, 100)
{
  QueryConfig config;
  config.numOfParallelTasks = 4;
  std::shared_ptr<Query> query = query_UsedTo(config);
  int counter=0;
  while(query->next()) {
    counter++;
  }
}

BENCHMARK_F(UsedTo, N5, GUMFixture, 10, 100)
{
  QueryConfig config;
  config.numOfParallelTasks = 5;
  std::shared_ptr<Query> query = query_UsedTo(config);
  int counter=0;
  while(query->next()) {
    counter++;
  }
}

BENCHMARK_F(UsedTo, N6, GUMFixture, 10, 100)
{
  QueryConfig config;
  config.numOfParallelTasks = 6;
  std::shared_ptr<Query> query = query_UsedTo(config);
  int counter=0;
  while(query->next()) {
    counter++;
  }
}

BENCHMARK_F(UsedTo, N7, GUMFixture, 10, 100)
{
  QueryConfig config;
  config.numOfParallelTasks = 7;
  std::shared_ptr<Query> query = query_UsedTo(config);
  int counter=0;
  while(query->next()) {
    counter++;
  }
}

BENCHMARK_F(UsedTo, N8, GUMFixture, 10, 100)
{
  QueryConfig config;
  config.numOfParallelTasks = 8;
  std::shared_ptr<Query> query = query_UsedTo(config);
  int counter=0;
  while(query->next()) {
    counter++;
  }
}

BASELINE_F(CreateQuery, N1, GUMFixture, 10, 100)
{
  QueryConfig config;
  config.numOfParallelTasks = 1;
  std::shared_ptr<Query> query = query_UsedTo(config);
  query->getBestPlan();
}

BENCHMARK_F(CreateQuery, N2, GUMFixture, 10, 100)
{
  QueryConfig config;
  config.numOfParallelTasks = 2;
  std::shared_ptr<Query> query = query_UsedTo(config);
  query->getBestPlan();
}

BENCHMARK_F(CreateQuery, N3, GUMFixture, 10, 100)
{
  QueryConfig config;
  config.numOfParallelTasks = 3;
  std::shared_ptr<Query> query = query_UsedTo(config);
  query->getBestPlan();
}

BENCHMARK_F(CreateQuery, N4, GUMFixture, 10, 100)
{
  QueryConfig config;
  config.numOfParallelTasks = 4;
  std::shared_ptr<Query> query = query_UsedTo(config);
  query->getBestPlan();
}

BENCHMARK_F(CreateQuery, N5, GUMFixture, 10, 100)
{
  QueryConfig config;
  config.numOfParallelTasks = 5;
  std::shared_ptr<Query> query = query_UsedTo(config);
  query->getBestPlan();
}

BENCHMARK_F(CreateQuery, N6, GUMFixture, 10, 100)
{
  QueryConfig config;
  config.numOfParallelTasks = 6;
  std::shared_ptr<Query> query = query_UsedTo(config);
  query->getBestPlan();
}

BENCHMARK_F(CreateQuery, N7, GUMFixture, 10, 100)
{
  QueryConfig config;
  config.numOfParallelTasks = 7;
  std::shared_ptr<Query> query = query_UsedTo(config);
  query->getBestPlan();
}

BENCHMARK_F(CreateQuery, N8, GUMFixture, 10, 100)
{
  QueryConfig config;
  config.numOfParallelTasks = 8;
  std::shared_ptr<Query> query = query_UsedTo(config);
  query->getBestPlan();
}

BASELINE(CreateThreadPool, N1, 10, 1000)
{
  ThreadPool t(1);
}

BENCHMARK(CreateThreadPool, N2, 10, 1000)
{
  ThreadPool t(2);
}

BENCHMARK(CreateThreadPool, N3, 10, 1000)
{
  ThreadPool t(3);
}

BENCHMARK(CreateThreadPool, N4, 10, 1000)
{
  ThreadPool t(4);
}

BENCHMARK(CreateThreadPool, N5, 10, 1000)
{
  ThreadPool t(5);
}

BENCHMARK(CreateThreadPool, N6, 10, 1000)
{
  ThreadPool t(6);
}

BENCHMARK(CreateThreadPool, N7, 10, 1000)
{
  ThreadPool t(7);
}

BENCHMARK(CreateThreadPool, N8, 10, 1000)
{
  ThreadPool t(8);
}

<|endoftext|>


<commit_before>/*ckwg +5
 * Copyright 2011 by Kitware, Inc. All Rights Reserved. Please refer to
 * KITWARE_LICENSE.TXT for licensing information, or contact General Counsel,
 * Kitware, Inc., 28 Corporate Drive, Clifton Park, NY 12065.
 */

#include <vistk/pipeline/config.h>

#include <boost/python.hpp>
#include <boost/python/suite/indexing/vector_indexing_suite.hpp>

/**
 * \file config.cxx
 *
 * \brief Python bindings for \link vistk::config\endlink.
 */

using namespace boost::python;

static vistk::config_t empty_config();
static vistk::config_t named_empty_config(vistk::config::key_t const& name);
static vistk::config::value_t get_value(vistk::config_t self, vistk::config::key_t const& key);
static vistk::config::value_t get_value_with_default(vistk::config_t self, vistk::config::key_t const& key, vistk::config::value_t const& def);
static void translator(vistk::configuration_exception const& e);

BOOST_PYTHON_MODULE(config)
{
  register_exception_translator<
    vistk::configuration_exception>(translator);

  def("empty_config", &vistk::config::empty_config
    , (arg("name") = vistk::config::key_t())
    , "Returns an empty configuration.");

  class_<vistk::config::key_t>("ConfigKey"
    , "A key for a configuration.");
  class_<vistk::config::keys_t>("ConfigKeys"
    , "A collection of keys for a configuration.")
    .def(vector_indexing_suite<vistk::config::keys_t>())
  ;
  class_<vistk::config::value_t>("ConfigValue"
    , "A value in the configuration.");

  class_<vistk::config, vistk::config_t, boost::noncopyable>("Config", no_init)
    .def("subblock", &vistk::config::subblock
      , (arg("name"))
      , "Returns a subblock from the configuration.")
    .def("subblock_view", &vistk::config::subblock_view
      , (arg("name"))
      , "Returns a linked subblock from the configuration.")
    .def("get_value", &get_value
      , (arg("key"))
      , "Retrieve a value from the configuration.")
    .def("get_value", &get_value_with_default
      , (arg("key"), arg("default"))
      , "Retrieve a value from the configuration, using a default in case of failure.")
    .def("set_value", &vistk::config::set_value
      , (arg("key"), arg("value"))
      , "Set a value in the configuration.")
    .def("unset_value", &vistk::config::unset_value
      , (arg("key"))
      , "Unset a value in the configuration.")
    .def("is_read_only", &vistk::config::is_read_only
      , (arg("key"))
      , "Check if a key is marked as read only.")
    .def("mark_read_only", &vistk::config::mark_read_only
      , (arg("key"))
      , "Mark a key as read only.")
    .def("merge_config", &vistk::config::merge_config
      , (arg("config"))
      , "Merge another configuration block into the current one.")
    .def("available_values", &vistk::config::available_values
      , "Retrieves the list of available values in the configuration.")
    .def("has_value", &vistk::config::has_value
      , (arg("key"))
      , "Returns True if the key is set.")
    .def_readonly("block_sep", &vistk::config::block_sep
      , "The string which separates block names from key names.")
    .def_readonly("global_value", &vistk::config::global_value
      , "A special key which is automatically inherited on subblock requests.")
  ;
}

vistk::config_t
empty_config()
{
  return vistk::config::empty_config();
}

vistk::config_t
named_empty_config(vistk::config::key_t const& name)
{
  return vistk::config::empty_config(name);
}

vistk::config::value_t
get_value(vistk::config_t self, vistk::config::key_t const& key)
{
  return self->get_value<vistk::config::value_t>(key);
}

vistk::config::value_t
get_value_with_default(vistk::config_t self, vistk::config::key_t const& key, vistk::config::value_t const& def)
{
  return self->get_value<vistk::config::value_t>(key, def);
}

void
translator(vistk::configuration_exception const& e)
{
  PyErr_SetString(PyExc_RuntimeError, e.what());
}
<commit_msg>Remove some unused code<commit_after>/*ckwg +5
 * Copyright 2011 by Kitware, Inc. All Rights Reserved. Please refer to
 * KITWARE_LICENSE.TXT for licensing information, or contact General Counsel,
 * Kitware, Inc., 28 Corporate Drive, Clifton Park, NY 12065.
 */

#include <vistk/pipeline/config.h>

#include <boost/python.hpp>
#include <boost/python/suite/indexing/vector_indexing_suite.hpp>

/**
 * \file config.cxx
 *
 * \brief Python bindings for \link vistk::config\endlink.
 */

using namespace boost::python;

static vistk::config::value_t get_value(vistk::config_t self, vistk::config::key_t const& key);
static vistk::config::value_t get_value_with_default(vistk::config_t self, vistk::config::key_t const& key, vistk::config::value_t const& def);
static void translator(vistk::configuration_exception const& e);

BOOST_PYTHON_MODULE(config)
{
  register_exception_translator<
    vistk::configuration_exception>(translator);

  def("empty_config", &vistk::config::empty_config
    , (arg("name") = vistk::config::key_t())
    , "Returns an empty configuration.");

  class_<vistk::config::key_t>("ConfigKey"
    , "A key for a configuration.");
  class_<vistk::config::keys_t>("ConfigKeys"
    , "A collection of keys for a configuration.")
    .def(vector_indexing_suite<vistk::config::keys_t>())
  ;
  class_<vistk::config::value_t>("ConfigValue"
    , "A value in the configuration.");

  class_<vistk::config, vistk::config_t, boost::noncopyable>("Config", no_init)
    .def("subblock", &vistk::config::subblock
      , (arg("name"))
      , "Returns a subblock from the configuration.")
    .def("subblock_view", &vistk::config::subblock_view
      , (arg("name"))
      , "Returns a linked subblock from the configuration.")
    .def("get_value", &get_value
      , (arg("key"))
      , "Retrieve a value from the configuration.")
    .def("get_value", &get_value_with_default
      , (arg("key"), arg("default"))
      , "Retrieve a value from the configuration, using a default in case of failure.")
    .def("set_value", &vistk::config::set_value
      , (arg("key"), arg("value"))
      , "Set a value in the configuration.")
    .def("unset_value", &vistk::config::unset_value
      , (arg("key"))
      , "Unset a value in the configuration.")
    .def("is_read_only", &vistk::config::is_read_only
      , (arg("key"))
      , "Check if a key is marked as read only.")
    .def("mark_read_only", &vistk::config::mark_read_only
      , (arg("key"))
      , "Mark a key as read only.")
    .def("merge_config", &vistk::config::merge_config
      , (arg("config"))
      , "Merge another configuration block into the current one.")
    .def("available_values", &vistk::config::available_values
      , "Retrieves the list of available values in the configuration.")
    .def("has_value", &vistk::config::has_value
      , (arg("key"))
      , "Returns True if the key is set.")
    .def_readonly("block_sep", &vistk::config::block_sep
      , "The string which separates block names from key names.")
    .def_readonly("global_value", &vistk::config::global_value
      , "A special key which is automatically inherited on subblock requests.")
  ;
}

vistk::config::value_t
get_value(vistk::config_t self, vistk::config::key_t const& key)
{
  return self->get_value<vistk::config::value_t>(key);
}

vistk::config::value_t
get_value_with_default(vistk::config_t self, vistk::config::key_t const& key, vistk::config::value_t const& def)
{
  return self->get_value<vistk::config::value_t>(key, def);
}

void
translator(vistk::configuration_exception const& e)
{
  PyErr_SetString(PyExc_RuntimeError, e.what());
}
<|endoftext|>