<commit_before>/****************************************************************************
 *   Copyright (C) 2012-2015 by Savoir-Faire Linux                          *
 *   Author : Emmanuel Lepage Vallee <emmanuel.lepage@savoirfairelinux.com> *
 *                                                                          *
 *   This library is free software; you can redistribute it and/or          *
 *   modify it under the terms of the GNU Lesser General Public             *
 *   License as published by the Free Software Foundation; either           *
 *   version 2.1 of the License, or (at your option) any later version.     *
 *                                                                          *
 *   This library is distributed in the hope that it will be useful,        *
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of         *
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU      *
 *   Lesser General Public License for more details.                        *
 *                                                                          *
 *   You should have received a copy of the GNU General Public License      *
 *   along with this program.  If not, see <http://www.gnu.org/licenses/>.  *
 ***************************************************************************/
#include "codecmodel.h"

//Qt
#include <QtCore/QDebug>
#include <QtCore/QCoreApplication>
#include <QtCore/QSortFilterProxyModel>

//DRing
#include <account_const.h>

//Ring
#include "account.h"
#include "dbus/configurationmanager.h"

class CodecModelPrivate : public QObject
{
   Q_OBJECT
public:
   CodecModelPrivate(CodecModel* parent);
   ///@struct AudioCodecData store audio codec information
   struct AudioCodecData {
      int              id        ;
      QString          name      ;
      QString          bitrate   ;
      QString          samplerate;
      QString          type      ;
   };

   //Attributes
   QList<AudioCodecData*> m_lAudioCodecs  ;
   QMap<int,bool>         m_lEnabledCodecs;
   Account*               m_pAccount      ;
   QSortFilterProxyModel* m_pAudioProxy   ;
   QSortFilterProxyModel* m_pVideoProxy   ;

   //Helpers
   bool findCodec(int id);

private:
   CodecModel* q_ptr;
};

CodecModelPrivate::CodecModelPrivate(CodecModel* parent) : q_ptr(parent),
m_pAudioProxy(nullptr),m_pVideoProxy(nullptr)
{

}

///Constructor
CodecModel::CodecModel(Account* account) :
QAbstractListModel(account?(QObject*)account:(QObject*)QCoreApplication::instance()), d_ptr(new CodecModelPrivate(this))
{
   d_ptr->m_pAccount = account;
   setObjectName("CodecModel: "+(account?account->id():"Unknown"));
}

CodecModel::~CodecModel()
{
   while (d_ptr->m_lAudioCodecs.size()) {
      CodecModelPrivate::AudioCodecData* c = d_ptr->m_lAudioCodecs[0];
      d_ptr->m_lAudioCodecs.removeAt(0);
      delete c;
   }
}

QHash<int,QByteArray> CodecModel::roleNames() const
{
   static QHash<int, QByteArray> roles = QAbstractItemModel::roleNames();
   static bool initRoles = false;
   if (!initRoles) {
      initRoles = true;
      roles.insert(CodecModel::Role::ID        ,QByteArray("id"));
      roles.insert(CodecModel::Role::NAME      ,QByteArray("name"));
      roles.insert(CodecModel::Role::BITRATE   ,QByteArray("bitrate"));
      roles.insert(CodecModel::Role::SAMPLERATE,QByteArray("samplerate"));
      roles.insert(CodecModel::Role::TYPE      ,QByteArray("type"));
   }
   return roles;
}

///Model data
QVariant CodecModel::data(const QModelIndex& idx, int role) const {
   if(idx.column() == 0      && role == Qt::DisplayRole                   ) {
      return QVariant(d_ptr->m_lAudioCodecs[idx.row()]->name);
   }
   else if(idx.column() == 0 && role == Qt::CheckStateRole                ) {
      return QVariant(d_ptr->m_lEnabledCodecs[d_ptr->m_lAudioCodecs[idx.row()]->id] ? Qt::Checked : Qt::Unchecked);
   }
   else if (idx.column() == 0 && role == CodecModel::Role::NAME       ) {
      return d_ptr->m_lAudioCodecs[idx.row()]->name;
   }
   else if (idx.column() == 0 && role == CodecModel::Role::BITRATE    ) {
      return d_ptr->m_lAudioCodecs[idx.row()]->bitrate;
   }
   else if (idx.column() == 0 && role == CodecModel::Role::SAMPLERATE ) {
      return d_ptr->m_lAudioCodecs[idx.row()]->samplerate;
   }
   else if (idx.column() == 0 && role == CodecModel::Role::ID         ) {
      return d_ptr->m_lAudioCodecs[idx.row()]->id;
   }
   else if (idx.column() == 0 && role == CodecModel::Role::TYPE         ) {
      return d_ptr->m_lAudioCodecs[idx.row()]->type;
   }
   return QVariant();
}

///Number of audio codecs
int CodecModel::rowCount(const QModelIndex& par) const {
   Q_UNUSED(par)
   return d_ptr->m_lAudioCodecs.size();
}

///Model flags
Qt::ItemFlags CodecModel::flags(const QModelIndex& idx) const {
   if (idx.column() == 0)
      return QAbstractItemModel::flags(idx) | Qt::ItemIsUserCheckable | Qt::ItemIsEnabled | Qt::ItemIsSelectable;
   return QAbstractItemModel::flags(idx);
}

///Set audio codec data
bool CodecModel::setData( const QModelIndex& idx, const QVariant &value, int role) {
   if (idx.column() == 0 && role == CodecModel::NAME) {
      d_ptr->m_lAudioCodecs[idx.row()]->name = value.toString();
      emit dataChanged(idx, idx);
      return true;
   }
   else if (idx.column() == 0 && role == CodecModel::BITRATE) {
      d_ptr->m_lAudioCodecs[idx.row()]->bitrate = value.toString();
      emit dataChanged(idx, idx);
      return true;
   }
   else if(idx.column() == 0 && role == Qt::CheckStateRole) {
      d_ptr->m_lEnabledCodecs[d_ptr->m_lAudioCodecs[idx.row()]->id] = value.toBool();
      emit dataChanged(idx, idx);
      return true;
   }
   else if (idx.column() == 0 && role == CodecModel::SAMPLERATE) {
      d_ptr->m_lAudioCodecs[idx.row()]->samplerate = value.toString();
      emit dataChanged(idx, idx);
      return true;
   }
   else if (idx.column() == 0 && role == CodecModel::ID) {
      d_ptr->m_lAudioCodecs[idx.row()]->id = value.toInt();
      emit dataChanged(idx, idx);
      return true;
   }
   else if (idx.column() == 0 && role == CodecModel::TYPE) {
      d_ptr->m_lAudioCodecs[idx.row()]->type = value.toString();
      emit dataChanged(idx, idx);
      return true;
   }
   return false;
}

///Add a new audio codec
QModelIndex CodecModel::add() {
   d_ptr->m_lAudioCodecs << new CodecModelPrivate::AudioCodecData;
   emit dataChanged(index(d_ptr->m_lAudioCodecs.size()-1,0), index(d_ptr->m_lAudioCodecs.size()-1,0));
   return index(d_ptr->m_lAudioCodecs.size()-1,0);
}

///Remove audio codec at 'idx'
void CodecModel::remove(const QModelIndex& idx) {
   if (idx.isValid()) {
      CodecModelPrivate::AudioCodecData* d = d_ptr->m_lAudioCodecs[idx.row()];
      d_ptr->m_lAudioCodecs.removeAt(idx.row());
      delete d;
      emit dataChanged(idx, index(d_ptr->m_lAudioCodecs.size()-1,0));
   }
   else {
      qDebug() << "Failed to remove an invalid audio codec";
   }
}

///Remove everything
void CodecModel::clear()
{
   while(d_ptr->m_lAudioCodecs.size()) {
      CodecModelPrivate::AudioCodecData* d = d_ptr->m_lAudioCodecs[0];
      d_ptr->m_lAudioCodecs.removeAt(0);
      delete d;
   }
   d_ptr->m_lAudioCodecs.clear  ();
   d_ptr->m_lEnabledCodecs.clear();
}

///Increase codec priority
bool CodecModel::moveUp(const QModelIndex& idx)
{
   if(idx.row() > 0 && idx.row() <= rowCount()) {
      CodecModelPrivate::AudioCodecData* data2 = d_ptr->m_lAudioCodecs[idx.row()];
      d_ptr->m_lAudioCodecs.removeAt(idx.row());
      d_ptr->m_lAudioCodecs.insert(idx.row() - 1, data2);
      emit dataChanged(index(idx.row() - 1, 0, QModelIndex()), index(idx.row(), 0, QModelIndex()));
      return true;
   }
   return false;
}

///Decrease codec priority
bool CodecModel::moveDown(const QModelIndex& idx)
{
   if(idx.row() >= 0 && idx.row() < rowCount()) {
      CodecModelPrivate::AudioCodecData* data2 = d_ptr->m_lAudioCodecs[idx.row()];
      d_ptr->m_lAudioCodecs.removeAt(idx.row());
      d_ptr->m_lAudioCodecs.insert(idx.row() + 1, data2);
      emit dataChanged(index(idx.row(), 0, QModelIndex()), index(idx.row() + 1, 0, QModelIndex()));
      return true;
   }
   return false;
}

///Reload the codeclist
void CodecModel::reload()
{
   ConfigurationManagerInterface& configurationManager = DBus::ConfigurationManager::instance();
   QVector<uint> codecIdList = configurationManager.getCodecList();
   if (!d_ptr->m_pAccount->isNew()) {
      QVector<uint> activeCodecList = configurationManager.getActiveCodecList(d_ptr->m_pAccount->id());
      QStringList tmpNameList;

      foreach (const int aCodec, activeCodecList) {
         if (!d_ptr->findCodec(aCodec)) {

            const QMap<QString,QString> codec = configurationManager.getCodecDetails(d_ptr->m_pAccount->id(),aCodec);

            QModelIndex idx = add();
            setData(idx,codec[ DRing::Account::ConfProperties::CodecInfo::NAME        ] ,CodecModel::Role::NAME       );
            setData(idx,codec[ DRing::Account::ConfProperties::CodecInfo::SAMPLE_RATE ] ,CodecModel::Role::SAMPLERATE );
            setData(idx,codec[ DRing::Account::ConfProperties::CodecInfo::BITRATE     ] ,CodecModel::Role::BITRATE    );
            setData(idx,codec[ DRing::Account::ConfProperties::CodecInfo::TYPE        ] ,CodecModel::Role::TYPE       );
            setData(idx,QString::number(aCodec)  ,CodecModel::Role::ID         );
            setData(idx, Qt::Checked ,Qt::CheckStateRole               );

            if (codecIdList.indexOf(aCodec)!=-1)
               codecIdList.remove(codecIdList.indexOf(aCodec));
         }
      }
   }

   foreach (const int aCodec, codecIdList) {
      if (!d_ptr->findCodec(aCodec)) {
         const QMap<QString,QString> codec = configurationManager.getCodecDetails(d_ptr->m_pAccount->id(),aCodec);
         const QModelIndex& idx = add();
         setData(idx,codec[ DRing::Account::ConfProperties::CodecInfo::NAME        ] ,CodecModel::Role::NAME       );
         setData(idx,codec[ DRing::Account::ConfProperties::CodecInfo::SAMPLE_RATE ] ,CodecModel::Role::SAMPLERATE );
         setData(idx,codec[ DRing::Account::ConfProperties::CodecInfo::BITRATE     ] ,CodecModel::Role::BITRATE    );
         setData(idx,codec[ DRing::Account::ConfProperties::CodecInfo::TYPE        ] ,CodecModel::Role::TYPE       );
         setData(idx,QString::number(aCodec)  ,CodecModel::Role::ID         );
         setData(idx, Qt::Unchecked ,Qt::CheckStateRole);
      }
   }
}

///Save details
void CodecModel::save()
{
   VectorUInt _codecList;
   for (int i=0; i < rowCount();i++) {
      const QModelIndex& idx = index(i,0);
      if (data(idx,Qt::CheckStateRole) == Qt::Checked) {
         _codecList << data(idx,CodecModel::Role::ID).toInt();
      }
   }

   ConfigurationManagerInterface& configurationManager = DBus::ConfigurationManager::instance();
   configurationManager.setActiveCodecList(d_ptr->m_pAccount->id(), _codecList);
}

///Check is a codec is already in the list
bool CodecModelPrivate::findCodec(int id)
{
   foreach(const AudioCodecData* data, m_lAudioCodecs) {
      if (data->id == id)
         return true;
   }
   return false;
}

QSortFilterProxyModel* CodecModel::audioCodecs() const
{
    if (!d_ptr->m_pAudioProxy) {
        d_ptr->m_pAudioProxy = new QSortFilterProxyModel(const_cast<CodecModel*>(this));
        d_ptr->m_pAudioProxy->setSourceModel(const_cast<CodecModel*>(this));
        d_ptr->m_pAudioProxy->setFilterRole(CodecModel::Role::TYPE);
        d_ptr->m_pAudioProxy->setFilterFixedString("AUDIO");
    }
    return d_ptr->m_pAudioProxy;
}

