<commit_before>#include "btree.h"

#include <map>
#include <vector>
using namespace std;

// TODO: For ease to debug, start with a simple 2-3 tree
const int max_size = 3;
const int min_size = 2;

class btree_node;

struct insert_result
{
    bool succeed;
    bool split;
};

struct split_result
{
    btree_node* sibling;
    int key;
};

class btree_node
{
public:
    virtual ~btree_node();
    virtual insert_result insert(int key, int value) = 0;
    virtual split_result split() = 0;
};

class btree_internal_node : public btree_node
{
public:
    btree_internal_node(int key, btree_node* left, btree_node* right);
    ~btree_internal_node();
    virtual insert_result insert(int key, int value);
    virtual split_result split();
private:
    vector<int> keys;
    vector<btree_node*> children;
};

class btree_leaf_node : public btree_node
{
public:
    virtual ~btree_leaf_node();
    virtual insert_result insert(int key, int value);
    virtual split_result split();
private:
    // TODO: Ideally, this should work on the memory page directly
    map<int, int> entries;
};

class btree_impl
{
public:
    bool insert(int key, int value);
private:
    btree_node* m_root;
};

btree::btree()
{
    this->m_impl = new btree_impl();
}

btree::~btree()
{
    delete this->m_impl;
}

bool btree::insert(int key, int value)
{
    return this->m_impl->insert(key, value);
}

btree_node::~btree_node()
{
}

btree_leaf_node::~btree_leaf_node()
{
}

insert_result btree_leaf_node::insert(int key, int value)
{
    insert_result result;

    auto probe = this->entries.find(key);
    if (probe == this->entries.end())
    {
        result.succeed = true;
        this->entries.insert(pair<int, int>(key, value));
        result.split = (entries.size() == max_size + 1);
        return result;
    }
    else
    {
        result.succeed = false;
        return result;
    }
}

split_result btree_leaf_node::split()
{
    split_result result;
    btree_leaf_node* sibling = new btree_leaf_node();
    int i = 0;
    for (auto iter = this->entries.begin(); i < min_size; iter++, i++)
    {
        sibling->entries.insert(*iter);
    }
    for (auto iter = sibling->entries.begin(); iter != sibling->entries.end(); iter++)
    {
        this->entries.erase(iter->first);
    }

    result.sibling = sibling;
    result.key = this->entries.begin()->first;
    return result;
}

btree_internal_node::btree_internal_node(int key, btree_node* left, btree_node* right)
{
    this->keys.push_back(key);
    this->children.push_back(left);
    this->children.push_back(right);
}

btree_internal_node::~btree_internal_node()
{

}

insert_result btree_internal_node::insert(int key, int value)
{
    insert_result result;
    for (int upper_index = 0; upper_index <= this->keys.size(); upper_index++)
    {
        int lower_index = upper_index - 1;
        bool lower_is_good = (lower_index == -1) || (this->keys[lower_index] <= key);
        bool upper_is_good = (upper_index == this->keys.size()) || (key < this->keys[upper_index]);
        if (lower_is_good && upper_is_good)
        {
            insert_result children_insert_result = this->children[upper_index]->insert(key, value);
            if (children_insert_result.succeed)
            {
                result.succeed = true;
                if (children_insert_result.split)
                {
                    split_result children_split_result = this->children[upper_index]->split();
                    this->children.insert(this->children.begin() + upper_index, children_split_result.sibling);
                    this->keys.insert(this->keys.begin() + upper_index, children_split_result.key);
                    result.split = this->keys.size() == max_size;
                }
                else
                {
                    result.split = false;
                }
            }
            else
            {
                result.succeed = false;
            }

            break;
        }
    }

    return result;
}

split_result btree_internal_node::split()
{
    // TODO: Implementation
    split_result result;
    result.key = 0;
    return result;
}

bool btree_impl::insert(int key, int value)
{
    if (this->m_root == nullptr)
    {
        this->m_root = new btree_leaf_node();
    }

    insert_result result = this->m_root->insert(key, value);

    if (result.succeed)
    {
        if (result.split)
        {
            split_result split_result = this->m_root->split();
            this->m_root = new btree_internal_node(split_result.key, split_result.sibling, this->m_root);

            return true;
        }
        else
        {
            return true;
        }
    }
    else
    {
        return false;
    }
}<commit_msg>btree insertion with splitting completed<commit_after>#include "btree.h"

#include <map>
#include <vector>
using namespace std;

// TODO: For ease to debug, start with a simple 2-3 tree
const int max_size = 3;
const int min_size = 2;

class btree_node;

struct insert_result
{
    bool succeed;
    bool split;
};

struct split_result
{
    btree_node* sibling;
    int key;
};

class btree_node
{
public:
    virtual ~btree_node();
    virtual insert_result insert(int key, int value) = 0;
    virtual split_result split() = 0;
};

class btree_internal_node : public btree_node
{
public:
    btree_internal_node(int key, btree_node* left, btree_node* right);
    ~btree_internal_node();
    virtual insert_result insert(int key, int value);
    virtual split_result split();
private:
    btree_internal_node();
    vector<int> keys;
    vector<btree_node*> children;
};

class btree_leaf_node : public btree_node
{
public:
    virtual ~btree_leaf_node();
    virtual insert_result insert(int key, int value);
    virtual split_result split();
private:
    vector<int> keys;
    vector<int> values;
};

class btree_impl
{
public:
    bool insert(int key, int value);
private:
    btree_node* m_root;
};

btree::btree()
{
    this->m_impl = new btree_impl();
}

btree::~btree()
{
    delete this->m_impl;
}

bool btree::insert(int key, int value)
{
    return this->m_impl->insert(key, value);
}

btree_node::~btree_node()
{
}

btree_leaf_node::~btree_leaf_node()
{
}

insert_result btree_leaf_node::insert(int key, int value)
{
    insert_result result;
    for (size_t upper_index = 0; upper_index <= this->keys.size(); upper_index++)
    {
        int lower_index = upper_index - 1;
        bool lower_is_good = (lower_index == -1) || (this->keys[lower_index] <= key);
        bool upper_is_good = (upper_index == this->keys.size()) || (key < this->keys[upper_index]);
        if (lower_is_good && upper_is_good)
        {
            if (lower_index != -1 && key == this->keys[lower_index])
            {
                result.succeed = false;
            }
            else
            {
                this->keys.insert(this->keys.begin() + upper_index, key);
                this->values.insert(this->values.begin() + upper_index, value);
                result.succeed = true;
                result.split = (this->keys.size() == (max_size + 1));
            }

            break;
        }
    }

    return result;
}

split_result btree_leaf_node::split()
{
    split_result result;
    btree_leaf_node* sibling = new btree_leaf_node();
    for (size_t i = min_size; i < this->keys.size(); i++)
    {
        sibling->keys.push_back(this->keys[i]);
        sibling->values.push_back(this->values[i]);
    }
    this->keys.resize(min_size);
    this->values.resize(min_size);

    result.sibling = sibling;
    result.key = sibling->keys[0];
    return result;
}

btree_internal_node::btree_internal_node(int key, btree_node* left, btree_node* right)
{
    this->keys.push_back(key);
    this->children.push_back(left);
    this->children.push_back(right);
}

btree_internal_node::btree_internal_node()
{

}

btree_internal_node::~btree_internal_node()
{

}

insert_result btree_internal_node::insert(int key, int value)
{
    insert_result result;
    for (size_t upper_index = 0; upper_index <= this->keys.size(); upper_index++)
    {
        int lower_index = upper_index - 1;
        bool lower_is_good = (lower_index == -1) || (this->keys[lower_index] <= key);
        bool upper_is_good = (upper_index == this->keys.size()) || (key < this->keys[upper_index]);
        if (lower_is_good && upper_is_good)
        {
            insert_result children_insert_result = this->children[upper_index]->insert(key, value);
            if (children_insert_result.succeed)
            {
                result.succeed = true;
                if (children_insert_result.split)
                {
                    split_result children_split_result = this->children[upper_index]->split();
                    if (upper_index == this->keys.size())
                    {
                        this->children.push_back(children_split_result.sibling);
                        this->keys.push_back(children_split_result.key);
                    }
                    else
                    {
                        this->children.insert(this->children.begin() + upper_index + 1, children_split_result.sibling);
                        this->keys.insert(this->keys.begin() + upper_index, children_split_result.key);
                    }

                    result.split = this->children.size() == max_size + 1;
                }
                else
                {
                    result.split = false;
                }
            }
            else
            {
                result.succeed = false;
            }

            break;
        }
    }

    return result;
}

split_result btree_internal_node::split()
{
    split_result result;
    btree_internal_node* sibling = new btree_internal_node();
    for (int i = min_size; i < this->children.size(); i++)
    {
        sibling->children.push_back(this->children[i]);
    }
    for (int i = min_size; i < this->keys.size(); i++)
    {
        sibling->keys.push_back(this->keys[i]);
    }
    result.sibling = sibling;
    result.key = this->keys[min_size - 1];
    this->keys.resize(min_size - 1);
    this->children.resize(min_size);
    return result;
}

bool btree_impl::insert(int key, int value)
{
    if (this->m_root == nullptr)
    {
        this->m_root = new btree_leaf_node();
    }

    insert_result result = this->m_root->insert(key, value);

    if (result.succeed)
    {
        if (result.split)
        {
            split_result split_result = this->m_root->split();
            this->m_root = new btree_internal_node(split_result.key, this->m_root, split_result.sibling);
            return true;
        }
        else
        {
            return true;
        }
    }
    else
    {
        return false;
    }
}<|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/>.
 */

#ifdef HOST_W32
// A peculiar thing this one. If commented out or included *after* "config.h",
// mingw32-g++ returns: error: '::malloc' has not been declared
#include <cstdlib>
#endif

#include <string>
#include <vector>

#include "config.h"

#include "hosthandler.h"
#include "opts.h"

#ifdef WITH_PERL // -----------------------------
#include <EXTERN.h>
#include <perl.h>
#include <XSUB.h>

EXTERN_C void xs_init(pTHX);

static PerlInterpreter *perl;

static const char script_title[] =
"binmode(STDOUT, \":utf8\");"

"use Encode qw(from_to decode_utf8 FB_CROAK);"
"use HTML::TokeParser;"

"from_to($html, $1, \"utf8\")"
"    if ($html =~ /charset=(.*?)\"/);"

"$html = Encode::decode_utf8($html, Encode::FB_CROAK);"

"$parser = HTML::TokeParser->new(\\$html);"
"$parser->get_tag('title');"
"$title = $parser->get_trimmed_text;"
;

static const char script_filter[] =
"$title =~ s/(youtube|video|liveleak.com|sevenload|dailymotion)//gi;"
"$title =~ s/(on vimeo|.golem.de|clipfish|funny hub)//gi;"
"$title =~ s/video//gi;"
"$title =~ s/^[-\\s]+//;"
"$title =~ s/\\s+$//;"

"if (!$no_cclass) {"
"    $re = $cclass || qr|\\w|;"
"    $title = join('', $title =~ /$re/g);"
"}"
;

static void
initPerl() {
    perl = perl_alloc();
    perl_construct(perl);

    const char   *args[] = {"", "-e", "0"};
    perl_parse(perl, xs_init, 3, const_cast<char**>(args), 0);

    perl_run(perl);
}

static void
freePerl() {
    perl_destruct(perl);
    perl_free(perl);
}

static std::string
getPageTitle(const std::string &html) {

    initPerl();

    SV *sv_html = perl_get_sv("html", TRUE);
    sv_setpv(sv_html, html.c_str());

    perl_eval_pv(script_title, TRUE);

    return SvPV(perl_get_sv("title", FALSE), PL_na);
}

static void
filterTitle(std::string& title) {

    Options opts = optsmgr.getOptions();

    if (opts.cclass_given) {
        SV     *sv_cclass = perl_get_sv("cclass", TRUE);
        sv_setpv(sv_cclass, opts.cclass_arg);
    }

    if (opts.no_cclass_given) {
        SV *sv_nocclass = perl_get_sv("no_cclass", TRUE);
        sv_setiv(sv_nocclass, 1);
    }

    SV *sv_title = perl_get_sv("title", TRUE);
    sv_setpv(sv_title, title.c_str());

    perl_eval_pv(script_filter, TRUE);

    title = SvPV(get_sv("title", FALSE), PL_na);

    freePerl();
}
#endif // WITH_PERL -----------------------------

