<commit_before>// Copyright (c) 2011, Cornell University
// 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 HyperDex 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 OWNER 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.

// STL
#include <memory>
#include <string>

// po6
#include <po6/net/ipaddr.h>
#include <po6/net/location.h>

// e
#include <e/convert.h>
#include <e/timer.h>

// HyperDex
#include <hyperclient/client.h>

const char* colnames[] = {"1", "2", "3", "4", "5", "6", "7", "8", "9", "10",
                          "11", "12", "13", "14", "15", "16", "17", "18", "19",
                          "20", "21", "22", "23", "24", "25", "26", "27", "28",
                          "29", "30", "31", "32"};

static int
usage();

void
handle_put(hyperclient::returncode ret)
{
    if (ret != hyperclient::SUCCESS)
    {
        std::cerr << "Put returned " << ret << "." << std::endl;
    }
}

void
handle_search(size_t* count,
              const e::buffer& expected_key,
              hyperclient::returncode ret,
              const e::buffer& key,
              const std::vector<e::buffer>& value)
{
    ++*count;

    if (*count > 1)
    {
        std::cerr << "Search returned more than 1 result." << std::endl;
    }

    if (expected_key != key)
    {
        std::cerr << "Search returned unexpected key:  " << expected_key.hex()
                  << " != " << key.hex() << std::endl;
    }
}

int
main(int argc, char* argv[])
{
    if (argc != 5)
    {
        return usage();
    }

    po6::net::ipaddr ip;
    uint16_t port;
    std::string space = argv[3];
    uint32_t numbers;

    try
    {
        ip = argv[1];
    }
    catch (std::invalid_argument& e)
    {
        std::cerr << "The IP address must be an IPv4 or IPv6 address." << std::endl;
        return EXIT_FAILURE;
    }

    try
    {
        port = e::convert::to_uint16_t(argv[2]);
    }
    catch (std::domain_error& e)
    {
        std::cerr << "The port number must be an integer." << std::endl;
        return EXIT_FAILURE;
    }
    catch (std::out_of_range& e)
    {
        std::cerr << "The port number must be suitably small." << std::endl;
        return EXIT_FAILURE;
    }

    try
    {
        numbers = e::convert::to_uint32_t(argv[4]);
    }
    catch (std::domain_error& e)
    {
        std::cerr << "The number must be an integer." << std::endl;
        return EXIT_FAILURE;
    }
    catch (std::out_of_range& e)
    {
        std::cerr << "The number must be suitably small." << std::endl;
        return EXIT_FAILURE;
    }

    try
    {
        hyperclient::client cl(po6::net::location(ip, port));
        cl.connect();
        e::buffer one("one", 3);
        e::buffer zero("zero", 3);

        for (uint32_t num = 0; num < numbers; ++num)
        {
            e::buffer key;
            key.pack() << num;
            std::vector<e::buffer> value;

            for (size_t i = 0; i < 32; ++i)
            {
                value.push_back(e::buffer());

                if ((num & (1 << i)))
                {
                    value.back() = one;
                }
                else
                {
                    value.back() = zero;
                }
            }

            cl.put(space, key, value, handle_put);

            if (cl.outstanding() > 10000)
            {
                cl.flush(-1);
            }
        }

        cl.flush(-1);
        e::sleep_ms(1, 0);
        std::cerr << "Starting searches." << std::endl;
        timespec start;
        timespec end;

        clock_gettime(CLOCK_REALTIME, &start);

        for (uint32_t num = 0; num < numbers; ++num)
        {
            e::buffer key;
            key.pack() << num;
            std::map<std::string, e::buffer> search;

            for (size_t i = 0; i < 32; ++i)
            {
                if ((num & (1 << i)))
                {
                    search.insert(std::make_pair(colnames[i], one));
                }
                else
                {
                    search.insert(std::make_pair(colnames[i], zero));
                }
            }

            using std::tr1::bind;
            using std::tr1::placeholders::_1;
            using std::tr1::placeholders::_2;
            using std::tr1::placeholders::_3;
            size_t count = 0;
            cl.search(argv[3], search, std::tr1::bind(handle_search, &count, key, _1, _2, _3));
            cl.flush(-1);
        }

        clock_gettime(CLOCK_REALTIME, &end);
        timespec diff;

        if ((end.tv_nsec < start.tv_nsec) < 0)
        {
            diff.tv_sec = end.tv_sec - start.tv_sec - 1;
            diff.tv_nsec = 1000000000 + end.tv_nsec - start.tv_nsec;
        }
        else
        {
            diff.tv_sec = end.tv_sec - start.tv_sec;
            diff.tv_nsec = end.tv_nsec - start.tv_nsec;
        }

        uint64_t nanosecs = diff.tv_sec * 1000000000 + diff.tv_nsec;
        std::cerr << "test took " << nanosecs << " nanoseconds for " << numbers << " searches" << std::endl;
    }
    catch (po6::error& e)
    {
        std::cerr << "There was a system error:  " << e.what();
        return EXIT_FAILURE;
    }
    catch (std::runtime_error& e)
    {
        std::cerr << "There was a runtime error:  " << e.what();
        return EXIT_FAILURE;
    }
    catch (std::bad_alloc& e)
    {
        std::cerr << "There was a memory allocation error:  " << e.what();
        return EXIT_FAILURE;
    }
    catch (std::exception& e)
    {
        std::cerr << "There was a generic error:  " << e.what();
        return EXIT_FAILURE;
    }

    return EXIT_SUCCESS;
}

int
usage()
{
    std::cerr << "Usage:  binary <coordinator ip> <coordinator port> <space name> <numbers>\n"
              << "This will create <numbers> points whose key is a number [0, <numbers>) and "
              << "then perform searches over the bits of the number.  The space should have 32 "
              << "secondary dimensions so that all bits of a number may be stored."
              << std::endl;
    return EXIT_FAILURE;
}
<commit_msg>Flush every 1000 PUTs in binary-test.cc<commit_after>// Copyright (c) 2011, Cornell University
// 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 HyperDex 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 OWNER 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.

// STL
#include <memory>
#include <string>

// po6
#include <po6/net/ipaddr.h>
#include <po6/net/location.h>

// e
#include <e/convert.h>
#include <e/timer.h>

// HyperDex
#include <hyperclient/client.h>

const char* colnames[] = {"1", "2", "3", "4", "5", "6", "7", "8", "9", "10",
                          "11", "12", "13", "14", "15", "16", "17", "18", "19",
                          "20", "21", "22", "23", "24", "25", "26", "27", "28",
                          "29", "30", "31", "32"};

static int
usage();

void
handle_put(hyperclient::returncode ret)
{
    if (ret != hyperclient::SUCCESS)
    {
        std::cerr << "Put returned " << ret << "." << std::endl;
    }
}

void
handle_search(size_t* count,
              const e::buffer& expected_key,
              hyperclient::returncode ret,
              const e::buffer& key,
              const std::vector<e::buffer>& value)
{
    ++*count;

    if (*count > 1)
    {
        std::cerr << "Search returned more than 1 result." << std::endl;
    }

    if (expected_key != key)
    {
        std::cerr << "Search returned unexpected key:  " << expected_key.hex()
                  << " != " << key.hex() << std::endl;
    }
}

int
main(int argc, char* argv[])
{
    if (argc != 5)
    {
        return usage();
    }

    po6::net::ipaddr ip;
    uint16_t port;
    std::string space = argv[3];
    uint32_t numbers;

    try
    {
        ip = argv[1];
    }
    catch (std::invalid_argument& e)
    {
        std::cerr << "The IP address must be an IPv4 or IPv6 address." << std::endl;
        return EXIT_FAILURE;
    }

    try
    {
        port = e::convert::to_uint16_t(argv[2]);
    }
    catch (std::domain_error& e)
    {
        std::cerr << "The port number must be an integer." << std::endl;
        return EXIT_FAILURE;
    }
    catch (std::out_of_range& e)
    {
        std::cerr << "The port number must be suitably small." << std::endl;
        return EXIT_FAILURE;
    }

    try
    {
        numbers = e::convert::to_uint32_t(argv[4]);
    }
    catch (std::domain_error& e)
    {
        std::cerr << "The number must be an integer." << std::endl;
        return EXIT_FAILURE;
    }
    catch (std::out_of_range& e)
    {
        std::cerr << "The number must be suitably small." << std::endl;
        return EXIT_FAILURE;
    }

    try
    {
        hyperclient::client cl(po6::net::location(ip, port));
        cl.connect();
        e::buffer one("one", 3);
        e::buffer zero("zero", 3);

        for (uint32_t num = 0; num < numbers; ++num)
        {
            e::buffer key;
            key.pack() << num;
            std::vector<e::buffer> value;

            for (size_t i = 0; i < 32; ++i)
            {
                value.push_back(e::buffer());

                if ((num & (1 << i)))
                {
                    value.back() = one;
                }
                else
                {
                    value.back() = zero;
                }
            }

            cl.put(space, key, value, handle_put);

            if (cl.outstanding() > 1000)
            {
                cl.flush(-1);
            }
        }

        cl.flush(-1);
        e::sleep_ms(1, 0);
        std::cerr << "Starting searches." << std::endl;
        timespec start;
        timespec end;

        clock_gettime(CLOCK_REALTIME, &start);

        for (uint32_t num = 0; num < numbers; ++num)
        {
            e::buffer key;
            key.pack() << num;
            std::map<std::string, e::buffer> search;

            for (size_t i = 0; i < 32; ++i)
            {
                if ((num & (1 << i)))
                {
                    search.insert(std::make_pair(colnames[i], one));
                }
                else
                {
                    search.insert(std::make_pair(colnames[i], zero));
                }
            }

            using std::tr1::bind;
            using std::tr1::placeholders::_1;
            using std::tr1::placeholders::_2;
            using std::tr1::placeholders::_3;
            size_t count = 0;
            cl.search(argv[3], search, std::tr1::bind(handle_search, &count, key, _1, _2, _3));
            cl.flush(-1);
        }

        clock_gettime(CLOCK_REALTIME, &end);
        timespec diff;

        if ((end.tv_nsec < start.tv_nsec) < 0)
        {
            diff.tv_sec = end.tv_sec - start.tv_sec - 1;
            diff.tv_nsec = 1000000000 + end.tv_nsec - start.tv_nsec;
        }
        else
        {
            diff.tv_sec = end.tv_sec - start.tv_sec;
            diff.tv_nsec = end.tv_nsec - start.tv_nsec;
        }

        uint64_t nanosecs = diff.tv_sec * 1000000000 + diff.tv_nsec;
        std::cerr << "test took " << nanosecs << " nanoseconds for " << numbers << " searches" << std::endl;
    }
    catch (po6::error& e)
    {
        std::cerr << "There was a system error:  " << e.what();
        return EXIT_FAILURE;
    }
    catch (std::runtime_error& e)
    {
        std::cerr << "There was a runtime error:  " << e.what();
        return EXIT_FAILURE;
    }
    catch (std::bad_alloc& e)
    {
        std::cerr << "There was a memory allocation error:  " << e.what();
        return EXIT_FAILURE;
    }
    catch (std::exception& e)
    {
        std::cerr << "There was a generic error:  " << e.what();
        return EXIT_FAILURE;
    }

    return EXIT_SUCCESS;
}

