<commit_before>/*****************************************************************************
 * Media Library
 *****************************************************************************
 * Copyright (C) 2015-2019 Hugo Beauzée-Luyssen, Videolabs, VideoLAN
 *
 * Authors: Hugo Beauzée-Luyssen <hugo@beauzee.fr>
 *
 * This program 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 program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * GNU Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with this program; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
 *****************************************************************************/

#if HAVE_CONFIG_H
# include "config.h"
#endif

#include "AudioTrack.h"

#include "Media.h"

namespace medialibrary
{

const std::string AudioTrack::Table::Name = "AudioTrack";
const std::string AudioTrack::Table::PrimaryKeyColumn  = "id_track";
int64_t AudioTrack::* const AudioTrack::Table::PrimaryKey = &AudioTrack::m_id;

AudioTrack::AudioTrack( MediaLibraryPtr, sqlite::Row& row )
    : m_id( row.extract<decltype(m_id)>() )
    , m_codec( row.extract<decltype(m_codec)>() )
    , m_bitrate( row.extract<decltype(m_bitrate)>() )
    , m_sampleRate( row.extract<decltype(m_sampleRate)>() )
    , m_nbChannels( row.extract<decltype(m_nbChannels)>() )
    , m_language( row.extract<decltype(m_language)>() )
    , m_description( row.extract<decltype(m_description)>() )
    , m_mediaId( row.extract<decltype(m_mediaId)>() )
{
    assert( row.hasRemainingColumns() == false );
}

AudioTrack::AudioTrack( MediaLibraryPtr, const std::string& codec, unsigned int bitrate, unsigned int sampleRate,
                        unsigned int nbChannels, const std::string& language, const std::string& desc,
                        int64_t mediaId )
    : m_id( 0 )
    , m_codec( codec )
    , m_bitrate( bitrate )
    , m_sampleRate( sampleRate )
    , m_nbChannels( nbChannels )
    , m_language( language )
    , m_description( desc )
    , m_mediaId( mediaId )
{
}

int64_t AudioTrack::id() const
{
    return m_id;
}

const std::string&AudioTrack::codec() const
{
    return m_codec;
}

unsigned int AudioTrack::bitrate() const
{
    return m_bitrate;
}

unsigned int AudioTrack::sampleRate() const
{
    return m_sampleRate;
}

unsigned int AudioTrack::nbChannels() const
{
    return m_nbChannels;
}

const std::string& AudioTrack::language() const
{
    return m_language;
}

const std::string& AudioTrack::description() const
{
    return m_description;
}

void AudioTrack::createTable( sqlite::Connection* dbConnection )
{
    sqlite::Tools::executeRequest( dbConnection,
                                   schema( Table::Name, Settings::DbModelVersion ) );
}

void AudioTrack::createIndexes(sqlite::Connection* dbConnection)
{
    const std::string indexReq = "CREATE INDEX IF NOT EXISTS "
            "audio_track_media_idx ON " + Table::Name + "(media_id)";
    sqlite::Tools::executeRequest( dbConnection, indexReq );
}

std::string AudioTrack::schema( const std::string& tableName, uint32_t )
{
    assert( tableName == Table::Name );
    return "CREATE TABLE IF NOT EXISTS " + Table::Name +
    "(" +
        AudioTrack::Table::PrimaryKeyColumn + " INTEGER PRIMARY KEY AUTOINCREMENT,"
        "codec TEXT,"
        "bitrate UNSIGNED INTEGER,"
        "samplerate UNSIGNED INTEGER,"
        "nb_channels UNSIGNED INTEGER,"
        "language TEXT,"
        "description TEXT,"
        "media_id UNSIGNED INT,"
        "FOREIGN KEY(media_id) REFERENCES " + Media::Table::Name
            + "(id_media) ON DELETE CASCADE"
    ")";
}

std::shared_ptr<AudioTrack> AudioTrack::create( MediaLibraryPtr ml, const std::string& codec,
                                                unsigned int bitrate, unsigned int sampleRate, unsigned int nbChannels,
                                                const std::string& language, const std::string& desc, int64_t mediaId )
{
    static const std::string req = "INSERT INTO " + AudioTrack::Table::Name
            + "(codec, bitrate, samplerate, nb_channels, language, description, media_id) VALUES(?, ?, ?, ?, ?, ?, ?)";
    auto track = std::make_shared<AudioTrack>( ml, codec, bitrate, sampleRate, nbChannels, language, desc, mediaId );
    if ( insert( ml, track, req, codec, bitrate, sampleRate, nbChannels, language, desc, mediaId ) == false )
        return nullptr;
    return track;
}

void AudioTrack::removeFromMedia(MediaLibraryPtr ml, int64_t mediaId)
{
    static const std::string req = "DELETE FROM " + Table::Name + " "
            "WHERE media_id = ?";
    sqlite::Tools::executeDelete( ml->getConn(), req, mediaId );
}

}
<commit_msg>AudioTrack: Remove IF NOT EXISTS from the table creation request<commit_after>/*****************************************************************************
 * Media Library
 *****************************************************************************
 * Copyright (C) 2015-2019 Hugo Beauzée-Luyssen, Videolabs, VideoLAN
 *
 * Authors: Hugo Beauzée-Luyssen <hugo@beauzee.fr>
 *
 * This program 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 program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * GNU Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with this program; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
 *****************************************************************************/

#if HAVE_CONFIG_H
# include "config.h"
#endif

#include "AudioTrack.h"

#include "Media.h"

namespace medialibrary
{

const std::string AudioTrack::Table::Name = "AudioTrack";
const std::string AudioTrack::Table::PrimaryKeyColumn  = "id_track";
int64_t AudioTrack::* const AudioTrack::Table::PrimaryKey = &AudioTrack::m_id;

AudioTrack::AudioTrack( MediaLibraryPtr, sqlite::Row& row )
    : m_id( row.extract<decltype(m_id)>() )
    , m_codec( row.extract<decltype(m_codec)>() )
    , m_bitrate( row.extract<decltype(m_bitrate)>() )
    , m_sampleRate( row.extract<decltype(m_sampleRate)>() )
    , m_nbChannels( row.extract<decltype(m_nbChannels)>() )
    , m_language( row.extract<decltype(m_language)>() )
    , m_description( row.extract<decltype(m_description)>() )
    , m_mediaId( row.extract<decltype(m_mediaId)>() )
{
    assert( row.hasRemainingColumns() == false );
}

AudioTrack::AudioTrack( MediaLibraryPtr, const std::string& codec, unsigned int bitrate, unsigned int sampleRate,
                        unsigned int nbChannels, const std::string& language, const std::string& desc,
                        int64_t mediaId )
    : m_id( 0 )
    , m_codec( codec )
    , m_bitrate( bitrate )
    , m_sampleRate( sampleRate )
    , m_nbChannels( nbChannels )
    , m_language( language )
    , m_description( desc )
    , m_mediaId( mediaId )
{
}

int64_t AudioTrack::id() const
{
    return m_id;
}

const std::string&AudioTrack::codec() const
{
    return m_codec;
}

unsigned int AudioTrack::bitrate() const
{
    return m_bitrate;
}

unsigned int AudioTrack::sampleRate() const
{
    return m_sampleRate;
}

unsigned int AudioTrack::nbChannels() const
{
    return m_nbChannels;
}

const std::string& AudioTrack::language() const
{
    return m_language;
}

const std::string& AudioTrack::description() const
{
    return m_description;
}

void AudioTrack::createTable( sqlite::Connection* dbConnection )
{
    sqlite::Tools::executeRequest( dbConnection,
                                   schema( Table::Name, Settings::DbModelVersion ) );
}

void AudioTrack::createIndexes(sqlite::Connection* dbConnection)
{
    const std::string indexReq = "CREATE INDEX IF NOT EXISTS "
            "audio_track_media_idx ON " + Table::Name + "(media_id)";
    sqlite::Tools::executeRequest( dbConnection, indexReq );
}

std::string AudioTrack::schema( const std::string& tableName, uint32_t )
{
    assert( tableName == Table::Name );
    return "CREATE TABLE " + Table::Name +
    "(" +
        AudioTrack::Table::PrimaryKeyColumn + " INTEGER PRIMARY KEY AUTOINCREMENT,"
        "codec TEXT,"
        "bitrate UNSIGNED INTEGER,"
        "samplerate UNSIGNED INTEGER,"
        "nb_channels UNSIGNED INTEGER,"
        "language TEXT,"
        "description TEXT,"
        "media_id UNSIGNED INT,"
        "FOREIGN KEY(media_id) REFERENCES " + Media::Table::Name
            + "(id_media) ON DELETE CASCADE"
    ")";
}

std::shared_ptr<AudioTrack> AudioTrack::create( MediaLibraryPtr ml, const std::string& codec,
                                                unsigned int bitrate, unsigned int sampleRate, unsigned int nbChannels,
                                                const std::string& language, const std::string& desc, int64_t mediaId )
{
    static const std::string req = "INSERT INTO " + AudioTrack::Table::Name
            + "(codec, bitrate, samplerate, nb_channels, language, description, media_id) VALUES(?, ?, ?, ?, ?, ?, ?)";
    auto track = std::make_shared<AudioTrack>( ml, codec, bitrate, sampleRate, nbChannels, language, desc, mediaId );
    if ( insert( ml, track, req, codec, bitrate, sampleRate, nbChannels, language, desc, mediaId ) == false )
        return nullptr;
    return track;
}

void AudioTrack::removeFromMedia(MediaLibraryPtr ml, int64_t mediaId)
{
    static const std::string req = "DELETE FROM " + Table::Name + " "
            "WHERE media_id = ?";
    sqlite::Tools::executeDelete( ml->getConn(), req, mediaId );
}

}
<|endoftext|>


<commit_before>//===--- ReplaceAutoType.cpp -------------------------------------*- C++-*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
#include "refactor/Tweak.h"

#include "Logger.h"
#include "clang/AST/Type.h"
#include "clang/AST/TypeLoc.h"
#include "clang/Basic/LLVM.h"
#include "llvm/ADT/None.h"
#include "llvm/ADT/Optional.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/Error.h"
#include <climits>
#include <memory>
#include <string>
#include <AST.h>
#include "XRefs.h"
#include "llvm/ADT/StringExtras.h"

namespace clang {
namespace clangd {
namespace {

/// Expand the "auto" type to the derived type
/// Before:
///    auto x = Something();
///    ^^^^
/// After:
///    MyClass x = Something();
///    ^^^^^^^
/// FIXME: Handle decltype as well
class ExpandAutoType : public Tweak {
public:
  const char *id() const final;
  Intent intent() const override { return Intent::Refactor;}
  bool prepare(const Selection &Inputs) override;
  Expected<Effect> apply(const Selection &Inputs) override;
  std::string title() const override;

private:
  /// Cache the AutoTypeLoc, so that we do not need to search twice.
  llvm::Optional<clang::AutoTypeLoc> CachedLocation;

  /// Create an error message with filename and line number in it
  llvm::Error createErrorMessage(const std::string& Message,
                                 const Selection &Inputs);

};

REGISTER_TWEAK(ExpandAutoType)

std::string ExpandAutoType::title() const { return "Expand auto type"; }

bool ExpandAutoType::prepare(const Selection& Inputs) {
  CachedLocation = llvm::None;
  if (auto *Node = Inputs.ASTSelection.commonAncestor()) {
    if (auto *TypeNode = Node->ASTNode.get<TypeLoc>()) {
      if (const AutoTypeLoc Result = TypeNode->getAs<AutoTypeLoc>()) {
        CachedLocation = Result;
      }
    }
  }
  return (bool) CachedLocation;
}

Expected<Tweak::Effect> ExpandAutoType::apply(const Selection& Inputs) {
  auto& SrcMgr = Inputs.AST.getASTContext().getSourceManager();

  llvm::Optional<clang::QualType> DeducedType =
      getDeducedType(Inputs.AST, CachedLocation->getBeginLoc());

  // if we can't resolve the type, return an error message
  if (DeducedType == llvm::None || DeducedType->isNull()) {
    return createErrorMessage("Could not deduce type for 'auto' type", Inputs);
  }

  // if it's a lambda expression, return an error message
  if (isa<RecordType>(*DeducedType) and
      dyn_cast<RecordType>(*DeducedType)->getDecl()->isLambda()) {
    return createErrorMessage("Could not expand type of lambda expression",
                              Inputs);
  }

  // if it's a function expression, return an error message
  // naively replacing 'auto' with the type will break declarations.
  // FIXME: there are other types that have similar problems
  if (DeducedType->getTypePtr()->isFunctionPointerType()) {
    return createErrorMessage("Could not expand type of function pointer",
                              Inputs);
  }

  std::string PrettyTypeName = printType(*DeducedType,
      Inputs.ASTSelection.commonAncestor()->getDeclContext());

  tooling::Replacement
      Expansion(SrcMgr, CharSourceRange(CachedLocation->getSourceRange(), true),
                PrettyTypeName);

  return Tweak::Effect::applyEdit(tooling::Replacements(Expansion));
}

llvm::Error ExpandAutoType::createErrorMessage(const std::string& Message,
                                               const Selection& Inputs) {
  auto& SrcMgr = Inputs.AST.getASTContext().getSourceManager();
  std::string ErrorMessage =
      Message + ": " +
          SrcMgr.getFilename(Inputs.Cursor).str() + " Line " +
          std::to_string(SrcMgr.getExpansionLineNumber(Inputs.Cursor));

  return llvm::createStringError(llvm::inconvertibleErrorCode(),
                                 ErrorMessage.c_str());
}

} // namespace
} // namespace clangd
} // namespace clang
<commit_msg>[clangd] Update a stale comment, NFC.<commit_after>//===--- ExpandAutoType.cpp --------------------------------------*- C++-*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
#include "refactor/Tweak.h"

