<commit_before>/*
 * led_strip.cpp - LEDs Strip class dedicated to WS2801
 *
 * Copyright (C) 2013 William Markezana <william.markezana@me.com>
 *
 */

#include "led_strip.h"

/*
 * constructor
 *
 */
led_strip::led_strip(const char *pDevice, size_t pWidth, size_t pHeight)
{
	mWidth = pWidth;
	mHeight = pHeight;
	mBuffer.resize(mWidth * mHeight * 3);
	mSpi = new spi(pDevice);
	mTwoDimensions = true;

	set_gamma(0.25);
}

/*
 * constructor
 *
 */
led_strip::led_strip(const char *pDevice, size_t pLength)
{
	mWidth = pLength;
	mHeight = 1;
	mBuffer.resize(mWidth * 3);
	mSpi = new spi(pDevice);
	mTwoDimensions = false;

	set_gamma(0.25);
}

/*
 * destructor
 *
 */
led_strip::~led_strip()
{
	delete mSpi;
}

/*
 * public functions
 *
 */
void led_strip::set_gamma(float pGamma)
{
	float gamma;
	for (int i = 0; i < 256; i++)
	{
		gamma = pow(256.0f,pow((float)i/255.0f,pGamma))-1.0f;
		if (gamma > 255.0f) gamma = 255.0f;
		if (gamma <  0.0f) gamma = 0.0f;
		mGammaTable[i] = (uint8_t)gamma;
	}
}

void led_strip::paint(bitmap *pBitmap, bool pReversed, bool pWaitForCompletion)
{
	int bufferPtr = 0;
	rgb_color CurrentColor;

	if (!mTwoDimensions)
	{
		if (!pReversed)
		{
			for (size_t x = 0; x < mWidth; x++)
			{
				CurrentColor = pBitmap->get_pixel(x,0);

				mBuffer[bufferPtr++] = mGammaTable[CurrentColor.B];
				mBuffer[bufferPtr++] = mGammaTable[CurrentColor.G];
				mBuffer[bufferPtr++] = mGammaTable[CurrentColor.R];
			}
		}
		else
		{
			for (size_t x = 0; x < mWidth; x++)
			{
				CurrentColor = pBitmap->get_pixel(mWidth-1-x,0);

				mBuffer[bufferPtr++] = mGammaTable[CurrentColor.B];
				mBuffer[bufferPtr++] = mGammaTable[CurrentColor.G];
				mBuffer[bufferPtr++] = mGammaTable[CurrentColor.R];
			}
		}
	}
	else
	{
		if (!pReversed)
		{
			for (size_t y = 0; y < mHeight; y++)
			{
				if (y%2 == 0)
				{
					for (size_t x = 0; x < mWidth; x++)
					{
						CurrentColor = pBitmap->get_pixel(x,y);

						mBuffer[bufferPtr++] = mGammaTable[CurrentColor.B];
						mBuffer[bufferPtr++] = mGammaTable[CurrentColor.G];
						mBuffer[bufferPtr++] = mGammaTable[CurrentColor.R];
					}
				}
				else
				{
					for (size_t x = 0; x < mWidth; x++)
					{
						CurrentColor = pBitmap->get_pixel(mWidth-1-x,y);

						mBuffer[bufferPtr++] = mGammaTable[CurrentColor.B];
						mBuffer[bufferPtr++] = mGammaTable[CurrentColor.G];
						mBuffer[bufferPtr++] = mGammaTable[CurrentColor.R];
					}
				}
			}
		}
		else
		{
			for (size_t y = mHeight - 1; y >= 0; y--)
			{
				if (y%2 == 0)
				{
					for (size_t x = 0; x < mWidth; x++)
					{
						CurrentColor = pBitmap->get_pixel(x,y);

						mBuffer[bufferPtr++] = mGammaTable[CurrentColor.B];
						mBuffer[bufferPtr++] = mGammaTable[CurrentColor.G];
						mBuffer[bufferPtr++] = mGammaTable[CurrentColor.R];
					}
				}
				else
				{
					for (size_t x = 0; x < mWidth; x++)
					{
						CurrentColor = pBitmap->get_pixel(mWidth-1-x,y);

						mBuffer[bufferPtr++] = mGammaTable[CurrentColor.B];
						mBuffer[bufferPtr++] = mGammaTable[CurrentColor.G];
						mBuffer[bufferPtr++] = mGammaTable[CurrentColor.R];
					}
				}
			}
		}
	}

	mSpi->write_buffer(&mBuffer.front(), mBuffer.size());

	if (pWaitForCompletion)
		mSpi->waitForTransfertToComplete();
}
<commit_msg>WS2801 RGB order bug fix<commit_after>/*
 * led_strip.cpp - LEDs Strip class dedicated to WS2801
 *
 * Copyright (C) 2013 William Markezana <william.markezana@me.com>
 *
 */

#include "led_strip.h"

/*
 * constructor
 *
 */
led_strip::led_strip(const char *pDevice, size_t pWidth, size_t pHeight)
{
	mWidth = pWidth;
	mHeight = pHeight;
	mBuffer.resize(mWidth * mHeight * 3);
	mSpi = new spi(pDevice);
	mTwoDimensions = true;

	set_gamma(0.25);
}

/*
 * constructor
 *
 */
led_strip::led_strip(const char *pDevice, size_t pLength)
{
	mWidth = pLength;
	mHeight = 1;
	mBuffer.resize(mWidth * 3);
	mSpi = new spi(pDevice);
	mTwoDimensions = false;

	set_gamma(0.25);
}

/*
 * destructor
 *
 */
led_strip::~led_strip()
{
	delete mSpi;
}

/*
 * public functions
 *
 */
void led_strip::set_gamma(float pGamma)
{
	float gamma;
	for (int i = 0; i < 256; i++)
	{
		gamma = pow(256.0f,pow((float)i/255.0f,pGamma))-1.0f;
		if (gamma > 255.0f) gamma = 255.0f;
		if (gamma <  0.0f) gamma = 0.0f;
		mGammaTable[i] = (uint8_t)gamma;
	}
}

void led_strip::paint(bitmap *pBitmap, bool pReversed, bool pWaitForCompletion)
{
	int bufferPtr = 0;
	rgb_color CurrentColor;

	if (!mTwoDimensions)
	{
		if (!pReversed)
		{
			for (size_t x = 0; x < mWidth; x++)
			{
				CurrentColor = pBitmap->get_pixel(x,0);

				mBuffer[bufferPtr++] = mGammaTable[CurrentColor.B];
				mBuffer[bufferPtr++] = mGammaTable[CurrentColor.G];
				mBuffer[bufferPtr++] = mGammaTable[CurrentColor.R];
			}
		}
		else
		{
			for (size_t x = 0; x < mWidth; x++)
			{
				CurrentColor = pBitmap->get_pixel(mWidth-1-x,0);

				mBuffer[bufferPtr++] = mGammaTable[CurrentColor.B];
				mBuffer[bufferPtr++] = mGammaTable[CurrentColor.G];
				mBuffer[bufferPtr++] = mGammaTable[CurrentColor.R];
			}
		}
	}
	else
	{
		if (!pReversed)
		{
			for (size_t y = 0; y < mHeight; y++)
			{
				if (y%2 == 0)
				{
					for (size_t x = 0; x < mWidth; x++)
					{
						CurrentColor = pBitmap->get_pixel(x,y);

						mBuffer[bufferPtr++] = mGammaTable[CurrentColor.R];
						mBuffer[bufferPtr++] = mGammaTable[CurrentColor.G];
						mBuffer[bufferPtr++] = mGammaTable[CurrentColor.B];
					}
				}
				else
				{
					for (size_t x = 0; x < mWidth; x++)
					{
						CurrentColor = pBitmap->get_pixel(mWidth-1-x,y);

						mBuffer[bufferPtr++] = mGammaTable[CurrentColor.R];
						mBuffer[bufferPtr++] = mGammaTable[CurrentColor.G];
						mBuffer[bufferPtr++] = mGammaTable[CurrentColor.B];
					}
				}
			}
		}
		else
		{
			for (size_t y = mHeight - 1; y >= 0; y--)
			{
				if (y%2 == 0)
				{
					for (size_t x = 0; x < mWidth; x++)
					{
						CurrentColor = pBitmap->get_pixel(x,y);

						mBuffer[bufferPtr++] = mGammaTable[CurrentColor.R];
						mBuffer[bufferPtr++] = mGammaTable[CurrentColor.G];
						mBuffer[bufferPtr++] = mGammaTable[CurrentColor.B];
					}
				}
				else
				{
					for (size_t x = 0; x < mWidth; x++)
					{
						CurrentColor = pBitmap->get_pixel(mWidth-1-x,y);

						mBuffer[bufferPtr++] = mGammaTable[CurrentColor.R];
						mBuffer[bufferPtr++] = mGammaTable[CurrentColor.G];
						mBuffer[bufferPtr++] = mGammaTable[CurrentColor.B];
					}
				}
			}
		}
	}

	mSpi->write_buffer(&mBuffer.front(), mBuffer.size());

	if (pWaitForCompletion)
		mSpi->waitForTransfertToComplete();
}
<|endoftext|>


<commit_before>#ifndef MINIASCAPE_STEPPER
#define MINIASCAPE_STEPPER
#include "Space.hpp"
#include "Rule.hpp"
#include "zip_iterator.hpp"

namespace miniascape
{

template<typename T_traits>
class Stepper
{
  public:
    using traits_type = T_traits;
    using time_type   = typename traits_type::time_type;
    using state_type  = typename traits_type::state_type;
    using cell_type   = typename traits_type::cell_type;
    using rule_type   = RuleBase<traits_type>;
    using space_type  = Space<traits_type>;

    static time_type step(space_type& space, const rule_type& rule);
};

template<typename T_traits>
typename Stepper<T_traits>::time_type
Stepper<T_traits>::step(space_type& space, const rule_type& rule)
{
    for(auto cell = make_zip(space.world().cbegin(),space.temp().begin());
            cell != make_zip(space.world().cend(),  space.temp().end()); ++cell)
        **get<1>(cell) = rule.step(**get<0>(cell));

    for(auto cell = make_zip(space.world().begin(), space.temp().begin());
            cell != make_zip(space.world().end(),   space.temp().end()); ++cell)
        (*get<0>(cell))->state = std::move(**get<1>(cell));

    return rule.delta_t();
}

}

#endif /* MINIASCAPE_STEPPER */
<commit_msg>fix value access of space.temp<commit_after>#ifndef MINIASCAPE_STEPPER
#define MINIASCAPE_STEPPER
#include "Space.hpp"
#include "Rule.hpp"
#include "zip_iterator.hpp"

namespace miniascape
{

template<typename T_traits>
class Stepper
{
  public:
    using traits_type = T_traits;
    using time_type   = typename traits_type::time_type;
    using state_type  = typename traits_type::state_type;
    using cell_type   = typename traits_type::cell_type;
    using rule_type   = RuleBase<traits_type>;
    using space_type  = Space<traits_type>;

    static time_type step(space_type& space, const rule_type& rule);
};

template<typename T_traits>
typename Stepper<T_traits>::time_type
Stepper<T_traits>::step(space_type& space, const rule_type& rule)
{
    for(auto cell = make_zip(space.world().cbegin(),space.temp().begin());
            cell != make_zip(space.world().cend(),  space.temp().end()); ++cell)
        *get<1>(cell) = rule.step(**get<0>(cell));

    for(auto cell = make_zip(space.world().begin(), space.temp().begin());
            cell != make_zip(space.world().end(),   space.temp().end()); ++cell)
        (*get<0>(cell))->state = *get<1>(cell);

    return rule.delta_t();
}

}

#endif /* MINIASCAPE_STEPPER */
<|endoftext|>


<commit_before>/*
 * This file is part of kpeople
 *
 * Copyright (C) 2010-2011 Collabora Ltd. <info@collabora.co.uk>
 *   @author George Goldberg <george.goldberg@collabora.co.uk>
 *   @author Martin Klapetek <martin.klapetek@gmail.com>
 *
 * Copyright (C) 2012  Aleix Pol Gonzalez <aleixpol@blue-systems.com>
 *
 * 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.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 */

#include "person-cache.h"

#include <KDebug>
#include <KGlobal>
#include <KUrl>

#include <QtCore/QHash>

#include <Soprano/Query/QueryLanguage>
#include <Soprano/QueryResultIterator>
#include <Soprano/Model>