int
usage()
{
    std::cerr << "Usage:  binary <coordinator ip> <coordinator port> <space name> <numbers>\n"
              << "This will create <numbers> points whose key is a number [0, <numbers>) and "
              << "then perform searches over the bits of the number.  The space should have 32 "
              << "secondary dimensions so that all bits of a number may be stored."
              << std::endl;
    return EXIT_FAILURE;
}
<|endoftext|>


<commit_before>//
// This file is part of the Marble Desktop Globe.
//
// This program is free software licensed under the GNU LGPL. You can
// find a copy of this license in LICENSE.txt in the top directory of
// the source code.
//
// Copyright 2009 Bastian Holst <bastianholst@gmx.de>
//

// Self
#include "PluginItemDelegate.h"

// Marble
#include "RenderPlugin.h"
#include "PluginModelItem.h"

// Qt
#include <QtCore/QDebug>
#include <QtCore/QVariant>
#include <QtGui/QAbstractItemView>
#include <QtGui/QStandardItemModel>
#include <QtGui/QApplication>
#include <QtGui/QPainter>
#include <QtGui/QStandardItem>

using namespace Marble;

PluginItemDelegate::PluginItemDelegate( QAbstractItemView *itemView, QObject * parent )
    : QStyledItemDelegate( parent ),
      m_itemView( itemView )
{
    connect( itemView, SIGNAL( clicked( QModelIndex ) ),
                       SLOT( handleClickEvent( const QModelIndex& ) ) );
}

PluginItemDelegate::~PluginItemDelegate() {
}

void PluginItemDelegate::paint( QPainter *painter,
                                const QStyleOptionViewItem& option,
                                const QModelIndex& index ) const
{
    Q_ASSERT(index.isValid());
    // TODO: Do background rendering, implement clicking on buttons, add configure button.
    QRect rect = option.rect;

    painter->save();

    painter->translate( rect.topLeft() );

    // Painting the checkbox
    QStyleOptionButton checkboxOption;
    if ( index.data( Qt::CheckStateRole ).toBool() )
        checkboxOption.state = option.state | QStyle::State_On;
    else
        checkboxOption.state = option.state | QStyle::State_Off;
    checkboxOption.rect.setTopLeft( QPoint( 0, 0 ) );
    checkboxOption.rect.setSize( QSize( rect.height(), rect.height() ) );
    painter->save();
    QApplication::style()->drawControl( QStyle::CE_CheckBox, &checkboxOption, painter );
    painter->restore();
    painter->translate( checkboxOption.rect.width(), 0 );

    // Painting the Name string
    QString name = index.data( Qt::DisplayRole ).toString();
    QRect nameRect( QPoint( 0, 0 ), QApplication::fontMetrics().size( 0, name ) );
    nameRect.setHeight( rect.height() );
    QApplication::style()->drawItemText( painter,
                                         nameRect,
                                         Qt::AlignLeft | Qt::AlignVCenter,
                                         option.palette,
                                         false,
                                         name );
    painter->translate( nameRect.width(), 0 );

    // Painting the About Button
    if ( /*index.data( RenderPlugin::AboutDialogAvailable ).toBool()*/ true ) {
        QStyleOptionButton buttonOption;
        buttonOption.state = option.state;
        buttonOption.state &= ~QStyle::State_HasFocus;

        buttonOption.rect.setTopLeft( QPoint( 0, 0 ) );
        buttonOption.palette = option.palette;
        buttonOption.features = QStyleOptionButton::None;
        buttonOption.text = tr( "About" );
        buttonOption.state = option.state;

        QSize aboutSize = buttonOption.fontMetrics.size( 0, buttonOption.text ) + QSize( 4, 4 );
        QSize aboutButtonSize = QApplication::style()->sizeFromContents( QStyle::CT_PushButton,
                                                                         &buttonOption,
                                                                         aboutSize );
        buttonOption.rect.setWidth( aboutButtonSize.width() );
        buttonOption.rect.setHeight( rect.height() );

        QApplication::style()->drawControl( QStyle::CE_PushButton, &buttonOption, painter );
        painter->translate( aboutButtonSize.width(), 0 );
    }
    painter->restore();
}

QSize PluginItemDelegate::sizeHint( const QStyleOptionViewItem& option,
                                    const QModelIndex & index ) const
{
    QSize sz = QStyledItemDelegate::sizeHint(option, index) + QSize( 4, 4 );
    return sz;
}

void PluginItemDelegate::handleClickEvent( const QModelIndex& ) {
    // TODO: Click handling.
}

#include "PluginItemDelegate.moc"
<commit_msg>Removing a not existing header file from the includes of Marble PluginItemDelegate.<commit_after>//
// This file is part of the Marble Desktop Globe.
//
// This program is free software licensed under the GNU LGPL. You can
// find a copy of this license in LICENSE.txt in the top directory of
// the source code.
//
// Copyright 2009 Bastian Holst <bastianholst@gmx.de>
//

// Self
#include "PluginItemDelegate.h"

// Marble
#include "RenderPlugin.h"

// Qt
#include <QtCore/QDebug>
#include <QtCore/QVariant>
#include <QtGui/QAbstractItemView>
#include <QtGui/QStandardItemModel>
#include <QtGui/QApplication>
#include <QtGui/QPainter>
#include <QtGui/QStandardItem>

using namespace Marble;

PluginItemDelegate::PluginItemDelegate( QAbstractItemView *itemView, QObject * parent )
    : QStyledItemDelegate( parent ),
      m_itemView( itemView )
{
    connect( itemView, SIGNAL( clicked( QModelIndex ) ),
                       SLOT( handleClickEvent( const QModelIndex& ) ) );
}

PluginItemDelegate::~PluginItemDelegate() {
}

void PluginItemDelegate::paint( QPainter *painter,
                                const QStyleOptionViewItem& option,
                                const QModelIndex& index ) const
{
    Q_ASSERT(index.isValid());
    // TODO: Do background rendering, implement clicking on buttons, add configure button.
    QRect rect = option.rect;

    painter->save();

    painter->translate( rect.topLeft() );

    // Painting the checkbox
    QStyleOptionButton checkboxOption;
    if ( index.data( Qt::CheckStateRole ).toBool() )
        checkboxOption.state = option.state | QStyle::State_On;
    else
        checkboxOption.state = option.state | QStyle::State_Off;
    checkboxOption.rect.setTopLeft( QPoint( 0, 0 ) );
    checkboxOption.rect.setSize( QSize( rect.height(), rect.height() ) );
    painter->save();
    QApplication::style()->drawControl( QStyle::CE_CheckBox, &checkboxOption, painter );
    painter->restore();
    painter->translate( checkboxOption.rect.width(), 0 );

    // Painting the Name string
    QString name = index.data( Qt::DisplayRole ).toString();
    QRect nameRect( QPoint( 0, 0 ), QApplication::fontMetrics().size( 0, name ) );
    nameRect.setHeight( rect.height() );
    QApplication::style()->drawItemText( painter,
                                         nameRect,
                                         Qt::AlignLeft | Qt::AlignVCenter,
                                         option.palette,
                                         false,
                                         name );
    painter->translate( nameRect.width(), 0 );

    // Painting the About Button
    if ( /*index.data( RenderPlugin::AboutDialogAvailable ).toBool()*/ true ) {
        QStyleOptionButton buttonOption;
        buttonOption.state = option.state;
        buttonOption.state &= ~QStyle::State_HasFocus;

        buttonOption.rect.setTopLeft( QPoint( 0, 0 ) );
        buttonOption.palette = option.palette;
        buttonOption.features = QStyleOptionButton::None;
        buttonOption.text = tr( "About" );
        buttonOption.state = option.state;

        QSize aboutSize = buttonOption.fontMetrics.size( 0, buttonOption.text ) + QSize( 4, 4 );
        QSize aboutButtonSize = QApplication::style()->sizeFromContents( QStyle::CT_PushButton,
                                                                         &buttonOption,
                                                                         aboutSize );
        buttonOption.rect.setWidth( aboutButtonSize.width() );
        buttonOption.rect.setHeight( rect.height() );

        QApplication::style()->drawControl( QStyle::CE_PushButton, &buttonOption, painter );
        painter->translate( aboutButtonSize.width(), 0 );
    }
    painter->restore();
}

