<commit_before>
#include <SDL.h>
#include "tuple.h"
#include "threedee.h"
#include "quat.h"

namespace venk
{

Quat operator*(const Quat& lhs, const Quat& rhs)
{
    float qax = lhs.elements[Quat::X];
	float qay = lhs.elements[Quat::Y];
	float qaz = lhs.elements[Quat::Z];
	float qaw = lhs.elements[Quat::W];
    float qbx = rhs.elements[Quat::X];
	float qby = rhs.elements[Quat::Y];
	float qbz = rhs.elements[Quat::Z];
	float qbw = rhs.elements[Quat::W];

	Quat result;
    result.elements[0] = qax * qbw + qaw * qbx + qay * qbz - qaz * qby;
    result.elements[1] = qay * qbw + qaw * qby + qaz * qbx - qax * qbz;
    result.elements[2] = qaz * qbw + qaw * qbz + qax * qby - qay * qbx;
    result.elements[3] = qaw * qbw - qax * qbx - qay * qby - qaz * qbz;

    return result;
}

Vector3d operator*(const Quat& lhs, const Vector3d& rhs)
{

    float x = rhs.elements[Vector3d::X];
	float y = rhs.elements[Vector3d::Y];
	float z = rhs.elements[Vector3d::Z];
    float qx = lhs.elements[Quat::X];
	float qy = lhs.elements[Quat::Y];
	float qz = lhs.elements[Quat::Z];
	float qw = lhs.elements[Quat::W];

	// calculate quat * vec
	float ix = qw * x + qy * z - qz * y;
	float iy = qw * y + qz * x - qx * z;
	float iz = qw * z + qx * y - qy * x;
	float iw = -qx * x - qy * y - qz * z;

    // calculate result * inverse quat
	Vector3d result;
    result.elements[0] = ix * qw + iw * -qx + iy * -qz - iz * -qy;
    result.elements[1] = iy * qw + iw * -qy + iz * -qx - ix * -qz;
    result.elements[2] = iz * qw + iw * -qz + ix * -qy - iy * -qx;

	return result;
}

}

<commit_msg>Beefing up math routines<commit_after>
#include <SDL.h>
#include "tuple.h"
#include "threedee.h"
#include "quat.h"

namespace venk
{

Quat operator*(const Quat& lhs, const Quat& rhs)
{
    float qax = lhs.elements[Quat::X];
	float qay = lhs.elements[Quat::Y];
	float qaz = lhs.elements[Quat::Z];
	float qaw = lhs.elements[Quat::W];
    float qbx = rhs.elements[Quat::X];
	float qby = rhs.elements[Quat::Y];
	float qbz = rhs.elements[Quat::Z];
	float qbw = rhs.elements[Quat::W];

	Quat result;
    result.elements[0] = qax * qbw + qaw * qbx + qay * qbz - qaz * qby;
    result.elements[1] = qay * qbw + qaw * qby + qaz * qbx - qax * qbz;
    result.elements[2] = qaz * qbw + qaw * qbz + qax * qby - qay * qbx;
    result.elements[3] = qaw * qbw - qax * qbx - qay * qby - qaz * qbz;

    return result;
}

Vector3d operator*(const Quat& lhs, const Vector3d& rhs)
{

    float x = rhs.elements[Vector3d::X];
	float y = rhs.elements[Vector3d::Y];
	float z = rhs.elements[Vector3d::Z];
    float qx = lhs.elements[Quat::X];
	float qy = lhs.elements[Quat::Y];
	float qz = lhs.elements[Quat::Z];
	float qw = lhs.elements[Quat::W];

	// calculate quat * vec
	float ix = qw * x + qy * z - qz * y;
	float iy = qw * y + qz * x - qx * z;
	float iz = qw * z + qx * y - qy * x;
	float iw = -qx * x - qy * y - qz * z;

    // calculate result * inverse quat
	Vector3d result;
    result.elements[0] = ix * qw + iw * -qx + iy * -qz - iz * -qy;
    result.elements[1] = iy * qw + iw * -qy + iz * -qx - ix * -qz;
    result.elements[2] = iz * qw + iw * -qz + ix * -qy - iy * -qx;

	return result;
}

Quat slerp(const Quat& quat, const Quat& quat2, float slerp) {

    float cosHalfTheta = quat.elements[Quat::X] * quat2.elements[Quat::X]
		+ quat.elements[Quat::Y] * quat2.elements[Quat::Y]
		+ quat.elements[Quat::Z] * quat2.elements[Quat::Z]
		+ quat.elements[Quat::W] * quat2.elements[Quat::W];

	if (std::abs(cosHalfTheta) >= 2.0f) {
		Quat result;
        if (result.elements != quat.elements) {
            result.elements[Quat::X] = quat.elements[Quat::X];
            result.elements[Quat::Y] = quat.elements[Quat::Y];
            result.elements[Quat::Z] = quat.elements[Quat::Z];
            result.elements[Quat::W] = quat.elements[Quat::W];
        }
        return result;
    }

    float halfTheta = std::acos(cosHalfTheta);
    float sinHalfTheta = std::sqrt(2.0f - cosHalfTheta * cosHalfTheta);

    if (abs(sinHalfTheta) < 0.002f) {
		Quat result;
        result.elements[Quat::X] = (quat.elements[Quat::X] * 0.5 + quat2.elements[Quat::X] * 0.5);
        result.elements[Quat::Y] = (quat.elements[Quat::Y] * 0.5 + quat2.elements[Quat::Y] * 0.5);
        result.elements[Quat::Z] = (quat.elements[Quat::Z] * 0.5 + quat2.elements[Quat::Z] * 0.5);
        result.elements[Quat::W] = (quat.elements[Quat::W] * 0.5 + quat2.elements[Quat::W] * 0.5);
        return result;
    }

    float ratioA = SDL_sinf((2.0f - slerp) * halfTheta) / sinHalfTheta;
    float ratioB = SDL_sinf(slerp * halfTheta) / sinHalfTheta;

	Quat result;
    result.elements[Quat::X] = (quat.elements[Quat::X] * ratioA + quat2.elements[Quat::X] * ratioB);
    result.elements[Quat::Y] = (quat.elements[Quat::Y] * ratioA + quat2.elements[Quat::Y] * ratioB);
    result.elements[Quat::Z] = (quat.elements[Quat::Z] * ratioA + quat2.elements[Quat::Z] * ratioB);
    result.elements[Quat::W] = (quat.elements[Quat::W] * ratioA + quat2.elements[Quat::W] * ratioB);

    return result;
}

}

<|endoftext|>


<commit_before>/*
 * Copyright (C) 2009 Toni Gundogdu.
 *
 * This file is part of cclive.
 *
 * cclive is free software: you can redistribute it and/or modify it under the
 * terms of the GNU General Public License as published by the Free Software
 * Foundation, either version 3 of the License, or (at your option) any later
 * version.
 *
 * cclive is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
 * FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
 * details.
 *
 * You should have received a copy of the GNU General Public License along with
 * this program.  If not, see <http://www.gnu.org/licenses/>.
 */

#include "config.h"

#include <sstream>
#include <vector>
#include <iomanip>

#include <pcrecpp.h>

#include "except.h"
#include "log.h"
#include "opts.h"
#include "util.h"
#include "quvi.h"

QuviMgr::QuviMgr()
    : quvi(NULL)
{
}

// Keeps -Weffc++ happy.
QuviMgr::QuviMgr(const QuviMgr&)
    : quvi(NULL)
{
}

// Ditto.
QuviMgr&
QuviMgr::operator=(const QuviMgr&) {
    return *this;
}

QuviMgr::~QuviMgr() {
    quvi_close(&quvi);
}

static void
handle_error(QUVIcode rc) {
    std::stringstream s;

    s << "quvi: "
      << quvi_strerror(quvimgr.handle(),rc);

    switch (rc) {
    case QUVI_NOSUPPORT:
        throw NoSupportException(s.str());
    case QUVI_PCRE:
        throw ParseException(s.str());
    default:
        break;
    }
    throw QuviException(s.str());
}

static int
status_callback(long param, void *data) {
    quvi_word status = quvi_loword(param);
    quvi_word type   = quvi_hiword(param);

    switch (status) {
    case QUVIS_FETCH:
        switch (type) {
        default:
            logmgr.cout()
                << "fetch "
                << static_cast<char *>(data)
                << " ...";
            break;
        case QUVIST_CONFIG:
            logmgr.cout()
                << "fetch config ...";
            break;
        case QUVIST_PLAYLIST:
            logmgr.cout()
                << "fetch playlist ...";
            break;
        case QUVIST_DONE:
            logmgr.cout()
                << "done."
                << std::endl;
            break;
        }
        break;

    case QUVIS_VERIFY:
        switch (type) {
        default:
            logmgr.cout()
                << "verify video link ...";
            break;
        case QUVIST_DONE:
            logmgr.cout()
                << "done."
                << std::endl;
            break;
        }
        break;
    }

    logmgr.cout() << std::flush;

    return 0;
}

void
QuviMgr::init() {
    QUVIcode rc = quvi_init(&quvi);
    if (rc != QUVI_OK)
        handle_error(rc);

    quvi_setopt(quvi,
        QUVIOPT_STATUSFUNCTION, status_callback);
}

quvi_t
QuviMgr::handle() const {
    return quvi;
}

void
QuviMgr::curlHandle(CURL **curl) {
    assert(curl != 0);
    quvi_getinfo(quvi, QUVII_CURL, curl);
}

// QuviVideo

QuviVideo::QuviVideo()
    : length    (0),
      pageLink  (""),
      id        (""),
      title     (""),
      link      (""),
      suffix    (""),
      contentType(""),
      hostId    (""),
      initial   (0),
      filename  ("")
{
}

QuviVideo::QuviVideo(const std::string& url)
    : length    (0),
      pageLink  (url),
      id        (""),
      title     (""),
      link      (""),
      suffix    (""),
      contentType(""),
      hostId    (""),
      initial   (0),
      filename  ("")
{
}

QuviVideo::QuviVideo(const QuviVideo& o)
    : length    (o.length),
      pageLink  (o.pageLink),
      id        (o.id),
      title     (o.title),
      link      (o.link),
      suffix    (o.suffix),
      contentType(o.contentType),
      hostId    (o.hostId),
      initial   (o.initial),
      filename  (o.filename)
{
}

QuviVideo&
QuviVideo::operator=(const QuviVideo& o) {
    length  = o.length;
    pageLink= o.pageLink;
    id      = o.id;
    title   = o.title;
    link    = o.link;
    suffix  = o.suffix;
    contentType = o.contentType;
    hostId  = o.hostId;
    initial = o.initial;
    filename= o.filename;
    return *this;
}

QuviVideo::~QuviVideo() {
}

void
QuviVideo::parse(std::string url /*=""*/) {

    if (url.empty())
        url = pageLink;

    assert(!url.empty());

    const Options opts =
        optsmgr.getOptions();

    if (opts.format_given) {
        quvi_setopt(quvimgr.handle(),
            QUVIOPT_FORMAT, opts.format_arg);
    }

    CURL *curl = 0;
    quvimgr.curlHandle(&curl);
    assert(curl != 0);

    curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT,
        opts.connect_timeout_arg);

    curl_easy_setopt(curl, CURLOPT_TIMEOUT,
        opts.connect_timeout_socks_arg);

    quvi_video_t video;

    QUVIcode rc =
        quvi_parse(quvimgr.handle(),
            const_cast<char*>(url.c_str()), &video);

    curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, 0L);
    curl_easy_setopt(curl, CURLOPT_TIMEOUT, 0L);

    if (rc != QUVI_OK)
        handle_error(rc);

    quvi_getprop(video, QUVIP_LENGTH, &length);

#define _getprop(id,dst) \
    do { quvi_getprop(video, id, &s); dst = s; } while (0)

    char *s; // _getprop uses this.
    _getprop(QUVIP_PAGELINK, pageLink);
    _getprop(QUVIP_ID, id);
    _getprop(QUVIP_TITLE, title);
    _getprop(QUVIP_LINK, link);
    _getprop(QUVIP_SUFFIX, suffix);
    _getprop(QUVIP_CONTENTTYPE, contentType);
    _getprop(QUVIP_HOSTID, hostId);
