<commit_before>//
// This file is part of the Marble Desktop Globe.
//
// This program is free software licensed under the GNU LGPL. You can
// find a copy of this license in LICENSE.txt in the top directory of
// the source code.
//
// Copyright 2008      Patrick Spendrin <ps_ml@gmx.de>
// Copyright 2008      Simon Schmeisser <mail_to_wrt@gmx.de>
//

// Own
#include "MarbleGeometryModel.h"

// Qt
#include <QtCore/QDebug>
#include <QtCore/QModelIndex>
#include <QtCore/QFile>
#include <QtCore/QVector>
#include <QtGui/QPixmap>

// Marble
#include "GeoDataDocument.h"       // In geodata/data/
#include "GeoDataContainer.h"
#include "GeoDataFeature.h"
#include "GeoDataFolder.h"
#include "GeoDataGeometry.h"
#include "GeoDataMultiGeometry.h"
#include "GeoDataPlacemark.h"
#include "GeoDataObject.h"
#include "GeoDataParser.h"

using namespace Marble;

class MarbleGeometryModel::Private {
 public:
    Private( GeoDataDocument* rootDocument ) : m_rootDocument( rootDocument ) {
        mapFeature( m_rootDocument );
    };

    Private() : m_rootDocument( 0 ) {};

    void mapGeometry( GeoDataGeometry* geometry ) {
        /*
        * This function iterates over all geometry objects in a MultiGeometry.
        * This is needed to build up the parent Hash.
        */
        if( !geometry ) return;

        QVector<GeoDataGeometry>::iterator iterator;
        GeoDataMultiGeometry* multiGeometry = static_cast<GeoDataMultiGeometry*>( geometry );
        for( iterator = multiGeometry->begin();
             iterator != multiGeometry->end();
             ++iterator ) {
            m_parent[ iterator ] = geometry;
            if( iterator->geometryId() == GeoDataMultiGeometryId ) mapGeometry( iterator );
        }
    };

    void mapFeature( GeoDataFeature* feature ) {
        if( !feature ) return;

        if( feature->featureId() == GeoDataDocumentId || feature->featureId() == GeoDataFolderId ) {
            Q_FOREACH( GeoDataFeature childFeature, static_cast<GeoDataContainer*>( feature )->features() ) {
                m_parent[ &childFeature ] = feature;
                mapFeature( &childFeature );
            }
        }
        if( feature->featureId() == GeoDataPlacemarkId ) {
            if( dynamic_cast<GeoDataPlacemark*>( feature )->geometry() && dynamic_cast<GeoDataPlacemark*>( feature )->geometry()->geometryId() == GeoDataMultiGeometryId ) {
                m_parent[ dynamic_cast<GeoDataPlacemark*>( feature )->geometry() ] = feature;
                mapGeometry( dynamic_cast<GeoDataPlacemark*>( feature )->geometry() );
            }
        }
    };

    GeoDataDocument* m_rootDocument;
    QHash<GeoDataObject*,GeoDataObject*> m_parent;
};

MarbleGeometryModel::MarbleGeometryModel( QObject *parent )
    : QAbstractItemModel(), d( new Private() )
{
}

MarbleGeometryModel::MarbleGeometryModel( GeoDataDocument *rootDocument, QObject *parent )
    : QAbstractItemModel(), d( new Private( rootDocument ) )
{
}

MarbleGeometryModel::~MarbleGeometryModel()
{
    delete d;
}

void MarbleGeometryModel::setGeoDataRoot( GeoDataDocument* root )
{
    if( d->m_rootDocument != root ) {
        reset();
        qDebug() << "resetting the base of the Geometry model" << root;
        d->m_rootDocument = root;
        d->mapFeature( d->m_rootDocument );
    }
}

GeoDataDocument* MarbleGeometryModel::geoDataRoot() const
{
    return d->m_rootDocument;
}

int MarbleGeometryModel::rowCount( const QModelIndex &parent ) const
{
    /* For now we will simply take over the mechanism of TreeModels:
     * each node gives the number of subnodes it has as its rowCount
     */
    GeoDataObject *parentItem;
    if( parent.column() > 0 )
        return 0;

    if( !parent.isValid() )
        parentItem = d->m_rootDocument;
    else
        parentItem = static_cast<GeoDataObject*>( parent.internalPointer() );

    if( dynamic_cast<GeoDataDocument*>( parentItem ) ||
        dynamic_cast<GeoDataFolder*>( parentItem ) )
    {
        return dynamic_cast<GeoDataContainer*>( parentItem )->features().size();
    }

    if( dynamic_cast<GeoDataPlacemark*>( parentItem ) )
    {
        /* there is only one GeoDataGeometry Object per Placemark; if Styles
        * are added later, add them here */
        return 1;
    }

    if( dynamic_cast<GeoDataMultiGeometry*>( parentItem ) )
    {
        return dynamic_cast<GeoDataMultiGeometry*>( parentItem )->size();
    }
    return 0;
}

QVariant MarbleGeometryModel::data( const QModelIndex &index, int role ) const
{
    GeoDataObject *item;
    if( index.isValid() )
    {
        item = static_cast<GeoDataObject*>( index.internalPointer() );
    }
    else /* the rootIndex is invalid */
    {
        item = static_cast<GeoDataObject*>( d->m_rootDocument );
    }

    /* for now simply give back the type of the GeoDataObject
    * there might be a need to extend this, but usually we want
    */
    if( role == Qt::DisplayRole ) {
        if( dynamic_cast<GeoDataFeature*>( item ) ) {
            switch( dynamic_cast<GeoDataFeature*>( item )->featureId() ) {
                case InvalidFeatureId:
                    return QVariant( "InvalidFeature" );
                case GeoDataDocumentId:
                    return QVariant( "GeoDataDocument" );
                case GeoDataFolderId:
                    return QVariant( "GeoDataFolder" );
                case GeoDataPlacemarkId:
                    return QVariant( "GeoDataPlacemark" );
                case GeoDataNetworkLinkId:
                    return QVariant( "GeoDataNetworkLink" );
                case GeoDataScreenOverlayId:
                    return QVariant( "GeoDataScreenOverlay" );
                case GeoDataGroundOverlayId:
                    return QVariant( "GeoDataGroundOverlay" );
            }
        }
        if( dynamic_cast<GeoDataGeometry*>( item ) ) {
            switch( dynamic_cast<GeoDataGeometry*>( item )->geometryId() ) {
                case InvalidGeometryId:
                    return QVariant( "InvalidGeometry" );
                case GeoDataMultiGeometryId:
                    return QVariant( "GeoDataMultiGeometry" );
                case GeoDataLineStringId:
                    return QVariant( "GeoDataLineString" );
                case GeoDataLinearRingId:
                    return QVariant( "GeoDataLinearRing" );
                case GeoDataPolygonId:
                    return QVariant( "GeoDataPolygon" );
                case GeoDataPointId:
                    return QVariant( "GeoDataPoint" );
            }
        }
    }

    if( role == Qt::UserRole + 11 ) //equivalent to MarblePlacemarkModel::ObjectPointerRole
    {
        /* return the pointer item as a QVariant of (meta-)type
         * Marble::GeoDataObject* */
        QVariant v;
        v.setValue( item );
        return v;
    }

    return QVariant( "GeoDataObject" );
    /* TODO the data is hardcoded and very limited right now,
     * the logic what data is returned might be moved to the items
     * themselves later. Use the following code then:
     * return item->data( index.column() ); */

}

QModelIndex MarbleGeometryModel::index( int row, int column, const QModelIndex &parent ) const
{
    if ( !hasIndex( row, column, parent ) )
        return QModelIndex();

    GeoDataObject *parentItem;

    if ( !parent.isValid() )
        parentItem = d->m_rootDocument;
    else
        parentItem = static_cast<GeoDataObject*>( parent.internalPointer() );

    GeoDataObject *childItem = 0;

    /* go down into GeoDataContainers */
    if( dynamic_cast<GeoDataDocument*>( parentItem ) ||
        dynamic_cast<GeoDataFolder*>( parentItem ) )
    {
        *childItem =     dynamic_cast<GeoDataContainer*>(
                            parentItem )->features().at( row );
    }

    if( dynamic_cast<GeoDataPlacemark*>( parentItem ) )
    {
        /* as said above - if you add styles, please check for the row over here */
        childItem = dynamic_cast<GeoDataPlacemark*>( parentItem )->geometry();
    }

    if( dynamic_cast<GeoDataMultiGeometry*>( parentItem ) )
    {
        *childItem = dynamic_cast<GeoDataMultiGeometry*>( parentItem )->at( row );
    }

    if ( childItem )
        return createIndex( row, column, childItem );
    else
        return QModelIndex();
}

QModelIndex MarbleGeometryModel::parent( const QModelIndex &index ) const
{
    if ( !index.isValid() )
        return QModelIndex();

    GeoDataObject *childItem = static_cast<GeoDataObject*>( index.internalPointer() );
    GeoDataObject *parentItem = d->m_parent[ childItem ];

    if ( parentItem == d->m_rootDocument )
        return QModelIndex();

    if( parentItem == 0 ){
        /* this shouldn't happen */
        return QModelIndex();
    }

    /* for now leave that as 0, 0 -> this needs some more thoughts as
     * it is simply wrong */
    return createIndex( 0, 0, parentItem );
}

int MarbleGeometryModel::columnCount( const QModelIndex &node ) const
{
    if ( node.isValid() )
        return 1;
        /* TODO when nodes handle their information themselves they will have
         * varying amounts of properties ( or columns ). Right now we only have
         * one information ( type ) per node, so it's hardcoded to "1".
         * static_cast<GeoDataObject*>( node.internalPointer() )->columnCount(); */
    else
        return 1;
}

void MarbleGeometryModel::update()
{
    QAbstractItemModel::reset();
}

#include "MarbleGeometryModel.moc"
<commit_msg>as we already have the advantage of copying Feature into placemarks and reversed, use it here.<commit_after>//
// This file is part of the Marble Desktop Globe.
//
// This program is free software licensed under the GNU LGPL. You can
// find a copy of this license in LICENSE.txt in the top directory of
// the source code.
//
// Copyright 2008      Patrick Spendrin <ps_ml@gmx.de>
// Copyright 2008      Simon Schmeisser <mail_to_wrt@gmx.de>
//

// Own
#include "MarbleGeometryModel.h"

// Qt
#include <QtCore/QDebug>
#include <QtCore/QModelIndex>
#include <QtCore/QFile>
#include <QtCore/QVector>
#include <QtGui/QPixmap>

// Marble
#include "GeoDataDocument.h"       // In geodata/data/
#include "GeoDataContainer.h"
#include "GeoDataFeature.h"
#include "GeoDataFolder.h"
#include "GeoDataGeometry.h"
#include "GeoDataMultiGeometry.h"
#include "GeoDataPlacemark.h"
#include "GeoDataObject.h"
#include "GeoDataParser.h"

using namespace Marble;

class MarbleGeometryModel::Private {
 public:
    Private( GeoDataDocument* rootDocument ) : m_rootDocument( rootDocument ) {
        mapFeature( m_rootDocument );
    };

    Private() : m_rootDocument( 0 ) {};

    void mapGeometry( GeoDataGeometry* geometry ) {
        /*
        * This function iterates over all geometry objects in a MultiGeometry.
        * This is needed to build up the parent Hash.
        */
        if( !geometry ) return;

        QVector<GeoDataGeometry>::iterator iterator;
        GeoDataMultiGeometry* multiGeometry = static_cast<GeoDataMultiGeometry*>( geometry );
        for( iterator = multiGeometry->begin();
             iterator != multiGeometry->end();
             ++iterator ) {
            m_parent[ iterator ] = geometry;
            if( iterator->geometryId() == GeoDataMultiGeometryId ) mapGeometry( iterator );
        }
    };

    void mapFeature( GeoDataFeature* feature ) {
        if( !feature ) return;

        if( feature->featureId() == GeoDataDocumentId || feature->featureId() == GeoDataFolderId ) {
            Q_FOREACH( GeoDataFeature childFeature, static_cast<GeoDataContainer*>( feature )->features() ) {
                m_parent[ &childFeature ] = feature;
                mapFeature( &childFeature );
            }
        }
        if( feature->featureId() == GeoDataPlacemarkId ) {
            GeoDataPlacemark placemark = *feature;
            if( placemark.geometry() && placemark.geometry()->geometryId() == GeoDataMultiGeometryId ) {
                m_parent[ placemark.geometry() ] = feature;
                mapGeometry( placemark.geometry() );
            }
        }
    };

    GeoDataDocument* m_rootDocument;
    QHash<GeoDataObject*,GeoDataObject*> m_parent;
};

MarbleGeometryModel::MarbleGeometryModel( QObject *parent )
    : QAbstractItemModel(), d( new Private() )
{
}

