<commit_before>//============================================================================
// Name        : Label.cpp
// Authors     : Julien Combattelli & Guillaume Sarthou
// EMail       : open.pode@gmail.com
// Date		   : 19 avr. 2017
// Version     : 1.0.0
// Copyright   : This file is part of PicasoSDK project which is released under
//               MIT license. See file LICENSE.txt for full license details
// Description : It provides a label widget
//============================================================================

#include "PicasoSDK/Widgets/Label.h"

namespace Picaso
{

Label::Label(Serial_Commander& lcd, const std::string& text, Color foreground_color, uint16_t x_origin, uint16_t y_origin, uint16_t width, uint16_t height, int font_size, Alignment_H h_alignment, Alignment_V v_alignment, bool auto_update) :
	Widget(lcd)
{
    m_auto_update = auto_update;

    create(text, foreground_color, x_origin, y_origin, width, height, font_size, h_alignment, v_alignment);

    show();
}

Label::Label(Serial_Commander& lcd, bool auto_update) : Widget(lcd)
{
    m_auto_update = auto_update;

    create("", Color::WHITE, 0, 0, 20, 20, 1, Alignment_H::LEFT, Alignment_V::TOP);
}

Label::~Label()
{

}

void Label::update_attributes()
{
    m_lcd.txt_set_font(3);
    m_lcd.txt_width_multiplier(m_font_size);
    m_lcd.txt_height_multiplier(m_font_size);
    m_lcd.txt_foreground_color(m_foreground_color);
    m_lcd.txt_background_color(m_background_color);
}

void Label::write_text()
{
    uint8_t sector = 0;
    uint8_t u = m_lcd.txt_char_width('0');
    uint8_t nb_car_max = m_boundingBox.size.width/u;
    uint8_t nb_car_per_sector[100];
    uint8_t car_index_total = 0;
    uint8_t car_index = 0;
    uint16_t size_text = m_text.size();
    std::string text_cpy;
    std::string buffer;
    text_cpy = m_text;

    uint16_t y_location = 0, x_location = 0;
    if(nb_car_max != 0)
    {
        while(car_index_total < size_text)
        {
            car_index += nb_car_max;

            if(car_index < size_text)
            {
                while((text_cpy[car_index] != ' ') && (car_index_total != car_index))
                    car_index --;

                if(car_index_total == car_index)
                {
                    car_index += nb_car_max;
                }
                else
                {
                    text_cpy.erase(car_index,1);
                    size_text = text_cpy.size();
                }
            }
            else
                car_index = size_text;

            nb_car_per_sector[sector] = car_index - car_index_total;
            sector ++;
            car_index_total = car_index;
        }

        switch(m_alignment.v)
        {
            case Alignment_V::TOP:
                y_location = m_boundingBox.origin.y;
                break;

            case Alignment_V::BOTTOM:
                y_location = (m_boundingBox.origin.y + m_boundingBox.size.height) - sector*m_lcd.txt_char_height('0');
                break;

            case Alignment_V::CENTER:
                y_location = ((m_boundingBox.size.height - sector*m_lcd.txt_char_height('0')) / 2) + m_boundingBox.origin.y;
                break;
        }

        car_index = 0;
        for(uint8_t i = 0; i < sector; i++)
        {
             switch(m_alignment.h)
            {
                case Alignment_H::LEFT:
                    x_location = m_boundingBox.origin.x;
                    break;

                case Alignment_H::RIGHT:
                	x_location = (m_boundingBox.origin.x + m_boundingBox.size.width) - nb_car_per_sector[i]*m_lcd.txt_char_width('0');
                	break;

                case Alignment_H::CENTER:
                	x_location = ((m_boundingBox.size.width - nb_car_per_sector[i]*m_lcd.txt_char_width('0'))/2) + m_boundingBox.origin.x;
                	break;
            }
            buffer = text_cpy.substr(car_index, nb_car_per_sector[i]);
            car_index += nb_car_per_sector[i];

            m_lcd.gfx_move_origin(x_location, y_location);
            m_lcd.txt_put_str(buffer);

            y_location += m_lcd.txt_char_height('0');
        }
    }
}

void Label::show()
{
    update_attributes();
    write_text();
}

void Label::show_delimitation()
{
    m_lcd.gfx_draw_filled_rectangle(
    		m_boundingBox.origin.x,
			m_boundingBox.origin.y,
			m_boundingBox.origin.x + m_boundingBox.size.width,
			m_boundingBox.origin.y + m_boundingBox.size.height,
			m_background_color);
    write_text();
}

void Label::change_color(Color foreground_color, Color background_color)
{
    m_foreground_color = foreground_color;
    m_background_color = background_color;
    if(m_auto_update)
    {
		update_attributes();
		write_text();
    }
}

void Label::change_size(uint16_t width, uint16_t height)
{
	m_boundingBox.size.width = width;
	m_boundingBox.size.height = height;
	if(m_auto_update)
	{
		update_attributes();
		write_text();
	}
}

void Label::change_origin(uint16_t x_origin, uint16_t y_origin)
{
	m_boundingBox.origin.x = x_origin;
	m_boundingBox.origin.y = y_origin;
	if(m_auto_update)
	{
		update_attributes();
		write_text();
	}
}

void Label::change_alignment(Alignment_H h_alignment, Alignment_V v_alignment)
{
    m_alignment.h = h_alignment;
    m_alignment.v = v_alignment;
    if(m_auto_update)
    {
		update_attributes();
		write_text();
    }
}

void Label::change_font_size(int font_size)
{
    m_font_size = font_size;
    if(m_auto_update)
    {
		update_attributes();
		write_text();
    }
}

void Label::change_text(const std::string& text)
{
    m_text = text;
    if(m_auto_update)
    {
		update_attributes();
		write_text();
    }
}

void Label::create(const std::string& text, Color foreground_color, uint16_t x_origin, uint16_t y_origin, uint16_t width, uint16_t height, int font_size, Alignment_H h_alignment, Alignment_V v_alignment)
{
    m_alignment.h = h_alignment;
    m_alignment.v = v_alignment;
    m_boundingBox.origin.x = x_origin;
    m_boundingBox.origin.y = y_origin;
    m_boundingBox.size.width = width;
    m_boundingBox.size.height = height;
    m_foreground_color = foreground_color;
    m_background_color = Color::BLACK;
    m_font_size = font_size;
    m_text = text;

    update_attributes();
    write_text();
}

} // namespace Picaso
<commit_msg>Optimize Label::write_text method<commit_after>//============================================================================
// Name        : Label.cpp
// Authors     : Julien Combattelli & Guillaume Sarthou
// EMail       : open.pode@gmail.com
// Date		   : 19 avr. 2017
// Version     : 1.0.0
// Copyright   : This file is part of PicasoSDK project which is released under
//               MIT license. See file LICENSE.txt for full license details
// Description : It provides a label widget
//============================================================================

#include "PicasoSDK/Widgets/Label.h"
#include <iostream>
#include <algorithm>

namespace Picaso
{

Label::Label(Serial_Commander& lcd, const std::string& text, Color foreground_color, uint16_t x_origin, uint16_t y_origin, uint16_t width, uint16_t height, int font_size, Alignment_H h_alignment, Alignment_V v_alignment, bool auto_update) :
	Widget(lcd)
{
    m_auto_update = auto_update;

    create(text, foreground_color, x_origin, y_origin, width, height, font_size, h_alignment, v_alignment);

    show();
}

Label::Label(Serial_Commander& lcd, bool auto_update) : Widget(lcd)
{
    m_auto_update = auto_update;

    create("", Color::WHITE, 0, 0, 20, 20, 1, Alignment_H::LEFT, Alignment_V::TOP);
}

Label::~Label()
{

}

void Label::update_attributes()
{
    m_lcd.txt_set_font(3);
    m_lcd.txt_width_multiplier(m_font_size);
    m_lcd.txt_height_multiplier(m_font_size);
    m_lcd.txt_foreground_color(m_foreground_color);
    m_lcd.txt_background_color(m_background_color);
}

inline std::string trim(const std::string &s)
{
	auto wsfront = std::find_if_not(s.begin(),s.end(),[](int c){return std::isspace(c);});
	auto wsback = std::find_if_not(s.rbegin(),s.rend(),[](int c){return std::isspace(c);}).base();
	return (wsback <= wsfront ? std::string() : std::string(wsfront,wsback));
}

void Label::write_text()
{
    uint8_t character_width = m_lcd.txt_char_width('0');
    uint8_t character_height = m_lcd.txt_char_height('0');
    uint8_t max_char_per_line = m_boundingBox.size.width/character_width;

    if(max_char_per_line == 0)
    	return;

	size_t space_pos = 0;
	size_t index = 0;
	Point text_location{m_boundingBox.origin.x, m_boundingBox.origin.x};
	std::string tmp{m_text};
	std::vector<std::string> str_vect;

	while(space_pos != std::string::npos)
	{
		space_pos = tmp.find(" ", index);
		if(space_pos > max_char_per_line)
		{
			str_vect.emplace_back(trim(tmp.substr(0, index)));
			tmp.erase(0, index);
		}
		else
			index = space_pos + 1;
	}

	size_t line_count = str_vect.size();

	switch(m_alignment.v)
	{
		case Alignment_V::TOP:
			text_location.y = m_boundingBox.origin.y;
			break;

		case Alignment_V::BOTTOM:
			text_location.y = (m_boundingBox.origin.y + m_boundingBox.size.height) - line_count*character_height;
			break;

		case Alignment_V::CENTER:
			text_location.y = ((m_boundingBox.size.height - line_count*character_height) / 2) + m_boundingBox.origin.y;
			break;
	}

	for(unsigned i = 0; i < line_count; i++)
	{
		switch(m_alignment.h)
		{
			case Alignment_H::LEFT:
				text_location.x = m_boundingBox.origin.x;
				break;

			case Alignment_H::RIGHT:
				text_location.x = (m_boundingBox.origin.x + m_boundingBox.size.width) - str_vect[i].size()*character_height;
				break;

			case Alignment_H::CENTER:
				text_location.x = ((m_boundingBox.size.width - str_vect[i].size()*character_width)/2) + m_boundingBox.origin.x;
				break;
		}

		m_lcd.gfx_move_origin(text_location.x, text_location.y);
		m_lcd.txt_put_str(str_vect[i]);

		text_location.y += character_height;
	}
}

void Label::show()
{
    update_attributes();
    write_text();
}

void Label::show_delimitation()
{
    m_lcd.gfx_draw_filled_rectangle(
    		m_boundingBox.origin.x,
			m_boundingBox.origin.y,
			m_boundingBox.origin.x + m_boundingBox.size.width,
			m_boundingBox.origin.y + m_boundingBox.size.height,
			m_background_color);
    write_text();
}

void Label::change_color(Color foreground_color, Color background_color)
{
    m_foreground_color = foreground_color;
    m_background_color = background_color;
    if(m_auto_update)
    {
		update_attributes();
		write_text();
    }
}

void Label::change_size(uint16_t width, uint16_t height)
{
	m_boundingBox.size.width = width;
	m_boundingBox.size.height = height;
	if(m_auto_update)
	{
		update_attributes();
		write_text();
	}
}

void Label::change_origin(uint16_t x_origin, uint16_t y_origin)
{
	m_boundingBox.origin.x = x_origin;
	m_boundingBox.origin.y = y_origin;
	if(m_auto_update)
	{
		update_attributes();
		write_text();
	}
}

void Label::change_alignment(Alignment_H h_alignment, Alignment_V v_alignment)
{
    m_alignment.h = h_alignment;
    m_alignment.v = v_alignment;
    if(m_auto_update)
    {
		update_attributes();
		write_text();
    }
}

void Label::change_font_size(int font_size)
{
    m_font_size = font_size;
    if(m_auto_update)
    {
		update_attributes();
		write_text();
    }
}

void Label::change_text(const std::string& text)
{
    m_text = text;
    if(m_auto_update)
    {
		update_attributes();
		write_text();
    }
}

void Label::create(const std::string& text, Color foreground_color, uint16_t x_origin, uint16_t y_origin, uint16_t width, uint16_t height, int font_size, Alignment_H h_alignment, Alignment_V v_alignment)
{
    m_alignment.h = h_alignment;
    m_alignment.v = v_alignment;
    m_boundingBox.origin.x = x_origin;
    m_boundingBox.origin.y = y_origin;
    m_boundingBox.size.width = width;
    m_boundingBox.size.height = height;
    m_foreground_color = foreground_color;
    m_background_color = Color::BLACK;
    m_font_size = font_size;
    m_text = text;

    update_attributes();
    write_text();
}

} // namespace Picaso
<|endoftext|>


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