#include "Logger.h"
#include "clang/AST/Type.h"
#include "clang/AST/TypeLoc.h"
#include "clang/Basic/LLVM.h"
#include "llvm/ADT/None.h"
#include "llvm/ADT/Optional.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/Error.h"
#include <climits>
#include <memory>
#include <string>
#include <AST.h>
#include "XRefs.h"
#include "llvm/ADT/StringExtras.h"

namespace clang {
namespace clangd {
namespace {

/// Expand the "auto" type to the derived type
/// Before:
///    auto x = Something();
///    ^^^^
/// After:
///    MyClass x = Something();
///    ^^^^^^^
/// FIXME: Handle decltype as well
class ExpandAutoType : public Tweak {
public:
  const char *id() const final;
  Intent intent() const override { return Intent::Refactor;}
  bool prepare(const Selection &Inputs) override;
  Expected<Effect> apply(const Selection &Inputs) override;
  std::string title() const override;

private:
  /// Cache the AutoTypeLoc, so that we do not need to search twice.
  llvm::Optional<clang::AutoTypeLoc> CachedLocation;

  /// Create an error message with filename and line number in it
  llvm::Error createErrorMessage(const std::string& Message,
                                 const Selection &Inputs);

};

REGISTER_TWEAK(ExpandAutoType)

std::string ExpandAutoType::title() const { return "Expand auto type"; }

bool ExpandAutoType::prepare(const Selection& Inputs) {
  CachedLocation = llvm::None;
  if (auto *Node = Inputs.ASTSelection.commonAncestor()) {
    if (auto *TypeNode = Node->ASTNode.get<TypeLoc>()) {
      if (const AutoTypeLoc Result = TypeNode->getAs<AutoTypeLoc>()) {
        CachedLocation = Result;
      }
    }
  }
  return (bool) CachedLocation;
}

Expected<Tweak::Effect> ExpandAutoType::apply(const Selection& Inputs) {
  auto& SrcMgr = Inputs.AST.getASTContext().getSourceManager();

  llvm::Optional<clang::QualType> DeducedType =
      getDeducedType(Inputs.AST, CachedLocation->getBeginLoc());

  // if we can't resolve the type, return an error message
  if (DeducedType == llvm::None || DeducedType->isNull()) {
    return createErrorMessage("Could not deduce type for 'auto' type", Inputs);
  }

  // if it's a lambda expression, return an error message
  if (isa<RecordType>(*DeducedType) and
      dyn_cast<RecordType>(*DeducedType)->getDecl()->isLambda()) {
    return createErrorMessage("Could not expand type of lambda expression",
                              Inputs);
  }

  // if it's a function expression, return an error message
  // naively replacing 'auto' with the type will break declarations.
  // FIXME: there are other types that have similar problems
  if (DeducedType->getTypePtr()->isFunctionPointerType()) {
    return createErrorMessage("Could not expand type of function pointer",
                              Inputs);
  }

  std::string PrettyTypeName = printType(*DeducedType,
      Inputs.ASTSelection.commonAncestor()->getDeclContext());

  tooling::Replacement
      Expansion(SrcMgr, CharSourceRange(CachedLocation->getSourceRange(), true),
                PrettyTypeName);

  return Tweak::Effect::applyEdit(tooling::Replacements(Expansion));
}

llvm::Error ExpandAutoType::createErrorMessage(const std::string& Message,
                                               const Selection& Inputs) {
  auto& SrcMgr = Inputs.AST.getASTContext().getSourceManager();
  std::string ErrorMessage =
      Message + ": " +
          SrcMgr.getFilename(Inputs.Cursor).str() + " Line " +
          std::to_string(SrcMgr.getExpansionLineNumber(Inputs.Cursor));

  return llvm::createStringError(llvm::inconvertibleErrorCode(),
                                 ErrorMessage.c_str());
}

} // namespace
} // namespace clangd
} // namespace clang
<|endoftext|>


<commit_before>#include <boost/filesystem.hpp>

#include <QFileDialog>
#include <QMessageBox>

#include "fish_detector/image_annotator/mainwindow.h"
#include "ui_mainwindow.h"

#include <iostream>
namespace fish_detector { namespace image_annotator {

namespace fs = boost::filesystem;

namespace { //anonymous

static const std::vector<std::string> kDirExtensions = {
  ".jpg", ".png", ".bmp", ".tif", ".jpeg",
  ".JPG", ".PNG", ".BMP", ".TIF", ".JPEG"};

} // anonymous namespace

MainWindow::MainWindow(QWidget *parent)
  : annotations_(nullptr)
  , scene_(new QGraphicsScene)
  , pixmap_(nullptr)
  , ui_(new Ui::MainWidget)
  , image_files_() {
  ui_->setupUi(this);
  setStyleSheet("QPushButton { background-color: rgb(230, 230, 230);"
	  "border-style: outset; border-radius: 5px; border-width: 2px; "
    "border-color: grey; padding: 6px;}"
	  "QPushButton:pressed{background-color: rgb(190, 190, 190); "
    "border-style: outset; border-radius: 5px;"
	  "border-width: 2px; border-color: grey; padding: 6px;}");
  ui_->next->setEnabled(false);
  ui_->prev->setEnabled(false);
  ui_->saveAnnotations->setEnabled(false);
  ui_->imageSlider->setEnabled(false);
}

void MainWindow::on_addSpecies_clicked() {
}

void MainWindow::on_loadSpecies_clicked() {
}

void MainWindow::on_saveSpecies_clicked() {
}

void MainWindow::on_next_clicked() {
  int next_val = ui_->imageSlider->value() + 1;
  if(next_val <= ui_->imageSlider->maximum()) {
    ui_->imageSlider->setValue(next_val);
  }
}

void MainWindow::on_prev_clicked() {
  int prev_val = ui_->imageSlider->value() - 1;
  if(prev_val >= ui_->imageSlider->minimum()) {
    ui_->imageSlider->setValue(prev_val);
  }
}

void MainWindow::on_loadImageDir_clicked() {
  QString image_dir = QFileDialog::getExistingDirectory(this,
    "Select an image directory.");
  if(!image_dir.isEmpty()) {
    onLoadDirectorySuccess(image_dir);
  }
}

void MainWindow::on_saveAnnotations_clicked() {
}

void MainWindow::on_imageSlider_valueChanged() {
  if(pixmap_ != nullptr) {
    scene_->removeItem(pixmap_.get());
  }
  QString filename(image_files_[ui_->imageSlider->value()].c_str());
  QImage current(filename);
  if(!current.isNull()) {
    pixmap_.reset(scene_->addPixmap(QPixmap::fromImage(current)));
    scene_->setSceneRect(current.rect());
    ui_->imageWindow->setScene(scene_.get());
    ui_->imageWindow->fitInView(scene_->sceneRect(), Qt::KeepAspectRatio);
    ui_->imageWindow->show();
  }
  else {
    QMessageBox err;
    err.critical(0, "Error", std::string(
        std::string("Error loading image ")
      + filename.toStdString()
      + std::string(".")).c_str());
  }
}

void MainWindow::onLoadDirectorySuccess(const QString &image_dir) {
  image_files_.clear();
  fs::directory_iterator dir_it(image_dir.toStdString());
  std::cout << "GOT HERE 1" << std::endl;
  fs::directory_iterator dir_end;
  for(; dir_it != dir_end; ++dir_it) {
    fs::path ext(dir_it->path().extension());
    for(auto &ok_ext : kDirExtensions) {
      if(ext == ok_ext) {
        image_files_.push_back(dir_it->path().generic_string());
      }
    }
  }
  std::cout << "GOT HERE 2" << std::endl;
  if(image_files_.size() > 0) {
    ui_->next->setEnabled(true);
    ui_->prev->setEnabled(true);
    ui_->saveAnnotations->setEnabled(true);
    ui_->imageSlider->setEnabled(true);
    ui_->imageSlider->setMinimum(0);
    ui_->imageSlider->setMaximum(static_cast<int>(image_files_.size() - 1));
    ui_->imageSlider->setSingleStep(1);
  }
  else {
    QMessageBox err;
    err.critical(0, "Error", "No images found in this directory.");
  }
  std::cout << "GOT HERE 3" << std::endl;
}

#include "../../include/fish_detector/image_annotator/moc_mainwindow.cpp"

}} // namespace fish_detector::image_annotator
<commit_msg>Go to first frame and update image upon loading new directory<commit_after>#include <boost/filesystem.hpp>

#include <QFileDialog>
#include <QMessageBox>

#include "fish_detector/image_annotator/mainwindow.h"
#include "ui_mainwindow.h"

namespace fish_detector { namespace image_annotator {

namespace fs = boost::filesystem;

namespace { //anonymous

static const std::vector<std::string> kDirExtensions = {
  ".jpg", ".png", ".bmp", ".tif", ".jpeg",
  ".JPG", ".PNG", ".BMP", ".TIF", ".JPEG"};

} // anonymous namespace

MainWindow::MainWindow(QWidget *parent)
  : annotations_(nullptr)
  , scene_(new QGraphicsScene)
  , pixmap_(nullptr)
  , ui_(new Ui::MainWidget)
  , image_files_() {
  ui_->setupUi(this);
  setStyleSheet("QPushButton { background-color: rgb(230, 230, 230);"
	  "border-style: outset; border-radius: 5px; border-width: 2px; "
    "border-color: grey; padding: 6px;}"
	  "QPushButton:pressed{background-color: rgb(190, 190, 190); "
    "border-style: outset; border-radius: 5px;"
	  "border-width: 2px; border-color: grey; padding: 6px;}");
  ui_->next->setEnabled(false);
  ui_->prev->setEnabled(false);
  ui_->saveAnnotations->setEnabled(false);
  ui_->imageSlider->setEnabled(false);
}

void MainWindow::on_addSpecies_clicked() {
}

void MainWindow::on_loadSpecies_clicked() {
}

void MainWindow::on_saveSpecies_clicked() {
}

void MainWindow::on_next_clicked() {
  int next_val = ui_->imageSlider->value() + 1;
  if(next_val <= ui_->imageSlider->maximum()) {
    ui_->imageSlider->setValue(next_val);
  }
}

void MainWindow::on_prev_clicked() {
  int prev_val = ui_->imageSlider->value() - 1;
  if(prev_val >= ui_->imageSlider->minimum()) {
    ui_->imageSlider->setValue(prev_val);
  }
}

void MainWindow::on_loadImageDir_clicked() {
  QString image_dir = QFileDialog::getExistingDirectory(this,
    "Select an image directory.");
  if(!image_dir.isEmpty()) {
    onLoadDirectorySuccess(image_dir);
  }
}

void MainWindow::on_saveAnnotations_clicked() {
}

void MainWindow::on_imageSlider_valueChanged() {
  if(pixmap_ != nullptr) {
    scene_->removeItem(pixmap_.get());
  }
  QString filename(image_files_[ui_->imageSlider->value()].c_str());
  QImage current(filename);
  if(!current.isNull()) {
    pixmap_.reset(scene_->addPixmap(QPixmap::fromImage(current)));
    scene_->setSceneRect(current.rect());
    ui_->imageWindow->setScene(scene_.get());
    ui_->imageWindow->fitInView(scene_->sceneRect(), Qt::KeepAspectRatio);
    ui_->imageWindow->show();
  }
  else {
    QMessageBox err;
    err.critical(0, "Error", std::string(
        std::string("Error loading image ")
      + filename.toStdString()
      + std::string(".")).c_str());
  }
}

void MainWindow::onLoadDirectorySuccess(const QString &image_dir) {
  image_files_.clear();
  fs::directory_iterator dir_it(image_dir.toStdString());
  fs::directory_iterator dir_end;
  for(; dir_it != dir_end; ++dir_it) {
    fs::path ext(dir_it->path().extension());
    for(auto &ok_ext : kDirExtensions) {
      if(ext == ok_ext) {
        image_files_.push_back(dir_it->path().generic_string());
      }
    }
  }
  if(image_files_.size() > 0) {
    ui_->next->setEnabled(true);
    ui_->prev->setEnabled(true);
    ui_->saveAnnotations->setEnabled(true);
    ui_->imageSlider->setEnabled(true);
    ui_->imageSlider->setMinimum(0);
    ui_->imageSlider->setMaximum(static_cast<int>(image_files_.size() - 1));
    ui_->imageSlider->setSingleStep(1);
    ui_->imageSlider->setValue(0);
    on_imageSlider_valueChanged();
  }
  else {
    QMessageBox err;
    err.critical(0, "Error", "No images found in this directory.");
  }
}

#include "../../include/fish_detector/image_annotator/moc_mainwindow.cpp"

}} // namespace fish_detector::image_annotator
<|endoftext|>