MarbleGeometryModel::MarbleGeometryModel( GeoDataDocument *rootDocument, QObject *parent )
    : QAbstractItemModel(), d( new Private( rootDocument ) )
{
}

MarbleGeometryModel::~MarbleGeometryModel()
{
    delete d;
}

void MarbleGeometryModel::setGeoDataRoot( GeoDataDocument* root )
{
    if( d->m_rootDocument != root ) {
        reset();
        qDebug() << "resetting the base of the Geometry model" << root;
        d->m_rootDocument = root;
        d->mapFeature( d->m_rootDocument );
    }
}

GeoDataDocument* MarbleGeometryModel::geoDataRoot() const
{
    return d->m_rootDocument;
}

int MarbleGeometryModel::rowCount( const QModelIndex &parent ) const
{
    /* For now we will simply take over the mechanism of TreeModels:
     * each node gives the number of subnodes it has as its rowCount
     */
    GeoDataObject *parentItem;
    if( parent.column() > 0 )
        return 0;

    if( !parent.isValid() )
        parentItem = d->m_rootDocument;
    else
        parentItem = static_cast<GeoDataObject*>( parent.internalPointer() );

    if( dynamic_cast<GeoDataDocument*>( parentItem ) ||
        dynamic_cast<GeoDataFolder*>( parentItem ) )
    {
        return dynamic_cast<GeoDataContainer*>( parentItem )->features().size();
    }

    if( dynamic_cast<GeoDataPlacemark*>( parentItem ) )
    {
        /* there is only one GeoDataGeometry Object per Placemark; if Styles
        * are added later, add them here */
        return 1;
    }

    if( dynamic_cast<GeoDataMultiGeometry*>( parentItem ) )
    {
        return dynamic_cast<GeoDataMultiGeometry*>( parentItem )->size();
    }
    return 0;
}

QVariant MarbleGeometryModel::data( const QModelIndex &index, int role ) const
{
    GeoDataObject *item;
    if( index.isValid() )
    {
        item = static_cast<GeoDataObject*>( index.internalPointer() );
    }
    else /* the rootIndex is invalid */
    {
        item = static_cast<GeoDataObject*>( d->m_rootDocument );
    }

    /* for now simply give back the type of the GeoDataObject
    * there might be a need to extend this, but usually we want
    */
    if( role == Qt::DisplayRole ) {
        if( dynamic_cast<GeoDataFeature*>( item ) ) {
            switch( dynamic_cast<GeoDataFeature*>( item )->featureId() ) {
                case InvalidFeatureId:
                    return QVariant( "InvalidFeature" );
                case GeoDataDocumentId:
                    return QVariant( "GeoDataDocument" );
                case GeoDataFolderId:
                    return QVariant( "GeoDataFolder" );
                case GeoDataPlacemarkId:
                    return QVariant( "GeoDataPlacemark" );
                case GeoDataNetworkLinkId:
                    return QVariant( "GeoDataNetworkLink" );
                case GeoDataScreenOverlayId:
                    return QVariant( "GeoDataScreenOverlay" );
                case GeoDataGroundOverlayId:
                    return QVariant( "GeoDataGroundOverlay" );
            }
        }
        if( dynamic_cast<GeoDataGeometry*>( item ) ) {
            switch( dynamic_cast<GeoDataGeometry*>( item )->geometryId() ) {
                case InvalidGeometryId:
                    return QVariant( "InvalidGeometry" );
                case GeoDataMultiGeometryId:
                    return QVariant( "GeoDataMultiGeometry" );
                case GeoDataLineStringId:
                    return QVariant( "GeoDataLineString" );
                case GeoDataLinearRingId:
                    return QVariant( "GeoDataLinearRing" );
                case GeoDataPolygonId:
                    return QVariant( "GeoDataPolygon" );
                case GeoDataPointId:
                    return QVariant( "GeoDataPoint" );
            }
        }
    }

    if( role == Qt::UserRole + 11 ) //equivalent to MarblePlacemarkModel::ObjectPointerRole
    {
        /* return the pointer item as a QVariant of (meta-)type
         * Marble::GeoDataObject* */
        QVariant v;
        v.setValue( item );
        return v;
    }

    return QVariant( "GeoDataObject" );
    /* TODO the data is hardcoded and very limited right now,
     * the logic what data is returned might be moved to the items
     * themselves later. Use the following code then:
     * return item->data( index.column() ); */

}

QModelIndex MarbleGeometryModel::index( int row, int column, const QModelIndex &parent ) const
{
    if ( !hasIndex( row, column, parent ) )
        return QModelIndex();

    GeoDataObject *parentItem;

    if ( !parent.isValid() )
        parentItem = d->m_rootDocument;
    else
        parentItem = static_cast<GeoDataObject*>( parent.internalPointer() );

    GeoDataObject *childItem = 0;

    /* go down into GeoDataContainers */
    if( dynamic_cast<GeoDataDocument*>( parentItem ) ||
        dynamic_cast<GeoDataFolder*>( parentItem ) )
    {
        *childItem =     dynamic_cast<GeoDataContainer*>(
                            parentItem )->features().at( row );
    }

    if( dynamic_cast<GeoDataPlacemark*>( parentItem ) )
    {
        /* as said above - if you add styles, please check for the row over here */
        childItem = dynamic_cast<GeoDataPlacemark*>( parentItem )->geometry();
    }

    if( dynamic_cast<GeoDataMultiGeometry*>( parentItem ) )
    {
        *childItem = dynamic_cast<GeoDataMultiGeometry*>( parentItem )->at( row );
    }

    if ( childItem )
        return createIndex( row, column, childItem );
    else
        return QModelIndex();
}

QModelIndex MarbleGeometryModel::parent( const QModelIndex &index ) const
{
    if ( !index.isValid() )
        return QModelIndex();

    GeoDataObject *childItem = static_cast<GeoDataObject*>( index.internalPointer() );
    GeoDataObject *parentItem = d->m_parent[ childItem ];

    if ( parentItem == d->m_rootDocument )
        return QModelIndex();

    if( parentItem == 0 ){
        /* this shouldn't happen */
        return QModelIndex();
    }

    /* for now leave that as 0, 0 -> this needs some more thoughts as
     * it is simply wrong */
    return createIndex( 0, 0, parentItem );
}

int MarbleGeometryModel::columnCount( const QModelIndex &node ) const
{
    if ( node.isValid() )
        return 1;
        /* TODO when nodes handle their information themselves they will have
         * varying amounts of properties ( or columns ). Right now we only have
         * one information ( type ) per node, so it's hardcoded to "1".
         * static_cast<GeoDataObject*>( node.internalPointer() )->columnCount(); */
    else
        return 1;
}

void MarbleGeometryModel::update()
{
    QAbstractItemModel::reset();
}

#include "MarbleGeometryModel.moc"
<|endoftext|>


<commit_before>//
// This file is part of the Marble Virtual Globe.
//
// This program is free software licensed under the GNU LGPL. You can
// find a copy of this license in LICENSE.txt in the top directory of
// the source code.
//
// Copyright 2008 Henry de Valence <hdevalence@gmail.com>
// Copyright 2010 Dennis Nienhüser <earthwings@gentoo.org>

#include "MarbleRunnerManager.h"

#include "MarblePlacemarkModel.h"
#include "MarbleDebug.h"
#include "MarbleModel.h"
#include "Planet.h"
#include "GeoDataPlacemark.h"
#include "PluginManager.h"
#include "RunnerPlugin.h"
#include "RunnerTask.h"
#include "routing/RouteRequest.h"
#include "routing/RoutingProfilesModel.h"

#include <QtCore/QObject>
#include <QtCore/QString>
#include <QtCore/QVector>
#include <QtCore/QThreadPool>
#include <QtCore/QTimer>

namespace Marble
{

class MarbleModel;

class MarbleRunnerManagerPrivate
{
public:
    MarbleRunnerManager* q;
    QString m_lastSearchTerm;
    QMutex m_modelMutex;
    MarbleModel * m_marbleModel;
    MarblePlacemarkModel *m_model;
    QVector<GeoDataPlacemark*> m_placemarkContainer;
    QVector<GeoDataDocument*> m_routingResult;
    QList<GeoDataCoordinates> m_reverseGeocodingResults;
    RouteRequest* m_routeRequest;
    PluginManager* m_pluginManager;

    MarbleRunnerManagerPrivate( MarbleRunnerManager* parent, PluginManager* pluginManager );

    ~MarbleRunnerManagerPrivate();

    QList<RunnerPlugin*> plugins( RunnerPlugin::Capability capability );

    QList<RunnerTask*> m_searchTasks;
    QList<RunnerTask*> m_routingTasks;

    void cleanupSearchTask( RunnerTask* task );

    void cleanupRoutingTask( RunnerTask* task );
};

MarbleRunnerManagerPrivate::MarbleRunnerManagerPrivate( MarbleRunnerManager* parent, PluginManager* pluginManager ) :
        q( parent ),
        m_marbleModel( 0 ),
        m_model( new MarblePlacemarkModel ),
        m_routeRequest( 0 ),
        m_pluginManager( pluginManager )
{
    m_model->setPlacemarkContainer( &m_placemarkContainer );
    qRegisterMetaType<GeoDataPlacemark>( "GeoDataPlacemark" );
    qRegisterMetaType<GeoDataCoordinates>( "GeoDataCoordinates" );
    qRegisterMetaType<QVector<GeoDataPlacemark*> >( "QVector<GeoDataPlacemark*>" );
}

MarbleRunnerManagerPrivate::~MarbleRunnerManagerPrivate()
{
    delete m_model;
}

QList<RunnerPlugin*> MarbleRunnerManagerPrivate::plugins( RunnerPlugin::Capability capability )
{
    QList<RunnerPlugin*> result;
    QList<RunnerPlugin*> plugins = m_pluginManager->runnerPlugins();
    foreach( RunnerPlugin* plugin, plugins ) {
        if ( !plugin->supports( capability ) ) {
            continue;
        }

        if ( ( m_marbleModel && m_marbleModel->workOffline() && !plugin->canWorkOffline() ) ) {
            continue;
        }

        if ( !plugin->canWork( capability ) ) {
            continue;
        }

        if ( m_marbleModel && !plugin->supportsCelestialBody( m_marbleModel->planet()->id() ) )
        {
            continue;
        }

        result << plugin;
    }

    return result;
}

void MarbleRunnerManagerPrivate::cleanupSearchTask( RunnerTask* task )
{
    m_searchTasks.removeAll( task );

    if ( m_searchTasks.isEmpty() ) {
        emit q->searchFinished( m_lastSearchTerm );
    }
}

void MarbleRunnerManagerPrivate::cleanupRoutingTask( RunnerTask* task )
{
    m_routingTasks.removeAll( task );

    if ( m_routingTasks.isEmpty() && m_routingResult.isEmpty() ) {
        emit q->routeRetrieved( 0 );
    }
}

MarbleRunnerManager::MarbleRunnerManager( PluginManager* pluginManager, QObject *parent )
    : QObject( parent ), d( new MarbleRunnerManagerPrivate( this, pluginManager ) )
{
    if ( QThreadPool::globalInstance()->maxThreadCount() < 4 ) {
        QThreadPool::globalInstance()->setMaxThreadCount( 4 );
    }
}

MarbleRunnerManager::~MarbleRunnerManager()
{
    delete d;
}

void MarbleRunnerManager::reverseGeocoding( const GeoDataCoordinates &coordinates )
{
    d->m_reverseGeocodingResults.removeAll( coordinates );
    QList<RunnerPlugin*> plugins = d->plugins( RunnerPlugin::ReverseGeocoding );
    foreach( RunnerPlugin* plugin, plugins ) {
        MarbleAbstractRunner* runner = plugin->newRunner();
        runner->setParent( this );
        connect( runner, SIGNAL( reverseGeocodingFinished( GeoDataCoordinates, GeoDataPlacemark ) ),
                 this, SLOT( addReverseGeocodingResult( GeoDataCoordinates, GeoDataPlacemark ) ) );
        runner->setModel( d->m_marbleModel );
        QThreadPool::globalInstance()->start( new ReverseGeocodingTask( runner, coordinates ) );
    }

    if ( plugins.isEmpty() ) {
        emit reverseGeocodingFinished( coordinates, GeoDataPlacemark() );
    }
}

void MarbleRunnerManager::findPlacemarks( const QString &searchTerm )
{
    if ( searchTerm == d->m_lastSearchTerm ) {
      emit searchFinished( searchTerm );
      emit searchResultChanged( d->m_model );
      return;
    }

    d->m_lastSearchTerm = searchTerm;

    d->m_searchTasks.clear();

    d->m_modelMutex.lock();
    d->m_model->removePlacemarks( "MarbleRunnerManager", 0, d->m_placemarkContainer.size() );
    qDeleteAll( d->m_placemarkContainer );
    d->m_placemarkContainer.clear();
    d->m_modelMutex.unlock();
    emit searchResultChanged( d->m_model );

    QList<RunnerPlugin*> plugins = d->plugins( RunnerPlugin::Search );
    foreach( RunnerPlugin* plugin, plugins ) {
        MarbleAbstractRunner* runner = plugin->newRunner();
        runner->setParent( this );
        connect( runner, SIGNAL( searchFinished( QVector<GeoDataPlacemark*> ) ),
                 this, SLOT( addSearchResult( QVector<GeoDataPlacemark*> ) ) );
        runner->setModel( d->m_marbleModel );
        SearchTask* task = new SearchTask( runner, searchTerm );
        connect( task, SIGNAL( finished( RunnerTask* ) ), this, SLOT( cleanupSearchTask( RunnerTask* ) ) );
        d->m_searchTasks << task;
        QThreadPool::globalInstance()->start( task );
    }
}

void MarbleRunnerManager::addSearchResult( QVector<GeoDataPlacemark*> result )
{
    mDebug() << "Runner reports" << result.size() << " search results";
    if( result.isEmpty() )
        return;

    d->m_modelMutex.lock();
    int start = d->m_placemarkContainer.size();
    d->m_placemarkContainer << result;
    d->m_model->addPlacemarks( start, result.size() );
    d->m_modelMutex.unlock();
    emit searchResultChanged( d->m_model );
    emit searchResultChanged( d->m_placemarkContainer );
}

void MarbleRunnerManager::setModel( MarbleModel * model )
{
    // TODO: Terminate runners which are making use of the map.
    d->m_marbleModel = model;
}

void MarbleRunnerManager::addReverseGeocodingResult( const GeoDataCoordinates &coordinates, const GeoDataPlacemark &placemark )
{
    if ( !d->m_reverseGeocodingResults.contains( coordinates ) && !placemark.address().isEmpty() ) {
        d->m_reverseGeocodingResults.push_back( coordinates );
        emit reverseGeocodingFinished( coordinates, placemark );
    }
}

void MarbleRunnerManager::retrieveRoute( RouteRequest *request )
{
    RoutingProfile profile = request->routingProfile();

    d->m_routingTasks.clear();
    d->m_routingResult.clear();

    d->m_routeRequest = request;
    QList<RunnerPlugin*> plugins = d->plugins( RunnerPlugin::Routing );
    bool started = false;
    foreach( RunnerPlugin* plugin, plugins ) {
        if ( !profile.name().isEmpty() && !profile.pluginSettings().contains( plugin->nameId() ) ) {
            continue;
        }

        started = true;
        MarbleAbstractRunner* runner = plugin->newRunner();
        runner->setParent( this );
        connect( runner, SIGNAL( routeCalculated( GeoDataDocument* ) ),
                 this, SLOT( addRoutingResult( GeoDataDocument* ) ) );
        runner->setModel( d->m_marbleModel );
        RoutingTask* task = new RoutingTask( runner, request );
        d->m_routingTasks << task;
        connect( task, SIGNAL( finished( RunnerTask* ) ), this, SLOT( cleanupRoutingTask( RunnerTask* ) ) );
        QThreadPool::globalInstance()->start( task );
    }

    if ( !started ) {
        mDebug() << "No routing plugins found, cannot retrieve a route";
        d->cleanupRoutingTask( 0 );
    }
}

void MarbleRunnerManager::addRoutingResult( GeoDataDocument* route )
{
    if ( route ) {
        d->m_routingResult.push_back( route );
        emit routeRetrieved( route );
    }
}

}