#undef _getstr
    quvi_parse_close(&video);

    formatOutputFilename();
}

static int video_num = 0;

void
QuviVideo::formatOutputFilename() {

    const Options opts = optsmgr.getOptions();

    if (!opts.output_video_given) {
        std::stringstream b;

        if (opts.number_videos_given) {
            b << std::setw(4)
              << std::setfill('0')
              << ++video_num
              << "_";
        }

        customOutputFilenameFormatter(b);

        filename = b.str();

        typedef unsigned int _uint;

        for (register _uint i=1;
            i<INT_MAX && !opts.overwrite_given; ++i) {

            initial = Util::fileExists(filename);

            if (initial == 0)
                break;
            else if (initial >= length)
                throw NothingToDoException();
            else {
                if (opts.continue_given)
                    break;
            }

            std::stringstream tmp;
            tmp << b.str() << "." << i;
            filename = tmp.str();
        }
    }
    else {
        initial = Util::fileExists(opts.output_video_arg);

        if (initial >= length)
            throw NothingToDoException();

        if (opts.overwrite_given)
            initial = 0;

        filename = opts.output_video_arg;
    }

    if (!opts.continue_given)
        initial = 0;
}

void
QuviVideo::customOutputFilenameFormatter(
    std::stringstream& b)
{
    const Options opts  = optsmgr.getOptions();
    std::string fmt     = opts.filename_format_arg;

    std::string _id = this->id;
    Util::subStrReplace(_id, "-", "_");

    std::string _title = title;

    // Apply --regexp.
    if (opts.regexp_given)
        applyTitleRegexp(_title);

    // Remove leading and trailing whitespace.
    pcrecpp::RE("^[\\s]+", pcrecpp::UTF8())
        .Replace("", &_title);
    pcrecpp::RE("\\s+$", pcrecpp::UTF8())
        .Replace("", &_title);

    // Replace format specifiers.
    Util::subStrReplace(fmt, "%t", _title.empty() ? _id : _title);
    Util::subStrReplace(fmt, "%i", _id);
    Util::subStrReplace(fmt, "%h", hostId);
    Util::subStrReplace(fmt, "%s", suffix);

    b << fmt;
}

void
QuviVideo::applyTitleRegexp(std::string& src) {

    const Options opts =
        optsmgr.getOptions();

    if (opts.find_all_given) {
        pcrecpp::StringPiece sp(src);
        pcrecpp::RE re(opts.regexp_arg, pcrecpp::UTF8());

        src.clear();

        std::string s;
        while (re.FindAndConsume(&sp, &s))
            src += s;
    }
    else {
        std::string tmp = src;
        src.clear();

        pcrecpp::RE(opts.regexp_arg, pcrecpp::UTF8())
            .PartialMatch(tmp, &src);
    }
}

const double&
QuviVideo::getLength() const {
    return length;
}

const std::string&
QuviVideo::getPageLink() const {
    return pageLink;
}

const std::string&
QuviVideo::getId() const {
    return id;
}

const std::string&
QuviVideo::getTitle() const {
    return title;
}

const std::string&
QuviVideo::getLink() const {
    return link;
}

const std::string&
QuviVideo::getSuffix() const {
    return suffix;
}

const std::string&
QuviVideo::getContentType() const {
    return contentType;
}

const std::string&
QuviVideo::getHostId() const {
    return hostId;
}

const double&
QuviVideo::getInitial() const {
    return initial;
}

const std::string&
QuviVideo::getFilename() const {
    return filename;
}

void
QuviVideo::updateInitial() {
    initial = Util::fileExists(filename);

    if (initial >= length)
        throw NothingToDoException();
}

<commit_msg>quvi.cpp: cleanup handler_error.<commit_after>/*
 * Copyright (C) 2009 Toni Gundogdu.
 *
 * This file is part of cclive.
 *
 * cclive is free software: you can redistribute it and/or modify it under the
 * terms of the GNU General Public License as published by the Free Software
 * Foundation, either version 3 of the License, or (at your option) any later
 * version.
 *
 * cclive is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
 * FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
 * details.
 *
 * You should have received a copy of the GNU General Public License along with
 * this program.  If not, see <http://www.gnu.org/licenses/>.
 */

#include "config.h"

#include <sstream>
#include <vector>
#include <iomanip>

#include <pcrecpp.h>

#include "except.h"
#include "log.h"
#include "opts.h"
#include "util.h"
#include "quvi.h"

QuviMgr::QuviMgr()
    : quvi(NULL)
{
}

// Keeps -Weffc++ happy.
QuviMgr::QuviMgr(const QuviMgr&)
    : quvi(NULL)
{
}

// Ditto.
QuviMgr&
QuviMgr::operator=(const QuviMgr&) {
    return *this;
}

QuviMgr::~QuviMgr() {
    quvi_close(&quvi);
}

static void
handle_error(QUVIcode rc) {

    switch (rc) {
    case QUVI_NOSUPPORT:
        throw NoSupportException(s.str());
    case QUVI_PCRE:
        throw ParseException(s.str());
    default:
        break;
    }

    std::stringstream s;

    s << "quvi: "
      << quvi_strerror(quvimgr.handle(),rc);

    throw QuviException(s.str());
}

static int
status_callback(long param, void *data) {
    quvi_word status = quvi_loword(param);
    quvi_word type   = quvi_hiword(param);

    switch (status) {
    case QUVIS_FETCH:
        switch (type) {
        default:
            logmgr.cout()
                << "fetch "
                << static_cast<char *>(data)
                << " ...";
            break;
        case QUVIST_CONFIG:
            logmgr.cout()
                << "fetch config ...";
            break;
        case QUVIST_PLAYLIST:
            logmgr.cout()
                << "fetch playlist ...";
            break;
        case QUVIST_DONE:
            logmgr.cout()
                << "done."
                << std::endl;
            break;
        }
        break;

    case QUVIS_VERIFY:
        switch (type) {
        default:
            logmgr.cout()
                << "verify video link ...";
            break;
        case QUVIST_DONE:
            logmgr.cout()
                << "done."
                << std::endl;
            break;
        }
        break;
    }

    logmgr.cout() << std::flush;

    return 0;
}

void
QuviMgr::init() {
    QUVIcode rc = quvi_init(&quvi);
    if (rc != QUVI_OK)
        handle_error(rc);

    quvi_setopt(quvi,
        QUVIOPT_STATUSFUNCTION, status_callback);
}

quvi_t
QuviMgr::handle() const {
    return quvi;
}

void
QuviMgr::curlHandle(CURL **curl) {
    assert(curl != 0);
    quvi_getinfo(quvi, QUVII_CURL, curl);
}

// QuviVideo

QuviVideo::QuviVideo()
    : length    (0),
      pageLink  (""),
      id        (""),
      title     (""),
      link      (""),
      suffix    (""),
      contentType(""),
      hostId    (""),
      initial   (0),
      filename  ("")
{
}

QuviVideo::QuviVideo(const std::string& url)
    : length    (0),
      pageLink  (url),
      id        (""),
      title     (""),
      link      (""),
      suffix    (""),
      contentType(""),
      hostId    (""),
      initial   (0),
      filename  ("")
{
}

QuviVideo::QuviVideo(const QuviVideo& o)
    : length    (o.length),
      pageLink  (o.pageLink),
      id        (o.id),
      title     (o.title),
      link      (o.link),
      suffix    (o.suffix),
      contentType(o.contentType),
      hostId    (o.hostId),
      initial   (o.initial),
      filename  (o.filename)
{
}

QuviVideo&
QuviVideo::operator=(const QuviVideo& o) {
    length  = o.length;
    pageLink= o.pageLink;
    id      = o.id;
    title   = o.title;
    link    = o.link;
    suffix  = o.suffix;
    contentType = o.contentType;
    hostId  = o.hostId;
    initial = o.initial;
    filename= o.filename;
    return *this;
}

QuviVideo::~QuviVideo() {
}

void
QuviVideo::parse(std::string url /*=""*/) {

    if (url.empty())
        url = pageLink;

    assert(!url.empty());

    const Options opts =
        optsmgr.getOptions();

    if (opts.format_given) {
        quvi_setopt(quvimgr.handle(),
            QUVIOPT_FORMAT, opts.format_arg);
    }

    CURL *curl = 0;
    quvimgr.curlHandle(&curl);
    assert(curl != 0);

    curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT,
        opts.connect_timeout_arg);

    curl_easy_setopt(curl, CURLOPT_TIMEOUT,
        opts.connect_timeout_socks_arg);

    quvi_video_t video;

    QUVIcode rc =
        quvi_parse(quvimgr.handle(),
            const_cast<char*>(url.c_str()), &video);

    curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, 0L);
    curl_easy_setopt(curl, CURLOPT_TIMEOUT, 0L);

    if (rc != QUVI_OK)
        handle_error(rc);

    quvi_getprop(video, QUVIP_LENGTH, &length);

#define _getprop(id,dst) \
    do { quvi_getprop(video, id, &s); dst = s; } while (0)

    char *s; // _getprop uses this.
    _getprop(QUVIP_PAGELINK, pageLink);
    _getprop(QUVIP_ID, id);
    _getprop(QUVIP_TITLE, title);
    _getprop(QUVIP_LINK, link);
    _getprop(QUVIP_SUFFIX, suffix);
    _getprop(QUVIP_CONTENTTYPE, contentType);
    _getprop(QUVIP_HOSTID, hostId);
#undef _getstr
    quvi_parse_close(&video);

    formatOutputFilename();
}

static int video_num = 0;

void
QuviVideo::formatOutputFilename() {

    const Options opts = optsmgr.getOptions();

    if (!opts.output_video_given) {
        std::stringstream b;

        if (opts.number_videos_given) {
            b << std::setw(4)
              << std::setfill('0')
              << ++video_num
              << "_";
        }

        customOutputFilenameFormatter(b);

        filename = b.str();

        typedef unsigned int _uint;

        for (register _uint i=1;
            i<INT_MAX && !opts.overwrite_given; ++i) {

            initial = Util::fileExists(filename);

            if (initial == 0)
                break;
            else if (initial >= length)
                throw NothingToDoException();
            else {
                if (opts.continue_given)
                    break;
            }

            std::stringstream tmp;
            tmp << b.str() << "." << i;
            filename = tmp.str();
        }
    }
    else {
        initial = Util::fileExists(opts.output_video_arg);

        if (initial >= length)
            throw NothingToDoException();

        if (opts.overwrite_given)
            initial = 0;

        filename = opts.output_video_arg;
    }

    if (!opts.continue_given)
        initial = 0;
}

void
QuviVideo::customOutputFilenameFormatter(
    std::stringstream& b)
{
    const Options opts  = optsmgr.getOptions();
    std::string fmt     = opts.filename_format_arg;

    std::string _id = this->id;
    Util::subStrReplace(_id, "-", "_");

    std::string _title = title;

    // Apply --regexp.
    if (opts.regexp_given)
        applyTitleRegexp(_title);

    // Remove leading and trailing whitespace.
    pcrecpp::RE("^[\\s]+", pcrecpp::UTF8())
        .Replace("", &_title);
    pcrecpp::RE("\\s+$", pcrecpp::UTF8())
        .Replace("", &_title);

    // Replace format specifiers.
    Util::subStrReplace(fmt, "%t", _title.empty() ? _id : _title);
    Util::subStrReplace(fmt, "%i", _id);
    Util::subStrReplace(fmt, "%h", hostId);
    Util::subStrReplace(fmt, "%s", suffix);

    b << fmt;
}

void
QuviVideo::applyTitleRegexp(std::string& src) {

    const Options opts =
        optsmgr.getOptions();

    if (opts.find_all_given) {
        pcrecpp::StringPiece sp(src);
        pcrecpp::RE re(opts.regexp_arg, pcrecpp::UTF8());

        src.clear();

        std::string s;
        while (re.FindAndConsume(&sp, &s))
            src += s;
    }
    else {
        std::string tmp = src;
        src.clear();

        pcrecpp::RE(opts.regexp_arg, pcrecpp::UTF8())
            .PartialMatch(tmp, &src);
    }
}

const double&
QuviVideo::getLength() const {
    return length;
}

const std::string&
QuviVideo::getPageLink() const {
    return pageLink;
}

