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

  Program:   Monteverdi2
  Language:  C++

  Copyright (c) Centre National d'Etudes Spatiales. All rights reserved.
  See Copyright.txt for details.

  Monteverdi2 is distributed under the CeCILL licence version 2. See
  Licence_CeCILL_V2-en.txt or
  http://www.cecill.info/licences/Licence_CeCILL_V2-en.txt for more details.

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

=========================================================================*/
#include "mvdDatabaseBrowserWidget.h"
#include "ui_mvdDatabaseBrowserWidget.h"

/*****************************************************************************/
/* INCLUDE SECTION                                                           */

//
// Qt includes (sorted by alphabetic order)
//// Must be included before system/custom includes.

//
// System includes (sorted by alphabetic order)
#include <cassert>

//
// ITK includes (sorted by alphabetic order)

//
// OTB includes (sorted by alphabetic order)

//
// Monteverdi includes (sorted by alphabetic order)
#include "Gui/mvdDatabaseTreeWidget.h"
#include "Gui/mvdTreeWidgetItem.h"

#define ENABLE_DISPLAY_ID 1

namespace mvd
{

/*
  TRANSLATOR mvd::DatabaseBrowserWidget

  Necessary for lupdate to be aware of C++ namespaces.

  Context comment for translator.
*/

/*****************************************************************************/
/* CONSTANTS                                                                 */

/*****************************************************************************/
/* STATIC IMPLEMENTATION SECTION                                             */

/*****************************************************************************/
/* CLASS IMPLEMENTATION SECTION                                              */

/*******************************************************************************/
DatabaseBrowserWidget
::DatabaseBrowserWidget( QWidget* parent, Qt::WindowFlags flags  ):
  QWidget( parent, flags ),
  m_UI( new mvd::Ui::DatabaseBrowserWidget() ),
  m_DatasetRootItem( NULL ),
  m_DatasetList(),
  m_StartDragPosition(),
  m_SearchText()
{
  m_UI->setupUi( this );

  SetupUI();

  /*
  // Devember 12th, 2013 - Trainee example.
  QPushButton* button=new QPushButton ("Click me", this);
  layout()->addWidget(button);
  */
}

/*******************************************************************************/
DatabaseBrowserWidget
::~DatabaseBrowserWidget()
{
  delete m_UI;
  m_UI = NULL;
}

/*****************************************************************************/
const QTreeWidgetItem*
DatabaseBrowserWidget
::GetRootItem() const
{
  return m_UI->databaseTreeWidget->invisibleRootItem();
}

/*****************************************************************************/
QTreeWidgetItem*
DatabaseBrowserWidget
::GetRootItem()
{
  return m_UI->databaseTreeWidget->invisibleRootItem();
}

/*******************************************************************************/
QTreeWidgetItem*
DatabaseBrowserWidget
::InsertNodeItem( QTreeWidgetItem* parent,
                  const QString& text,
                  const QVariant& id,
                  const QStringList& columns )
{
  return
    InsertItem(
      parent,
      TreeWidgetItem::ITEM_TYPE_NODE,
      text,
      id,
      columns
    );
}

/*******************************************************************************/
QTreeWidgetItem*
DatabaseBrowserWidget
::InsertLeafItem( QTreeWidgetItem* parent,
                  const QString& text,
                  const QVariant& id,
                  const QStringList& columns )
{
  return
    InsertItem(
      parent,
      TreeWidgetItem::ITEM_TYPE_LEAF,
      text,
      id,
      columns
    );
}

/*******************************************************************************/
QTreeWidgetItem*
DatabaseBrowserWidget
::InsertItem( QTreeWidgetItem* parent,
              TreeWidgetItem::ItemType type,
              const QString& text,
              const QVariant& id,
              const QStringList& columns )
{
  TreeWidgetItem* item =
    new TreeWidgetItem(
      parent,
      text,
      id,
      columns,
      type
    );

  return item;
}

/*******************************************************************************/
void
DatabaseBrowserWidget
::SetDatasetList( const StringPairListType& list )
{
  // qDebug() << this << "::SetDatasetList(" << list << ")";

  // remember dataset list
  m_DatasetList = list;

  // Fill Tree
  FillTree();
}

/*******************************************************************************/
void
DatabaseBrowserWidget
::FillTree()
{
  // get the currentItem Id if any selected.
  // since all the TreeWidgetItem are deleted next, need to remember
  // it in order to set it back
  QString currentItemHash;

  TreeWidgetItem* selectedItem =
    dynamic_cast< TreeWidgetItem* >(
      GetDatabaseTreeWidget()->currentItem()
    );

  if (selectedItem)
    {
    currentItemHash = selectedItem->GetHash();
    }

  // TODO: Get initial algorithm back (synchronizes two ordered
  // sequences using QTreeWidget::findItems<>().
  //
  // Because:
  // 1. removing items can provoque selection changes;
  // 2. it's needed to re-emit signal to keep current selection
  // active.
  //
  // Initial algorithm took care of current-selection and was
  // optimized to not delete useful items which must be inserted
  // again.

  // Remove all previously stored dataset child items.
  while( m_DatasetRootItem->childCount()>0 )
    {
    // Remove dataset child item and reference it.
    QTreeWidgetItem* child = m_DatasetRootItem->takeChild( 0 );

    // Delete it from memory.
    delete child;
    child = NULL;
    }

  // Append full dataset list...
  for( StringPairListType::const_iterator it( m_DatasetList.begin() );
       it!=m_DatasetList.end();
       ++it )
    {
    // current alias
    const StringPairListType::value_type::first_type& alias = it->first;
    const StringPairListType::value_type::second_type& hash = it->second;

    TreeWidgetItem* item =
      new TreeWidgetItem(
        m_DatasetRootItem,
        alias,
        QVariant(),
        QStringList( hash )
      );

    // Item is visible is search-text is empty or if alias contains
    // search-text.
    item->setHidden(
      !m_SearchText.isEmpty() &&
      !item->text( 0 ).contains( m_SearchText, Qt::CaseInsensitive )
    );

    // was it the selected item ?
    if( currentItemHash == hash )
      {
      // ...add this child item as currentItem
      GetDatabaseTreeWidget()->setCurrentItem( item );
      }
    }
}

/*****************************************************************************/
void
DatabaseBrowserWidget
::SetupUI()
{
  setAcceptDrops( true );

  //
  // Header columns.
  m_UI->databaseTreeWidget->headerItem()->setText( 1, "Id" );
  m_UI->databaseTreeWidget->headerItem()->setText( 2, "Info" );

#if (!defined( _DEBUG ) && 1) || 0
  m_UI->databaseTreeWidget->setColumnHidden( 1, true );
  m_UI->databaseTreeWidget->setColumnHidden( 2, true );
#endif

  //
  // Dataset root item.
#if 0
  m_DatasetRootItem = new QTreeWidgetItem( "Datasets", m_UI->databaseTreeWidget );

  m_DatasetRootItem->setChildIndicatorPolicy(
    QTreeWidgetItem::DontShowIndicatorWhenChildless
  );

  m_DatasetRootItem->setExpanded( true );
#endif

  // set placeholder text
#if (QT_VERSION >= 0x407000)
  m_UI->m_SearchLine->setPlaceholderText( tr( "Search Dataset..." ) );
#endif
}

/*******************************************************************************/
DatabaseTreeWidget*
DatabaseBrowserWidget
::GetDatabaseTreeWidget()
{
  return m_UI->databaseTreeWidget;
}

/*****************************************************************************/
void
DatabaseBrowserWidget
::SetCurrentDataset( const QString& hash )
{
  // qDebug() << this << "::SetCurrentDataset(" << id << ")";

  assert( m_UI!=NULL );
  assert( m_UI->databaseTreeWidget!=NULL );

  QList< QTreeWidgetItem* > items(
    m_UI->databaseTreeWidget->findItems(
      hash,
      Qt::MatchExactly | Qt::MatchRecursive,
      1
    )
  );

  assert( items.isEmpty() || items.size() == 1 );

  /*
  qDebug()
    << ( items.isEmpty() ? "NONE" : items.first()->text( 0 ) )
    << m_UI->databaseTreeWidget->selectionModel()->selectedIndexes().size();
  */

#if 0

   m_UI->databaseTreeWidget->setCurrentItem(
    items.isEmpty() ? NULL : items.first(),
    0,
    QItemSelectionModel::Clear |
    QItemSelectionModel::Current
  );
#else
  if( items.isEmpty() )
    return;

  m_UI->databaseTreeWidget->setCurrentItem( items.first() );
#endif
}

/*******************************************************************************/
/* SLOTS                                                                       */
/*******************************************************************************/
void
DatabaseBrowserWidget
::on_databaseTreeWidget_currentItemChanged( QTreeWidgetItem* current,
					    QTreeWidgetItem* previous )
{
  //
  // Current

  // TODO: Should be DatabaseModel::DatasetId but widgets should not depend on models!!!
  QString currentHash;

  TreeWidgetItem* currentItem = dynamic_cast< TreeWidgetItem* >( current );

  if( currentItem!=NULL && currentItem->parent()!=NULL )
    // if current is root and not NULL get the Id of the corresponding
    // Dataset.
    currentHash = currentItem->GetHash();

  //
  // Previous

  // TODO: Should be DatabaseModel::DatasetId but widgets should not depend on models!!!
  QString previousHash;

  TreeWidgetItem* previousItem = dynamic_cast< TreeWidgetItem* >( previous );

  if( previousItem!=NULL )
    previousHash = previousItem->GetHash();

  //
  // Emit event.
  emit CurrentDatasetChanged( currentHash, previousHash );
}

/*******************************************************************************/
void
DatabaseBrowserWidget
::on_m_SearchLine_textChanged( const QString& search )
{
  //
  // get the search text
  m_SearchText = search;

#if 0
  // fill the tree with the application
  FillTree();
#else
  for( int i=0; i<m_DatasetRootItem->childCount();  ++i )
    {
    QTreeWidgetItem* item = m_DatasetRootItem->child( i );
    assert( item!=NULL );

    // Item is visible if search is empty or if alias contains
    // search-text.
    item->setHidden(
      !search.isEmpty() &&
      !item->text( 0 ).contains( search, Qt::CaseInsensitive )
    );
    }
#endif
}

} // end namespace 'mvd'
<commit_msg>ENH: Fixed crash when typing text into DatabaseBrowser search filter line-edit.<commit_after>/*=========================================================================

  Program:   Monteverdi2
  Language:  C++

  Copyright (c) Centre National d'Etudes Spatiales. All rights reserved.
  See Copyright.txt for details.

  Monteverdi2 is distributed under the CeCILL licence version 2. See
  Licence_CeCILL_V2-en.txt or
  http://www.cecill.info/licences/Licence_CeCILL_V2-en.txt for more details.

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

=========================================================================*/
#include "mvdDatabaseBrowserWidget.h"
#include "ui_mvdDatabaseBrowserWidget.h"

/*****************************************************************************/
/* INCLUDE SECTION                                                           */

//
// Qt includes (sorted by alphabetic order)
//// Must be included before system/custom includes.

//
// System includes (sorted by alphabetic order)
#include <cassert>

//
// ITK includes (sorted by alphabetic order)

//
// OTB includes (sorted by alphabetic order)

//
// Monteverdi includes (sorted by alphabetic order)
#include "Gui/mvdDatabaseTreeWidget.h"
#include "Gui/mvdTreeWidgetItem.h"

#define ENABLE_DISPLAY_ID 1

