<commit_before>// Copyright (c) 2017 Kai Luo <gluokai@gmail.com>. All rights reserved.
// Use of this source code is governed by the BSD license that can be found in
// the LICENSE file.

#include "scheduler.h"
#include "env.h"

namespace kl {

// REQUIRES: num_of_worker_threads >= 1
Scheduler::Scheduler(size_t num_of_worker_threads)
    : num_of_worker_threads_(num_of_worker_threads), stop_(false),
      task_queues_(nullptr), queue_round_robin_(0) {}

Scheduler::~Scheduler() {
  if (task_queues_) {
    delete[] task_queues_;
    task_queues_ = nullptr;
  }
}

kl::Status Scheduler::LaunchLoggingThread() {
  logger_ = std::make_unique<kl::logging::Logger>([this](const char *message) {
    logging_queue_.Push(std::string(message));
  });
  sync_.Add();
  std::thread([this] {
    kl::env::Defer defer([this] { sync_.Done(); });
    while (!stop_) {
      auto next = logging_queue_.Pop(5000);
      if (!next && logging_queue_.Closed()) {
        break;
      }
      if (next) {
        std::string &message = *next;
        std::fprintf(stderr, "%s", message.c_str());
      }
    }
  }).detach();
  return kl::Ok();
}

kl::Status Scheduler::RegisterEpollEvent(int fd, uint32_t events,
                                         EpollHandler &&callback) {
  auto status = epoll_.AddFd(fd, events);
  if (!status) {
    return status;
  }
  callback_mapping_rwlock_.WLock();
  callbacks_.insert(std::make_pair(fd, std::move(callback)));
  callback_mapping_rwlock_.WUnlock();
  return kl::Ok();
}

kl::Status Scheduler::UnregisterEpollEvent(int fd) {
  auto status = epoll_.DelFd(fd);
  if (!status) {
    return status;
  }
  callback_mapping_rwlock_.WLock();
  callbacks_.erase(fd);
  callback_mapping_rwlock_.WUnlock();
  return kl::Ok();
}

void Scheduler::SubmitTask(std::function<void(void)> &&task) {
  size_t current = queue_round_robin_++;
  current = current % num_of_worker_threads_;
  task_queues_[current].Push(std::move(task));
}

kl::Status Scheduler::LaunchEpollThread() {
  sync_.Add();
  std::thread([this] {
    kl::env::Defer defer([this] { sync_.Done(); });
    while (!stop_) {
      auto wait = epoll_.Wait(64, 5000);
      if (!wait) {
        Stop(wait.Err().ToCString());
        break;
      }
      for (const auto &event : *wait) {
        int fd = event.data.fd;
        uint32_t events = event.events;
        callback_mapping_rwlock_.RLock();
        auto iter = callbacks_.find(fd);
        if (iter == callbacks_.end()) {
          KL_DEBUG_L(Logger(), "callback for fd %d is empty");
          callback_mapping_rwlock_.RUnlock();
          continue;
        }
        SubmitTask([ handler = iter->second, events ] { handler(events); });
        callback_mapping_rwlock_.RUnlock();
      }
    }
  }).detach();
  return kl::Ok();
}

void Scheduler::WorkerRoutine(size_t id) {
  kl::env::Defer defer([this] { sync_.Done(); });
  while (!stop_) {
    auto task = task_queues_[id].Pop(5000);
    if (!task && task_queues_[id].Closed()) {
      break;
    }
    if (task) {
      try {
        (*task)();
      } catch (const std::exception &e) {
        KL_ERROR_L(Logger(), e.what());
      }
    }
  }
}

kl::logging::Logger &Scheduler::Logger() {
  assert(logger_);
  return *logger_;
}

kl::Status Scheduler::Go() {
  auto status = LaunchLoggingThread();
  if (!status) {
    Stop(status.Err().ToCString());
    return status;
  }
  status = LaunchEpollThread();
  if (!status) {
    Stop(status.Err().ToCString());
    return status;
  }
  status = LaunchWorkerThreads();
  if (!status) {
    Stop(status.Err().ToCString());
    return status;
  }
  sync_.Wait();
  if (!exit_reason_.empty()) {
    return kl::Err(exit_reason_.c_str());
  }
  return kl::Ok();
}

void Scheduler::Stop(const char *reason) {
  if (reason) {
    exit_reason_ = reason;
  }
  stop_.store(true);
}

kl::Status Scheduler::LaunchWorkerThreads() {
  task_queues_ =
      new kl::Chan<std::function<void(void)>>[num_of_worker_threads_];
  for (size_t i = 0; i < num_of_worker_threads_; ++i) {
    sync_.Add();
    std::thread([this, i] { WorkerRoutine(i); }).detach();
  }
  return kl::Ok();
}

}  // namespace kl
<commit_msg>minor fix<commit_after>// Copyright (c) 2017 Kai Luo <gluokai@gmail.com>. All rights reserved.
// Use of this source code is governed by the BSD license that can be found in
// the LICENSE file.

#include "scheduler.h"
#include "env.h"

namespace kl {

namespace {
const int kLoggingThreadWaitTimeout = 5000;
const int kEpollThreadWaitTimeout = 5000;
const int kWorkerThreadWaitTimeout = 5000;
}

// REQUIRES: num_of_worker_threads >= 1
Scheduler::Scheduler(size_t num_of_worker_threads)
    : num_of_worker_threads_(num_of_worker_threads), stop_(false),
      task_queues_(nullptr), queue_round_robin_(0) {}

Scheduler::~Scheduler() {
  if (task_queues_) {
    delete[] task_queues_;
    task_queues_ = nullptr;
  }
}

kl::Status Scheduler::LaunchLoggingThread() {
  logger_ = std::make_unique<kl::logging::Logger>([this](const char *message) {
    logging_queue_.Push(std::string(message));
  });
  sync_.Add();
  std::thread([this] {
    kl::env::Defer defer([this] { sync_.Done(); });
    while (!stop_) {
      auto next = logging_queue_.Pop(kLoggingThreadWaitTimeout);
      if (!next && logging_queue_.Closed()) {
        break;
      }
      if (next) {
        std::string &message = *next;
        std::fprintf(stderr, "%s", message.c_str());
      }
    }
  }).detach();
  return kl::Ok();
}

kl::Status Scheduler::RegisterEpollEvent(int fd, uint32_t events,
                                         EpollHandler &&callback) {
  auto status = epoll_.AddFd(fd, events);
  if (!status) {
    return status;
  }
  callback_mapping_rwlock_.WLock();
  callbacks_.insert(std::make_pair(fd, std::move(callback)));
  callback_mapping_rwlock_.WUnlock();
  return kl::Ok();
}

kl::Status Scheduler::UnregisterEpollEvent(int fd) {
  auto status = epoll_.DelFd(fd);
  if (!status) {
    return status;
  }
  callback_mapping_rwlock_.WLock();
  callbacks_.erase(fd);
  callback_mapping_rwlock_.WUnlock();
  return kl::Ok();
}

void Scheduler::SubmitTask(std::function<void(void)> &&task) {
  size_t current = queue_round_robin_++;
  current = current % num_of_worker_threads_;
  task_queues_[current].Push(std::move(task));
}

kl::Status Scheduler::LaunchEpollThread() {
  sync_.Add();
  std::thread([this] {
    kl::env::Defer defer([this] { sync_.Done(); });
    while (!stop_) {
      auto wait = epoll_.Wait(64, kEpollThreadWaitTimeout);
      if (!wait) {
        Stop(wait.Err().ToCString());
        break;
      }
      for (const auto &event : *wait) {
        int fd = event.data.fd;
        uint32_t events = event.events;
        callback_mapping_rwlock_.RLock();
        auto iter = callbacks_.find(fd);
        if (iter == callbacks_.end()) {
          KL_DEBUG_L(Logger(), "callback for fd %d is empty");
          callback_mapping_rwlock_.RUnlock();
          continue;
        }
        SubmitTask([ handler = iter->second, events ] { handler(events); });
        callback_mapping_rwlock_.RUnlock();
      }
    }
  }).detach();
  return kl::Ok();
}

void Scheduler::WorkerRoutine(size_t id) {
  kl::env::Defer defer([this] { sync_.Done(); });
  while (!stop_) {
    auto task = task_queues_[id].Pop(kWorkerThreadWaitTimeout);
    if (!task && task_queues_[id].Closed()) {
      break;
    }
    if (task) {
      try {
        (*task)();
      } catch (const std::exception &e) {
        KL_ERROR_L(Logger(), e.what());
      }
    }
  }
}

kl::logging::Logger &Scheduler::Logger() {
  assert(logger_);
  return *logger_;
}

kl::Status Scheduler::Go() {
  auto status = LaunchLoggingThread();
  if (!status) {
    Stop(status.Err().ToCString());
    return status;
  }
  status = LaunchEpollThread();
  if (!status) {
    Stop(status.Err().ToCString());
    return status;
  }
  status = LaunchWorkerThreads();
  if (!status) {
    Stop(status.Err().ToCString());
    return status;
  }
  sync_.Wait();
  if (!exit_reason_.empty()) {
    return kl::Err(exit_reason_.c_str());
  }
  return kl::Ok();
}

void Scheduler::Stop(const char *reason) {
  if (reason) {
    exit_reason_ = reason;
  }
  stop_.store(true);
}

kl::Status Scheduler::LaunchWorkerThreads() {
  task_queues_ =
      new kl::Chan<std::function<void(void)>>[num_of_worker_threads_];
  for (size_t i = 0; i < num_of_worker_threads_; ++i) {
    sync_.Add();
    std::thread([this, i] { WorkerRoutine(i); }).detach();
  }
  return kl::Ok();
}

}  // namespace kl
<|endoftext|>


<commit_before>// Alexis Giraudet
// Théo Cesbron

#ifndef HASH_TABLE_HPP
#define HASH_TABLE_HPP

#include <functional>
#include <exception>
#include "dictionary.hpp"

template <typename K, typename V, int S=100>
class hash_table
{
    private:
        dictionary *_dictionaries;

    public:
        hash_table();
        ~hash_table();
};

template <typename K, typename V, int S>
hash_table<K,V>::hash_table()
{
    _dictionaries = new dictionary[S];
}

template <typename K, typename V, int S>
hash_table<K,V>::~hash_table()
{

    ;
}

#endif
<commit_msg>add some functions<commit_after>// Alexis Giraudet
// Théo Cesbron

#ifndef HASH_TABLE_HPP
#define HASH_TABLE_HPP

#include <functional>
#include <exception>
#include "dictionary.hpp"

template <typename K, typename V, int S=100>
class hash_table
{
    private:
        dictionary *_dictionaries;
        std::hash<K> _hash_fn;

    public:
        hash_table();
        ~hash_table();
        void clear();
        bool contains_key(K key);
        bool contains_value(V value);
        V get(K key);
        bool is_empty();
        //K* keys_array();
        std::ostream& print();
        std::ostream& print(std::ostream &os);
        bool put(K key, V value);
        bool remove(K key);
        int size();
        //V* values_array();
};

template <typename K, typename V, int S>
hash_table<K,V,S>::hash_table(): _dictionaries(0)
{
    _dictionaries = new dictionary[S];
}

template <typename K, typename V, int S>
hash_table<K,V,S>::~hash_table()
{

    delete[] _dictionaries;
}