#include "spork.h"
#include "base58.h"
#include "key.h"
#include "main.h"
#include "masternode-budget.h"
#include "net.h"
#include "protocol.h"
#include "sync.h"
#include "sporkdb.h"
#include "util.h"
#include <boost/lexical_cast.hpp>

using namespace std;
using namespace boost;

class CSporkMessage;
class CSporkManager;

CSporkManager sporkManager;

std::map<uint256, CSporkMessage> mapSporks;
std::map<int, CSporkMessage> mapSporksActive;

// PIVX: on startup load spork values from previous session if they exist in the sporkDB
void LoadSporksFromDB()
{
    for (int i = SPORK_START; i <= SPORK_END; ++i) {
        // Since not all spork IDs are in use, we have to exclude undefined IDs
        std::string strSpork = sporkManager.GetSporkNameByID(i);
        if (strSpork == "Unknown") continue;

        // attempt to read spork from sporkDB
        CSporkMessage spork;
        if (!pSporkDB->ReadSpork(i, spork)) {
            LogPrintf("%s : no previous value for %s found in database\n", __func__, strSpork);
            continue;
        }

        // add spork to memory
        mapSporks[spork.GetHash()] = spork;
        mapSporksActive[spork.nSporkID] = spork;
        LogPrintf("%s : loaded spork %s with value %d\n", __func__, sporkManager.GetSporkNameByID(spork.nSporkID), spork.nValue);
    }
}

void ProcessSpork(CNode* pfrom, std::string& strCommand, CDataStream& vRecv)
{
    if (fLiteMode) return; //disable all obfuscation/masternode related functionality

    if (strCommand == "spork") {
        //LogPrintf("ProcessSpork::spork\n");
        CDataStream vMsg(vRecv);
        CSporkMessage spork;
        vRecv >> spork;

        if (chainActive.Tip() == NULL) return;

        uint256 hash = spork.GetHash();
        if (mapSporksActive.count(spork.nSporkID)) {
            if (mapSporksActive[spork.nSporkID].nTimeSigned >= spork.nTimeSigned) {
                if (fDebug) LogPrintf("spork - seen %s block %d \n", hash.ToString(), chainActive.Tip()->nHeight);
                return;
            } else {
                if (fDebug) LogPrintf("spork - got updated spork %s block %d \n", hash.ToString(), chainActive.Tip()->nHeight);
            }
        }

        LogPrintf("spork - new %s ID %d Time %d bestHeight %d\n", hash.ToString(), spork.nSporkID, spork.nValue, chainActive.Tip()->nHeight);

        if (!sporkManager.CheckSignature(spork)) {
            LogPrintf("spork - invalid signature\n");
            Misbehaving(pfrom->GetId(), 100);
            return;
        }

        mapSporks[hash] = spork;
        mapSporksActive[spork.nSporkID] = spork;
        sporkManager.Relay(spork);

        // PIVX: add to spork database.
        pSporkDB->WriteSpork(spork.nSporkID, spork);
    }
    if (strCommand == "getsporks") {
        std::map<int, CSporkMessage>::iterator it = mapSporksActive.begin();

        while (it != mapSporksActive.end()) {
            pfrom->PushMessage("spork", it->second);
            it++;
        }
    }
}

// grab the value of the spork on the network, or the default
int64_t GetSporkValue(int nSporkID)
{
    int64_t r = -1;

    if (mapSporksActive.count(nSporkID)) {
        r = mapSporksActive[nSporkID].nValue;
    } else {
        if (nSporkID == SPORK_2_SWIFTTX) r = SPORK_2_SWIFTTX_DEFAULT;
        if (nSporkID == SPORK_3_SWIFTTX_BLOCK_FILTERING) r = SPORK_3_SWIFTTX_BLOCK_FILTERING_DEFAULT;
        if (nSporkID == SPORK_5_MAX_VALUE) r = SPORK_5_MAX_VALUE_DEFAULT;
        if (nSporkID == SPORK_7_MASTERNODE_SCANNING) r = SPORK_7_MASTERNODE_SCANNING_DEFAULT;
        if (nSporkID == SPORK_8_MASTERNODE_PAYMENT_ENFORCEMENT) r = SPORK_8_MASTERNODE_PAYMENT_ENFORCEMENT_DEFAULT;
        if (nSporkID == SPORK_9_MASTERNODE_BUDGET_ENFORCEMENT) r = SPORK_9_MASTERNODE_BUDGET_ENFORCEMENT_DEFAULT;
        if (nSporkID == SPORK_10_MASTERNODE_PAY_UPDATED_NODES) r = SPORK_10_MASTERNODE_PAY_UPDATED_NODES_DEFAULT;
        if (nSporkID == SPORK_13_ENABLE_SUPERBLOCKS) r = SPORK_13_ENABLE_SUPERBLOCKS_DEFAULT;
        if (nSporkID == SPORK_14_NEW_PROTOCOL_ENFORCEMENT) r = SPORK_14_NEW_PROTOCOL_ENFORCEMENT_DEFAULT;
        if (nSporkID == SPORK_15_NEW_PROTOCOL_ENFORCEMENT_2) r = SPORK_15_NEW_PROTOCOL_ENFORCEMENT_2_DEFAULT;
        if (nSporkID == SPORK_16_MN_WINNER_MINIMUM_AGE) r = SPORK_16_MN_WINNER_MINIMUM_AGE_DEFAULT;
        if (nSporkID == SPORK_17_ENABLE_ZEROCOIN) r = SPORK_17_ENABLE_ZEROCOIN_DEFAULT;

        if (r == -1) LogPrintf("GetSpork::Unknown Spork %d\n", nSporkID);
    }

    return r;
}

// grab the spork value, and see if it's off
bool IsSporkActive(int nSporkID)
{
    int64_t r = GetSporkValue(nSporkID);
    if (r == -1) return false;
    return r < GetTime();
}

void ReprocessBlocks(int nBlocks)
{
    std::map<uint256, int64_t>::iterator it = mapRejectedBlocks.begin();
    while (it != mapRejectedBlocks.end()) {
        //use a window twice as large as is usual for the nBlocks we want to reset
        if ((*it).second > GetTime() - (nBlocks * 60 * 5)) {
            BlockMap::iterator mi = mapBlockIndex.find((*it).first);
            if (mi != mapBlockIndex.end() && (*mi).second) {
                LOCK(cs_main);

                CBlockIndex* pindex = (*mi).second;
                LogPrintf("ReprocessBlocks - %s\n", (*it).first.ToString());

                CValidationState state;
                ReconsiderBlock(state, pindex);
            }
        }
        ++it;
    }

    CValidationState state;
    {
        LOCK(cs_main);
        DisconnectBlocksAndReprocess(nBlocks);
    }

    if (state.IsValid()) {
        ActivateBestChain(state);
    }
}

bool CSporkManager::CheckSignature(CSporkMessage& spork)
{
    //note: need to investigate why this is failing
    std::string strMessage = boost::lexical_cast<std::string>(spork.nSporkID) + boost::lexical_cast<std::string>(spork.nValue) + boost::lexical_cast<std::string>(spork.nTimeSigned);
    CPubKey pubkey(ParseHex(Params().SporkKey()));

    std::string errorMessage = "";
    if (!obfuScationSigner.VerifyMessage(pubkey, spork.vchSig, strMessage, errorMessage)) {
        return false;
    }

    return true;
}

bool CSporkManager::Sign(CSporkMessage& spork)
{
    std::string strMessage = boost::lexical_cast<std::string>(spork.nSporkID) + boost::lexical_cast<std::string>(spork.nValue) + boost::lexical_cast<std::string>(spork.nTimeSigned);

    CKey key2;
    CPubKey pubkey2;
    std::string errorMessage = "";

    if (!obfuScationSigner.SetKey(strMasterPrivKey, errorMessage, key2, pubkey2)) {
        LogPrintf("CMasternodePayments::Sign - ERROR: Invalid masternodeprivkey: '%s'\n", errorMessage);
        return false;
    }

    if (!obfuScationSigner.SignMessage(strMessage, errorMessage, spork.vchSig, key2)) {
        LogPrintf("CMasternodePayments::Sign - Sign message failed");
        return false;
    }

    if (!obfuScationSigner.VerifyMessage(pubkey2, spork.vchSig, strMessage, errorMessage)) {
        LogPrintf("CMasternodePayments::Sign - Verify message failed");
        return false;
    }

    return true;
}

bool CSporkManager::UpdateSpork(int nSporkID, int64_t nValue)
{
    CSporkMessage msg;
    msg.nSporkID = nSporkID;
    msg.nValue = nValue;
    msg.nTimeSigned = GetTime();

    if (Sign(msg)) {
        Relay(msg);
        mapSporks[msg.GetHash()] = msg;
        mapSporksActive[nSporkID] = msg;
        return true;
    }

    return false;
}

void CSporkManager::Relay(CSporkMessage& msg)
{
    CInv inv(MSG_SPORK, msg.GetHash());
    RelayInv(inv);
}

bool CSporkManager::SetPrivKey(std::string strPrivKey)
{
    CSporkMessage msg;

    // Test signing successful, proceed
    strMasterPrivKey = strPrivKey;

    Sign(msg);

    if (CheckSignature(msg)) {
        LogPrintf("CSporkManager::SetPrivKey - Successfully initialized as spork signer\n");
        return true;
    } else {
        return false;
    }
}

int CSporkManager::GetSporkIDByName(std::string strName)
{
    if (strName == "SPORK_2_SWIFTTX") return SPORK_2_SWIFTTX;
    if (strName == "SPORK_3_SWIFTTX_BLOCK_FILTERING") return SPORK_3_SWIFTTX_BLOCK_FILTERING;
    if (strName == "SPORK_5_MAX_VALUE") return SPORK_5_MAX_VALUE;
    if (strName == "SPORK_7_MASTERNODE_SCANNING") return SPORK_7_MASTERNODE_SCANNING;
    if (strName == "SPORK_8_MASTERNODE_PAYMENT_ENFORCEMENT") return SPORK_8_MASTERNODE_PAYMENT_ENFORCEMENT;
    if (strName == "SPORK_9_MASTERNODE_BUDGET_ENFORCEMENT") return SPORK_9_MASTERNODE_BUDGET_ENFORCEMENT;
    if (strName == "SPORK_10_MASTERNODE_PAY_UPDATED_NODES") return SPORK_10_MASTERNODE_PAY_UPDATED_NODES;
    if (strName == "SPORK_13_ENABLE_SUPERBLOCKS") return SPORK_13_ENABLE_SUPERBLOCKS;
    if (strName == "SPORK_14_NEW_PROTOCOL_ENFORCEMENT") return SPORK_14_NEW_PROTOCOL_ENFORCEMENT;
    if (strName == "SPORK_15_NEW_PROTOCOL_ENFORCEMENT_2") return SPORK_15_NEW_PROTOCOL_ENFORCEMENT_2;
    if (strName == "SPORK_16_MN_WINNER_MINIMUM_AGE") return SPORK_16_MN_WINNER_MINIMUM_AGE;
    if (strName == "SPORK_17_ENABLE_ZEROCOIN") return SPORK_17_ENABLE_ZEROCOIN;

    return -1;
}

std::string CSporkManager::GetSporkNameByID(int id)
{
    if (id == SPORK_2_SWIFTTX) return "SPORK_2_SWIFTTX";
    if (id == SPORK_3_SWIFTTX_BLOCK_FILTERING) return "SPORK_3_SWIFTTX_BLOCK_FILTERING";
    if (id == SPORK_5_MAX_VALUE) return "SPORK_5_MAX_VALUE";
    if (id == SPORK_7_MASTERNODE_SCANNING) return "SPORK_7_MASTERNODE_SCANNING";
    if (id == SPORK_8_MASTERNODE_PAYMENT_ENFORCEMENT) return "SPORK_8_MASTERNODE_PAYMENT_ENFORCEMENT";
    if (id == SPORK_9_MASTERNODE_BUDGET_ENFORCEMENT) return "SPORK_9_MASTERNODE_BUDGET_ENFORCEMENT";
    if (id == SPORK_10_MASTERNODE_PAY_UPDATED_NODES) return "SPORK_10_MASTERNODE_PAY_UPDATED_NODES";
    if (id == SPORK_13_ENABLE_SUPERBLOCKS) return "SPORK_13_ENABLE_SUPERBLOCKS";
    if (id == SPORK_14_NEW_PROTOCOL_ENFORCEMENT) return "SPORK_14_NEW_PROTOCOL_ENFORCEMENT";
    if (id == SPORK_15_NEW_PROTOCOL_ENFORCEMENT_2) return "SPORK_15_NEW_PROTOCOL_ENFORCEMENT_2";
    if (id == SPORK_16_MN_WINNER_MINIMUM_AGE) return "SPORK_16_MN_WINNER_MINIMUM_AGE";
    if (id == SPORK_17_ENABLE_ZEROCOIN) return "SPORK_17_ENABLE_ZEROCOIN";

    return "Unknown";
}
<commit_msg>When printing log for loading sporks, print out date if appropriate<commit_after>// Copyright (c) 2014-2016 The Dash developers
// Copyright (c) 2016-2017 The PIVX developers
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.

