<commit_before>#include <allegro5/allegro.h>
#include <allegro5/allegro_image.h>

#include <map>
#include <stdexcept>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <string>
#include <vector>

#include "display.h"
#include "dungeon.h"
#include "entity.h"

Display::Display():
    display(NULL),
    tileset(NULL),
    tileset_filename("tileset.png")
{
    init();
}

void Display::init() throw (std::runtime_error)
{
    if(!al_init()) {
        throw std::runtime_error("Failed to initialize allegro.");
    }

    if (!al_init_image_addon()) {
        throw std::runtime_error("Failed to initialize image addon.");
    }

    tileset = al_load_bitmap(tileset_filename.c_str());
    if (!tileset) {
        throw std::runtime_error("Failed to load tileset.");
    }

    display = al_create_display(DISP_WIDTH, DISP_HEIGHT);
    if(!display) {
        throw std::runtime_error("Failed to create display.");
    }

    al_install_keyboard();

    init_tilemap();
}

void Display::init_tilemap()
{
    uint64_t tileset_char_width = 32;
    uint64_t tileset_char_height = 9;
    uint64_t tile_width = 8;
    uint64_t tile_height = 16;

    std::vector<std::string> char_rows = {
        " !\"#$%&'()*+,-./0123456789:;<=>?",
        "@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_",
        "`abcdefghijklmnopqrstuvwxyz{|}~ "
    };
    uint64_t start_row_tileset = 1;

    for (int i = 0; i < char_rows.size(); i++) {
        for (int j = 0; j < tileset_char_width; j++)
        {
            printf("i: %d, j: %d, c: %c\n", i, j, char_rows[i][j]);

            tilemap[char_rows[i][j]] = al_create_sub_bitmap(
                tileset,
                j * tile_width, (start_row_tileset + i) * tile_height,
                8, 16
            );
        }
    }

    tilemap[' '] = al_create_sub_bitmap(tileset, 0, 0, 8, 16);
}

void Display::draw_dungeon(
    int width, int height, int center_x, int center_y,
    const Dungeon* dungeon, const std::vector<const Entity*> entities
) {
    al_clear_to_color(al_map_rgb_f(0, 0, 0));

    al_hold_bitmap_drawing(true);

    int start_y = center_y - (height / 2);
    int start_x = center_x - (width / 2);
    int end_x = center_x + (width / 2);
    int end_y = center_y + (height / 2);

    for (int y = center_y - (height / 2); y < end_y; y++)
    {
        for (int x = start_x; x < end_x; x++)
        {
            ALLEGRO_BITMAP* tile;
            if (
                y >= 0 && y < dungeon->get_height() &&
                x >= 0 && x < dungeon->get_width())
            {
                tile = tilemap[dungeon->entity_at_index(x, y).get_symbol()];
            }
            else
            {
                tile = tilemap[' '];
            }

            al_draw_tinted_bitmap_region(
                tile,
                al_map_rgba(255, 255, 255, 255),
                0, 0,
                8, 16,
                (x - start_x) * 8, (y - start_y) * 16,
                0
            );
        }
    }

    for (auto it = entities.begin(); it != entities.end(); ++it)
    {
        if (
            (*it)->get_x() >= start_x && (*it)->get_x() <= end_x &&
            (*it)->get_y() >= start_y && (*it)->get_y() <= end_y
        ) {
            al_draw_tinted_bitmap_region(
                tilemap[(*it)->get_symbol()],
                al_map_rgba(255, 255, 255, 255),
                0, 0,
                8, 16,
                ((*it)->get_x() - start_x) * 8, ((*it)->get_y() - start_y) * 16,
                0
            );
        }
    }

    al_hold_bitmap_drawing(false);

    al_flip_display();
}

Display::~Display()
{
    for (auto it = tilemap.begin(); it != tilemap.end(); ++it)
    {
        al_destroy_bitmap(it->second);
    }
    al_destroy_bitmap(tileset);
    al_destroy_display(display);
}
<commit_msg>Add some comments<commit_after>#include <allegro5/allegro.h>
#include <allegro5/allegro_image.h>

#include <map>
#include <stdexcept>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <string>
#include <vector>

#include "display.h"
#include "dungeon.h"
#include "entity.h"

Display::Display():
    display(NULL),
    tileset(NULL),
    tileset_filename("tileset.png")
{
    init();
}

void Display::init() throw (std::runtime_error)
{
    if(!al_init()) {
        throw std::runtime_error("Failed to initialize allegro.");
    }

    if (!al_init_image_addon()) {
        throw std::runtime_error("Failed to initialize image addon.");
    }

    tileset = al_load_bitmap(tileset_filename.c_str());
    if (!tileset) {
        throw std::runtime_error("Failed to load tileset.");
    }

    display = al_create_display(DISP_WIDTH, DISP_HEIGHT);
    if(!display) {
        throw std::runtime_error("Failed to create display.");
    }

    al_install_keyboard();

    init_tilemap();
}

void Display::init_tilemap()
{
    uint64_t tileset_char_width = 32;
    uint64_t tileset_char_height = 9;
    uint64_t tile_width = 8;
    uint64_t tile_height = 16;

    // These rows match rows in the current tileset file, with any extraneous
    // spaces being placeholders for special characters.
    std::vector<std::string> char_rows = {
        " !\"#$%&'()*+,-./0123456789:;<=>?",
        "@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_",
        "`abcdefghijklmnopqrstuvwxyz{|}~ "
    };
    uint64_t start_row_tileset = 1;

    for (int i = 0; i < char_rows.size(); i++) {
        for (int j = 0; j < tileset_char_width; j++)
        {
            printf("i: %d, j: %d, c: %c\n", i, j, char_rows[i][j]);

            tilemap[char_rows[i][j]] = al_create_sub_bitmap(
                tileset,
                j * tile_width, (start_row_tileset + i) * tile_height,
                8, 16
            );
        }
    }

    tilemap[' '] = al_create_sub_bitmap(tileset, 0, 0, 8, 16);
}

void Display::draw_dungeon(
    int width, int height, int center_x, int center_y,
    const Dungeon* dungeon, const std::vector<const Entity*> entities
) {
    al_clear_to_color(al_map_rgb_f(0, 0, 0));

    // Defer actually "rendering" any drawing we do until this is disabled.
    // Gives a significant performance boost.
    al_hold_bitmap_drawing(true);

    int start_y = center_y - (height / 2);
    int start_x = center_x - (width / 2);
    int end_x = center_x + (width / 2);
    int end_y = center_y + (height / 2);

    // Draw the designated "window" into the dungeon
    for (int y = center_y - (height / 2); y < end_y; y++)
    {
        for (int x = start_x; x < end_x; x++)
        {
            ALLEGRO_BITMAP* tile;
            if (
                y >= 0 && y < dungeon->get_height() &&
                x >= 0 && x < dungeon->get_width())
            {
                tile = tilemap[dungeon->entity_at_index(x, y).get_symbol()];
            }
            else
            {
                tile = tilemap[' '];
            }

            al_draw_tinted_bitmap_region(
                tile,
                al_map_rgba(255, 255, 255, 255),
                0, 0,
                8, 16,
                (x - start_x) * 8, (y - start_y) * 16,
                0
            );
        }
    }

    // If a given entity shows up within the dungeon display window, draw it
    for (auto it = entities.begin(); it != entities.end(); ++it)
    {
        if (
            (*it)->get_x() >= start_x && (*it)->get_x() <= end_x &&
            (*it)->get_y() >= start_y && (*it)->get_y() <= end_y
        ) {
            al_draw_tinted_bitmap_region(
                tilemap[(*it)->get_symbol()],
                al_map_rgba(255, 255, 255, 255),
                0, 0,
                8, 16,
                ((*it)->get_x() - start_x) * 8, ((*it)->get_y() - start_y) * 16,
                0
            );
        }
    }

    // Re-enable drawing, so that all the work we did above can be batched.
    // We've essentially queued up a bunch of drawing work, to be done all at
    // once.
    al_hold_bitmap_drawing(false);

    al_flip_display();
}

Display::~Display()
{
    for (auto it = tilemap.begin(); it != tilemap.end(); ++it)
    {
        al_destroy_bitmap(it->second);
    }

    al_destroy_bitmap(tileset);
    al_destroy_display(display);
}
<|endoftext|>


<commit_before>/*
 * Copyright (c) 2013 Geocent - Published under the MIT License.
 * See LICENSE for the full text of the license.
 */

#include <string>

#include "HMDDeviceInfo.h"

HMDDeviceInfo::HMDDeviceInfo() {
	memset(this->displayDeviceName, '\0', MAX_DESCRIPTION_LENGTH);
	memset(this->productName, '\0', MAX_DESCRIPTION_LENGTH);
	memset(this->manufacturer, '\0', MAX_DESCRIPTION_LENGTH);
}<commit_msg>Replacement of memset to std::fill<commit_after>/*
 * Copyright (c) 2013 Geocent - Published under the MIT License.
 * See LICENSE for the full text of the license.
 */

#include <algorithm>

#include "HMDDeviceInfo.h"

HMDDeviceInfo::HMDDeviceInfo() {
	std::fill(this->displayDeviceName, this->displayDeviceName + MAX_DESCRIPTION_LENGTH, '\0');
	std::fill(this->productName, this->productName + MAX_DESCRIPTION_LENGTH, '\0');
	std::fill(this->manufacturer, this->manufacturer + MAX_DESCRIPTION_LENGTH, '\0');
}<|endoftext|>


<commit_before><commit_msg>OSL_TRACE: Remove trailing newlines<commit_after><|endoftext|>


<commit_before><commit_msg>coverity#738638 Uninitialized scalar field<commit_after><|endoftext|>


<commit_before>// Copyright 2020 The Pigweed Authors
//
// Licensed under the Apache License, Version 2.0 (the "License"); you may not
// use this file except in compliance with the License. You may obtain a copy of
// the License at
//
//     https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
// License for the specific language governing permissions and limitations under
// the License.

#include "pw_bytes/byte_builder.h"

namespace pw {

ByteBuilder& ByteBuilder::append(size_t count, std::byte b) {
  std::byte* const append_destination = &buffer_[size_];
  std::memset(append_destination, static_cast<int>(b), ResizeForAppend(count));
  return *this;
}

ByteBuilder& ByteBuilder::append(const void* bytes, size_t count) {
  if (count > 0) {
    std::byte* const append_destination = &buffer_[size_];
    std::memcpy(append_destination, bytes, ResizeForAppend(count));
  }
  return *this;
}

size_t ByteBuilder::ResizeForAppend(size_t bytes_to_append) {
  if (!status_.ok()) {
    return 0;
  }

  if (bytes_to_append > max_size() - size()) {
    status_ = Status::ResourceExhausted();
    return 0;
  }

  size_ += bytes_to_append;
  status_ = OkStatus();
  return bytes_to_append;
}

void ByteBuilder::resize(size_t new_size) {
  if (new_size <= size_) {
    size_ = new_size;
    status_ = OkStatus();
  } else {
    status_ = Status::OutOfRange();
  }
}

}  // namespace pw
<commit_msg>pw_bytes: Avoid memcpy to nullptr, even if zero-length<commit_after>// Copyright 2020 The Pigweed Authors
//
// Licensed under the Apache License, Version 2.0 (the "License"); you may not
// use this file except in compliance with the License. You may obtain a copy of
// the License at
//
//     https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
// License for the specific language governing permissions and limitations under
// the License.

#include "pw_bytes/byte_builder.h"

namespace pw {

ByteBuilder& ByteBuilder::append(size_t count, std::byte b) {
  std::byte* const append_destination = buffer_.begin() + size_;
  std::fill_n(append_destination, ResizeForAppend(count), b);
  return *this;
}

ByteBuilder& ByteBuilder::append(const void* bytes, size_t count) {
  std::byte* const append_destination = buffer_.begin() + size_;
  std::copy_n(static_cast<const std::byte*>(bytes),
              ResizeForAppend(count),
              append_destination);
  return *this;
}

size_t ByteBuilder::ResizeForAppend(size_t bytes_to_append) {
  if (!status_.ok()) {
    return 0;
  }

  if (bytes_to_append > max_size() - size()) {
    status_ = Status::ResourceExhausted();
    return 0;
  }

  size_ += bytes_to_append;
  status_ = OkStatus();
  return bytes_to_append;
}

void ByteBuilder::resize(size_t new_size) {
  if (new_size <= size_) {
    size_ = new_size;
    status_ = OkStatus();
  } else {
    status_ = Status::OutOfRange();
  }
}

}  // namespace pw
<|endoftext|>


<commit_before>/*
 *            Copyright 2009-2017 The VOTCA Development Team
 *                       (http://www.votca.org)
 *
 *      Licensed under the Apache License, Version 2.0 (the "License")
 *
 * You may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *              http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 */

