<commit_before>/********************************************************************
* Description: emcops.cc
*   Initialization and other ad hoc functions for NML. This complements
*   the auto-generated emc.cc, which contains all the rote update
*   methods for the message classes.
*
*   Derived from a work by Fred Proctor & Will Shackleford
*
* Author:
* License: GPL Version 2
* System: Linux
*
* Copyright (c) 2004 All rights reserved.
*
* Last change:
********************************************************************/

#include "emc.hh"
#include "emc_nml.hh"

EMC_AXIS_STAT::EMC_AXIS_STAT():
EMC_AXIS_STAT_MSG(EMC_AXIS_STAT_TYPE, sizeof(EMC_AXIS_STAT))
{
    axisType = EMC_AXIS_LINEAR;
    units = 1.0;
    backlash = 0.0;
    maxError = 0.0;
    minPositionLimit = -1.0;
    maxPositionLimit = 1.0;
    maxFerror = 1.0;
    ferrorCurrent = 0.0;
    ferrorHighMark = 0.0;
    output = 0.0;
    input = 0.0;
    inpos = 1;
    homing = 0;
    homed = 0;
    enabled = 0;
    fault = 0;
    minSoftLimit = 0;
    maxSoftLimit = 0;
    minHardLimit = 0;
    maxHardLimit = 0;
    overrideLimits = 0;
}

EMC_TRAJ_STAT::EMC_TRAJ_STAT():
EMC_TRAJ_STAT_MSG(EMC_TRAJ_STAT_TYPE, sizeof(EMC_TRAJ_STAT))
{
    linearUnits = 1.0;
    angularUnits = 1.0;
    cycleTime = 0.0;
    axes = 1;
    axis_mask = 1;
    mode = EMC_TRAJ_MODE_FREE;
    enabled = 0;
    inpos = 1;
    queue = 0;
    activeQueue = 0;
    queueFull = 0;
    id = 0;
    paused = 0;
    scale = 0.0;
    spindle_scale = 0.0;

    ZERO_EMC_POSE(position);
    ZERO_EMC_POSE(actualPosition);

    velocity = 1.0;
    acceleration = 1.0;
    maxVelocity = 1.0;
    maxAcceleration = 1.0;

    ZERO_EMC_POSE(probedPosition);
    probe_tripped = 0;
    probing = 0;
    probeval = 0;

    ZERO_EMC_POSE(dtg);
    distance_to_go = 0.0;
    kinematics_type = 0;
    motion_type = 0;
    current_vel = 0.0;
    feed_override_enabled = 0;
    spindle_override_enabled = 0;
    adaptive_feed_enabled = 0;
    feed_hold_enabled = 0;
    delayLeft = 0.0;
}

EMC_MOTION_STAT::EMC_MOTION_STAT():
EMC_MOTION_STAT_MSG(EMC_MOTION_STAT_TYPE, sizeof(EMC_MOTION_STAT))
{
    int i;

    for (i = 0; i < EMC_MAX_DIO; i++)
	synch_di[i] = 0;

    for (i = 0; i < EMC_MAX_AIO; i++)
	analog_input[i] = 0;

    debug = 0;
};

EMC_TASK_STAT::EMC_TASK_STAT():
EMC_TASK_STAT_MSG(EMC_TASK_STAT_TYPE, sizeof(EMC_TASK_STAT))
{
    int t;

    mode = EMC_TASK_MODE_MANUAL;
    state = EMC_TASK_STATE_ESTOP;
    execState = EMC_TASK_EXEC_DONE;
    interpState = EMC_TASK_INTERP_IDLE;
    motionLine = 0;
    currentLine = 0;
    readLine = 0;
    optional_stop_state = OFF;
    block_delete_state = OFF;
    input_timeout = OFF;
    file[0] = 0;
    command[0] = 0;

    ZERO_EMC_POSE(origin);
    ZERO_EMC_POSE(toolOffset);

    rotation_xy = 0.0;
    tloIsAlongW = OFF;

    for (t = 0; t < ACTIVE_G_CODES; t++)
	activeGCodes[t] = -1;
    for (t = 0; t < ACTIVE_M_CODES; t++)
	activeMCodes[t] = -1;
    for (t = 0; t < ACTIVE_SETTINGS; t++)
	activeSettings[t] = 0.0;

    programUnits = CANON_UNITS_MM;
    interpreter_errcode = 0;
    task_paused = 0;
}

EMC_TOOL_STAT::EMC_TOOL_STAT():
EMC_TOOL_STAT_MSG(EMC_TOOL_STAT_TYPE, sizeof(EMC_TOOL_STAT))
{
    int t;

    toolPrepped = 0;
    toolInSpindle = 0;

    for (t = 0; t <= CANON_TOOL_MAX; t++) {
	toolTable[t].id = 0;
	toolTable[t].xoffset = 0.0;
	toolTable[t].zoffset = 0.0;
	toolTable[t].diameter = 0.0;
	toolTable[t].orientation = 0;
	toolTable[t].frontangle = 0.0;
	toolTable[t].backangle = 0.0;
    }
}

EMC_AUX_STAT::EMC_AUX_STAT():
EMC_AUX_STAT_MSG(EMC_AUX_STAT_TYPE, sizeof(EMC_AUX_STAT))
{
    int t;

    estop = 1;

    for (t = 0; t < EMC_AUX_MAX_DOUT; t++) {
	dout[t] = 0;
    }

    for (t = 0; t < EMC_AUX_MAX_DIN; t++) {
	din[t] = 0;
    }

    for (t = 0; t < EMC_AUX_MAX_AOUT; t++) {
	aout[t] = 0;
    }

    for (t = 0; t < EMC_AUX_MAX_AIN; t++) {
	ain[t] = 0;
    }
}

EMC_SPINDLE_STAT::EMC_SPINDLE_STAT():
EMC_SPINDLE_STAT_MSG(EMC_SPINDLE_STAT_TYPE, sizeof(EMC_SPINDLE_STAT))
{
    speed = 0.0;
    direction = 0;
    brake = 1;
    increasing = 0;
    enabled = 0;
}

EMC_COOLANT_STAT::EMC_COOLANT_STAT():EMC_COOLANT_STAT_MSG(EMC_COOLANT_STAT_TYPE,
		     sizeof
		     (EMC_COOLANT_STAT))
{
    mist = 0;
    flood = 0;
}

EMC_LUBE_STAT::EMC_LUBE_STAT():
EMC_LUBE_STAT_MSG(EMC_LUBE_STAT_TYPE, sizeof(EMC_LUBE_STAT))
{
    on = 0;
    level = 1;
}

// overload = , since class has array elements
EMC_TOOL_STAT EMC_TOOL_STAT::operator =(EMC_TOOL_STAT s)
{
    int t;

    toolPrepped = s.toolPrepped;
    toolInSpindle = s.toolInSpindle;

    for (t = 0; t <= CANON_TOOL_MAX; t++) {
	toolTable[t].id = s.toolTable[t].id;
	toolTable[t].xoffset = s.toolTable[t].xoffset;
	toolTable[t].zoffset = s.toolTable[t].zoffset;
	toolTable[t].diameter = s.toolTable[t].diameter;
	toolTable[t].frontangle = s.toolTable[t].frontangle;
	toolTable[t].backangle = s.toolTable[t].backangle;
	toolTable[t].orientation = s.toolTable[t].orientation;
    }

    return s;
}

// overload = , since class has array elements
EMC_AUX_STAT EMC_AUX_STAT::operator =(EMC_AUX_STAT s)
{
    int t;

    estop = s.estop;

    for (t = 0; t < EMC_AUX_MAX_DOUT; t++) {
	dout[t] = s.dout[t];
    }

    for (t = 0; t < EMC_AUX_MAX_DIN; t++) {
	din[t] = s.din[t];
    }

    for (t = 0; t < EMC_AUX_MAX_AOUT; t++) {
	aout[t] = s.aout[t];
    }

    for (t = 0; t < EMC_AUX_MAX_AIN; t++) {
	ain[t] = s.ain[t];
    }

    return s;
}

EMC_STAT::EMC_STAT():EMC_STAT_MSG(EMC_STAT_TYPE, sizeof(EMC_STAT))
{
}
<commit_msg>Add last missing field of EMC_AXIS_STAT Signed-off-by: Michael Geszkiewicz <micges@wp.pl><commit_after>/********************************************************************
* Description: emcops.cc
*   Initialization and other ad hoc functions for NML. This complements
*   the auto-generated emc.cc, which contains all the rote update
*   methods for the message classes.
*
*   Derived from a work by Fred Proctor & Will Shackleford
*
* Author:
* License: GPL Version 2
* System: Linux
*
* Copyright (c) 2004 All rights reserved.
*
* Last change:
********************************************************************/

#include "emc.hh"
#include "emc_nml.hh"

EMC_AXIS_STAT::EMC_AXIS_STAT():
EMC_AXIS_STAT_MSG(EMC_AXIS_STAT_TYPE, sizeof(EMC_AXIS_STAT))
{
    axisType = EMC_AXIS_LINEAR;
    units = 1.0;
    backlash = 0.0;
    maxError = 0.0;
    minPositionLimit = -1.0;
    maxPositionLimit = 1.0;
    minFerror = 1.0;
    maxFerror = 1.0;
    ferrorCurrent = 0.0;
    ferrorHighMark = 0.0;
    output = 0.0;
    input = 0.0;
    inpos = 1;
    homing = 0;
    homed = 0;
    enabled = 0;
    fault = 0;
    minSoftLimit = 0;
    maxSoftLimit = 0;
    minHardLimit = 0;
    maxHardLimit = 0;
    overrideLimits = 0;
}

EMC_TRAJ_STAT::EMC_TRAJ_STAT():
EMC_TRAJ_STAT_MSG(EMC_TRAJ_STAT_TYPE, sizeof(EMC_TRAJ_STAT))
{
    linearUnits = 1.0;
    angularUnits = 1.0;
    cycleTime = 0.0;
    axes = 1;
    axis_mask = 1;
    mode = EMC_TRAJ_MODE_FREE;
    enabled = 0;
    inpos = 1;
    queue = 0;
    activeQueue = 0;
    queueFull = 0;
    id = 0;
    paused = 0;
    scale = 0.0;
    spindle_scale = 0.0;

    ZERO_EMC_POSE(position);
    ZERO_EMC_POSE(actualPosition);

    velocity = 1.0;
    acceleration = 1.0;
    maxVelocity = 1.0;
    maxAcceleration = 1.0;

    ZERO_EMC_POSE(probedPosition);
    probe_tripped = 0;
    probing = 0;
    probeval = 0;

    ZERO_EMC_POSE(dtg);
    distance_to_go = 0.0;
    kinematics_type = 0;
    motion_type = 0;
    current_vel = 0.0;
    feed_override_enabled = 0;
    spindle_override_enabled = 0;
    adaptive_feed_enabled = 0;
    feed_hold_enabled = 0;
    delayLeft = 0.0;
}

EMC_MOTION_STAT::EMC_MOTION_STAT():
EMC_MOTION_STAT_MSG(EMC_MOTION_STAT_TYPE, sizeof(EMC_MOTION_STAT))
{
    int i;

    for (i = 0; i < EMC_MAX_DIO; i++)
	synch_di[i] = 0;

    for (i = 0; i < EMC_MAX_AIO; i++)
	analog_input[i] = 0;

    debug = 0;
};

EMC_TASK_STAT::EMC_TASK_STAT():
EMC_TASK_STAT_MSG(EMC_TASK_STAT_TYPE, sizeof(EMC_TASK_STAT))
{
    int t;

    mode = EMC_TASK_MODE_MANUAL;
    state = EMC_TASK_STATE_ESTOP;
    execState = EMC_TASK_EXEC_DONE;
    interpState = EMC_TASK_INTERP_IDLE;
    motionLine = 0;
    currentLine = 0;
    readLine = 0;
    optional_stop_state = OFF;
    block_delete_state = OFF;
    input_timeout = OFF;
    file[0] = 0;
    command[0] = 0;

    ZERO_EMC_POSE(origin);
    ZERO_EMC_POSE(toolOffset);

    rotation_xy = 0.0;
    tloIsAlongW = OFF;

    for (t = 0; t < ACTIVE_G_CODES; t++)
	activeGCodes[t] = -1;
    for (t = 0; t < ACTIVE_M_CODES; t++)
	activeMCodes[t] = -1;
    for (t = 0; t < ACTIVE_SETTINGS; t++)
	activeSettings[t] = 0.0;

    programUnits = CANON_UNITS_MM;
    interpreter_errcode = 0;
    task_paused = 0;
}

EMC_TOOL_STAT::EMC_TOOL_STAT():
EMC_TOOL_STAT_MSG(EMC_TOOL_STAT_TYPE, sizeof(EMC_TOOL_STAT))
{
    int t;

    toolPrepped = 0;
    toolInSpindle = 0;

    for (t = 0; t <= CANON_TOOL_MAX; t++) {
	toolTable[t].id = 0;
	toolTable[t].xoffset = 0.0;
	toolTable[t].zoffset = 0.0;
	toolTable[t].diameter = 0.0;
	toolTable[t].orientation = 0;
	toolTable[t].frontangle = 0.0;
	toolTable[t].backangle = 0.0;
    }
}