QSize PluginItemDelegate::sizeHint( const QStyleOptionViewItem& option,
                                    const QModelIndex & index ) const
{
    QSize sz = QStyledItemDelegate::sizeHint(option, index) + QSize( 4, 4 );
    return sz;
}

void PluginItemDelegate::handleClickEvent( const QModelIndex& ) {
    // TODO: Click handling.
}

#include "PluginItemDelegate.moc"
<|endoftext|>


<commit_before>/*
 * Header-only library abstracting some filesystem properties.
 */

#ifndef MODTOOLS_COMPAT_FS_HPP
#define MODTOOLS_COMPAT_FS_HPP

#include "modtools_compat/common.hpp"
#include "modtools_compat/posix.hpp"

#include <string>
#include <algorithm>
#include <iterator>
#include <cassert>
#include <cstdlib>

#ifndef PATH_MAX
#	define PATH_MAX 65536
#endif

namespace Compat {
#ifdef IS_UNIX
#	define DIR_SEP_MACRO '/'
#	define DIR_SEP_STR_MACRO "/"
#else
#	define DIR_SEP_MACRO '\\'
#	define DIR_SEP_STR_MACRO "\\"
#endif

#if !defined(S_ISDIR)
#	error "The POSIX macro S_ISDIR is not defined."
#endif

	static const char DIRECTORY_SEPARATOR = DIR_SEP_MACRO;

	static const char DUAL_DIRECTORY_SEPARATOR = (DIRECTORY_SEPARATOR == '/' ? '\\' : '/');

	class Path : public std::string {
	public:
		typedef struct stat stat_t;

		static const char SEPARATOR = DIRECTORY_SEPARATOR;

		std::string& toString() {
			return static_cast<std::string&>(*this);
		}

		const std::string& toString() const {
			return static_cast<const std::string&>(*this);
		}

	private:
		static void normalizeDirSeps(std::string& str, size_t offset = 0) {
			std::string::iterator _begin = str.begin();
			std::advance(_begin, offset);
			std::replace(_begin, str.end(), DUAL_DIRECTORY_SEPARATOR, DIRECTORY_SEPARATOR);
		}

		/*
		 * Skips extra slashes in a normalized string.
		 * Receives begin and end iterators, modifying them
		 * to the actual range.
		 */
		static void skip_extra_slashes(std::string::const_iterator& begin, std::string::const_iterator& end) {
			if(begin == end)
				return;

			const size_t len = static_cast<size_t>( std::distance(begin, end) );
			const std::string::const_iterator real_end = end;

			// It points to the last character, for now.
			end = begin;
			std::advance(end, len - 1);

			for(; begin != real_end && *begin == DIRECTORY_SEPARATOR; ++begin);
			for(; end != begin && *end == DIRECTORY_SEPARATOR; --end);
			++end;
		}

		int inner_stat(stat_t& buf) const {
			if(empty())
				return -1;
			return ::stat(this->c_str(), &buf);
		}

		size_t get_extension_position() const {
			const size_t dot_pos = find_last_of('.');
			const size_t last_sep_pos = find_last_of(SEPARATOR);
			if(dot_pos == npos || (last_sep_pos != npos && dot_pos < last_sep_pos)) {
				return npos;
			}
			else {
				return dot_pos + 1;
			}
		}

	public:
		bool stat(stat_t& buf) const {
			if(inner_stat(buf)) {
				buf = stat_t();
				return false;
			}
			return true;
		}

		stat_t stat() const {
			stat_t buf;
			stat(buf);
			return buf;
		}

		bool isDirectory() const {
			stat_t buf;
			return stat(buf) && S_ISDIR(buf.st_mode);
		}

		/*
		 * Appends a string, preceded by a directory separator if necessary.
		 */
		Path& appendPath(std::string str) {
			if(str.length() == 0)
				return *this;

			normalizeDirSeps(str);

			const size_t old_len = this->length();

			if(old_len != 0 || str[0] == DIRECTORY_SEPARATOR) {
				std::string::append(1, DIRECTORY_SEPARATOR);
			}
			std::string::const_iterator _begin, _end;
			_begin = str.begin();
			_end = str.end();
			skip_extra_slashes(_begin, _end);

			std::string::append(_begin, _end);
			return *this;
		}

		Path& assignPath(const std::string& str) {
			std::string::clear();
			return appendPath(str);
		}

		Path& operator=(const std::string& str) {
			return assignPath(str);
		}

		Path& operator=(const char *str) {
			return assignPath(str);
		}

		Path& operator=(const Path& p) {
			std::string::assign(p);
			return *this;
		}

		void makeAbsolute() {
#if IS_UNIX
			char resolved_path[PATH_MAX];
			if( realpath(c_str(), resolved_path) != NULL ) {
				assignPath(resolved_path);
			}
#endif
		}

		Path(const std::string& str) : std::string() {
			*this = str;
		}

		Path(const char* str) : std::string() {
			*this = str;
		}

		Path(const Path& p) : std::string() {
			*this = p;
		}

		Path() {}

		Path copy() const {
			return Path(*this);
		}

		Path& operator+=(const std::string& str) {
			std::string::append(str);
			return *this;
		}

		Path& operator+=(const char *str) {
			std::string::append(str);
			return *this;
		}

		Path operator+(const std::string& str) const {
			return this->copy() += str;
		}

		Path operator+(const char *str) const {
			return this->copy() += str;
		}

		Path& operator/=(const std::string& str) {
			return appendPath(str);
		}

		Path& operator/=(const char *str) {
			return appendPath(str);
		}

		Path operator/(const std::string& str) const {
			return this->copy() /= str;
		}

		Path operator/(const char *str) const {
			return this->copy() /= str;
		}

		/*
		 * Splits the path into directory and file parts.
		 *
		 * The "directory part" accounts for everything until the last
		 * separator (not including the separator itself). If no separator
		 * exists, the directory will be ".".
		 *
		 * The directory part DOES NOT include a trailing slash.
		 */
		void split(std::string& dir, std::string& base) const {
			assert( length() > 0 );

			const size_t last_sep = find_last_of(DIRECTORY_SEPARATOR);

			if(last_sep == 0 && length() == 1) {
				// Root directory (so Unix).
				dir = "/";
				base = "/";
				return;
			}

			if(last_sep == npos) {
				dir = ".";
				base = *this;
			}
			else {
				dir = substr(0, last_sep);
				base = substr(last_sep + 1);
			}
		}

		Path dirname() const {
			Path dir, base;
			split(dir, base);
			return dir;
		}

		// With trailing slash.
		Path dirnameWithSlash() const {
			Path p = dirname();
			if(p != "/") {
				p.append(1, DIRECTORY_SEPARATOR);
			}
			return p;
		}

		Path basename() const {
			Path dir, base;
			split(dir, base);
			return base;
		}

		std::string getExtension() const {
			const size_t start = get_extension_position();
			if(start == npos) {
				return "";
			}
			else {
				return substr(start);
			}
		}

		Path& replaceExtension(const std::string& newext) {
			const size_t start = get_extension_position();
			if(start == npos) {
				std::string::append(1, '.');
			}
			else {
				std::string::erase(start);
			}
			std::string::append(newext);
			return *this;
		}

		Path& removeExtension() {
			const size_t start = get_extension_position();
			if(start != npos) {
				assert( start >= 1 );
				std::string::erase(start - 1);
			}
			return *this;
		}

		bool exists() const {
			stat_t buf;
			return inner_stat(buf) == 0;
		}

		operator bool() const {
			return exists();
		}

		/*
		 * If p doesn't exist and *this does, returns true.
		 * Likewise, if *this doesn't exist and p does, returns false.
		 */
		bool isNewerThan(const Path& p) const {
			stat_t mybuf, otherbuf;
			stat(mybuf);
			p.stat(otherbuf);

			if(mybuf.st_mtime > otherbuf.st_mtime) {
				return true;
			}
			else if(mybuf.st_mtime == otherbuf.st_mtime) {
				// Compares nanoseconds under Unix.
#if defined(IS_LINUX)
				return mybuf.st_mtim.tv_nsec > otherbuf.st_mtim.tv_nsec;
#elif defined(IS_MAC)
				return mybuf.st_mtimespec.tv_nsec > otherbuf.st_mtimespec.tv_nsec;
#endif
			}
			else {
				return false;
			}
		}

		bool isOlderThan(const Path& p) const {
			return p.isNewerThan(*this);
		}
	};
}

#endif
<commit_msg>some more fixes<commit_after>/*
 * Header-only library abstracting some filesystem properties.
 */

#ifndef MODTOOLS_COMPAT_FS_HPP
#define MODTOOLS_COMPAT_FS_HPP

#include "modtools_compat/common.hpp"
#include "modtools_compat/posix.hpp"

#include <string>
#include <algorithm>
#include <iterator>
#include <cassert>
#include <cstdlib>

#ifndef PATH_MAX
#	define PATH_MAX 65536
#endif

namespace Compat {
#ifdef IS_UNIX
#	define DIR_SEP_MACRO '/'
#	define DIR_SEP_STR_MACRO "/"
#else
#	define DIR_SEP_MACRO '\\'
#	define DIR_SEP_STR_MACRO "\\"
#endif

#if !defined(S_ISDIR)
#	error "The POSIX macro S_ISDIR is not defined."
#endif

	static const char DIRECTORY_SEPARATOR = DIR_SEP_MACRO;

	static const char DUAL_DIRECTORY_SEPARATOR = (DIRECTORY_SEPARATOR == '/' ? '\\' : '/');

	class Path : public std::string {
	public:
		typedef struct stat stat_t;

		static const char SEPARATOR = DIRECTORY_SEPARATOR;

		std::string& toString() {
			return static_cast<std::string&>(*this);
		}

		const std::string& toString() const {
			return static_cast<const std::string&>(*this);
		}