HostHandler::HostHandler()
    : pageContent(""), props(VideoProperties())
{
}

HostHandler::~HostHandler() {
}

const bool
HostHandler::isHost(std::string url) {
    return Util::toLower(url).find(props.getDomain())
        != std::string::npos;
}

void
HostHandler::parsePage(
    const std::string& pageContent,
    const std::string& url)
{
    this->pageContent = pageContent;

    props.setPageLink(url);

#ifdef WITH_PERL
    if (optsmgr.getOptions().title_given)
        props.setTitle( getPageTitle(pageContent) );
#endif

    // call overridden functions
    parseId   ();
    parseLink ();

#ifdef WITH_PERL
    // Overridden parseLink may have changed the title video property.
    // Apply --cclass here.
    if (optsmgr.getOptions().title_given) {
        std::string title = props.getTitle();
        filterTitle(title);
        props.setTitle(title);
    }
#endif

    this->pageContent.clear();
}

const VideoProperties&
HostHandler::getVideoProperties() const {
    return props;
}

HostHandler::
    ParseException::ParseException(const std::string& error)
        : RuntimeException(CCLIVE_PARSE, error)
{
}
<commit_msg>Fix: title: cleanup with funnyhub.<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/>.
 */

#ifdef HOST_W32
// A peculiar thing this one. If commented out or included *after* "config.h",
// mingw32-g++ returns: error: '::malloc' has not been declared
#include <cstdlib>
#endif

#include <string>
#include <vector>

#include "config.h"

#include "hosthandler.h"
#include "opts.h"

#ifdef WITH_PERL // -----------------------------
#include <EXTERN.h>
#include <perl.h>
#include <XSUB.h>

EXTERN_C void xs_init(pTHX);

static PerlInterpreter *perl;

static const char script_title[] =
"binmode(STDOUT, \":utf8\");"

"use Encode qw(from_to decode_utf8 FB_CROAK);"
"use HTML::TokeParser;"

"from_to($html, $1, \"utf8\")"
"    if ($html =~ /charset=(.*?)\"/);"

"$html = Encode::decode_utf8($html, Encode::FB_CROAK);"

"$parser = HTML::TokeParser->new(\\$html);"
"$parser->get_tag('title');"
"$title = $parser->get_trimmed_text;"
;

static const char script_filter[] =
"$title =~ s/(youtube|liveleak.com|sevenload|dailymotion)//gi;"
"$title =~ s/(on vimeo|.golem.de|clipfish|funny hub)//gi;"
"$title =~ s/(video[s])//gi;"
"$title =~ s/^[-\\s]+//;"
"$title =~ s/\\s+$//;"

"if (!$no_cclass) {"
"    $re = $cclass || qr|\\w|;"
"    $title = join('', $title =~ /$re/g);"
"}"
;

static void
initPerl() {
    perl = perl_alloc();
    perl_construct(perl);

    const char   *args[] = {"", "-e", "0"};
    perl_parse(perl, xs_init, 3, const_cast<char**>(args), 0);

    perl_run(perl);
}

static void
freePerl() {
    perl_destruct(perl);
    perl_free(perl);
}

static std::string
getPageTitle(const std::string &html) {

    initPerl();

    SV *sv_html = perl_get_sv("html", TRUE);
    sv_setpv(sv_html, html.c_str());

    perl_eval_pv(script_title, TRUE);

    return SvPV(perl_get_sv("title", FALSE), PL_na);
}

static void
filterTitle(std::string& title) {

    Options opts = optsmgr.getOptions();

    if (opts.cclass_given) {
        SV     *sv_cclass = perl_get_sv("cclass", TRUE);
        sv_setpv(sv_cclass, opts.cclass_arg);
    }

    if (opts.no_cclass_given) {
        SV *sv_nocclass = perl_get_sv("no_cclass", TRUE);
        sv_setiv(sv_nocclass, 1);
    }

    SV *sv_title = perl_get_sv("title", TRUE);
    sv_setpv(sv_title, title.c_str());

    perl_eval_pv(script_filter, TRUE);

    title = SvPV(get_sv("title", FALSE), PL_na);

    freePerl();
}
#endif // WITH_PERL -----------------------------

HostHandler::HostHandler()
    : pageContent(""), props(VideoProperties())
{
}

HostHandler::~HostHandler() {
}

const bool
HostHandler::isHost(std::string url) {
    return Util::toLower(url).find(props.getDomain())
        != std::string::npos;
}

void
HostHandler::parsePage(
    const std::string& pageContent,
    const std::string& url)
{
    this->pageContent = pageContent;

    props.setPageLink(url);

#ifdef WITH_PERL
    if (optsmgr.getOptions().title_given)
        props.setTitle( getPageTitle(pageContent) );
#endif

    // call overridden functions
    parseId   ();
    parseLink ();

#ifdef WITH_PERL
    // Overridden parseLink may have changed the title video property.
    // Apply --cclass here.
    if (optsmgr.getOptions().title_given) {
        std::string title = props.getTitle();
        filterTitle(title);
        props.setTitle(title);
    }
#endif

    this->pageContent.clear();
}

const VideoProperties&
HostHandler::getVideoProperties() const {
    return props;
}

HostHandler::
    ParseException::ParseException(const std::string& error)
        : RuntimeException(CCLIVE_PARSE, error)
{
}
<|endoftext|>


<commit_before>/** Copyright (C) 2013 David Braam - Released under terms of the AGPLv3 License */
#include "pathOrderOptimizer.h"
#include "utils/logOutput.h"

namespace cura {

void PathOrderOptimizer::optimize()
{
    std::vector<bool> picked;
    for(unsigned int i=0;i<polygons.size(); i++)
    {
        int best = -1;
        float bestDist = 0xFFFFFFFFFFFFFFFFLL;
        PolygonRef poly = polygons[i];
        for(unsigned int j=0; j<poly.size(); j++)
        {
            float dist = vSize2f(poly[j] - startPoint);
            if (dist < bestDist)
            {
                best = j;
                bestDist = dist;
            }
        }
        polyStart.push_back(best);
        picked.push_back(false);
    }

    Point incommingPerpundicularNormal(0, 0);
    Point p0 = startPoint;
    for(unsigned int n=0; n<polygons.size(); n++)
    {
        int best = -1;
        float bestDist = 0xFFFFFFFFFFFFFFFFLL;
        for(unsigned int i=0;i<polygons.size(); i++)
        {
            if (picked[i] || polygons[i].size() < 1)
                continue;
            if (polygons[i].size() == 2)
            {
                float dist = vSize2f(polygons[i][0] - p0);
                dist += abs(dot(incommingPerpundicularNormal, normal(polygons[i][1] - polygons[i][0], 1000))) * 0.0001f;
                if (dist < bestDist)
                {
                    best = i;
                    bestDist = dist;
                    polyStart[i] = 0;
                }
                dist = vSize2f(polygons[i][1] - p0);
                dist += abs(dot(incommingPerpundicularNormal, normal(polygons[i][0] - polygons[i][1], 1000))) * 0.0001f;
                if (dist < bestDist)
                {
                    best = i;
                    bestDist = dist;
                    polyStart[i] = 1;
                }
            }else{
                float dist = vSize2f(polygons[i][polyStart[i]] - p0);
                if (dist < bestDist)
                {
                    best = i;
                    bestDist = dist;
                }
            }
        }
        if (best > -1)
        {
            if (polygons[best].size() == 2)
            {
                int endIdx = (polyStart[best] + 1) % 2;
                p0 = polygons[best][endIdx];
                incommingPerpundicularNormal = crossZ(normal(polygons[best][endIdx] - polygons[best][polyStart[best]], 1000));
            }else{
                p0 = polygons[best][polyStart[best]];
                incommingPerpundicularNormal = Point(0, 0);
            }
            picked[best] = true;
            polyOrder.push_back(best);
        }
    }

    p0 = startPoint;
    for(unsigned int n=0; n<polyOrder.size(); n++)
    {
        int nr = polyOrder[n];
        PolygonRef poly = polygons[nr];
        int best = -1;
        float bestDist = 0xFFFFFFFFFFFFFFFFLL;
        bool orientation = poly.orientation();
        for(unsigned int i=0;i<poly.size(); i++)
        {
            float dist = vSize2f(polygons[nr][i] - p0);
            Point n0 = normal(poly[(i+poly.size()-1)%poly.size()] - poly[i], 10000);
            Point n1 = normal(poly[i] - poly[(i + 1) % poly.size()], 10000);
            float dot_score = dot(n0, n1) - dot(crossZ(n0), n1);
            if (orientation)
                dot_score = -dot_score;
            if (dist + dot_score < bestDist)
            {
                best = i;
                bestDist = dist;
            }
        }
        polyStart[nr] = best;
        if (poly.size() <= 2)
        {
            p0 = poly[(best + 1) % 2];
        }else{
            p0 = poly[best];
        }
    }
}

}//namespace cura
<commit_msg>Some better parameters for the corner finding routine.<commit_after>/** Copyright (C) 2013 David Braam - Released under terms of the AGPLv3 License */
#include "pathOrderOptimizer.h"
#include "utils/logOutput.h"

namespace cura {

void PathOrderOptimizer::optimize()
{
    std::vector<bool> picked;
    for(unsigned int i=0;i<polygons.size(); i++)
    {
        int best = -1;
        float bestDist = 0xFFFFFFFFFFFFFFFFLL;
        PolygonRef poly = polygons[i];
        for(unsigned int j=0; j<poly.size(); j++)
        {
            float dist = vSize2f(poly[j] - startPoint);
            if (dist < bestDist)
            {
                best = j;
                bestDist = dist;
            }
        }
        polyStart.push_back(best);
        picked.push_back(false);
    }

    Point incommingPerpundicularNormal(0, 0);
    Point p0 = startPoint;
    for(unsigned int n=0; n<polygons.size(); n++)
    {
        int best = -1;
        float bestDist = 0xFFFFFFFFFFFFFFFFLL;
        for(unsigned int i=0;i<polygons.size(); i++)
        {
            if (picked[i] || polygons[i].size() < 1)
                continue;
            if (polygons[i].size() == 2)
            {
                float dist = vSize2f(polygons[i][0] - p0);
                dist += abs(dot(incommingPerpundicularNormal, normal(polygons[i][1] - polygons[i][0], 1000))) * 0.0001f;
                if (dist < bestDist)
                {
                    best = i;
                    bestDist = dist;
                    polyStart[i] = 0;
                }
                dist = vSize2f(polygons[i][1] - p0);
                dist += abs(dot(incommingPerpundicularNormal, normal(polygons[i][0] - polygons[i][1], 1000))) * 0.0001f;
                if (dist < bestDist)
                {
                    best = i;
                    bestDist = dist;
                    polyStart[i] = 1;
                }
            }else{
                float dist = vSize2f(polygons[i][polyStart[i]] - p0);
                if (dist < bestDist)
                {
                    best = i;
                    bestDist = dist;
                }
            }
        }
        if (best > -1)
        {
            if (polygons[best].size() == 2)
            {
                int endIdx = (polyStart[best] + 1) % 2;
                p0 = polygons[best][endIdx];
                incommingPerpundicularNormal = crossZ(normal(polygons[best][endIdx] - polygons[best][polyStart[best]], 1000));
            }else{
                p0 = polygons[best][polyStart[best]];
                incommingPerpundicularNormal = Point(0, 0);
            }
            picked[best] = true;
            polyOrder.push_back(best);
        }
    }

    p0 = startPoint;
    for(unsigned int n=0; n<polyOrder.size(); n++)
    {
        int nr = polyOrder[n];
        PolygonRef poly = polygons[nr];
        int best = -1;
        float bestDist = 0xFFFFFFFFFFFFFFFFLL;
        bool orientation = poly.orientation();
        for(unsigned int i=0;i<poly.size(); i++)
        {
            float dist = vSize2f(polygons[nr][i] - p0);
            Point n0 = normal(poly[(i+poly.size()-1)%poly.size()] - poly[i], 2000);
            Point n1 = normal(poly[i] - poly[(i + 1) % poly.size()], 2000);
            float dot_score = dot(n0, n1) - dot(crossZ(n0), n1);
            if (orientation)
                dot_score = -dot_score;
            if (dist + dot_score < bestDist)
            {
                best = i;
                bestDist = dist;
            }
        }
        polyStart[nr] = best;
        if (poly.size() <= 2)
        {
            p0 = poly[(best + 1) % 2];
        }else{
            p0 = poly[best];
        }
    }
}

}//namespace cura
<|endoftext|>