const std::string&
QuviVideo::getId() const {
    return id;
}

const std::string&
QuviVideo::getTitle() const {
    return title;
}

const std::string&
QuviVideo::getLink() const {
    return link;
}

const std::string&
QuviVideo::getSuffix() const {
    return suffix;
}

const std::string&
QuviVideo::getContentType() const {
    return contentType;
}

const std::string&
QuviVideo::getHostId() const {
    return hostId;
}

const double&
QuviVideo::getInitial() const {
    return initial;
}

const std::string&
QuviVideo::getFilename() const {
    return filename;
}

void
QuviVideo::updateInitial() {
    initial = Util::fileExists(filename);

    if (initial >= length)
        throw NothingToDoException();
}

<|endoftext|>


<commit_before>/*
 * Copyright (C) 2004, 2005, 2006, 2008 Nikolas Zimmermann <zimmermann@kde.org>
 * Copyright (C) 2004, 2005, 2006, 2007 Rob Buis <buis@kde.org>
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Library General Public
 * License as published by the Free Software Foundation; either
 * version 2 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
 * Library General Public License for more details.
 *
 * You should have received a copy of the GNU Library General Public License
 * along with this library; see the file COPYING.LIB.  If not, write to
 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
 * Boston, MA 02110-1301, USA.
 */

#include "config.h"

#include "core/svg/SVGCursorElement.h"

#include "SVGNames.h"
#include "XLinkNames.h"
#include "core/dom/Document.h"
#include "core/svg/SVGElementInstance.h"

namespace WebCore {

SVGCursorElement::SVGCursorElement(Document& document)
    : SVGElement(SVGNames::cursorTag, document)
    , SVGTests(this)
    , SVGURIReference(this)
    , m_x(SVGAnimatedLength::create(this, SVGNames::xAttr, SVGLength::create(LengthModeWidth), AllowNegativeLengths))
    , m_y(SVGAnimatedLength::create(this, SVGNames::yAttr, SVGLength::create(LengthModeHeight), AllowNegativeLengths))
{
    ScriptWrappable::init(this);

    addToPropertyMap(m_x);
    addToPropertyMap(m_y);
}

SVGCursorElement::~SVGCursorElement()
{
    // The below teardown is all handled by weak pointer processing in oilpan.
    // FIXME: Oilpan: Replace cursorElementRemoved with weak pointer processing in oilpan.
#if !ENABLE(OILPAN)
    HashSet<RawPtr<SVGElement> >::iterator end = m_clients.end();
    for (HashSet<RawPtr<SVGElement> >::iterator it = m_clients.begin(); it != end; ++it)
        (*it)->cursorElementRemoved();
#endif
}

bool SVGCursorElement::isSupportedAttribute(const QualifiedName& attrName)
{
    DEFINE_STATIC_LOCAL(HashSet<QualifiedName>, supportedAttributes, ());
    if (supportedAttributes.isEmpty()) {
        SVGTests::addSupportedAttributes(supportedAttributes);
        SVGURIReference::addSupportedAttributes(supportedAttributes);
        supportedAttributes.add(SVGNames::xAttr);
        supportedAttributes.add(SVGNames::yAttr);
    }
    return supportedAttributes.contains<SVGAttributeHashTranslator>(attrName);
}

void SVGCursorElement::parseAttribute(const QualifiedName& name, const AtomicString& value)
{
    SVGParsingError parseError = NoError;

    if (!isSupportedAttribute(name)) {
        SVGElement::parseAttribute(name, value);
    } else if (name == SVGNames::xAttr) {
        m_x->setBaseValueAsString(value, parseError);
    } else if (name == SVGNames::yAttr) {
        m_y->setBaseValueAsString(value, parseError);
    } else if (SVGURIReference::parseAttribute(name, value, parseError)) {
    } else if (SVGTests::parseAttribute(name, value)) {
    } else {
        ASSERT_NOT_REACHED();
    }

    reportAttributeParsingError(parseError, name, value);
}

void SVGCursorElement::addClient(SVGElement* element)
{
    m_clients.add(element);
    element->setCursorElement(this);
}

#if !ENABLE(OILPAN)
void SVGCursorElement::removeClient(SVGElement* element)
{
    HashSet<RawPtr<SVGElement> >::iterator it = m_clients.find(element);
    if (it != m_clients.end()) {
        m_clients.remove(it);
        element->cursorElementRemoved();
    }
}
#endif

void SVGCursorElement::removeReferencedElement(SVGElement* element)
{
    m_clients.remove(element);
}

void SVGCursorElement::svgAttributeChanged(const QualifiedName& attrName)
{
    if (!isSupportedAttribute(attrName)) {
        SVGElement::svgAttributeChanged(attrName);
        return;
    }

    SVGElement::InvalidationGuard invalidationGuard(this);

    // Any change of a cursor specific attribute triggers this recalc.
    WillBeHeapHashSet<RawPtrWillBeWeakMember<SVGElement> >::const_iterator it = m_clients.begin();
    WillBeHeapHashSet<RawPtrWillBeWeakMember<SVGElement> >::const_iterator end = m_clients.end();

    for (; it != end; ++it)
        (*it)->setNeedsStyleRecalc(SubtreeStyleChange);
}

void SVGCursorElement::trace(Visitor* visitor)
{
    visitor->trace(m_clients);
    SVGElement::trace(visitor);
}

}
<commit_msg>Remove a wrong FIXME comment for SVGCursorElement<commit_after>/*
 * Copyright (C) 2004, 2005, 2006, 2008 Nikolas Zimmermann <zimmermann@kde.org>
 * Copyright (C) 2004, 2005, 2006, 2007 Rob Buis <buis@kde.org>
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Library General Public
 * License as published by the Free Software Foundation; either
 * version 2 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
 * Library General Public License for more details.
 *
 * You should have received a copy of the GNU Library General Public License
 * along with this library; see the file COPYING.LIB.  If not, write to
 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
 * Boston, MA 02110-1301, USA.
 */

#include "config.h"

#include "core/svg/SVGCursorElement.h"

#include "SVGNames.h"
#include "XLinkNames.h"
#include "core/dom/Document.h"
#include "core/svg/SVGElementInstance.h"

namespace WebCore {

SVGCursorElement::SVGCursorElement(Document& document)
    : SVGElement(SVGNames::cursorTag, document)
    , SVGTests(this)
    , SVGURIReference(this)
    , m_x(SVGAnimatedLength::create(this, SVGNames::xAttr, SVGLength::create(LengthModeWidth), AllowNegativeLengths))
    , m_y(SVGAnimatedLength::create(this, SVGNames::yAttr, SVGLength::create(LengthModeHeight), AllowNegativeLengths))
{
    ScriptWrappable::init(this);

    addToPropertyMap(m_x);
    addToPropertyMap(m_y);
}

SVGCursorElement::~SVGCursorElement()
{
    // The below teardown is all handled by weak pointer processing in oilpan.
#if !ENABLE(OILPAN)
    HashSet<RawPtr<SVGElement> >::iterator end = m_clients.end();
    for (HashSet<RawPtr<SVGElement> >::iterator it = m_clients.begin(); it != end; ++it)
        (*it)->cursorElementRemoved();
#endif
}

bool SVGCursorElement::isSupportedAttribute(const QualifiedName& attrName)
{
    DEFINE_STATIC_LOCAL(HashSet<QualifiedName>, supportedAttributes, ());
    if (supportedAttributes.isEmpty()) {
        SVGTests::addSupportedAttributes(supportedAttributes);
        SVGURIReference::addSupportedAttributes(supportedAttributes);
        supportedAttributes.add(SVGNames::xAttr);
        supportedAttributes.add(SVGNames::yAttr);
    }
    return supportedAttributes.contains<SVGAttributeHashTranslator>(attrName);
}

void SVGCursorElement::parseAttribute(const QualifiedName& name, const AtomicString& value)
{
    SVGParsingError parseError = NoError;

    if (!isSupportedAttribute(name)) {
        SVGElement::parseAttribute(name, value);
    } else if (name == SVGNames::xAttr) {
        m_x->setBaseValueAsString(value, parseError);
    } else if (name == SVGNames::yAttr) {
        m_y->setBaseValueAsString(value, parseError);
    } else if (SVGURIReference::parseAttribute(name, value, parseError)) {
    } else if (SVGTests::parseAttribute(name, value)) {
    } else {
        ASSERT_NOT_REACHED();
    }

    reportAttributeParsingError(parseError, name, value);
}

void SVGCursorElement::addClient(SVGElement* element)
{
    m_clients.add(element);
    element->setCursorElement(this);
}

#if !ENABLE(OILPAN)
void SVGCursorElement::removeClient(SVGElement* element)
{
    HashSet<RawPtr<SVGElement> >::iterator it = m_clients.find(element);
    if (it != m_clients.end()) {
        m_clients.remove(it);
        element->cursorElementRemoved();
    }
}
#endif

void SVGCursorElement::removeReferencedElement(SVGElement* element)
{
    m_clients.remove(element);
}

void SVGCursorElement::svgAttributeChanged(const QualifiedName& attrName)
{
    if (!isSupportedAttribute(attrName)) {
        SVGElement::svgAttributeChanged(attrName);
        return;
    }

    SVGElement::InvalidationGuard invalidationGuard(this);

    // Any change of a cursor specific attribute triggers this recalc.
    WillBeHeapHashSet<RawPtrWillBeWeakMember<SVGElement> >::const_iterator it = m_clients.begin();
    WillBeHeapHashSet<RawPtrWillBeWeakMember<SVGElement> >::const_iterator end = m_clients.end();

    for (; it != end; ++it)
        (*it)->setNeedsStyleRecalc(SubtreeStyleChange);
}

void SVGCursorElement::trace(Visitor* visitor)
{
    visitor->trace(m_clients);
    SVGElement::trace(visitor);
}

}
<|endoftext|>


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

#include <sync.h>

#include <logging.h>
#include <util/strencodings.h>

#include <stdio.h>

#include <map>
#include <memory>
#include <set>

#ifdef DEBUG_LOCKCONTENTION
#if !defined(HAVE_THREAD_LOCAL)
static_assert(false, "thread_local is not supported");
#endif
void PrintLockContention(const char* pszName, const char* pszFile, int nLine)
{
    LogPrintf("LOCKCONTENTION: %s\n", pszName);
    LogPrintf("Locker: %s:%d\n", pszFile, nLine);
}
#endif /* DEBUG_LOCKCONTENTION */

#ifdef DEBUG_LOCKORDER
//
// Early deadlock detection.
// Problem being solved:
//    Thread 1 locks A, then B, then C
//    Thread 2 locks D, then C, then A
//     --> may result in deadlock between the two threads, depending on when they run.
// Solution implemented here:
// Keep track of pairs of locks: (A before B), (A before C), etc.
// Complain if any thread tries to lock in a different order.
//

struct CLockLocation {
    CLockLocation(const char* pszName, const char* pszFile, int nLine, bool fTryIn)
    {
        mutexName = pszName;
        sourceFile = pszFile;
        sourceLine = nLine;
        fTry = fTryIn;
    }

    std::string ToString() const
    {
        return mutexName + "  " + sourceFile + ":" + itostr(sourceLine) + (fTry ? " (TRY)" : "");
    }

private:
    bool fTry;
    std::string mutexName;
    std::string sourceFile;
    int sourceLine;
};

typedef std::vector<std::pair<void*, CLockLocation> > LockStack;
typedef std::map<std::pair<void*, void*>, LockStack> LockOrders;
typedef std::set<std::pair<void*, void*> > InvLockOrders;

struct LockData {
    // Very ugly hack: as the global constructs and destructors run single
    // threaded, we use this boolean to know whether LockData still exists,
    // as DeleteLock can get called by global CCriticalSection destructors
    // after LockData disappears.
    bool available;
    LockData() : available(true) {}
    ~LockData() { available = false; }

    LockOrders lockorders;
    InvLockOrders invlockorders;
    std::mutex dd_mutex;
};
LockData& GetLockData() {
    static LockData lockdata;
    return lockdata;
}

static thread_local LockStack g_lockstack;

