<commit_before>/**************************************************************************
**
** This file is part of Qt Creator
**
** Copyright (c) 2012 Nokia Corporation and/or its subsidiary(-ies).
**
** Contact: Nokia Corporation (qt-info@nokia.com)
**
**
** GNU Lesser General Public License Usage
**
** This file may be used under the terms of the GNU Lesser General Public
** License version 2.1 as published by the Free Software Foundation and
** appearing in the file LICENSE.LGPL included in the packaging of this file.
** Please review the following information to ensure the GNU Lesser General
** Public License version 2.1 requirements will be met:
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** Other Usage
**
** Alternatively, this file may be used in accordance with the terms and
** conditions contained in a signed written agreement between you and Nokia.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
**
**************************************************************************/

#include "fileiconprovider.h"
#include "mimedatabase.h"

#include <utils/qtcassert.h>

#include <QApplication>
#include <QStyle>
#include <QPainter>
#include <QFileInfo>
#include <QPair>
#include <QDebug>

#include <QFileIconProvider>
#include <QIcon>
#include <QStyle>

/*!
  \class Core::FileIconProvider

  Provides icons based on file suffixes with the ability to overwrite system
  icons for specific subtypes. Implements the QFileIconProvider interface
  and can therefore be used for QFileSystemModel.

  Note: Registering overlay icons currently completely replaces the system
        icon and is therefore not recommended on platforms that have their
        own overlay icon handling (Mac/Windows).

  The class is a singleton: It's instance can be accessed via the static instance() method.
  Plugins can register custom icons via registerIconSuffix(), and retrieve icons via the icon()
  method.
  The instance is explicitly deleted by the core plugin for destruction order reasons.
  */

// Cache icons in a list of pairs suffix/icon which should be faster than
// hashes for small lists.

enum { debug = 0 };

typedef QPair<QString, QIcon> StringIconPair;
typedef QList<StringIconPair> StringIconPairList;

// Helper to find an icon by suffix in a list of pairs for const/non-const-iterators.

template <class StringIconPairListIterator>
inline StringIconPairListIterator
findBySuffix(const QString &suffix,
             StringIconPairListIterator iter,
             const StringIconPairListIterator &end)
{
    for (; iter != end; ++iter)
        if ((*iter).first == suffix)
            return iter;
    return end;
}

namespace Core {

struct FileIconProviderPrivate {
    FileIconProviderPrivate();

    // Mapping of file suffix to icon.
    StringIconPairList m_cache;

    QIcon m_unknownFileIcon;

    // singleton pattern
    static FileIconProvider *m_instance;
};

FileIconProviderPrivate::FileIconProviderPrivate() :
    m_unknownFileIcon(qApp->style()->standardIcon(QStyle::SP_FileIcon))
{
}

FileIconProvider *FileIconProviderPrivate::m_instance = 0;

// FileIconProvider

FileIconProvider::FileIconProvider() :
    d(new FileIconProviderPrivate)
{
    FileIconProviderPrivate::m_instance = this;
}

FileIconProvider::~FileIconProvider()
{
    FileIconProviderPrivate::m_instance = 0;
    delete d;
}

/*!
  Returns the icon associated with the file suffix in fileInfo. If there is none,
  the default icon of the operating system is returned.
  */

QIcon FileIconProvider::icon(const QFileInfo &fileInfo) const
{
    typedef StringIconPairList::const_iterator CacheConstIterator;

    if (debug)
        qDebug() << "FileIconProvider::icon" << fileInfo.absoluteFilePath();
    // Check for cached overlay icons by file suffix.
    if (!d->m_cache.isEmpty() && !fileInfo.isDir()) {
        const QString suffix = fileInfo.suffix();
        if (!suffix.isEmpty()) {
            const CacheConstIterator it = findBySuffix(suffix, d->m_cache.constBegin(), d->m_cache.constEnd());
            if (it != d->m_cache.constEnd())
                return (*it).second;
        }
    }
    // Get icon from OS.
#if defined(Q_WS_WIN) || defined(Q_OS_MAC)
    return QFileIconProvider::icon(fileInfo);
#else
    // File icons are unknown on linux systems.
    return (fileInfo.isDir()) ?
           QFileIconProvider::icon(fileInfo) :
           d->m_unknownFileIcon;
#endif
}

/*!
  Creates a pixmap with baseicon at size and overlays overlayIcon over it.
  See platform note in class documentation about recommended usage.
  */
QPixmap FileIconProvider::overlayIcon(QStyle::StandardPixmap baseIcon, const QIcon &overlayIcon, const QSize &size)
{
    QPixmap iconPixmap = qApp->style()->standardIcon(baseIcon).pixmap(size);
    QPainter painter(&iconPixmap);
    painter.drawPixmap(0, 0, overlayIcon.pixmap(size));
    painter.end();
    return iconPixmap;
}

/*!
  Registers an icon for a given suffix, overlaying the system file icon.
  See platform note in class documentation about recommended usage.
  */
void FileIconProvider::registerIconOverlayForSuffix(const QIcon &icon,
                                                    const QString &suffix)
{
    typedef StringIconPairList::iterator CacheIterator;

    if (debug)
        qDebug() << "FileIconProvider::registerIconOverlayForSuffix" << suffix;

    QTC_ASSERT(!icon.isNull() && !suffix.isEmpty(), return)

    const QPixmap fileIconPixmap = overlayIcon(QStyle::SP_FileIcon, icon, QSize(16, 16));
    // replace old icon, if it exists
    const CacheIterator it = findBySuffix(suffix, d->m_cache.begin(), d->m_cache.end());
    if (it == d->m_cache.end()) {
        d->m_cache.append(StringIconPair(suffix, fileIconPixmap));
    } else {
       (*it).second = fileIconPixmap;
    }
}

/*!
  Registers an icon for all the suffixes of a given mime type, overlaying the system file icon.
  */
void FileIconProvider::registerIconOverlayForMimeType(const QIcon &icon, const MimeType &mimeType)
{
    foreach (const QString &suffix, mimeType.suffixes())
        registerIconOverlayForSuffix(icon, suffix);
}

/*!
  Returns the sole instance of FileIconProvider.
  */

FileIconProvider *FileIconProvider::instance()
{
    if (!FileIconProviderPrivate::m_instance)
        FileIconProviderPrivate::m_instance = new FileIconProvider;
    return FileIconProviderPrivate::m_instance;
}

} // namespace core
<commit_msg>FileIconProvider: Fix doc<commit_after>/**************************************************************************
**
** This file is part of Qt Creator
**
** Copyright (c) 2012 Nokia Corporation and/or its subsidiary(-ies).
**
** Contact: Nokia Corporation (qt-info@nokia.com)
**
**
** GNU Lesser General Public License Usage
**
** This file may be used under the terms of the GNU Lesser General Public
** License version 2.1 as published by the Free Software Foundation and
** appearing in the file LICENSE.LGPL included in the packaging of this file.
** Please review the following information to ensure the GNU Lesser General
** Public License version 2.1 requirements will be met:
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** Other Usage
**
** Alternatively, this file may be used in accordance with the terms and
** conditions contained in a signed written agreement between you and Nokia.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
**
**************************************************************************/

#include "fileiconprovider.h"
#include "mimedatabase.h"

#include <utils/qtcassert.h>

#include <QApplication>
#include <QStyle>
#include <QPainter>
#include <QFileInfo>
#include <QPair>
#include <QDebug>

#include <QFileIconProvider>
#include <QIcon>
#include <QStyle>

/*!
  \class Core::FileIconProvider

  Provides icons based on file suffixes with the ability to overwrite system
  icons for specific subtypes. Implements the QFileIconProvider interface
  and can therefore be used for QFileSystemModel.

  Note: Registering overlay icons currently completely replaces the system
        icon and is therefore not recommended on platforms that have their
        own overlay icon handling (Mac/Windows).

  The class is a singleton: It's instance can be accessed via the static instance() method.
  Plugins can register custom overlay icons via registerIconOverlayForSuffix(), and
  retrieve icons via the icon() method.
  The instance is explicitly deleted by the core plugin for destruction order reasons.
  */

// Cache icons in a list of pairs suffix/icon which should be faster than
// hashes for small lists.

enum { debug = 0 };

typedef QPair<QString, QIcon> StringIconPair;
typedef QList<StringIconPair> StringIconPairList;

// Helper to find an icon by suffix in a list of pairs for const/non-const-iterators.

template <class StringIconPairListIterator>
inline StringIconPairListIterator
findBySuffix(const QString &suffix,
             StringIconPairListIterator iter,
             const StringIconPairListIterator &end)
{
    for (; iter != end; ++iter)
        if ((*iter).first == suffix)
            return iter;
    return end;
}

namespace Core {

struct FileIconProviderPrivate {
    FileIconProviderPrivate();

    // Mapping of file suffix to icon.
    StringIconPairList m_cache;

    QIcon m_unknownFileIcon;

    // singleton pattern
    static FileIconProvider *m_instance;
};

FileIconProviderPrivate::FileIconProviderPrivate() :
    m_unknownFileIcon(qApp->style()->standardIcon(QStyle::SP_FileIcon))
{
}

FileIconProvider *FileIconProviderPrivate::m_instance = 0;

// FileIconProvider

FileIconProvider::FileIconProvider() :
    d(new FileIconProviderPrivate)
{
    FileIconProviderPrivate::m_instance = this;
}

FileIconProvider::~FileIconProvider()
{
    FileIconProviderPrivate::m_instance = 0;
    delete d;
}

/*!
  Returns the icon associated with the file suffix in fileInfo. If there is none,
  the default icon of the operating system is returned.
  */

QIcon FileIconProvider::icon(const QFileInfo &fileInfo) const
{
    typedef StringIconPairList::const_iterator CacheConstIterator;

    if (debug)
        qDebug() << "FileIconProvider::icon" << fileInfo.absoluteFilePath();
    // Check for cached overlay icons by file suffix.
    if (!d->m_cache.isEmpty() && !fileInfo.isDir()) {
        const QString suffix = fileInfo.suffix();
        if (!suffix.isEmpty()) {
            const CacheConstIterator it = findBySuffix(suffix, d->m_cache.constBegin(), d->m_cache.constEnd());
            if (it != d->m_cache.constEnd())
                return (*it).second;
        }
    }
    // Get icon from OS.
#if defined(Q_WS_WIN) || defined(Q_OS_MAC)
    return QFileIconProvider::icon(fileInfo);
#else
    // File icons are unknown on linux systems.
    return (fileInfo.isDir()) ?
           QFileIconProvider::icon(fileInfo) :
           d->m_unknownFileIcon;
#endif
}

/*!
  Creates a pixmap with baseicon at size and overlays overlayIcon over it.
  See platform note in class documentation about recommended usage.
  */
QPixmap FileIconProvider::overlayIcon(QStyle::StandardPixmap baseIcon, const QIcon &overlayIcon, const QSize &size)
{
    QPixmap iconPixmap = qApp->style()->standardIcon(baseIcon).pixmap(size);
    QPainter painter(&iconPixmap);
    painter.drawPixmap(0, 0, overlayIcon.pixmap(size));
    painter.end();
    return iconPixmap;
}

/*!
  Registers an icon for a given suffix, overlaying the system file icon.
  See platform note in class documentation about recommended usage.
  */
void FileIconProvider::registerIconOverlayForSuffix(const QIcon &icon,
                                                    const QString &suffix)
{
    typedef StringIconPairList::iterator CacheIterator;

    if (debug)
        qDebug() << "FileIconProvider::registerIconOverlayForSuffix" << suffix;

    QTC_ASSERT(!icon.isNull() && !suffix.isEmpty(), return)

    const QPixmap fileIconPixmap = overlayIcon(QStyle::SP_FileIcon, icon, QSize(16, 16));
    // replace old icon, if it exists
    const CacheIterator it = findBySuffix(suffix, d->m_cache.begin(), d->m_cache.end());
    if (it == d->m_cache.end()) {
        d->m_cache.append(StringIconPair(suffix, fileIconPixmap));
    } else {
       (*it).second = fileIconPixmap;
    }
}

/*!
  Registers an icon for all the suffixes of a given mime type, overlaying the system file icon.
  */
void FileIconProvider::registerIconOverlayForMimeType(const QIcon &icon, const MimeType &mimeType)
{
    foreach (const QString &suffix, mimeType.suffixes())
        registerIconOverlayForSuffix(icon, suffix);
}

/*!
  Returns the sole instance of FileIconProvider.
  */

FileIconProvider *FileIconProvider::instance()
{
    if (!FileIconProviderPrivate::m_instance)
        FileIconProviderPrivate::m_instance = new FileIconProvider;
    return FileIconProviderPrivate::m_instance;
}

} // namespace core
<|endoftext|>