<commit_before>/*
 *
 * MIT License
 *
 * Copyright (c) 2016-2018 The Cats Project
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 *
 */

#ifndef CATS_CORECAT_UTIL_EXCEPTIONPTR_HPP
#define CATS_CORECAT_UTIL_EXCEPTIONPTR_HPP

#include <exception>
#include <memory>
#include <type_traits>

#include "Exception.hpp"

namespace Cats {
namespace Corecat {
inline namespace Util {

class ExceptionPtr {

private:

    template <typename T>
    using EnableIfException = std::enable_if_t<std::is_base_of<std::exception, T>::value>;

    template <typename F>
    struct ArgumantTypeImpl;
    template <typename Class, typename Arg, typename Ret>
    struct ArgumantTypeImpl<Ret (Class::*)(Arg)> { using Type = Arg; };
    template <typename Class, typename Arg, typename Ret>
    struct ArgumantTypeImpl<Ret (Class::*)(Arg) const> { using Type = Arg; };
    template <typename F, typename T = std::decay_t<F>>
    using ArgumentType = typename ArgumantTypeImpl<decltype(&T::operator())>::Type;

    class HolderBase {

    public:

        virtual ~HolderBase() = default;

        virtual const void* get() const noexcept = 0;
        [[noreturn]] virtual void rethrow() const = 0;
        virtual const std::type_info* getType() const noexcept = 0;

    };

    template <typename T>
    class Holder1 : public HolderBase {

    private:

        T t;

    public:

        template <typename... Arg>
        Holder1(Arg&&... arg) : t(std::forward<Arg>(arg)...) {}
        virtual ~Holder1() = default;

        const void* get() const noexcept final { return std::addressof(t); }
        [[noreturn]] void rethrow() const final { throw t; }
        const std::type_info* getType() const noexcept final { return &typeid(T); }

    };

    class Holder2 : public HolderBase {

    private:

        std::exception_ptr ptr;

    public:

        Holder2(std::exception_ptr ptr_) : ptr(ptr_) {}
        virtual ~Holder2() = default;

        const void* get() const noexcept final { return nullptr; }
        [[noreturn]] void rethrow() const final { std::rethrow_exception(ptr); }
        const std::type_info* getType() const noexcept final { return nullptr; }

    };

private:

    std::shared_ptr<HolderBase> data;

    std::shared_ptr<std::exception> exception;
    const std::type_info* type = nullptr;
    void (*throwFunction)(const std::exception&) = nullptr;
    std::exception_ptr eptr = nullptr;

private:

    template <typename T>
    static void throwFunctionImpl(const std::exception& e) { throw static_cast<const T&>(e); }

public:

    ExceptionPtr() = default;
    template <typename T, typename U = std::remove_reference_t<T>, typename = EnableIfException<U>>
    ExceptionPtr(T&& t) : data(std::make_shared<Holder1<U>>(std::forward<T>(t))) {}
    ExceptionPtr(std::exception_ptr ptr) : data(std::make_shared<Holder2>(ptr)) {}
    ExceptionPtr(const ExceptionPtr& src) : data(src.data) {}

    template <typename T, typename U = std::remove_reference_t<T>, typename = EnableIfException<U>>
    ExceptionPtr& operator =(T&& t) { return *this = ExceptionPtr(std::forward<T>(t)); }
    ExceptionPtr& operator =(std::exception_ptr ptr) noexcept { return *this = ExceptionPtr(ptr); }
    ExceptionPtr& operator =(const ExceptionPtr& src) noexcept { data = src.data; return *this; }

    operator bool() const noexcept { return bool(data); }

    [[noreturn]] void rethrow() const {

        if(data) data->rethrow();
        throw InvalidArgumentException("No exception in ExceptionPtr");

    }

    template <typename F, typename T = std::remove_reference_t<ArgumentType<F>>>
    bool with(F&& f) const {

        if(!data) return false;
        auto type = data->getType();
        if(type && *type == typeid(T)) {

            f(*static_cast<const T*>(data->get()));
            return true;

        }
        try { data->rethrow(); }
        catch(const T& arg) { f(arg); return true; }
        catch(...) {}
        return false;

    }

public:

    static ExceptionPtr getCurrent() noexcept { return std::current_exception(); }

};

}
}
}

#endif
<commit_msg>Update ExceptionPtr<commit_after>/*
 *
 * MIT License
 *
 * Copyright (c) 2016-2018 The Cats Project
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 *
 */

#ifndef CATS_CORECAT_UTIL_EXCEPTIONPTR_HPP
#define CATS_CORECAT_UTIL_EXCEPTIONPTR_HPP

#include <exception>
#include <memory>
#include <type_traits>

#include "Exception.hpp"

namespace Cats {
namespace Corecat {
inline namespace Util {

class ExceptionPtr {

private:

    template <typename T>
    using EnableIfException = std::enable_if_t<std::is_base_of<std::exception, T>::value>;

    template <typename F>
    struct ArgumantTypeImpl;
    template <typename Class, typename Arg, typename Ret>
    struct ArgumantTypeImpl<Ret (Class::*)(Arg)> { using Type = Arg; };
    template <typename Class, typename Arg, typename Ret>
    struct ArgumantTypeImpl<Ret (Class::*)(Arg) const> { using Type = Arg; };
    template <typename F, typename T = std::decay_t<F>>
    using ArgumentType = typename ArgumantTypeImpl<decltype(&T::operator())>::Type;

    class HolderBase {

    public:

        virtual ~HolderBase() = default;

        virtual const void* get() const noexcept = 0;
        [[noreturn]] virtual void rethrow() const = 0;
        virtual const std::type_info* getType() const noexcept = 0;

    };

    template <typename T>
    class Holder1 : public HolderBase {

    private:

        T t;

    public:

        template <typename... Arg>
        Holder1(Arg&&... arg) : t(std::forward<Arg>(arg)...) {}
        virtual ~Holder1() = default;

        const void* get() const noexcept final { return std::addressof(t); }
        [[noreturn]] void rethrow() const final { throw t; }
        const std::type_info* getType() const noexcept final { return &typeid(T); }

    };

    class Holder2 : public HolderBase {

    private:

        std::exception_ptr ptr;

    public:

        Holder2(std::exception_ptr ptr_) : ptr(ptr_) {}
        virtual ~Holder2() = default;

        const void* get() const noexcept final { return nullptr; }
        [[noreturn]] void rethrow() const final { std::rethrow_exception(ptr); }
        const std::type_info* getType() const noexcept final { return nullptr; }

    };

private:

    std::shared_ptr<HolderBase> data;

public:

    ExceptionPtr() = default;
    template <typename T, typename U = std::remove_reference_t<T>, typename = EnableIfException<U>>
    ExceptionPtr(T&& t) : data(std::make_shared<Holder1<U>>(std::forward<T>(t))) {}
    ExceptionPtr(std::exception_ptr ptr) : data(std::make_shared<Holder2>(ptr)) {}
    ExceptionPtr(const ExceptionPtr& src) : data(src.data) {}

    template <typename T, typename U = std::remove_reference_t<T>, typename = EnableIfException<U>>
    ExceptionPtr& operator =(T&& t) { return *this = ExceptionPtr(std::forward<T>(t)); }
    ExceptionPtr& operator =(std::exception_ptr ptr) noexcept { return *this = ExceptionPtr(ptr); }
    ExceptionPtr& operator =(const ExceptionPtr& src) noexcept { data = src.data; return *this; }

    operator bool() const noexcept { return bool(data); }

    [[noreturn]] void rethrow() const {

        if(data) data->rethrow();
        throw InvalidArgumentException("No exception in ExceptionPtr");

    }

    template <typename F, typename T = std::remove_reference_t<ArgumentType<F>>>
    bool with(F&& f) const {

        if(!data) return false;
        auto type = data->getType();
        if(type && *type == typeid(T)) {

            f(*static_cast<const T*>(data->get()));
            return true;

        }
        try { data->rethrow(); }
        catch(const T& arg) { f(arg); return true; }
        catch(...) {}
        return false;

    }

public:

    static ExceptionPtr getCurrent() noexcept { return std::current_exception(); }

};

}
}
}

#endif
<|endoftext|>


<commit_before>/*
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 3 of the License, or
 * (at your option) any later version.
 *
 * Written (W) 2013 Heiko Strathmann
 */

#include <shogun/base/init.h>
#include <shogun/kernel/GaussianKernel.h>
#include <shogun/kernel/CustomKernel.h>
#include <shogun/features/DenseFeatures.h>
#include <shogun/features/streaming/generators/MeanShiftDataGenerator.h>
#include <gtest/gtest.h>

using namespace shogun;

TEST(CustomKernelTest,add_row_subset)
{
	index_t m=3;
	CMeanShiftDataGenerator* gen=new CMeanShiftDataGenerator(0, 2);
	CFeatures* feats=gen->get_streamed_features(m);
	SG_REF(feats);

	CGaussianKernel* gauss=new CGaussianKernel(10, 3);
	gauss->init(feats, feats);
	CCustomKernel* custom=new CCustomKernel(gauss);

	SGVector<index_t> inds(m);
	inds.range_fill();

	index_t num_runs=10;
	for (index_t i=0; i<num_runs; ++i)
	{
		inds.permute();

		feats->add_subset(inds);
		custom->add_row_subset(inds);
		custom->add_col_subset(inds);
		gauss->init(feats, feats); // to make sure digonal is fine

		SGMatrix<float64_t> gauss_matrix=gauss->get_kernel_matrix();
		SGMatrix<float64_t> custom_matrix=custom->get_kernel_matrix();
//		gauss_matrix.display_matrix("gauss");
//		gauss_matrix.display_matrix("custom");
		for (index_t j=0; j<m*m; ++j)
			EXPECT_LE(CMath::abs(gauss_matrix.matrix[j]-custom_matrix.matrix[j]), 1E-6);

		feats->remove_subset();
		custom->remove_row_subset();
		custom->remove_col_subset();
	}

	SG_UNREF(gen);
	SG_UNREF(feats);
	SG_UNREF(gauss);
	SG_UNREF(custom);
}