#include <Nepomuk/ResourceManager>
#include <Nepomuk/Variant>

#include <Nepomuk/Vocabulary/PIMO>
#include <Nepomuk/Vocabulary/NCO>
#include <Soprano/Vocabulary/NAO>

#include "persons-model.h"
#include "persons-model-item.h"
#include "persons-model-contact-item.h"

/******************************** PersonCache::Private ********************************************/

class PersonCachePrivate {

public:
    explicit PersonCachePrivate()
    { }

    QHash<QUrl, PersonsModelItem*> persons;
    QList<QUrl> allRequestedKeys;
};

/******************************** PersonCache *****************************************************/

PersonCache::PersonCache(QObject* parent)
  : QObject(parent),
    d_ptr(new PersonCachePrivate)
{}

PersonCache::~PersonCache()
{
    delete d_ptr;
}

void PersonCache::startQuery()
{
    QMetaObject::invokeMethod(this, "query", Qt::QueuedConnection);
}

//TODO: maybe move to a thread?
void PersonCache::query()
{
    Q_D(PersonCache);
    kDebug();

    QString nco_query = QString::fromUtf8("select distinct ?uri ?nao_prefLabel ?pimo_groundingOccurance ?nco_hasIMAccount"
                      "?nco_imNickname ?telepathy_statusType ?nco_imID ?nco_imAccountType ?nco_hasEmailAddress"
                      "?nao_prefSymbol ?telepathy_accountIdentifier ?nco_imStatus"

                      "WHERE { ?uri a nco:Contact ."

                      "?uri                       nco:hasIMAccount            ?nco_hasIMAccount ."
                      "?nco_hasIMAccount          nco:imNickname              ?nco_imNickname ."
                      "?nco_hasIMAccount          telepathy:statusType        ?telepathy_statusType ."
                      "?nco_hasIMAccount          nco:imStatus                ?nco_imStatus ."
                      "?nco_hasIMAccount          nco:imID                    ?nco_imID ."
                      "?nco_hasIMAccount          nco:imAccountType           ?nco_imAccountType ."
                      "?nco_hasIMAccount          nco:isAccessedBy            ?nco_isAccessedBy ."
                      "?nco_isAccessedBy          telepathy:accountIdentifier ?telepathy_accountIdentifier ."

                      "OPTIONAL { ?pimo_groundingOccurance  pimo:groundingOccurrence    ?uri . }"

                      "OPTIONAL { ?uri            nao:prefLabel        ?nao_prefLabel . }"
                      "OPTIONAL { ?uri            nao:prefSymbol       ?nao_prefSymbol . }"
                      "OPTIONAL { ?uri            nco:hasEmailAddress  ?nco_hasEmailAddress . }"

    "}");

    QList<QUrl> list;
    list << Soprano::Vocabulary::NAO::prefLabel()
    << Soprano::Vocabulary::NAO::prefSymbol()
    << Nepomuk::Vocabulary::NCO::imNickname()
    << Nepomuk::Vocabulary::NCO::imAccountType()
    << Nepomuk::Vocabulary::NCO::imID()
    //                      << Nepomuk::Vocabulary::Telepathy::statusType()
    //                      << Nepomuk::Vocabulary::Telepathy::accountIdentifier()
    << QUrl(QLatin1String("http://nepomuk.kde.org/ontologies/2009/06/20/telepathy#statusType"))
    << QUrl(QLatin1String("http://nepomuk.kde.org/ontologies/2009/06/20/telepathy#accountIdentifier"))
    << Nepomuk::Vocabulary::NCO::imStatus()
    << Nepomuk::Vocabulary::NCO::hasEmailAddress();

    Soprano::Model* m = Nepomuk::ResourceManager::instance()->mainModel();
    Soprano::QueryResultIterator it = m->executeQuery(nco_query,
                                                      Soprano::Query::QueryLanguageSparql);

    QList<PersonsModelContactItem*> nonpersonContacts;

    while(it.next()) {
        QUrl currentUri = it[QLatin1String("uri")].uri();
        QString display = it[QLatin1String("nao_prefLabel")].toString();
        PersonsModelContactItem* contactNode = new PersonsModelContactItem(currentUri, display);

        Q_FOREACH(const QUrl &keyUri, list) {
            QString keyString = keyUri.toString();
            //convert every key to correspond to the nepomuk bindings
            //FIXME: get this method out of the loop, it repeats too many times for nothing
            keyString = keyString.mid(keyString.lastIndexOf(QLatin1Char('/')) + 1).replace(QLatin1Char('#'), QLatin1Char('_'));

            contactNode->addData(keyUri, it[keyString].toString());
        }

        QUrl pimoPersonUri = it[QLatin1String("pimo_groundingOccurance")].uri();
        if (!pimoPersonUri.isEmpty()) {
            QHash< QUrl, PersonsModelItem* >::const_iterator pos = d->persons.constFind(pimoPersonUri);
            if (pos == d->persons.constEnd())
                pos = d->persons.insert(pimoPersonUri, new PersonsModelItem(pimoPersonUri));
            pos.value()->appendRow(contactNode);
        } else {
            kDebug() << "Not a person" << currentUri << pimoPersonUri;
            nonpersonContacts += contactNode;
        }
    }

    // FIXME: Connect up signals/slots so that when the nepomuk context signals something has
    //        happened we relay it to the model

    emit contactsFetched(d->persons.values(), nonpersonContacts);
}

void PersonCache::onNewPersonCreated(Nepomuk::Resource res, QList<QUrl> types)
{
    Q_D(PersonCache);

    bool newPerson = false;
    PersonsModelItem *person = d->persons.value(res.resourceUri());
    if (!person) {
        person = new PersonsModelItem(res.resourceUri());
        newPerson = true;
    }

    kDebug() << "New person created in Nepomuk:" << newPerson;

//     Q_FOREACH (const QUrl &keyUri, types) {
//         if (res.hasProperty(keyUri)) {
//             person->addData(keyUri, res.property(keyUri).variant());
//         }
//     }
    if (newPerson) {
        d->persons.insert(res.resourceUri(), person);
        emit personAddedToCache(person);
    }
    //TODO: Shouldn't we add the contacts now?
}

void PersonCache::onPersonRemoved(Nepomuk::Resource res)
{
    //TODO: how do we connect that?
    Q_D(PersonCache);
    PersonsModelItem *person = d->persons.value(res.resourceUri());
    if(person) {
        emit removePerson(person);
    }
}

void PersonCache::onPersonPropertyChanged(Nepomuk::Resource res, Nepomuk::Types::Property property, QVariant value)
{
    //TODO: implement. wouldn't it be more interesting to listen to contacts changes? the only change for a person is different contacts...
    Q_D(PersonCache);
    PersonsModelItem *person = d->persons.value(res.resourceUri());
    if(person) {
//         person->setProperty(property, value)
    }
}

#include "person-cache.moc"
<commit_msg>Remove some information from the query that we're not using<commit_after>/*
 * This file is part of kpeople
 *
 * Copyright (C) 2010-2011 Collabora Ltd. <info@collabora.co.uk>
 *   @author George Goldberg <george.goldberg@collabora.co.uk>
 *   @author Martin Klapetek <martin.klapetek@gmail.com>
 *
 * Copyright (C) 2012  Aleix Pol Gonzalez <aleixpol@blue-systems.com>
 *
 * 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.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 */

#include "person-cache.h"

#include <KDebug>
#include <KGlobal>
#include <KUrl>

#include <QtCore/QHash>

#include <Soprano/Query/QueryLanguage>
#include <Soprano/QueryResultIterator>
#include <Soprano/Model>

#include <Nepomuk/ResourceManager>
#include <Nepomuk/Variant>

#include <Nepomuk/Vocabulary/PIMO>
#include <Nepomuk/Vocabulary/NCO>
#include <Soprano/Vocabulary/NAO>

#include "persons-model.h"
#include "persons-model-item.h"
#include "persons-model-contact-item.h"

/******************************** PersonCache::Private ********************************************/

class PersonCachePrivate {

public:
    explicit PersonCachePrivate()
    { }

    QHash<QUrl, PersonsModelItem*> persons;
    QList<QUrl> allRequestedKeys;
};

/******************************** PersonCache *****************************************************/

PersonCache::PersonCache(QObject* parent)
  : QObject(parent),
    d_ptr(new PersonCachePrivate)
{}

PersonCache::~PersonCache()
{
    delete d_ptr;
}

void PersonCache::startQuery()
{
    QMetaObject::invokeMethod(this, "query", Qt::QueuedConnection);
}

//TODO: maybe move to a thread?
void PersonCache::query()
{
    Q_D(PersonCache);
    kDebug();

    QString nco_query = QString::fromUtf8("select distinct ?uri ?nao_prefLabel ?pimo_groundingOccurance ?nco_hasIMAccount"
                      "?nco_imNickname ?telepathy_statusType ?nco_imID ?nco_imAccountType ?nco_hasEmailAddress"
                      "?nao_prefSymbol ?telepathy_accountIdentifier ?nco_imStatus"

                      "WHERE { ?uri a nco:Contact ."

                      "?uri                       nco:hasIMAccount            ?nco_hasIMAccount ."
                      "?nco_hasIMAccount          nco:imNickname              ?nco_imNickname ."
                      "?nco_hasIMAccount          telepathy:statusType        ?telepathy_statusType ."
                      "?nco_hasIMAccount          nco:imStatus                ?nco_imStatus ."
                      "?nco_hasIMAccount          nco:imID                    ?nco_imID ."
                      "?nco_hasIMAccount          nco:imAccountType           ?nco_imAccountType ."

                      "OPTIONAL { ?pimo_groundingOccurance  pimo:groundingOccurrence    ?uri . }"

                      "OPTIONAL { ?uri            nao:prefLabel        ?nao_prefLabel . }"
                      "OPTIONAL { ?uri            nao:prefSymbol       ?nao_prefSymbol . }"
                      "OPTIONAL { ?uri            nco:hasEmailAddress  ?nco_hasEmailAddress . }"

    "}");

    QList<QUrl> list;
    list << Soprano::Vocabulary::NAO::prefLabel()
    << Soprano::Vocabulary::NAO::prefSymbol()
    << Nepomuk::Vocabulary::NCO::imNickname()
    << Nepomuk::Vocabulary::NCO::imAccountType()
    << Nepomuk::Vocabulary::NCO::imID()
    //                      << Nepomuk::Vocabulary::Telepathy::statusType()
    //                      << Nepomuk::Vocabulary::Telepathy::accountIdentifier()
    << QUrl(QLatin1String("http://nepomuk.kde.org/ontologies/2009/06/20/telepathy#statusType"))
    << Nepomuk::Vocabulary::NCO::imStatus()
    << Nepomuk::Vocabulary::NCO::hasEmailAddress();

    Soprano::Model* m = Nepomuk::ResourceManager::instance()->mainModel();
    Soprano::QueryResultIterator it = m->executeQuery(nco_query,
                                                      Soprano::Query::QueryLanguageSparql);

    QList<PersonsModelContactItem*> nonpersonContacts;

    while(it.next()) {
        QUrl currentUri = it[QLatin1String("uri")].uri();
        QString display = it[QLatin1String("nao_prefLabel")].toString();
        PersonsModelContactItem* contactNode = new PersonsModelContactItem(currentUri, display);

        Q_FOREACH(const QUrl &keyUri, list) {
            QString keyString = keyUri.toString();
            //convert every key to correspond to the nepomuk bindings
            //FIXME: get this method out of the loop, it repeats too many times for nothing
            keyString = keyString.mid(keyString.lastIndexOf(QLatin1Char('/')) + 1).replace(QLatin1Char('#'), QLatin1Char('_'));

            contactNode->addData(keyUri, it[keyString].toString());
        }

        QUrl pimoPersonUri = it[QLatin1String("pimo_groundingOccurance")].uri();
        if (!pimoPersonUri.isEmpty()) {
            QHash< QUrl, PersonsModelItem* >::const_iterator pos = d->persons.constFind(pimoPersonUri);
            if (pos == d->persons.constEnd())
                pos = d->persons.insert(pimoPersonUri, new PersonsModelItem(pimoPersonUri));
            pos.value()->appendRow(contactNode);
        } else {
            kDebug() << "Not a person" << currentUri << pimoPersonUri;
            nonpersonContacts += contactNode;
        }
    }

    // FIXME: Connect up signals/slots so that when the nepomuk context signals something has
    //        happened we relay it to the model

    emit contactsFetched(d->persons.values(), nonpersonContacts);
}