#include "gitversion.h"
#include <iostream>
#include <stdexcept>
#include <votca/xtp/checkpoint.h>
namespace votca {
namespace xtp {

namespace hdf5_utils {

H5::DataSpace str_scalar(H5::DataSpace(H5S_SCALAR));

// inline H5::DataSpace StrScalar() { return H5::DataSpace(H5S_SCALAR); }

void WriteScalarAttribute(const H5::H5Location& obj, const std::string& value,
                          const std::string& name) {

  hsize_t dims[1] = {1};
  H5::DataSpace dp(1, dims);
  const H5::DataType* strType = InferDataType<std::string>::get();

  H5::Attribute attr = obj.createAttribute(name, *strType, StrScalar());

  attr.write(*strType, value);
}
}  // namespace hdf5_utils

using namespace hdf5_utils;

CheckpointFile::CheckpointFile(std::string fN)
    : _fileName(fN), _version(gitversion) {

  try {
    H5::Exception::dontPrint();
    _fileHandle = H5::H5File(_fileName, H5F_ACC_TRUNC);

    WriteScalarAttribute(_fileHandle, gitversion, "Version");

  } catch (H5::Exception& error) {
    error.printError();
    throw std::runtime_error(error.getDetailMsg());
  }
};

std::string CheckpointFile::getFileName() { return _fileName; };
std::string CheckpointFile::getVersion() { return _version; };

H5::H5File CheckpointFile::getHandle() { return _fileHandle; };

}  // namespace xtp
}  // namespace votca
<commit_msg>Delete unnecessary code<commit_after>/*
 *            Copyright 2009-2017 The VOTCA Development Team
 *                       (http://www.votca.org)
 *
 *      Licensed under the Apache License, Version 2.0 (the "License")
 *
 * You may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *              http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 */

#include "gitversion.h"
#include <iostream>
#include <stdexcept>
#include <votca/xtp/checkpoint.h>
namespace votca {
namespace xtp {

namespace hdf5_utils {

H5::DataSpace str_scalar(H5::DataSpace(H5S_SCALAR));

void WriteScalarAttribute(const H5::H5Location& obj, const std::string& value,
                          const std::string& name) {

  hsize_t dims[1] = {1};
  H5::DataSpace dp(1, dims);
  const H5::DataType* strType = InferDataType<std::string>::get();

  H5::Attribute attr = obj.createAttribute(name, *strType, StrScalar());

  attr.write(*strType, value);
}
}  // namespace hdf5_utils

using namespace hdf5_utils;

CheckpointFile::CheckpointFile(std::string fN)
    : _fileName(fN), _version(gitversion) {

  try {
    H5::Exception::dontPrint();
    _fileHandle = H5::H5File(_fileName, H5F_ACC_TRUNC);

    WriteScalarAttribute(_fileHandle, gitversion, "Version");

  } catch (H5::Exception& error) {
    error.printError();
    throw std::runtime_error(error.getDetailMsg());
  }
};

std::string CheckpointFile::getFileName() { return _fileName; };
std::string CheckpointFile::getVersion() { return _version; };

H5::H5File CheckpointFile::getHandle() { return _fileHandle; };

}  // namespace xtp
}  // namespace votca
<|endoftext|>


<commit_before>
/// \author James Hughes
/// \date   November 2013

#ifndef IAUNS_SPIREFIXTURE_HPP
#define IAUNS_SPIREFIXTURE_HPP

class SpireContext : public CPM_SPIRE_NS::Context
{
public:
  SpireContext(std::shared_ptr<CPM_GL_BATCH_ENV_NS::BatchEnvironment> env);

  void makeCurrent() override;
  void swapBuffers() override;

private:
  std::shared_ptr<CPM_GL_BATCH_ENV_NS::BatchEnvironment> mEnv;
};

class SpireTestFixture : public testing::Test
{
public:
  InterfaceTestFixture () {}

  virtual void SetUp() override
  {
    std::vector<std::string> shaderSearchDirs;
    shaderSearchDirs.push_back("shaders");

    // Build spire using the context from GlobalTestEnvironment.
    std::shared_ptr<spire::Context> ctx = GlobalTestEnvironment::instance()->getContext();
    ctx->makeCurrent();
    mSpire = std::shared_ptr<spire::Interface>(new spire::Interface(
        ctx, shaderSearchDirs));

    // Add default attributes.
    addDefaultAttributes();

    // Build camera that we will use for testing purposes.
    mCamera = std::unique_ptr<TestCamera>(new TestCamera);
  }

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

  void addDefaultAttributes()
  {
    mSpire->addShaderAttribute("aPos",         3,  false,  sizeof(float) * 3,  spire::Interface::TYPE_FLOAT);
    mSpire->addShaderAttribute("aNormal",      3,  false,  sizeof(float) * 3,  spire::Interface::TYPE_FLOAT);
    mSpire->addShaderAttribute("aColorFloat",  4,  false,  sizeof(float) * 4,  spire::Interface::TYPE_FLOAT);
    mSpire->addShaderAttribute("aColor",       4,  true,   sizeof(char) * 4,   spire::Interface::TYPE_UBYTE);

    // Used to test attribute mis-alignment.
    mSpire->addShaderAttribute("aFieldData",   1,  false,  sizeof(float) * 1,  spire::Interface::TYPE_FLOAT);
  }

  std::shared_ptr<spire::Interface>     mSpire;
  std::unique_ptr<TestCamera>           mCamera;
};

#endif
<commit_msg>Updating spire namespace.<commit_after>
/// \author James Hughes
/// \date   November 2013

#ifndef IAUNS_SPIREFIXTURE_HPP
#define IAUNS_SPIREFIXTURE_HPP

class SpireContext : public CPM_SPIRE_NS::Context
{
public:
  SpireContext(std::shared_ptr<CPM_GL_BATCH_ENV_NS::BatchEnvironment> env);

  void makeCurrent() override;
  void swapBuffers() override;

private:
  std::shared_ptr<CPM_GL_BATCH_ENV_NS::BatchEnvironment> mEnv;
};

class SpireTestFixture : public testing::Test
{
public:
  InterfaceTestFixture() {}

  virtual void SetUp() override
  {
    std::vector<std::string> shaderSearchDirs;
    shaderSearchDirs.push_back("shaders");

    // Build spire using the context from GlobalTestEnvironment.
    std::shared_ptr<CPM_GL_BATCH_ENV_NS::BatchEnvironment> ctx
        = GlobalTestEnvironment::instance()->getBatchEnvironment();

    mSpireContext = std::shared_ptr<SpireContext>(ctx);

    ctx->makeCurrent();
    mSpire = std::shared_ptr<CPM_SPIRE_NS::Interface>(
        new CPM_SPIRE_NS::Interface(mSpireContext, shaderSearchDirs));

    // Add default attributes.
    addDefaultAttributes();

    // Build camera that we will use for testing purposes.
    mCamera = std::unique_ptr<TestCamera>(new TestCamera);
  }

  virtual void TearDown() override
  {
    mSpire.reset();
    mSpireContext.reset();
  }

  void addDefaultAttributes()
  {
    mSpire->addShaderAttribute("aPos",         3,  false,  sizeof(float) * 3,  CPM_SPIRE_NS::Interface::TYPE_FLOAT);
    mSpire->addShaderAttribute("aNormal",      3,  false,  sizeof(float) * 3,  CPM_SPIRE_NS::Interface::TYPE_FLOAT);
    mSpire->addShaderAttribute("aColorFloat",  4,  false,  sizeof(float) * 4,  CPM_SPIRE_NS::Interface::TYPE_FLOAT);
    mSpire->addShaderAttribute("aColor",       4,  true,   sizeof(char) * 4,   CPM_SPIRE_NS::Interface::TYPE_UBYTE);

    // Used to test attribute mis-alignment.
    mSpire->addShaderAttribute("aFieldData",   1,  false,  sizeof(float) * 1,  CPM_SPIRE_NS::Interface::TYPE_FLOAT);
  }

  std::shared_ptr<CPM_SPIRE_NS::Interface>    mSpire;
  std::unique_ptr<TestCamera>                 mCamera;

private:

  std::shared_ptr<SpireContext>         mSpireContext;
};

#endif
<|endoftext|>