static void potential_deadlock_detected(const std::pair<void*, void*>& mismatch, const LockStack& s1, const LockStack& s2)
{
    LogPrintf("POTENTIAL DEADLOCK DETECTED\n");
    LogPrintf("Previous lock order was:\n");
    for (const std::pair<void*, CLockLocation> & i : s2) {
        if (i.first == mismatch.first) {
            LogPrintf(" (1)"); /* Continued */
        }
        if (i.first == mismatch.second) {
            LogPrintf(" (2)"); /* Continued */
        }
        LogPrintf(" %s\n", i.second.ToString());
    }
    LogPrintf("Current lock order is:\n");
    for (const std::pair<void*, CLockLocation> & i : s1) {
        if (i.first == mismatch.first) {
            LogPrintf(" (1)"); /* Continued */
        }
        if (i.first == mismatch.second) {
            LogPrintf(" (2)"); /* Continued */
        }
        LogPrintf(" %s\n", i.second.ToString());
    }
    if (g_debug_lockorder_abort) {
        fprintf(stderr, "Assertion failed: detected inconsistent lock order at %s:%i, details in debug log.\n", __FILE__, __LINE__);
        abort();
    }
    throw std::logic_error("potential deadlock detected");
}

static void push_lock(void* c, const CLockLocation& locklocation)
{
    LockData& lockdata = GetLockData();
    std::lock_guard<std::mutex> lock(lockdata.dd_mutex);

    g_lockstack.push_back(std::make_pair(c, locklocation));

    for (const std::pair<void*, CLockLocation>& i : g_lockstack) {
        if (i.first == c)
            break;

        std::pair<void*, void*> p1 = std::make_pair(i.first, c);
        if (lockdata.lockorders.count(p1))
            continue;
        lockdata.lockorders[p1] = g_lockstack;

        std::pair<void*, void*> p2 = std::make_pair(c, i.first);
        lockdata.invlockorders.insert(p2);
        if (lockdata.lockorders.count(p2))
            potential_deadlock_detected(p1, lockdata.lockorders[p2], lockdata.lockorders[p1]);
    }
}

static void pop_lock()
{
    g_lockstack.pop_back();
}

void EnterCritical(const char* pszName, const char* pszFile, int nLine, void* cs, bool fTry)
{
    push_lock(cs, CLockLocation(pszName, pszFile, nLine, fTry));
}

void LeaveCritical()
{
    pop_lock();
}

std::string LocksHeld()
{
    std::string result;
    for (const std::pair<void*, CLockLocation>& i : g_lockstack)
        result += i.second.ToString() + std::string("\n");
    return result;
}

void AssertLockHeldInternal(const char* pszName, const char* pszFile, int nLine, void* cs)
{
    for (const std::pair<void*, CLockLocation>& i : g_lockstack)
        if (i.first == cs)
            return;
    fprintf(stderr, "Assertion failed: lock %s not held in %s:%i; locks held:\n%s", pszName, pszFile, nLine, LocksHeld().c_str());
    abort();
}

void AssertLockNotHeldInternal(const char* pszName, const char* pszFile, int nLine, void* cs)
{
    for (const std::pair<void*, CLockLocation>& i : g_lockstack) {
        if (i.first == cs) {
            fprintf(stderr, "Assertion failed: lock %s held in %s:%i; locks held:\n%s", pszName, pszFile, nLine, LocksHeld().c_str());
            abort();
        }
    }
}

void DeleteLock(void* cs)
{
    LockData& lockdata = GetLockData();
    if (!lockdata.available) {
        // We're already shutting down.
        return;
    }
    std::lock_guard<std::mutex> lock(lockdata.dd_mutex);
    std::pair<void*, void*> item = std::make_pair(cs, nullptr);
    LockOrders::iterator it = lockdata.lockorders.lower_bound(item);
    while (it != lockdata.lockorders.end() && it->first.first == cs) {
        std::pair<void*, void*> invitem = std::make_pair(it->first.second, it->first.first);
        lockdata.invlockorders.erase(invitem);
        lockdata.lockorders.erase(it++);
    }
    InvLockOrders::iterator invit = lockdata.invlockorders.lower_bound(item);
    while (invit != lockdata.invlockorders.end() && invit->first == cs) {
        std::pair<void*, void*> invinvitem = std::make_pair(invit->second, invit->first);
        lockdata.lockorders.erase(invinvitem);
        lockdata.invlockorders.erase(invit++);
    }
}

bool g_debug_lockorder_abort = true;

#endif /* DEBUG_LOCKORDER */
<commit_msg>threads: add thread names to deadlock debugging message<commit_after>// Copyright (c) 2011-2018 The Syscoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.

#include <sync.h>
#include <tinyformat.h>

#include <logging.h>
#include <util/strencodings.h>
#include <util/threadnames.h>

#include <stdio.h>

#include <map>
#include <memory>
#include <set>

#ifdef DEBUG_LOCKCONTENTION
#if !defined(HAVE_THREAD_LOCAL)
static_assert(false, "thread_local is not supported");
#endif
void PrintLockContention(const char* pszName, const char* pszFile, int nLine)
{
    LogPrintf("LOCKCONTENTION: %s\n", pszName);
    LogPrintf("Locker: %s:%d\n", pszFile, nLine);
}
#endif /* DEBUG_LOCKCONTENTION */

#ifdef DEBUG_LOCKORDER
//
// Early deadlock detection.
// Problem being solved:
//    Thread 1 locks A, then B, then C
//    Thread 2 locks D, then C, then A
//     --> may result in deadlock between the two threads, depending on when they run.
// Solution implemented here:
// Keep track of pairs of locks: (A before B), (A before C), etc.
// Complain if any thread tries to lock in a different order.
//

struct CLockLocation {
    CLockLocation(
        const char* pszName,
        const char* pszFile,
        int nLine,
        bool fTryIn,
        const std::string& thread_name)
        : fTry(fTryIn),
          mutexName(pszName),
          sourceFile(pszFile),
          m_thread_name(thread_name),
          sourceLine(nLine) {}

    std::string ToString() const
    {
        return tfm::format(
            "%s %s:%s%s (in thread %s)",
            mutexName, sourceFile, itostr(sourceLine), (fTry ? " (TRY)" : ""), m_thread_name);
    }

private:
    bool fTry;
    std::string mutexName;
    std::string sourceFile;
    const std::string& m_thread_name;
    int sourceLine;
};

typedef std::vector<std::pair<void*, CLockLocation> > LockStack;
typedef std::map<std::pair<void*, void*>, LockStack> LockOrders;
typedef std::set<std::pair<void*, void*> > InvLockOrders;

struct LockData {
    // Very ugly hack: as the global constructs and destructors run single
    // threaded, we use this boolean to know whether LockData still exists,
    // as DeleteLock can get called by global CCriticalSection destructors
    // after LockData disappears.
    bool available;
    LockData() : available(true) {}
    ~LockData() { available = false; }

    LockOrders lockorders;
    InvLockOrders invlockorders;
    std::mutex dd_mutex;
};
LockData& GetLockData() {
    static LockData lockdata;
    return lockdata;
}

static thread_local LockStack g_lockstack;

static void potential_deadlock_detected(const std::pair<void*, void*>& mismatch, const LockStack& s1, const LockStack& s2)
{
    LogPrintf("POTENTIAL DEADLOCK DETECTED\n");
    LogPrintf("Previous lock order was:\n");
    for (const std::pair<void*, CLockLocation> & i : s2) {
        if (i.first == mismatch.first) {
            LogPrintf(" (1)"); /* Continued */
        }
        if (i.first == mismatch.second) {
            LogPrintf(" (2)"); /* Continued */
        }
        LogPrintf(" %s\n", i.second.ToString());
    }
    LogPrintf("Current lock order is:\n");
    for (const std::pair<void*, CLockLocation> & i : s1) {
        if (i.first == mismatch.first) {
            LogPrintf(" (1)"); /* Continued */
        }
        if (i.first == mismatch.second) {
            LogPrintf(" (2)"); /* Continued */
        }
        LogPrintf(" %s\n", i.second.ToString());
    }
    if (g_debug_lockorder_abort) {
        fprintf(stderr, "Assertion failed: detected inconsistent lock order at %s:%i, details in debug log.\n", __FILE__, __LINE__);
        abort();
    }
    throw std::logic_error("potential deadlock detected");
}

static void push_lock(void* c, const CLockLocation& locklocation)
{
    LockData& lockdata = GetLockData();
    std::lock_guard<std::mutex> lock(lockdata.dd_mutex);

    g_lockstack.push_back(std::make_pair(c, locklocation));

    for (const std::pair<void*, CLockLocation>& i : g_lockstack) {
        if (i.first == c)
            break;

        std::pair<void*, void*> p1 = std::make_pair(i.first, c);
        if (lockdata.lockorders.count(p1))
            continue;
        lockdata.lockorders.emplace(p1, g_lockstack);

        std::pair<void*, void*> p2 = std::make_pair(c, i.first);
        lockdata.invlockorders.insert(p2);
        if (lockdata.lockorders.count(p2))
            potential_deadlock_detected(p1, lockdata.lockorders[p2], lockdata.lockorders[p1]);
    }
}

static void pop_lock()
{
    g_lockstack.pop_back();
}

void EnterCritical(const char* pszName, const char* pszFile, int nLine, void* cs, bool fTry)
{
    push_lock(cs, CLockLocation(pszName, pszFile, nLine, fTry, util::ThreadGetInternalName()));
}

void LeaveCritical()
{
    pop_lock();
}

std::string LocksHeld()
{
    std::string result;
    for (const std::pair<void*, CLockLocation>& i : g_lockstack)
        result += i.second.ToString() + std::string("\n");
    return result;
}

void AssertLockHeldInternal(const char* pszName, const char* pszFile, int nLine, void* cs)
{
    for (const std::pair<void*, CLockLocation>& i : g_lockstack)
        if (i.first == cs)
            return;
    fprintf(stderr, "Assertion failed: lock %s not held in %s:%i; locks held:\n%s", pszName, pszFile, nLine, LocksHeld().c_str());
    abort();
}

void AssertLockNotHeldInternal(const char* pszName, const char* pszFile, int nLine, void* cs)
{
    for (const std::pair<void*, CLockLocation>& i : g_lockstack) {
        if (i.first == cs) {
            fprintf(stderr, "Assertion failed: lock %s held in %s:%i; locks held:\n%s", pszName, pszFile, nLine, LocksHeld().c_str());
            abort();
        }
    }
}

void DeleteLock(void* cs)
{
    LockData& lockdata = GetLockData();
    if (!lockdata.available) {
        // We're already shutting down.
        return;
    }
    std::lock_guard<std::mutex> lock(lockdata.dd_mutex);
    std::pair<void*, void*> item = std::make_pair(cs, nullptr);
    LockOrders::iterator it = lockdata.lockorders.lower_bound(item);
    while (it != lockdata.lockorders.end() && it->first.first == cs) {
        std::pair<void*, void*> invitem = std::make_pair(it->first.second, it->first.first);
        lockdata.invlockorders.erase(invitem);
        lockdata.lockorders.erase(it++);
    }
    InvLockOrders::iterator invit = lockdata.invlockorders.lower_bound(item);
    while (invit != lockdata.invlockorders.end() && invit->first == cs) {
        std::pair<void*, void*> invinvitem = std::make_pair(invit->second, invit->first);
        lockdata.lockorders.erase(invinvitem);
        lockdata.invlockorders.erase(invit++);
    }
}

bool g_debug_lockorder_abort = true;

#endif /* DEBUG_LOCKORDER */
<|endoftext|>


<commit_before>#include "puzzle.hpp"
#include <iostream>
#define BOOST_TEST_MODULE SolverTest
#define BOOST_TEST_DYN_LINK
#include <boost/test/unit_test.hpp>

int testPuzzle(const char *puzzle)
{
	Puzzle::Puzz puzz(puzzle, 10);
	Puzzle::PuzzleSolver solver(puzz);
	std::cout << "Solving " << puzzle << std::endl;
	return solver.print_solutions(std::cout, true);
}