TEST(CustomKernelTest,add_row_subset_constructor)
{
	index_t n=4;
	CMeanShiftDataGenerator* gen=new CMeanShiftDataGenerator(1, 2);
	CDenseFeatures<float64_t>* feats=
			(CDenseFeatures<float64_t>*)gen->get_streamed_features(n);
	CGaussianKernel* gaussian=new CGaussianKernel(feats, feats, 2, 10);
	CCustomKernel* main_kernel=new CCustomKernel(gaussian);

	/* create custom kernel copy of gaussien and assert equalness */
	SGMatrix<float64_t> kmg=gaussian->get_kernel_matrix();
	SGMatrix<float64_t> km=main_kernel->get_kernel_matrix();
	for (index_t i=0; i<n; ++i)
	{
		for (index_t j=0; j<n; ++j)
			EXPECT_LE(CMath::abs(kmg(i, j)-km(i, j)), 1E-7);
	}

	/* create copy of custom kernel and assert equalness */
	CCustomKernel* copy=new CCustomKernel(km);
	SGMatrix<float64_t> kmc=copy->get_kernel_matrix();
	for (index_t i=0; i<n; ++i)
	{
		for (index_t j=0; j<n; ++j)
			EXPECT_EQ(km(i, j), kmc(i, j));
	}

	/* add a subset to the custom kernel, create copy, create another kernel
	 * from this, assert equalness */
	SGVector<index_t> inds(n);
	inds.range_fill();
	inds.permute();
	main_kernel->add_row_subset(inds);
	SGMatrix<float64_t> main_subset_matrix=main_kernel->get_kernel_matrix();
	main_kernel->remove_row_subset();
	main_kernel->remove_col_subset();
	CCustomKernel* main_subset_copy=new CCustomKernel(main_subset_matrix);
	SGMatrix<float64_t> main_subset_copy_matrix=main_subset_copy->get_kernel_matrix();
	for (index_t i=0; i<n; ++i)
	{
		for (index_t j=0; j<n; ++j)
			EXPECT_EQ(main_subset_matrix(i, j), main_subset_copy_matrix(i, j));
	}

	SG_UNREF(gaussian);
	SG_UNREF(main_kernel);
	SG_UNREF(copy);
	SG_UNREF(gen);
}
<commit_msg>removed unnecessary remove subset command<commit_after>/*
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 3 of the License, or
 * (at your option) any later version.
 *
 * Written (W) 2013 Heiko Strathmann
 */

#include <shogun/base/init.h>
#include <shogun/kernel/GaussianKernel.h>
#include <shogun/kernel/CustomKernel.h>
#include <shogun/features/DenseFeatures.h>
#include <shogun/features/streaming/generators/MeanShiftDataGenerator.h>
#include <gtest/gtest.h>

using namespace shogun;

TEST(CustomKernelTest,add_row_subset)
{
	index_t m=3;
	CMeanShiftDataGenerator* gen=new CMeanShiftDataGenerator(0, 2);
	CFeatures* feats=gen->get_streamed_features(m);
	SG_REF(feats);

	CGaussianKernel* gauss=new CGaussianKernel(10, 3);
	gauss->init(feats, feats);
	CCustomKernel* custom=new CCustomKernel(gauss);

	SGVector<index_t> inds(m);
	inds.range_fill();

	index_t num_runs=10;
	for (index_t i=0; i<num_runs; ++i)
	{
		inds.permute();

		feats->add_subset(inds);
		custom->add_row_subset(inds);
		custom->add_col_subset(inds);
		gauss->init(feats, feats); // to make sure digonal is fine

		SGMatrix<float64_t> gauss_matrix=gauss->get_kernel_matrix();
		SGMatrix<float64_t> custom_matrix=custom->get_kernel_matrix();
//		gauss_matrix.display_matrix("gauss");
//		gauss_matrix.display_matrix("custom");
		for (index_t j=0; j<m*m; ++j)
			EXPECT_LE(CMath::abs(gauss_matrix.matrix[j]-custom_matrix.matrix[j]), 1E-6);

		feats->remove_subset();
		custom->remove_row_subset();
		custom->remove_col_subset();
	}

	SG_UNREF(gen);
	SG_UNREF(feats);
	SG_UNREF(gauss);
	SG_UNREF(custom);
}

TEST(CustomKernelTest,add_row_subset_constructor)
{
	index_t n=4;
	CMeanShiftDataGenerator* gen=new CMeanShiftDataGenerator(1, 2);
	CDenseFeatures<float64_t>* feats=
			(CDenseFeatures<float64_t>*)gen->get_streamed_features(n);
	CGaussianKernel* gaussian=new CGaussianKernel(feats, feats, 2, 10);
	CCustomKernel* main_kernel=new CCustomKernel(gaussian);

	/* create custom kernel copy of gaussien and assert equalness */
	SGMatrix<float64_t> kmg=gaussian->get_kernel_matrix();
	SGMatrix<float64_t> km=main_kernel->get_kernel_matrix();
	for (index_t i=0; i<n; ++i)
	{
		for (index_t j=0; j<n; ++j)
			EXPECT_LE(CMath::abs(kmg(i, j)-km(i, j)), 1E-7);
	}

	/* create copy of custom kernel and assert equalness */
	CCustomKernel* copy=new CCustomKernel(km);
	SGMatrix<float64_t> kmc=copy->get_kernel_matrix();
	for (index_t i=0; i<n; ++i)
	{
		for (index_t j=0; j<n; ++j)
			EXPECT_EQ(km(i, j), kmc(i, j));
	}

	/* add a subset to the custom kernel, create copy, create another kernel
	 * from this, assert equalness */
	SGVector<index_t> inds(n);
	inds.range_fill();
	inds.permute();
	main_kernel->add_row_subset(inds);
	SGMatrix<float64_t> main_subset_matrix=main_kernel->get_kernel_matrix();
	main_kernel->remove_row_subset();
	CCustomKernel* main_subset_copy=new CCustomKernel(main_subset_matrix);
	SGMatrix<float64_t> main_subset_copy_matrix=main_subset_copy->get_kernel_matrix();
	for (index_t i=0; i<n; ++i)
	{
		for (index_t j=0; j<n; ++j)
			EXPECT_EQ(main_subset_matrix(i, j), main_subset_copy_matrix(i, j));
	}

	SG_UNREF(gaussian);
	SG_UNREF(main_kernel);
	SG_UNREF(copy);
	SG_UNREF(gen);
}
<|endoftext|>


<commit_before>
/*

                        /~` _  _ _|_. _     _ |_ | _
                        \_,(_)| | | || ||_|(_||_)|(/_

                    https://github.com/Naios/continuable
                                   v3.0.0

  Copyright(c) 2015 - 2018 Denis Blank <denis.blank at outlook dot com>

  Permission is hereby granted, free of charge, to any person obtaining a copy
  of this software and associated documentation files(the "Software"), to deal
  in the Software without restriction, including without limitation the rights
  to use, copy, modify, merge, publish, distribute, sublicense, and / or sell
  copies of the Software, and to permit persons to whom the Software is
  furnished to do so, subject to the following conditions :

  The above copyright notice and this permission notice shall be included in
  all copies or substantial portions of the Software.

  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE
  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
  SOFTWARE.
**/

#ifndef CONTINUABLE_RESULT_HPP_INCLUDED
#define CONTINUABLE_RESULT_HPP_INCLUDED

#include <type_traits>
#include <utility>
#include <continuable/continuable-primitives.hpp>
#include <continuable/detail/utility/flat-variant.hpp>
#include <continuable/detail/utility/result-trait.hpp>
#include <continuable/detail/utility/traits.hpp>

namespace cti {
/// A class which is convertible to any result and that definitly holds no
/// value so the real result gets invalidated when
/// this object is passed to it
struct empty_result {};

/// A class which is convertible to any result and that definitly holds
/// an exception which is then passed to the converted result object.
class exceptional_result {
  exception_t exception_;

public:
  exceptional_result() = delete;
  exceptional_result(exceptional_result const&) = default;
  exceptional_result(exceptional_result&&) = default;
  exceptional_result& operator=(exceptional_result const&) = default;
  exceptional_result& operator=(exceptional_result&&) = default;
  ~exceptional_result() = default;

  explicit exceptional_result(exception_t exception)
      // NOLINTNEXTLINE(hicpp-move-const-arg, performance-move-const-arg)
      : exception_(std::move(exception)) {
  }

  exceptional_result& operator=(exception_t exception) {
    // NOLINTNEXTLINE(hicpp-move-const-arg, performance-move-const-arg)
    exception_ = std::move(exception);
    return *this;
  }

  void set_exception(exception_t exception) {
    // NOLINTNEXTLINE(hicpp-move-const-arg, performance-move-const-arg)
    exception_ = std::move(exception);
  }

  exception_t& get_exception() & noexcept {
    return exception_;
  }
  exception_t const& get_exception() const& noexcept {
    return exception_;
  }
  exception_t&& get_exception() && noexcept {
    return std::move(exception_);
  }
};

/// A class similar to the one in the result proposal,
/// however it's capable of carrying an exception_t.
template <typename... T>
class result {
  using trait_t = detail::result_trait<T...>;
  using surrogate_t = typename trait_t::surrogate_t;

public:
  using value_t = typename trait_t::value_t;
  using exception_t = exception_t;

  result() = default;
  result(result const&) = default;
  result(result&&) = default;
  result& operator=(result const&) = default;
  result& operator=(result&&) = default;
  ~result() = default;

  template <typename... Args,
            decltype(trait_t::wrap(std::declval<Args>()...))* = nullptr>
  explicit result(Args&&... values)
      : variant_(trait_t::wrap(std::forward<Args>(values)...)) {
  }
  explicit result(exception_t exception) : variant_(std::move(exception)) {
  }
  result(empty_result){};
  result(exceptional_result exceptional_result)
      : variant_(std::move(exceptional_result.get_exception())) {
  }

  result& operator=(empty_result) {
    set_empty();
    return *this;
  }
  result& operator=(exceptional_result exceptional_result) {
    set_exception(std::move(exceptional_result.get_exception()));
    return *this;
  }

  void set_empty() {
    variant_.set_empty();
  }
  void set_value(T... values) {
    variant_ = trait_t::wrap(std::move(values)...);
  }
  void set_exception(exception_t exception) {
    variant_ = std::move(exception);
  }

  bool is_empty() const noexcept {
    return variant_.is_empty();
  }
  bool is_value() const noexcept {
    return variant_.template is<surrogate_t>();
  }
  bool is_exception() const noexcept {
    return variant_.template is<exception_t>();
  }

  explicit constexpr operator bool() const noexcept {
    return is_value();
  }

  decltype(auto) get_value() & noexcept {
    return trait_t::unwrap(variant_.template cast<surrogate_t>());
  }
  decltype(auto) get_value() const& noexcept {
    return trait_t::unwrap(variant_.template cast<surrogate_t>());
  }
  decltype(auto) get_value() && noexcept {
    return trait_t::unwrap(std::move(variant_).template cast<surrogate_t>());
  }

  decltype(auto) operator*() & noexcept {
    return get_value();
  }
  decltype(auto) operator*() const& noexcept {
    return get_value();
  }
  decltype(auto) operator*() && noexcept {
    return std::move(*this).get_value();
  }

  exception_t& get_exception() & noexcept {
    return variant_.template cast<exception_t>();
  }
  exception_t const& get_exception() const& noexcept {
    return variant_.template cast<exception_t>();
  }
  exception_t&& get_exception() && noexcept {
    return std::move(variant_).template cast<exception_t>();
  }

private:
  detail::container::flat_variant<surrogate_t, exception_t> variant_;
};

template <typename... T>
auto make_result(T&&... values) {
  return result<detail::traits::unrefcv_t<T>...>(std::forward<T>(values)...);
}

// NOLINTNEXTLINE(performance-unnecessary-value-param)
inline exceptional_result make_exceptional_result(exception_t exception) {
  // NOLINTNEXTLINE(hicpp-move-const-arg, performance-move-const-arg)
  return exceptional_result{std::move(exception)};
}

inline empty_result make_empty_result() {
  return {};
}
} // namespace cti

#endif // CONTINUABLE_RESULT_HPP_INCLUDED
<commit_msg>Only provide value_t from result<commit_after>
/*

                        /~` _  _ _|_. _     _ |_ | _
                        \_,(_)| | | || ||_|(_||_)|(/_

                    https://github.com/Naios/continuable
                                   v3.0.0

  Copyright(c) 2015 - 2018 Denis Blank <denis.blank at outlook dot com>

  Permission is hereby granted, free of charge, to any person obtaining a copy
  of this software and associated documentation files(the "Software"), to deal
  in the Software without restriction, including without limitation the rights
  to use, copy, modify, merge, publish, distribute, sublicense, and / or sell
  copies of the Software, and to permit persons to whom the Software is
  furnished to do so, subject to the following conditions :

  The above copyright notice and this permission notice shall be included in
  all copies or substantial portions of the Software.

  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE
  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
  SOFTWARE.
**/

#ifndef CONTINUABLE_RESULT_HPP_INCLUDED
#define CONTINUABLE_RESULT_HPP_INCLUDED