<commit_before>/* Copyright 2009 Klarälvdalens Datakonsult AB

   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 2 of
   the License or (at your option) version 3 or any later version
   accepted by the membership of KDE e.V. (or its successor approved
   by the membership of KDE e.V.), which shall act as a proxy
   defined in Section 14 of version 3 of the license.

   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU General Public License for more details.

   You should have received a copy of the GNU General Public License
   along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/
#include "archivefolderdialog.h"

#include "backupjob.h"
#include "kmkernel.h"
#include "kmfolder.h"
#include "kmmainwidget.h"
#include "folderrequester.h"

#include <klocale.h>
#include <kcombobox.h>
#include <kurlrequester.h>
#include <kmessagebox.h>

#include <qlabel.h>
#include <qcheckbox.h>
#include <qlayout.h>

using namespace KMail;

static QString standardArchivePath( const QString &folderName )
{
  return KGlobalSettings::documentPath() +
    i18nc( "Start of the filename for a mail archive file" , "Archive" ) + '_' + folderName + '_' + QDate::currentDate().toString( Qt::ISODate ) + ".zip";
}

ArchiveFolderDialog::ArchiveFolderDialog( QWidget *parent )
  : KDialog( parent ), mParentWidget( parent )
{
  setObjectName( "archive_folder_dialog" );
  setCaption( i18n( "Archive Folder" ) );
  setButtons( Ok|Cancel );
  setDefaultButton( Ok );
  setModal( true );
  QWidget *mainWidget = new QWidget( this );
  QGridLayout *mainLayout = new QGridLayout( mainWidget );
  mainLayout->setSpacing( KDialog::spacingHint() );
  mainLayout->setMargin( KDialog::marginHint() );
  setMainWidget( mainWidget );

  int row = 0;

  // TODO: better label for "Ok" button
  // TODO: Explaination label
  // TODO: Use QFormLayout in KDE4

  QLabel *folderLabel = new QLabel( i18n( "Folder:" ), mainWidget );
  mainLayout->addWidget( folderLabel, row, 0 );
  mFolderRequester = new FolderRequester( mainWidget );
  mFolderRequester->setFolderTree( kmkernel->getKMMainWidget()->mainFolderView() );
  mainLayout->addWidget( mFolderRequester, row, 1 );
  row++;

  QLabel *formatLabel = new QLabel( i18n( "Format:" ), mainWidget );
  mainLayout->addWidget( formatLabel, row, 0 );
  mFormatComboBox = new KComboBox( mainWidget );

  // These combobox values have to stay in sync with the ArchiveType enum from BackupJob!
  mFormatComboBox->addItem( i18n( "Compressed Zip Archive (.zip)" ) );
  mFormatComboBox->addItem( i18n( "Uncompressed Archive (.tar)" ) );
  mFormatComboBox->addItem( i18n( "BZ2-Compressed Tar Archive (.tar.bz2)" ) );
  mFormatComboBox->addItem( i18n( "GZ-Compressed Tar Archive (.tar.gz)" ) );
  mFormatComboBox->setCurrentItem( 0 );
  connect( mFormatComboBox, SIGNAL(activated(int)),
           this, SLOT(slotFixFileExtension()) );
  mainLayout->addWidget( mFormatComboBox, row, 1 );
  row++;

  QLabel *fileNameLabel = new QLabel( i18n( "Archive File:" ), mainWidget );
  mainLayout->addWidget( fileNameLabel, row, 0 );
  mUrlRequester = new KUrlRequester( mainWidget );
  mUrlRequester->setMode( KFile::LocalOnly );
  mUrlRequester->setFilter( "*.tar *.zip *.tar.gz *.tar.bz2" );
  connect( mUrlRequester, SIGNAL(urlSelected(const QString&)),
           this, SLOT(slotFixFileExtension()) );
  mainLayout->addWidget( mUrlRequester, row, 1 );
  row++;

  // TODO: Make this appear more dangerous!
  mDeleteCheckBox = new QCheckBox( i18n( "Delete folders after completion" ), mainWidget );
  mainLayout->addWidget( mDeleteCheckBox, row, 0, 1, 2, Qt::AlignLeft );
  row++;

  // TODO: what's this, tooltips

  // TODO: Warn that user should do mail check for online IMAP and possibly cached IMAP as well

  mainLayout->setColumnStretch( 1, 1 );
  mainLayout->addItem( new QSpacerItem( 1, 1, QSizePolicy::Expanding, QSizePolicy::Expanding ), row, 0 );

  // Make it a bit bigger, else the folder requester cuts off the text too early
  resize( 500, minimumSize().height() );
}

void ArchiveFolderDialog::setFolder( KMFolder *defaultFolder )
{
  mFolderRequester->setFolder( defaultFolder );
  // TODO: what if the file already exists?
  mUrlRequester->setUrl( standardArchivePath( defaultFolder->name() ) );
}

void ArchiveFolderDialog::slotOk()
{
  if ( QFile::exists( mUrlRequester->url().path() ) ) {
    if ( KMessageBox::questionYesNo( this, i18n( "The specified file already exists. Do you want to overwrite it?" ),
                                     i18n( "File already exists" ), KGuiItem( i18n( "Overwrite" ) ),
                                      KGuiItem( i18n( "Cancel" ) ) ) != KMessageBox::Yes ) {
      return;
    }

    // TODO: Check if overwriting actually works!
  }

  if ( !mFolderRequester->folder() ) {
    KMessageBox::information( this, i18n( "Please select the folder that should be archived." ),
                              i18n( "No folder selected" ) );
    return;
  }

  // TODO: check if url is empty. or better yet, disable ok button until file is chosen
  KMail::BackupJob *backupJob = new KMail::BackupJob( mParentWidget );
  backupJob->setRootFolder( mFolderRequester->folder() );
  backupJob->setSaveLocation( mUrlRequester->url() );
  backupJob->setArchiveType( static_cast<BackupJob::ArchiveType>( mFormatComboBox->currentIndex() ) );
  backupJob->setDeleteFoldersAfterCompletion( mDeleteCheckBox->isChecked() );
  backupJob->start();
  accept();
}

void ArchiveFolderDialog::slotFixFileExtension()
{
  // KDE4: use KMimeType::extractKnownExtension() here
  const int numExtensions = 4;

  // These extensions are sorted differently, .tar has to come last, or it will match before giving
  // the more specific ones time to match.
  const char *sortedExtensions[numExtensions] = { ".zip", ".tar.bz2", ".tar.gz", ".tar" };

  // The extensions here are also sorted, like the enum order of BackupJob::ArchiveType
  const char *extensions[numExtensions] = { ".zip", ".tar", ".tar.bz2", ".tar.gz" };

  QString fileName = mUrlRequester->url().path();

  // First, try to find the extension of the file name and remove it
  for( int i = 0; i < numExtensions; i++ ) {
    int index = fileName.toLower().lastIndexOf( sortedExtensions[i] );
    if ( index != -1 ) {
      fileName = fileName.left( fileName.length() - QString( sortedExtensions[i] ).length() );
      break;
    }
  }

  // Now, we've got a filename without an extension, simply append the correct one
  fileName += extensions[mFormatComboBox->currentIndex()];
  mUrlRequester->setUrl( fileName );
}

#include "archivefolderdialog.moc"
<commit_msg>SVN_MERGE Merged revisions 1048508 via svnmerge from  svn+ssh://tmcguire@svn.kde.org/home/kde/branches/kdepim/enterprise4/kdepim<commit_after>/* Copyright 2009 Klarälvdalens Datakonsult AB

   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 2 of
   the License or (at your option) version 3 or any later version
   accepted by the membership of KDE e.V. (or its successor approved
   by the membership of KDE e.V.), which shall act as a proxy
   defined in Section 14 of version 3 of the license.

   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU General Public License for more details.

   You should have received a copy of the GNU General Public License
   along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/
#include "archivefolderdialog.h"

#include "backupjob.h"
#include "kmkernel.h"
#include "kmfolder.h"
#include "kmmainwidget.h"
#include "folderrequester.h"

#include <klocale.h>
#include <kcombobox.h>
#include <kurlrequester.h>
#include <kmessagebox.h>

#include <qlabel.h>
#include <qcheckbox.h>
#include <qlayout.h>

using namespace KMail;

static QString standardArchivePath( const QString &folderName )
{
  return KGlobalSettings::documentPath() +
    i18nc( "Start of the filename for a mail archive file" , "Archive" ) + '_' + folderName + '_' + QDate::currentDate().toString( Qt::ISODate ) + ".zip";
}

ArchiveFolderDialog::ArchiveFolderDialog( QWidget *parent )
  : KDialog( parent ), mParentWidget( parent )
{
  setObjectName( "archive_folder_dialog" );
  setCaption( i18n( "Archive Folder" ) );
  setButtons( Ok|Cancel );
  setDefaultButton( Ok );
  setModal( true );
  QWidget *mainWidget = new QWidget( this );
  QGridLayout *mainLayout = new QGridLayout( mainWidget );
  mainLayout->setSpacing( KDialog::spacingHint() );
  mainLayout->setMargin( KDialog::marginHint() );
  setMainWidget( mainWidget );

  int row = 0;

  // TODO: better label for "Ok" button
  // TODO: Explaination label
  // TODO: Use QFormLayout in KDE4

  QLabel *folderLabel = new QLabel( i18n( "Folder:" ), mainWidget );
  mainLayout->addWidget( folderLabel, row, 0 );
  mFolderRequester = new FolderRequester( mainWidget );
  mFolderRequester->setFolderTree( kmkernel->getKMMainWidget()->mainFolderView() );
  mainLayout->addWidget( mFolderRequester, row, 1 );
  row++;

  QLabel *formatLabel = new QLabel( i18n( "Format:" ), mainWidget );
  mainLayout->addWidget( formatLabel, row, 0 );
  mFormatComboBox = new KComboBox( mainWidget );

  // These combobox values have to stay in sync with the ArchiveType enum from BackupJob!
  mFormatComboBox->addItem( i18n( "Compressed Zip Archive (.zip)" ) );
  mFormatComboBox->addItem( i18n( "Uncompressed Archive (.tar)" ) );
  mFormatComboBox->addItem( i18n( "BZ2-Compressed Tar Archive (.tar.bz2)" ) );
  mFormatComboBox->addItem( i18n( "GZ-Compressed Tar Archive (.tar.gz)" ) );
  mFormatComboBox->setCurrentIndex( 0 );
  connect( mFormatComboBox, SIGNAL(activated(int)),
           this, SLOT(slotFixFileExtension()) );
  mainLayout->addWidget( mFormatComboBox, row, 1 );
  row++;

  QLabel *fileNameLabel = new QLabel( i18n( "Archive File:" ), mainWidget );
  mainLayout->addWidget( fileNameLabel, row, 0 );
  mUrlRequester = new KUrlRequester( mainWidget );
  mUrlRequester->setMode( KFile::LocalOnly );
  mUrlRequester->setFilter( "*.tar *.zip *.tar.gz *.tar.bz2" );
  connect( mUrlRequester, SIGNAL(urlSelected(const QString&)),
           this, SLOT(slotFixFileExtension()) );
  mainLayout->addWidget( mUrlRequester, row, 1 );
  row++;

  // TODO: Make this appear more dangerous!
  mDeleteCheckBox = new QCheckBox( i18n( "Delete folders after completion" ), mainWidget );
  mainLayout->addWidget( mDeleteCheckBox, row, 0, 1, 2, Qt::AlignLeft );
  row++;

  // TODO: what's this, tooltips

  // TODO: Warn that user should do mail check for online IMAP and possibly cached IMAP as well

  mainLayout->setColumnStretch( 1, 1 );
  mainLayout->addItem( new QSpacerItem( 1, 1, QSizePolicy::Expanding, QSizePolicy::Expanding ), row, 0 );

  // Make it a bit bigger, else the folder requester cuts off the text too early
  resize( 500, minimumSize().height() );
}

void ArchiveFolderDialog::setFolder( KMFolder *defaultFolder )
{
  mFolderRequester->setFolder( defaultFolder );
  // TODO: what if the file already exists?
  mUrlRequester->setUrl( standardArchivePath( defaultFolder->name() ) );
}

void ArchiveFolderDialog::slotOk()
{
  if ( QFile::exists( mUrlRequester->url().path() ) ) {
    if ( KMessageBox::questionYesNo( this, i18n( "The specified file already exists. Do you want to overwrite it?" ),
                                     i18n( "File already exists" ), KGuiItem( i18n( "Overwrite" ) ),
                                      KGuiItem( i18n( "Cancel" ) ) ) != KMessageBox::Yes ) {
      return;
    }

    // TODO: Check if overwriting actually works!
  }

  if ( !mFolderRequester->folder() ) {
    KMessageBox::information( this, i18n( "Please select the folder that should be archived." ),
                              i18n( "No folder selected" ) );
    return;
  }

  // TODO: check if url is empty. or better yet, disable ok button until file is chosen
  KMail::BackupJob *backupJob = new KMail::BackupJob( mParentWidget );
  backupJob->setRootFolder( mFolderRequester->folder() );
  backupJob->setSaveLocation( mUrlRequester->url() );
  backupJob->setArchiveType( static_cast<BackupJob::ArchiveType>( mFormatComboBox->currentIndex() ) );
  backupJob->setDeleteFoldersAfterCompletion( mDeleteCheckBox->isChecked() );
  backupJob->start();
  accept();
}

void ArchiveFolderDialog::slotFixFileExtension()
{
  // KDE4: use KMimeType::extractKnownExtension() here
  const int numExtensions = 4;

  // These extensions are sorted differently, .tar has to come last, or it will match before giving
  // the more specific ones time to match.
  const char *sortedExtensions[numExtensions] = { ".zip", ".tar.bz2", ".tar.gz", ".tar" };

  // The extensions here are also sorted, like the enum order of BackupJob::ArchiveType
  const char *extensions[numExtensions] = { ".zip", ".tar", ".tar.bz2", ".tar.gz" };

  QString fileName = mUrlRequester->url().path();

  // First, try to find the extension of the file name and remove it
  for( int i = 0; i < numExtensions; i++ ) {
    int index = fileName.toLower().lastIndexOf( sortedExtensions[i] );
    if ( index != -1 ) {
      fileName = fileName.left( fileName.length() - QString( sortedExtensions[i] ).length() );
      break;
    }
  }

  // Now, we've got a filename without an extension, simply append the correct one
  fileName += extensions[mFormatComboBox->currentIndex()];
  mUrlRequester->setUrl( fileName );
}

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


<commit_before>/*
 * Copyright (c) 2008-2018 the MRtrix3 contributors.
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, you can obtain one at http://mozilla.org/MPL/2.0/
 *
 * MRtrix3 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.
 *
 * For more details, see http://www.mrtrix.org/
 */

#include "stride.h"
#include "header.h"

namespace MR
{

  namespace Stride
  {

    using namespace App;

    const OptionGroup Options = OptionGroup ("Stride options")
      + Option ("strides",
          "specify the strides of the output data in memory; either "
          "as a comma-separated list of (signed) integers, or "
          "as a template image from which the strides shall be extracted and used. "
          "The actual strides produced will depend on whether the output image "
          "format can support it.")
      + Argument ("spec").type_text();

    List& sanitise (List& current, const List& desired, const vector<ssize_t>& dims)
    {
      // remove duplicates
      for (size_t i = 0; i < current.size()-1; ++i) {
        if (dims[i] == 1) current[i] = 0;
        if (!current[i]) continue;
        for (size_t j = i+1; j < current.size(); ++j) {
          if (!current[j]) continue;
          if (std::abs (current[i]) == std::abs (current[j]))
            current[j] = 0;
        }
      }

      ssize_t desired_max = 0;
      for (size_t i = 0; i < desired.size(); ++i)
        if (std::abs (desired[i]) > desired_max)
          desired_max = std::abs (desired[i]);

      ssize_t in_max = 0;
      for (size_t i = 0; i < current.size(); ++i)
        if (std::abs (current[i]) > in_max)
          in_max = std::abs (current[i]);
      in_max += desired_max + 1;

      for (size_t i = 0; i < current.size(); ++i)
        if (dims[i] > 1 && desired[i])
          current[i] = desired[i];
        else if (current[i])
          current[i] += current[i] < 0 ? -desired_max : desired_max;
        else
          current[i] = in_max++;

      symbolise (current);
      return current;
    }