<commit_before>#include "synchronization/AbstractDataHistory.hpp"
#include "synchronization/AbstractConnection.hpp"

namespace Synchronization
{

    AbstractDataHistory::AbstractDataHistory(const Initialization::HistoryPlan& in)
    : _history(),
      _inputHistory()
    {
    }

    void AbstractDataHistory::addFmu(FMI::AbstractFmu* fmu, std::vector<ConnectionSPtr> & connList)
    {
        if(_knownFmus.insert(fmu->getFmuName()).second)
        {
            if(_history.size() < fmu->getLocalId()+1)
                _history.resize(fmu->getLocalId()+1,RingBufferSubHistory(Interpolation(),fmu->getValues(FMI::ReferenceContainerType::ALL)));
            for(ConnectionSPtr & con : connList)
            {
                if(_inputHistory.size() < con->getLocalId()+1)
                    _inputHistory.resize(con->getLocalId()+1,RingBufferSubHistory(Interpolation(),fmu->getValues(FMI::ReferenceContainerType::ALL)));
            }
        }
        else
        {
            LOGGER_WRITE("DataHistory: FMU " + fmu->getFmuName() + " already registered.", Util::LC_LOADER, Util::LL_ERROR);
            throw std::runtime_error("AbstractDahistory initialization fail.");
        }
    }

    const RingBufferSubHistory & AbstractDataHistory::getInputHistory(size_type idInputSubhistory) const
    {
        return _inputHistory[idInputSubhistory];
    }

    bool_type AbstractDataHistory::insertInputs(const HistoryEntry & in, size_type conId)
    {
        return _inputHistory[conId].insert(in);
    }

    size_type AbstractDataHistory::size() const
    {
        return _history.size();
    }

    bool_type AbstractDataHistory::insert(const HistoryEntry & in, size_type fmuId, WriteInfo write)
    {
        //LOGGER_WRITE("Insert " + to_string(in.getTime()) + " into history " + to_string(fmuId),Util::LC_SOLVER,Util::LL_DEBUG);
        return _history[fmuId].insert(in);
    }

    void AbstractDataHistory::deleteOlderThan(real_type in, size_type id)
    {
        HistoryEntry tmp(in);
        _history[id].deleteOlderThan(tmp);
    }

    void AbstractDataHistory::createInputHistory(const std::list<shared_ptr<Initialization::ConnectionPlan> > & connections)
    {
        for(const auto& cp : connections)
        {
            _inputHistory.push_back(RingBufferSubHistory(Interpolation(),cp->inputMapping.getPackedValueCollection()));
        }
    }

} /* namespace Synchronization */

<commit_msg>Correct spelling issue<commit_after>#include "synchronization/AbstractDataHistory.hpp"
#include "synchronization/AbstractConnection.hpp"

namespace Synchronization
{

    AbstractDataHistory::AbstractDataHistory(const Initialization::HistoryPlan& in)
    : _history(),
      _inputHistory()
    {
    }

    void AbstractDataHistory::addFmu(FMI::AbstractFmu* fmu, std::vector<ConnectionSPtr> & connList)
    {
        if(_knownFmus.insert(fmu->getFmuName()).second)
        {
            if(_history.size() < fmu->getLocalId()+1)
                _history.resize(fmu->getLocalId()+1,RingBufferSubHistory(Interpolation(),fmu->getValues(FMI::ReferenceContainerType::ALL)));
            for(ConnectionSPtr & con : connList)
            {
                if(_inputHistory.size() < con->getLocalId()+1)
                    _inputHistory.resize(con->getLocalId()+1,RingBufferSubHistory(Interpolation(),fmu->getValues(FMI::ReferenceContainerType::ALL)));
            }
        }
        else
        {
            LOGGER_WRITE("DataHistory: FMU " + fmu->getFmuName() + " already registered.", Util::LC_LOADER, Util::LL_ERROR);
            throw std::runtime_error("AbstractDataHistory initialization fail.");
        }
    }

    const RingBufferSubHistory & AbstractDataHistory::getInputHistory(size_type idInputSubhistory) const
    {
        return _inputHistory[idInputSubhistory];
    }

    bool_type AbstractDataHistory::insertInputs(const HistoryEntry & in, size_type conId)
    {
        return _inputHistory[conId].insert(in);
    }

    size_type AbstractDataHistory::size() const
    {
        return _history.size();
    }

    bool_type AbstractDataHistory::insert(const HistoryEntry & in, size_type fmuId, WriteInfo write)
    {
        //LOGGER_WRITE("Insert " + to_string(in.getTime()) + " into history " + to_string(fmuId),Util::LC_SOLVER,Util::LL_DEBUG);
        return _history[fmuId].insert(in);
    }

    void AbstractDataHistory::deleteOlderThan(real_type in, size_type id)
    {
        HistoryEntry tmp(in);
        _history[id].deleteOlderThan(tmp);
    }

    void AbstractDataHistory::createInputHistory(const std::list<shared_ptr<Initialization::ConnectionPlan> > & connections)
    {
        for(const auto& cp : connections)
        {
            _inputHistory.push_back(RingBufferSubHistory(Interpolation(),cp->inputMapping.getPackedValueCollection()));
        }
    }

} /* namespace Synchronization */

<|endoftext|>


<commit_before>#ifndef _SDD_TOOLS_SERIALIZATION_HH_
#define _SDD_TOOLS_SERIALIZATION_HH_

#include <iosfwd>
#include <tuple>

#include <cereal/types/forward_list.hpp>
#include <cereal/types/unordered_map.hpp>
#include <cereal/types/utility.hpp>

#include "sdd/manager.hh"
#include "sdd/mem/unique_table.hh"
#include "sdd/tools/arcs.hh"
#include "sdd/tools/nodes.hh"
#include "sdd/tools/sdd_statistics.hh"
#include "sdd/tools/size.hh"

namespace sdd { namespace mem { namespace /* anonymous */ {

/*------------------------------------------------------------------------------------------------*/

template<class Archive>
void
save(Archive& archive, const unique_table_statistics& s)
{
  archive( cereal::make_nvp("#", static_cast<unsigned int>(s.size))
         , cereal::make_nvp("# peak", static_cast<unsigned int>(s.peak))
         , cereal::make_nvp("# accesses", static_cast<unsigned int>(s.access))
         , cereal::make_nvp("# hits", static_cast<unsigned int>(s.hits))
         , cereal::make_nvp("# misses", static_cast<unsigned int>(s.misses))
         , cereal::make_nvp("load factor", static_cast<unsigned int>(s.load_factor))
         );
}

/*------------------------------------------------------------------------------------------------*/

template<class Archive>
void
save(Archive& archive, const cache_statistics::round& r)
{
  archive( cereal::make_nvp("# hits", static_cast<unsigned int>(r.hits))
         , cereal::make_nvp("# misses", static_cast<unsigned int>(r.misses))
         , cereal::make_nvp("# filtered", static_cast<unsigned int>(r.filtered))
         );
}

/*------------------------------------------------------------------------------------------------*/

template<class Archive>
void
save(Archive& archive, const cache_statistics& s)
{
  archive( cereal::make_nvp("# cleanup", static_cast<unsigned int>(s.cleanups()))
         , cereal::make_nvp("total", s.total())
         , cereal::make_nvp("rounds", s.rounds)
         );
}

/*------------------------------------------------------------------------------------------------*/

}} // namespace mem::anonymous

/*------------------------------------------------------------------------------------------------*/

template<typename C, typename Archive>
void
save(Archive& archive, const manager<C>& m)
{
  archive( cereal::make_nvp("SDD unique table", m.sdd_stats())
         , cereal::make_nvp("SDD differences cache", m.sdd_difference_cache_stats())
         , cereal::make_nvp("SDD intersections cache", m.sdd_intersection_cache_stats())
         , cereal::make_nvp("SDD sums cache", m.sdd_sum_cache_stats())
         , cereal::make_nvp("hom unique table", m.hom_stats())
         , cereal::make_nvp("hom cache", m.hom_cache_stats())
         );
}

/*------------------------------------------------------------------------------------------------*/

namespace tools {

template<typename C, typename Archive>
void
save(Archive& archive, const sdd_statistics<C>& stats)
{
  archive( cereal::make_nvp("bytes", static_cast<unsigned int>(stats.bytes))
         , cereal::make_nvp("flat nodes", stats.all_nodes.first)
         , cereal::make_nvp("hierarchical nodes", stats.all_nodes.second)
         , cereal::make_nvp("flat arcs", stats.all_arcs.first)
         , cereal::make_nvp("hierarchical arcs", stats.all_arcs.second)
         , cereal::make_nvp("arcs frequency", stats.frequency)
         );
}

/*------------------------------------------------------------------------------------------------*/

}} // namespace sdd::tools

#endif // _SDD_TOOLS_SERIALIZATION_HH_
<commit_msg>Fix JSPN output now that cereal behaves correctly for 64 bits types.<commit_after>#ifndef _SDD_TOOLS_SERIALIZATION_HH_
#define _SDD_TOOLS_SERIALIZATION_HH_

#include <iosfwd>
#include <tuple>

#include <cereal/types/forward_list.hpp>
#include <cereal/types/unordered_map.hpp>
#include <cereal/types/utility.hpp>