#include "MarbleRunnerManager.moc"
<commit_msg>Don't execute empty search queries.<commit_after>//
// This file is part of the Marble Virtual Globe.
//
// This program is free software licensed under the GNU LGPL. You can
// find a copy of this license in LICENSE.txt in the top directory of
// the source code.
//
// Copyright 2008 Henry de Valence <hdevalence@gmail.com>
// Copyright 2010 Dennis Nienhüser <earthwings@gentoo.org>

#include "MarbleRunnerManager.h"

#include "MarblePlacemarkModel.h"
#include "MarbleDebug.h"
#include "MarbleModel.h"
#include "Planet.h"
#include "GeoDataPlacemark.h"
#include "PluginManager.h"
#include "RunnerPlugin.h"
#include "RunnerTask.h"
#include "routing/RouteRequest.h"
#include "routing/RoutingProfilesModel.h"

#include <QtCore/QObject>
#include <QtCore/QString>
#include <QtCore/QVector>
#include <QtCore/QThreadPool>
#include <QtCore/QTimer>

namespace Marble
{

class MarbleModel;

class MarbleRunnerManagerPrivate
{
public:
    MarbleRunnerManager* q;
    QString m_lastSearchTerm;
    QMutex m_modelMutex;
    MarbleModel * m_marbleModel;
    MarblePlacemarkModel *m_model;
    QVector<GeoDataPlacemark*> m_placemarkContainer;
    QVector<GeoDataDocument*> m_routingResult;
    QList<GeoDataCoordinates> m_reverseGeocodingResults;
    RouteRequest* m_routeRequest;
    PluginManager* m_pluginManager;

    MarbleRunnerManagerPrivate( MarbleRunnerManager* parent, PluginManager* pluginManager );

    ~MarbleRunnerManagerPrivate();

    QList<RunnerPlugin*> plugins( RunnerPlugin::Capability capability );

    QList<RunnerTask*> m_searchTasks;
    QList<RunnerTask*> m_routingTasks;

    void cleanupSearchTask( RunnerTask* task );

    void cleanupRoutingTask( RunnerTask* task );
};

MarbleRunnerManagerPrivate::MarbleRunnerManagerPrivate( MarbleRunnerManager* parent, PluginManager* pluginManager ) :
        q( parent ),
        m_marbleModel( 0 ),
        m_model( new MarblePlacemarkModel ),
        m_routeRequest( 0 ),
        m_pluginManager( pluginManager )
{
    m_model->setPlacemarkContainer( &m_placemarkContainer );
    qRegisterMetaType<GeoDataPlacemark>( "GeoDataPlacemark" );
    qRegisterMetaType<GeoDataCoordinates>( "GeoDataCoordinates" );
    qRegisterMetaType<QVector<GeoDataPlacemark*> >( "QVector<GeoDataPlacemark*>" );
}

MarbleRunnerManagerPrivate::~MarbleRunnerManagerPrivate()
{
    delete m_model;
}

QList<RunnerPlugin*> MarbleRunnerManagerPrivate::plugins( RunnerPlugin::Capability capability )
{
    QList<RunnerPlugin*> result;
    QList<RunnerPlugin*> plugins = m_pluginManager->runnerPlugins();
    foreach( RunnerPlugin* plugin, plugins ) {
        if ( !plugin->supports( capability ) ) {
            continue;
        }

        if ( ( m_marbleModel && m_marbleModel->workOffline() && !plugin->canWorkOffline() ) ) {
            continue;
        }

        if ( !plugin->canWork( capability ) ) {
            continue;
        }

        if ( m_marbleModel && !plugin->supportsCelestialBody( m_marbleModel->planet()->id() ) )
        {
            continue;
        }

        result << plugin;
    }

    return result;
}

void MarbleRunnerManagerPrivate::cleanupSearchTask( RunnerTask* task )
{
    m_searchTasks.removeAll( task );

    if ( m_searchTasks.isEmpty() ) {
        emit q->searchFinished( m_lastSearchTerm );
    }
}

void MarbleRunnerManagerPrivate::cleanupRoutingTask( RunnerTask* task )
{
    m_routingTasks.removeAll( task );

    if ( m_routingTasks.isEmpty() && m_routingResult.isEmpty() ) {
        emit q->routeRetrieved( 0 );
    }
}

MarbleRunnerManager::MarbleRunnerManager( PluginManager* pluginManager, QObject *parent )
    : QObject( parent ), d( new MarbleRunnerManagerPrivate( this, pluginManager ) )
{
    if ( QThreadPool::globalInstance()->maxThreadCount() < 4 ) {
        QThreadPool::globalInstance()->setMaxThreadCount( 4 );
    }
}

MarbleRunnerManager::~MarbleRunnerManager()
{
    delete d;
}

void MarbleRunnerManager::reverseGeocoding( const GeoDataCoordinates &coordinates )
{
    d->m_reverseGeocodingResults.removeAll( coordinates );
    QList<RunnerPlugin*> plugins = d->plugins( RunnerPlugin::ReverseGeocoding );
    foreach( RunnerPlugin* plugin, plugins ) {
        MarbleAbstractRunner* runner = plugin->newRunner();
        runner->setParent( this );
        connect( runner, SIGNAL( reverseGeocodingFinished( GeoDataCoordinates, GeoDataPlacemark ) ),
                 this, SLOT( addReverseGeocodingResult( GeoDataCoordinates, GeoDataPlacemark ) ) );
        runner->setModel( d->m_marbleModel );
        QThreadPool::globalInstance()->start( new ReverseGeocodingTask( runner, coordinates ) );
    }

    if ( plugins.isEmpty() ) {
        emit reverseGeocodingFinished( coordinates, GeoDataPlacemark() );
    }
}

void MarbleRunnerManager::findPlacemarks( const QString &searchTerm )
{
    if ( searchTerm == d->m_lastSearchTerm ) {
      emit searchResultChanged( d->m_model );
      emit searchFinished( searchTerm );
      return;
    }

    d->m_lastSearchTerm = searchTerm;

    d->m_searchTasks.clear();

    d->m_modelMutex.lock();
    d->m_model->removePlacemarks( "MarbleRunnerManager", 0, d->m_placemarkContainer.size() );
    qDeleteAll( d->m_placemarkContainer );
    d->m_placemarkContainer.clear();
    d->m_modelMutex.unlock();
    emit searchResultChanged( d->m_model );

    if ( searchTerm.trimmed().isEmpty() ) {
        emit searchFinished( searchTerm );
        return;
    }

    QList<RunnerPlugin*> plugins = d->plugins( RunnerPlugin::Search );
    foreach( RunnerPlugin* plugin, plugins ) {
        MarbleAbstractRunner* runner = plugin->newRunner();
        runner->setParent( this );
        connect( runner, SIGNAL( searchFinished( QVector<GeoDataPlacemark*> ) ),
                 this, SLOT( addSearchResult( QVector<GeoDataPlacemark*> ) ) );
        runner->setModel( d->m_marbleModel );
        SearchTask* task = new SearchTask( runner, searchTerm );
        connect( task, SIGNAL( finished( RunnerTask* ) ), this, SLOT( cleanupSearchTask( RunnerTask* ) ) );
        d->m_searchTasks << task;
        QThreadPool::globalInstance()->start( task );
    }
}

void MarbleRunnerManager::addSearchResult( QVector<GeoDataPlacemark*> result )
{
    mDebug() << "Runner reports" << result.size() << " search results";
    if( result.isEmpty() )
        return;

    d->m_modelMutex.lock();
    int start = d->m_placemarkContainer.size();
    d->m_placemarkContainer << result;
    d->m_model->addPlacemarks( start, result.size() );
    d->m_modelMutex.unlock();
    emit searchResultChanged( d->m_model );
    emit searchResultChanged( d->m_placemarkContainer );
}

void MarbleRunnerManager::setModel( MarbleModel * model )
{
    // TODO: Terminate runners which are making use of the map.
    d->m_marbleModel = model;
}

void MarbleRunnerManager::addReverseGeocodingResult( const GeoDataCoordinates &coordinates, const GeoDataPlacemark &placemark )
{
    if ( !d->m_reverseGeocodingResults.contains( coordinates ) && !placemark.address().isEmpty() ) {
        d->m_reverseGeocodingResults.push_back( coordinates );
        emit reverseGeocodingFinished( coordinates, placemark );
    }
}

void MarbleRunnerManager::retrieveRoute( RouteRequest *request )
{
    RoutingProfile profile = request->routingProfile();

    d->m_routingTasks.clear();
    d->m_routingResult.clear();

    d->m_routeRequest = request;
    QList<RunnerPlugin*> plugins = d->plugins( RunnerPlugin::Routing );
    bool started = false;
    foreach( RunnerPlugin* plugin, plugins ) {
        if ( !profile.name().isEmpty() && !profile.pluginSettings().contains( plugin->nameId() ) ) {
            continue;
        }

        started = true;
        MarbleAbstractRunner* runner = plugin->newRunner();
        runner->setParent( this );
        connect( runner, SIGNAL( routeCalculated( GeoDataDocument* ) ),
                 this, SLOT( addRoutingResult( GeoDataDocument* ) ) );
        runner->setModel( d->m_marbleModel );
        RoutingTask* task = new RoutingTask( runner, request );
        d->m_routingTasks << task;
        connect( task, SIGNAL( finished( RunnerTask* ) ), this, SLOT( cleanupRoutingTask( RunnerTask* ) ) );
        QThreadPool::globalInstance()->start( task );
    }

    if ( !started ) {
        mDebug() << "No routing plugins found, cannot retrieve a route";
        d->cleanupRoutingTask( 0 );
    }
}

void MarbleRunnerManager::addRoutingResult( GeoDataDocument* route )
{
    if ( route ) {
        d->m_routingResult.push_back( route );
        emit routeRetrieved( route );
    }
}

}