    List __from_command_line (const List& current)
    {
      List strides;
      auto opt = App::get_options ("strides");
      if (!opt.size())
        return strides;

      try {
        auto header = Header::open (std::string(opt[0][0]));
        strides = get_symbolic (header);
      }
      catch (Exception& E) {
        E.display (3);
        try {
          auto tmp = parse_ints (opt[0][0]);
          for (auto x : tmp)
            strides.push_back (x);
        }
        catch (Exception& E) {
          E.display(3);
          throw Exception ("argument \"" + std::string(opt[0][0]) + "\" to option \"-strides\" is not a list of strides or an image");
        }
      }

      if (strides.size() > current.size())
        WARN ("too many axes supplied to -strides option - ignoring remaining strides");
      strides.resize (current.size(), 0);

      for (const auto x : strides)
        if (std::abs(x) > int (current.size()))
          throw Exception ("strides specified exceed image dimensions: got " + str(opt[0][0]) + ", but image has " + str(current.size()) + " axes");

      for (size_t i = 0; i < strides.size()-1; ++i) {
        if (!strides[1]) continue;
        for (size_t j = i+1; j < strides.size(); ++j)
          if (std::abs (strides[i]) == std::abs (strides[j]))
            throw Exception ("duplicate entries provided to \"-strides\" option: " + str(opt[0][0]));
      }

      List prev = get_symbolic (current);

      for (size_t i = 0; i < strides.size(); ++i)
        if (strides[i] != 0)
          prev[i] = 0;

      prev = get_symbolic (prev);
      ssize_t max_remaining = 0;
      for (const auto x : prev)
        if (std::abs(x) > max_remaining)
          max_remaining = std::abs(x);

      struct FindStride { NOMEMALIGN
        FindStride (List::value_type value) : x (std::abs(value)) { }
        bool operator() (List::value_type a) { return std::abs (a) == x; }
        const List::value_type x;
      };

      ssize_t next_avail = 0;
      for (ssize_t next = 1; next <= max_remaining; ++next) {
        auto p = std::find_if (prev.begin(), prev.end(), FindStride (next));
        assert (p != prev.end());
        List::value_type s;
        while (1) {
          s = *p + ( *p > 0 ? next_avail : -next_avail );
          if (std::find_if (strides.begin(), strides.end(), FindStride (s)) == strides.end())
            break;
          ++next_avail;
        }
        strides[std::distance (prev.begin(), p)] = s;
      }

      return strides;
    }

  }
}

<commit_msg>Stride::Option: Define as type_various()<commit_after>/*
 * Copyright (c) 2008-2018 the MRtrix3 contributors.
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, you can obtain one at http://mozilla.org/MPL/2.0/
 *
 * MRtrix3 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.
 *
 * For more details, see http://www.mrtrix.org/
 */

#include "stride.h"
#include "header.h"

namespace MR
{

  namespace Stride
  {

    using namespace App;

    const OptionGroup Options = OptionGroup ("Stride options")
      + Option ("strides",
          "specify the strides of the output data in memory; either "
          "as a comma-separated list of (signed) integers, or "
          "as a template image from which the strides shall be extracted and used. "
          "The actual strides produced will depend on whether the output image "
          "format can support it.")
      + Argument ("spec").type_various();

    List& sanitise (List& current, const List& desired, const vector<ssize_t>& dims)
    {
      // remove duplicates
      for (size_t i = 0; i < current.size()-1; ++i) {
        if (dims[i] == 1) current[i] = 0;
        if (!current[i]) continue;
        for (size_t j = i+1; j < current.size(); ++j) {
          if (!current[j]) continue;
          if (std::abs (current[i]) == std::abs (current[j]))
            current[j] = 0;
        }
      }

      ssize_t desired_max = 0;
      for (size_t i = 0; i < desired.size(); ++i)
        if (std::abs (desired[i]) > desired_max)
          desired_max = std::abs (desired[i]);

      ssize_t in_max = 0;
      for (size_t i = 0; i < current.size(); ++i)
        if (std::abs (current[i]) > in_max)
          in_max = std::abs (current[i]);
      in_max += desired_max + 1;

      for (size_t i = 0; i < current.size(); ++i)
        if (dims[i] > 1 && desired[i])
          current[i] = desired[i];
        else if (current[i])
          current[i] += current[i] < 0 ? -desired_max : desired_max;
        else
          current[i] = in_max++;

      symbolise (current);
      return current;
    }

    List __from_command_line (const List& current)
    {
      List strides;
      auto opt = App::get_options ("strides");
      if (!opt.size())
        return strides;

      try {
        auto header = Header::open (std::string(opt[0][0]));
        strides = get_symbolic (header);
      }
      catch (Exception& E) {
        E.display (3);
        try {
          auto tmp = parse_ints (opt[0][0]);
          for (auto x : tmp)
            strides.push_back (x);
        }
        catch (Exception& E) {
          E.display(3);
          throw Exception ("argument \"" + std::string(opt[0][0]) + "\" to option \"-strides\" is not a list of strides or an image");
        }
      }

      if (strides.size() > current.size())
        WARN ("too many axes supplied to -strides option - ignoring remaining strides");
      strides.resize (current.size(), 0);

      for (const auto x : strides)
        if (std::abs(x) > int (current.size()))
          throw Exception ("strides specified exceed image dimensions: got " + str(opt[0][0]) + ", but image has " + str(current.size()) + " axes");

      for (size_t i = 0; i < strides.size()-1; ++i) {
        if (!strides[1]) continue;
        for (size_t j = i+1; j < strides.size(); ++j)
          if (std::abs (strides[i]) == std::abs (strides[j]))
            throw Exception ("duplicate entries provided to \"-strides\" option: " + str(opt[0][0]));
      }

      List prev = get_symbolic (current);

      for (size_t i = 0; i < strides.size(); ++i)
        if (strides[i] != 0)
          prev[i] = 0;

      prev = get_symbolic (prev);
      ssize_t max_remaining = 0;
      for (const auto x : prev)
        if (std::abs(x) > max_remaining)
          max_remaining = std::abs(x);

      struct FindStride { NOMEMALIGN
        FindStride (List::value_type value) : x (std::abs(value)) { }
        bool operator() (List::value_type a) { return std::abs (a) == x; }
        const List::value_type x;
      };

      ssize_t next_avail = 0;
      for (ssize_t next = 1; next <= max_remaining; ++next) {
        auto p = std::find_if (prev.begin(), prev.end(), FindStride (next));
        assert (p != prev.end());
        List::value_type s;
        while (1) {
          s = *p + ( *p > 0 ? next_avail : -next_avail );
          if (std::find_if (strides.begin(), strides.end(), FindStride (s)) == strides.end())
            break;
          ++next_avail;
        }
        strides[std::distance (prev.begin(), p)] = s;
      }

      return strides;
    }

  }
}

<|endoftext|>


<commit_before>#include <iostream>
#include <string>
#include <vector>
#include <tuple>

#include "acmacs-base/argv.hh"
#include "acmacs-base/filesystem.hh"
#include "acmacs-base/named-type.hh"
#include "acmacs-base/string.hh"
#include "acmacs-chart-2/factory-import.hh"
#include "acmacs-chart-2/chart.hh"

// ----------------------------------------------------------------------

class SerumIds
{
 public:
    using Name = acmacs::chart::Name;
    using Passage = acmacs::chart::Passage;
    using Reassortant = acmacs::chart::Reassortant;
    using Annotations = acmacs::chart::Annotations;
    using SerumId = acmacs::chart::SerumId;
    using SerumIdRoot = acmacs::named_t<std::string, struct SerumIdRootTag>;
    using SerumEntry = std::tuple<Name, Reassortant, Annotations, SerumId, Passage>;
    using TableEntry = std::tuple<acmacs::chart::VirusType, acmacs::chart::Lab, acmacs::chart::Assay, acmacs::chart::RbcSpecies, acmacs::chart::TableDate>;
    using Entry = std::tuple<SerumIdRoot, SerumId, Name, Reassortant, Annotations, acmacs::chart::VirusType, acmacs::chart::Lab, acmacs::chart::Assay, acmacs::chart::RbcSpecies, acmacs::chart::TableDate, Passage>;
    using Entries = std::vector<Entry>;
    using EntryPtr = typename Entries::const_iterator;
    using PerSerumIdEntry = std::tuple<EntryPtr, EntryPtr>;
    using PerSerumIdRootEntry = std::tuple<EntryPtr, EntryPtr, std::vector<PerSerumIdEntry>>;
    using PerSerumIdRootEntries = std::vector<PerSerumIdRootEntry>;

    SerumIds() = default;

    size_t size() const { return data_.size(); }
    void sort() { std::sort(data_.begin(), data_.end()); /* data_.erase(std::unique(data_.begin(), data_.end()), data_.end()); */ }

    void add(const SerumEntry& serum, const TableEntry& table)
        {
            data_.emplace_back(serum_id_root(serum, table), std::get<SerumId>(serum),
                               std::get<Name>(serum), std::get<Reassortant>(serum), std::get<Annotations>(serum),
                               std::get<acmacs::chart::VirusType>(table), std::get<acmacs::chart::Lab>(table), std::get<acmacs::chart::Assay>(table), std::get<acmacs::chart::RbcSpecies>(table), std::get<acmacs::chart::TableDate>(table),
                               std::get<Passage>(serum));
        }

    void scan()
        {
            for (EntryPtr entry_ptr = data_.begin(); entry_ptr != data_.end(); ++entry_ptr) {
                if (per_root_.empty() || std::get<SerumIdRoot>(*entry_ptr) !=  std::get<SerumIdRoot>(*std::get<0>(per_root_.back()))) {
                    per_root_.emplace_back(entry_ptr, entry_ptr + 1, std::vector<PerSerumIdEntry>{{entry_ptr, entry_ptr + 1}});
                }
                else {
                    std::get<1>(per_root_.back()) = entry_ptr + 1;
                    const auto last = std::get<0>(std::get<2>(per_root_.back()).back());
                    const auto name = make_name(entry_ptr), name_last = make_name(last);
                    if (std::get<SerumId>(*entry_ptr) != std::get<SerumId>(*last) || name != name_last) {
                        std::get<2>(per_root_.back()).emplace_back(entry_ptr, entry_ptr + 1);
                    }
                    else {
                        std::get<1>(std::get<2>(per_root_.back()).back()) = entry_ptr + 1;
                    }
                }
            }
            std::cout << "per_root_ " << per_root_.size() << '\n';
        }

        void print(bool print_good) const
        {
            const bool show_assay = std::get<acmacs::chart::VirusType>(*std::get<0>(per_root_.front())) == "A(H3N2)";
            const bool show_rbc = show_assay;
            for (const auto& per_root_entry : per_root_) {
                const auto name = make_name(std::get<0>(per_root_entry)), name_last = make_name(std::get<1>(per_root_entry) - 1);
                if (const bool good = std::get<2>(per_root_entry).size() == 1; !good || print_good) {
                    std::cout << std::get<SerumIdRoot>(*std::get<0>(per_root_entry)) << ' ' << (std::get<1>(per_root_entry) - std::get<0>(per_root_entry)) << '\n';
                    for (const auto& per_serum_id_entry : std::get<2>(per_root_entry)) {
                        const auto tabs = tables(std::get<0>(per_serum_id_entry), std::get<1>(per_serum_id_entry), show_assay, show_rbc);
                        std::cout << "    " << std::get<SerumId>(*std::get<0>(per_serum_id_entry)) << ' ' << tabs.size()
                                  << " [" << make_name(std::get<0>(per_serum_id_entry)) << ']';
                        for (const auto& table : tabs)
                            std::cout << ' ' << table;
                        std::cout << '\n';
                    }
                    if (!good) {
                        const auto& sids = std::get<2>(per_root_entry);
                        if (std::get<SerumId>(*std::get<0>(sids.front())) != std::get<SerumId>(*std::get<0>(sids.back()))) {
                            const auto sid = std::max_element(sids.begin(), sids.end(), [](const auto& e1, const auto& e2) -> bool { return (std::get<1>(e1) - std::get<0>(e1)) <  (std::get<1>(e2) - std::get<0>(e2)); });
                            for (auto ep = sids.begin(); ep != sids.end(); ++ep) {
                                if (ep != sid) {
                                    const bool same_size = (std::get<1>(*ep) - std::get<0>(*ep)) == (std::get<1>(*sid) - std::get<0>(*sid));
                                    std::cout << "    " << (same_size ? "?? " : "") << "--fix " << std::get<SerumId>(*std::get<0>(*ep)) << '^' << std::get<SerumId>(*std::get<0>(*sid)) << '\n';
                                }
                            }
                        }
                    }
                }
            }
        }

 private:
    Entries data_;
    PerSerumIdRootEntries per_root_;

    SerumIdRoot serum_id_root(const SerumEntry& serum, const TableEntry& table) const
        {
            const auto& serum_id = std::get<SerumId>(serum);
            if (std::get<acmacs::chart::Lab>(table) == "MELB") {
                if (serum_id.size() > 6 && (serum_id[0] == 'F' || serum_id[0] == 'R') && serum_id[5] == '-' && serum_id.back() == 'D')
                    return SerumIdRoot(serum_id.substr(0, 5));
                else
                    return SerumIdRoot(serum_id);
            }
            else
                return SerumIdRoot(serum_id);
        }

    static inline std::string make_name(EntryPtr ptr)
        {
            return string::join({std::get<Name>(*ptr), std::get<Reassortant>(*ptr), string::join(" ", std::get<Annotations>(*ptr))});
        }