<commit_before>/*
Copyright (c) 2016, Patricio Gonzalez Vivo
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
    * Redistributions of source code must retain the above copyright
      notice, this list of conditions and the following disclaimer.
    * Redistributions in binary form must reproduce the above copyright
      notice, this list of conditions and the following disclaimer in the
      documentation and/or other materials provided with the distribution.
    * Neither the name of the copyright holder nor the
      names of its contributors may be used to endorse or promote products
      derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/

#include "fbo.h"
#include <iostream>

Fbo::Fbo():m_id(0), m_old_fbo_id(0), m_texture(0), m_depth_buffer(0), m_depth_texture(0), m_type(COLOR_TEXTURE), m_width(0), m_height(0), m_allocated(false), m_binded(false), m_depth(false) {
}

Fbo::~Fbo() {
    unbind();
    if (m_allocated) {
        glDeleteTextures(1, &m_texture);
        glDeleteRenderbuffers(1, &m_depth_buffer);
        glDeleteFramebuffers(1, &m_id);
        m_allocated = false;
    }
}

void Fbo::allocate(const uint _width, const uint _height, FboType _type) {
    m_type = _type;

    bool color_texture = true;
    bool depth_texture = false;

    switch(_type) {
        case COLOR_TEXTURE:
            m_depth = false;
            color_texture = true;
            depth_texture = false;
        break;
        case COLOR_TEXTURE_DEPTH_BUFFER:
            m_depth = true;
            color_texture = true;
            depth_texture = false;
        break;
        case COLOR_DEPTH_TEXTURES:
            m_depth = true;
            color_texture = true;
            depth_texture = true;
        break;
        case DEPTH_TEXTURE:
            m_depth = true;
            color_texture = false;
            depth_texture = true;
        break;
    }

    if (!m_allocated) {
        // Create a frame buffer
        glGenFramebuffers(1, &m_id);

        if (color_texture) {
            // Generate a texture to hold the colour buffer
            glGenTextures(1, &m_texture);
        }

        if (m_depth) {
            // Create a texture to hold the depth buffer
            glGenRenderbuffers(1, &m_depth_buffer);
        }
    }

    m_width = _width;
    m_height = _height;

    bind();

    if (color_texture) {
        // Color
        glBindTexture(GL_TEXTURE_2D, m_texture);
        glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, m_width, m_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);

        // glGenerateMipmap(GL_TEXTURE_2D);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
        // glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
        glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, m_texture, 0);
    }

    // Depth Buffer
    if (m_depth) {
        glBindRenderbuffer(GL_RENDERBUFFER, m_depth_buffer);

#ifdef PLATFORM_RPI
        glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT16, m_width, m_height);
#else
        glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT, m_width, m_height);
#endif
        glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, m_depth_buffer);

        if (depth_texture) {

            // Generate a texture to hold the depth buffer
            if (m_depth_texture == 0) {
                glGenTextures(1, &m_depth_texture);
            }

            glBindTexture(GL_TEXTURE_2D, m_depth_texture);
#ifdef PLATFORM_RPI
            // glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT16, m_width, m_height, 0, GL_DEPTH_COMPONENT, GL_FLOAT, NULL);
            glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT16, m_width, m_height, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, NULL);
#else
            glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT32, m_width, m_height, 0, GL_DEPTH_COMPONENT, GL_FLOAT, NULL);
#endif

            glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
            glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
            glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
            glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
            glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, m_depth_texture, 0);
        }
    }

    if (glCheckFramebufferStatus(GL_FRAMEBUFFER) == GL_FRAMEBUFFER_COMPLETE) {
        m_allocated = true;
    }
    else {
        std::cout << "FBO: not complete" << std::endl;
    }
    unbind();

    glBindTexture(GL_TEXTURE_2D, 0);
    if (m_depth){
        glBindRenderbuffer(GL_RENDERBUFFER, 0);
    }
}

void Fbo::bind() {
    if (!m_binded) {
        glGetIntegerv(GL_FRAMEBUFFER_BINDING, (GLint *)&m_old_fbo_id);

        glBindTexture(GL_TEXTURE_2D, 0);
        glEnable(GL_TEXTURE_2D);
        glBindFramebuffer(GL_FRAMEBUFFER, m_id);
        glViewport(0.0f, 0.0f, m_width, m_height);
        glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
        if (m_depth) {
            glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
        } else {
            glClear(GL_COLOR_BUFFER_BIT);
        }
        m_binded = true;
    }
}

void Fbo::unbind() {
    if (m_binded) {
        glBindFramebuffer(GL_FRAMEBUFFER, m_old_fbo_id);
        m_binded = false;
    }
}
<commit_msg>trying GL_UNSIGNED_SHORT<commit_after>/*
Copyright (c) 2016, Patricio Gonzalez Vivo
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
    * Redistributions of source code must retain the above copyright
      notice, this list of conditions and the following disclaimer.
    * Redistributions in binary form must reproduce the above copyright
      notice, this list of conditions and the following disclaimer in the
      documentation and/or other materials provided with the distribution.
    * Neither the name of the copyright holder nor the
      names of its contributors may be used to endorse or promote products
      derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/

#include "fbo.h"
#include <iostream>

Fbo::Fbo():m_id(0), m_old_fbo_id(0), m_texture(0), m_depth_buffer(0), m_depth_texture(0), m_type(COLOR_TEXTURE), m_width(0), m_height(0), m_allocated(false), m_binded(false), m_depth(false) {
}

Fbo::~Fbo() {
    unbind();
    if (m_allocated) {
        glDeleteTextures(1, &m_texture);
        glDeleteRenderbuffers(1, &m_depth_buffer);
        glDeleteFramebuffers(1, &m_id);
        m_allocated = false;
    }
}

void Fbo::allocate(const uint _width, const uint _height, FboType _type) {
    m_type = _type;

    bool color_texture = true;
    bool depth_texture = false;

    switch(_type) {
        case COLOR_TEXTURE:
            m_depth = false;
            color_texture = true;
            depth_texture = false;
        break;
        case COLOR_TEXTURE_DEPTH_BUFFER:
            m_depth = true;
            color_texture = true;
            depth_texture = false;
        break;
        case COLOR_DEPTH_TEXTURES:
            m_depth = true;
            color_texture = true;
            depth_texture = true;
        break;
        case DEPTH_TEXTURE:
            m_depth = true;
            color_texture = false;
            depth_texture = true;
        break;
    }

    if (!m_allocated) {
        // Create a frame buffer
        glGenFramebuffers(1, &m_id);

        if (color_texture) {
            // Generate a texture to hold the colour buffer
            glGenTextures(1, &m_texture);
        }

        if (m_depth) {
            // Create a texture to hold the depth buffer
            glGenRenderbuffers(1, &m_depth_buffer);
        }
    }

    m_width = _width;
    m_height = _height;

    bind();

    if (color_texture) {
        // Color
        glBindTexture(GL_TEXTURE_2D, m_texture);
        glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, m_width, m_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);

        // glGenerateMipmap(GL_TEXTURE_2D);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
        // glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
        glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, m_texture, 0);
    }

    // Depth Buffer
    if (m_depth) {
        glBindRenderbuffer(GL_RENDERBUFFER, m_depth_buffer);

#ifdef PLATFORM_RPI
        glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT16, m_width, m_height);
#else
        glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT, m_width, m_height);
#endif
        glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, m_depth_buffer);

        if (depth_texture) {

            // Generate a texture to hold the depth buffer
            if (m_depth_texture == 0) {
                glGenTextures(1, &m_depth_texture);
            }

            glBindTexture(GL_TEXTURE_2D, m_depth_texture);
#ifdef PLATFORM_RPI
            // glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT16, m_width, m_height, 0, GL_DEPTH_COMPONENT, GL_FLOAT, NULL);
            glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT16, m_width, m_height, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_SHORT, NULL);
#else
            glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT24, m_width, m_height, 0, GL_DEPTH_COMPONENT, GL_FLOAT, NULL);
#endif

            glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
            glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
            glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
            glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
            glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, m_depth_texture, 0);
        }
    }

    if (glCheckFramebufferStatus(GL_FRAMEBUFFER) == GL_FRAMEBUFFER_COMPLETE) {
        m_allocated = true;
    }
    else {
        std::cout << "FBO: not complete" << std::endl;
    }
    unbind();

    glBindTexture(GL_TEXTURE_2D, 0);
    if (m_depth){
        glBindRenderbuffer(GL_RENDERBUFFER, 0);
    }
}

void Fbo::bind() {
    if (!m_binded) {
        glGetIntegerv(GL_FRAMEBUFFER_BINDING, (GLint *)&m_old_fbo_id);

        glBindTexture(GL_TEXTURE_2D, 0);
        glEnable(GL_TEXTURE_2D);
        glBindFramebuffer(GL_FRAMEBUFFER, m_id);
        glViewport(0.0f, 0.0f, m_width, m_height);
        glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
        if (m_depth) {
            glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
        } else {
            glClear(GL_COLOR_BUFFER_BIT);
        }
        m_binded = true;
    }
}

void Fbo::unbind() {
    if (m_binded) {
        glBindFramebuffer(GL_FRAMEBUFFER, m_old_fbo_id);
        m_binded = false;
    }
}
<|endoftext|>


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

  FILE:  mydefs.hpp

  CONTENTS:

    Basic data type definitions and operations to be robust across platforms.

  PROGRAMMERS:

    martin.isenburg@rapidlasso.com  -  http://rapidlasso.com

  COPYRIGHT:

    (c) 2005-2015, martin isenburg, rapidlasso - fast tools to catch reality

    This is free software; you can redistribute and/or modify it under the
    terms of the GNU Lesser General Licence as published by the Free Software
    Foundation. See the COPYING file for more information.

    This software is distributed WITHOUT ANY WARRANTY and without even the
    implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

  CHANGE HISTORY:

    28 October 2015 -- adding DLL bindings via 'COMPILE_AS_DLL' and 'USE_AS_DLL'
    10 January 2011 -- licensing change for LGPL release and libLAS integration
    13 July 2005 -- created after returning with many mosquito bites from OBX

===============================================================================
*/
#ifndef MYDEFS_HPP
#define MYDEFS_HPP

#ifndef _WIN32
#define LASLIB_DLL
#else  // _WIN32
#ifdef COMPILE_AS_DLL
#define LASLIB_DLL __declspec(dllexport)
#elif USE_AS_DLL
#define LASLIB_DLL __declspec(dllimport)
#else
#define LASLIB_DLL
#endif
#endif // _WIN32

typedef char               CHAR;

typedef int                I32;
typedef short              I16;
typedef char               I8;

typedef unsigned int       U32;
typedef unsigned short     U16;
typedef unsigned char      U8;

#if defined(_WIN32) && ! defined (__MINGW32__) // 64 byte integer under Windows
typedef unsigned __int64   U64;
typedef __int64            I64;
#else                                          // 64 byte integer elsewhere ...
typedef unsigned long long U64;
typedef long long          I64;
#endif

typedef float              F32;
typedef double             F64;

#if defined(_MSC_VER) || defined (__MINGW32__)
typedef int                BOOL;
#else
typedef bool               BOOL;
#endif

typedef union U32I32F32 { U32 u32; I32 i32; F32 f32; } U32I32F32;
typedef union U64I64F64 { U64 u64; I64 i64; F64 f64; } U64I64F64;
typedef union I64U32I32F32 { I64 i64; U32 u32[2]; I32 i32[2]; F32 f32[2]; } I64U32I32F32;

#define F32_MAX            +2.0e+37f
#define F32_MIN            -2.0e+37f