EMC_AUX_STAT::EMC_AUX_STAT():
EMC_AUX_STAT_MSG(EMC_AUX_STAT_TYPE, sizeof(EMC_AUX_STAT))
{
    int t;

    estop = 1;

    for (t = 0; t < EMC_AUX_MAX_DOUT; t++) {
	dout[t] = 0;
    }

    for (t = 0; t < EMC_AUX_MAX_DIN; t++) {
	din[t] = 0;
    }

    for (t = 0; t < EMC_AUX_MAX_AOUT; t++) {
	aout[t] = 0;
    }

    for (t = 0; t < EMC_AUX_MAX_AIN; t++) {
	ain[t] = 0;
    }
}

EMC_SPINDLE_STAT::EMC_SPINDLE_STAT():
EMC_SPINDLE_STAT_MSG(EMC_SPINDLE_STAT_TYPE, sizeof(EMC_SPINDLE_STAT))
{
    speed = 0.0;
    direction = 0;
    brake = 1;
    increasing = 0;
    enabled = 0;
}

EMC_COOLANT_STAT::EMC_COOLANT_STAT():EMC_COOLANT_STAT_MSG(EMC_COOLANT_STAT_TYPE,
		     sizeof
		     (EMC_COOLANT_STAT))
{
    mist = 0;
    flood = 0;
}

EMC_LUBE_STAT::EMC_LUBE_STAT():
EMC_LUBE_STAT_MSG(EMC_LUBE_STAT_TYPE, sizeof(EMC_LUBE_STAT))
{
    on = 0;
    level = 1;
}

// overload = , since class has array elements
EMC_TOOL_STAT EMC_TOOL_STAT::operator =(EMC_TOOL_STAT s)
{
    int t;

    toolPrepped = s.toolPrepped;
    toolInSpindle = s.toolInSpindle;

    for (t = 0; t <= CANON_TOOL_MAX; t++) {
	toolTable[t].id = s.toolTable[t].id;
	toolTable[t].xoffset = s.toolTable[t].xoffset;
	toolTable[t].zoffset = s.toolTable[t].zoffset;
	toolTable[t].diameter = s.toolTable[t].diameter;
	toolTable[t].frontangle = s.toolTable[t].frontangle;
	toolTable[t].backangle = s.toolTable[t].backangle;
	toolTable[t].orientation = s.toolTable[t].orientation;
    }

    return s;
}

// overload = , since class has array elements
EMC_AUX_STAT EMC_AUX_STAT::operator =(EMC_AUX_STAT s)
{
    int t;

    estop = s.estop;

    for (t = 0; t < EMC_AUX_MAX_DOUT; t++) {
	dout[t] = s.dout[t];
    }

    for (t = 0; t < EMC_AUX_MAX_DIN; t++) {
	din[t] = s.din[t];
    }

    for (t = 0; t < EMC_AUX_MAX_AOUT; t++) {
	aout[t] = s.aout[t];
    }

    for (t = 0; t < EMC_AUX_MAX_AIN; t++) {
	ain[t] = s.ain[t];
    }

    return s;
}

EMC_STAT::EMC_STAT():EMC_STAT_MSG(EMC_STAT_TYPE, sizeof(EMC_STAT))
{
}
<|endoftext|>


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

#include "palette.hpp"

// node
#include <node_buffer.h>

// stl
#include <vector>
#include <iomanip>
#include <sstream>

using namespace v8;

rgb::rgb(rgba const& c)
    : r(c.r), g(c.g), b(c.b) {}

// ordering by mean(a,r,g,b), a, r, g, b
bool rgba::mean_sort_cmp::operator() (const rgba& x, const rgba& y) const
{
    int t1 = (int)x.a + x.r + x.g + x.b;
    int t2 = (int)y.a + y.r + y.g + y.b;
    if (t1 != t2) return t1 < t2;

    // https://github.com/mapnik/mapnik/issues/1087
    if (x.a != y.a) return x.a < y.a;
    if (x.r != y.r) return x.r < y.r;
    if (x.g != y.g) return x.g < y.g;
    return x.b < y.b;
}

std::size_t rgba::hash_func::operator()(rgba const& p) const
{
    return ((std::size_t)p.r * 33023 + (std::size_t)p.g * 30013 +
            (std::size_t)p.b * 27011 + (std::size_t)p.a * 24007) % 21001;
}

rgba_palette::rgba_palette(std::string const& pal, palette_type type)
    : colors_(0)
{
    parse(pal, type);
}

rgba_palette::rgba_palette()
    : colors_(0) {}

const std::vector<rgb>& rgba_palette::palette() const
{
    return rgb_pal_;
}

const std::vector<unsigned>& rgba_palette::alphaTable() const
{
    return alpha_pal_;
}

bool rgba_palette::valid() const
{
    return colors_ > 0;
}

// return color index in returned earlier palette
unsigned rgba_palette::quantize(rgba const& c) const
{
    unsigned index = 0;
    if (colors_ == 1) return index;

    rgba_hash_table::iterator it = color_hashmap_.find(c);
    if (it != color_hashmap_.end())
    {
        index = it->second;
    }
    else
    {
        int dr, dg, db, da;
        int dist, newdist;

        // find closest match based on mean of r,g,b,a
        std::vector<rgba>::const_iterator pit =
            std::lower_bound(sorted_pal_.begin(), sorted_pal_.end(), c, rgba::mean_sort_cmp());
        index = pit - sorted_pal_.begin();
        if (index == sorted_pal_.size()) index--;

        dr = sorted_pal_[index].r - c.r;
        dg = sorted_pal_[index].g - c.g;
        db = sorted_pal_[index].b - c.b;
        da = sorted_pal_[index].a - c.a;
        dist = dr*dr + dg*dg + db*db + da*da;
        int poz = index;

        // search neighbour positions in both directions for better match
        for (int i = poz - 1; i >= 0; i--)
        {
            dr = sorted_pal_[i].r - c.r;
            dg = sorted_pal_[i].g - c.g;
            db = sorted_pal_[i].b - c.b;
            da = sorted_pal_[i].a - c.a;
            // stop criteria based on properties of used sorting
            if ((dr+db+dg+da) * (dr+db+dg+da) / 4 > dist)
            {
                break;
            }
            newdist = dr*dr + dg*dg + db*db + da*da;
            if (newdist < dist)
            {
                index = i;
                dist = newdist;
            }
        }

        for (unsigned i = poz + 1; i < sorted_pal_.size(); i++)
        {
            dr = sorted_pal_[i].r - c.r;
            dg = sorted_pal_[i].g - c.g;
            db = sorted_pal_[i].b - c.b;
            da = sorted_pal_[i].a - c.a;
            // stop criteria based on properties of used sorting
            if ((dr+db+dg+da) * (dr+db+dg+da) / 4 > dist)
            {
                break;
            }
            newdist = dr*dr + dg*dg + db*db + da*da;
            if (newdist < dist)
            {
                index = i;
                dist = newdist;
            }
        }

        // Cache found index for the color c into the hashmap.
        color_hashmap_[c] = index;
    }

    return index;
}

void rgba_palette::parse(std::string const& pal, palette_type type)
{
    unsigned length = pal.length();

    if ((type == PALETTE_RGBA && length % 4 > 0) ||
        (type == PALETTE_RGB && length % 3 > 0) ||
        (type == PALETTE_ACT && length != 772))
    {
        return;
    }

    if (type == PALETTE_ACT)
    {
        length = (pal[768] << 8 | pal[769]) * 3;
    }

    sorted_pal_.clear();
    color_hashmap_.clear();
    rgb_pal_.clear();
    alpha_pal_.clear();

    if (type == PALETTE_RGBA)
    {
        for (unsigned i = 0; i < length; i += 4)
        {
            sorted_pal_.push_back(rgba(pal[i], pal[i + 1], pal[i + 2], pal[i + 3]));
        }
    }
    else
    {
        for (unsigned i = 0; i < length; i += 3)
        {
            sorted_pal_.push_back(rgba(pal[i], pal[i + 1], pal[i + 2], 0xFF));
        }
    }

    // Make sure we have at least one entry in the palette.
    if (sorted_pal_.size() == 0)
    {
        sorted_pal_.push_back(rgba(0, 0, 0, 0));
    }

    colors_ = sorted_pal_.size();

    // Sort palette for binary searching in quantization
    std::sort(sorted_pal_.begin(), sorted_pal_.end(), rgba::mean_sort_cmp());

    // Insert all palette colors into the hashmap and into the palette vectors.
    for (unsigned i = 0; i < colors_; i++)
    {
        rgba c = sorted_pal_[i];
        color_hashmap_[c] = i;
        rgb_pal_.push_back(rgb(c));
        if (c.a < 0xFF)
        {
            alpha_pal_.push_back(c.a);
        }
    }
}

// ------- node implementation -------

Persistent<FunctionTemplate> Palette::constructor;

void Palette::Initialize(Handle<Object> target) {
    HandleScope scope;

    constructor = Persistent<FunctionTemplate>::New(FunctionTemplate::New(Palette::New));
    constructor->InstanceTemplate()->SetInternalFieldCount(1);
    constructor->SetClassName(String::NewSymbol("Palette"));

    NODE_SET_PROTOTYPE_METHOD(constructor, "toString", ToString);
    NODE_SET_PROTOTYPE_METHOD(constructor, "toBuffer", ToBuffer);

    target->Set(String::NewSymbol("Palette"), constructor->GetFunction());
}

Palette::Palette(std::string const& palette, rgba_palette::palette_type type) :
    ObjectWrap(),
    palette_(new rgba_palette(palette, type)) {}

Palette::~Palette() {
}

Handle<Value> Palette::New(const Arguments& args) {
    HandleScope scope;

    if (!args.IsConstructCall()) {
        return ThrowException(String::New("Cannot call constructor as function, you need to use 'new' keyword"));
    }

    std::string palette;
    rgba_palette::palette_type type = rgba_palette::PALETTE_RGBA;
    if (args.Length() >= 1) {
        if (args[0]->IsString()) {
            String::AsciiValue obj(args[0]->ToString());
            palette = std::string(*obj, obj.length());
        }
        else if (node::Buffer::HasInstance(args[0])) {
            Local<Object> obj = args[0]->ToObject();
            palette = std::string(node::Buffer::Data(obj), node::Buffer::Length(obj));
        }
    }
    if (args.Length() >= 2) {
        if (args[1]->IsString()) {
            std::string obj = *String::Utf8Value(args[1]->ToString());
            if (obj == "rgb") type = rgba_palette::PALETTE_RGB;
            else if (obj == "act") type = rgba_palette::PALETTE_ACT;
        }
    }

    if (!palette.length()) {
        return ThrowException(Exception::TypeError(
            String::New("First parameter must be a palette string")));
    }

    Palette* p = new Palette(palette, type);
    if (!p->palette()->valid()) {
        delete p;
        return ThrowException(Exception::TypeError(String::New("Invalid palette length")));
    } else {
        p->Wrap(args.This());
        return args.This();
    }
}

Handle<Value> Palette::ToString(const Arguments& args)
{
    HandleScope scope;
    palette_ptr p = ObjectWrap::Unwrap<Palette>(args.This())->palette_;

    const std::vector<rgb>& colors = p->palette();
    unsigned length = colors.size();
    const std::vector<unsigned>& alpha = p->alphaTable();
    unsigned alphaLength = alpha.size();

    std::ostringstream str("");
    str << "[Palette " << length;
    if (length == 1) str << " color";
    else str << " colors";

    str << std::hex << std::setfill('0');

    for (unsigned i = 0; i < length; i++) {
        str << " #";
        str << std::setw(2) << (unsigned)colors[i].r;
        str << std::setw(2) << (unsigned)colors[i].g;
        str << std::setw(2) << (unsigned)colors[i].b;
        if (i < alphaLength) str << std::setw(2) << alpha[i];
    }

    str << "]";
    return scope.Close(String::New(str.str().c_str()));
}

Handle<Value> Palette::ToBuffer(const Arguments& args)
{
    HandleScope scope;

    palette_ptr p = ObjectWrap::Unwrap<Palette>(args.This())->palette_;

    const std::vector<rgb>& colors = p->palette();
    unsigned length = colors.size();
    const std::vector<unsigned>& alpha = p->alphaTable();
    unsigned alphaLength = alpha.size();

    char palette[256 * 4];
    for (unsigned i = 0, pos = 0; i < length; i++) {
        palette[pos++] = colors[i].r;
        palette[pos++] = colors[i].g;
        palette[pos++] = colors[i].b;
        palette[pos++] = (i < alphaLength) ? alpha[i] : 0xFF;
    }

    node::Buffer *buffer = node::Buffer::New(palette, length * 4);
    return scope.Close(buffer->handle_);
}

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

#include "palette.hpp"

// node
#include <node_buffer.h>

// stl
#include <vector>
#include <iomanip>
#include <sstream>
#include <algorithm>

using namespace v8;

rgb::rgb(rgba const& c)
    : r(c.r), g(c.g), b(c.b) {}

// ordering by mean(a,r,g,b), a, r, g, b
bool rgba::mean_sort_cmp::operator() (const rgba& x, const rgba& y) const
{
    int t1 = (int)x.a + x.r + x.g + x.b;
    int t2 = (int)y.a + y.r + y.g + y.b;
    if (t1 != t2) return t1 < t2;

    // https://github.com/mapnik/mapnik/issues/1087
    if (x.a != y.a) return x.a < y.a;
    if (x.r != y.r) return x.r < y.r;
    if (x.g != y.g) return x.g < y.g;
    return x.b < y.b;
}