template <typename K, typename V, int S>
V hash_table<K,V,S>::get(K key)
{
    size_t i = _hash_fn(key)%S;
    return _dictionaries[i].get(key);
}

template <typename K, typename V, int S>
bool hash_table<K,V,S>::put(K key, V value)
{
    size_t i = _hash_fn(key)%S;
    return _dictionaries[i].put(key,value);
}

template <typename K, typename V, int S>
bool hash_table<K,V,S>::remove(K key)
{
    size_t i = _hash_fn(key)%S;
    return _dictionaries[i].remove(key);
}

template <typename K, typename V, int S>
int hash_table<K,V,S>::size()
{
    return S;
}

#endif
<|endoftext|>


<commit_before>// Copyright (c) 2016 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.

#include "modaloverlay.h"
#include "ui_modaloverlay.h"

#include "guiutil.h"

#include "chainparams.h"

#include <QResizeEvent>
#include <QPropertyAnimation>

ModalOverlay::ModalOverlay(QWidget *parent) :
QWidget(parent),
ui(new Ui::ModalOverlay),
bestHeaderHeight(0),
bestHeaderDate(QDateTime()),
layerIsVisible(false),
userClosed(false)
{
    ui->setupUi(this);
    connect(ui->closeButton, SIGNAL(clicked()), this, SLOT(closeClicked()));
    if (parent) {
        parent->installEventFilter(this);
        raise();
    }

    blockProcessTime.clear();
    setVisible(false);
}

ModalOverlay::~ModalOverlay()
{
    delete ui;
}

bool ModalOverlay::eventFilter(QObject * obj, QEvent * ev) {
    if (obj == parent()) {
        if (ev->type() == QEvent::Resize) {
            QResizeEvent * rev = static_cast<QResizeEvent*>(ev);
            resize(rev->size());
            if (!layerIsVisible)
                setGeometry(0, height(), width(), height());

        }
        else if (ev->type() == QEvent::ChildAdded) {
            raise();
        }
    }
    return QWidget::eventFilter(obj, ev);
}

//! Tracks parent widget changes
bool ModalOverlay::event(QEvent* ev) {
    if (ev->type() == QEvent::ParentAboutToChange) {
        if (parent()) parent()->removeEventFilter(this);
    }
    else if (ev->type() == QEvent::ParentChange) {
        if (parent()) {
            parent()->installEventFilter(this);
            raise();
        }
    }
    return QWidget::event(ev);
}

void ModalOverlay::setKnownBestHeight(int count, const QDateTime& blockDate)
{
    if (count > bestHeaderHeight) {
        bestHeaderHeight = count;
        bestHeaderDate = blockDate;
    }
}

void ModalOverlay::tipUpdate(int count, const QDateTime& blockDate, double nVerificationProgress)
{
    QDateTime currentDate = QDateTime::currentDateTime();

    // keep a vector of samples of verification progress at height
    blockProcessTime.push_front(qMakePair(currentDate.toMSecsSinceEpoch(), nVerificationProgress));

    // show progress speed if we have more then one sample
    if (blockProcessTime.size() >= 2)
    {
        double progressStart = blockProcessTime[0].second;
        double progressDelta = 0;
        double progressPerHour = 0;
        qint64 timeDelta = 0;
        qint64 remainingMSecs = 0;
        double remainingProgress = 1.0 - nVerificationProgress;
        for (int i = 1; i < blockProcessTime.size(); i++)
        {
            QPair<qint64, double> sample = blockProcessTime[i];

            // take first sample after 500 seconds or last available one
            if (sample.first < (currentDate.toMSecsSinceEpoch() - 500 * 1000) || i == blockProcessTime.size() - 1) {
                progressDelta = progressStart-sample.second;
                timeDelta = blockProcessTime[0].first - sample.first;
                progressPerHour = progressDelta/(double)timeDelta*1000*3600;
                remainingMSecs = remainingProgress / progressDelta * timeDelta;
                break;
            }
        }
        // show progress increase per hour
        ui->progressIncreasePerH->setText(QString::number(progressPerHour*100, 'f', 2)+"%");

        // show expected remaining time
        ui->expectedTimeLeft->setText(GUIUtil::formatNiceTimeOffset(remainingMSecs/1000.0));

        static const int MAX_SAMPLES = 5000;
        if (blockProcessTime.count() > MAX_SAMPLES)
            blockProcessTime.remove(MAX_SAMPLES, blockProcessTime.count()-MAX_SAMPLES);
    }

    // show the last block date
    ui->newestBlockDate->setText(blockDate.toString());

    // show the percentage done according to nVerificationProgress
    ui->percentageProgress->setText(QString::number(nVerificationProgress*100, 'f', 2)+"%");
    ui->progressBar->setValue(nVerificationProgress*100);

    if (!bestHeaderDate.isValid())
        // not syncing
        return;

    // estimate the number of headers left based on nPowTargetSpacing
    // and check if the gui is not aware of the best header (happens rarely)
    int estimateNumHeadersLeft = bestHeaderDate.secsTo(currentDate) / Params().GetConsensus().nPowTargetSpacing;
    bool hasBestHeader = bestHeaderHeight >= count;

    // show remaining number of blocks
    if (estimateNumHeadersLeft < HEADER_HEIGHT_DELTA_SYNC && hasBestHeader) {
        ui->numberOfBlocksLeft->setText(QString::number(bestHeaderHeight - count));
    } else {
        ui->numberOfBlocksLeft->setText(tr("Unknown. Syncing Headers (%1)...").arg(bestHeaderHeight));
        ui->expectedTimeLeft->setText(tr("Unknown..."));
    }
}

void ModalOverlay::toggleVisibility()
{
    showHide(layerIsVisible, true);
    if (!layerIsVisible)
        userClosed = true;
}

void ModalOverlay::showHide(bool hide, bool userRequested)
{
    if ( (layerIsVisible && !hide) || (!layerIsVisible && hide) || (!hide && userClosed && !userRequested))
        return;

    if (!isVisible() && !hide)
        setVisible(true);

    setGeometry(0, hide ? 0 : height(), width(), height());

    QPropertyAnimation* animation = new QPropertyAnimation(this, "pos");
    animation->setDuration(300);
    animation->setStartValue(QPoint(0, hide ? 0 : this->height()));
    animation->setEndValue(QPoint(0, hide ? this->height() : 0));
    animation->setEasingCurve(QEasingCurve::OutQuad);
    animation->start(QAbstractAnimation::DeleteWhenStopped);
    layerIsVisible = !hide;
}

void ModalOverlay::closeClicked()
{
    showHide(true);
    userClosed = true;
}
<commit_msg>Fix division by zero in time remaining<commit_after>// Copyright (c) 2016 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.

#include "modaloverlay.h"
#include "ui_modaloverlay.h"

#include "guiutil.h"

#include "chainparams.h"

#include <QResizeEvent>
#include <QPropertyAnimation>

ModalOverlay::ModalOverlay(QWidget *parent) :
QWidget(parent),
ui(new Ui::ModalOverlay),
bestHeaderHeight(0),
bestHeaderDate(QDateTime()),
layerIsVisible(false),
userClosed(false)
{
    ui->setupUi(this);
    connect(ui->closeButton, SIGNAL(clicked()), this, SLOT(closeClicked()));
    if (parent) {
        parent->installEventFilter(this);
        raise();
    }

    blockProcessTime.clear();
    setVisible(false);
}

ModalOverlay::~ModalOverlay()
{
    delete ui;
}

bool ModalOverlay::eventFilter(QObject * obj, QEvent * ev) {
    if (obj == parent()) {
        if (ev->type() == QEvent::Resize) {
            QResizeEvent * rev = static_cast<QResizeEvent*>(ev);
            resize(rev->size());
            if (!layerIsVisible)
                setGeometry(0, height(), width(), height());

        }
        else if (ev->type() == QEvent::ChildAdded) {
            raise();
        }
    }
    return QWidget::eventFilter(obj, ev);
}

//! Tracks parent widget changes
bool ModalOverlay::event(QEvent* ev) {
    if (ev->type() == QEvent::ParentAboutToChange) {
        if (parent()) parent()->removeEventFilter(this);
    }
    else if (ev->type() == QEvent::ParentChange) {
        if (parent()) {
            parent()->installEventFilter(this);
            raise();
        }
    }
    return QWidget::event(ev);
}

void ModalOverlay::setKnownBestHeight(int count, const QDateTime& blockDate)
{
    if (count > bestHeaderHeight) {
        bestHeaderHeight = count;
        bestHeaderDate = blockDate;
    }
}

void ModalOverlay::tipUpdate(int count, const QDateTime& blockDate, double nVerificationProgress)
{
    QDateTime currentDate = QDateTime::currentDateTime();

    // keep a vector of samples of verification progress at height
    blockProcessTime.push_front(qMakePair(currentDate.toMSecsSinceEpoch(), nVerificationProgress));

    // show progress speed if we have more then one sample
    if (blockProcessTime.size() >= 2)
    {
        double progressStart = blockProcessTime[0].second;
        double progressDelta = 0;
        double progressPerHour = 0;
        qint64 timeDelta = 0;
        qint64 remainingMSecs = 0;
        double remainingProgress = 1.0 - nVerificationProgress;
        for (int i = 1; i < blockProcessTime.size(); i++)
        {
            QPair<qint64, double> sample = blockProcessTime[i];

            // take first sample after 500 seconds or last available one
            if (sample.first < (currentDate.toMSecsSinceEpoch() - 500 * 1000) || i == blockProcessTime.size() - 1) {
                progressDelta = progressStart-sample.second;
                timeDelta = blockProcessTime[0].first - sample.first;
                progressPerHour = progressDelta/(double)timeDelta*1000*3600;
                remainingMSecs = (progressDelta > 0) ? remainingProgress / progressDelta * timeDelta : -1;
                break;
            }
        }
        // show progress increase per hour
        ui->progressIncreasePerH->setText(QString::number(progressPerHour*100, 'f', 2)+"%");

        if(remainingMSecs >= 0) {
            ui->expectedTimeLeft->setText(GUIUtil::formatNiceTimeOffset(remainingMSecs / 1000.0));
        } else {
            ui->expectedTimeLeft->setText(QObject::tr("unknown"));
        }

        static const int MAX_SAMPLES = 5000;
        if (blockProcessTime.count() > MAX_SAMPLES)
            blockProcessTime.remove(MAX_SAMPLES, blockProcessTime.count()-MAX_SAMPLES);
    }

    // show the last block date
    ui->newestBlockDate->setText(blockDate.toString());

    // show the percentage done according to nVerificationProgress
    ui->percentageProgress->setText(QString::number(nVerificationProgress*100, 'f', 2)+"%");
    ui->progressBar->setValue(nVerificationProgress*100);

    if (!bestHeaderDate.isValid())
        // not syncing
        return;

    // estimate the number of headers left based on nPowTargetSpacing
    // and check if the gui is not aware of the best header (happens rarely)
    int estimateNumHeadersLeft = bestHeaderDate.secsTo(currentDate) / Params().GetConsensus().nPowTargetSpacing;
    bool hasBestHeader = bestHeaderHeight >= count;

    // show remaining number of blocks
    if (estimateNumHeadersLeft < HEADER_HEIGHT_DELTA_SYNC && hasBestHeader) {
        ui->numberOfBlocksLeft->setText(QString::number(bestHeaderHeight - count));
    } else {
        ui->numberOfBlocksLeft->setText(tr("Unknown. Syncing Headers (%1)...").arg(bestHeaderHeight));
        ui->expectedTimeLeft->setText(tr("Unknown..."));
    }
}