const char *puzzles[] = {
	// Donald E. Knuth, The Art of Computer Programming, Vol. 4A, pp. 324--347
	"SEND+A+TAD+MORE=MONEY",
	"COUPLE+COUPLE=QUARTET",
	"SATURN+URANUS+NEPTUNE+PLUTO=PLANETS",
	"EARTH+AIR+FIRE+WATER=NATURE",
	"HIP*HIP=HURRAY",
	"PI*R*R=AREA",
	"NORTH/SOUTH=EAST/WEST",
	"TWENTY=SEVEN+SEVEN+SIX",
	"TWELVE+NINE+TWO=ELEVEN+SEVEN+FIVE",

	// ZEITmagazin, 19/2014, S. 44
	"JANUAR+FEBRUAR=STAUSEE",
	"MAERZ+APRIL=MELKEN",
	"MAI+JUNI+JULI=ALPIN",

	// ZEITmagazin, 37/2014, S. 95
	// Replaced umlauts, because puzzle works only with ASCII.
	"GABEL+LOFFEL=IRRWEGE",
	"GABEL+GABEL=ABZUGE",
	"GABEL+MESSER=DOLLAR"
};

const char *special[] = {
	// nonpure
	"VIOLIN+VIOLIN+VIOLA=TRIO+SONATA",
	"TWO*TWO=SQUARE",

	// special condition: no zero
	"A/BC+D/EF+G/HI=1",
};

BOOST_AUTO_TEST_CASE(solver_test)
{
	for (int i=0; i<(sizeof(puzzles)/sizeof(const char *)); ++i)
		BOOST_CHECK(testPuzzle(puzzles[i]) == 1);
}
<commit_msg>Added even more examples from ZEITmagazin<commit_after>#include "puzzle.hpp"
#include <iostream>
#define BOOST_TEST_MODULE SolverTest
#define BOOST_TEST_DYN_LINK
#include <boost/test/unit_test.hpp>

int testPuzzle(const char *puzzle)
{
	Puzzle::Puzz puzz(puzzle, 10);
	Puzzle::PuzzleSolver solver(puzz);
	std::cout << "Solving " << puzzle << std::endl;
	return solver.print_solutions(std::cout, true);
}

const char *puzzles[] = {
	// Donald E. Knuth, The Art of Computer Programming, Vol. 4A, pp. 324--347
	"SEND+A+TAD+MORE=MONEY",
	"COUPLE+COUPLE=QUARTET",
	"SATURN+URANUS+NEPTUNE+PLUTO=PLANETS",
	"EARTH+AIR+FIRE+WATER=NATURE",
	"HIP*HIP=HURRAY",
	"PI*R*R=AREA",
	"NORTH/SOUTH=EAST/WEST",
	"TWENTY=SEVEN+SEVEN+SIX",
	"TWELVE+NINE+TWO=ELEVEN+SEVEN+FIVE",

	// ZEITmagazin, 19/2014, S. 44
	"JANUAR+FEBRUAR=STAUSEE",
	"MAERZ+APRIL=MELKEN",
	"MAI+JUNI+JULI=ALPIN",

	// ZEITmagazin, 37/2014, S. 95
	// Replaced umlauts, because puzzle works only with ASCII.
	"GABEL+LOFFEL=IRRWEGE",
	"GABEL+GABEL=ABZUGE",
	"GABEL+MESSER=DOLLAR",

	// ZEITmagazin, 6/2015
	"ZAUN+TUERE=MERLIN",
	"ZAUN+TUERE=ELSTER"
};

const char *special[] = {
	// nonpure
	"VIOLIN+VIOLIN+VIOLA=TRIO+SONATA",
	"TWO*TWO=SQUARE",

	// special condition: no zero
	"A/BC+D/EF+G/HI=1",
};

BOOST_AUTO_TEST_CASE(solver_test)
{
	for (int i=0; i<(sizeof(puzzles)/sizeof(const char *)); ++i)
		BOOST_CHECK(testPuzzle(puzzles[i]) == 1);
}
<|endoftext|>


<commit_before>#include<iostream>
#include<cassert>
#include<thread>
#include<chrono>

#include "ics3/ics"

int main(int argc, char **argv) {
  {
    std::cout << std::endl << "ID test section" << std::endl;
    ics::ID id {0};
    assert(id == 0);
    assert(id.get() == 0);
    ics::ID id31 {31};
    assert(id31 == 31);
    assert(id31.get() == 31);
    try {
      ics::ID id32 {32};
      assert(false);
    } catch (std::invalid_argument& e) {
      std::cout << e.what() << std::endl;
    }
  }
  {
    std::cout << std::endl << "EepParam test section" << std::endl;
    auto speed = ics::EepParam::speed();
    assert(127 == speed.get());
    speed.set(100);
    assert(100 == speed.get());
    try {
      speed.set(200);
      std::cerr << "Never run this" << std::endl;
    } catch (std::invalid_argument& e) {
      std::cout << e.what() << std::endl;
    }
  }
  {
    std::cout << std::endl << "angle test section" << std::endl;
    auto degree = ics::Angle::newDegree();
    auto radian = ics::Angle::newRadian();
    assert(degree.getRaw() == radian.getRaw());
    degree.set(0);
    radian.set(0);
    assert(degree.getRaw() == radian.getRaw());
    degree.set(90);
    radian.set(M_PI / 2);
    assert(degree.getRaw() == radian.getRaw());
    degree.set(60);
    radian.set(M_PI / 3);
    assert(degree.getRaw() == radian.getRaw());
    try {
      degree.set(150);
      std::cerr << "Never run this" << std::endl;
    } catch (const std::invalid_argument& e) {
      std::cout << e.what() << std::endl;
    }
    try {
      radian.set(M_PI);
      std::cerr << "Never run this" << std::endl;
    } catch (const std::invalid_argument& e) {
      std::cout << e.what() << std::endl;
    }
  }
  {
    std::cout << std::endl << "angle factory test section" << std::endl;
    auto degree = ics::Angle::newDegree(90);
    auto radian = ics::Angle::newRadian(M_PI / 2);
    assert(degree.getRaw() == radian.getRaw());
  }
  {
    std::cout << std::endl << "parameter test section" << std::endl;
    auto current = ics::Parameter::current();
    assert(63 == current.get());
    current.set(30);
    assert(30 == current.get());
    try {
      current.set(70);
      std::cerr << "Never run this" << std::endl;
    } catch (const std::invalid_argument& e) {
      std::cout << e.what() << std::endl;
    }
  }
  {
    std::cout << std::endl << "ICS3 test section" << std::endl;
    auto id(2);
    auto degree = ics::Angle::newDegree();
    try {
      ics::ICS3 ics {"/dev/ttyUSB0"};
      assert(7500 == degree.getRaw());
      auto nowPos = ics.move(id, degree);
      std::cout << nowPos.get() << std::endl;
      std::this_thread::sleep_for(std::chrono::milliseconds(1000));
      degree.set(50);
      nowPos = ics.move(id, degree);
      std::cout << nowPos.get() << std::endl;
      std::this_thread::sleep_for(std::chrono::milliseconds(1000));
      degree.set(-50);
      nowPos = ics.move(id, degree);
      std::cout << nowPos.get() << std::endl;
      std::this_thread::sleep_for(std::chrono::milliseconds(1000));
      degree.set(0);
      nowPos = ics.move(id, degree);
      std::cout << nowPos.get() << std::endl;
      nowPos = ics.free(id);
      std::cout << nowPos.get() << std::endl;
    } catch (std::runtime_error& e) {
      std::cout << e.what() << std::endl;
    }
  }
  return 0;
}
<commit_msg>Update testcode for constexpr of id<commit_after>#include<iostream>
#include<cassert>
#include<thread>
#include<chrono>

#include "ics3/ics"

int main(int argc, char **argv) {
  {
    std::cout << std::endl << "ID test section" << std::endl;
    constexpr ics::ID id {0};
    assert(id == 0);
    assert(id.get() == 0);
    constexpr ics::ID id31 {31};
    assert(id31 == 31);
    assert(id31.get() == 31);
    try {
      ics::ID id32 {32};
      assert(false);
    } catch (std::invalid_argument& e) {
      std::cout << e.what() << std::endl;
    }
  }
  {
    std::cout << std::endl << "EepParam test section" << std::endl;
    auto speed = ics::EepParam::speed();
    assert(127 == speed.get());
    speed.set(100);
    assert(100 == speed.get());
    try {
      speed.set(200);
      std::cerr << "Never run this" << std::endl;
    } catch (std::invalid_argument& e) {
      std::cout << e.what() << std::endl;
    }
  }
  {
    std::cout << std::endl << "angle test section" << std::endl;
    auto degree = ics::Angle::newDegree();
    auto radian = ics::Angle::newRadian();
    assert(degree.getRaw() == radian.getRaw());
    degree.set(0);
    radian.set(0);
    assert(degree.getRaw() == radian.getRaw());
    degree.set(90);
    radian.set(M_PI / 2);
    assert(degree.getRaw() == radian.getRaw());
    degree.set(60);
    radian.set(M_PI / 3);
    assert(degree.getRaw() == radian.getRaw());
    try {
      degree.set(150);
      std::cerr << "Never run this" << std::endl;
    } catch (const std::invalid_argument& e) {
      std::cout << e.what() << std::endl;
    }
    try {
      radian.set(M_PI);
      std::cerr << "Never run this" << std::endl;
    } catch (const std::invalid_argument& e) {
      std::cout << e.what() << std::endl;
    }
  }
  {
    std::cout << std::endl << "angle factory test section" << std::endl;
    auto degree = ics::Angle::newDegree(90);
    auto radian = ics::Angle::newRadian(M_PI / 2);
    assert(degree.getRaw() == radian.getRaw());
  }
  {
    std::cout << std::endl << "parameter test section" << std::endl;
    auto current = ics::Parameter::current();
    assert(63 == current.get());
    current.set(30);
    assert(30 == current.get());
    try {
      current.set(70);
      std::cerr << "Never run this" << std::endl;
    } catch (const std::invalid_argument& e) {
      std::cout << e.what() << std::endl;
    }
  }
  {
    std::cout << std::endl << "ICS3 test section" << std::endl;
    auto id(2);
    auto degree = ics::Angle::newDegree();
    try {
      ics::ICS3 ics {"/dev/ttyUSB0"};
      assert(7500 == degree.getRaw());
      auto nowPos = ics.move(id, degree);
      std::cout << nowPos.get() << std::endl;
      std::this_thread::sleep_for(std::chrono::milliseconds(1000));
      degree.set(50);
      nowPos = ics.move(id, degree);
      std::cout << nowPos.get() << std::endl;
      std::this_thread::sleep_for(std::chrono::milliseconds(1000));
      degree.set(-50);
      nowPos = ics.move(id, degree);
      std::cout << nowPos.get() << std::endl;
      std::this_thread::sleep_for(std::chrono::milliseconds(1000));
      degree.set(0);
      nowPos = ics.move(id, degree);
      std::cout << nowPos.get() << std::endl;
      nowPos = ics.free(id);
      std::cout << nowPos.get() << std::endl;
    } catch (std::runtime_error& e) {
      std::cout << e.what() << std::endl;
    }
  }
  return 0;
}
<|endoftext|>


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

#include "txdb.h"

#include "core.h"
#include "uint256.h"

#include <stdint.h>

using namespace std;

void static BatchWriteCoins(CLevelDBBatch &batch, const uint256 &hash, const CCoins &coins) {
    if (coins.IsPruned())
        batch.Erase(make_pair('c', hash));
    else
        batch.Write(make_pair('c', hash), coins);
}

void static BatchWriteHashBestChain(CLevelDBBatch &batch, const uint256 &hash) {
    batch.Write('B', hash);
}

CCoinsViewDB::CCoinsViewDB(size_t nCacheSize, bool fMemory, bool fWipe) : db(GetDataDir() / "chainstate", nCacheSize, fMemory, fWipe) {
}

bool CCoinsViewDB::GetCoins(const uint256 &txid, CCoins &coins) {
    return db.Read(make_pair('c', txid), coins);
}

bool CCoinsViewDB::SetCoins(const uint256 &txid, const CCoins &coins) {
    CLevelDBBatch batch;
    BatchWriteCoins(batch, txid, coins);
    return db.WriteBatch(batch);
}

bool CCoinsViewDB::HaveCoins(const uint256 &txid) {
    return db.Exists(make_pair('c', txid));
}

uint256 CCoinsViewDB::GetBestBlock() {
    uint256 hashBestChain;
    if (!db.Read('B', hashBestChain))
        return uint256(0);
    return hashBestChain;
}