std::size_t rgba::hash_func::operator()(rgba const& p) const
{
    return ((std::size_t)p.r * 33023 + (std::size_t)p.g * 30013 +
            (std::size_t)p.b * 27011 + (std::size_t)p.a * 24007) % 21001;
}

rgba_palette::rgba_palette(std::string const& pal, palette_type type)
    : colors_(0)
{
    parse(pal, type);
}

rgba_palette::rgba_palette()
    : colors_(0) {}

const std::vector<rgb>& rgba_palette::palette() const
{
    return rgb_pal_;
}

const std::vector<unsigned>& rgba_palette::alphaTable() const
{
    return alpha_pal_;
}

bool rgba_palette::valid() const
{
    return colors_ > 0;
}

// return color index in returned earlier palette
unsigned rgba_palette::quantize(rgba const& c) const
{
    unsigned index = 0;
    if (colors_ == 1) return index;

    rgba_hash_table::iterator it = color_hashmap_.find(c);
    if (it != color_hashmap_.end())
    {
        index = it->second;
    }
    else
    {
        int dr, dg, db, da;
        int dist, newdist;

        // find closest match based on mean of r,g,b,a
        std::vector<rgba>::const_iterator pit =
            std::lower_bound(sorted_pal_.begin(), sorted_pal_.end(), c, rgba::mean_sort_cmp());
        index = pit - sorted_pal_.begin();
        if (index == sorted_pal_.size()) index--;

        dr = sorted_pal_[index].r - c.r;
        dg = sorted_pal_[index].g - c.g;
        db = sorted_pal_[index].b - c.b;
        da = sorted_pal_[index].a - c.a;
        dist = dr*dr + dg*dg + db*db + da*da;
        int poz = index;

        // search neighbour positions in both directions for better match
        for (int i = poz - 1; i >= 0; i--)
        {
            dr = sorted_pal_[i].r - c.r;
            dg = sorted_pal_[i].g - c.g;
            db = sorted_pal_[i].b - c.b;
            da = sorted_pal_[i].a - c.a;
            // stop criteria based on properties of used sorting
            if ((dr+db+dg+da) * (dr+db+dg+da) / 4 > dist)
            {
                break;
            }
            newdist = dr*dr + dg*dg + db*db + da*da;
            if (newdist < dist)
            {
                index = i;
                dist = newdist;
            }
        }

        for (unsigned i = poz + 1; i < sorted_pal_.size(); i++)
        {
            dr = sorted_pal_[i].r - c.r;
            dg = sorted_pal_[i].g - c.g;
            db = sorted_pal_[i].b - c.b;
            da = sorted_pal_[i].a - c.a;
            // stop criteria based on properties of used sorting
            if ((dr+db+dg+da) * (dr+db+dg+da) / 4 > dist)
            {
                break;
            }
            newdist = dr*dr + dg*dg + db*db + da*da;
            if (newdist < dist)
            {
                index = i;
                dist = newdist;
            }
        }

        // Cache found index for the color c into the hashmap.
        color_hashmap_[c] = index;
    }

    return index;
}

void rgba_palette::parse(std::string const& pal, palette_type type)
{
    unsigned length = pal.length();

    if ((type == PALETTE_RGBA && length % 4 > 0) ||
        (type == PALETTE_RGB && length % 3 > 0) ||
        (type == PALETTE_ACT && length != 772))
    {
        return;
    }

    if (type == PALETTE_ACT)
    {
        length = (pal[768] << 8 | pal[769]) * 3;
    }

    sorted_pal_.clear();
    color_hashmap_.clear();
    rgb_pal_.clear();
    alpha_pal_.clear();

    if (type == PALETTE_RGBA)
    {
        for (unsigned i = 0; i < length; i += 4)
        {
            sorted_pal_.push_back(rgba(pal[i], pal[i + 1], pal[i + 2], pal[i + 3]));
        }
    }
    else
    {
        for (unsigned i = 0; i < length; i += 3)
        {
            sorted_pal_.push_back(rgba(pal[i], pal[i + 1], pal[i + 2], 0xFF));
        }
    }

    // Make sure we have at least one entry in the palette.
    if (sorted_pal_.size() == 0)
    {
        sorted_pal_.push_back(rgba(0, 0, 0, 0));
    }

    colors_ = sorted_pal_.size();

    // Sort palette for binary searching in quantization
    std::sort(sorted_pal_.begin(), sorted_pal_.end(), rgba::mean_sort_cmp());

    // Insert all palette colors into the hashmap and into the palette vectors.
    for (unsigned i = 0; i < colors_; i++)
    {
        rgba c = sorted_pal_[i];
        color_hashmap_[c] = i;
        rgb_pal_.push_back(rgb(c));
        if (c.a < 0xFF)
        {
            alpha_pal_.push_back(c.a);
        }
    }
}

// ------- node implementation -------

Persistent<FunctionTemplate> Palette::constructor;

void Palette::Initialize(Handle<Object> target) {
    HandleScope scope;

    constructor = Persistent<FunctionTemplate>::New(FunctionTemplate::New(Palette::New));
    constructor->InstanceTemplate()->SetInternalFieldCount(1);
    constructor->SetClassName(String::NewSymbol("Palette"));

    NODE_SET_PROTOTYPE_METHOD(constructor, "toString", ToString);
    NODE_SET_PROTOTYPE_METHOD(constructor, "toBuffer", ToBuffer);

    target->Set(String::NewSymbol("Palette"), constructor->GetFunction());
}

Palette::Palette(std::string const& palette, rgba_palette::palette_type type) :
    ObjectWrap(),
    palette_(new rgba_palette(palette, type)) {}

Palette::~Palette() {
}

Handle<Value> Palette::New(const Arguments& args) {
    HandleScope scope;

    if (!args.IsConstructCall()) {
        return ThrowException(String::New("Cannot call constructor as function, you need to use 'new' keyword"));
    }

    std::string palette;
    rgba_palette::palette_type type = rgba_palette::PALETTE_RGBA;
    if (args.Length() >= 1) {
        if (args[0]->IsString()) {
            String::AsciiValue obj(args[0]->ToString());
            palette = std::string(*obj, obj.length());
        }
        else if (node::Buffer::HasInstance(args[0])) {
            Local<Object> obj = args[0]->ToObject();
            palette = std::string(node::Buffer::Data(obj), node::Buffer::Length(obj));
        }
    }
    if (args.Length() >= 2) {
        if (args[1]->IsString()) {
            std::string obj = *String::Utf8Value(args[1]->ToString());
            if (obj == "rgb") type = rgba_palette::PALETTE_RGB;
            else if (obj == "act") type = rgba_palette::PALETTE_ACT;
        }
    }

    if (!palette.length()) {
        return ThrowException(Exception::TypeError(
            String::New("First parameter must be a palette string")));
    }

    Palette* p = new Palette(palette, type);
    if (!p->palette()->valid()) {
        delete p;
        return ThrowException(Exception::TypeError(String::New("Invalid palette length")));
    } else {
        p->Wrap(args.This());
        return args.This();
    }
}

Handle<Value> Palette::ToString(const Arguments& args)
{
    HandleScope scope;
    palette_ptr p = ObjectWrap::Unwrap<Palette>(args.This())->palette_;

    const std::vector<rgb>& colors = p->palette();
    unsigned length = colors.size();
    const std::vector<unsigned>& alpha = p->alphaTable();
    unsigned alphaLength = alpha.size();

    std::ostringstream str("");
    str << "[Palette " << length;
    if (length == 1) str << " color";
    else str << " colors";

    str << std::hex << std::setfill('0');

    for (unsigned i = 0; i < length; i++) {
        str << " #";
        str << std::setw(2) << (unsigned)colors[i].r;
        str << std::setw(2) << (unsigned)colors[i].g;
        str << std::setw(2) << (unsigned)colors[i].b;
        if (i < alphaLength) str << std::setw(2) << alpha[i];
    }

    str << "]";
    return scope.Close(String::New(str.str().c_str()));
}

Handle<Value> Palette::ToBuffer(const Arguments& args)
{
    HandleScope scope;

    palette_ptr p = ObjectWrap::Unwrap<Palette>(args.This())->palette_;

    const std::vector<rgb>& colors = p->palette();
    unsigned length = colors.size();
    const std::vector<unsigned>& alpha = p->alphaTable();
    unsigned alphaLength = alpha.size();

    char palette[256 * 4];
    for (unsigned i = 0, pos = 0; i < length; i++) {
        palette[pos++] = colors[i].r;
        palette[pos++] = colors[i].g;
        palette[pos++] = colors[i].b;
        palette[pos++] = (i < alphaLength) ? alpha[i] : 0xFF;
    }

    node::Buffer *buffer = node::Buffer::New(palette, length * 4);
    return scope.Close(buffer->handle_);
}

<|endoftext|>


<commit_before>#include <pb_view.h>
#include <pb_controller.h>
#include <poddlthread.h>
#include <download.h>
#include <config.h>
#include <logger.h>

#include <dllist.h>
#include <help.h>
#include <utils.h>

#include <sstream>
#include <iostream>
#include <cstring>

using namespace newsbeuter;