#include "MarbleRunnerManager.moc"
<|endoftext|>


<commit_before>#ifndef FILE_MYDEFS
#define FILE_MYDEFS

/**************************************************************************/
/* File:   mydefs.hh                                                      */
/* Author: Joachim Schoeberl                                              */
/* Date:   10. Mar. 98                                                    */
/**************************************************************************/

/*
  defines for graphics, testmodes, ...
*/

// #define DEBUG

// Philippose - 31/01/2009
// Hack for the Windows Version
// in Linux, "PACKAGE_VERSION" is replaced
// in the configure/make phases, with the
// right version number
#ifdef WIN32
#define PACKAGE_VERSION "4.9.13"
#endif

#ifdef WIN32
   #if NGINTERFACE_EXPORTS || NGLIB_EXPORTS || nglib_EXPORTS
      #define DLL_HEADER   __declspec(dllexport)
   #else
      #define DLL_HEADER   __declspec(dllimport)
   #endif
#else
   #define DLL_HEADER
#endif

#define noDEMOVERSION
#define noDEVELOP
#define noSTEP
#define noSOLIDGEOM

#define noDEMOAPP
#define noMODELLER

#define noSTAT_STREAM
#define noLOG_STREAM

#endif
<commit_msg>windows version<commit_after>#ifndef FILE_MYDEFS
#define FILE_MYDEFS

/**************************************************************************/
/* File:   mydefs.hh                                                      */
/* Author: Joachim Schoeberl                                              */
/* Date:   10. Mar. 98                                                    */
/**************************************************************************/

/*
  defines for graphics, testmodes, ...
*/

// #define DEBUG

// Philippose - 31/01/2009
// Hack for the Windows Version
// in Linux, "PACKAGE_VERSION" is replaced
// in the configure/make phases, with the
// right version number
#ifdef WIN32
#define PACKAGE_VERSION "4.9.14"
#endif

#ifdef WIN32
   #if NGINTERFACE_EXPORTS || NGLIB_EXPORTS || nglib_EXPORTS
      #define DLL_HEADER   __declspec(dllexport)
   #else
      #define DLL_HEADER   __declspec(dllimport)
   #endif
#else
   #define DLL_HEADER
#endif

#define noDEMOVERSION
#define noDEVELOP
#define noSTEP
#define noSOLIDGEOM

#define noDEMOAPP
#define noMODELLER

#define noSTAT_STREAM
#define noLOG_STREAM

#endif
<|endoftext|>


<commit_before><commit_msg>instance check - bug fixes and refactoring based on code review.<commit_after><|endoftext|>


<commit_before><commit_msg>Cleanup in Matrix3x3 tests<commit_after><|endoftext|>


<commit_before><commit_msg>INTEGRATION: CWS fwk29 (1.66.214); FILE MERGED 2006/01/02 15:40:00 cd 1.66.214.1: #i58471# Don't disable fontname box when docshell is not available but we have a valid font list<commit_after><|endoftext|>


<commit_before><commit_msg>INTEGRATION: CWS pages01_DEV300 (1.70.12); FILE MERGED 2008/02/26 10:15:20 fme 1.70.12.7: #i1598# Multiple page view - sync with new notes feature 2008/02/21 12:43:52 fme 1.70.12.6: RESYNC: (1.71-1.72); FILE MERGED 2008/01/10 09:18:38 fme 1.70.12.5: RESYNC: (1.70-1.71); FILE MERGED 2007/12/04 15:39:56 fme 1.70.12.4: #i1598# Multiple Page View - Table row/column selection 2007/11/28 16:02:02 fme 1.70.12.3: #i1598# Multiple Page View - RTL 2007/11/19 13:11:02 fme 1.70.12.2: #i1598# Multiple page view 2007/10/24 15:00:18 fme 1.70.12.1: #i1598# Multiple Page View<commit_after><|endoftext|>


<commit_before>/****************************************************************************
 *
 *   Copyright (c) 2013 PX4 Development Team. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in
 *    the documentation and/or other materials provided with the
 *    distribution.
 * 3. Neither the name PX4 nor the names of its contributors may be
 *    used to endorse or promote products derived from this software
 *    without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
 * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 *
 ****************************************************************************/

/**
 * @file Limits.hpp
 *
 * Limiting / constrain helper functions
 */

#pragma once

#include <platforms/px4_defines.h>
#include <stdint.h>

//this should be defined in stdint.h, but seems to be missing in the ARM toolchain (5.2.0)
#ifndef UINT64_C
# if __WORDSIZE == 64
#  define UINT64_C(c)	c ## UL
# else
#  define UINT64_C(c)	c ## ULL
# endif
#endif

namespace math
{

template<typename _Tp>
inline const _Tp &min(const _Tp &a, const _Tp &b)
{
	return (a < b) ? a : b;
}

template<typename _Tp>
inline const _Tp &max(const _Tp &a, const _Tp &b)
{
	return (a > b) ? a : b;
}

template<typename _Tp>
inline const _Tp &constrain(const _Tp &val, const _Tp &min_val, const _Tp &max_val)
{
	return (val < min_val) ? min_val : ((val > max_val) ? max_val : val);
}

float __EXPORT radians(float degrees);

double __EXPORT radians(double degrees);

float __EXPORT degrees(float radians);

double __EXPORT degrees(double radians);

}
<commit_msg>mathlib : switch min/max to constexpr to match std::min/max<commit_after>/****************************************************************************
 *
 *   Copyright (c) 2013 PX4 Development Team. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in
 *    the documentation and/or other materials provided with the
 *    distribution.
 * 3. Neither the name PX4 nor the names of its contributors may be
 *    used to endorse or promote products derived from this software
 *    without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
 * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 *
 ****************************************************************************/

/**
 * @file Limits.hpp
 *
 * Limiting / constrain helper functions
 */

#pragma once

#include <platforms/px4_defines.h>
#include <stdint.h>

//this should be defined in stdint.h, but seems to be missing in the ARM toolchain (5.2.0)
#ifndef UINT64_C
# if __WORDSIZE == 64
#  define UINT64_C(c)	c ## UL
# else
#  define UINT64_C(c)	c ## ULL
# endif
#endif

namespace math
{

template<typename _Tp>
inline constexpr const _Tp &min(const _Tp &a, const _Tp &b)
{
	return (a < b) ? a : b;
}

template<typename _Tp>
inline constexpr const _Tp &max(const _Tp &a, const _Tp &b)
{
	return (a > b) ? a : b;
}

template<typename _Tp>
inline constexpr const _Tp &constrain(const _Tp &val, const _Tp &min_val, const _Tp &max_val)
{
	return (val < min_val) ? min_val : ((val > max_val) ? max_val : val);
}

float __EXPORT radians(float degrees);

double __EXPORT radians(double degrees);

float __EXPORT degrees(float radians);

double __EXPORT degrees(double radians);

}
<|endoftext|>


<commit_before>#include <cstring>
#include <iostream>
#include <memory>
#include <string>
#include <vector>

using namespace std;

/*
 * INSTRUCTIONS
 *
 * This module builds a simple cmdline program that tells whether words/phrases
 * match certain criteria. It uses C++11 constructs, but nothing overly
 * mysterious; reasonable familiarity with STL will probably be enough to
 * make you comfortable. You will be extending and debugging the program.
 *
 * 1. Read and understand the basics of the program. Don't worry too much
 *    about style; focus on what work gets done, and how.
 * 2. Extend the program so it can test for palindromes (words/phrases that are
 *    the same written forward and backward, like "noon" or "a toyotas a toyota").
 * 3. Bonus: can you find a latent bug in VowelHeavy::matches_def?
 * 4. Bonus: can you find a latent bug in FirstConsonant::matches_def?
 * 5. Bonus: can you find a bug with security ramifications in main()?
 * 6. Come up with a list of unit tests for specializations of Test. Think of
 *    ones that would catch the bugs you've found, as well as others that might
 *    be useful.
*/

/// A Test decides whether a string matches the definition of a
/// an interesting category. For example, a Test might tell you if
/// a string is a noun, a palindrome, longer than 10 letters, etc.
class Test {
public:
	virtual bool matches_def(const string &) const = 0;
	virtual const char * get_name() const = 0;
};

typedef unique_ptr<Test> TestHandle;
typedef vector<TestHandle> Tests;

static bool is_vowel(char c) {
	return strchr("aeiouAEIOU", c) != nullptr;
}

static bool is_consonant(char c) {
	return strchr("bcdfghjklmnpqrstvwxyzBCDFGHJKLMNPQRSTVWXYZ", c) != nullptr;
}

// Does a string have more vowels than consonants?
class VowelHeavy: public Test {
public:
	virtual bool matches_def(const string & x) const {
		auto vowel_count = 0u;
		auto consonant_count = 0u;
		for (auto c: x) {
			if (is_vowel(c)) {
				++vowel_count;
			} else if (is_consonant(c)) {
				++consonant_count;
			}
		}
		return vowel_count / (float)consonant_count > 1.0;
	}
	virtual const char * get_name() const { return "vowelheavy"; }
};

// Does a string begin with a consonant?
class FirstConsonant: public Test {
public:
	virtual bool matches_def(const string & x) const {
		return !x.empty() && !is_vowel(x[0]);
	}
	virtual const char * get_name() const { return "firstcons"; }
};

// Show usage for the program
static void show_help(const Tests & tests) {
	cout << "check ";
	int i = 0;
	for (auto & test: tests) {
		if (i++ > 0) {
			cout << '|';
		}
		cout << test->get_name();
	}
	cout << " word" << endl;
}

int main(int argc, char ** argv) {
	Tests tests;
	tests.push_back(TestHandle(new VowelHeavy()));
	tests.push_back(TestHandle(new FirstConsonant()));
	if (argc < 3) {
		show_help(tests);
		return 1;
	}
	auto selected_test = argv[1];
	auto word = argv[2];
	for (auto & test: tests) {
		if (strcmp(selected_test, test->get_name()) == 0) {
			cout << (test->matches_def(word) ? "yes" : "no") << endl;
			return 0;
		}
	}
	cout << "Huh?" << endl;
	return 1;
}

<commit_msg>Improve instructions at top of test.<commit_after>#include <cstring>
#include <iostream>
#include <memory>
#include <string>
#include <vector>

using namespace std;

/*
 * INSTRUCTIONS
 *
 * This module builds a simple cmdline program that tells whether words/phrases
 * match certain criteria. It uses C++11 constructs, but nothing overly
 * mysterious; reasonable familiarity with STL will probably be enough to
 * make you comfortable. You will be extending and debugging the program.
 *
 * 1. Read and understand the basics of the program. Don't worry too much
 *    about style; focus on what work gets done, and how.
 * 2. Extend the program so it can test for palindromes (words/phrases that are
 *    the same written forward and backward, like "noon" or "a toyotas a toyota").
 * 3. Bonus: can you find a latent bug in VowelHeavy::matches_def?
 * 4. Bonus: can you find a latent bug in FirstConsonant::matches_def?
 * 5. Bonus: can you find a bug with security ramifications in main()?
 * 6. Come up with a list of unit tests for specializations of Test. Think of
 *    ones that would catch the bugs you've found, as well as others that might
 *    be useful. You don't have to code the tests, just describe them.
*/

/// A Test decides whether a string matches the definition of a
/// an interesting category. For example, a Test might tell you if
/// a string is a noun, a palindrome, longer than 10 letters, etc.
class Test {
public:
	virtual bool matches_def(const string &) const = 0;
	virtual const char * get_name() const = 0;
};

typedef unique_ptr<Test> TestHandle;
typedef vector<TestHandle> Tests;

static bool is_vowel(char c) {
	return strchr("aeiouAEIOU", c) != nullptr;
}

static bool is_consonant(char c) {
	return strchr("bcdfghjklmnpqrstvwxyzBCDFGHJKLMNPQRSTVWXYZ", c) != nullptr;
}

// Does a string have more vowels than consonants?
class VowelHeavy: public Test {
public:
	virtual bool matches_def(const string & x) const {
		auto vowel_count = 0u;
		auto consonant_count = 0u;
		for (auto c: x) {
			if (is_vowel(c)) {
				++vowel_count;
			} else if (is_consonant(c)) {
				++consonant_count;
			}
		}
		return vowel_count / (float)consonant_count > 1.0;
	}
	virtual const char * get_name() const { return "vowelheavy"; }
};