#include <type_traits>
#include <utility>
#include <continuable/continuable-primitives.hpp>
#include <continuable/detail/utility/flat-variant.hpp>
#include <continuable/detail/utility/result-trait.hpp>
#include <continuable/detail/utility/traits.hpp>

namespace cti {
/// A class which is convertible to any result and that definitly holds no
/// value so the real result gets invalidated when
/// this object is passed to it
struct empty_result {};

/// A class which is convertible to any result and that definitly holds
/// an exception which is then passed to the converted result object.
class exceptional_result {
  exception_t exception_;

public:
  exceptional_result() = delete;
  exceptional_result(exceptional_result const&) = default;
  exceptional_result(exceptional_result&&) = default;
  exceptional_result& operator=(exceptional_result const&) = default;
  exceptional_result& operator=(exceptional_result&&) = default;
  ~exceptional_result() = default;

  explicit exceptional_result(exception_t exception)
      // NOLINTNEXTLINE(hicpp-move-const-arg, performance-move-const-arg)
      : exception_(std::move(exception)) {
  }

  exceptional_result& operator=(exception_t exception) {
    // NOLINTNEXTLINE(hicpp-move-const-arg, performance-move-const-arg)
    exception_ = std::move(exception);
    return *this;
  }

  void set_exception(exception_t exception) {
    // NOLINTNEXTLINE(hicpp-move-const-arg, performance-move-const-arg)
    exception_ = std::move(exception);
  }

  exception_t& get_exception() & noexcept {
    return exception_;
  }
  exception_t const& get_exception() const& noexcept {
    return exception_;
  }
  exception_t&& get_exception() && noexcept {
    return std::move(exception_);
  }
};

/// A class similar to the one in the result proposal,
/// however it's capable of carrying an exception_t.
template <typename... T>
class result {
  using trait_t = detail::result_trait<T...>;
  using surrogate_t = typename trait_t::surrogate_t;

public:
  using value_t = typename trait_t::value_t;

  result() = default;
  result(result const&) = default;
  result(result&&) = default;
  result& operator=(result const&) = default;
  result& operator=(result&&) = default;
  ~result() = default;

  template <typename... Args,
            decltype(trait_t::wrap(std::declval<Args>()...))* = nullptr>
  explicit result(Args&&... values)
      : variant_(trait_t::wrap(std::forward<Args>(values)...)) {
  }
  explicit result(exception_t exception) : variant_(std::move(exception)) {
  }
  result(empty_result){};
  result(exceptional_result exceptional_result)
      : variant_(std::move(exceptional_result.get_exception())) {
  }

  result& operator=(empty_result) {
    set_empty();
    return *this;
  }
  result& operator=(exceptional_result exceptional_result) {
    set_exception(std::move(exceptional_result.get_exception()));
    return *this;
  }

  void set_empty() {
    variant_.set_empty();
  }
  void set_value(T... values) {
    variant_ = trait_t::wrap(std::move(values)...);
  }
  void set_exception(exception_t exception) {
    variant_ = std::move(exception);
  }

  bool is_empty() const noexcept {
    return variant_.is_empty();
  }
  bool is_value() const noexcept {
    return variant_.template is<surrogate_t>();
  }
  bool is_exception() const noexcept {
    return variant_.template is<exception_t>();
  }

  explicit constexpr operator bool() const noexcept {
    return is_value();
  }

  decltype(auto) get_value() & noexcept {
    return trait_t::unwrap(variant_.template cast<surrogate_t>());
  }
  decltype(auto) get_value() const& noexcept {
    return trait_t::unwrap(variant_.template cast<surrogate_t>());
  }
  decltype(auto) get_value() && noexcept {
    return trait_t::unwrap(std::move(variant_).template cast<surrogate_t>());
  }

  decltype(auto) operator*() & noexcept {
    return get_value();
  }
  decltype(auto) operator*() const& noexcept {
    return get_value();
  }
  decltype(auto) operator*() && noexcept {
    return std::move(*this).get_value();
  }

  exception_t& get_exception() & noexcept {
    return variant_.template cast<exception_t>();
  }
  exception_t const& get_exception() const& noexcept {
    return variant_.template cast<exception_t>();
  }
  exception_t&& get_exception() && noexcept {
    return std::move(variant_).template cast<exception_t>();
  }

private:
  detail::container::flat_variant<surrogate_t, exception_t> variant_;
};

template <typename... T>
auto make_result(T&&... values) {
  return result<detail::traits::unrefcv_t<T>...>(std::forward<T>(values)...);
}

// NOLINTNEXTLINE(performance-unnecessary-value-param)
inline exceptional_result make_exceptional_result(exception_t exception) {
  // NOLINTNEXTLINE(hicpp-move-const-arg, performance-move-const-arg)
  return exceptional_result{std::move(exception)};
}

inline empty_result make_empty_result() {
  return {};
}
} // namespace cti

#endif // CONTINUABLE_RESULT_HPP_INCLUDED
<|endoftext|>


<commit_before>#ifndef K3_RUNTIME_COMMON_H
#define K3_RUNTIME_COMMON_H

#include <list>
#include <map>
#include <memory>
#include <stdexcept>
#include <tuple>
#include <utility>
#include <boost/any.hpp>
#include <boost/asio.hpp>
#include <boost/archive/text_iarchive.hpp>
#include <boost/archive/text_oarchive.hpp>
#include <boost/log/core.hpp>
#include <boost/log/sources/record_ostream.hpp>
#include <boost/log/sources/severity_channel_logger.hpp>
#include <boost/log/sources/severity_feature.hpp>
#include <boost/log/trivial.hpp>
#include <boost/phoenix/core.hpp>
#include <boost/phoenix/stl/algorithm.hpp>

namespace K3 {

  using namespace std;
  using boost::any;

  using namespace boost::log;
  using namespace boost::log::sources;
  using namespace boost::log::trivial;
  using namespace boost::phoenix;

  typedef string Identifier;
  typedef string Value;

  typedef string Value;
  typedef string EValue;
  typedef string IValue;

  typedef tuple<boost::asio::ip::address, unsigned short> Address;

  enum class Builtin { Stdin, Stdout, Stderr };
  enum class IOMode  { Read, Write, Append, ReadWrite };

  //---------------
  // Addresses.

  Address make_address(const string& host, unsigned short port) {
    return Address(boost::asio::ip::address::from_string(host), port);
  }

  Address make_address(const char* host, unsigned short port) {
    return Address(boost::asio::ip::address::from_string(host), port);
  }

  Address make_address(const string&& host, unsigned short port) {
    return Address(boost::asio::ip::address::from_string(host), port);
  }

  inline string addressHost(const Address& addr) { return get<0>(addr).to_string(); }
  inline string addressHost(Address&& addr) { return get<0>(std::forward<Address>(addr)).to_string(); }

  inline int addressPort(const Address& addr) { return get<1>(addr); }
  inline int addressPort(Address&& addr) { return get<1>(std::forward<Address>(addr)); }

  string addressAsString(const Address& addr) {
    return addressHost(addr) + ":" + to_string(addressPort(addr));
  }

  string addressAsString(Address&& addr) {
    return addressHost(std::forward<Address>(addr))
            + ":" + to_string(addressPort(std::forward<Address>(addr)));
  }

  Address internalSendAddress(const Address& addr) {
    return make_address(addressHost(addr), addressPort(addr)+1);
  }

  Address internalSendAddress(Address&& addr) {
    return make_address(addressHost(std::forward<Address>(addr)),
                        addressPort(std::forward<Address>(addr))+1);
  }

  Address externalSendAddress(const Address& addr) {
    return make_address(addressHost(addr), addressPort(addr)+2);
  }

  Address externalSendAddress(Address&& addr) {
    return make_address(addressHost(std::forward<Address>(addr)),
                        addressPort(std::forward<Address>(addr))+2);
  }

  Address defaultAddress = make_address("127.0.0.1", 40000);

  //-------------
  // Messages.

  template<typename Value>
  class Message : public tuple<Address, Identifier, Value> {
  public:
    Message(Address addr, Identifier id, const Value& v)
      : tuple<Address, Identifier, Value>(std::move(addr), std::move(id), v)
    {}

    Message(Address addr, Identifier id, Value&& v)
      : tuple<Address, Identifier, Value>(std::move(addr), std::move(id), std::forward<Value>(v))
    {}

    Message(Address&& addr, Identifier&& id, Value&& v)
      : tuple<Address, Identifier, Value>(std::forward<Address>(addr),
                                          std::forward<Identifier>(id),
                                          std::forward<Value>(v))
    {}

    Address&    address()  { return get<0>(*this); }
    Identifier& id()       { return get<1>(*this); }
    Value&      contents() { return get<2>(*this); }
    string      target()   { return id() + "@" + addressAsString(address()); }
    const Address&    address()  const { return get<0>(*this); }
    const Identifier& id()       const { return get<1>(*this); }
    const Value&      contents() const { return get<2>(*this); }
    const string      target()   const { return id() + "@" + addressAsString(address()); }
  };

  //--------------------
  // System environment.

  // Literals are native values rather than an AST reprensentation as in Haskell.
  typedef any Literal;
  typedef map<Identifier, Literal> PeerBootstrap;
  typedef map<Address, PeerBootstrap> SystemEnvironment;

  list<Address> deployedNodes(const SystemEnvironment& sysEnv) {
    list<Address> r;
    for ( auto x : sysEnv ) { r.push_back(x.first); }
    return std::move(r);
  }

  bool isDeployedNode(const SystemEnvironment& sysEnv, Address addr) {
    return sysEnv.find(addr) != sysEnv.end();
  }

  //-------------
  // Logging.
  class Log {
  public:
    Log() {}
    Log(severity_level lvl) : defaultLevel(lvl) {}

    virtual void log(const string& msg) = 0;
    virtual void log(const char* msg) = 0;
    virtual void logAt(severity_level lvl, const string& msg) = 0;
    virtual void logAt(severity_level lvl, const char* msg) = 0;

  protected:
    severity_level defaultLevel;
  };

  class LogST : public severity_channel_logger<severity_level,string>, public Log
  {
  public:
    typedef severity_channel_logger<severity_level,string> logger;

    LogST(string chan) : logger(keywords::channel = chan), Log(severity_level::info) {}
    LogST(string chan, severity_level lvl) : logger(keywords::channel = chan), Log(lvl) {}

    void log(const string& msg) { BOOST_LOG_SEV(*this, defaultLevel) << msg; }
    void log(const char* msg) { BOOST_LOG_SEV(*this, defaultLevel) << msg; }

    void logAt(severity_level lvl, const string& msg) { BOOST_LOG_SEV(*this, lvl) << msg; }
    void logAt(severity_level lvl, const char& msg) { BOOST_LOG_SEV(*this, lvl) << msg; }
  };

  class LogMT : public severity_channel_logger_mt<severity_level,string>, public Log
  {
  public:
    typedef severity_channel_logger_mt<severity_level,string> logger;

    LogMT(string chan) : logger(keywords::channel = chan), Log(severity_level::info) {}
    LogMT(string chan, severity_level lvl) : logger(keywords::channel = chan), Log(lvl) {}

    void log(const string& msg) { BOOST_LOG_SEV(*this, defaultLevel) << msg; }
    void log(const char* msg) { BOOST_LOG_SEV(*this, defaultLevel) << msg; }

    void logAt(severity_level lvl, const string& msg) { BOOST_LOG_SEV(*this, lvl) << msg; }
    void logAt(severity_level lvl, const char* msg) { BOOST_LOG_SEV(*this, lvl) << msg; }
  };

  //--------------------
  // Wire descriptions

  // A generic exception that can be thrown by wire descriptor methods.
  class CodecException : public runtime_error {
  public:
    CodecException(const string& msg) : runtime_error(msg) {}
    CodecException(const char* msg) : runtime_error(msg) {}
  };

  // Message serializtion/deserialization abstract base class.
  // Implementations can encapsulate framing concerns as well as serdes operations.
  //
  // The unpack method may be supplied a complete or incomplete string corresponding
  // to a value. It is left to the implementation to determine the scope of functionality
  // supported, for example partial unpacking (e.g., for network sockets).
  // The semantics of repeated invocations are dependent on the actual implementation
  // of the wire description (including factors such as message loss).
  // This includes the conditions under which an exception is thrown.

  class Codec: public virtual LogMT {
    public:
      Codec(): LogMT("Codec") {}

      virtual Value encode(Value) = 0;
      virtual Value decode(Value) = 0;
  };
}