void ModalOverlay::toggleVisibility()
{
    showHide(layerIsVisible, true);
    if (!layerIsVisible)
        userClosed = true;
}

void ModalOverlay::showHide(bool hide, bool userRequested)
{
    if ( (layerIsVisible && !hide) || (!layerIsVisible && hide) || (!hide && userClosed && !userRequested))
        return;

    if (!isVisible() && !hide)
        setVisible(true);

    setGeometry(0, hide ? 0 : height(), width(), height());

    QPropertyAnimation* animation = new QPropertyAnimation(this, "pos");
    animation->setDuration(300);
    animation->setStartValue(QPoint(0, hide ? 0 : this->height()));
    animation->setEndValue(QPoint(0, hide ? this->height() : 0));
    animation->setEasingCurve(QEasingCurve::OutQuad);
    animation->start(QAbstractAnimation::DeleteWhenStopped);
    layerIsVisible = !hide;
}

void ModalOverlay::closeClicked()
{
    showHide(true);
    userClosed = true;
}<|endoftext|>


<commit_before>// Copyright (c) 2011-2014 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.

#if defined(HAVE_CONFIG_H)
#include "config/bitcoin-config.h"
#endif

#include "optionsmodel.h"

#include "bitcoinunits.h"
#include "guiutil.h"

#include "amount.h"
#include "init.h"
#include "main.h"
#include "net.h"
#include "txdb.h" // for -dbcache defaults

#ifdef ENABLE_WALLET
#include "wallet/wallet.h"
#include "wallet/walletdb.h"
#endif

#include <QNetworkProxy>
#include <QSettings>
#include <QStringList>

OptionsModel::OptionsModel(QObject *parent) :
    QAbstractListModel(parent)
{
    Init();
}

void OptionsModel::addOverriddenOption(const std::string &option)
{
    strOverriddenByCommandLine += QString::fromStdString(option) + "=" + QString::fromStdString(mapArgs[option]) + " ";
}

// Writes all missing QSettings with their default values
void OptionsModel::Init()
{
    QSettings settings;

    // Ensure restart flag is unset on client startup
    setRestartRequired(false);

    // These are Qt-only settings:

    // Window
    if (!settings.contains("fMinimizeToTray"))
        settings.setValue("fMinimizeToTray", false);
    fMinimizeToTray = settings.value("fMinimizeToTray").toBool();

    if (!settings.contains("fMinimizeOnClose"))
        settings.setValue("fMinimizeOnClose", false);
    fMinimizeOnClose = settings.value("fMinimizeOnClose").toBool();

    // Display
    if (!settings.contains("nDisplayUnit"))
        settings.setValue("nDisplayUnit", BitcoinUnits::BTC);
    nDisplayUnit = settings.value("nDisplayUnit").toInt();

    if (!settings.contains("strThirdPartyTxUrls"))
        settings.setValue("strThirdPartyTxUrls", "https://cryptap.us/myr/explorer/tx/%s");
    strThirdPartyTxUrls = settings.value("strThirdPartyTxUrls", "").toString();

    if (!settings.contains("fCoinControlFeatures"))
        settings.setValue("fCoinControlFeatures", false);
    fCoinControlFeatures = settings.value("fCoinControlFeatures", false).toBool();

    // These are shared with the core or have a command-line parameter
    // and we want command-line parameters to overwrite the GUI settings.
    //
    // If setting doesn't exist create it with defaults.
    //
    // If SoftSetArg() or SoftSetBoolArg() return false we were overridden
    // by command-line and show this in the UI.

    // Main
    if (!settings.contains("nDatabaseCache"))
        settings.setValue("nDatabaseCache", (qint64)nDefaultDbCache);
    if (!SoftSetArg("-dbcache", settings.value("nDatabaseCache").toString().toStdString()))
        addOverriddenOption("-dbcache");

    if (!settings.contains("nThreadsScriptVerif"))
        settings.setValue("nThreadsScriptVerif", DEFAULT_SCRIPTCHECK_THREADS);
    if (!SoftSetArg("-par", settings.value("nThreadsScriptVerif").toString().toStdString()))
        addOverriddenOption("-par");

    // Wallet
#ifdef ENABLE_WALLET
    if (!settings.contains("bSpendZeroConfChange"))
        settings.setValue("bSpendZeroConfChange", true);
    if (!SoftSetBoolArg("-spendzeroconfchange", settings.value("bSpendZeroConfChange").toBool()))
        addOverriddenOption("-spendzeroconfchange");
#endif

    // Network
    if (!settings.contains("fUseUPnP"))
        settings.setValue("fUseUPnP", DEFAULT_UPNP);
    if (!SoftSetBoolArg("-upnp", settings.value("fUseUPnP").toBool()))
        addOverriddenOption("-upnp");

    if (!settings.contains("fListen"))
        settings.setValue("fListen", DEFAULT_LISTEN);
    if (!SoftSetBoolArg("-listen", settings.value("fListen").toBool()))
        addOverriddenOption("-listen");

    if (!settings.contains("fUseProxy"))
        settings.setValue("fUseProxy", false);
    if (!settings.contains("addrProxy"))
        settings.setValue("addrProxy", "127.0.0.1:9050");
    // Only try to set -proxy, if user has enabled fUseProxy
    if (settings.value("fUseProxy").toBool() && !SoftSetArg("-proxy", settings.value("addrProxy").toString().toStdString()))
        addOverriddenOption("-proxy");
    else if(!settings.value("fUseProxy").toBool() && !GetArg("-proxy", "").empty())
        addOverriddenOption("-proxy");

    // Display
    if (!settings.contains("language"))
        settings.setValue("language", "");
    if (!SoftSetArg("-lang", settings.value("language").toString().toStdString()))
        addOverriddenOption("-lang");

    language = settings.value("language").toString();
}

void OptionsModel::Reset()
{
    QSettings settings;

    // Remove all entries from our QSettings object
    settings.clear();

    // default setting for OptionsModel::StartAtStartup - disabled
    if (GUIUtil::GetStartOnSystemStartup())
        GUIUtil::SetStartOnSystemStartup(false);
}

int OptionsModel::rowCount(const QModelIndex & parent) const
{
    return OptionIDRowCount;
}

// read QSettings values and return them
QVariant OptionsModel::data(const QModelIndex & index, int role) const
{
    if(role == Qt::EditRole)
    {
        QSettings settings;
        switch(index.row())
        {
        case StartAtStartup:
            return GUIUtil::GetStartOnSystemStartup();
        case MinimizeToTray:
            return fMinimizeToTray;
        case MapPortUPnP:
#ifdef USE_UPNP
            return settings.value("fUseUPnP");
#else
            return false;
#endif
        case MinimizeOnClose:
            return fMinimizeOnClose;

        // default proxy
        case ProxyUse:
            return settings.value("fUseProxy", false);
        case ProxyIP: {
            // contains IP at index 0 and port at index 1
            QStringList strlIpPort = settings.value("addrProxy").toString().split(":", QString::SkipEmptyParts);
            return strlIpPort.at(0);
        }
        case ProxyPort: {
            // contains IP at index 0 and port at index 1
            QStringList strlIpPort = settings.value("addrProxy").toString().split(":", QString::SkipEmptyParts);
            return strlIpPort.at(1);
        }

#ifdef ENABLE_WALLET
        case SpendZeroConfChange:
            return settings.value("bSpendZeroConfChange");
#endif
        case DisplayUnit:
            return nDisplayUnit;
        case ThirdPartyTxUrls:
            return strThirdPartyTxUrls;
        case Language:
            return settings.value("language");
        case CoinControlFeatures:
            return fCoinControlFeatures;
        case DatabaseCache:
            return settings.value("nDatabaseCache");
        case ThreadsScriptVerif:
            return settings.value("nThreadsScriptVerif");
        case Listen:
            return settings.value("fListen");
        default:
            return QVariant();
        }
    }
    return QVariant();
}

// write QSettings values
bool OptionsModel::setData(const QModelIndex & index, const QVariant & value, int role)
{
    bool successful = true; /* set to false on parse error */
    if(role == Qt::EditRole)
    {
        QSettings settings;
        switch(index.row())
        {
        case StartAtStartup:
            successful = GUIUtil::SetStartOnSystemStartup(value.toBool());
            break;
        case MinimizeToTray:
            fMinimizeToTray = value.toBool();
            settings.setValue("fMinimizeToTray", fMinimizeToTray);
            break;
        case MapPortUPnP: // core option - can be changed on-the-fly
            settings.setValue("fUseUPnP", value.toBool());
            MapPort(value.toBool());
            break;
        case MinimizeOnClose:
            fMinimizeOnClose = value.toBool();
            settings.setValue("fMinimizeOnClose", fMinimizeOnClose);
            break;

        // default proxy
        case ProxyUse:
            if (settings.value("fUseProxy") != value) {
                settings.setValue("fUseProxy", value.toBool());
                setRestartRequired(true);
            }
            break;
        case ProxyIP: {
            // contains current IP at index 0 and current port at index 1
            QStringList strlIpPort = settings.value("addrProxy").toString().split(":", QString::SkipEmptyParts);
            // if that key doesn't exist or has a changed IP
            if (!settings.contains("addrProxy") || strlIpPort.at(0) != value.toString()) {
                // construct new value from new IP and current port
                QString strNewValue = value.toString() + ":" + strlIpPort.at(1);
                settings.setValue("addrProxy", strNewValue);
                setRestartRequired(true);
            }
        }
        break;
        case ProxyPort: {
            // contains current IP at index 0 and current port at index 1
            QStringList strlIpPort = settings.value("addrProxy").toString().split(":", QString::SkipEmptyParts);
            // if that key doesn't exist or has a changed port
            if (!settings.contains("addrProxy") || strlIpPort.at(1) != value.toString()) {
                // construct new value from current IP and new port
                QString strNewValue = strlIpPort.at(0) + ":" + value.toString();
                settings.setValue("addrProxy", strNewValue);
                setRestartRequired(true);
            }
        }
        break;
#ifdef ENABLE_WALLET
        case SpendZeroConfChange:
            if (settings.value("bSpendZeroConfChange") != value) {
                settings.setValue("bSpendZeroConfChange", value);
                setRestartRequired(true);
            }
            break;
#endif
        case DisplayUnit:
            setDisplayUnit(value);
            break;
        case ThirdPartyTxUrls:
            if (strThirdPartyTxUrls != value.toString()) {
                strThirdPartyTxUrls = value.toString();
                settings.setValue("strThirdPartyTxUrls", strThirdPartyTxUrls);
                setRestartRequired(true);
            }
            break;
        case Language:
            if (settings.value("language") != value) {
                settings.setValue("language", value);
                setRestartRequired(true);
            }
            break;
        case CoinControlFeatures:
            fCoinControlFeatures = value.toBool();
            settings.setValue("fCoinControlFeatures", fCoinControlFeatures);
            Q_EMIT coinControlFeaturesChanged(fCoinControlFeatures);
            break;
        case DatabaseCache:
            if (settings.value("nDatabaseCache") != value) {
                settings.setValue("nDatabaseCache", value);
                setRestartRequired(true);
            }
            break;
        case ThreadsScriptVerif:
            if (settings.value("nThreadsScriptVerif") != value) {
                settings.setValue("nThreadsScriptVerif", value);
                setRestartRequired(true);
            }
            break;
        case Listen:
            if (settings.value("fListen") != value) {
                settings.setValue("fListen", value);
                setRestartRequired(true);
            }
            break;
        default:
            break;
        }
    }

    Q_EMIT dataChanged(index, index);

    return successful;
}