void PersonCache::onNewPersonCreated(Nepomuk::Resource res, QList<QUrl> types)
{
    Q_D(PersonCache);

    bool newPerson = false;
    PersonsModelItem *person = d->persons.value(res.resourceUri());
    if (!person) {
        person = new PersonsModelItem(res.resourceUri());
        newPerson = true;
    }

    kDebug() << "New person created in Nepomuk:" << newPerson;

//     Q_FOREACH (const QUrl &keyUri, types) {
//         if (res.hasProperty(keyUri)) {
//             person->addData(keyUri, res.property(keyUri).variant());
//         }
//     }
    if (newPerson) {
        d->persons.insert(res.resourceUri(), person);
        emit personAddedToCache(person);
    }
    //TODO: Shouldn't we add the contacts now?
}

void PersonCache::onPersonRemoved(Nepomuk::Resource res)
{
    //TODO: how do we connect that?
    Q_D(PersonCache);
    PersonsModelItem *person = d->persons.value(res.resourceUri());
    if(person) {
        emit removePerson(person);
    }
}

void PersonCache::onPersonPropertyChanged(Nepomuk::Resource res, Nepomuk::Types::Property property, QVariant value)
{
    //TODO: implement. wouldn't it be more interesting to listen to contacts changes? the only change for a person is different contacts...
    Q_D(PersonCache);
    PersonsModelItem *person = d->persons.value(res.resourceUri());
    if(person) {
//         person->setProperty(property, value)
    }
}

#include "person-cache.moc"
<|endoftext|>


<commit_before>#include <cstring>
#include <cstdio>
#include <memory>
#include <zlib.h>
#if NSPIRE
#include "../../platform/nspire/Interrupts.h"
#endif
#include "Archive.h"
#include "Quirks.h"
#include "utility/misc.h"

using tinystl::string;
using WalrusRPG::PIAF::ARCHIVE_VERSION;
using WalrusRPG::PIAF::Archive;
using WalrusRPG::PIAF::File;
using WalrusRPG::PIAF::FileType;
using WalrusRPG::PIAF::CompressionType;
using namespace WalrusRPG::PIAF;

#if TARGET_NSPIRE
using namespace Nspire;
#endif
namespace
{
    // Must get a pointer on the file table.
    /**
     * Reads the file table from given data pointer to an empty FileEntry
     * array long enough and a given number of files to load.
     * The pointer must directly access the file entry region of the archive.
     */
    void load_file_table(File *entries, uint32_t *data_offsets, char *data,
                         uint32_t nb_files)
    {
        for (unsigned index = 0; index < nb_files; index++)
        {
            // Offsetting the data pointer to the current file entry.
            char *current_entry_data = &data[index * 24];

            // Copying the filename to the FileEntry
            memcpy(entries[index].filename, current_entry_data, 8);
            // Making sure there is a terminating \0 character in the filename.
            entries[index].filename[8] = '\0';
            // /!\ Parsing a value to an enumeration.
            // Parses the file type and store it.
            entries[index].file_type =
                (FileType) read_big_endian_value<uint32_t>(&current_entry_data[8]);
            // /!\ Parsing a value to an enumeration.
            // Parses the compression type and store it.
            entries[index].compression_type =
                (CompressionType) read_big_endian_value<uint32_t>(
                    &current_entry_data[12]);
            // Parsign the file size and storing it.
            entries[index].file_size =
                read_big_endian_value<uint32_t>(&current_entry_data[16]);
            // Reading the file's data position in the archive data section.
            data_offsets[index] =
                read_big_endian_value<uint32_t>(&current_entry_data[20]);
        }
    }
}

Archive::Archive(string &filepath) : Archive(filepath.c_str())
{
}

Archive::Archive(const char *filepath)
    : file(nullptr), entries(nullptr), files_data(nullptr), files_loaded(nullptr)
{
#if TARGET_NSPIRE
    Interrupts::off();
#endif
    // Null pointer exception trigger
    if (filepath == nullptr)
    {
        throw PIAF::PIAFException("%s: Null path given", __FILE__);
    }
    // Solves the absolute path for given relative path.
    // Must be needed in targets like Ndless as it doesn't support environment
    // vars and thus PATH.
    std::unique_ptr<char> real_filename(Quirks::solve_absolute_path(filepath));

    // Open the archive
    file = fopen(real_filename.get(), "rb");
    // Again another null pointer trigger
    if (file == nullptr || file == NULL)
    {
        throw PIAF::PIAFException("%s: Missing file : %s", __FILE__, filepath);
    }

    // Loading stuff happens NOW
    // Checking if the file is long enough to have a header
    fseek(file, 0L, SEEK_END);
    uint64_t filesize = ftell(file);
    fseek(file, 0L, SEEK_SET);
    // File to small exception trigger
    if (filesize < 32)
    {
        throw PIAF::PIAFException("%s: File too small (%s): %d", __FILE__, filepath,
                                  filesize);
    }

    // Tempoary buffer to contain the header.
    char header_container[32] = {0};
    // Read the headers and trigger exceptions on errors
    if (fread(header_container, sizeof(char), 32, file) != 32)
    {
        throw PIAF::PIAFException("%s: Errorneous header : %s", __FILE__, filepath);
    }
    // Check if the magic cookie is the same.
    // It's a first way to detect if the file is correctly an archive.
    if (strncmp(header_container, "WRPGPIAF", 8) != 0)
    {
        // TODO throw bad header
        // fprintf(stderr, "Bad header magic word\n");
        throw PIAF::PIAFException("%s: Magic cookie mismatch : %s", __FILE__, filepath);
    }
    // Checksum time! Let's check if the header hasn"t been altered.
    uint32_t expected_checksum = read_big_endian_value<uint32_t>(&header_container[8]);
    uint32_t calculated_checksum = crc32(0L, (unsigned char *) &header_container[16], 16);
    if (expected_checksum != calculated_checksum)
    {
        // TODO throw bad checksum
        // fprintf(stderr, "Bad header checksum : %x != %x\n", expected_checksum,
        // calculated_checksum);
        throw PIAF::PIAFException("%s: Bad checksum : %s", __FILE__, filepath);
    }

    // TODO : version checking
    version = read_big_endian_value<uint32_t>(&header_container[16]);
    if (version != ARCHIVE_VERSION)
    {
        // std::exception up;
        // throw up; // haha
        throw PIAF::PIAFException("%s: Wrong(%s) : %08x is not supported by %08x",
                                  __FILE__, filepath, version, ARCHIVE_VERSION);
    }

    // At this point, the archive header looks unaltered and we finally can parse
    // and load the header.

    // Read the archive's number of files
    nb_files = read_big_endian_value<uint32_t>(&header_container[20]);
    // printf("nb_files : %u\n", nb_files);

    data_size = read_big_endian_value<uint32_t>(&header_container[24]);
    uint64_t calculated_data_size = filesize - 32 - 24 * nb_files;
    if (data_size != calculated_data_size)
    {
        // fprintf(stderr, "Bad data size : expected %u, got %lld\n", data_size,
        // calculated_data_size);
        throw PIAF::PIAFException("Data size mismatch", __LINE__, filepath);
    }
    // Check if there are files to manage.
    if (nb_files != 0)
    {
        // So, the file table is not empty. let's check if it's
        // not altered.
        uint32_t expected_filetable_checksum =
            read_big_endian_value<uint32_t>(&header_container[12]);
        char *file_entry_data = new char[24 * nb_files];
        fseek(file, 32, SEEK_SET);
        if (fread(file_entry_data, sizeof(char), 24 * nb_files, file) < 24 * nb_files)
        {
            throw PIAF::PIAFException("Can't read file entry data", __LINE__, filepath);
        }
        // Compare and trigger an exception if the checksum doesn't match.
        if (expected_filetable_checksum !=
            crc32(0L, (unsigned char *) file_entry_data, 24 * nb_files))
        {
            // fprintf(stderr, "Bad filetable checksum\n");
            throw PIAF::PIAFException("Bad Filetable checksum", __LINE__, filepath);
        }
        // Create the filetable.
        entries = new File[nb_files];
        // Parse and story the filetable.

        files_data = new uint8_t *[nb_files];
        files_loaded = new bool[nb_files];
        files_data_offset = new uint32_t[nb_files];
        for (unsigned i = 0; i < nb_files; i++)
        {
            files_data[i] = nullptr;
            files_loaded[i] = false;
            files_data_offset[i] = 0;
        }

        load_file_table(entries, files_data_offset, file_entry_data, nb_files);
        delete[] file_entry_data;
    }
#if TARGET_NSPIRE
    Interrupts::init();
#endif
}

Archive::~Archive()
{
    if (file != nullptr)
        fclose(file);
    if (entries != nullptr)
        delete[] entries;

    if (files_data != nullptr)
    {
        for (unsigned i = 0; i < nb_files; i++)
        {
            if (files_data[i] != nullptr)
            {
                delete[] files_data[i];
            }
        }
    }
    delete[] files_data;
    delete[] files_loaded;
    delete[] files_data_offset;
}

bool Archive::has(const char *filename)
{
    for (unsigned index = 0; index < nb_files; index++)
        if (strncmp(filename, entries[index].filename, 8) == 0)
            return true;
    return false;
}

/**
 * Returns the stored file's data from giving a filename.
 */
File Archive::get(const char *filename)
{
    for (unsigned index = 0; index < nb_files; index++)
    {
        if (strncmp(filename, entries[index].filename, 8) == 0)
        {
            // On demand load
            if (!files_loaded[index])
            {
#if TARGET_NSPIRE
                Interrupts::off();
#endif
                uint8_t *data = new uint8_t[entries[index].file_size];
                fseek(file, files_data_offset[index] + 32 + 24 * nb_files, SEEK_SET);
                if (fread(data, sizeof(uint8_t), entries[index].file_size, file) !=
                    entries[index].file_size)
                {
                    throw PIAF::PIAFException("%s: couldn't load %s from an archive.",
                                              filename);
                }
                else
                {
                    files_data[index] = data;
                    entries[index].data = data;
                }
                files_loaded[index] = true;
#if TARGET_NSPIRE
                Interrupts::init();
#endif
            }
            return entries[index];
        }
    }
    return File();
}

File::File(uint8_t *data) : data(data)
{
}

File::File() : data(nullptr)
{
}

File::~File()
{
}

const uint8_t *File::get()
{
    return data;
}
<commit_msg>Fixed a conditionnal<commit_after>#include <cstring>
#include <cstdio>
#include <memory>
#include <zlib.h>
#if TARGET_NSPIRE
#include "../../platform/nspire/Interrupts.h"
#endif
#include "Archive.h"
#include "Quirks.h"
#include "utility/misc.h"

using tinystl::string;
using WalrusRPG::PIAF::ARCHIVE_VERSION;
using WalrusRPG::PIAF::Archive;
using WalrusRPG::PIAF::File;
using WalrusRPG::PIAF::FileType;
using WalrusRPG::PIAF::CompressionType;
using namespace WalrusRPG::PIAF;

#ifdef TARGET_NSPIRE
using namespace Nspire;
#endif
namespace
{
    // Must get a pointer on the file table.
    /**
     * Reads the file table from given data pointer to an empty FileEntry
     * array long enough and a given number of files to load.
     * The pointer must directly access the file entry region of the archive.
     */
    void load_file_table(File *entries, uint32_t *data_offsets, char *data,
                         uint32_t nb_files)
    {
        for (unsigned index = 0; index < nb_files; index++)
        {
            // Offsetting the data pointer to the current file entry.
            char *current_entry_data = &data[index * 24];

            // Copying the filename to the FileEntry
            memcpy(entries[index].filename, current_entry_data, 8);
            // Making sure there is a terminating \0 character in the filename.
            entries[index].filename[8] = '\0';
            // /!\ Parsing a value to an enumeration.
            // Parses the file type and store it.
            entries[index].file_type =
                (FileType) read_big_endian_value<uint32_t>(&current_entry_data[8]);
            // /!\ Parsing a value to an enumeration.
            // Parses the compression type and store it.
            entries[index].compression_type =
                (CompressionType) read_big_endian_value<uint32_t>(
                    &current_entry_data[12]);
            // Parsign the file size and storing it.
            entries[index].file_size =
                read_big_endian_value<uint32_t>(&current_entry_data[16]);
            // Reading the file's data position in the archive data section.
            data_offsets[index] =
                read_big_endian_value<uint32_t>(&current_entry_data[20]);
        }
    }
}