#define F64_MAX            +2.0e+307
#define F64_MIN            -2.0e+307

#define U8_MIN             ((U8)0x0)  // 0
#define U8_MAX             ((U8)0xFF) // 255
#define U8_MAX_MINUS_ONE   ((U8)0xFE) // 254
#define U8_MAX_PLUS_ONE    0x0100     // 256

#define U16_MIN            ((U16)0x0)    // 0
#define U16_MAX            ((U16)0xFFFF) // 65535
#define U16_MAX_MINUS_ONE  ((U16)0xFFFE) // 65534
#define U16_MAX_PLUS_ONE   0x00010000    // 65536

#define U32_MIN            ((U32)0x0)            // 0
#define U32_MAX            ((U32)0xFFFFFFFF)     // 4294967295
#define U32_MAX_MINUS_ONE  ((U32)0xFFFFFFFE)     // 4294967294
#if defined(WIN32)            // 64 byte unsigned int constant under Windows
#define U32_MAX_PLUS_ONE   0x0000000100000000    // 4294967296
#else                         // 64 byte unsigned int constant elsewhere ...
#define U32_MAX_PLUS_ONE   0x0000000100000000ull // 4294967296
#endif

#define I8_MIN             ((I8)0x80) // -128
#define I8_MAX             ((I8)0x7F) // 127

#define I16_MIN            ((I16)0x8000) // -32768
#define I16_MAX            ((I16)0x7FFF) // 32767

#define I32_MIN            ((I32)0x80000000) // -2147483648
#define I32_MAX            ((I32)0x7FFFFFFF) //  2147483647

#define I64_MIN            ((I64)0x8000000000000000)
#define I64_MAX            ((I64)0x7FFFFFFFFFFFFFFF)

#define U8_FOLD(n)      (((n) < U8_MIN) ? (n+U8_MAX_PLUS_ONE) : (((n) > U8_MAX) ? (n-U8_MAX_PLUS_ONE) : (n)))

#define I8_CLAMP(n)     (((n) <= I8_MIN) ? I8_MIN : (((n) >= I8_MAX) ? I8_MAX : ((I8)(n))))
#define U8_CLAMP(n)     (((n) <= U8_MIN) ? U8_MIN : (((n) >= U8_MAX) ? U8_MAX : ((U8)(n))))

#define I16_CLAMP(n)    (((n) <= I16_MIN) ? I16_MIN : (((n) >= I16_MAX) ? I16_MAX : ((I16)(n))))
#define U16_CLAMP(n)    (((n) <= U16_MIN) ? U16_MIN : (((n) >= U16_MAX) ? U16_MAX : ((U16)(n))))

#define I32_CLAMP(n)    (((n) <= I32_MIN) ? I32_MIN : (((n) >= I32_MAX) ? I32_MAX : ((I32)(n))))
#define U32_CLAMP(n)    (((n) <= U32_MIN) ? U32_MIN : (((n) >= U32_MAX) ? U32_MAX : ((U32)(n))))

#define I8_QUANTIZE(n) (((n) >= 0) ? (I8)((n)+0.5) : (I8)((n)-0.5))
#define U8_QUANTIZE(n) (((n) >= 0) ? (U8)((n)+0.5) : (U8)(0))

#define I16_QUANTIZE(n) (((n) >= 0) ? (I16)((n)+0.5) : (I16)((n)-0.5))
#define U16_QUANTIZE(n) (((n) >= 0) ? (U16)((n)+0.5) : (U16)(0))

#define I32_QUANTIZE(n) (((n) >= 0) ? (I32)((n)+0.5) : (I32)((n)-0.5))
#define U32_QUANTIZE(n) (((n) >= 0) ? (U32)((n)+0.5) : (U32)(0))

#define I64_QUANTIZE(n) (((n) >= 0) ? (I64)((n)+0.5) : (I64)((n)-0.5))
#define U64_QUANTIZE(n) (((n) >= 0) ? (U64)((n)+0.5) : (U64)(0))

#define I16_FLOOR(n) ((((I16)(n)) > (n)) ? (((I16)(n))-1) : ((I16)(n)))
#define I32_FLOOR(n) ((((I32)(n)) > (n)) ? (((I32)(n))-1) : ((I32)(n)))
#define I64_FLOOR(n) ((((I64)(n)) > (n)) ? (((I64)(n))-1) : ((I64)(n)))

#define I16_CEIL(n) ((((I16)(n)) < (n)) ? (((I16)(n))+1) : ((I16)(n)))
#define I32_CEIL(n) ((((I32)(n)) < (n)) ? (((I32)(n))+1) : ((I32)(n)))
#define I64_CEIL(n) ((((I64)(n)) < (n)) ? (((I64)(n))+1) : ((I64)(n)))

#define I8_FITS_IN_RANGE(n) (((n) >= I8_MIN) && ((n) <= I8_MAX) ? TRUE : FALSE)
#define U8_FITS_IN_RANGE(n) (((n) >= U8_MIN) && ((n) <= U8_MAX) ? TRUE : FALSE)
#define I16_FITS_IN_RANGE(n) (((n) >= I16_MIN) && ((n) <= I16_MAX) ? TRUE : FALSE)
#define U16_FITS_IN_RANGE(n) (((n) >= U16_MIN) && ((n) <= U16_MAX) ? TRUE : FALSE)
#define I32_FITS_IN_RANGE(n) (((n) >= I32_MIN) && ((n) <= I32_MAX) ? TRUE : FALSE)
#define U32_FITS_IN_RANGE(n) (((n) >= U32_MIN) && ((n) <= U32_MAX) ? TRUE : FALSE)

#define F32_IS_FINITE(n) ((F32_MIN < (n)) && ((n) < F32_MAX))
#define F64_IS_FINITE(n) ((F64_MIN < (n)) && ((n) < F64_MAX))

#define U32_ZERO_BIT_0(n) (((n)&(U32)0xFFFFFFFE))
#define U32_ZERO_BIT_0_1(n) (((n)&(U32)0xFFFFFFFC))

#ifndef FALSE
#define FALSE   0
#endif

#ifndef TRUE
#define TRUE    1
#endif

#ifndef NULL
#define NULL    0
#endif

inline BOOL IS_LITTLE_ENDIAN()
{
  const U32 i = 1;
  return (*((const U8*)&i) == 1);
}

#define ENDIANSWAP16(n) \
	( ((((U16) n) << 8) & 0xFF00) | \
	  ((((U16) n) >> 8) & 0x00FF) )

#define ENDIANSWAP32(n) \
	( ((((U32) n) << 24) & 0xFF000000) |	\
	  ((((U32) n) <<  8) & 0x00FF0000) |	\
	  ((((U32) n) >>  8) & 0x0000FF00) |	\
	  ((((U32) n) >> 24) & 0x000000FF) )

inline void ENDIAN_SWAP_16(U8* field)
{
  U8 help = field[0];
  field[0] = field[1];
  field[1] = help;
}

inline void ENDIAN_SWAP_32(U8* field)
{
  U8 help;
  help = field[0];
  field[0] = field[3];
  field[3] = help;
  help = field[1];
  field[1] = field[2];
  field[2] = help;
}

inline void ENDIAN_SWAP_64(U8* field)
{
  U8 help;
  help = field[0];
  field[0] = field[7];
  field[7] = help;
  help = field[1];
  field[1] = field[6];
  field[6] = help;
  help = field[2];
  field[2] = field[5];
  field[5] = help;
  help = field[3];
  field[3] = field[4];
  field[4] = help;
}

inline void ENDIAN_SWAP_16(const U8* from, U8* to)
{
  to[0] = from[1];
  to[1] = from[0];
}

inline void ENDIAN_SWAP_32(const U8* from, U8* to)
{
  to[0] = from[3];
  to[1] = from[2];
  to[2] = from[1];
  to[3] = from[0];
}

inline void ENDIAN_SWAP_64(const U8* from, U8* to)
{
  to[0] = from[7];
  to[1] = from[6];
  to[2] = from[5];
  to[3] = from[4];
  to[4] = from[3];
  to[5] = from[2];
  to[6] = from[1];
  to[7] = from[0];
}

#if defined(_MSC_VER)
#include <windows.h>
wchar_t* UTF8toUTF16(const char* utf8);
#endif

#endif
<commit_msg>new comvenience macros I16_CLAMP_QUANTIZE()<commit_after>/*
===============================================================================

  FILE:  mydefs.hpp

  CONTENTS:

    Basic data type definitions and operations to be robust across platforms.

  PROGRAMMERS:

    martin.isenburg@rapidlasso.com  -  http://rapidlasso.com

  COPYRIGHT:

    (c) 2005-2015, martin isenburg, rapidlasso - fast tools to catch reality

    This is free software; you can redistribute and/or modify it under the
    terms of the GNU Lesser General Licence as published by the Free Software
    Foundation. See the COPYING file for more information.

    This software is distributed WITHOUT ANY WARRANTY and without even the
    implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

  CHANGE HISTORY:

    28 October 2015 -- adding DLL bindings via 'COMPILE_AS_DLL' and 'USE_AS_DLL'
    10 January 2011 -- licensing change for LGPL release and libLAS integration
    13 July 2005 -- created after returning with many mosquito bites from OBX

===============================================================================
*/
#ifndef MYDEFS_HPP
#define MYDEFS_HPP

#ifndef _WIN32
#define LASLIB_DLL
#else  // _WIN32
#ifdef COMPILE_AS_DLL
#define LASLIB_DLL __declspec(dllexport)
#elif USE_AS_DLL
#define LASLIB_DLL __declspec(dllimport)
#else
#define LASLIB_DLL
#endif
#endif // _WIN32

typedef char               CHAR;

typedef int                I32;
typedef short              I16;
typedef char               I8;

typedef unsigned int       U32;
typedef unsigned short     U16;
typedef unsigned char      U8;

#if defined(_WIN32) && ! defined (__MINGW32__) // 64 byte integer under Windows
typedef unsigned __int64   U64;
typedef __int64            I64;
#else                                          // 64 byte integer elsewhere ...
typedef unsigned long long U64;
typedef long long          I64;
#endif

typedef float              F32;
typedef double             F64;

#if defined(_MSC_VER) || defined (__MINGW32__)
typedef int                BOOL;
#else
typedef bool               BOOL;
#endif

typedef union U32I32F32 { U32 u32; I32 i32; F32 f32; } U32I32F32;
typedef union U64I64F64 { U64 u64; I64 i64; F64 f64; } U64I64F64;
typedef union I64U32I32F32 { I64 i64; U32 u32[2]; I32 i32[2]; F32 f32[2]; } I64U32I32F32;

#define F32_MAX            +2.0e+37f
#define F32_MIN            -2.0e+37f

#define F64_MAX            +2.0e+307
#define F64_MIN            -2.0e+307

#define U8_MIN             ((U8)0x0)  // 0
#define U8_MAX             ((U8)0xFF) // 255
#define U8_MAX_MINUS_ONE   ((U8)0xFE) // 254
#define U8_MAX_PLUS_ONE    0x0100     // 256

#define U16_MIN            ((U16)0x0)    // 0
#define U16_MAX            ((U16)0xFFFF) // 65535
#define U16_MAX_MINUS_ONE  ((U16)0xFFFE) // 65534
#define U16_MAX_PLUS_ONE   0x00010000    // 65536

#define U32_MIN            ((U32)0x0)            // 0
#define U32_MAX            ((U32)0xFFFFFFFF)     // 4294967295
#define U32_MAX_MINUS_ONE  ((U32)0xFFFFFFFE)     // 4294967294
#if defined(WIN32)            // 64 byte unsigned int constant under Windows
#define U32_MAX_PLUS_ONE   0x0000000100000000    // 4294967296
#else                         // 64 byte unsigned int constant elsewhere ...
#define U32_MAX_PLUS_ONE   0x0000000100000000ull // 4294967296
#endif

#define I8_MIN             ((I8)0x80) // -128
#define I8_MAX             ((I8)0x7F) // 127

#define I16_MIN            ((I16)0x8000) // -32768
#define I16_MAX            ((I16)0x7FFF) // 32767

#define I32_MIN            ((I32)0x80000000) // -2147483648
#define I32_MAX            ((I32)0x7FFFFFFF) //  2147483647