QSortFilterProxyModel* CodecModel::videoCodecs() const
{
    if (!d_ptr->m_pVideoProxy) {
        d_ptr->m_pVideoProxy = new QSortFilterProxyModel(const_cast<CodecModel*>(this));
        d_ptr->m_pVideoProxy->setSourceModel(const_cast<CodecModel*>(this));
        d_ptr->m_pVideoProxy->setFilterRole(CodecModel::Role::TYPE);
        d_ptr->m_pVideoProxy->setFilterFixedString("VIDEO");
    }
    return d_ptr->m_pVideoProxy;
}

#include <codecmodel.moc>
<commit_msg>codecmodel: remove unnecessary check<commit_after>/****************************************************************************
 *   Copyright (C) 2012-2015 by Savoir-Faire Linux                          *
 *   Author : Emmanuel Lepage Vallee <emmanuel.lepage@savoirfairelinux.com> *
 *                                                                          *
 *   This library is free software; you can redistribute it and/or          *
 *   modify it under the terms of the GNU Lesser General Public             *
 *   License as published by the Free Software Foundation; either           *
 *   version 2.1 of the License, or (at your option) any later version.     *
 *                                                                          *
 *   This library is distributed in the hope that it will be useful,        *
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of         *
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU      *
 *   Lesser General Public License for more details.                        *
 *                                                                          *
 *   You should have received a copy of the GNU General Public License      *
 *   along with this program.  If not, see <http://www.gnu.org/licenses/>.  *
 ***************************************************************************/
#include "codecmodel.h"

//Qt
#include <QtCore/QDebug>
#include <QtCore/QCoreApplication>
#include <QtCore/QSortFilterProxyModel>

//DRing
#include <account_const.h>

//Ring
#include "account.h"
#include "dbus/configurationmanager.h"

class CodecModelPrivate : public QObject
{
   Q_OBJECT
public:
   CodecModelPrivate(CodecModel* parent);
   ///@struct AudioCodecData store audio codec information
   struct AudioCodecData {
      int              id        ;
      QString          name      ;
      QString          bitrate   ;
      QString          samplerate;
      QString          type      ;
   };

   //Attributes
   QList<AudioCodecData*> m_lAudioCodecs  ;
   QMap<int,bool>         m_lEnabledCodecs;
   Account*               m_pAccount      ;
   QSortFilterProxyModel* m_pAudioProxy   ;
   QSortFilterProxyModel* m_pVideoProxy   ;

   //Helpers
   bool findCodec(int id);

private:
   CodecModel* q_ptr;
};

CodecModelPrivate::CodecModelPrivate(CodecModel* parent) : q_ptr(parent),
m_pAudioProxy(nullptr),m_pVideoProxy(nullptr)
{

}

///Constructor
CodecModel::CodecModel(Account* account) :
QAbstractListModel(account?(QObject*)account:(QObject*)QCoreApplication::instance()), d_ptr(new CodecModelPrivate(this))
{
   d_ptr->m_pAccount = account;
   setObjectName("CodecModel: "+(account?account->id():"Unknown"));
}

CodecModel::~CodecModel()
{
   while (d_ptr->m_lAudioCodecs.size()) {
      CodecModelPrivate::AudioCodecData* c = d_ptr->m_lAudioCodecs[0];
      d_ptr->m_lAudioCodecs.removeAt(0);
      delete c;
   }
}

QHash<int,QByteArray> CodecModel::roleNames() const
{
   static QHash<int, QByteArray> roles = QAbstractItemModel::roleNames();
   static bool initRoles = false;
   if (!initRoles) {
      initRoles = true;
      roles.insert(CodecModel::Role::ID        ,QByteArray("id"));
      roles.insert(CodecModel::Role::NAME      ,QByteArray("name"));
      roles.insert(CodecModel::Role::BITRATE   ,QByteArray("bitrate"));
      roles.insert(CodecModel::Role::SAMPLERATE,QByteArray("samplerate"));
      roles.insert(CodecModel::Role::TYPE      ,QByteArray("type"));
   }
   return roles;
}

///Model data
QVariant CodecModel::data(const QModelIndex& idx, int role) const {
   if(idx.column() == 0      && role == Qt::DisplayRole                   ) {
      return QVariant(d_ptr->m_lAudioCodecs[idx.row()]->name);
   }
   else if(idx.column() == 0 && role == Qt::CheckStateRole                ) {
      return QVariant(d_ptr->m_lEnabledCodecs[d_ptr->m_lAudioCodecs[idx.row()]->id] ? Qt::Checked : Qt::Unchecked);
   }
   else if (idx.column() == 0 && role == CodecModel::Role::NAME       ) {
      return d_ptr->m_lAudioCodecs[idx.row()]->name;
   }
   else if (idx.column() == 0 && role == CodecModel::Role::BITRATE    ) {
      return d_ptr->m_lAudioCodecs[idx.row()]->bitrate;
   }
   else if (idx.column() == 0 && role == CodecModel::Role::SAMPLERATE ) {
      return d_ptr->m_lAudioCodecs[idx.row()]->samplerate;
   }
   else if (idx.column() == 0 && role == CodecModel::Role::ID         ) {
      return d_ptr->m_lAudioCodecs[idx.row()]->id;
   }
   else if (idx.column() == 0 && role == CodecModel::Role::TYPE         ) {
      return d_ptr->m_lAudioCodecs[idx.row()]->type;
   }
   return QVariant();
}

///Number of audio codecs
int CodecModel::rowCount(const QModelIndex& par) const {
   Q_UNUSED(par)
   return d_ptr->m_lAudioCodecs.size();
}

///Model flags
Qt::ItemFlags CodecModel::flags(const QModelIndex& idx) const {
   if (idx.column() == 0)
      return QAbstractItemModel::flags(idx) | Qt::ItemIsUserCheckable | Qt::ItemIsEnabled | Qt::ItemIsSelectable;
   return QAbstractItemModel::flags(idx);
}

///Set audio codec data
bool CodecModel::setData( const QModelIndex& idx, const QVariant &value, int role) {
   if (idx.column() == 0 && role == CodecModel::NAME) {
      d_ptr->m_lAudioCodecs[idx.row()]->name = value.toString();
      emit dataChanged(idx, idx);
      return true;
   }
   else if (idx.column() == 0 && role == CodecModel::BITRATE) {
      d_ptr->m_lAudioCodecs[idx.row()]->bitrate = value.toString();
      emit dataChanged(idx, idx);
      return true;
   }
   else if(idx.column() == 0 && role == Qt::CheckStateRole) {
      d_ptr->m_lEnabledCodecs[d_ptr->m_lAudioCodecs[idx.row()]->id] = value.toBool();
      emit dataChanged(idx, idx);
      return true;
   }
   else if (idx.column() == 0 && role == CodecModel::SAMPLERATE) {
      d_ptr->m_lAudioCodecs[idx.row()]->samplerate = value.toString();
      emit dataChanged(idx, idx);
      return true;
   }
   else if (idx.column() == 0 && role == CodecModel::ID) {
      d_ptr->m_lAudioCodecs[idx.row()]->id = value.toInt();
      emit dataChanged(idx, idx);
      return true;
   }
   else if (idx.column() == 0 && role == CodecModel::TYPE) {
      d_ptr->m_lAudioCodecs[idx.row()]->type = value.toString();
      emit dataChanged(idx, idx);
      return true;
   }
   return false;
}

///Add a new audio codec
QModelIndex CodecModel::add() {
   d_ptr->m_lAudioCodecs << new CodecModelPrivate::AudioCodecData;
   emit dataChanged(index(d_ptr->m_lAudioCodecs.size()-1,0), index(d_ptr->m_lAudioCodecs.size()-1,0));
   return index(d_ptr->m_lAudioCodecs.size()-1,0);
}

///Remove audio codec at 'idx'
void CodecModel::remove(const QModelIndex& idx) {
   if (idx.isValid()) {
      CodecModelPrivate::AudioCodecData* d = d_ptr->m_lAudioCodecs[idx.row()];
      d_ptr->m_lAudioCodecs.removeAt(idx.row());
      delete d;
      emit dataChanged(idx, index(d_ptr->m_lAudioCodecs.size()-1,0));
   }
   else {
      qDebug() << "Failed to remove an invalid audio codec";
   }
}

///Remove everything
void CodecModel::clear()
{
   while(d_ptr->m_lAudioCodecs.size()) {
      CodecModelPrivate::AudioCodecData* d = d_ptr->m_lAudioCodecs[0];
      d_ptr->m_lAudioCodecs.removeAt(0);
      delete d;
   }
   d_ptr->m_lAudioCodecs.clear  ();
   d_ptr->m_lEnabledCodecs.clear();
}

///Increase codec priority
bool CodecModel::moveUp(const QModelIndex& idx)
{
   if(idx.row() > 0 && idx.row() <= rowCount()) {
      CodecModelPrivate::AudioCodecData* data2 = d_ptr->m_lAudioCodecs[idx.row()];
      d_ptr->m_lAudioCodecs.removeAt(idx.row());
      d_ptr->m_lAudioCodecs.insert(idx.row() - 1, data2);
      emit dataChanged(index(idx.row() - 1, 0, QModelIndex()), index(idx.row(), 0, QModelIndex()));
      return true;
   }
   return false;
}

///Decrease codec priority
bool CodecModel::moveDown(const QModelIndex& idx)
{
   if(idx.row() >= 0 && idx.row() < rowCount()) {
      CodecModelPrivate::AudioCodecData* data2 = d_ptr->m_lAudioCodecs[idx.row()];
      d_ptr->m_lAudioCodecs.removeAt(idx.row());
      d_ptr->m_lAudioCodecs.insert(idx.row() + 1, data2);
      emit dataChanged(index(idx.row(), 0, QModelIndex()), index(idx.row() + 1, 0, QModelIndex()));
      return true;
   }
   return false;
}

///Reload the codeclist
void CodecModel::reload()
{
   ConfigurationManagerInterface& configurationManager = DBus::ConfigurationManager::instance();
   QVector<uint> codecIdList = configurationManager.getCodecList();
      QVector<uint> activeCodecList = configurationManager.getActiveCodecList(d_ptr->m_pAccount->id());
      QStringList tmpNameList;

  foreach (const int aCodec, activeCodecList) {
     if (!d_ptr->findCodec(aCodec)) {

        const QMap<QString,QString> codec = configurationManager.getCodecDetails(d_ptr->m_pAccount->id(),aCodec);

        QModelIndex idx = add();
        setData(idx,codec[ DRing::Account::ConfProperties::CodecInfo::NAME        ] ,CodecModel::Role::NAME       );
        setData(idx,codec[ DRing::Account::ConfProperties::CodecInfo::SAMPLE_RATE ] ,CodecModel::Role::SAMPLERATE );
        setData(idx,codec[ DRing::Account::ConfProperties::CodecInfo::BITRATE     ] ,CodecModel::Role::BITRATE    );
        setData(idx,codec[ DRing::Account::ConfProperties::CodecInfo::TYPE        ] ,CodecModel::Role::TYPE       );
        setData(idx,QString::number(aCodec)  ,CodecModel::Role::ID         );
        setData(idx, Qt::Checked ,Qt::CheckStateRole               );

        if (codecIdList.indexOf(aCodec)!=-1)
           codecIdList.remove(codecIdList.indexOf(aCodec));
     }
  }

   foreach (const int aCodec, codecIdList) {
      if (!d_ptr->findCodec(aCodec)) {
         const QMap<QString,QString> codec = configurationManager.getCodecDetails(d_ptr->m_pAccount->id(),aCodec);
         const QModelIndex& idx = add();
         setData(idx,codec[ DRing::Account::ConfProperties::CodecInfo::NAME        ] ,CodecModel::Role::NAME       );
         setData(idx,codec[ DRing::Account::ConfProperties::CodecInfo::SAMPLE_RATE ] ,CodecModel::Role::SAMPLERATE );
         setData(idx,codec[ DRing::Account::ConfProperties::CodecInfo::BITRATE     ] ,CodecModel::Role::BITRATE    );
         setData(idx,codec[ DRing::Account::ConfProperties::CodecInfo::TYPE        ] ,CodecModel::Role::TYPE       );
         setData(idx,QString::number(aCodec)  ,CodecModel::Role::ID         );
         setData(idx, Qt::Unchecked ,Qt::CheckStateRole);
      }
   }
}

///Save details
void CodecModel::save()
{
   VectorUInt _codecList;
   for (int i=0; i < rowCount();i++) {
      const QModelIndex& idx = index(i,0);
      if (data(idx,Qt::CheckStateRole) == Qt::Checked) {
         _codecList << data(idx,CodecModel::Role::ID).toInt();
      }
   }

   ConfigurationManagerInterface& configurationManager = DBus::ConfigurationManager::instance();
   configurationManager.setActiveCodecList(d_ptr->m_pAccount->id(), _codecList);
}