#include "spork.h"
#include "base58.h"
#include "key.h"
#include "main.h"
#include "masternode-budget.h"
#include "net.h"
#include "protocol.h"
#include "sync.h"
#include "sporkdb.h"
#include "util.h"
#include <boost/lexical_cast.hpp>

using namespace std;
using namespace boost;

class CSporkMessage;
class CSporkManager;

CSporkManager sporkManager;

std::map<uint256, CSporkMessage> mapSporks;
std::map<int, CSporkMessage> mapSporksActive;

// PIVX: on startup load spork values from previous session if they exist in the sporkDB
void LoadSporksFromDB()
{
    for (int i = SPORK_START; i <= SPORK_END; ++i) {
        // Since not all spork IDs are in use, we have to exclude undefined IDs
        std::string strSpork = sporkManager.GetSporkNameByID(i);
        if (strSpork == "Unknown") continue;

        // attempt to read spork from sporkDB
        CSporkMessage spork;
        if (!pSporkDB->ReadSpork(i, spork)) {
            LogPrintf("%s : no previous value for %s found in database\n", __func__, strSpork);
            continue;
        }

        // add spork to memory
        mapSporks[spork.GetHash()] = spork;
        mapSporksActive[spork.nSporkID] = spork;
        std::time_t result = spork.nValue;
        // If SPORK Value is greater than 1,000,000 assume it's actually a Date and then convert to a more readable format
        if (spork.nValue > 1000000) {
            LogPrintf("%s : loaded spork %s with value %d : %s", __func__,
                      sporkManager.GetSporkNameByID(spork.nSporkID), spork.nValue,
                      std::ctime(&result));
        } else {
            LogPrintf("%s : loaded spork %s with value %d\n", __func__,
                      sporkManager.GetSporkNameByID(spork.nSporkID), spork.nValue);
        }
    }
}

void ProcessSpork(CNode* pfrom, std::string& strCommand, CDataStream& vRecv)
{
    if (fLiteMode) return; //disable all obfuscation/masternode related functionality

    if (strCommand == "spork") {
        //LogPrintf("ProcessSpork::spork\n");
        CDataStream vMsg(vRecv);
        CSporkMessage spork;
        vRecv >> spork;

        if (chainActive.Tip() == NULL) return;

        uint256 hash = spork.GetHash();
        if (mapSporksActive.count(spork.nSporkID)) {
            if (mapSporksActive[spork.nSporkID].nTimeSigned >= spork.nTimeSigned) {
                if (fDebug) LogPrintf("spork - seen %s block %d \n", hash.ToString(), chainActive.Tip()->nHeight);
                return;
            } else {
                if (fDebug) LogPrintf("spork - got updated spork %s block %d \n", hash.ToString(), chainActive.Tip()->nHeight);
            }
        }

        LogPrintf("spork - new %s ID %d Time %d bestHeight %d\n", hash.ToString(), spork.nSporkID, spork.nValue, chainActive.Tip()->nHeight);

        if (!sporkManager.CheckSignature(spork)) {
            LogPrintf("spork - invalid signature\n");
            Misbehaving(pfrom->GetId(), 100);
            return;
        }

        mapSporks[hash] = spork;
        mapSporksActive[spork.nSporkID] = spork;
        sporkManager.Relay(spork);

        // PIVX: add to spork database.
        pSporkDB->WriteSpork(spork.nSporkID, spork);
    }
    if (strCommand == "getsporks") {
        std::map<int, CSporkMessage>::iterator it = mapSporksActive.begin();

        while (it != mapSporksActive.end()) {
            pfrom->PushMessage("spork", it->second);
            it++;
        }
    }
}

// grab the value of the spork on the network, or the default
int64_t GetSporkValue(int nSporkID)
{
    int64_t r = -1;

    if (mapSporksActive.count(nSporkID)) {
        r = mapSporksActive[nSporkID].nValue;
    } else {
        if (nSporkID == SPORK_2_SWIFTTX) r = SPORK_2_SWIFTTX_DEFAULT;
        if (nSporkID == SPORK_3_SWIFTTX_BLOCK_FILTERING) r = SPORK_3_SWIFTTX_BLOCK_FILTERING_DEFAULT;
        if (nSporkID == SPORK_5_MAX_VALUE) r = SPORK_5_MAX_VALUE_DEFAULT;
        if (nSporkID == SPORK_7_MASTERNODE_SCANNING) r = SPORK_7_MASTERNODE_SCANNING_DEFAULT;
        if (nSporkID == SPORK_8_MASTERNODE_PAYMENT_ENFORCEMENT) r = SPORK_8_MASTERNODE_PAYMENT_ENFORCEMENT_DEFAULT;
        if (nSporkID == SPORK_9_MASTERNODE_BUDGET_ENFORCEMENT) r = SPORK_9_MASTERNODE_BUDGET_ENFORCEMENT_DEFAULT;
        if (nSporkID == SPORK_10_MASTERNODE_PAY_UPDATED_NODES) r = SPORK_10_MASTERNODE_PAY_UPDATED_NODES_DEFAULT;
        if (nSporkID == SPORK_13_ENABLE_SUPERBLOCKS) r = SPORK_13_ENABLE_SUPERBLOCKS_DEFAULT;
        if (nSporkID == SPORK_14_NEW_PROTOCOL_ENFORCEMENT) r = SPORK_14_NEW_PROTOCOL_ENFORCEMENT_DEFAULT;
        if (nSporkID == SPORK_15_NEW_PROTOCOL_ENFORCEMENT_2) r = SPORK_15_NEW_PROTOCOL_ENFORCEMENT_2_DEFAULT;
        if (nSporkID == SPORK_16_MN_WINNER_MINIMUM_AGE) r = SPORK_16_MN_WINNER_MINIMUM_AGE_DEFAULT;
        if (nSporkID == SPORK_17_ENABLE_ZEROCOIN) r = SPORK_17_ENABLE_ZEROCOIN_DEFAULT;

        if (r == -1) LogPrintf("GetSpork::Unknown Spork %d\n", nSporkID);
    }

    return r;
}

// grab the spork value, and see if it's off
bool IsSporkActive(int nSporkID)
{
    int64_t r = GetSporkValue(nSporkID);
    if (r == -1) return false;
    return r < GetTime();
}

void ReprocessBlocks(int nBlocks)
{
    std::map<uint256, int64_t>::iterator it = mapRejectedBlocks.begin();
    while (it != mapRejectedBlocks.end()) {
        //use a window twice as large as is usual for the nBlocks we want to reset
        if ((*it).second > GetTime() - (nBlocks * 60 * 5)) {
            BlockMap::iterator mi = mapBlockIndex.find((*it).first);
            if (mi != mapBlockIndex.end() && (*mi).second) {
                LOCK(cs_main);

                CBlockIndex* pindex = (*mi).second;
                LogPrintf("ReprocessBlocks - %s\n", (*it).first.ToString());

                CValidationState state;
                ReconsiderBlock(state, pindex);
            }
        }
        ++it;
    }

    CValidationState state;
    {
        LOCK(cs_main);
        DisconnectBlocksAndReprocess(nBlocks);
    }

    if (state.IsValid()) {
        ActivateBestChain(state);
    }
}

bool CSporkManager::CheckSignature(CSporkMessage& spork)
{
    //note: need to investigate why this is failing
    std::string strMessage = boost::lexical_cast<std::string>(spork.nSporkID) + boost::lexical_cast<std::string>(spork.nValue) + boost::lexical_cast<std::string>(spork.nTimeSigned);
    CPubKey pubkey(ParseHex(Params().SporkKey()));

    std::string errorMessage = "";
    if (!obfuScationSigner.VerifyMessage(pubkey, spork.vchSig, strMessage, errorMessage)) {
        return false;
    }

    return true;
}

bool CSporkManager::Sign(CSporkMessage& spork)
{
    std::string strMessage = boost::lexical_cast<std::string>(spork.nSporkID) + boost::lexical_cast<std::string>(spork.nValue) + boost::lexical_cast<std::string>(spork.nTimeSigned);

    CKey key2;
    CPubKey pubkey2;
    std::string errorMessage = "";

    if (!obfuScationSigner.SetKey(strMasterPrivKey, errorMessage, key2, pubkey2)) {
        LogPrintf("CMasternodePayments::Sign - ERROR: Invalid masternodeprivkey: '%s'\n", errorMessage);
        return false;
    }

    if (!obfuScationSigner.SignMessage(strMessage, errorMessage, spork.vchSig, key2)) {
        LogPrintf("CMasternodePayments::Sign - Sign message failed");
        return false;
    }

    if (!obfuScationSigner.VerifyMessage(pubkey2, spork.vchSig, strMessage, errorMessage)) {
        LogPrintf("CMasternodePayments::Sign - Verify message failed");
        return false;
    }

    return true;
}

bool CSporkManager::UpdateSpork(int nSporkID, int64_t nValue)
{
    CSporkMessage msg;
    msg.nSporkID = nSporkID;
    msg.nValue = nValue;
    msg.nTimeSigned = GetTime();

    if (Sign(msg)) {
        Relay(msg);
        mapSporks[msg.GetHash()] = msg;
        mapSporksActive[nSporkID] = msg;
        return true;
    }

    return false;
}

void CSporkManager::Relay(CSporkMessage& msg)
{
    CInv inv(MSG_SPORK, msg.GetHash());
    RelayInv(inv);
}

bool CSporkManager::SetPrivKey(std::string strPrivKey)
{
    CSporkMessage msg;

    // Test signing successful, proceed
    strMasterPrivKey = strPrivKey;

    Sign(msg);

    if (CheckSignature(msg)) {
        LogPrintf("CSporkManager::SetPrivKey - Successfully initialized as spork signer\n");
        return true;
    } else {
        return false;
    }
}

int CSporkManager::GetSporkIDByName(std::string strName)
{
    if (strName == "SPORK_2_SWIFTTX") return SPORK_2_SWIFTTX;
    if (strName == "SPORK_3_SWIFTTX_BLOCK_FILTERING") return SPORK_3_SWIFTTX_BLOCK_FILTERING;
    if (strName == "SPORK_5_MAX_VALUE") return SPORK_5_MAX_VALUE;
    if (strName == "SPORK_7_MASTERNODE_SCANNING") return SPORK_7_MASTERNODE_SCANNING;
    if (strName == "SPORK_8_MASTERNODE_PAYMENT_ENFORCEMENT") return SPORK_8_MASTERNODE_PAYMENT_ENFORCEMENT;
    if (strName == "SPORK_9_MASTERNODE_BUDGET_ENFORCEMENT") return SPORK_9_MASTERNODE_BUDGET_ENFORCEMENT;
    if (strName == "SPORK_10_MASTERNODE_PAY_UPDATED_NODES") return SPORK_10_MASTERNODE_PAY_UPDATED_NODES;
    if (strName == "SPORK_13_ENABLE_SUPERBLOCKS") return SPORK_13_ENABLE_SUPERBLOCKS;
    if (strName == "SPORK_14_NEW_PROTOCOL_ENFORCEMENT") return SPORK_14_NEW_PROTOCOL_ENFORCEMENT;
    if (strName == "SPORK_15_NEW_PROTOCOL_ENFORCEMENT_2") return SPORK_15_NEW_PROTOCOL_ENFORCEMENT_2;
    if (strName == "SPORK_16_MN_WINNER_MINIMUM_AGE") return SPORK_16_MN_WINNER_MINIMUM_AGE;
    if (strName == "SPORK_17_ENABLE_ZEROCOIN") return SPORK_17_ENABLE_ZEROCOIN;

    return -1;
}