#define I64_MIN            ((I64)0x8000000000000000)
#define I64_MAX            ((I64)0x7FFFFFFFFFFFFFFF)

#define U8_FOLD(n)      (((n) < U8_MIN) ? (n+U8_MAX_PLUS_ONE) : (((n) > U8_MAX) ? (n-U8_MAX_PLUS_ONE) : (n)))

#define I8_CLAMP(n)     (((n) <= I8_MIN) ? I8_MIN : (((n) >= I8_MAX) ? I8_MAX : ((I8)(n))))
#define U8_CLAMP(n)     (((n) <= U8_MIN) ? U8_MIN : (((n) >= U8_MAX) ? U8_MAX : ((U8)(n))))

#define I16_CLAMP(n)    (((n) <= I16_MIN) ? I16_MIN : (((n) >= I16_MAX) ? I16_MAX : ((I16)(n))))
#define U16_CLAMP(n)    (((n) <= U16_MIN) ? U16_MIN : (((n) >= U16_MAX) ? U16_MAX : ((U16)(n))))

#define I32_CLAMP(n)    (((n) <= I32_MIN) ? I32_MIN : (((n) >= I32_MAX) ? I32_MAX : ((I32)(n))))
#define U32_CLAMP(n)    (((n) <= U32_MIN) ? U32_MIN : (((n) >= U32_MAX) ? U32_MAX : ((U32)(n))))

#define I8_QUANTIZE(n) (((n) >= 0) ? (I8)((n)+0.5) : (I8)((n)-0.5))
#define U8_QUANTIZE(n) (((n) >= 0) ? (U8)((n)+0.5) : (U8)(0))

#define I16_QUANTIZE(n) (((n) >= 0) ? (I16)((n)+0.5) : (I16)((n)-0.5))
#define U16_QUANTIZE(n) (((n) >= 0) ? (U16)((n)+0.5) : (U16)(0))

#define I32_QUANTIZE(n) (((n) >= 0) ? (I32)((n)+0.5) : (I32)((n)-0.5))
#define U32_QUANTIZE(n) (((n) >= 0) ? (U32)((n)+0.5) : (U32)(0))

#define I64_QUANTIZE(n) (((n) >= 0) ? (I64)((n)+0.5) : (I64)((n)-0.5))
#define U64_QUANTIZE(n) (((n) >= 0) ? (U64)((n)+0.5) : (U64)(0))

#define I8_CLAMP_QUANTIZE(n)     (((n) <= I8_MIN) ? I8_MIN : (((n) >= I8_MAX) ? I8_MAX : (I8_QUANTIZE(n))))
#define U8_CLAMP_QUANTIZE(n)     (((n) <= U8_MIN) ? U8_MIN : (((n) >= U8_MAX) ? U8_MAX : (U8_QUANTIZE(n))))

#define I16_CLAMP_QUANTIZE(n)    (((n) <= I16_MIN) ? I16_MIN : (((n) >= I16_MAX) ? I16_MAX : (I16_QUANTIZE(n))))
#define U16_CLAMP_QUANTIZE(n)    (((n) <= U16_MIN) ? U16_MIN : (((n) >= U16_MAX) ? U16_MAX : (U16_QUANTIZE(n))))

#define I32_CLAMP_QUANTIZE(n)    (((n) <= I32_MIN) ? I32_MIN : (((n) >= I32_MAX) ? I32_MAX : (I32_QUANTIZE(n))))
#define U32_CLAMP_QUANTIZE(n)    (((n) <= U32_MIN) ? U32_MIN : (((n) >= U32_MAX) ? U32_MAX : (U32_QUANTIZE(n))))

#define I16_FLOOR(n) ((((I16)(n)) > (n)) ? (((I16)(n))-1) : ((I16)(n)))
#define I32_FLOOR(n) ((((I32)(n)) > (n)) ? (((I32)(n))-1) : ((I32)(n)))
#define I64_FLOOR(n) ((((I64)(n)) > (n)) ? (((I64)(n))-1) : ((I64)(n)))

#define I16_CEIL(n) ((((I16)(n)) < (n)) ? (((I16)(n))+1) : ((I16)(n)))
#define I32_CEIL(n) ((((I32)(n)) < (n)) ? (((I32)(n))+1) : ((I32)(n)))
#define I64_CEIL(n) ((((I64)(n)) < (n)) ? (((I64)(n))+1) : ((I64)(n)))

#define I8_FITS_IN_RANGE(n) (((n) >= I8_MIN) && ((n) <= I8_MAX) ? TRUE : FALSE)
#define U8_FITS_IN_RANGE(n) (((n) >= U8_MIN) && ((n) <= U8_MAX) ? TRUE : FALSE)
#define I16_FITS_IN_RANGE(n) (((n) >= I16_MIN) && ((n) <= I16_MAX) ? TRUE : FALSE)
#define U16_FITS_IN_RANGE(n) (((n) >= U16_MIN) && ((n) <= U16_MAX) ? TRUE : FALSE)
#define I32_FITS_IN_RANGE(n) (((n) >= I32_MIN) && ((n) <= I32_MAX) ? TRUE : FALSE)
#define U32_FITS_IN_RANGE(n) (((n) >= U32_MIN) && ((n) <= U32_MAX) ? TRUE : FALSE)

#define F32_IS_FINITE(n) ((F32_MIN < (n)) && ((n) < F32_MAX))
#define F64_IS_FINITE(n) ((F64_MIN < (n)) && ((n) < F64_MAX))

#define U32_ZERO_BIT_0(n) (((n)&(U32)0xFFFFFFFE))
#define U32_ZERO_BIT_0_1(n) (((n)&(U32)0xFFFFFFFC))

#ifndef FALSE
#define FALSE   0
#endif

#ifndef TRUE
#define TRUE    1
#endif

#ifndef NULL
#define NULL    0
#endif

inline BOOL IS_LITTLE_ENDIAN()
{
  const U32 i = 1;
  return (*((const U8*)&i) == 1);
}

#define ENDIANSWAP16(n) \
	( ((((U16) n) << 8) & 0xFF00) | \
	  ((((U16) n) >> 8) & 0x00FF) )

#define ENDIANSWAP32(n) \
	( ((((U32) n) << 24) & 0xFF000000) |	\
	  ((((U32) n) <<  8) & 0x00FF0000) |	\
	  ((((U32) n) >>  8) & 0x0000FF00) |	\
	  ((((U32) n) >> 24) & 0x000000FF) )

inline void ENDIAN_SWAP_16(U8* field)
{
  U8 help = field[0];
  field[0] = field[1];
  field[1] = help;
}

inline void ENDIAN_SWAP_32(U8* field)
{
  U8 help;
  help = field[0];
  field[0] = field[3];
  field[3] = help;
  help = field[1];
  field[1] = field[2];
  field[2] = help;
}

inline void ENDIAN_SWAP_64(U8* field)
{
  U8 help;
  help = field[0];
  field[0] = field[7];
  field[7] = help;
  help = field[1];
  field[1] = field[6];
  field[6] = help;
  help = field[2];
  field[2] = field[5];
  field[5] = help;
  help = field[3];
  field[3] = field[4];
  field[4] = help;
}

inline void ENDIAN_SWAP_16(const U8* from, U8* to)
{
  to[0] = from[1];
  to[1] = from[0];
}

inline void ENDIAN_SWAP_32(const U8* from, U8* to)
{
  to[0] = from[3];
  to[1] = from[2];
  to[2] = from[1];
  to[3] = from[0];
}

inline void ENDIAN_SWAP_64(const U8* from, U8* to)
{
  to[0] = from[7];
  to[1] = from[6];
  to[2] = from[5];
  to[3] = from[4];
  to[4] = from[3];
  to[5] = from[2];
  to[6] = from[1];
  to[7] = from[0];
}

#if defined(_MSC_VER)
#include <windows.h>
wchar_t* UTF8toUTF16(const char* utf8);
#endif

#endif
<|endoftext|>


<commit_before>#include <stdlib.h>
#include <exception>
#include <sstream>
#include <string>
#include <algorithm>
#include <vector>
#include <iostream>
#include "tinyxml.h"

class SvgError: public std::runtime_error
{ public: SvgError(const std::string& what_arg): std::runtime_error(what_arg){};};

struct Point
{
    double x;
    double y;
};

struct Command
{
   char type;
   std::vector<double> numbers;

   std::string tostr()
   {
     std::ostringstream os;
     os << type << "[";
     for (double d : numbers)
     {
       os << d << ", ";
     }
     os << "]";
     return os.str();
   }
};

struct Path
{
//   std::vector<Command> cmds;
   std::string id;
   std::string style;

   std::vector< std::vector<Command> > subpaths;
};

class SvgReader
{

  public: SvgReader(){}

  public: void Parse(const char*path, std::vector<Path> &paths);
  public: void Dump_paths(const std::vector<Path> paths ) const;

  private: void make_commands(char cmd, const std::vector<double> &numbers, std::vector<Command> &cmds);
  private: void get_path_commands(const std::vector<std::string> &tokens, Path &path);
  private: void get_path_attribs(TiXmlElement* pElement, Path &path);
  private: void get_svg_paths(TiXmlNode* pParent, std::vector<Path> &paths);

  private: void ExpandCommands(const std::vector< std::vector<Command> > &subpaths, Path &path);
  private: void SplitSubpaths(const std::vector<Command> cmds, std::vector< std::vector<Command> > &split_cmds);
  private: void PathToPoints(const Path &path, double resolution, std::vector< std::vector<Point> > &polys);

};

std::string lowercase(const std::string& in)
{
  std::string out = in;
  std::transform(out.begin(), out.end(), out.begin(), ::tolower);
  return out;
}

std::string lowercase(const char* in)
{
  std::string ins = in;
  return lowercase(ins);
}

std::vector<std::string> &split(const std::string &s, char delim, std::vector<std::string> &elems) {
    std::stringstream ss(s);
    std::string item;
    while (std::getline(ss, item, delim)) {
        elems.push_back(item);
    }
    return elems;
}

void SvgReader::SplitSubpaths(const std::vector<Command> cmds, std::vector< std::vector<Command> > &subpaths)
{
  if(cmds.size() ==0)
  {
    std::ostringstream os;
    os << "Path has no commands";
    SvgError x(os.str());
    throw x;
  }

  for(Command cmd: cmds)
  {
    if( tolower(cmd.type) == 'm')
    {
      // the path contains a subpath
      std::vector<Command> sub;
      subpaths.push_back(sub);
    }
    // get a reference to the latest subpath
    std::vector<Command> &subpath = subpaths.back();
    // give the cmd to the latest
    subpath.push_back(cmd);
  }
}

void SvgReader::make_commands(char cmd, const std::vector<double> &numbers, std::vector<Command> &cmds)
{
  if(cmd != 'x')
  {
    Command c;
    c.type = cmd;
    c.numbers = numbers;
    cmds.push_back(c);
  }

/*
  if (tolower(cmd) == 'v' || tolower(cmd) == 'h')
  {
    unsigned int i = 0;
    size_t size = numbers.size();
    while (i < size)
    {
      Command c;
      c.type = cmd;
      c.data[0] = numbers[0];
      c.data[1] = numbers[1];
      cmds.push_back(c);
      i += 1;
    }
    return;
  }

  if (tolower(cmd) == 'z')
  {
    Command c;
    c.type = cmd;
    cmds.push_back(c);
    return;
  }

  std::string s = "Unknown cmd " + cmd;
  SvgError x(s.c_str());
  throw(x);
 */

}

void SvgReader::ExpandCommands(const std::vector< std::vector<Command> > &subpaths,  Path &path)
{
  for (std::vector<Command> compressedSubpath :subpaths)
  {
    // add new subpath
    path.subpaths.push_back( std::vector<Command>());
    // get a reference
    std::vector<Command> &subpath = path.subpaths.back();
    // copy the cmds with repeating commands, grouping the numbers
    for (Command xCmd : compressedSubpath)
    {
      unsigned int numberCount = 0;
      if (tolower(xCmd.type) == 'c')
	numberCount = 6;
      if (tolower(xCmd.type) == 'm')
	numberCount = 2;
      if (tolower(xCmd.type) == 'l')
	numberCount = 2;
      if (tolower(xCmd.type) == 'v')
	numberCount = 1;
      if (tolower(xCmd.type) == 'h')
	numberCount = 1;
      if (tolower(xCmd.type) == 'z')
      {
        subpath.push_back(xCmd);
      }

      // group numbers together and repeat the command
      // for each group
      unsigned int n = 0;
      size_t size = xCmd.numbers.size();

      while(n < size)
      {
        subpath.push_back(Command());
        Command &cmd = subpath.back();
        cmd.type = xCmd.type;

	for(size_t i=0; i < numberCount; i++)
	{
	   cmd.numbers.push_back(xCmd.numbers[i+n]);
	}
        n += numberCount;
      }
    }
  }
}