/** Updates current unit in memory, settings and emits displayUnitChanged(newUnit) signal */
void OptionsModel::setDisplayUnit(const QVariant &value)
{
    if (!value.isNull())
    {
        QSettings settings;
        nDisplayUnit = value.toInt();
        settings.setValue("nDisplayUnit", nDisplayUnit);
        Q_EMIT displayUnitChanged(nDisplayUnit);
    }
}

bool OptionsModel::getProxySettings(QNetworkProxy& proxy) const
{
    // Directly query current base proxy, because
    // GUI settings can be overridden with -proxy.
    proxyType curProxy;
    if (GetProxy(NET_IPV4, curProxy)) {
        proxy.setType(QNetworkProxy::Socks5Proxy);
        proxy.setHostName(QString::fromStdString(curProxy.proxy.ToStringIP()));
        proxy.setPort(curProxy.proxy.GetPort());

        return true;
    }
    else
        proxy.setType(QNetworkProxy::NoProxy);

    return false;
}

void OptionsModel::setRestartRequired(bool fRequired)
{
    QSettings settings;
    return settings.setValue("fRestartRequired", fRequired);
}

bool OptionsModel::isRestartRequired()
{
    QSettings settings;
    return settings.value("fRestartRequired", false).toBool();
}
<commit_msg>Update optionsmodel.cpp<commit_after>// Copyright (c) 2011-2014 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.

#if defined(HAVE_CONFIG_H)
#include "config/bitcoin-config.h"
#endif

#include "optionsmodel.h"

#include "bitcoinunits.h"
#include "guiutil.h"

#include "amount.h"
#include "init.h"
#include "main.h"
#include "net.h"
#include "txdb.h" // for -dbcache defaults

#ifdef ENABLE_WALLET
#include "wallet/wallet.h"
#include "wallet/walletdb.h"
#endif

#include <QNetworkProxy>
#include <QSettings>
#include <QStringList>

OptionsModel::OptionsModel(QObject *parent) :
    QAbstractListModel(parent)
{
    Init();
}

void OptionsModel::addOverriddenOption(const std::string &option)
{
    strOverriddenByCommandLine += QString::fromStdString(option) + "=" + QString::fromStdString(mapArgs[option]) + " ";
}

// Writes all missing QSettings with their default values
void OptionsModel::Init()
{
    QSettings settings;

    // Ensure restart flag is unset on client startup
    setRestartRequired(false);

    // These are Qt-only settings:

    // Window
    if (!settings.contains("fMinimizeToTray"))
        settings.setValue("fMinimizeToTray", false);
    fMinimizeToTray = settings.value("fMinimizeToTray").toBool();

    if (!settings.contains("fMinimizeOnClose"))
        settings.setValue("fMinimizeOnClose", false);
    fMinimizeOnClose = settings.value("fMinimizeOnClose").toBool();

    // Display
    if (!settings.contains("nDisplayUnit"))
        settings.setValue("nDisplayUnit", BitcoinUnits::BTC);
    nDisplayUnit = settings.value("nDisplayUnit").toInt();

    if (!settings.contains("strThirdPartyTxUrls"))
        settings.setValue("strThirdPartyTxUrls", "http://insight-myr.cryptap.us/tx/%s");
    strThirdPartyTxUrls = settings.value("strThirdPartyTxUrls", "").toString();

    if (!settings.contains("fCoinControlFeatures"))
        settings.setValue("fCoinControlFeatures", false);
    fCoinControlFeatures = settings.value("fCoinControlFeatures", false).toBool();

    // These are shared with the core or have a command-line parameter
    // and we want command-line parameters to overwrite the GUI settings.
    //
    // If setting doesn't exist create it with defaults.
    //
    // If SoftSetArg() or SoftSetBoolArg() return false we were overridden
    // by command-line and show this in the UI.

    // Main
    if (!settings.contains("nDatabaseCache"))
        settings.setValue("nDatabaseCache", (qint64)nDefaultDbCache);
    if (!SoftSetArg("-dbcache", settings.value("nDatabaseCache").toString().toStdString()))
        addOverriddenOption("-dbcache");

    if (!settings.contains("nThreadsScriptVerif"))
        settings.setValue("nThreadsScriptVerif", DEFAULT_SCRIPTCHECK_THREADS);
    if (!SoftSetArg("-par", settings.value("nThreadsScriptVerif").toString().toStdString()))
        addOverriddenOption("-par");

    // Wallet
#ifdef ENABLE_WALLET
    if (!settings.contains("bSpendZeroConfChange"))
        settings.setValue("bSpendZeroConfChange", true);
    if (!SoftSetBoolArg("-spendzeroconfchange", settings.value("bSpendZeroConfChange").toBool()))
        addOverriddenOption("-spendzeroconfchange");
#endif

    // Network
    if (!settings.contains("fUseUPnP"))
        settings.setValue("fUseUPnP", DEFAULT_UPNP);
    if (!SoftSetBoolArg("-upnp", settings.value("fUseUPnP").toBool()))
        addOverriddenOption("-upnp");

    if (!settings.contains("fListen"))
        settings.setValue("fListen", DEFAULT_LISTEN);
    if (!SoftSetBoolArg("-listen", settings.value("fListen").toBool()))
        addOverriddenOption("-listen");

    if (!settings.contains("fUseProxy"))
        settings.setValue("fUseProxy", false);
    if (!settings.contains("addrProxy"))
        settings.setValue("addrProxy", "127.0.0.1:9050");
    // Only try to set -proxy, if user has enabled fUseProxy
    if (settings.value("fUseProxy").toBool() && !SoftSetArg("-proxy", settings.value("addrProxy").toString().toStdString()))
        addOverriddenOption("-proxy");
    else if(!settings.value("fUseProxy").toBool() && !GetArg("-proxy", "").empty())
        addOverriddenOption("-proxy");

    // Display
    if (!settings.contains("language"))
        settings.setValue("language", "");
    if (!SoftSetArg("-lang", settings.value("language").toString().toStdString()))
        addOverriddenOption("-lang");

    language = settings.value("language").toString();
}

void OptionsModel::Reset()
{
    QSettings settings;

    // Remove all entries from our QSettings object
    settings.clear();

    // default setting for OptionsModel::StartAtStartup - disabled
    if (GUIUtil::GetStartOnSystemStartup())
        GUIUtil::SetStartOnSystemStartup(false);
}

int OptionsModel::rowCount(const QModelIndex & parent) const
{
    return OptionIDRowCount;
}

// read QSettings values and return them
QVariant OptionsModel::data(const QModelIndex & index, int role) const
{
    if(role == Qt::EditRole)
    {
        QSettings settings;
        switch(index.row())
        {
        case StartAtStartup:
            return GUIUtil::GetStartOnSystemStartup();
        case MinimizeToTray:
            return fMinimizeToTray;
        case MapPortUPnP:
#ifdef USE_UPNP
            return settings.value("fUseUPnP");
#else
            return false;
#endif
        case MinimizeOnClose:
            return fMinimizeOnClose;

        // default proxy
        case ProxyUse:
            return settings.value("fUseProxy", false);
        case ProxyIP: {
            // contains IP at index 0 and port at index 1
            QStringList strlIpPort = settings.value("addrProxy").toString().split(":", QString::SkipEmptyParts);
            return strlIpPort.at(0);
        }
        case ProxyPort: {
            // contains IP at index 0 and port at index 1
            QStringList strlIpPort = settings.value("addrProxy").toString().split(":", QString::SkipEmptyParts);
            return strlIpPort.at(1);
        }

#ifdef ENABLE_WALLET
        case SpendZeroConfChange:
            return settings.value("bSpendZeroConfChange");
#endif
        case DisplayUnit:
            return nDisplayUnit;
        case ThirdPartyTxUrls:
            return strThirdPartyTxUrls;
        case Language:
            return settings.value("language");
        case CoinControlFeatures:
            return fCoinControlFeatures;
        case DatabaseCache:
            return settings.value("nDatabaseCache");
        case ThreadsScriptVerif:
            return settings.value("nThreadsScriptVerif");
        case Listen:
            return settings.value("fListen");
        default:
            return QVariant();
        }
    }
    return QVariant();
}

// write QSettings values
bool OptionsModel::setData(const QModelIndex & index, const QVariant & value, int role)
{
    bool successful = true; /* set to false on parse error */
    if(role == Qt::EditRole)
    {
        QSettings settings;
        switch(index.row())
        {
        case StartAtStartup:
            successful = GUIUtil::SetStartOnSystemStartup(value.toBool());
            break;
        case MinimizeToTray:
            fMinimizeToTray = value.toBool();
            settings.setValue("fMinimizeToTray", fMinimizeToTray);
            break;
        case MapPortUPnP: // core option - can be changed on-the-fly
            settings.setValue("fUseUPnP", value.toBool());
            MapPort(value.toBool());
            break;
        case MinimizeOnClose:
            fMinimizeOnClose = value.toBool();
            settings.setValue("fMinimizeOnClose", fMinimizeOnClose);
            break;

        // default proxy
        case ProxyUse:
            if (settings.value("fUseProxy") != value) {
                settings.setValue("fUseProxy", value.toBool());
                setRestartRequired(true);
            }
            break;
        case ProxyIP: {
            // contains current IP at index 0 and current port at index 1
            QStringList strlIpPort = settings.value("addrProxy").toString().split(":", QString::SkipEmptyParts);
            // if that key doesn't exist or has a changed IP
            if (!settings.contains("addrProxy") || strlIpPort.at(0) != value.toString()) {
                // construct new value from new IP and current port
                QString strNewValue = value.toString() + ":" + strlIpPort.at(1);
                settings.setValue("addrProxy", strNewValue);
                setRestartRequired(true);
            }
        }
        break;
        case ProxyPort: {
            // contains current IP at index 0 and current port at index 1
            QStringList strlIpPort = settings.value("addrProxy").toString().split(":", QString::SkipEmptyParts);
            // if that key doesn't exist or has a changed port
            if (!settings.contains("addrProxy") || strlIpPort.at(1) != value.toString()) {
                // construct new value from current IP and new port
                QString strNewValue = strlIpPort.at(0) + ":" + value.toString();
                settings.setValue("addrProxy", strNewValue);
                setRestartRequired(true);
            }
        }
        break;
#ifdef ENABLE_WALLET
        case SpendZeroConfChange:
            if (settings.value("bSpendZeroConfChange") != value) {
                settings.setValue("bSpendZeroConfChange", value);
                setRestartRequired(true);
            }
            break;
#endif
        case DisplayUnit:
            setDisplayUnit(value);
            break;
        case ThirdPartyTxUrls:
            if (strThirdPartyTxUrls != value.toString()) {
                strThirdPartyTxUrls = value.toString();
                settings.setValue("strThirdPartyTxUrls", strThirdPartyTxUrls);
                setRestartRequired(true);
            }
            break;
        case Language:
            if (settings.value("language") != value) {
                settings.setValue("language", value);
                setRestartRequired(true);
            }
            break;
        case CoinControlFeatures:
            fCoinControlFeatures = value.toBool();
            settings.setValue("fCoinControlFeatures", fCoinControlFeatures);
            Q_EMIT coinControlFeaturesChanged(fCoinControlFeatures);
            break;
        case DatabaseCache:
            if (settings.value("nDatabaseCache") != value) {
                settings.setValue("nDatabaseCache", value);
                setRestartRequired(true);
            }
            break;
        case ThreadsScriptVerif:
            if (settings.value("nThreadsScriptVerif") != value) {
                settings.setValue("nThreadsScriptVerif", value);
                setRestartRequired(true);
            }
            break;
        case Listen:
            if (settings.value("fListen") != value) {
                settings.setValue("fListen", value);
                setRestartRequired(true);
            }
            break;
        default:
            break;
        }
    }

    Q_EMIT dataChanged(index, index);

    return successful;
}