///Check is a codec is already in the list
bool CodecModelPrivate::findCodec(int id)
{
   foreach(const AudioCodecData* data, m_lAudioCodecs) {
      if (data->id == id)
         return true;
   }
   return false;
}

QSortFilterProxyModel* CodecModel::audioCodecs() const
{
    if (!d_ptr->m_pAudioProxy) {
        d_ptr->m_pAudioProxy = new QSortFilterProxyModel(const_cast<CodecModel*>(this));
        d_ptr->m_pAudioProxy->setSourceModel(const_cast<CodecModel*>(this));
        d_ptr->m_pAudioProxy->setFilterRole(CodecModel::Role::TYPE);
        d_ptr->m_pAudioProxy->setFilterFixedString("AUDIO");
    }
    return d_ptr->m_pAudioProxy;
}

QSortFilterProxyModel* CodecModel::videoCodecs() const
{
    if (!d_ptr->m_pVideoProxy) {
        d_ptr->m_pVideoProxy = new QSortFilterProxyModel(const_cast<CodecModel*>(this));
        d_ptr->m_pVideoProxy->setSourceModel(const_cast<CodecModel*>(this));
        d_ptr->m_pVideoProxy->setFilterRole(CodecModel::Role::TYPE);
        d_ptr->m_pVideoProxy->setFilterFixedString("VIDEO");
    }
    return d_ptr->m_pVideoProxy;
}

#include <codecmodel.moc>
<|endoftext|>


<commit_before>//
// Copyright (c) 2013-2017 Christoph Malek
// See LICENSE for more information.
//

#ifndef RJ_CORE_GAME_WINDOW_HPP
#define RJ_CORE_GAME_WINDOW_HPP

#include "game_updater.hpp"
#include <rectojump/shared/input.hpp>

#include <mlk/log/log.h>
#include <mlk/signals_slots/slot.h>
#include <mlk/time/time.h>
#include <mlk/types/types.h>

#include <SFML/Graphics.hpp>

namespace rj
{
	using window_style = int;

	class game_window
	{
		mlk::uint m_width, m_height;
		std::string m_title{"Recto Jump"};
		sf::RenderWindow m_window;
		window_style m_windowstyles;
		bool m_running{false};
		bool m_need_recreate{false};

		game_updater m_game_updater;
		input<game_window>& m_input{input<game_window>::get()};

		mlk::event_delegates<sf::Event::EventType, sf::Event> m_on_event;

	public:
		mlk::slot<> on_stop;

		game_window(const vec2u& size, bool fullscreen = false)
			: m_width{size.x}, m_height{size.y}
		{
			m_window.setFramerateLimit(60);
			this->set_fullscreen(fullscreen);
			this->init();
		}

		// interface
		void start()
		{
			if(m_running) return;

			this->prepare_start();
			while(m_running)
			{
				if(m_need_recreate) this->recreate();

				m_game_updater.start_pt();

				// update
				this->update_events();
				m_input.update();
				m_game_updater.update();

				// render
				m_window.clear();
				m_game_updater.render();
				m_window.display();

				m_game_updater.end_pt();
			}
		}

		void stop() noexcept
		{
			on_stop();
			m_running = false;
		}

		auto& on_event(sf::Event::EventType type) { return m_on_event[type]; }

		template <typename... Args>
		void draw(Args&&... args)
		{
			m_window.draw(std::forward<Args>(args)...);
		}

		void toggle_fullscreen() noexcept
		{
			m_windowstyles ^= sf::Style::Fullscreen;
			m_need_recreate = true;
		}

		void toggle_titlebar() noexcept
		{
			m_windowstyles ^= sf::Style::Titlebar;
			m_need_recreate = true;
		}

		// setters
		void set_framereate_limit(mlk::uint limit) noexcept
		{
			m_window.setFramerateLimit(limit);
		}

		void set_size(const vec2u& size) noexcept { m_window.setSize(size); }

		void set_position(const vec2i& position) noexcept
		{
			m_window.setPosition(position);
		}

		void set_fullscreen(bool b) noexcept
		{
			if(b == (m_windowstyles & sf::Style::Fullscreen)) return;
			b ? m_windowstyles |= sf::Style::Fullscreen
			  : m_windowstyles &= ~sf::Style::Fullscreen;
			m_need_recreate = true;
		}

		void set_titlebar(bool b) noexcept
		{
			if(b == (m_windowstyles & sf::Style::Titlebar)) return;
			b ? m_windowstyles |= sf::Style::Titlebar
			  : m_windowstyles &= ~sf::Style::Titlebar;
			m_need_recreate = true;
		}

		void set_view(const sf::View& v) noexcept { m_window.setView(v); }

		// getters
		sf::RenderWindow& get_renderwindow() noexcept { return m_window; }

		game_updater& get_updater() noexcept { return m_game_updater; }

		vec2u get_size() const noexcept { return m_window.getSize(); }

		vec2i get_position() const noexcept { return m_window.getPosition(); }

		bool get_fullscreen() const noexcept
		{
			return m_windowstyles & sf::Style::Fullscreen;
		}

		bool get_titlebar() const noexcept
		{
			return m_windowstyles & sf::Style::Titlebar;
		}

	private:
		void init()
		{
			m_input.init(this);
			m_windowstyles |= sf::Style::Default;
			this->recreate();
		}

		void prepare_start() noexcept
		{
			m_running = true;
			mlk::lout("rj::game_window", true) << "starting gamewindow";
		}

		void update_events() noexcept
		{
			sf::Event ev;
			while(m_window.pollEvent(ev))
			{
				switch(ev.type)
				{
					case sf::Event::EventType::Closed:
						this->stop();
						break;
					case sf::Event::EventType::KeyPressed:
						m_input.key_pressed(ev.key.code);
						break;
					case sf::Event::EventType::KeyReleased:
						m_input.key_released(ev.key.code);
						break;
					case sf::Event::EventType::MouseButtonPressed:
						m_input.btn_pressed(ev.mouseButton.button);
						break;
					case sf::Event::EventType::MouseButtonReleased:
						m_input.btn_released(ev.mouseButton.button);
						break;
					case sf::Event::EventType::MouseWheelMoved:
						m_input.mousewheel_moved(ev.mouseWheel.delta);
						break;
					default:
						break;
				}

				// call custom on_event
				m_on_event[ev.type](ev);
			}
		}

		void recreate()
		{
			m_window.close();
			m_window.create({m_width, m_height}, m_title, m_windowstyles);
			m_need_recreate = false;
		}
	};
}// namespace rj

#endif// RJ_CORE_GAME_WINDOW_HPP
<commit_msg>rem testing<commit_after>//
// Copyright (c) 2013-2017 Christoph Malek
// See LICENSE for more information.
//

#ifndef RJ_CORE_GAME_WINDOW_HPP
#define RJ_CORE_GAME_WINDOW_HPP

#include "game_updater.hpp"
#include <rectojump/shared/input.hpp>

#include <mlk/log/log.h>
#include <mlk/signals_slots/slot.h>
#include <mlk/time/time.h>
#include <mlk/types/types.h>

#include <SFML/Graphics.hpp>

namespace rj
{
	using window_style = int;

	class game_window
	{
		mlk::uint m_width, m_height;
		std::string m_title{"Recto Jump"};
		sf::RenderWindow m_window;
		window_style m_windowstyles;
		bool m_running{false};
		bool m_need_recreate{false};

		game_updater m_game_updater;
		input<game_window>& m_input{input<game_window>::get()};

		mlk::event_delegates<sf::Event::EventType, sf::Event> m_on_event;

	public:
		mlk::slot<> on_stop;

		game_window(const vec2u& size, bool fullscreen = false)
			: m_width{size.x}, m_height{size.y}
		{
			this->set_fullscreen(fullscreen);
			this->init();
		}

		// interface
		void start()
		{
			if(m_running) return;

			this->prepare_start();
			while(m_running)
			{
				if(m_need_recreate) this->recreate();

				m_game_updater.start_pt();

				// update
				this->update_events();
				m_input.update();
				m_game_updater.update();

				// render
				m_window.clear();
				m_game_updater.render();
				m_window.display();

				m_game_updater.end_pt();
			}
		}

		void stop() noexcept
		{
			on_stop();
			m_running = false;
		}

		auto& on_event(sf::Event::EventType type) { return m_on_event[type]; }

		template <typename... Args>
		void draw(Args&&... args)
		{
			m_window.draw(std::forward<Args>(args)...);
		}

		void toggle_fullscreen() noexcept
		{
			m_windowstyles ^= sf::Style::Fullscreen;
			m_need_recreate = true;
		}

		void toggle_titlebar() noexcept
		{
			m_windowstyles ^= sf::Style::Titlebar;
			m_need_recreate = true;
		}

		// setters
		void set_framereate_limit(mlk::uint limit) noexcept
		{
			m_window.setFramerateLimit(limit);
		}

		void set_size(const vec2u& size) noexcept { m_window.setSize(size); }

		void set_position(const vec2i& position) noexcept
		{
			m_window.setPosition(position);
		}

		void set_fullscreen(bool b) noexcept
		{
			if(b == (m_windowstyles & sf::Style::Fullscreen)) return;
			b ? m_windowstyles |= sf::Style::Fullscreen
			  : m_windowstyles &= ~sf::Style::Fullscreen;
			m_need_recreate = true;
		}

		void set_titlebar(bool b) noexcept
		{
			if(b == (m_windowstyles & sf::Style::Titlebar)) return;
			b ? m_windowstyles |= sf::Style::Titlebar
			  : m_windowstyles &= ~sf::Style::Titlebar;
			m_need_recreate = true;
		}

		void set_view(const sf::View& v) noexcept { m_window.setView(v); }

		// getters
		sf::RenderWindow& get_renderwindow() noexcept { return m_window; }

		game_updater& get_updater() noexcept { return m_game_updater; }

		vec2u get_size() const noexcept { return m_window.getSize(); }

		vec2i get_position() const noexcept { return m_window.getPosition(); }

		bool get_fullscreen() const noexcept
		{
			return m_windowstyles & sf::Style::Fullscreen;
		}

		bool get_titlebar() const noexcept
		{
			return m_windowstyles & sf::Style::Titlebar;
		}

	private:
		void init()
		{
			m_input.init(this);
			m_windowstyles |= sf::Style::Default;
			this->recreate();
		}

		void prepare_start() noexcept
		{
			m_running = true;
			mlk::lout("rj::game_window", true) << "starting gamewindow";
		}

		void update_events() noexcept
		{
			sf::Event ev;
			while(m_window.pollEvent(ev))
			{
				switch(ev.type)
				{
					case sf::Event::EventType::Closed:
						this->stop();
						break;
					case sf::Event::EventType::KeyPressed:
						m_input.key_pressed(ev.key.code);
						break;
					case sf::Event::EventType::KeyReleased:
						m_input.key_released(ev.key.code);
						break;
					case sf::Event::EventType::MouseButtonPressed:
						m_input.btn_pressed(ev.mouseButton.button);
						break;
					case sf::Event::EventType::MouseButtonReleased:
						m_input.btn_released(ev.mouseButton.button);
						break;
					case sf::Event::EventType::MouseWheelMoved:
						m_input.mousewheel_moved(ev.mouseWheel.delta);
						break;
					default:
						break;
				}

				// call custom on_event
				m_on_event[ev.type](ev);
			}
		}

		void recreate()
		{
			m_window.close();
			m_window.create({m_width, m_height}, m_title, m_windowstyles);
			m_need_recreate = false;
		}
	};
}// namespace rj

#endif// RJ_CORE_GAME_WINDOW_HPP
<|endoftext|>


<commit_before>// This file is distributed under the MIT license.
// See the LICENSE file for details.