// Does a string begin with a consonant?
class FirstConsonant: public Test {
public:
	virtual bool matches_def(const string & x) const {
		return !x.empty() && !is_vowel(x[0]);
	}
	virtual const char * get_name() const { return "firstcons"; }
};

// Show usage for the program
static void show_help(const Tests & tests) {
	cout << "check ";
	int i = 0;
	for (auto & test: tests) {
		if (i++ > 0) {
			cout << '|';
		}
		cout << test->get_name();
	}
	cout << " word" << endl;
}

int main(int argc, char ** argv) {
	Tests tests;
	tests.push_back(TestHandle(new VowelHeavy()));
	tests.push_back(TestHandle(new FirstConsonant()));
	if (argc < 3) {
		show_help(tests);
		return 1;
	}
	auto selected_test = argv[1];
	auto word = argv[2];
	for (auto & test: tests) {
		if (strcmp(selected_test, test->get_name()) == 0) {
			cout << (test->matches_def(word) ? "yes" : "no") << endl;
			return 0;
		}
	}
	cout << "Huh?" << endl;
	return 1;
}

<|endoftext|>


<commit_before>/*
 * opencog/atoms/reduct/PlusLink.cc
 *
 * Copyright (C) 2015 Linas Vepstas
 * All Rights Reserved
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License v3 as
 * published by the Plus Software Foundation and including the exceptions
 * at http://opencog.org/wiki/Licenses
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program; if not, write to:
 * Plus Software Foundation, Inc.,
 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 */

#include <opencog/atomspace/atom_types.h>
#include <opencog/atomspace/ClassServer.h>
#include <opencog/atoms/NumberNode.h>
#include "PlusLink.h"
#include "TimesLink.h"

using namespace opencog;

PlusLink::PlusLink(const HandleSeq& oset,
                   TruthValuePtr tv,
                   AttentionValuePtr av)
    : ArithmeticLink(PLUS_LINK, oset, tv, av)
{
	init();
}

PlusLink::PlusLink(Type t, const HandleSeq& oset,
                   TruthValuePtr tv,
                   AttentionValuePtr av)
    : ArithmeticLink(t, oset, tv, av)
{
	if (not classserver().isA(t, PLUS_LINK))
		throw InvalidParamException(TRACE_INFO, "Expecting a PlusLink");
	init();
}

PlusLink::PlusLink(Type t, const Handle& a, const Handle& b,
                   TruthValuePtr tv,
                   AttentionValuePtr av)
    : ArithmeticLink(t, a, b, tv, av)
{
	if (not classserver().isA(t, PLUS_LINK))
		throw InvalidParamException(TRACE_INFO, "Expecting a PlusLink");
	init();
}

PlusLink::PlusLink(Link& l)
    : ArithmeticLink(l)
{
	Type tscope = l.getType();
	if (not classserver().isA(tscope, PLUS_LINK))
		throw InvalidParamException(TRACE_INFO, "Expecting a PlusLink");
	init();
}

static double plus(double a, double b) { return a+b; }

void PlusLink::init(void)
{
	knild = 0.0;
	konsd = plus;
}

// ============================================================

/// re-order the contents of a PlusLink into "lexicographic" order.
///
/// The goal of the re-ordering is to simplify the reduction code,
/// by placing atoms where they are easily found.  For now, this
/// means:
/// first, all of the variables,
/// next, all compound expressions,
/// last, all number nodes (of which there should be only zero or one.)
/// We do not currently sort the variables, but maybe we should...?
/// The FoldLink::reduce() method already returns expressions that are
/// almost in the correct order.
Handle PlusLink::reorder(void)
{
	HandleSeq vars;
	HandleSeq exprs;
	HandleSeq numbers;

	for (const Handle& h : _outgoing)
	{
		if (h->getType() == VARIABLE_NODE)
			vars.push_back(h);
		else if (h->getType() == NUMBER_NODE)
			numbers.push_back(h);
		else
			exprs.push_back(h);
	}

	if (1 < numbers.size())
		throw RuntimeException(TRACE_INFO,
		      "Expecting the plus link to have already been reduced!");

	HandleSeq result;
	for (const Handle& h : vars) result.push_back(h);
	for (const Handle& h : exprs) result.push_back(h);
	for (const Handle& h : numbers) result.push_back(h);

	return Handle(createPlusLink(result));
}

// ============================================================

/// Handle normalization of addition into multiplication.
/// aka "mutiplicattive reduction"
///
/// There are four cases handled here:
/// x+x ==> 2x
/// x + ax ==> (a+1) x
/// ax + x ==> (a+1) x
/// ax + bx ==> (a + b) x
///
Handle PlusLink::reduce(void)
{
	// First, let FoldLink do its stuff.
	Handle fold = ArithmeticLink::reduce();

	if (PLUS_LINK != fold->getType()) return fold;

	PlusLinkPtr pfold(PlusLinkCast(fold));
	if (NULL == pfold)
		pfold = createPlusLink(*LinkCast(fold));
	fold = pfold->reorder();

	// Now, look for repeated atoms, two atoms that appear twice
	// in the outgoing set. If they do, then can be mutliplied.
	LinkPtr lfold(LinkCast(fold));

	bool do_reduce = false;
	Handle reduct = Handle::UNDEFINED;

	const HandleSeq& ofs = lfold->getOutgoingSet();
	size_t fsz = ofs.size();
	for (size_t i = 0; i < fsz; i++)
	{
		const Handle& fi = ofs[i];
		for (size_t j=i+1; j < fsz; j++)
		{
			const Handle& fj = ofs[j];

			// Is atom in position i identical to atom in position j?
			// If so, then replace by 2*i
			if (fi == fj)
			{
				Handle two(createNumberNode("2"));
				reduct = Handle(createTimesLink(fi, two));
				do_reduce = true;
			}

			// If j is (TimesLink x a) and i is identical to x,
			// then create (TimesLink x (a+1))
			//
			// If j is (TimesLink x a) and i is (TimesLink x b)
			// then create (TimesLink x (a+b))
			//
			else if (fj->getType() == TIMES_LINK)
			{
				bool do_add = false;
				HandleSeq rest;

				LinkPtr ilp = LinkCast(fi);
				LinkPtr jlp = LinkCast(fj);
				Handle exx = jlp->getOutgoingAtom(0);

				// Handle the (a+1) case described above.
				if (fi == exx)
				{
					Handle one(createNumberNode("1"));
					rest.push_back(one);
					do_add = true;
				}

				// Handle the (a+b) case described above.
				else if (ilp->getOutgoingAtom(0) == exx)
				{
					const HandleSeq& ilpo = ilp->getOutgoingSet();
					size_t ilpsz = ilpo.size();
					for (size_t k=1; k<ilpsz; k++)
						rest.push_back(ilpo[k]);
					do_add = true;
				}

				if (do_add)
				{
					const HandleSeq& jlpo = jlp->getOutgoingSet();
					size_t jlpsz = jlpo.size();
					for (size_t k=1; k<jlpsz; k++)
						rest.push_back(jlpo[k]);

					// a_plus is now (a+1) or (a+b) as described above.
					PlusLinkPtr ap = createPlusLink(rest);
					Handle a_plus(ap->reduce());

					reduct = Handle(createTimesLink(exx, a_plus));
					do_reduce = true;
				}
			}

			if (do_reduce)
			{
				HandleSeq norm;
				norm.push_back(reduct);

				// copy everything else, except for i and j.
				for (size_t k = 0; k< fsz; k++)
				{
					if (k == i or k == j) continue;
					norm.push_back(ofs[k]);
				}

				PlusLinkPtr plp = createPlusLink(norm);

				Handle red(plp->reduce());

				// Place the result into the same atomspace we are in.
				// XXX this is bad, buggy, uncomfortable, icky: it pollutes
				// the atomspace with intermediate results. This needs to
				// be fixed somehow. Right now, I don't know how.
				if (not _atomTable) return red;

				AtomSpace* as = _atomTable->getAtomSpace();
				return as->addAtom(red);
			}
		}
	}

	return fold;
}
<commit_msg>Bug fix unit test<commit_after>/*
 * opencog/atoms/reduct/PlusLink.cc
 *
 * Copyright (C) 2015 Linas Vepstas
 * All Rights Reserved
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License v3 as
 * published by the Plus Software Foundation and including the exceptions
 * at http://opencog.org/wiki/Licenses
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program; if not, write to:
 * Plus Software Foundation, Inc.,
 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 */

#include <opencog/atomspace/atom_types.h>
#include <opencog/atomspace/ClassServer.h>
#include <opencog/atoms/NumberNode.h>
#include "PlusLink.h"
#include "TimesLink.h"

using namespace opencog;

PlusLink::PlusLink(const HandleSeq& oset,
                   TruthValuePtr tv,
                   AttentionValuePtr av)
    : ArithmeticLink(PLUS_LINK, oset, tv, av)
{
	init();
}

PlusLink::PlusLink(Type t, const HandleSeq& oset,
                   TruthValuePtr tv,
                   AttentionValuePtr av)
    : ArithmeticLink(t, oset, tv, av)
{
	if (not classserver().isA(t, PLUS_LINK))
		throw InvalidParamException(TRACE_INFO, "Expecting a PlusLink");
	init();
}

PlusLink::PlusLink(Type t, const Handle& a, const Handle& b,
                   TruthValuePtr tv,
                   AttentionValuePtr av)
    : ArithmeticLink(t, a, b, tv, av)
{
	if (not classserver().isA(t, PLUS_LINK))
		throw InvalidParamException(TRACE_INFO, "Expecting a PlusLink");
	init();
}

PlusLink::PlusLink(Link& l)
    : ArithmeticLink(l)
{
	Type tscope = l.getType();
	if (not classserver().isA(tscope, PLUS_LINK))
		throw InvalidParamException(TRACE_INFO, "Expecting a PlusLink");
	init();
}

static double plus(double a, double b) { return a+b; }

void PlusLink::init(void)
{
	knild = 0.0;
	konsd = plus;
}

// ============================================================

/// re-order the contents of a PlusLink into "lexicographic" order.
///
/// The goal of the re-ordering is to simplify the reduction code,
/// by placing atoms where they are easily found.  For now, this
/// means:
/// first, all of the variables,
/// next, all compound expressions,
/// last, all number nodes (of which there should be only zero or one.)
/// We do not currently sort the variables, but maybe we should...?
/// The FoldLink::reduce() method already returns expressions that are
/// almost in the correct order.
Handle PlusLink::reorder(void)
{
	HandleSeq vars;
	HandleSeq exprs;
	HandleSeq numbers;

	for (const Handle& h : _outgoing)
	{
		if (h->getType() == VARIABLE_NODE)
			vars.push_back(h);
		else if (h->getType() == NUMBER_NODE)
			numbers.push_back(h);
		else
			exprs.push_back(h);
	}

	if (1 < numbers.size())
		throw RuntimeException(TRACE_INFO,
		      "Expecting the plus link to have already been reduced!");

	HandleSeq result;
	for (const Handle& h : vars) result.push_back(h);
	for (const Handle& h : exprs) result.push_back(h);
	for (const Handle& h : numbers) result.push_back(h);

	return Handle(createPlusLink(result));
}

// ============================================================