#include "sdd/manager.hh"
#include "sdd/mem/unique_table.hh"
#include "sdd/tools/arcs.hh"
#include "sdd/tools/nodes.hh"
#include "sdd/tools/sdd_statistics.hh"
#include "sdd/tools/size.hh"

namespace sdd { namespace mem { namespace /* anonymous */ {

/*------------------------------------------------------------------------------------------------*/

template<class Archive>
void
save(Archive& archive, const unique_table_statistics& s)
{
  archive( cereal::make_nvp("#", s.size)
         , cereal::make_nvp("# peak", s.peak)
         , cereal::make_nvp("# accesses", s.access)
         , cereal::make_nvp("# hits", s.hits)
         , cereal::make_nvp("# misses", s.misses)
         , cereal::make_nvp("load factor", s.load_factor)
         );
}

/*------------------------------------------------------------------------------------------------*/

template<class Archive>
void
save(Archive& archive, const cache_statistics::round& r)
{
  archive( cereal::make_nvp("# hits", r.hits)
         , cereal::make_nvp("# misses", r.misses)
         , cereal::make_nvp("# filtered", r.filtered)
         );
}

/*------------------------------------------------------------------------------------------------*/

template<class Archive>
void
save(Archive& archive, const cache_statistics& s)
{
  archive( cereal::make_nvp("# cleanup", s.cleanups())
         , cereal::make_nvp("total", s.total())
         , cereal::make_nvp("rounds", s.rounds)
         );
}

/*------------------------------------------------------------------------------------------------*/

}} // namespace mem::anonymous

/*------------------------------------------------------------------------------------------------*/

template<typename C, typename Archive>
void
save(Archive& archive, const manager<C>& m)
{
  archive( cereal::make_nvp("SDD unique table", m.sdd_stats())
         , cereal::make_nvp("SDD differences cache", m.sdd_difference_cache_stats())
         , cereal::make_nvp("SDD intersections cache", m.sdd_intersection_cache_stats())
         , cereal::make_nvp("SDD sums cache", m.sdd_sum_cache_stats())
         , cereal::make_nvp("hom unique table", m.hom_stats())
         , cereal::make_nvp("hom cache", m.hom_cache_stats())
         );
}

/*------------------------------------------------------------------------------------------------*/

namespace tools {

template<typename C, typename Archive>
void
save(Archive& archive, const sdd_statistics<C>& stats)
{
  archive( cereal::make_nvp("bytes", stats.bytes)
         , cereal::make_nvp("flat nodes", stats.all_nodes.first)
         , cereal::make_nvp("hierarchical nodes", stats.all_nodes.second)
         , cereal::make_nvp("flat arcs", stats.all_arcs.first)
         , cereal::make_nvp("hierarchical arcs", stats.all_arcs.second)
         , cereal::make_nvp("arcs frequency", stats.frequency)
         );
}

/*------------------------------------------------------------------------------------------------*/

}} // namespace sdd::tools

#endif // _SDD_TOOLS_SERIALIZATION_HH_
<|endoftext|>


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

  Program:   Visualization Toolkit
  Module:    vtkNewickTreeReader.cxx

  Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
  All rights reserved.
  See Copyright.txt or http://www.kitware.com/Copyright.htm for details.

     This software is distributed WITHOUT ANY WARRANTY; without even
     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
     PURPOSE.  See the above copyright notice for more information.

=========================================================================*/
#include "vtkNewickTreeReader.h"

#include "vtkByteSwap.h"
#include "vtkCellArray.h"
#include "vtkDataSetAttributes.h"
#include "vtkDoubleArray.h"
#include "vtkFieldData.h"
#include "vtkNew.h"
#include "vtkTree.h"
#include "vtkTreeDFSIterator.h"
#include "vtkInformation.h"
#include "vtkInformationVector.h"
#include "vtkMutableDirectedGraph.h"
#include "vtkObjectFactory.h"
#include "vtkStreamingDemandDrivenPipeline.h"
#include "vtkStringArray.h"

#include <iostream>
#include <fstream>

vtkStandardNewMacro(vtkNewickTreeReader);

#ifdef read
#undef read
#endif

//----------------------------------------------------------------------------
vtkNewickTreeReader::vtkNewickTreeReader()
{
  vtkTree *output = vtkTree::New();
  this->SetOutput(output);
  // Releasing data for pipeline parallism.
  // Filters will know it is empty.
  output->ReleaseData();
  output->Delete();
}

//----------------------------------------------------------------------------
vtkNewickTreeReader::~vtkNewickTreeReader()
{
}

//----------------------------------------------------------------------------
vtkTree* vtkNewickTreeReader::GetOutput()
{
  return this->GetOutput(0);
}

//----------------------------------------------------------------------------
vtkTree* vtkNewickTreeReader::GetOutput(int idx)
{
  return vtkTree::SafeDownCast(this->GetOutputDataObject(idx));
}

//----------------------------------------------------------------------------
void vtkNewickTreeReader::SetOutput(vtkTree *output)
{
  this->GetExecutive()->SetOutputData(0, output);
}

//----------------------------------------------------------------------------
// I do not think this should be here, but I do not want to remove it now.
int vtkNewickTreeReader::RequestUpdateExtent(
  vtkInformation *,
  vtkInformationVector **,
  vtkInformationVector *outputVector)
{
  vtkInformation *outInfo = outputVector->GetInformationObject(0);
  int piece, numPieces;

  piece = outInfo->Get(vtkStreamingDemandDrivenPipeline::UPDATE_PIECE_NUMBER());
  numPieces = outInfo->Get(vtkStreamingDemandDrivenPipeline::UPDATE_NUMBER_OF_PIECES());

  // make sure piece is valid
  if (piece < 0 || piece >= numPieces)
    {
    return 1;
    }

  return 1;
}

//----------------------------------------------------------------------------
int vtkNewickTreeReader:: ReadNewickTree(  const char *  buffer, vtkTree & tree)
{
  // Read through the input file to count the number of nodes in the tree.
  // We start at one to account for the root node
  vtkIdType numNodes = 1;
  this->CountNodes(buffer, &numNodes);

  // Create the edge weight array
  vtkNew<vtkDoubleArray> weights;
  weights->SetNumberOfComponents(1);
  weights->SetName("weight");
  weights->SetNumberOfValues(numNodes-1);//the number of edges = number of nodes -1 for a tree
  weights->FillComponent(0, 0.0);

  // Create the names array
  vtkNew<vtkStringArray> names;
  names->SetNumberOfComponents(1);
  names->SetName("node name");
  names->SetNumberOfValues(numNodes);

  //parse the input file to create the graph
  vtkNew<vtkMutableDirectedGraph> builder;
  this->BuildTree(const_cast<char*> (buffer), builder.GetPointer(), weights.GetPointer(),
    names.GetPointer(), -1);

  builder->GetEdgeData()->AddArray(weights.GetPointer());
  builder->GetVertexData()->AddArray(names.GetPointer());

  if (!tree.CheckedShallowCopy(builder.GetPointer()))
    {
    vtkErrorMacro(<<"Edges do not create a valid tree.");
    return 1;
    }

  vtkNew<vtkDoubleArray> nodeWeights;
  nodeWeights->SetNumberOfTuples(tree.GetNumberOfVertices());

  //set node weights
  vtkNew<vtkTreeDFSIterator> treeIterator;
  treeIterator->SetStartVertex(tree.GetRoot());
  treeIterator->SetTree(&tree);
  while (treeIterator->HasNext())
    {
    vtkIdType vertex = treeIterator->Next();
    vtkIdType parent = tree.GetParent(vertex);
    double weight = 0.0;
    if (parent >= 0)
      {
      weight = weights->GetValue(tree.GetEdgeId(parent, vertex));
      weight += nodeWeights->GetValue(parent);
      }
    nodeWeights->SetValue(vertex, weight);
    }

  nodeWeights->SetName("node weight");
  tree.GetVertexData()->AddArray(nodeWeights.GetPointer());

  return 1;

}
//----------------------------------------------------------------------------
int vtkNewickTreeReader::RequestData(
  vtkInformation *,
  vtkInformationVector **,
  vtkInformationVector *outputVector)
{
  vtkInformation *outInfo = outputVector->GetInformationObject(0);

  // Return all data in the first piece ...
  if(outInfo->Get(vtkStreamingDemandDrivenPipeline::UPDATE_PIECE_NUMBER()) > 0)
    {
    return 1;
    }

  vtkDebugMacro(<<"Reading Newick tree ...");

  if( !this->ReadFromInputString)
    {
    if(!this->GetFileName())
      {
      vtkErrorMacro("FileName not set.");
      return 1;
      }

    std::ifstream ifs( this->GetFileName(), std::ifstream::in );
    if(!ifs.good())
      {
      vtkErrorMacro(<<"Unable to open " << this->GetFileName() << " for reading");
      return 1;
      }

    // Read the input file into a char *
    ifs.seekg(0, std::ios::end);
    this->InputStringLength = ifs.tellg();
    ifs.seekg(0, std::ios::beg);
    this->InputString = new char[this->InputStringLength];
    ifs.read(this->InputString, this->InputStringLength);
    ifs.close();
    }
  else
    {
    if ( (!this->InputString) || (this->InputStringLength == 0))
      {
      vtkErrorMacro(<<"Input string is empty!");
      return 1;
      }
    }

  vtkTree* const output = vtkTree::SafeDownCast(
    outInfo->Get(vtkDataObject::DATA_OBJECT()));

  if(!ReadNewickTree(this->InputString, *output))
    {
    vtkErrorMacro(<<"Error reading a vtkTree from the input.");
    return 1;
    }

  vtkDebugMacro(<< "Read " << output->GetNumberOfVertices() <<" vertices and "
    << output->GetNumberOfEdges() <<" edges.\n");

  return 1;
}

void vtkNewickTreeReader::CountNodes(const char *buffer, vtkIdType *numNodes)
{
  char *current;
  char *start;
  char temp;
  int childCount;

  start = const_cast<char*>(buffer);

  if (*start != '(')
  {
    // Leaf node. Separate name from weight.
    // If weight doesn't exist then take care of name only
    current = const_cast<char*>(buffer);
    while (*current != '\0')
    {
      current++;
    }
    ++(*numNodes);
  }
  else
  {
    ++(*numNodes);
    // Search for all child nodes
    // Find all ',' until corresponding ')' is encountered
    childCount = 0;
    start++;
    current = start;
    while (childCount >= 0)
    {
      switch (*current)
      {
        case '(':
          // Find corresponding ')' by counting
          start = current;
          current++;
          childCount++;
          while (childCount > 0)
          {
            if (*current == '(')
            {
              childCount++;
            }
            else if (*current == ')')
            {
              childCount--;
            }
            current++;
          }
          while (*current != ',' && *current != ')')
          {
            current++;
          }

          temp = *current;
          *current = '\0';
          // Count child nodes using recursion
          this->CountNodes(start, numNodes);
          *current = temp;

          if (*current != ')')
          {
            current++;
          }
        break;

        case ')':
          // End of this tree. Go to next part to retrieve distance
          childCount--;
        break;

        case ',':
          // Impossible separation since according to the algorithm, this symbol will never encountered.
          // Currently don't handle this and don't create any node
        break;

        default:
          // leaf node encountered
          start = current;
          while (*current != ',' && *current != ')')
          {
            current++;
          }

          temp = *current;
          *current = '\0';
          // Count child nodes using recursion
          this->CountNodes(start, numNodes);
          *current = temp;

          if (*current != ')')
          {
            current++;
          }
        break;
      }
    }

    // If start at ':', then the internal node has no name.
    current++;
    if (*current == ':')
    {
      start = current + 1;
      while (*current != '\0' && *current != ';')
      {
        current++;
      }
    }
    else if (*current != ';' && *current != '\0')
    {
      while (*current != ':' && *(current+1) != ';' && *(current+1) != '\0')
      {
        current++;
      }
      current++;
      while (*current != '\0' && *current != ';')
      {
        current++;
      }
    }
  }
}