	private:
		static void normalizeDirSeps(std::string& str, size_t offset = 0) {
			std::string::iterator _begin = str.begin();
			std::advance(_begin, offset);
			std::replace(_begin, str.end(), DUAL_DIRECTORY_SEPARATOR, DIRECTORY_SEPARATOR);
		}

		/*
		 * Skips extra slashes in a normalized string.
		 * Receives begin and end iterators, modifying them
		 * to the actual range.
		 */
		static void skip_extra_slashes(std::string::const_iterator& begin, std::string::const_iterator& end) {
			if(begin == end)
				return;

			const size_t len = static_cast<size_t>( std::distance(begin, end) );
			const std::string::const_iterator real_end = end;

			// It points to the last character, for now.
			end = begin;
			std::advance(end, len - 1);

			for(; begin != real_end && *begin == DIRECTORY_SEPARATOR; ++begin);
			for(; end != begin && *end == DIRECTORY_SEPARATOR; --end);
			++end;
		}

		int inner_stat(stat_t& buf) const {
			if(empty())
				return -1;
			return ::stat(this->c_str(), &buf);
		}

		size_t get_extension_position() const {
			const size_t dot_pos = find_last_of('.');
			const size_t last_sep_pos = find_last_of(SEPARATOR);
			if(dot_pos == npos || (last_sep_pos != npos && dot_pos < last_sep_pos)) {
				return npos;
			}
			else {
				return dot_pos + 1;
			}
		}

	public:
		bool stat(stat_t& buf) const {
			if(inner_stat(buf)) {
				buf = stat_t();
				return false;
			}
			return true;
		}

		stat_t stat() const {
			stat_t buf;
			stat(buf);
			return buf;
		}

		bool isDirectory() const {
			stat_t buf;
			return stat(buf) && S_ISDIR(buf.st_mode);
		}

		/*
		 * Appends a string, preceded by a directory separator if necessary.
		 */
		Path& appendPath(std::string str) {
			if(str.length() == 0)
				return *this;

			normalizeDirSeps(str);

			const size_t old_len = this->length();

			if(old_len != 0 || str[0] == DIRECTORY_SEPARATOR) {
				std::string::append(1, DIRECTORY_SEPARATOR);
			}
			std::string::const_iterator _begin, _end;
			_begin = str.begin();
			_end = str.end();
			skip_extra_slashes(_begin, _end);

			std::string::append(_begin, _end);
			return *this;
		}

		Path& assignPath(const std::string& str) {
			std::string::clear();
			return appendPath(str);
		}

		Path& operator=(const std::string& str) {
			return assignPath(str);
		}

		Path& operator=(const char *str) {
			return assignPath(str);
		}

		Path& operator=(const Path& p) {
			std::string::assign(p);
			return *this;
		}

		void makeAbsolute() {
#ifdef IS_UNIX
			char resolved_path[PATH_MAX];
			if( realpath(c_str(), resolved_path) != NULL ) {
				assignPath(resolved_path);
			}
#endif
		}

		Path(const std::string& str) : std::string() {
			*this = str;
		}

		Path(const char* str) : std::string() {
			*this = str;
		}

		Path(const Path& p) : std::string() {
			*this = p;
		}

		Path() {}

		Path copy() const {
			return Path(*this);
		}

		Path& operator+=(const std::string& str) {
			std::string::append(str);
			return *this;
		}

		Path& operator+=(const char *str) {
			std::string::append(str);
			return *this;
		}

		Path operator+(const std::string& str) const {
			return this->copy() += str;
		}

		Path operator+(const char *str) const {
			return this->copy() += str;
		}

		Path& operator/=(const std::string& str) {
			return appendPath(str);
		}

		Path& operator/=(const char *str) {
			return appendPath(str);
		}

		Path operator/(const std::string& str) const {
			return this->copy() /= str;
		}

		Path operator/(const char *str) const {
			return this->copy() /= str;
		}

		/*
		 * Splits the path into directory and file parts.
		 *
		 * The "directory part" accounts for everything until the last
		 * separator (not including the separator itself). If no separator
		 * exists, the directory will be ".".
		 *
		 * The directory part DOES NOT include a trailing slash.
		 */
		void split(std::string& dir, std::string& base) const {
			assert( length() > 0 );

			const size_t last_sep = find_last_of(DIRECTORY_SEPARATOR);

			if(last_sep == 0 && length() == 1) {
				// Root directory (so Unix).
				dir = "/";
				base = "/";
				return;
			}

			if(last_sep == npos) {
				dir = ".";
				base = *this;
			}
			else {
				dir = substr(0, last_sep);
				base = substr(last_sep + 1);
			}
		}

		Path dirname() const {
			Path dir, base;
			split(dir, base);
			return dir;
		}

		// With trailing slash.
		Path dirnameWithSlash() const {
			Path p = dirname();
			if(p != "/") {
				p.append(1, DIRECTORY_SEPARATOR);
			}
			return p;
		}

		Path basename() const {
			Path dir, base;
			split(dir, base);
			return base;
		}

		std::string getExtension() const {
			const size_t start = get_extension_position();
			if(start == npos) {
				return "";
			}
			else {
				return substr(start);
			}
		}

		Path& replaceExtension(const std::string& newext) {
			const size_t start = get_extension_position();
			if(start == npos) {
				std::string::append(1, '.');
			}
			else {
				std::string::erase(start);
			}
			std::string::append(newext);
			return *this;
		}

		Path& removeExtension() {
			const size_t start = get_extension_position();
			if(start != npos) {
				assert( start >= 1 );
				std::string::erase(start - 1);
			}
			return *this;
		}

		bool exists() const {
			stat_t buf;
			return inner_stat(buf) == 0;
		}

		operator bool() const {
			return exists();
		}

		/*
		 * If p doesn't exist and *this does, returns true.
		 * Likewise, if *this doesn't exist and p does, returns false.
		 */
		bool isNewerThan(const Path& p) const {
			stat_t mybuf, otherbuf;
			stat(mybuf);
			p.stat(otherbuf);

			if(mybuf.st_mtime > otherbuf.st_mtime) {
				return true;
			}
			else if(mybuf.st_mtime == otherbuf.st_mtime) {
				// Compares nanoseconds under Unix.
#if defined(IS_LINUX)
				return mybuf.st_mtim.tv_nsec > otherbuf.st_mtim.tv_nsec;
#elif defined(IS_MAC)
				return mybuf.st_mtimespec.tv_nsec > otherbuf.st_mtimespec.tv_nsec;
#endif
			}
			else {
				return false;
			}
		}

		bool isOlderThan(const Path& p) const {
			return p.isNewerThan(*this);
		}
	};
}

#endif
<|endoftext|>


<commit_before>#pragma once
#include <appbase/application.hpp>
#include <eos/chain/chain_controller.hpp>
#include <eos/chain/key_value_object.hpp>
#include <eos/chain/account_object.hpp>
#include <eos/types/AbiSerializer.hpp>

#include <eos/database_plugin/database_plugin.hpp>

namespace fc { class variant; }

namespace eos {
   using eos::chain::chain_controller;
   using std::unique_ptr;
   using namespace appbase;
   using chain::Name;
   using fc::optional;
   using chain::uint128_t;

namespace chain_apis {
struct empty{};

class read_only {
   const chain_controller& db;

   const string KEYi64 = "i64";
   const string KEYi128i128 = "i128i128";
   const string KEYi64i64i64 = "i64i64i64";
   const string PRIMARY = "primary";
   const string SECONDARY = "secondary";
   const string TERTIARY = "tertiary";

public:
   read_only(const chain_controller& db)
      : db(db) {}

   using get_info_params = empty;

   struct get_info_results {
      uint32_t              head_block_num = 0;
      uint32_t              last_irreversible_block_num = 0;
      chain::block_id_type  head_block_id;
      fc::time_point_sec    head_block_time;
      types::AccountName    head_block_producer;
      string                recent_slots;
      double                participation_rate = 0;
   };
   get_info_results get_info(const get_info_params&) const;

   struct producer_info {
      Name                       name;
   };

   struct get_account_results {
      Name                       name;
      uint64_t                   eos_balance       = 0;
      uint64_t                   staked_balance    = 0;
      uint64_t                   unstaking_balance = 0;
      fc::time_point_sec         last_unstaking_time;
      optional<producer_info>    producer;
      optional<types::Abi>       abi;
   };
   struct get_account_params {
      Name name;
   };
   get_account_results get_account( const get_account_params& params )const;

   struct abi_json_to_bin_params {
      Name         code;
      Name         action;
      fc::variant  args;
   };
   struct abi_json_to_bin_result {
      vector<char>   binargs;
      vector<Name>   required_scope;
      vector<Name>   required_auth;
   };

   abi_json_to_bin_result abi_json_to_bin( const abi_json_to_bin_params& params )const;

   struct abi_bin_to_json_params {
      Name         code;
      Name         action;
      vector<char> binargs;
   };
   struct abi_bin_to_json_result {
      fc::variant    args;
      vector<Name>   required_scope;
      vector<Name>   required_auth;
   };

   abi_bin_to_json_result abi_bin_to_json( const abi_bin_to_json_params& params )const;

   struct get_block_params {
      string block_num_or_id;
   };

   struct get_block_results : public chain::signed_block {
      get_block_results( const chain::signed_block& b )
      :signed_block(b),
      id(b.id()),
      block_num(b.block_num()),
      refBlockPrefix( id._hash[1] )
      {}

      chain::block_id_type id;
      uint32_t             block_num = 0;
      uint32_t             refBlockPrefix = 0;
   };

   get_block_results get_block(const get_block_params& params) const;

   struct get_table_rows_params {
      bool        json = false;
      Name        scope;
      Name        code;
      Name        table;
      string      table_type;
      string      table_key;
      string      lower_bound;
      string      upper_bound;
      uint32_t    limit = 10;
    };