namespace visionaray
{
namespace simd
{

//-------------------------------------------------------------------------------------------------
// Functions to pack four materials into a single SIMD material
//

inline matte<float4> pack(
        matte<float> const& m1,
        matte<float> const& m2,
        matte<float> const& m3,
        matte<float> const& m4
        )
{
    matte<float4> result;

    result.set_ca( pack(m1.get_ca(), m2.get_ca(), m3.get_ca(), m4.get_ca()) );
    result.set_cd( pack(m1.get_cd(), m2.get_cd(), m3.get_cd(), m4.get_cd()) );
    result.set_ka( float4(m1.get_ka(), m2.get_ka(), m3.get_ka(), m4.get_ka()) );
    result.set_kd( float4(m1.get_kd(), m2.get_kd(), m3.get_kd(), m4.get_kd()) );

    return result;
}

inline mirror<float4> pack(
        mirror<float> const& m1,
        mirror<float> const& m2,
        mirror<float> const& m3,
        mirror<float> const& m4
        )
{
    mirror<float4> result;

    result.set_cr( pack(m1.get_cr(), m2.get_cr(), m3.get_cr(), m4.get_cr()) );
    result.set_kr( float4(m1.get_kr(), m2.get_kr(), m3.get_kr(), m4.get_kr()) );

    return result;
}

inline plastic<float4> pack(
        plastic<float> const& m1,
        plastic<float> const& m2,
        plastic<float> const& m3,
        plastic<float> const& m4
        )
{
    plastic<float4> result;

    result.set_ca( pack(m1.get_ca(), m2.get_ca(), m3.get_ca(), m4.get_ca()) );
    result.set_cd( pack(m1.get_cd(), m2.get_cd(), m3.get_cd(), m4.get_cd()) );
    result.set_cs( pack(m1.get_cs(), m2.get_cs(), m3.get_cs(), m4.get_cs()) );
    result.set_ka( float4(m1.get_ka(), m2.get_ka(), m3.get_ka(), m4.get_ka()) );
    result.set_kd( float4(m1.get_kd(), m2.get_kd(), m3.get_kd(), m4.get_kd()) );
    result.set_ks( float4(m1.get_ks(), m2.get_ks(), m3.get_ks(), m4.get_ks()) );
    result.set_specular_exp( float4(
            m1.get_specular_exp(),
            m2.get_specular_exp(),
            m3.get_specular_exp(),
            m4.get_specular_exp()
            ) );

    return result;
}

inline emissive<float4> pack(
        emissive<float> const& m1,
        emissive<float> const& m2,
        emissive<float> const& m3,
        emissive<float> const& m4
        )
{
    emissive<float4> result;

    result.set_ce(
            pack(m1.get_ce(),
            m2.get_ce(),
            m3.get_ce(),
            m4.get_ce())
            );

    result.set_ls( float4(
            m1.get_ls(),
            m2.get_ls(),
            m3.get_ls(),
            m4.get_ls())
            );

    return result;
}

#if VSNRAY_SIMD_ISA >= VSNRAY_SIMD_ISA_AVX

//-------------------------------------------------------------------------------------------------
// Functions to pack eight materials into a single SIMD material
//

inline emissive<float8> pack(
        emissive<float> const& m1,
        emissive<float> const& m2,
        emissive<float> const& m3,
        emissive<float> const& m4,
        emissive<float> const& m5,
        emissive<float> const& m6,
        emissive<float> const& m7,
        emissive<float> const& m8
        )
{
    emissive<float8> result;

    result.set_ce(pack(
            m1.get_ce(), m2.get_ce(), m3.get_ce(), m4.get_ce(),
            m5.get_ce(), m6.get_ce(), m7.get_ce(), m8.get_ce()
            ));

    result.set_ls(float8(
            m1.get_ls(), m2.get_ls(), m3.get_ls(), m4.get_ls(),
            m5.get_ls(), m6.get_ls(), m7.get_ls(), m8.get_ls()
            ));

    return result;
}

inline matte<float8> pack(
        matte<float> const& m1,
        matte<float> const& m2,
        matte<float> const& m3,
        matte<float> const& m4,
        matte<float> const& m5,
        matte<float> const& m6,
        matte<float> const& m7,
        matte<float> const& m8
        )
{
    matte<float8> result;

    result.set_ca(pack(
            m1.get_ca(), m2.get_ca(), m3.get_ca(), m4.get_ca(),
            m5.get_ca(), m6.get_ca(), m7.get_ca(), m8.get_ca()
            ));
    result.set_cd(pack(
            m1.get_cd(), m2.get_cd(), m3.get_cd(), m4.get_cd(),
            m5.get_cd(), m6.get_cd(), m7.get_cd(), m8.get_cd()
            ));
    result.set_ka(float8(
            m1.get_ka(), m2.get_ka(), m3.get_ka(), m4.get_ka(),
            m5.get_ka(), m6.get_ka(), m7.get_ka(), m8.get_ka()
            ));
    result.set_kd(float8(
            m1.get_kd(), m2.get_kd(), m3.get_kd(), m4.get_kd(),
            m5.get_kd(), m6.get_kd(), m7.get_kd(), m8.get_kd()
            ));

    return result;
}

inline mirror<float8> pack(
        mirror<float> const& m1,
        mirror<float> const& m2,
        mirror<float> const& m3,
        mirror<float> const& m4,
        mirror<float> const& m5,
        mirror<float> const& m6,
        mirror<float> const& m7,
        mirror<float> const& m8
        )
{
    mirror<float8> result;

    result.set_cr(pack(
            m1.get_cr(), m2.get_cr(), m3.get_cr(), m4.get_cr(),
            m5.get_cr(), m6.get_cr(), m7.get_cr(), m8.get_cr()
            ));
    result.set_kr(float8(
            m1.get_kr(), m2.get_kr(), m3.get_kr(), m4.get_kr(),
            m5.get_kr(), m6.get_kr(), m7.get_kr(), m8.get_kr()
            ));

    return result;
}

inline plastic<float8> pack(
        plastic<float> const& m1,
        plastic<float> const& m2,
        plastic<float> const& m3,
        plastic<float> const& m4,
        plastic<float> const& m5,
        plastic<float> const& m6,
        plastic<float> const& m7,
        plastic<float> const& m8
        )
{
    using C = spectrum<float>;

    C ca[8]                         = { m1.get_ca(), m2.get_ca(), m3.get_ca(), m4.get_ca(),
                                        m5.get_ca(), m6.get_ca(), m7.get_ca(), m8.get_ca() };
    C cd[8]                         = { m1.get_cd(), m2.get_cd(), m3.get_cd(), m4.get_cd(),
                                        m5.get_cd(), m6.get_cd(), m7.get_cd(), m8.get_cd() };
    C cs[8]                         = { m1.get_cs(), m2.get_cs(), m3.get_cs(), m4.get_cs(),
                                        m5.get_cs(), m6.get_cs(), m7.get_cs(), m8.get_cs() };
    VSNRAY_ALIGN(32) float ka[8]    = { m1.get_ka(), m2.get_ka(), m3.get_ka(), m4.get_ka(),
                                        m5.get_ka(), m6.get_ka(), m7.get_ka(), m8.get_ka() };
    VSNRAY_ALIGN(32) float kd[8]    = { m1.get_kd(), m2.get_kd(), m3.get_kd(), m4.get_kd(),
                                        m5.get_kd(), m6.get_kd(), m7.get_kd(), m8.get_kd() };
    VSNRAY_ALIGN(32) float ks[8]    = { m1.get_ks(), m2.get_ks(), m3.get_ks(), m4.get_ks(),
                                        m5.get_ks(), m6.get_ks(), m7.get_ks(), m8.get_ks() };
    VSNRAY_ALIGN(32) float exp[8]   = { m1.get_specular_exp(), m2.get_specular_exp(), m3.get_specular_exp(), m4.get_specular_exp(),
                                        m5.get_specular_exp(), m6.get_specular_exp(), m7.get_specular_exp(), m8.get_specular_exp() };

    plastic<float8> result;

    spectrum<float8> ca8;
    spectrum<float8> cd8;
    spectrum<float8> cs8;

    for (size_t d = 0; d < C::num_samples; ++d)
    {
        ca8[d] = float8(
                ca[0][d],
                ca[1][d],
                ca[2][d],
                ca[3][d],
                ca[4][d],
                ca[5][d],
                ca[6][d],
                ca[7][d]
                );

        cd8[d] = float8(
                cd[0][d],
                cd[1][d],
                cd[2][d],
                cd[3][d],
                cd[4][d],
                cd[5][d],
                cd[6][d],
                cd[7][d]
                );

        cs8[d] = float8(
                cs[0][d],
                cs[1][d],
                cs[2][d],
                cs[3][d],
                cs[4][d],
                cs[5][d],
                cs[6][d],
                cs[7][d]
                );
    }

    result.set_ca(ca8);
    result.set_cd(cd8);
    result.set_cs(cs8);
    result.set_ka(ka);
    result.set_kd(kd);
    result.set_ks(ks);
    result.set_specular_exp(exp);

    return result;
}

#endif // VSNRAY_SIMD_ISA >= VSNRAY_SIMD_ISA_AVX

} // simd
} // visioanray
<commit_msg>Code layout changes<commit_after>// This file is distributed under the MIT license.
// See the LICENSE file for details.

namespace visionaray
{
namespace simd
{

//-------------------------------------------------------------------------------------------------
// Functions to pack four materials into a single SIMD material
//

inline emissive<float4> pack(
        emissive<float> const& m1,
        emissive<float> const& m2,
        emissive<float> const& m3,
        emissive<float> const& m4
        )
{
    emissive<float4> result;

    result.set_ce( pack(m1.get_ce(), m2.get_ce(), m3.get_ce(), m4.get_ce()) );
    result.set_ls( float4(m1.get_ls(), m2.get_ls(), m3.get_ls(), m4.get_ls()) );

    return result;
}

inline matte<float4> pack(
        matte<float> const& m1,
        matte<float> const& m2,
        matte<float> const& m3,
        matte<float> const& m4
        )
{
    matte<float4> result;

    result.set_ca( pack(m1.get_ca(), m2.get_ca(), m3.get_ca(), m4.get_ca()) );
    result.set_cd( pack(m1.get_cd(), m2.get_cd(), m3.get_cd(), m4.get_cd()) );
    result.set_ka( float4(m1.get_ka(), m2.get_ka(), m3.get_ka(), m4.get_ka()) );
    result.set_kd( float4(m1.get_kd(), m2.get_kd(), m3.get_kd(), m4.get_kd()) );

    return result;
}

inline mirror<float4> pack(
        mirror<float> const& m1,
        mirror<float> const& m2,
        mirror<float> const& m3,
        mirror<float> const& m4
        )
{
    mirror<float4> result;

    result.set_cr( pack(m1.get_cr(), m2.get_cr(), m3.get_cr(), m4.get_cr()) );
    result.set_kr( float4(m1.get_kr(), m2.get_kr(), m3.get_kr(), m4.get_kr()) );

    return result;
}

inline plastic<float4> pack(
        plastic<float> const& m1,
        plastic<float> const& m2,
        plastic<float> const& m3,
        plastic<float> const& m4
        )
{
    plastic<float4> result;

    result.set_ca( pack(m1.get_ca(), m2.get_ca(), m3.get_ca(), m4.get_ca()) );
    result.set_cd( pack(m1.get_cd(), m2.get_cd(), m3.get_cd(), m4.get_cd()) );
    result.set_cs( pack(m1.get_cs(), m2.get_cs(), m3.get_cs(), m4.get_cs()) );
    result.set_ka( float4(m1.get_ka(), m2.get_ka(), m3.get_ka(), m4.get_ka()) );
    result.set_kd( float4(m1.get_kd(), m2.get_kd(), m3.get_kd(), m4.get_kd()) );
    result.set_ks( float4(m1.get_ks(), m2.get_ks(), m3.get_ks(), m4.get_ks()) );
    result.set_specular_exp( float4(
            m1.get_specular_exp(),
            m2.get_specular_exp(),
            m3.get_specular_exp(),
            m4.get_specular_exp()
            ) );

    return result;
}

#if VSNRAY_SIMD_ISA >= VSNRAY_SIMD_ISA_AVX

//-------------------------------------------------------------------------------------------------
// Functions to pack eight materials into a single SIMD material
//

inline emissive<float8> pack(
        emissive<float> const& m1,
        emissive<float> const& m2,
        emissive<float> const& m3,
        emissive<float> const& m4,
        emissive<float> const& m5,
        emissive<float> const& m6,
        emissive<float> const& m7,
        emissive<float> const& m8
        )
{
    emissive<float8> result;

    result.set_ce(pack(
            m1.get_ce(), m2.get_ce(), m3.get_ce(), m4.get_ce(),
            m5.get_ce(), m6.get_ce(), m7.get_ce(), m8.get_ce()
            ));

    result.set_ls(float8(
            m1.get_ls(), m2.get_ls(), m3.get_ls(), m4.get_ls(),
            m5.get_ls(), m6.get_ls(), m7.get_ls(), m8.get_ls()
            ));

    return result;
}

inline matte<float8> pack(
        matte<float> const& m1,
        matte<float> const& m2,
        matte<float> const& m3,
        matte<float> const& m4,
        matte<float> const& m5,
        matte<float> const& m6,
        matte<float> const& m7,
        matte<float> const& m8
        )
{
    matte<float8> result;

    result.set_ca(pack(
            m1.get_ca(), m2.get_ca(), m3.get_ca(), m4.get_ca(),
            m5.get_ca(), m6.get_ca(), m7.get_ca(), m8.get_ca()
            ));
    result.set_cd(pack(
            m1.get_cd(), m2.get_cd(), m3.get_cd(), m4.get_cd(),
            m5.get_cd(), m6.get_cd(), m7.get_cd(), m8.get_cd()
            ));
    result.set_ka(float8(
            m1.get_ka(), m2.get_ka(), m3.get_ka(), m4.get_ka(),
            m5.get_ka(), m6.get_ka(), m7.get_ka(), m8.get_ka()
            ));
    result.set_kd(float8(
            m1.get_kd(), m2.get_kd(), m3.get_kd(), m4.get_kd(),
            m5.get_kd(), m6.get_kd(), m7.get_kd(), m8.get_kd()
            ));

    return result;
}

inline mirror<float8> pack(
        mirror<float> const& m1,
        mirror<float> const& m2,
        mirror<float> const& m3,
        mirror<float> const& m4,
        mirror<float> const& m5,
        mirror<float> const& m6,
        mirror<float> const& m7,
        mirror<float> const& m8
        )
{
    mirror<float8> result;

    result.set_cr(pack(
            m1.get_cr(), m2.get_cr(), m3.get_cr(), m4.get_cr(),
            m5.get_cr(), m6.get_cr(), m7.get_cr(), m8.get_cr()
            ));
    result.set_kr(float8(
            m1.get_kr(), m2.get_kr(), m3.get_kr(), m4.get_kr(),
            m5.get_kr(), m6.get_kr(), m7.get_kr(), m8.get_kr()
            ));

    return result;
}

inline plastic<float8> pack(
        plastic<float> const& m1,
        plastic<float> const& m2,
        plastic<float> const& m3,
        plastic<float> const& m4,
        plastic<float> const& m5,
        plastic<float> const& m6,
        plastic<float> const& m7,
        plastic<float> const& m8
        )
{
    using C = spectrum<float>;

    C ca[8]                         = { m1.get_ca(), m2.get_ca(), m3.get_ca(), m4.get_ca(),
                                        m5.get_ca(), m6.get_ca(), m7.get_ca(), m8.get_ca() };
    C cd[8]                         = { m1.get_cd(), m2.get_cd(), m3.get_cd(), m4.get_cd(),
                                        m5.get_cd(), m6.get_cd(), m7.get_cd(), m8.get_cd() };
    C cs[8]                         = { m1.get_cs(), m2.get_cs(), m3.get_cs(), m4.get_cs(),
                                        m5.get_cs(), m6.get_cs(), m7.get_cs(), m8.get_cs() };
    VSNRAY_ALIGN(32) float ka[8]    = { m1.get_ka(), m2.get_ka(), m3.get_ka(), m4.get_ka(),
                                        m5.get_ka(), m6.get_ka(), m7.get_ka(), m8.get_ka() };
    VSNRAY_ALIGN(32) float kd[8]    = { m1.get_kd(), m2.get_kd(), m3.get_kd(), m4.get_kd(),
                                        m5.get_kd(), m6.get_kd(), m7.get_kd(), m8.get_kd() };
    VSNRAY_ALIGN(32) float ks[8]    = { m1.get_ks(), m2.get_ks(), m3.get_ks(), m4.get_ks(),
                                        m5.get_ks(), m6.get_ks(), m7.get_ks(), m8.get_ks() };
    VSNRAY_ALIGN(32) float exp[8]   = { m1.get_specular_exp(), m2.get_specular_exp(), m3.get_specular_exp(), m4.get_specular_exp(),
                                        m5.get_specular_exp(), m6.get_specular_exp(), m7.get_specular_exp(), m8.get_specular_exp() };

    plastic<float8> result;

    spectrum<float8> ca8;
    spectrum<float8> cd8;
    spectrum<float8> cs8;

    for (size_t d = 0; d < C::num_samples; ++d)
    {
        ca8[d] = float8(
                ca[0][d], ca[1][d], ca[2][d], ca[3][d],
                ca[4][d], ca[5][d], ca[6][d], ca[7][d]
                );

        cd8[d] = float8(
                cd[0][d], cd[1][d], cd[2][d], cd[3][d],
                cd[4][d], cd[5][d], cd[6][d], cd[7][d]
                );

        cs8[d] = float8(
                cs[0][d], cs[1][d], cs[2][d], cs[3][d],
                cs[4][d], cs[5][d], cs[6][d], cs[7][d]
                );
    }

    result.set_ca(ca8);
    result.set_cd(cd8);
    result.set_cs(cs8);
    result.set_ka(ka);
    result.set_kd(kd);
    result.set_ks(ks);
    result.set_specular_exp(exp);

    return result;
}

#endif // VSNRAY_SIMD_ISA >= VSNRAY_SIMD_ISA_AVX

} // simd
} // visioanray
<|endoftext|>