vtkIdType vtkNewickTreeReader::BuildTree(char *buffer,
  vtkMutableDirectedGraph *g, vtkDoubleArray *weights, vtkStringArray *names,
  vtkIdType parent)
{
  char *current;
  char *start;
  char *colon = NULL;
  char temp;
  int childCount;
  vtkIdType node;

  start = buffer;

  if(parent == -1)
    {
    parent = g->AddVertex();
    names->SetValue(parent, "");
    }

  if (*start != '(')
  {
    // Leaf node. Separate name from weight (if it exists).
    current = buffer;
    while (*current != '\0')
    {
      if (*current == ':')
      {
        colon = current;
      }
      current++;
    }
    node = g->AddChild(parent);
    if (colon == NULL)
    {
      // Name only
      std::string name(start, strlen(start));
      names->SetValue(node, name);
    }
    else
    {
      // Name
      *colon = '\0';
      std::string name(start, strlen(start));
      names->SetValue(node, name);
      *colon = ':';
      // Weight
      colon++;
      weights->SetValue(g->GetEdgeId(parent, node), atof(colon));
    }
  }
  else
  {
    // Create node
    node = g->AddChild(parent);

    // Search for all child nodes
    // Find all ',' until corresponding ')' is encountered
    childCount = 0;
    start++;
    current = start;
    while (childCount >= 0)
    {
      switch (*current)
      {
        case '(':
          // Find corresponding ')' by counting
          start = current;
          current++;
          childCount++;
          while (childCount > 0)
          {
            if (*current == '(')
            {
              childCount++;
            }
            else if (*current == ')')
            {
              childCount--;
            }
            current++;
          }
          while (*current != ',' && *current != ')')
          {
            current++;
          }
          temp = *current;
          *current = '\0';
          // Create a child node using recursion
          this->BuildTree(start, g, weights, names, node);
          *current = temp;
          if (*current != ')')
          {
            current++;
          }
        break;

        case ')':
          // End of this tree. Go to next part to retrieve distance
          childCount--;
        break;

        case ',':
          // Impossible separation since according to the algorithm, this symbol will never encountered.
          // Currently don't handle this and don't create any node
        break;

        default:
          // leaf node encountered
          start = current;
          while (*current != ',' && *current != ')')
          {
            current++;
          }
          temp = *current;
          *current = '\0';
          // Create a child node using recursion
          this->BuildTree(start, g, weights, names, node);
          *current = temp;
          if (*current != ')')
          {
            current++;
          }
        break;
      }
    }

    // If start at ':', then the internal node has no name.
    current++;
    if (*current == ':')
    {
      start = current + 1;
      while (*current != '\0' && *current != ';')
      {
        current++;
      }
      temp = *current;
      *current = '\0';
      weights->SetValue(g->GetEdgeId(parent, node), atof(start));
      names->SetValue(node, "");
      *current = temp;
    }
    else if (*current != ';' && *current != '\0')
    {
      // Find ':' to retrieve distance, if any.
      // At this time *current should equal to ')'
      start = current;
      while (*current != ':')
      {
        current++;
      }
      temp = *current;
      *current = '\0';
      std::string name(start, strlen(start));
      names->SetValue(node, name);
      *current = temp;
      current++;
      start = current;
      while (*current != '\0' && *current != ';')
      {
        current++;
      }
      temp = *current;
      *current = '\0';
      weights->SetValue(g->GetEdgeId(parent, node), atof(start));
      *current = temp;
    }
  }

  return node;
}

//----------------------------------------------------------------------------
int vtkNewickTreeReader::FillOutputPortInformation(int, vtkInformation* info)
{
  info->Set(vtkDataObject::DATA_TYPE_NAME(), "vtkTree");
  return 1;
}

//----------------------------------------------------------------------------
void vtkNewickTreeReader::PrintSelf(ostream& os, vtkIndent indent)
{
  this->Superclass::PrintSelf(os,indent);
  os << indent << "FileName: "
     << (this->FileName ? this->FileName : "(none)") << endl;
  os << indent << "InputString: " << this->InputString << endl;
  os << indent << "ReadFromInputString: "
     << (this->ReadFromInputString ? "on" : "off") << endl;
}
<commit_msg>Fix segfault in otherPrint test.<commit_after>/*=========================================================================

  Program:   Visualization Toolkit
  Module:    vtkNewickTreeReader.cxx

  Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
  All rights reserved.
  See Copyright.txt or http://www.kitware.com/Copyright.htm for details.

     This software is distributed WITHOUT ANY WARRANTY; without even
     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
     PURPOSE.  See the above copyright notice for more information.

=========================================================================*/
#include "vtkNewickTreeReader.h"

#include "vtkByteSwap.h"
#include "vtkCellArray.h"
#include "vtkDataSetAttributes.h"
#include "vtkDoubleArray.h"
#include "vtkFieldData.h"
#include "vtkNew.h"
#include "vtkTree.h"
#include "vtkTreeDFSIterator.h"
#include "vtkInformation.h"
#include "vtkInformationVector.h"
#include "vtkMutableDirectedGraph.h"
#include "vtkObjectFactory.h"
#include "vtkStreamingDemandDrivenPipeline.h"
#include "vtkStringArray.h"

#include <iostream>
#include <fstream>

vtkStandardNewMacro(vtkNewickTreeReader);

#ifdef read
#undef read
#endif

//----------------------------------------------------------------------------
vtkNewickTreeReader::vtkNewickTreeReader()
{
  vtkTree *output = vtkTree::New();
  this->SetOutput(output);
  // Releasing data for pipeline parallism.
  // Filters will know it is empty.
  output->ReleaseData();
  output->Delete();
}

//----------------------------------------------------------------------------
vtkNewickTreeReader::~vtkNewickTreeReader()
{
}

//----------------------------------------------------------------------------
vtkTree* vtkNewickTreeReader::GetOutput()
{
  return this->GetOutput(0);
}

//----------------------------------------------------------------------------
vtkTree* vtkNewickTreeReader::GetOutput(int idx)
{
  return vtkTree::SafeDownCast(this->GetOutputDataObject(idx));
}

//----------------------------------------------------------------------------
void vtkNewickTreeReader::SetOutput(vtkTree *output)
{
  this->GetExecutive()->SetOutputData(0, output);
}

//----------------------------------------------------------------------------
// I do not think this should be here, but I do not want to remove it now.
int vtkNewickTreeReader::RequestUpdateExtent(
  vtkInformation *,
  vtkInformationVector **,
  vtkInformationVector *outputVector)
{
  vtkInformation *outInfo = outputVector->GetInformationObject(0);
  int piece, numPieces;

  piece = outInfo->Get(vtkStreamingDemandDrivenPipeline::UPDATE_PIECE_NUMBER());
  numPieces = outInfo->Get(vtkStreamingDemandDrivenPipeline::UPDATE_NUMBER_OF_PIECES());

  // make sure piece is valid
  if (piece < 0 || piece >= numPieces)
    {
    return 1;
    }

  return 1;
}

//----------------------------------------------------------------------------
int vtkNewickTreeReader:: ReadNewickTree(  const char *  buffer, vtkTree & tree)
{
  // Read through the input file to count the number of nodes in the tree.
  // We start at one to account for the root node
  vtkIdType numNodes = 1;
  this->CountNodes(buffer, &numNodes);

  // Create the edge weight array
  vtkNew<vtkDoubleArray> weights;
  weights->SetNumberOfComponents(1);
  weights->SetName("weight");
  weights->SetNumberOfValues(numNodes-1);//the number of edges = number of nodes -1 for a tree
  weights->FillComponent(0, 0.0);

  // Create the names array
  vtkNew<vtkStringArray> names;
  names->SetNumberOfComponents(1);
  names->SetName("node name");
  names->SetNumberOfValues(numNodes);

  //parse the input file to create the graph
  vtkNew<vtkMutableDirectedGraph> builder;
  this->BuildTree(const_cast<char*> (buffer), builder.GetPointer(), weights.GetPointer(),
    names.GetPointer(), -1);

  builder->GetEdgeData()->AddArray(weights.GetPointer());
  builder->GetVertexData()->AddArray(names.GetPointer());

  if (!tree.CheckedShallowCopy(builder.GetPointer()))
    {
    vtkErrorMacro(<<"Edges do not create a valid tree.");
    return 1;
    }

  vtkNew<vtkDoubleArray> nodeWeights;
  nodeWeights->SetNumberOfTuples(tree.GetNumberOfVertices());

  //set node weights
  vtkNew<vtkTreeDFSIterator> treeIterator;
  treeIterator->SetStartVertex(tree.GetRoot());
  treeIterator->SetTree(&tree);
  while (treeIterator->HasNext())
    {
    vtkIdType vertex = treeIterator->Next();
    vtkIdType parent = tree.GetParent(vertex);
    double weight = 0.0;
    if (parent >= 0)
      {
      weight = weights->GetValue(tree.GetEdgeId(parent, vertex));
      weight += nodeWeights->GetValue(parent);
      }
    nodeWeights->SetValue(vertex, weight);
    }

  nodeWeights->SetName("node weight");
  tree.GetVertexData()->AddArray(nodeWeights.GetPointer());

  return 1;

}
//----------------------------------------------------------------------------
int vtkNewickTreeReader::RequestData(
  vtkInformation *,
  vtkInformationVector **,
  vtkInformationVector *outputVector)
{
  vtkInformation *outInfo = outputVector->GetInformationObject(0);

  // Return all data in the first piece ...
  if(outInfo->Get(vtkStreamingDemandDrivenPipeline::UPDATE_PIECE_NUMBER()) > 0)
    {
    return 1;
    }

  vtkDebugMacro(<<"Reading Newick tree ...");

  if( !this->ReadFromInputString)
    {
    if(!this->GetFileName())
      {
      vtkErrorMacro("FileName not set.");
      return 1;
      }

    std::ifstream ifs( this->GetFileName(), std::ifstream::in );
    if(!ifs.good())
      {
      vtkErrorMacro(<<"Unable to open " << this->GetFileName() << " for reading");
      return 1;
      }

    // Read the input file into a char *
    ifs.seekg(0, std::ios::end);
    this->InputStringLength = ifs.tellg();
    ifs.seekg(0, std::ios::beg);
    this->InputString = new char[this->InputStringLength];
    ifs.read(this->InputString, this->InputStringLength);
    ifs.close();
    }
  else
    {
    if ( (!this->InputString) || (this->InputStringLength == 0))
      {
      vtkErrorMacro(<<"Input string is empty!");
      return 1;
      }
    }

  vtkTree* const output = vtkTree::SafeDownCast(
    outInfo->Get(vtkDataObject::DATA_OBJECT()));

  if(!ReadNewickTree(this->InputString, *output))
    {
    vtkErrorMacro(<<"Error reading a vtkTree from the input.");
    return 1;
    }

  vtkDebugMacro(<< "Read " << output->GetNumberOfVertices() <<" vertices and "
    << output->GetNumberOfEdges() <<" edges.\n");

  return 1;
}