std::string CSporkManager::GetSporkNameByID(int id)
{
    if (id == SPORK_2_SWIFTTX) return "SPORK_2_SWIFTTX";
    if (id == SPORK_3_SWIFTTX_BLOCK_FILTERING) return "SPORK_3_SWIFTTX_BLOCK_FILTERING";
    if (id == SPORK_5_MAX_VALUE) return "SPORK_5_MAX_VALUE";
    if (id == SPORK_7_MASTERNODE_SCANNING) return "SPORK_7_MASTERNODE_SCANNING";
    if (id == SPORK_8_MASTERNODE_PAYMENT_ENFORCEMENT) return "SPORK_8_MASTERNODE_PAYMENT_ENFORCEMENT";
    if (id == SPORK_9_MASTERNODE_BUDGET_ENFORCEMENT) return "SPORK_9_MASTERNODE_BUDGET_ENFORCEMENT";
    if (id == SPORK_10_MASTERNODE_PAY_UPDATED_NODES) return "SPORK_10_MASTERNODE_PAY_UPDATED_NODES";
    if (id == SPORK_13_ENABLE_SUPERBLOCKS) return "SPORK_13_ENABLE_SUPERBLOCKS";
    if (id == SPORK_14_NEW_PROTOCOL_ENFORCEMENT) return "SPORK_14_NEW_PROTOCOL_ENFORCEMENT";
    if (id == SPORK_15_NEW_PROTOCOL_ENFORCEMENT_2) return "SPORK_15_NEW_PROTOCOL_ENFORCEMENT_2";
    if (id == SPORK_16_MN_WINNER_MINIMUM_AGE) return "SPORK_16_MN_WINNER_MINIMUM_AGE";
    if (id == SPORK_17_ENABLE_ZEROCOIN) return "SPORK_17_ENABLE_ZEROCOIN";

    return "Unknown";
}
<|endoftext|>


<commit_before><commit_msg>Revert 68291 - DCHECK to detect invalid BrokerRpcClient usage.<commit_after><|endoftext|>


<commit_before>/** \copyright
 * Copyright (c) 2015, Balazs Racz
 * 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.
 *
 * 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.
 *
 * \file SimpleStack.cxx
 *
 * A complete OpenLCB stack for use in straightforward OpenLCB nodes.
 *
 * @author Balazs Racz
 * @date 18 Mar 2015
 */

#if defined(__linux__) || defined(__MACH__)
#include <termios.h> /* tc* functions */
#include <net/if.h>
#include <linux/sockios.h>
#endif

#include "nmranet/SimpleStack.hxx"

#include "nmranet/EventHandler.hxx"
#include "nmranet/SimpleNodeInfo.hxx"

namespace nmranet
{

SimpleCanStack::SimpleCanStack(const nmranet::NodeID node_id)
    : node_(&ifCan_, node_id)
{
    AddAliasAllocator(node_id, &ifCan_);
}

void SimpleCanStack::start_stack()
{
    // Opens the eeprom file and sends configuration update commands to all
    // listeners.
    configUpdateFlow_.open_file(CONFIG_FILENAME);
    configUpdateFlow_.init_flow();

    // Bootstraps the alias allocation process.
    ifCan_.alias_allocator()->send(ifCan_.alias_allocator()->alloc());

    // Adds memory spaces.
    if (config_enable_all_memory_space() == CONSTANT_TRUE)
    {
        auto *space = new ReadOnlyMemoryBlock(nullptr, 0xFFFFFFFFUL);
        memoryConfigHandler_.registry()->insert(
            nullptr, MemoryConfigDefs::SPACE_ALL_MEMORY, space);
        additionalComponents_.emplace_back(space);
    }
    {
        auto *space = new ReadOnlyMemoryBlock(
            reinterpret_cast<const uint8_t *>(&SNIP_STATIC_DATA),
            sizeof(SNIP_STATIC_DATA));
        memoryConfigHandler_.registry()->insert(
            &node_, MemoryConfigDefs::SPACE_ACDI_SYS, space);
        additionalComponents_.emplace_back(space);
    }
    {
        auto *space = new FileMemorySpace(
            SNIP_DYNAMIC_FILENAME, sizeof(SimpleNodeDynamicValues));
        memoryConfigHandler_.registry()->insert(
            &node_, MemoryConfigDefs::SPACE_ACDI_USR, space);
        additionalComponents_.emplace_back(space);
    }
    {
        auto *space = new ReadOnlyMemoryBlock(
            reinterpret_cast<const uint8_t *>(&CDI_DATA), strlen(CDI_DATA) + 1);
        memoryConfigHandler_.registry()->insert(
            &node_, MemoryConfigDefs::SPACE_CDI, space);
        additionalComponents_.emplace_back(space);
    }
    if (CONFIG_FILENAME != nullptr)
    {
        auto *space = new FileMemorySpace(CONFIG_FILENAME, CONFIG_FILE_SIZE);
        memory_config_handler()->registry()->insert(
            &node_, nmranet::MemoryConfigDefs::SPACE_CONFIG, space);
        additionalComponents_.emplace_back(space);
    }
}

void SimpleCanStack::restart_stack()
{
    node_.clear_initialized();
    ifCan_.alias_allocator()->reinit_seed();
    ifCan_.local_aliases()->clear();
    ifCan_.remote_aliases()->clear();
    // Deletes all reserved aliases from the queue.
    while (!ifCan_.alias_allocator()->reserved_aliases()->empty())
    {
        Buffer<AliasInfo> *a = static_cast<Buffer<AliasInfo> *>(
            ifCan_.alias_allocator()->reserved_aliases()->next().item);
        if (a)
        {
            a->unref();
        }
    }

    // Bootstraps the fresh alias allocation process.
    ifCan_.alias_allocator()->send(ifCan_.alias_allocator()->alloc());
    extern void StartInitializationFlow(Node * node);
    StartInitializationFlow(&node_);
}

void SimpleCanStack::check_version_and_factory_reset(
    const InternalConfigData &cfg, uint16_t expected_version, bool force)
{
    HASSERT(CONFIG_FILENAME);
    int fd = configUpdateFlow_.open_file(CONFIG_FILENAME);
    if (cfg.version().read(fd) != expected_version)
    {
        /// TODO(balazs.racz): We need to clear the eeprom. Best would be if
        /// there was an ioctl to return the eeprom to factory default state by
        /// just erasing the segments.
        cfg.version().write(fd, expected_version);
        cfg.next_event().write(fd, 0);
        // ACDI version byte. This is not very nice because we cannot be
        // certain that the EEPROM starts with the ACDI data. We'll check it
        // though.
        HASSERT(SNIP_DYNAMIC_FILENAME == CONFIG_FILENAME);
        Uint8ConfigEntry(0).write(fd, 2);
        force = true;
    }
    if (force)
    {
        factory_reset_all_events(cfg, fd);
        configUpdateFlow_.factory_reset();
    }
}

extern const uint16_t CDI_EVENT_OFFSETS[];

void SimpleCanStack::factory_reset_all_events(
    const InternalConfigData &cfg, int fd)
{
    // First we find the event count.
    uint16_t new_next_event = cfg.next_event().read(fd);
    uint16_t next_event = new_next_event;
    for (unsigned i = 0; CDI_EVENT_OFFSETS[i]; ++i)
    {
        ++new_next_event;
    }
    // We block off the event IDs first.
    cfg.next_event().write(fd, new_next_event);
    // Then we write them to eeprom.
    for (unsigned i = 0; CDI_EVENT_OFFSETS[i]; ++i)
    {
        EventId id = node_.node_id();
        id <<= 16;
        id |= next_event++;
        EventConfigEntry(CDI_EVENT_OFFSETS[i]).write(fd, id);
    }
}

void SimpleCanStack::add_gridconnect_port(const char *path, Notifiable *on_exit)
{
    int fd = ::open(path, O_RDWR);
    HASSERT(fd >= 0);
    LOG(INFO, "Adding device %s as fd %d", path, fd);
    create_gc_port_for_can_hub(&canHub0_, fd, on_exit);
}

#if defined(__linux__) || defined(__MACH__)
void SimpleCanStack::add_gridconnect_tty(
    const char *device, Notifiable *on_exit)
{
    int fd = ::open(device, O_RDWR);
    HASSERT(fd >= 0);
    LOG(INFO, "Adding device %s as fd %d", device, fd);
    create_gc_port_for_can_hub(&canHub0_, fd, on_exit);

    HASSERT(!tcflush(fd, TCIOFLUSH));
    struct termios settings;
    HASSERT(!tcgetattr(fd, &settings));
    cfmakeraw(&settings);
    cfsetspeed(&settings, B115200);
    HASSERT(!tcsetattr(fd, TCSANOW, &settings));
}

void SimpleCanStack::add_socketcan_port_select(const char *device)
{
    int s;
    struct sockaddr_can addr;
    struct ifreq ifr;

    s = socket(PF_CAN, SOCK_RAW, CAN_RAW);

    /* Set the blocking limit to the minimum allowed, typically 1024 in Linux */
    int sndbuf = 0;
    setsockopt(s, SOL_SOCKET, SO_SNDBUF, &sndbuf, sizeof(sndbuf));

    strcpy(ifr.ifr_name, device );
    ioctl(s, SIOCGIFINDEX, &ifr);

    addr.can_family = AF_CAN;
    addr.can_ifindex = ifr.ifr_ifindex;

    bind(s, (struct sockaddr *)&addr, sizeof(addr));

    auto* port = new HubDeviceSelect<CanHubFlow>(&canHub0_, s);
    additionalComponents_.emplace_back(port);
}
#endif
extern Pool *const __attribute__((
    __weak__)) g_incoming_datagram_allocator = init_main_buffer_pool();

} // namespace nmranet
<commit_msg>trivial todo comment fix<commit_after>/** \copyright
 * Copyright (c) 2015, Balazs Racz
 * 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.
 *
 * 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.
 *
 * \file SimpleStack.cxx
 *
 * A complete OpenLCB stack for use in straightforward OpenLCB nodes.
 *
 * @author Balazs Racz
 * @date 18 Mar 2015
 */

#if defined(__linux__) || defined(__MACH__)
#include <termios.h> /* tc* functions */
#include <net/if.h>
#include <linux/sockios.h>
#endif

#include "nmranet/SimpleStack.hxx"

#include "nmranet/EventHandler.hxx"
#include "nmranet/SimpleNodeInfo.hxx"