namespace podbeuter {

pb_view::pb_view(pb_controller * c) : ctrl(c), dllist_form(dllist_str), help_form(help_str), keys(0) {
}

pb_view::~pb_view() {
	stfl::reset();
}

void pb_view::run(bool auto_download) {
	bool quit = false;

	set_dllist_keymap_hint();

	do {

		if (ctrl->view_update_necessary()) {

			double total_kbps = ctrl->get_total_kbps();

			char parbuf[128] = "";
			if (ctrl->get_maxdownloads() > 1) {
				snprintf(parbuf, sizeof(parbuf), _(" - %u parallel downloads"), ctrl->get_maxdownloads());
			}

			char buf[1024];
			snprintf(buf, sizeof(buf), _("Queue (%u downloads in progress, %u total) - %.2f kb/s total%s"),
			         static_cast<unsigned int>(ctrl->downloads_in_progress()),
			         static_cast<unsigned int>(ctrl->downloads().size()), total_kbps, parbuf);

			dllist_form.set("head", buf);

			LOG(LOG_DEBUG, "pb_view::run: updating view... downloads().size() = %u", ctrl->downloads().size());

			if (ctrl->downloads().size() > 0) {
				std::string code = "{list";

				unsigned int i = 0;
				for (auto dl : ctrl->downloads()) {
					char lbuf[1024];
					snprintf(lbuf, sizeof(lbuf), " %4u [%6.1fMB/%6.1fMB] [%5.1f %%] [%7.2f kb/s] %-20s %s -> %s", i+1, dl.current_size()/(1024*1024), dl.total_size()/(1024*1024), dl.percents_finished(), dl.kbps(), dl.status_text(), dl.url(), dl.filename());
					code.append(utils::strprintf("{listitem[%u] text:%s}", i, stfl::quote(lbuf).c_str()));
					i++;
				}

				code.append("}");

				dllist_form.modify("dls", "replace_inner", code);
			}

			ctrl->set_view_update_necessary(false);
		}

		const char * event = dllist_form.run(500);

		if (auto_download) {
			if (ctrl->get_maxdownloads() > ctrl->downloads_in_progress()) {
				ctrl->start_downloads();
			}
		}

		if (!event || strcmp(event,"TIMEOUT")==0) continue;

		operation op = keys->get_operation(event, "podbeuter");

		if (dllist_form.get("msg").length() > 0) {
			dllist_form.set("msg", "");
			ctrl->set_view_update_necessary(true);
		}

		switch (op) {
		case OP_PB_TOGGLE_DLALL:
			auto_download = !auto_download;
			break;
		case OP_HARDQUIT:
		case OP_QUIT:
			if (ctrl->downloads_in_progress() > 0) {
				dllist_form.set("msg", _("Error: can't quit: download(s) in progress."));
				ctrl->set_view_update_necessary(true);
			} else {
				quit = true;
			}
			break;
		case OP_PB_MOREDL:
			ctrl->increase_parallel_downloads();
			break;
		case OP_PB_LESSDL:
			ctrl->decrease_parallel_downloads();
			break;
		case OP_PB_DOWNLOAD: {
			std::istringstream os(dllist_form.get("dlposname"));
			int idx = -1;
			os >> idx;
			if (idx != -1) {
				if (ctrl->downloads()[idx].status() != DL_DOWNLOADING) {
					std::thread t {poddlthread(&ctrl->downloads()[idx], ctrl->get_cfgcont())};
				}
			}
		}
		break;
		case OP_PB_PLAY: {
			std::istringstream os(dllist_form.get("dlposname"));
			int idx = -1;
			os >> idx;
			if (idx != -1) {
				dlstatus_t status = ctrl->downloads()[idx].status();
				if (status == DL_FINISHED || status == DL_PLAYED || status == DL_READY) {
					ctrl->play_file(ctrl->downloads()[idx].filename());
					ctrl->downloads()[idx].set_status(DL_PLAYED);
				} else {
					dllist_form.set("msg", _("Error: download needs to be finished before the file can be played."));
				}
			}
		}
		break;
		case OP_PB_MARK_FINISHED: {
			std::istringstream os(dllist_form.get("dlposname"));
			int idx = -1;
			os >> idx;
			if (idx != -1) {
				dlstatus_t status = ctrl->downloads()[idx].status();
				if ( status == DL_PLAYED ) {
					ctrl->downloads()[idx].set_status(DL_FINISHED);
				}
			}
		}
		break;
		case OP_PB_CANCEL: {
			std::istringstream os(dllist_form.get("dlposname"));
			int idx = -1;
			os >> idx;
			if (idx != -1) {
				if (ctrl->downloads()[idx].status() == DL_DOWNLOADING) {
					ctrl->downloads()[idx].set_status(DL_CANCELLED);
				}
			}
		}
		break;
		case OP_PB_DELETE: {
			std::istringstream os(dllist_form.get("dlposname"));
			int idx = -1;
			os >> idx;
			if (idx != -1) {
				if (ctrl->downloads()[idx].status() != DL_DOWNLOADING) {
					ctrl->downloads()[idx].set_status(DL_DELETED);
				}
			}
		}
		break;
		case OP_PB_PURGE:
			if (ctrl->downloads_in_progress() > 0) {
				dllist_form.set("msg", _("Error: unable to perform operation: download(s) in progress."));
			} else {
				ctrl->reload_queue(true);
			}
			ctrl->set_view_update_necessary(true);
			break;
		case OP_HELP:
			run_help();
			break;
		default:
			break;
		}

	} while (!quit);
}

void pb_view::set_bindings() {
	if (keys) {
		std::string upkey("** ");
		upkey.append(keys->getkey(OP_SK_UP, "podbeuter"));
		std::string downkey("** ");
		downkey.append(keys->getkey(OP_SK_DOWN, "podbeuter"));
		std::string pgupkey("** ");
		pgupkey.append(keys->getkey(OP_SK_PGUP, "podbeuter"));
		std::string pgdownkey("** ");
		pgdownkey.append(keys->getkey(OP_SK_PGDOWN, "podbeuter"));
		std::string homekey("** ");
		homekey.append(keys->getkey(OP_SK_HOME, "podbeuter"));
		std::string endkey("** ");
		endkey.append(keys->getkey(OP_SK_END, "podbeuter"));

		dllist_form.set("bind_up", upkey);
		dllist_form.set("bind_down", downkey);
		dllist_form.set("bind_page_up", pgupkey);
		dllist_form.set("bind_page_down", pgdownkey);
		dllist_form.set("bind_home", homekey);
		dllist_form.set("bind_end", endkey);

		help_form.set("bind_up", upkey);
		help_form.set("bind_down", downkey);
		help_form.set("bind_page_up", pgupkey);
		help_form.set("bind_page_down", pgdownkey);
		help_form.set("bind_home", homekey);
		help_form.set("bind_end", endkey);

	}
}

void pb_view::run_help() {
	set_help_keymap_hint();

	help_form.set("head",_("Help"));

	std::vector<keymap_desc> descs;
	keys->get_keymap_descriptions(descs, KM_PODBEUTER);

	std::string code = "{list";

	for (auto desc : descs) {
		std::string line = "{listitem text:";

		std::string descline;
		descline.append(desc.key);
		descline.append(8-desc.key.length(),' ');
		descline.append(desc.cmd);
		descline.append(24-desc.cmd.length(),' ');
		descline.append(desc.desc);
		line.append(stfl::quote(descline));

		line.append("}");

		code.append(line);
	}

	code.append("}");

	help_form.modify("helptext","replace_inner",code);

	bool quit = false;

	do {
		const char * event = help_form.run(0);
		if (!event) continue;

		operation op = keys->get_operation(event, "help");

		switch (op) {
		case OP_HARDQUIT:
		case OP_QUIT:
			quit = true;
			break;
		default:
			break;
		}
	} while (!quit);
}

std::string pb_view::prepare_keymaphint(keymap_hint_entry * hints) {
	std::string keymap_hint;
	for (int i=0; hints[i].op != OP_NIL; ++i) {
		keymap_hint.append(keys->getkey(hints[i].op, "podbeuter"));
		keymap_hint.append(":");
		keymap_hint.append(hints[i].text);
		keymap_hint.append(" ");
	}
	return keymap_hint;
}

void pb_view::set_help_keymap_hint() {
	keymap_hint_entry hints[] = {
		{ OP_QUIT, _("Quit") },
		{ OP_NIL, NULL }
	};
	std::string keymap_hint = prepare_keymaphint(hints);
	help_form.set("help", keymap_hint);
}

void pb_view::set_dllist_keymap_hint() {
	keymap_hint_entry hints[] = {
		{ OP_QUIT, _("Quit") },
		{ OP_PB_DOWNLOAD, _("Download") },
		{ OP_PB_CANCEL, _("Cancel") },
		{ OP_PB_DELETE, _("Delete") },
		{ OP_PB_PURGE, _("Purge Finished") },
		{ OP_PB_TOGGLE_DLALL, _("Toggle Automatic Download") },
		{ OP_PB_PLAY, _("Play") },
		{ OP_PB_MARK_FINISHED, _("Mark as Finished") },
		{ OP_HELP, _("Help") },
		{ OP_NIL, NULL }
	};

	std::string keymap_hint = prepare_keymaphint(hints);
	dllist_form.set("help", keymap_hint);
}

}
<commit_msg>Another threa.detach() missing<commit_after>#include <pb_view.h>
#include <pb_controller.h>
#include <poddlthread.h>
#include <download.h>
#include <config.h>
#include <logger.h>

#include <dllist.h>
#include <help.h>
#include <utils.h>

#include <sstream>
#include <iostream>
#include <cstring>

using namespace newsbeuter;

namespace podbeuter {

pb_view::pb_view(pb_controller * c) : ctrl(c), dllist_form(dllist_str), help_form(help_str), keys(0) {
}

pb_view::~pb_view() {
	stfl::reset();
}

void pb_view::run(bool auto_download) {
	bool quit = false;

	set_dllist_keymap_hint();

	do {

		if (ctrl->view_update_necessary()) {

			double total_kbps = ctrl->get_total_kbps();

			char parbuf[128] = "";
			if (ctrl->get_maxdownloads() > 1) {
				snprintf(parbuf, sizeof(parbuf), _(" - %u parallel downloads"), ctrl->get_maxdownloads());
			}

			char buf[1024];
			snprintf(buf, sizeof(buf), _("Queue (%u downloads in progress, %u total) - %.2f kb/s total%s"),
			         static_cast<unsigned int>(ctrl->downloads_in_progress()),
			         static_cast<unsigned int>(ctrl->downloads().size()), total_kbps, parbuf);

			dllist_form.set("head", buf);

			LOG(LOG_DEBUG, "pb_view::run: updating view... downloads().size() = %u", ctrl->downloads().size());

			if (ctrl->downloads().size() > 0) {
				std::string code = "{list";

				unsigned int i = 0;
				for (auto dl : ctrl->downloads()) {
					char lbuf[1024];
					snprintf(lbuf, sizeof(lbuf), " %4u [%6.1fMB/%6.1fMB] [%5.1f %%] [%7.2f kb/s] %-20s %s -> %s", i+1, dl.current_size()/(1024*1024), dl.total_size()/(1024*1024), dl.percents_finished(), dl.kbps(), dl.status_text(), dl.url(), dl.filename());
					code.append(utils::strprintf("{listitem[%u] text:%s}", i, stfl::quote(lbuf).c_str()));
					i++;
				}

				code.append("}");

				dllist_form.modify("dls", "replace_inner", code);
			}

			ctrl->set_view_update_necessary(false);
		}

		const char * event = dllist_form.run(500);

		if (auto_download) {
			if (ctrl->get_maxdownloads() > ctrl->downloads_in_progress()) {
				ctrl->start_downloads();
			}
		}

		if (!event || strcmp(event,"TIMEOUT")==0) continue;

		operation op = keys->get_operation(event, "podbeuter");

		if (dllist_form.get("msg").length() > 0) {
			dllist_form.set("msg", "");
			ctrl->set_view_update_necessary(true);
		}

		switch (op) {
		case OP_PB_TOGGLE_DLALL:
			auto_download = !auto_download;
			break;
		case OP_HARDQUIT:
		case OP_QUIT:
			if (ctrl->downloads_in_progress() > 0) {
				dllist_form.set("msg", _("Error: can't quit: download(s) in progress."));
				ctrl->set_view_update_necessary(true);
			} else {
				quit = true;
			}
			break;
		case OP_PB_MOREDL:
			ctrl->increase_parallel_downloads();
			break;
		case OP_PB_LESSDL:
			ctrl->decrease_parallel_downloads();
			break;
		case OP_PB_DOWNLOAD: {
			std::istringstream os(dllist_form.get("dlposname"));
			int idx = -1;
			os >> idx;
			if (idx != -1) {
				if (ctrl->downloads()[idx].status() != DL_DOWNLOADING) {
					std::thread t {poddlthread(&ctrl->downloads()[idx], ctrl->get_cfgcont())};
					t.detach();
				}
			}
		}
		break;
		case OP_PB_PLAY: {
			std::istringstream os(dllist_form.get("dlposname"));
			int idx = -1;
			os >> idx;
			if (idx != -1) {
				dlstatus_t status = ctrl->downloads()[idx].status();
				if (status == DL_FINISHED || status == DL_PLAYED || status == DL_READY) {
					ctrl->play_file(ctrl->downloads()[idx].filename());
					ctrl->downloads()[idx].set_status(DL_PLAYED);
				} else {
					dllist_form.set("msg", _("Error: download needs to be finished before the file can be played."));
				}
			}
		}
		break;
		case OP_PB_MARK_FINISHED: {
			std::istringstream os(dllist_form.get("dlposname"));
			int idx = -1;
			os >> idx;
			if (idx != -1) {
				dlstatus_t status = ctrl->downloads()[idx].status();
				if ( status == DL_PLAYED ) {
					ctrl->downloads()[idx].set_status(DL_FINISHED);
				}
			}
		}
		break;
		case OP_PB_CANCEL: {
			std::istringstream os(dllist_form.get("dlposname"));
			int idx = -1;
			os >> idx;
			if (idx != -1) {
				if (ctrl->downloads()[idx].status() == DL_DOWNLOADING) {
					ctrl->downloads()[idx].set_status(DL_CANCELLED);
				}
			}
		}
		break;
		case OP_PB_DELETE: {
			std::istringstream os(dllist_form.get("dlposname"));
			int idx = -1;
			os >> idx;
			if (idx != -1) {
				if (ctrl->downloads()[idx].status() != DL_DOWNLOADING) {
					ctrl->downloads()[idx].set_status(DL_DELETED);
				}
			}
		}
		break;
		case OP_PB_PURGE:
			if (ctrl->downloads_in_progress() > 0) {
				dllist_form.set("msg", _("Error: unable to perform operation: download(s) in progress."));
			} else {
				ctrl->reload_queue(true);
			}
			ctrl->set_view_update_necessary(true);
			break;
		case OP_HELP:
			run_help();
			break;
		default:
			break;
		}

	} while (!quit);
}

void pb_view::set_bindings() {
	if (keys) {
		std::string upkey("** ");
		upkey.append(keys->getkey(OP_SK_UP, "podbeuter"));
		std::string downkey("** ");
		downkey.append(keys->getkey(OP_SK_DOWN, "podbeuter"));
		std::string pgupkey("** ");
		pgupkey.append(keys->getkey(OP_SK_PGUP, "podbeuter"));
		std::string pgdownkey("** ");
		pgdownkey.append(keys->getkey(OP_SK_PGDOWN, "podbeuter"));
		std::string homekey("** ");
		homekey.append(keys->getkey(OP_SK_HOME, "podbeuter"));
		std::string endkey("** ");
		endkey.append(keys->getkey(OP_SK_END, "podbeuter"));

		dllist_form.set("bind_up", upkey);
		dllist_form.set("bind_down", downkey);
		dllist_form.set("bind_page_up", pgupkey);
		dllist_form.set("bind_page_down", pgdownkey);
		dllist_form.set("bind_home", homekey);
		dllist_form.set("bind_end", endkey);

		help_form.set("bind_up", upkey);
		help_form.set("bind_down", downkey);
		help_form.set("bind_page_up", pgupkey);
		help_form.set("bind_page_down", pgdownkey);
		help_form.set("bind_home", homekey);
		help_form.set("bind_end", endkey);

	}
}

void pb_view::run_help() {
	set_help_keymap_hint();

	help_form.set("head",_("Help"));

	std::vector<keymap_desc> descs;
	keys->get_keymap_descriptions(descs, KM_PODBEUTER);

	std::string code = "{list";

	for (auto desc : descs) {
		std::string line = "{listitem text:";

		std::string descline;
		descline.append(desc.key);
		descline.append(8-desc.key.length(),' ');
		descline.append(desc.cmd);
		descline.append(24-desc.cmd.length(),' ');
		descline.append(desc.desc);
		line.append(stfl::quote(descline));

		line.append("}");

		code.append(line);
	}

	code.append("}");

	help_form.modify("helptext","replace_inner",code);

	bool quit = false;

	do {
		const char * event = help_form.run(0);
		if (!event) continue;

		operation op = keys->get_operation(event, "help");

		switch (op) {
		case OP_HARDQUIT:
		case OP_QUIT:
			quit = true;
			break;
		default:
			break;
		}
	} while (!quit);
}

std::string pb_view::prepare_keymaphint(keymap_hint_entry * hints) {
	std::string keymap_hint;
	for (int i=0; hints[i].op != OP_NIL; ++i) {
		keymap_hint.append(keys->getkey(hints[i].op, "podbeuter"));
		keymap_hint.append(":");
		keymap_hint.append(hints[i].text);
		keymap_hint.append(" ");
	}
	return keymap_hint;
}

void pb_view::set_help_keymap_hint() {
	keymap_hint_entry hints[] = {
		{ OP_QUIT, _("Quit") },
		{ OP_NIL, NULL }
	};
	std::string keymap_hint = prepare_keymaphint(hints);
	help_form.set("help", keymap_hint);
}

void pb_view::set_dllist_keymap_hint() {
	keymap_hint_entry hints[] = {
		{ OP_QUIT, _("Quit") },
		{ OP_PB_DOWNLOAD, _("Download") },
		{ OP_PB_CANCEL, _("Cancel") },
		{ OP_PB_DELETE, _("Delete") },
		{ OP_PB_PURGE, _("Purge Finished") },
		{ OP_PB_TOGGLE_DLALL, _("Toggle Automatic Download") },
		{ OP_PB_PLAY, _("Play") },
		{ OP_PB_MARK_FINISHED, _("Mark as Finished") },
		{ OP_HELP, _("Help") },
		{ OP_NIL, NULL }
	};

	std::string keymap_hint = prepare_keymaphint(hints);
	dllist_form.set("help", keymap_hint);
}

}
<|endoftext|>