void vtkNewickTreeReader::CountNodes(const char *buffer, vtkIdType *numNodes)
{
  char *current;
  char *start;
  char temp;
  int childCount;

  start = const_cast<char*>(buffer);

  if (*start != '(')
  {
    // Leaf node. Separate name from weight.
    // If weight doesn't exist then take care of name only
    current = const_cast<char*>(buffer);
    while (*current != '\0')
    {
      current++;
    }
    ++(*numNodes);
  }
  else
  {
    ++(*numNodes);
    // Search for all child nodes
    // Find all ',' until corresponding ')' is encountered
    childCount = 0;
    start++;
    current = start;
    while (childCount >= 0)
    {
      switch (*current)
      {
        case '(':
          // Find corresponding ')' by counting
          start = current;
          current++;
          childCount++;
          while (childCount > 0)
          {
            if (*current == '(')
            {
              childCount++;
            }
            else if (*current == ')')
            {
              childCount--;
            }
            current++;
          }
          while (*current != ',' && *current != ')')
          {
            current++;
          }

          temp = *current;
          *current = '\0';
          // Count child nodes using recursion
          this->CountNodes(start, numNodes);
          *current = temp;

          if (*current != ')')
          {
            current++;
          }
        break;

        case ')':
          // End of this tree. Go to next part to retrieve distance
          childCount--;
        break;

        case ',':
          // Impossible separation since according to the algorithm, this symbol will never encountered.
          // Currently don't handle this and don't create any node
        break;

        default:
          // leaf node encountered
          start = current;
          while (*current != ',' && *current != ')')
          {
            current++;
          }

          temp = *current;
          *current = '\0';
          // Count child nodes using recursion
          this->CountNodes(start, numNodes);
          *current = temp;

          if (*current != ')')
          {
            current++;
          }
        break;
      }
    }

    // If start at ':', then the internal node has no name.
    current++;
    if (*current == ':')
    {
      start = current + 1;
      while (*current != '\0' && *current != ';')
      {
        current++;
      }
    }
    else if (*current != ';' && *current != '\0')
    {
      while (*current != ':' && *(current+1) != ';' && *(current+1) != '\0')
      {
        current++;
      }
      current++;
      while (*current != '\0' && *current != ';')
      {
        current++;
      }
    }
  }
}

vtkIdType vtkNewickTreeReader::BuildTree(char *buffer,
  vtkMutableDirectedGraph *g, vtkDoubleArray *weights, vtkStringArray *names,
  vtkIdType parent)
{
  char *current;
  char *start;
  char *colon = NULL;
  char temp;
  int childCount;
  vtkIdType node;

  start = buffer;

  if(parent == -1)
    {
    parent = g->AddVertex();
    names->SetValue(parent, "");
    }

  if (*start != '(')
  {
    // Leaf node. Separate name from weight (if it exists).
    current = buffer;
    while (*current != '\0')
    {
      if (*current == ':')
      {
        colon = current;
      }
      current++;
    }
    node = g->AddChild(parent);
    if (colon == NULL)
    {
      // Name only
      std::string name(start, strlen(start));
      names->SetValue(node, name);
    }
    else
    {
      // Name
      *colon = '\0';
      std::string name(start, strlen(start));
      names->SetValue(node, name);
      *colon = ':';
      // Weight
      colon++;
      weights->SetValue(g->GetEdgeId(parent, node), atof(colon));
    }
  }
  else
  {
    // Create node
    node = g->AddChild(parent);

    // Search for all child nodes
    // Find all ',' until corresponding ')' is encountered
    childCount = 0;
    start++;
    current = start;
    while (childCount >= 0)
    {
      switch (*current)
      {
        case '(':
          // Find corresponding ')' by counting
          start = current;
          current++;
          childCount++;
          while (childCount > 0)
          {
            if (*current == '(')
            {
              childCount++;
            }
            else if (*current == ')')
            {
              childCount--;
            }
            current++;
          }
          while (*current != ',' && *current != ')')
          {
            current++;
          }
          temp = *current;
          *current = '\0';
          // Create a child node using recursion
          this->BuildTree(start, g, weights, names, node);
          *current = temp;
          if (*current != ')')
          {
            current++;
          }
        break;

        case ')':
          // End of this tree. Go to next part to retrieve distance
          childCount--;
        break;

        case ',':
          // Impossible separation since according to the algorithm, this symbol will never encountered.
          // Currently don't handle this and don't create any node
        break;

        default:
          // leaf node encountered
          start = current;
          while (*current != ',' && *current != ')')
          {
            current++;
          }
          temp = *current;
          *current = '\0';
          // Create a child node using recursion
          this->BuildTree(start, g, weights, names, node);
          *current = temp;
          if (*current != ')')
          {
            current++;
          }
        break;
      }
    }

    // If start at ':', then the internal node has no name.
    current++;
    if (*current == ':')
    {
      start = current + 1;
      while (*current != '\0' && *current != ';')
      {
        current++;
      }
      temp = *current;
      *current = '\0';
      weights->SetValue(g->GetEdgeId(parent, node), atof(start));
      names->SetValue(node, "");
      *current = temp;
    }
    else if (*current != ';' && *current != '\0')
    {
      // Find ':' to retrieve distance, if any.
      // At this time *current should equal to ')'
      start = current;
      while (*current != ':')
      {
        current++;
      }
      temp = *current;
      *current = '\0';
      std::string name(start, strlen(start));
      names->SetValue(node, name);
      *current = temp;
      current++;
      start = current;
      while (*current != '\0' && *current != ';')
      {
        current++;
      }
      temp = *current;
      *current = '\0';
      weights->SetValue(g->GetEdgeId(parent, node), atof(start));
      *current = temp;
    }
  }

  return node;
}

//----------------------------------------------------------------------------
int vtkNewickTreeReader::FillOutputPortInformation(int, vtkInformation* info)
{
  info->Set(vtkDataObject::DATA_TYPE_NAME(), "vtkTree");
  return 1;
}

//----------------------------------------------------------------------------
void vtkNewickTreeReader::PrintSelf(ostream& os, vtkIndent indent)
{
  this->Superclass::PrintSelf(os,indent);
  os << indent << "FileName: "
     << (this->FileName ? this->FileName : "(none)") << endl;
  os << indent << "InputString: "
     << (this->InputString ? this->InputString : "(none)") << endl;
  os << indent << "ReadFromInputString: "
     << (this->ReadFromInputString ? "on" : "off") << endl;
}
<|endoftext|>


<commit_before>/**
 * File    : E.cpp
 * Author  : Kazune Takahashi
 * Created : 11/25/2018, 12:14:31 PM
 * Powered by Visual Studio Code
 */

#include <iostream>
#include <iomanip>   // << fixed << setprecision(xxx)
#include <algorithm> // do { } while ( next_permutation(A, A+xxx) ) ;
#include <vector>
#include <string> // to_string(nnn) // substr(m, n) // stoi(nnn)
#include <complex>
#include <tuple>
#include <queue>
#include <stack>
#include <map> // if (M.find(key) != M.end()) { }
#include <set>
#include <functional>
#include <random> // auto rd = bind(uniform_int_distribution<int>(0, 9), mt19937(19920725));
#include <chrono> // std::chrono::system_clock::time_point start_time, end_time;
// start = std::chrono::system_clock::now();
// double elapsed = std::chrono::duration_cast<std::chrono::milliseconds>(end_time-start_time).count();
#include <cctype>
#include <cassert>
#include <cmath>
#include <cstdio>
#include <cstdlib>
using namespace std;

#define DEBUG 0 // change 0 -> 1 if we need debug.

typedef long long ll;

// const int dx[4] = {1, 0, -1, 0};
// const int dy[4] = {0, 1, 0, -1};

// const int C = 1e6+10;
const ll M = 1000000007;

int T;
ll a[310];
ll DP[310][1000];

ll cnt(ll i, ll l)
{
  if (0 <= l && l <= a[i])
  {
    return 1;
  }
  else
  {
    return 0;
  }
}

int main()
{
  cin >> T;
  for (auto i = 1; i <= T; i++)
  {
    cin >> a[i];
  }
  for (auto i = 0; i < 1000; i++)
  {
    DP[0][i] = 0;
  }
  DP[0][0] = 1;
  for (auto i = 1; i <= T; i++)
  {
    for (auto j = 0; j < 1000; j++)
    {
      DP[i][j] = 0;
      for (auto k = 0; k <= min(2 * j, 999); k++)
      {
        DP[i][j] += DP[i - 1][k] * cnt(i, 2 * j - k);
        DP[i][j] %= M;
      }
    }
  }
  /*
  for (auto i = 0; i < T; i++)
  {
    for (auto j = 0; j < 1000; j++)
    {
      cerr << "DP[" << i << "][" << j << "] = " << DP[i][j] << endl;
    }
  }
  */
  ll ans = 0;
  for (auto i = 1; i <= T; i++)
  {
    if (a[i] > 0)
    {
      ans++;
    }
  }
  for (auto i = 1; i <= T; i++)
  {
    for (auto j = 0; j <= 9; j++)
    {
      cerr << "DP[" << i << "][" << (1 << j) << "] = " << DP[i][1 << j] << endl;
      ans += DP[i][1 << j];
    }
    ans %= M;
  }
  cout << ans << endl;
}<commit_msg>submit E.cpp to 'E - Union' (code-thanks-festival-2018) [C++14 (GCC 5.4.1)]<commit_after>/**
 * File    : E.cpp
 * Author  : Kazune Takahashi
 * Created : 11/25/2018, 12:14:31 PM
 * Powered by Visual Studio Code
 */