   struct get_table_rows_result {
      vector<fc::variant> rows; ///< one row per item, either encoded as hex String or JSON object
      bool                more; ///< true if last element in data is not the end and sizeof data() < limit
   };

   get_table_rows_result get_table_rows( const get_table_rows_params& params )const;

   void copy_row(const chain::key_value_object& obj, vector<char>& data)const {
      data.resize( sizeof(uint64_t) + obj.value.size() );
      memcpy( data.data(), &obj.primary_key, sizeof(uint64_t) );
      memcpy( data.data()+sizeof(uint64_t), obj.value.data(), obj.value.size() );
   }

   void copy_row(const chain::key128x128_value_object& obj, vector<char>& data)const {
      data.resize( 2*sizeof(uint128_t) + obj.value.size() );
      memcpy( data.data(), &obj.primary_key, sizeof(uint128_t) );
      memcpy( data.data()+sizeof(uint128_t), &obj.secondary_key, sizeof(uint128_t) );
      memcpy( data.data()+2*sizeof(uint128_t), obj.value.data(), obj.value.size() );
   }

   void copy_row(const chain::key64x64x64_value_object& obj, vector<char>& data)const {
      data.resize( 3*sizeof(uint64_t) + obj.value.size() );
      memcpy( data.data(), &obj.primary_key, sizeof(uint64_t) );
      memcpy( data.data()+sizeof(uint64_t), &obj.secondary_key, sizeof(uint64_t) );
      memcpy( data.data()+2*sizeof(uint64_t), &obj.tertiary_key, sizeof(uint64_t) );
      memcpy( data.data()+3*sizeof(uint64_t), obj.value.data(), obj.value.size() );
   }

   template <typename IndexType, typename Scope>
   read_only::get_table_rows_result get_table_rows_ex( const read_only::get_table_rows_params& p )const {
      read_only::get_table_rows_result result;
      const auto& d = db.get_database();
      const auto& code_account = d.get<chain::account_object,chain::by_name>( p.code );

      types::AbiSerializer abis;
      if( code_account.abi.size() > 4 ) { /// 4 == packsize of empty Abi
         eos::types::Abi abi;
         fc::datastream<const char*> ds( code_account.abi.data(), code_account.abi.size() );
         fc::raw::unpack( ds, abi );
         abis.setAbi( abi );
      }

      const auto& idx = d.get_index<IndexType, Scope>();
      auto lower = idx.lower_bound( boost::make_tuple(p.scope, p.code, p.table, boost::lexical_cast<typename IndexType::value_type::key_type>(p.lower_bound)) );
      auto upper = idx.upper_bound( boost::make_tuple(p.scope, p.code, p.table, boost::lexical_cast<typename IndexType::value_type::key_type>(p.upper_bound)) );

      vector<char> data;

      auto start = fc::time_point::now();
      auto end   = fc::time_point::now() + fc::microseconds( 1000*10 ); /// 10ms max time

      int count = 0;
      auto itr = lower;
      for( itr = lower; itr != upper && itr->table == p.table; ++itr ) {
         copy_row(*itr, data);

         if( p.json )
            result.rows.emplace_back( abis.binaryToVariant( abis.getTableType(p.table), data ) );
         else
            result.rows.emplace_back( fc::variant(data) );
         if( ++count == p.limit || fc::time_point::now() > end )
            break;
      }
      if( itr != upper )
         result.more = true;
      return result;
   }

};

class read_write {
   chain_controller& db;
   uint32_t skip_flags;
public:
   read_write(chain_controller& db, uint32_t skip_flags) : db(db), skip_flags(skip_flags) {}

   using push_block_params = chain::signed_block;
   using push_block_results = empty;
   push_block_results push_block(const push_block_params& params);

   using push_transaction_params = chain::SignedTransaction;
   struct push_transaction_results {
      chain::transaction_id_type  transaction_id;
      fc::variant                 processed;
   };
   push_transaction_results push_transaction(const push_transaction_params& params);
};
} // namespace chain_apis

class chain_plugin : public plugin<chain_plugin> {
public:
   APPBASE_PLUGIN_REQUIRES((database_plugin))

   chain_plugin();
   virtual ~chain_plugin();

   virtual void set_program_options(options_description& cli, options_description& cfg) override;

   void plugin_initialize(const variables_map& options);
   void plugin_startup();
   void plugin_shutdown();

   chain_apis::read_only get_read_only_api() const { return chain_apis::read_only(chain()); }
   chain_apis::read_write get_read_write_api();

   bool accept_block(const chain::signed_block& block, bool currently_syncing);
   void accept_transaction(const chain::SignedTransaction& trx);

   bool block_is_on_preferred_chain(const chain::block_id_type& block_id);

   // return true if --skip-transaction-signatures passed to eosd
   bool is_skipping_transaction_signatures() const;

   // Only call this after plugin_startup()!
   chain_controller& chain();
   // Only call this after plugin_startup()!
   const chain_controller& chain() const;

  void get_chain_id (chain::chain_id_type &cid) const;

private:
   unique_ptr<class chain_plugin_impl> my;
};

}

FC_REFLECT(eos::chain_apis::empty, )
FC_REFLECT(eos::chain_apis::read_only::get_info_results,
  (head_block_num)(last_irreversible_block_num)(head_block_id)(head_block_time)(head_block_producer)
  (recent_slots)(participation_rate))
FC_REFLECT(eos::chain_apis::read_only::get_block_params, (block_num_or_id))

FC_REFLECT_DERIVED( eos::chain_apis::read_only::get_block_results, (eos::chain::signed_block), (id)(block_num)(refBlockPrefix) );
FC_REFLECT( eos::chain_apis::read_write::push_transaction_results, (transaction_id)(processed) )

FC_REFLECT( eos::chain_apis::read_only::get_table_rows_params, (json)(table_type)(table_key)(scope)(code)(table)(lower_bound)(upper_bound)(limit) )
FC_REFLECT( eos::chain_apis::read_only::get_table_rows_result, (rows)(more) );

FC_REFLECT( eos::chain_apis::read_only::get_account_results, (name)(eos_balance)(staked_balance)(unstaking_balance)(last_unstaking_time)(producer)(abi) )
FC_REFLECT( eos::chain_apis::read_only::get_account_params, (name) )
FC_REFLECT( eos::chain_apis::read_only::producer_info, (name) )
FC_REFLECT( eos::chain_apis::read_only::abi_json_to_bin_params, (code)(action)(args) )
FC_REFLECT( eos::chain_apis::read_only::abi_json_to_bin_result, (binargs)(required_scope)(required_auth) )
FC_REFLECT( eos::chain_apis::read_only::abi_bin_to_json_params, (code)(action)(binargs) )
FC_REFLECT( eos::chain_apis::read_only::abi_bin_to_json_result, (args)(required_scope)(required_auth) )
<commit_msg>fix build on OS X by convert lexical cast to variant cast, #250<commit_after>#pragma once
#include <appbase/application.hpp>
#include <eos/chain/chain_controller.hpp>
#include <eos/chain/key_value_object.hpp>
#include <eos/chain/account_object.hpp>
#include <eos/types/AbiSerializer.hpp>

#include <eos/database_plugin/database_plugin.hpp>

namespace fc { class variant; }

namespace eos {
   using eos::chain::chain_controller;
   using std::unique_ptr;
   using namespace appbase;
   using chain::Name;
   using fc::optional;
   using chain::uint128_t;

namespace chain_apis {
struct empty{};

class read_only {
   const chain_controller& db;

   const string KEYi64 = "i64";
   const string KEYi128i128 = "i128i128";
   const string KEYi64i64i64 = "i64i64i64";
   const string PRIMARY = "primary";
   const string SECONDARY = "secondary";
   const string TERTIARY = "tertiary";

public:
   read_only(const chain_controller& db)
      : db(db) {}

   using get_info_params = empty;

   struct get_info_results {
      uint32_t              head_block_num = 0;
      uint32_t              last_irreversible_block_num = 0;
      chain::block_id_type  head_block_id;
      fc::time_point_sec    head_block_time;
      types::AccountName    head_block_producer;
      string                recent_slots;
      double                participation_rate = 0;
   };
   get_info_results get_info(const get_info_params&) const;

   struct producer_info {
      Name                       name;
   };

   struct get_account_results {
      Name                       name;
      uint64_t                   eos_balance       = 0;
      uint64_t                   staked_balance    = 0;
      uint64_t                   unstaking_balance = 0;
      fc::time_point_sec         last_unstaking_time;
      optional<producer_info>    producer;
      optional<types::Abi>       abi;
   };
   struct get_account_params {
      Name name;
   };
   get_account_results get_account( const get_account_params& params )const;

   struct abi_json_to_bin_params {
      Name         code;
      Name         action;
      fc::variant  args;
   };
   struct abi_json_to_bin_result {
      vector<char>   binargs;
      vector<Name>   required_scope;
      vector<Name>   required_auth;
   };

   abi_json_to_bin_result abi_json_to_bin( const abi_json_to_bin_params& params )const;

   struct abi_bin_to_json_params {
      Name         code;
      Name         action;
      vector<char> binargs;
   };
   struct abi_bin_to_json_result {
      fc::variant    args;
      vector<Name>   required_scope;
      vector<Name>   required_auth;
   };

   abi_bin_to_json_result abi_bin_to_json( const abi_bin_to_json_params& params )const;

   struct get_block_params {
      string block_num_or_id;
   };

   struct get_block_results : public chain::signed_block {
      get_block_results( const chain::signed_block& b )
      :signed_block(b),
      id(b.id()),
      block_num(b.block_num()),
      refBlockPrefix( id._hash[1] )
      {}

      chain::block_id_type id;
      uint32_t             block_num = 0;
      uint32_t             refBlockPrefix = 0;
   };

   get_block_results get_block(const get_block_params& params) const;