bool CCoinsViewDB::SetBestBlock(const uint256 &hashBlock) {
    CLevelDBBatch batch;
    BatchWriteHashBestChain(batch, hashBlock);
    return db.WriteBatch(batch);
}

bool CCoinsViewDB::BatchWrite(const std::map<uint256, CCoins> &mapCoins, const uint256 &hashBlock) {
    LogPrint("coindb", "Committing %u changed transactions to coin database...\n", (unsigned int)mapCoins.size());

    CLevelDBBatch batch;
    for (std::map<uint256, CCoins>::const_iterator it = mapCoins.begin(); it != mapCoins.end(); it++)
        BatchWriteCoins(batch, it->first, it->second);
    if (hashBlock != uint256(0))
        BatchWriteHashBestChain(batch, hashBlock);

    return db.WriteBatch(batch);
}

CBlockTreeDB::CBlockTreeDB(size_t nCacheSize, bool fMemory, bool fWipe) : CLevelDBWrapper(GetDataDir() / "blocks" / "index", nCacheSize, fMemory, fWipe) {
}

bool CBlockTreeDB::WriteBlockIndex(const CDiskBlockIndex& blockindex)
{
    return Write(make_pair('b', blockindex.GetBlockHash()), blockindex);
}

bool CBlockTreeDB::WriteBestInvalidWork(const CBigNum& bnBestInvalidWork)
{
    // Obsolete; only written for backward compatibility.
    return Write('I', bnBestInvalidWork);
}

bool CBlockTreeDB::WriteBlockFileInfo(int nFile, const CBlockFileInfo &info) {
    return Write(make_pair('f', nFile), info);
}

bool CBlockTreeDB::ReadBlockFileInfo(int nFile, CBlockFileInfo &info) {
    return Read(make_pair('f', nFile), info);
}

bool CBlockTreeDB::WriteLastBlockFile(int nFile) {
    return Write('l', nFile);
}

bool CBlockTreeDB::WriteReindexing(bool fReindexing) {
    if (fReindexing)
        return Write('R', '1');
    else
        return Erase('R');
}

bool CBlockTreeDB::ReadReindexing(bool &fReindexing) {
    fReindexing = Exists('R');
    return true;
}

bool CBlockTreeDB::ReadLastBlockFile(int &nFile) {
    return Read('l', nFile);
}

bool CCoinsViewDB::GetStats(CCoinsStats &stats) {
    leveldb::Iterator *pcursor = db.NewIterator();
    pcursor->SeekToFirst();

    CHashWriter ss(SER_GETHASH, PROTOCOL_VERSION);
    stats.hashBlock = GetBestBlock();
    ss << stats.hashBlock;
    int64_t nTotalAmount = 0;
    while (pcursor->Valid()) {
        boost::this_thread::interruption_point();
        try {
            leveldb::Slice slKey = pcursor->key();
            CDataStream ssKey(slKey.data(), slKey.data()+slKey.size(), SER_DISK, CLIENT_VERSION);
            char chType;
            ssKey >> chType;
            if (chType == 'c') {
                leveldb::Slice slValue = pcursor->value();
                CDataStream ssValue(slValue.data(), slValue.data()+slValue.size(), SER_DISK, CLIENT_VERSION);
                CCoins coins;
                ssValue >> coins;
                uint256 txhash;
                ssKey >> txhash;
                ss << txhash;
                ss << VARINT(coins.nVersion);
                ss << (coins.fCoinBase ? 'c' : 'n');
                ss << VARINT(coins.nHeight);
                stats.nTransactions++;
                for (unsigned int i=0; i<coins.vout.size(); i++) {
                    const CTxOut &out = coins.vout[i];
                    if (!out.IsNull()) {
                        stats.nTransactionOutputs++;
                        ss << VARINT(i+1);
                        ss << out;
                        nTotalAmount += out.nValue;
                    }
                }
                stats.nSerializedSize += 32 + slValue.size();
                ss << VARINT(0);
            }
            pcursor->Next();
        } catch (std::exception &e) {
            return error("%s() : deserialize error", __PRETTY_FUNCTION__);
        }
    }
    delete pcursor;
    stats.nHeight = mapBlockIndex.find(GetBestBlock())->second->nHeight;
    stats.hashSerialized = ss.GetHash();
    stats.nTotalAmount = nTotalAmount;
    return true;
}

bool CBlockTreeDB::ReadTxIndex(const uint256 &txid, CDiskTxPos &pos) {
    return Read(make_pair('t', txid), pos);
}

bool CBlockTreeDB::WriteTxIndex(const std::vector<std::pair<uint256, CDiskTxPos> >&vect) {
    CLevelDBBatch batch;
    for (std::vector<std::pair<uint256,CDiskTxPos> >::const_iterator it=vect.begin(); it!=vect.end(); it++)
        batch.Write(make_pair('t', it->first), it->second);
    return WriteBatch(batch);
}

bool CBlockTreeDB::WriteFlag(const std::string &name, bool fValue) {
    return Write(std::make_pair('F', name), fValue ? '1' : '0');
}

bool CBlockTreeDB::ReadFlag(const std::string &name, bool &fValue) {
    char ch;
    if (!Read(std::make_pair('F', name), ch))
        return false;
    fValue = ch == '1';
    return true;
}

bool CBlockTreeDB::LoadBlockIndexGuts()
{
    leveldb::Iterator *pcursor = NewIterator();

    CDataStream ssKeySet(SER_DISK, CLIENT_VERSION);
    ssKeySet << make_pair('b', uint256(0));
    pcursor->Seek(ssKeySet.str());

    // Load mapBlockIndex
    while (pcursor->Valid()) {
        boost::this_thread::interruption_point();
        try {
            leveldb::Slice slKey = pcursor->key();
            CDataStream ssKey(slKey.data(), slKey.data()+slKey.size(), SER_DISK, CLIENT_VERSION);
            char chType;
            ssKey >> chType;
            if (chType == 'b') {
                leveldb::Slice slValue = pcursor->value();
                CDataStream ssValue(slValue.data(), slValue.data()+slValue.size(), SER_DISK, CLIENT_VERSION);
                CDiskBlockIndex diskindex;
                ssValue >> diskindex;

                // Construct block index object
                CBlockIndex* pindexNew = InsertBlockIndex(diskindex.GetBlockHash());
                pindexNew->pprev          = InsertBlockIndex(diskindex.hashPrev);
                pindexNew->nHeight        = diskindex.nHeight;
                pindexNew->nFile          = diskindex.nFile;
                pindexNew->nDataPos       = diskindex.nDataPos;
                pindexNew->nUndoPos       = diskindex.nUndoPos;
                pindexNew->nVersion       = diskindex.nVersion;
                pindexNew->hashMerkleRoot = diskindex.hashMerkleRoot;
                pindexNew->nTime          = diskindex.nTime;
                pindexNew->nBits          = diskindex.nBits;
                pindexNew->nNonce         = diskindex.nNonce;
                pindexNew->nStatus        = diskindex.nStatus;
                pindexNew->nTx            = diskindex.nTx;

                if (!pindexNew->CheckIndex())
                    return error("LoadBlockIndex() : CheckIndex failed: %s", pindexNew->ToString().c_str());

                pcursor->Next();
            } else {
                break; // if shutdown requested or finished loading block index
            }
        } catch (std::exception &e) {
            return error("%s() : deserialize error", __PRETTY_FUNCTION__);
        }
    }
    delete pcursor;

    return true;
}
<commit_msg>extend std::exception logging in txdb.cpp<commit_after>// Copyright (c) 2009-2010 Satoshi Nakamoto
// Copyright (c) 2009-2013 The Bitcoin developers
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.

#include "txdb.h"

#include "core.h"
#include "uint256.h"

#include <stdint.h>

using namespace std;

void static BatchWriteCoins(CLevelDBBatch &batch, const uint256 &hash, const CCoins &coins) {
    if (coins.IsPruned())
        batch.Erase(make_pair('c', hash));
    else
        batch.Write(make_pair('c', hash), coins);
}

void static BatchWriteHashBestChain(CLevelDBBatch &batch, const uint256 &hash) {
    batch.Write('B', hash);
}

CCoinsViewDB::CCoinsViewDB(size_t nCacheSize, bool fMemory, bool fWipe) : db(GetDataDir() / "chainstate", nCacheSize, fMemory, fWipe) {
}

bool CCoinsViewDB::GetCoins(const uint256 &txid, CCoins &coins) {
    return db.Read(make_pair('c', txid), coins);
}

bool CCoinsViewDB::SetCoins(const uint256 &txid, const CCoins &coins) {
    CLevelDBBatch batch;
    BatchWriteCoins(batch, txid, coins);
    return db.WriteBatch(batch);
}

bool CCoinsViewDB::HaveCoins(const uint256 &txid) {
    return db.Exists(make_pair('c', txid));
}

uint256 CCoinsViewDB::GetBestBlock() {
    uint256 hashBestChain;
    if (!db.Read('B', hashBestChain))
        return uint256(0);
    return hashBestChain;
}

bool CCoinsViewDB::SetBestBlock(const uint256 &hashBlock) {
    CLevelDBBatch batch;
    BatchWriteHashBestChain(batch, hashBlock);
    return db.WriteBatch(batch);
}

bool CCoinsViewDB::BatchWrite(const std::map<uint256, CCoins> &mapCoins, const uint256 &hashBlock) {
    LogPrint("coindb", "Committing %u changed transactions to coin database...\n", (unsigned int)mapCoins.size());

    CLevelDBBatch batch;
    for (std::map<uint256, CCoins>::const_iterator it = mapCoins.begin(); it != mapCoins.end(); it++)
        BatchWriteCoins(batch, it->first, it->second);
    if (hashBlock != uint256(0))
        BatchWriteHashBestChain(batch, hashBlock);

    return db.WriteBatch(batch);
}

CBlockTreeDB::CBlockTreeDB(size_t nCacheSize, bool fMemory, bool fWipe) : CLevelDBWrapper(GetDataDir() / "blocks" / "index", nCacheSize, fMemory, fWipe) {
}

bool CBlockTreeDB::WriteBlockIndex(const CDiskBlockIndex& blockindex)
{
    return Write(make_pair('b', blockindex.GetBlockHash()), blockindex);
}

bool CBlockTreeDB::WriteBestInvalidWork(const CBigNum& bnBestInvalidWork)
{
    // Obsolete; only written for backward compatibility.
    return Write('I', bnBestInvalidWork);
}

bool CBlockTreeDB::WriteBlockFileInfo(int nFile, const CBlockFileInfo &info) {
    return Write(make_pair('f', nFile), info);
}

bool CBlockTreeDB::ReadBlockFileInfo(int nFile, CBlockFileInfo &info) {
    return Read(make_pair('f', nFile), info);
}

bool CBlockTreeDB::WriteLastBlockFile(int nFile) {
    return Write('l', nFile);
}

bool CBlockTreeDB::WriteReindexing(bool fReindexing) {
    if (fReindexing)
        return Write('R', '1');
    else
        return Erase('R');
}

bool CBlockTreeDB::ReadReindexing(bool &fReindexing) {
    fReindexing = Exists('R');
    return true;
}

bool CBlockTreeDB::ReadLastBlockFile(int &nFile) {
    return Read('l', nFile);
}