/** Updates current unit in memory, settings and emits displayUnitChanged(newUnit) signal */
void OptionsModel::setDisplayUnit(const QVariant &value)
{
    if (!value.isNull())
    {
        QSettings settings;
        nDisplayUnit = value.toInt();
        settings.setValue("nDisplayUnit", nDisplayUnit);
        Q_EMIT displayUnitChanged(nDisplayUnit);
    }
}

bool OptionsModel::getProxySettings(QNetworkProxy& proxy) const
{
    // Directly query current base proxy, because
    // GUI settings can be overridden with -proxy.
    proxyType curProxy;
    if (GetProxy(NET_IPV4, curProxy)) {
        proxy.setType(QNetworkProxy::Socks5Proxy);
        proxy.setHostName(QString::fromStdString(curProxy.proxy.ToStringIP()));
        proxy.setPort(curProxy.proxy.GetPort());

        return true;
    }
    else
        proxy.setType(QNetworkProxy::NoProxy);

    return false;
}

void OptionsModel::setRestartRequired(bool fRequired)
{
    QSettings settings;
    return settings.setValue("fRestartRequired", fRequired);
}

bool OptionsModel::isRestartRequired()
{
    QSettings settings;
    return settings.value("fRestartRequired", false).toBool();
}
<|endoftext|>


<commit_before>#include <qtum/qtumledger.h>
#include <util/system.h>
#include <chainparams.h>
#include <univalue.h>
#include <util/strencodings.h>
#include <pubkey.h>
#include <boost/process.hpp>
#include <boost/asio.hpp>
#include <boost/filesystem.hpp>
#ifdef WIN32
#include <boost/process/windows.hpp>
#endif

namespace QtumLedger_NS {
// Read json document
UniValue json_read_doc(const std::string& jsondata)
{
    UniValue v;
    v.read(jsondata);
    return v;
}

// Read json object
UniValue json_get_object(const UniValue& jsondata)
{
    UniValue v(UniValue::VOBJ);
    if(jsondata.isObject())
        v = jsondata.get_obj();
    return v;
}

// Read json array
UniValue json_get_array(const UniValue& jsondata)
{
    UniValue v(UniValue::VARR);
    if(jsondata.isArray())
        v = jsondata.get_array();
    return v;
}

// Get json string for key
std::string json_get_key_string(const UniValue& jsondata, std::string key)
{
    UniValue v(UniValue::VSTR);
    if(jsondata.exists(key))
    {
        UniValue data = jsondata[key];
        if(data.isStr())
            v = data;
    }

    return v.get_str();
}

// Append data to vector
std::vector<std::string>& operator<<(std::vector<std::string>& os, const std::string& dt)
{
    os.push_back(dt);
    return os;
}

// Start process from qtumd
class CProcess
{
public:
    ~CProcess()
    {
        clean();
    }

    // Set process params
    void start(const std::string& prog, const std::vector<std::string> &arg)
    {
        clean();
        m_program = prog;
        m_arguments = arg;
    }

    // Start and wait for it to finish
    void waitForFinished()
    {
        boost::asio::io_service svc;
        boost::asio::streambuf out, err;
#ifdef WIN32
        boost::process::child child(m_program, ::boost::process::windows::create_no_window, boost::process::args(m_arguments),
                                    boost::process::std_out > out, boost::process::std_err > err, svc);
#else
        boost::process::child child(m_program, boost::process::args(m_arguments),
                                    boost::process::std_out > out, boost::process::std_err > err, svc);
#endif

        svc.run();
        child.wait();
        m_std_out = toString(&out);
        m_std_err = toString(&err);
    }

    // Read all standard output
    std::string readAllStandardOutput()
    {
        return m_std_out;
    }

    // Read all standard error
    std::string readAllStandardError()
    {
        return m_std_err;
    }

    // Clean process
    void clean()
    {
        m_program = "";
        m_std_out = "";
        m_std_err = "";
    }

private:
    std::string toString(boost::asio::streambuf* stream)
    {
        std::istream is(stream);
        std::ostringstream os;
        is >> os.rdbuf();
        return os.str();
    }

private:
    std::string m_program;
    std::vector<std::string> m_arguments;
    std::string m_std_out;
    std::string m_std_err;
};
}
using namespace QtumLedger_NS;

class QtumLedgerPriv
{
public:
    QtumLedgerPriv()
    {
        toolPath = gArgs.GetArg("-hwitoolpath", "");
        toolExists = boost::filesystem::exists(toolPath);
        if(gArgs.GetChainName() != CBaseChainParams::MAIN)
        {
            arguments << "--testnet";
        }
    }

    std::atomic<bool> fStarted{false};
    CProcess process;
    std::string strStdout;
    std::string strError;
    std::string toolPath;
    std::vector<std::string> arguments;
    bool toolExists = false;
};

QtumLedger::QtumLedger():
    d(0)
{
    d = new QtumLedgerPriv();
}

QtumLedger::~QtumLedger()
{
    if(d)
        delete d;
    d = 0;
}

bool QtumLedger::signCoinStake(const std::string &fingerprint, std::string &psbt)
{
    // Check if tool exists
    if(!toolExists())
        return false;

    // Sign PSBT transaction
    if(isStarted())
        return false;

    if(!beginSignTx(fingerprint, psbt))
        return false;

    wait();

    return endSignTx(fingerprint, psbt);
}

bool QtumLedger::signBlockHeader(const std::string &fingerprint, const std::string &header, const std::string &path, std::vector<unsigned char> &vchSig)
{
    // Check if tool exists
    if(!toolExists())
        return false;

    // Sign block header
    if(isStarted())
        return false;

    if(!beginSignBlockHeader(fingerprint, header, path, vchSig))
        return false;

    wait();

    return endSignBlockHeader(fingerprint, header, path, vchSig);
}

bool QtumLedger::toolExists()
{
    return d->toolExists;
}

bool QtumLedger::isStarted()
{
    return d->fStarted;
}

void QtumLedger::wait()
{
    if(d->fStarted)
    {
        d->process.waitForFinished();
        d->strStdout = d->process.readAllStandardOutput();
        d->strError = d->process.readAllStandardError();
        d->fStarted = false;
    }
}

bool QtumLedger::beginSignTx(const std::string &fingerprint, std::string &psbt)
{
    // Execute command line
    std::vector<std::string> arguments = d->arguments;
    arguments << "-f" << fingerprint << "signtx" << psbt;
    d->process.start(d->toolPath, arguments);
    d->fStarted = true;

    return d->fStarted;
}

bool QtumLedger::endSignTx(const std::string &, std::string &psbt)
{
    // Decode command line results
    UniValue jsonDocument = json_read_doc(d->strStdout);
    UniValue data = json_get_object(jsonDocument);
    std::string psbtSigned = json_get_key_string(data, "psbt");
    if(!psbtSigned.empty())
    {
        psbt = psbtSigned;
        return true;
    }

    return false;
}

bool QtumLedger::beginSignBlockHeader(const std::string &fingerprint, const std::string &header, const std::string &path, std::vector<unsigned char> &)
{
    // Execute command line
    std::vector<std::string> arguments = d->arguments;
    arguments << "-f" << fingerprint << "signheader" << header << path;
    d->process.start(d->toolPath, arguments);
    d->fStarted = true;

    return d->fStarted;
}

bool QtumLedger::endSignBlockHeader(const std::string &, const std::string &, const std::string &, std::vector<unsigned char> &vchSig)
{
    // Decode command line results
    UniValue jsonDocument = json_read_doc(d->strStdout);
    UniValue data = json_get_object(jsonDocument);
    std::string headerSigned = json_get_key_string(data, "signature");
    if(!headerSigned.empty())
    {
        vchSig = DecodeBase64(headerSigned.c_str());
        return vchSig.size() == CPubKey::COMPACT_SIGNATURE_SIZE;
    }

    return false;
}

bool QtumLedger::isConnected(const std::string &fingerprint)
{
    // Check if a device is connected
    try
    {
        std::vector<LedgerDevice> devices;
        if(enumerate(devices))
        {
            for(LedgerDevice device: devices)
            {
                if(device.fingerprint == fingerprint)
                    return true;
            }
        }
    }
    catch(...)
    {}

    return false;
}

bool QtumLedger::enumerate(std::vector<LedgerDevice> &devices)
{
    // Enumerate hardware wallet devices
    if(isStarted())
        return false;

    if(!beginEnumerate(devices))
        return false;

    wait();

    return endEnumerate(devices);
}

bool QtumLedger::beginEnumerate(std::vector<LedgerDevice> &)
{
    // Execute command line
    std::vector<std::string> arguments = d->arguments;
    arguments << "enumerate";
    d->process.start(d->toolPath, arguments);
    d->fStarted = true;

    return d->fStarted;
}

bool QtumLedger::endEnumerate(std::vector<LedgerDevice> &devices)
{
    // Decode command line results
    UniValue jsonDocument = json_read_doc(d->strStdout);
    UniValue jsonDevices = json_get_array(jsonDocument);
    for(size_t i = 0; i < jsonDevices.size(); i++)
    {
        const UniValue& jsonDevice = jsonDevices[i];
        if(!jsonDevice.isObject())
            return false;

        // Get device info
        UniValue data = json_get_object(jsonDevice);
        LedgerDevice device;
        device.fingerprint = json_get_key_string(data, "fingerprint");
        device.serial_number = json_get_key_string(data, "serial_number");
        device.type = json_get_key_string(data, "type");
        device.path = json_get_key_string(data, "path");
        device.error = json_get_key_string(data, "error");
        device.model = json_get_key_string(data, "model");
        device.code = json_get_key_string(data, "code");
        devices.push_back(device);
    }

    return devices.size() > 0;
}

QtumLedger &QtumLedger::instance()
{
    static QtumLedger device;
    return device;
}
<commit_msg>Fix qtumledger start for Windows when use .py script<commit_after>#include <qtum/qtumledger.h>
#include <util/system.h>
#include <chainparams.h>
#include <univalue.h>
#include <util/strencodings.h>
#include <pubkey.h>
#include <logging.h>
#include <boost/process.hpp>
#include <boost/asio.hpp>
#include <boost/filesystem.hpp>
#include <boost/algorithm/string.hpp>
#ifdef WIN32
#include <boost/process/windows.hpp>
#endif