<commit_before><commit_msg>Revert "Add back ctrl+shift+delete for bringing up the "Clear browsing data""<commit_after><|endoftext|>


<commit_before>#include <luabind/luabind.hpp>
#include "../externals/json/json.h"
#include "math.h"
#include "motionstate.h"
#include "physics.h"

Physics::Physics(){
	mKinematic.Vel	 = Vector2f(0, 0);
	mKinematic.Accel = Vector2f(0, 0);
	mHorizDir = MOVE::STOP;
	mVertDir  = MOVE::STOP;
}
Physics::~Physics(){}
void Physics::Move(float deltaT){
	//Update the velocity
	UpdateVelocity(deltaT);
	//test if the move is ok before applying changes
	Vector2f testPos;
	testPos = mBox.Pos() + (mKinematic.Vel * deltaT);

	//Clamp the test position x & y
	//TODO: Change these clamp ranges to be the map range, ie. map.x min map.x + map.w max
	//map.y min map.y + map.h max
	testPos.x = Math::Clamp(testPos.x, 0.0, 320.0);
	testPos.y = Math::Clamp(testPos.y, 0.0, 320.0);

	//x axis collision checks
	if (CheckCollision(Rectf(testPos.x, mBox.Y(), mBox.W(), mBox.H()))){
	}
	else
		mBox.Set(testPos.x, mBox.Y());
	//y axis collision checks
	if (CheckCollision(Rectf(mBox.X(), testPos.y, mBox.W(), mBox.H()))){
	}
	else
		mBox.Set(mBox.X(), testPos.y);

	//mMotionState.UpdateState(mKinematic);
}
void Physics::UpdateVelocity(float deltaT){
	ApplyAcceleration();
	ApplyFriction();
	//if applying the friction would cause the velocity to flip signs, set velocity to 0
	if (mHorizDir == MOVE::STOP && ((mKinematic.Vel.x + mKinematic.Accel.x * deltaT > 0.0 && mKinematic.Vel.x < 0.0)
		|| (mKinematic.Vel.x + mKinematic.Accel.x * deltaT < 0.0 && mKinematic.Vel.x > 0.0)))
			mKinematic.Vel.x = 0.0;
	else
		mKinematic.Vel.x += mKinematic.Accel.x * deltaT;
	//same for y
	if (mVertDir == MOVE::STOP && ((mKinematic.Vel.y + mKinematic.Accel.y * deltaT > 0.0 && mKinematic.Vel.y < 0.0)
		|| (mKinematic.Vel.y + mKinematic.Accel.y * deltaT < 0.0 && mKinematic.Vel.y > 0.0)))
			mKinematic.Vel.y = 0.0;
	else
		mKinematic.Vel.y += mKinematic.Accel.y * deltaT;

	//limit velocity
	if ((mKinematic.Vel.x > mPhysConstants.hSpeed) || (mKinematic.Vel.x < -mPhysConstants.hSpeed))
		mKinematic.Vel.x = mPhysConstants.hSpeed * (mKinematic.Vel.x / abs(mKinematic.Vel.x));
	//for y as well
	if ((mKinematic.Vel.y > mPhysConstants.hSpeed) || (mKinematic.Vel.y < -mPhysConstants.hSpeed))
		mKinematic.Vel.y = mPhysConstants.hSpeed * (mKinematic.Vel.y / abs(mKinematic.Vel.y));
}
void Physics::ApplyAcceleration(){
	if (mHorizDir == Math::RIGHT)
		mKinematic.Accel.x = mPhysConstants.hAccel;
	else if (mHorizDir == Math::LEFT)
		mKinematic.Accel.x = -mPhysConstants.hAccel;
	else
		mKinematic.Accel.x = 0;
	if (mVertDir == Math::UP)
		mKinematic.Accel.y = -mPhysConstants.hAccel;
	else if (mVertDir == Math::DOWN)
		mKinematic.Accel.y = mPhysConstants.hAccel;
	else
		mKinematic.Accel.y = 0;
}
void Physics::ApplyFriction(){
	if (mHorizDir == MOVE::STOP && mKinematic.Vel.x != 0.0){
		mKinematic.Accel.x += GROUND_FRICTION * (-mKinematic.Vel.x / abs(mKinematic.Vel.x));
	}
	if (mVertDir == MOVE::STOP && mKinematic.Vel.y != 0.0){
		mKinematic.Accel.y += GROUND_FRICTION * (-mKinematic.Vel.y / abs(mKinematic.Vel.y));
	}
}
bool Physics::CheckCollision(Rectf box){
	//We wait to exit the loop until we've found the collision direction and
	//checked it against our movement direction to set v to 0 if moving in direction of
	//the collision
	bool colliding = false;
	for (Recti i : mCollisionMap){
		if (Math::CheckCollision(box, i)){
			colliding = true;
			//Check collision direction against movement directions
			int colDir = Math::RectNearRect(box, i, 15);
			if (mHorizDir == colDir){
				mKinematic.Vel.x = 0;
				return colliding;
			}
			if (mVertDir == colDir){
				mKinematic.Vel.y = 0;
				return colliding;
			}
		}
	}
	return colliding;
}

Vector2f Physics::Position() const{
	return mBox.Pos();
}
Vector2f Physics::Velocity() const{
	return mKinematic.Vel;
}
Vector2f Physics::Acceleration() const{
	return mKinematic.Accel;
}
Rectf Physics::Box() const{
	return mBox;
}
int Physics::MotionState() const{
//	return mMotionState.GetMotionState();
	return 0;
}
void Physics::SetPosition(Vector2f pos){
	mBox.Set(pos);
}
void Physics::SetVelocity(Vector2f vel){
	mKinematic.Vel = vel;
}
void Physics::SetAcceleration(Vector2f accel){
	mKinematic.Accel = accel;
}
void Physics::SetHorizDir(int moveDir){
	if (moveDir == Math::UP || moveDir == Math::DOWN)
		throw std::runtime_error("Bad Horizontal Direction");
	mHorizDir = moveDir;
}
void Physics::SetVertDir(int moveDir){
	if (moveDir == Math::LEFT || moveDir == Math::RIGHT)
		throw std::runtime_error("Bad Vertical Direction");
	mVertDir = moveDir;
}
void Physics::SetPhysConstants(PhysicalConstants physConstants){
	mPhysConstants = physConstants;
}
void Physics::SetBox(Rectf box){
	mBox = box;
}
void Physics::SetMap(CollisionMap map){
	mCollisionMap = map;
}
Json::Value Physics::Save(){
	//Save the object's physical constants and box
	Json::Value val;
	val["box"] 	  = mBox.Save();
	val["hSpeed"] = mPhysConstants.hSpeed;
	val["hAccel"] = mPhysConstants.hAccel;
	return val;
}
void Physics::Load(Json::Value val){
	mBox.Load(val["box"]);
	mPhysConstants.hAccel = val["hAccel"].asInt();
	mPhysConstants.hSpeed = val["hSpeed"].asInt();

	//Setup motion values
	mKinematic.Vel	 = Vector2f(0, 0);
	mKinematic.Accel = Vector2f(0, 0);
	mHorizDir = MOVE::STOP;
	mVertDir  = MOVE::STOP;
}
void Physics::RegisterLua(lua_State *l){
	using namespace luabind;

	module(l, "LPC")[
		class_<Physics>("Physics")
			.def(constructor<>())
			.def("Move", &Physics::Move)
			.def("Position", &Physics::Position)
			.def("Velocity", &Physics::Velocity)
			.def("Acceleration", &Physics::Acceleration)
	];
}<commit_msg>uncommented MotionState usage in Physics<commit_after>#include <luabind/luabind.hpp>
#include "../externals/json/json.h"
#include "math.h"
#include "motionstate.h"
#include "physics.h"

Physics::Physics(){
	mKinematic.Vel	 = Vector2f(0, 0);
	mKinematic.Accel = Vector2f(0, 0);
	mHorizDir = MOVE::STOP;
	mVertDir  = MOVE::STOP;
}
Physics::~Physics(){}
void Physics::Move(float deltaT){
	//Update the velocity
	UpdateVelocity(deltaT);
	//test if the move is ok before applying changes
	Vector2f testPos;
	testPos = mBox.Pos() + (mKinematic.Vel * deltaT);

	//Clamp the test position x & y
	//TODO: Change these clamp ranges to be the map range, ie. map.x min map.x + map.w max
	//map.y min map.y + map.h max
	testPos.x = Math::Clamp(testPos.x, 0.0, 320.0);
	testPos.y = Math::Clamp(testPos.y, 0.0, 320.0);

	//x axis collision checks
	if (CheckCollision(Rectf(testPos.x, mBox.Y(), mBox.W(), mBox.H()))){
	}
	else
		mBox.Set(testPos.x, mBox.Y());
	//y axis collision checks
	if (CheckCollision(Rectf(mBox.X(), testPos.y, mBox.W(), mBox.H()))){
	}
	else
		mBox.Set(mBox.X(), testPos.y);

	mMotionState.UpdateState(mKinematic);
}
void Physics::UpdateVelocity(float deltaT){
	ApplyAcceleration();
	ApplyFriction();
	//if applying the friction would cause the velocity to flip signs, set velocity to 0
	if (mHorizDir == MOVE::STOP && ((mKinematic.Vel.x + mKinematic.Accel.x * deltaT > 0.0 && mKinematic.Vel.x < 0.0)
		|| (mKinematic.Vel.x + mKinematic.Accel.x * deltaT < 0.0 && mKinematic.Vel.x > 0.0)))
			mKinematic.Vel.x = 0.0;
	else
		mKinematic.Vel.x += mKinematic.Accel.x * deltaT;
	//same for y
	if (mVertDir == MOVE::STOP && ((mKinematic.Vel.y + mKinematic.Accel.y * deltaT > 0.0 && mKinematic.Vel.y < 0.0)
		|| (mKinematic.Vel.y + mKinematic.Accel.y * deltaT < 0.0 && mKinematic.Vel.y > 0.0)))
			mKinematic.Vel.y = 0.0;
	else
		mKinematic.Vel.y += mKinematic.Accel.y * deltaT;

	//limit velocity
	if ((mKinematic.Vel.x > mPhysConstants.hSpeed) || (mKinematic.Vel.x < -mPhysConstants.hSpeed))
		mKinematic.Vel.x = mPhysConstants.hSpeed * (mKinematic.Vel.x / abs(mKinematic.Vel.x));
	//for y as well
	if ((mKinematic.Vel.y > mPhysConstants.hSpeed) || (mKinematic.Vel.y < -mPhysConstants.hSpeed))
		mKinematic.Vel.y = mPhysConstants.hSpeed * (mKinematic.Vel.y / abs(mKinematic.Vel.y));
}
void Physics::ApplyAcceleration(){
	if (mHorizDir == Math::RIGHT)
		mKinematic.Accel.x = mPhysConstants.hAccel;
	else if (mHorizDir == Math::LEFT)
		mKinematic.Accel.x = -mPhysConstants.hAccel;
	else
		mKinematic.Accel.x = 0;
	if (mVertDir == Math::UP)
		mKinematic.Accel.y = -mPhysConstants.hAccel;
	else if (mVertDir == Math::DOWN)
		mKinematic.Accel.y = mPhysConstants.hAccel;
	else
		mKinematic.Accel.y = 0;
}
void Physics::ApplyFriction(){
	if (mHorizDir == MOVE::STOP && mKinematic.Vel.x != 0.0){
		mKinematic.Accel.x += GROUND_FRICTION * (-mKinematic.Vel.x / abs(mKinematic.Vel.x));
	}
	if (mVertDir == MOVE::STOP && mKinematic.Vel.y != 0.0){
		mKinematic.Accel.y += GROUND_FRICTION * (-mKinematic.Vel.y / abs(mKinematic.Vel.y));
	}
}
bool Physics::CheckCollision(Rectf box){
	//We wait to exit the loop until we've found the collision direction and
	//checked it against our movement direction to set v to 0 if moving in direction of
	//the collision
	bool colliding = false;
	for (Recti i : mCollisionMap){
		if (Math::CheckCollision(box, i)){
			colliding = true;
			//Check collision direction against movement directions
			int colDir = Math::RectNearRect(box, i, 15);
			if (mHorizDir == colDir){
				mKinematic.Vel.x = 0;
				return colliding;
			}
			if (mVertDir == colDir){
				mKinematic.Vel.y = 0;
				return colliding;
			}
		}
	}
	return colliding;
}