namespace mvd
{

/*
  TRANSLATOR mvd::DatabaseBrowserWidget

  Necessary for lupdate to be aware of C++ namespaces.

  Context comment for translator.
*/

/*****************************************************************************/
/* CONSTANTS                                                                 */

/*****************************************************************************/
/* STATIC IMPLEMENTATION SECTION                                             */

/*****************************************************************************/
/* CLASS IMPLEMENTATION SECTION                                              */

/*******************************************************************************/
DatabaseBrowserWidget
::DatabaseBrowserWidget( QWidget* parent, Qt::WindowFlags flags  ):
  QWidget( parent, flags ),
  m_UI( new mvd::Ui::DatabaseBrowserWidget() ),
  m_DatasetRootItem( NULL ),
  m_DatasetList(),
  m_StartDragPosition(),
  m_SearchText()
{
  m_UI->setupUi( this );

  SetupUI();

  /*
  // Devember 12th, 2013 - Trainee example.
  QPushButton* button=new QPushButton ("Click me", this);
  layout()->addWidget(button);
  */
}

/*******************************************************************************/
DatabaseBrowserWidget
::~DatabaseBrowserWidget()
{
  delete m_UI;
  m_UI = NULL;
}

/*****************************************************************************/
const QTreeWidgetItem*
DatabaseBrowserWidget
::GetRootItem() const
{
  return m_UI->databaseTreeWidget->invisibleRootItem();
}

/*****************************************************************************/
QTreeWidgetItem*
DatabaseBrowserWidget
::GetRootItem()
{
  return m_UI->databaseTreeWidget->invisibleRootItem();
}

/*******************************************************************************/
QTreeWidgetItem*
DatabaseBrowserWidget
::InsertNodeItem( QTreeWidgetItem* parent,
                  const QString& text,
                  const QVariant& id,
                  const QStringList& columns )
{
  return
    InsertItem(
      parent,
      TreeWidgetItem::ITEM_TYPE_NODE,
      text,
      id,
      columns
    );
}

/*******************************************************************************/
QTreeWidgetItem*
DatabaseBrowserWidget
::InsertLeafItem( QTreeWidgetItem* parent,
                  const QString& text,
                  const QVariant& id,
                  const QStringList& columns )
{
  return
    InsertItem(
      parent,
      TreeWidgetItem::ITEM_TYPE_LEAF,
      text,
      id,
      columns
    );
}

/*******************************************************************************/
QTreeWidgetItem*
DatabaseBrowserWidget
::InsertItem( QTreeWidgetItem* parent,
              TreeWidgetItem::ItemType type,
              const QString& text,
              const QVariant& id,
              const QStringList& columns )
{
  TreeWidgetItem* item =
    new TreeWidgetItem(
      parent,
      text,
      id,
      columns,
      type
    );

  return item;
}

/*******************************************************************************/
void
DatabaseBrowserWidget
::SetDatasetList( const StringPairListType& list )
{
  // qDebug() << this << "::SetDatasetList(" << list << ")";

  // remember dataset list
  m_DatasetList = list;

  // Fill Tree
  FillTree();
}

/*******************************************************************************/
void
DatabaseBrowserWidget
::FillTree()
{
  // get the currentItem Id if any selected.
  // since all the TreeWidgetItem are deleted next, need to remember
  // it in order to set it back
  QString currentItemHash;

  TreeWidgetItem* selectedItem =
    dynamic_cast< TreeWidgetItem* >(
      GetDatabaseTreeWidget()->currentItem()
    );

  if (selectedItem)
    {
    currentItemHash = selectedItem->GetHash();
    }

  // TODO: Get initial algorithm back (synchronizes two ordered
  // sequences using QTreeWidget::findItems<>().
  //
  // Because:
  // 1. removing items can provoque selection changes;
  // 2. it's needed to re-emit signal to keep current selection
  // active.
  //
  // Initial algorithm took care of current-selection and was
  // optimized to not delete useful items which must be inserted
  // again.

  // Remove all previously stored dataset child items.
  while( m_DatasetRootItem->childCount()>0 )
    {
    // Remove dataset child item and reference it.
    QTreeWidgetItem* child = m_DatasetRootItem->takeChild( 0 );

    // Delete it from memory.
    delete child;
    child = NULL;
    }

  // Append full dataset list...
  for( StringPairListType::const_iterator it( m_DatasetList.begin() );
       it!=m_DatasetList.end();
       ++it )
    {
    // current alias
    const StringPairListType::value_type::first_type& alias = it->first;
    const StringPairListType::value_type::second_type& hash = it->second;

    TreeWidgetItem* item =
      new TreeWidgetItem(
        m_DatasetRootItem,
        alias,
        QVariant(),
        QStringList( hash )
      );

    // Item is visible is search-text is empty or if alias contains
    // search-text.
    item->setHidden(
      !m_SearchText.isEmpty() &&
      !item->text( 0 ).contains( m_SearchText, Qt::CaseInsensitive )
    );

    // was it the selected item ?
    if( currentItemHash == hash )
      {
      // ...add this child item as currentItem
      GetDatabaseTreeWidget()->setCurrentItem( item );
      }
    }
}

/*****************************************************************************/
void
DatabaseBrowserWidget
::SetupUI()
{
  setAcceptDrops( true );

  //
  // Header columns.
  m_UI->databaseTreeWidget->headerItem()->setText( 1, "Id" );
  m_UI->databaseTreeWidget->headerItem()->setText( 2, "Info" );

#if (!defined( _DEBUG ) && 1) || 0
  m_UI->databaseTreeWidget->setColumnHidden( 1, true );
  m_UI->databaseTreeWidget->setColumnHidden( 2, true );
#endif

  //
  // Dataset root item.
#if 0
  m_DatasetRootItem = new QTreeWidgetItem( "Datasets", m_UI->databaseTreeWidget );

  m_DatasetRootItem->setChildIndicatorPolicy(
    QTreeWidgetItem::DontShowIndicatorWhenChildless
  );

  m_DatasetRootItem->setExpanded( true );
#endif

  // set placeholder text
#if (QT_VERSION >= 0x407000)
  m_UI->m_SearchLine->setPlaceholderText( tr( "Search Dataset..." ) );
#endif
}

/*******************************************************************************/
DatabaseTreeWidget*
DatabaseBrowserWidget
::GetDatabaseTreeWidget()
{
  return m_UI->databaseTreeWidget;
}

/*****************************************************************************/
void
DatabaseBrowserWidget
::SetCurrentDataset( const QString& hash )
{
  // qDebug() << this << "::SetCurrentDataset(" << id << ")";

  assert( m_UI!=NULL );
  assert( m_UI->databaseTreeWidget!=NULL );

  QList< QTreeWidgetItem* > items(
    m_UI->databaseTreeWidget->findItems(
      hash,
      Qt::MatchExactly | Qt::MatchRecursive,
      1
    )
  );

  assert( items.isEmpty() || items.size() == 1 );

  /*
  qDebug()
    << ( items.isEmpty() ? "NONE" : items.first()->text( 0 ) )
    << m_UI->databaseTreeWidget->selectionModel()->selectedIndexes().size();
  */

#if 0

   m_UI->databaseTreeWidget->setCurrentItem(
    items.isEmpty() ? NULL : items.first(),
    0,
    QItemSelectionModel::Clear |
    QItemSelectionModel::Current
  );
#else
  if( items.isEmpty() )
    return;

  m_UI->databaseTreeWidget->setCurrentItem( items.first() );
#endif
}

/*******************************************************************************/
/* SLOTS                                                                       */
/*******************************************************************************/
void
DatabaseBrowserWidget
::on_databaseTreeWidget_currentItemChanged( QTreeWidgetItem* current,
					    QTreeWidgetItem* previous )
{
  //
  // Current

  // TODO: Should be DatabaseModel::DatasetId but widgets should not depend on models!!!
  QString currentHash;

  TreeWidgetItem* currentItem = dynamic_cast< TreeWidgetItem* >( current );

  if( currentItem!=NULL && currentItem->parent()!=NULL )
    // if current is root and not NULL get the Id of the corresponding
    // Dataset.
    currentHash = currentItem->GetHash();

  //
  // Previous

  // TODO: Should be DatabaseModel::DatasetId but widgets should not depend on models!!!
  QString previousHash;

  TreeWidgetItem* previousItem = dynamic_cast< TreeWidgetItem* >( previous );

  if( previousItem!=NULL )
    previousHash = previousItem->GetHash();

  //
  // Emit event.
  emit CurrentDatasetChanged( currentHash, previousHash );
}

/*******************************************************************************/
void
DatabaseBrowserWidget
::on_m_SearchLine_textChanged( const QString& search )
{
  //
  // get the search text
  m_SearchText = search;

#if 0
  // fill the tree with the application
  FillTree();
#else
  if( m_DatasetRootItem==NULL )
    return;

  for( int i=0; i<m_DatasetRootItem->childCount();  ++i )
    {
    QTreeWidgetItem* item = m_DatasetRootItem->child( i );
    assert( item!=NULL );

    // Item is visible if search is empty or if alias contains
    // search-text.
    item->setHidden(
      !search.isEmpty() &&
      !item->text( 0 ).contains( search, Qt::CaseInsensitive )
    );
    }
#endif
}

} // end namespace 'mvd'
<|endoftext|>


<commit_before>#include <algorithm>
#include <numeric>

#include <cstdio>

#include "vector_utils.h"
#include "time_utils.h"

#include "vector_utils.cpp"
#include "time_utils.cpp"

#include "sse_set_intersection.cpp"
#include "binarysearch_set_intersection.cpp"

constexpr int STD = 0;
constexpr int SSE = 1;
constexpr int BINARY = 2;

class Application final {

    vec input_vec;
    static constexpr size_t input_size = 1024*1024;
    static constexpr size_t iterations = 1000;

    FILE* csv = nullptr;

public:
    void run() {

        csv = fopen("out.csv", "wt");
        assert((csv != nullptr) && "can't open file");

        measure_time("create input table: ", [this]{
            input_vec = create_sorted(input_size);
        });

        for (size_t base_size: {128, 1024}) {
            for (size_t factor: {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 20, 50}) {
                const size_t size = base_size * factor;
                test_all(size);
            }
        }

        fclose(csv);
    }

private:
    template <int version>
    void test(const char* info, const vec& a, const vec& b, int k) {

        vec result;
        volatile int32_t ref = 0;

        printf("%s [a.size = %lu, b.size = %lu, %d iterations] ", info, a.size(), b.size(), k);
        fflush(stdout);

        Clock::rep best_time = 0;
        int tmp = k;
        while (tmp-- > 0) {
            result.clear();
            const auto t1 = Clock::now();
            if constexpr (version == STD) {
                std::set_intersection(a.begin(), a.end(), b.begin(), b.end(), std::back_inserter(result));
            } else if constexpr (version == SSE) {
                sse_set_intersection(a, b, std::back_inserter(result));
            } else if constexpr (version == BINARY) {
                binsearch_set_intersection(a, b, std::back_inserter(result));
            }
            const auto t2 = Clock::now();
            best_time += elapsed(t1, t2);

            ref += std::accumulate(result.begin(), result.end(), int32_t(0));
        }

        printf("%lu us (%d)\n", best_time, ref);

        fprintf(csv, "%s,%lu,%lu,%lu\n", info, a.size(), b.size(), best_time);
    }

    void test_all(size_t size) {

        auto sampled = sample_sorted(input_vec, size);

        test<STD>("std",          sampled, input_vec, iterations);
        test<SSE>("SSE",          sampled, input_vec, iterations);
        test<BINARY>("binsearch", sampled, input_vec, iterations);
    }

};

int main() {

    Application app;
    app.run();
}

<commit_msg>enable result validation<commit_after>#include <algorithm>
#include <numeric>

#include <cstdio>

#include "vector_utils.h"
#include "time_utils.h"

#include "vector_utils.cpp"
#include "time_utils.cpp"

#include "sse_set_intersection.cpp"
#include "binarysearch_set_intersection.cpp"

constexpr int STD = 0;
constexpr int SSE = 1;
constexpr int BINARY = 2;