<commit_before>// Time:  O(2^n), n is the size of debt.
// Space: O(2^n)

class Solution {
public:
    int minTransfers(vector<vector<int>>& transactions) {
        unordered_map<int, int> account;
        for (const auto& transaction: transactions) {
            account[transaction[0]] += transaction[2];
            account[transaction[1]] -= transaction[2];
        }

        vector<int> debt;
        for (const auto& kvp: account) {
            if (kvp.second) {
                debt.emplace_back(kvp.second);
            }
        }
        if (debt.empty()) {
            return 0;
        }

        const auto n = 1 << debt.size();
        vector<int> dp(n, numeric_limits<int>::max()), subset;
        for (int i = 1; i < n; ++i) {
            int net_debt = 0, number = 0;
            for (int j = 0; j < debt.size(); ++j) {
                if (i & 1 << j) {
                    net_debt += debt[j];
                    ++number;
                }
            }
            if (net_debt == 0) {
                dp[i] = number - 1;
                for (const auto& s: subset) {
                    if ((i & s) == s) {
                        if (dp[s] != numeric_limits<int>::max() &&
                            dp[i - s] != numeric_limits<int>::max()) {
                            dp[i] = min(dp[i], dp[s] + dp[i - s]);
                        }
                    }
                }
                subset.emplace_back(i);
            }
        }
        return dp.back();
    }
};
<commit_msg>Update optimal-account-balancing.cpp<commit_after>// Time:  O(2^n), n is the size of debt.
// Space: O(2^n)

class Solution {
public:
    int minTransfers(vector<vector<int>>& transactions) {
        unordered_map<int, int> account;
        for (const auto& transaction : transactions) {
            account[transaction[0]] += transaction[2];
            account[transaction[1]] -= transaction[2];
        }

        vector<int> debt;
        for (const auto& kvp : account) {
            if (kvp.second) {
                debt.emplace_back(kvp.second);
            }
        }
        if (debt.empty()) {
            return 0;
        }

        const auto n = 1 << debt.size();
        vector<int> dp(n, numeric_limits<int>::max()), subset;
        for (int i = 1; i < n; ++i) {
            int net_debt = 0, number = 0;
            for (int j = 0; j < debt.size(); ++j) {
                if (i & 1 << j) {
                    net_debt += debt[j];
                    ++number;
                }
            }
            if (net_debt == 0) {
                dp[i] = number - 1;
                for (const auto& s: subset) {
                    if ((i & s) == s) {
                        if (dp[s] != numeric_limits<int>::max() &&
                            dp[i - s] != numeric_limits<int>::max()) {
                            dp[i] = min(dp[i], dp[s] + dp[i - s]);
                        }
                    }
                }
                subset.emplace_back(i);
            }
        }
        return dp.back();
    }
};
<|endoftext|>


<commit_before>#include "stream_parser.h"
#include "util.h"

stream_parser::stream_parser(const pcre *url_filter_re, const pcre_extra *url_filter_extra,
                             const std::string &output_path) :
        url_filter_re(url_filter_re),
        url_filter_extra(url_filter_extra),
        output_path(output_path),
        gzip_flag(false),
        dump_flag(-1) {
    std::memset(&next_seq, 0, sizeof next_seq);
    std::memset(&ts_usc, 0, sizeof ts_usc);
    std::memset(&fin_nxtseq, 0, sizeof fin_nxtseq);
    http_parser_init(&parser[HTTP_REQUEST], HTTP_REQUEST);
    parser[HTTP_REQUEST].data = this;
    http_parser_init(&parser[HTTP_RESPONSE], HTTP_RESPONSE);
    parser[HTTP_RESPONSE].data = this;

    http_parser_settings_init(&settings);
    settings.on_url = on_url;
    settings.on_message_begin = on_message_begin;
    settings.on_header_field = on_header_field;
    settings.on_header_value = on_header_value;
    settings.on_headers_complete = on_headers_complete;
    settings.on_body = on_body;
    settings.on_message_complete = on_message_complete;
}

bool stream_parser::parse(const struct packet_info &packet, enum http_parser_type type) {
    std::string *str = NULL;
    size_t orig_size = raw[type].size();
    str = &raw[type];
    if (next_seq[type] != 0 && packet.seq != next_seq[type]) {
        if (packet.seq < next_seq[type]) {
            // retransmission packet
            if (packet.is_rst || is_stream_fin(packet, type)) {
                dump_http_request();
                return false;
            }
            return true;
        } else {
            // out-of-order packet
            out_of_order_packet[type].insert(
                    std::make_pair(packet.seq, std::make_pair(packet.body, packet.nxtseq)));
        }
    } else {
        str->append(packet.body);
        next_seq[type] = packet.nxtseq;
    }
    while (!out_of_order_packet[type].empty()) {
        const std::map<uint32_t, std::pair<std::string, uint32_t> >::iterator &iterator =
                out_of_order_packet[type].find(next_seq[type]);
        if (iterator == out_of_order_packet[type].end()) break;
        str->append(iterator->second.first);
        next_seq[type] = iterator->second.second;
        out_of_order_packet[type].erase(iterator);
    }

    bool ret = true;
    if (str->size() > orig_size) {
        last_ts_usc = packet.ts_usc;
        size_t parse_bytes = http_parser_execute(&parser[type], &settings, str->c_str() + orig_size,
                                                 str->size() - orig_size);
        ret = parse_bytes > 0 && HTTP_PARSER_ERRNO(&parser[type]) == HPE_OK;
    }
    if (packet.is_rst || is_stream_fin(packet, type)) {
        dump_http_request();
        return false;
    }
    return ret;
}

void stream_parser::set_addr(const std::string &req_addr, const std::string &resp_addr) {
    this->address[HTTP_REQUEST].assign(req_addr);
    this->address[HTTP_RESPONSE].assign(resp_addr);
}

int stream_parser::on_message_begin(http_parser *parser) {
    stream_parser *self = reinterpret_cast<stream_parser *>(parser->data);
    if (parser->type == HTTP_REQUEST) {
        self->ts_usc[parser->type] = self->last_ts_usc;
    }
    self->dump_flag = 0;
    return 0;
}

int stream_parser::on_url(http_parser *parser, const char *at, size_t length) {
    stream_parser *self = reinterpret_cast<stream_parser *>(parser->data);
    self->url.assign(at, length);
    self->method.assign(http_method_str(static_cast<enum http_method>(parser->method)));
    if (!self->match_url(self->url)) {
        return -1;
    }
    return 0;
};

int stream_parser::on_header_field(http_parser *parser, const char *at, size_t length) {
    stream_parser *self = reinterpret_cast<stream_parser *>(parser->data);
    self->temp_header_field.assign(at, length);
    for (size_t i = 0; i < length; ++i) {
        if (at[i] >= 'A' && at[i] <= 'Z') {
            self->temp_header_field[i] = at[i] ^ (char) 0x20;
        }
    }
    return 0;
}

int stream_parser::on_header_value(http_parser *parser, const char *at, size_t length) {
    stream_parser *self = reinterpret_cast<stream_parser *>(parser->data);
    if (parser->type == HTTP_RESPONSE) {
        if (self->temp_header_field == "content-encoding" && std::strstr(at, "gzip")) {
            self->gzip_flag = true;
        }
    } else {
        if (self->temp_header_field == "host") {
            self->host.assign(at, length);
        }
    }
    // std::cout << self->temp_header_field <<  ":" << std::string(at, length) << std::endl;
    return 0;
}

int stream_parser::on_headers_complete(http_parser *parser) {
    if (parser->type == HTTP_REQUEST || parser->type == HTTP_RESPONSE) {
        stream_parser *self = reinterpret_cast<stream_parser *>(parser->data);
        self->header[parser->type] = self->raw[parser->type].substr(0, parser->nread);
        if (parser->type == HTTP_RESPONSE) {
            self->ts_usc[parser->type] = self->last_ts_usc;
        }
    }
    return 0;
}

int stream_parser::on_body(http_parser *parser, const char *at, size_t length) {
    if (parser->type == HTTP_REQUEST || parser->type == HTTP_RESPONSE) {
        stream_parser *self = reinterpret_cast<stream_parser *>(parser->data);
        self->body[parser->type].append(at, length);
        if (parser->type == HTTP_RESPONSE) {
            self->ts_usc[parser->type] = self->last_ts_usc;
        }
    }
    return 0;
}