Archive::Archive(string &filepath) : Archive(filepath.c_str())
{
}

Archive::Archive(const char *filepath)
    : file(nullptr), entries(nullptr), files_data(nullptr), files_loaded(nullptr)
{
#if TARGET_NSPIRE
    Interrupts::off();
#endif
    // Null pointer exception trigger
    if (filepath == nullptr)
    {
        throw PIAF::PIAFException("%s: Null path given", __FILE__);
    }
    // Solves the absolute path for given relative path.
    // Must be needed in targets like Ndless as it doesn't support environment
    // vars and thus PATH.
    std::unique_ptr<char> real_filename(Quirks::solve_absolute_path(filepath));

    // Open the archive
    file = fopen(real_filename.get(), "rb");
    // Again another null pointer trigger
    if (file == nullptr || file == NULL)
    {
        throw PIAF::PIAFException("%s: Missing file : %s", __FILE__, filepath);
    }

    // Loading stuff happens NOW
    // Checking if the file is long enough to have a header
    fseek(file, 0L, SEEK_END);
    uint64_t filesize = ftell(file);
    fseek(file, 0L, SEEK_SET);
    // File to small exception trigger
    if (filesize < 32)
    {
        throw PIAF::PIAFException("%s: File too small (%s): %d", __FILE__, filepath,
                                  filesize);
    }

    // Tempoary buffer to contain the header.
    char header_container[32] = {0};
    // Read the headers and trigger exceptions on errors
    if (fread(header_container, sizeof(char), 32, file) != 32)
    {
        throw PIAF::PIAFException("%s: Errorneous header : %s", __FILE__, filepath);
    }
    // Check if the magic cookie is the same.
    // It's a first way to detect if the file is correctly an archive.
    if (strncmp(header_container, "WRPGPIAF", 8) != 0)
    {
        // TODO throw bad header
        // fprintf(stderr, "Bad header magic word\n");
        throw PIAF::PIAFException("%s: Magic cookie mismatch : %s", __FILE__, filepath);
    }
    // Checksum time! Let's check if the header hasn"t been altered.
    uint32_t expected_checksum = read_big_endian_value<uint32_t>(&header_container[8]);
    uint32_t calculated_checksum = crc32(0L, (unsigned char *) &header_container[16], 16);
    if (expected_checksum != calculated_checksum)
    {
        // TODO throw bad checksum
        // fprintf(stderr, "Bad header checksum : %x != %x\n", expected_checksum,
        // calculated_checksum);
        throw PIAF::PIAFException("%s: Bad checksum : %s", __FILE__, filepath);
    }

    // TODO : version checking
    version = read_big_endian_value<uint32_t>(&header_container[16]);
    if (version != ARCHIVE_VERSION)
    {
        // std::exception up;
        // throw up; // haha
        throw PIAF::PIAFException("%s: Wrong(%s) : %08x is not supported by %08x",
                                  __FILE__, filepath, version, ARCHIVE_VERSION);
    }

    // At this point, the archive header looks unaltered and we finally can parse
    // and load the header.

    // Read the archive's number of files
    nb_files = read_big_endian_value<uint32_t>(&header_container[20]);
    // printf("nb_files : %u\n", nb_files);

    data_size = read_big_endian_value<uint32_t>(&header_container[24]);
    uint64_t calculated_data_size = filesize - 32 - 24 * nb_files;
    if (data_size != calculated_data_size)
    {
        // fprintf(stderr, "Bad data size : expected %u, got %lld\n", data_size,
        // calculated_data_size);
        throw PIAF::PIAFException("Data size mismatch", __LINE__, filepath);
    }
    // Check if there are files to manage.
    if (nb_files != 0)
    {
        // So, the file table is not empty. let's check if it's
        // not altered.
        uint32_t expected_filetable_checksum =
            read_big_endian_value<uint32_t>(&header_container[12]);
        char *file_entry_data = new char[24 * nb_files];
        fseek(file, 32, SEEK_SET);
        if (fread(file_entry_data, sizeof(char), 24 * nb_files, file) < 24 * nb_files)
        {
            throw PIAF::PIAFException("Can't read file entry data", __LINE__, filepath);
        }
        // Compare and trigger an exception if the checksum doesn't match.
        if (expected_filetable_checksum !=
            crc32(0L, (unsigned char *) file_entry_data, 24 * nb_files))
        {
            // fprintf(stderr, "Bad filetable checksum\n");
            throw PIAF::PIAFException("Bad Filetable checksum", __LINE__, filepath);
        }
        // Create the filetable.
        entries = new File[nb_files];
        // Parse and story the filetable.

        files_data = new uint8_t *[nb_files];
        files_loaded = new bool[nb_files];
        files_data_offset = new uint32_t[nb_files];
        for (unsigned i = 0; i < nb_files; i++)
        {
            files_data[i] = nullptr;
            files_loaded[i] = false;
            files_data_offset[i] = 0;
        }

        load_file_table(entries, files_data_offset, file_entry_data, nb_files);
        delete[] file_entry_data;
    }
#if TARGET_NSPIRE
    Interrupts::init();
#endif
}

Archive::~Archive()
{
    if (file != nullptr)
        fclose(file);
    if (entries != nullptr)
        delete[] entries;

    if (files_data != nullptr)
    {
        for (unsigned i = 0; i < nb_files; i++)
        {
            if (files_data[i] != nullptr)
            {
                delete[] files_data[i];
            }
        }
    }
    delete[] files_data;
    delete[] files_loaded;
    delete[] files_data_offset;
}

bool Archive::has(const char *filename)
{
    for (unsigned index = 0; index < nb_files; index++)
        if (strncmp(filename, entries[index].filename, 8) == 0)
            return true;
    return false;
}

/**
 * Returns the stored file's data from giving a filename.
 */
File Archive::get(const char *filename)
{
    for (unsigned index = 0; index < nb_files; index++)
    {
        if (strncmp(filename, entries[index].filename, 8) == 0)
        {
            // On demand load
            if (!files_loaded[index])
            {
#if TARGET_NSPIRE
                Interrupts::off();
#endif
                uint8_t *data = new uint8_t[entries[index].file_size];
                fseek(file, files_data_offset[index] + 32 + 24 * nb_files, SEEK_SET);
                if (fread(data, sizeof(uint8_t), entries[index].file_size, file) !=
                    entries[index].file_size)
                {
                    throw PIAF::PIAFException("%s: couldn't load %s from an archive.",
                                              filename);
                }
                else
                {
                    files_data[index] = data;
                    entries[index].data = data;
                }
                files_loaded[index] = true;
#if TARGET_NSPIRE
                Interrupts::init();
#endif
            }
            return entries[index];
        }
    }
    return File();
}

File::File(uint8_t *data) : data(data)
{
}

File::File() : data(nullptr)
{
}

File::~File()
{
}

const uint8_t *File::get()
{
    return data;
}
<|endoftext|>


<commit_before>// Copyright (c) 2011 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "content/ppapi_plugin/ppapi_thread.h"

#include <limits>

#include "base/process_util.h"
#include "base/rand_util.h"
#include "content/common/child_process.h"
#include "content/ppapi_plugin/plugin_process_dispatcher.h"
#include "ipc/ipc_channel_handle.h"
#include "ipc/ipc_sync_channel.h"
#include "ppapi/c/pp_errors.h"
#include "ppapi/c/ppp.h"
#include "ppapi/proxy/ppapi_messages.h"

PpapiThread::PpapiThread()
    : get_plugin_interface_(NULL),
      local_pp_module_(
          base::RandInt(0, std::numeric_limits<PP_Module>::max())) {
}

PpapiThread::~PpapiThread() {
  if (library_.is_valid()) {
    // The ShutdownModule function is optional.
    pp::proxy::Dispatcher::ShutdownModuleFunc shutdown_module =
        reinterpret_cast<pp::proxy::Dispatcher::ShutdownModuleFunc>(
            library_.GetFunctionPointer("PPP_ShutdownModule"));
    if (shutdown_module)
      shutdown_module();
  }
}

// The "regular" ChildThread implements this function and does some standard
// dispatching, then uses the message router. We don't actually need any of
// this so this function just overrides that one.
//
// Note that this function is called only for messages from the channel to the
// browser process. Messages from the renderer process are sent via a different
// channel that ends up at Dispatcher::OnMessageReceived.
bool PpapiThread::OnMessageReceived(const IPC::Message& msg) {
  IPC_BEGIN_MESSAGE_MAP(PpapiThread, msg)
    IPC_MESSAGE_HANDLER(PpapiMsg_LoadPlugin, OnMsgLoadPlugin)
    IPC_MESSAGE_HANDLER(PpapiMsg_CreateChannel, OnMsgCreateChannel)
  IPC_END_MESSAGE_MAP()
  return true;
}

MessageLoop* PpapiThread::GetIPCMessageLoop() {
  return ChildProcess::current()->io_message_loop();
}

base::WaitableEvent* PpapiThread::GetShutdownEvent() {
  return ChildProcess::current()->GetShutDownEvent();
}

std::set<PP_Instance>* PpapiThread::GetGloballySeenInstanceIDSet() {
  return &globally_seen_instance_ids_;
}

void PpapiThread::OnMsgLoadPlugin(const FilePath& path) {
  base::ScopedNativeLibrary library(base::LoadNativeLibrary(path));
  if (!library.is_valid())
    return;

  // Get the GetInterface function (required).
  get_plugin_interface_ =
      reinterpret_cast<pp::proxy::Dispatcher::GetInterfaceFunc>(
          library.GetFunctionPointer("PPP_GetInterface"));
  if (!get_plugin_interface_) {
    LOG(WARNING) << "No PPP_GetInterface in plugin library";
    return;
  }

  // Get the InitializeModule function (required).
  pp::proxy::Dispatcher::InitModuleFunc init_module =
      reinterpret_cast<pp::proxy::Dispatcher::InitModuleFunc>(
          library.GetFunctionPointer("PPP_InitializeModule"));
  if (!init_module) {
    LOG(WARNING) << "No PPP_InitializeModule in plugin library";
    return;
  }
  int32_t init_error = init_module(
      local_pp_module_,
      &pp::proxy::PluginDispatcher::GetInterfaceFromDispatcher);
  if (init_error != PP_OK) {
    LOG(WARNING) << "InitModule failed with error " << init_error;
    return;
  }

  library_.Reset(library.Release());
}

void PpapiThread::OnMsgCreateChannel(base::ProcessHandle host_process_handle,
                                     int renderer_id) {
  IPC::ChannelHandle channel_handle;
  if (!library_.is_valid() ||  // Plugin couldn't be loaded.
      !SetupRendererChannel(host_process_handle, renderer_id,
                            &channel_handle)) {
    Send(new PpapiHostMsg_ChannelCreated(IPC::ChannelHandle()));
    return;
  }

  Send(new PpapiHostMsg_ChannelCreated(channel_handle));
}

bool PpapiThread::SetupRendererChannel(base::ProcessHandle host_process_handle,
                                       int renderer_id,
                                       IPC::ChannelHandle* handle) {
  PluginProcessDispatcher* dispatcher = new PluginProcessDispatcher(
      host_process_handle, get_plugin_interface_);

  IPC::ChannelHandle plugin_handle;
  plugin_handle.name = StringPrintf("%d.r%d", base::GetCurrentProcId(),
                                    renderer_id);
  if (!dispatcher->InitWithChannel(this, plugin_handle, false))
    return false;

  handle->name = plugin_handle.name;
#if defined(OS_POSIX)
  // On POSIX, pass the renderer-side FD.
  handle->socket = base::FileDescriptor(::dup(dispatcher->GetRendererFD()),
                                        true);
#endif

  return true;
}

<commit_msg>Clarify the ownership of the dispatcher when we create it. Delete it if initialization fails (up until now, init can't fail, so this didn't end up being a real leak). Review URL: http://codereview.chromium.org/6821019<commit_after>// Copyright (c) 2011 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "content/ppapi_plugin/ppapi_thread.h"

#include <limits>

#include "base/process_util.h"
#include "base/rand_util.h"
#include "content/common/child_process.h"
#include "content/ppapi_plugin/plugin_process_dispatcher.h"
#include "ipc/ipc_channel_handle.h"
#include "ipc/ipc_sync_channel.h"
#include "ppapi/c/pp_errors.h"
#include "ppapi/c/ppp.h"
#include "ppapi/proxy/ppapi_messages.h"