class Application final {

    vec input_vec;
    static constexpr size_t input_size = 1024*1024;
    static constexpr size_t iterations = 1000;

    FILE* csv = nullptr;

public:
    void run() {

        csv = fopen("out.csv", "wt");
        assert((csv != nullptr) && "can't open file");

        measure_time("create input table: ", [this]{
            input_vec = create_sorted(input_size);
        });

        for (size_t base_size: {128, 1024}) {
            for (size_t factor: {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 20, 50}) {
                const size_t size = base_size * factor;
                test_all(size);
            }
        }

        fclose(csv);
    }

private:
    template <int version>
    int32_t test(const char* info, const vec& a, const vec& b, int k, int32_t valid_ref = 0) {

        vec result;
        volatile int32_t ref = 0;

        printf("%s [a.size = %lu, b.size = %lu, %d iterations] ", info, a.size(), b.size(), k);
        fflush(stdout);

        Clock::rep best_time = 0;
        int tmp = k;
        while (tmp-- > 0) {
            result.clear();
            const auto t1 = Clock::now();
            if constexpr (version == STD) {
                std::set_intersection(a.begin(), a.end(), b.begin(), b.end(), std::back_inserter(result));
            } else if constexpr (version == SSE) {
                sse_set_intersection(a, b, std::back_inserter(result));
            } else if constexpr (version == BINARY) {
                binsearch_set_intersection(a, b, std::back_inserter(result));
            }
            const auto t2 = Clock::now();
            best_time += elapsed(t1, t2);

            ref += std::accumulate(result.begin(), result.end(), int32_t(0));
        }

        printf("%lu us (%d)", best_time, ref);
        if (valid_ref != 0 && valid_ref != ref) {
            printf(" !!! ERROR !!!");
        }

        putchar('\n');

        fprintf(csv, "%s,%lu,%lu,%lu\n", info, a.size(), b.size(), best_time);

        return ref;
    }

    void test_all(size_t size) {

        auto sampled = sample_sorted(input_vec, size);

        const int32_t ref = test<STD>("std", sampled, input_vec, iterations);
        test<SSE>("SSE",          sampled, input_vec, iterations, ref);
        test<BINARY>("binsearch", sampled, input_vec, iterations, ref);
    }

};

int main() {

    Application app;
    app.run();
}

<|endoftext|>


<commit_before>#ifndef STAN_MATH_REV_CORE_PROFILING_HPP
#define STAN_MATH_REV_CORE_PROFILING_HPP

#include <stan/math/prim/fun/Eigen.hpp>
#include <stan/math/prim/fun/typedefs.hpp>
#include <stan/math/rev/core/var.hpp>
#include <stan/math/rev/meta.hpp>
#include <stan/math/rev/fun/value_of.hpp>
#include <stan/math/prim/err.hpp>
#include <iostream>
#include <sstream>
#include <thread>

namespace stan {
namespace math {

/**
 * Class used for storing profiling information.
 */
class profile_info {
 private:
  bool active_;

  double fwd_pass_time_;
  double rev_pass_time_;
  size_t n_fwd_AD_passes_;
  size_t n_fwd_no_AD_passes_;
  size_t n_rev_passes_;
  size_t chain_stack_size_sum_;
  size_t nochain_stack_size_sum_;
  std::chrono::time_point<std::chrono::steady_clock> fwd_pass_tp_;
  std::chrono::time_point<std::chrono::steady_clock> rev_pass_tp_;
  size_t start_chain_stack_size_;
  size_t start_nochain_stack_size_;

 public:
  profile_info()
      : active_(false),
        fwd_pass_time_(0.0),
        rev_pass_time_(0.0),
        n_fwd_AD_passes_(0),
        n_fwd_no_AD_passes_(0),
        n_rev_passes_(0),
        chain_stack_size_sum_(0),
        nochain_stack_size_sum_(0),
        fwd_pass_tp_(std::chrono::steady_clock::now()),
        rev_pass_tp_(std::chrono::steady_clock::now()),
        start_chain_stack_size_(0),
        start_nochain_stack_size_(0){};

  bool is_active() const noexcept { return active_; }

  template <typename T>
  void fwd_pass_start() {
    if (!is_constant<T>::value) {
      start_chain_stack_size_ = ChainableStack::instance_->var_stack_.size();
      start_nochain_stack_size_
          = ChainableStack::instance_->var_nochain_stack_.size();
    }
    fwd_pass_tp_ = std::chrono::steady_clock::now();
    active_ = true;
  }

  template <typename T>
  void fwd_pass_stop() {
    if (!is_constant<T>::value) {
      n_fwd_AD_passes_++;
      chain_stack_size_sum_ += (ChainableStack::instance_->var_stack_.size()
                                - start_chain_stack_size_ - 1);
      nochain_stack_size_sum_
          += (ChainableStack::instance_->var_nochain_stack_.size()
              - start_nochain_stack_size_);
    } else {
      n_fwd_no_AD_passes_++;
    }
    fwd_pass_time_ += std::chrono::duration<double>(
                          std::chrono::steady_clock::now() - fwd_pass_tp_)
                          .count();
    active_ = false;
  }

  void rev_pass_start() { rev_pass_tp_ = std::chrono::steady_clock::now(); }

  void rev_pass_stop() {
    rev_pass_time_ += std::chrono::duration<double>(
                          std::chrono::steady_clock::now() - rev_pass_tp_)
                          .count();
    n_rev_passes_++;
  }

  size_t get_chain_stack_used() const noexcept {
    return chain_stack_size_sum_;
  };

  size_t get_nochain_stack_used() const noexcept {
    return nochain_stack_size_sum_;
  };

  size_t get_num_no_AD_fwd_passes() const noexcept {
    return n_fwd_no_AD_passes_;
  }

  size_t get_num_AD_fwd_passes() const noexcept { return n_fwd_AD_passes_; }

  size_t get_num_fwd_passes() const noexcept {
    return n_fwd_AD_passes_ + n_fwd_no_AD_passes_;
  }

  double get_fwd_time() const noexcept { return fwd_pass_time_; }

  size_t get_num_rev_passes() const noexcept { return n_rev_passes_; }

  double get_rev_time() const noexcept { return rev_pass_time_; }
};

using profile_key = std::pair<std::string, std::thread::id>;

using profile_map = std::map<profile_key, profile_info>;

/**
 * Profiles C++ lines where the object is in scope.
 * When T is var, the constructor starts the profile for the forward pass
 * and places a var with a callback to stop the reverse pass on the
 * AD tape. The destructor stops the profile for the forward pass and
 * places a var with a callback to start the profile for the reverse pass.
 * When T is not var, the constructor and destructor only profile the
 *
 *
 * @tparam T type of profile class. If var, the created object is used
 * to profile reverse mode AD. Only profiles the forward pass otherwise.
 */
template <typename T>
class profile {
  profile_key key_;
  profile_info* profile_;

 public:
  profile(std::string name, profile_map& profiles)
      : key_({name, std::this_thread::get_id()}) {
    profile_map::iterator p = profiles.find(key_);
    if (p == profiles.end()) {
      profiles[key_] = profile_info();
    }
    profile_ = &profiles[key_];
    if (profile_->is_active()) {
      std::ostringstream msg;
      msg << "Profile '" << key_.first << "' already started!";
      throw std::runtime_error(msg.str());
    }
    profile_->fwd_pass_start<T>();
    if (!is_constant<T>::value) {
      reverse_pass_callback([=]() mutable { profile_->rev_pass_stop(); });
    }
  }
  ~profile() {
    profile_->fwd_pass_stop<T>();
    if (!is_constant<T>::value) {
      reverse_pass_callback([=]() mutable { profile_->rev_pass_start(); });
    }
  }
};

}  // namespace math
}  // namespace stan
#endif
<commit_msg>remove ";"<commit_after>#ifndef STAN_MATH_REV_CORE_PROFILING_HPP
#define STAN_MATH_REV_CORE_PROFILING_HPP

#include <stan/math/prim/fun/Eigen.hpp>
#include <stan/math/prim/fun/typedefs.hpp>
#include <stan/math/rev/core/var.hpp>
#include <stan/math/rev/meta.hpp>
#include <stan/math/rev/fun/value_of.hpp>
#include <stan/math/prim/err.hpp>
#include <iostream>
#include <sstream>
#include <thread>

namespace stan {
namespace math {

/**
 * Class used for storing profiling information.
 */
class profile_info {
 private:
  bool active_;

  double fwd_pass_time_;
  double rev_pass_time_;
  size_t n_fwd_AD_passes_;
  size_t n_fwd_no_AD_passes_;
  size_t n_rev_passes_;
  size_t chain_stack_size_sum_;
  size_t nochain_stack_size_sum_;
  std::chrono::time_point<std::chrono::steady_clock> fwd_pass_tp_;
  std::chrono::time_point<std::chrono::steady_clock> rev_pass_tp_;
  size_t start_chain_stack_size_;
  size_t start_nochain_stack_size_;

 public:
  profile_info()
      : active_(false),
        fwd_pass_time_(0.0),
        rev_pass_time_(0.0),
        n_fwd_AD_passes_(0),
        n_fwd_no_AD_passes_(0),
        n_rev_passes_(0),
        chain_stack_size_sum_(0),
        nochain_stack_size_sum_(0),
        fwd_pass_tp_(std::chrono::steady_clock::now()),
        rev_pass_tp_(std::chrono::steady_clock::now()),
        start_chain_stack_size_(0),
        start_nochain_stack_size_(0){}

  bool is_active() const noexcept { return active_; }

  template <typename T>
  void fwd_pass_start() {
    if (!is_constant<T>::value) {
      start_chain_stack_size_ = ChainableStack::instance_->var_stack_.size();
      start_nochain_stack_size_
          = ChainableStack::instance_->var_nochain_stack_.size();
    }
    fwd_pass_tp_ = std::chrono::steady_clock::now();
    active_ = true;
  }

  template <typename T>
  void fwd_pass_stop() {
    if (!is_constant<T>::value) {
      n_fwd_AD_passes_++;
      chain_stack_size_sum_ += (ChainableStack::instance_->var_stack_.size()
                                - start_chain_stack_size_ - 1);
      nochain_stack_size_sum_
          += (ChainableStack::instance_->var_nochain_stack_.size()
              - start_nochain_stack_size_);
    } else {
      n_fwd_no_AD_passes_++;
    }
    fwd_pass_time_ += std::chrono::duration<double>(
                          std::chrono::steady_clock::now() - fwd_pass_tp_)
                          .count();
    active_ = false;
  }

  void rev_pass_start() { rev_pass_tp_ = std::chrono::steady_clock::now(); }

  void rev_pass_stop() {
    rev_pass_time_ += std::chrono::duration<double>(
                          std::chrono::steady_clock::now() - rev_pass_tp_)
                          .count();
    n_rev_passes_++;
  }

  size_t get_chain_stack_used() const noexcept {
    return chain_stack_size_sum_;
  };

  size_t get_nochain_stack_used() const noexcept {
    return nochain_stack_size_sum_;
  };

  size_t get_num_no_AD_fwd_passes() const noexcept {
    return n_fwd_no_AD_passes_;
  }

  size_t get_num_AD_fwd_passes() const noexcept { return n_fwd_AD_passes_; }

  size_t get_num_fwd_passes() const noexcept {
    return n_fwd_AD_passes_ + n_fwd_no_AD_passes_;
  }

  double get_fwd_time() const noexcept { return fwd_pass_time_; }

  size_t get_num_rev_passes() const noexcept { return n_rev_passes_; }