namespace nmranet
{

SimpleCanStack::SimpleCanStack(const nmranet::NodeID node_id)
    : node_(&ifCan_, node_id)
{
    AddAliasAllocator(node_id, &ifCan_);
}

void SimpleCanStack::start_stack()
{
    // Opens the eeprom file and sends configuration update commands to all
    // listeners.
    configUpdateFlow_.open_file(CONFIG_FILENAME);
    configUpdateFlow_.init_flow();

    // Bootstraps the alias allocation process.
    ifCan_.alias_allocator()->send(ifCan_.alias_allocator()->alloc());

    // Adds memory spaces.
    if (config_enable_all_memory_space() == CONSTANT_TRUE)
    {
        auto *space = new ReadOnlyMemoryBlock(nullptr, 0xFFFFFFFFUL);
        memoryConfigHandler_.registry()->insert(
            nullptr, MemoryConfigDefs::SPACE_ALL_MEMORY, space);
        additionalComponents_.emplace_back(space);
    }
    {
        auto *space = new ReadOnlyMemoryBlock(
            reinterpret_cast<const uint8_t *>(&SNIP_STATIC_DATA),
            sizeof(SNIP_STATIC_DATA));
        memoryConfigHandler_.registry()->insert(
            &node_, MemoryConfigDefs::SPACE_ACDI_SYS, space);
        additionalComponents_.emplace_back(space);
    }
    {
        auto *space = new FileMemorySpace(
            SNIP_DYNAMIC_FILENAME, sizeof(SimpleNodeDynamicValues));
        memoryConfigHandler_.registry()->insert(
            &node_, MemoryConfigDefs::SPACE_ACDI_USR, space);
        additionalComponents_.emplace_back(space);
    }
    {
        auto *space = new ReadOnlyMemoryBlock(
            reinterpret_cast<const uint8_t *>(&CDI_DATA), strlen(CDI_DATA) + 1);
        memoryConfigHandler_.registry()->insert(
            &node_, MemoryConfigDefs::SPACE_CDI, space);
        additionalComponents_.emplace_back(space);
    }
    if (CONFIG_FILENAME != nullptr)
    {
        auto *space = new FileMemorySpace(CONFIG_FILENAME, CONFIG_FILE_SIZE);
        memory_config_handler()->registry()->insert(
            &node_, nmranet::MemoryConfigDefs::SPACE_CONFIG, space);
        additionalComponents_.emplace_back(space);
    }
}

void SimpleCanStack::restart_stack()
{
    node_.clear_initialized();
    ifCan_.alias_allocator()->reinit_seed();
    ifCan_.local_aliases()->clear();
    ifCan_.remote_aliases()->clear();
    // Deletes all reserved aliases from the queue.
    while (!ifCan_.alias_allocator()->reserved_aliases()->empty())
    {
        Buffer<AliasInfo> *a = static_cast<Buffer<AliasInfo> *>(
            ifCan_.alias_allocator()->reserved_aliases()->next().item);
        if (a)
        {
            a->unref();
        }
    }

    // Bootstraps the fresh alias allocation process.
    ifCan_.alias_allocator()->send(ifCan_.alias_allocator()->alloc());
    extern void StartInitializationFlow(Node * node);
    StartInitializationFlow(&node_);
}

void SimpleCanStack::check_version_and_factory_reset(
    const InternalConfigData &cfg, uint16_t expected_version, bool force)
{
    HASSERT(CONFIG_FILENAME);
    int fd = configUpdateFlow_.open_file(CONFIG_FILENAME);
    if (cfg.version().read(fd) != expected_version)
    {
        /// @todo (balazs.racz): We need to clear the eeprom. Best would be if
        /// there was an ioctl to return the eeprom to factory default state by
        /// just erasing the segments.
        cfg.version().write(fd, expected_version);
        cfg.next_event().write(fd, 0);
        // ACDI version byte. This is not very nice because we cannot be
        // certain that the EEPROM starts with the ACDI data. We'll check it
        // though.
        HASSERT(SNIP_DYNAMIC_FILENAME == CONFIG_FILENAME);
        Uint8ConfigEntry(0).write(fd, 2);
        force = true;
    }
    if (force)
    {
        factory_reset_all_events(cfg, fd);
        configUpdateFlow_.factory_reset();
    }
}

extern const uint16_t CDI_EVENT_OFFSETS[];

void SimpleCanStack::factory_reset_all_events(
    const InternalConfigData &cfg, int fd)
{
    // First we find the event count.
    uint16_t new_next_event = cfg.next_event().read(fd);
    uint16_t next_event = new_next_event;
    for (unsigned i = 0; CDI_EVENT_OFFSETS[i]; ++i)
    {
        ++new_next_event;
    }
    // We block off the event IDs first.
    cfg.next_event().write(fd, new_next_event);
    // Then we write them to eeprom.
    for (unsigned i = 0; CDI_EVENT_OFFSETS[i]; ++i)
    {
        EventId id = node_.node_id();
        id <<= 16;
        id |= next_event++;
        EventConfigEntry(CDI_EVENT_OFFSETS[i]).write(fd, id);
    }
}

void SimpleCanStack::add_gridconnect_port(const char *path, Notifiable *on_exit)
{
    int fd = ::open(path, O_RDWR);
    HASSERT(fd >= 0);
    LOG(INFO, "Adding device %s as fd %d", path, fd);
    create_gc_port_for_can_hub(&canHub0_, fd, on_exit);
}

#if defined(__linux__) || defined(__MACH__)
void SimpleCanStack::add_gridconnect_tty(
    const char *device, Notifiable *on_exit)
{
    int fd = ::open(device, O_RDWR);
    HASSERT(fd >= 0);
    LOG(INFO, "Adding device %s as fd %d", device, fd);
    create_gc_port_for_can_hub(&canHub0_, fd, on_exit);

    HASSERT(!tcflush(fd, TCIOFLUSH));
    struct termios settings;
    HASSERT(!tcgetattr(fd, &settings));
    cfmakeraw(&settings);
    cfsetspeed(&settings, B115200);
    HASSERT(!tcsetattr(fd, TCSANOW, &settings));
}

void SimpleCanStack::add_socketcan_port_select(const char *device)
{
    int s;
    struct sockaddr_can addr;
    struct ifreq ifr;

    s = socket(PF_CAN, SOCK_RAW, CAN_RAW);

    /* Set the blocking limit to the minimum allowed, typically 1024 in Linux */
    int sndbuf = 0;
    setsockopt(s, SOL_SOCKET, SO_SNDBUF, &sndbuf, sizeof(sndbuf));

    strcpy(ifr.ifr_name, device );
    ioctl(s, SIOCGIFINDEX, &ifr);

    addr.can_family = AF_CAN;
    addr.can_ifindex = ifr.ifr_ifindex;

    bind(s, (struct sockaddr *)&addr, sizeof(addr));

    auto* port = new HubDeviceSelect<CanHubFlow>(&canHub0_, s);
    additionalComponents_.emplace_back(port);
}
#endif
extern Pool *const __attribute__((
    __weak__)) g_incoming_datagram_allocator = init_main_buffer_pool();

} // namespace nmranet
<|endoftext|>