PpapiThread::PpapiThread()
    : get_plugin_interface_(NULL),
      local_pp_module_(
          base::RandInt(0, std::numeric_limits<PP_Module>::max())) {
}

PpapiThread::~PpapiThread() {
  if (library_.is_valid()) {
    // The ShutdownModule function is optional.
    pp::proxy::Dispatcher::ShutdownModuleFunc shutdown_module =
        reinterpret_cast<pp::proxy::Dispatcher::ShutdownModuleFunc>(
            library_.GetFunctionPointer("PPP_ShutdownModule"));
    if (shutdown_module)
      shutdown_module();
  }
}

// The "regular" ChildThread implements this function and does some standard
// dispatching, then uses the message router. We don't actually need any of
// this so this function just overrides that one.
//
// Note that this function is called only for messages from the channel to the
// browser process. Messages from the renderer process are sent via a different
// channel that ends up at Dispatcher::OnMessageReceived.
bool PpapiThread::OnMessageReceived(const IPC::Message& msg) {
  IPC_BEGIN_MESSAGE_MAP(PpapiThread, msg)
    IPC_MESSAGE_HANDLER(PpapiMsg_LoadPlugin, OnMsgLoadPlugin)
    IPC_MESSAGE_HANDLER(PpapiMsg_CreateChannel, OnMsgCreateChannel)
  IPC_END_MESSAGE_MAP()
  return true;
}

MessageLoop* PpapiThread::GetIPCMessageLoop() {
  return ChildProcess::current()->io_message_loop();
}

base::WaitableEvent* PpapiThread::GetShutdownEvent() {
  return ChildProcess::current()->GetShutDownEvent();
}

std::set<PP_Instance>* PpapiThread::GetGloballySeenInstanceIDSet() {
  return &globally_seen_instance_ids_;
}

void PpapiThread::OnMsgLoadPlugin(const FilePath& path) {
  base::ScopedNativeLibrary library(base::LoadNativeLibrary(path));
  if (!library.is_valid())
    return;

  // Get the GetInterface function (required).
  get_plugin_interface_ =
      reinterpret_cast<pp::proxy::Dispatcher::GetInterfaceFunc>(
          library.GetFunctionPointer("PPP_GetInterface"));
  if (!get_plugin_interface_) {
    LOG(WARNING) << "No PPP_GetInterface in plugin library";
    return;
  }

  // Get the InitializeModule function (required).
  pp::proxy::Dispatcher::InitModuleFunc init_module =
      reinterpret_cast<pp::proxy::Dispatcher::InitModuleFunc>(
          library.GetFunctionPointer("PPP_InitializeModule"));
  if (!init_module) {
    LOG(WARNING) << "No PPP_InitializeModule in plugin library";
    return;
  }
  int32_t init_error = init_module(
      local_pp_module_,
      &pp::proxy::PluginDispatcher::GetInterfaceFromDispatcher);
  if (init_error != PP_OK) {
    LOG(WARNING) << "InitModule failed with error " << init_error;
    return;
  }

  library_.Reset(library.Release());
}

void PpapiThread::OnMsgCreateChannel(base::ProcessHandle host_process_handle,
                                     int renderer_id) {
  IPC::ChannelHandle channel_handle;
  if (!library_.is_valid() ||  // Plugin couldn't be loaded.
      !SetupRendererChannel(host_process_handle, renderer_id,
                            &channel_handle)) {
    Send(new PpapiHostMsg_ChannelCreated(IPC::ChannelHandle()));
    return;
  }

  Send(new PpapiHostMsg_ChannelCreated(channel_handle));
}

bool PpapiThread::SetupRendererChannel(base::ProcessHandle host_process_handle,
                                       int renderer_id,
                                       IPC::ChannelHandle* handle) {
  PluginProcessDispatcher* dispatcher(new PluginProcessDispatcher(
      host_process_handle, get_plugin_interface_));

  IPC::ChannelHandle plugin_handle;
  plugin_handle.name = StringPrintf("%d.r%d", base::GetCurrentProcId(),
                                    renderer_id);
  if (!dispatcher->InitWithChannel(this, plugin_handle, false)) {
    delete dispatcher;
    return false;
  }

  handle->name = plugin_handle.name;
#if defined(OS_POSIX)
  // On POSIX, pass the renderer-side FD.
  handle->socket = base::FileDescriptor(::dup(dispatcher->GetRendererFD()),
                                        true);
#endif

  // From here, the dispatcher will manage its own lifetime according to the
  // lifetime of the attached channel.
  return true;
}

<|endoftext|>


<commit_before>#include <string>

#include "MT_Test.h"

#include "MT/MT_Core/support/stringsupport.h"

void FORMAT_STRING_TEST(std::string formatter,
                       MT_FORMAT_STRING_TYPE expect_format,
                       int expect_start,
                       int expect_stop,
                       int* p_in_status)
{

    MT_FORMAT_STRING_TYPE fs_type = MT_FORMAT_STRING_INVALID;
    int p_startof = -1;
    int p_endof = -1;

    fs_type = MT_hasFormatString(formatter.c_str(), &p_startof, &p_endof);

    if(fs_type != expect_format
       || p_startof != expect_start
       || p_endof != expect_stop)
    {
        *p_in_status = MT_TEST_ERROR;
        MT_TEST_ERROR_MESSAGE("MT_hasFormatString Error");
        fprintf(stderr, "    + With formatter %s gave fs_type %d, "
                        "p_startof %d, p_endof %d\n",
                        formatter.c_str(), fs_type, p_startof, p_endof);
        fprintf(stderr,
                "    + When expecting fs_type %d, "
                "p_startof %d, p_endof %d\n",
                expect_format, expect_start, expect_stop);
    }

}

void GET_FILE_EXTENSION_TEST(const std::string& path,
                             const std::string& expected_ext,
                             int* p_in_status)
{
    std::string ext = MT_GetFileExtension(path);
    if(strcmp(ext.c_str(), expected_ext.c_str()))
    {
        *p_in_status = MT_TEST_ERROR;
        fprintf(stderr,
                "    With path %s got extension %s when expecting %s\n",
                path.c_str(), ext.c_str(), expected_ext.c_str());
    }
}

void CHECK_FILE_EXTENSION_TEST(const char* path,
                               const char* check_ext,
                               bool expected_result,
                               int* p_in_status)
{
    bool result = MT_PathHasFileExtension(path, check_ext);
    if(result != expected_result)
    {
        *p_in_status = MT_TEST_ERROR;
        fprintf(stderr,
                "    With path %s got result '%s' when expecting '%s'\n",
                path, result ? "true" : "false",
                expected_result ? "true" : "false");
    }
}

void IS_DIGIT_TEST(char c, bool expected_result, int* p_in_status)
{
    bool result = MT_isdigit(c);
    if(result != expected_result)
    {
        *p_in_status = MT_TEST_ERROR;
        fprintf(stderr,
                "    With char '%c' got '%s' when expecting '%s'\n",
                c, result ? "true" : "false",
                expected_result ? "true" : "false");
    }
}

int main(int argc, char** argv)
{
    int status = MT_TEST_SUCCESS;

    /**************************************************/
    MT_TEST_START("MT_hasFormatString");

    FORMAT_STRING_TEST("%03d", MT_FORMAT_STRING_INT, 0, 3, &status);
    FORMAT_STRING_TEST("Hello %s", MT_FORMAT_STRING_STRING, 6, 7, &status);
    FORMAT_STRING_TEST("frame%05d", MT_FORMAT_STRING_INT, 5, 8, &status);
    FORMAT_STRING_TEST("%lc", MT_FORMAT_STRING_CHAR, 0, 2, &status);
    FORMAT_STRING_TEST("% a stray percent", MT_FORMAT_STRING_INVALID, -1, -1, &status);
    FORMAT_STRING_TEST("a percent at the end %", MT_FORMAT_STRING_INVALID, -1, -1, &status);

    /**************************************************/
    MT_TEST_START("MT_GetFileExtension");

#ifndef _WIN32
    GET_FILE_EXTENSION_TEST("/some/path/some.txt", "txt", &status);
    GET_FILE_EXTENSION_TEST("/some/path/and_no_extension", "", &status);
    GET_FILE_EXTENSION_TEST("~/a/path/with.long_extension", "long_extension", &status);
    GET_FILE_EXTENSION_TEST("relpath/with.dot/and.dat", "dat", &status);
    GET_FILE_EXTENSION_TEST("relpath/with.dot/and_no_extension", "", &status);
    GET_FILE_EXTENSION_TEST("/some/path.dot/with.two/dots.txt", "txt", &status);
    GET_FILE_EXTENSION_TEST("file.avi", "avi", &status);
    GET_FILE_EXTENSION_TEST("file..ext", "ext", &status);
    GET_FILE_EXTENSION_TEST("path/file..ext", "ext", &status);
    GET_FILE_EXTENSION_TEST("path\\with\\wrong\\seps.txt", "txt", &status);
#else
    /* TODO */
#endif

    /**************************************************/
    MT_TEST_START("MT_PathHasFileExtension");

    CHECK_FILE_EXTENSION_TEST("/some/path/file.txt", "txt", true, &status);
    CHECK_FILE_EXTENSION_TEST("/some/path/file.txt", "snot", false, &status);
    CHECK_FILE_EXTENSION_TEST("movie.avi", "avi", true, &status);
    CHECK_FILE_EXTENSION_TEST("someavi", "avi", false, &status);

    /**************************************************/
    MT_TEST_START("MT_isdigit");

    IS_DIGIT_TEST('0', true, &status);
    IS_DIGIT_TEST('1', true, &status);
    IS_DIGIT_TEST('2', true, &status);
    IS_DIGIT_TEST('3', true, &status);
    IS_DIGIT_TEST('4', true, &status);
    IS_DIGIT_TEST('5', true, &status);
    IS_DIGIT_TEST('6', true, &status);
    IS_DIGIT_TEST('7', true, &status);
    IS_DIGIT_TEST('8', true, &status);
    IS_DIGIT_TEST('9', true, &status);
    IS_DIGIT_TEST('0'-1, false, &status);
    IS_DIGIT_TEST('9'+1, false, &status);
    IS_DIGIT_TEST('a', false, &status);
    IS_DIGIT_TEST('!', false, &status);

    return status;
}
<commit_msg>[Test] Needed to include <string.h> in test_stringsupport to get successful build on linux.<commit_after>#include <string>
#include <string.h>

#include "MT_Test.h"

#include "MT/MT_Core/support/stringsupport.h"

void FORMAT_STRING_TEST(std::string formatter,
                       MT_FORMAT_STRING_TYPE expect_format,
                       int expect_start,
                       int expect_stop,
                       int* p_in_status)
{

    MT_FORMAT_STRING_TYPE fs_type = MT_FORMAT_STRING_INVALID;
    int p_startof = -1;
    int p_endof = -1;

    fs_type = MT_hasFormatString(formatter.c_str(), &p_startof, &p_endof);

    if(fs_type != expect_format
       || p_startof != expect_start
       || p_endof != expect_stop)
    {
        *p_in_status = MT_TEST_ERROR;
        MT_TEST_ERROR_MESSAGE("MT_hasFormatString Error");
        fprintf(stderr, "    + With formatter %s gave fs_type %d, "
                        "p_startof %d, p_endof %d\n",
                        formatter.c_str(), fs_type, p_startof, p_endof);
        fprintf(stderr,
                "    + When expecting fs_type %d, "
                "p_startof %d, p_endof %d\n",
                expect_format, expect_start, expect_stop);
    }

}

void GET_FILE_EXTENSION_TEST(const std::string& path,
                             const std::string& expected_ext,
                             int* p_in_status)
{
    std::string ext = MT_GetFileExtension(path);
    if(strcmp(ext.c_str(), expected_ext.c_str()))
    {
        *p_in_status = MT_TEST_ERROR;
        fprintf(stderr,
                "    With path %s got extension %s when expecting %s\n",
                path.c_str(), ext.c_str(), expected_ext.c_str());
    }
}

void CHECK_FILE_EXTENSION_TEST(const char* path,
                               const char* check_ext,
                               bool expected_result,
                               int* p_in_status)
{
    bool result = MT_PathHasFileExtension(path, check_ext);
    if(result != expected_result)
    {
        *p_in_status = MT_TEST_ERROR;
        fprintf(stderr,
                "    With path %s got result '%s' when expecting '%s'\n",
                path, result ? "true" : "false",
                expected_result ? "true" : "false");
    }
}