  double get_rev_time() const noexcept { return rev_pass_time_; }
};

using profile_key = std::pair<std::string, std::thread::id>;

using profile_map = std::map<profile_key, profile_info>;

/**
 * Profiles C++ lines where the object is in scope.
 * When T is var, the constructor starts the profile for the forward pass
 * and places a var with a callback to stop the reverse pass on the
 * AD tape. The destructor stops the profile for the forward pass and
 * places a var with a callback to start the profile for the reverse pass.
 * When T is not var, the constructor and destructor only profile the
 *
 *
 * @tparam T type of profile class. If var, the created object is used
 * to profile reverse mode AD. Only profiles the forward pass otherwise.
 */
template <typename T>
class profile {
  profile_key key_;
  profile_info* profile_;

 public:
  profile(std::string name, profile_map& profiles)
      : key_({name, std::this_thread::get_id()}) {
    profile_map::iterator p = profiles.find(key_);
    if (p == profiles.end()) {
      profiles[key_] = profile_info();
    }
    profile_ = &profiles[key_];
    if (profile_->is_active()) {
      std::ostringstream msg;
      msg << "Profile '" << key_.first << "' already started!";
      throw std::runtime_error(msg.str());
    }
    profile_->fwd_pass_start<T>();
    if (!is_constant<T>::value) {
      reverse_pass_callback([=]() mutable { profile_->rev_pass_stop(); });
    }
  }
  ~profile() {
    profile_->fwd_pass_stop<T>();
    if (!is_constant<T>::value) {
      reverse_pass_callback([=]() mutable { profile_->rev_pass_start(); });
    }
  }
};

}  // namespace math
}  // namespace stan
#endif
<|endoftext|>


<commit_before>/**
 * @file
 *
 * @brief Tests for KDB
 *
 * @copyright BSD License (see doc/COPYING or http://www.libelektra.org)
 *
 */

#include <keysetio.hpp>

#include <gtest/gtest-elektra.h>

#include <stdio.h>

class Error : public ::testing::Test
{
protected:
	static const std::string testRoot;
	static const std::string configFileRoot;

	testing::Namespaces namespaces;
	testing::MountpointPtr mpRoot;

	Error () : namespaces ()
	{
	}

	virtual void SetUp () override
	{
		mpRoot.reset (new testing::Mountpoint (testRoot, configFileRoot));
	}

	virtual void TearDown () override
	{
		mpRoot.reset ();
	}
};

const std::string Error::testRoot = "/tests/kdb/";
const std::string Error::configFileRoot = "kdbFileError.dump";

TEST_F (Error, Simple)
{
	using namespace kdb;
	KDB kdb;
	KeySet ks;

	ks.append (Key ("system" + testRoot + "key", KEY_META, "trigger/error", "10", KEY_END));

	ASSERT_EQ (kdb.get (ks, testRoot), 0) << "should be nothing to update";
	ASSERT_EQ (ks.size (), 1) << "did not keep key at get" << ks;

	Key parentKey (testRoot, KEY_END);
	EXPECT_THROW (kdb.set (ks, parentKey), kdb::KDBException) << "could not trigger error";
	struct stat buf;
	ASSERT_EQ (stat (mpRoot->systemConfigFile.c_str (), &buf), -1) << "found wrong file";

	EXPECT_TRUE (parentKey.getMeta<const kdb::Key> ("error"));
	EXPECT_TRUE (parentKey.getMeta<const kdb::Key> ("error/number"));
	EXPECT_EQ (parentKey.getMeta<int> ("error/number"), 10);

	ASSERT_EQ (ks.size (), 1) << "did not keep key at set" << ks;
}

TEST_F (Error, Again)
{
	using namespace kdb;
	KDB kdb;
	KeySet ks;

	ks.append (Key ("system" + testRoot + "key", KEY_META, "trigger/error", "10", KEY_END));

	ASSERT_EQ (kdb.get (ks, testRoot), 0) << "should be nothing to update";

	Key parentKey (testRoot, KEY_END);
	EXPECT_THROW (kdb.set (ks, parentKey), kdb::KDBException) << "could not trigger error";

	EXPECT_TRUE (parentKey.getMeta<const kdb::Key> ("error"));
	EXPECT_TRUE (parentKey.getMeta<const kdb::Key> ("error/number"));
	EXPECT_EQ (parentKey.getMeta<int> ("error/number"), 10);

	ks.append (Key ("system" + testRoot + "key", KEY_META, "trigger/error", "110", KEY_END));

	EXPECT_THROW (kdb.set (ks, parentKey), kdb::KDBException) << "could not trigger error (again)";

	EXPECT_TRUE (parentKey.getMeta<const kdb::Key> ("error"));
	EXPECT_TRUE (parentKey.getMeta<const kdb::Key> ("error/number"));
	EXPECT_EQ (parentKey.getMeta<int> ("error/number"), 110);

	ASSERT_EQ (ks.size (), 1) << "did not keep key at set (again)" << ks;
}

TEST_F (Error, CSimple)
{
	using namespace ckdb;
	Key * parentKey = keyNew (testRoot.c_str (), KEY_END);
	KDB * kdb = kdbOpen (parentKey);
	KeySet * ks = ksNew (20, KS_END);

	ksAppendKey (ks, keyNew (("system" + testRoot + "key").c_str (), KEY_META, "trigger/error", "10", KEY_END));

	ASSERT_EQ (kdbGet (kdb, ks, parentKey), 0) << "should be nothing to update";
	ASSERT_EQ (ksGetSize (ks), 1) << "did not keep key at get" << ks;

	EXPECT_EQ (kdbSet (kdb, ks, parentKey), -1) << "could not trigger error";

	EXPECT_TRUE (ckdb::keyGetMeta (parentKey, "error"));
	EXPECT_STREQ (keyString (ckdb::keyGetMeta (parentKey, "error/number")), "10");

	kdbClose (kdb, parentKey);
	keyDel (parentKey);
	ksDel (ks);
}

TEST_F (Error, ToWarning)
{
	using namespace ckdb;
	Key * parentKey = keyNew (testRoot.c_str (), KEY_END);
	KDB * kdb = kdbOpen (parentKey);
	KeySet * ks = ksNew (20, KS_END);

	ksAppendKey (ks, keyNew (("system" + testRoot + "key1").c_str (), KEY_META, "trigger/error/nofail", "10", KEY_END));
	ksAppendKey (ks, keyNew (("system" + testRoot + "key2").c_str (), KEY_META, "trigger/error", "110", KEY_END));

	ASSERT_EQ (kdbGet (kdb, ks, parentKey), 0) << "should be nothing to update";
	ASSERT_EQ (ksGetSize (ks), 2) << "did not keep key at get" << ks;

	EXPECT_EQ (kdbSet (kdb, ks, parentKey), -1) << "could not trigger error";

	EXPECT_TRUE (ckdb::keyGetMeta (parentKey, "error"));
	EXPECT_STREQ (keyString (ckdb::keyGetMeta (parentKey, "error/number")), "10");

	EXPECT_TRUE (ckdb::keyGetMeta (parentKey, "warnings/#00"));
	EXPECT_STREQ (keyString (ckdb::keyGetMeta (parentKey, "warnings/#00/number")), "110");

	kdbClose (kdb, parentKey);
	keyDel (parentKey);
	ksDel (ks);
}

TEST_F (Error, Persists)
{
	using namespace ckdb;
	Key * parentKey = keyNew (testRoot.c_str (), KEY_END);
	KDB * kdb = kdbOpen (parentKey);
	KeySet * ks = ksNew (20, KS_END);

	ksAppendKey (ks, keyNew (("system" + testRoot + "key").c_str (), KEY_META, "trigger/error", "10", KEY_END));

	ASSERT_EQ (kdbGet (kdb, ks, parentKey), 0) << "should be nothing to update";
	ASSERT_EQ (ksGetSize (ks), 1) << "did not keep key at get" << ks;

	EXPECT_EQ (kdbSet (kdb, ks, parentKey), -1) << "could not trigger error";

	EXPECT_TRUE (ckdb::keyGetMeta (parentKey, "error"));
	EXPECT_STREQ (keyString (ckdb::keyGetMeta (parentKey, "error/number")), "10");

	keyDel (ksLookup (ks, keyNew (("system" + testRoot + "key").c_str (), KEY_END), KDB_O_POP));

	EXPECT_EQ (kdbSet (kdb, ks, parentKey), 0) << "kdbSet failed";
	EXPECT_TRUE (ckdb::keyGetMeta (parentKey, "error"));
	EXPECT_STREQ (keyString (ckdb::keyGetMeta (parentKey, "error/number")), "10");

	kdbClose (kdb, parentKey);
	keyDel (parentKey);
	ksDel (ks);
}
<commit_msg>test: readd repeat again test case<commit_after>/**
 * @file
 *
 * @brief Tests for KDB
 *
 * @copyright BSD License (see doc/COPYING or http://www.libelektra.org)
 *
 */

#include <keysetio.hpp>

#include <gtest/gtest-elektra.h>

#include <stdio.h>

class Error : public ::testing::Test
{
protected:
	static const std::string testRoot;
	static const std::string configFileRoot;

	testing::Namespaces namespaces;
	testing::MountpointPtr mpRoot;

	Error () : namespaces ()
	{
	}

	virtual void SetUp () override
	{
		mpRoot.reset (new testing::Mountpoint (testRoot, configFileRoot));
	}

	virtual void TearDown () override
	{
		mpRoot.reset ();
	}
};

const std::string Error::testRoot = "/tests/kdb/";
const std::string Error::configFileRoot = "kdbFileError.dump";

TEST_F (Error, Simple)
{
	using namespace kdb;
	KDB kdb;
	KeySet ks;

	ks.append (Key ("system" + testRoot + "key", KEY_META, "trigger/error", "10", KEY_END));

	ASSERT_EQ (kdb.get (ks, testRoot), 0) << "should be nothing to update";
	ASSERT_EQ (ks.size (), 1) << "did not keep key at get" << ks;

	Key parentKey (testRoot, KEY_END);
	EXPECT_THROW (kdb.set (ks, parentKey), kdb::KDBException) << "could not trigger error";
	struct stat buf;
	ASSERT_EQ (stat (mpRoot->systemConfigFile.c_str (), &buf), -1) << "found wrong file";

	EXPECT_TRUE (parentKey.getMeta<const kdb::Key> ("error"));
	EXPECT_TRUE (parentKey.getMeta<const kdb::Key> ("error/number"));
	EXPECT_EQ (parentKey.getMeta<int> ("error/number"), 10);

	ASSERT_EQ (ks.size (), 1) << "did not keep key at set" << ks;
}

TEST_F (Error, Again)
{
	using namespace kdb;
	KDB kdb;
	KeySet ks;

	ks.append (Key ("system" + testRoot + "key", KEY_META, "trigger/error", "10", KEY_END));

	ASSERT_EQ (kdb.get (ks, testRoot), 0) << "should be nothing to update";

	Key parentKey (testRoot, KEY_END);
	EXPECT_THROW (kdb.set (ks, parentKey), kdb::KDBException) << "could not trigger error";

	EXPECT_TRUE (parentKey.getMeta<const kdb::Key> ("error"));
	EXPECT_TRUE (parentKey.getMeta<const kdb::Key> ("error/number"));
	EXPECT_EQ (parentKey.getMeta<int> ("error/number"), 10);

	ks.append (Key ("system" + testRoot + "key", KEY_META, "trigger/error", "110", KEY_END));

	EXPECT_THROW (kdb.set (ks, parentKey), kdb::KDBException) << "could not trigger error (again)";

	EXPECT_TRUE (parentKey.getMeta<const kdb::Key> ("error"));
	EXPECT_TRUE (parentKey.getMeta<const kdb::Key> ("error/number"));
	EXPECT_EQ (parentKey.getMeta<int> ("error/number"), 110);

	ASSERT_EQ (ks.size (), 1) << "did not keep key at set (again)" << ks;
}