   struct get_table_rows_params {
      bool        json = false;
      Name        scope;
      Name        code;
      Name        table;
      string      table_type;
      string      table_key;
      string      lower_bound;
      string      upper_bound;
      uint32_t    limit = 10;
    };

   struct get_table_rows_result {
      vector<fc::variant> rows; ///< one row per item, either encoded as hex String or JSON object
      bool                more; ///< true if last element in data is not the end and sizeof data() < limit
   };

   get_table_rows_result get_table_rows( const get_table_rows_params& params )const;

   void copy_row(const chain::key_value_object& obj, vector<char>& data)const {
      data.resize( sizeof(uint64_t) + obj.value.size() );
      memcpy( data.data(), &obj.primary_key, sizeof(uint64_t) );
      memcpy( data.data()+sizeof(uint64_t), obj.value.data(), obj.value.size() );
   }

   void copy_row(const chain::key128x128_value_object& obj, vector<char>& data)const {
      data.resize( 2*sizeof(uint128_t) + obj.value.size() );
      memcpy( data.data(), &obj.primary_key, sizeof(uint128_t) );
      memcpy( data.data()+sizeof(uint128_t), &obj.secondary_key, sizeof(uint128_t) );
      memcpy( data.data()+2*sizeof(uint128_t), obj.value.data(), obj.value.size() );
   }

   void copy_row(const chain::key64x64x64_value_object& obj, vector<char>& data)const {
      data.resize( 3*sizeof(uint64_t) + obj.value.size() );
      memcpy( data.data(), &obj.primary_key, sizeof(uint64_t) );
      memcpy( data.data()+sizeof(uint64_t), &obj.secondary_key, sizeof(uint64_t) );
      memcpy( data.data()+2*sizeof(uint64_t), &obj.tertiary_key, sizeof(uint64_t) );
      memcpy( data.data()+3*sizeof(uint64_t), obj.value.data(), obj.value.size() );
   }

   template <typename IndexType, typename Scope>
   read_only::get_table_rows_result get_table_rows_ex( const read_only::get_table_rows_params& p )const {
      read_only::get_table_rows_result result;
      const auto& d = db.get_database();
      const auto& code_account = d.get<chain::account_object,chain::by_name>( p.code );

      types::AbiSerializer abis;
      if( code_account.abi.size() > 4 ) { /// 4 == packsize of empty Abi
         eos::types::Abi abi;
         fc::datastream<const char*> ds( code_account.abi.data(), code_account.abi.size() );
         fc::raw::unpack( ds, abi );
         abis.setAbi( abi );
      }

      const auto& idx = d.get_index<IndexType, Scope>();
      auto lower = idx.lower_bound( boost::make_tuple(p.scope, p.code, p.table, fc::variant(p.lower_bound).as<typename IndexType::value_type::key_type>() ) );
      auto upper = idx.lower_bound( boost::make_tuple(p.scope, p.code, p.table, fc::variant(p.upper_bound).as<typename IndexType::value_type::key_type>() ) );
  //    auto upper = idx.upper_bound( boost::make_tuple(p.scope, p.code, p.table, boost::lexical_cast<typename IndexType::value_type::key_type>(p.upper_bound)) );

      vector<char> data;

      auto start = fc::time_point::now();
      auto end   = fc::time_point::now() + fc::microseconds( 1000*10 ); /// 10ms max time

      int count = 0;
      auto itr = lower;
      for( itr = lower; itr != upper && itr->table == p.table; ++itr ) {
         copy_row(*itr, data);

         if( p.json )
            result.rows.emplace_back( abis.binaryToVariant( abis.getTableType(p.table), data ) );
         else
            result.rows.emplace_back( fc::variant(data) );
         if( ++count == p.limit || fc::time_point::now() > end )
            break;
      }
      if( itr != upper )
         result.more = true;
      return result;
   }

};

class read_write {
   chain_controller& db;
   uint32_t skip_flags;
public:
   read_write(chain_controller& db, uint32_t skip_flags) : db(db), skip_flags(skip_flags) {}

   using push_block_params = chain::signed_block;
   using push_block_results = empty;
   push_block_results push_block(const push_block_params& params);

   using push_transaction_params = chain::SignedTransaction;
   struct push_transaction_results {
      chain::transaction_id_type  transaction_id;
      fc::variant                 processed;
   };
   push_transaction_results push_transaction(const push_transaction_params& params);
};
} // namespace chain_apis

class chain_plugin : public plugin<chain_plugin> {
public:
   APPBASE_PLUGIN_REQUIRES((database_plugin))

   chain_plugin();
   virtual ~chain_plugin();

   virtual void set_program_options(options_description& cli, options_description& cfg) override;

   void plugin_initialize(const variables_map& options);
   void plugin_startup();
   void plugin_shutdown();

   chain_apis::read_only get_read_only_api() const { return chain_apis::read_only(chain()); }
   chain_apis::read_write get_read_write_api();

   bool accept_block(const chain::signed_block& block, bool currently_syncing);
   void accept_transaction(const chain::SignedTransaction& trx);

   bool block_is_on_preferred_chain(const chain::block_id_type& block_id);

   // return true if --skip-transaction-signatures passed to eosd
   bool is_skipping_transaction_signatures() const;

   // Only call this after plugin_startup()!
   chain_controller& chain();
   // Only call this after plugin_startup()!
   const chain_controller& chain() const;

  void get_chain_id (chain::chain_id_type &cid) const;

private:
   unique_ptr<class chain_plugin_impl> my;
};

}

FC_REFLECT(eos::chain_apis::empty, )
FC_REFLECT(eos::chain_apis::read_only::get_info_results,
  (head_block_num)(last_irreversible_block_num)(head_block_id)(head_block_time)(head_block_producer)
  (recent_slots)(participation_rate))
FC_REFLECT(eos::chain_apis::read_only::get_block_params, (block_num_or_id))

FC_REFLECT_DERIVED( eos::chain_apis::read_only::get_block_results, (eos::chain::signed_block), (id)(block_num)(refBlockPrefix) );
FC_REFLECT( eos::chain_apis::read_write::push_transaction_results, (transaction_id)(processed) )

FC_REFLECT( eos::chain_apis::read_only::get_table_rows_params, (json)(table_type)(table_key)(scope)(code)(table)(lower_bound)(upper_bound)(limit) )
FC_REFLECT( eos::chain_apis::read_only::get_table_rows_result, (rows)(more) );

FC_REFLECT( eos::chain_apis::read_only::get_account_results, (name)(eos_balance)(staked_balance)(unstaking_balance)(last_unstaking_time)(producer)(abi) )
FC_REFLECT( eos::chain_apis::read_only::get_account_params, (name) )
FC_REFLECT( eos::chain_apis::read_only::producer_info, (name) )
FC_REFLECT( eos::chain_apis::read_only::abi_json_to_bin_params, (code)(action)(args) )
FC_REFLECT( eos::chain_apis::read_only::abi_json_to_bin_result, (binargs)(required_scope)(required_auth) )
FC_REFLECT( eos::chain_apis::read_only::abi_bin_to_json_params, (code)(action)(binargs) )
FC_REFLECT( eos::chain_apis::read_only::abi_bin_to_json_result, (args)(required_scope)(required_auth) )
<|endoftext|>


<commit_before>#include <configure/bind.hpp>

#include <configure/Node.hpp>
#include <configure/lua/State.hpp>
#include <configure/lua/Type.hpp>

#include <boost/filesystem/path.hpp>

namespace fs = boost::filesystem;

namespace configure {

	void bind_node(lua::State& state)
	{
		/// Node represent a vertex in the build graph.
		//
		// @classmod Node
		lua::Type<Node, NodePtr>(state, "Node")
			/// True if the node is a virtual node.
			// @function Node:is_virtual
			// @treturn bool
			.def("is_virtual", &Node::is_virtual)

			/// Path of the node
			// @function Node:path
			// @treturn Path absolute path
			.def("path", &Node::path)

			/// Name of a virtual node.
			// @function Node:name
			// @treturn string
			.def("name", &Node::name)

			.def("__tostring", &Node::string)

			/// Relative path to the node
			// @tparam Path start Starting point of the relative path
			// @treturn Path the relative path
			// @function Node:relative_path
			.def("relative_path", &Node::relative_path)
		;
	}

}

<commit_msg>Bind node properties accessor.<commit_after>#include "environ_utils.hpp"

#include <configure/bind.hpp>
#include <configure/Node.hpp>
#include <configure/PropertyMap.hpp>
#include <configure/lua/State.hpp>
#include <configure/lua/Type.hpp>

#include <boost/filesystem/path.hpp>

namespace fs = boost::filesystem;

namespace configure {

	static int Node_property(lua_State* state)
	{
		NodePtr& self = lua::Converter<NodePtr>::extract(state, 1);
		Environ& env = self->properties().values();
		return utils::env_get(state, env);
	}

	static int Node_set_property(lua_State* state)
	{
		NodePtr& self = lua::Converter<NodePtr>::extract(state, 1);
		Environ& env = self->properties().values();
		return utils::env_set(state, env);
	}

	static int Node_set_property_default(lua_State* state)
	{
		NodePtr& self = lua::Converter<NodePtr>::extract(state, 1);
		Environ& env = self->properties().values();
		return utils::env_set_default(state, env);
	}