bool CCoinsViewDB::GetStats(CCoinsStats &stats) {
    leveldb::Iterator *pcursor = db.NewIterator();
    pcursor->SeekToFirst();

    CHashWriter ss(SER_GETHASH, PROTOCOL_VERSION);
    stats.hashBlock = GetBestBlock();
    ss << stats.hashBlock;
    int64_t nTotalAmount = 0;
    while (pcursor->Valid()) {
        boost::this_thread::interruption_point();
        try {
            leveldb::Slice slKey = pcursor->key();
            CDataStream ssKey(slKey.data(), slKey.data()+slKey.size(), SER_DISK, CLIENT_VERSION);
            char chType;
            ssKey >> chType;
            if (chType == 'c') {
                leveldb::Slice slValue = pcursor->value();
                CDataStream ssValue(slValue.data(), slValue.data()+slValue.size(), SER_DISK, CLIENT_VERSION);
                CCoins coins;
                ssValue >> coins;
                uint256 txhash;
                ssKey >> txhash;
                ss << txhash;
                ss << VARINT(coins.nVersion);
                ss << (coins.fCoinBase ? 'c' : 'n');
                ss << VARINT(coins.nHeight);
                stats.nTransactions++;
                for (unsigned int i=0; i<coins.vout.size(); i++) {
                    const CTxOut &out = coins.vout[i];
                    if (!out.IsNull()) {
                        stats.nTransactionOutputs++;
                        ss << VARINT(i+1);
                        ss << out;
                        nTotalAmount += out.nValue;
                    }
                }
                stats.nSerializedSize += 32 + slValue.size();
                ss << VARINT(0);
            }
            pcursor->Next();
        } catch (std::exception &e) {
            return error("%s : Deserialize or I/O error - %s", __PRETTY_FUNCTION__, e.what());
        }
    }
    delete pcursor;
    stats.nHeight = mapBlockIndex.find(GetBestBlock())->second->nHeight;
    stats.hashSerialized = ss.GetHash();
    stats.nTotalAmount = nTotalAmount;
    return true;
}

bool CBlockTreeDB::ReadTxIndex(const uint256 &txid, CDiskTxPos &pos) {
    return Read(make_pair('t', txid), pos);
}

bool CBlockTreeDB::WriteTxIndex(const std::vector<std::pair<uint256, CDiskTxPos> >&vect) {
    CLevelDBBatch batch;
    for (std::vector<std::pair<uint256,CDiskTxPos> >::const_iterator it=vect.begin(); it!=vect.end(); it++)
        batch.Write(make_pair('t', it->first), it->second);
    return WriteBatch(batch);
}

bool CBlockTreeDB::WriteFlag(const std::string &name, bool fValue) {
    return Write(std::make_pair('F', name), fValue ? '1' : '0');
}

bool CBlockTreeDB::ReadFlag(const std::string &name, bool &fValue) {
    char ch;
    if (!Read(std::make_pair('F', name), ch))
        return false;
    fValue = ch == '1';
    return true;
}

bool CBlockTreeDB::LoadBlockIndexGuts()
{
    leveldb::Iterator *pcursor = NewIterator();

    CDataStream ssKeySet(SER_DISK, CLIENT_VERSION);
    ssKeySet << make_pair('b', uint256(0));
    pcursor->Seek(ssKeySet.str());

    // Load mapBlockIndex
    while (pcursor->Valid()) {
        boost::this_thread::interruption_point();
        try {
            leveldb::Slice slKey = pcursor->key();
            CDataStream ssKey(slKey.data(), slKey.data()+slKey.size(), SER_DISK, CLIENT_VERSION);
            char chType;
            ssKey >> chType;
            if (chType == 'b') {
                leveldb::Slice slValue = pcursor->value();
                CDataStream ssValue(slValue.data(), slValue.data()+slValue.size(), SER_DISK, CLIENT_VERSION);
                CDiskBlockIndex diskindex;
                ssValue >> diskindex;

                // Construct block index object
                CBlockIndex* pindexNew = InsertBlockIndex(diskindex.GetBlockHash());
                pindexNew->pprev          = InsertBlockIndex(diskindex.hashPrev);
                pindexNew->nHeight        = diskindex.nHeight;
                pindexNew->nFile          = diskindex.nFile;
                pindexNew->nDataPos       = diskindex.nDataPos;
                pindexNew->nUndoPos       = diskindex.nUndoPos;
                pindexNew->nVersion       = diskindex.nVersion;
                pindexNew->hashMerkleRoot = diskindex.hashMerkleRoot;
                pindexNew->nTime          = diskindex.nTime;
                pindexNew->nBits          = diskindex.nBits;
                pindexNew->nNonce         = diskindex.nNonce;
                pindexNew->nStatus        = diskindex.nStatus;
                pindexNew->nTx            = diskindex.nTx;

                if (!pindexNew->CheckIndex())
                    return error("LoadBlockIndex() : CheckIndex failed: %s", pindexNew->ToString().c_str());

                pcursor->Next();
            } else {
                break; // if shutdown requested or finished loading block index
            }
        } catch (std::exception &e) {
            return error("%s : Deserialize or I/O error - %s", __PRETTY_FUNCTION__, e.what());
        }
    }
    delete pcursor;

    return true;
}
<|endoftext|>


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

//--------
// #include's
//--------
#include <config4cpp/StringBuffer.h>
#include "util.h"