TEST_F (Error, AgainRepeat)
{
	using namespace kdb;
	KDB kdb;
	KeySet ks;

	ks.append (Key ("system" + testRoot + "key", KEY_META, "trigger/error", "10", KEY_END));

	ASSERT_EQ (kdb.get (ks, testRoot), 0) << "should be nothing to update";

	Key parentKey (testRoot, KEY_END);
	EXPECT_THROW (kdb.set (ks, parentKey), kdb::KDBException) << "could not trigger error";

	EXPECT_TRUE (parentKey.getMeta<const kdb::Key> ("error"));
	EXPECT_TRUE (parentKey.getMeta<const kdb::Key> ("error/number"));
	EXPECT_EQ (parentKey.getMeta<int> ("error/number"), 10);

	for (int i = 0; i < 10; ++i)
	{
		ks.append (Key ("system" + testRoot + "key", KEY_END));

		EXPECT_NO_THROW (kdb.set (ks, parentKey)) << "no error trigger?";

		ks.append (Key ("system" + testRoot + "key", KEY_META, "trigger/error", std::to_string (119 + i).c_str (), KEY_END));

		EXPECT_THROW (kdb.set (ks, parentKey), kdb::KDBException) << "could not trigger error (again)";

		EXPECT_TRUE (parentKey.getMeta<const kdb::Key> ("error"));
		EXPECT_TRUE (parentKey.getMeta<const kdb::Key> ("error/number"));
		EXPECT_EQ (parentKey.getMeta<int> ("error/number"), 119 + i);

		ASSERT_EQ (ks.size (), 1) << "did not keep key at set (again)" << ks;
	}
}

TEST_F (Error, CSimple)
{
	using namespace ckdb;
	Key * parentKey = keyNew (testRoot.c_str (), KEY_END);
	KDB * kdb = kdbOpen (parentKey);
	KeySet * ks = ksNew (20, KS_END);

	ksAppendKey (ks, keyNew (("system" + testRoot + "key").c_str (), KEY_META, "trigger/error", "10", KEY_END));

	ASSERT_EQ (kdbGet (kdb, ks, parentKey), 0) << "should be nothing to update";
	ASSERT_EQ (ksGetSize (ks), 1) << "did not keep key at get" << ks;

	EXPECT_EQ (kdbSet (kdb, ks, parentKey), -1) << "could not trigger error";

	EXPECT_TRUE (ckdb::keyGetMeta (parentKey, "error"));
	EXPECT_STREQ (keyString (ckdb::keyGetMeta (parentKey, "error/number")), "10");

	kdbClose (kdb, parentKey);
	keyDel (parentKey);
	ksDel (ks);
}

TEST_F (Error, ToWarning)
{
	using namespace ckdb;
	Key * parentKey = keyNew (testRoot.c_str (), KEY_END);
	KDB * kdb = kdbOpen (parentKey);
	KeySet * ks = ksNew (20, KS_END);

	ksAppendKey (ks, keyNew (("system" + testRoot + "key1").c_str (), KEY_META, "trigger/error/nofail", "10", KEY_END));
	ksAppendKey (ks, keyNew (("system" + testRoot + "key2").c_str (), KEY_META, "trigger/error", "110", KEY_END));

	ASSERT_EQ (kdbGet (kdb, ks, parentKey), 0) << "should be nothing to update";
	ASSERT_EQ (ksGetSize (ks), 2) << "did not keep key at get" << ks;

	EXPECT_EQ (kdbSet (kdb, ks, parentKey), -1) << "could not trigger error";

	EXPECT_TRUE (ckdb::keyGetMeta (parentKey, "error"));
	EXPECT_STREQ (keyString (ckdb::keyGetMeta (parentKey, "error/number")), "10");

	EXPECT_TRUE (ckdb::keyGetMeta (parentKey, "warnings/#00"));
	EXPECT_STREQ (keyString (ckdb::keyGetMeta (parentKey, "warnings/#00/number")), "110");

	kdbClose (kdb, parentKey);
	keyDel (parentKey);
	ksDel (ks);
}

TEST_F (Error, Persists)
{
	using namespace ckdb;
	Key * parentKey = keyNew (testRoot.c_str (), KEY_END);
	KDB * kdb = kdbOpen (parentKey);
	KeySet * ks = ksNew (20, KS_END);

	ksAppendKey (ks, keyNew (("system" + testRoot + "key").c_str (), KEY_META, "trigger/error", "10", KEY_END));

	ASSERT_EQ (kdbGet (kdb, ks, parentKey), 0) << "should be nothing to update";
	ASSERT_EQ (ksGetSize (ks), 1) << "did not keep key at get" << ks;

	EXPECT_EQ (kdbSet (kdb, ks, parentKey), -1) << "could not trigger error";

	EXPECT_TRUE (ckdb::keyGetMeta (parentKey, "error"));
	EXPECT_STREQ (keyString (ckdb::keyGetMeta (parentKey, "error/number")), "10");

	keyDel (ksLookup (ks, keyNew (("system" + testRoot + "key").c_str (), KEY_END), KDB_O_POP));

	EXPECT_EQ (kdbSet (kdb, ks, parentKey), 0) << "kdbSet failed";
	EXPECT_TRUE (ckdb::keyGetMeta (parentKey, "error"));
	EXPECT_STREQ (keyString (ckdb::keyGetMeta (parentKey, "error/number")), "10");

	kdbClose (kdb, parentKey);
	keyDel (parentKey);
	ksDel (ks);
}
<|endoftext|>


<commit_before>#include <Generate/Agent.h>

using namespace std;

TAU_BEGIN

namespace Generate
{
	bool Agent::Generate(TauParser const &p, const char *fname) override
	{
		return false;
	}

	bool Agent::Namespace(TauParser::AstNode const &ns)
	{
		return false;
	}

	bool Agent::Class(TauParser::AstNode const &cl)
	{
		return false;
	}

	bool Agent::Property(TauParser::AstNode const &prop)
	{
		return false;
	}

	bool Agent::Method(TauParser::AstNode const &method)
	{
		return false;
	}

	std::string Agent::ArgType(std::string &&text) const
	{
		return move(text);
	}

	std::string ReturnType(std::string &&text) const
	{
		return move(text);
	}
}

TAU_END
<commit_msg>Falling asleep<commit_after>#include <Generate/Agent.h>

using namespace std;

TAU_BEGIN

namespace Generate
{
	bool Agent::Generate(TauParser const &p, const char *fname)
	{
		return false;
	}

	bool Agent::Namespace(TauParser::AstNode const &ns)
	{
		return false;
	}

	bool Agent::Class(TauParser::AstNode const &cl)
	{
		return false;
	}

	bool Agent::Property(TauParser::AstNode const &prop)
	{
		return false;
	}

	bool Agent::Method(TauParser::AstNode const &method)
	{
		return false;
	}

	std::string Agent::ArgType(std::string &&text) const
	{
		return move(text);
	}

	std::string Agent::ReturnType(std::string &&text) const
	{
		return move(text);
	}
}

TAU_END
<|endoftext|>


<commit_before><commit_msg>Revert "MLDB-1058: improved performance by making HttpRestEndpoint::RestConnectionHandler::sendResponse call "send" directly, instead of instantiating an HttpResponse"<commit_after><|endoftext|>


<commit_before><commit_msg>EDID vendor and product IDs were swapped. Oops!<commit_after><|endoftext|>


<commit_before>//
// Created by dar on 1/23/16.
//

#include <window/MainMenu.h>
#include <window/Window.h>
#include "Application.h"
#include "render/RenderManager.h"
#include "logging.h"
#include <ApplicationContext.h>
#include <window/LoadingScreen.h>

Application::Application() {
    this->renderer = new RenderManager();
    auto switchWindow = [&](Window *window) {
        if (window == nullptr) {
            this->running = false;
            return false;
        }
        this->previousWindow = this->window;
        this->window = window;
        this->renderer->initWindow(this->window);
        this->resize(this->renderer->getRenderContext()->getWindowWidth(), this->renderer->getRenderContext()->getWindowHeight());
        return true;
    };
    this->window = new LoadingScreen(new ApplicationContext(switchWindow));
    this->timer = new Timer();
    this->inputManager = new InputManager();
    this->reinit();
    this->resize(1366, 750);
}

void Application::reinit() {
    this->renderer->init();
    this->renderer->initWindow(this->window); //TODO
    timer->GetDelta(); //if not called right now, first call in game loop would return a very huge value
    this->inputManager->reload();
}

void Application::run() {
    while (isRunning()) {
        update(true);
    }
}

void Application::update(bool dynamic) {
    if (this->previousWindow != nullptr) {
        delete this->previousWindow;
        this->previousWindow = nullptr;
    }
    if (dynamic) {
        this->deltaTimeHistory[this->ticks] = timer->GetDelta();
        if (this->ticks == 14) {
            this->averageDeltaTime = 0.0;
            for (int i = 0; i < 15; i++) {
                this->averageDeltaTime += this->deltaTimeHistory[i];
            }
        }
        this->getCurrentWindow()->tick(this->averageDeltaTime * 4.0); //multiplied by 4.0 to make the whole equal ~1.0
    } else {
        this->getCurrentWindow()->tick(1.0);
    }
    this->renderer->render(this->getCurrentWindow());
    if (!IS_MOBILE) this->handleEvents();
    this->inputManager->tick(this->getCurrentWindow());
    this->ticks++;
    if (this->ticks > 14) {
        this->ticks = 0;
    }
}

Application::~Application() {
    delete this->window;
}

#ifdef __ANDROID__

#include <jni.h>

Application *application = nullptr;

extern "C" {
JNIEXPORT void JNICALL Java_tk_approach_android_spookytom_JniBridge_init(JNIEnv *env, jobject obj);
JNIEXPORT void JNICALL Java_tk_approach_android_spookytom_JniBridge_resize(JNIEnv *env, jobject obj, jint width, jint height);
JNIEXPORT void JNICALL Java_tk_approach_android_spookytom_JniBridge_tick(JNIEnv *env, jobject obj);
JNIEXPORT void JNICALL Java_tk_approach_android_spookytom_JniBridge_handleTouch(JNIEnv *env, jobject obj, jint i, jint action, jfloat x, jfloat y);
};

JNIEXPORT void JNICALL Java_tk_approach_android_spookytom_JniBridge_init(JNIEnv *env, jobject obj) {
    if (application == nullptr || application->getCurrentWindow() == nullptr) {
        application =  new Application();
    } else {
        application->reinit();
    }
    /*jclass cls = env->GetObjectClass(obj);
    jmethodID mid = env->GetMethodID(cls, "loadTexture", "()V");
    if (mid == 0) {
        return;
    }
    env->CallVoidMethod(obj, mid);*/
}

JNIEXPORT void JNICALL Java_tk_approach_android_spookytom_JniBridge_resize(JNIEnv *env, jobject obj, jint width, jint height) {
    application->resize(width, height);
}

JNIEXPORT void JNICALL Java_tk_approach_android_spookytom_JniBridge_tick(JNIEnv *env, jobject obj) {
    application->update(false);
    if (!application->isRunning()) {
        jclass cls = env->GetObjectClass(obj);
        jmethodID mid = env->GetMethodID(cls, "exit", "()V");
        if (mid != 0) {
            delete application;
            env->CallVoidMethod(obj, mid);
        }
    }
}

JNIEXPORT void JNICALL Java_tk_approach_android_spookytom_JniBridge_handleTouch(JNIEnv *env, jobject obj, jint i,  jint action, jfloat x, jfloat y) {
    application->handleClick(i, action, x, y);
}

#endif //__ANDROID__

void Application::resize(int width, int height) {
    this->getCurrentWindow()->reload(width, height);
    this->renderer->resize(this->getCurrentWindow(), width, height);
}