#endif
<commit_msg>Deparameterized Messages<commit_after>#ifndef K3_RUNTIME_COMMON_H
#define K3_RUNTIME_COMMON_H

#include <list>
#include <map>
#include <memory>
#include <stdexcept>
#include <tuple>
#include <utility>
#include <boost/any.hpp>
#include <boost/asio.hpp>
#include <boost/archive/text_iarchive.hpp>
#include <boost/archive/text_oarchive.hpp>
#include <boost/log/core.hpp>
#include <boost/log/sources/record_ostream.hpp>
#include <boost/log/sources/severity_channel_logger.hpp>
#include <boost/log/sources/severity_feature.hpp>
#include <boost/log/trivial.hpp>
#include <boost/phoenix/core.hpp>
#include <boost/phoenix/stl/algorithm.hpp>

namespace K3 {

  using namespace std;
  using boost::any;

  using namespace boost::log;
  using namespace boost::log::sources;
  using namespace boost::log::trivial;
  using namespace boost::phoenix;

  typedef string Identifier;
  typedef string Value;

  typedef string Value;
  typedef string EValue;
  typedef string IValue;

  typedef tuple<boost::asio::ip::address, unsigned short> Address;

  enum class Builtin { Stdin, Stdout, Stderr };
  enum class IOMode  { Read, Write, Append, ReadWrite };

  //---------------
  // Addresses.

  Address make_address(const string& host, unsigned short port) {
    return Address(boost::asio::ip::address::from_string(host), port);
  }

  Address make_address(const char* host, unsigned short port) {
    return Address(boost::asio::ip::address::from_string(host), port);
  }

  Address make_address(const string&& host, unsigned short port) {
    return Address(boost::asio::ip::address::from_string(host), port);
  }

  inline string addressHost(const Address& addr) { return get<0>(addr).to_string(); }
  inline string addressHost(Address&& addr) { return get<0>(std::forward<Address>(addr)).to_string(); }

  inline int addressPort(const Address& addr) { return get<1>(addr); }
  inline int addressPort(Address&& addr) { return get<1>(std::forward<Address>(addr)); }

  string addressAsString(const Address& addr) {
    return addressHost(addr) + ":" + to_string(addressPort(addr));
  }

  string addressAsString(Address&& addr) {
    return addressHost(std::forward<Address>(addr))
            + ":" + to_string(addressPort(std::forward<Address>(addr)));
  }

  Address internalSendAddress(const Address& addr) {
    return make_address(addressHost(addr), addressPort(addr)+1);
  }

  Address internalSendAddress(Address&& addr) {
    return make_address(addressHost(std::forward<Address>(addr)),
                        addressPort(std::forward<Address>(addr))+1);
  }

  Address externalSendAddress(const Address& addr) {
    return make_address(addressHost(addr), addressPort(addr)+2);
  }

  Address externalSendAddress(Address&& addr) {
    return make_address(addressHost(std::forward<Address>(addr)),
                        addressPort(std::forward<Address>(addr))+2);
  }

  Address defaultAddress = make_address("127.0.0.1", 40000);

  //-------------
  // Messages.

  class Message : public tuple<Address, Identifier, Value> {
  public:
    Message(Address addr, Identifier id, const Value& v)
      : tuple<Address, Identifier, Value>(std::move(addr), std::move(id), v)
    {}

    Message(Address addr, Identifier id, Value&& v)
      : tuple<Address, Identifier, Value>(std::move(addr), std::move(id), std::forward<Value>(v))
    {}

    Message(Address&& addr, Identifier&& id, Value&& v)
      : tuple<Address, Identifier, Value>(std::forward<Address>(addr),
                                          std::forward<Identifier>(id),
                                          std::forward<Value>(v))
    {}

    Address&    address()  { return get<0>(*this); }
    Identifier& id()       { return get<1>(*this); }
    Value&      contents() { return get<2>(*this); }
    string      target()   { return id() + "@" + addressAsString(address()); }
    const Address&    address()  const { return get<0>(*this); }
    const Identifier& id()       const { return get<1>(*this); }
    const Value&      contents() const { return get<2>(*this); }
    const string      target()   const { return id() + "@" + addressAsString(address()); }
  };

  //--------------------
  // System environment.

  // Literals are native values rather than an AST reprensentation as in Haskell.
  typedef any Literal;
  typedef map<Identifier, Literal> PeerBootstrap;
  typedef map<Address, PeerBootstrap> SystemEnvironment;

  list<Address> deployedNodes(const SystemEnvironment& sysEnv) {
    list<Address> r;
    for ( auto x : sysEnv ) { r.push_back(x.first); }
    return std::move(r);
  }

  bool isDeployedNode(const SystemEnvironment& sysEnv, Address addr) {
    return sysEnv.find(addr) != sysEnv.end();
  }

  //-------------
  // Logging.
  class Log {
  public:
    Log() {}
    Log(severity_level lvl) : defaultLevel(lvl) {}

    virtual void log(const string& msg) = 0;
    virtual void log(const char* msg) = 0;
    virtual void logAt(severity_level lvl, const string& msg) = 0;
    virtual void logAt(severity_level lvl, const char* msg) = 0;

  protected:
    severity_level defaultLevel;
  };

  class LogST : public severity_channel_logger<severity_level,string>, public Log
  {
  public:
    typedef severity_channel_logger<severity_level,string> logger;

    LogST(string chan) : logger(keywords::channel = chan), Log(severity_level::info) {}
    LogST(string chan, severity_level lvl) : logger(keywords::channel = chan), Log(lvl) {}

    void log(const string& msg) { BOOST_LOG_SEV(*this, defaultLevel) << msg; }
    void log(const char* msg) { BOOST_LOG_SEV(*this, defaultLevel) << msg; }

    void logAt(severity_level lvl, const string& msg) { BOOST_LOG_SEV(*this, lvl) << msg; }
    void logAt(severity_level lvl, const char& msg) { BOOST_LOG_SEV(*this, lvl) << msg; }
  };

  class LogMT : public severity_channel_logger_mt<severity_level,string>, public Log
  {
  public:
    typedef severity_channel_logger_mt<severity_level,string> logger;

    LogMT(string chan) : logger(keywords::channel = chan), Log(severity_level::info) {}
    LogMT(string chan, severity_level lvl) : logger(keywords::channel = chan), Log(lvl) {}

    void log(const string& msg) { BOOST_LOG_SEV(*this, defaultLevel) << msg; }
    void log(const char* msg) { BOOST_LOG_SEV(*this, defaultLevel) << msg; }

    void logAt(severity_level lvl, const string& msg) { BOOST_LOG_SEV(*this, lvl) << msg; }
    void logAt(severity_level lvl, const char* msg) { BOOST_LOG_SEV(*this, lvl) << msg; }
  };

  //--------------------
  // Wire descriptions

  // A generic exception that can be thrown by wire descriptor methods.
  class CodecException : public runtime_error {
  public:
    CodecException(const string& msg) : runtime_error(msg) {}
    CodecException(const char* msg) : runtime_error(msg) {}
  };

  // Message serializtion/deserialization abstract base class.
  // Implementations can encapsulate framing concerns as well as serdes operations.
  //
  // The unpack method may be supplied a complete or incomplete string corresponding
  // to a value. It is left to the implementation to determine the scope of functionality
  // supported, for example partial unpacking (e.g., for network sockets).
  // The semantics of repeated invocations are dependent on the actual implementation
  // of the wire description (including factors such as message loss).
  // This includes the conditions under which an exception is thrown.

  class Codec: public virtual LogMT {
    public:
      Codec(): LogMT("Codec") {}

      virtual Value encode(Value) = 0;
      virtual shared_ptr<Value> decode(Value) = 0;
  };
}

#endif
<|endoftext|>


<commit_before>#include <QPushButton>
#include <QGridLayout>
#include <QIcon>
#include <QSize>
#include <QLineEdit>
#include <QTcpSocket>
#include <QStatusBar>
#include <QLabel>
#include <QAction>
#include <QMenuBar>
#include <QStackedLayout>
#include <QMessageBox>
#include <QPainter>

#include "Window.h"
#include "AbstractSymbol.h"
#include "Circle.h"
#include "Cross.h"
#include "AbstractBoard.h"
#include "SetupConnection.h"
#include "Game.h"

#include "BoardMulti.h"

CBoardMulti::CBoardMulti(CWindow *window, CGame *game) : CAbstractBoard(window), win(window), g(game)
{
	hide();
	win->removeFromLayout(this);
	win->adjustSize();
	win->setAboutEnabled(false);
	setup_connection = new CSetupConnection(window, socket);
	setup_connection->show();

	for(int x = 0; x < 3; x++) for(int y = 0; y < 3; y++)
	{
		connect(&button[x][y], &QPushButton::clicked, [&, x, y]
		{
			if(turn)
			{
				makeMove(x, y, symbol_my, symbol_char_my, false, "Opponent's turn");
				socket.write(QByteArray(QByteArray::number(x) + ',' + QByteArray::number(y)));
				socket.waitForBytesWritten(3000);
				markDisabledAll();
				checkConditions();
			}
		});
	}

	connect(&socket, &QTcpSocket::connected, this, &CBoardMulti::handleConnection);
	connect(&restart, &QPushButton::clicked, this, &CBoardMulti::handleRestart);

	statusbar.setSizeGripEnabled(false);
	layout.setRowMinimumHeight(7, 30);
	layout.addWidget(&statusbar, 7, 0, 1, 5);
}

CBoardMulti::~CBoardMulti()
{
	if(socket.state() == QAbstractSocket::ConnectedState)
		socket.disconnectFromHost();
	if(setup_connection != nullptr)
		delete setup_connection;
}

void CBoardMulti::handleRead()
{
	response = socket.readAll().data();
	CGame::logger("Received: " + response);
	if(setup_connection->isVisible())
	{
		setup_connection->hide();
		delete setup_connection;
		setup_connection = nullptr;
		win->addToLayout(this);
		show();

		handleRandom();
	}
	else
	{
		if(response.contains("restart"))
		{
			enum QMessageBox::StandardButton btn = QMessageBox::question(this, "Restart request", "Opponent wants to restart the game\n\nAgreed?", QMessageBox::Yes | QMessageBox::No, QMessageBox::Yes);
			if(btn == QMessageBox::Yes)
				socket.write("ry");
			else
				socket.write("rn");
		}
		else if(response.contains("rn"))
		{
			QMessageBox::information(this, "Info", "Opponent has not agreed");
			if(turn)
				statusbar.showMessage("Your turn");
			else
				statusbar.showMessage("Opponent's turn");
			markEnabledWhatLeft();
			restart.setEnabled(true);
		}
		else if(response.contains("r-"))
		{
			handleRandom();
			restartBoard();
			restart.setEnabled(true);
		}
		else if(response.contains("dis"))
		{
			QMessageBox::information(this, "Info", "Opponent has disconnected\n\nPress OK to return to menu");
			g->handleReturn();
		}
		else
		{
			makeMove(response[0].digitValue(), response[2].digitValue(), symbol_enemy, symbol_char_enemy, true, "Your turn");
			markEnabledWhatLeft();
			checkConditions();
		}
	}
}

void CBoardMulti::makeMove(const int &x, const int &y, const CAbstractSymbol *symbol, QChar symbol_char, bool isMyTurn, QString message)
{
	button[x][y].setDisabled(true);
	button[x][y].setIcon(symbol->getIcon());
	button[x][y].setIconSize(symbol->getSize());
	button_str[x][y] = symbol_char;
	turn = isMyTurn;
	statusbar.showMessage(message);
}

void CBoardMulti::handleConnection()
{
	CGame::logger("Connected");

	connect(&socket, &QTcpSocket::readyRead, this, &CBoardMulti::handleRead);
	connect(&socket, &QTcpSocket::disconnected, this, &CBoardMulti::handleDisconnection);
}

void CBoardMulti::handleDisconnection()
{
	CGame::logger("Disconnected");
}

void CBoardMulti::handleRestart()
{
	markDisabledAll();
	restart.setDisabled(true);
	socket.write("restart");
	statusbar.showMessage("Waiting for response");
}