/// Handle normalization of addition into multiplication.
/// aka "mutiplicattive reduction"
///
/// There are four cases handled here:
/// x+x ==> 2x
/// x + ax ==> (a+1) x
/// ax + x ==> (a+1) x
/// ax + bx ==> (a + b) x
///
Handle PlusLink::reduce(void)
{
	// First, let FoldLink do its stuff.
	Handle fold = ArithmeticLink::reduce();

	if (PLUS_LINK != fold->getType()) return fold;

	PlusLinkPtr pfold(PlusLinkCast(fold));
	if (NULL == pfold)
		pfold = createPlusLink(*LinkCast(fold));
	fold = pfold->reorder();

	// Now, look for repeated atoms, two atoms that appear twice
	// in the outgoing set. If they do, then can be mutliplied.
	LinkPtr lfold(LinkCast(fold));

	bool do_reduce = false;
	Handle reduct = Handle::UNDEFINED;

	const HandleSeq& ofs = lfold->getOutgoingSet();
	size_t fsz = ofs.size();
	for (size_t i = 0; i < fsz; i++)
	{
		const Handle& fi = ofs[i];
		for (size_t j=i+1; j < fsz; j++)
		{
			const Handle& fj = ofs[j];

			// Is atom in position i identical to atom in position j?
			// If so, then replace by 2*i
			if (fi == fj)
			{
				Handle two(createNumberNode("2"));
				reduct = Handle(createTimesLink(fi, two));
				do_reduce = true;
			}

			// If j is (TimesLink x a) and i is identical to x,
			// then create (TimesLink x (a+1))
			//
			// If j is (TimesLink x a) and i is (TimesLink x b)
			// then create (TimesLink x (a+b))
			//
			else if (fj->getType() == TIMES_LINK)
			{
				bool do_add = false;
				HandleSeq rest;

				LinkPtr ilp = LinkCast(fi);
				LinkPtr jlp = LinkCast(fj);
				Handle exx = jlp->getOutgoingAtom(0);

				// Handle the (a+1) case described above.
				if (fi == exx)
				{
					Handle one(createNumberNode("1"));
					rest.push_back(one);
					do_add = true;
				}

				// Handle the (a+b) case described above.
				else if (ilp->getOutgoingAtom(0) == exx)
				{
					const HandleSeq& ilpo = ilp->getOutgoingSet();
					size_t ilpsz = ilpo.size();
					for (size_t k=1; k<ilpsz; k++)
						rest.push_back(ilpo[k]);
					do_add = true;
				}

				if (do_add)
				{
					const HandleSeq& jlpo = jlp->getOutgoingSet();
					size_t jlpsz = jlpo.size();
					for (size_t k=1; k<jlpsz; k++)
						rest.push_back(jlpo[k]);

					// a_plus is now (a+1) or (a+b) as described above.
					PlusLinkPtr ap = createPlusLink(rest);
					Handle a_plus(ap->reduce());

					reduct = Handle(createTimesLink(exx, a_plus));
					do_reduce = true;
				}
			}

			if (do_reduce)
			{
				HandleSeq norm;
				norm.push_back(reduct);

				// copy everything else, except for i and j.
				for (size_t k = 0; k< fsz; k++)
				{
					if (k == i or k == j) continue;
					norm.push_back(ofs[k]);
				}

				PlusLinkPtr plp = createPlusLink(norm);

				Handle red(plp->reduce());

				// Place the result into the same atomspace we are in.
				// XXX this is bad, buggy, uncomfortable, icky: it pollutes
				// the atomspace with intermediate results. This needs to
				// be fixed somehow. Right now, I don't know how.
				if (not _atomTable) return red;

				AtomSpace* as = _atomTable->getAtomSpace();
				return as->addAtom(red);
			}
		}
	}

	if (not _atomTable) return fold;
	AtomSpace* as = _atomTable->getAtomSpace();
	return as->addAtom(fold);
}
<|endoftext|>


<commit_before>/*
 *
 * Copyright 2016 gRPC authors.
 *
 * 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.
 *
 */

#include "test/cpp/util/cli_credentials.h"

#include <gflags/gflags.h>

DEFINE_bool(enable_ssl, false, "Whether to use ssl/tls.");
DEFINE_bool(use_auth, false, "Whether to create default google credentials.");
DEFINE_string(
    access_token, "",
    "The access token that will be sent to the server to authenticate RPCs.");
DEFINE_string(
    ssl_target, "",
    "If not empty, treat the server host name as this for ssl/tls certificate "
    "validation.");

namespace grpc {
namespace testing {

std::shared_ptr<grpc::ChannelCredentials> CliCredentials::GetCredentials()
    const {
  if (!FLAGS_access_token.empty()) {
    if (FLAGS_use_auth) {
      fprintf(stderr,
              "warning: use_auth is ignored when access_token is provided.");
    }

    return grpc::CompositeChannelCredentials(
        grpc::SslCredentials(grpc::SslCredentialsOptions()),
        grpc::AccessTokenCredentials(FLAGS_access_token));
  }

  if (FLAGS_use_auth) {
    return grpc::GoogleDefaultCredentials();
  }

  if (FLAGS_enable_ssl) {
    return grpc::SslCredentials(grpc::SslCredentialsOptions());
  }

  return grpc::InsecureChannelCredentials();
}

const grpc::string CliCredentials::GetCredentialUsage() const {
  return "    --enable_ssl             ; Set whether to use tls\n"
         "    --use_auth               ; Set whether to create default google"
         " credentials\n"
         "    --access_token           ; Set the access token in metadata,"
         " overrides --use_auth\n"
         "    --ssl_target             ; Set server host for tls validation\n";
}

const grpc::string CliCredentials::GetSslTargetNameOverride() const {
  return FLAGS_enable_ssl ? FLAGS_ssl_target : "";
}

}  // namespace testing
}  // namespace grpc
<commit_msg>GoogleDefaultCredentials use SSL under the covers; include that case.<commit_after>/*
 *
 * Copyright 2016 gRPC authors.
 *
 * 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.
 *
 */

#include "test/cpp/util/cli_credentials.h"

#include <gflags/gflags.h>

DEFINE_bool(enable_ssl, false, "Whether to use ssl/tls.");
DEFINE_bool(use_auth, false, "Whether to create default google credentials.");
DEFINE_string(
    access_token, "",
    "The access token that will be sent to the server to authenticate RPCs.");
DEFINE_string(
    ssl_target, "",
    "If not empty, treat the server host name as this for ssl/tls certificate "
    "validation.");

namespace grpc {
namespace testing {

std::shared_ptr<grpc::ChannelCredentials> CliCredentials::GetCredentials()
    const {
  if (!FLAGS_access_token.empty()) {
    if (FLAGS_use_auth) {
      fprintf(stderr,
              "warning: use_auth is ignored when access_token is provided.");
    }

    return grpc::CompositeChannelCredentials(
        grpc::SslCredentials(grpc::SslCredentialsOptions()),
        grpc::AccessTokenCredentials(FLAGS_access_token));
  }

  if (FLAGS_use_auth) {
    return grpc::GoogleDefaultCredentials();
  }

  if (FLAGS_enable_ssl) {
    return grpc::SslCredentials(grpc::SslCredentialsOptions());
  }

  return grpc::InsecureChannelCredentials();
}

const grpc::string CliCredentials::GetCredentialUsage() const {
  return "    --enable_ssl             ; Set whether to use tls\n"
         "    --use_auth               ; Set whether to create default google"
         " credentials\n"
         "    --access_token           ; Set the access token in metadata,"
         " overrides --use_auth\n"
         "    --ssl_target             ; Set server host for tls validation\n";
}

const grpc::string CliCredentials::GetSslTargetNameOverride() const {
  return (FLAGS_enable_ssl || FLAGS_use_auth) ? FLAGS_ssl_target : "";
}

}  // namespace testing
}  // namespace grpc
<|endoftext|>


<commit_before><commit_msg>re-enable cumulative relaxation<commit_after><|endoftext|>


<commit_before>/*
 * linked_circular_Queue.hpp
 *
 *  Created on: 22-May-2017
 *      Author: Anshu
 */

#ifndef LINKED_CIRCULAR_QUEUE_HPP_
#define LINKED_CIRCULAR_QUEUE_HPP_

#include "link_node.h"

template<class T>
class LinkedCircularQueue {
private:
	Node<T>* head;
	Node<T>* tail;
	unsigned int size_t;

	inline void range_check(void) const;

public:

	LinkedCircularQueue(void);

	LinkedCircularQueue(const LinkedCircularQueue& other);

	virtual ~LinkedCircularQueue(void);

	void offer(const T& element);

	const T& take(void);

	inline const T& peek(void) const;

	inline bool empty(void) const;

	inline unsigned int size(void) const;
};

template<class T>
LinkedCircularQueue<T>::LinkedCircularQueue(void) {
	head = tail = nullptr;
	size_t = 0;
}

template<class T>
LinkedCircularQueue<T>::LinkedCircularQueue(
		const LinkedCircularQueue<T>& otherQueue) {
	Node<T> *node;
	if (!otherQueue.empty()) {
		node = new Node<T>(otherQueue.head->getData(), nullptr);
		head = tail = node;
		tail->setNext(head);

		Node<T> *ptr = otherQueue.head->getNext();
		for (; ptr != otherQueue.head; ptr = ptr->getNext()) {
			node = new Node<T>(ptr->getData(), head);
			tail->setNext(node);
			tail = node;
		}
	}
	size_t = otherQueue.size_t;
}

template<class T>
LinkedCircularQueue<T>::~LinkedCircularQueue(void) {
	tail->setNext(nullptr);
	for (Node<T> *ptr = head; ptr != nullptr;) {
		head = ptr->getNext();
		delete ptr;
		ptr = head;
	}
}

template<class T>
inline unsigned int LinkedCircularQueue<T>::size(void) const {
	return size_t;
}

template<class T>
void LinkedCircularQueue<T>::offer(const T& data) {
	Node<T> *node = new Node<T>(data, head);

	if (size_t == 0) {
		tail = head = node;
	} else {
		tail->setNext(node);
		tail = node;
	}
	++size_t;
}

template<class T>
const T& LinkedCircularQueue<T>::take(void) {
	range_check();

	Node<T> *node = head;
	T& data = node->getData();
	if (size_t == 1) {
		head = tail = nullptr;
	} else {
		head = node->getNext();
		tail->setNext(head);
	}
	--size_t;
	delete node;
	return data;
}

template<class T>
inline const T& LinkedCircularQueue<T>::peek(void) const {
	range_check();
	return head->getData();
}

template<class T>
bool LinkedCircularQueue<T>::empty(void) const {
	return size_t == 0;
}

template<class T>
inline void LinkedCircularQueue<T>::range_check(void) const {
	if (size_t == 0) {
		throw std::logic_error("Queue was empty");
	}
}
#endif /* LINKED_CIRCULAR_QUEUE_HPP_ */
<commit_msg>Added circular Queue linked implementation<commit_after>/*
 * linked_circular_Queue.hpp
 *
 *  Created on: 22-May-2017
 *      Author: Amit
 */

#ifndef LINKED_CIRCULAR_QUEUE_HPP_
#define LINKED_CIRCULAR_QUEUE_HPP_

#include "link_node.h"

template<class T>
class LinkedCircularQueue {
private:
	Node<T>* head;
	Node<T>* tail;
	unsigned int size_t;

	inline void range_check(void) const;

public:

	LinkedCircularQueue(void);

	LinkedCircularQueue(const LinkedCircularQueue& other);

	virtual ~LinkedCircularQueue(void);

	void offer(const T& element);

	const T& take(void);

	inline const T& peek(void) const;

	inline bool empty(void) const;

	inline unsigned int size(void) const;
};

template<class T>
LinkedCircularQueue<T>::LinkedCircularQueue(void) {
	head = tail = nullptr;
	size_t = 0;
}

template<class T>
LinkedCircularQueue<T>::LinkedCircularQueue(
		const LinkedCircularQueue<T>& otherQueue) {
	Node<T> *node;
	if (!otherQueue.empty()) {
		node = new Node<T>(otherQueue.head->getData(), nullptr);
		head = tail = node;
		tail->setNext(head);

		Node<T> *ptr = otherQueue.head->getNext();
		for (; ptr != otherQueue.head; ptr = ptr->getNext()) {
			node = new Node<T>(ptr->getData(), head);
			tail->setNext(node);
			tail = node;
		}
	}
	size_t = otherQueue.size_t;
}

template<class T>
LinkedCircularQueue<T>::~LinkedCircularQueue(void) {
	tail->setNext(nullptr);
	for (Node<T> *ptr = head; ptr != nullptr;) {
		head = ptr->getNext();
		delete ptr;
		ptr = head;
	}
}

template<class T>
inline unsigned int LinkedCircularQueue<T>::size(void) const {
	return size_t;
}

template<class T>
void LinkedCircularQueue<T>::offer(const T& data) {
	Node<T> *node = new Node<T>(data, head);

	if (size_t == 0) {
		tail = head = node;
	} else {
		tail->setNext(node);
		tail = node;
	}
	++size_t;
}

template<class T>
const T& LinkedCircularQueue<T>::take(void) {
	range_check();

	Node<T> *node = head;
	T& data = node->getData();
	if (size_t == 1) {
		head = tail = nullptr;
	} else {
		head = node->getNext();
		tail->setNext(head);
	}
	--size_t;
	delete node;
	return data;
}

template<class T>
inline const T& LinkedCircularQueue<T>::peek(void) const {
	range_check();
	return head->getData();
}

template<class T>
bool LinkedCircularQueue<T>::empty(void) const {
	return size_t == 0;
}

template<class T>
inline void LinkedCircularQueue<T>::range_check(void) const {
	if (size_t == 0) {
		throw std::logic_error("Queue was empty");
	}
}
#endif /* LINKED_CIRCULAR_QUEUE_HPP_ */
<|endoftext|>


<commit_before>#ifndef __CLITL_HPP__
#define __CLITL_HPP__

#include <cstddef>
#include <cstdio>
#include <locale>
#include <ostream>
#include <string>
#include <tuple>
#include <utility>