void Application::handleClick(int i, int action, float x, float y) {
    this->inputManager->handleClick(i, action, x, y);
}

void Application::handleEvents() {
#ifndef __ANDROID__
    while (SDL_PollEvent(&e) != 0) {
        switch (e.type) {
            case SDL_QUIT:
                this->running = false;
                break;
            case SDL_WINDOWEVENT:
                if (e.window.event == SDL_WINDOWEVENT_RESIZED || e.window.event == SDL_WINDOWEVENT_SIZE_CHANGED) {
                    this->resize((unsigned int) e.window.data1, (unsigned int) e.window.data2);
                }
                break;
            case SDL_KEYDOWN:
            case SDL_KEYUP:
                this->inputManager->handleKeypress(&e);
                break;
            case SDL_MOUSEBUTTONDOWN:
            case SDL_MOUSEBUTTONUP:
                Log::debug("%s button with id %d\n", e.type == SDL_MOUSEBUTTONDOWN ? "Pressed" : "Unpressed", e.button.button);
            case SDL_MOUSEMOTION: {
                int button = (int) round(log((double) e.button.button) / log(2.0)) + 1;
                if (button < 0 || button >= 5) break;
                int x, y;
                SDL_GetMouseState(&x, &y);
                this->handleClick(button, e.type == SDL_MOUSEBUTTONDOWN ? 0 : (e.type == SDL_MOUSEBUTTONUP ? 1 : 2), x, y);
                break;
            }
        }
    }
#else //__ANDROID__
    LOGW("SDL is not supported on this platform\n");
#endif //__ANDROID__

}
<commit_msg>Keep application object by value on Android<commit_after>//
// Created by dar on 1/23/16.
//

#include <window/MainMenu.h>
#include <window/Window.h>
#include "Application.h"
#include "render/RenderManager.h"
#include "logging.h"
#include <ApplicationContext.h>
#include <window/LoadingScreen.h>

Application::Application() {
    this->renderer = new RenderManager();
    auto switchWindow = [&](Window *window) {
        if (window == nullptr) {
            this->running = false;
            return false;
        }
        this->previousWindow = this->window;
        this->window = window;
        this->renderer->initWindow(this->window);
        this->resize(this->renderer->getRenderContext()->getWindowWidth(), this->renderer->getRenderContext()->getWindowHeight());
        return true;
    };
    this->window = new LoadingScreen(new ApplicationContext(switchWindow));
    this->timer = new Timer();
    this->inputManager = new InputManager();
    this->reinit();
    this->resize(1366, 750);
}

void Application::reinit() {
    this->renderer->init();
    this->renderer->initWindow(this->window); //TODO
    timer->GetDelta(); //if not called right now, first call in game loop would return a very huge value
    this->inputManager->reload();
}

void Application::run() {
    while (isRunning()) {
        update(true);
    }
}

void Application::update(bool dynamic) {
    if (this->previousWindow != nullptr) {
        delete this->previousWindow;
        this->previousWindow = nullptr;
    }
    if (dynamic) {
        this->deltaTimeHistory[this->ticks] = timer->GetDelta();
        if (this->ticks == 14) {
            this->averageDeltaTime = 0.0;
            for (int i = 0; i < 15; i++) {
                this->averageDeltaTime += this->deltaTimeHistory[i];
            }
        }
        this->getCurrentWindow()->tick(this->averageDeltaTime * 4.0); //multiplied by 4.0 to make the whole equal ~1.0
    } else {
        this->getCurrentWindow()->tick(1.0);
    }
    this->renderer->render(this->getCurrentWindow());
    if (!IS_MOBILE) this->handleEvents();
    this->inputManager->tick(this->getCurrentWindow());
    this->ticks++;
    if (this->ticks > 14) {
        this->ticks = 0;
    }
}

Application::~Application() {
    delete this->window;
}

#ifdef __ANDROID__

#include <jni.h>

Application application;
bool initialized = false;

extern "C" {
JNIEXPORT void JNICALL Java_tk_approach_android_spookytom_JniBridge_init(JNIEnv *env, jobject obj);
JNIEXPORT void JNICALL Java_tk_approach_android_spookytom_JniBridge_resize(JNIEnv *env, jobject obj, jint width, jint height);
JNIEXPORT void JNICALL Java_tk_approach_android_spookytom_JniBridge_tick(JNIEnv *env, jobject obj);
JNIEXPORT void JNICALL Java_tk_approach_android_spookytom_JniBridge_handleTouch(JNIEnv *env, jobject obj, jint i, jint action, jfloat x, jfloat y);
};

JNIEXPORT void JNICALL Java_tk_approach_android_spookytom_JniBridge_init(JNIEnv *env, jobject obj) {
    if (initialized) {
        application.reinit();
    }
    /*jclass cls = env->GetObjectClass(obj);
    jmethodID mid = env->GetMethodID(cls, "loadTexture", "()V");
    if (mid == 0) {
        return;
    }
    env->CallVoidMethod(obj, mid);*/
}

JNIEXPORT void JNICALL Java_tk_approach_android_spookytom_JniBridge_resize(JNIEnv *env, jobject obj, jint width, jint height) {
    application.resize(width, height);
}

JNIEXPORT void JNICALL Java_tk_approach_android_spookytom_JniBridge_tick(JNIEnv *env, jobject obj) {
    application.update(false);
    if (!application.isRunning()) {
        jclass cls = env->GetObjectClass(obj);
        jmethodID mid = env->GetMethodID(cls, "exit", "()V");
        if (mid != 0) {
            env->CallVoidMethod(obj, mid);
        }
    }
}

JNIEXPORT void JNICALL Java_tk_approach_android_spookytom_JniBridge_handleTouch(JNIEnv *env, jobject obj, jint i,  jint action, jfloat x, jfloat y) {
    application.handleClick(i, action, x, y);
}

#endif //__ANDROID__

void Application::resize(int width, int height) {
    this->getCurrentWindow()->reload(width, height);
    this->renderer->resize(this->getCurrentWindow(), width, height);
}

void Application::handleClick(int i, int action, float x, float y) {
    this->inputManager->handleClick(i, action, x, y);
}

void Application::handleEvents() {
#ifndef __ANDROID__
    while (SDL_PollEvent(&e) != 0) {
        switch (e.type) {
            case SDL_QUIT:
                this->running = false;
                break;
            case SDL_WINDOWEVENT:
                if (e.window.event == SDL_WINDOWEVENT_RESIZED || e.window.event == SDL_WINDOWEVENT_SIZE_CHANGED) {
                    this->resize((unsigned int) e.window.data1, (unsigned int) e.window.data2);
                }
                break;
            case SDL_KEYDOWN:
            case SDL_KEYUP:
                this->inputManager->handleKeypress(&e);
                break;
            case SDL_MOUSEBUTTONDOWN:
            case SDL_MOUSEBUTTONUP:
                Log::debug("%s button with id %d\n", e.type == SDL_MOUSEBUTTONDOWN ? "Pressed" : "Unpressed", e.button.button);
            case SDL_MOUSEMOTION: {
                int button = (int) round(log((double) e.button.button) / log(2.0)) + 1;
                if (button < 0 || button >= 5) break;
                int x, y;
                SDL_GetMouseState(&x, &y);
                this->handleClick(button, e.type == SDL_MOUSEBUTTONDOWN ? 0 : (e.type == SDL_MOUSEBUTTONUP ? 1 : 2), x, y);
                break;
            }
        }
    }
#else //__ANDROID__
    LOGW("SDL is not supported on this platform\n");
#endif //__ANDROID__

}
<|endoftext|>


<commit_before>// This file is part of playd.
// playd is licensed under the MIT licence: see LICENSE.txt.

/**
 * @file
 * Implementation of the Mp3AudioSource class.
 * @see audio/sources/mp3.hpp
 */

#include <cassert>
#include <cstdint>
#include <cstdlib>
#include <iostream>
#include <map>
#include <memory>
#include <sstream>
#include <string>

extern "C" {
#include <mpg123.h>
}

#include "../../errors.hpp"
#include "../../messages.h"
#include "../audio_source.hpp"
#include "../sample_formats.hpp"
#include "mp3.hpp"

// This value is somewhat arbitrary, but corresponds to the minimum buffer size
// used by ffmpeg, so it's probably sensible.
const size_t Mp3AudioSource::BUFFER_SIZE = 16384;

Mp3AudioSource::Mp3AudioSource(const std::string &path)
    : AudioSource(path), buffer(BUFFER_SIZE), context(nullptr)
{
	this->context = mpg123_new(nullptr, nullptr);
	mpg123_format_none(this->context);

	const long *rates = nullptr;
	size_t nrates = 0;
	mpg123_rates(&rates, &nrates);
	for (size_t r = 0; r < nrates; r++) {
		Debug() << "trying to enable formats at " << rates[r]
		        << std::endl;
		AddFormat(rates[r]);
	}

	if (mpg123_open(this->context, path.c_str()) == MPG123_ERR) {
		throw FileError("mp3: can't open " + path + ": " +
		                mpg123_strerror(this->context));
	}

	Debug() << "mp3: sample rate:" << this->SampleRate() << std::endl;
	Debug() << "mp3: bytes per sample:" << this->BytesPerSample()
	        << std::endl;
	Debug() << "mp3: channels:" << (int)this->ChannelCount() << std::endl;
	Debug() << "mp3: playd format:" << (int)this->OutputSampleFormat()
	        << std::endl;
}

Mp3AudioSource::~Mp3AudioSource()
{
	mpg123_delete(this->context);
	this->context = nullptr;
}

void Mp3AudioSource::AddFormat(long rate)
{
	// The requested encodings correspond to the sample formats available in
	// the SampleFormat enum.
	if (mpg123_format(this->context, rate, MPG123_STEREO | MPG123_MONO,
	                  (MPG123_ENC_UNSIGNED_8 | MPG123_ENC_SIGNED_8 |
	                   MPG123_ENC_SIGNED_16 | MPG123_ENC_SIGNED_24 |
	                   MPG123_ENC_SIGNED_32 | MPG123_ENC_FLOAT_32)) ==
	    MPG123_ERR) {
		// Ignore the error for now -- another sample rate may be
		// available.
		// If no sample rates work, loading a file will fail anyway.
		Debug() << "can't support" << rate << std::endl;
	};
}

std::uint8_t Mp3AudioSource::ChannelCount() const
{
	assert(this->context != nullptr);

	int chans = 0;
	mpg123_getformat(this->context, nullptr, &chans, nullptr);
	assert(chans != 0);
	return static_cast<std::uint8_t>(chans);
}

std::uint32_t Mp3AudioSource::SampleRate() const
{
	assert(this->context != nullptr);

	long rate = 0;
	mpg123_getformat(this->context, &rate, nullptr, nullptr);

	assert(0 < rate);
	// INT32_MAX isn't a typo; if we compare against UINT32_MAX, we'll
	// set off sign-compare errors, and the sample rate shouldn't be above
	// INT32_MAX anyroad.
	assert(rate <= INT32_MAX);
	return static_cast<std::uint32_t>(rate);
}

std::uint64_t Mp3AudioSource::Seek(std::uint64_t in_samples)
{
	assert(this->context != nullptr);

	// See BytesPerSample() for an explanation of this ChannelCount().
	auto mono_samples = in_samples * this->ChannelCount();

	// Have we tried to seek past the end of the file?
	auto clen = static_cast<unsigned long>(mpg123_length(this->context));
	if (clen < mono_samples) {
		Debug() << "mp3: seek at" << mono_samples << "past EOF at"
		        << clen << std::endl;
		throw SeekError(MSG_SEEK_FAIL);
	}

	if (mpg123_seek(this->context, mono_samples, SEEK_SET) == MPG123_ERR) {
		Debug() << "mp3: seek failed:" << mpg123_strerror(this->context)
		        << std::endl;
		throw SeekError(MSG_SEEK_FAIL);
	}

	// The actual seek position may not be the same as the requested
	// position.
	// mpg123_tell gives us the exact mono-samples position.
	return mpg123_tell(this->context) / this->ChannelCount();
}