<commit_before>
/*
 * MIT License
 *
 * Copyright (c) 2017 Susanow
 * Copyright (c) 2017 Hiroki SHIROKURA
 *
 * 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 <stdio.h>
#include <stdint.h>
#include <stddef.h>
#include <slankdev/string.h>
#include <slankdev/exception.h>

#include <ssn_port.h>
#include <ssn_common.h>
#include <ssn_log.h>
#include <dpdk/dpdk.h>
#include <ssn_vnf_v02_l2fwd1b.h>

int main(int argc, char** argv)
{
  ssn_init(argc, argv);
  size_t n_ports = ssn_dev_count();
  if (n_ports != 2) {
    std::string err = slankdev::format("n_ports is not 2 (current %zd)",
        ssn_dev_count());
    throw slankdev::exception(err.c_str());
  }

  rte_mempool* mp = dpdk::mp_alloc("ssn");
  ssn_vnf_port* port0 = new ssn_vnf_port_dpdk("dpdk0", 0, 4, 4, mp); // dpdk0
  ssn_vnf_port* port1 = new ssn_vnf_port_dpdk("dpdk1", 1, 4, 4, mp); // dpdk1
  printf("\n");
  port0->debug_dump(stdout); printf("\n");
  port1->debug_dump(stdout); printf("\n");

  ssn_vnf_l2fwd1b v0("vnf0");
  v0.attach_port(0, port0);
  v0.attach_port(1, port1);

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

  v0.reset_allport_acc();
  v0.set_coremask(0, 0b00000010);
  v0.deploy();
  getchar();
  v0.undeploy();

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

  v0.reset_allport_acc();
  v0.set_coremask(0, 0b00000110);
  v0.deploy();
  getchar();
  v0.undeploy();

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

  v0.reset_allport_acc();
  v0.set_coremask(0, 0b00011110);
  v0.deploy();
  getchar();
  v0.undeploy();

fin:
  rte_mempool_free(mp);
  delete port0;
  delete port1;
  ssn_fin();
}

<commit_msg>WIP lib/libsusanow: add interface to ssn_vnf<commit_after>
/*
 * MIT License
 *
 * Copyright (c) 2017 Susanow
 * Copyright (c) 2017 Hiroki SHIROKURA
 *
 * 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 <stdio.h>
#include <stdint.h>
#include <stddef.h>
#include <slankdev/string.h>
#include <slankdev/exception.h>

#include <ssn_port.h>
#include <ssn_common.h>
#include <ssn_log.h>
#include <dpdk/dpdk.h>
#include <ssn_vnf_v02_l2fwd1b.h>

bool running;
void print_perf(void*)
{
  running = true;
  while (running) {
    printf("perf\n");
    ssn_sleep(1000);
    ssn_yield();
  }
}

int main(int argc, char** argv)
{
  ssn_init(argc, argv);
  size_t n_ports = ssn_dev_count();
  if (n_ports != 2) {
    std::string err = slankdev::format("n_ports is not 2 (current %zd)",
        ssn_dev_count());
    throw slankdev::exception(err.c_str());
  }

  constexpr size_t green_thread_lid = 7;
  ssn_green_thread_sched_register(green_thread_lid);
  uint64_t tid = ssn_thread_launch(print_perf, nullptr, green_thread_lid);

  rte_mempool* mp = dpdk::mp_alloc("ssn");
  ssn_vnf_port* port0 = new ssn_vnf_port_dpdk("dpdk0", 0, 4, 4, mp); // dpdk0
  ssn_vnf_port* port1 = new ssn_vnf_port_dpdk("dpdk1", 1, 4, 4, mp); // dpdk1
  printf("\n");
  port0->debug_dump(stdout); printf("\n");
  port1->debug_dump(stdout); printf("\n");

  ssn_vnf_l2fwd1b v0("vnf0");
  v0.attach_port(0, port0);
  v0.attach_port(1, port1);

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

  v0.reset_allport_acc();
  v0.set_coremask(0, 0b00000010);
  v0.deploy();
  getchar();
  v0.undeploy();

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

  v0.reset_allport_acc();
  v0.set_coremask(0, 0b00000110);
  v0.deploy();
  getchar();
  v0.undeploy();

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

  v0.reset_allport_acc();
  v0.set_coremask(0, 0b00011110);
  v0.deploy();
  getchar();
  v0.undeploy();

fin:
  running = false;
  ssn_thread_join(tid);
  rte_mempool_free(mp);
  delete port0;
  delete port1;
  ssn_fin();
}

<|endoftext|>


<commit_before>
/*
 * BSD 3-Clause License
 *
 * Copyright (c) 2017, mtezych
 * 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 <utility>
#include <cassert>

namespace adt
{
	template <typename value_type>
	class unique_ptr
	{
	private:
		value_type* ptr;

	public:
		unique_ptr ()
		:
			ptr { nullptr }
		{
		}

		unique_ptr (std::nullptr_t)
		:
			ptr { nullptr }
		{
		}

		explicit unique_ptr (value_type* const ptr)
		:
			ptr { ptr }
		{
		}

		~unique_ptr ()
		{
			delete ptr;
		}

		unique_ptr (const unique_ptr&) = delete;

		unique_ptr& operator = (const unique_ptr&) = delete;

		unique_ptr (unique_ptr&& uptr)
		:
			ptr { uptr.ptr }
		{
			uptr.ptr = nullptr;
		}

		unique_ptr& operator = (unique_ptr&& uptr)
		{
			delete ptr;
			ptr = uptr.ptr;
			uptr.ptr = nullptr;
			return *this;
		}

		unique_ptr& operator = (std::nullptr_t)
		{
			delete ptr;
			ptr = nullptr;
			return *this;
		}

		value_type& operator * () const
		{
			assert(ptr != nullptr);
			return *ptr;
		}

		value_type* operator -> () const
		{
			return ptr;
		}

		value_type* get () const
		{
			return ptr;
		}

		explicit operator bool () const
		{
			return ptr != nullptr;
		}

		value_type* release ()
		{
			const auto result = ptr;
			ptr = nullptr;
			return result;
		}

		void reset (value_type* const ptr = nullptr)
		{
			delete this->ptr;
			this->ptr = ptr;
		}
	};

	template <typename value_type>
	bool operator == (const unique_ptr<value_type>& uptr, std::nullptr_t)
	{
		return uptr.get() == nullptr;
	}

	template <typename value_type>
	bool operator != (const unique_ptr<value_type>& uptr, std::nullptr_t)
	{
		return uptr.get() != nullptr;
	}

	template <typename value_type>
	bool operator == (std::nullptr_t, const unique_ptr<value_type>& uptr)
	{
		return nullptr == uptr.get();
	}

	template <typename value_type>
	bool operator != (std::nullptr_t, const unique_ptr<value_type>& uptr)
	{
		return nullptr != uptr.get();
	}

	template <typename value_type, typename... args_types>
	unique_ptr<value_type> make_unique (args_types&&... args)
	{
		return unique_ptr<value_type> { new value_type { std::forward<args_types>(args)... } };
	}
}

namespace assert
{
	template <typename value_type>
	void empty (const adt::unique_ptr<value_type>& ptr)
	{
		assert(ptr.get() == nullptr);
		assert(ptr == nullptr);
		assert(!ptr);
	}

	template <typename value_type>
	void owns (const adt::unique_ptr<value_type>& ptr, const value_type& value)
	{
		assert(ptr.get() != nullptr);
		assert(ptr != nullptr);
		assert(ptr);

		assert(*ptr.get() == value);
		assert(*ptr == value);
	}

	void success()
	{
		static_assert(true);
	}

	void fail()
	{
		assert(false);
	}
}

#include <vector>

namespace test
{
	void default_constructor ()
	{
		const adt::unique_ptr<float> ptr { };

		assert::empty(ptr);
	}

	void converting_constructor ()
	{
		const adt::unique_ptr<char> ptr { nullptr };

		assert::empty(ptr);
	}

	void from_pointer_constructor ()
	{
		const adt::unique_ptr<char> ptr { new char { '#' } };

		assert::owns(ptr, '#');
	}

	void destructor ()
	{
		struct Foo
		{
		private:
			bool& isDestructorCalled;

		public:
			explicit Foo (bool& isDestructorCalled)
			:
				isDestructorCalled { isDestructorCalled }
			{
			}

			~Foo ()
			{
				isDestructorCalled = true;
			}

			bool operator == (const Foo& foo) const
			{
				return &isDestructorCalled == &foo.isDestructorCalled;
			}
		};

		auto isDestructorCalled = false;
		{
			const adt::unique_ptr<Foo> ptr { new Foo { isDestructorCalled } };

			assert::owns(ptr, Foo { isDestructorCalled });
		}
		assert(isDestructorCalled);
	}

	void move_constructor ()
	{
		const auto ptr = adt::unique_ptr<int> { new int { 8 } };

		assert::owns(ptr, 8);
	}

	void move_assignment ()
	{
		// Moving generally invalidates objects,
		// but this implementation should leave unique pointer in empty state.

		auto ptr1 = adt::unique_ptr<int> { new int { 7 } };
		auto ptr2 = adt::unique_ptr<int> { nullptr };
		assert::owns(ptr1, 7);
		assert::empty(ptr2);

		ptr2 = std::move(ptr1);
		assert::owns(ptr2, 7);
		assert::empty(ptr1);

		ptr1 = std::move(ptr2);
		assert::owns(ptr1, 7);
		assert::empty(ptr2);
	}

	void nullptr_assignment ()
	{
		auto ptr = adt::unique_ptr<int> { new int { 9 } };
		assert::owns(ptr, 9);

		ptr = nullptr;
		assert::empty(ptr);
	}

	void make_unique ()
	{
		struct Foo
		{
			int   i;
			float f;

			bool operator == (const Foo& foo) const
			{
				return (i == foo.i) && (f == foo.f);
			}
		};

		const auto ptr1 = adt::make_unique<Foo>(8, 1.0f);
		assert::owns(ptr1, Foo { 8, 1.0f });

		const auto ptr2 = adt::make_unique<Foo>();
		assert::owns(ptr2, Foo { });
	}

	void arrow_operator ()
	{
		struct Foo
		{
		private:
			mutable
			bool isBarCalled = false;
			bool isQuxCalled = false;

		public:
			const Foo& Bar () const
			{
				isBarCalled = true;
				return *this;
			}

			Foo& Qux ()
			{
				isQuxCalled = true;
				return *this;
			}

			bool operator == (const Foo& foo) const
			{
				return (isBarCalled == foo.isBarCalled) && (isQuxCalled == foo.isQuxCalled);
			}
		};

		const auto ptr1 = adt::make_unique<Foo>();
		assert::owns(ptr1, Foo { });

		ptr1->Qux();
		ptr1->Bar();
		assert::owns(ptr1, Foo { }.Qux().Bar());

		const auto ptr2 = adt::make_unique<const Foo>();
		assert::owns<const Foo>(ptr2, Foo { });

		ptr2->Bar();
		assert::owns<const Foo>(ptr2, Foo { }.Bar());
	}

	void bool_conversion_operator ()
	{
		auto ptr1 = adt::make_unique<int>(1);
		assert::owns(ptr1, 1);

		if (ptr1)
		{
			assert::success();
		}
		else
		{
			assert::fail();
		}

		auto ptr2 = adt::unique_ptr<int> { nullptr };
		assert::empty(ptr2);

		if (!ptr2)
		{
			assert::success();
		}
		else
		{
			assert::fail();
		}
	}

	void comparison_operators ()
	{
		auto ptr1 = adt::make_unique<int>(1);
		assert::owns(ptr1, 1);

		auto ptr2 = adt::unique_ptr<int> { nullptr };
		assert::empty(ptr2);

		const auto conditions = std::vector<bool>
		{
			ptr1 != nullptr, nullptr != ptr1,
			ptr2 == nullptr, nullptr == ptr2,
		};

		for (auto condition : conditions)
		{
			if (condition)
			{
				assert::success();
			}
			else
			{
				assert::fail();
			}
		}
	}

	void release ()
	{
		auto ptr = adt::make_unique<int>(4);
		assert::owns(ptr, 4);

		delete ptr.release();
		assert::empty(ptr);
	}

	void reset_nullptr ()
	{
		auto ptr = adt::make_unique<int>(2);
		assert::owns(ptr, 2);

		ptr.reset();
		assert::empty(ptr);
	}

	void reset ()
	{
		auto ptr = adt::make_unique<int>(1);
		assert::owns(ptr, 1);

		ptr.reset(new int { 11 });
		assert::owns(ptr, 11);
	}
}

int main ()
{
	test::default_constructor();
	test::converting_constructor();
	test::from_pointer_constructor();
	test::destructor();
	test::move_constructor();
	test::move_assignment();
	test::nullptr_assignment();
	test::make_unique();
	test::arrow_operator();
	test::bool_conversion_operator();
	test::comparison_operators();
	test::release();
	test::reset_nullptr();
	test::reset();

	return 0;
}
<commit_msg>ADT -> Assert fix in unique_ptr.<commit_after>
/*
 * BSD 3-Clause License
 *
 * Copyright (c) 2017, mtezych
 * 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 <utility>
#include <cassert>

namespace adt
{
	template <typename value_type>
	class unique_ptr
	{
	private:
		value_type* ptr;

	public:
		unique_ptr ()
		:
			ptr { nullptr }
		{
		}

		unique_ptr (std::nullptr_t)
		:
			ptr { nullptr }
		{
		}

		explicit unique_ptr (value_type* const ptr)
		:
			ptr { ptr }
		{
		}

		~unique_ptr ()
		{
			delete ptr;
		}

		unique_ptr (const unique_ptr&) = delete;

		unique_ptr& operator = (const unique_ptr&) = delete;

		unique_ptr (unique_ptr&& uptr)
		:
			ptr { uptr.ptr }
		{
			uptr.ptr = nullptr;
		}

		unique_ptr& operator = (unique_ptr&& uptr)
		{
			delete ptr;
			ptr = uptr.ptr;
			uptr.ptr = nullptr;
			return *this;
		}

		unique_ptr& operator = (std::nullptr_t)
		{
			delete ptr;
			ptr = nullptr;
			return *this;
		}

		value_type& operator * () const
		{
			assert(ptr != nullptr);
			return *ptr;
		}

		value_type* operator -> () const
		{
			return ptr;
		}

		value_type* get () const
		{
			return ptr;
		}

		explicit operator bool () const
		{
			return ptr != nullptr;
		}

		value_type* release ()
		{
			const auto result = ptr;
			ptr = nullptr;
			return result;
		}

		void reset (value_type* const ptr = nullptr)
		{
			delete this->ptr;
			this->ptr = ptr;
		}
	};

	template <typename value_type>
	bool operator == (const unique_ptr<value_type>& uptr, std::nullptr_t)
	{
		return uptr.get() == nullptr;
	}

	template <typename value_type>
	bool operator != (const unique_ptr<value_type>& uptr, std::nullptr_t)
	{
		return uptr.get() != nullptr;
	}

	template <typename value_type>
	bool operator == (std::nullptr_t, const unique_ptr<value_type>& uptr)
	{
		return nullptr == uptr.get();
	}

	template <typename value_type>
	bool operator != (std::nullptr_t, const unique_ptr<value_type>& uptr)
	{
		return nullptr != uptr.get();
	}

	template <typename value_type, typename... args_types>
	unique_ptr<value_type> make_unique (args_types&&... args)
	{
		return unique_ptr<value_type> { new value_type { std::forward<args_types>(args)... } };
	}
}

namespace assert
{
	template <typename value_type>
	void empty (const adt::unique_ptr<value_type>& ptr)
	{
		assert(ptr.get() == nullptr);
		assert(ptr == nullptr);
		assert(!ptr);
	}

	template <typename value_type>
	void owns (const adt::unique_ptr<value_type>& ptr, const value_type& value)
	{
		assert(ptr.get() != nullptr);
		assert(ptr != nullptr);
		assert(ptr);

		assert(*ptr.get() == value);
		assert(*ptr == value);
	}

	void success()
	{
		assert(true);
	}

	void fail()
	{
		assert(false);
	}
}

#include <vector>

namespace test
{
	void default_constructor ()
	{
		const adt::unique_ptr<float> ptr { };

		assert::empty(ptr);
	}

	void converting_constructor ()
	{
		const adt::unique_ptr<char> ptr { nullptr };

		assert::empty(ptr);
	}

	void from_pointer_constructor ()
	{
		const adt::unique_ptr<char> ptr { new char { '#' } };

		assert::owns(ptr, '#');
	}

	void destructor ()
	{
		struct Foo
		{
		private:
			bool& isDestructorCalled;

		public:
			explicit Foo (bool& isDestructorCalled)
			:
				isDestructorCalled { isDestructorCalled }
			{
			}

			~Foo ()
			{
				isDestructorCalled = true;
			}

			bool operator == (const Foo& foo) const
			{
				return &isDestructorCalled == &foo.isDestructorCalled;
			}
		};

		auto isDestructorCalled = false;
		{
			const adt::unique_ptr<Foo> ptr { new Foo { isDestructorCalled } };

			assert::owns(ptr, Foo { isDestructorCalled });
		}
		assert(isDestructorCalled);
	}

	void move_constructor ()
	{
		const auto ptr = adt::unique_ptr<int> { new int { 8 } };

		assert::owns(ptr, 8);
	}

	void move_assignment ()
	{
		// Moving generally invalidates objects,
		// but this implementation should leave unique pointer in empty state.

		auto ptr1 = adt::unique_ptr<int> { new int { 7 } };
		auto ptr2 = adt::unique_ptr<int> { nullptr };
		assert::owns(ptr1, 7);
		assert::empty(ptr2);

		ptr2 = std::move(ptr1);
		assert::owns(ptr2, 7);
		assert::empty(ptr1);

		ptr1 = std::move(ptr2);
		assert::owns(ptr1, 7);
		assert::empty(ptr2);
	}

	void nullptr_assignment ()
	{
		auto ptr = adt::unique_ptr<int> { new int { 9 } };
		assert::owns(ptr, 9);

		ptr = nullptr;
		assert::empty(ptr);
	}

	void make_unique ()
	{
		struct Foo
		{
			int   i;
			float f;

			bool operator == (const Foo& foo) const
			{
				return (i == foo.i) && (f == foo.f);
			}
		};

		const auto ptr1 = adt::make_unique<Foo>(8, 1.0f);
		assert::owns(ptr1, Foo { 8, 1.0f });

		const auto ptr2 = adt::make_unique<Foo>();
		assert::owns(ptr2, Foo { });
	}

	void arrow_operator ()
	{
		struct Foo
		{
		private:
			mutable
			bool isBarCalled = false;
			bool isQuxCalled = false;

		public:
			const Foo& Bar () const
			{
				isBarCalled = true;
				return *this;
			}

			Foo& Qux ()
			{
				isQuxCalled = true;
				return *this;
			}

			bool operator == (const Foo& foo) const
			{
				return (isBarCalled == foo.isBarCalled) && (isQuxCalled == foo.isQuxCalled);
			}
		};

		const auto ptr1 = adt::make_unique<Foo>();
		assert::owns(ptr1, Foo { });

		ptr1->Qux();
		ptr1->Bar();
		assert::owns(ptr1, Foo { }.Qux().Bar());

		const auto ptr2 = adt::make_unique<const Foo>();
		assert::owns<const Foo>(ptr2, Foo { });

		ptr2->Bar();
		assert::owns<const Foo>(ptr2, Foo { }.Bar());
	}

	void bool_conversion_operator ()
	{
		auto ptr1 = adt::make_unique<int>(1);
		assert::owns(ptr1, 1);

		if (ptr1)
		{
			assert::success();
		}
		else
		{
			assert::fail();
		}

		auto ptr2 = adt::unique_ptr<int> { nullptr };
		assert::empty(ptr2);

		if (!ptr2)
		{
			assert::success();
		}
		else
		{
			assert::fail();
		}
	}

	void comparison_operators ()
	{
		auto ptr1 = adt::make_unique<int>(1);
		assert::owns(ptr1, 1);

		auto ptr2 = adt::unique_ptr<int> { nullptr };
		assert::empty(ptr2);

		const auto conditions = std::vector<bool>
		{
			ptr1 != nullptr, nullptr != ptr1,
			ptr2 == nullptr, nullptr == ptr2,
		};

		for (auto condition : conditions)
		{
			if (condition)
			{
				assert::success();
			}
			else
			{
				assert::fail();
			}
		}
	}

	void release ()
	{
		auto ptr = adt::make_unique<int>(4);
		assert::owns(ptr, 4);

		delete ptr.release();
		assert::empty(ptr);
	}

	void reset_nullptr ()
	{
		auto ptr = adt::make_unique<int>(2);
		assert::owns(ptr, 2);

		ptr.reset();
		assert::empty(ptr);
	}

	void reset ()
	{
		auto ptr = adt::make_unique<int>(1);
		assert::owns(ptr, 1);

		ptr.reset(new int { 11 });
		assert::owns(ptr, 11);
	}
}

int main ()
{
	test::default_constructor();
	test::converting_constructor();
	test::from_pointer_constructor();
	test::destructor();
	test::move_constructor();
	test::move_assignment();
	test::nullptr_assignment();
	test::make_unique();
	test::arrow_operator();
	test::bool_conversion_operator();
	test::comparison_operators();
	test::release();
	test::reset_nullptr();
	test::reset();

	return 0;
}
<|endoftext|>


<commit_before>#include <iostream>
#include "SFML\Graphics.hpp"
#include "Utils.h"
#include "Ball.h"

int main() {
    //You can turn off antialiasing if your graphics card doesn't support it
    sf::ContextSettings context;
    context.antialiasingLevel = 4;

    sf::RenderWindow window(sf::VideoMode(400, 400), "Boxes", sf::Style::Titlebar | sf::Style::Close,
                            context);
    window.setFramerateLimit(60);

    Ball ball(window.getSize().x / 2, window.getSize().y / 2, 40, sf::Color::Red);
    sf::Font font;
    if(!font.loadFromFile("res/cour.ttf")){
        std::cerr << "Error loading cout.ttf file" << std::endl;
        return -1;
    }

    sf::Text hitText;
    hitText.setFont(font);
    hitText.setCharacterSize(15);
    hitText.setFillColor(sf::Color::Black);
    hitText.setPosition(sf::Vector2f(10,10));

    window.clear(sf::Color::White);
    std::vector<sf::Vertex> bounds;
    bounds.emplace_back(sf::Vertex(sf::Vector2f(ball.GetBounds().top, ball.GetBounds().left), sf::Color::Black));
    bounds.emplace_back(sf::Vertex(sf::Vector2f(ball.GetBounds().top, ball.GetBounds().left + ball.GetBounds().width), sf::Color::Black));
    bounds.emplace_back(sf::Vertex(sf::Vector2f(ball.GetBounds().top + ball.GetBounds().height, ball.GetBounds().left + ball.GetBounds().width), sf::Color::Black));
    bounds.emplace_back(sf::Vertex(sf::Vector2f(ball.GetBounds().top + ball.GetBounds().height, ball.GetBounds().left), sf::Color::Black));
    bounds.emplace_back(sf::Vertex(sf::Vector2f(ball.GetBounds().top, ball.GetBounds().left), sf::Color::Black));

    window.draw(&bounds[0], bounds.size(), sf::PrimitiveType::LinesStrip);
    window.draw(ball.shape);

    while (window.isOpen()) {
        sf::Event event;
        while (window.pollEvent(event)) {
            switch (event.type) {
                case sf::Event::Closed:
                    window.close();
                    break;
                case sf::Event::MouseMoved:
                    if(Utils::ContainsPoint(ball.GetBounds(), event.mouseMove.x, event.mouseMove.y))
                        hitText.setString("Hit");
                    else
                        hitText.setString("");
            }
        }
        window.clear(sf::Color::White);
        window.draw(hitText);
        window.draw(&bounds[0], bounds.size(), sf::PrimitiveType::LinesStrip);
        window.draw(ball.shape);
        window.display();
    }
}<commit_msg>Fixed window title of CH09E03<commit_after>#include <iostream>
#include "SFML\Graphics.hpp"
#include "Utils.h"
#include "Ball.h"

int main() {
    //You can turn off antialiasing if your graphics card doesn't support it
    sf::ContextSettings context;
    context.antialiasingLevel = 4;

    sf::RenderWindow window(sf::VideoMode(400, 400), "Point Hit Test", sf::Style::Titlebar | sf::Style::Close,
                            context);
    window.setFramerateLimit(60);

    Ball ball(window.getSize().x / 2, window.getSize().y / 2, 40, sf::Color::Red);
    sf::Font font;
    if(!font.loadFromFile("res/cour.ttf")){
        std::cerr << "Error loading cout.ttf file" << std::endl;
        return -1;
    }

    sf::Text hitText;
    hitText.setFont(font);
    hitText.setCharacterSize(15);
    hitText.setFillColor(sf::Color::Black);
    hitText.setPosition(sf::Vector2f(10,10));

    window.clear(sf::Color::White);
    std::vector<sf::Vertex> bounds;
    bounds.emplace_back(sf::Vertex(sf::Vector2f(ball.GetBounds().top, ball.GetBounds().left), sf::Color::Black));
    bounds.emplace_back(sf::Vertex(sf::Vector2f(ball.GetBounds().top, ball.GetBounds().left + ball.GetBounds().width), sf::Color::Black));
    bounds.emplace_back(sf::Vertex(sf::Vector2f(ball.GetBounds().top + ball.GetBounds().height, ball.GetBounds().left + ball.GetBounds().width), sf::Color::Black));
    bounds.emplace_back(sf::Vertex(sf::Vector2f(ball.GetBounds().top + ball.GetBounds().height, ball.GetBounds().left), sf::Color::Black));
    bounds.emplace_back(sf::Vertex(sf::Vector2f(ball.GetBounds().top, ball.GetBounds().left), sf::Color::Black));

    window.draw(&bounds[0], bounds.size(), sf::PrimitiveType::LinesStrip);
    window.draw(ball.shape);

    while (window.isOpen()) {
        sf::Event event;
        while (window.pollEvent(event)) {
            switch (event.type) {
                case sf::Event::Closed:
                    window.close();
                    break;
                case sf::Event::MouseMoved:
                    if(Utils::ContainsPoint(ball.GetBounds(), event.mouseMove.x, event.mouseMove.y))
                        hitText.setString("Hit");
                    else
                        hitText.setString("");
            }
        }
        window.clear(sf::Color::White);
        window.draw(hitText);
        window.draw(&bounds[0], bounds.size(), sf::PrimitiveType::LinesStrip);
        window.draw(ball.shape);
        window.display();
    }
}<|endoftext|>


<commit_before>#include <ros/ros.h>
#include <pcl_ros/point_cloud.h>
#include <pcl/point_types.h>
#include <pcl/octree/octree.h>
#include <vector>
#include <pcl/filters/voxel_grid.h>
#include <boost/foreach.hpp>
#include <ros/console.h>
#include <pcl/filters/extract_indices.h>
#include "std_msgs/Int64.h"

typedef pcl::PointCloud<pcl::PointXYZ> PointCloud;
float resolution = 1.0f;
pcl::octree::OctreePointCloudChangeDetector<pcl::PointXYZ> octree (resolution);
ros::Publisher pub;

void callback(const PointCloud::ConstPtr& msg)
{
  pcl::ExtractIndices<pcl::PointXYZ> extract;
  octree.switchBuffers();
  octree.setInputCloud(msg);
  octree.addPointsFromInputCloud();
  std::vector<int> newPointIdxVector;
  octree.getPointIndicesFromNewVoxels(newPointIdxVector);
  std_msgs::Int64 msg_publish;
  msg_publish.data = newPointIdxVector.size();
  pub.publish(msg_publish);

}

int main(int argc, char** argv)
{
  ros::init(argc, argv, "change_viewer");
  ros::NodeHandle nh;
  ros::Subscriber sub = nh.subscribe<PointCloud>("kinect2/sd/points", 1, callback);
  pub = nh.advertise<std_msgs::Int64>("commotion",10);
  ros::spin();
}
<commit_msg>Prevent change_viewer from publishing the first frame of data<commit_after>#include <ros/ros.h>
#include <pcl_ros/point_cloud.h>
#include <pcl/point_types.h>
#include <pcl/octree/octree.h>
#include <vector>
#include <pcl/filters/voxel_grid.h>
#include <boost/foreach.hpp>
#include <ros/console.h>
#include <pcl/filters/extract_indices.h>
#include "std_msgs/Int64.h"

typedef pcl::PointCloud<pcl::PointXYZ> PointCloud;
float resolution = 1.0f;
pcl::octree::OctreePointCloudChangeDetector<pcl::PointXYZ> octree (resolution);
ros::Publisher pub;

void callback(const PointCloud::ConstPtr& msg)
{
  pcl::ExtractIndices<pcl::PointXYZ> extract;
  octree.switchBuffers();
  octree.setInputCloud(msg);
  octree.addPointsFromInputCloud();
  std::vector<int> newPointIdxVector;
  octree.getPointIndicesFromNewVoxels(newPointIdxVector);
  std_msgs::Int64 msg_publish;
  if (newPointIdxVector.size()<20000)
    msg_publish.data = newPointIdxVector.size();
  pub.publish(msg_publish);

}

int main(int argc, char** argv)
{
  ros::init(argc, argv, "change_viewer");
  ros::NodeHandle nh;
  ros::Subscriber sub = nh.subscribe<PointCloud>("kinect2/sd/points", 1, callback);
  pub = nh.advertise<std_msgs::Int64>("commotion",10);
  ros::spin();
}
<|endoftext|>


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

  Program:   Visualization Toolkit
  Module:    vtkPlot.cxx

  Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
  All rights reserved.
  See Copyright.txt or http://www.kitware.com/Copyright.htm for details.

     This software is distributed WITHOUT ANY WARRANTY; without even
     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
     PURPOSE.  See the above copyright notice for more information.

=========================================================================*/