namespace QtumLedger_NS {
// Read json document
UniValue json_read_doc(const std::string& jsondata)
{
    UniValue v;
    v.read(jsondata);
    return v;
}

// Read json object
UniValue json_get_object(const UniValue& jsondata)
{
    UniValue v(UniValue::VOBJ);
    if(jsondata.isObject())
        v = jsondata.get_obj();
    return v;
}

// Read json array
UniValue json_get_array(const UniValue& jsondata)
{
    UniValue v(UniValue::VARR);
    if(jsondata.isArray())
        v = jsondata.get_array();
    return v;
}

// Get json string for key
std::string json_get_key_string(const UniValue& jsondata, std::string key)
{
    UniValue v(UniValue::VSTR);
    if(jsondata.exists(key))
    {
        UniValue data = jsondata[key];
        if(data.isStr())
            v = data;
    }

    return v.get_str();
}

// Append data to vector
std::vector<std::string>& operator<<(std::vector<std::string>& os, const std::string& dt)
{
    os.push_back(dt);
    return os;
}

#ifdef WIN32
// Check suffix
bool endsWith(const std::string& str, const std::string& suffix)
{
    return str.size() >= suffix.size() && 0 == str.compare(str.size()-suffix.size(), suffix.size(), suffix);
}

// Check if the path is to python executable
bool isPyPath(const std::string& str)
{
    std::size_t found = str.find("python");
    return found!=std::string::npos;
}
#endif

// Start process from qtumd
class CProcess
{
public:
    ~CProcess()
    {
        clean();
    }

    // Set process params
    void start(const std::string& prog, const std::vector<std::string> &arg)
    {
        clean();
        m_program = prog;
        m_arguments = arg;
    }

    // Start and wait for it to finish
    void waitForFinished()
    {
        boost::asio::io_service svc;
        boost::asio::streambuf out, err;
#ifdef WIN32
        boost::process::child child(m_program, ::boost::process::windows::create_no_window, boost::process::args(m_arguments),
                                    boost::process::std_out > out, boost::process::std_err > err, svc);
#else
        boost::process::child child(m_program, boost::process::args(m_arguments),
                                    boost::process::std_out > out, boost::process::std_err > err, svc);
#endif

        svc.run();
        child.wait();
        m_std_out = toString(&out);
        m_std_err = toString(&err);
    }

    // Read all standard output
    std::string readAllStandardOutput()
    {
        return m_std_out;
    }

    // Read all standard error
    std::string readAllStandardError()
    {
        return m_std_err;
    }

    // Clean process
    void clean()
    {
        m_program = "";
        m_std_out = "";
        m_std_err = "";
    }

private:
    std::string toString(boost::asio::streambuf* stream)
    {
        std::istream is(stream);
        std::ostringstream os;
        is >> os.rdbuf();
        return os.str();
    }

private:
    std::string m_program;
    std::vector<std::string> m_arguments;
    std::string m_std_out;
    std::string m_std_err;
};
}
using namespace QtumLedger_NS;

class QtumLedgerPriv
{
public:
    QtumLedgerPriv()
    {
        toolPath = gArgs.GetArg("-hwitoolpath", "");
        toolExists = boost::filesystem::exists(toolPath);
        initToolPath();

        if(gArgs.GetChainName() != CBaseChainParams::MAIN)
        {
            arguments << "--testnet";
        }

        if(!toolExists)
        {
            LogPrintf("QtumLedger(): HWI tool not found %s\n", toolPath);
        }
    }

    void initToolPath()
    {
#ifdef WIN32
        if(endsWith(toolPath, ".py") ||
                endsWith(toolPath, ".PY") ||
                endsWith(toolPath, ".Py") ||
                endsWith(toolPath, ".pY"))
        {
            arguments << toolPath;
            toolPath = boost::process::search_path("python3").string();
            toolExists &= isPyPath(toolPath);
            if(!toolExists)
            {
                std::string prog = boost::process::search_path("cmd").string();
                std::vector<std::string> arg;
                arg << "/c" << "python3" << "-c" << "import sys; print(sys.executable)";
                process.start(prog, arg);
                process.waitForFinished();
                toolPath = process.readAllStandardOutput();
                boost::erase_all(toolPath, "\r");
                boost::erase_all(toolPath, "\n");
                toolExists = isPyPath(toolPath);
                process.clean();
            }
        }
#endif
    }

    std::atomic<bool> fStarted{false};
    CProcess process;
    std::string strStdout;
    std::string strError;
    std::string toolPath;
    std::vector<std::string> arguments;
    bool toolExists = false;
};

QtumLedger::QtumLedger():
    d(0)
{
    d = new QtumLedgerPriv();
}

QtumLedger::~QtumLedger()
{
    if(d)
        delete d;
    d = 0;
}

bool QtumLedger::signCoinStake(const std::string &fingerprint, std::string &psbt)
{
    // Check if tool exists
    if(!toolExists())
        return false;

    // Sign PSBT transaction
    if(isStarted())
        return false;

    if(!beginSignTx(fingerprint, psbt))
        return false;

    wait();

    return endSignTx(fingerprint, psbt);
}

bool QtumLedger::signBlockHeader(const std::string &fingerprint, const std::string &header, const std::string &path, std::vector<unsigned char> &vchSig)
{
    // Check if tool exists
    if(!toolExists())
        return false;

    // Sign block header
    if(isStarted())
        return false;

    if(!beginSignBlockHeader(fingerprint, header, path, vchSig))
        return false;

    wait();

    return endSignBlockHeader(fingerprint, header, path, vchSig);
}

bool QtumLedger::toolExists()
{
    return d->toolExists;
}

bool QtumLedger::isStarted()
{
    return d->fStarted;
}

void QtumLedger::wait()
{
    if(d->fStarted)
    {
        d->process.waitForFinished();
        d->strStdout = d->process.readAllStandardOutput();
        d->strError = d->process.readAllStandardError();
        d->fStarted = false;
    }
}

bool QtumLedger::beginSignTx(const std::string &fingerprint, std::string &psbt)
{
    // Execute command line
    std::vector<std::string> arguments = d->arguments;
    arguments << "-f" << fingerprint << "signtx" << psbt;
    d->process.start(d->toolPath, arguments);
    d->fStarted = true;

    return d->fStarted;
}

bool QtumLedger::endSignTx(const std::string &, std::string &psbt)
{
    // Decode command line results
    UniValue jsonDocument = json_read_doc(d->strStdout);
    UniValue data = json_get_object(jsonDocument);
    std::string psbtSigned = json_get_key_string(data, "psbt");
    if(!psbtSigned.empty())
    {
        psbt = psbtSigned;
        return true;
    }

    return false;
}

bool QtumLedger::beginSignBlockHeader(const std::string &fingerprint, const std::string &header, const std::string &path, std::vector<unsigned char> &)
{
    // Execute command line
    std::vector<std::string> arguments = d->arguments;
    arguments << "-f" << fingerprint << "signheader" << header << path;
    d->process.start(d->toolPath, arguments);
    d->fStarted = true;

    return d->fStarted;
}

bool QtumLedger::endSignBlockHeader(const std::string &, const std::string &, const std::string &, std::vector<unsigned char> &vchSig)
{
    // Decode command line results
    UniValue jsonDocument = json_read_doc(d->strStdout);
    UniValue data = json_get_object(jsonDocument);
    std::string headerSigned = json_get_key_string(data, "signature");
    if(!headerSigned.empty())
    {
        vchSig = DecodeBase64(headerSigned.c_str());
        return vchSig.size() == CPubKey::COMPACT_SIGNATURE_SIZE;
    }

    return false;
}

bool QtumLedger::isConnected(const std::string &fingerprint)
{
    // Check if a device is connected
    try
    {
        std::vector<LedgerDevice> devices;
        if(enumerate(devices))
        {
            for(LedgerDevice device: devices)
            {
                if(device.fingerprint == fingerprint)
                    return true;
            }
        }
    }
    catch(...)
    {}

    return false;
}

bool QtumLedger::enumerate(std::vector<LedgerDevice> &devices)
{
    // Check if tool exists
    if(!toolExists())
        return false;

    // Enumerate hardware wallet devices
    if(isStarted())
        return false;

    if(!beginEnumerate(devices))
        return false;

    wait();

    return endEnumerate(devices);
}

bool QtumLedger::beginEnumerate(std::vector<LedgerDevice> &)
{
    // Execute command line
    std::vector<std::string> arguments = d->arguments;
    arguments << "enumerate";
    d->process.start(d->toolPath, arguments);
    d->fStarted = true;

    return d->fStarted;
}

bool QtumLedger::endEnumerate(std::vector<LedgerDevice> &devices)
{
    // Decode command line results
    UniValue jsonDocument = json_read_doc(d->strStdout);
    UniValue jsonDevices = json_get_array(jsonDocument);
    for(size_t i = 0; i < jsonDevices.size(); i++)
    {
        const UniValue& jsonDevice = jsonDevices[i];
        if(!jsonDevice.isObject())
            return false;

        // Get device info
        UniValue data = json_get_object(jsonDevice);
        LedgerDevice device;
        device.fingerprint = json_get_key_string(data, "fingerprint");
        device.serial_number = json_get_key_string(data, "serial_number");
        device.type = json_get_key_string(data, "type");
        device.path = json_get_key_string(data, "path");
        device.error = json_get_key_string(data, "error");
        device.model = json_get_key_string(data, "model");
        device.code = json_get_key_string(data, "code");
        devices.push_back(device);
    }

    return devices.size() > 0;
}

QtumLedger &QtumLedger::instance()
{
    static QtumLedger device;
    return device;
}
<|endoftext|>


<commit_before>//=======================================================================
// Copyright Baptiste Wicht 2011.
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
//  http://www.boost.org/LICENSE_1_0.txt)
//=======================================================================

#include <iostream>

#include "il/Compare.hpp"
#include "il/Operand.hpp"

#include "AssemblyFileWriter.hpp"

using namespace eddic;

Compare::Compare(std::shared_ptr<Operand> lhs, std::shared_ptr<Operand> rhs) : m_lhs(lhs), m_rhs(rhs) {}

void Compare::write(AssemblyFileWriter& writer){
    //We can always put an immediate value everywhere
    writer.stream() << "cmpl " << m_lhs->getValue() << ", " << m_rhs->getValue() << std::endl;

    //TODO Improve ?
}
<commit_msg>No way to improve that now<commit_after>//=======================================================================
// Copyright Baptiste Wicht 2011.
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
//  http://www.boost.org/LICENSE_1_0.txt)
//=======================================================================

#include <iostream>

#include "il/Compare.hpp"
#include "il/Operand.hpp"

#include "AssemblyFileWriter.hpp"

using namespace eddic;

Compare::Compare(std::shared_ptr<Operand> lhs, std::shared_ptr<Operand> rhs) : m_lhs(lhs), m_rhs(rhs) {}

void Compare::write(AssemblyFileWriter& writer){
    //We can always put an immediate value everywhere
    writer.stream() << "cmpl " << m_lhs->getValue() << ", " << m_rhs->getValue() << std::endl;
}
<|endoftext|>


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