Mp3AudioSource::DecodeResult Mp3AudioSource::Decode()
{
	assert(this->context != nullptr);

	auto buf = reinterpret_cast<unsigned char *>(&this->buffer.front());
	size_t rbytes = 0;
	int err = mpg123_read(this->context, buf, this->buffer.size(), &rbytes);

	DecodeVector decoded;
	DecodeState decode_state;

	if (err == MPG123_DONE) {
		Debug() << "mp3: end of file" << std::endl;
		decode_state = DecodeState::END_OF_FILE;
	} else if (err != MPG123_OK && err != MPG123_NEW_FORMAT) {
		Debug() << "mp3: decode error:" << mpg123_strerror(this->context)
		        << std::endl;
		decode_state = DecodeState::END_OF_FILE;
	} else {
		decode_state = DecodeState::DECODING;

		// Copy only the bit of the buffer occupied by decoded data
		auto front = this->buffer.begin();
		decoded = DecodeVector(front, front + rbytes);
	}

	return std::make_pair(decode_state, decoded);
}

SampleFormat Mp3AudioSource::OutputSampleFormat() const
{
	assert(this->context != nullptr);

	int encoding = 0;
	mpg123_getformat(this->context, nullptr, nullptr, &encoding);

	switch (encoding) {
		case MPG123_ENC_UNSIGNED_8:
			return SampleFormat::PACKED_UNSIGNED_INT_8;
		case MPG123_ENC_SIGNED_8:
			return SampleFormat::PACKED_SIGNED_INT_8;
		case MPG123_ENC_SIGNED_16:
			return SampleFormat::PACKED_SIGNED_INT_16;
		case MPG123_ENC_SIGNED_24:
			return SampleFormat::PACKED_SIGNED_INT_24;
		case MPG123_ENC_SIGNED_32:
			return SampleFormat::PACKED_SIGNED_INT_32;
		case MPG123_ENC_FLOAT_32:
			return SampleFormat::PACKED_FLOAT_32;
		default:
			// We shouldn't get here, if the format was set up
			// correctly earlier.
			assert(false);
	}
}
<commit_msg>Add polyfills for Ubuntu 12.04's ancient libmpg123.<commit_after>// This file is part of playd.
// playd is licensed under the MIT licence: see LICENSE.txt.

/**
 * @file
 * Implementation of the Mp3AudioSource class.
 * @see audio/sources/mp3.hpp
 */

#include <cassert>
#include <cstdint>
#include <cstdlib>
#include <iostream>
#include <map>
#include <memory>
#include <sstream>
#include <string>

extern "C" {
#include <mpg123.h>
}

#include "../../errors.hpp"
#include "../../messages.h"
#include "../audio_source.hpp"
#include "../sample_formats.hpp"
#include "mp3.hpp"

// Fix for the ancient 2010 version of mpg123 carried by Ubuntu 12.04 and pals,
// which doesn't have 24-bit support
// See http://www.mpg123.de/cgi-bin/scm/mpg123/trunk/NEWS?pathrev=2791
#if MPG123_API_VERSION < 28
	// Let us be able to omit the check for 24-bit formats later.
	#define HAVE_MPG123_24BIT 1

	// Make the use of this when divining formats a no-op.
	#define MPG123_ENC_SIGNED_24 0
#endif

// This value is somewhat arbitrary, but corresponds to the minimum buffer size
// used by ffmpeg, so it's probably sensible.
const size_t Mp3AudioSource::BUFFER_SIZE = 16384;

Mp3AudioSource::Mp3AudioSource(const std::string &path)
    : AudioSource(path), buffer(BUFFER_SIZE), context(nullptr)
{
	this->context = mpg123_new(nullptr, nullptr);
	mpg123_format_none(this->context);

	const long *rates = nullptr;
	size_t nrates = 0;
	mpg123_rates(&rates, &nrates);
	for (size_t r = 0; r < nrates; r++) {
		Debug() << "trying to enable formats at " << rates[r]
		        << std::endl;
		AddFormat(rates[r]);
	}

	if (mpg123_open(this->context, path.c_str()) == MPG123_ERR) {
		throw FileError("mp3: can't open " + path + ": " +
		                mpg123_strerror(this->context));
	}

	Debug() << "mp3: sample rate:" << this->SampleRate() << std::endl;
	Debug() << "mp3: bytes per sample:" << this->BytesPerSample()
	        << std::endl;
	Debug() << "mp3: channels:" << (int)this->ChannelCount() << std::endl;
	Debug() << "mp3: playd format:" << (int)this->OutputSampleFormat()
	        << std::endl;
}

Mp3AudioSource::~Mp3AudioSource()
{
	mpg123_delete(this->context);
	this->context = nullptr;
}

void Mp3AudioSource::AddFormat(long rate)
{
	// The requested encodings correspond to the sample formats available in
	// the SampleFormat enum.
	if (mpg123_format(this->context, rate, MPG123_STEREO | MPG123_MONO,
	                  (MPG123_ENC_UNSIGNED_8 | MPG123_ENC_SIGNED_8 |
	                   MPG123_ENC_SIGNED_16 | MPG123_ENC_SIGNED_24 |
	                   MPG123_ENC_SIGNED_32 | MPG123_ENC_FLOAT_32)) ==
	    MPG123_ERR) {
		// Ignore the error for now -- another sample rate may be
		// available.
		// If no sample rates work, loading a file will fail anyway.
		Debug() << "can't support" << rate << std::endl;
	};
}

std::uint8_t Mp3AudioSource::ChannelCount() const
{
	assert(this->context != nullptr);

	int chans = 0;
	mpg123_getformat(this->context, nullptr, &chans, nullptr);
	assert(chans != 0);
	return static_cast<std::uint8_t>(chans);
}

std::uint32_t Mp3AudioSource::SampleRate() const
{
	assert(this->context != nullptr);

	long rate = 0;
	mpg123_getformat(this->context, &rate, nullptr, nullptr);

	assert(0 < rate);
	// INT32_MAX isn't a typo; if we compare against UINT32_MAX, we'll
	// set off sign-compare errors, and the sample rate shouldn't be above
	// INT32_MAX anyroad.
	assert(rate <= INT32_MAX);
	return static_cast<std::uint32_t>(rate);
}

std::uint64_t Mp3AudioSource::Seek(std::uint64_t in_samples)
{
	assert(this->context != nullptr);

	// See BytesPerSample() for an explanation of this ChannelCount().
	auto mono_samples = in_samples * this->ChannelCount();

	// Have we tried to seek past the end of the file?
	auto clen = static_cast<unsigned long>(mpg123_length(this->context));
	if (clen < mono_samples) {
		Debug() << "mp3: seek at" << mono_samples << "past EOF at"
		        << clen << std::endl;
		throw SeekError(MSG_SEEK_FAIL);
	}

	if (mpg123_seek(this->context, mono_samples, SEEK_SET) == MPG123_ERR) {
		Debug() << "mp3: seek failed:" << mpg123_strerror(this->context)
		        << std::endl;
		throw SeekError(MSG_SEEK_FAIL);
	}

	// The actual seek position may not be the same as the requested
	// position.
	// mpg123_tell gives us the exact mono-samples position.
	return mpg123_tell(this->context) / this->ChannelCount();
}

Mp3AudioSource::DecodeResult Mp3AudioSource::Decode()
{
	assert(this->context != nullptr);

	auto buf = reinterpret_cast<unsigned char *>(&this->buffer.front());
	size_t rbytes = 0;
	int err = mpg123_read(this->context, buf, this->buffer.size(), &rbytes);

	DecodeVector decoded;
	DecodeState decode_state;

	if (err == MPG123_DONE) {
		Debug() << "mp3: end of file" << std::endl;
		decode_state = DecodeState::END_OF_FILE;
	} else if (err != MPG123_OK && err != MPG123_NEW_FORMAT) {
		Debug() << "mp3: decode error:" << mpg123_strerror(this->context)
		        << std::endl;
		decode_state = DecodeState::END_OF_FILE;
	} else {
		decode_state = DecodeState::DECODING;

		// Copy only the bit of the buffer occupied by decoded data
		auto front = this->buffer.begin();
		decoded = DecodeVector(front, front + rbytes);
	}

	return std::make_pair(decode_state, decoded);
}

SampleFormat Mp3AudioSource::OutputSampleFormat() const
{
	assert(this->context != nullptr);

	int encoding = 0;
	mpg123_getformat(this->context, nullptr, nullptr, &encoding);

	switch (encoding) {
		case MPG123_ENC_UNSIGNED_8:
			return SampleFormat::PACKED_UNSIGNED_INT_8;
		case MPG123_ENC_SIGNED_8:
			return SampleFormat::PACKED_SIGNED_INT_8;
		case MPG123_ENC_SIGNED_16:
			return SampleFormat::PACKED_SIGNED_INT_16;
#ifdef HAVE_MPG123_24BIT
		case MPG123_ENC_SIGNED_24:
			return SampleFormat::PACKED_SIGNED_INT_24;
#endif
		case MPG123_ENC_SIGNED_32:
			return SampleFormat::PACKED_SIGNED_INT_32;
		case MPG123_ENC_FLOAT_32:
			return SampleFormat::PACKED_FLOAT_32;
		default:
			// We shouldn't get here, if the format was set up
			// correctly earlier.
			assert(false);
	}
}
<|endoftext|>


<commit_before><commit_msg>no message<commit_after><|endoftext|>


<commit_before>/*************************************************************************
Dictionnaire - Classe de stockage des donnes de maladies
-------------------
dbut                :	06/05/17
copyright            :	(C) 2017 par VOGEL
e-mail               :	hugues.vogel@insa-lyon.fr
*************************************************************************/

//- Ralisation de la classe <Dictionnaire> (fichier Dictionnaire.cpp) -//

//---------------------------------------------------------------- INCLUDE

//-------------------------------------------------------- Include systme

//------------------------------------------------------ Include personnel

#include "Dictionnaire.h"
#include "Mots.h"
#include <string>
#include <fstream>
#include <sstream>
#include <string>

using namespace std;

//----------------------------------------------------------------- PUBLIC

Dictionnaire & Dictionnaire::ObtenirInstance()
{
	// TODO: changer le retour par l'instance du singleton
	return *((Dictionnaire*) nullptr);
}

void Dictionnaire::RafraichirInstance()
{
	/* EXEMPLE
	if (instanceMots != nullptr) {
		delete instanceMots;
	}

	instanceMots = new Mots();
	*/
}