    static inline std::vector<std::string> tables(EntryPtr first, EntryPtr last, bool assay, bool rbc)
    {
        std::vector<std::string> tables(static_cast<size_t>(last - first));
        std::transform(first, last, tables.begin(), [assay, rbc](const auto& entry) {
            std::vector<std::string> fields;
            if (assay)
                fields.push_back(std::get<acmacs::chart::Assay>(entry));
            if (rbc)
                fields.push_back(std::get<acmacs::chart::RbcSpecies>(entry));
            fields.push_back(std::get<acmacs::chart::TableDate>(entry));
            return string::join(":", fields);
        });
        std::reverse(tables.begin(), tables.end());
        return tables;
    }

};

// ----------------------------------------------------------------------

inline bool is_acmacs_file(const fs::path& path)
{
    if (path.extension() == ".ace")
        return true;
    if (path.extension() == ".bz2") {
        if (path.stem().extension() == ".acd1")
            return true;
    }
    return false;
}

// ----------------------------------------------------------------------

using namespace acmacs::argv;

struct Options : public argv
{
    Options(int a_argc, const char* const a_argv[], on_error on_err = on_error::exit) : argv() { parse(a_argc, a_argv, on_err); }

    option<str> fix{*this, "fix", dflt{""}};
    // argument<str> period{*this, arg_name{"monthly|yearly|weekly"}, mandatory};
    // argument<Date> start{*this, arg_name{"start-date"}, mandatory};
    // argument<Date> end{*this, arg_name{"end-date"}, mandatory};
    // argument<str> output{*this, arg_name{"output.json"}, dflt{""}};
};

// ----------------------------------------------------------------------

int main(int argc, const char* argv[])
{
    int exit_code = 0;
    try {
        Options opt(argc, argv);
        SerumIds serum_ids;
        size_t charts_processed = 0;
        for (auto& entry : fs::directory_iterator(".")) {
            if (entry.is_regular_file() && is_acmacs_file(entry.path())) {
                // std::cout << entry.path() << '\n';
                auto chart = acmacs::chart::import_from_file(entry.path());
                if (!opt.fix.has_value()) { // scan
                    std::tuple table(chart->info()->virus_type(), chart->info()->lab(), chart->info()->assay(), chart->info()->rbc_species(), chart->info()->date());
                    auto sera = chart->sera();
                    for (auto serum : *sera)
                        serum_ids.add({serum->name(), serum->reassortant(), serum->annotations(), serum->serum_id(), serum->passage()}, table);
                }
                else {          // fix
                    std::cerr << "FIX\n";
                }
                ++charts_processed;
            }
        }
        std::cout << charts_processed << " charts processed\n";
        std::cout << serum_ids.size() << " entries\n";
        serum_ids.sort();
        serum_ids.scan();
        // std::cout << serum_ids.size() << " entries\n";
        serum_ids.print(false);
    }
    catch (std::exception& err) {
        std::cerr << "ERROR: " << err.what() << '\n';
        exit_code = 2;
    }
    return exit_code;
}

// ----------------------------------------------------------------------
/// Local Variables:
/// eval: (if (fboundp 'eu-rename-buffer) (eu-rename-buffer))
/// End:
<commit_msg>fix serum ids in MELB tables<commit_after>#include <iostream>
#include <string>
#include <vector>
#include <tuple>

#include "acmacs-base/argv.hh"
#include "acmacs-base/filesystem.hh"
#include "acmacs-base/named-type.hh"
#include "acmacs-base/string.hh"
#include "acmacs-chart-2/factory-import.hh"
#include "acmacs-chart-2/chart.hh"

// ----------------------------------------------------------------------

class SerumIds
{
 public:
    using Name = acmacs::chart::Name;
    using Passage = acmacs::chart::Passage;
    using Reassortant = acmacs::chart::Reassortant;
    using Annotations = acmacs::chart::Annotations;
    using SerumId = acmacs::chart::SerumId;
    using SerumIdRoot = acmacs::named_t<std::string, struct SerumIdRootTag>;
    using SerumEntry = std::tuple<Name, Reassortant, Annotations, SerumId, Passage>;
    using TableEntry = std::tuple<acmacs::chart::VirusType, acmacs::chart::Lab, acmacs::chart::Assay, acmacs::chart::RbcSpecies, acmacs::chart::TableDate>;
    using Entry = std::tuple<SerumIdRoot, SerumId, Name, Reassortant, Annotations, acmacs::chart::VirusType, acmacs::chart::Lab, acmacs::chart::Assay, acmacs::chart::RbcSpecies, acmacs::chart::TableDate, Passage>;
    using Entries = std::vector<Entry>;
    using EntryPtr = typename Entries::const_iterator;
    using PerSerumIdEntry = std::tuple<EntryPtr, EntryPtr>;
    using PerSerumIdRootEntry = std::tuple<EntryPtr, EntryPtr, std::vector<PerSerumIdEntry>>;
    using PerSerumIdRootEntries = std::vector<PerSerumIdRootEntry>;

    SerumIds() = default;

    size_t size() const { return data_.size(); }
    void sort() { std::sort(data_.begin(), data_.end()); /* data_.erase(std::unique(data_.begin(), data_.end()), data_.end()); */ }

    void add(const SerumEntry& serum, const TableEntry& table)
        {
            data_.emplace_back(serum_id_root(serum, table), std::get<SerumId>(serum),
                               std::get<Name>(serum), std::get<Reassortant>(serum), std::get<Annotations>(serum),
                               std::get<acmacs::chart::VirusType>(table), std::get<acmacs::chart::Lab>(table), std::get<acmacs::chart::Assay>(table), std::get<acmacs::chart::RbcSpecies>(table), std::get<acmacs::chart::TableDate>(table),
                               std::get<Passage>(serum));
        }

    void scan()
        {
            for (EntryPtr entry_ptr = data_.begin(); entry_ptr != data_.end(); ++entry_ptr) {
                if (per_root_.empty() || std::get<SerumIdRoot>(*entry_ptr) !=  std::get<SerumIdRoot>(*std::get<0>(per_root_.back()))) {
                    per_root_.emplace_back(entry_ptr, entry_ptr + 1, std::vector<PerSerumIdEntry>{{entry_ptr, entry_ptr + 1}});
                }
                else {
                    std::get<1>(per_root_.back()) = entry_ptr + 1;
                    const auto last = std::get<0>(std::get<2>(per_root_.back()).back());
                    const auto name = make_name(entry_ptr), name_last = make_name(last);
                    if (std::get<SerumId>(*entry_ptr) != std::get<SerumId>(*last) || name != name_last) {
                        std::get<2>(per_root_.back()).emplace_back(entry_ptr, entry_ptr + 1);
                    }
                    else {
                        std::get<1>(std::get<2>(per_root_.back()).back()) = entry_ptr + 1;
                    }
                }
            }
            std::cout << "per_root_ " << per_root_.size() << '\n';
        }

        void print(bool print_good) const
        {
            const bool show_assay = std::get<acmacs::chart::VirusType>(*std::get<0>(per_root_.front())) == "A(H3N2)";
            const bool show_rbc = show_assay;
            for (const auto& per_root_entry : per_root_) {
                const auto name = make_name(std::get<0>(per_root_entry)), name_last = make_name(std::get<1>(per_root_entry) - 1);
                if (const bool good = std::get<2>(per_root_entry).size() == 1; !good || print_good) {
                    std::cout << std::get<SerumIdRoot>(*std::get<0>(per_root_entry)) << ' ' << (std::get<1>(per_root_entry) - std::get<0>(per_root_entry)) << '\n';
                    for (const auto& per_serum_id_entry : std::get<2>(per_root_entry)) {
                        const auto tabs = tables(std::get<0>(per_serum_id_entry), std::get<1>(per_serum_id_entry), show_assay, show_rbc);
                        std::cout << "    " << std::get<SerumId>(*std::get<0>(per_serum_id_entry)) << ' ' << tabs.size()
                                  << " [" << make_name(std::get<0>(per_serum_id_entry)) << ']';
                        for (const auto& table : tabs)
                            std::cout << ' ' << table;
                        std::cout << '\n';
                    }
                    if (!good) {
                        const auto& sids = std::get<2>(per_root_entry);
                        if (std::get<SerumId>(*std::get<0>(sids.front())) != std::get<SerumId>(*std::get<0>(sids.back()))) {
                            const auto sid = std::max_element(sids.begin(), sids.end(), [](const auto& e1, const auto& e2) -> bool { return (std::get<1>(e1) - std::get<0>(e1)) <  (std::get<1>(e2) - std::get<0>(e2)); });
                            for (auto ep = sids.begin(); ep != sids.end(); ++ep) {
                                if (ep != sid) {
                                    const bool same_size = (std::get<1>(*ep) - std::get<0>(*ep)) == (std::get<1>(*sid) - std::get<0>(*sid));
                                    std::cout << "    " << (same_size ? "?? " : "") << "--fix " << std::get<SerumId>(*std::get<0>(*ep)) << '^' << std::get<SerumId>(*std::get<0>(*sid)) << '\n';
                                }
                            }
                        }
                    }
                }
            }
        }

 private:
    Entries data_;
    PerSerumIdRootEntries per_root_;

    SerumIdRoot serum_id_root(const SerumEntry& serum, const TableEntry& table) const
        {
            const auto& serum_id = std::get<SerumId>(serum);
            if (std::get<acmacs::chart::Lab>(table) == "MELB") {
                if (serum_id.size() > 6 && (serum_id[0] == 'F' || serum_id[0] == 'R') && serum_id[5] == '-' && serum_id.back() == 'D')
                    return SerumIdRoot(serum_id.substr(0, 5));
                else
                    return SerumIdRoot(serum_id);
            }
            else
                return SerumIdRoot(serum_id);
        }

    static inline std::string make_name(EntryPtr ptr)
        {
            return string::join({std::get<Name>(*ptr), std::get<Reassortant>(*ptr), string::join(" ", std::get<Annotations>(*ptr))});
        }

    static inline std::vector<std::string> tables(EntryPtr first, EntryPtr last, bool assay, bool rbc)
    {
        std::vector<std::string> tables(static_cast<size_t>(last - first));
        std::transform(first, last, tables.begin(), [assay, rbc](const auto& entry) {
            std::vector<std::string> fields;
            if (assay)
                fields.push_back(std::get<acmacs::chart::Assay>(entry));
            if (rbc)
                fields.push_back(std::get<acmacs::chart::RbcSpecies>(entry));
            fields.push_back(std::get<acmacs::chart::TableDate>(entry));
            return string::join(":", fields);
        });
        std::reverse(tables.begin(), tables.end());
        return tables;
    }

};

// ----------------------------------------------------------------------

inline bool is_acmacs_file(const fs::path& path)
{
    if (path.extension() == ".ace")
        return true;
    if (path.extension() == ".bz2") {
        if (path.stem().extension() == ".acd1")
            return true;
    }
    return false;
}

// ----------------------------------------------------------------------

using namespace acmacs::argv;

struct Options : public argv
{
    Options(int a_argc, const char* const a_argv[], on_error on_err = on_error::exit) : argv() { parse(a_argc, a_argv, on_err); }

    option<str_array> fix{*this, "fix"};
    // argument<str> period{*this, arg_name{"monthly|yearly|weekly"}, mandatory};
    // argument<Date> start{*this, arg_name{"start-date"}, mandatory};
    // argument<Date> end{*this, arg_name{"end-date"}, mandatory};
    // argument<str> output{*this, arg_name{"output.json"}, dflt{""}};
};

// ----------------------------------------------------------------------

int main(int argc, const char* argv[])
{
    int exit_code = 0;
    try {
        Options opt(argc, argv);
        SerumIds serum_ids;
        size_t charts_processed = 0;
        for (auto& entry : fs::directory_iterator(".")) {
            if (const auto pathname = entry.path(); entry.is_regular_file() && is_acmacs_file(pathname)) {
                // std::cout << entry.path() << '\n';
                auto chart = acmacs::chart::import_from_file(pathname);
                if (!opt.fix.has_value()) { // scan
                    std::tuple table(chart->info()->virus_type(), chart->info()->lab(), chart->info()->assay(), chart->info()->rbc_species(), chart->info()->date());
                    auto sera = chart->sera();
                    for (auto serum : *sera)
                        serum_ids.add({serum->name(), serum->reassortant(), serum->annotations(), serum->serum_id(), serum->passage()}, table);
                }
                else {          // fix
                    std::cerr << "FIX " << acmacs::argv::detail::to_string(opt.fix.get()) << '\n';
                }
                ++charts_processed;
            }
        }
        std::cout << charts_processed << " charts processed\n";
        std::cout << serum_ids.size() << " entries\n";
        serum_ids.sort();
        serum_ids.scan();
        // std::cout << serum_ids.size() << " entries\n";
        serum_ids.print(false);
    }
    catch (std::exception& err) {
        std::cerr << "ERROR: " << err.what() << '\n';
        exit_code = 2;
    }
    return exit_code;
}