#ifdef UNIX
#include <sys/ioctl.h>
#include <termios.h>
#include <unistd.h>
#elif WIN32
#include <conio.h>
#include <Windows.h>
#endif

namespace clitl {
    /* Color class */
    enum class color {
#ifdef UNIX
        DEFAULT = 0,
        BLACK = 0,
        RED = 1,
        GREEN = 2,
        BROWN = 3,
        BLUE = 4,
        MAGENTA = 5,
        CYAN = 6,
        WHITE = 7,
#elif WIN32
        DEFAULT = 0x7,
        BLACK = 0x0,
        RED = 0x4,
        GREEN = 0x2,
        BROWN = 0x7, // Worthless
        BLUE = 0x1,
        MAGENTA = 0x7, // Worthless
        CYAN = 0x9,
        WHITE = 0x7,
#endif
    };

    /* Basic definitions and containers */
    typedef int coord_t;
    //typedef int colornum_t;

    template <typename coordT, typename charT,
        typename traits = std::char_traits<charT>, typename Alloc = std::allocator<charT> >
    class basic_cli_object {
        std::pair<coordT, coordT> origin;
        std::pair<coordT, coordT> endpoint;
        std::basic_string<charT, traits, Alloc> str;
        color foreground;
        color background;
    public:
        explicit basic_cli_object(
            const std::pair<coordT, coordT>& origin = std::pair<coordT, coordT>(0, 0),
            const std::pair<coordT, coordT>& endpoint = std::pair<coordT, coordT>(0, 0),
            const std::basic_string<charT, traits, Alloc>& str
                                            = std::basic_string<charT, traits, Alloc>(),
            const color& foreground = color::WHITE,
            const color& background = color::BLACK)
            : origin(origin), endpoint(endpoint), str(str),
                foreground(foreground), background(background) {}

        const basic_cli_object<coordT, charT>& set_origin(const std::pair<coordT, coordT>& coord)
        {
            origin = coord;
            return *this;
        }

        const basic_cli_object<coordT, charT>& set_endpoint(const std::pair<coordT, coordT>& coord)
        {
            endpoint = coord;
            return *this;
        }

        const basic_cli_object<coordT, charT>& set_string(const std::basic_string<charT, traits, Alloc>& stri)
        {
            str = stri;
            return *this;
        }

        const basic_cli_object<coordT, charT>& set_foreground(const color& foreg)
        {
            foreground = foreg;
            return *this;
        }

        const basic_cli_object<coordT, charT>& set_background(const color& backg)
        {
            background = backg;
            return *this;
        }

        const std::pair<coordT, coordT>& get_origin() const
        {
            return origin;
        }

        const std::pair<coordT, coordT>& get_endpoint() const
        {
            return endpoint;
        }

        const std::basic_string<charT, traits, Alloc>& get_string() const
        {
            return str;
        }

        const color& get_foreground() const
        {
            return foreground;
        }

        const color& get_background() const
        {
            return background;
        }
    };

    template <typename coordT, typename charT = char,
        typename traits = std::char_traits<charT>, typename Alloc = std::allocator<charT> >
    class rect : public basic_cli_object<coordT, charT, traits, Alloc> {
    public:
        explicit rect(
            const std::pair<coordT, coordT>& origin = std::pair<coordT, coordT>(0, 0),
            const std::pair<coordT, coordT>& endpoint = std::pair<coordT, coordT>(0, 0),
            const color& background = color::WHITE)
            : basic_cli_object<coordT, charT, traits, Alloc>(origin, endpoint,
                std::basic_string<charT, traits, Alloc>(" "), color::DEFAULT, background) {}
    };

    template <typename coordT, typename charT,
        typename traits = std::char_traits<charT>, typename Alloc = std::allocator<charT> >
        class coloredstring : public basic_cli_object<coordT, charT, traits, Alloc> {
    public:
        explicit coloredstring(
            const std::pair<coordT, coordT>& origin = std::pair<coordT, coordT>(0, 0),
            const std::pair<coordT, coordT>& endpoint = std::pair<coordT, coordT>(0, 0),
            const std::basic_string<charT, traits, Alloc>& str
            = std::basic_string<charT, traits, Alloc>(),
            const color& foreground = clitl::color::WHITE,
            const color& background = clitl::color::BLACK)
            : basic_cli_object<coordT, charT, traits, Alloc>(
                origin, endpoint, str, foreground, background) {}
        explicit coloredstring(
            const std::basic_string<charT, traits, Alloc>& str
            = std::basic_string<charT, traits, Alloc>(),
            const color& foreground = clitl::color::WHITE,
            const color& background = clitl::color::BLACK)
            : basic_cli_object<coordT, charT, traits, Alloc>(
                std::pair<coordT, coordT>(0, 0), std::pair<coordT, coordT>(0, 0),
                str, foreground, background) {}
    };

    /* Output buffer */
    template <typename charT, typename traits = std::char_traits<charT> >
    class basic_outbuf : public std::basic_streambuf<charT, traits> {
    protected:
        virtual typename traits::int_type
            overflow(typename traits::int_type c)
        {
            if (std::putchar(c) == EOF) {
                return traits::eof();
            }
            return traits::not_eof(c);
        }
    };

    typedef basic_outbuf<char> outbuf;
    typedef basic_outbuf<wchar_t> woutbuf;

    /* Output stream */
    template <typename charT, typename traits = std::char_traits<charT> >
    class basic_ostream : public std::basic_ostream<charT, traits> {
    public:
#ifdef UNIX
        struct winsize wsize;
#endif
#ifdef WIN32
        HANDLE termout_handle;
        CONSOLE_CURSOR_INFO termout_curinfo;
        CONSOLE_SCREEN_BUFFER_INFO termout_sbufinfo;
        CONSOLE_SCREEN_BUFFER_INFO termout_initial_sbufinfo;
#endif
        explicit basic_ostream(basic_outbuf<charT, traits>* sb)
            : std::basic_ostream<charT, traits>(sb)
        {
#ifdef UNIX
            wsize = { 0 };
#elif WIN32
            termout_handle = GetStdHandle(STD_OUTPUT_HANDLE);
            GetConsoleScreenBufferInfo(termout_handle, &termout_initial_sbufinfo);
#endif
        }

        basic_ostream<charT, traits>& movecursor(coord_t xpos, coord_t ypos)
        {
#ifdef UNIX
            *this << "\033[" << ypos << ";" << xpos << "f";
#elif WIN32
            COORD pos = { static_cast<SHORT>(xpos) - 1, static_cast<SHORT>(ypos) - 1 };
            SetConsoleCursorPosition(termout_handle, pos);
#endif
            return *this;
        }

        basic_ostream<charT, traits>& movecursor(const std::pair<coord_t, coord_t>& coord)
        {
            movecursor(coord.first, coord.second);
            return *this;
        }

        std::pair<coord_t, coord_t> screensize()
        {
            static coord_t column;
            static coord_t row;

#ifdef UNIX
            column = wsize.ws_col;
            row = wsize.ws_row;
#elif WIN32
            GetConsoleScreenBufferInfo(termout_handle, &termout_sbufinfo);
            column = static_cast<coord_t>(termout_sbufinfo.dwSize.X);
            row = static_cast<coord_t>(termout_sbufinfo.dwSize.Y);
#endif

            return std::pair<coord_t, coord_t>(column, row);
        }

        basic_ostream<charT, traits>& paintmode(color fgd, color bgd)
        {
#ifdef UNIX
            *this << "\033["
                << 30 + static_cast<int>(fgd)
                << ";"
                << 40 + static_cast<int>(bgd)
                << "m";
#elif WIN32
            SetConsoleTextAttribute(this->termout_handle,
                static_cast<WORD>(static_cast<int>(fgd)
                    + 0x10 * static_cast<int>(bgd)));
#endif
            return *this;
        }

        basic_ostream<charT, traits>& paintmode(nullptr_t nullp)
        {
            // Recovery mode
#ifdef UNIX
            os << "\033[0m";
#elif WIN32
            SetConsoleTextAttribute(termout_handle, termout_initial_sbufinfo.wAttributes);
#endif
            return *this;
        }

        basic_ostream<charT, traits>& operator<<
            (basic_ostream<charT, traits>& (*op)(basic_ostream<charT, traits>&))
        {
            return (*op)(*this);
        }
    };

    typedef basic_ostream<char> ostream;
    typedef basic_ostream<wchar_t> wostream;

    template <typename charT, typename traits>
    basic_ostream<charT, traits>& alternative_system_screenbuffer(basic_ostream<charT, traits>& os)
    {
#if UNIX
        os << "\033[?1049h"; // Use alternate screen buffer
#endif
        return os;
    }

    template <typename charT, typename traits>
    basic_ostream<charT, traits>& clear(basic_ostream<charT, traits>& os)
    {
#ifdef UNIX
        os << "\033[2J";
#elif WIN32
        COORD startpoint = { 0, 0 };
        DWORD dw;

        GetConsoleScreenBufferInfo(os.termout_handle, &os.termout_sbufinfo);
        FillConsoleOutputCharacterA(os.termout_handle, ' ',
            os.termout_sbufinfo.dwSize.X * os.termout_sbufinfo.dwSize.Y,
            startpoint, &dw);
        FillConsoleOutputAttribute(os.termout_handle,
            FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_BLUE,
            os.termout_sbufinfo.dwSize.X * os.termout_sbufinfo.dwSize.Y,
            startpoint, &dw);
#endif
        return os;
    }

    template <typename charT, typename traits>
    basic_ostream<charT, traits>& hide_cursor(basic_ostream<charT, traits>& os)
    {
#ifdef UNIX
        os << "\033[?25l"; // Hide cursor
#elif WIN32
    GetConsoleCursorInfo(os.termout_handle, &os.termout_curinfo);
    os.termout_curinfo.bVisible = 0;
    SetConsoleCursorInfo(os.termout_handle, &os.termout_curinfo);
#endif
        return os;
    }

    template <typename charT, typename traits>
    basic_ostream<charT, traits>& normal_system_screenbuffer(basic_ostream<charT, traits>& os)
    {
#if UNIX
        os << "\033[?1049l"; // Use normal screen buffer
#endif
        return os;
    }

    template <typename charT, typename traits>
    basic_ostream<charT, traits>& refresh(basic_ostream<charT, traits>& os)
    {
        std::fflush(stdout);
        return os;
    }

    template <typename charT, typename traits>
    basic_ostream<charT, traits>& show_cursor(basic_ostream<charT, traits>& os)
    {
#if UNIX
        os << "\033[?25h"; // Show cursor
#elif WIN32
    CONSOLE_CURSOR_INFO termout_curinfo;
    GetConsoleCursorInfo(os.termout_handle, &termout_curinfo);
    termout_curinfo.bVisible = 1;
    SetConsoleCursorInfo(os.termout_handle, &termout_curinfo);
#endif
        return os;
    }

    template <typename charT, typename traits>
    basic_ostream<charT, traits>& pre_process(basic_ostream<charT, traits>& os)
    {
        os << alternative_system_screenbuffer;
        os << hide_cursor;
        os << clear;
        return os;
    }

    template <typename charT, typename traits>
    basic_ostream<charT, traits>& post_process(basic_ostream<charT, traits>& os)
    {
        os.paintmode(color::WHITE, color::BLACK);
        os << clear;
        os << show_cursor;
        os.movecursor(1, 1);
        os.paintmode(nullptr);
        os << normal_system_screenbuffer;
        return os;
    }

    template <typename coordT, typename charT, typename traits, typename Alloc>
    basic_ostream<charT, traits>& operator<<
        (basic_ostream<charT, traits>& os,
            const coloredstring<coordT, charT, traits, Alloc>& cs)
    {
        os.paintmode(cs.get_foreground(), cs.get_background());
        os << cs.get_string().c_str();
        return os;
    }

    template <typename coordT, typename charT, typename traits, typename Alloc>
    basic_ostream<charT, traits>& operator<<
        (basic_ostream<charT, traits>& os, const rect<coordT, charT, traits, Alloc>& re)
    {
        for (int i = re.get_origin().first; i <= re.get_endpoint().first; ++i) {
            for (int j = re.get_origin().second; j <= re.get_endpoint().second; ++j) {
                os.movecursor(i, j);
                os << coloredstring<coordT, charT, traits, Alloc>(
                    re.get_string(), re.get_foreground(), re.get_background());
            }
        }
        return os;
    }

    /* Input buffer */

    /* Input stream */
    template <typename charT, typename traits = std::char_traits<charT> >
    class basic_istream : public std::basic_istream<charT, traits> {

    };

    typedef basic_istream<char> istream;
    typedef basic_istream<wchar_t> wistream;
}

#endif
<commit_msg>Complete the prototype of ostream<commit_after>#ifndef __CLITL_HPP__
#define __CLITL_HPP__