void Dictionnaire::ChargerFichier(const string & fichierDico)
{
	//TODO Destroy Maladies *
	//Reinitialisation des attributs
	maladies= unordered_map<string, Maladie*>();
	maladiesParMot = unordered_map<unsigned int, unordered_set<Maladie*>>();

	//Variables local
	unsigned int l = 0; //numero de ligne actuel
	string ligne;

	ifstream inDico(fichierDico);

	//1er ligne
	l++;
	if (!getline(inDico, ligne)||ligne != "MA v1.0") {//Si on n'arrive pas a lire la 1er ligne
		throw runtime_error("FileTypeINVALIDE");
	}

	//boucle sur tous les autres ligne (les maladies)
	while (getline(inDico, ligne)) {
		l++;
		if (ligne.empty()) {
			//On Ignor les ligne vide
		}
		/*else if (ligne.at(0)=='#') { // Pour l'implementation de ligne de commentaire
			//On Ignor les ligne de commentaire
		}*/
		else {
			//Recuperation du nom de la maladie
			unsigned int pos = ligne.find(';');
			if (pos = string::npos || pos == ligne.length-1) {
				throw runtime_error("Nom de maladie sans definition : " + ligne + " (L " + to_string(l) + ")");
			}
			Maladie * onreadMaladie = new Maladie();
			onreadMaladie->nom = ligne.substr(0, pos);

			//Recuperation de tous les mots de la maladie
			do {

				unsigned int lastpos = pos;
				unsigned int pos = ligne.find(';', lastpos + 1);
				if (pos == string::npos) {
					pos = ligne.length;
				}
				unsigned int length = pos - lastpos - 1; //longeur du mot
				if (length) {
					throw runtime_error("Maladie avec un mot de taille 0 : " + onreadMaladie->nom);
				}

				//recuperation du mot dans un char *
				char * mot = new char[length + 1];
				for (int i = 0; i < length; i++) {
					mot[i] = ligne.at(i + lastpos + 1);
					switch (mot[i] != 'A'    &&    mot[i] != 'T'    &&    mot[i] != 'C'    &&    mot[i] != 'G') {
						throw runtime_error("Maladie avec un mot invalide : " + onreadMaladie->nom + " contien un mot avec '" + mot[i] + "' (L " + to_string(l) + ")");
					}
				}
				mot[length] = '\0';

				//indexation du mot
				unsigned int indexMot;
				try {
					indexMot = Mots::ObtenirInstance().ObtenirIndex(mot);
				}
				catch (const range_error &e) {
					indexMot = Mots::ObtenirInstance().InsererMot(mot);
				}

				//Ajout du mot a la definition
				if (onreadMaladie->definition.find(indexMot) == onreadMaladie->definition.end()) {// Si le mot n'est pas dans la definition (filtre doublon)
					onreadMaladie->definition.insert(indexMot);
				}

				lastpos = pos;
			} while (pos < ligne.length() - 1 || (pos == ligne.length() - 1 && ligne.at(pos) != ';'));

			//Multi definition
			unordered_map<string, Maladie*>::iterator it = maladies.find(onreadMaladie->nom);
			if (it != maladies.end()) {// Si le Maladie est deja referancer
				if (!(*(it->second) == *onreadMaladie)) {
					delete onreadMaladie;
					throw runtime_error("Different definition d'une meme maladie : " + it->first + " (L " + to_string(l) + ")");
				}
				delete onreadMaladie;
			}
			else {//Fist definition
				maladies.insert(pair<string,Maladie *>(onreadMaladie->nom, onreadMaladie));
				for (unordered_set<unsigned int>::iterator motIt = onreadMaladie->definition.begin; motIt != onreadMaladie->definition.begin.end; motIt++) {
					maladiesParMot[*motIt].insert(onreadMaladie);
				}
			}
		}
	}
}

const Maladie & Dictionnaire::ObtenirMaladie(const string & name) {
	return Maladie();
}

const unordered_set<Maladie *> Dictionnaire::ObtenirMaladies(const unsigned int indexMot) {
	// TODO
	return unordered_set<Maladie *>();
}

const unordered_set<string> Dictionnaire::ObtenirNomsMaladies() {
	// TODO
	return unordered_set<string>();
}

//----------------------------------------------------------------- PRIVEE

Dictionnaire::Dictionnaire()
{
}

Dictionnaire::~Dictionnaire()
{
}
<commit_msg>Implementation de Dictionnaire::ObtenirMaladie<commit_after>/*************************************************************************
Dictionnaire - Classe de stockage des donnes de maladies
-------------------
dbut                :	06/05/17
copyright            :	(C) 2017 par VOGEL
e-mail               :	hugues.vogel@insa-lyon.fr
*************************************************************************/

//- Ralisation de la classe <Dictionnaire> (fichier Dictionnaire.cpp) -//

//---------------------------------------------------------------- INCLUDE

//-------------------------------------------------------- Include systme

//------------------------------------------------------ Include personnel

#include "Dictionnaire.h"
#include "Mots.h"
#include <string>
#include <fstream>
#include <sstream>
#include <string>

using namespace std;

//----------------------------------------------------------------- PUBLIC

Dictionnaire & Dictionnaire::ObtenirInstance()
{
	// TODO: changer le retour par l'instance du singleton
	return *((Dictionnaire*) nullptr);
}

void Dictionnaire::RafraichirInstance()
{
	/* EXEMPLE
	if (instanceMots != nullptr) {
		delete instanceMots;
	}

	instanceMots = new Mots();
	*/
}

void Dictionnaire::ChargerFichier(const string & fichierDico)
{
	//TODO Destroy Maladies *
	//Reinitialisation des attributs
	maladies= unordered_map<string, Maladie*>();
	maladiesParMot = unordered_map<unsigned int, unordered_set<Maladie*>>();

	//Variables local
	unsigned int l = 0; //numero de ligne actuel
	string ligne;

	ifstream inDico(fichierDico);

	//1er ligne
	l++;
	if (!getline(inDico, ligne)||ligne != "MA v1.0") {//Si on n'arrive pas a lire la 1er ligne
		throw runtime_error("FileTypeINVALIDE");
	}

	//boucle sur tous les autres ligne (les maladies)
	while (getline(inDico, ligne)) {
		l++;
		if (ligne.empty()) {
			//On Ignor les ligne vide
		}
		/*else if (ligne.at(0)=='#') { // Pour l'implementation de ligne de commentaire
			//On Ignor les ligne de commentaire
		}*/
		else {
			//Recuperation du nom de la maladie
			unsigned int pos = ligne.find(';');
			if (pos = string::npos || pos == ligne.length-1) {
				throw runtime_error("Nom de maladie sans definition : " + ligne + " (L " + to_string(l) + ")");
			}
			Maladie * onreadMaladie = new Maladie();
			onreadMaladie->nom = ligne.substr(0, pos);

			//Recuperation de tous les mots de la maladie
			do {

				unsigned int lastpos = pos;
				unsigned int pos = ligne.find(';', lastpos + 1);
				if (pos == string::npos) {
					pos = ligne.length;
				}
				unsigned int length = pos - lastpos - 1; //longeur du mot
				if (length) {
					throw runtime_error("Maladie avec un mot de taille 0 : " + onreadMaladie->nom);
				}

				//recuperation du mot dans un char *
				char * mot = new char[length + 1];
				for (int i = 0; i < length; i++) {
					mot[i] = ligne.at(i + lastpos + 1);
					switch (mot[i] != 'A'    &&    mot[i] != 'T'    &&    mot[i] != 'C'    &&    mot[i] != 'G') {
						throw runtime_error("Maladie avec un mot invalide : " + onreadMaladie->nom + " contien un mot avec '" + mot[i] + "' (L " + to_string(l) + ")");
					}
				}
				mot[length] = '\0';

				//indexation du mot
				unsigned int indexMot;
				try {
					indexMot = Mots::ObtenirInstance().ObtenirIndex(mot);
				}
				catch (const range_error &e) {
					indexMot = Mots::ObtenirInstance().InsererMot(mot);
				}

				//Ajout du mot a la definition
				if (onreadMaladie->definition.find(indexMot) == onreadMaladie->definition.end()) {// Si le mot n'est pas dans la definition (filtre doublon)
					onreadMaladie->definition.insert(indexMot);
				}

				lastpos = pos;
			} while (pos < ligne.length() - 1 || (pos == ligne.length() - 1 && ligne.at(pos) != ';'));

			//Multi definition
			unordered_map<string, Maladie*>::iterator it = maladies.find(onreadMaladie->nom);
			if (it != maladies.end()) {// Si le Maladie est deja referancer
				if (!(*(it->second) == *onreadMaladie)) {
					delete onreadMaladie;
					throw runtime_error("Different definition d'une meme maladie : " + it->first + " (L " + to_string(l) + ")");
				}
				delete onreadMaladie;
			}
			else {//Fist definition
				maladies.insert(pair<string,Maladie *>(onreadMaladie->nom, onreadMaladie));
				for (unordered_set<unsigned int>::iterator motIt = onreadMaladie->definition.begin; motIt != onreadMaladie->definition.begin.end; motIt++) {
					maladiesParMot[*motIt].insert(onreadMaladie);
				}
			}
		}
	}
}

const Maladie & Dictionnaire::ObtenirMaladie(const string & name) {
	unordered_map<string, Maladie*>::iterator it = maladies.find(name);
	if (it == maladies.end()) {
		throw range_error("maladie " + name + " non defini");
	}
	return *(it->second);
}

const unordered_set<Maladie *> Dictionnaire::ObtenirMaladies(const unsigned int indexMot) {
	// TODO
	return unordered_set<Maladie *>();
}

const unordered_set<string> Dictionnaire::ObtenirNomsMaladies() {
	// TODO
	return unordered_set<string>();
}

//----------------------------------------------------------------- PRIVEE

Dictionnaire::Dictionnaire()
{
}

Dictionnaire::~Dictionnaire()
{
}
<|endoftext|>


<commit_before>#pragma once
#include <string>

namespace But
{
namespace Format
{

inline auto toString(std::string str) { return str; }
inline auto toString(char c) { return std::string(1,c); }
inline auto toString(char* c) { return std::string{c}; }
inline auto toString(char const* c) { return std::string{c}; }
//inline auto toString(std::wstring str) { return str; }

inline auto toString(const bool b) { return b ? "true" : "false"; }

//inline auto toString(const int8_t i) { return std::to_string(i); }
inline auto toString(const uint8_t ui) { return std::to_string(ui); }

inline auto toString(const int16_t i) { return std::to_string(i); }
inline auto toString(const uint16_t ui) { return std::to_string(ui); }

inline auto toString(const int32_t i) { return std::to_string(i); }
inline auto toString(const uint32_t ui) { return std::to_string(ui); }

inline auto toString(const int64_t i) { return std::to_string(i); }
inline auto toString(const uint64_t ui) { return std::to_string(ui); }

inline auto toString(const long long i) { return std::to_string(i); }
inline auto toString(const unsigned long long ui) { return std::to_string(ui); }

inline auto toString(const float fp) { return std::to_string(fp); }
inline auto toString(const long double fp) { return std::to_string(fp); }
inline auto toString(const double fp) { return std::to_string(fp); }

}
}
<commit_msg>one more file requiring 32-bit fix<commit_after>#pragma once
#include <string>

namespace But
{
namespace Format
{

inline auto toString(std::string str) { return str; }
inline auto toString(char c) { return std::string(1,c); }
inline auto toString(char* c) { return std::string{c}; }
inline auto toString(char const* c) { return std::string{c}; }
//inline auto toString(std::wstring str) { return str; }

inline auto toString(const bool b) { return b ? "true" : "false"; }

inline auto toString(const signed char i) { return std::to_string(i); }
inline auto toString(const unsigned char ui) { return std::to_string(ui); }

inline auto toString(const signed short i) { return std::to_string(i); }
inline auto toString(const unsigned short ui) { return std::to_string(ui); }

inline auto toString(const signed int i) { return std::to_string(i); }
inline auto toString(const unsigned int ui) { return std::to_string(ui); }

inline auto toString(const long i) { return std::to_string(i); }
inline auto toString(const unsigned long ui) { return std::to_string(ui); }

inline auto toString(const long long i) { return std::to_string(i); }
inline auto toString(const unsigned long long ui) { return std::to_string(ui); }

inline auto toString(const float fp) { return std::to_string(fp); }
inline auto toString(const long double fp) { return std::to_string(fp); }
inline auto toString(const double fp) { return std::to_string(fp); }

}
}
<|endoftext|>


<commit_before><commit_msg>fix mouse selection for high DPI screens<commit_after><|endoftext|>


<commit_before><commit_msg>Fixed documentation.<commit_after><|endoftext|>


<commit_before><commit_msg>Superfluous #endif<commit_after><|endoftext|>