int stream_parser::on_message_complete(http_parser *parser) {
    stream_parser *self = reinterpret_cast<stream_parser *>(parser->data);
    if (parser->type == HTTP_RESPONSE) {
        if (parser->type == HTTP_RESPONSE && parser->status_code == HTTP_STATUS_CONTINUE) {
            self->header_100_continue.assign(self->header[HTTP_RESPONSE]);
            self->body_100_continue.assign(self->body[HTTP_RESPONSE]);
            self->raw[HTTP_RESPONSE].clear();
            self->body[HTTP_RESPONSE].clear();
            // reset response parser
            http_parser_init(parser, HTTP_RESPONSE);
        } else {
            self->ts_usc[parser->type] = self->last_ts_usc;
            self->dump_http_request();
        }
    }
    return 0;
}

bool stream_parser::match_url(const std::string &url) {
    if (!url_filter_re) return true;
    int ovector[30];
    int rc = pcre_exec(url_filter_re, url_filter_extra, url.c_str(), url.size(), 0, 0, ovector, 30);
    return rc >= 0;
}

void stream_parser::dump_http_request() {
    if (dump_flag != 0) return;

    if (gzip_flag && !body[HTTP_RESPONSE].empty()) {
        std::string new_body;
        if (gzip_decompress(body[HTTP_RESPONSE], new_body)) {
            body[HTTP_RESPONSE].assign(new_body);
        } else {
            std::cerr << ANSI_COLOR_RED << "[decompress error]" << ANSI_COLOR_RESET << std::endl;
        }
    }

    std::cout << ANSI_COLOR_CYAN << address[HTTP_REQUEST] << " -> " << address[HTTP_RESPONSE];
    if (!host.empty()) {
        std::cout << " " << ANSI_COLOR_GREEN << host << ANSI_COLOR_CYAN;
    }
    std::size_t i = url.find('?');
    std::string url_no_query = i == std::string::npos ? url : url.substr(0, i);
    std::cout << " " << url_no_query << ANSI_COLOR_RESET;

    char buff[128];
    if (ts_usc[HTTP_RESPONSE] && ts_usc[HTTP_REQUEST]) {
        if (ts_usc[HTTP_REQUEST] % 1000000 == 0 && ts_usc[HTTP_RESPONSE] % 1000000 == 0) {
            std::snprintf(buff, 128, " cost %lu ", (ts_usc[HTTP_RESPONSE] - ts_usc[HTTP_REQUEST]) / 1000000);
        } else {
            std::snprintf(buff, 128, " cost %.6f ", (ts_usc[HTTP_RESPONSE] - ts_usc[HTTP_REQUEST]) / 1000000.0);
        }
        std::cout << buff;
    }

    if (!output_path.empty()) {
        static size_t req_idx = 0;
        std::snprintf(buff, 128, "/%p.%lu", this, ++req_idx);
        std::string save_filename = output_path;
        save_filename.append(buff);
        std::cout << " saved at " << save_filename << std::endl;
        std::ofstream out(save_filename.c_str(), std::ios::app | std::ios::out);
        if (out.is_open()) {
            out << *this << std::endl;
            out.close();
        } else {
            std::cerr << "ofstream [" << save_filename << "] is not opened." << std::endl;
            out.close();
            exit(1);
        }
    } else {
        std::cout << std::endl << *this << std::endl;
    }
    // clear
    raw[HTTP_REQUEST] = std::string();
    raw[HTTP_RESPONSE] = std::string();
    body[HTTP_REQUEST] = std::string();
    body[HTTP_RESPONSE] = std::string();
    header_100_continue.clear();
    body_100_continue.clear();
    host.clear();
    std::memset(&ts_usc, 0, sizeof ts_usc);
    dump_flag = 1;
}

bool stream_parser::is_stream_fin(const struct packet_info &packet, enum http_parser_type type) {
    // three-way handshake
    if (packet.is_fin) {
        fin_nxtseq[type] = packet.nxtseq;
        return false;
    } else {
        return fin_nxtseq[HTTP_REQUEST] && fin_nxtseq[HTTP_RESPONSE] && packet.ack == fin_nxtseq[!type];
    }
}

std::ostream &operator<<(std::ostream &out, const stream_parser &parser) {
    out << ANSI_COLOR_GREEN
        << parser.header[HTTP_REQUEST]
        << ANSI_COLOR_RESET;
    if (!parser.header_100_continue.empty()) {
        out << ANSI_COLOR_BLUE
            << parser.header_100_continue
            << ANSI_COLOR_RESET;
    }
    if (!parser.body_100_continue.empty()) {
        out << parser.body_100_continue;
    }
    if (!is_atty || is_plain_text(parser.body[HTTP_REQUEST])) {
        out << parser.body[HTTP_REQUEST];
    } else {
        out << ANSI_COLOR_RED << "[binary request body] (size:" << parser.body[HTTP_REQUEST].size() << ")"
            << ANSI_COLOR_RESET;
    }
    out << std::endl
        << ANSI_COLOR_BLUE
        << parser.header[HTTP_RESPONSE]
        << ANSI_COLOR_RESET;
    if (parser.body[HTTP_RESPONSE].empty()) {
        out << ANSI_COLOR_RED << "[empty response body]" << ANSI_COLOR_RESET;
    } else if (!is_atty || is_plain_text(parser.body[HTTP_RESPONSE])) {
        out << parser.body[HTTP_RESPONSE];
    } else {
        out << ANSI_COLOR_RED << "[binary response body] (size:" << parser.body[HTTP_RESPONSE].size() << ")"
            << ANSI_COLOR_RESET;
    }
    out << std::endl;
    return out;
}

std::ofstream &operator<<(std::ofstream &out, const stream_parser &parser) {
    out << parser.header[HTTP_REQUEST]
        << parser.header_100_continue
        << parser.body_100_continue
        << parser.body[HTTP_REQUEST]
        << parser.header[HTTP_RESPONSE]
        << parser.body[HTTP_RESPONSE];
    return out;
}
<commit_msg>Reset gzip_flag<commit_after>#include "stream_parser.h"
#include "util.h"

stream_parser::stream_parser(const pcre *url_filter_re, const pcre_extra *url_filter_extra,
                             const std::string &output_path) :
        url_filter_re(url_filter_re),
        url_filter_extra(url_filter_extra),
        output_path(output_path),
        gzip_flag(false),
        dump_flag(-1) {
    std::memset(&next_seq, 0, sizeof next_seq);
    std::memset(&ts_usc, 0, sizeof ts_usc);
    std::memset(&fin_nxtseq, 0, sizeof fin_nxtseq);
    http_parser_init(&parser[HTTP_REQUEST], HTTP_REQUEST);
    parser[HTTP_REQUEST].data = this;
    http_parser_init(&parser[HTTP_RESPONSE], HTTP_RESPONSE);
    parser[HTTP_RESPONSE].data = this;

    http_parser_settings_init(&settings);
    settings.on_url = on_url;
    settings.on_message_begin = on_message_begin;
    settings.on_header_field = on_header_field;
    settings.on_header_value = on_header_value;
    settings.on_headers_complete = on_headers_complete;
    settings.on_body = on_body;
    settings.on_message_complete = on_message_complete;
}

bool stream_parser::parse(const struct packet_info &packet, enum http_parser_type type) {
    std::string *str = NULL;
    size_t orig_size = raw[type].size();
    str = &raw[type];
    if (next_seq[type] != 0 && packet.seq != next_seq[type]) {
        if (packet.seq < next_seq[type]) {
            // retransmission packet
            if (packet.is_rst || is_stream_fin(packet, type)) {
                dump_http_request();
                return false;
            }
            return true;
        } else {
            // out-of-order packet
            out_of_order_packet[type].insert(
                    std::make_pair(packet.seq, std::make_pair(packet.body, packet.nxtseq)));
        }
    } else {
        str->append(packet.body);
        next_seq[type] = packet.nxtseq;
    }
    while (!out_of_order_packet[type].empty()) {
        const std::map<uint32_t, std::pair<std::string, uint32_t> >::iterator &iterator =
                out_of_order_packet[type].find(next_seq[type]);
        if (iterator == out_of_order_packet[type].end()) break;
        str->append(iterator->second.first);
        next_seq[type] = iterator->second.second;
        out_of_order_packet[type].erase(iterator);
    }

    bool ret = true;
    if (str->size() > orig_size) {
        last_ts_usc = packet.ts_usc;
        size_t parse_bytes = http_parser_execute(&parser[type], &settings, str->c_str() + orig_size,
                                                 str->size() - orig_size);
        ret = parse_bytes > 0 && HTTP_PARSER_ERRNO(&parser[type]) == HPE_OK;
    }
    if (packet.is_rst || is_stream_fin(packet, type)) {
        dump_http_request();
        return false;
    }
    return ret;
}

void stream_parser::set_addr(const std::string &req_addr, const std::string &resp_addr) {
    this->address[HTTP_REQUEST].assign(req_addr);
    this->address[HTTP_RESPONSE].assign(resp_addr);
}

int stream_parser::on_message_begin(http_parser *parser) {
    stream_parser *self = reinterpret_cast<stream_parser *>(parser->data);
    if (parser->type == HTTP_REQUEST) {
        self->ts_usc[parser->type] = self->last_ts_usc;
    }
    self->dump_flag = 0;
    return 0;
}

int stream_parser::on_url(http_parser *parser, const char *at, size_t length) {
    stream_parser *self = reinterpret_cast<stream_parser *>(parser->data);
    self->url.assign(at, length);
    self->method.assign(http_method_str(static_cast<enum http_method>(parser->method)));
    if (!self->match_url(self->url)) {
        return -1;
    }
    return 0;
};

int stream_parser::on_header_field(http_parser *parser, const char *at, size_t length) {
    stream_parser *self = reinterpret_cast<stream_parser *>(parser->data);
    self->temp_header_field.assign(at, length);
    for (size_t i = 0; i < length; ++i) {
        if (at[i] >= 'A' && at[i] <= 'Z') {
            self->temp_header_field[i] = at[i] ^ (char) 0x20;
        }
    }
    return 0;
}

int stream_parser::on_header_value(http_parser *parser, const char *at, size_t length) {
    stream_parser *self = reinterpret_cast<stream_parser *>(parser->data);
    if (parser->type == HTTP_RESPONSE) {
        if (self->temp_header_field == "content-encoding" && std::strstr(at, "gzip")) {
            self->gzip_flag = true;
        }
    } else {
        if (self->temp_header_field == "host") {
            self->host.assign(at, length);
        }
    }
    // std::cout << self->temp_header_field <<  ":" << std::string(at, length) << std::endl;
    return 0;
}

int stream_parser::on_headers_complete(http_parser *parser) {
    if (parser->type == HTTP_REQUEST || parser->type == HTTP_RESPONSE) {
        stream_parser *self = reinterpret_cast<stream_parser *>(parser->data);
        self->header[parser->type] = self->raw[parser->type].substr(0, parser->nread);
        if (parser->type == HTTP_RESPONSE) {
            self->ts_usc[parser->type] = self->last_ts_usc;
        }
    }
    return 0;
}

int stream_parser::on_body(http_parser *parser, const char *at, size_t length) {
    if (parser->type == HTTP_REQUEST || parser->type == HTTP_RESPONSE) {
        stream_parser *self = reinterpret_cast<stream_parser *>(parser->data);
        self->body[parser->type].append(at, length);
        if (parser->type == HTTP_RESPONSE) {
            self->ts_usc[parser->type] = self->last_ts_usc;
        }
    }
    return 0;
}

int stream_parser::on_message_complete(http_parser *parser) {
    stream_parser *self = reinterpret_cast<stream_parser *>(parser->data);
    if (parser->type == HTTP_RESPONSE) {
        if (parser->type == HTTP_RESPONSE && parser->status_code == HTTP_STATUS_CONTINUE) {
            self->header_100_continue.assign(self->header[HTTP_RESPONSE]);
            self->body_100_continue.assign(self->body[HTTP_RESPONSE]);
            self->raw[HTTP_RESPONSE].clear();
            self->body[HTTP_RESPONSE].clear();
            // reset response parser
            http_parser_init(parser, HTTP_RESPONSE);
        } else {
            self->ts_usc[parser->type] = self->last_ts_usc;
            self->dump_http_request();
        }
    }
    return 0;
}

bool stream_parser::match_url(const std::string &url) {
    if (!url_filter_re) return true;
    int ovector[30];
    int rc = pcre_exec(url_filter_re, url_filter_extra, url.c_str(), url.size(), 0, 0, ovector, 30);
    return rc >= 0;
}