void CBoardMulti::handleRandom()
{
	turn = response[2].digitValue();
	symbol_char_my = response[3];

	if(symbol_char_my == 'x')
	{
		symbol_my = ✗
		symbol_enemy = &circle;
		symbol_char_enemy = 'o';
	}
	else if(symbol_char_my == 'o')
	{
		symbol_my = &circle;
		symbol_enemy = ✗
		symbol_char_enemy = 'x';
	}

	if(turn)
	{
		statusbar.showMessage("Your turn");
		markEnabledAll();
	}
	else
	{
		statusbar.showMessage("Opponent's turn");
		markDisabledAll();
	}

	label_turn.setText("Your symbol:");
	label_current.setPixmap(symbol_my->getIcon().pixmap(size_current));
}
<commit_msg>change condition<commit_after>#include <QPushButton>
#include <QGridLayout>
#include <QIcon>
#include <QSize>
#include <QLineEdit>
#include <QTcpSocket>
#include <QStatusBar>
#include <QLabel>
#include <QAction>
#include <QMenuBar>
#include <QStackedLayout>
#include <QMessageBox>
#include <QPainter>

#include "Window.h"
#include "AbstractSymbol.h"
#include "Circle.h"
#include "Cross.h"
#include "AbstractBoard.h"
#include "SetupConnection.h"
#include "Game.h"

#include "BoardMulti.h"

CBoardMulti::CBoardMulti(CWindow *window, CGame *game) : CAbstractBoard(window), win(window), g(game)
{
	hide();
	win->removeFromLayout(this);
	win->adjustSize();
	win->setAboutEnabled(false);
	setup_connection = new CSetupConnection(window, socket);
	setup_connection->show();

	for(int x = 0; x < 3; x++) for(int y = 0; y < 3; y++)
	{
		connect(&button[x][y], &QPushButton::clicked, [&, x, y]
		{
			if(turn)
			{
				makeMove(x, y, symbol_my, symbol_char_my, false, "Opponent's turn");
				socket.write(QByteArray(QByteArray::number(x) + ',' + QByteArray::number(y)));
				socket.waitForBytesWritten(3000);
				markDisabledAll();
				checkConditions();
			}
		});
	}

	connect(&socket, &QTcpSocket::connected, this, &CBoardMulti::handleConnection);
	connect(&restart, &QPushButton::clicked, this, &CBoardMulti::handleRestart);

	statusbar.setSizeGripEnabled(false);
	layout.setRowMinimumHeight(7, 30);
	layout.addWidget(&statusbar, 7, 0, 1, 5);
}

CBoardMulti::~CBoardMulti()
{
	if(socket.state() == QAbstractSocket::ConnectedState)
		socket.disconnectFromHost();
	if(setup_connection != nullptr)
		delete setup_connection;
}

void CBoardMulti::handleRead()
{
	response = socket.readAll().data();
	CGame::logger("Received: " + response);
	if(setup_connection != nullptr)
	{
		setup_connection->hide();
		delete setup_connection;
		setup_connection = nullptr;
		win->addToLayout(this);
		show();

		handleRandom();
	}
	else
	{
		if(response.contains("restart"))
		{
			enum QMessageBox::StandardButton btn = QMessageBox::question(this, "Restart request", "Opponent wants to restart the game\n\nAgreed?", QMessageBox::Yes | QMessageBox::No, QMessageBox::Yes);
			if(btn == QMessageBox::Yes)
				socket.write("ry");
			else
				socket.write("rn");
		}
		else if(response.contains("rn"))
		{
			QMessageBox::information(this, "Info", "Opponent has not agreed");
			if(turn)
				statusbar.showMessage("Your turn");
			else
				statusbar.showMessage("Opponent's turn");
			markEnabledWhatLeft();
			restart.setEnabled(true);
		}
		else if(response.contains("r-"))
		{
			handleRandom();
			restartBoard();
			restart.setEnabled(true);
		}
		else if(response.contains("dis"))
		{
			QMessageBox::information(this, "Info", "Opponent has disconnected\n\nPress OK to return to menu");
			g->handleReturn();
		}
		else
		{
			makeMove(response[0].digitValue(), response[2].digitValue(), symbol_enemy, symbol_char_enemy, true, "Your turn");
			markEnabledWhatLeft();
			checkConditions();
		}
	}
}

void CBoardMulti::makeMove(const int &x, const int &y, const CAbstractSymbol *symbol, QChar symbol_char, bool isMyTurn, QString message)
{
	button[x][y].setDisabled(true);
	button[x][y].setIcon(symbol->getIcon());
	button[x][y].setIconSize(symbol->getSize());
	button_str[x][y] = symbol_char;
	turn = isMyTurn;
	statusbar.showMessage(message);
}

void CBoardMulti::handleConnection()
{
	CGame::logger("Connected");

	connect(&socket, &QTcpSocket::readyRead, this, &CBoardMulti::handleRead);
	connect(&socket, &QTcpSocket::disconnected, this, &CBoardMulti::handleDisconnection);
}

void CBoardMulti::handleDisconnection()
{
	CGame::logger("Disconnected");
}

void CBoardMulti::handleRestart()
{
	markDisabledAll();
	restart.setDisabled(true);
	socket.write("restart");
	statusbar.showMessage("Waiting for response");
}

void CBoardMulti::handleRandom()
{
	turn = response[2].digitValue();
	symbol_char_my = response[3];

	if(symbol_char_my == 'x')
	{
		symbol_my = ✗
		symbol_enemy = &circle;
		symbol_char_enemy = 'o';
	}
	else if(symbol_char_my == 'o')
	{
		symbol_my = &circle;
		symbol_enemy = ✗
		symbol_char_enemy = 'x';
	}

	if(turn)
	{
		statusbar.showMessage("Your turn");
		markEnabledAll();
	}
	else
	{
		statusbar.showMessage("Opponent's turn");
		markDisabledAll();
	}

	label_turn.setText("Your symbol:");
	label_current.setPixmap(symbol_my->getIcon().pixmap(size_current));
}
<|endoftext|>


<commit_before>/*
 * Copyright (C) 2013 Aggregate
 *
 * Permission is hereby granted, free of charge, to any person
 * obtaining a copy of this software and associated documentation
 * files (the "Software"), to deal in the Software without
 * restriction, including without limitation the rights to use, copy,
 * modify, merge, publish, distribute, sublicense, and/or sell copies
 * of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be
 * included in all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 */

#ifndef __LIBENV_CRYPT_HPP__
#define __LIBENV_CRYPT_HPP__

namespace crypt
{
	void newSalt(char* salt, size_t len);

	template <size_t len>
	void newSalt(char (&salt)[len])
	{
		newSalt(salt, len);
	}

	// the output should be at least (len * 8 + 5) DIV 6 long
	void base64_encode(const void* data, size_t len, char* output);

	template <typename T, size_t salt_length, size_t digest_size, char alg_id>
	struct HashBase
	{
		enum {
			SALT_LENGTH = salt_length,
			SALT_SIZE = SALT_LENGTH + 1,
			DIGEST_SIZE = digest_size,
			PAYLOAD_LENGTH = (DIGEST_SIZE * 8 + 5) / 6,
			HASH_SIZE = PAYLOAD_LENGTH + SALT_LENGTH + 2,
			ALG_ID = alg_id
		};
		typedef char salt_t[SALT_SIZE];
		typedef char hash_t[HASH_SIZE];
		typedef unsigned char digest_t[DIGEST_SIZE];
		static bool verify(const char* message, const char* hash)
		{
			if (!message || !*message || !hash || !*hash)
				return false;

			size_t msg_len = strlen(message);
			size_t hash_len = strlen(hash);

			// is there enough data in the hash to hold the salt and the id?
			if (hash_len != HASH_SIZE - 1)
				return false;

			const char* salt = hash + hash_len - 1;

			if (*salt != ALG_ID)
				return false;

			salt -= SALT_LENGTH;
			digest_t digest;

			if (!T::__crypt(salt, message, msg_len, digest))
				return false;

			hash_t new_hash;
			pack(digest, (salt_t&)salt, new_hash);

			return strcmp(new_hash, hash) == 0;
		}

		static bool crypt(const char* message, hash_t& hash)
		{
			if (!message || !*message)
				return false;

			salt_t salt;
			digest_t digest;
			newSalt(salt);
			if (!T::__crypt(salt, message, strlen(message), digest))
				return false;

			pack(digest, salt, hash);
			return true;
		}

		static void pack(const digest_t& digest, const salt_t& salt, hash_t& hash)
		{
			base64_encode(digest, DIGEST_SIZE, hash);
			strcpy(hash + PAYLOAD_LENGTH, salt);
			hash[HASH_SIZE - 2] = ALG_ID;
			hash[HASH_SIZE - 1] = 0;
		}
	};

	struct SHA512Hash: HashBase<SHA512Hash, 16, 64, '5'>
	{
		static bool __crypt(const char* salt, const char* message, size_t len, digest_t &digest);
	};

	struct MD5Hash: HashBase<MD5Hash, 12, 16, 'M'>
	{
		static bool __crypt(const char* salt, const char* message, size_t len, digest_t &digest);
	};

	typedef SHA512Hash PasswordHash;
	typedef MD5Hash SessionHash;

	typedef PasswordHash::hash_t password_t;
	typedef SessionHash::hash_t session_t;

	inline bool password(const char* passphrase, password_t& hash)
	{
		return PasswordHash::crypt(passphrase, hash);
	}

	inline bool session(const char* seedMessage, session_t& sessionId)
	{
		return SessionHash::crypt(seedMessage, sessionId);
	}

	bool verify(const char* message, const char* hash);
};

#endif //__LIBENV_CRYPT_HPP__
<commit_msg>Verification bug fixed<commit_after>/*
 * Copyright (C) 2013 Aggregate
 *
 * Permission is hereby granted, free of charge, to any person
 * obtaining a copy of this software and associated documentation
 * files (the "Software"), to deal in the Software without
 * restriction, including without limitation the rights to use, copy,
 * modify, merge, publish, distribute, sublicense, and/or sell copies
 * of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be
 * included in all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 */

#ifndef __LIBENV_CRYPT_HPP__
#define __LIBENV_CRYPT_HPP__

namespace crypt
{
	void newSalt(char* salt, size_t len);

	template <size_t len>
	void newSalt(char (&salt)[len])
	{
		newSalt(salt, len);
	}

	// the output should be at least (len * 8 + 5) DIV 6 long
	void base64_encode(const void* data, size_t len, char* output);

	template <typename T, size_t salt_length, size_t digest_size, char alg_id>
	struct HashBase
	{
		enum {
			SALT_LENGTH = salt_length,
			SALT_SIZE = SALT_LENGTH + 1,
			DIGEST_SIZE = digest_size,
			PAYLOAD_LENGTH = (DIGEST_SIZE * 8 + 5) / 6,
			HASH_SIZE = PAYLOAD_LENGTH + SALT_LENGTH + 2,
			ALG_ID = alg_id
		};
		typedef char salt_t[SALT_SIZE];
		typedef char hash_t[HASH_SIZE];
		typedef unsigned char digest_t[DIGEST_SIZE];
		static bool verify(const char* message, const char* hash)
		{
			if (!message || !*message || !hash || !*hash)
				return false;

			size_t msg_len = strlen(message);
			size_t hash_len = strlen(hash);

			// is there enough data in the hash to hold the salt and the id?
			if (hash_len != HASH_SIZE - 1)
				return false;

			const char* salt = hash + hash_len - 1;

			if (*salt != ALG_ID)
				return false;

			salt -= SALT_LENGTH;
			digest_t digest;

			if (!T::__crypt(salt, message, msg_len, digest))
				return false;

			hash_t new_hash;
			salt_t out;
			memcpy(out, salt, SALT_SIZE);
			out[SALT_LENGTH] = 0;
			pack(digest, out, new_hash);

			return strcmp(new_hash, hash) == 0;
		}

		static bool crypt(const char* message, hash_t& hash)
		{
			if (!message || !*message)
				return false;

			salt_t salt;
			digest_t digest;
			newSalt(salt);
			if (!T::__crypt(salt, message, strlen(message), digest))
				return false;

			pack(digest, salt, hash);
			return true;
		}

		static void pack(const digest_t& digest, const salt_t& salt, hash_t& hash)
		{
			base64_encode(digest, DIGEST_SIZE, hash);
			strcpy(hash + PAYLOAD_LENGTH, salt);
			hash[HASH_SIZE - 2] = ALG_ID;
			hash[HASH_SIZE - 1] = 0;
		}
	};

	struct SHA512Hash: HashBase<SHA512Hash, 16, 64, '5'>
	{
		static bool __crypt(const char* salt, const char* message, size_t len, digest_t &digest);
	};

	struct MD5Hash: HashBase<MD5Hash, 12, 16, 'M'>
	{
		static bool __crypt(const char* salt, const char* message, size_t len, digest_t &digest);
	};