#include <iostream>
#include <iomanip>   // << fixed << setprecision(xxx)
#include <algorithm> // do { } while ( next_permutation(A, A+xxx) ) ;
#include <vector>
#include <string> // to_string(nnn) // substr(m, n) // stoi(nnn)
#include <complex>
#include <tuple>
#include <queue>
#include <stack>
#include <map> // if (M.find(key) != M.end()) { }
#include <set>
#include <functional>
#include <random> // auto rd = bind(uniform_int_distribution<int>(0, 9), mt19937(19920725));
#include <chrono> // std::chrono::system_clock::time_point start_time, end_time;
// start = std::chrono::system_clock::now();
// double elapsed = std::chrono::duration_cast<std::chrono::milliseconds>(end_time-start_time).count();
#include <cctype>
#include <cassert>
#include <cmath>
#include <cstdio>
#include <cstdlib>
using namespace std;

#define DEBUG 0 // change 0 -> 1 if we need debug.

typedef long long ll;

// const int dx[4] = {1, 0, -1, 0};
// const int dy[4] = {0, 1, 0, -1};

// const int C = 1e6+10;
const ll M = 1000000007;

int T;
ll a[700];
ll DP[700][1000];

ll cnt(ll i, ll l)
{
  if (0 <= l && l <= a[i])
  {
    return 1;
  }
  else
  {
    return 0;
  }
}

int main()
{
  cin >> T;
  fill(a, a + 700, 0);
  for (auto i = 1; i <= T; i++)
  {
    cin >> a[i];
  }
  for (auto i = 0; i < 1000; i++)
  {
    DP[0][i] = 0;
  }
  DP[0][0] = 1;
  for (auto i = 1; i <= 2 * T; i++)
  {
    for (auto j = 0; j < 1000; j++)
    {
      DP[i][j] = 0;
      for (auto k = 0; k <= min(2 * j, 999); k++)
      {
        DP[i][j] += DP[i - 1][k] * cnt(i, 2 * j - k);
        DP[i][j] %= M;
      }
    }
  }
  /*
  for (auto i = 0; i < T; i++)
  {
    for (auto j = 0; j < 1000; j++)
    {
      cerr << "DP[" << i << "][" << j << "] = " << DP[i][j] << endl;
    }
  }
  */
  ll ans = 0;
  for (auto i = 1; i <= 2 * T; i++)
  {
    if (a[i] > 0)
    {
      ans++;
    }
  }
  for (auto i = 1; i <= 2 * T; i++)
  {
    ans += DP[i][1];
    ans %= M;
  }
  cout << ans << endl;
}<|endoftext|>


<commit_before>// 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.

#ifndef __STOUT_DURATION_HPP__
#define __STOUT_DURATION_HPP__

#include <ctype.h> // For 'isdigit'.

// For 'timeval'.
#ifndef __WINDOWS__
#include <sys/time.h>
#endif // __WINDOWS__

#include <iomanip>
#include <iostream>
#include <limits>
#include <string>

#include "error.hpp"
#include "numify.hpp"
#include "try.hpp"

class Duration
{
public:
  static Try<Duration> parse(const std::string& s)
  {
    // TODO(benh): Support negative durations (i.e., starts with '-').
    size_t index = 0;
    while (index < s.size()) {
      if (isdigit(s[index]) || s[index] == '.') {
        index++;
        continue;
      }

      Try<double> value = numify<double>(s.substr(0, index));

      if (value.isError()) {
        return Error(value.error());
      }

      const std::string unit = s.substr(index);

      if (unit == "ns") {
        return Duration(value.get(), NANOSECONDS);
      } else if (unit == "us") {
        return Duration(value.get(), MICROSECONDS);
      } else if (unit == "ms") {
        return Duration(value.get(), MILLISECONDS);
      } else if (unit == "secs") {
        return Duration(value.get(), SECONDS);
      } else if (unit == "mins") {
        return Duration(value.get(), MINUTES);
      } else if (unit == "hrs") {
        return Duration(value.get(), HOURS);
      } else if (unit == "days") {
        return Duration(value.get(), DAYS);
      } else if (unit == "weeks") {
        return Duration(value.get(), WEEKS);
      } else {
        return Error(
            "Unknown duration unit '" + unit + "'; supported units are"
            " 'ns', 'us', 'ms', 'secs', 'mins', 'hrs', 'days', and 'weeks'");
      }
    }
    return Error("Invalid duration '" + s + "'");
  }

  static Try<Duration> create(double seconds);

  constexpr Duration() : nanos(0) {}

  explicit Duration(const timeval& t)
  {
    nanos = t.tv_sec * SECONDS + t.tv_usec * MICROSECONDS;
  }

  int64_t ns() const   { return nanos; }
  double us() const    { return static_cast<double>(nanos) / MICROSECONDS; }
  double ms() const    { return static_cast<double>(nanos) / MILLISECONDS; }
  double secs() const  { return static_cast<double>(nanos) / SECONDS; }
  double mins() const  { return static_cast<double>(nanos) / MINUTES; }
  double hrs() const   { return static_cast<double>(nanos) / HOURS; }
  double days() const  { return static_cast<double>(nanos) / DAYS; }
  double weeks() const { return static_cast<double>(nanos) / WEEKS; }

  struct timeval timeval() const
  {
    struct timeval t;

    // Explicitly compute `tv_sec` and `tv_usec` instead of using `us` and
    // `secs` to avoid converting `int64_t` -> `double` -> `long`.
    t.tv_sec = ns() / SECONDS;
    t.tv_usec = (ns() / MICROSECONDS) - (t.tv_sec * SECONDS / MICROSECONDS);
    return t;
  }

  bool operator<(const Duration& d) const { return nanos < d.nanos; }
  bool operator<=(const Duration& d) const { return nanos <= d.nanos; }
  bool operator>(const Duration& d) const { return nanos > d.nanos; }
  bool operator>=(const Duration& d) const { return nanos >= d.nanos; }
  bool operator==(const Duration& d) const { return nanos == d.nanos; }
  bool operator!=(const Duration& d) const { return nanos != d.nanos; }

  Duration& operator+=(const Duration& that)
  {
    nanos += that.nanos;
    return *this;
  }

  Duration& operator-=(const Duration& that)
  {
    nanos -= that.nanos;
    return *this;
  }

  Duration& operator*=(double multiplier)
  {
    nanos = static_cast<int64_t>(nanos * multiplier);
    return *this;
  }

  Duration& operator/=(double divisor)
  {
    nanos = static_cast<int64_t>(nanos / divisor);
    return *this;
  }

  Duration operator+(const Duration& that) const
  {
    Duration sum = *this;
    sum += that;
    return sum;
  }

  Duration operator-(const Duration& that) const
  {
    Duration diff = *this;
    diff -= that;
    return diff;
  }

  Duration operator*(double multiplier) const
  {
    Duration product = *this;
    product *= multiplier;
    return product;
  }

  Duration operator/(double divisor) const
  {
    Duration quotient = *this;
    quotient /= divisor;
    return quotient;
  }

  // A constant holding the maximum value a Duration can have.
  static constexpr Duration max();
  // A constant holding the minimum (negative) value a Duration can
  // have.
  static constexpr Duration min();
  // A constant holding a Duration of a "zero" value.
  static constexpr Duration zero() { return Duration(); }

protected:
  static constexpr int64_t NANOSECONDS  = 1;
  static constexpr int64_t MICROSECONDS = 1000 * NANOSECONDS;
  static constexpr int64_t MILLISECONDS = 1000 * MICROSECONDS;
  static constexpr int64_t SECONDS      = 1000 * MILLISECONDS;
  static constexpr int64_t MINUTES      = 60 * SECONDS;
  static constexpr int64_t HOURS        = 60 * MINUTES;
  static constexpr int64_t DAYS         = 24 * HOURS;
  static constexpr int64_t WEEKS        = 7 * DAYS;

  // Construct from a (value, unit) pair.
  constexpr Duration(int64_t value, int64_t unit)
    : nanos(value * unit) {}

private:
  // Used only by "parse".
  constexpr Duration(double value, int64_t unit)
    : nanos(static_cast<int64_t>(value * unit)) {}

  int64_t nanos;

  friend std::ostream& operator<<(
    std::ostream& stream,
    const Duration& duration);
};

class Nanoseconds : public Duration
{
public:
  explicit constexpr Nanoseconds(int64_t nanoseconds)
    : Duration(nanoseconds, NANOSECONDS) {}

  constexpr Nanoseconds(const Duration& d) : Duration(d) {}

  double value() const { return static_cast<double>(this->ns()); }

  static std::string units() { return "ns"; }
};

class Microseconds : public Duration
{
public:
  explicit constexpr Microseconds(int64_t microseconds)
    : Duration(microseconds, MICROSECONDS) {}

  constexpr Microseconds(const Duration& d) : Duration(d) {}

  double value() const { return this->us(); }

  static std::string units() { return "us"; }
};

class Milliseconds : public Duration
{
public:
  explicit constexpr Milliseconds(int64_t milliseconds)
    : Duration(milliseconds, MILLISECONDS) {}

  constexpr Milliseconds(const Duration& d) : Duration(d) {}

  double value() const { return this->ms(); }

  static std::string units() { return "ms"; }
};

class Seconds : public Duration
{
public:
  explicit constexpr Seconds(int64_t seconds)
    : Duration(seconds, SECONDS) {}

  constexpr Seconds(const Duration& d) : Duration(d) {}

  double value() const { return this->secs(); }

  static std::string units() { return "secs"; }
};

class Minutes : public Duration
{
public:
  explicit constexpr Minutes(int64_t minutes)
    : Duration(minutes, MINUTES) {}

  constexpr Minutes(const Duration& d) : Duration(d) {}

  double value() const { return this->mins(); }

  static std::string units() { return "mins"; }
};

class Hours : public Duration
{
public:
  explicit constexpr Hours(int64_t hours)
    : Duration(hours, HOURS) {}

  constexpr Hours(const Duration& d) : Duration(d) {}

  double value() const { return this->hrs(); }

  static std::string units() { return "hrs"; }
};

class Days : public Duration
{
public:
  explicit constexpr Days(int64_t days)
    : Duration(days, DAYS) {}

  constexpr Days(const Duration& d) : Duration(d) {}

  double value() const { return this->days(); }

  static std::string units() { return "days"; }
};

class Weeks : public Duration
{
public:
  explicit constexpr Weeks(int64_t value) : Duration(value, WEEKS) {}

  constexpr Weeks(const Duration& d) : Duration(d) {}

  double value() const { return this->weeks(); }

  static std::string units() { return "weeks"; }
};