void IS_DIGIT_TEST(char c, bool expected_result, int* p_in_status)
{
    bool result = MT_isdigit(c);
    if(result != expected_result)
    {
        *p_in_status = MT_TEST_ERROR;
        fprintf(stderr,
                "    With char '%c' got '%s' when expecting '%s'\n",
                c, result ? "true" : "false",
                expected_result ? "true" : "false");
    }
}

int main(int argc, char** argv)
{
    int status = MT_TEST_SUCCESS;

    /**************************************************/
    MT_TEST_START("MT_hasFormatString");

    FORMAT_STRING_TEST("%03d", MT_FORMAT_STRING_INT, 0, 3, &status);
    FORMAT_STRING_TEST("Hello %s", MT_FORMAT_STRING_STRING, 6, 7, &status);
    FORMAT_STRING_TEST("frame%05d", MT_FORMAT_STRING_INT, 5, 8, &status);
    FORMAT_STRING_TEST("%lc", MT_FORMAT_STRING_CHAR, 0, 2, &status);
    FORMAT_STRING_TEST("% a stray percent", MT_FORMAT_STRING_INVALID, -1, -1, &status);
    FORMAT_STRING_TEST("a percent at the end %", MT_FORMAT_STRING_INVALID, -1, -1, &status);

    /**************************************************/
    MT_TEST_START("MT_GetFileExtension");

#ifndef _WIN32
    GET_FILE_EXTENSION_TEST("/some/path/some.txt", "txt", &status);
    GET_FILE_EXTENSION_TEST("/some/path/and_no_extension", "", &status);
    GET_FILE_EXTENSION_TEST("~/a/path/with.long_extension", "long_extension", &status);
    GET_FILE_EXTENSION_TEST("relpath/with.dot/and.dat", "dat", &status);
    GET_FILE_EXTENSION_TEST("relpath/with.dot/and_no_extension", "", &status);
    GET_FILE_EXTENSION_TEST("/some/path.dot/with.two/dots.txt", "txt", &status);
    GET_FILE_EXTENSION_TEST("file.avi", "avi", &status);
    GET_FILE_EXTENSION_TEST("file..ext", "ext", &status);
    GET_FILE_EXTENSION_TEST("path/file..ext", "ext", &status);
    GET_FILE_EXTENSION_TEST("path\\with\\wrong\\seps.txt", "txt", &status);
#else
    /* TODO */
#endif

    /**************************************************/
    MT_TEST_START("MT_PathHasFileExtension");

    CHECK_FILE_EXTENSION_TEST("/some/path/file.txt", "txt", true, &status);
    CHECK_FILE_EXTENSION_TEST("/some/path/file.txt", "snot", false, &status);
    CHECK_FILE_EXTENSION_TEST("movie.avi", "avi", true, &status);
    CHECK_FILE_EXTENSION_TEST("someavi", "avi", false, &status);

    /**************************************************/
    MT_TEST_START("MT_isdigit");

    IS_DIGIT_TEST('0', true, &status);
    IS_DIGIT_TEST('1', true, &status);
    IS_DIGIT_TEST('2', true, &status);
    IS_DIGIT_TEST('3', true, &status);
    IS_DIGIT_TEST('4', true, &status);
    IS_DIGIT_TEST('5', true, &status);
    IS_DIGIT_TEST('6', true, &status);
    IS_DIGIT_TEST('7', true, &status);
    IS_DIGIT_TEST('8', true, &status);
    IS_DIGIT_TEST('9', true, &status);
    IS_DIGIT_TEST('0'-1, false, &status);
    IS_DIGIT_TEST('9'+1, false, &status);
    IS_DIGIT_TEST('a', false, &status);
    IS_DIGIT_TEST('!', false, &status);

    return status;
}
<|endoftext|>


<commit_before>/*=========================================================================

   Library:   TubeTK

   Copyright 2010 Kitware Inc. 28 Corporate Drive,
   Clifton Park, NY, 12065, USA.

   All rights reserved.

   Licensed under the Apache License, Version 2.0 (the "License");
   you may not use this file except in compliance with the License.
   You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

   Unless required by applicable law or agreed to in writing, software
   distributed under the License is distributed on an "AS IS" BASIS,
   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   See the License for the specific language governing permissions and
   limitations under the License.

=========================================================================*/

// TubeTK INCLUDES
#include "tubeMacro.h"
#include "tubeMessage.h"
#include "tubeCLIProgressReporter.h"
#include "itktubeTortuositySpatialObjectFilter.h"
#include "tubeTubeMath.h"

// ITK INCLUDES
#include "itkTimeProbesCollectorBase.h"
#include "itkSpatialObjectReader.h"
#include "itkSpatialObjectWriter.h"
#include "itkGroupSpatialObject.h"
#include "itkVesselTubeSpatialObject.h"
#include "metaScene.h"

// VTK INCLUDES
#include "vtkNew.h"
#include "vtkTable.h"
#include "vtkIntArray.h"
#include "vtkDoubleArray.h"
#include "vtkSmartPointer.h"
#include "vtkDelimitedTextWriter.h"

// std includes
#include <sstream>
#include <string.h>
#include <vector>
#include <map>
#include <string>

#include "ComputeTubeTortuosityMeasuresCLP.h"

template< unsigned int VDimension >
int DoIt( int argc, char * argv[] )
{
  PARSE_ARGS;

  // Ensure that the input image dimension is valid
  // We only support 2D and 3D Images due to the
  // limitation of itkTubeSpatialObject
  if( VDimension != 2 && VDimension != 3 )
    {
    tube::ErrorMessage("Error: Only 2D and 3D data is currently supported.");
    return EXIT_FAILURE;
    }

  // The timeCollector to perform basic profiling of algorithmic components
  itk::TimeProbesCollectorBase timeCollector;

  // typedefs
  typedef itk::VesselTubeSpatialObject< VDimension >  TubeType;
  typedef itk::SpatialObjectReader< VDimension >      TubesReaderType;
  typedef itk::GroupSpatialObject< VDimension >       TubeGroupType;
  typedef typename TubeGroupType::ChildrenListPointer TubeListPointerType;
  typedef itk::tube::TortuositySpatialObjectFilter< TubeType >
  TortuosityFilterType;

  // Load TRE File
  tubeStandardOutputMacro( << "\n>> Loading TRE File" );

  timeCollector.Start( "Loading Input TRE File" );

  typename TubesReaderType::Pointer tubeFileReader = TubesReaderType::New();

  try
    {
    tubeFileReader->SetFileName( inputTREFile.c_str() );
    tubeFileReader->Update();
    }
  catch( itk::ExceptionObject & err )
    {
    tube::ErrorMessage( "Error loading TRE File: "
                        + std::string( err.GetDescription() ) );
    timeCollector.Report();
    return EXIT_FAILURE;
    }

  typename TubeGroupType::Pointer pTubeGroup = tubeFileReader->GetGroup();

  timeCollector.Stop( "Loading Input TRE File" );

  // Get specified smoothing method
  tube::SmoothTubeFunctionEnum smoothingMethodEnum;

  if(smoothingMethod == "SMOOTH_TUBE_USING_INDEX_AVERAGE" )
    {
    smoothingMethodEnum =
      tube::SMOOTH_TUBE_USING_INDEX_AVERAGE;
    }
  else if(smoothingMethod == "SMOOTH_TUBE_USING_DISTANCE_GAUSSIAN")
    {
    smoothingMethodEnum =
      tube::SMOOTH_TUBE_USING_DISTANCE_GAUSSIAN;
    }
  else
    {
    smoothingMethodEnum =
      tube::SMOOTH_TUBE_USING_INDEX_GAUSSIAN;
    }

  // Prepare tortuosity measure flag
  int metricFlag = 0;

  if( basicMetrics )
    {
    metricFlag = metricFlag
                 | TortuosityFilterType::AVERAGE_RADIUS_METRIC
                 | TortuosityFilterType::CHORD_LENGTH_METRIC
                 | TortuosityFilterType::PATH_LENGTH_METRIC;
    }

  if( oldMetrics )
    {
    metricFlag = metricFlag
                 | TortuosityFilterType::DISTANCE_METRIC
                 | TortuosityFilterType::INFLECTION_COUNT_METRIC
                 | TortuosityFilterType::INFLECTION_POINTS_METRIC
                 | TortuosityFilterType::SUM_OF_ANGLES_METRIC;
    }

  if( curvatureMetrics )
    {
    metricFlag = metricFlag
                 | TortuosityFilterType::INFLECTION_COUNT_1_METRIC
                 | TortuosityFilterType::INFLECTION_COUNT_2_METRIC
                 | TortuosityFilterType::PERCENTILE_95_METRIC
                 | TortuosityFilterType::TOTAL_CURVATURE_METRIC
                 | TortuosityFilterType::TOTAL_SQUARED_CURVATURE_METRIC
                 | TortuosityFilterType::CURVATURE_SCALAR_METRIC
                 | TortuosityFilterType::CURVATURE_VECTOR_METRIC;
    }

  if( histogramMetrics )
    {
    metricFlag |= TortuosityFilterType::CURVATURE_HISTOGRAM_METRICS;
    }

  std::map<int, std::string> MetricFlagToNameMap;
  MetricFlagToNameMap
    [TortuosityFilterType::AVERAGE_RADIUS_METRIC] = "AverageRadiusMetric";
  MetricFlagToNameMap
    [TortuosityFilterType::CHORD_LENGTH_METRIC] = "ChordLengthMetric";
  MetricFlagToNameMap
    [TortuosityFilterType::DISTANCE_METRIC] = "DistanceMetric";
  MetricFlagToNameMap
    [TortuosityFilterType::INFLECTION_COUNT_METRIC] = "InflectionCountMetric";
  MetricFlagToNameMap
    [TortuosityFilterType::INFLECTION_COUNT_1_METRIC]
      = "InflectionCount1Metric";
  MetricFlagToNameMap
    [TortuosityFilterType::INFLECTION_COUNT_2_METRIC]
      = "InflectionCount2Metric";
  MetricFlagToNameMap
    [TortuosityFilterType::PATH_LENGTH_METRIC] = "PathLengthMetric";
  MetricFlagToNameMap
    [TortuosityFilterType::PERCENTILE_95_METRIC] = "Percentile95Metric";
  MetricFlagToNameMap
    [TortuosityFilterType::SUM_OF_ANGLES_METRIC] = "SumOfAnglesMetric";
  MetricFlagToNameMap
    [TortuosityFilterType::TOTAL_CURVATURE_METRIC] = "TotalCurvatureMetric";
  MetricFlagToNameMap
    [TortuosityFilterType::TOTAL_SQUARED_CURVATURE_METRIC]
      = "TotalSquaredCurvatureMetric";

  // Run tortuosity filter
  tubeStandardOutputMacro( << "\n>> Computing tortuosity measures" );

  timeCollector.Start( "Computing tortuosity measures" );

  char childName[] = "Tube";
  TubeListPointerType tubeList = pTubeGroup->GetChildren(
    pTubeGroup->GetMaximumDepth(), childName );

  vtkSmartPointer< vtkIntArray > tubeIdArray =
    vtkSmartPointer<vtkIntArray>::New();
  tubeIdArray->Initialize();
  tubeIdArray->SetName( "TubeIDs" );
  tubeIdArray->SetNumberOfValues( tubeList->size() );

  vtkSmartPointer< vtkIntArray > numPointsArray =
    vtkSmartPointer<vtkIntArray>::New();
  numPointsArray->Initialize();
  numPointsArray->SetName( "NumberOfPoints" );
  numPointsArray->SetNumberOfValues( tubeList->size() );

  std::vector< vtkSmartPointer< vtkDoubleArray >  > metricArrayVec;
  for (long int compareFlag = 0x01;
    compareFlag <= TortuosityFilterType::BITMASK_ALL_METRICS;
    compareFlag = compareFlag << 1)
    {
    // If metric is asked to print and is printable
    if( (metricFlag & compareFlag &
        TortuosityFilterType::BITMASK_VESSEL_WISE_METRICS) > 0 )
      {
      vtkSmartPointer< vtkDoubleArray > metricArray =
        vtkSmartPointer< vtkDoubleArray >::New();
      metricArray->Initialize();
      metricArray->SetName( MetricFlagToNameMap[compareFlag].c_str() );
      metricArray->SetNumberOfValues( tubeList->size() );
      metricArrayVec.push_back( metricArray );
      }
    }

  if( curvatureMetrics )
    {
    vtkSmartPointer< vtkDoubleArray > tau4Array =
      vtkSmartPointer< vtkDoubleArray >::New();
    tau4Array->Initialize();
    tau4Array->SetName( "Tau4Metric" );
    tau4Array->SetNumberOfValues( tubeList->size() );
    metricArrayVec.push_back( tau4Array );
    }

  std::vector< vtkSmartPointer<vtkIntArray> > histogramArrays;
  if( (metricFlag & TortuosityFilterType::CURVATURE_HISTOGRAM_METRICS) > 0 )
    {
    double histStep = (histogramMax - histogramMin) / numberOfHistogramBins;

    for(int i = 0; i < numberOfHistogramBins; i++)
      {
      std::ostringstream oss;
      oss << "Hist-Bin#" << i << ": " << i*histStep <<" - " << (i+1)*histStep;
      std::string binArrayName = oss.str();

      vtkSmartPointer< vtkIntArray > histArray =
        vtkSmartPointer< vtkIntArray >::New();
      histArray->Initialize();
      histArray->SetName( binArrayName.c_str() );
      histArray->SetNumberOfValues( tubeList->size() );
      histogramArrays.push_back(histArray);
      }
    }

  int tubeIndex = 0;
  for( typename TubeGroupType::ChildrenListType::iterator
       itTubes = tubeList->begin();
       itTubes != tubeList->end(); ++itTubes )
    {
    TubeType* curTube = dynamic_cast<TubeType*>((*itTubes).GetPointer());
    if (!curTube)
      {
      continue;
      }

    typename TortuosityFilterType::Pointer tortuosityFilter =
      TortuosityFilterType::New();
    tortuosityFilter->SetMeasureFlag( metricFlag );
    tortuosityFilter->SetSmoothingScale( smoothingScale );
    tortuosityFilter->SetSmoothingMethod( smoothingMethodEnum );
    tortuosityFilter->SetNumberOfBins( numberOfHistogramBins );
    tortuosityFilter->SetHistogramMin( histogramMin );
    tortuosityFilter->SetHistogramMax( histogramMax );
    tortuosityFilter->SetInput( curTube );
    tortuosityFilter->Update();

    tubeIdArray->SetValue( tubeIndex, tubeIndex );
    numPointsArray->SetValue( tubeIndex, curTube->GetNumberOfPoints() );

    for(int i = 0; i < metricArrayVec.size(); i++)
      {
      std::string metricName = metricArrayVec[i]->GetName();

      if(metricName == "AverageRadiusMetric")
        {
        metricArrayVec[i]->SetValue( tubeIndex,
          tortuosityFilter->GetAverageRadiusMetric() );
        }
      if(metricName == "ChordLengthMetric")
        {
        metricArrayVec[i]->SetValue( tubeIndex,
          tortuosityFilter->GetChordLengthMetric() );
        }
      if(metricName == "DistanceMetric")
        {
        metricArrayVec[i]->SetValue( tubeIndex,
          tortuosityFilter->GetDistanceMetric() );
        }
      if(metricName == "InflectionCountMetric")
        {
        metricArrayVec[i]->SetValue( tubeIndex,
          tortuosityFilter->GetInflectionCountMetric() );
        }
      if(metricName == "InflectionCount1Metric")
        {
        metricArrayVec[i]->SetValue( tubeIndex,
          tortuosityFilter->GetInflectionCount1Metric() );
        }
      if(metricName == "InflectionCount2Metric")
        {
        metricArrayVec[i]->SetValue( tubeIndex,
          tortuosityFilter->GetInflectionCount2Metric() );
        }
      if(metricName == "PathLengthMetric")
        {
        metricArrayVec[i]->SetValue( tubeIndex,
          tortuosityFilter->GetPathLengthMetric() );
        }
      if(metricName == "Percentile95Metric")
        {
        metricArrayVec[i]->SetValue( tubeIndex,
          tortuosityFilter->GetPercentile95Metric() );
        }
      if(metricName == "SumOfAnglesMetric")
        {
        metricArrayVec[i]->SetValue( tubeIndex,
          tortuosityFilter->GetSumOfAnglesMetric() );
        }
      if(metricName == "Tau4Metric")
        {
        metricArrayVec[i]->SetValue( tubeIndex,
          tortuosityFilter->GetTotalCurvatureMetric()
            / tortuosityFilter->GetPathLengthMetric() );
        }
      if(metricName == "TotalCurvatureMetric")
        {
        metricArrayVec[i]->SetValue( tubeIndex,
          tortuosityFilter->GetTotalCurvatureMetric() );
        }
      if(metricName == "TotalSquaredCurvatureMetric")
        {
        metricArrayVec[i]->SetValue( tubeIndex,
          tortuosityFilter->GetTotalSquaredCurvatureMetric() );
        }
      }

    if( (metricFlag & TortuosityFilterType::CURVATURE_HISTOGRAM_METRICS) > 0 )
      {
      // Get the histogram features
      for(int i = 0; i < numberOfHistogramBins; i++)
        {
        histogramArrays[i]->SetValue( tubeIndex,
          tortuosityFilter->GetCurvatureHistogramMetric(i) );
        }
      }

    tubeIndex++;
    }

  timeCollector.Stop( "Computing tortuosity measures" );

  // Write tortuosity measures to a CSV file
  tubeStandardOutputMacro( << "\n>> Writing tortuosity measures to CSV" );

  timeCollector.Start( "Writing tortuosity measures to CSV" );

  vtkNew< vtkTable > table;

  table->AddColumn( tubeIdArray.GetPointer() );
  table->AddColumn( numPointsArray.GetPointer() );

  for(int i = 0; i < metricArrayVec.size(); i++)
    {
    table->AddColumn( metricArrayVec[i].GetPointer() );
    }

  if( (metricFlag & TortuosityFilterType::CURVATURE_HISTOGRAM_METRICS) > 0 )
    {
    // Get the histogram features
    for(int i = 0; i < numberOfHistogramBins; i++)
      {
      table->AddColumn( histogramArrays[i].GetPointer() );
      }
    }

  vtkNew< vtkDelimitedTextWriter > writer;
  writer->SetFileName( outputCSVFile.c_str() );
  writer->SetInputData( table.GetPointer() );
  writer->Write();

  timeCollector.Stop( "Writing tortuosity measures to CSV" );

  // All done
  timeCollector.Report();
  return EXIT_SUCCESS;
}