// ----------------------------------------------------------------------
/// Local Variables:
/// eval: (if (fboundp 'eu-rename-buffer) (eu-rename-buffer))
/// End:
<|endoftext|>


<commit_before>#define BOOST_TEST_MODULE BitSharesTest
#include <boost/test/unit_test.hpp>
#include <bts/wallet.hpp>
#include <bts/address.hpp>
#include <fc/exception/exception.hpp>
#include <fc/log/logger.hpp>
#include <fc/reflect/variant.hpp>
#include <bts/mini_pow.hpp>
#include <bts/dds/mmap_array.hpp>
#include <bts/blockchain/asset.hpp>
#include <bts/blockchain/blockchain_db.hpp>
#include <bts/config.hpp>
#include <fc/io/json.hpp>
#include <fc/io/raw.hpp>

using namespace bts;
using bts::blockchain::asset;
using bts::blockchain::price;
using namespace bts::blockchain;

BOOST_AUTO_TEST_CASE( mining_reward_rate )
{
  uint64_t supply = -INITIAL_REWARD/2;
  for( uint32_t i = 0; i < BLOCKS_WITH_REWARD; ++i )
  {
     supply += bts::blockchain::calculate_mining_reward(i);
  }
  ilog( "INITIAL_REWARD ${i}", ("i",INITIAL_REWARD) );
  ilog( "BLOCKS_WITH_REWARD ${i}", ("i",BLOCKS_WITH_REWARD) );
  ilog( "REWARD_DELTA_PER_BLOCK ${i}", ("i",REWARD_DELTA_PER_BLOCK) );
  ilog( "LAST_BLOCK_REWARD ${i}", ("i",calculate_mining_reward(BLOCKS_WITH_REWARD)) );
  ilog( "LAST_BLOCK_REWARD+1 ${i}", ("i",calculate_mining_reward(BLOCKS_WITH_REWARD+1)) );
  ilog( "end supply: ${e}  target supply ${t}", ("e",supply)("t",MAX_BITSHARE_SUPPLY) );
  ilog( "error: ${e}       error per block: ${epp}", ("e", (supply-MAX_BITSHARE_SUPPLY) )("epp", (supply-MAX_BITSHARE_SUPPLY)/BLOCKS_WITH_REWARD ) );
}

BOOST_AUTO_TEST_CASE( fixed_math )
{
  try{
   asset usd( 30000, asset::usd );
   asset bts( 5000, asset::bts );
   auto  usd_bts = usd / bts;
   auto  bts_usd = bts / usd;

   ilog( "usd: ${u}  bts: ${b}", ("u",usd)("b",bts) );
   ilog( "usd_bts = ${ub}   bts_usd = ${bu}", ("ub", usd_bts)("bu",bts_usd) );

   asset usd56( 5, asset::usd );
   asset bts43( 43, asset::bts );

   auto bts43_in_usd =  bts43 * bts_usd;
   auto back_to_bts = bts43_in_usd * bts_usd;
   ilog( " ${b} * ${p}  =>  ${a}", ("b", bts43)("p",bts_usd)("a",bts43_in_usd) );
   ilog( " ${b} * ${p}  =>  ${a}", ("b", bts43_in_usd)("p",bts_usd)("a",back_to_bts) );
   BOOST_CHECK( back_to_bts.amount.high_bits() == bts43.amount.high_bits() );
   {
   asset usd( 5, asset::usd );
   asset bts( 3, asset::bts );
   auto  usd_bts = usd / bts;
   auto  bts_usd = bts / usd;

   ilog( "usd: ${u}  bts: ${b}", ("u",usd)("b",bts) );
   ilog( "usd_bts = ${ub}   bts_usd = ${bu}", ("ub", usd_bts)("bu",bts_usd) );
   }

  } catch ( const fc::exception& e )
  {
    elog( "${e}", ("e",e.to_detail_string()) );
    throw;
  }
}

BOOST_AUTO_TEST_CASE( bts_address )
{
  try
  {
     auto priv = fc::ecc::private_key::generate();
     bts::address addr =  priv.get_public_key();
     std::string addrstr = addr;
     bts::address addr2 = addrstr;
     bts::address addr3 =  priv.get_public_key();

     BOOST_REQUIRE( addr == addr2 );
     BOOST_REQUIRE( addr3 == addr2 );
     BOOST_REQUIRE_THROW( bts::address("invalid"), fc::exception);
     BOOST_REQUIRE_THROW( bts::address("a23"), fc::exception);
     ilog( "address ${adr}", ("adr", addrstr ) );
     ilog( "address ${adr}", ("adr", addr ) );
  } catch( fc::exception& e )
  {
    elog( "${e}", ("e",e.to_detail_string()) );
    throw;
  }
}
<commit_msg>added extra checks to unit tests<commit_after>#define BOOST_TEST_MODULE BitSharesTest
#include <boost/test/unit_test.hpp>
#include <bts/wallet.hpp>
#include <bts/address.hpp>
#include <fc/exception/exception.hpp>
#include <fc/log/logger.hpp>
#include <fc/reflect/variant.hpp>
#include <bts/mini_pow.hpp>
#include <bts/dds/mmap_array.hpp>
#include <bts/blockchain/asset.hpp>
#include <bts/blockchain/blockchain_db.hpp>
#include <bts/config.hpp>
#include <fc/io/json.hpp>
#include <fc/io/raw.hpp>

using namespace bts;
using bts::blockchain::asset;
using bts::blockchain::price;
using namespace bts::blockchain;

BOOST_AUTO_TEST_CASE( mining_reward_rate )
{
  uint64_t supply = -INITIAL_REWARD/2;
  for( uint32_t i = 0; i < BLOCKS_WITH_REWARD; ++i )
  {
     supply += bts::blockchain::calculate_mining_reward(i);
  }
  ilog( "INITIAL_REWARD ${i}", ("i",INITIAL_REWARD) );
  ilog( "BLOCKS_WITH_REWARD ${i}", ("i",BLOCKS_WITH_REWARD) );
  ilog( "REWARD_DELTA_PER_BLOCK ${i}", ("i",REWARD_DELTA_PER_BLOCK) );
  ilog( "LAST_BLOCK_REWARD ${i}", ("i",calculate_mining_reward(BLOCKS_WITH_REWARD)) );
  ilog( "LAST_BLOCK_REWARD+1 ${i}", ("i",calculate_mining_reward(BLOCKS_WITH_REWARD+1)) );
  ilog( "end supply: ${e}  target supply ${t}", ("e",supply)("t",MAX_BITSHARE_SUPPLY) );
  ilog( "error: ${e}       error per block: ${epp}", ("e", (supply-MAX_BITSHARE_SUPPLY) )("epp", (supply-MAX_BITSHARE_SUPPLY)/BLOCKS_WITH_REWARD ) );
  BOOST_REQUIRE( supply == MAX_BITSHARE_SUPPLY );
  BOOST_REQUIRE( 0 == calculate_mining_reward(BLOCKS_WITH_REWARD+1));
  BOOST_REQUIRE( 0 == calculate_mining_reward(BLOCKS_WITH_REWARD));
}

BOOST_AUTO_TEST_CASE( fixed_math )
{
  try{
   asset usd( 30000, asset::usd );
   asset bts( 5000, asset::bts );
   auto  usd_bts = usd / bts;
   auto  bts_usd = bts / usd;

   ilog( "usd: ${u}  bts: ${b}", ("u",usd)("b",bts) );
   ilog( "usd_bts = ${ub}   bts_usd = ${bu}", ("ub", usd_bts)("bu",bts_usd) );

   asset usd56( 5, asset::usd );
   asset bts43( 43, asset::bts );

   auto bts43_in_usd =  bts43 * bts_usd;
   auto back_to_bts = bts43_in_usd * bts_usd;
   ilog( " ${b} * ${p}  =>  ${a}", ("b", bts43)("p",bts_usd)("a",bts43_in_usd) );
   ilog( " ${b} * ${p}  =>  ${a}", ("b", bts43_in_usd)("p",bts_usd)("a",back_to_bts) );
   BOOST_CHECK( back_to_bts.amount.high_bits() == bts43.amount.high_bits() );
   {
   asset usd( 5, asset::usd );
   asset bts( 3, asset::bts );
   auto  usd_bts = usd / bts;
   auto  bts_usd = bts / usd;

   ilog( "usd: ${u}  bts: ${b}", ("u",usd)("b",bts) );
   ilog( "usd_bts = ${ub}   bts_usd = ${bu}", ("ub", usd_bts)("bu",bts_usd) );
   }

  } catch ( const fc::exception& e )
  {
    elog( "${e}", ("e",e.to_detail_string()) );
    throw;
  }
}

BOOST_AUTO_TEST_CASE( bts_address )
{
  try
  {
     auto priv = fc::ecc::private_key::generate();
     bts::address addr =  priv.get_public_key();
     std::string addrstr = addr;
     bts::address addr2 = addrstr;
     bts::address addr3 =  priv.get_public_key();

     BOOST_REQUIRE( addr == addr2 );
     BOOST_REQUIRE( addr3 == addr2 );
     BOOST_REQUIRE_THROW( bts::address("invalid"), fc::exception);
     BOOST_REQUIRE_THROW( bts::address("a23"), fc::exception);
     ilog( "address ${adr}", ("adr", addrstr ) );
     ilog( "address ${adr}", ("adr", addr ) );
  } catch( fc::exception& e )
  {
    elog( "${e}", ("e",e.to_detail_string()) );
    throw;
  }
}
<|endoftext|>


<commit_before>#include "RobotService.h"
#include <boost/thread.hpp>

namespace {
  /**
   * Callback invoked when the async connect operation completes.
   */
  void connect_handler(boost::system::error_code const& error) {
    if (!error) {
      std::cerr << "AsyncRobotService: Connected to the robot." << std::endl;
    } else {
      std::cerr << "AsyncRobotService: Failed to connect to the robot" << std::endl;
    }
  }

  /**
   * A simple function that is used to spin up the io service event loop in a
   * dedicated thread.
   * Makes sure that the loop does not end when the service does not have any
   * work to do (temporarily).
   */
  void service_thread(boost::asio::io_service* io_service) {
    // Prevent the IO service from running out of work (and exitting when no
    // async operations are queued).
    boost::asio::io_service::work work(*io_service);
    io_service->run();
    std::cout << "AsyncRobotService: Exiting service thread..." << std::endl;
  }

  /**
   * A callback for write operations.
   */
  void write_handler(boost::system::error_code const& error,
               std::size_t sent) {
    if (!error) {
      std::cerr << "AsyncRobotService: Send complete. "
                << "Sent " << sent << " bytes." << std::endl;
    } else {
      std::cerr << "AsyncRobotService: Error sending message." << std::endl;
    }
  }
}

VisionMessage VisionMessage::DeleteMessage(int model_id) {
  std::cout << "Constructing with object_id = " << model_id << std::endl;
  VisionMessage msg;
  msg.id = REMOVE_SSV;
  msg.len = sizeof params;
  memset(msg.params, 0, sizeof msg.params);
  // 0 - unused, no point setting the type
  msg.params[1] = model_id;
  // 2 - unused -- since the entire model is getting removed...
  // 3 - unused, no point setting the radius
  msg.params[4] = VisionMessage::DEL_WHOLE_SEGMENT_FLAG;
  // The rest of the parameters are also irrelevant.
  std::cout << "Constructed " << msg << std::endl;
  return msg;
}

VisionMessage VisionMessage::DeletePartMessage(int model_id, int part_id) {
  std::cout << "Constructing with object_id = " << part_id << std::endl;
  VisionMessage msg;
  msg.id = REMOVE_SSV;
  msg.len = sizeof params;
  memset(msg.params, 0, sizeof msg.params);
  // 0 - unused, no point setting the type
  msg.params[1] = model_id;
  msg.params[2] = part_id;
  // 3 - unused, no point setting the radius
  msg.params[4] = VisionMessage::DEL_ONLY_PART_FLAG;
  // The rest of the parameters are also irrelevant.
  std::cout << "Constructed " << msg << std::endl;
  return msg;
}

VisionMessage VisionMessage::SetMessage(
    int type_id, int model_id, int part_id, double radius, std::vector<double> const& coefs) {
  VisionMessage msg;
  msg.id = SET_SSV;
  memset(msg.params, 0, sizeof msg.params);
  msg.params[0] = type_id;
  msg.params[1] = model_id;
  msg.params[2] = part_id;
  msg.params[3] = radius;
  // 4 - unused
  // 5 - unused
  for (size_t i = 0; i < coefs.size(); ++i) msg.params[6 + i] = coefs[i];

  return msg;
}