//$Id: image_util.cpp 36 2005-04-05 14:32:18Z pavlenko $

// mapnik
#include <mapnik/image_util.hpp>
#include <mapnik/png_io.hpp>
#include <mapnik/jpeg_io.hpp>
#include <mapnik/graphics.hpp>
#include <mapnik/memory.hpp>
#include <mapnik/image_view.hpp>

// stl
#include <string>
#include <iostream>
#include <fstream>

namespace mapnik
{
   template <typename T>
   std::string save_to_string(T const& image,
                     std::string const& type)
   {
      std::ostringstream ss(std::ios::out|std::ios::binary);
     //all this should go into image_writer factory
     if (type=="png")  save_as_png(ss,image);
     else if (type == "png256") save_as_png256(ss,image);
     else if (type=="jpeg") save_as_jpeg(ss,85,image);
     else throw ImageWriterException("unknown file type: " + type);
     return ss.str();
   }

   template <typename T>
   void save_to_file(T const& image,
                     std::string const& filename,
                     std::string const& type)
   {
      std::ofstream file (filename.c_str(), std::ios::out| std::ios::trunc|std::ios::binary);
      if (file)
      {
         //all this should go into image_writer factory
         if (type=="png")  save_as_png(file,image);
         else if (type == "png256") save_as_png256(file,image);
         else if (type=="jpeg") save_as_jpeg(file,85,image);
         else throw ImageWriterException("unknown file type: " + type);
      }
   }

   template <typename T>
   void save_to_file(T const& image,std::string const& filename)
   {
      std::string type = type_from_filename(filename);
      save_to_file<T>(image,filename,type);
   }

   template void save_to_file<ImageData32>(ImageData32 const&,
                                           std::string const&,
                                           std::string const&);

   template void save_to_file<ImageData32>(ImageData32 const&,
                                           std::string const&);

   template std::string save_to_string<ImageData32>(ImageData32 const&,
                                           std::string const&);

   template void save_to_file<image_view<ImageData32> > (image_view<ImageData32> const&,
                                                         std::string const&,
                                                         std::string const&);

   template void save_to_file<image_view<ImageData32> > (image_view<ImageData32> const&,
                                                         std::string const&);

   template std::string save_to_string<image_view<ImageData32> > (image_view<ImageData32> const&,
                                                         std::string const&);

}
<commit_msg>Includes png.h early to avoid ordering issues with setjmp.h. Fixes #231<commit_after>/*****************************************************************************
 *
 * This file is part of Mapnik (c++ mapping toolkit)
 *
 * Copyright (C) 2006 Artem Pavlenko
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 *
 *****************************************************************************/

//$Id: image_util.cpp 36 2005-04-05 14:32:18Z pavlenko $

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

// mapnik
#include <mapnik/image_util.hpp>
#include <mapnik/png_io.hpp>
#include <mapnik/jpeg_io.hpp>
#include <mapnik/graphics.hpp>
#include <mapnik/memory.hpp>
#include <mapnik/image_view.hpp>

// stl
#include <string>
#include <iostream>
#include <fstream>

namespace mapnik
{
   template <typename T>
   std::string save_to_string(T const& image,
                     std::string const& type)
   {
      std::ostringstream ss(std::ios::out|std::ios::binary);
     //all this should go into image_writer factory
     if (type=="png")  save_as_png(ss,image);
     else if (type == "png256") save_as_png256(ss,image);
     else if (type=="jpeg") save_as_jpeg(ss,85,image);
     else throw ImageWriterException("unknown file type: " + type);
     return ss.str();
   }

   template <typename T>
   void save_to_file(T const& image,
                     std::string const& filename,
                     std::string const& type)
   {
      std::ofstream file (filename.c_str(), std::ios::out| std::ios::trunc|std::ios::binary);
      if (file)
      {
         //all this should go into image_writer factory
         if (type=="png")  save_as_png(file,image);
         else if (type == "png256") save_as_png256(file,image);
         else if (type=="jpeg") save_as_jpeg(file,85,image);
         else throw ImageWriterException("unknown file type: " + type);
      }
   }

   template <typename T>
   void save_to_file(T const& image,std::string const& filename)
   {
      std::string type = type_from_filename(filename);
      save_to_file<T>(image,filename,type);
   }

   template void save_to_file<ImageData32>(ImageData32 const&,
                                           std::string const&,
                                           std::string const&);

   template void save_to_file<ImageData32>(ImageData32 const&,
                                           std::string const&);

   template std::string save_to_string<ImageData32>(ImageData32 const&,
                                           std::string const&);

   template void save_to_file<image_view<ImageData32> > (image_view<ImageData32> const&,
                                                         std::string const&,
                                                         std::string const&);

   template void save_to_file<image_view<ImageData32> > (image_view<ImageData32> const&,
                                                         std::string const&);

   template std::string save_to_string<image_view<ImageData32> > (image_view<ImageData32> const&,
                                                         std::string const&);

}
<|endoftext|>


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

//$Id: image_util.cpp 36 2005-04-05 14:32:18Z pavlenko $

#include <string>
#include <png.h>
#include <jpeglib.h>
#include "graphics.hpp"
#include "image_util.hpp"
#include "memory.hpp"

namespace mapnik
{

    //use memory manager for mem allocation in libpng

    png_voidp malloc_fn(png_structp png_ptr,png_size_t size)
    {
        return Object::operator new(size);
    }
    void free_fn(png_structp png_ptr, png_voidp ptr)
    {
        Object::operator delete(ptr);
    }
    //
    void ImageUtils::save_to_file(const std::string& filename,const std::string& type,const Image32& image)
    {
	//all that should go into image_writer factory
        if (type=="png")
        {
            save_as_png(filename,image);
        }
	else if (type=="jpeg")
	{
	    save_as_jpeg(filename,85,image);
	}
    }

    void ImageUtils::save_as_png(const std::string& filename,const Image32& image)
    {
        FILE *fp=fopen(filename.c_str(), "wb");
        if (!fp) return;
        png_voidp mem_ptr=0;
        png_structp png_ptr=png_create_write_struct(PNG_LIBPNG_VER_STRING,
						    (png_voidp)mem_ptr,0, 0);

        if (!png_ptr) return;
        png_set_mem_fn(png_ptr,mem_ptr,malloc_fn,free_fn);

        // switch on optimization
	#if defined(PNG_LIBPNG_VER) && (PNG_LIBPNG_VER >= 10200)
        png_uint_32 mask, flags;

        flags = png_get_asm_flags(png_ptr);
        mask = png_get_asm_flagmask(PNG_SELECT_READ | PNG_SELECT_WRITE);
        png_set_asm_flags(png_ptr, flags | mask);
	#endif
	png_set_filter (png_ptr, 0, PNG_FILTER_NONE);
        png_infop info_ptr = png_create_info_struct(png_ptr);
        if (!info_ptr)
        {
            png_destroy_write_struct(&png_ptr,(png_infopp)0);
            fclose(fp);
            return;
        }
        if (setjmp(png_jmpbuf(png_ptr)))
        {
            png_destroy_write_struct(&png_ptr, &info_ptr);
            fclose(fp);
            return;
        }

        png_init_io(png_ptr, fp);
	//png_set_compression_level(png_ptr, Z_BEST_COMPRESSION);
	//png_set_compression_strategy(png_ptr, Z_FILTERED);
        png_set_IHDR(png_ptr, info_ptr,image.width(),image.height(),8,
            PNG_COLOR_TYPE_RGB_ALPHA,PNG_INTERLACE_NONE,
            PNG_COMPRESSION_TYPE_DEFAULT,PNG_FILTER_TYPE_DEFAULT);
        png_write_info(png_ptr, info_ptr);

        const ImageData32& imageData=image.data();

        for (unsigned i=0;i<image.height();i++)
        {
            png_write_row(png_ptr,(png_bytep)imageData.getRow(i));
        }

        png_write_end(png_ptr, info_ptr);
        png_destroy_write_struct(&png_ptr, &info_ptr);
        fclose(fp);
    }

    void ImageUtils::save_as_jpeg(const std::string& filename,int quality, const Image32& image)
    {
	FILE *fp=fopen(filename.c_str(), "wb");
        if (!fp) return;
	struct jpeg_compress_struct cinfo;
	struct jpeg_error_mgr jerr;

	int width=image.width();
	int height=image.height();

	cinfo.err = jpeg_std_error(&jerr);
	jpeg_create_compress(&cinfo);
	jpeg_stdio_dest(&cinfo, fp);
	cinfo.image_width = width;
	cinfo.image_height = height;
	cinfo.input_components = 3;
	cinfo.in_color_space = JCS_RGB;
	jpeg_set_defaults(&cinfo);
	jpeg_set_quality(&cinfo, quality,1);
	jpeg_start_compress(&cinfo, 1);
	JSAMPROW row_pointer[1];
	JSAMPLE* row=new JSAMPLE[width*3];
	const ImageData32& imageData=image.data();
	while (cinfo.next_scanline < cinfo.image_height)
	{
	    const unsigned* imageRow=imageData.getRow(cinfo.next_scanline);
	    int index=0;
	    for (int i=0;i<width;++i)
	    {
		row[index++]=(imageRow[i])&0xff;
		row[index++]=(imageRow[i]>>8)&0xff;
		row[index++]=(imageRow[i]>>16)&0xff;
	    }
	    row_pointer[0] = &row[0];
	    (void) jpeg_write_scanlines(&cinfo, row_pointer, 1);
	}
	delete [] row;
	jpeg_finish_compress(&cinfo);
	fclose(fp);
	jpeg_destroy_compress(&cinfo);
    }
}
<commit_msg>Switched from <fstream.h> to <fstream> as per the warning the compiler gave me, and the C++ standard.<commit_after>/*****************************************************************************
 *
 * This file is part of Mapnik (c++ mapping toolkit)
 *
 * Copyright (C) 2006 Artem Pavlenko
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 *
 *****************************************************************************/

//$Id: image_util.cpp 36 2005-04-05 14:32:18Z pavlenko $

#include <string>
#include <png.h>
#include <jpeglib.h>
#include <gif_lib.h>
#include <fstream>
#include "graphics.hpp"
#include "image_util.hpp"
#include "memory.hpp"

namespace mapnik
{

    //use memory manager for mem allocation in libpng

    png_voidp malloc_fn(png_structp png_ptr,png_size_t size)
    {
        return Object::operator new(size);
    }
    void free_fn(png_structp png_ptr, png_voidp ptr)
    {
        Object::operator delete(ptr);
    }
    //
    void ImageUtils::save_to_file(const std::string& filename,const std::string& type,const Image32& image)
    {
	//all that should go into image_writer factory
        if (type=="png")
        {
            save_as_png(filename,image);
        }
	else if (type=="jpeg")
	{
	    save_as_jpeg(filename,85,image);
	}
        else if (type=="gif")
        {
	    save_as_gif(filename,image);
        }
    }