// Main
int main( int argc, char * argv[] )
{
  try
    {
    PARSE_ARGS;
    }
  catch( const std::exception & err )
    {
    tube::ErrorMessage( err.what() );
    return EXIT_FAILURE;
    }
  PARSE_ARGS;

  MetaScene *mScene = new MetaScene;
  mScene->Read( inputTREFile.c_str() );
  if( mScene->GetObjectList()->empty() )
    {
    tubeWarningMacro( << "Input TRE file has no spatial objects" );
    return EXIT_SUCCESS;
    }

  switch( mScene->GetObjectList()->front()->NDims() )
    {
    case 3:
      return DoIt<3>( argc, argv );
      break;

    default:
      tubeErrorMacro(<< "Error: Only 3D data is currently supported.");
      return EXIT_FAILURE;
    }
}
<commit_msg>Fixed a bug to make it work on older VTK versions<commit_after>/*=========================================================================

   Library:   TubeTK

   Copyright 2010 Kitware Inc. 28 Corporate Drive,
   Clifton Park, NY, 12065, USA.

   All rights reserved.

   Licensed under the Apache License, Version 2.0 (the "License");
   you may not use this file except in compliance with the License.
   You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

   Unless required by applicable law or agreed to in writing, software
   distributed under the License is distributed on an "AS IS" BASIS,
   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   See the License for the specific language governing permissions and
   limitations under the License.

=========================================================================*/

// TubeTK INCLUDES
#include "tubeMacro.h"
#include "tubeMessage.h"
#include "tubeCLIProgressReporter.h"
#include "itktubeTortuositySpatialObjectFilter.h"
#include "tubeTubeMath.h"

// ITK INCLUDES
#include "itkTimeProbesCollectorBase.h"
#include "itkSpatialObjectReader.h"
#include "itkSpatialObjectWriter.h"
#include "itkGroupSpatialObject.h"
#include "itkVesselTubeSpatialObject.h"
#include "metaScene.h"

// VTK INCLUDES
#include "vtkNew.h"
#include "vtkTable.h"
#include "vtkVersion.h"
#include "vtkIntArray.h"
#include "vtkDoubleArray.h"
#include "vtkSmartPointer.h"
#include "vtkDelimitedTextWriter.h"

// std includes
#include <sstream>
#include <string.h>
#include <vector>
#include <map>
#include <string>

#include "ComputeTubeTortuosityMeasuresCLP.h"