Vector2f Physics::Position() const{
	return mBox.Pos();
}
Vector2f Physics::Velocity() const{
	return mKinematic.Vel;
}
Vector2f Physics::Acceleration() const{
	return mKinematic.Accel;
}
Rectf Physics::Box() const{
	return mBox;
}
int Physics::MotionState() const{
	return mMotionState.GetMotionState();
}
void Physics::SetPosition(Vector2f pos){
	mBox.Set(pos);
}
void Physics::SetVelocity(Vector2f vel){
	mKinematic.Vel = vel;
}
void Physics::SetAcceleration(Vector2f accel){
	mKinematic.Accel = accel;
}
void Physics::SetHorizDir(int moveDir){
	if (moveDir == Math::UP || moveDir == Math::DOWN)
		throw std::runtime_error("Bad Horizontal Direction");
	mHorizDir = moveDir;
}
void Physics::SetVertDir(int moveDir){
	if (moveDir == Math::LEFT || moveDir == Math::RIGHT)
		throw std::runtime_error("Bad Vertical Direction");
	mVertDir = moveDir;
}
void Physics::SetPhysConstants(PhysicalConstants physConstants){
	mPhysConstants = physConstants;
}
void Physics::SetBox(Rectf box){
	mBox = box;
}
void Physics::SetMap(CollisionMap map){
	mCollisionMap = map;
}
Json::Value Physics::Save(){
	//Save the object's physical constants and box
	Json::Value val;
	val["box"] 	  = mBox.Save();
	val["hSpeed"] = mPhysConstants.hSpeed;
	val["hAccel"] = mPhysConstants.hAccel;
	return val;
}
void Physics::Load(Json::Value val){
	mBox.Load(val["box"]);
	mPhysConstants.hAccel = val["hAccel"].asInt();
	mPhysConstants.hSpeed = val["hSpeed"].asInt();

	//Setup motion values
	mKinematic.Vel	 = Vector2f(0, 0);
	mKinematic.Accel = Vector2f(0, 0);
	mHorizDir = MOVE::STOP;
	mVertDir  = MOVE::STOP;
}
void Physics::RegisterLua(lua_State *l){
	using namespace luabind;

	module(l, "LPC")[
		class_<Physics>("Physics")
			.def(constructor<>())
			.def("Move", &Physics::Move)
			.def("Position", &Physics::Position)
			.def("Velocity", &Physics::Velocity)
			.def("Acceleration", &Physics::Acceleration)
			.def("Box", &Physics::Box)
			.def("MotionState", &Physics::MotionState)
			.def("SetPosition", &Physics::SetPosition)
			.def("SetVelocity", &Physics::SetVelocity)
	];
}<|endoftext|>