void stream_parser::dump_http_request() {
    if (dump_flag != 0) return;

    if (gzip_flag && !body[HTTP_RESPONSE].empty()) {
        std::string new_body;
        if (gzip_decompress(body[HTTP_RESPONSE], new_body)) {
            body[HTTP_RESPONSE].assign(new_body);
        } else {
            std::cerr << ANSI_COLOR_RED << "[decompress error]" << ANSI_COLOR_RESET << std::endl;
        }
    }

    std::cout << ANSI_COLOR_CYAN << address[HTTP_REQUEST] << " -> " << address[HTTP_RESPONSE];
    if (!host.empty()) {
        std::cout << " " << ANSI_COLOR_GREEN << host << ANSI_COLOR_CYAN;
    }
    std::size_t i = url.find('?');
    std::string url_no_query = i == std::string::npos ? url : url.substr(0, i);
    std::cout << " " << url_no_query << ANSI_COLOR_RESET;

    char buff[128];
    if (ts_usc[HTTP_RESPONSE] && ts_usc[HTTP_REQUEST]) {
        if (ts_usc[HTTP_REQUEST] % 1000000 == 0 && ts_usc[HTTP_RESPONSE] % 1000000 == 0) {
            std::snprintf(buff, 128, " cost %lu ", (ts_usc[HTTP_RESPONSE] - ts_usc[HTTP_REQUEST]) / 1000000);
        } else {
            std::snprintf(buff, 128, " cost %.6f ", (ts_usc[HTTP_RESPONSE] - ts_usc[HTTP_REQUEST]) / 1000000.0);
        }
        std::cout << buff;
    }

    if (!output_path.empty()) {
        static size_t req_idx = 0;
        std::snprintf(buff, 128, "/%p.%lu", this, ++req_idx);
        std::string save_filename = output_path;
        save_filename.append(buff);
        std::cout << " saved at " << save_filename << std::endl;
        std::ofstream out(save_filename.c_str(), std::ios::app | std::ios::out);
        if (out.is_open()) {
            out << *this << std::endl;
            out.close();
        } else {
            std::cerr << "ofstream [" << save_filename << "] is not opened." << std::endl;
            out.close();
            exit(1);
        }
    } else {
        std::cout << std::endl << *this << std::endl;
    }
    // clear
    raw[HTTP_REQUEST] = std::string();
    raw[HTTP_RESPONSE] = std::string();
    body[HTTP_REQUEST] = std::string();
    body[HTTP_RESPONSE] = std::string();
    header_100_continue.clear();
    body_100_continue.clear();
    host.clear();
    std::memset(&ts_usc, 0, sizeof ts_usc);
    gzip_flag = false;
    dump_flag = 1;
}

bool stream_parser::is_stream_fin(const struct packet_info &packet, enum http_parser_type type) {
    // three-way handshake
    if (packet.is_fin) {
        fin_nxtseq[type] = packet.nxtseq;
        return false;
    } else {
        return fin_nxtseq[HTTP_REQUEST] && fin_nxtseq[HTTP_RESPONSE] && packet.ack == fin_nxtseq[!type];
    }
}

std::ostream &operator<<(std::ostream &out, const stream_parser &parser) {
    out << ANSI_COLOR_GREEN
        << parser.header[HTTP_REQUEST]
        << ANSI_COLOR_RESET;
    if (!parser.header_100_continue.empty()) {
        out << ANSI_COLOR_BLUE
            << parser.header_100_continue
            << ANSI_COLOR_RESET;
    }
    if (!parser.body_100_continue.empty()) {
        out << parser.body_100_continue;
    }
    if (!is_atty || is_plain_text(parser.body[HTTP_REQUEST])) {
        out << parser.body[HTTP_REQUEST];
    } else {
        out << ANSI_COLOR_RED << "[binary request body] (size:" << parser.body[HTTP_REQUEST].size() << ")"
            << ANSI_COLOR_RESET;
    }
    out << std::endl
        << ANSI_COLOR_BLUE
        << parser.header[HTTP_RESPONSE]
        << ANSI_COLOR_RESET;
    if (parser.body[HTTP_RESPONSE].empty()) {
        out << ANSI_COLOR_RED << "[empty response body]" << ANSI_COLOR_RESET;
    } else if (!is_atty || is_plain_text(parser.body[HTTP_RESPONSE])) {
        out << parser.body[HTTP_RESPONSE];
    } else {
        out << ANSI_COLOR_RED << "[binary response body] (size:" << parser.body[HTTP_RESPONSE].size() << ")"
            << ANSI_COLOR_RESET;
    }
    out << std::endl;
    return out;
}

std::ofstream &operator<<(std::ofstream &out, const stream_parser &parser) {
    out << parser.header[HTTP_REQUEST]
        << parser.header_100_continue
        << parser.body_100_continue
        << parser.body[HTTP_REQUEST]
        << parser.header[HTTP_RESPONSE]
        << parser.body[HTTP_RESPONSE];
    return out;
}
<|endoftext|>


<commit_before>#include <algorithm>

#include "factory.hpp"

factory::interfaces::c_interface_manager g_factory;

NAMESPACE_REGION( factory )
NAMESPACE_REGION( interfaces )

c_interface_manager::c_interface_manager( ) {
	auto teb = reinterpret_cast< PTEB >( __readfsdword( uintptr_t( &static_cast< NT_TIB* >( nullptr )->Self ) ) );
	auto peb = teb->ProcessEnvironmentBlock;

	auto root = &peb->Ldr->InMemoryOrderModuleList;
	//iterate module list
	for ( auto entry = root->Flink->Flink->Flink->Flink; entry != root; entry = entry->Flink ) {
		PLDR_DATA_TABLE_ENTRY	data_table;
		HMODULE			module_base;
		uintptr_t		create_interface_export;
		uintptr_t		create_interface_;
		uintptr_t*		list_iterator_ptr;
		interface_iterator_t*	list_iterator;

		data_table = reinterpret_cast< PLDR_DATA_TABLE_ENTRY >( entry );
		module_base = reinterpret_cast< HMODULE >( data_table->Reserved2[ 0 ] );
		create_interface_export = uintptr_t( GetProcAddress( module_base, "CreateInterface" ) );

		if ( !create_interface_export || !is_createinterface_export( create_interface_export ) ) {
			continue;
		}

		//find the createinterface function
		create_interface_ = follow_createinterface_export( create_interface_export );
		if ( !is_createinterface_fn( create_interface_ ) ) {
			continue;
		}

		//find the list iterator
		list_iterator_ptr = find_list_ptr( create_interface_ );

		//iterate the interface list
		for ( list_iterator = reinterpret_cast< interface_iterator_t* >(
			list_iterator_ptr );
			!!list_iterator;
			list_iterator = list_iterator->m_next
			) {
			std::string name( list_iterator->m_name );
			std::string module_name( util::unicode_to_ascii(
				std::wstring( data_table->FullDllName.Buffer, data_table->FullDllName.Length ) ) );

			uintptr_t ptr = static_cast< uintptr_t( *)( ) >( list_iterator->m_create_fn )( );

			size_t version = [ & ]( ) {
				std::string ret( name );
				ret.erase( std::remove_if( ret.begin( ), ret.end( ),
					[ & ]( int i ) { return !::isdigit( i ); }
				), ret.end( ) );
				return atoi( ret.c_str( ) );
			}( );

			m_interfaces.push_back( interface_data_t{ name, module_name, version, ptr } );
		}
	}
}

END_REGION
END_REGION
<commit_msg>iterate exports instead of procaddress<commit_after>#include <algorithm>

#include "factory.hpp"

NAMESPACE_REGION( factory )
NAMESPACE_REGION( interfaces )

//iterate all exports inside of a module and find createinterface
uintptr_t c_interface_manager::find_createinterface( void* module_ ) {
	IMAGE_DOS_HEADER*	dos_header;
	IMAGE_NT_HEADERS*	nt_headers;
	uintptr_t		export_address;
	IMAGE_EXPORT_DIRECTORY*	export_dir;
	const char*		export_name;
	uintptr_t*		names;
	uintptr_t*		funcs;
	uint16_t*		ords;

	dos_header = reinterpret_cast< decltype( dos_header ) >( uintptr_t( module_ ) );
	nt_headers = reinterpret_cast< decltype( nt_headers ) >( uintptr_t( module_ ) + dos_header->e_lfanew );

	export_address = nt_headers->OptionalHeader.DataDirectory[ 0 ].VirtualAddress;
	export_dir = reinterpret_cast< decltype( export_dir ) >( uintptr_t( module_ ) + export_address );

	if ( !export_dir->NumberOfFunctions )
		return uintptr_t{ };

	names = reinterpret_cast< uintptr_t* >( uintptr_t( module_ ) + export_dir->AddressOfNames );
	funcs = reinterpret_cast< uintptr_t* >( uintptr_t( module_ ) + export_dir->AddressOfFunctions );

	ords = reinterpret_cast< uint16_t* >( uintptr_t( module_ ) + export_dir->AddressOfNameOrdinals );

	if ( names && funcs && ords ) {
		for ( size_t i{ }; i < export_dir->NumberOfNames; ++i ) {
			export_name = reinterpret_cast< const char* >( uintptr_t( module_ ) + names[ i ] );
			if ( !strcmp( export_name, "CreateInterface" ) ) {
				return uintptr_t( module_ ) + funcs[ ords[ i ] ];
			}
		}
	}

	return uintptr_t{ };
}

c_interface_manager::c_interface_manager( ) {
	auto teb = reinterpret_cast< PTEB >( __readfsdword( uintptr_t( &static_cast< NT_TIB* >( nullptr )->Self ) ) );
	auto peb = teb->ProcessEnvironmentBlock;

	auto root = &peb->Ldr->InMemoryOrderModuleList;
	//iterate module list
	for ( auto entry = root->Flink->Flink->Flink->Flink; entry != root; entry = entry->Flink ) {
		PLDR_DATA_TABLE_ENTRY	data_table;
		HMODULE			module_base;
		uintptr_t		create_interface_export;
		uintptr_t		create_interface_;
		uintptr_t*		list_iterator_ptr;
		interface_iterator_t*	list_iterator;

		data_table = reinterpret_cast< PLDR_DATA_TABLE_ENTRY >( entry );
		module_base = reinterpret_cast< HMODULE >( data_table->Reserved2[ 0 ] );
		printf( "module: %s\n", util::unicode_to_ascii(
			std::wstring( data_table->FullDllName.Buffer, data_table->FullDllName.Length ) ).c_str( ) );
		create_interface_export = find_createinterface( module_base );

		if ( !create_interface_export || !is_createinterface_export( create_interface_export ) ) {
			continue;
		}

		//find the createinterface function
		create_interface_ = follow_createinterface_export( create_interface_export );
		if ( !is_createinterface_fn( create_interface_ ) ) {
			continue;
		}

		//find the list iterator
		list_iterator_ptr = find_list_ptr( create_interface_ );

		//iterate the interface list
		for ( list_iterator = reinterpret_cast< interface_iterator_t* >(
			list_iterator_ptr );
			!!list_iterator;
			list_iterator = list_iterator->m_next
			) {
			std::string name( list_iterator->m_name );
			std::string module_name( util::unicode_to_ascii(
				std::wstring( data_table->FullDllName.Buffer, data_table->FullDllName.Length ) ) );

			uintptr_t ptr = static_cast< uintptr_t( *)( ) >( list_iterator->m_create_fn )( );

			size_t version = [ & ]( ) {
				std::string ret( name );
				ret.erase( std::remove_if( ret.begin( ), ret.end( ),
					[ & ]( int i ) { return !::isdigit( i ); }
				), ret.end( ) );
				return atoi( ret.c_str( ) );
			}( );

			m_interfaces.emplace_back( interface_data_t{ name, module_name, version, ptr } );
		}
	}
}

END_REGION
END_REGION
<|endoftext|>


<commit_before>//
// This file is part of khmer, http://github.com/ged-lab/khmer/, and is
// Copyright (C) Michigan State University, 2009-2013. It is licensed under
// the three-clause BSD license; see doc/LICENSE.txt.
// Contact: khmer-project@idyll.org
//

#ifndef HASHBITS_HH
#define HASHBITS_HH

#include <vector>
#include "hashtable.hh"

namespace khmer
{
class CountingHash;
class LabelHash;

class Hashbits : public khmer::Hashtable
{
protected:
    std::vector<HashIntoType> _tablesizes;
    size_t _n_tables;
    HashIntoType _occupied_bins;
    HashIntoType _n_unique_kmers;
    HashIntoType _n_overlap_kmers;
    Byte ** _counts;

    virtual void _allocate_counters()
    {
        _n_tables = _tablesizes.size();

        _counts = new Byte*[_n_tables];

        for (size_t i = 0; i < _n_tables; i++) {
            HashIntoType tablesize = _tablesizes[i];
            HashIntoType tablebytes = tablesize / 8 + 1;

            _counts[i] = new Byte[tablebytes];
            memset(_counts[i], 0, tablebytes);
        }
    }

public:
    Hashbits(WordLength ksize, std::vector<HashIntoType>& tablesizes)
        : khmer::Hashtable(ksize),
          _tablesizes(tablesizes)
    {
        _occupied_bins = 0;
        _n_unique_kmers = 0;
        _n_overlap_kmers = 0;

        _allocate_counters();
    }