template< unsigned int VDimension >
int DoIt( int argc, char * argv[] )
{
  PARSE_ARGS;

  // Ensure that the input image dimension is valid
  // We only support 2D and 3D Images due to the
  // limitation of itkTubeSpatialObject
  if( VDimension != 2 && VDimension != 3 )
    {
    tube::ErrorMessage("Error: Only 2D and 3D data is currently supported.");
    return EXIT_FAILURE;
    }

  // The timeCollector to perform basic profiling of algorithmic components
  itk::TimeProbesCollectorBase timeCollector;

  // typedefs
  typedef itk::VesselTubeSpatialObject< VDimension >  TubeType;
  typedef itk::SpatialObjectReader< VDimension >      TubesReaderType;
  typedef itk::GroupSpatialObject< VDimension >       TubeGroupType;
  typedef typename TubeGroupType::ChildrenListPointer TubeListPointerType;
  typedef itk::tube::TortuositySpatialObjectFilter< TubeType >
  TortuosityFilterType;

  // Load TRE File
  tubeStandardOutputMacro( << "\n>> Loading TRE File" );

  timeCollector.Start( "Loading Input TRE File" );

  typename TubesReaderType::Pointer tubeFileReader = TubesReaderType::New();

  try
    {
    tubeFileReader->SetFileName( inputTREFile.c_str() );
    tubeFileReader->Update();
    }
  catch( itk::ExceptionObject & err )
    {
    tube::ErrorMessage( "Error loading TRE File: "
                        + std::string( err.GetDescription() ) );
    timeCollector.Report();
    return EXIT_FAILURE;
    }

  typename TubeGroupType::Pointer pTubeGroup = tubeFileReader->GetGroup();

  timeCollector.Stop( "Loading Input TRE File" );

  // Get specified smoothing method
  tube::SmoothTubeFunctionEnum smoothingMethodEnum;

  if(smoothingMethod == "SMOOTH_TUBE_USING_INDEX_AVERAGE" )
    {
    smoothingMethodEnum =
      tube::SMOOTH_TUBE_USING_INDEX_AVERAGE;
    }
  else if(smoothingMethod == "SMOOTH_TUBE_USING_DISTANCE_GAUSSIAN")
    {
    smoothingMethodEnum =
      tube::SMOOTH_TUBE_USING_DISTANCE_GAUSSIAN;
    }
  else
    {
    smoothingMethodEnum =
      tube::SMOOTH_TUBE_USING_INDEX_GAUSSIAN;
    }

  // Prepare tortuosity measure flag
  int metricFlag = 0;

  if( basicMetrics )
    {
    metricFlag = metricFlag
                 | TortuosityFilterType::AVERAGE_RADIUS_METRIC
                 | TortuosityFilterType::CHORD_LENGTH_METRIC
                 | TortuosityFilterType::PATH_LENGTH_METRIC;
    }

  if( oldMetrics )
    {
    metricFlag = metricFlag
                 | TortuosityFilterType::DISTANCE_METRIC
                 | TortuosityFilterType::INFLECTION_COUNT_METRIC
                 | TortuosityFilterType::INFLECTION_POINTS_METRIC
                 | TortuosityFilterType::SUM_OF_ANGLES_METRIC;
    }

  if( curvatureMetrics )
    {
    metricFlag = metricFlag
                 | TortuosityFilterType::INFLECTION_COUNT_1_METRIC
                 | TortuosityFilterType::INFLECTION_COUNT_2_METRIC
                 | TortuosityFilterType::PERCENTILE_95_METRIC
                 | TortuosityFilterType::TOTAL_CURVATURE_METRIC
                 | TortuosityFilterType::TOTAL_SQUARED_CURVATURE_METRIC
                 | TortuosityFilterType::CURVATURE_SCALAR_METRIC
                 | TortuosityFilterType::CURVATURE_VECTOR_METRIC;
    }

  if( histogramMetrics )
    {
    metricFlag |= TortuosityFilterType::CURVATURE_HISTOGRAM_METRICS;
    }

  std::map<int, std::string> MetricFlagToNameMap;
  MetricFlagToNameMap
    [TortuosityFilterType::AVERAGE_RADIUS_METRIC] = "AverageRadiusMetric";
  MetricFlagToNameMap
    [TortuosityFilterType::CHORD_LENGTH_METRIC] = "ChordLengthMetric";
  MetricFlagToNameMap
    [TortuosityFilterType::DISTANCE_METRIC] = "DistanceMetric";
  MetricFlagToNameMap
    [TortuosityFilterType::INFLECTION_COUNT_METRIC] = "InflectionCountMetric";
  MetricFlagToNameMap
    [TortuosityFilterType::INFLECTION_COUNT_1_METRIC]
      = "InflectionCount1Metric";
  MetricFlagToNameMap
    [TortuosityFilterType::INFLECTION_COUNT_2_METRIC]
      = "InflectionCount2Metric";
  MetricFlagToNameMap
    [TortuosityFilterType::PATH_LENGTH_METRIC] = "PathLengthMetric";
  MetricFlagToNameMap
    [TortuosityFilterType::PERCENTILE_95_METRIC] = "Percentile95Metric";
  MetricFlagToNameMap
    [TortuosityFilterType::SUM_OF_ANGLES_METRIC] = "SumOfAnglesMetric";
  MetricFlagToNameMap
    [TortuosityFilterType::TOTAL_CURVATURE_METRIC] = "TotalCurvatureMetric";
  MetricFlagToNameMap
    [TortuosityFilterType::TOTAL_SQUARED_CURVATURE_METRIC]
      = "TotalSquaredCurvatureMetric";

  // Run tortuosity filter
  tubeStandardOutputMacro( << "\n>> Computing tortuosity measures" );

  timeCollector.Start( "Computing tortuosity measures" );

  char childName[] = "Tube";
  TubeListPointerType tubeList = pTubeGroup->GetChildren(
    pTubeGroup->GetMaximumDepth(), childName );

  vtkSmartPointer< vtkIntArray > tubeIdArray =
    vtkSmartPointer<vtkIntArray>::New();
  tubeIdArray->Initialize();
  tubeIdArray->SetName( "TubeIDs" );
  tubeIdArray->SetNumberOfValues( tubeList->size() );

  vtkSmartPointer< vtkIntArray > numPointsArray =
    vtkSmartPointer<vtkIntArray>::New();
  numPointsArray->Initialize();
  numPointsArray->SetName( "NumberOfPoints" );
  numPointsArray->SetNumberOfValues( tubeList->size() );

  std::vector< vtkSmartPointer< vtkDoubleArray >  > metricArrayVec;
  for (long int compareFlag = 0x01;
    compareFlag <= TortuosityFilterType::BITMASK_ALL_METRICS;
    compareFlag = compareFlag << 1)
    {
    // If metric is asked to print and is printable
    if( (metricFlag & compareFlag &
        TortuosityFilterType::BITMASK_VESSEL_WISE_METRICS) > 0 )
      {
      vtkSmartPointer< vtkDoubleArray > metricArray =
        vtkSmartPointer< vtkDoubleArray >::New();
      metricArray->Initialize();
      metricArray->SetName( MetricFlagToNameMap[compareFlag].c_str() );
      metricArray->SetNumberOfValues( tubeList->size() );
      metricArrayVec.push_back( metricArray );
      }
    }

  if( curvatureMetrics )
    {
    vtkSmartPointer< vtkDoubleArray > tau4Array =
      vtkSmartPointer< vtkDoubleArray >::New();
    tau4Array->Initialize();
    tau4Array->SetName( "Tau4Metric" );
    tau4Array->SetNumberOfValues( tubeList->size() );
    metricArrayVec.push_back( tau4Array );
    }

  std::vector< vtkSmartPointer<vtkIntArray> > histogramArrays;
  if( (metricFlag & TortuosityFilterType::CURVATURE_HISTOGRAM_METRICS) > 0 )
    {
    double histStep = (histogramMax - histogramMin) / numberOfHistogramBins;

    for(int i = 0; i < numberOfHistogramBins; i++)
      {
      std::ostringstream oss;
      oss << "Hist-Bin#" << i << ": " << i*histStep <<" - " << (i+1)*histStep;
      std::string binArrayName = oss.str();

      vtkSmartPointer< vtkIntArray > histArray =
        vtkSmartPointer< vtkIntArray >::New();
      histArray->Initialize();
      histArray->SetName( binArrayName.c_str() );
      histArray->SetNumberOfValues( tubeList->size() );
      histogramArrays.push_back(histArray);
      }
    }

  int tubeIndex = 0;
  for( typename TubeGroupType::ChildrenListType::iterator
       itTubes = tubeList->begin();
       itTubes != tubeList->end(); ++itTubes )
    {
    TubeType* curTube = dynamic_cast<TubeType*>((*itTubes).GetPointer());
    if (!curTube)
      {
      continue;
      }

    typename TortuosityFilterType::Pointer tortuosityFilter =
      TortuosityFilterType::New();
    tortuosityFilter->SetMeasureFlag( metricFlag );
    tortuosityFilter->SetSmoothingScale( smoothingScale );
    tortuosityFilter->SetSmoothingMethod( smoothingMethodEnum );
    tortuosityFilter->SetNumberOfBins( numberOfHistogramBins );
    tortuosityFilter->SetHistogramMin( histogramMin );
    tortuosityFilter->SetHistogramMax( histogramMax );
    tortuosityFilter->SetInput( curTube );
    tortuosityFilter->Update();

    tubeIdArray->SetValue( tubeIndex, tubeIndex );
    numPointsArray->SetValue( tubeIndex, curTube->GetNumberOfPoints() );

    for(int i = 0; i < metricArrayVec.size(); i++)
      {
      std::string metricName = metricArrayVec[i]->GetName();

      if(metricName == "AverageRadiusMetric")
        {
        metricArrayVec[i]->SetValue( tubeIndex,
          tortuosityFilter->GetAverageRadiusMetric() );
        }
      if(metricName == "ChordLengthMetric")
        {
        metricArrayVec[i]->SetValue( tubeIndex,
          tortuosityFilter->GetChordLengthMetric() );
        }
      if(metricName == "DistanceMetric")
        {
        metricArrayVec[i]->SetValue( tubeIndex,
          tortuosityFilter->GetDistanceMetric() );
        }
      if(metricName == "InflectionCountMetric")
        {
        metricArrayVec[i]->SetValue( tubeIndex,
          tortuosityFilter->GetInflectionCountMetric() );
        }
      if(metricName == "InflectionCount1Metric")
        {
        metricArrayVec[i]->SetValue( tubeIndex,
          tortuosityFilter->GetInflectionCount1Metric() );
        }
      if(metricName == "InflectionCount2Metric")
        {
        metricArrayVec[i]->SetValue( tubeIndex,
          tortuosityFilter->GetInflectionCount2Metric() );
        }
      if(metricName == "PathLengthMetric")
        {
        metricArrayVec[i]->SetValue( tubeIndex,
          tortuosityFilter->GetPathLengthMetric() );
        }
      if(metricName == "Percentile95Metric")
        {
        metricArrayVec[i]->SetValue( tubeIndex,
          tortuosityFilter->GetPercentile95Metric() );
        }
      if(metricName == "SumOfAnglesMetric")
        {
        metricArrayVec[i]->SetValue( tubeIndex,
          tortuosityFilter->GetSumOfAnglesMetric() );
        }
      if(metricName == "Tau4Metric")
        {
        metricArrayVec[i]->SetValue( tubeIndex,
          tortuosityFilter->GetTotalCurvatureMetric()
            / tortuosityFilter->GetPathLengthMetric() );
        }
      if(metricName == "TotalCurvatureMetric")
        {
        metricArrayVec[i]->SetValue( tubeIndex,
          tortuosityFilter->GetTotalCurvatureMetric() );
        }
      if(metricName == "TotalSquaredCurvatureMetric")
        {
        metricArrayVec[i]->SetValue( tubeIndex,
          tortuosityFilter->GetTotalSquaredCurvatureMetric() );
        }
      }

    if( (metricFlag & TortuosityFilterType::CURVATURE_HISTOGRAM_METRICS) > 0 )
      {
      // Get the histogram features
      for(int i = 0; i < numberOfHistogramBins; i++)
        {
        histogramArrays[i]->SetValue( tubeIndex,
          tortuosityFilter->GetCurvatureHistogramMetric(i) );
        }
      }

    tubeIndex++;
    }

  timeCollector.Stop( "Computing tortuosity measures" );

  // Write tortuosity measures to a CSV file
  tubeStandardOutputMacro( << "\n>> Writing tortuosity measures to CSV" );

  timeCollector.Start( "Writing tortuosity measures to CSV" );

  vtkNew< vtkTable > table;

  table->AddColumn( tubeIdArray.GetPointer() );
  table->AddColumn( numPointsArray.GetPointer() );

  for(int i = 0; i < metricArrayVec.size(); i++)
    {
    table->AddColumn( metricArrayVec[i].GetPointer() );
    }

  if( (metricFlag & TortuosityFilterType::CURVATURE_HISTOGRAM_METRICS) > 0 )
    {
    // Get the histogram features
    for(int i = 0; i < numberOfHistogramBins; i++)
      {
      table->AddColumn( histogramArrays[i].GetPointer() );
      }
    }

  vtkNew< vtkDelimitedTextWriter > writer;
  writer->SetFileName( outputCSVFile.c_str() );

#if VTK_MAJOR_VERSION <= 5
  writer->SetInput( table.GetPointer() );
#else
  writer->SetInputData( table.GetPointer() );
#endif

  writer->Write();

  timeCollector.Stop( "Writing tortuosity measures to CSV" );

  // All done
  timeCollector.Report();
  return EXIT_SUCCESS;
}

// Main
int main( int argc, char * argv[] )
{
  try
    {
    PARSE_ARGS;
    }
  catch( const std::exception & err )
    {
    tube::ErrorMessage( err.what() );
    return EXIT_FAILURE;
    }
  PARSE_ARGS;

  MetaScene *mScene = new MetaScene;
  mScene->Read( inputTREFile.c_str() );
  if( mScene->GetObjectList()->empty() )
    {
    tubeWarningMacro( << "Input TRE file has no spatial objects" );
    return EXIT_SUCCESS;
    }

  switch( mScene->GetObjectList()->front()->NDims() )
    {
    case 3:
      return DoIt<3>( argc, argv );
      break;

    default:
      tubeErrorMacro(<< "Error: Only 3D data is currently supported.");
      return EXIT_FAILURE;
    }
}
<|endoftext|>


<commit_before>#include <assert.h>
#include <iostream>
#include <iso646.h>
#include <random>

#include "number.h"

int main()
{
    std::mt19937_64 r;
    for (int i = 0; i < 100000; i++) {
        Number n;
        n.x = r();
        char buf1[40];
        bid64_to_string(buf1, n.x);
        std::string buf2 = number_to_string(n);
        Number x = number_from_string(buf1);
        Number y = number_from_string(buf2.c_str());
        if (not (number_is_equal(x, y) || (number_is_nan(x) && number_is_nan(y)))) {
            std::cout << buf1 << " " << buf2 << std::endl;
            assert(false);
        }
    }
}
<commit_msg>Actually seed random number generator for test<commit_after>#include <assert.h>
#include <iostream>
#include <iso646.h>
#include <random>

#include "number.h"

int main()
{
    std::random_device rd;
    std::mt19937_64 r(rd());
    for (int i = 0; i < 100000; i++) {
        Number n;
        n.x = r();
        char buf1[40];
        bid64_to_string(buf1, n.x);
        std::string buf2 = number_to_string(n);
        Number x = number_from_string(buf1);
        Number y = number_from_string(buf2.c_str());
        if (not (number_is_equal(x, y) || (number_is_nan(x) && number_is_nan(y)))) {
            std::cout << buf1 << " " << buf2 << std::endl;
            assert(false);
        }
    }
}
<|endoftext|>