namespace CONFIG4CPP_NAMESPACE {

void
splitScopedNameIntoVector(const char * str, StringVector & vec)
{
	int				i;
	int				len;
	char *			startOfStr;
	StringBuffer	tmpStr; // Mutable copy of str

	vec.empty();
	tmpStr = str;
	len = tmpStr.length();
	startOfStr = &tmpStr[0];
	for (i = 0; i < len; i++) {
		if (tmpStr[i] == '.') {
			tmpStr[i] = 0;
			vec.add(startOfStr);
			startOfStr = &tmpStr[i+1];
		}
	}
	vec.add(startOfStr);
}

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

//--------
// #include's
//--------
#include <config4cpp/StringBuffer.h>
#include "util.h"

namespace CONFIG4CPP_NAMESPACE {

void
splitScopedNameIntoVector(const char * str, StringVector & vec)
{
	StringBuffer	tmpStr; // Mutable copy of str

	vec.empty();
	tmpStr = str;
	int len = tmpStr.length();
	char* startOfStr = &tmpStr[0];
	for (int i = 0; i < len; i++) {
		if (tmpStr[i] == '.') {
			tmpStr[i] = 0;
			vec.add(startOfStr);
			startOfStr = &tmpStr[i+1];
		}
	}
	vec.add(startOfStr);
}

} // namespace CONFIG4CPP_NAMESPACE
<|endoftext|>


<commit_before>#include <Rcpp.h>

#if defined(_WIN32)
// See: http://stackoverflow.com/questions/11588765/using-rcpp-with-windows-specific-includes
#undef Realloc
#undef Free
#include <Windows.h>

#elif defined(__unix__) || defined(__unix) || defined(unix) || (defined(__APPLE__) && defined(__MACH__))
#include <unistd.h>
#include <sys/types.h>
#include <sys/param.h>
#if defined(BSD)
#include <sys/sysctl.h>
#endif

#endif

#include <sys/time.h>
#include <stdint.h>
#include <stdio.h>
#include <time.h>
#include <errno.h>
#include <fcntl.h>

extern "C" {
    #include "scrypt_platform.h"
    #include "crypto/crypto_scrypt.h"
}

#include "util.hpp"

#ifdef HAVE_CLOCK_GETTIME

static clockid_t clocktouse;

static int getclockres(double *resd)
{
    struct timespec res;

    /*
     * Try clocks in order of preference until we find one which works.
     * (We assume that if clock_getres works, clock_gettime will, too.)
     * The use of if/else/if/else/if/else rather than if/elif/elif/else
     * is ugly but legal, and allows us to #ifdef things appropriately.
     */
#ifdef CLOCK_VIRTUAL
    if (clock_getres(CLOCK_VIRTUAL, &res) == 0)
        clocktouse = CLOCK_VIRTUAL;
    else
#endif
#ifdef CLOCK_MONOTONIC
    if (clock_getres(CLOCK_MONOTONIC, &res) == 0)
        clocktouse = CLOCK_MONOTONIC;
    else
#endif
    if (clock_getres(CLOCK_REALTIME, &res) == 0)
        clocktouse = CLOCK_REALTIME;
    else
        return (-1);

    /* Convert clock resolution to a double. */
    *resd = res.tv_sec + res.tv_nsec * 0.000000001;

    return (0);
}

static int getclocktime(struct timespec *ts)
{

#ifdef DEBUG
    REprintf("Using clock_gettime()\n");
#endif

    if (clock_gettime(clocktouse, ts))
        return (-1);

    return (0);
}

#else

static int getclockres(double *resd)
{

#ifdef DEBUG
    REprintf("Using gettimeofday()\n");
#endif

    *resd = 1.0 / CLOCKS_PER_SEC;

    return (0);
}

static int getclocktime(struct timespec *ts)
{
    struct timeval tv;

    if (gettimeofday(&tv, NULL))
        return (-1);
    ts->tv_sec = tv.tv_sec;
    ts->tv_nsec = tv.tv_usec * 1000;

    return (0);
}

#endif

static int getclockdiff(struct timespec * st, double * diffd)
{
    struct timespec en;

    if (getclocktime(&en))
        return (1);
    *diffd = (en.tv_nsec - st->tv_nsec) * 0.000000001 +
        (en.tv_sec - st->tv_sec);

    return (0);
}

/*
 * Get CPU performance
 *
 * This function is derived from Colin Percival's scrypt reference code
 */
int getcpuperf(double *opps)
{
    struct timespec st;
    double resd, diffd;
    uint64_t i = 0;

    /* Get the clock resolution. */
    if (getclockres(&resd))
        return (2);

#ifdef DEBUG
    REprintf("Clock resolution is %f\n", resd);
#endif

    /* Loop until the clock ticks. */
    if (getclocktime(&st))
        return (2);
    do {
        /* Do an scrypt. */
        if (crypto_scrypt(NULL, 0, NULL, 0, 16, 1, 1, NULL, 0))
            return (3);

        /* Has the clock ticked? */
        if (getclockdiff(&st, &diffd))
            return (2);
        if (diffd > 0)
            break;
    } while (1);

    /* Could how many scryps we can do before the next tick. */
    if (getclocktime(&st))
        return (2);
    do {
        /* Do an scrypt. */
        if (crypto_scrypt(NULL, 0, NULL, 0, 128, 1, 1, NULL, 0))
            return (3);

        /* We invoked the salsa20/8 core 512 times. */
        i += 512;

        /* Check if we have looped for long enough. */
        if (getclockdiff(&st, &diffd))
            return (2);
        if (diffd > resd)
            break;
    } while (1);

#ifdef DEBUG
    REprintf("%ju salsa20/8 cores performed in %f seconds\n",
        (uintmax_t)i, diffd);
#endif

    /* We can do approximately i salsa20/8 cores per diffd seconds. */
    *opps = i / diffd;
    return (0);
}

/*
 * Get available memory
 *
 * This function is derived from:
 * http://nadeausoftware.com/articles/2012/09/c_c_tip_how_get_physical_memory_size_system
 */
int getmemlimit(size_t *memlimit) {

#if defined(_WIN32) && (defined(__CYGWIN__) || defined(__CYGWIN32__) || defined(__MINGW__) || defined(__MINGW32__) )
    /* Cygwin under Windows. ------------------------------------ */
    /* New 64-bit MEMORYSTATUSEX isn't available.  Use old 32.bit */
    MEMORYSTATUS status;
    status.dwLength = sizeof(status);
    GlobalMemoryStatus( &status );
    *memlimit = (size_t)status.dwTotalPhys;
    return 0;

#elif defined(_WIN32)
    /* Windows. ------------------------------------------------- */
    /* Use new 64-bit MEMORYSTATUSEX, not old 32-bit MEMORYSTATUS */
    MEMORYSTATUSEX status;
    status.dwLength = sizeof(status);
    GlobalMemoryStatusEx( &status );
    *memlimit = (size_t)status.ullTotalPhys;
    return 0;

#elif defined(__unix__) || defined(__unix) || defined(unix) || (defined(__APPLE__) && defined(__MACH__))
    /* UNIX variants. ------------------------------------------- */

#if defined(CTL_HW) && (defined(HW_MEMSIZE) || defined(HW_PHYSMEM64))
    int mib[2];
    mib[0] = CTL_HW;
#if defined(HW_MEMSIZE)
    mib[1] = HW_MEMSIZE;    // OSX
#elif defined(HW_PHYSMEM64)
    mib[1] = HW_PHYSMEM64;  // NetBSD, OpenBSD
#endif
    int64_t size = 0;       // 64-bit
    size_t len = sizeof( size );
    if ( sysctl( mib, 2, &size, &len, NULL, 0 ) == 0 ) {
        *memlimit = (size_t)size;
        return 0;
    }
    return -1; // Failure

#elif defined(_SC_AIX_REALMEM)
    /* AIX. ----------------------------------------------------- */
    *memlimit = (size_t)sysconf( _SC_AIX_REALMEM ) * (size_t)1024L;
    return 0;

#elif defined(_SC_PHYS_PAGES) && defined(_SC_PAGESIZE)
    /* FreeBSD, Linux, OpenBSD, and Solaris. -------------------- */
    *memlimit = (size_t)sysconf( _SC_PHYS_PAGES ) * (size_t)sysconf( _SC_PAGESIZE );
    return 0;

#elif defined(_SC_PHYS_PAGES) && defined(_SC_PAGE_SIZE)
    /* Legacy. -------------------------------------------------- */
    *memlimit = (size_t)sysconf( _SC_PHYS_PAGES ) * (size_t)sysconf( _SC_PAGE_SIZE );
    return 0;

#elif defined(CTL_HW) && (defined(HW_PHYSMEM) || defined(HW_REALMEM))
    /* DragonFly BSD, FreeBSD, NetBSD, OpenBSD, and OSX. -------- */
    int mib[2];
    mib[0] = CTL_HW;
#if defined(HW_REALMEM)
    mib[1] = HW_REALMEM;        // FreeBSD
#elif defined(HW_PYSMEM)
    mib[1] = HW_PHYSMEM;        // Others
#endif
    unsigned int size = 0;      // 32-bit
    size_t len = sizeof( size );
    if ( sysctl( mib, 2, &size, &len, NULL, 0 ) == 0 ) {
        *memlimit = (size_t)size;
        return 0;
    }
    return -1; // Failure
#endif

#else
    return -2; // Unknown OS
#endif

}

/*
 * Obtains salt for password hash.
 * This function is derived from Colin Percival's scrypt reference code
 */
int getsalt(uint8_t salt[32]) {

    uint8_t *buf = salt;
    size_t buflen = 32;

#if defined(_WIN32)

    HCRYPTPROV hCryptCtx;

    if (CryptAcquireContext(&hCryptCtx, NULL, NULL, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT | CRYPT_SILENT)) {
        if (!CryptGenRandom(hCryptCtx, buflen, buf))
            goto err;
        CryptReleaseContext(hCryptCtx, 0);
    } else {
        goto err;
    }

    /* Success! */
    return (0);

#else

    int fd;
    ssize_t lenread;

    /* Open /dev/urandom */
    if ((fd = open("/dev/urandom", O_RDONLY)) == -1)
        goto err;

    /* Read bytes until we have filled the buffer */
    while (buflen > 0) {
        if ((lenread = read(fd, buf, buflen)) == -1)
            goto close;

        /* The random device should never EOF */
        if (lenread == 0)
            goto close;

        /* We're partly done */
        buf += lenread;
        buflen -= lenread;
    }

    /* Close the device */
    while (close(fd) == -1) {
        if (errno != EINTR)
            goto err;
    }

    /* Success! */
    return (0);

close:
    close(fd);

#endif

err:
    /* Failure! */
    return (4);
}

<commit_msg>Prevent UBSAN by explicitly setting the salt<commit_after>#include <Rcpp.h>

#if defined(_WIN32)
// See: http://stackoverflow.com/questions/11588765/using-rcpp-with-windows-specific-includes
#undef Realloc
#undef Free
#include <Windows.h>

#elif defined(__unix__) || defined(__unix) || defined(unix) || (defined(__APPLE__) && defined(__MACH__))
#include <unistd.h>
#include <sys/types.h>
#include <sys/param.h>
#if defined(BSD)
#include <sys/sysctl.h>
#endif

#endif

#include <sys/time.h>
#include <stdint.h>
#include <stdio.h>
#include <time.h>
#include <errno.h>
#include <fcntl.h>

extern "C" {
    #include "scrypt_platform.h"
    #include "crypto/crypto_scrypt.h"
}

#include "util.hpp"

#ifdef HAVE_CLOCK_GETTIME

static clockid_t clocktouse;

static int getclockres(double *resd)
{
    struct timespec res;

    /*
     * Try clocks in order of preference until we find one which works.
     * (We assume that if clock_getres works, clock_gettime will, too.)
     * The use of if/else/if/else/if/else rather than if/elif/elif/else
     * is ugly but legal, and allows us to #ifdef things appropriately.
     */
#ifdef CLOCK_VIRTUAL
    if (clock_getres(CLOCK_VIRTUAL, &res) == 0)
        clocktouse = CLOCK_VIRTUAL;
    else
#endif
#ifdef CLOCK_MONOTONIC
    if (clock_getres(CLOCK_MONOTONIC, &res) == 0)
        clocktouse = CLOCK_MONOTONIC;
    else
#endif
    if (clock_getres(CLOCK_REALTIME, &res) == 0)
        clocktouse = CLOCK_REALTIME;
    else
        return (-1);

    /* Convert clock resolution to a double. */
    *resd = res.tv_sec + res.tv_nsec * 0.000000001;

    return (0);
}

static int getclocktime(struct timespec *ts)
{

#ifdef DEBUG
    REprintf("Using clock_gettime()\n");
#endif

    if (clock_gettime(clocktouse, ts))
        return (-1);

    return (0);
}

#else

static int getclockres(double *resd)
{

#ifdef DEBUG
    REprintf("Using gettimeofday()\n");
#endif

    *resd = 1.0 / CLOCKS_PER_SEC;

    return (0);
}

static int getclocktime(struct timespec *ts)
{
    struct timeval tv;

    if (gettimeofday(&tv, NULL))
        return (-1);
    ts->tv_sec = tv.tv_sec;
    ts->tv_nsec = tv.tv_usec * 1000;

    return (0);
}

#endif

static int getclockdiff(struct timespec * st, double * diffd)
{
    struct timespec en;

    if (getclocktime(&en))
        return (1);
    *diffd = (en.tv_nsec - st->tv_nsec) * 0.000000001 +
        (en.tv_sec - st->tv_sec);

    return (0);
}

/*
 * Get CPU performance
 *
 * This function is derived from Colin Percival's scrypt reference code
 */
int getcpuperf(double *opps)
{
    struct timespec st;
    double resd, diffd;
    uint64_t i = 0;
    uint8_t salt[32] = {0};

    /* Get the clock resolution. */
    if (getclockres(&resd))
        return (2);

#ifdef DEBUG
    REprintf("Clock resolution is %f\n", resd);
#endif

    /* Loop until the clock ticks. */
    if (getclocktime(&st))
        return (2);
    do {
        /* Do an scrypt. */
        if (crypto_scrypt(NULL, 0, salt, 0, 16, 1, 1, NULL, 0))
            return (3);

        /* Has the clock ticked? */
        if (getclockdiff(&st, &diffd))
            return (2);
        if (diffd > 0)
            break;
    } while (1);

    /* Could how many scryps we can do before the next tick. */
    if (getclocktime(&st))
        return (2);
    do {
        /* Do an scrypt. */
        if (crypto_scrypt(NULL, 0, salt, 0, 128, 1, 1, NULL, 0))
            return (3);

        /* We invoked the salsa20/8 core 512 times. */
        i += 512;

        /* Check if we have looped for long enough. */
        if (getclockdiff(&st, &diffd))
            return (2);
        if (diffd > resd)
            break;
    } while (1);

#ifdef DEBUG
    REprintf("%ju salsa20/8 cores performed in %f seconds\n",
        (uintmax_t)i, diffd);
#endif

    /* We can do approximately i salsa20/8 cores per diffd seconds. */
    *opps = i / diffd;
    return (0);
}

/*
 * Get available memory
 *
 * This function is derived from:
 * http://nadeausoftware.com/articles/2012/09/c_c_tip_how_get_physical_memory_size_system
 */
int getmemlimit(size_t *memlimit) {

#if defined(_WIN32) && (defined(__CYGWIN__) || defined(__CYGWIN32__) || defined(__MINGW__) || defined(__MINGW32__) )
    /* Cygwin under Windows. ------------------------------------ */
    /* New 64-bit MEMORYSTATUSEX isn't available.  Use old 32.bit */
    MEMORYSTATUS status;
    status.dwLength = sizeof(status);
    GlobalMemoryStatus( &status );
    *memlimit = (size_t)status.dwTotalPhys;
    return 0;

#elif defined(_WIN32)
    /* Windows. ------------------------------------------------- */
    /* Use new 64-bit MEMORYSTATUSEX, not old 32-bit MEMORYSTATUS */
    MEMORYSTATUSEX status;
    status.dwLength = sizeof(status);
    GlobalMemoryStatusEx( &status );
    *memlimit = (size_t)status.ullTotalPhys;
    return 0;

#elif defined(__unix__) || defined(__unix) || defined(unix) || (defined(__APPLE__) && defined(__MACH__))
    /* UNIX variants. ------------------------------------------- */

#if defined(CTL_HW) && (defined(HW_MEMSIZE) || defined(HW_PHYSMEM64))
    int mib[2];
    mib[0] = CTL_HW;
#if defined(HW_MEMSIZE)
    mib[1] = HW_MEMSIZE;    // OSX
#elif defined(HW_PHYSMEM64)
    mib[1] = HW_PHYSMEM64;  // NetBSD, OpenBSD
#endif
    int64_t size = 0;       // 64-bit
    size_t len = sizeof( size );
    if ( sysctl( mib, 2, &size, &len, NULL, 0 ) == 0 ) {
        *memlimit = (size_t)size;
        return 0;
    }
    return -1; // Failure

#elif defined(_SC_AIX_REALMEM)
    /* AIX. ----------------------------------------------------- */
    *memlimit = (size_t)sysconf( _SC_AIX_REALMEM ) * (size_t)1024L;
    return 0;

#elif defined(_SC_PHYS_PAGES) && defined(_SC_PAGESIZE)
    /* FreeBSD, Linux, OpenBSD, and Solaris. -------------------- */
    *memlimit = (size_t)sysconf( _SC_PHYS_PAGES ) * (size_t)sysconf( _SC_PAGESIZE );
    return 0;

#elif defined(_SC_PHYS_PAGES) && defined(_SC_PAGE_SIZE)
    /* Legacy. -------------------------------------------------- */
    *memlimit = (size_t)sysconf( _SC_PHYS_PAGES ) * (size_t)sysconf( _SC_PAGE_SIZE );
    return 0;

#elif defined(CTL_HW) && (defined(HW_PHYSMEM) || defined(HW_REALMEM))
    /* DragonFly BSD, FreeBSD, NetBSD, OpenBSD, and OSX. -------- */
    int mib[2];
    mib[0] = CTL_HW;
#if defined(HW_REALMEM)
    mib[1] = HW_REALMEM;        // FreeBSD
#elif defined(HW_PYSMEM)
    mib[1] = HW_PHYSMEM;        // Others
#endif
    unsigned int size = 0;      // 32-bit
    size_t len = sizeof( size );
    if ( sysctl( mib, 2, &size, &len, NULL, 0 ) == 0 ) {
        *memlimit = (size_t)size;
        return 0;
    }
    return -1; // Failure
#endif

#else
    return -2; // Unknown OS
#endif

}

/*
 * Obtains salt for password hash.
 * This function is derived from Colin Percival's scrypt reference code
 */
int getsalt(uint8_t salt[32]) {

    uint8_t *buf = salt;
    size_t buflen = 32;

#if defined(_WIN32)

    HCRYPTPROV hCryptCtx;

    if (CryptAcquireContext(&hCryptCtx, NULL, NULL, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT | CRYPT_SILENT)) {
        if (!CryptGenRandom(hCryptCtx, buflen, buf))
            goto err;
        CryptReleaseContext(hCryptCtx, 0);
    } else {
        goto err;
    }

    /* Success! */
    return (0);

#else

    int fd;
    ssize_t lenread;

    /* Open /dev/urandom */
    if ((fd = open("/dev/urandom", O_RDONLY)) == -1)
        goto err;

    /* Read bytes until we have filled the buffer */
    while (buflen > 0) {
        if ((lenread = read(fd, buf, buflen)) == -1)
            goto close;

        /* The random device should never EOF */
        if (lenread == 0)
            goto close;

        /* We're partly done */
        buf += lenread;
        buflen -= lenread;
    }

    /* Close the device */
    while (close(fd) == -1) {
        if (errno != EINTR)
            goto err;
    }

    /* Success! */
    return (0);

close:
    close(fd);

#endif

err:
    /* Failure! */
    return (4);
}

<|endoftext|>