	void bind_node(lua::State& state)
	{
		/// Node represent a vertex in the build graph.
		//
		// @classmod Node
		lua::Type<Node, NodePtr>(state, "Node")
			/// True if the node is a virtual node.
			// @function Node:is_virtual
			// @treturn bool
			.def("is_virtual", &Node::is_virtual)

			/// Path of the node
			// @function Node:path
			// @treturn Path absolute path
			.def("path", &Node::path)

			/// Name of a virtual node.
			// @function Node:name
			// @treturn string
			.def("name", &Node::name)

			.def("__tostring", &Node::string)

			/// Relative path to the node
			// @tparam Path start Starting point of the relative path
			// @treturn Path the relative path
			// @function Node:relative_path
			.def("relative_path", &Node::relative_path)

			/// Retrieve a Node property
			// @string name The property name
			// @treturn string|Path|boolean|nil
			.def("property", &Node_property)

			/// Set a Node property
			// @string name The property name
			// @tparam string|Path|boolean|nil the value to set
			// @treturn string|Path|boolean|nil
			.def("set_property", &Node_set_property)

			/// Set a Node property default value
			// @string name The property name
			// @tparam string|Path|boolean|nil the default value to set
			// @treturn string|Path|boolean|nil
			.def("set_property_default", &Node_set_property_default)
		;
	}

}

<|endoftext|>


<commit_before>/** @file
    @brief Implementation

    @date 2016

    @author
    Sensics, Inc.
    <http://sensics.com/osvr>
*/

// Copyright 2016 Sensics, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//        http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

// Internal Includes
#include "CSVTools.h"
#include "ConfigParams.h"
#include "LedMeasurement.h"
#include "MakeHDKTrackingSystem.h"
#include "TrackedBodyTarget.h"
#include "newuoa.h"
#include <osvr/Util/TimeValue.h>

// Library/third-party includes
#include <Eigen/Core>
#include <Eigen/Geometry>

// Standard includes
#include <fstream>
#include <sstream>

using osvr::util::time::TimeValue;
static const cv::Size IMAGE_SIZE = {640, 480};

/// Friendlier wrapper around newuoa
template <typename Function, typename Vec>
inline double ei_newuoa(long npt, Vec &x, std::pair<double, double> rho,
                        long maxfun, Function &&f) {

    double rhoBeg, rhoEnd;
    std::tie(rhoBeg, rhoEnd) = rho;
    if (rhoEnd > rhoBeg) {
        std::swap(rhoBeg, rhoEnd);
    }
    long n = x.size();
    auto workingSpaceNeeded = (npt + 13) * (npt + n) + 3 * n * (n + 3) / 2;
    Eigen::VectorXd workingSpace(workingSpaceNeeded);
    return newuoa(std::forward<Function>(f), n, npt, x.data(), rhoBeg, rhoEnd,
                  maxfun, workingSpace.data());
}

using ParamVec = Eigen::Vector4d;

namespace osvr {
namespace vbtracker {

    void updateConfigFromVec(ConfigParams &params, ParamVec const &paramVec) {
        /// positional noise
        params.processNoiseAutocorrelation[0] =
            params.processNoiseAutocorrelation[1] =
                params.processNoiseAutocorrelation[2] = paramVec[0];
        /// rotational noise
        params.processNoiseAutocorrelation[3] =
            params.processNoiseAutocorrelation[4] =
                params.processNoiseAutocorrelation[5] = paramVec[1];

        params.beaconProcessNoise = paramVec[2];

        params.measurementVarianceScaleFactor = paramVec[3];
    }

    struct TimestampedMeasurements {
        EIGEN_MAKE_ALIGNED_OPERATOR_NEW
        TimeValue tv;
        Eigen::Vector3d xlate;
        Eigen::Quaterniond rot;
        LedMeasurementVec measurements;
        bool ok = false;
    };

    class LoadRow {
      public:
        LoadRow(csvtools::FieldParserHelper &helper,
                TimestampedMeasurements &row)
            : helper_(helper), row_(row) {}
        ~LoadRow() {
            if (!measurementPieces_.empty()) {
                std::cerr << "Leftover measurement pieces on loadrow "
                             "destruction, suggests a parsing error!"
                          << std::endl;
            }
        }
        bool operator()(std::string const &line, std::size_t beginPos,
                        std::size_t endPos) {
            field_++;
            csvtools::StringField strField(line, beginPos, endPos);
            //std::cout << strField.beginPos() << ":" << strField.virtualEndPos() << std::endl;
            if (field_ <= 3) {
                // refx/y/z
                bool success = false;
                double val;
                std::tie(success, val) = helper_.getFieldAs<double>(strField);
                if (!success) {
                    return false;
                }
                row_.xlate[field_] = val;
                return true;
            }
            if (field_ <= 7) {
                // refqw/qx/qy/qz
                bool success = false;
                double val;
                std::tie(success, val) = helper_.getFieldAs<double>(strField);
                if (!success) {
                    return false;
                }
                switch (field_) {
                case 4:
                    row_.rot.w() = val;
                    break;
                case 5:
                    row_.rot.x() = val;
                    break;
                case 6:
                    row_.rot.y() = val;
                    break;
                case 7:
                    row_.rot.z() = val;
                    break;
                }
                return true;
            }
            if (field_ == 8) {
                // sec
                auto success = helper_.getField(strField, row_.tv.seconds);
                return success;
            }
            if (field_ == 9) {
                // usec
                auto success = helper_.getField(strField, row_.tv.microseconds);
                if (success) {
                    row_.ok = true;
                }
                return success;
            }
            // Now, we are looping through x, y, size for every blob.

            bool success = false;
            float val;
            std::tie(success, val) = helper_.getFieldAs<float>(strField);
            if (!success) {
                return false;
            }
            measurementPieces_.push_back(val);
            if (measurementPieces_.size() == 3) {
                // that's a new LED!
                row_.measurements.emplace_back(
                    measurementPieces_[0], measurementPieces_[1],
                    measurementPieces_[2], IMAGE_SIZE);
                measurementPieces_.clear();
            }
            return true;
        }

      private:
        csvtools::FieldParserHelper &helper_;
        TimestampedMeasurements &row_;
        std::size_t field_ = 0;
        std::vector<float> measurementPieces_;
    };

    inline std::vector<std::unique_ptr<TimestampedMeasurements>>
    loadData(std::string const &fn) {
        std::vector<std::unique_ptr<TimestampedMeasurements>> ret;
        std::ifstream csvFile(fn);
        if (!csvFile) {
            std::cerr << "Could not open csvFile " << fn << std::endl;
            return ret;
        }
        {
            auto headerRow = csvtools::getCleanLine(csvFile);
            if (headerRow.empty() || !csvFile) {
                /// @todo this is pretty crude precondition handling, but
                /// probably good enough for now.
                std::cerr << "Header row was empty, that's not a good sign!"
                          << std::endl;
                return ret;
            }
        }
        csvtools::FieldParserHelper helper;

        std::string dataLine = csvtools::getCleanLine(csvFile);
        while (csvFile) {
            std::unique_ptr<TimestampedMeasurements> newRow(
                new TimestampedMeasurements);
            csvtools::iterateFields(LoadRow(helper, *newRow), dataLine);
            //std::cout << "Done with iterate fields" << std::endl;
            if (newRow->ok) {
                std::cout << "Row has " << newRow->measurements.size() << " blobs" << std::endl;
                ret.emplace_back(std::move(newRow));
            } else {
                std::cerr << "Something went wrong parsing that row: "
                          << dataLine << std::endl;
            }

            dataLine = csvtools::getCleanLine(csvFile);
        }
        std::cout << "Total of " << ret.size() << " rows" << std::endl;
        return ret;
    }

    ParamVec runOptimizer(std::string const &fn) {
        // initial values.
        ParamVec x = {4.14e-6, 1e-2, 0, 5e-2};
        auto npt = x.size() * 2; // who knows?

        auto ret = ei_newuoa(
            npt, x, {1e-8, 1e-4}, 10, [&](long n, double *x) -> double {
                using namespace osvr::vbtracker;
                ConfigParams params;
                updateConfigFromVec(params, ParamVec::Map(x));
                auto system = makeHDKTrackingSystem(params);
                auto &target =
                    *(system->getBody(BodyId(0)).getTarget(TargetId(0)));

                /// @todo

                return 0;
            });

        std::cout << "Optimizer returned " << ret
                  << " and these parameter values:" << std::endl;
        std::cout << x.transpose() << std::endl;
        return x;
    }
}
}

int main() {
    //osvr::vbtracker::runOptimizer("augmented-blobs.csv");
    osvr::vbtracker::loadData("augmented-blobs.csv");
    std::cin.ignore();
    return 0;
}
<commit_msg>Load and process the data.<commit_after>/** @file
    @brief Implementation

    @date 2016

    @author
    Sensics, Inc.
    <http://sensics.com/osvr>
*/

// Copyright 2016 Sensics, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//        http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

// Internal Includes
#include "CSVTools.h"
#include "ConfigParams.h"
#include "LedMeasurement.h"
#include "MakeHDKTrackingSystem.h"
#include "TrackedBodyTarget.h"
#include "newuoa.h"
#include <osvr/Util/EigenFilters.h>
#include <osvr/Util/TimeValue.h>

// Library/third-party includes
#include <Eigen/Core>
#include <Eigen/Geometry>

// Standard includes
#include <fstream>
#include <sstream>

using osvr::util::time::TimeValue;
static const cv::Size IMAGE_SIZE = {640, 480};

/// Friendlier wrapper around newuoa
template <typename Function, typename Vec>
inline double ei_newuoa(long npt, Vec &x, std::pair<double, double> rho,
                        long maxfun, Function &&f) {

    double rhoBeg, rhoEnd;
    std::tie(rhoBeg, rhoEnd) = rho;
    if (rhoEnd > rhoBeg) {
        std::swap(rhoBeg, rhoEnd);
    }
    long n = x.size();
    auto workingSpaceNeeded = (npt + 13) * (npt + n) + 3 * n * (n + 3) / 2;
    Eigen::VectorXd workingSpace(workingSpaceNeeded);
    return newuoa(std::forward<Function>(f), n, npt, x.data(), rhoBeg, rhoEnd,
                  maxfun, workingSpace.data());
}

using ParamVec = Eigen::Vector4d;

namespace osvr {
namespace vbtracker {