VisionMessage VisionMessage::ModifyMessage(
    int type_id, int model_id, int part_id, double radius, std::vector<double> const& coefs) {
  VisionMessage msg;
  msg.id = MODIFY_SSV;
  memset(msg.params, 0, sizeof msg.params);
  msg.params[0] = type_id;
  msg.params[1] = model_id;
  msg.params[2] = part_id;
  msg.params[3] = radius;
  // 4 - unused
  // 5 - unused
  for (size_t i = 0; i < coefs.size(); ++i) msg.params[6 + i] = coefs[i];

  return msg;
}

std::ostream& operator<<(std::ostream& out, VisionMessage const& msg) {
  out << "[" << msg.id << " | " << msg.len << " | ";
  for (size_t i = 0; i < 15; ++i) out << msg.params[i] << ", ";
  out << "]";

  return out;
}

void AsyncRobotService::start() {
  // Start it up...
  boost::asio::ip::tcp::endpoint endpoint(
    boost::asio::ip::address::from_string(remote_), port_);
  std::cerr << "AsyncRobotService: Initiating a connection asynchronously..."
            << std::endl;
  socket_.async_connect(endpoint, connect_handler);
  // Start the service thread in the background...
  boost::thread(boost::bind(service_thread, &io_service_));
}

void AsyncRobotService::inner_send(VisionMessage const& next_message) {
  char const* buf = (char const*)&next_message;
  std::cerr << "AsyncRobotService: Sending a queued message: "
            << "msg == " << next_message
            << std::endl;
  // Synchronously send the message, i.e. block until the send is complete.
  try {
    socket_.send(
        boost::asio::buffer(buf, sizeof(VisionMessage)));
  } catch (...) {
    std::cerr << "AsyncRobotService: Error sending message." << std::endl;
  }
  // After each sent message, we want to wait a pre-defined amount of time
  // before sending the next one.
  // This is because we do not want to overwhelm the robot with a large
  // number of messages all sent in the same time.
  boost::this_thread::sleep(message_timeout_);
}

void AsyncRobotService::sendMessage(VisionMessage const& msg) {
  // Just queue another message to be sent by the io_service thread.
  // Since `inner_send` makes sure to wait after it's finished sending
  // each message (i.e. the io_service thread is blocked), the queued
  // messages will all be sent with a preset time delay between subsequent
  // messages.
  io_service_.post(boost::bind(&AsyncRobotService::inner_send, this, msg));
}
<commit_msg>Remove unnecessary and **invalid** message len assignment<commit_after>#include "RobotService.h"
#include <boost/thread.hpp>

namespace {
  /**
   * Callback invoked when the async connect operation completes.
   */
  void connect_handler(boost::system::error_code const& error) {
    if (!error) {
      std::cerr << "AsyncRobotService: Connected to the robot." << std::endl;
    } else {
      std::cerr << "AsyncRobotService: Failed to connect to the robot" << std::endl;
    }
  }

  /**
   * A simple function that is used to spin up the io service event loop in a
   * dedicated thread.
   * Makes sure that the loop does not end when the service does not have any
   * work to do (temporarily).
   */
  void service_thread(boost::asio::io_service* io_service) {
    // Prevent the IO service from running out of work (and exitting when no
    // async operations are queued).
    boost::asio::io_service::work work(*io_service);
    io_service->run();
    std::cout << "AsyncRobotService: Exiting service thread..." << std::endl;
  }

  /**
   * A callback for write operations.
   */
  void write_handler(boost::system::error_code const& error,
               std::size_t sent) {
    if (!error) {
      std::cerr << "AsyncRobotService: Send complete. "
                << "Sent " << sent << " bytes." << std::endl;
    } else {
      std::cerr << "AsyncRobotService: Error sending message." << std::endl;
    }
  }
}

VisionMessage VisionMessage::DeleteMessage(int model_id) {
  std::cout << "Constructing with object_id = " << model_id << std::endl;
  VisionMessage msg;
  msg.id = REMOVE_SSV;
  memset(msg.params, 0, sizeof msg.params);
  // 0 - unused, no point setting the type
  msg.params[1] = model_id;
  // 2 - unused -- since the entire model is getting removed...
  // 3 - unused, no point setting the radius
  msg.params[4] = VisionMessage::DEL_WHOLE_SEGMENT_FLAG;
  // The rest of the parameters are also irrelevant.
  std::cout << "Constructed " << msg << std::endl;
  return msg;
}

VisionMessage VisionMessage::DeletePartMessage(int model_id, int part_id) {
  std::cout << "Constructing with object_id = " << part_id << std::endl;
  VisionMessage msg;
  msg.id = REMOVE_SSV;
  memset(msg.params, 0, sizeof msg.params);
  // 0 - unused, no point setting the type
  msg.params[1] = model_id;
  msg.params[2] = part_id;
  // 3 - unused, no point setting the radius
  msg.params[4] = VisionMessage::DEL_ONLY_PART_FLAG;
  // The rest of the parameters are also irrelevant.
  std::cout << "Constructed " << msg << std::endl;
  return msg;
}

VisionMessage VisionMessage::SetMessage(
    int type_id, int model_id, int part_id, double radius, std::vector<double> const& coefs) {
  VisionMessage msg;
  msg.id = SET_SSV;
  memset(msg.params, 0, sizeof msg.params);
  msg.params[0] = type_id;
  msg.params[1] = model_id;
  msg.params[2] = part_id;
  msg.params[3] = radius;
  // 4 - unused
  // 5 - unused
  for (size_t i = 0; i < coefs.size(); ++i) msg.params[6 + i] = coefs[i];

  return msg;
}

VisionMessage VisionMessage::ModifyMessage(
    int type_id, int model_id, int part_id, double radius, std::vector<double> const& coefs) {
  VisionMessage msg;
  msg.id = MODIFY_SSV;
  memset(msg.params, 0, sizeof msg.params);
  msg.params[0] = type_id;
  msg.params[1] = model_id;
  msg.params[2] = part_id;
  msg.params[3] = radius;
  // 4 - unused
  // 5 - unused
  for (size_t i = 0; i < coefs.size(); ++i) msg.params[6 + i] = coefs[i];

  return msg;
}

std::ostream& operator<<(std::ostream& out, VisionMessage const& msg) {
  out << "[" << msg.id << " | " << msg.len << " | ";
  for (size_t i = 0; i < 15; ++i) out << msg.params[i] << ", ";
  out << "]";

  return out;
}

void AsyncRobotService::start() {
  // Start it up...
  boost::asio::ip::tcp::endpoint endpoint(
    boost::asio::ip::address::from_string(remote_), port_);
  std::cerr << "AsyncRobotService: Initiating a connection asynchronously..."
            << std::endl;
  socket_.async_connect(endpoint, connect_handler);
  // Start the service thread in the background...
  boost::thread(boost::bind(service_thread, &io_service_));
}

void AsyncRobotService::inner_send(VisionMessage const& next_message) {
  char const* buf = (char const*)&next_message;
  std::cerr << "AsyncRobotService: Sending a queued message: "
            << "msg == " << next_message
            << std::endl;
  // Synchronously send the message, i.e. block until the send is complete.
  try {
    socket_.send(
        boost::asio::buffer(buf, sizeof(VisionMessage)));
  } catch (...) {
    std::cerr << "AsyncRobotService: Error sending message." << std::endl;
  }
  // After each sent message, we want to wait a pre-defined amount of time
  // before sending the next one.
  // This is because we do not want to overwhelm the robot with a large
  // number of messages all sent in the same time.
  boost::this_thread::sleep(message_timeout_);
}

void AsyncRobotService::sendMessage(VisionMessage const& msg) {
  // Just queue another message to be sent by the io_service thread.
  // Since `inner_send` makes sure to wait after it's finished sending
  // each message (i.e. the io_service thread is blocked), the queued
  // messages will all be sent with a preset time delay between subsequent
  // messages.
  io_service_.post(boost::bind(&AsyncRobotService::inner_send, this, msg));
}
<|endoftext|>


<commit_before><commit_msg>not stop localize, just ignore invalid po entries<commit_after><|endoftext|>


<commit_before><commit_msg>char array should be null terminated<commit_after><|endoftext|>