#include "vtkPlot.h"

#include "vtkAxis.h"
#include "vtkPen.h"
#include "vtkBrush.h"
#include "vtkTable.h"
#include "vtkDataObject.h"
#include "vtkIdTypeArray.h"
#include "vtkContextMapper2D.h"
#include "vtkObjectFactory.h"
#include "vtkStdString.h"
#include "vtkStringArray.h"

vtkCxxSetObjectMacro(vtkPlot, Selection, vtkIdTypeArray);
vtkCxxSetObjectMacro(vtkPlot, XAxis, vtkAxis);
vtkCxxSetObjectMacro(vtkPlot, YAxis, vtkAxis);

//-----------------------------------------------------------------------------
vtkPlot::vtkPlot()
{
  this->Pen = vtkPen::New();
  this->Pen->SetWidth(2.0);
  this->Brush = vtkBrush::New();
  this->Labels = NULL;
  this->UseIndexForXSeries = false;
  this->Data = vtkContextMapper2D::New();
  this->Selection = NULL;
  this->XAxis = NULL;
  this->YAxis = NULL;
}

//-----------------------------------------------------------------------------
vtkPlot::~vtkPlot()
{
  if (this->Pen)
    {
    this->Pen->Delete();
    this->Pen = NULL;
    }
  if (this->Brush)
    {
    this->Brush->Delete();
    this->Brush = NULL;
    }
  if (this->Data)
    {
    this->Data->Delete();
    this->Data = NULL;
    }
  if (this->Selection)
    {
    this->Selection->Delete();
    this->Selection = NULL;
    }
  this->SetLabels(NULL);
  this->SetXAxis(NULL);
  this->SetYAxis(NULL);
}

//-----------------------------------------------------------------------------
bool vtkPlot::PaintLegend(vtkContext2D*, const vtkRectf&, int)
{
  return false;
}

//-----------------------------------------------------------------------------
int vtkPlot::GetNearestPoint(const vtkVector2f&, const vtkVector2f&,
                              vtkVector2f*)
{
  return -1;
}

//-----------------------------------------------------------------------------
bool vtkPlot::SelectPoints(const vtkVector2f&, const vtkVector2f&)
{
  return false;
}

//-----------------------------------------------------------------------------
void vtkPlot::SetColor(unsigned char r, unsigned char g, unsigned char b,
                       unsigned char a)
{
  this->Pen->SetColor(r, g, b, a);
}

//-----------------------------------------------------------------------------
void vtkPlot::SetColor(double r, double g, double b)
{
  this->Pen->SetColorF(r, g, b);
}

//-----------------------------------------------------------------------------
void vtkPlot::GetColor(double rgb[3])
{
  this->Pen->GetColorF(rgb);
}