<commit_before>/*
 The MIT License (MIT)

 Copyright (c) [2016] [BTC.COM]

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

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

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

#include "gtest/gtest.h"
#include "Common.h"
#include "Utils.h"

#include "StratumServer.h"

// #include "Kafka.h"

#ifndef WORK_WITH_STRATUM_SWITCHER

TEST(StratumServer, SessionIDManager24Bits) {
  // KafkaProducer a("", "", 0);
  // a.produce("", 0);

  SessionIDManagerT<24> m(0xFFu);
  uint32_t j, sessionID;

  // fill all session ids
  for (uint32_t i = 0; i <= 0x00FFFFFFu; i++) {
    uint32_t id = (0xFFu << 24) | i;
    ASSERT_EQ(m.allocSessionId(&sessionID), true);
    ASSERT_EQ(sessionID, id);
  }
  ASSERT_EQ(m.ifFull(), true);

  // free the fisrt one
  j = 0xFF000000u;
  m.freeSessionId(j);
  ASSERT_EQ(m.ifFull(), false);
  ASSERT_EQ(m.allocSessionId(&sessionID), true);
  ASSERT_EQ(sessionID, j);
  ASSERT_EQ(m.ifFull(), true);

  // free the last one
  j = 0xFFFFFFFFu;
  m.freeSessionId(j);
  ASSERT_EQ(m.ifFull(), false);
  ASSERT_EQ(m.allocSessionId(&sessionID), true);
  ASSERT_EQ(sessionID, j);
  ASSERT_EQ(m.ifFull(), true);
}

TEST(StratumServer, SessionIDManager16Bits) {
  SessionIDManagerT<16> m(0x99u);
  uint32_t j, sessionID;

  // fill all session ids
  for (uint32_t i = 0; i <= 0x0000FFFFu; i++) {
    uint32_t id = (0x99u << 16) | i;
    ASSERT_EQ(m.allocSessionId(&sessionID), true);
    ASSERT_EQ(sessionID, id);
  }
  ASSERT_EQ(m.ifFull(), true);

  // free the fisrt one
  j = 0x00990000u;
  m.freeSessionId(j);
  ASSERT_EQ(m.ifFull(), false);
  ASSERT_EQ(m.allocSessionId(&sessionID), true);
  ASSERT_EQ(sessionID, j);
  ASSERT_EQ(m.ifFull(), true);

  // free the last one
  j = 0x0099FFFFu;
  m.freeSessionId(j);
  ASSERT_EQ(m.ifFull(), false);
  ASSERT_EQ(m.allocSessionId(&sessionID), true);
  ASSERT_EQ(sessionID, j);
  ASSERT_EQ(m.ifFull(), true);
}

TEST(StratumServer, SessionIDManager16BitsWithInterval) {
  SessionIDManagerT<16> m(0x99u);
  m.setAllocInterval(256);

  uint32_t j, sessionID;

  // fill all session ids
  // Use std::vector<bool> because the compile time of
  // std::bitset<0x100000000ull> is too long.
  {
    std::vector<bool> ids(0x100000000ull);
    for (uint32_t i = 0; i <= 0x0000FFFFu; i++) {
      ASSERT_EQ(m.allocSessionId(&sessionID), true);
      ASSERT_EQ(ids[sessionID], false);
      ids[sessionID] = true;
    }
    ASSERT_EQ(m.ifFull(), true);
  }

  // free the fisrt one
  {
    j = 0x00990000u;
    m.freeSessionId(j);
    ASSERT_EQ(m.ifFull(), false);
    ASSERT_EQ(m.allocSessionId(&sessionID), true);
    ASSERT_EQ(sessionID, j);
    ASSERT_EQ(m.ifFull(), true);
  }

  // free the last one
  {
    j = 0x0099FFFFu;
    m.freeSessionId(j);
    ASSERT_EQ(m.ifFull(), false);
    ASSERT_EQ(m.allocSessionId(&sessionID), true);
    ASSERT_EQ(sessionID, j);
    ASSERT_EQ(m.ifFull(), true);
  }

  // free all
  for (uint32_t i = 0x00990000u; i <= 0x0099FFFFu; i++) {
    m.freeSessionId(i);
  }

  // fill all again
  {
    std::vector<bool> ids(0x100000000ull);
    for (uint32_t i = 0; i <= 0x0000FFFFu; i++) {
      ASSERT_EQ(m.allocSessionId(&sessionID), true);
      ASSERT_EQ(ids[sessionID], false);
      ids[sessionID] = true;
    }
    ASSERT_EQ(m.ifFull(), true);
  }
}

TEST(StratumServer, SessionIDManager8Bits) {
  SessionIDManagerT<8> m(0x68u);
  uint32_t j, sessionID;

  // fill all session ids
  for (uint32_t i = 0; i <= 0x000000FFu; i++) {
    uint32_t id = (0x68u << 8) | i;
    ASSERT_EQ(m.allocSessionId(&sessionID), true);
    ASSERT_EQ(sessionID, id);
  }
  ASSERT_EQ(m.ifFull(), true);

  // free the fisrt one
  j = 0x00006800u;
  m.freeSessionId(j);
  ASSERT_EQ(m.ifFull(), false);
  ASSERT_EQ(m.allocSessionId(&sessionID), true);
  ASSERT_EQ(sessionID, j);
  ASSERT_EQ(m.ifFull(), true);

  // free the last one
  j = 0x000068FFu;
  m.freeSessionId(j);
  ASSERT_EQ(m.ifFull(), false);
  ASSERT_EQ(m.allocSessionId(&sessionID), true);
  ASSERT_EQ(sessionID, j);
  ASSERT_EQ(m.ifFull(), true);
}

#endif // #ifndef WORK_WITH_STRATUM_SWITCHER
<commit_msg>add a testcase for StratumServerBitcoin::checkShare()<commit_after>/*
 The MIT License (MIT)

 Copyright (c) [2016] [BTC.COM]

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

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

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

#include "gtest/gtest.h"
#include "Common.h"
#include "Utils.h"

#include "StratumServer.h"
#include "bitcoin/BitcoinUtils.h"
#include "bitcoin/StratumBitcoin.h"
#include "bitcoin/StratumServerBitcoin.h"

// #include "Kafka.h"

#ifndef WORK_WITH_STRATUM_SWITCHER

TEST(StratumServer, SessionIDManager24Bits) {
  // KafkaProducer a("", "", 0);
  // a.produce("", 0);

  SessionIDManagerT<24> m(0xFFu);
  uint32_t j, sessionID;

  // fill all session ids
  for (uint32_t i = 0; i <= 0x00FFFFFFu; i++) {
    uint32_t id = (0xFFu << 24) | i;
    ASSERT_EQ(m.allocSessionId(&sessionID), true);
    ASSERT_EQ(sessionID, id);
  }
  ASSERT_EQ(m.ifFull(), true);

  // free the fisrt one
  j = 0xFF000000u;
  m.freeSessionId(j);
  ASSERT_EQ(m.ifFull(), false);
  ASSERT_EQ(m.allocSessionId(&sessionID), true);
  ASSERT_EQ(sessionID, j);
  ASSERT_EQ(m.ifFull(), true);

  // free the last one
  j = 0xFFFFFFFFu;
  m.freeSessionId(j);
  ASSERT_EQ(m.ifFull(), false);
  ASSERT_EQ(m.allocSessionId(&sessionID), true);
  ASSERT_EQ(sessionID, j);
  ASSERT_EQ(m.ifFull(), true);
}

TEST(StratumServer, SessionIDManager16Bits) {
  SessionIDManagerT<16> m(0x99u);
  uint32_t j, sessionID;

  // fill all session ids
  for (uint32_t i = 0; i <= 0x0000FFFFu; i++) {
    uint32_t id = (0x99u << 16) | i;
    ASSERT_EQ(m.allocSessionId(&sessionID), true);
    ASSERT_EQ(sessionID, id);
  }
  ASSERT_EQ(m.ifFull(), true);

  // free the fisrt one
  j = 0x00990000u;
  m.freeSessionId(j);
  ASSERT_EQ(m.ifFull(), false);
  ASSERT_EQ(m.allocSessionId(&sessionID), true);
  ASSERT_EQ(sessionID, j);
  ASSERT_EQ(m.ifFull(), true);

  // free the last one
  j = 0x0099FFFFu;
  m.freeSessionId(j);
  ASSERT_EQ(m.ifFull(), false);
  ASSERT_EQ(m.allocSessionId(&sessionID), true);
  ASSERT_EQ(sessionID, j);
  ASSERT_EQ(m.ifFull(), true);
}

TEST(StratumServer, SessionIDManager16BitsWithInterval) {
  SessionIDManagerT<16> m(0x99u);
  m.setAllocInterval(256);

  uint32_t j, sessionID;

  // fill all session ids
  // Use std::vector<bool> because the compile time of
  // std::bitset<0x100000000ull> is too long.
  {
    std::vector<bool> ids(0x100000000ull);
    for (uint32_t i = 0; i <= 0x0000FFFFu; i++) {
      ASSERT_EQ(m.allocSessionId(&sessionID), true);
      ASSERT_EQ(ids[sessionID], false);
      ids[sessionID] = true;
    }
    ASSERT_EQ(m.ifFull(), true);
  }

  // free the fisrt one
  {
    j = 0x00990000u;
    m.freeSessionId(j);
    ASSERT_EQ(m.ifFull(), false);
    ASSERT_EQ(m.allocSessionId(&sessionID), true);
    ASSERT_EQ(sessionID, j);
    ASSERT_EQ(m.ifFull(), true);
  }

  // free the last one
  {
    j = 0x0099FFFFu;
    m.freeSessionId(j);
    ASSERT_EQ(m.ifFull(), false);
    ASSERT_EQ(m.allocSessionId(&sessionID), true);
    ASSERT_EQ(sessionID, j);
    ASSERT_EQ(m.ifFull(), true);
  }

  // free all
  for (uint32_t i = 0x00990000u; i <= 0x0099FFFFu; i++) {
    m.freeSessionId(i);
  }

  // fill all again
  {
    std::vector<bool> ids(0x100000000ull);
    for (uint32_t i = 0; i <= 0x0000FFFFu; i++) {
      ASSERT_EQ(m.allocSessionId(&sessionID), true);
      ASSERT_EQ(ids[sessionID], false);
      ids[sessionID] = true;
    }
    ASSERT_EQ(m.ifFull(), true);
  }
}

TEST(StratumServer, SessionIDManager8Bits) {
  SessionIDManagerT<8> m(0x68u);
  uint32_t j, sessionID;

  // fill all session ids
  for (uint32_t i = 0; i <= 0x000000FFu; i++) {
    uint32_t id = (0x68u << 8) | i;
    ASSERT_EQ(m.allocSessionId(&sessionID), true);
    ASSERT_EQ(sessionID, id);
  }
  ASSERT_EQ(m.ifFull(), true);

  // free the fisrt one
  j = 0x00006800u;
  m.freeSessionId(j);
  ASSERT_EQ(m.ifFull(), false);
  ASSERT_EQ(m.allocSessionId(&sessionID), true);
  ASSERT_EQ(sessionID, j);
  ASSERT_EQ(m.ifFull(), true);

  // free the last one
  j = 0x000068FFu;
  m.freeSessionId(j);
  ASSERT_EQ(m.ifFull(), false);
  ASSERT_EQ(m.allocSessionId(&sessionID), true);
  ASSERT_EQ(sessionID, j);
  ASSERT_EQ(m.ifFull(), true);
}

#endif // #ifndef WORK_WITH_STRATUM_SWITCHER

TEST(StratumServerBitcoin, CheckShare) {
  string sjobJson = "{\"jobId\":6645522065066147329,\"gbtHash\":\"d349be274f007c2e1ee773b33bd21ef43d2615c089b7c5460b66584881a10683\","
  "\"prevHash\":\"00000000000000000019d1d9c84df0ecc23e549b86644ad47cb92570a26b12a5\",\"prevHashBeStr\":\"a26b12a57cb9257086644ad4c23e"
  "549bc84df0ec0019d1d90000000000000000\",\"height\":558201,\"coinbase1\":\"020000000100000000000000000000000000000000000000000000000"
  "00000000000000000ffffffff4b03798408041ba3395c612f4254432e434f4d2ffabe6d6dc807e51bd76025d65ccad2ba8ba1e9fba5f09118b6b55a348638cc17b"
  "14e3909080000005fb54ad0\",\"coinbase2\":\"ffffffff036734ec4a0000000016001497cfc76442fe717f2a3f0cc9c175f7561b6619970000000000000000"
  "266a24aa21a9ed40cbdaa98da815640f815b938df95bffe0775d8078771bc47ed4f43ac4e30b0600000000000000002952534b424c4f434b3a9ad45fdcc194d788"
  "895f3ad389b583ea327f826353f7edf6b168db038372cb2700000000\",\"merkleBranch\":\"53146311555e15816f4549a893ff2eb50e60741ecccb2996bafd"
  "dcf4ee008d5ac504967e375b2522af2be8411b1b032dda0e700c2e8913d869533256ff30caccea4ba404b68e625cfd3237e07e8deddb342690b08314d2638b5272"
  "b74ab12fa3b3812908cd6bef999dea979875ba2730615be08b480e4b6f7b878000510a778c557f44bc3f21813d138d25530df85a89a38e2d2827f758ebc68a62e8"
  "225933a5af086e72d9a65fd9be526648e8bcf74271308d9d273425b47bd12db075e841ba703f4c8a20be62d036958278b16f214d7fcd35c46a9f9fb1910618fa9e"
  "029d3f96518aae34efbdabfbfbc055bffe891d93edbc7539ae9c0a22a35e87d5ccb033b89976cbb624af024b53c6a02309cb838eb285ecf675b801f1dd7f2d5c92"
  "4cb1491731c28bea800b12b94bb4f70502a40559c8edb5f73b906ba8e814f10e852ef87365a49346c4b7361b75e38f1d9b96f028880227b7186a0b114e170b170b"
  "47\",\"nVersion\":536870912,\"nBits\":389159077,\"nTime\":1547281171,\"minTime\":1547277926,\"coinbaseValue\":1256993895,\"witness"
  "Commitment\":\"6a24aa21a9ed40cbdaa98da815640f815b938df95bffe0775d8078771bc47ed4f43ac4e30b06\",\"nmcBlockHash\":\"c807e51bd76025d65"
  "ccad2ba8ba1e9fba5f09118b6b55a348638cc17b14e3909\",\"nmcBits\":402868319,\"nmcHeight\":433937,\"nmcRpcAddr\":\"http://127.0.0.1:899"
  "9\",\"nmcRpcUserpass\":\"user:pass\",\"rskBlockHashForMergedMining\":\"0x9ad45fdcc194d788895f3ad389b583ea327f826353f7edf6b168db038"
  "372cb27\",\"rskNetworkTarget\":\"0x00000000000000001386e3444eba74f8a750a71a75ed0b7fecdfd282a8cef091\",\"rskFeesForMiner\":\"0\",\""
  "rskdRpcAddress\":\"http://127.0.0.1:4444\",\"rskdRpcUserPwd\":\"user:pass\",\"isRskCleanJob\":true}";

  StratumJobBitcoin *sjob = new StratumJobBitcoin();
  sjob->unserializeFromJson(sjobJson.c_str(), sjobJson.size());

  StratumJobExBitcoin exjob(sjob, true);

  CBlockHeader header;
  std::vector<char> coinbaseBin;

  exjob.generateBlockHeader(
    &header, &coinbaseBin,
    0xfe0000c3u, "260103fe60004690",
    sjob->merkleBranch_, sjob->prevHash_,
    sjob->nBits_, sjob->nVersion_,
    0x5c39a313u, 0x07ba7929u,
    0x00013f00u
  );

  uint256 blkHash = uint256S("1028e53e8145994a9ebe4f39eb6a7e3fd4036f2f21a05a5a696e8ac6d0829ef4");
  ASSERT_EQ(blkHash, header.GetHash());
}
<|endoftext|>


<commit_before>#ifndef XPATHIC_MATCH_TEST_HPP
#define XPATHIC_MATCH_TEST_HPP

#include "../CppUnit/framework/TestCase.h"
#include "../CppUnit/framework/TestSuite.h"
#include "../CppUnit/framework/TestCaller.h"

#include <XPath/XPath.hpp>
#include <DOM/Simple/DOMImplementation.h>

template<class string_type, class string_adaptor>
class MatchTest : public TestCase
{
  Arabica::XPath::XPath<string_type> parser;
  typedef string_adaptor SA;

public:
  MatchTest(std::string name) : TestCase(name)
  {
  } // MatchTest

  void setUp()
  {
  } // setUp

  void testParse()
  {
    using namespace Arabica::XPath;
    assertTrue(compileThis("/"));
    assertTrue(compileThis("/element"));
    assertTrue(compileThis("//element"));
    assertTrue(compileThis("node()"));
    assertTrue(compileThis("text()"));
    assertTrue(compileThis("element"));
    assertTrue(compileThis("element/child"));
    assertTrue(compileThis("/element/child"));
    assertTrue(compileThis("//element/child"));
    assertTrue(compileThis("/element//child"));
    assertTrue(compileThis("//element//child"));
    assertTrue(compileThis("element/child/child"));
    assertTrue(compileThis("/element/child/child"));
    assertTrue(compileThis("//element/child/child"));
    assertTrue(compileThis("/element//child/child"));
    assertTrue(compileThis("//element//child/child"));
    assertTrue(compileThis("//element//child//child"));
    assertTrue(compileThis("element[@ref]"));
    assertTrue(compileThis("element[@type]|element[complexType]|attribute"));
    assertTrue(compileThis("node()|@*"));
    assertTrue(compileThis("hello"));
    assertTrue(compileThis("@hello"));
    assertTrue(compileThis("child::hello"));
    assertTrue(compileThis("attribute::hello"));
    assertTrue(compileThis("hello[@ref]"));
    assertTrue(compileThis("@hello[../poop]"));
    assertTrue(compileThis("child::hello[../poop]"));
    assertTrue(compileThis("attribute::hello[../poop]"));
    assertTrue(compileThis("node()|attribute::*"));
  } // testParse

  void testParseFails()
  {
    using namespace Arabica::XPath;
    assertTrue(dontCompileThis("boolean(../hello)"));
    assertTrue(dontCompileThis("../hello"));
    assertTrue(dontCompileThis("following-sibling::hello"));
    assertTrue(dontCompileThis("descendant::hello"));
    assertTrue(dontCompileThis("ancestor-or-self::hello"));
    assertTrue(dontCompileThis("///"));
    assertTrue(dontCompileThis("test///test"));
    assertTrue(dontCompileThis("descendant-or-self::element"));
    assertTrue(dontCompileThis("//element/following-sibling::trousers"));
  } // testParseFails

  bool dontCompileThis(const char* path)
  {
    try {
      parser.compile_match(SA::construct_from_utf8(path));
      return false;
    }
    catch(const Arabica::XPath::SyntaxException& ex) {
      std::cerr << ex.what() << std::endl;
    }
    return true;
  } // dontCompileThis

  bool compileThis(const char* path)
  {
    try {
      std::cout << "\n-----\n" << path << "\n";
      parser.compile_match(SA::construct_from_utf8(path));
      return true;
    }
    catch(const Arabica::XPath::UnsupportedException&) {
      return true;
    }
    catch(const Arabica::XPath::SyntaxException& ex) {
      std::cerr << ex.what() << std::endl;
    }
    return false;
  } // compileThis

}; // class MatchTest

template<class string_type, class string_adaptor>
TestSuite* MatchTest_suite()
{
  TestSuite *suiteOfTests = new TestSuite;

  suiteOfTests->addTest(new TestCaller<MatchTest<string_type, string_adaptor> >("testParse", &MatchTest<string_type, string_adaptor>::testParse));
  suiteOfTests->addTest(new TestCaller<MatchTest<string_type, string_adaptor> >("testParseFail", &MatchTest<string_type, string_adaptor>::testParseFails));

  return suiteOfTests;
} // MatchTest_suite

#endif

<commit_msg>started evaluating matches<commit_after>#ifndef XPATHIC_MATCH_TEST_HPP
#define XPATHIC_MATCH_TEST_HPP

#include "../CppUnit/framework/TestCase.h"
#include "../CppUnit/framework/TestSuite.h"
#include "../CppUnit/framework/TestCaller.h"

#include <XPath/XPath.hpp>
#include <DOM/SAX2DOM/SAX2DOM.h>
#include <SAX/helpers/CatchErrorHandler.h>

template<class string_type, class string_adaptor>
class MatchTest : public TestCase
{
  Arabica::XPath::XPath<string_type> parser;
  typedef string_adaptor SA;

public:
  MatchTest(std::string name) : TestCase(name)
  {
  } // MatchTest

  void setUp()
  {
  } // setUp

  void testParse()
  {
    using namespace Arabica::XPath;
    assertTrue(compileThis("/"));
    assertTrue(compileThis("/element"));
    assertTrue(compileThis("//element"));
    assertTrue(compileThis("node()"));
    assertTrue(compileThis("text()"));
    assertTrue(compileThis("element"));
    assertTrue(compileThis("element/child"));
    assertTrue(compileThis("/element/child"));
    assertTrue(compileThis("//element/child"));
    assertTrue(compileThis("/element//child"));
    assertTrue(compileThis("//element//child"));
    assertTrue(compileThis("element/child/child"));
    assertTrue(compileThis("/element/child/child"));
    assertTrue(compileThis("//element/child/child"));
    assertTrue(compileThis("/element//child/child"));
    assertTrue(compileThis("//element//child/child"));
    assertTrue(compileThis("//element//child//child"));
    assertTrue(compileThis("element[@ref]"));
    assertTrue(compileThis("element[@type]|element[complexType]|attribute"));
    assertTrue(compileThis("node()|@*"));
    assertTrue(compileThis("hello"));
    assertTrue(compileThis("doc"));
    assertTrue(compileThis("@hello"));
    assertTrue(compileThis("child::hello"));
    assertTrue(compileThis("attribute::hello"));
    assertTrue(compileThis("hello[@ref]"));
    assertTrue(compileThis("@hello[../poop]"));
    assertTrue(compileThis("child::hello[../poop]"));
    assertTrue(compileThis("attribute::hello[../poop]"));
    assertTrue(compileThis("node()|attribute::*"));
  } // testParse

  void testParseFails()
  {
    using namespace Arabica::XPath;
    assertTrue(dontCompileThis("boolean(../hello)"));
    assertTrue(dontCompileThis("../hello"));
    assertTrue(dontCompileThis("following-sibling::hello"));
    assertTrue(dontCompileThis("descendant::hello"));
    assertTrue(dontCompileThis("ancestor-or-self::hello"));
    assertTrue(dontCompileThis("///"));
    assertTrue(dontCompileThis("test///test"));
    assertTrue(dontCompileThis("descendant-or-self::element"));
    assertTrue(dontCompileThis("//element/following-sibling::trousers"));
  } // testParseFails

  void testEvaluateDocMatch()
  {
    DOM::Document<string_type> doc = parseXML("<doc><para>hello</para></doc>");
    assertTrue(compileMatch("/")->evaluateAsBool(doc));
  } // testEvaluateDocMatch

  void testDocElementMatch()
  {
    DOM::Document<string_type> doc = parseXML("<doc><para>hello</para></doc>");

    assertTrue(compileMatch("doc")->evaluateAsBool(doc.getDocumentElement()));
    assertTrue(compileMatch("doc[para]")->evaluateAsBool(doc.getDocumentElement()));
    assertTrue(compileMatch("*")->evaluateAsBool(doc.getDocumentElement()));
    assertTrue(compileMatch("node()")->evaluateAsBool(doc.getDocumentElement()));
    assertTrue(compileMatch("/doc")->evaluateAsBool(doc.getDocumentElement()));
    assertTrue(compileMatch("//doc")->evaluateAsBool(doc.getDocumentElement()));
  } // testDocElementMatch

  void testDocElementNotMatch()
  {
    DOM::Document<string_type> doc = parseXML("<doc><para>hello</para></doc>");

    assertFalse(compileMatch("para")->evaluateAsBool(doc.getDocumentElement()));
    assertFalse(compileMatch("text()")->evaluateAsBool(doc.getDocumentElement()));
    assertFalse(compileMatch("comment()")->evaluateAsBool(doc.getDocumentElement()));
    assertFalse(compileMatch("processing-instruction()")->evaluateAsBool(doc.getDocumentElement()));
    assertFalse(compileMatch("/para")->evaluateAsBool(doc.getDocumentElement()));
    assertFalse(compileMatch("//para")->evaluateAsBool(doc.getDocumentElement()));
  } // testDocElementNotMatch

  bool dontCompileThis(const char* path)
  {
    try {
      compileMatch(path);
      return false;
    }
    catch(const Arabica::XPath::SyntaxException& ex) {
      std::cerr << ex.what() << std::endl;
    }
    return true;
  } // dontCompileThis

  bool compileThis(const char* path)
  {
    try {
      std::cout << "\n-----\n" << path << "\n";
      compileMatch(path);
      return true;
    }
    catch(const Arabica::XPath::UnsupportedException&) {
      return true;
    }
    catch(const Arabica::XPath::SyntaxException& ex) {
      std::cerr << ex.what() << std::endl;
    }
    return false;
  } // compileThis

  Arabica::XPath::XPathExpressionPtr<string_type, string_adaptor> compileMatch(const char* match)
  {
    return parser.compile_match(SA::construct_from_utf8(match));
  } // compileMatch

  DOM::Document<string_type> parseXML(const char* match)
  {
    std::stringstream ss;
    ss << match;

    SAX::basic_InputSource<string_type> is(ss);
    SAX::CatchErrorHandler<string_type> eh;
    SAX2DOM::Parser<string_type, string_adaptor> parser;
    parser.setErrorHandler(eh);
    parser.parse(is);

    if(eh.errorsReported())
      throw std::runtime_error(eh.errors());

    return parser.getDocument();
  } // parse
}; // class MatchTest

template<class string_type, class string_adaptor>
TestSuite* MatchTest_suite()
{
  TestSuite *suiteOfTests = new TestSuite;

  suiteOfTests->addTest(new TestCaller<MatchTest<string_type, string_adaptor> >("testParse", &MatchTest<string_type, string_adaptor>::testParse));
  suiteOfTests->addTest(new TestCaller<MatchTest<string_type, string_adaptor> >("testParseFail", &MatchTest<string_type, string_adaptor>::testParseFails));
  suiteOfTests->addTest(new TestCaller<MatchTest<string_type, string_adaptor> >("testEvaluateDocMatch", &MatchTest<string_type, string_adaptor>::testEvaluateDocMatch));
  suiteOfTests->addTest(new TestCaller<MatchTest<string_type, string_adaptor> >("testDocElementMatch", &MatchTest<string_type, string_adaptor>::testDocElementMatch));
  suiteOfTests->addTest(new TestCaller<MatchTest<string_type, string_adaptor> >("testDocElementNotMatch", &MatchTest<string_type, string_adaptor>::testDocElementNotMatch));

  return suiteOfTests;
} // MatchTest_suite

#endif

<|endoftext|>


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

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

#ifndef _WIN32
#include <unistd.h>
#endif

using namespace std;

namespace essentia {

bool infoLevelActive = true;
bool warningLevelActive = true;
bool errorLevelActive = true;

int activatedDebugLevels = 0;
int debugIndentLevel = 0;

Logger loggerInstance;

const char* debugModuleDescription(DebuggingModule module) {
  switch (module) {
  case EAlgorithm:  return "[Algorithm ] ";
  case EConnectors: return "[Connectors] ";
  case EFactory:    return "[Factory   ] ";
  case ENetwork:    return "[Network   ] ";
  case EGraph:      return "[Graph     ] ";
  case EExecution:  return "[Execution ] ";
  case EMemory:     return "[Memory    ] ";
  case EScheduler:  return "[Scheduler ] ";

  case EPython:     return "[  PYTHON  ] ";
  case EPyBindings: return "[  PYBIND  ] ";
  case EUnittest:   return "[ UNITTEST ] ";

  case EUser1:      return "[  USER1   ] ";
  case EUser2:      return "[  USER2   ] ";

  case ENone:       return "[          ] ";
  case EAll:        return "[   ALL    ] ";
  default:          return "[ Mixed    ] ";
  }
}

void setDebugLevel(int levels) {
  activatedDebugLevels |= levels;
}

void unsetDebugLevel(int levels) {
  activatedDebugLevels &= ~levels;
}

DebuggingScheduleVector _schedule;

int _savedDebugLevels = ENone;

void scheduleDebug(const DebuggingScheduleVector& schedule) {
  _schedule = schedule;
}

void scheduleDebug(DebuggingSchedule schedule, int nentries) {
  _schedule.resize(nentries);
  for (int i=0; i<nentries; i++) {
    _schedule[i].first.first = schedule[i][0];
    _schedule[i].first.second = schedule[i][1];
    _schedule[i].second = schedule[i][2];
  }
}

void restoreDebugLevels() {
   activatedDebugLevels = _savedDebugLevels;
}

void saveDebugLevels() {
  _savedDebugLevels = activatedDebugLevels;
}

void setDebugLevelForTimeIndex(int index) {
  restoreDebugLevels();
  for (int i=0; i<(int)_schedule.size(); i++) {
    if (_schedule[i].first.first <= index && index <= _schedule[i].first.second) {
      setDebugLevel(_schedule[i].second);
    }
  }
}

// NOTE: in a thread-safe implementation, the msg queue would be thread-safe and
//       the flushing would need to happen in a separate thread
//       This can be achieved using tbb::concurrent_queue

void Logger::flush() {
  while (!_msgQueue.empty()) {
    std::cerr << _msgQueue.front();
    //std::cout << _msgQueue.front() << std::flush;
    _msgQueue.pop_front();
  }
}

void Logger::debug(DebuggingModule module, const string& msg, bool resetHeader) {
  if (module & activatedDebugLevels) {
    if (_addHeader) {
      _msgQueue.push_back(E_STRINGIFY(debugModuleDescription(module)      // module name
                                      + string(debugIndentLevel * 8, ' ') // indentation
                                      + msg));                            // msg
    }
    else {
      _msgQueue.push_back(msg);
    }

    _addHeader = resetHeader;
    flush();
  }
}

void Logger::info(const string& msg) {
  if (!infoLevelActive) return;
  static string GREEN_FONT = "\x1B[0;32m";
  static string RESET_FONT = "\x1B[0m";

#ifndef _WIN32
  if(!isatty(2)) { // no colors if stderr is not a terminal
    GREEN_FONT.clear();
    RESET_FONT .clear();
  }
#endif

  _msgQueue.push_back(E_STRINGIFY(GREEN_FONT << "[   INFO   ] " << RESET_FONT << msg << '\n'));
  flush();
}

void Logger::warning(const string& msg) {
  if (!warningLevelActive) return;
  static string YELLOW_FONT = "\x1B[0;33m";
  static string RESET_FONT = "\x1B[0m";

#ifndef _WIN32
  if(!isatty(2)) {
    YELLOW_FONT.clear();
    RESET_FONT.clear();
  }
#endif

  _msgQueue.push_back(E_STRINGIFY(YELLOW_FONT << "[ WARNING  ] " << RESET_FONT << msg << '\n'));
  flush();
}

void Logger::error(const string& msg) {
  if (!errorLevelActive) return;
  static string RED_FONT = "\x1B[0;31m";
  static string RESET_FONT = "\x1B[0m";

#ifndef _WIN32
  if(!isatty(2)) {
    RED_FONT.clear();
    RESET_FONT.clear();
  }
#endif

  _msgQueue.push_back(E_STRINGIFY(RED_FONT << "[  ERROR   ] " << RESET_FONT << msg << '\n'));
  flush();
}

} // namespace essentia
<commit_msg>Remove space<commit_after>/*
 * Copyright (C) 2006-2016  Music Technology Group - Universitat Pompeu Fabra
 *
 * This file is part of Essentia
 *
 * Essentia is free software: you can redistribute it and/or modify it under
 * the terms of the GNU Affero General Public License as published by the Free
 * Software Foundation (FSF), either version 3 of the License, or (at your
 * option) any later version.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
 * FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
 * details.
 *
 * You should have received a copy of the Affero GNU General Public License
 * version 3 along with this program.  If not, see http://www.gnu.org/licenses/
 */

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