void SvgReader::get_path_commands(const std::vector<std::string> &tokens, Path &path)
{
     std::vector <Command> cmds;

     std::string lookup = "cCmMlLvVhHzZ";
     char lastCmd = 'x';
     std::vector<double> numbers;

     for(std::string token: tokens)
     {
       // new command?
       if(lookup.find(token[0]) == std::string::npos)
       {
         // its just numbers
         std::cout << std::endl;
         std::vector<std::string> numberStrs;
         split(token, ',', numberStrs);
         for(std::string numberStr : numberStrs)
         {
           double f = atof(numberStr.c_str());
           numbers.push_back(f);
         }
       }
       else
       {

         if(lastCmd != 'x')
         {
           Command c;
           c.type = lastCmd;
           c.numbers = numbers;
           cmds.push_back(c);
         }

         // its new command
         lastCmd = token[0];
         numbers.resize(0);
       }
     }
     // the last command
     if(lastCmd != 'x')
     {
       Command c;
       c.type = lastCmd;
       c.numbers = numbers;
       cmds.push_back(c);
     }
    // split the commands into sub_paths
    std::vector< std::vector< Command> > subpaths;
    this->SplitSubpaths(cmds, subpaths);

    this->ExpandCommands(subpaths, path );

//    for (std::vector<Command> subpath : subpaths)
//    {
//      std::vector<Command> s;
//      path.subpaths.push_back(s);
//    }

}

void SvgReader::get_path_attribs(TiXmlElement* pElement, Path &path)
{
    if ( !pElement ) return;

    TiXmlAttribute* pAttrib=pElement->FirstAttribute();
    while (pAttrib)
    {
        std::string name = lowercase(pAttrib->Name());
        std::string value= lowercase(pAttrib->Value());
        if (name == "style")
        {
            path.style = value;
        }
        if (name == "id")
        {
            path.id = value;
        }
        if (name == "d")
        {
            using namespace std;
            // this attribute contains a list of coordinates
            std::vector<std::string> tokens;
            split(value, ' ', tokens);
            get_path_commands(tokens, path);

        }
        // int ival;
        // double dval;
        // if (pAttrib->QueryIntValue(&ival)==TIXML_SUCCESS)    printf( " int=%d", ival);
        // if (pAttrib->QueryDoubleValue(&dval)==TIXML_SUCCESS) printf( " d=%1.1f", dval);
        pAttrib=pAttrib->Next();
    }
}

void SvgReader::get_svg_paths(TiXmlNode* pParent, std::vector<Path> &paths)
{
    if ( !pParent ) return;

    TiXmlNode* pChild;
    TiXmlText* pText;
    int t = pParent->Type();
    int num;
    std::string name;
    switch ( t )
    {
      case TiXmlNode::TINYXML_ELEMENT:
        name = lowercase(pParent->Value());
        if (name == "path")
        {
          Path p;
          get_path_attribs(pParent->ToElement(), p);
          paths.push_back(p);
        }
        break;

     default:
        break;
   }

  for ( pChild = pParent->FirstChild(); pChild != 0; pChild = pChild->NextSibling())
  {
      get_svg_paths( pChild, paths );
  }
}

// load the named file and dump its structure to STDOUT
void SvgReader::Parse(const char* pFilename, std::vector<Path> &paths)
{
    TiXmlDocument doc(pFilename);
    bool loadOkay = doc.LoadFile();
    if (!loadOkay)
    {
      std::ostringstream os;
      os << "Failed to load file " <<  pFilename;
      SvgError x(os.str());
      throw x;
    }

  get_svg_paths( &doc, paths);

}

void SvgReader::Dump_paths(const std::vector<Path> paths ) const
{
  std::cout << "PATHS: " << std::endl;
  for (Path path : paths)
  {
    std::cout << " -" << path.id << " " << path.style << std::endl;
    for (std::vector<Command> subpath : path.subpaths)
    {
      std::cout << "   subpath (" << subpath.size() << " cmds)" << std::endl;
      for (Command cmd: subpath)
      {
        std::cout << "    " << cmd.tostr() << std::endl;
      }
    }
  }
}

// ----------------------------------------------------------------------
// main() for printing files named on the command line
// ----------------------------------------------------------------------
int main(int argc, char* argv[])
{
    std::vector<Path> paths;

    for (int i=1; i<argc; i++)
    {
      std::cout << "=========\nFILE: " << argv[i] << std::endl;
      std::vector<Path> paths;

      SvgReader svg;
      svg.Parse(argv[i], paths);
      svg.Dump_paths(paths);
    }

    return 0;
}

<commit_msg>ready to interpolate<commit_after>#include <stdlib.h>
#include <exception>
#include <sstream>
#include <string>
#include <algorithm>
#include <vector>
#include <iostream>
#include "tinyxml.h"

class SvgError: public std::runtime_error
{ public: SvgError(const std::string& what_arg): std::runtime_error(what_arg){};};

struct Point
{
    double x;
    double y;
};

struct Command
{
   char type;
   std::vector<double> numbers;

   std::string tostr()
   {
     std::ostringstream os;
     os << type << "[";
     for (double d : numbers)
     {
       os << d << ", ";
     }
     os << "]";
     return os.str();
   }
};

struct Path
{
   std::string id;
   std::string style;

   std::vector< std::vector<Command> > subpaths;

   std::vector< std::vector<Point> > polylines;
};

class SvgReader
{

  public: SvgReader(){}

  public: void Parse(const char*path, std::vector<Path> &paths);
  public: void Dump_paths(const std::vector<Path> paths ) const;

  private: void make_commands(char cmd, const std::vector<double> &numbers, std::vector<Command> &cmds);
  private: void get_path_commands(const std::vector<std::string> &tokens, Path &path);
  private: void get_path_attribs(TiXmlElement* pElement, Path &path);
  private: void get_svg_paths(TiXmlNode* pParent, std::vector<Path> &paths);

  private: void ExpandCommands(const std::vector< std::vector<Command> > &subpaths, Path &path);
  private: void SplitSubpaths(const std::vector<Command> cmds, std::vector< std::vector<Command> > &split_cmds);
  private: void PathToPoints(const Path &path, double resolution, std::vector< std::vector<Point> > &polys);

  private: void SubpathToPolyline(const std::vector<Command> &subpath, std::vector<Point> &polyline);

};

std::string lowercase(const std::string& in)
{
  std::string out = in;
  std::transform(out.begin(), out.end(), out.begin(), ::tolower);
  return out;
}

std::string lowercase(const char* in)
{
  std::string ins = in;
  return lowercase(ins);
}

std::vector<std::string> &split(const std::string &s, char delim, std::vector<std::string> &elems) {
    std::stringstream ss(s);
    std::string item;
    while (std::getline(ss, item, delim)) {
        elems.push_back(item);
    }
    return elems;
}

Point bezierInterpolate(double t, const Point &p0, const Point &p1, const Point &p2, const Point &p3)
{
  double t_1 = 1.0 - t;
  double t_1_2 = t_1 * t_1;
  double t_1_3 = t_1_2 * t_1;
  double t2 = t * t;
  double t3 = t2 * t;

  Point p;
  p.x = t_1_3 * p0.x + 3 * t *  t_1_2 * p1.x + 3 * t2 * t_1 * p2.x + t3 * p3.x;
  p.y = t_1_3 * p0.y + 3 * t *  t_1_2 * p1.y + 3 * t2 * t_1 * p2.y + t3 * p3.y;

  return p;
}

double Distance(const Point &p0, const Point &p1)
{
  double xx = (p0.x - p1.x) *  (p0.x - p1.x);
  double yy = (p0.y - p1.y) *  (p0.y - p1.y);
  return sqrt(xx + yy);
}

unsigned int GetStepCount(const Point &p0, const Point &p1, const Point &p2, const Point &p3, double res)
{
  double d = Distance(p0,p1) + Distance(p1,p2) + Distance(p2, p3);
  double steps = res / d;
  return (unsigned int) fabs(steps);
}

void SvgReader::SubpathToPolyline(const std::vector<Command> &subpath, std::vector<Point> &polyline)
{
  for (Command cmd: subpath)
  {
    if (cmd.type == 'm' || cmd.type == 'l')
    {
       todo
    }
  }
}

void SvgReader::SplitSubpaths(const std::vector<Command> cmds, std::vector< std::vector<Command> > &subpaths)
{
  if(cmds.size() ==0)
  {
    std::ostringstream os;
    os << "Path has no commands";
    SvgError x(os.str());
    throw x;
  }

  for(Command cmd: cmds)
  {
    if( tolower(cmd.type) == 'm')
    {
      // the path contains a subpath
      std::vector<Command> sub;
      subpaths.push_back(sub);
    }
    // get a reference to the latest subpath
    std::vector<Command> &subpath = subpaths.back();
    // give the cmd to the latest
    subpath.push_back(cmd);
  }
}

void SvgReader::make_commands(char cmd, const std::vector<double> &numbers, std::vector<Command> &cmds)
{
  if(cmd != 'x')
  {
    Command c;
    c.type = cmd;
    c.numbers = numbers;
    cmds.push_back(c);
  }

}

void SvgReader::ExpandCommands(const std::vector< std::vector<Command> > &subpaths,  Path &path)
{
  for (std::vector<Command> compressedSubpath :subpaths)
  {
    // add new subpath
    path.subpaths.push_back( std::vector<Command>());
    // get a reference
    std::vector<Command> &subpath = path.subpaths.back();
    // copy the cmds with repeating commands, grouping the numbers
    for (Command xCmd : compressedSubpath)
    {
      unsigned int numberCount = 0;
      if (tolower(xCmd.type) == 'c')
	numberCount = 6;
      if (tolower(xCmd.type) == 'm')
	numberCount = 2;
      if (tolower(xCmd.type) == 'l')
	numberCount = 2;
      if (tolower(xCmd.type) == 'v')
	numberCount = 1;
      if (tolower(xCmd.type) == 'h')
	numberCount = 1;
      if (tolower(xCmd.type) == 'z')
      {
        subpath.push_back(xCmd);
      }

      // group numbers together and repeat the command
      // for each group
      unsigned int n = 0;
      size_t size = xCmd.numbers.size();

      while(n < size)
      {
        subpath.push_back(Command());
        Command &cmd = subpath.back();
        cmd.type = xCmd.type;

     	for(size_t i=0; i < numberCount; i++)
	    {
	      cmd.numbers.push_back(xCmd.numbers[i+n]);
	    }
        n += numberCount;
      }
    }
  }
}

void SvgReader::get_path_commands(const std::vector<std::string> &tokens, Path &path)
{
     std::vector <Command> cmds;

     std::string lookup = "cCmMlLvVhHzZ";
     char lastCmd = 'x';
     std::vector<double> numbers;

     for(std::string token: tokens)
     {
       // new command?
       if(lookup.find(token[0]) == std::string::npos)
       {
         // its just numbers
         std::cout << std::endl;
         std::vector<std::string> numberStrs;
         split(token, ',', numberStrs);
         for(std::string numberStr : numberStrs)
         {
           double f = atof(numberStr.c_str());
           numbers.push_back(f);
         }
       }
       else
       {

         if(lastCmd != 'x')
         {
           Command c;
           c.type = lastCmd;
           c.numbers = numbers;
           cmds.push_back(c);
         }

         // its new command
         lastCmd = token[0];
         numbers.resize(0);
       }
     }
     // the last command
     if(lastCmd != 'x')
     {
       Command c;
       c.type = lastCmd;
       c.numbers = numbers;
       cmds.push_back(c);
     }
    // split the commands into sub_paths
    std::vector< std::vector< Command> > subpaths;
    this->SplitSubpaths(cmds, subpaths);

    this->ExpandCommands(subpaths, path );

    for (std::vector<Command> subpath : subpaths)
    {
        path.polylines.push_back(std::vector<Point>());
        std::vector<Point> &polyline = path.polylines.back();
        this->SubpathToPolyline(subpath, polyline);
    }

}