//-----------------------------------------------------------------------------
void vtkPlot::GetColor(unsigned char rgb[3])
{
  double rgbF[3];
  this->GetColor(rgbF);
  rgb[0] = static_cast<unsigned char>(255. * rgbF[0] + 0.5);
  rgb[1] = static_cast<unsigned char>(255. * rgbF[1] + 0.5);
  rgb[2] = static_cast<unsigned char>(255. * rgbF[2] + 0.5);
}

//-----------------------------------------------------------------------------
void vtkPlot::SetWidth(float width)
{
  this->Pen->SetWidth(width);
}

//-----------------------------------------------------------------------------
float vtkPlot::GetWidth()
{
  return this->Pen->GetWidth();
}

//-----------------------------------------------------------------------------
void vtkPlot::SetLabel(const vtkStdString& label)
{
  vtkStringArray *labels = vtkStringArray::New();
  labels->InsertNextValue(label);
  this->SetLabels(labels);
  labels->Delete();
}

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

vtkStdString vtkPlot::GetLabel()
{
  return this->GetLabel(0);
}

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

void vtkPlot::SetLabels(vtkStringArray *labels)
{
  if (this->Labels == labels)
    {
    return;
    }

  this->Labels = labels;
  this->Modified();
}

//-----------------------------------------------------------------------------
vtkStringArray * vtkPlot::GetLabels()
{
  // If the label string is empty, return the y column name
  if (this->Labels)
    {
    return this->Labels;
    }
  else if (this->AutoLabels)
    {
    return this->AutoLabels;
    }
  else if (this->Data->GetInput() &&
           this->Data->GetInputArrayToProcess(1, this->Data->GetInput()))
    {
    this->AutoLabels = vtkSmartPointer<vtkStringArray>::New();
    this->AutoLabels->InsertNextValue(this->Data->GetInputArrayToProcess(1, this->Data->GetInput())->GetName());
    return this->AutoLabels;
    }
  else
    {
    return NULL;
    }
}
//-----------------------------------------------------------------------------
int vtkPlot::GetNumberOfLabels()
{
  vtkStringArray *labels = this->GetLabels();
  if (labels)
    {
    return labels->GetNumberOfValues();
    }
  else
    {
    return 0;
    }
}

//-----------------------------------------------------------------------------
vtkStdString vtkPlot::GetLabel(vtkIdType index)
{
  vtkStringArray *labels = this->GetLabels();
  if (labels && index >= 0 && index < labels->GetNumberOfValues())
    {
    return labels->GetValue(index);
    }
  else
    {
    return vtkStdString();
    }
}
//-----------------------------------------------------------------------------
void vtkPlot::SetInput(vtkTable *table)
{
  this->Data->SetInput(table);
  this->AutoLabels = 0;  // No longer valid
}

//-----------------------------------------------------------------------------
void vtkPlot::SetInput(vtkTable *table, const vtkStdString &xColumn,
                       const vtkStdString &yColumn)
{
  if (xColumn.empty() || yColumn.empty())
    {
    vtkErrorMacro(<< "Called with null arguments for X or Y column.")
    }
  vtkDebugMacro(<< "Setting input, X column = \"" << xColumn.c_str()
                << "\", " << "Y column = \"" << yColumn.c_str() << "\"");

  this->Data->SetInput(table);
  this->Data->SetInputArrayToProcess(0, 0, 0,
                                     vtkDataObject::FIELD_ASSOCIATION_ROWS,
                                     xColumn);
  this->Data->SetInputArrayToProcess(1, 0, 0,
                                     vtkDataObject::FIELD_ASSOCIATION_ROWS,
                                     yColumn);
  this->AutoLabels = 0;  // No longer valid
}

//-----------------------------------------------------------------------------
void vtkPlot::SetInput(vtkTable *table, vtkIdType xColumn,
                       vtkIdType yColumn)
{
  this->SetInput(table,
                 table->GetColumnName(xColumn),
                 table->GetColumnName(yColumn));
}

//-----------------------------------------------------------------------------
vtkTable* vtkPlot::GetInput()
{
  return this->Data->GetInput();
}

//-----------------------------------------------------------------------------
void vtkPlot::SetInputArray(int index, const vtkStdString &name)
{
  this->Data->SetInputArrayToProcess(index, 0, 0,
                                     vtkDataObject::FIELD_ASSOCIATION_ROWS,
                                     name);
  this->AutoLabels = 0; // No longer valid
}

//-----------------------------------------------------------------------------
void vtkPlot::SetProperty(const vtkStdString&, const vtkVariant&)
{
}

//-----------------------------------------------------------------------------
vtkVariant vtkPlot::GetProperty(const vtkStdString&)
{
  return vtkVariant();
}

//-----------------------------------------------------------------------------
void vtkPlot::PrintSelf(ostream &os, vtkIndent indent)
{
  this->Superclass::PrintSelf(os, indent);
}
<commit_msg>COMP: Use c_str() rather than implicit cast.<commit_after>/*=========================================================================

  Program:   Visualization Toolkit
  Module:    vtkPlot.cxx

  Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
  All rights reserved.
  See Copyright.txt or http://www.kitware.com/Copyright.htm for details.

     This software is distributed WITHOUT ANY WARRANTY; without even
     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
     PURPOSE.  See the above copyright notice for more information.

=========================================================================*/

#include "vtkPlot.h"

#include "vtkAxis.h"
#include "vtkPen.h"
#include "vtkBrush.h"
#include "vtkTable.h"
#include "vtkDataObject.h"
#include "vtkIdTypeArray.h"
#include "vtkContextMapper2D.h"
#include "vtkObjectFactory.h"
#include "vtkStdString.h"
#include "vtkStringArray.h"

vtkCxxSetObjectMacro(vtkPlot, Selection, vtkIdTypeArray);
vtkCxxSetObjectMacro(vtkPlot, XAxis, vtkAxis);
vtkCxxSetObjectMacro(vtkPlot, YAxis, vtkAxis);

//-----------------------------------------------------------------------------
vtkPlot::vtkPlot()
{
  this->Pen = vtkPen::New();
  this->Pen->SetWidth(2.0);
  this->Brush = vtkBrush::New();
  this->Labels = NULL;
  this->UseIndexForXSeries = false;
  this->Data = vtkContextMapper2D::New();
  this->Selection = NULL;
  this->XAxis = NULL;
  this->YAxis = NULL;
}

//-----------------------------------------------------------------------------
vtkPlot::~vtkPlot()
{
  if (this->Pen)
    {
    this->Pen->Delete();
    this->Pen = NULL;
    }
  if (this->Brush)
    {
    this->Brush->Delete();
    this->Brush = NULL;
    }
  if (this->Data)
    {
    this->Data->Delete();
    this->Data = NULL;
    }
  if (this->Selection)
    {
    this->Selection->Delete();
    this->Selection = NULL;
    }
  this->SetLabels(NULL);
  this->SetXAxis(NULL);
  this->SetYAxis(NULL);
}

//-----------------------------------------------------------------------------
bool vtkPlot::PaintLegend(vtkContext2D*, const vtkRectf&, int)
{
  return false;
}

//-----------------------------------------------------------------------------
int vtkPlot::GetNearestPoint(const vtkVector2f&, const vtkVector2f&,
                              vtkVector2f*)
{
  return -1;
}

//-----------------------------------------------------------------------------
bool vtkPlot::SelectPoints(const vtkVector2f&, const vtkVector2f&)
{
  return false;
}

//-----------------------------------------------------------------------------
void vtkPlot::SetColor(unsigned char r, unsigned char g, unsigned char b,
                       unsigned char a)
{
  this->Pen->SetColor(r, g, b, a);
}

//-----------------------------------------------------------------------------
void vtkPlot::SetColor(double r, double g, double b)
{
  this->Pen->SetColorF(r, g, b);
}

//-----------------------------------------------------------------------------
void vtkPlot::GetColor(double rgb[3])
{
  this->Pen->GetColorF(rgb);
}

//-----------------------------------------------------------------------------
void vtkPlot::GetColor(unsigned char rgb[3])
{
  double rgbF[3];
  this->GetColor(rgbF);
  rgb[0] = static_cast<unsigned char>(255. * rgbF[0] + 0.5);
  rgb[1] = static_cast<unsigned char>(255. * rgbF[1] + 0.5);
  rgb[2] = static_cast<unsigned char>(255. * rgbF[2] + 0.5);
}

//-----------------------------------------------------------------------------
void vtkPlot::SetWidth(float width)
{
  this->Pen->SetWidth(width);
}

//-----------------------------------------------------------------------------
float vtkPlot::GetWidth()
{
  return this->Pen->GetWidth();
}

//-----------------------------------------------------------------------------
void vtkPlot::SetLabel(const vtkStdString& label)
{
  vtkStringArray *labels = vtkStringArray::New();
  labels->InsertNextValue(label);
  this->SetLabels(labels);
  labels->Delete();
}

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

vtkStdString vtkPlot::GetLabel()
{
  return this->GetLabel(0);
}

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

void vtkPlot::SetLabels(vtkStringArray *labels)
{
  if (this->Labels == labels)
    {
    return;
    }

  this->Labels = labels;
  this->Modified();
}

//-----------------------------------------------------------------------------
vtkStringArray * vtkPlot::GetLabels()
{
  // If the label string is empty, return the y column name
  if (this->Labels)
    {
    return this->Labels;
    }
  else if (this->AutoLabels)
    {
    return this->AutoLabels;
    }
  else if (this->Data->GetInput() &&
           this->Data->GetInputArrayToProcess(1, this->Data->GetInput()))
    {
    this->AutoLabels = vtkSmartPointer<vtkStringArray>::New();
    this->AutoLabels->InsertNextValue(this->Data->GetInputArrayToProcess(1, this->Data->GetInput())->GetName());
    return this->AutoLabels;
    }
  else
    {
    return NULL;
    }
}
//-----------------------------------------------------------------------------
int vtkPlot::GetNumberOfLabels()
{
  vtkStringArray *labels = this->GetLabels();
  if (labels)
    {
    return labels->GetNumberOfValues();
    }
  else
    {
    return 0;
    }
}

//-----------------------------------------------------------------------------
vtkStdString vtkPlot::GetLabel(vtkIdType index)
{
  vtkStringArray *labels = this->GetLabels();
  if (labels && index >= 0 && index < labels->GetNumberOfValues())
    {
    return labels->GetValue(index);
    }
  else
    {
    return vtkStdString();
    }
}
//-----------------------------------------------------------------------------
void vtkPlot::SetInput(vtkTable *table)
{
  this->Data->SetInput(table);
  this->AutoLabels = 0;  // No longer valid
}

//-----------------------------------------------------------------------------
void vtkPlot::SetInput(vtkTable *table, const vtkStdString &xColumn,
                       const vtkStdString &yColumn)
{
  if (xColumn.empty() || yColumn.empty())
    {
    vtkErrorMacro(<< "Called with null arguments for X or Y column.")
    }
  vtkDebugMacro(<< "Setting input, X column = \"" << xColumn.c_str()
                << "\", " << "Y column = \"" << yColumn.c_str() << "\"");

  this->Data->SetInput(table);
  this->Data->SetInputArrayToProcess(0, 0, 0,
                                     vtkDataObject::FIELD_ASSOCIATION_ROWS,
                                     xColumn.c_str());
  this->Data->SetInputArrayToProcess(1, 0, 0,
                                     vtkDataObject::FIELD_ASSOCIATION_ROWS,
                                     yColumn.c_str());
  this->AutoLabels = 0;  // No longer valid
}

//-----------------------------------------------------------------------------
void vtkPlot::SetInput(vtkTable *table, vtkIdType xColumn,
                       vtkIdType yColumn)
{
  this->SetInput(table,
                 table->GetColumnName(xColumn),
                 table->GetColumnName(yColumn));
}

//-----------------------------------------------------------------------------
vtkTable* vtkPlot::GetInput()
{
  return this->Data->GetInput();
}

//-----------------------------------------------------------------------------
void vtkPlot::SetInputArray(int index, const vtkStdString &name)
{
  this->Data->SetInputArrayToProcess(index, 0, 0,
                                     vtkDataObject::FIELD_ASSOCIATION_ROWS,
                                     name.c_str());
  this->AutoLabels = 0; // No longer valid
}

//-----------------------------------------------------------------------------
void vtkPlot::SetProperty(const vtkStdString&, const vtkVariant&)
{
}

//-----------------------------------------------------------------------------
vtkVariant vtkPlot::GetProperty(const vtkStdString&)
{
  return vtkVariant();
}

//-----------------------------------------------------------------------------
void vtkPlot::PrintSelf(ostream &os, vtkIndent indent)
{
  this->Superclass::PrintSelf(os, indent);
}
<|endoftext|>