<commit_before>/**
Copyright (c) 2017, Philip Deegan.
All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:

    * Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
    * Redistributions in binary form must reproduce the above
copyright notice, this list of conditions and the following disclaimer
in the documentation and/or other materials provided with the
distribution.
    * Neither the name of Philip Deegan nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "maiken.hpp"
#include "maiken/dist.hpp"
#include "maiken/source.hpp"

#include <mutex>

namespace maiken {
class CompilerPrinter {
 public:
  static void print_for(const Application& app) {
    if (!AppVars::INSTANCE().dryRun()) {
      std::stringstream ss;
      ss << MKN_PROJECT << ": " << app.project().dir().path();
      if (app.profile().size() > 0) ss << " [" << app.profile() << "]";
      KOUT(NON) << ss.str();
    }
    if (!AppVars::INSTANCE().dryRun() && kul::LogMan::INSTANCE().inf() &&
        app.includes().size()) {
      KOUT(NON) << "INCLUDES";
      for (const auto& s : app.includes()) KOUT(NON) << "\t" << s.first;
    }

    if (!AppVars::INSTANCE().dryRun() && kul::LogMan::INSTANCE().inf()) {
      if (!app.arg.empty()) KOUT(NON) << "ARGUMENTS\n\t" << app.arg;
      if (app.arguments().size()) {
        KOUT(NON) << "FILE ARGUMENTS";
        for (const auto& kv : app.arguments())
          for (const std::string& s : kv.second)
            KOUT(NON) << "\t" << kv.first << " : " << s;
      }
      if (!AppVars::INSTANCE().args().empty())
        KOUT(NON) << "ADDITIONAL ARGUMENTS: \n\t" << AppVars::INSTANCE().args();
      if (AppVars::INSTANCE().jargs().size()) {
        KOUT(NON) << "ADDITIONAL FILE ARGUMENTS:";
        for (const auto& kv : AppVars::INSTANCE().jargs())
          KOUT(NON) << "\t" << kv.first << " : " << kv.second;
      }
    }
    if (!AppVars::INSTANCE().envVars().count("MKN_OBJ"))
      KEXCEPTION("INTERNAL BADNESS ERROR!");
  }
};
}  // namespace maiken

void maiken::Application::compile(kul::hash::set::String& objects)
    KTHROW(kul::Exception) {
  auto sources = sourceMap();

  showConfig();
  CompilerPrinter::print_for(*this);

  SourceFinder s_finder(*this);
  CompilerValidation::check_compiler_for(*this, sources);
  std::vector<kul::File> cacheFiles;
  auto src_objs = s_finder.all_sources_from(sources, objects, cacheFiles);

  compile(src_objs, objects, cacheFiles);
}

void maiken::Application::compile(
    std::vector<std::pair<std::string, std::string>>& src_objs,
    kul::hash::set::String& objects, std::vector<kul::File>& cacheFiles)
    KTHROW(kul::Exception) {
#if defined(_MKN_WITH_MKN_RAM_) && defined(_MKN_WITH_IO_CEREAL_)
  std::vector<std::shared_ptr<maiken::dist::Post>> posts;
  auto compile_lambda = [](std::shared_ptr<maiken::dist::Post> post,
                           const dist::Host& host) {
    post->send(host);
    dist::FileWriter fw;
    dist::Blob b;
    do {
      auto dowd = std::make_shared<maiken::dist::Post>(std::move(
          maiken::dist::RemoteCommandManager::INST().build_download_request()));
      dowd->send(host);
      std::string body(std::move(dowd->body()));
      std::istringstream iss(body);
      {
        cereal::PortableBinaryInputArchive iarchive(iss);
        iarchive(b);
      }
      size_t size = b.len;
      if (!b.file.empty()) {
        if (!fw.bw) {
          kul::File obj(b.file);
          if (obj) obj = kul::File(std::string(b.file + ".new"));
          fw.bw = std::make_unique<kul::io::BinaryWriter>(obj);
        }
        for (size_t i = 0; i < b.len; i++) (*fw.bw.get()) << b.c1[i];
      }
      if (b.last_packet) fw.bw.reset();
    } while (b.files_left > 0);

  };
  size_t threads = 0;

  auto& hosts(maiken::dist::RemoteCommandManager::INST().hosts());
  if (AppVars::INSTANCE().nodes()) {
    threads = (hosts.size() < AppVars::INSTANCE().nodes())
                  ? hosts.size()
                  : AppVars::INSTANCE().nodes();
  }
  kul::ChroncurrentThreadPool<> ctp(threads, 1, 1000000000, 1000);
  auto compile_ex = [&](const kul::Exception& e) {
    ctp.stop().interrupt();
    throw e;
  };
  for (size_t i = 0; i < threads; i++) {
    KLOG(INF);
    std::vector<std::pair<std::string, std::string>> remote_src_objs;
    if (src_objs.size() > 1) {
      remote_src_objs.push_back(src_objs[0]);
      src_objs.erase(src_objs.begin());
    }

    if (!remote_src_objs.empty()) {
      posts.emplace_back(std::make_shared<maiken::dist::Post>(std::move(
          maiken::dist::RemoteCommandManager::INST().build_compile_request(
              this->project().dir().real(), remote_src_objs))));
      ctp.async(std::bind(compile_lambda, posts[i], std::ref(hosts[i])),
                compile_ex);
    }
  }

#endif  //  _MKN_WITH_MKN_RAM_) && defined(_MKN_WITH_IO_CEREAL_)
  std::queue<std::pair<std::string, std::string>> sourceQueue;
  for (auto& so : src_objs) {
    sourceQueue.push(std::make_pair(so.first, so.second));
    kul::File object_file(so.second);
    if (!object_file.dir()) object_file.dir().mk();
  }
  if (!src_objs.empty()) compile(sourceQueue, objects, cacheFiles);
#if defined(_MKN_WITH_MKN_RAM_) && defined(_MKN_WITH_IO_CEREAL_)
  ctp.finish(10000000);  // 10 milliseconds
  ctp.rethrow();
#endif  //  _MKN_WITH_MKN_RAM_) && defined(_MKN_WITH_IO_CEREAL_)

  if (_MKN_TIMESTAMPS_) writeTimeStamps(objects, cacheFiles);
}

void maiken::Application::compile(
    std::queue<std::pair<std::string, std::string>>& sourceQueue,
    kul::hash::set::String& objects, std::vector<kul::File>& cacheFiles)
    KTHROW(kul::Exception) {
  ThreadingCompiler tc(*this);
  kul::ChroncurrentThreadPool<> ctp(AppVars::INSTANCE().threads(), 1,
                                    1000000000, 1000);
  std::vector<maiken::CompilationUnit> c_units;
  std::queue<std::pair<std::string, std::string>> cQueue;
  while (sourceQueue.size() > 0) {
    c_units.emplace_back(tc.compilationUnit(sourceQueue.front()));
    cQueue.push(sourceQueue.front());
    sourceQueue.pop();
  }

  auto o = [](const std::string& s) {
    if (s.size()) KOUT(NON) << s;
  };
  auto e = [](const std::string& s) {
    if (s.size()) KERR << s;
  };

  std::mutex mute;
  std::vector<CompilerProcessCapture> cpcs;
  auto lambda = [o, e, &ctp, &mute,
                 &cpcs](const maiken::CompilationUnit& c_unit) {
    if (ctp.exception()) ctp.interrupt();
    const CompilerProcessCapture cpc = c_unit.compile();
    if (!AppVars::INSTANCE().dryRun()) {
      if (kul::LogMan::INSTANCE().inf() || cpc.exception()) o(cpc.outs());
      if (kul::LogMan::INSTANCE().inf() || cpc.exception()) e(cpc.errs());
      KOUT(INF) << cpc.cmd();
    } else
      KOUT(NON) << cpc.cmd();
    std::lock_guard<std::mutex> lock(mute);
    cpcs.push_back(cpc);
  };

  auto lambex = [&](const kul::Exception& e) {
    ctp.stop();
    std::cerr << ":EXCEPTION!: " << e.debug() << std::endl;
    ctp.interrupt();
    throw e;
  };

  for (const auto& unit : c_units) {
    kul::this_thread::nSleep(
        5000000);  // dup appears to be overloaded with too many threads
    ctp.async(std::bind(lambda, unit),
              std::bind(lambex, std::placeholders::_1));
  }

  ctp.finish(1000000 * 1000);
  if (ctp.exception()) KEXIT(1, "Compile error detected");

  for (auto& cpc : cpcs) {
    if (cpc.exception()) std::rethrow_exception(cpc.exception());
  }

  while (cQueue.size()) {
    objects.insert(cQueue.front().second);
    cacheFiles.push_back(kul::File(cQueue.front().first));
    cQueue.pop();
  }
}
<commit_msg>remote compilation delegation<commit_after>/**
Copyright (c) 2017, Philip Deegan.
All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:

    * Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
    * Redistributions in binary form must reproduce the above
copyright notice, this list of conditions and the following disclaimer
in the documentation and/or other materials provided with the
distribution.
    * Neither the name of Philip Deegan nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "maiken.hpp"
#include "maiken/dist.hpp"
#include "maiken/source.hpp"

#include <mutex>

namespace maiken {
class CompilerPrinter {
 public:
  static void print_for(const Application& app) {
    if (!AppVars::INSTANCE().dryRun()) {
      std::stringstream ss;
      ss << MKN_PROJECT << ": " << app.project().dir().path();
      if (app.profile().size() > 0) ss << " [" << app.profile() << "]";
      KOUT(NON) << ss.str();
    }
    if (!AppVars::INSTANCE().dryRun() && kul::LogMan::INSTANCE().inf() &&
        app.includes().size()) {
      KOUT(NON) << "INCLUDES";
      for (const auto& s : app.includes()) KOUT(NON) << "\t" << s.first;
    }

    if (!AppVars::INSTANCE().dryRun() && kul::LogMan::INSTANCE().inf()) {
      if (!app.arg.empty()) KOUT(NON) << "ARGUMENTS\n\t" << app.arg;
      if (app.arguments().size()) {
        KOUT(NON) << "FILE ARGUMENTS";
        for (const auto& kv : app.arguments())
          for (const std::string& s : kv.second)
            KOUT(NON) << "\t" << kv.first << " : " << s;
      }
      if (!AppVars::INSTANCE().args().empty())
        KOUT(NON) << "ADDITIONAL ARGUMENTS: \n\t" << AppVars::INSTANCE().args();
      if (AppVars::INSTANCE().jargs().size()) {
        KOUT(NON) << "ADDITIONAL FILE ARGUMENTS:";
        for (const auto& kv : AppVars::INSTANCE().jargs())
          KOUT(NON) << "\t" << kv.first << " : " << kv.second;
      }
    }
    if (!AppVars::INSTANCE().envVars().count("MKN_OBJ"))
      KEXCEPTION("INTERNAL BADNESS ERROR!");
  }
};
}  // namespace maiken

void maiken::Application::compile(kul::hash::set::String& objects)
    KTHROW(kul::Exception) {
  auto sources = sourceMap();

  showConfig();
  CompilerPrinter::print_for(*this);

  SourceFinder s_finder(*this);
  CompilerValidation::check_compiler_for(*this, sources);
  std::vector<kul::File> cacheFiles;
  auto src_objs = s_finder.all_sources_from(sources, objects, cacheFiles);

  compile(src_objs, objects, cacheFiles);
}

void maiken::Application::compile(
    std::vector<std::pair<std::string, std::string>>& src_objs,
    kul::hash::set::String& objects, std::vector<kul::File>& cacheFiles)
    KTHROW(kul::Exception) {
#if defined(_MKN_WITH_MKN_RAM_) && defined(_MKN_WITH_IO_CEREAL_)
  std::vector<std::shared_ptr<maiken::dist::Post>> posts;
  auto compile_lambda = [](std::shared_ptr<maiken::dist::Post> post,
                           const dist::Host& host) {
    post->send(host);
    dist::FileWriter fw;
    dist::Blob b;
    do {
      auto dowd = std::make_shared<maiken::dist::Post>(std::move(
          maiken::dist::RemoteCommandManager::INST().build_download_request()));
      dowd->send(host);
      std::string body(std::move(dowd->body()));
      std::istringstream iss(body);
      {
        cereal::PortableBinaryInputArchive iarchive(iss);
        iarchive(b);
      }
      size_t size = b.len;
      if (!b.file.empty()) {
        if (!fw.bw) {
          kul::File obj(b.file);
          if (obj) obj = kul::File(std::string(b.file + ".new"));
          fw.bw = std::make_unique<kul::io::BinaryWriter>(obj);
        }
        for (size_t i = 0; i < b.len; i++) (*fw.bw.get()) << b.c1[i];
      }
      if (b.last_packet) fw.bw.reset();
    } while (b.files_left > 0);

  };
  size_t threads = 0;

  auto& hosts(maiken::dist::RemoteCommandManager::INST().hosts());
  if (AppVars::INSTANCE().nodes()) {
    threads = (hosts.size() < AppVars::INSTANCE().nodes())
                  ? hosts.size()
                  : AppVars::INSTANCE().nodes();
  }
  kul::ChroncurrentThreadPool<> ctp(threads, 1, 1000000000, 1000);
  auto compile_ex = [&](const kul::Exception& e) {
    ctp.stop().interrupt();
    throw e;
  };
  {
    size_t sources = src_objs.size();
    size_t divisor = std::floor(sources / (threads + 1));
    for (size_t i = 0; i < threads; i++) {
      std::vector<std::pair<std::string, std::string>> remote_src_objs;
      for (size_t k = 0; k < divisor; k++) {
        remote_src_objs.push_back(src_objs[0]);
        src_objs.erase(src_objs.begin());
      }

      if (!remote_src_objs.empty()) {
        posts.emplace_back(std::make_shared<maiken::dist::Post>(std::move(
            maiken::dist::RemoteCommandManager::INST().build_compile_request(
                this->project().dir().real(), remote_src_objs))));
        ctp.async(std::bind(compile_lambda, posts[i], std::ref(hosts[i])),
                  compile_ex);
      }
    }
  }

#endif  //  _MKN_WITH_MKN_RAM_) && defined(_MKN_WITH_IO_CEREAL_)
  std::queue<std::pair<std::string, std::string>> sourceQueue;
  for (auto& so : src_objs) {
    sourceQueue.push(std::make_pair(so.first, so.second));
    kul::File object_file(so.second);
    if (!object_file.dir()) object_file.dir().mk();
  }
  if (!src_objs.empty()) compile(sourceQueue, objects, cacheFiles);
#if defined(_MKN_WITH_MKN_RAM_) && defined(_MKN_WITH_IO_CEREAL_)
  ctp.finish(10000000);  // 10 milliseconds
  ctp.rethrow();
#endif  //  _MKN_WITH_MKN_RAM_) && defined(_MKN_WITH_IO_CEREAL_)

  if (_MKN_TIMESTAMPS_) writeTimeStamps(objects, cacheFiles);
}

void maiken::Application::compile(
    std::queue<std::pair<std::string, std::string>>& sourceQueue,
    kul::hash::set::String& objects, std::vector<kul::File>& cacheFiles)
    KTHROW(kul::Exception) {
  ThreadingCompiler tc(*this);
  kul::ChroncurrentThreadPool<> ctp(AppVars::INSTANCE().threads(), 1,
                                    1000000000, 1000);
  std::vector<maiken::CompilationUnit> c_units;
  std::queue<std::pair<std::string, std::string>> cQueue;
  while (sourceQueue.size() > 0) {
    c_units.emplace_back(tc.compilationUnit(sourceQueue.front()));
    cQueue.push(sourceQueue.front());
    sourceQueue.pop();
  }

  auto o = [](const std::string& s) {
    if (s.size()) KOUT(NON) << s;
  };
  auto e = [](const std::string& s) {
    if (s.size()) KERR << s;
  };

  std::mutex mute;
  std::vector<CompilerProcessCapture> cpcs;
  auto lambda = [o, e, &ctp, &mute,
                 &cpcs](const maiken::CompilationUnit& c_unit) {
    if (ctp.exception()) ctp.interrupt();
    const CompilerProcessCapture cpc = c_unit.compile();
    if (!AppVars::INSTANCE().dryRun()) {
      if (kul::LogMan::INSTANCE().inf() || cpc.exception()) o(cpc.outs());
      if (kul::LogMan::INSTANCE().inf() || cpc.exception()) e(cpc.errs());
      KOUT(INF) << cpc.cmd();
    } else
      KOUT(NON) << cpc.cmd();
    std::lock_guard<std::mutex> lock(mute);
    cpcs.push_back(cpc);
  };

  auto lambex = [&](const kul::Exception& e) {
    ctp.stop();
    std::cerr << ":EXCEPTION!: " << e.debug() << std::endl;
    ctp.interrupt();
    throw e;
  };

  for (const auto& unit : c_units) {
    kul::this_thread::nSleep(
        5000000);  // dup appears to be overloaded with too many threads
    ctp.async(std::bind(lambda, unit),
              std::bind(lambex, std::placeholders::_1));
  }

  ctp.finish(1000000 * 1000);
  if (ctp.exception()) KEXIT(1, "Compile error detected");

  for (auto& cpc : cpcs) {
    if (cpc.exception()) std::rethrow_exception(cpc.exception());
  }

  while (cQueue.size()) {
    objects.insert(cQueue.front().second);
    cacheFiles.push_back(kul::File(cQueue.front().first));
    cQueue.pop();
  }
}
<|endoftext|>