inline std::ostream& operator<<(std::ostream& stream, const Duration& duration_)
{
  // Output the duration in full double precision and save the old precision.
  std::streamsize precision =
    stream.precision(std::numeric_limits<double>::digits10);

  // Parse the duration as the sign and the absolute value.
  Duration duration = duration_;
  if (duration_ < Duration::zero()) {
    stream << "-";

    // Duration::min() may not be representable as a positive Duration.
    if (duration_ == Duration::min()) {
      duration = Duration::max();
    } else {
      duration = duration_ * -1;
    }
  }

  // First determine which bucket of time unit the duration falls into
  // then check whether the duration can be represented as a whole
  // number with this time unit or a smaller one.
  // e.g. 1.42857142857143weeks falls into the 'Weeks' bucket but
  // reads better with a smaller unit: '10days'. So we use 'days'
  // instead of 'weeks' to output the duration.
  int64_t nanoseconds = duration.ns();
  if (duration < Microseconds(1)) {
    stream << duration.ns() << Nanoseconds::units();
  } else if (duration < Milliseconds(1)) {
    if (nanoseconds % Duration::MICROSECONDS != 0) {
      // We can't get a whole number using this unit but we can at
      // one level down.
      stream << duration.ns() << Nanoseconds::units();
    } else {
      stream << duration.us() << Microseconds::units();
    }
  } else if (duration < Seconds(1)) {
    if (nanoseconds % Duration::MILLISECONDS != 0 &&
        nanoseconds % Duration::MICROSECONDS == 0) {
      stream << duration.us() << Microseconds::units();
    } else {
      stream << duration.ms() << Milliseconds::units();
    }
  } else if (duration < Minutes(1)) {
    if (nanoseconds % Duration::SECONDS != 0 &&
        nanoseconds % Duration::MILLISECONDS == 0) {
      stream << duration.ms() << Milliseconds::units();
    } else {
      stream << duration.secs() << Seconds::units();
    }
  } else if (duration < Hours(1)) {
    if (nanoseconds % Duration::MINUTES != 0 &&
        nanoseconds % Duration::SECONDS == 0) {
      stream << duration.secs() << Seconds::units();
    } else {
      stream << duration.mins() << Minutes::units();
    }
  } else if (duration < Days(1)) {
    if (nanoseconds % Duration::HOURS != 0 &&
        nanoseconds % Duration::MINUTES == 0) {
      stream << duration.mins() << Minutes::units();
    } else {
      stream << duration.hrs() << Hours::units();
    }
  } else if (duration < Weeks(1)) {
    if (nanoseconds % Duration::DAYS != 0 &&
        nanoseconds % Duration::HOURS == 0) {
      stream << duration.hrs() << Hours::units();
    } else {
      stream << duration.days() << Days::units();
    }
  } else {
    if (nanoseconds % Duration::WEEKS != 0 &&
        nanoseconds % Duration::DAYS == 0) {
      stream << duration.days() << Days::units();
    } else {
      stream << duration.weeks() << Weeks::units();
    }
  }

  // Return the stream to original formatting state.
  stream.precision(precision);

  return stream;
}

inline Try<Duration> Duration::create(double seconds)
{
  if (seconds * SECONDS > std::numeric_limits<int64_t>::max() ||
      seconds * SECONDS < std::numeric_limits<int64_t>::min()) {
    return Error("Argument out of the range that a Duration can represent due "
                 "to int64_t's size limit");
  }

  return Nanoseconds(static_cast<int64_t>(seconds * SECONDS));
}

inline constexpr Duration Duration::max()
{
  return Nanoseconds(std::numeric_limits<int64_t>::max());
}

inline constexpr Duration Duration::min()
{
  return Nanoseconds(std::numeric_limits<int64_t>::min());
}

#endif // __STOUT_DURATION_HPP__
<commit_msg>Fixed conversion warning in `duration.hpp`.<commit_after>// 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.

#ifndef __STOUT_DURATION_HPP__
#define __STOUT_DURATION_HPP__

#include <ctype.h> // For 'isdigit'.

// For 'timeval'.
#ifndef __WINDOWS__
#include <sys/time.h>
#endif // __WINDOWS__

#include <iomanip>
#include <iostream>
#include <limits>
#include <string>

#include "error.hpp"
#include "numify.hpp"
#include "try.hpp"

class Duration
{
public:
  static Try<Duration> parse(const std::string& s)
  {
    // TODO(benh): Support negative durations (i.e., starts with '-').
    size_t index = 0;
    while (index < s.size()) {
      if (isdigit(s[index]) || s[index] == '.') {
        index++;
        continue;
      }

      Try<double> value = numify<double>(s.substr(0, index));

      if (value.isError()) {
        return Error(value.error());
      }

      const std::string unit = s.substr(index);

      if (unit == "ns") {
        return Duration(value.get(), NANOSECONDS);
      } else if (unit == "us") {
        return Duration(value.get(), MICROSECONDS);
      } else if (unit == "ms") {
        return Duration(value.get(), MILLISECONDS);
      } else if (unit == "secs") {
        return Duration(value.get(), SECONDS);
      } else if (unit == "mins") {
        return Duration(value.get(), MINUTES);
      } else if (unit == "hrs") {
        return Duration(value.get(), HOURS);
      } else if (unit == "days") {
        return Duration(value.get(), DAYS);
      } else if (unit == "weeks") {
        return Duration(value.get(), WEEKS);
      } else {
        return Error(
            "Unknown duration unit '" + unit + "'; supported units are"
            " 'ns', 'us', 'ms', 'secs', 'mins', 'hrs', 'days', and 'weeks'");
      }
    }
    return Error("Invalid duration '" + s + "'");
  }

  static Try<Duration> create(double seconds);

  constexpr Duration() : nanos(0) {}

  explicit Duration(const timeval& t)
  {
    nanos = t.tv_sec * SECONDS + t.tv_usec * MICROSECONDS;
  }

  int64_t ns() const   { return nanos; }
  double us() const    { return static_cast<double>(nanos) / MICROSECONDS; }
  double ms() const    { return static_cast<double>(nanos) / MILLISECONDS; }
  double secs() const  { return static_cast<double>(nanos) / SECONDS; }
  double mins() const  { return static_cast<double>(nanos) / MINUTES; }
  double hrs() const   { return static_cast<double>(nanos) / HOURS; }
  double days() const  { return static_cast<double>(nanos) / DAYS; }
  double weeks() const { return static_cast<double>(nanos) / WEEKS; }

  struct timeval timeval() const
  {
    struct timeval t;

    // Explicitly compute `tv_sec` and `tv_usec` instead of using `us` and
    // `secs` to avoid converting `int64_t` -> `double` -> `long`.
    t.tv_sec = static_cast<decltype(t.tv_sec)>(ns() / SECONDS);
    t.tv_usec = static_cast<decltype(t.tv_usec)>(
        (ns() / MICROSECONDS) - (t.tv_sec * SECONDS / MICROSECONDS));
    return t;
  }

  bool operator<(const Duration& d) const { return nanos < d.nanos; }
  bool operator<=(const Duration& d) const { return nanos <= d.nanos; }
  bool operator>(const Duration& d) const { return nanos > d.nanos; }
  bool operator>=(const Duration& d) const { return nanos >= d.nanos; }
  bool operator==(const Duration& d) const { return nanos == d.nanos; }
  bool operator!=(const Duration& d) const { return nanos != d.nanos; }

  Duration& operator+=(const Duration& that)
  {
    nanos += that.nanos;
    return *this;
  }

  Duration& operator-=(const Duration& that)
  {
    nanos -= that.nanos;
    return *this;
  }

  Duration& operator*=(double multiplier)
  {
    nanos = static_cast<int64_t>(nanos * multiplier);
    return *this;
  }

  Duration& operator/=(double divisor)
  {
    nanos = static_cast<int64_t>(nanos / divisor);
    return *this;
  }

  Duration operator+(const Duration& that) const
  {
    Duration sum = *this;
    sum += that;
    return sum;
  }

  Duration operator-(const Duration& that) const
  {
    Duration diff = *this;
    diff -= that;
    return diff;
  }

  Duration operator*(double multiplier) const
  {
    Duration product = *this;
    product *= multiplier;
    return product;
  }

  Duration operator/(double divisor) const
  {
    Duration quotient = *this;
    quotient /= divisor;
    return quotient;
  }

  // A constant holding the maximum value a Duration can have.
  static constexpr Duration max();
  // A constant holding the minimum (negative) value a Duration can
  // have.
  static constexpr Duration min();
  // A constant holding a Duration of a "zero" value.
  static constexpr Duration zero() { return Duration(); }

protected:
  static constexpr int64_t NANOSECONDS  = 1;
  static constexpr int64_t MICROSECONDS = 1000 * NANOSECONDS;
  static constexpr int64_t MILLISECONDS = 1000 * MICROSECONDS;
  static constexpr int64_t SECONDS      = 1000 * MILLISECONDS;
  static constexpr int64_t MINUTES      = 60 * SECONDS;
  static constexpr int64_t HOURS        = 60 * MINUTES;
  static constexpr int64_t DAYS         = 24 * HOURS;
  static constexpr int64_t WEEKS        = 7 * DAYS;

  // Construct from a (value, unit) pair.
  constexpr Duration(int64_t value, int64_t unit)
    : nanos(value * unit) {}

private:
  // Used only by "parse".
  constexpr Duration(double value, int64_t unit)
    : nanos(static_cast<int64_t>(value * unit)) {}

  int64_t nanos;

  friend std::ostream& operator<<(
    std::ostream& stream,
    const Duration& duration);
};

class Nanoseconds : public Duration
{
public:
  explicit constexpr Nanoseconds(int64_t nanoseconds)
    : Duration(nanoseconds, NANOSECONDS) {}

  constexpr Nanoseconds(const Duration& d) : Duration(d) {}

  double value() const { return static_cast<double>(this->ns()); }

  static std::string units() { return "ns"; }
};

class Microseconds : public Duration
{
public:
  explicit constexpr Microseconds(int64_t microseconds)
    : Duration(microseconds, MICROSECONDS) {}

  constexpr Microseconds(const Duration& d) : Duration(d) {}

  double value() const { return this->us(); }

  static std::string units() { return "us"; }
};

class Milliseconds : public Duration
{
public:
  explicit constexpr Milliseconds(int64_t milliseconds)
    : Duration(milliseconds, MILLISECONDS) {}

  constexpr Milliseconds(const Duration& d) : Duration(d) {}

  double value() const { return this->ms(); }

  static std::string units() { return "ms"; }
};

class Seconds : public Duration
{
public:
  explicit constexpr Seconds(int64_t seconds)
    : Duration(seconds, SECONDS) {}

  constexpr Seconds(const Duration& d) : Duration(d) {}

  double value() const { return this->secs(); }

  static std::string units() { return "secs"; }
};

class Minutes : public Duration
{
public:
  explicit constexpr Minutes(int64_t minutes)
    : Duration(minutes, MINUTES) {}

  constexpr Minutes(const Duration& d) : Duration(d) {}

  double value() const { return this->mins(); }

  static std::string units() { return "mins"; }
};

class Hours : public Duration
{
public:
  explicit constexpr Hours(int64_t hours)
    : Duration(hours, HOURS) {}

  constexpr Hours(const Duration& d) : Duration(d) {}

  double value() const { return this->hrs(); }

  static std::string units() { return "hrs"; }
};

class Days : public Duration
{
public:
  explicit constexpr Days(int64_t days)
    : Duration(days, DAYS) {}