#ifndef _WIN32
#include <unistd.h>
#endif

using namespace std;

namespace essentia {

bool infoLevelActive = true;
bool warningLevelActive = true;
bool errorLevelActive = true;

int activatedDebugLevels = 0;
int debugIndentLevel = 0;

Logger loggerInstance;

const char* debugModuleDescription(DebuggingModule module) {
  switch (module) {
  case EAlgorithm:  return "[Algorithm ] ";
  case EConnectors: return "[Connectors] ";
  case EFactory:    return "[Factory   ] ";
  case ENetwork:    return "[Network   ] ";
  case EGraph:      return "[Graph     ] ";
  case EExecution:  return "[Execution ] ";
  case EMemory:     return "[Memory    ] ";
  case EScheduler:  return "[Scheduler ] ";

  case EPython:     return "[  PYTHON  ] ";
  case EPyBindings: return "[  PYBIND  ] ";
  case EUnittest:   return "[ UNITTEST ] ";

  case EUser1:      return "[  USER1   ] ";
  case EUser2:      return "[  USER2   ] ";

  case ENone:       return "[          ] ";
  case EAll:        return "[   ALL    ] ";
  default:          return "[ Mixed    ] ";
  }
}

void setDebugLevel(int levels) {
  activatedDebugLevels |= levels;
}

void unsetDebugLevel(int levels) {
  activatedDebugLevels &= ~levels;
}

DebuggingScheduleVector _schedule;

int _savedDebugLevels = ENone;

void scheduleDebug(const DebuggingScheduleVector& schedule) {
  _schedule = schedule;
}

void scheduleDebug(DebuggingSchedule schedule, int nentries) {
  _schedule.resize(nentries);
  for (int i=0; i<nentries; i++) {
    _schedule[i].first.first = schedule[i][0];
    _schedule[i].first.second = schedule[i][1];
    _schedule[i].second = schedule[i][2];
  }
}

void restoreDebugLevels() {
   activatedDebugLevels = _savedDebugLevels;
}

void saveDebugLevels() {
  _savedDebugLevels = activatedDebugLevels;
}

void setDebugLevelForTimeIndex(int index) {
  restoreDebugLevels();
  for (int i=0; i<(int)_schedule.size(); i++) {
    if (_schedule[i].first.first <= index && index <= _schedule[i].first.second) {
      setDebugLevel(_schedule[i].second);
    }
  }
}

// NOTE: in a thread-safe implementation, the msg queue would be thread-safe and
//       the flushing would need to happen in a separate thread
//       This can be achieved using tbb::concurrent_queue

void Logger::flush() {
  while (!_msgQueue.empty()) {
    std::cerr << _msgQueue.front();
    //std::cout << _msgQueue.front() << std::flush;
    _msgQueue.pop_front();
  }
}

void Logger::debug(DebuggingModule module, const string& msg, bool resetHeader) {
  if (module & activatedDebugLevels) {
    if (_addHeader) {
      _msgQueue.push_back(E_STRINGIFY(debugModuleDescription(module)      // module name
                                      + string(debugIndentLevel * 8, ' ') // indentation
                                      + msg));                            // msg
    }
    else {
      _msgQueue.push_back(msg);
    }

    _addHeader = resetHeader;
    flush();
  }
}

void Logger::info(const string& msg) {
  if (!infoLevelActive) return;
  static string GREEN_FONT = "\x1B[0;32m";
  static string RESET_FONT = "\x1B[0m";

#ifndef _WIN32
  if(!isatty(2)) { // no colors if stderr is not a terminal
    GREEN_FONT.clear();
    RESET_FONT.clear();
  }
#endif

  _msgQueue.push_back(E_STRINGIFY(GREEN_FONT << "[   INFO   ] " << RESET_FONT << msg << '\n'));
  flush();
}

void Logger::warning(const string& msg) {
  if (!warningLevelActive) return;
  static string YELLOW_FONT = "\x1B[0;33m";
  static string RESET_FONT = "\x1B[0m";

#ifndef _WIN32
  if(!isatty(2)) {
    YELLOW_FONT.clear();
    RESET_FONT.clear();
  }
#endif

  _msgQueue.push_back(E_STRINGIFY(YELLOW_FONT << "[ WARNING  ] " << RESET_FONT << msg << '\n'));
  flush();
}

void Logger::error(const string& msg) {
  if (!errorLevelActive) return;
  static string RED_FONT = "\x1B[0;31m";
  static string RESET_FONT = "\x1B[0m";

#ifndef _WIN32
  if(!isatty(2)) {
    RED_FONT.clear();
    RESET_FONT.clear();
  }
#endif

  _msgQueue.push_back(E_STRINGIFY(RED_FONT << "[  ERROR   ] " << RESET_FONT << msg << '\n'));
  flush();
}

} // namespace essentia
<|endoftext|>