    void ImageUtils::save_as_png(const std::string& filename,const Image32& image)
    {
        FILE *fp=fopen(filename.c_str(), "wb");
        if (!fp) return;
        png_voidp mem_ptr=0;
        png_structp png_ptr=png_create_write_struct(PNG_LIBPNG_VER_STRING,
						    (png_voidp)mem_ptr,0, 0);

        if (!png_ptr) return;
        png_set_mem_fn(png_ptr,mem_ptr,malloc_fn,free_fn);

        // switch on optimization
	#if defined(PNG_LIBPNG_VER) && (PNG_LIBPNG_VER >= 10200)
        png_uint_32 mask, flags;

        flags = png_get_asm_flags(png_ptr);
        mask = png_get_asm_flagmask(PNG_SELECT_READ | PNG_SELECT_WRITE);
        png_set_asm_flags(png_ptr, flags | mask);
	#endif
	png_set_filter (png_ptr, 0, PNG_FILTER_NONE);
        png_infop info_ptr = png_create_info_struct(png_ptr);
        if (!info_ptr)
        {
            png_destroy_write_struct(&png_ptr,(png_infopp)0);
            fclose(fp);
            return;
        }
        if (setjmp(png_jmpbuf(png_ptr)))
        {
            png_destroy_write_struct(&png_ptr, &info_ptr);
            fclose(fp);
            return;
        }

        png_init_io(png_ptr, fp);
	//png_set_compression_level(png_ptr, Z_BEST_COMPRESSION);
	//png_set_compression_strategy(png_ptr, Z_FILTERED);
        png_set_IHDR(png_ptr, info_ptr,image.width(),image.height(),8,
            PNG_COLOR_TYPE_RGB_ALPHA,PNG_INTERLACE_NONE,
            PNG_COMPRESSION_TYPE_DEFAULT,PNG_FILTER_TYPE_DEFAULT);
        png_write_info(png_ptr, info_ptr);

        const ImageData32& imageData=image.data();

        for (unsigned i=0;i<image.height();i++)
        {
            png_write_row(png_ptr,(png_bytep)imageData.getRow(i));
        }

        png_write_end(png_ptr, info_ptr);
        png_destroy_write_struct(&png_ptr, &info_ptr);
        fclose(fp);
    }

    void ImageUtils::save_as_jpeg(const std::string& filename,int quality, const Image32& image)
    {
	FILE *fp=fopen(filename.c_str(), "wb");
        if (!fp) return;
	struct jpeg_compress_struct cinfo;
	struct jpeg_error_mgr jerr;

	int width=image.width();
	int height=image.height();

	cinfo.err = jpeg_std_error(&jerr);
	jpeg_create_compress(&cinfo);
	jpeg_stdio_dest(&cinfo, fp);
	cinfo.image_width = width;
	cinfo.image_height = height;
	cinfo.input_components = 3;
	cinfo.in_color_space = JCS_RGB;
	jpeg_set_defaults(&cinfo);
	jpeg_set_quality(&cinfo, quality,1);
	jpeg_start_compress(&cinfo, 1);
	JSAMPROW row_pointer[1];
	JSAMPLE* row=new JSAMPLE[width*3];
	const ImageData32& imageData=image.data();
	while (cinfo.next_scanline < cinfo.image_height)
	{
	    const unsigned* imageRow=imageData.getRow(cinfo.next_scanline);
	    int index=0;
	    for (int i=0;i<width;++i)
	    {
		row[index++]=(imageRow[i])&0xff;
		row[index++]=(imageRow[i]>>8)&0xff;
		row[index++]=(imageRow[i]>>16)&0xff;
	    }
	    row_pointer[0] = &row[0];
	    (void) jpeg_write_scanlines(&cinfo, row_pointer, 1);
	}
	delete [] row;
	jpeg_finish_compress(&cinfo);
	fclose(fp);
	jpeg_destroy_compress(&cinfo);
    }

    void ImageUtils::save_as_gif(const std::string& filename,const Image32& image)
    {
        GifFileType *fp=EGifOpenFileName(filename.c_str(),0);
        if (!fp) return;
        int width=image.width();
        int height=image.height();
 	ColorMapObject *OutputColorMap = MakeMapObject(256, NULL);

	EGifPutScreenDesc(fp, width, height, 8, 0, OutputColorMap);
        EGifPutImageDesc(fp, 0, 0, width, height, FALSE, NULL);

	const ImageData32& imageData=image.data();

        for (int i=0;i<height;i++)
        {
            EGifPutLine(fp, (GifPixelType*)imageData.getRow(i), width);
        }

        EGifCloseFile(fp);
	FreeMapObject(OutputColorMap);
    }
}
<|endoftext|>


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

//$Id: image_util.cpp 36 2005-04-05 14:32:18Z pavlenko $

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

// mapnik
#include <mapnik/image_util.hpp>
#include <mapnik/png_io.hpp>
#include <mapnik/jpeg_io.hpp>
#include <mapnik/graphics.hpp>
#include <mapnik/memory.hpp>
#include <mapnik/image_view.hpp>

// stl
#include <string>
#include <iostream>
#include <fstream>
#include <sstream>

namespace mapnik
{
   template <typename T>
   std::string save_to_string(T const& image,
                     std::string const& type)
   {
      std::ostringstream ss(std::ios::out|std::ios::binary);
     //all this should go into image_writer factory
     if (type=="png")  save_as_png(ss,image);
     else if (type == "png256") save_as_png256(ss,image);
     else if (boost::algorithm::istarts_with(type,std::string("jpeg")))
	 {
	   int quality = 85;
	   try
	   {
		  if(type.substr(4).length() != 0)
		  {
		     quality = boost::lexical_cast<int>(type.substr(4));
			 if(quality<1 || quality>100)
				  throw ImageWriterException("invalid jpeg quality: " + type.substr(4));
		  }
	      save_as_jpeg(ss,quality,image);
	   }
	   catch(boost::bad_lexical_cast &)
       {
          throw ImageWriterException("invalid jpeg quality: " + type.substr(4));
       }
   }
     else throw ImageWriterException("unknown file type: " + type);
     return ss.str();
   }

   template <typename T>
   void save_to_file(T const& image,
                     std::string const& filename,
                     std::string const& type)
   {
      std::ofstream file (filename.c_str(), std::ios::out| std::ios::trunc|std::ios::binary);
      if (file)
      {
         //all this should go into image_writer factory
         if (type=="png")  save_as_png(file,image);
         else if (type == "png256") save_as_png256(file,image);
		  else if (boost::algorithm::istarts_with(type,std::string("jpeg")))
		  {
			  int quality = 85;
			  try
			  {
				  if(type.substr(4).length() != 0)
				  {
					  quality = boost::lexical_cast<int>(type.substr(4));
					  if(quality<0 || quality>100)
						  throw ImageWriterException("invalid jpeg quality: " + type.substr(4) + " out of bounds");
				  }
				  save_as_jpeg(file,quality,image);
			  }
			  catch(boost::bad_lexical_cast &)
			  {
				  throw ImageWriterException("invalid jpeg quality: " + type.substr(4) + " not a number");
			  }
		  }
		  else throw ImageWriterException("unknown file type: " + type);
	  }
   }

   template <typename T>
   void save_to_file(T const& image,std::string const& filename)
   {
      std::string type = type_from_filename(filename);
      save_to_file<T>(image,filename,type);
   }

   template void save_to_file<ImageData32>(ImageData32 const&,
                                           std::string const&,
                                           std::string const&);

   template void save_to_file<ImageData32>(ImageData32 const&,
                                           std::string const&);

   template std::string save_to_string<ImageData32>(ImageData32 const&,
                                           std::string const&);

   template void save_to_file<image_view<ImageData32> > (image_view<ImageData32> const&,
                                                         std::string const&,
                                                         std::string const&);

   template void save_to_file<image_view<ImageData32> > (image_view<ImageData32> const&,
                                                         std::string const&);

   template std::string save_to_string<image_view<ImageData32> > (image_view<ImageData32> const&,
                                                         std::string const&);

}
<commit_msg>+ formatting <commit_after>/*****************************************************************************
 *
 * This file is part of Mapnik (c++ mapping toolkit)
 *
 * Copyright (C) 2006 Artem Pavlenko
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 *
 *****************************************************************************/

//$Id: image_util.cpp 36 2005-04-05 14:32:18Z pavlenko $

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

// mapnik
#include <mapnik/image_util.hpp>
#include <mapnik/png_io.hpp>
#include <mapnik/jpeg_io.hpp>
#include <mapnik/graphics.hpp>
#include <mapnik/memory.hpp>
#include <mapnik/image_view.hpp>

// stl
#include <string>
#include <iostream>
#include <fstream>
#include <sstream>

namespace mapnik
{
    template <typename T>
    std::string save_to_string(T const& image,
                               std::string const& type)
    {
        std::ostringstream ss(std::ios::out|std::ios::binary);
        //all this should go into image_writer factory
        if (type=="png")  save_as_png(ss,image);
        else if (type == "png256") save_as_png256(ss,image);
        else if (boost::algorithm::istarts_with(type,std::string("jpeg")))
        {
            int quality = 85;
            try
            {
                if(type.substr(4).length() != 0)
                {
                    quality = boost::lexical_cast<int>(type.substr(4));
                    if(quality<1 || quality>100)
                        throw ImageWriterException("invalid jpeg quality: " + type.substr(4));
                }
                save_as_jpeg(ss,quality,image);
            }
            catch(boost::bad_lexical_cast &)
            {
                throw ImageWriterException("invalid jpeg quality: " + type.substr(4));
            }
        }
        else throw ImageWriterException("unknown file type: " + type);
        return ss.str();
    }

    template <typename T>
    void save_to_file(T const& image,
                      std::string const& filename,
                      std::string const& type)
    {
        std::ofstream file (filename.c_str(), std::ios::out| std::ios::trunc|std::ios::binary);
        if (file)
        {
            //all this should go into image_writer factory
            if (type=="png")  save_as_png(file,image);
            else if (type == "png256") save_as_png256(file,image);
            else if (boost::algorithm::istarts_with(type,std::string("jpeg")))
            {
                int quality = 85;
                try
                {
                    if(type.substr(4).length() != 0)
                    {
                        quality = boost::lexical_cast<int>(type.substr(4));
                        if(quality<0 || quality>100)
                            throw ImageWriterException("invalid jpeg quality: " + type.substr(4) + " out of bounds");
                    }
                    save_as_jpeg(file,quality,image);
                }
                catch(boost::bad_lexical_cast &)
                {
                    throw ImageWriterException("invalid jpeg quality: " + type.substr(4) + " not a number");
                }
            }
            else throw ImageWriterException("unknown file type: " + type);
        }
    }

    template <typename T>
    void save_to_file(T const& image,std::string const& filename)
    {
        std::string type = type_from_filename(filename);
        save_to_file<T>(image,filename,type);
    }

    template void save_to_file<ImageData32>(ImageData32 const&,
                                            std::string const&,
                                            std::string const&);

    template void save_to_file<ImageData32>(ImageData32 const&,
                                            std::string const&);

    template std::string save_to_string<ImageData32>(ImageData32 const&,
                                                     std::string const&);

    template void save_to_file<image_view<ImageData32> > (image_view<ImageData32> const&,
                                                          std::string const&,
                                                          std::string const&);

    template void save_to_file<image_view<ImageData32> > (image_view<ImageData32> const&,
                                                          std::string const&);

    template std::string save_to_string<image_view<ImageData32> > (image_view<ImageData32> const&,
                                                                   std::string const&);

}
<|endoftext|>