  constexpr Days(const Duration& d) : Duration(d) {}

  double value() const { return this->days(); }

  static std::string units() { return "days"; }
};

class Weeks : public Duration
{
public:
  explicit constexpr Weeks(int64_t value) : Duration(value, WEEKS) {}

  constexpr Weeks(const Duration& d) : Duration(d) {}

  double value() const { return this->weeks(); }

  static std::string units() { return "weeks"; }
};

inline std::ostream& operator<<(std::ostream& stream, const Duration& duration_)
{
  // Output the duration in full double precision and save the old precision.
  std::streamsize precision =
    stream.precision(std::numeric_limits<double>::digits10);

  // Parse the duration as the sign and the absolute value.
  Duration duration = duration_;
  if (duration_ < Duration::zero()) {
    stream << "-";

    // Duration::min() may not be representable as a positive Duration.
    if (duration_ == Duration::min()) {
      duration = Duration::max();
    } else {
      duration = duration_ * -1;
    }
  }

  // First determine which bucket of time unit the duration falls into
  // then check whether the duration can be represented as a whole
  // number with this time unit or a smaller one.
  // e.g. 1.42857142857143weeks falls into the 'Weeks' bucket but
  // reads better with a smaller unit: '10days'. So we use 'days'
  // instead of 'weeks' to output the duration.
  int64_t nanoseconds = duration.ns();
  if (duration < Microseconds(1)) {
    stream << duration.ns() << Nanoseconds::units();
  } else if (duration < Milliseconds(1)) {
    if (nanoseconds % Duration::MICROSECONDS != 0) {
      // We can't get a whole number using this unit but we can at
      // one level down.
      stream << duration.ns() << Nanoseconds::units();
    } else {
      stream << duration.us() << Microseconds::units();
    }
  } else if (duration < Seconds(1)) {
    if (nanoseconds % Duration::MILLISECONDS != 0 &&
        nanoseconds % Duration::MICROSECONDS == 0) {
      stream << duration.us() << Microseconds::units();
    } else {
      stream << duration.ms() << Milliseconds::units();
    }
  } else if (duration < Minutes(1)) {
    if (nanoseconds % Duration::SECONDS != 0 &&
        nanoseconds % Duration::MILLISECONDS == 0) {
      stream << duration.ms() << Milliseconds::units();
    } else {
      stream << duration.secs() << Seconds::units();
    }
  } else if (duration < Hours(1)) {
    if (nanoseconds % Duration::MINUTES != 0 &&
        nanoseconds % Duration::SECONDS == 0) {
      stream << duration.secs() << Seconds::units();
    } else {
      stream << duration.mins() << Minutes::units();
    }
  } else if (duration < Days(1)) {
    if (nanoseconds % Duration::HOURS != 0 &&
        nanoseconds % Duration::MINUTES == 0) {
      stream << duration.mins() << Minutes::units();
    } else {
      stream << duration.hrs() << Hours::units();
    }
  } else if (duration < Weeks(1)) {
    if (nanoseconds % Duration::DAYS != 0 &&
        nanoseconds % Duration::HOURS == 0) {
      stream << duration.hrs() << Hours::units();
    } else {
      stream << duration.days() << Days::units();
    }
  } else {
    if (nanoseconds % Duration::WEEKS != 0 &&
        nanoseconds % Duration::DAYS == 0) {
      stream << duration.days() << Days::units();
    } else {
      stream << duration.weeks() << Weeks::units();
    }
  }

  // Return the stream to original formatting state.
  stream.precision(precision);

  return stream;
}

inline Try<Duration> Duration::create(double seconds)
{
  if (seconds * SECONDS > std::numeric_limits<int64_t>::max() ||
      seconds * SECONDS < std::numeric_limits<int64_t>::min()) {
    return Error("Argument out of the range that a Duration can represent due "
                 "to int64_t's size limit");
  }

  return Nanoseconds(static_cast<int64_t>(seconds * SECONDS));
}

inline constexpr Duration Duration::max()
{
  return Nanoseconds(std::numeric_limits<int64_t>::max());
}

inline constexpr Duration Duration::min()
{
  return Nanoseconds(std::numeric_limits<int64_t>::min());
}

#endif // __STOUT_DURATION_HPP__
<|endoftext|>


<commit_before>/*
 * This file is part of telepathy-accounts-kcm
 *
 * Copyright (C) 2009 Collabora Ltd. <http://www.collabora.co.uk/>
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 */

#include "accounts-list-model.h"

#include "account-item.h"

#include <kdebug.h>

#include <TelepathyQt4/Client/Account>

AccountsListModel::AccountsListModel(QObject *parent)
 : QAbstractListModel(parent)
{
    m_unreadyAccounts.clear();
    m_readyAccounts.clear();
}

AccountsListModel::~AccountsListModel()
{
    // TODO: Implement me!
}

int AccountsListModel::rowCount(const QModelIndex &index) const
{
    if(index == QModelIndex())
    {
       return m_readyAccounts.size();
    }

    return 0;
}

QVariant AccountsListModel::data(const QModelIndex &index, int role) const
{
    // FIXME: This is a basic implementation just so I can see what's going
    // on while developing this code further. Needs expanding.
    if(role == Qt::DisplayRole)
    {
        return QVariant(m_readyAccounts.at(index.row())->account()->displayName());
    }

    return QVariant();
}

void AccountsListModel::addAccount(Telepathy::Client::Account *account)
{
    kDebug() << "Creating a new AccountItem from account:" << account;
    // Check if the account is already in the model.
    bool found = false;

    foreach(const AccountItem* ai, m_unreadyAccounts)
    {
        if(ai->account() == account)
        {
            found = true;
            break;
        }
    }
    if(!found)
    {
        foreach(const AccountItem* ai, m_readyAccounts)
        {
            if(ai->account() == account)
            {
                found = true;
                break;
            }
        }
    }

    if(found)
    {
       kDebug() << "Requested to add account"
               << account
               << "to model, but it is already present. Doing nothing.";
   }
   else
   {
       AccountItem *item = new AccountItem(account, this);
       m_unreadyAccounts.append(item);
       connect(item, SIGNAL(ready()), this, SLOT(onAccountItemReady()));
       connect(item, SIGNAL(removed()), this, SLOT(onAccountItemRemoved()));
       connect(item, SIGNAL(updated()), this, SLOT(onAccountItemUpdated()));
   }
}

void AccountsListModel::onAccountItemReady()
{
    AccountItem *item = qobject_cast<AccountItem*>(sender());
    Q_ASSERT(item);
    Q_ASSERT(m_unreadyAccounts.contains(item));
    Q_ASSERT(!m_readyAccounts.contains(item));

    beginInsertRows(QModelIndex(), m_readyAccounts.size(), m_readyAccounts.size()+1);
    m_readyAccounts.append(item);
    Q_ASSERT(1==m_unreadyAccounts.removeAll(item));
    endInsertRows();

    Q_ASSERT(!m_unreadyAccounts.contains(item));
    Q_ASSERT(m_readyAccounts.contains(item));
}

void AccountsListModel::onAccountItemRemoved()
{
    // TODO: Implement me!
}

void AccountsListModel::onAccountItemUpdated()
{
    // TODO: Implement me!
}

#include "accounts-list-model.moc"

<commit_msg>Display the accounts under the categories VALID and INVALID in the accounts list view.<commit_after>/*
 * This file is part of telepathy-accounts-kcm
 *
 * Copyright (C) 2009 Collabora Ltd. <http://www.collabora.co.uk/>
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 */

#include "accounts-list-model.h"

#include "account-item.h"

#include <kcategorizedsortfilterproxymodel.h>
#include <kdebug.h>

#include <TelepathyQt4/Client/Account>

AccountsListModel::AccountsListModel(QObject *parent)
 : QAbstractListModel(parent)
{
    m_unreadyAccounts.clear();
    m_readyAccounts.clear();
}

AccountsListModel::~AccountsListModel()
{
    // TODO: Implement me!
}

int AccountsListModel::rowCount(const QModelIndex &index) const
{
    if(index == QModelIndex())
    {
       return m_readyAccounts.size();
    }

    return 0;
}

QVariant AccountsListModel::data(const QModelIndex &index, int role) const
{
    // FIXME: This is a basic implementation just so I can see what's going
    // on while developing this code further. Needs expanding.
    QVariant data;

    switch(role)
    {
    case Qt::DisplayRole:
        data = QVariant(m_readyAccounts.at(index.row())->account()->displayName());
        break;
    case KCategorizedSortFilterProxyModel::CategoryDisplayRole:
        if(m_readyAccounts.at(index.row())->account()->isValidAccount())
        {
            data = QVariant(QString("Valid Accounts"));
        }
        else
        {
            data = QVariant(QString("Invalid Accounts"));
        }
        break;
    case KCategorizedSortFilterProxyModel::CategorySortRole:
        if(m_readyAccounts.at(index.row())->account()->isValidAccount())
        {
            data = QVariant(4);
        }
        else
        {
            data = QVariant(5);
        }
        break;
    default:
        break;
    }

    return data;
}

void AccountsListModel::addAccount(Telepathy::Client::Account *account)
{
    kDebug() << "Creating a new AccountItem from account:" << account;
    // Check if the account is already in the model.
    bool found = false;

    foreach(const AccountItem* ai, m_unreadyAccounts)
    {
        if(ai->account() == account)
        {
            found = true;
            break;
        }
    }
    if(!found)
    {
        foreach(const AccountItem* ai, m_readyAccounts)
        {
            if(ai->account() == account)
            {
                found = true;
                break;
            }
        }
    }

    if(found)
    {
       kDebug() << "Requested to add account"
               << account
               << "to model, but it is already present. Doing nothing.";
   }
   else
   {
       AccountItem *item = new AccountItem(account, this);
       m_unreadyAccounts.append(item);
       connect(item, SIGNAL(ready()), this, SLOT(onAccountItemReady()));
       connect(item, SIGNAL(removed()), this, SLOT(onAccountItemRemoved()));
       connect(item, SIGNAL(updated()), this, SLOT(onAccountItemUpdated()));
   }
}

void AccountsListModel::onAccountItemReady()
{
    AccountItem *item = qobject_cast<AccountItem*>(sender());
    Q_ASSERT(item);
    Q_ASSERT(m_unreadyAccounts.contains(item));
    Q_ASSERT(!m_readyAccounts.contains(item));

    beginInsertRows(QModelIndex(), m_readyAccounts.size(), m_readyAccounts.size()+1);
    m_readyAccounts.append(item);
    Q_ASSERT(1==m_unreadyAccounts.removeAll(item));
    endInsertRows();

    Q_ASSERT(!m_unreadyAccounts.contains(item));
    Q_ASSERT(m_readyAccounts.contains(item));
}

void AccountsListModel::onAccountItemRemoved()
{
    // TODO: Implement me!
}

void AccountsListModel::onAccountItemUpdated()
{
    // TODO: Implement me!
}

#include "accounts-list-model.moc"

<|endoftext|>