	typedef SHA512Hash PasswordHash;
	typedef MD5Hash SessionHash;

	typedef PasswordHash::hash_t password_t;
	typedef SessionHash::hash_t session_t;

	inline bool password(const char* passphrase, password_t& hash)
	{
		return PasswordHash::crypt(passphrase, hash);
	}

	inline bool session(const char* seedMessage, session_t& sessionId)
	{
		return SessionHash::crypt(seedMessage, sessionId);
	}

	bool verify(const char* message, const char* hash);
};

#endif //__LIBENV_CRYPT_HPP__
<|endoftext|>


<commit_before>//===-- ProtocolConformanceAnalysis.cpp - Protocol Conformance Analysis ---===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See https://swift.org/LICENSE.txt for license information
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===----------------------------------------------------------------------===//
// This analysis collects a set of nominal types (classes, structs, and enums)
// that conform to a protocol during whole module compilation. We only track
// protocols that are non-public.

#include "swift/SILOptimizer/Analysis/ProtocolConformanceAnalysis.h"
#include "swift/AST/ASTContext.h"
#include "swift/AST/ASTWalker.h"
#include "swift/AST/Module.h"
#include "swift/AST/ProtocolConformance.h"
#include "swift/SIL/SILInstruction.h"
#include "swift/SIL/SILModule.h"
#include "swift/SIL/SILValue.h"

using namespace swift;

namespace {
/// A helper class to collect all nominal type declarations.
class NominalTypeWalker : public ASTWalker {
  ProtocolConformanceAnalysis::ProtocolConformanceMap &ProtocolConformanceCache;

public:
  NominalTypeWalker(ProtocolConformanceAnalysis::ProtocolConformanceMap
                    &ProtocolConformanceCache)
      : ProtocolConformanceCache(ProtocolConformanceCache) {}

  bool walkToDeclPre(Decl *D) override {
    /// (1) Walk over all NominalTypeDecls to determine conformances.
    if (auto *NTD = dyn_cast<NominalTypeDecl>(D)) {
      auto Protocols = NTD->getAllProtocols();
      for (auto &Protocol : Protocols) {
        if (Protocol->getEffectiveAccess() <= AccessLevel::Internal) {
          ProtocolConformanceCache[Protocol].push_back(NTD);
        }
      }
    }
    /// (2) Walk over all ExtensionDecls to determine conformances.
    if (auto *e = dyn_cast<ExtensionDecl>(D)) {
      auto *ntd = e->getExtendedNominal();
      if (ntd && !isa<ProtocolDecl>(ntd)) {
        for (auto *conformance : e->getLocalConformances()) {
          if (isa<NormalProtocolConformance>(conformance)) {
            auto *proto = conformance->getProtocol();
            if (proto->getEffectiveAccess() <= AccessLevel::Internal) {
              ProtocolConformanceCache[proto].push_back(ntd);
            }
          }
        }
      }
    }
    return true;
  }
};
} // end anonymous namespace

void ProtocolConformanceAnalysis::init() {

  // We only do this in Whole-Module compilation mode.
  if (!M->isWholeModule())
    return;

  // Process all types implementing protocols.
  SmallVector<Decl *, 32> Decls;

  // Find all top level declarations.
  M->getSwiftModule()->getTopLevelDecls(Decls);

  /// This operation is quadratic and should only be performed
  /// in whole module compilation!
  NominalTypeWalker Walker(ProtocolConformanceCache);
  for (auto *D : Decls) {
    D->walk(Walker);
  }
}

/// Recursively traverse the conformance lists to determine sole conforming
/// class, struct or enum type.
NominalTypeDecl *
ProtocolConformanceAnalysis::findSoleConformingType(ProtocolDecl *Protocol) {

  /// First check in the SoleConformingTypeCache.
  auto SoleConformingTypeIt = SoleConformingTypeCache.find(Protocol);
  if (SoleConformingTypeIt != SoleConformingTypeCache.end())
    return SoleConformingTypeIt->second;

  SmallVector<ProtocolDecl *, 8> PDWorkList;
  SmallPtrSet<ProtocolDecl *, 8> VisitedPDs;
  NominalTypeDecl *SoleConformingNTD = nullptr;
  PDWorkList.push_back(Protocol);
  while (!PDWorkList.empty()) {
    auto *PD = PDWorkList.pop_back_val();
    // Protocols must have internal or lower access.
    if (PD->getEffectiveAccess() > AccessLevel::Internal) {
      return nullptr;
    }
    VisitedPDs.insert(PD);
    auto NTDList = getConformances(PD);
    for (auto *ConformingNTD : NTDList) {
      // Recurse on protocol types.
      if (auto *Proto = dyn_cast<ProtocolDecl>(ConformingNTD)) {
        // Ignore visited protocol decls.
        if (!VisitedPDs.count(Proto))
          PDWorkList.push_back(Proto);
      } else { // Classes, Structs and Enums are added here.
        // Bail if more than one conforming types were found.
        if (SoleConformingNTD && ConformingNTD != SoleConformingNTD) {
          return nullptr;
        } else {
          SoleConformingNTD = ConformingNTD;
        }
      }
    }
  }

  // Bail if we did not find a sole conforming type.
  if (!SoleConformingNTD)
    return nullptr;

  // Generic declarations are ignored.
  if (SoleConformingNTD->isGenericContext()) {
    return nullptr;
  }

  // Populate SoleConformingTypeCache.
  SoleConformingTypeCache.insert(std::pair<ProtocolDecl *, NominalTypeDecl *>(
      Protocol, SoleConformingNTD));

  // Return SoleConformingNTD.
  return SoleConformingNTD;
}

// Wrapper function to findSoleConformingType that checks for additional
// constraints for classes using ClassHierarchyAnalysis.
bool ProtocolConformanceAnalysis::getSoleConformingType(
    ProtocolDecl *Protocol, ClassHierarchyAnalysis *CHA, CanType &ConcreteType) {
  // Determine the sole conforming type.
  auto *NTD = findSoleConformingType(Protocol);
  if (!NTD)
    return false;

  // Sole conforming class should not be open access or have any derived class.
  ClassDecl *CD;
  if ((CD = dyn_cast<ClassDecl>(NTD)) &&
      (CD->getEffectiveAccess() == AccessLevel::Open ||
       CHA->hasKnownDirectSubclasses(CD))) {
    return false;
  }

  // Save the concrete type.
  ConcreteType = NTD->getDeclaredType()->getCanonicalType();
  return true;
}

ProtocolConformanceAnalysis::~ProtocolConformanceAnalysis() {}
<commit_msg>SILOptimizer: Stop calling getAllConformances() on protocols<commit_after>//===-- ProtocolConformanceAnalysis.cpp - Protocol Conformance Analysis ---===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See https://swift.org/LICENSE.txt for license information
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===----------------------------------------------------------------------===//
// This analysis collects a set of nominal types (classes, structs, and enums)
// that conform to a protocol during whole module compilation. We only track
// protocols that are non-public.

#include "swift/SILOptimizer/Analysis/ProtocolConformanceAnalysis.h"
#include "swift/AST/ASTContext.h"
#include "swift/AST/ASTWalker.h"
#include "swift/AST/Module.h"
#include "swift/AST/ProtocolConformance.h"
#include "swift/SIL/SILInstruction.h"
#include "swift/SIL/SILModule.h"
#include "swift/SIL/SILValue.h"

using namespace swift;

namespace {
/// A helper class to collect all nominal type declarations.
class NominalTypeWalker : public ASTWalker {
  ProtocolConformanceAnalysis::ProtocolConformanceMap &ProtocolConformanceCache;

public:
  NominalTypeWalker(ProtocolConformanceAnalysis::ProtocolConformanceMap
                    &ProtocolConformanceCache)
      : ProtocolConformanceCache(ProtocolConformanceCache) {}

  bool walkToDeclPre(Decl *D) override {
    /// (1) Walk over all NominalTypeDecls to determine conformances.
    if (auto *NTD = dyn_cast<NominalTypeDecl>(D)) {
      if (!isa<ProtocolDecl>(NTD)) {
        auto Protocols = NTD->getAllProtocols();
        for (auto &Protocol : Protocols) {
          if (Protocol->getEffectiveAccess() <= AccessLevel::Internal) {
            ProtocolConformanceCache[Protocol].push_back(NTD);
          }
        }
      }
    }
    /// (2) Walk over all ExtensionDecls to determine conformances.
    if (auto *e = dyn_cast<ExtensionDecl>(D)) {
      auto *ntd = e->getExtendedNominal();
      if (ntd && !isa<ProtocolDecl>(ntd)) {
        for (auto *conformance : e->getLocalConformances()) {
          if (isa<NormalProtocolConformance>(conformance)) {
            auto *proto = conformance->getProtocol();
            if (proto->getEffectiveAccess() <= AccessLevel::Internal) {
              ProtocolConformanceCache[proto].push_back(ntd);
            }
          }
        }
      }
    }
    return true;
  }
};
} // end anonymous namespace

void ProtocolConformanceAnalysis::init() {

  // We only do this in Whole-Module compilation mode.
  if (!M->isWholeModule())
    return;

  // Process all types implementing protocols.
  SmallVector<Decl *, 32> Decls;

  // Find all top level declarations.
  M->getSwiftModule()->getTopLevelDecls(Decls);

  /// This operation is quadratic and should only be performed
  /// in whole module compilation!
  NominalTypeWalker Walker(ProtocolConformanceCache);
  for (auto *D : Decls) {
    D->walk(Walker);
  }
}

/// Recursively traverse the conformance lists to determine sole conforming
/// class, struct or enum type.
NominalTypeDecl *
ProtocolConformanceAnalysis::findSoleConformingType(ProtocolDecl *Protocol) {

  /// First check in the SoleConformingTypeCache.
  auto SoleConformingTypeIt = SoleConformingTypeCache.find(Protocol);
  if (SoleConformingTypeIt != SoleConformingTypeCache.end())
    return SoleConformingTypeIt->second;

  SmallVector<ProtocolDecl *, 8> PDWorkList;
  SmallPtrSet<ProtocolDecl *, 8> VisitedPDs;
  NominalTypeDecl *SoleConformingNTD = nullptr;
  PDWorkList.push_back(Protocol);
  while (!PDWorkList.empty()) {
    auto *PD = PDWorkList.pop_back_val();
    // Protocols must have internal or lower access.
    if (PD->getEffectiveAccess() > AccessLevel::Internal) {
      return nullptr;
    }
    VisitedPDs.insert(PD);
    auto NTDList = getConformances(PD);
    for (auto *ConformingNTD : NTDList) {
      // Recurse on protocol types.
      if (auto *Proto = dyn_cast<ProtocolDecl>(ConformingNTD)) {
        // Ignore visited protocol decls.
        if (!VisitedPDs.count(Proto))
          PDWorkList.push_back(Proto);
      } else { // Classes, Structs and Enums are added here.
        // Bail if more than one conforming types were found.
        if (SoleConformingNTD && ConformingNTD != SoleConformingNTD) {
          return nullptr;
        } else {
          SoleConformingNTD = ConformingNTD;
        }
      }
    }
  }

  // Bail if we did not find a sole conforming type.
  if (!SoleConformingNTD)
    return nullptr;

  // Generic declarations are ignored.
  if (SoleConformingNTD->isGenericContext()) {
    return nullptr;
  }

  // Populate SoleConformingTypeCache.
  SoleConformingTypeCache.insert(std::pair<ProtocolDecl *, NominalTypeDecl *>(
      Protocol, SoleConformingNTD));

  // Return SoleConformingNTD.
  return SoleConformingNTD;
}

// Wrapper function to findSoleConformingType that checks for additional
// constraints for classes using ClassHierarchyAnalysis.
bool ProtocolConformanceAnalysis::getSoleConformingType(
    ProtocolDecl *Protocol, ClassHierarchyAnalysis *CHA, CanType &ConcreteType) {
  // Determine the sole conforming type.
  auto *NTD = findSoleConformingType(Protocol);
  if (!NTD)
    return false;

  // Sole conforming class should not be open access or have any derived class.
  ClassDecl *CD;
  if ((CD = dyn_cast<ClassDecl>(NTD)) &&
      (CD->getEffectiveAccess() == AccessLevel::Open ||
       CHA->hasKnownDirectSubclasses(CD))) {
    return false;
  }

  // Save the concrete type.
  ConcreteType = NTD->getDeclaredType()->getCanonicalType();
  return true;
}

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