    ~Hashbits()
    {
        if (_counts) {
            for (size_t i = 0; i < _n_tables; i++) {
                delete[] _counts[i];
                _counts[i] = NULL;
            }
            delete[] _counts;
            _counts = NULL;

            _n_tables = 0;
        }

    }

    std::vector<HashIntoType> get_tablesizes() const
    {
        return _tablesizes;
    }

    virtual void save(std::string);
    virtual void load(std::string);

    // for overlap k-mer counting
    void consume_fasta_overlap(const std::string &filename,
                               HashIntoType curve[2][100],
                               khmer::Hashbits &ht2,
                               unsigned int &total_reads,
                               unsigned long long &n_consumed);

    // just for overlap k-mer counting!
    unsigned int check_and_process_read_overlap(std::string &read,
            bool &is_valid,
            khmer::Hashbits &ht2);
    // for overlap k-mer counting!
    unsigned int consume_string_overlap(const std::string &s,
                                        khmer::Hashbits &ht2);

    // count number of occupied bins
    virtual const HashIntoType n_occupied(HashIntoType start=0,
                                          HashIntoType stop=0) const
    {
        // @@ CTB need to be able to *save* this...
        return _occupied_bins/_n_tables;
    }

    virtual const HashIntoType n_unique_kmers() const
    {
        return _n_unique_kmers;	// @@ CTB need to be able to *save* this...
    }

    // Get and set the hashbits for the given kmer.
    inline
    virtual
    BoundedCounterType
    test_and_set_bits(const char * kmer)
    {
        HashIntoType hash = _hash(kmer, _ksize);
        return test_and_set_bits(hash);
    }

    // Get and set the hashbits for the given kmer hash.
    // Generally, it is better to keep tests and mutations separate,
    // but, in the interests of efficiency and thread safety,
    // tests and mutations are being blended here against conventional
    // software engineering wisdom.
    inline
    virtual
    BoundedCounterType
    test_and_set_bits( HashIntoType khash )
    {
        bool is_new_kmer = false;

        for (size_t i = 0; i < _n_tables; i++) {
            HashIntoType bin = khash % _tablesizes[i];
            HashIntoType byte = bin / 8;
            unsigned char bit = (unsigned char)(1 << (bin % 8));

            unsigned char bits_orig = __sync_fetch_and_or( *(_counts + i) + byte, bit );
            if (!(bits_orig & bit)) {
                __sync_add_and_fetch( &_occupied_bins, 1 );
                is_new_kmer = true;
            }
        } // iteration over hashtables

        if (is_new_kmer) {
            __sync_add_and_fetch( &_n_unique_kmers, 1 );
            return 1; // kmer not seen before
        }

        return 0; // kmer already seen
    } // test_and_set_bits

    virtual const HashIntoType n_overlap_kmers(HashIntoType start=0,
            HashIntoType stop=0) const
    {
        return _n_overlap_kmers;	// @@ CTB need to be able to *save* this...
    }

    virtual void count(const char * kmer)
    {
        HashIntoType hash = _hash(kmer, _ksize);
        count(hash);
    }

    virtual void count(HashIntoType khash)
    {
        bool is_new_kmer = false;

        for (size_t i = 0; i < _n_tables; i++) {
            HashIntoType bin = khash % _tablesizes[i];
            HashIntoType byte = bin / 8;
            unsigned char bit = bin % 8;
            if (!( _counts[i][byte] & (1<<bit))) {
                _occupied_bins += 1;
                is_new_kmer = true;
            }
            _counts[i][byte] |= (1 << bit);
        }
        if (is_new_kmer) {
            _n_unique_kmers +=1;
        }
    }

    virtual bool check_overlap(HashIntoType khash, Hashbits &ht2)
    {

        for (size_t i = 0; i < ht2._n_tables; i++) {
            HashIntoType bin = khash % ht2._tablesizes[i];
            HashIntoType byte = bin / 8;
            unsigned char bit = bin % 8;
            if (!( ht2._counts[i][byte] & (1<<bit))) {
                return false;
            }
        }
        return true;
    }

    virtual void count_overlap(const char * kmer, Hashbits &ht2)
    {
        HashIntoType hash = _hash(kmer, _ksize);
        count_overlap(hash,ht2);
    }

    virtual void count_overlap(HashIntoType khash, Hashbits &ht2)
    {
        bool is_new_kmer = false;

        for (size_t i = 0; i < _n_tables; i++) {
            HashIntoType bin = khash % _tablesizes[i];
            HashIntoType byte = bin / 8;
            unsigned char bit = bin % 8;
            if (!( _counts[i][byte] & (1<<bit))) {
                _occupied_bins += 1;
                is_new_kmer = true;
            }
            _counts[i][byte] |= (1 << bit);
        }
        if (is_new_kmer) {
            _n_unique_kmers +=1;
            if (check_overlap(khash,ht2)) {
                _n_overlap_kmers +=1;
            }
        }
    }

    // get the count for the given k-mer.
    virtual const BoundedCounterType get_count(const char * kmer) const
    {
        HashIntoType hash = _hash(kmer, _ksize);
        return get_count(hash);
    }

    // get the count for the given k-mer hash.
    virtual const BoundedCounterType get_count(HashIntoType khash) const
    {
        for (size_t i = 0; i < _n_tables; i++) {
            HashIntoType bin = khash % _tablesizes[i];
            HashIntoType byte = bin / 8;
            unsigned char bit = bin % 8;

            if (!(_counts[i][byte] & (1 << bit))) {
                return 0;
            }
        }
        return 1;
    }
};
};

#include "counting.hh"
#include "labelhash.hh"
#endif // HASHBITS_HH

// vim: set sts=2 sw=2:
<commit_msg>Add n_tables accessor to Hashbits<commit_after>//
// This file is part of khmer, http://github.com/ged-lab/khmer/, and is
// Copyright (C) Michigan State University, 2009-2013. It is licensed under
// the three-clause BSD license; see doc/LICENSE.txt.
// Contact: khmer-project@idyll.org
//

#ifndef HASHBITS_HH
#define HASHBITS_HH

#include <vector>
#include "hashtable.hh"

namespace khmer
{
class CountingHash;
class LabelHash;

class Hashbits : public khmer::Hashtable
{
protected:
    std::vector<HashIntoType> _tablesizes;
    size_t _n_tables;
    HashIntoType _occupied_bins;
    HashIntoType _n_unique_kmers;
    HashIntoType _n_overlap_kmers;
    Byte ** _counts;

    virtual void _allocate_counters()
    {
        _n_tables = _tablesizes.size();

        _counts = new Byte*[_n_tables];

        for (size_t i = 0; i < _n_tables; i++) {
            HashIntoType tablesize = _tablesizes[i];
            HashIntoType tablebytes = tablesize / 8 + 1;

            _counts[i] = new Byte[tablebytes];
            memset(_counts[i], 0, tablebytes);
        }
    }

public:
    Hashbits(WordLength ksize, std::vector<HashIntoType>& tablesizes)
        : khmer::Hashtable(ksize),
          _tablesizes(tablesizes)
    {
        _occupied_bins = 0;
        _n_unique_kmers = 0;
        _n_overlap_kmers = 0;

        _allocate_counters();
    }

    ~Hashbits()
    {
        if (_counts) {
            for (size_t i = 0; i < _n_tables; i++) {
                delete[] _counts[i];
                _counts[i] = NULL;
            }
            delete[] _counts;
            _counts = NULL;

            _n_tables = 0;
        }

    }

    // Accessors for protected/private table info members
    std::vector<HashIntoType> get_tablesizes() const
    {
        return _tablesizes;
    }

    const size_t n_tables() const
    {
        return _n_tables;
    }

    virtual void save(std::string);
    virtual void load(std::string);

    // for overlap k-mer counting
    void consume_fasta_overlap(const std::string &filename,
                               HashIntoType curve[2][100],
                               khmer::Hashbits &ht2,
                               unsigned int &total_reads,
                               unsigned long long &n_consumed);

    // just for overlap k-mer counting!
    unsigned int check_and_process_read_overlap(std::string &read,
            bool &is_valid,
            khmer::Hashbits &ht2);
    // for overlap k-mer counting!
    unsigned int consume_string_overlap(const std::string &s,
                                        khmer::Hashbits &ht2);

    // count number of occupied bins
    virtual const HashIntoType n_occupied(HashIntoType start=0,
                                          HashIntoType stop=0) const
    {
        // @@ CTB need to be able to *save* this...
        return _occupied_bins/_n_tables;
    }

    virtual const HashIntoType n_unique_kmers() const
    {
        return _n_unique_kmers;	// @@ CTB need to be able to *save* this...
    }

    // Get and set the hashbits for the given kmer.
    inline
    virtual
    BoundedCounterType
    test_and_set_bits(const char * kmer)
    {
        HashIntoType hash = _hash(kmer, _ksize);
        return test_and_set_bits(hash);
    }

    // Get and set the hashbits for the given kmer hash.
    // Generally, it is better to keep tests and mutations separate,
    // but, in the interests of efficiency and thread safety,
    // tests and mutations are being blended here against conventional
    // software engineering wisdom.
    inline
    virtual
    BoundedCounterType
    test_and_set_bits( HashIntoType khash )
    {
        bool is_new_kmer = false;

        for (size_t i = 0; i < _n_tables; i++) {
            HashIntoType bin = khash % _tablesizes[i];
            HashIntoType byte = bin / 8;
            unsigned char bit = (unsigned char)(1 << (bin % 8));

            unsigned char bits_orig = __sync_fetch_and_or( *(_counts + i) + byte, bit );
            if (!(bits_orig & bit)) {
                __sync_add_and_fetch( &_occupied_bins, 1 );
                is_new_kmer = true;
            }
        } // iteration over hashtables

        if (is_new_kmer) {
            __sync_add_and_fetch( &_n_unique_kmers, 1 );
            return 1; // kmer not seen before
        }

        return 0; // kmer already seen
    } // test_and_set_bits

    virtual const HashIntoType n_overlap_kmers(HashIntoType start=0,
            HashIntoType stop=0) const
    {
        return _n_overlap_kmers;	// @@ CTB need to be able to *save* this...
    }

    virtual void count(const char * kmer)
    {
        HashIntoType hash = _hash(kmer, _ksize);
        count(hash);
    }

    virtual void count(HashIntoType khash)
    {
        bool is_new_kmer = false;

        for (size_t i = 0; i < _n_tables; i++) {
            HashIntoType bin = khash % _tablesizes[i];
            HashIntoType byte = bin / 8;
            unsigned char bit = bin % 8;
            if (!( _counts[i][byte] & (1<<bit))) {
                _occupied_bins += 1;
                is_new_kmer = true;
            }
            _counts[i][byte] |= (1 << bit);
        }
        if (is_new_kmer) {
            _n_unique_kmers +=1;
        }
    }

    virtual bool check_overlap(HashIntoType khash, Hashbits &ht2)
    {

        for (size_t i = 0; i < ht2._n_tables; i++) {
            HashIntoType bin = khash % ht2._tablesizes[i];
            HashIntoType byte = bin / 8;
            unsigned char bit = bin % 8;
            if (!( ht2._counts[i][byte] & (1<<bit))) {
                return false;
            }
        }
        return true;
    }

    virtual void count_overlap(const char * kmer, Hashbits &ht2)
    {
        HashIntoType hash = _hash(kmer, _ksize);
        count_overlap(hash,ht2);
    }

    virtual void count_overlap(HashIntoType khash, Hashbits &ht2)
    {
        bool is_new_kmer = false;

        for (size_t i = 0; i < _n_tables; i++) {
            HashIntoType bin = khash % _tablesizes[i];
            HashIntoType byte = bin / 8;
            unsigned char bit = bin % 8;
            if (!( _counts[i][byte] & (1<<bit))) {
                _occupied_bins += 1;
                is_new_kmer = true;
            }
            _counts[i][byte] |= (1 << bit);
        }
        if (is_new_kmer) {
            _n_unique_kmers +=1;
            if (check_overlap(khash,ht2)) {
                _n_overlap_kmers +=1;
            }
        }
    }

    // get the count for the given k-mer.
    virtual const BoundedCounterType get_count(const char * kmer) const
    {
        HashIntoType hash = _hash(kmer, _ksize);
        return get_count(hash);
    }

    // get the count for the given k-mer hash.
    virtual const BoundedCounterType get_count(HashIntoType khash) const
    {
        for (size_t i = 0; i < _n_tables; i++) {
            HashIntoType bin = khash % _tablesizes[i];
            HashIntoType byte = bin / 8;
            unsigned char bit = bin % 8;

            if (!(_counts[i][byte] & (1 << bit))) {
                return 0;
            }
        }
        return 1;
    }
};
};

#include "counting.hh"
#include "labelhash.hh"
#endif // HASHBITS_HH

// vim: set sts=2 sw=2:
<|endoftext|>