#include <cstddef>
#include <cstdio>
#include <locale>
#include <ostream>
#include <string>
#include <tuple>
#include <utility>

#ifdef UNIX
#include <sys/ioctl.h>
#include <termios.h>
#include <unistd.h>
#elif WIN32
#include <conio.h>
#include <Windows.h>
#endif

namespace clitl {
    /* Color class */
    enum class color {
#ifdef UNIX
        DEFAULT = 0,
        BLACK = 0,
        RED = 1,
        GREEN = 2,
        BROWN = 3,
        BLUE = 4,
        MAGENTA = 5,
        CYAN = 6,
        WHITE = 7,
#elif WIN32
        DEFAULT = 0x7,
        BLACK = 0x0,
        RED = 0x4,
        GREEN = 0x2,
        BROWN = 0x7, // Worthless
        BLUE = 0x1,
        MAGENTA = 0x7, // Worthless
        CYAN = 0x9,
        WHITE = 0x7,
#endif
    };

    /* Basic definitions and containers */
    typedef int coord_t;
    //typedef int colornum_t;

    template <typename coordT, typename charT,
        typename traits = std::char_traits<charT>, typename Alloc = std::allocator<charT> >
    class basic_cli_object {
        std::pair<coordT, coordT> origin;
        std::pair<coordT, coordT> endpoint;
        std::basic_string<charT, traits, Alloc> str;
        color foreground;
        color background;
    public:
        explicit basic_cli_object(
            const std::pair<coordT, coordT>& origin = std::pair<coordT, coordT>(0, 0),
            const std::pair<coordT, coordT>& endpoint = std::pair<coordT, coordT>(0, 0),
            const std::basic_string<charT, traits, Alloc>& str
                                            = std::basic_string<charT, traits, Alloc>(),
            const color& foreground = color::WHITE,
            const color& background = color::BLACK)
            : origin(origin), endpoint(endpoint), str(str),
                foreground(foreground), background(background) {}

        const basic_cli_object<coordT, charT>& set_origin(const std::pair<coordT, coordT>& coord)
        {
            origin = coord;
            return *this;
        }

        const basic_cli_object<coordT, charT>& set_endpoint(const std::pair<coordT, coordT>& coord)
        {
            endpoint = coord;
            return *this;
        }

        const basic_cli_object<coordT, charT>& set_string(const std::basic_string<charT, traits, Alloc>& stri)
        {
            str = stri;
            return *this;
        }

        const basic_cli_object<coordT, charT>& set_foreground(const color& foreg)
        {
            foreground = foreg;
            return *this;
        }

        const basic_cli_object<coordT, charT>& set_background(const color& backg)
        {
            background = backg;
            return *this;
        }

        const std::pair<coordT, coordT>& get_origin() const
        {
            return origin;
        }

        const std::pair<coordT, coordT>& get_endpoint() const
        {
            return endpoint;
        }

        const std::basic_string<charT, traits, Alloc>& get_string() const
        {
            return str;
        }

        const color& get_foreground() const
        {
            return foreground;
        }

        const color& get_background() const
        {
            return background;
        }
    };

    template <typename coordT, typename charT = char,
        typename traits = std::char_traits<charT>, typename Alloc = std::allocator<charT> >
    class rect : public basic_cli_object<coordT, charT, traits, Alloc> {
    public:
        explicit rect(
            const std::pair<coordT, coordT>& origin = std::pair<coordT, coordT>(0, 0),
            const std::pair<coordT, coordT>& endpoint = std::pair<coordT, coordT>(0, 0),
            const color& background = color::WHITE)
            : basic_cli_object<coordT, charT, traits, Alloc>(origin, endpoint,
                std::basic_string<charT, traits, Alloc>(" "), color::DEFAULT, background) {}
    };

    template <typename coordT, typename charT,
        typename traits = std::char_traits<charT>, typename Alloc = std::allocator<charT> >
        class coloredstring : public basic_cli_object<coordT, charT, traits, Alloc> {
    public:
        explicit coloredstring(
            const std::pair<coordT, coordT>& origin = std::pair<coordT, coordT>(0, 0),
            const std::pair<coordT, coordT>& endpoint = std::pair<coordT, coordT>(0, 0),
            const std::basic_string<charT, traits, Alloc>& str
            = std::basic_string<charT, traits, Alloc>(),
            const color& foreground = clitl::color::WHITE,
            const color& background = clitl::color::BLACK)
            : basic_cli_object<coordT, charT, traits, Alloc>(
                origin, endpoint, str, foreground, background) {}
        explicit coloredstring(
            const std::basic_string<charT, traits, Alloc>& str
            = std::basic_string<charT, traits, Alloc>(),
            const color& foreground = clitl::color::WHITE,
            const color& background = clitl::color::BLACK)
            : basic_cli_object<coordT, charT, traits, Alloc>(
                std::pair<coordT, coordT>(0, 0), std::pair<coordT, coordT>(0, 0),
                str, foreground, background) {}
    };

    /* Output buffer */
    template <typename charT, typename traits = std::char_traits<charT> >
    class basic_outbuf : public std::basic_streambuf<charT, traits> {
    protected:
        virtual typename traits::int_type
            overflow(typename traits::int_type c)
        {
            if (std::putchar(c) == EOF) {
                return traits::eof();
            }
            return traits::not_eof(c);
        }
    };

    typedef basic_outbuf<char> outbuf;
    typedef basic_outbuf<wchar_t> woutbuf;

    /* Output stream */
    template <typename charT, typename traits = std::char_traits<charT> >
    class basic_ostream : public std::basic_ostream<charT, traits> {
    public:
#ifdef UNIX
        struct winsize wsize;
#endif
#ifdef WIN32
        HANDLE termout_handle;
        CONSOLE_CURSOR_INFO termout_curinfo;
        CONSOLE_SCREEN_BUFFER_INFO termout_sbufinfo;
        CONSOLE_SCREEN_BUFFER_INFO termout_initial_sbufinfo;
#endif
        explicit basic_ostream(basic_outbuf<charT, traits>* sb)
            : std::basic_ostream<charT, traits>(sb)
        {
#ifdef UNIX
            wsize = { 0 };
#elif WIN32
            termout_handle = GetStdHandle(STD_OUTPUT_HANDLE);
            GetConsoleScreenBufferInfo(termout_handle, &termout_initial_sbufinfo);
#endif
        }

        basic_ostream<charT, traits>& movecursor(coord_t xpos, coord_t ypos)
        {
#ifdef UNIX
            *this << "\033[" << ypos << ";" << xpos << "f";
#elif WIN32
            COORD pos = { static_cast<SHORT>(xpos) - 1, static_cast<SHORT>(ypos) - 1 };
            SetConsoleCursorPosition(termout_handle, pos);
#endif
            return *this;
        }

        basic_ostream<charT, traits>& movecursor(const std::pair<coord_t, coord_t>& coord)
        {
            movecursor(coord.first, coord.second);
            return *this;
        }

        std::pair<coord_t, coord_t> screensize()
        {
            static coord_t column;
            static coord_t row;

#ifdef UNIX
            column = wsize.ws_col;
            row = wsize.ws_row;
#elif WIN32
            GetConsoleScreenBufferInfo(termout_handle, &termout_sbufinfo);
            column = static_cast<coord_t>(termout_sbufinfo.dwSize.X);
            row = static_cast<coord_t>(termout_sbufinfo.dwSize.Y);
#endif

            return std::pair<coord_t, coord_t>(column, row);
        }

        basic_ostream<charT, traits>& paintmode(color fgd, color bgd)
        {
#ifdef UNIX
            *this << "\033["
                << 30 + static_cast<int>(fgd)
                << ";"
                << 40 + static_cast<int>(bgd)
                << "m";
#elif WIN32
            SetConsoleTextAttribute(this->termout_handle,
                static_cast<WORD>(static_cast<int>(fgd)
                    + 0x10 * static_cast<int>(bgd)));
#endif
            return *this;
        }

        basic_ostream<charT, traits>& paintmode(nullptr_t nullp)
        {
            // Recovery mode
#ifdef UNIX
            os << "\033[0m";
#elif WIN32
            SetConsoleTextAttribute(termout_handle, termout_initial_sbufinfo.wAttributes);
#endif
            return *this;
        }

        basic_ostream<charT, traits>& operator<<
            (basic_ostream<charT, traits>& (*op)(basic_ostream<charT, traits>&))
        {
            return (*op)(*this);
        }
    };

    typedef basic_ostream<char> ostream;
    typedef basic_ostream<wchar_t> wostream;

    template <typename charT, typename traits>
    basic_ostream<charT, traits>& alternative_system_screenbuffer(basic_ostream<charT, traits>& os)
    {
#if UNIX
        os << "\033[?1049h"; // Use alternate screen buffer
#endif
        return os;
    }

    template <typename charT, typename traits>
    basic_ostream<charT, traits>& clear(basic_ostream<charT, traits>& os)
    {
#ifdef UNIX
        os << "\033[2J";
#elif WIN32
        COORD startpoint = { 0, 0 };
        DWORD dw;

        GetConsoleScreenBufferInfo(os.termout_handle, &os.termout_sbufinfo);
        FillConsoleOutputCharacterA(os.termout_handle, ' ',
            os.termout_sbufinfo.dwSize.X * os.termout_sbufinfo.dwSize.Y,
            startpoint, &dw);
        FillConsoleOutputAttribute(os.termout_handle,
            FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_BLUE,
            os.termout_sbufinfo.dwSize.X * os.termout_sbufinfo.dwSize.Y,
            startpoint, &dw);
#endif
        return os;
    }

    template <typename charT, typename traits>
    basic_ostream<charT, traits>& hide_cursor(basic_ostream<charT, traits>& os)
    {
#ifdef UNIX
        os << "\033[?25l"; // Hide cursor
#elif WIN32
        GetConsoleCursorInfo(os.termout_handle, &os.termout_curinfo);
        os.termout_curinfo.bVisible = 0;
        SetConsoleCursorInfo(os.termout_handle, &os.termout_curinfo);
#endif
        return os;
    }

    template <typename charT, typename traits>
    basic_ostream<charT, traits>& normal_system_screenbuffer(basic_ostream<charT, traits>& os)
    {
#if UNIX
        os << "\033[?1049l"; // Use normal screen buffer
#endif
        return os;
    }

    template <typename charT, typename traits>
    basic_ostream<charT, traits>& refresh(basic_ostream<charT, traits>& os)
    {
        std::fflush(stdout);
        return os;
    }

    template <typename charT, typename traits>
    basic_ostream<charT, traits>& show_cursor(basic_ostream<charT, traits>& os)
    {
#if UNIX
        os << "\033[?25h"; // Show cursor
#elif WIN32
        GetConsoleCursorInfo(os.termout_handle, &os.termout_curinfo);
        os.termout_curinfo.bVisible = 1;
        SetConsoleCursorInfo(os.termout_handle, &os.termout_curinfo);
#endif
        return os;
    }

    template <typename charT, typename traits>
    basic_ostream<charT, traits>& pre_process(basic_ostream<charT, traits>& os)
    {
        os << alternative_system_screenbuffer;
        os << hide_cursor;
        os << clear;
        return os;
    }

    template <typename charT, typename traits>
    basic_ostream<charT, traits>& post_process(basic_ostream<charT, traits>& os)
    {
        os << clear;
        os << show_cursor;
        os.movecursor(1, 1);
        os.paintmode(nullptr);
        os << normal_system_screenbuffer;
        return os;
    }

    template <typename coordT, typename charT, typename traits, typename Alloc>
    basic_ostream<charT, traits>& operator<<
        (basic_ostream<charT, traits>& os,
            const coloredstring<coordT, charT, traits, Alloc>& cs)
    {
        os.paintmode(cs.get_foreground(), cs.get_background());
        os << cs.get_string().c_str();
        return os;
    }

    template <typename coordT, typename charT, typename traits, typename Alloc>
    basic_ostream<charT, traits>& operator<<
        (basic_ostream<charT, traits>& os, const rect<coordT, charT, traits, Alloc>& re)
    {
        for (int i = re.get_origin().first; i <= re.get_endpoint().first; ++i) {
            for (int j = re.get_origin().second; j <= re.get_endpoint().second; ++j) {
                os.movecursor(i, j);
                os << coloredstring<coordT, charT, traits, Alloc>(
                    re.get_string(), re.get_foreground(), re.get_background());
            }
        }
        return os;
    }

    /* Input buffer */

    /* Input stream */
    /* Keeping it for further update

    template <typename charT, typename traits = std::char_traits<charT> >
    class basic_istream : public std::basic_istream<charT, traits> {

    };

    typedef basic_istream<char> istream;
    typedef basic_istream<wchar_t> wistream;
    */
}

#endif
<|endoftext|>