    void updateConfigFromVec(ConfigParams &params, ParamVec const &paramVec) {
        /// positional noise
        params.processNoiseAutocorrelation[0] =
            params.processNoiseAutocorrelation[1] =
                params.processNoiseAutocorrelation[2] = paramVec[0];
        /// rotational noise
        params.processNoiseAutocorrelation[3] =
            params.processNoiseAutocorrelation[4] =
                params.processNoiseAutocorrelation[5] = paramVec[1];

        params.beaconProcessNoise = paramVec[2];

        params.measurementVarianceScaleFactor = paramVec[3];
    }

    struct TimestampedMeasurements {
        EIGEN_MAKE_ALIGNED_OPERATOR_NEW
        TimeValue tv;
        Eigen::Vector3d xlate;
        Eigen::Quaterniond rot;
        LedMeasurementVec measurements;
        bool ok = false;
    };

    class LoadRow {
      public:
        LoadRow(csvtools::FieldParserHelper &helper,
                TimestampedMeasurements &row)
            : helper_(helper), row_(row) {}
        ~LoadRow() {
            if (!measurementPieces_.empty()) {
                std::cerr << "Leftover measurement pieces on loadrow "
                             "destruction, suggests a parsing error!"
                          << std::endl;
            }
        }
        bool operator()(std::string const &line, std::size_t beginPos,
                        std::size_t endPos) {
            field_++;
            csvtools::StringField strField(line, beginPos, endPos);
            // std::cout << strField.beginPos() << ":" <<
            // strField.virtualEndPos() << std::endl;
            if (field_ <= 3) {
                // refx/y/z
                bool success = false;
                double val;
                std::tie(success, val) = helper_.getFieldAs<double>(strField);
                if (!success) {
                    return false;
                }
                row_.xlate[field_] = val;
                return true;
            }
            if (field_ <= 7) {
                // refqw/qx/qy/qz
                bool success = false;
                double val;
                std::tie(success, val) = helper_.getFieldAs<double>(strField);
                if (!success) {
                    return false;
                }
                switch (field_) {
                case 4:
                    row_.rot.w() = val;
                    break;
                case 5:
                    row_.rot.x() = val;
                    break;
                case 6:
                    row_.rot.y() = val;
                    break;
                case 7:
                    row_.rot.z() = val;
                    break;
                }
                return true;
            }
            if (field_ == 8) {
                // sec
                auto success = helper_.getField(strField, row_.tv.seconds);
                return success;
            }
            if (field_ == 9) {
                // usec
                auto success = helper_.getField(strField, row_.tv.microseconds);
                if (success) {
                    row_.ok = true;
                }
                return success;
            }
            // Now, we are looping through x, y, size for every blob.

            bool success = false;
            float val;
            std::tie(success, val) = helper_.getFieldAs<float>(strField);
            if (!success) {
                return false;
            }
            measurementPieces_.push_back(val);
            if (measurementPieces_.size() == 3) {
                // that's a new LED!
                row_.measurements.emplace_back(
                    measurementPieces_[0], measurementPieces_[1],
                    measurementPieces_[2], IMAGE_SIZE);
                measurementPieces_.clear();
            }
            return true;
        }

      private:
        csvtools::FieldParserHelper &helper_;
        TimestampedMeasurements &row_;
        std::size_t field_ = 0;
        std::vector<float> measurementPieces_;
    };

    inline std::vector<std::unique_ptr<TimestampedMeasurements>>
    loadData(std::string const &fn) {
        std::vector<std::unique_ptr<TimestampedMeasurements>> ret;
        std::ifstream csvFile(fn);
        if (!csvFile) {
            std::cerr << "Could not open csvFile " << fn << std::endl;
            return ret;
        }
        {
            auto headerRow = csvtools::getCleanLine(csvFile);
            if (headerRow.empty() || !csvFile) {
                /// @todo this is pretty crude precondition handling, but
                /// probably good enough for now.
                std::cerr << "Header row was empty, that's not a good sign!"
                          << std::endl;
                return ret;
            }
        }
        csvtools::FieldParserHelper helper;

        std::string dataLine = csvtools::getCleanLine(csvFile);
        while (csvFile) {
            std::unique_ptr<TimestampedMeasurements> newRow(
                new TimestampedMeasurements);
            csvtools::iterateFields(LoadRow(helper, *newRow), dataLine);
            // std::cout << "Done with iterate fields" << std::endl;
            if (newRow->ok) {
                std::cout << "Row has " << newRow->measurements.size()
                          << " blobs" << std::endl;
                ret.emplace_back(std::move(newRow));
            } else {
                std::cerr << "Something went wrong parsing that row: "
                          << dataLine << std::endl;
            }

            dataLine = csvtools::getCleanLine(csvFile);
        }
        std::cout << "Total of " << ret.size() << " rows" << std::endl;
        return ret;
    }

    ImageOutputDataPtr
    makeImageOutputDataFromRow(TimestampedMeasurements const &row,
                               CameraParameters const &camParams) {
        ImageOutputDataPtr ret(new ImageProcessingOutput);
        ret->tv = row.tv;
        ret->ledMeasurements = row.measurements;
        ret->camParams = camParams;
        return ret;
    }

    ParamVec runOptimizer(std::string const &fn) {
        // initial values.
        ParamVec x = {4.14e-6, 1e-2, 0, 5e-2};
        auto npt = x.size() * 2; // who knows?

        auto ret = ei_newuoa(
            npt, x, {1e-8, 1e-4}, 10, [&](long n, double *x) -> double {
                using namespace osvr::vbtracker;
                ConfigParams params;
                updateConfigFromVec(params, ParamVec::Map(x));
                auto system = makeHDKTrackingSystem(params);
                auto &target =
                    *(system->getBody(BodyId(0)).getTarget(TargetId(0)));

                /// @todo

                return 0;
            });

        std::cout << "Optimizer returned " << ret
                  << " and these parameter values:" << std::endl;
        std::cout << x.transpose() << std::endl;
        return x;
    }

    class PoseFilter {
      public:
        PoseFilter(util::filters::one_euro::Params const &positionFilterParams =
                       util::filters::one_euro::Params{},
                   util::filters::one_euro::Params const &oriFilterParams =
                       util::filters::one_euro::Params{})
            : m_positionFilter(positionFilterParams),
              m_orientationFilter(oriFilterParams){};

        void filter(double dt, Eigen::Vector3d const &position,
                    Eigen::Quaterniond const &orientation) {
            if (dt <= 0) {
                /// Avoid div by 0
                dt = 1;
            }
            m_positionFilter.filter(dt, position);
            m_orientationFilter.filter(dt, orientation);
        }

        Eigen::Vector3d const &getPosition() const {
            return m_positionFilter.getState();
        }

        Eigen::Quaterniond const &getOrientation() const {
            return m_orientationFilter.getState();
        }

        Eigen::Isometry3d getIsometry() const {
            return Eigen::Translation3d(getPosition()) *
                   Eigen::Isometry3d(getOrientation());
        }

      private:
        util::filters::OneEuroFilter<Eigen::Vector3d> m_positionFilter;
        util::filters::OneEuroFilter<Eigen::Quaterniond> m_orientationFilter;
    };
    class MainAlgoUnderStudy {
      public:
        void operator()(CameraParameters const &camParams,
                        TrackingSystem &system, TrackedBodyTarget &target,
                        TimestampedMeasurements const &row) {
            auto indices = system.updateBodiesFromVideoData(
                std::move(makeImageOutputDataFromRow(row, camParams)));
            gotPose = target.getBody().hasPoseEstimate();
            if (gotPose) {
                pose = target.getBody().getState().getIsometry();
            }
        }
        bool havePose() const { return gotPose; }
        Eigen::Isometry3d const &getPose() const { return pose; }

      private:
        bool gotPose = false;
        Eigen::Isometry3d pose;
    };
    class RansacOneEuro {
      public:
        void operator()(CameraParameters const &camParams,
                        TrackingSystem &system, TrackedBodyTarget &target,
                        TimestampedMeasurements const &row) {
            gotPose = false;
            Eigen::Vector3d pos;
            Eigen::Quaterniond quat;
            auto gotRansac = target.uncalibratedRANSACPoseEstimateFromLeds(
                camParams, pos, quat);
            if (gotRansac) {
                double dt = 1;
                if (isFirst) {
                    isFirst = false;
                } else {
                    dt = osvrTimeValueDurationSeconds(&row.tv, &last);
                }
                ransacPoseFilter.filter(dt, pos, quat);
                std::cout << ransacPoseFilter.getPosition().transpose()
                          << std::endl;
                last = row.tv;
                gotPose = true;
            }
        }
        bool havePose() const { return gotPose; }
        Eigen::Isometry3d const &getPose() const {
            return ransacPoseFilter.getIsometry();
        }

      private:
        PoseFilter ransacPoseFilter;
        TimeValue last;
        bool isFirst = true;
        bool gotPose = false;
    };
}
}

int main() {
    // osvr::vbtracker::runOptimizer("augmented-blobs.csv");
    auto data = osvr::vbtracker::loadData("augmented-blobs.csv");
    const auto camParams =
        osvr::vbtracker::getHDKCameraParameters().createUndistortedVariant();
    {
        using namespace osvr::vbtracker;
        ConfigParams params;
        ParamVec x = {4.14e-6, 1e-2, 0, 5e-2};
        updateConfigFromVec(params, x);
        auto system = makeHDKTrackingSystem(params);
        auto &target = *(system->getBody(BodyId(0)).getTarget(TargetId(0)));

        MainAlgoUnderStudy mainAlgo;
        RansacOneEuro ransacOneEuro;
        for (auto const &rowPtr : data) {
            mainAlgo(camParams, *system, target, *rowPtr);
            ransacOneEuro(camParams, *system, target, *rowPtr);
        }
    }
    std::cout << "Press enter to exit." << std::endl;
    std::cin.ignore();
    return 0;
}
<|endoftext|>