void SvgReader::get_path_attribs(TiXmlElement* pElement, Path &path)
{
    if ( !pElement ) return;

    TiXmlAttribute* pAttrib=pElement->FirstAttribute();
    while (pAttrib)
    {
        std::string name = lowercase(pAttrib->Name());
        std::string value= lowercase(pAttrib->Value());
        if (name == "style")
        {
            path.style = value;
        }
        if (name == "id")
        {
            path.id = value;
        }
        if (name == "d")
        {
            using namespace std;
            // this attribute contains a list of coordinates
            std::vector<std::string> tokens;
            split(value, ' ', tokens);
            get_path_commands(tokens, path);

        }
        // int ival;
        // double dval;
        // if (pAttrib->QueryIntValue(&ival)==TIXML_SUCCESS)    printf( " int=%d", ival);
        // if (pAttrib->QueryDoubleValue(&dval)==TIXML_SUCCESS) printf( " d=%1.1f", dval);
        pAttrib=pAttrib->Next();
    }
}

void SvgReader::get_svg_paths(TiXmlNode* pParent, std::vector<Path> &paths)
{
    if ( !pParent ) return;

    TiXmlNode* pChild;
    TiXmlText* pText;
    int t = pParent->Type();
    int num;
    std::string name;
    switch ( t )
    {
      case TiXmlNode::TINYXML_ELEMENT:
        name = lowercase(pParent->Value());
        if (name == "path")
        {
          Path p;
          get_path_attribs(pParent->ToElement(), p);
          paths.push_back(p);
        }
        break;

     default:
        break;
   }

  for ( pChild = pParent->FirstChild(); pChild != 0; pChild = pChild->NextSibling())
  {
      get_svg_paths( pChild, paths );
  }
}

// load the named file and dump its structure to STDOUT
void SvgReader::Parse(const char* pFilename, std::vector<Path> &paths)
{
    TiXmlDocument doc(pFilename);
    bool loadOkay = doc.LoadFile();
    if (!loadOkay)
    {
      std::ostringstream os;
      os << "Failed to load file " <<  pFilename;
      SvgError x(os.str());
      throw x;
    }

  get_svg_paths( &doc, paths);

}

void SvgReader::Dump_paths(const std::vector<Path> paths ) const
{
  std::cout << "var svg = [];" << std::endl;
  for (Path path : paths)
  {
    std::cout << "svg.push({name:\"" << path.id <<  "\", subpaths:[], style: " << path.style << "}); " << std::endl;
    // std::cout << " -" << path.id << " " << path.style << std::endl;
    for (std::vector<Command> subpath : path.subpaths)
    {
      std::cout << "//  subpath (" << subpath.size() << " cmds)" << std::endl;
      for (Command cmd: subpath)
      {
        std::cout << "//    " << cmd.tostr() << std::endl;

      }
    }
  }
}

// ----------------------------------------------------------------------
// main() for printing files named on the command line
// ----------------------------------------------------------------------
int main(int argc, char* argv[])
{
    std::vector<Path> paths;

    for (int i=1; i<argc; i++)
    {
      std::cout << "=========\nFILE: " << argv[i] << std::endl;
      std::vector<Path> paths;

      SvgReader svg;
      svg.Parse(argv[i], paths);
      svg.Dump_paths(paths);
    }

    return 0;
}

<|endoftext|>


<commit_before>// Copyright (c) 2009-2010 Satoshi Nakamoto
// Copyright (c) 2009-2014 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 "random.h"

#include "crypto/sha512.h"
#include "support/cleanse.h"
#ifdef WIN32
#include "compat.h" // for Windows API
#include <wincrypt.h>
#endif
#include "util.h"             // for LogPrint()
#include "utilstrencodings.h" // for GetTime()

#include <stdlib.h>
#include <limits>

#ifndef WIN32
#include <sys/time.h>
#endif

#ifdef HAVE_SYS_GETRANDOM
#include <sys/syscall.h>
#include <linux/random.h>
#endif
#ifdef HAVE_GETENTROPY
#include <unistd.h>
#endif
#ifdef HAVE_SYSCTL_ARND
#include <sys/sysctl.h>
#endif

#include <mutex>

#include <openssl/err.h>
#include <openssl/rand.h>

static void RandFailure()
{
    LogPrintf("Failed to read randomness, aborting\n");
    abort();
}

static inline int64_t GetPerformanceCounter()
{
    int64_t nCounter = 0;
#ifdef WIN32
    QueryPerformanceCounter((LARGE_INTEGER*)&nCounter);
#else
    timeval t;
    gettimeofday(&t, NULL);
    nCounter = (int64_t)(t.tv_sec * 1000000 + t.tv_usec);
#endif
    return nCounter;
}

void RandAddSeed()
{
    // Seed with CPU performance counter
    int64_t nCounter = GetPerformanceCounter();
    RAND_add(&nCounter, sizeof(nCounter), 1.5);
    memory_cleanse((void*)&nCounter, sizeof(nCounter));
}

static void RandAddSeedPerfmon()
{
    RandAddSeed();

#ifdef WIN32
    // Don't need this on Linux, OpenSSL automatically uses /dev/urandom
    // Seed with the entire set of perfmon data

    // This can take up to 2 seconds, so only do it every 10 minutes
    static int64_t nLastPerfmon;
    if (GetTime() < nLastPerfmon + 10 * 60)
        return;
    nLastPerfmon = GetTime();

    std::vector<unsigned char> vData(250000, 0);
    long ret = 0;
    unsigned long nSize = 0;
    const size_t nMaxSize = 10000000; // Bail out at more than 10MB of performance data
    while (true) {
        nSize = vData.size();
        ret = RegQueryValueExA(HKEY_PERFORMANCE_DATA, "Global", NULL, NULL, vData.data(), &nSize);
        if (ret != ERROR_MORE_DATA || vData.size() >= nMaxSize)
            break;
        vData.resize(std::max((vData.size() * 3) / 2, nMaxSize)); // Grow size of buffer exponentially
    }
    RegCloseKey(HKEY_PERFORMANCE_DATA);
    if (ret == ERROR_SUCCESS) {
        RAND_add(vData.data(), nSize, nSize / 100.0);
        memory_cleanse(vData.data(), nSize);
        LogPrint("rand", "%s: %lu bytes\n", __func__, nSize);
    } else {
        static bool warned = false; // Warn only once
        if (!warned) {
            LogPrintf("%s: Warning: RegQueryValueExA(HKEY_PERFORMANCE_DATA) failed with code %i\n", __func__, ret);
            warned = true;
        }
    }
#endif
}

#ifndef WIN32
/** Fallback: get 32 bytes of system entropy from /dev/urandom. The most
 * compatible way to get cryptographic randomness on UNIX-ish platforms.
 */
void GetDevURandom(unsigned char *ent32)
{
    int f = open("/dev/urandom", O_RDONLY);
    if (f == -1) {
        RandFailure();
    }
    int have = 0;
    do {
        ssize_t n = read(f, ent32 + have, NUM_OS_RANDOM_BYTES - have);
        if (n <= 0 || n + have > NUM_OS_RANDOM_BYTES) {
            RandFailure();
        }
        have += n;
    } while (have < NUM_OS_RANDOM_BYTES);
    close(f);
}
#endif

/** Get 32 bytes of system entropy. */
void GetOSRand(unsigned char *ent32)
{
#if defined(WIN32)
    HCRYPTPROV hProvider;
    int ret = CryptAcquireContextW(&hProvider, NULL, NULL, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT);
    if (!ret) {
        RandFailure();
    }
    ret = CryptGenRandom(hProvider, NUM_OS_RANDOM_BYTES, ent32);
    if (!ret) {
        RandFailure();
    }
    CryptReleaseContext(hProvider, 0);
#elif defined(HAVE_SYS_GETRANDOM)
    /* Linux. From the getrandom(2) man page:
     * "If the urandom source has been initialized, reads of up to 256 bytes
     * will always return as many bytes as requested and will not be
     * interrupted by signals."
     */
    int rv = syscall(SYS_getrandom, ent32, NUM_OS_RANDOM_BYTES, 0);
    if (rv != NUM_OS_RANDOM_BYTES) {
        if (rv < 0 && errno == ENOSYS) {
            /* Fallback for kernel <3.17: the return value will be -1 and errno
             * ENOSYS if the syscall is not available, in that case fall back
             * to /dev/urandom.
             */
            GetDevURandom(ent32);
        } else {
            RandFailure();
        }
    }
#elif defined(HAVE_GETENTROPY) && defined(__OpenBSD__)
    /* On OpenBSD this can return up to 256 bytes of entropy, will return an
     * error if more are requested.
     * The call cannot return less than the requested number of bytes.
       getentropy is explicitly limited to openbsd here, as a similar (but not
       the same) function may exist on other platforms via glibc.
     */
    if (getentropy(ent32, NUM_OS_RANDOM_BYTES) != 0) {
        RandFailure();
    }
#elif defined(HAVE_SYSCTL_ARND)
    /* FreeBSD and similar. It is possible for the call to return less
     * bytes than requested, so need to read in a loop.
     */
    static const int name[2] = {CTL_KERN, KERN_ARND};
    int have = 0;
    do {
        size_t len = NUM_OS_RANDOM_BYTES - have;
        if (sysctl(name, ARRAYLEN(name), ent32 + have, &len, NULL, 0) != 0) {
            RandFailure();
        }
        have += len;
    } while (have < NUM_OS_RANDOM_BYTES);
#else
    /* Fall back to /dev/urandom if there is no specific method implemented to
     * get system entropy for this OS.
     */
    GetDevURandom(ent32);
#endif
}

void GetRandBytes(unsigned char* buf, int num)
{
    if (RAND_bytes(buf, num) != 1) {
        RandFailure();
    }
}

static std::mutex cs_rng_state;
static unsigned char rng_state[32] = {0};
static uint64_t rng_counter = 0;

void GetStrongRandBytes(unsigned char* out, int num)
{
    assert(num <= 32);
    CSHA512 hasher;
    unsigned char buf[64];

    // First source: OpenSSL's RNG
    RandAddSeedPerfmon();
    GetRandBytes(buf, 32);
    hasher.Write(buf, 32);

    // Second source: OS RNG
    GetOSRand(buf);
    hasher.Write(buf, 32);

    // Combine with and update state
    {
        std::unique_lock<std::mutex> lock(cs_rng_state);
        hasher.Write(rng_state, sizeof(rng_state));
        hasher.Write((const unsigned char*)&rng_counter, sizeof(rng_counter));
        ++rng_counter;
        hasher.Finalize(buf);
        memcpy(rng_state, buf + 32, 32);
    }

    // Produce output
    memcpy(out, buf, num);
    memory_cleanse(buf, 64);
}

uint64_t GetRand(uint64_t nMax)
{
    if (nMax == 0)
        return 0;

    // The range of the random source must be a multiple of the modulus
    // to give every possible output value an equal possibility
    uint64_t nRange = (std::numeric_limits<uint64_t>::max() / nMax) * nMax;
    uint64_t nRand = 0;
    do {
        GetRandBytes((unsigned char*)&nRand, sizeof(nRand));
    } while (nRand >= nRange);
    return (nRand % nMax);
}

int GetRandInt(int nMax)
{
    return GetRand(nMax);
}

uint256 GetRandHash()
{
    uint256 hash;
    GetRandBytes((unsigned char*)&hash, sizeof(hash));
    return hash;
}

void FastRandomContext::RandomSeed()
{
    uint256 seed = GetRandHash();
    rng.SetKey(seed.begin(), 32);
    requires_seed = false;
}

FastRandomContext::FastRandomContext(const uint256& seed) : requires_seed(false), bytebuf_size(0), bitbuf_size(0)
{
    rng.SetKey(seed.begin(), 32);
}

bool Random_SanityCheck()
{
    /* This does not measure the quality of randomness, but it does test that
     * OSRandom() overwrites all 32 bytes of the output given a maximum
     * number of tries.
     */
    static const ssize_t MAX_TRIES = 1024;
    uint8_t data[NUM_OS_RANDOM_BYTES];
    bool overwritten[NUM_OS_RANDOM_BYTES] = {}; /* Tracks which bytes have been overwritten at least once */
    int num_overwritten;
    int tries = 0;
    /* Loop until all bytes have been overwritten at least once, or max number tries reached */
    do {
        memset(data, 0, NUM_OS_RANDOM_BYTES);
        GetOSRand(data);
        for (int x=0; x < NUM_OS_RANDOM_BYTES; ++x) {
            overwritten[x] |= (data[x] != 0);
        }

        num_overwritten = 0;
        for (int x=0; x < NUM_OS_RANDOM_BYTES; ++x) {
            if (overwritten[x]) {
                num_overwritten += 1;
            }
        }

        tries += 1;
    } while (num_overwritten < NUM_OS_RANDOM_BYTES && tries < MAX_TRIES);
    return (num_overwritten == NUM_OS_RANDOM_BYTES); /* If this failed, bailed out after too many tries */
}

FastRandomContext::FastRandomContext(bool fDeterministic) : requires_seed(!fDeterministic), bytebuf_size(0), bitbuf_size(0)
{
    if (!fDeterministic) {
        return;
    }
    uint256 seed;
    rng.SetKey(seed.begin(), 32);
}
<commit_msg>Use hardware timestamps in RNG seeding<commit_after>// Copyright (c) 2009-2010 Satoshi Nakamoto
// Copyright (c) 2009-2014 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 "random.h"

#include "crypto/sha512.h"
#include "support/cleanse.h"
#ifdef WIN32
#include "compat.h" // for Windows API
#include <wincrypt.h>
#endif
#include "util.h"             // for LogPrint()
#include "utilstrencodings.h" // for GetTime()

#include <stdlib.h>
#include <limits>
#include <chrono>

#ifndef WIN32
#include <sys/time.h>
#endif

#ifdef HAVE_SYS_GETRANDOM
#include <sys/syscall.h>
#include <linux/random.h>
#endif
#ifdef HAVE_GETENTROPY
#include <unistd.h>
#endif
#ifdef HAVE_SYSCTL_ARND
#include <sys/sysctl.h>
#endif

#include <mutex>

#include <openssl/err.h>
#include <openssl/rand.h>

static void RandFailure()
{
    LogPrintf("Failed to read randomness, aborting\n");
    abort();
}

static inline int64_t GetPerformanceCounter()
{
    // Read the hardware time stamp counter when available.
    // See https://en.wikipedia.org/wiki/Time_Stamp_Counter for more information.
#if defined(_MSC_VER) && (defined(_M_IX86) || defined(_M_X64))
    return __rdtsc();
#elif !defined(_MSC_VER) && defined(__i386__)
    uint64_t r = 0;
    __asm__ volatile ("rdtsc" : "=A"(r)); // Constrain the r variable to the eax:edx pair.
    return r;
#elif !defined(_MSC_VER) && (defined(__x86_64__) || defined(__amd64__))
    uint64_t r1 = 0, r2 = 0;
    __asm__ volatile ("rdtsc" : "=a"(r1), "=d"(r2)); // Constrain r1 to rax and r2 to rdx.
    return (r2 << 32) | r1;
#else
    // Fall back to using C++11 clock (usually microsecond or nanosecond precision)
    return std::chrono::high_resolution_clock::now().time_since_epoch().count();
#endif
}

void RandAddSeed()
{
    // Seed with CPU performance counter
    int64_t nCounter = GetPerformanceCounter();
    RAND_add(&nCounter, sizeof(nCounter), 1.5);
    memory_cleanse((void*)&nCounter, sizeof(nCounter));
}

static void RandAddSeedPerfmon()
{
    RandAddSeed();

#ifdef WIN32
    // Don't need this on Linux, OpenSSL automatically uses /dev/urandom
    // Seed with the entire set of perfmon data

    // This can take up to 2 seconds, so only do it every 10 minutes
    static int64_t nLastPerfmon;
    if (GetTime() < nLastPerfmon + 10 * 60)
        return;
    nLastPerfmon = GetTime();

    std::vector<unsigned char> vData(250000, 0);
    long ret = 0;
    unsigned long nSize = 0;
    const size_t nMaxSize = 10000000; // Bail out at more than 10MB of performance data
    while (true) {
        nSize = vData.size();
        ret = RegQueryValueExA(HKEY_PERFORMANCE_DATA, "Global", NULL, NULL, vData.data(), &nSize);
        if (ret != ERROR_MORE_DATA || vData.size() >= nMaxSize)
            break;
        vData.resize(std::max((vData.size() * 3) / 2, nMaxSize)); // Grow size of buffer exponentially
    }
    RegCloseKey(HKEY_PERFORMANCE_DATA);
    if (ret == ERROR_SUCCESS) {
        RAND_add(vData.data(), nSize, nSize / 100.0);
        memory_cleanse(vData.data(), nSize);
        LogPrint("rand", "%s: %lu bytes\n", __func__, nSize);
    } else {
        static bool warned = false; // Warn only once
        if (!warned) {
            LogPrintf("%s: Warning: RegQueryValueExA(HKEY_PERFORMANCE_DATA) failed with code %i\n", __func__, ret);
            warned = true;
        }
    }
#endif
}

#ifndef WIN32
/** Fallback: get 32 bytes of system entropy from /dev/urandom. The most
 * compatible way to get cryptographic randomness on UNIX-ish platforms.
 */
void GetDevURandom(unsigned char *ent32)
{
    int f = open("/dev/urandom", O_RDONLY);
    if (f == -1) {
        RandFailure();
    }
    int have = 0;
    do {
        ssize_t n = read(f, ent32 + have, NUM_OS_RANDOM_BYTES - have);
        if (n <= 0 || n + have > NUM_OS_RANDOM_BYTES) {
            RandFailure();
        }
        have += n;
    } while (have < NUM_OS_RANDOM_BYTES);
    close(f);
}
#endif

/** Get 32 bytes of system entropy. */
void GetOSRand(unsigned char *ent32)
{
#if defined(WIN32)
    HCRYPTPROV hProvider;
    int ret = CryptAcquireContextW(&hProvider, NULL, NULL, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT);
    if (!ret) {
        RandFailure();
    }
    ret = CryptGenRandom(hProvider, NUM_OS_RANDOM_BYTES, ent32);
    if (!ret) {
        RandFailure();
    }
    CryptReleaseContext(hProvider, 0);
#elif defined(HAVE_SYS_GETRANDOM)
    /* Linux. From the getrandom(2) man page:
     * "If the urandom source has been initialized, reads of up to 256 bytes
     * will always return as many bytes as requested and will not be
     * interrupted by signals."
     */
    int rv = syscall(SYS_getrandom, ent32, NUM_OS_RANDOM_BYTES, 0);
    if (rv != NUM_OS_RANDOM_BYTES) {
        if (rv < 0 && errno == ENOSYS) {
            /* Fallback for kernel <3.17: the return value will be -1 and errno
             * ENOSYS if the syscall is not available, in that case fall back
             * to /dev/urandom.
             */
            GetDevURandom(ent32);
        } else {
            RandFailure();
        }
    }
#elif defined(HAVE_GETENTROPY) && defined(__OpenBSD__)
    /* On OpenBSD this can return up to 256 bytes of entropy, will return an
     * error if more are requested.
     * The call cannot return less than the requested number of bytes.
       getentropy is explicitly limited to openbsd here, as a similar (but not
       the same) function may exist on other platforms via glibc.
     */
    if (getentropy(ent32, NUM_OS_RANDOM_BYTES) != 0) {
        RandFailure();
    }
#elif defined(HAVE_SYSCTL_ARND)
    /* FreeBSD and similar. It is possible for the call to return less
     * bytes than requested, so need to read in a loop.
     */
    static const int name[2] = {CTL_KERN, KERN_ARND};
    int have = 0;
    do {
        size_t len = NUM_OS_RANDOM_BYTES - have;
        if (sysctl(name, ARRAYLEN(name), ent32 + have, &len, NULL, 0) != 0) {
            RandFailure();
        }
        have += len;
    } while (have < NUM_OS_RANDOM_BYTES);
#else
    /* Fall back to /dev/urandom if there is no specific method implemented to
     * get system entropy for this OS.
     */
    GetDevURandom(ent32);
#endif
}

void GetRandBytes(unsigned char* buf, int num)
{
    if (RAND_bytes(buf, num) != 1) {
        RandFailure();
    }
}

static std::mutex cs_rng_state;
static unsigned char rng_state[32] = {0};
static uint64_t rng_counter = 0;

void GetStrongRandBytes(unsigned char* out, int num)
{
    assert(num <= 32);
    CSHA512 hasher;
    unsigned char buf[64];

    // First source: OpenSSL's RNG
    RandAddSeedPerfmon();
    GetRandBytes(buf, 32);
    hasher.Write(buf, 32);

    // Second source: OS RNG
    GetOSRand(buf);
    hasher.Write(buf, 32);

    // Combine with and update state
    {
        std::unique_lock<std::mutex> lock(cs_rng_state);
        hasher.Write(rng_state, sizeof(rng_state));
        hasher.Write((const unsigned char*)&rng_counter, sizeof(rng_counter));
        ++rng_counter;
        hasher.Finalize(buf);
        memcpy(rng_state, buf + 32, 32);
    }

    // Produce output
    memcpy(out, buf, num);
    memory_cleanse(buf, 64);
}

uint64_t GetRand(uint64_t nMax)
{
    if (nMax == 0)
        return 0;

    // The range of the random source must be a multiple of the modulus
    // to give every possible output value an equal possibility
    uint64_t nRange = (std::numeric_limits<uint64_t>::max() / nMax) * nMax;
    uint64_t nRand = 0;
    do {
        GetRandBytes((unsigned char*)&nRand, sizeof(nRand));
    } while (nRand >= nRange);
    return (nRand % nMax);
}

int GetRandInt(int nMax)
{
    return GetRand(nMax);
}

uint256 GetRandHash()
{
    uint256 hash;
    GetRandBytes((unsigned char*)&hash, sizeof(hash));
    return hash;
}

void FastRandomContext::RandomSeed()
{
    uint256 seed = GetRandHash();
    rng.SetKey(seed.begin(), 32);
    requires_seed = false;
}

FastRandomContext::FastRandomContext(const uint256& seed) : requires_seed(false), bytebuf_size(0), bitbuf_size(0)
{
    rng.SetKey(seed.begin(), 32);
}

bool Random_SanityCheck()
{
    /* This does not measure the quality of randomness, but it does test that
     * OSRandom() overwrites all 32 bytes of the output given a maximum
     * number of tries.
     */
    static const ssize_t MAX_TRIES = 1024;
    uint8_t data[NUM_OS_RANDOM_BYTES];
    bool overwritten[NUM_OS_RANDOM_BYTES] = {}; /* Tracks which bytes have been overwritten at least once */
    int num_overwritten;
    int tries = 0;
    /* Loop until all bytes have been overwritten at least once, or max number tries reached */
    do {
        memset(data, 0, NUM_OS_RANDOM_BYTES);
        GetOSRand(data);
        for (int x=0; x < NUM_OS_RANDOM_BYTES; ++x) {
            overwritten[x] |= (data[x] != 0);
        }

        num_overwritten = 0;
        for (int x=0; x < NUM_OS_RANDOM_BYTES; ++x) {
            if (overwritten[x]) {
                num_overwritten += 1;
            }
        }

        tries += 1;
    } while (num_overwritten < NUM_OS_RANDOM_BYTES && tries < MAX_TRIES);
    return (num_overwritten == NUM_OS_RANDOM_BYTES); /* If this failed, bailed out after too many tries */
}

FastRandomContext::FastRandomContext(bool fDeterministic) : requires_seed(!fDeterministic), bytebuf_size(0), bitbuf_size(0)
{
    if (!fDeterministic) {
        return;
    }
    uint256 seed;
    rng.SetKey(seed.begin(), 32);
}
<|endoftext|>