<commit_before>/*
 * propertygroup.cpp
 *
 * Created on: Jan 17, 2013
 * @author Ralph Schurade
 */
#include "propertygroup.h"

#include <QDebug>

PropertyGroup::PropertyGroup()
{
}

PropertyGroup::~PropertyGroup()
{
}

bool PropertyGroup::contains( Fn::Property name ) const
{
    for ( int i = 0; i < m_properties.size(); ++i )
    {
        if ( m_properties[i].first == name )
        {
            return true;
        }
    }
    return false;
}

QVariant PropertyGroup::get( Fn::Property name ) const
{
    for ( int i = 0; i < m_properties.size(); ++i )
    {
        if ( m_properties[i].first == name )
        {
            return m_properties[i].second->getValue();
        }
    }
    return QVariant();
}

bool PropertyGroup::set( Fn::Property name, QVariant value )
{
    for ( int i = 0; i < m_properties.size(); ++i )
    {
        if ( m_properties[i].first == name )
        {
            m_properties[i].second->setValue( value );
            return true;
        }
    }

    qDebug() << "*** ERROR *** SET" << "property doesnt exist";
    exit( 0 );
    return false;
}

bool PropertyGroup::set2( Fn::Property name, QVariant value )
{
    for ( int i = 0; i < m_properties.size(); ++i )
    {
        if ( m_properties[i].first == name )
        {
            m_properties[i].second->setValue( value );
            return true;
        }
    }

    qDebug() << "*** ERROR *** SET" << "property doesnt exist";
    exit( 0 );
    return false;
}

bool PropertyGroup::set( Fn::Property name, bool value, QString tab )
{
    if ( contains( name ) )
    {
        set2( name, value );
    }
    else
    {
        PropertyBool* prop = new PropertyBool( Fn::Prop2String::s( (Fn::Property)name ), value );
        prop->setPropertyTab( tab );
        m_properties.push_back( QPair<Fn::Property, Property*>( name, prop ) );
        connect( prop, SIGNAL( valueChanged() ), this, SLOT( slotPropChanged() ) );
    }
    return true;
}

bool PropertyGroup::set( Fn::Property name, int value, QString tab )
{
    if ( contains( name ) )
    {
        set2( name, value );
    }
    else
    {
        PropertyInt* prop = new PropertyInt( Fn::Prop2String::s( (Fn::Property)name ), value );
        prop->setPropertyTab( tab );
        m_properties.push_back( QPair<Fn::Property, Property*>( name, prop ) );
        connect( prop, SIGNAL( valueChanged() ), this, SLOT( slotPropChanged() ) );
    }
    return true;
}

bool PropertyGroup::set( Fn::Property name, int value, int min, int max, QString tab )
{
    if ( contains( name ) )
    {
        return false;
    }
    else
    {
        PropertyInt* prop = new PropertyInt( Fn::Prop2String::s( (Fn::Property)name ), value, min, max );
        prop->setPropertyTab( tab );
        m_properties.push_back( QPair<Fn::Property, Property*>( name, prop ) );
        connect( prop, SIGNAL( valueChanged() ), this, SLOT( slotPropChanged() ) );
    }
    return true;
}

bool PropertyGroup::set( Fn::Property name, float value, QString tab )
{
    if ( contains( name ) )
    {
        set2( name, value );
    }
    else
    {
        PropertyFloat* prop = new PropertyFloat( Fn::Prop2String::s( (Fn::Property)name ), value );
        prop->setPropertyTab( tab );
        m_properties.push_back( QPair<Fn::Property, Property*>( name, prop ) );
        connect( prop, SIGNAL( valueChanged() ), this, SLOT( slotPropChanged() ) );
    }
    return true;
}

bool PropertyGroup::set( Fn::Property name, float value, float min, float max, QString tab )
{
    if ( contains( name ) )
    {
        return false;
    }
    PropertyFloat* prop = new PropertyFloat( Fn::Prop2String::s( (Fn::Property)name ), value, min, max );
    prop->setPropertyTab( tab );
    m_properties.push_back( QPair<Fn::Property, Property*>( name, prop ) );
    connect( prop, SIGNAL( valueChanged() ), this, SLOT( slotPropChanged() ) );
    return true;
}

bool PropertyGroup::set( Fn::Property name, QString value, QString tab )
{
    if ( contains( name ) )
    {
        set2( name, value );
    }
    else
    {
        PropertyString* prop = new PropertyString( Fn::Prop2String::s( (Fn::Property)name ), value );
        prop->setPropertyTab( tab );
        m_properties.push_back( QPair<Fn::Property, Property*>( name, prop ) );
        connect( prop, SIGNAL( valueChanged() ), this, SLOT( slotPropChanged() ) );
    }
    return true;
}

bool PropertyGroup::set( Fn::Property name, const char* value, QString tab )
{
    if ( contains( name ) )
    {
        set2( name, QString( value ) );
    }
    else
    {
        PropertyString* prop = new PropertyString( Fn::Prop2String::s( (Fn::Property)name ), QString( value ) );
        prop->setPropertyTab( tab );
        m_properties.push_back( QPair<Fn::Property, Property*>( name, prop ) );
        connect( prop, SIGNAL( valueChanged() ), this, SLOT( slotPropChanged() ) );
    }
    return true;
}

bool PropertyGroup::set( Fn::Property name, QColor value, QString tab )
{
    if ( contains( name ) )
    {
        set2( name, value );
    }
    else
    {
        PropertyColor* prop = new PropertyColor( Fn::Prop2String::s( (Fn::Property)name ), value );
        prop->setPropertyTab( tab );
        m_properties.push_back( QPair<Fn::Property, Property*>( name, prop ) );
        connect( prop, SIGNAL( valueChanged() ), this, SLOT( slotPropChanged() ) );
    }
    return true;
}

bool PropertyGroup::set( Fn::Property name, QDir value, QString tab )
{
    if ( contains( name ) )
    {
        set2( name, value.absolutePath() );
    }
    else
    {
        PropertyPath* prop = new PropertyPath( Fn::Prop2String::s( name ), value );
        prop->setPropertyTab( tab );
        m_properties.push_back( QPair<Fn::Property, Property*>( name, prop ) );
        connect( prop, SIGNAL( valueChanged() ), this, SLOT( slotPropChanged() ) );
    }
    return true;
}

bool PropertyGroup::set( Fn::Property name, std::initializer_list<QString>options, int value, QString tab )
{
    if ( contains( name ) )
    {
        set2( name, value );
    }
    else
    {
        PropertySelection* prop = new PropertySelection( Fn::Prop2String::s( (Fn::Property)name ), options, value );
        prop->setPropertyTab( tab );
        m_properties.push_back( QPair<Fn::Property, Property*>( name, prop ) );
        connect( prop, SIGNAL( valueChanged() ), this, SLOT( slotPropChanged() ) );
    }
    return true;
}

bool PropertyGroup::set( Fn::Property name, QVector<QString> options, int value, QString tab )
{
    if ( contains( name ) )
    {
        set2( name, value );
    }
    else
    {
        PropertySelection* prop = new PropertySelection( Fn::Prop2String::s( (Fn::Property)name ), options, value );
        prop->setPropertyTab( tab );
        m_properties.push_back( QPair<Fn::Property, Property*>( name, prop ) );
        connect( prop, SIGNAL( valueChanged() ), this, SLOT( slotPropChanged() ) );
    }
    return true;
}

QWidget* PropertyGroup::getWidget( Fn::Property name )
{
    for ( int i = 0; i < m_properties.size(); ++i )
    {
        if ( m_properties[i].first == name )
        {
            return m_properties[i].second->getWidget();
        }
    }
    return 0;
}

void PropertyGroup::slotPropChanged()
{
    emit( signalPropChanged() );
}

int PropertyGroup::size() const
{
    return m_properties.size();
}

Property* PropertyGroup::getProperty( Fn::Property name )
{
    for ( int i = 0; i < m_properties.size(); ++i )
    {
        if ( m_properties[i].first == name )
        {
            return m_properties[i].second;
        }
    }
    return 0;
}

Property* PropertyGroup::getNthProperty( int n )
{
    if ( n < 0 || n >= m_properties.size() )
    {
        return 0;
    }
    return m_properties[n].second;
}

bool PropertyGroup::setMin( Fn::Property name, float value )
{
    if ( contains( name ) )
    {
        ( (PropertyFloat*)( getProperty( name ) ) )->setMin( value );
        return true;
    }
    return false;
}

bool PropertyGroup::setMax( Fn::Property name, float value )
{
    if ( contains( name ) )
    {
        ( (PropertyFloat*)( getProperty( name ) ) )->setMax( value );
        return true;
    }
    return false;
}

bool PropertyGroup::setMin( Fn::Property name, int value )
{
    if ( contains( name ) )
    {
        ( (PropertyFloat*)( getProperty( name ) ) )->setMin( value );
        return true;
    }
    return false;
}

bool PropertyGroup::setMax( Fn::Property name, int value )
{
    if ( contains( name ) )
    {
        ( (PropertyFloat*)( getProperty( name ) ) )->setMax( value );
        return true;
    }
    return false;
}
<commit_msg>fix crash with property<commit_after>/*
 * propertygroup.cpp
 *
 * Created on: Jan 17, 2013
 * @author Ralph Schurade
 */
#include "propertygroup.h"

#include <QDebug>

PropertyGroup::PropertyGroup()
{
}

PropertyGroup::~PropertyGroup()
{
}

bool PropertyGroup::contains( Fn::Property name ) const
{
    for ( int i = 0; i < m_properties.size(); ++i )
    {
        if ( m_properties[i].first == name )
        {
            return true;
        }
    }
    return false;
}

QVariant PropertyGroup::get( Fn::Property name ) const
{
    for ( int i = 0; i < m_properties.size(); ++i )
    {
        if ( m_properties[i].first == name )
        {
            return m_properties[i].second->getValue();
        }
    }
    return QVariant();
}

bool PropertyGroup::set( Fn::Property name, QVariant value )
{
    for ( int i = 0; i < m_properties.size(); ++i )
    {
        if ( m_properties[i].first == name )
        {
            m_properties[i].second->setValue( value );
            return true;
        }
    }

    qDebug() << "*** ERROR *** SET" << "property doesnt exist";
    exit( 0 );
    return false;
}

bool PropertyGroup::set2( Fn::Property name, QVariant value )
{
    for ( int i = 0; i < m_properties.size(); ++i )
    {
        if ( m_properties[i].first == name )
        {
            m_properties[i].second->setValue( value );
            return true;
        }
    }

    qDebug() << "*** ERROR *** SET" << "property doesnt exist";
    exit( 0 );
    return false;
}

bool PropertyGroup::set( Fn::Property name, bool value, QString tab )
{
    if ( contains( name ) )
    {
        set2( name, value );
    }
    else
    {
        PropertyBool* prop = new PropertyBool( Fn::Prop2String::s( (Fn::Property)name ), value );
        prop->setPropertyTab( tab );
        m_properties.push_back( QPair<Fn::Property, Property*>( name, prop ) );
        connect( prop, SIGNAL( valueChanged() ), this, SLOT( slotPropChanged() ) );
    }
    return true;
}

bool PropertyGroup::set( Fn::Property name, int value, QString tab )
{
    if ( contains( name ) )
    {
        set2( name, value );
    }
    else
    {
        PropertyInt* prop = new PropertyInt( Fn::Prop2String::s( (Fn::Property)name ), value );
        prop->setPropertyTab( tab );
        m_properties.push_back( QPair<Fn::Property, Property*>( name, prop ) );
        connect( prop, SIGNAL( valueChanged() ), this, SLOT( slotPropChanged() ) );
    }
    return true;
}

bool PropertyGroup::set( Fn::Property name, int value, int min, int max, QString tab )
{
    if ( contains( name ) )
    {
        return false;
    }
    else
    {
        PropertyInt* prop = new PropertyInt( Fn::Prop2String::s( (Fn::Property)name ), value, min, max );
        prop->setPropertyTab( tab );
        m_properties.push_back( QPair<Fn::Property, Property*>( name, prop ) );
        connect( prop, SIGNAL( valueChanged() ), this, SLOT( slotPropChanged() ) );
    }
    return true;
}

bool PropertyGroup::set( Fn::Property name, float value, QString tab )
{
    if ( contains( name ) )
    {
        set2( name, value );
    }
    else
    {
        PropertyFloat* prop = new PropertyFloat( Fn::Prop2String::s( (Fn::Property)name ), value );
        prop->setPropertyTab( tab );
        m_properties.push_back( QPair<Fn::Property, Property*>( name, prop ) );
        connect( prop, SIGNAL( valueChanged() ), this, SLOT( slotPropChanged() ) );
    }
    return true;
}

bool PropertyGroup::set( Fn::Property name, float value, float min, float max, QString tab )
{
    if ( contains( name ) )
    {
        return false;
    }
    PropertyFloat* prop = new PropertyFloat( Fn::Prop2String::s( (Fn::Property)name ), value, min, max );
    prop->setPropertyTab( tab );
    m_properties.push_back( QPair<Fn::Property, Property*>( name, prop ) );
    connect( prop, SIGNAL( valueChanged() ), this, SLOT( slotPropChanged() ) );
    return true;
}

bool PropertyGroup::set( Fn::Property name, QString value, QString tab )
{
    if ( contains( name ) )
    {
        set2( name, value );
    }
    else
    {
        PropertyString* prop = new PropertyString( Fn::Prop2String::s( (Fn::Property)name ), value );
        prop->setPropertyTab( tab );
        m_properties.push_back( QPair<Fn::Property, Property*>( name, prop ) );
        connect( prop, SIGNAL( valueChanged() ), this, SLOT( slotPropChanged() ) );
    }
    return true;
}

bool PropertyGroup::set( Fn::Property name, const char* value, QString tab )
{
    if ( contains( name ) )
    {
        set2( name, QString( value ) );
    }
    else
    {
        PropertyString* prop = new PropertyString( Fn::Prop2String::s( (Fn::Property)name ), QString( value ) );
        prop->setPropertyTab( tab );
        m_properties.push_back( QPair<Fn::Property, Property*>( name, prop ) );
        connect( prop, SIGNAL( valueChanged() ), this, SLOT( slotPropChanged() ) );
    }
    return true;
}

bool PropertyGroup::set( Fn::Property name, QColor value, QString tab )
{
    if ( contains( name ) )
    {
        set2( name, value );
    }
    else
    {
        PropertyColor* prop = new PropertyColor( Fn::Prop2String::s( (Fn::Property)name ), value );
        prop->setPropertyTab( tab );
        m_properties.push_back( QPair<Fn::Property, Property*>( name, prop ) );
        connect( prop, SIGNAL( valueChanged() ), this, SLOT( slotPropChanged() ) );
    }
    return true;
}

bool PropertyGroup::set( Fn::Property name, QDir value, QString tab )
{
    if ( contains( name ) )
    {
        set2( name, value.absolutePath() );
    }
    else
    {
        PropertyPath* prop = new PropertyPath( Fn::Prop2String::s( name ), value );
        prop->setPropertyTab( tab );
        m_properties.push_back( QPair<Fn::Property, Property*>( name, prop ) );
        connect( prop, SIGNAL( valueChanged() ), this, SLOT( slotPropChanged() ) );
    }
    return true;
}

bool PropertyGroup::set( Fn::Property name, std::initializer_list<QString>options, int value, QString tab )
{
    if ( contains( name ) )
    {
        set2( name, value );
    }
    else
    {
        PropertySelection* prop = new PropertySelection( Fn::Prop2String::s( (Fn::Property)name ), options, value );
        prop->setPropertyTab( tab );
        m_properties.push_back( QPair<Fn::Property, Property*>( name, prop ) );
        connect( prop, SIGNAL( valueChanged() ), this, SLOT( slotPropChanged() ) );
    }
    return true;
}

bool PropertyGroup::set( Fn::Property name, QVector<QString> options, int value, QString tab )
{
    if ( contains( name ) )
    {
        set2( name, value );
    }
    else
    {
        PropertySelection* prop = new PropertySelection( Fn::Prop2String::s( (Fn::Property)name ), options, value );
        prop->setPropertyTab( tab );
        m_properties.push_back( QPair<Fn::Property, Property*>( name, prop ) );
        connect( prop, SIGNAL( valueChanged() ), this, SLOT( slotPropChanged() ) );
    }
    return true;
}

QWidget* PropertyGroup::getWidget( Fn::Property name )
{
    for ( int i = 0; i < m_properties.size(); ++i )
    {
        if ( m_properties[i].first == name )
        {
            return m_properties[i].second->getWidget();
        }
    }
    return 0;
}

void PropertyGroup::slotPropChanged()
{
    emit( signalPropChanged() );
}

int PropertyGroup::size() const
{
    return m_properties.size();
}

Property* PropertyGroup::getProperty( Fn::Property name )
{
    for ( int i = 0; i < m_properties.size(); ++i )
    {
        if ( m_properties[i].first == name )
        {
            return m_properties[i].second;
        }
    }
    return 0;
}

Property* PropertyGroup::getNthProperty( int n )
{
    if ( n < 0 || n >= m_properties.size() )
    {
        return 0;
    }
    return m_properties[n].second;
}

bool PropertyGroup::setMin( Fn::Property name, float value )
{
    if ( contains( name ) )
    {
        ( (PropertyFloat*)( getProperty( name ) ) )->setMin( value );
        return true;
    }
    return false;
}

bool PropertyGroup::setMax( Fn::Property name, float value )
{
    if ( contains( name ) )
    {
        ( (PropertyFloat*)( getProperty( name ) ) )->setMax( value );
        return true;
    }
    return false;
}

bool PropertyGroup::setMin( Fn::Property name, int value )
{
    if ( contains( name ) )
    {
        ( (PropertyInt*)( getProperty( name ) ) )->setMin( value );
        return true;
    }
    return false;
}

bool PropertyGroup::setMax( Fn::Property name, int value )
{
    if ( contains( name ) )
    {
        ( (PropertyInt*)( getProperty( name ) ) )->setMax( value );
        return true;
    }
    return false;
}
<|endoftext|>


<commit_before>/***************************************************************************
 *  @file       max_subarray.hpp
 *  @author     Alan.W
 *  @date       29  Aug 2014
 *  @version    2
 *  @remark     CLRS Algorithms implementation in C++ templates.
 ***************************************************************************/
//!
//! ex4.1-2
//! Write pseudocode for the brute-force method of solving the maximum-subarray problem.
//! Your procedure should run in n^2 time.
//!
#ifndef MAX_SUBARRAY_HPP
#define MAX_SUBARRAY_HPP

#include <algorithm>
#include "iterator.hpp"

namespace clrs { namespace ch4 {

/**
 * @brief The Record struct
 */
template<typename Iter>
struct Record
{
    Iter first;
    Iter last;
    clrs::IterValue<Iter> sum;
};

template<typename Iter>
inline bool
operator >=(const Record<Iter>& lhs, const Record<Iter>& rhs)
{
    return lhs.sum  >= rhs.sum;
}

/**
 * @brief brute_force_find_max_subarray
 * @param first
 * @param last
 * @return  a struct containing first and last for the max subarray and its sum.
 *
 * @complx  O(n^2)
 * for ex4.1-2
 */
template<typename Iter>
Record<Iter>
brute_force_find_max_subarray(Iter first, Iter last)
{
    Record<Iter> max{first, first + 1, *first};
    for(auto head = first; head != last; ++head)
        for(auto tail = last; tail != head ; --tail)
        {
            auto sum = std::accumulate(head, tail, 0);
            if(sum > max.sum)
                max = { head, tail, sum };
        }
    return max;
}

/**
 * @brief find_max_crossing_subarray
 * @param first
 * @param mid
 * @param last
 * @return the Struct for max crossing subarray
 *
 * @pyseudocode FIND-MAX-CROSSING-SUBARRAY, page 71.
 * @complx  theta(n)
 */
template<typename Iter>
Record<Iter>
find_max_crossing_subarray(Iter first, Iter mid, Iter last)
{
    //! left subarray   <--
    auto left_sum = *(mid - 1);
    IterValue<Iter> sum = 0;
    auto max_left = mid - 1;
    for(auto l = mid - 1; l != first - 1; --l)
    {
        sum += *l;
        if(sum > left_sum)
        {
            left_sum = sum;
            max_left = l;
        }
    }

    //! right subarray  -->
    auto right_sum = *mid;
    sum = 0;
    auto max_right = mid;
    for(auto r = mid; r != last; ++r)
    {
        sum += *r;
        if(sum > right_sum)
        {
            right_sum = sum;
            max_right = r;
        }
    }

    return {max_left, max_right, left_sum + right_sum};
}

/**
 * @brief find_max_subarray
 * @param first
 * @param last
 *
 * @recurrence      T(n) = theta(1)             if n = 1
 *                  T(n) = 2T(n/2) + theta(n)   if n > 1
 *
 * @complx          theta(n lg n)
 *
 * @pseudocode      FIND-MAXIMUM-SUBARRAY   Page 72
 */
template<typename Iter>
Record<Iter> find_max_subarray(Iter first, Iter last)
{
    //! base case
    if(first == last - 1)
        return {first, last, *first};

    //! recur
    Iter mid = first + (last - first)/2;
    Record<Iter> left   =   find_max_subarray(first, mid);                  //T(n)
    Record<Iter> right  =   find_max_subarray(mid, last);                   //T(n)
    Record<Iter> cross  =   find_max_crossing_subarray(first, mid, last);   //theta(n)

    //! return the largest one
    if(left >= right    &&  left >= cross)          return left;
    else if(right >= left   &&  right >= cross)     return right;
    else                                            return cross;
}

}}//namespace
#endif // MAX_SUBARRAY_HPP

//! @test   brute_force_find_max_subarray
//!         for ex4.1-2
//#include <iostream>
//#include <vector>
//#include "alan.hpp"
//#include "max_subarray.hpp"

//int main()
//{
//    std::vector<int> v{2,-1, 3,};
//    auto ret = clrs::ch4::brute_force_find_max_subarray(v.begin(), v.end());
//    std::cout << ret.sum;

//    alan::end();
//    return 0;
//}
//! @output
//!
//4
//exit normally

//! @test   find_max_crossing_subarray
//!         for FIND-MAX-CROSSING-SUBARRAY
//!
//#include <iostream>
//#include <vector>
//#include "alan.hpp"
//#include "max_subarray.hpp"

//int main()
//{
//    std::vector<int> v{2,-1, 3,};
//    auto ret = clrs::ch4::find_max_crossing_subarray(v.begin(),v.begin() + 1, v.end());
//    std::cout << ret.sum;

//    alan::end();
//    return 0;
//}
//! @output
//!
//4
//exit normally

//! @test   find_max_subarray
//!         for FIND-MAXIMUM-SUBARRAY
//#include <iostream>
//#include <vector>
//#include "alan.hpp"
//#include "max_subarray.hpp"

//int main()
//{
//    std::vector<int> v{2,-1, 3,5};
//    auto ret = clrs::ch4::find_max_subarray(v.begin(), v.end());
//    std::cout << ret.sum;

//    alan::end();
//    return 0;
//}
//! @output
//!
//9
//exit normally
<commit_msg>refactor : find_max_subarray_linear 	modified:   ch04/max_subarray.hpp<commit_after>/***************************************************************************
 *  @file       max_subarray.hpp
 *  @author     Alan.W
 *  @date       29  Aug 2014
 *  @version    2
 *  @remark     CLRS Algorithms implementation in C++ templates.
 ***************************************************************************/
//!
//! ex4.1-2
//! Write pseudocode for the brute-force method of solving the maximum-subarray problem.
//! Your procedure should run in n^2 time.
//!
#ifndef MAX_SUBARRAY_HPP
#define MAX_SUBARRAY_HPP

#include <algorithm>
#include <vector>
#include <assert.h>
#include "iterator.hpp"

namespace clrs { namespace ch4 {

/**
 * @brief The Record struct
 */
template<typename Iter>
struct Record
{
    Iter first;
    Iter last;
    clrs::IterValue<Iter> sum;
};

template<typename Iter>
inline bool
operator >=(const Record<Iter>& lhs, const Record<Iter>& rhs)
{
    return lhs.sum  >= rhs.sum;
}

/**
 * @brief brute_force_find_max_subarray
 * @param first
 * @param last
 * @return  a struct containing first and last for the max subarray and its sum.
 *
 * @complx  O(n^2)
 * for ex4.1-2
 */
template<typename Iter>
Record<Iter>
brute_force_find_max_subarray(Iter first, Iter last)
{
    Record<Iter> max{first, first + 1, *first};
    for(auto head = first; head != last; ++head)
        for(auto tail = last; tail != head ; --tail)
        {
            auto sum = std::accumulate(head, tail, 0);
            if(sum > max.sum)
                max = { head, tail, sum };
        }
    return max;
}

/**
 * @brief find_max_crossing_subarray
 * @param first
 * @param mid
 * @param last
 * @return the Struct for max crossing subarray
 *
 * @pyseudocode FIND-MAX-CROSSING-SUBARRAY, page 71.
 * @complx  theta(n)
 */
template<typename Iter>
Record<Iter>
find_max_crossing_subarray(Iter first, Iter mid, Iter last)
{
    //! left subarray   <--
    auto left_sum = *(mid - 1);
    IterValue<Iter> sum = 0;
    auto max_left = mid - 1;
    for(auto l = mid - 1; l != first - 1; --l)
    {
        sum += *l;
        if(sum > left_sum)
        {
            left_sum = sum;
            max_left = l;
        }
    }

    //! right subarray  -->
    auto right_sum = *mid;
    sum = 0;
    auto max_right = mid;
    for(auto r = mid; r != last; ++r)
    {
        sum += *r;
        if(sum > right_sum)
        {
            right_sum = sum;
            max_right = r;
        }
    }

    return {max_left, max_right, left_sum + right_sum};
}

/**
 * @brief find_max_subarray
 * @param first
 * @param last
 *
 * @recurrence      T(n) = theta(1)             if n = 1
 *                  T(n) = 2T(n/2) + theta(n)   if n > 1
 *
 * @complx          theta(n lg n)
 *
 * @pseudocode      FIND-MAXIMUM-SUBARRAY   Page 72
 */
template<typename Iter>
Record<Iter> find_max_subarray(Iter first, Iter last)
{
    //! base case
    if(first == last - 1)
        return {first, last, *first};

    //! recur
    Iter mid = first + (last - first)/2;
    Record<Iter> left   =   find_max_subarray(first, mid);                  //T(n)
    Record<Iter> right  =   find_max_subarray(mid, last);                   //T(n)
    Record<Iter> cross  =   find_max_crossing_subarray(first, mid, last);   //theta(n)

    //! return the largest one
    if(left >= right    &&  left >= cross)          return left;
    else if(right >= left   &&  right >= cross)     return right;
    else                                            return cross;
}

template<typename Iter>
Record<Iter> find_max_subarray_linear(Iter first, Iter last)
{
    using Vec = std::vector<Record<Iter>>;
    Vec v(last - first);
    v[0] = {first, first + 1, *first};
    for(Vec::size_type curr = 1; curr != v.size(); ++curr)
    {
        if(v[curr]->sum   <=  0)
            v[curr] =
            {
                first + curr,
                first + curr + 1,
                *(first + curr)
            };
        else
            v[curr] =
            {
                v[curr - 1]->first,
                first + curr + 1,
                v[curr - 1]->sum + *(first + curr)
            };
    }
    return std::max_element(v.begin(), v.end());
}

}}//namespace
#endif // MAX_SUBARRAY_HPP

//! @test   brute_force_find_max_subarray
//!         for ex4.1-2
//#include <iostream>
//#include <vector>
//#include "alan.hpp"
//#include "max_subarray.hpp"

//int main()
//{
//    std::vector<int> v{2,-1, 3,};
//    auto ret = clrs::ch4::brute_force_find_max_subarray(v.begin(), v.end());
//    std::cout << ret.sum;

//    alan::end();
//    return 0;
//}
//! @output
//!
//4
//exit normally

//! @test   find_max_crossing_subarray
//!         for FIND-MAX-CROSSING-SUBARRAY
//!
//#include <iostream>
//#include <vector>
//#include "alan.hpp"
//#include "max_subarray.hpp"

//int main()
//{
//    std::vector<int> v{2,-1, 3,};
//    auto ret = clrs::ch4::find_max_crossing_subarray(v.begin(),v.begin() + 1, v.end());
//    std::cout << ret.sum;

//    alan::end();
//    return 0;
//}
//! @output
//!
//4
//exit normally

//! @test   find_max_subarray
//!         for FIND-MAXIMUM-SUBARRAY
//#include <iostream>
//#include <vector>
//#include "alan.hpp"
//#include "max_subarray.hpp"

//int main()
//{
//    std::vector<int> v{2,-1, 3,5};
//    auto ret = clrs::ch4::find_max_subarray(v.begin(), v.end());
//    std::cout << ret.sum;

//    alan::end();
//    return 0;
//}
//! @output
//!
//9
//exit normally
<|endoftext|>


<commit_before>/***************************************************************************
 *  @file       redblacktree.hpp
 *  @author     Alan.W
 *  @date       05  July 2014
 *  @remark     Algorithims implementation for CLRS, using C++ templates.
 ***************************************************************************/
#ifndef REDBLACKTREE_HPP
#define REDBLACKTREE_HPP
#include <memory>
#include <functional>
#include "node.hpp"

namespace ch13{

/**
 * @brief The RedBlackTree class
 */
template<typename K, typename D>
class RedBlackTree
{
public:
    using KeyType   =   K;
    using DataType  =   D;
    using NodeType  =   Node<K,D>;
    using sPointer  =   std::shared_ptr<NodeType>;
    using wPointer  =   std::weak_ptr<NodeType>;

    RedBlackTree():
        nil(std::make_shared<NodeType>())
    {
        root = nil;
    }

    void remove(sPointer target)
    {
        sPointer x,y;
        Color  y_original_color;

        if(target->left == this->nil)
        {
            y = target;
            y_original_color = y->color;
            x = y->right;
            transplant(target,x);
        }
        else if(target->right   ==  this->nil)
        {
            y = target;
            y_original_color = y->color;
            x = y->left;
            transplant(target,x);
        }
        else
        {
            y = minimum(target->right);
            y_original_color = y->color;
            x = y->right;

            if(y->parent.lock() ==  target)
                x->parent   =   y;
            else
            {
                transplant(y,x);
                y->right    =   target->right;
                y->right->parent    =   y;
            }

            transplant(target, y);
            y->left         =   target->left;
            y->left->parent =   y;
            y->color        =   target->color;
        }

        if(y_original_color ==  Color::BLACK)
            //  to do   : add fix up function
        {}
    }

    /**
     * @brief print
     *
     * O(n)
     */
    void print()const
    {
        std::cout << "-----------------------------\n";
        std::cout << debug::yellow("root= ") << root
                  << " key = " << root->key    << std::endl;

        std::cout << debug::yellow("nil = ") << nil
                  << std::endl;

        std::function<void(sPointer node)> inorder_walk =
                [&inorder_walk,this](sPointer node)
        {
            if(node != nil)
            {
                inorder_walk(node->left);
                node->print();
                inorder_walk(node->right);
            }
        };
        inorder_walk(root);
    }

    /**
     * @brief insert
     * @param key
     *
     * O(h)
     */
    void insert(const KeyType& key)
    {
        sPointer added = std::make_shared<NodeType>(key);
        insert(added);
    }

    /**
     * @brief insert
     * @param added
     *
     * @page    315
     * O(h)
     */
    void insert(sPointer added)
    {
        sPointer tracker = nil;
        sPointer curr = root;
        while(curr != nil)
        {
            tracker =   curr;
            curr    =   curr->key > added->key?     curr->left  :   curr->right;
        }

        added->parent   =   tracker;
        if(tracker == nil)
            root    =   added;
        else
            (added->key < tracker->key?     tracker->left   :   tracker->right)
                    =   added;

        added->left =   added->right    =   nil;
        added->color=   Color::RED;

        insert_fixup(added);
    }

    /**
     * @brief search
     * @param key
     *
     * @complx  O(h)
     */
    sPointer search(const KeyType& key)const
    {
        sPointer ret  = nullptr;
        sPointer curr = this->root;
        while(curr)
        {
            if(curr->key    ==  key)
            {
                ret = curr;
                break;
            }
            else
                curr = (curr->key > key?    curr->left  :   curr->right);
        }
        return ret;
    }

    /**
     * @brief left_rotate
     * @param x
     *
     *      [x]                    [y]
     *         \        =>        /
     *          [y]            [x]
     *
     * @complx  o(1)
     *
     * @page    313
     */
    void left_rotate(sPointer x)
    {
        sPointer y = x->right;      //  set y

        x->right    =   y->left;    //  turn y's left into x's right
        if(y->left  !=  this->nil)
            y->left->parent = x;

        y->parent   =   x->parent;  //  link x's parent to y
        if(x->parent.lock()    ==  this->nil)
            this->root  =   y;
        else
            (x->is_left()?  x->parent.lock()->left  :  x->parent.lock()->right)
                        =   y;

        y->left     =   x;
        x->parent   =   y;
    }

    /**
     * @brief right_rotate
     * @param y
     *
     *          [y]             [x]
     *          /       =>         \
     *        [x]                   [y]
     *
     * @complx  O(1)
     */
    void right_rotate(sPointer y)
    {
        sPointer x = y->left;

        y->left = x->right;
        if(x->right != this->nil)
            x->right->parent    =   y;

        x->parent   =   y->parent;
        if(y->parent.lock() ==  this->nil)
            root    =   x;
        else
            (y->is_left()?  y->parent.lock()->left  :  y->parent.lock()->right)
                    =   x;

        x->right    =   y;
        y->parent   =   x;
    }
//private:
    sPointer root;
    sPointer nil;

    /**
     * @brief transplant
     * @param to
     * @param from
     *
     * @note    a bit different from the BST version
     * @complx  O(1)
     * @page    323
     */
    void transplant(sPointer to, sPointer from)
    {
        if(ascend(to,1) == this->nil)
            this->root  =   from;
        else
            (to->is_left()?     ascend(to,1)->left    :   ascend(to,1)->right)
                        =   from;

        from->parent    =   to->parent;
    }

    /**
     * @brief minimum
     */
    sPointer minimum(sPointer node)
    {
        assert(node != this->nil);

        while(node != this->nil)
            node    =   node->left;
        return node;
    }

    /**
     * @brief ascend
     *
     * used for insert_fixup
     */
    sPointer ascend(sPointer node, int level)
    {
        while(level--)
            node = node->parent.lock();
        return node;
    }

    /**
     * @brief insert_fixup
     *
     * @complx  O(1)
     *
     * based on the pyseudocode on Page 316
     */
    void insert_fixup(sPointer added)
    {
        while(ascend(added,1)->color   ==  Color::RED)
        {
            if(ascend(added,1)->is_left())
            {
                sPointer uncle = ascend(added,2)->right;
                if(uncle->color ==  Color::RED)
                {
                    uncle->color            =   Color::BLACK;
                    ascend(added,1)->color  =   Color::BLACK;
                    ascend(added,2)->color  =   Color::RED;
                    added   =   ascend(added,2);
                }
                else
                {
                    if(added->is_right())
                    {
                        added   =   ascend(added,1);
                        left_rotate(added);
                    }
                    ascend(added,1)->color  =   Color::BLACK;
                    ascend(added,2)->color  =   Color::RED;
                    right_rotate(ascend(added,2));
                }
            }
            else
            {
                sPointer uncle = ascend(added,2)->left;
                if(uncle->color ==  Color::RED)
                {
                    uncle->color            =   Color::BLACK;
                    ascend(added,1)->color  =   Color::BLACK;
                    ascend(added,2)->color  =   Color::RED;
                    added   =   ascend(added,2);
                }
                else
                {
                    if(added->is_left())
                    {
                        added   =   ascend(added,1);
                        right_rotate(added);
                    }
                    ascend(added,1)->color  =   Color::BLACK;
                    ascend(added,2)->color  =   Color::RED;
                    left_rotate(ascend(added,2));
                }
            }
        }
        root->color = Color::BLACK;
    }
};
}//namespace

#endif // REDBLACKTREE_HPP

//! testing insert()
//#include <iostream>
//#include <vector>
//#include <node.hpp>
//#include "redblacktree.hpp"

//int main()
//{
//    std::vector<int> v =
//        {6,5,1,1,2,34,5,6,7,8,9,8,7,4,3,2,2,3,5,6,7,2,345};
//    ch13::RedBlackTree<int,std::string> tree;

//    for(auto i : v)
//        tree.insert(i);

//    tree.print();
//    std::cout << "length = " << v.size() << std::endl;

//    return 0;
//}
<commit_msg>fix bug in minimum method  On branch ch13 	modified:   ch13/redblacktree.hpp<commit_after>/***************************************************************************
 *  @file       redblacktree.hpp
 *  @author     Alan.W
 *  @date       05  July 2014
 *  @remark     Algorithims implementation for CLRS, using C++ templates.
 ***************************************************************************/
#ifndef REDBLACKTREE_HPP
#define REDBLACKTREE_HPP
#include <memory>
#include <functional>
#include "node.hpp"

namespace ch13{

/**
 * @brief The RedBlackTree class
 */
template<typename K, typename D>
class RedBlackTree
{
public:
    using KeyType   =   K;
    using DataType  =   D;
    using NodeType  =   Node<K,D>;
    using sPointer  =   std::shared_ptr<NodeType>;
    using wPointer  =   std::weak_ptr<NodeType>;

    RedBlackTree():
        nil(std::make_shared<NodeType>())
    {
        root = nil;
    }

    void remove(sPointer target)
    {
        sPointer x,y;
        Color  y_original_color;

        if(target->left == this->nil)
        {
            y = target;
            y_original_color = y->color;
            x = y->right;
            transplant(target,x);
        }
        else if(target->right   ==  this->nil)
        {
            y = target;
            y_original_color = y->color;
            x = y->left;
            transplant(target,x);
        }
        else
        {
            y = minimum(target->right);
            y_original_color = y->color;
            x = y->right;

            if(y->parent.lock() ==  target)
                x->parent   =   y;
            else
            {
                transplant(y,x);
                y->right    =   target->right;
                y->right->parent    =   y;
            }

            transplant(target, y);
            y->left         =   target->left;
            y->left->parent =   y;
            y->color        =   target->color;
        }

        if(y_original_color ==  Color::BLACK)
            //  to do   : add fix up function
        {}
    }

    /**
     * @brief print
     *
     * O(n)
     */
    void print()const
    {
        std::cout << "-----------------------------\n";
        std::cout << debug::yellow("root= ") << root
                  << " key = " << root->key    << std::endl;

        std::cout << debug::yellow("nil = ") << nil
                  << std::endl;

        std::function<void(sPointer node)> inorder_walk =
                [&inorder_walk,this](sPointer node)
        {
            if(node != nil)
            {
                inorder_walk(node->left);
                node->print();
                inorder_walk(node->right);
            }
        };
        inorder_walk(root);
    }

    /**
     * @brief insert
     * @param key
     *
     * O(h)
     */
    void insert(const KeyType& key)
    {
        sPointer added = std::make_shared<NodeType>(key);
        insert(added);
    }

    /**
     * @brief insert
     * @param added
     *
     * @page    315
     * O(h)
     */
    void insert(sPointer added)
    {
        sPointer tracker = nil;
        sPointer curr = root;
        while(curr != nil)
        {
            tracker =   curr;
            curr    =   curr->key > added->key?     curr->left  :   curr->right;
        }

        added->parent   =   tracker;
        if(tracker == nil)
            root    =   added;
        else
            (added->key < tracker->key?     tracker->left   :   tracker->right)
                    =   added;

        added->left =   added->right    =   nil;
        added->color=   Color::RED;

        insert_fixup(added);
    }

    /**
     * @brief search
     * @param key
     *
     * @complx  O(h)
     */
    sPointer search(const KeyType& key)const
    {
        sPointer ret  = nullptr;
        sPointer curr = this->root;
        while(curr)
        {
            if(curr->key    ==  key)
            {
                ret = curr;
                break;
            }
            else
                curr = (curr->key > key?    curr->left  :   curr->right);
        }
        return ret;
    }

    /**
     * @brief left_rotate
     * @param x
     *
     *      [x]                    [y]
     *         \        =>        /
     *          [y]            [x]
     *
     * @complx  o(1)
     *
     * @page    313
     */
    void left_rotate(sPointer x)
    {
        sPointer y = x->right;      //  set y

        x->right    =   y->left;    //  turn y's left into x's right
        if(y->left  !=  this->nil)
            y->left->parent = x;

        y->parent   =   x->parent;  //  link x's parent to y
        if(x->parent.lock()    ==  this->nil)
            this->root  =   y;
        else
            (x->is_left()?  x->parent.lock()->left  :  x->parent.lock()->right)
                        =   y;

        y->left     =   x;
        x->parent   =   y;
    }

    /**
     * @brief right_rotate
     * @param y
     *
     *          [y]             [x]
     *          /       =>         \
     *        [x]                   [y]
     *
     * @complx  O(1)
     */
    void right_rotate(sPointer y)
    {
        sPointer x = y->left;

        y->left = x->right;
        if(x->right != this->nil)
            x->right->parent    =   y;

        x->parent   =   y->parent;
        if(y->parent.lock() ==  this->nil)
            root    =   x;
        else
            (y->is_left()?  y->parent.lock()->left  :  y->parent.lock()->right)
                    =   x;

        x->right    =   y;
        y->parent   =   x;
    }
//private:
    sPointer root;
    sPointer nil;

    /**
     * @brief transplant
     * @param to
     * @param from
     *
     * @note    a bit different from the BST version
     * @complx  O(1)
     * @page    323
     */
    void transplant(sPointer to, sPointer from)
    {
        if(ascend(to,1) == this->nil)
            this->root  =   from;
        else
            (to->is_left()?     ascend(to,1)->left    :   ascend(to,1)->right)
                        =   from;

        from->parent    =   to->parent;
    }

    /**
     * @brief minimum
     */
    sPointer minimum(sPointer node)
    {
        assert(node != this->nil);

        sPointer tracker = node;

        while(node != this->nil)
        {
            tracker =   node;
            node    =   node->left;
        }
        return tracker;
    }

    /**
     * @brief ascend
     *
     * used for insert_fixup
     */
    sPointer ascend(sPointer node, int level)
    {
        while(level--)
            node = node->parent.lock();
        return node;
    }

    /**
     * @brief insert_fixup
     *
     * @complx  O(1)
     *
     * based on the pyseudocode on Page 316
     */
    void insert_fixup(sPointer added)
    {
        while(ascend(added,1)->color   ==  Color::RED)
        {
            if(ascend(added,1)->is_left())
            {
                sPointer uncle = ascend(added,2)->right;
                if(uncle->color ==  Color::RED)
                {
                    uncle->color            =   Color::BLACK;
                    ascend(added,1)->color  =   Color::BLACK;
                    ascend(added,2)->color  =   Color::RED;
                    added   =   ascend(added,2);
                }
                else
                {
                    if(added->is_right())
                    {
                        added   =   ascend(added,1);
                        left_rotate(added);
                    }
                    ascend(added,1)->color  =   Color::BLACK;
                    ascend(added,2)->color  =   Color::RED;
                    right_rotate(ascend(added,2));
                }
            }
            else
            {
                sPointer uncle = ascend(added,2)->left;
                if(uncle->color ==  Color::RED)
                {
                    uncle->color            =   Color::BLACK;
                    ascend(added,1)->color  =   Color::BLACK;
                    ascend(added,2)->color  =   Color::RED;
                    added   =   ascend(added,2);
                }
                else
                {
                    if(added->is_left())
                    {
                        added   =   ascend(added,1);
                        right_rotate(added);
                    }
                    ascend(added,1)->color  =   Color::BLACK;
                    ascend(added,2)->color  =   Color::RED;
                    left_rotate(ascend(added,2));
                }
            }
        }
        root->color = Color::BLACK;
    }
};
}//namespace

#endif // REDBLACKTREE_HPP

//! testing insert()
//#include <iostream>
//#include <vector>
//#include <node.hpp>
//#include "redblacktree.hpp"

//int main()
//{
//    std::vector<int> v =
//        {6,5,1,1,2,34,5,6,7,8,9,8,7,4,3,2,2,3,5,6,7,2,345};
//    ch13::RedBlackTree<int,std::string> tree;

//    for(auto i : v)
//        tree.insert(i);

//    tree.print();
//    std::cout << "length = " << v.size() << std::endl;

//    return 0;
//}
<|endoftext|>


<commit_before>/*
 * =====================================================================================
 *
 *       Filename:  warp.cpp
 *
 *    Description:
 *
 *        Version:  1.0
 *        Created:  06/03/2014 13:38:27
 *       Revision:  none
 *       Compiler:  gcc
 *
 *         Author:  Eugene Scherba
 *   Organization:  Livefyre
 *
 * =====================================================================================
 */

#include <cmath>
#include <opencv2/opencv.hpp>

void identity(cv::Mat& dst, cv::Mat& src) {
    int height = src.rows;
    int width = src.cols;

    for (int j = 0; j < height; j++){
        int j_new = j;
        for (int i = 0; i < width; i++){
            int i_new = i;
            dst.at<float>(j_new, i_new) = (float)src.at<float>(j, i);
        }
    }
}

void project_flat(cv::Mat& dst, cv::Mat& src) {
    int height = src.rows;
    int width = src.cols;

    float jf = (float)height * 0.75f; // distance from camera to ceiling
    float zf = (float)height * 2.0f;  // distance to camera to projection plane
    float zb = (float)height * 0.5f;  // distance between projection and back planes

    for (int j = 0; j < height; j++){
        int j_new = (int)(jf + (zf * ((float)j - jf) / (zb + zf)));
        for (int i = 0; i < width; i++){
            int i_new = i;
            dst.at<float>(j_new, i_new) = (float)src.at<float>(j, i);
        }
    }
}

cv::Vec3b getSubpix(const cv::Mat& img, cv::Point2f pt)
{
    int x = (int)pt.x;
    int y = (int)pt.y;

    int x0 = cv::borderInterpolate(x,   img.cols, cv::BORDER_REFLECT_101);
    int x1 = cv::borderInterpolate(x+1, img.cols, cv::BORDER_REFLECT_101);
    int y0 = cv::borderInterpolate(y,   img.rows, cv::BORDER_REFLECT_101);
    int y1 = cv::borderInterpolate(y+1, img.rows, cv::BORDER_REFLECT_101);

    float a = pt.x - (float)x;
    float c = pt.y - (float)y;

    uchar b = (uchar)cvRound((img.at<cv::Vec3b>(y0, x0)[0] * (1.f - a) + img.at<cv::Vec3b>(y0, x1)[0] * a) * (1.f - c)
                           + (img.at<cv::Vec3b>(y1, x0)[0] * (1.f - a) + img.at<cv::Vec3b>(y1, x1)[0] * a) * c);
    uchar g = (uchar)cvRound((img.at<cv::Vec3b>(y0, x0)[1] * (1.f - a) + img.at<cv::Vec3b>(y0, x1)[1] * a) * (1.f - c)
                           + (img.at<cv::Vec3b>(y1, x0)[1] * (1.f - a) + img.at<cv::Vec3b>(y1, x1)[1] * a) * c);
    uchar r = (uchar)cvRound((img.at<cv::Vec3b>(y0, x0)[2] * (1.f - a) + img.at<cv::Vec3b>(y0, x1)[2] * a) * (1.f - c)
                           + (img.at<cv::Vec3b>(y1, x0)[2] * (1.f - a) + img.at<cv::Vec3b>(y1, x1)[2] * a) * c);

    return cv::Vec3b(b, g, r);
}

void wrap_cylinder(cv::Mat& dst, cv::Mat& src) {
    int height = src.rows;
    int width = src.cols;

    float jf = (float)height * 0.75f; // distance from camera to ceiling
    float zf = (float)height * 2.0f;  // distance to camera to projection plane

    float half_width = (float)width * 0.50f;
    float xf = half_width;
    float r = (float)width * 0.50f;
    float yf = (float)height * 0.75f;

    int channels = dst.channels();

    for (int i = 0; i < width; i++)
    {
        // X-axis (columns)
        float zb = r * (cos((half_width - (float)i) / r) - cos(half_width / r));
        float z_ratio = (zb + zf) / zf;
        float i_new = xf + z_ratio * (r * sin(((float)i - half_width) / r));
        for (int j = 0; j < height; j++)
        {
            // Y-axis (rows)
            float j_new = yf + z_ratio * ((float)j - yf);
            if (i_new > 0.0f && i_new < (float)width && j_new > 0.0f && j_new < (float)height) {
                cv::Vec3b new_val = getSubpix(src, cv::Point2f(i_new, j_new));
                dst.at<cv::Vec3b>(j, i) = new_val;
            }
        }
    }
}

int main() {
    cv::Mat src = cv::imread("Lenna_grid.jpg", CV_LOAD_IMAGE_COLOR);
    src.convertTo(src, CV_8UC3);
    cv::Mat dst = cv::Mat::zeros(src.rows, src.cols, src.type());

    wrap_cylinder(dst, src);

    cv::imshow("output", dst);
    cv::waitKey(0);
}
<commit_msg>fix typo<commit_after>/*
 * =====================================================================================
 *
 *       Filename:  warp.cpp
 *
 *    Description:
 *
 *        Version:  1.0
 *        Created:  06/03/2014 13:38:27
 *       Revision:  none
 *       Compiler:  gcc
 *
 *         Author:  Eugene Scherba
 *   Organization:  Livefyre
 *
 * =====================================================================================
 */

#include <cmath>
#include <opencv2/opencv.hpp>

void identity(cv::Mat& dst, cv::Mat& src) {
    int height = src.rows;
    int width = src.cols;

    for (int j = 0; j < height; j++){
        int j_new = j;
        for (int i = 0; i < width; i++){
            int i_new = i;
            dst.at<float>(j_new, i_new) = (float)src.at<float>(j, i);
        }
    }
}

void project_flat(cv::Mat& dst, cv::Mat& src) {
    int height = src.rows;
    int width = src.cols;

    float jf = (float)height * 0.75f; // distance from camera to ceiling
    float zf = (float)height * 2.0f;  // distance to camera to projection plane
    float zb = (float)height * 0.5f;  // distance between projection and back planes

    for (int j = 0; j < height; j++){
        int j_new = (int)(jf + (zf * ((float)j - jf) / (zb + zf)));
        for (int i = 0; i < width; i++){
            int i_new = i;
            dst.at<float>(j_new, i_new) = (float)src.at<float>(j, i);
        }
    }
}

cv::Vec3b getSubpix(const cv::Mat& img, cv::Point2f pt)
{
    int x = (int)pt.x;
    int y = (int)pt.y;

    int x0 = cv::borderInterpolate(x,   img.cols, cv::BORDER_REFLECT_101);
    int x1 = cv::borderInterpolate(x+1, img.cols, cv::BORDER_REFLECT_101);
    int y0 = cv::borderInterpolate(y,   img.rows, cv::BORDER_REFLECT_101);
    int y1 = cv::borderInterpolate(y+1, img.rows, cv::BORDER_REFLECT_101);

    float a = pt.x - (float)x;
    float c = pt.y - (float)y;

    uchar b = (uchar)cvRound((img.at<cv::Vec3b>(y0, x0)[0] * (1.f - a) + img.at<cv::Vec3b>(y0, x1)[0] * a) * (1.f - c)
                           + (img.at<cv::Vec3b>(y1, x0)[0] * (1.f - a) + img.at<cv::Vec3b>(y1, x1)[0] * a) * c);
    uchar g = (uchar)cvRound((img.at<cv::Vec3b>(y0, x0)[1] * (1.f - a) + img.at<cv::Vec3b>(y0, x1)[1] * a) * (1.f - c)
                           + (img.at<cv::Vec3b>(y1, x0)[1] * (1.f - a) + img.at<cv::Vec3b>(y1, x1)[1] * a) * c);
    uchar r = (uchar)cvRound((img.at<cv::Vec3b>(y0, x0)[2] * (1.f - a) + img.at<cv::Vec3b>(y0, x1)[2] * a) * (1.f - c)
                           + (img.at<cv::Vec3b>(y1, x0)[2] * (1.f - a) + img.at<cv::Vec3b>(y1, x1)[2] * a) * c);

    return cv::Vec3b(b, g, r);
}

void wrap_cylinder(cv::Mat& dst, cv::Mat& src) {
    int height = src.rows;
    int width = src.cols;

    float zf = (float)height * 2.0f;  // distance to camera to projection plane

    float half_width = (float)width * 0.50f;
    float xf = half_width;
    float r = (float)width * 0.50f;
    float yf = (float)height * 0.75f; // distance from camera to ceiling

    int channels = dst.channels();

    for (int i = 0; i < width; i++)
    {
        // X-axis (columns)
        float zb = r * (cos((half_width - (float)i) / r) - cos(half_width / r));
        float z_ratio = (zb + zf) / zf;
        float i_new = xf + z_ratio * (r * sin(((float)i - half_width) / r));
        for (int j = 0; j < height; j++)
        {
            // Y-axis (rows)
            float j_new = yf + z_ratio * ((float)j - yf);
            if (i_new > 0.0f && i_new < (float)width && j_new > 0.0f && j_new < (float)height) {
                cv::Vec3b new_val = getSubpix(src, cv::Point2f(i_new, j_new));
                dst.at<cv::Vec3b>(j, i) = new_val;
            }
        }
    }
}

int main() {
    cv::Mat src = cv::imread("Lenna_grid.jpg", CV_LOAD_IMAGE_COLOR);
    src.convertTo(src, CV_8UC3);
    cv::Mat dst = cv::Mat::zeros(src.rows, src.cols, src.type());

    wrap_cylinder(dst, src);

    cv::imshow("output", dst);
    cv::waitKey(0);
}
<|endoftext|>


<commit_before>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: shellexec.hxx,v $
 *
 *  $Revision: 1.5 $
 *
 *  last change: $Author: obo $ $Date: 2007-01-23 12:28:01 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    This library is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *    Lesser General Public License for more details.
 *
 *    You should have received a copy of the GNU Lesser General Public
 *    License along with this library; if not, write to the Free Software
 *    Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/

#ifndef _SHELLEXEC_HXX_
#define _SHELLEXEC_HXX_

#ifndef _CPPUHELPER_IMPLBASE2_HXX_
#include <cppuhelper/implbase2.hxx>
#endif

#ifndef _OSL_MUTEX_HXX_
#include <osl/mutex.hxx>
#endif

#ifndef _RTL_STRBUF_HXX_
#include <rtl/strbuf.hxx>
#endif

#ifndef _COM_SUN_STAR_LANG_XSERVICEINFO_HPP_
#include <com/sun/star/lang/XServiceInfo.hpp>
#endif

#ifndef _COM_SUN_STAR_UNO_XCOMPONENTCONTEXT_HPP_
#include <com/sun/star/uno/XComponentContext.hpp>
#endif

#ifndef _COM_SUN_STAR_SYS_SHELL_XSYSTEMSHELLEXECUTE_HPP_
#include <com/sun/star/system/XSystemShellExecute.hpp>
#endif

//----------------------------------------------------------
// class declaration
//----------------------------------------------------------

class ShellExec : public ::cppu::WeakImplHelper2< com::sun::star::system::XSystemShellExecute, com::sun::star::lang::XServiceInfo >
{
    ::rtl::OString m_aDesktopEnvironment;
    ::com::sun::star::uno::Reference< ::com::sun::star::uno::XComponentContext >
    m_xContext;

public:
    ShellExec(const ::com::sun::star::uno::Reference< ::com::sun::star::uno::XComponentContext >& xContext);

    //------------------------------------------------
    // XSystemShellExecute
    //------------------------------------------------

    virtual void SAL_CALL execute( const ::rtl::OUString& aCommand, const ::rtl::OUString& aParameter, sal_Int32 nFlags )
        throw (::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::system::SystemShellExecuteException, ::com::sun::star::uno::RuntimeException);

    //------------------------------------------------
    // XServiceInfo
    //------------------------------------------------

    virtual ::rtl::OUString SAL_CALL getImplementationName(  )
        throw(::com::sun::star::uno::RuntimeException);

    virtual sal_Bool SAL_CALL supportsService( const ::rtl::OUString& ServiceName )
        throw(::com::sun::star::uno::RuntimeException);

    virtual ::com::sun::star::uno::Sequence< ::rtl::OUString > SAL_CALL getSupportedServiceNames(  )
        throw(::com::sun::star::uno::RuntimeException);
};

// helper function - needed for urltest
void escapeForShell( rtl::OStringBuffer & rBuffer, const rtl::OString & rURL);

#endif
<commit_msg>INTEGRATION: CWS changefileheader (1.5.88); FILE MERGED 2008/04/01 15:40:20 thb 1.5.88.3: #i85898# Stripping all external header guards 2008/04/01 12:41:12 thb 1.5.88.2: #i85898# Stripping all external header guards 2008/03/31 13:17:10 rt 1.5.88.1: #i87441# Change license header to LPGL v3.<commit_after>/*************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2008 by Sun Microsystems, Inc.
 *
 * OpenOffice.org - a multi-platform office productivity suite
 *
 * $RCSfile: shellexec.hxx,v $
 * $Revision: 1.6 $
 *
 * This file is part of OpenOffice.org.
 *
 * OpenOffice.org is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License version 3
 * only, as published by the Free Software Foundation.
 *
 * OpenOffice.org is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License version 3 for more details
 * (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU Lesser General Public License
 * version 3 along with OpenOffice.org.  If not, see
 * <http://www.openoffice.org/license.html>
 * for a copy of the LGPLv3 License.
 *
 ************************************************************************/

#ifndef _SHELLEXEC_HXX_
#define _SHELLEXEC_HXX_

#include <cppuhelper/implbase2.hxx>
#include <osl/mutex.hxx>
#include <rtl/strbuf.hxx>
#include <com/sun/star/lang/XServiceInfo.hpp>
#include <com/sun/star/uno/XComponentContext.hpp>

#ifndef _COM_SUN_STAR_SYS_SHELL_XSYSTEMSHELLEXECUTE_HPP_
#include <com/sun/star/system/XSystemShellExecute.hpp>
#endif

//----------------------------------------------------------
// class declaration
//----------------------------------------------------------

class ShellExec : public ::cppu::WeakImplHelper2< com::sun::star::system::XSystemShellExecute, com::sun::star::lang::XServiceInfo >
{
    ::rtl::OString m_aDesktopEnvironment;
    ::com::sun::star::uno::Reference< ::com::sun::star::uno::XComponentContext >
    m_xContext;

public:
    ShellExec(const ::com::sun::star::uno::Reference< ::com::sun::star::uno::XComponentContext >& xContext);

    //------------------------------------------------
    // XSystemShellExecute
    //------------------------------------------------

    virtual void SAL_CALL execute( const ::rtl::OUString& aCommand, const ::rtl::OUString& aParameter, sal_Int32 nFlags )
        throw (::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::system::SystemShellExecuteException, ::com::sun::star::uno::RuntimeException);

    //------------------------------------------------
    // XServiceInfo
    //------------------------------------------------

    virtual ::rtl::OUString SAL_CALL getImplementationName(  )
        throw(::com::sun::star::uno::RuntimeException);

    virtual sal_Bool SAL_CALL supportsService( const ::rtl::OUString& ServiceName )
        throw(::com::sun::star::uno::RuntimeException);

    virtual ::com::sun::star::uno::Sequence< ::rtl::OUString > SAL_CALL getSupportedServiceNames(  )
        throw(::com::sun::star::uno::RuntimeException);
};

// helper function - needed for urltest
void escapeForShell( rtl::OStringBuffer & rBuffer, const rtl::OString & rURL);

#endif
<|endoftext|>


<commit_before>/*
 * Server.cpp
 *
 *  Created on: 23.04.2013
 *      Author: uli
 */

#include <czmq.h>
#include <string>
#include <iostream>
#include "Server.hpp"
#include "zutil.hpp"
#include "protocol.hpp"
#include "endpoints.hpp"
#include "macros.hpp"

using namespace std;

/**
 * This function is called by the reactor loop to process responses being sent from the worker threads.
 *
 * The worker threads can't directly use the main ROUTER socket because sockets may
 * only be used by one thread.
 *
 * By proxying the responses (non-PARTSYNC responses are sent directly by the main
 * thread before the request has been processed by the worker thread) the main ROUTER
 * socket is only be used by the main thread,
 * @param loop
 * @param poller
 * @param arg A pointer to the current KVServer instance
 * @return
 */
int proxyWorkerThreadResponse(zloop_t *loop, zmq_pollitem_t *poller, void *arg) {
    KeyValueServer* server = (KeyValueServer*) arg;
    zmsg_t* msg = zmsg_recv(server->responseProxySocket);
    if (unlikely(!msg)) {
        return -1;
    }
    //We assume the message contains a valid envelope.
    //Just proxy it. Nothing special here.
    //zmq_proxy is a loop and therefore can't be used here
    int rc = zmsg_send(&msg, server->externalRepSocket);
    if (unlikely(rc == -1)) {
        debugZMQError("Proxy worker thread response", errno);
    }

    return 0;
}

/**
 * Poll handler for the main request/response socket
 */
static int handleRequestResponse(zloop_t *loop, zmq_pollitem_t *poller, void *arg) {
    KeyValueServer* server = (KeyValueServer*) arg;
    //Initialize a scoped lock
    zmsg_t *msg = zmsg_recv(server->externalRepSocket);
    if (unlikely(!msg)) {
        return -1;
    }
    //The message consists of four frames: Client addr, empty delimiter, msg type (1 byte) and data
    assert(zmsg_size(msg) >= 3); //return addr + empty delimiter + protocol header [+ data frames]
    //Extract the frames
    zframe_t* addrFrame = zmsg_first(msg);
    zframe_t* delimiterFrame = zmsg_next(msg);
    zframe_t* headerFrame = zmsg_next(msg);
    //Check the header -- send error message if invalid
    string errorString;
    char* headerData = (char*) zframe_data(headerFrame);
    if (!checkProtocolVersion(headerData, zframe_size(headerFrame), errorString)) {
        server->logSource.error("Got illegal message (unmatching protocol version / magic bytes) from client");
        return 1;
    }
    RequestType requestType = (RequestType) (uint8_t) headerData[2];
    if (requestType == RequestType::ReadRequest || requestType == RequestType::CountRequest) {
        //Forward the message to the read worker controller, the response is sent asynchronously
        server->readWorkerController.send(&msg);
    } else if (requestType == RequestType::OpenTableRequest
            || requestType == RequestType::CloseTableRequest
            || requestType == RequestType::CompactTableRequest) {
        //Send the message to the update worker (--> processed async)
        server->updateWorkerController.send(&msg);
    } else if (requestType == RequestType::PutRequest || requestType == RequestType::DeleteRequest) {
        //We reuse the header frame and the routing information to send the acknowledge message
        //The rest of the msg (the table id + data) is directly forwarded to one of the handler threads
        //Get the routing information
        zframe_t* routingFrame = zmsg_first(msg);
        zframe_t* delimiterFrame = zmsg_next(msg);
        zframe_t* headerFrame = zmsg_next(msg);
        uint8_t writeFlags = getWriteFlags(headerFrame);
        //Duplicate the routing frame if we need it later
        //If partsync is not set (--> immediate reply)
        // the downstream processor doesn't need the update informatio
        if (!isPartsync(writeFlags)) {
            routingFrame = zmsg_unwrap(msg);
        }
        //Send the message to the update worker (--> processed async)
        server->updateWorkerController.send(&msg);
        //Send acknowledge message unless PARTSYNC is set (in which case it is sent in the update worker thread)
        if (!isPartsync(writeFlags)) {
            msg = zmsg_new();
            zmsg_wrap(msg, routingFrame); //Send response code 0x00 (ack)
            zmsg_addmem(msg, "\x31\x01\x20\x00", 4);
            zmsg_send(&msg, server->externalRepSocket);
        }
    } else if (requestType == RequestType::ServerInfoRequest) {
        //Server info requests are answered in the main thread
        const uint64_t serverFlags = SupportOnTheFlyTableOpen | SupportPARTSYNC | SupportFULLSYNC;
        const size_t responseSize = 3/*Metadata*/ + sizeof (uint64_t)/*Flags*/;
        char serverInfoData[responseSize]; //Allocate on stack
        serverInfoData[0] = magicByte;
        serverInfoData[1] = protocolVersion;
        serverInfoData[2] = ServerInfoResponse;
        memcpy(serverInfoData + 3, &serverFlags, sizeof (uint64_t));
        //Re-use the header frame and the original message and send the response
        zframe_reset(headerFrame, serverInfoData, responseSize);
        zmsg_send(&msg, server->externalRepSocket);
    } else {
        server->logSource.error("Unknown message type " + std::to_string(requestType) + "from client\n");
    }
    return 0;
}

static int handlePull(zloop_t *loop, zmq_pollitem_t *poller, void *arg) {
    KeyValueServer* server = (KeyValueServer*) arg;
    //Initialize a scoped lock
    zmsg_t *msg = zmsg_recv(server->externalRepSocket);
    if (unlikely(!msg)) {
        return -1;
    }
    //The message consists of four frames: Client addr, empty delimiter, msg type (1 byte) and data
    assert(zmsg_size(msg) >= 3); //return addr + empty delimiter + protocol header [+ data frames]
    //PULL requests do not contain routing information
    zframe_t* headerFrame = zmsg_first(msg);
    //The downstream processors require that if the message has been sent over a socket
    // that does not support replies (like PULL), the magic byte is set to 0x00 (they won't try to send a reply then)
    zframe_data(headerFrame)[0] = 0x00;
    //Check the header -- send error message if invalid
    string errorString;
    char* headerData = (char*) zframe_data(headerFrame);
    if (unlikely(!checkProtocolVersion(headerData, zframe_size(headerFrame), errorString))) {
        server->logSource.error("Got illegal message (unmatching protocol version / magic bytes) from client");
        return 1;
    }
    RequestType requestType = (RequestType) (uint8_t) headerData[2];
    if (requestType == RequestType::PutRequest || requestType == RequestType::DeleteRequest) {
        //Send the message to the update worker (--> processed async)
        //This is simpler than the req/rep controller because no
        // response flags need to be checked
        server->updateWorkerController.send(&msg);
    } else if (requestType == RequestType::OpenTableRequest
            || requestType == RequestType::CloseTableRequest
            || requestType == RequestType::CompactTableRequest) {
        //Send the message to the update worker (--> processed async)
        server->updateWorkerController.send(&msg);
    } else if (unlikely(requestType == RequestType::ReadRequest || requestType == RequestType::CountRequest)) {
        //These request types demand an response and don't make sense over PUB/SUB sockets
        //TODO Use the logger
        cerr << "Error: Received read/count/server info request over PULL/SUB socket (you need to use REQ/REP sockets for read/count requests)" << endl;
    } else {
        server->logSource.error("Unknown message type " + std::to_string(requestType) + " from client");
    }
    return 0;
}

KeyValueServer::KeyValueServer(bool dbCompressionEnabled) : ctx(zctx_new()),
tables(),
tableOpenServer(ctx, tables.getDatabases(), dbCompressionEnabled),
externalPullSocket(NULL),
externalSubSocket(NULL),
updateWorkerController(ctx, tables),
readWorkerController(ctx, tables),
logServer(ctx),
logSource(ctx, "Main router") {
    const char* reqRepUrl = "tcp://*:7100";
    const char* writeSubscriptionUrl = "tcp://*:7101";
    const char* errorPubUrl = "tcp://*:7102";
    //Start the log server
    logServer.addLogSink(new StderrLogSink());
    logServer.startInNewThread();
    //Initialize the sockets that run on the main thread
    externalRepSocket = zsocket_new(ctx, ZMQ_ROUTER);
    zsocket_bind(externalRepSocket, reqRepUrl);
    responseProxySocket = zsocket_new(ctx, ZMQ_PULL);
    zsocket_bind(responseProxySocket, externalRequestProxyEndpoint);
    //Now start the update and read workers
    //(before starting the worker threads the response sockets need to be bound)
    updateWorkerController.start();
    readWorkerController.start();
}

KeyValueServer::~KeyValueServer() {
    tables.cleanup();
    //Destroy the sockets
    if (externalRepSocket != nullptr) {
        zsocket_destroy(ctx, externalRepSocket);
    }
    if (externalSubSocket != nullptr) {
        zsocket_destroy(ctx, externalSubSocket);
    }
    if (externalPullSocket != nullptr) {
        zsocket_destroy(ctx, externalPullSocket);
    }
    zsocket_destroy(ctx, responseProxySocket);
    logSource.info("Gracefully closed tables, exiting...");
    zctx_destroy(&ctx);
}

void KeyValueServer::start() {
    zloop_t *reactor = zloop_new();
    //The main thread listens to the external sockets and proxies responses from the worker thread
    zmq_pollitem_t externalPoller = {externalRepSocket, 0, ZMQ_POLLIN};
    if (zloop_poller(reactor, &externalPoller, handleRequestResponse, this)) {
        debugZMQError("Add external poller to reactor", errno);
    }
    zmq_pollitem_t responsePoller = {responseProxySocket, 0, ZMQ_POLLIN};
    if (zloop_poller(reactor, &responsePoller, proxyWorkerThreadResponse, this)) {
        debugZMQError("Add response poller to reactor", errno);
    }
    //Start the reactor loop
    zloop_start(reactor);
    //Cleanup (called when finished, e.g. by interrupt)
    zloop_destroy(&reactor);
}
<commit_msg>Removed plain old logging code<commit_after>/*
 * Server.cpp
 *
 *  Created on: 23.04.2013
 *      Author: uli
 */

#include <czmq.h>
#include <string>
#include <iostream>
#include "Server.hpp"
#include "zutil.hpp"
#include "protocol.hpp"
#include "endpoints.hpp"
#include "macros.hpp"

using namespace std;

/**
 * This function is called by the reactor loop to process responses being sent from the worker threads.
 *
 * The worker threads can't directly use the main ROUTER socket because sockets may
 * only be used by one thread.
 *
 * By proxying the responses (non-PARTSYNC responses are sent directly by the main
 * thread before the request has been processed by the worker thread) the main ROUTER
 * socket is only be used by the main thread,
 * @param loop
 * @param poller
 * @param arg A pointer to the current KVServer instance
 * @return
 */
int proxyWorkerThreadResponse(zloop_t *loop, zmq_pollitem_t *poller, void *arg) {
    KeyValueServer* server = (KeyValueServer*) arg;
    zmsg_t* msg = zmsg_recv(server->responseProxySocket);
    if (unlikely(!msg)) {
        return -1;
    }
    //We assume the message contains a valid envelope.
    //Just proxy it. Nothing special here.
    //zmq_proxy is a loop and therefore can't be used here
    int rc = zmsg_send(&msg, server->externalRepSocket);
    if (unlikely(rc == -1)) {
        debugZMQError("Proxy worker thread response", errno);
    }

    return 0;
}

/**
 * Poll handler for the main request/response socket
 */
static int handleRequestResponse(zloop_t *loop, zmq_pollitem_t *poller, void *arg) {
    KeyValueServer* server = (KeyValueServer*) arg;
    //Initialize a scoped lock
    zmsg_t *msg = zmsg_recv(server->externalRepSocket);
    if (unlikely(!msg)) {
        return -1;
    }
    //The message consists of four frames: Client addr, empty delimiter, msg type (1 byte) and data
    assert(zmsg_size(msg) >= 3); //return addr + empty delimiter + protocol header [+ data frames]
    //Extract the frames
    zframe_t* addrFrame = zmsg_first(msg);
    zframe_t* delimiterFrame = zmsg_next(msg);
    zframe_t* headerFrame = zmsg_next(msg);
    //Check the header -- send error message if invalid
    string errorString;
    char* headerData = (char*) zframe_data(headerFrame);
    if (!checkProtocolVersion(headerData, zframe_size(headerFrame), errorString)) {
        server->logSource.error("Got illegal message (unmatching protocol version / magic bytes) from client");
        return 1;
    }
    RequestType requestType = (RequestType) (uint8_t) headerData[2];
    if (requestType == RequestType::ReadRequest || requestType == RequestType::CountRequest) {
        //Forward the message to the read worker controller, the response is sent asynchronously
        server->readWorkerController.send(&msg);
    } else if (requestType == RequestType::OpenTableRequest
            || requestType == RequestType::CloseTableRequest
            || requestType == RequestType::CompactTableRequest) {
        //Send the message to the update worker (--> processed async)
        server->updateWorkerController.send(&msg);
    } else if (requestType == RequestType::PutRequest || requestType == RequestType::DeleteRequest) {
        //We reuse the header frame and the routing information to send the acknowledge message
        //The rest of the msg (the table id + data) is directly forwarded to one of the handler threads
        //Get the routing information
        zframe_t* routingFrame = zmsg_first(msg);
        zframe_t* delimiterFrame = zmsg_next(msg);
        zframe_t* headerFrame = zmsg_next(msg);
        uint8_t writeFlags = getWriteFlags(headerFrame);
        //Duplicate the routing frame if we need it later
        //If partsync is not set (--> immediate reply)
        // the downstream processor doesn't need the update informatio
        if (!isPartsync(writeFlags)) {
            routingFrame = zmsg_unwrap(msg);
        }
        //Send the message to the update worker (--> processed async)
        server->updateWorkerController.send(&msg);
        //Send acknowledge message unless PARTSYNC is set (in which case it is sent in the update worker thread)
        if (!isPartsync(writeFlags)) {
            msg = zmsg_new();
            zmsg_wrap(msg, routingFrame); //Send response code 0x00 (ack)
            zmsg_addmem(msg, "\x31\x01\x20\x00", 4);
            zmsg_send(&msg, server->externalRepSocket);
        }
    } else if (requestType == RequestType::ServerInfoRequest) {
        //Server info requests are answered in the main thread
        const uint64_t serverFlags = SupportOnTheFlyTableOpen | SupportPARTSYNC | SupportFULLSYNC;
        const size_t responseSize = 3/*Metadata*/ + sizeof (uint64_t)/*Flags*/;
        char serverInfoData[responseSize]; //Allocate on stack
        serverInfoData[0] = magicByte;
        serverInfoData[1] = protocolVersion;
        serverInfoData[2] = ServerInfoResponse;
        memcpy(serverInfoData + 3, &serverFlags, sizeof (uint64_t));
        //Re-use the header frame and the original message and send the response
        zframe_reset(headerFrame, serverInfoData, responseSize);
        zmsg_send(&msg, server->externalRepSocket);
    } else {
        server->logSource.error("Unknown message type " + std::to_string(requestType) + "from client\n");
    }
    return 0;
}

static int handlePull(zloop_t *loop, zmq_pollitem_t *poller, void *arg) {
    KeyValueServer* server = (KeyValueServer*) arg;
    //Initialize a scoped lock
    zmsg_t *msg = zmsg_recv(server->externalRepSocket);
    if (unlikely(!msg)) {
        return -1;
    }
    //The message consists of four frames: Client addr, empty delimiter, msg type (1 byte) and data
    assert(zmsg_size(msg) >= 3); //return addr + empty delimiter + protocol header [+ data frames]
    //PULL requests do not contain routing information
    zframe_t* headerFrame = zmsg_first(msg);
    //The downstream processors require that if the message has been sent over a socket
    // that does not support replies (like PULL), the magic byte is set to 0x00 (they won't try to send a reply then)
    zframe_data(headerFrame)[0] = 0x00;
    //Check the header -- send error message if invalid
    string errorString;
    char* headerData = (char*) zframe_data(headerFrame);
    if (unlikely(!checkProtocolVersion(headerData, zframe_size(headerFrame), errorString))) {
        server->logSource.error("Got illegal message (unmatching protocol version / magic bytes) from client");
        return 1;
    }
    RequestType requestType = (RequestType) (uint8_t) headerData[2];
    if (requestType == RequestType::PutRequest || requestType == RequestType::DeleteRequest) {
        //Send the message to the update worker (--> processed async)
        //This is simpler than the req/rep controller because no
        // response flags need to be checked
        server->updateWorkerController.send(&msg);
    } else if (requestType == RequestType::OpenTableRequest
            || requestType == RequestType::CloseTableRequest
            || requestType == RequestType::CompactTableRequest) {
        //Send the message to the update worker (--> processed async)
        server->updateWorkerController.send(&msg);
    } else if (unlikely(requestType == RequestType::ReadRequest || requestType == RequestType::CountRequest)) {
        //These request types demand an response and don't make sense over PUB/SUB sockets
        //TODO Use the logger
        cerr << "Error: Received read/count/server info request over PULL/SUB socket (you need to use REQ/REP sockets for read/count requests)" << endl;
    } else {
        server->logSource.error("Unknown message type " + std::to_string(requestType) + " from client");
    }
    return 0;
}

KeyValueServer::KeyValueServer(bool dbCompressionEnabled) : ctx(zctx_new()),
tables(ctx),
tableOpenServer(ctx, tables.getDatabases(), dbCompressionEnabled),
externalPullSocket(NULL),
externalSubSocket(NULL),
updateWorkerController(ctx, tables),
readWorkerController(ctx, tables),
logServer(ctx),
logSource(ctx, "Main router") {
    const char* reqRepUrl = "tcp://*:7100";
    const char* writeSubscriptionUrl = "tcp://*:7101";
    const char* errorPubUrl = "tcp://*:7102";
    //Start the log server
    logServer.addLogSink(new StderrLogSink());
    logServer.startInNewThread();
    //Initialize the sockets that run on the main thread
    externalRepSocket = zsocket_new(ctx, ZMQ_ROUTER);
    zsocket_bind(externalRepSocket, reqRepUrl);
    responseProxySocket = zsocket_new(ctx, ZMQ_PULL);
    zsocket_bind(responseProxySocket, externalRequestProxyEndpoint);
    //Now start the update and read workers
    //(before starting the worker threads the response sockets need to be bound)
    updateWorkerController.start();
    readWorkerController.start();
}

KeyValueServer::~KeyValueServer() {
    tables.cleanup();
    //Destroy the sockets
    if (externalRepSocket != nullptr) {
        zsocket_destroy(ctx, externalRepSocket);
    }
    if (externalSubSocket != nullptr) {
        zsocket_destroy(ctx, externalSubSocket);
    }
    if (externalPullSocket != nullptr) {
        zsocket_destroy(ctx, externalPullSocket);
    }
    zsocket_destroy(ctx, responseProxySocket);
    logSource.info("Gracefully closed tables, exiting...");
    zctx_destroy(&ctx);
}

void KeyValueServer::start() {
    zloop_t *reactor = zloop_new();
    //The main thread listens to the external sockets and proxies responses from the worker thread
    zmq_pollitem_t externalPoller = {externalRepSocket, 0, ZMQ_POLLIN};
    if (zloop_poller(reactor, &externalPoller, handleRequestResponse, this)) {
        debugZMQError("Add external poller to reactor", errno);
    }
    zmq_pollitem_t responsePoller = {responseProxySocket, 0, ZMQ_POLLIN};
    if (zloop_poller(reactor, &responsePoller, proxyWorkerThreadResponse, this)) {
        debugZMQError("Add response poller to reactor", errno);
    }
    //Start the reactor loop
    zloop_start(reactor);
    //Cleanup (called when finished, e.g. by interrupt)
    zloop_destroy(&reactor);
}
<|endoftext|>


<commit_before>#include <stingray/toolkit/Factory.h>

#include <stingray/toolkit/any.h>

#include <stingray/app/PushVideoOnDemand.h>
#include <stingray/app/activation_manager/ActivationIntent.h>
#include <stingray/app/application_context/AppChannel.h>
#include <stingray/app/application_context/ChannelList.h>
#include <stingray/app/scheduler/ScheduledEvents.h>
#include <stingray/app/tests/AutoFilter.h>
#include <stingray/app/zapper/User.h>
#include <stingray/ca/BasicSubscription.h>
#include <stingray/crypto/PlainCipherKey.h>
#include <stingray/details/IReceiverTrait.h>
#include <stingray/hdmi/IHDMI.h>
#include <stingray/media/ImageFileMediaData.h>
#include <stingray/media/MediaInfoBase.h>
#include <stingray/media/Mp3MediaInfo.h>
#include <stingray/media/formats/flv/MediaInfo.h>
#include <stingray/media/formats/mp4/MediaInfo.h>
#include <stingray/media/formats/mp4/Stream.h>
#include <stingray/media/formats/mp4/StreamDescriptors.h>
#include <stingray/mpeg/Stream.h>
#include <stingray/net/DHCPInterfaceConfiguration.h>
#include <stingray/net/IgnoredInterfaceConfiguration.h>
#include <stingray/net/LinkLocalInterfaceConfiguration.h>
#include <stingray/net/ManualInterfaceConfiguration.h>
#include <stingray/parentalcontrol/AgeRating.h>
#ifdef PLATFORM_EMU
#	include <stingray/platform/emu/scanner/Channel.h>
#endif
#ifdef PLATFORM_MSTAR
#	include <stingray/platform/mstar/crypto/HardwareCipherKey.h>
#endif
#ifdef PLATFORM_OPENSSL
#	include <stingray/platform/openssl/crypto/Certificate.h>
#endif
#ifdef PLATFORM_OPENSSL
#	include <stingray/platform/openssl/crypto/EvpKey.h>
#endif
#ifdef PLATFORM_STAPI
#	include <stingray/platform/stapi/crypto/HardwareCipherKey.h>
#endif
#include <stingray/records/FileSystemRecord.h>
#include <stingray/rpc/UrlObjectId.h>
#include <stingray/scanner/DVBServiceId.h>
#include <stingray/scanner/DefaultDVBTBandInfo.h>
#include <stingray/scanner/DefaultMpegService.h>
#include <stingray/scanner/DefaultMpegStreamDescriptor.h>
#include <stingray/scanner/DefaultScanParams.h>
#include <stingray/scanner/DreCasGeographicRegion.h>
#include <stingray/scanner/LybidScanParams.h>
#include <stingray/scanner/TerrestrialScanParams.h>
#include <stingray/scanner/TricolorGeographicRegion.h>
#include <stingray/scanner/TricolorScanParams.h>
#include <stingray/scanner/lybid/LybidServiceMetaInfo.h>
#include <stingray/scanner/terrestrial/TerrestrialServiceMetaInfo.h>
#include <stingray/scanner/tricolor/TricolorServiceMetaInfo.h>
#include <stingray/stats/ChannelViewingEventInfo.h>
#include <stingray/streams/PlaybackStreamContent.h>
#include <stingray/streams/RecordStreamContent.h>
#include <stingray/streams/RecordStreamMetaInfo.h>
#include <stingray/tuners/TunerState.h>
#include <stingray/tuners/dvbs/Antenna.h>
#include <stingray/tuners/dvbs/DefaultDVBSTransport.h>
#include <stingray/tuners/dvbs/Satellite.h>
#include <stingray/tuners/dvbt/DVBTTransport.h>
#include <stingray/tuners/ip/TsOverIpTransport.h>
#include <stingray/update/VersionRequirement.h>
#include <stingray/update/system/CopyFile.h>
#include <stingray/update/system/EraseFlashPartition.h>
#include <stingray/update/system/MountFilesystem.h>
#include <stingray/update/system/MoveFile.h>
#include <stingray/update/system/RemoveFile.h>
#include <stingray/update/system/UnmountFilesystem.h>
#include <stingray/update/system/WriteFlashPartition.h>

/* WARNING! This is autogenerated file, DO NOT EDIT! */

namespace stingray { namespace Detail
{
	void Factory::RegisterTypes()
	{
#ifdef BUILD_SHARED_LIB
		/*nothing*/
#else
		TOOLKIT_REGISTER_CLASS_EXPLICIT(app::PVODVideoInfo);
		TOOLKIT_REGISTER_CLASS_EXPLICIT(app::ActivationKeyIntent);
		TOOLKIT_REGISTER_CLASS_EXPLICIT(app::PersonalCodeIntent);
		TOOLKIT_REGISTER_CLASS_EXPLICIT(app::PlatformNameIntent);
		TOOLKIT_REGISTER_CLASS_EXPLICIT(app::ReceiverTraitIntent);
		TOOLKIT_REGISTER_CLASS_EXPLICIT(app::AppChannel);
		TOOLKIT_REGISTER_CLASS_EXPLICIT(app::ChannelList);
		TOOLKIT_REGISTER_CLASS_EXPLICIT(app::CinemaHallScheduledViewing);
		TOOLKIT_REGISTER_CLASS_EXPLICIT(app::ContinuousScheduledEvent);
		TOOLKIT_REGISTER_CLASS_EXPLICIT(app::DeferredStandby);
		TOOLKIT_REGISTER_CLASS_EXPLICIT(app::InfiniteScheduledEvent);
		TOOLKIT_REGISTER_CLASS_EXPLICIT(app::ScheduledEvent);
		TOOLKIT_REGISTER_CLASS_EXPLICIT(app::ScheduledRecord);
		TOOLKIT_REGISTER_CLASS_EXPLICIT(app::ScheduledViewing);
		TOOLKIT_REGISTER_CLASS_EXPLICIT(app::AutoFilter);
		TOOLKIT_REGISTER_CLASS_EXPLICIT(app::User);
		TOOLKIT_REGISTER_CLASS_EXPLICIT(BasicSubscription);
		TOOLKIT_REGISTER_CLASS_EXPLICIT(BasicSubscriptionProvider);
		TOOLKIT_REGISTER_CLASS_EXPLICIT(PlainCipherKey);
		TOOLKIT_REGISTER_CLASS_EXPLICIT(DVBCReceiverTrait);
		TOOLKIT_REGISTER_CLASS_EXPLICIT(DVBSReceiverTrait);
		TOOLKIT_REGISTER_CLASS_EXPLICIT(DVBTReceiverTrait);
		TOOLKIT_REGISTER_CLASS_EXPLICIT(HouseholdClientTrait);
		TOOLKIT_REGISTER_CLASS_EXPLICIT(HouseholdServerTrait);
		TOOLKIT_REGISTER_CLASS_EXPLICIT(LybidOperatorTrait);
		TOOLKIT_REGISTER_CLASS_EXPLICIT(TricolorOperatorTrait);
		TOOLKIT_REGISTER_CLASS_EXPLICIT(HDMIConfig);
		TOOLKIT_REGISTER_CLASS_EXPLICIT(ImageFileMediaInfo);
		TOOLKIT_REGISTER_CLASS_EXPLICIT(ImageFileMediaPreview);
		TOOLKIT_REGISTER_CLASS_EXPLICIT(InMemoryImageMediaPreview);
		TOOLKIT_REGISTER_CLASS_EXPLICIT(MediaInfoBase);
		TOOLKIT_REGISTER_CLASS_EXPLICIT(Mp3MediaInfo);
		TOOLKIT_REGISTER_CLASS_EXPLICIT(flv::MediaInfo);
		TOOLKIT_REGISTER_CLASS_EXPLICIT(mp4::MediaInfo);
		TOOLKIT_REGISTER_CLASS_EXPLICIT(mp4::Stream);
		TOOLKIT_REGISTER_CLASS_EXPLICIT(mp4::Mp4MediaAudioStreamDescriptor);
		TOOLKIT_REGISTER_CLASS_EXPLICIT(mp4::Mp4MediaVideoStreamDescriptor);
		TOOLKIT_REGISTER_CLASS_EXPLICIT(mpeg::Stream);
		TOOLKIT_REGISTER_CLASS_EXPLICIT(DHCPInterfaceConfiguration);
		TOOLKIT_REGISTER_CLASS_EXPLICIT(IgnoredInterfaceConfiguration);
		TOOLKIT_REGISTER_CLASS_EXPLICIT(LinkLocalInterfaceConfiguration);
		TOOLKIT_REGISTER_CLASS_EXPLICIT(ManualInterfaceConfiguration);
		TOOLKIT_REGISTER_CLASS_EXPLICIT(AgeRating);
#ifdef PLATFORM_EMU
		TOOLKIT_REGISTER_CLASS_EXPLICIT(emu::EmuServiceId);
#endif
#ifdef PLATFORM_EMU
		TOOLKIT_REGISTER_CLASS_EXPLICIT(emu::RadioChannel);
#endif
#ifdef PLATFORM_EMU
		TOOLKIT_REGISTER_CLASS_EXPLICIT(emu::StreamDescriptor);
#endif
#ifdef PLATFORM_EMU
		TOOLKIT_REGISTER_CLASS_EXPLICIT(emu::TVChannel);
#endif
#ifdef PLATFORM_MSTAR
		TOOLKIT_REGISTER_CLASS_EXPLICIT(mstar::HardwareCipherKey);
#endif
#ifdef PLATFORM_OPENSSL
		TOOLKIT_REGISTER_CLASS_EXPLICIT(openssl::Certificate);
#endif
#ifdef PLATFORM_OPENSSL
		TOOLKIT_REGISTER_CLASS_EXPLICIT(openssl::EvpKey);
#endif
#ifdef PLATFORM_STAPI
		TOOLKIT_REGISTER_CLASS_EXPLICIT(stapi::HardwareCipherKey);
#endif
		TOOLKIT_REGISTER_CLASS_EXPLICIT(FileSystemRecord);
		TOOLKIT_REGISTER_CLASS_EXPLICIT(rpc::UrlObjectId);
		TOOLKIT_REGISTER_CLASS_EXPLICIT(DVBServiceId);
		TOOLKIT_REGISTER_CLASS_EXPLICIT(DefaultDVBTBandInfo);
		TOOLKIT_REGISTER_CLASS_EXPLICIT(DefaultMpegRadioChannel);
		TOOLKIT_REGISTER_CLASS_EXPLICIT(DefaultMpegService);
		TOOLKIT_REGISTER_CLASS_EXPLICIT(DefaultMpegTVChannel);
		TOOLKIT_REGISTER_CLASS_EXPLICIT(MpegAudioStreamDescriptor);
		TOOLKIT_REGISTER_CLASS_EXPLICIT(MpegDataCarouselStreamDescriptor);
		TOOLKIT_REGISTER_CLASS_EXPLICIT(MpegPcrStreamDescriptor);
		TOOLKIT_REGISTER_CLASS_EXPLICIT(MpegSubtitlesStreamDescriptor);
		TOOLKIT_REGISTER_CLASS_EXPLICIT(MpegTeletextBasedSubtitlesStreamDescriptor);
		TOOLKIT_REGISTER_CLASS_EXPLICIT(MpegTeletextStreamDescriptor);
		TOOLKIT_REGISTER_CLASS_EXPLICIT(MpegVideoStreamDescriptor);
		TOOLKIT_REGISTER_CLASS_EXPLICIT(DefaultScanParams);
		TOOLKIT_REGISTER_CLASS_EXPLICIT(DreCasGeographicRegion);
		TOOLKIT_REGISTER_CLASS_EXPLICIT(LybidScanParams);
		TOOLKIT_REGISTER_CLASS_EXPLICIT(TerrestrialScanParams);
		TOOLKIT_REGISTER_CLASS_EXPLICIT(TricolorGeographicRegion);
		TOOLKIT_REGISTER_CLASS_EXPLICIT(TricolorScanParams);
		TOOLKIT_REGISTER_CLASS_EXPLICIT(LybidServiceMetaInfo);
		TOOLKIT_REGISTER_CLASS_EXPLICIT(TerrestrialServiceMetaInfo);
		TOOLKIT_REGISTER_CLASS_EXPLICIT(TricolorServiceMetaInfo);
		TOOLKIT_REGISTER_CLASS_EXPLICIT(::stingray::Detail::any::ObjectHolder<stingray::ChannelViewingEventInfo>);
		TOOLKIT_REGISTER_CLASS_EXPLICIT(PlaybackStreamContent);
		TOOLKIT_REGISTER_CLASS_EXPLICIT(RecordStreamContent);
		TOOLKIT_REGISTER_CLASS_EXPLICIT(RecordStreamMetaInfo);
		TOOLKIT_REGISTER_CLASS_EXPLICIT(CircuitedTunerState);
		TOOLKIT_REGISTER_CLASS_EXPLICIT(LockedTunerState);
		TOOLKIT_REGISTER_CLASS_EXPLICIT(UnlockedTunerState);
		TOOLKIT_REGISTER_CLASS_EXPLICIT(Antenna);
		TOOLKIT_REGISTER_CLASS_EXPLICIT(DefaultDVBSTransport);
		TOOLKIT_REGISTER_CLASS_EXPLICIT(Satellite);
		TOOLKIT_REGISTER_CLASS_EXPLICIT(DVBTTransport);
		TOOLKIT_REGISTER_CLASS_EXPLICIT(TsOverIpTransport);
		TOOLKIT_REGISTER_CLASS_EXPLICIT(VersionRequirement);
		TOOLKIT_REGISTER_CLASS_EXPLICIT(CopyFile);
		TOOLKIT_REGISTER_CLASS_EXPLICIT(EraseFlashPartition);
		TOOLKIT_REGISTER_CLASS_EXPLICIT(MountFilesystem);
		TOOLKIT_REGISTER_CLASS_EXPLICIT(MoveFile);
		TOOLKIT_REGISTER_CLASS_EXPLICIT(RemoveFile);
		TOOLKIT_REGISTER_CLASS_EXPLICIT(UnmountFilesystem);
		TOOLKIT_REGISTER_CLASS_EXPLICIT(WriteFlashPartition);
#endif
	}
}}
<commit_msg>Great renaming - renamed StreamDescriptor to SubstreamDescriptor<commit_after>#include <stingray/toolkit/Factory.h>

#include <stingray/toolkit/any.h>

#include <stingray/app/PushVideoOnDemand.h>
#include <stingray/app/activation_manager/ActivationIntent.h>
#include <stingray/app/application_context/AppChannel.h>
#include <stingray/app/application_context/ChannelList.h>
#include <stingray/app/scheduler/ScheduledEvents.h>
#include <stingray/app/tests/AutoFilter.h>
#include <stingray/app/zapper/User.h>
#include <stingray/ca/BasicSubscription.h>
#include <stingray/crypto/PlainCipherKey.h>
#include <stingray/details/IReceiverTrait.h>
#include <stingray/hdmi/IHDMI.h>
#include <stingray/media/ImageFileMediaData.h>
#include <stingray/media/MediaInfoBase.h>
#include <stingray/media/Mp3MediaInfo.h>
#include <stingray/media/formats/flv/MediaInfo.h>
#include <stingray/media/formats/mp4/MediaInfo.h>
#include <stingray/media/formats/mp4/Stream.h>
#include <stingray/media/formats/mp4/SubstreamDescriptors.h>
#include <stingray/mpeg/Stream.h>
#include <stingray/net/DHCPInterfaceConfiguration.h>
#include <stingray/net/IgnoredInterfaceConfiguration.h>
#include <stingray/net/LinkLocalInterfaceConfiguration.h>
#include <stingray/net/ManualInterfaceConfiguration.h>
#include <stingray/parentalcontrol/AgeRating.h>
#ifdef PLATFORM_EMU
#	include <stingray/platform/emu/scanner/Channel.h>
#endif
#ifdef PLATFORM_MSTAR
#	include <stingray/platform/mstar/crypto/HardwareCipherKey.h>
#endif
#ifdef PLATFORM_OPENSSL
#	include <stingray/platform/openssl/crypto/Certificate.h>
#endif
#ifdef PLATFORM_OPENSSL
#	include <stingray/platform/openssl/crypto/EvpKey.h>
#endif
#ifdef PLATFORM_STAPI
#	include <stingray/platform/stapi/crypto/HardwareCipherKey.h>
#endif
#include <stingray/records/FileSystemRecord.h>
#include <stingray/rpc/UrlObjectId.h>
#include <stingray/scanner/DVBServiceId.h>
#include <stingray/scanner/DefaultDVBTBandInfo.h>
#include <stingray/scanner/DefaultMpegService.h>
#include <stingray/scanner/DefaultMpegSubstreamDescriptor.h>
#include <stingray/scanner/DefaultScanParams.h>
#include <stingray/scanner/DreCasGeographicRegion.h>
#include <stingray/scanner/LybidScanParams.h>
#include <stingray/scanner/TerrestrialScanParams.h>
#include <stingray/scanner/TricolorGeographicRegion.h>
#include <stingray/scanner/TricolorScanParams.h>
#include <stingray/scanner/lybid/LybidServiceMetaInfo.h>
#include <stingray/scanner/terrestrial/TerrestrialServiceMetaInfo.h>
#include <stingray/scanner/tricolor/TricolorServiceMetaInfo.h>
#include <stingray/stats/ChannelViewingEventInfo.h>
#include <stingray/streams/PlaybackStreamContent.h>
#include <stingray/streams/RecordStreamContent.h>
#include <stingray/streams/RecordStreamMetaInfo.h>
#include <stingray/tuners/TunerState.h>
#include <stingray/tuners/dvbs/Antenna.h>
#include <stingray/tuners/dvbs/DefaultDVBSTransport.h>
#include <stingray/tuners/dvbs/Satellite.h>
#include <stingray/tuners/dvbt/DVBTTransport.h>
#include <stingray/tuners/ip/TsOverIpTransport.h>
#include <stingray/update/VersionRequirement.h>
#include <stingray/update/system/CopyFile.h>
#include <stingray/update/system/EraseFlashPartition.h>
#include <stingray/update/system/MountFilesystem.h>
#include <stingray/update/system/MoveFile.h>
#include <stingray/update/system/RemoveFile.h>
#include <stingray/update/system/UnmountFilesystem.h>
#include <stingray/update/system/WriteFlashPartition.h>

/* WARNING! This is autogenerated file, DO NOT EDIT! */

namespace stingray { namespace Detail
{
	void Factory::RegisterTypes()
	{
#ifdef BUILD_SHARED_LIB
		/*nothing*/
#else
		TOOLKIT_REGISTER_CLASS_EXPLICIT(app::PVODVideoInfo);
		TOOLKIT_REGISTER_CLASS_EXPLICIT(app::ActivationKeyIntent);
		TOOLKIT_REGISTER_CLASS_EXPLICIT(app::PersonalCodeIntent);
		TOOLKIT_REGISTER_CLASS_EXPLICIT(app::PlatformNameIntent);
		TOOLKIT_REGISTER_CLASS_EXPLICIT(app::ReceiverTraitIntent);
		TOOLKIT_REGISTER_CLASS_EXPLICIT(app::AppChannel);
		TOOLKIT_REGISTER_CLASS_EXPLICIT(app::ChannelList);
		TOOLKIT_REGISTER_CLASS_EXPLICIT(app::CinemaHallScheduledViewing);
		TOOLKIT_REGISTER_CLASS_EXPLICIT(app::ContinuousScheduledEvent);
		TOOLKIT_REGISTER_CLASS_EXPLICIT(app::DeferredStandby);
		TOOLKIT_REGISTER_CLASS_EXPLICIT(app::InfiniteScheduledEvent);
		TOOLKIT_REGISTER_CLASS_EXPLICIT(app::ScheduledEvent);
		TOOLKIT_REGISTER_CLASS_EXPLICIT(app::ScheduledRecord);
		TOOLKIT_REGISTER_CLASS_EXPLICIT(app::ScheduledViewing);
		TOOLKIT_REGISTER_CLASS_EXPLICIT(app::AutoFilter);
		TOOLKIT_REGISTER_CLASS_EXPLICIT(app::User);
		TOOLKIT_REGISTER_CLASS_EXPLICIT(BasicSubscription);
		TOOLKIT_REGISTER_CLASS_EXPLICIT(BasicSubscriptionProvider);
		TOOLKIT_REGISTER_CLASS_EXPLICIT(PlainCipherKey);
		TOOLKIT_REGISTER_CLASS_EXPLICIT(DVBCReceiverTrait);
		TOOLKIT_REGISTER_CLASS_EXPLICIT(DVBSReceiverTrait);
		TOOLKIT_REGISTER_CLASS_EXPLICIT(DVBTReceiverTrait);
		TOOLKIT_REGISTER_CLASS_EXPLICIT(HouseholdClientTrait);
		TOOLKIT_REGISTER_CLASS_EXPLICIT(HouseholdServerTrait);
		TOOLKIT_REGISTER_CLASS_EXPLICIT(LybidOperatorTrait);
		TOOLKIT_REGISTER_CLASS_EXPLICIT(TricolorOperatorTrait);
		TOOLKIT_REGISTER_CLASS_EXPLICIT(HDMIConfig);
		TOOLKIT_REGISTER_CLASS_EXPLICIT(ImageFileMediaInfo);
		TOOLKIT_REGISTER_CLASS_EXPLICIT(ImageFileMediaPreview);
		TOOLKIT_REGISTER_CLASS_EXPLICIT(InMemoryImageMediaPreview);
		TOOLKIT_REGISTER_CLASS_EXPLICIT(MediaInfoBase);
		TOOLKIT_REGISTER_CLASS_EXPLICIT(Mp3MediaInfo);
		TOOLKIT_REGISTER_CLASS_EXPLICIT(flv::MediaInfo);
		TOOLKIT_REGISTER_CLASS_EXPLICIT(mp4::MediaInfo);
		TOOLKIT_REGISTER_CLASS_EXPLICIT(mp4::Stream);
		TOOLKIT_REGISTER_CLASS_EXPLICIT(mp4::Mp4MediaAudioSubstreamDescriptor);
		TOOLKIT_REGISTER_CLASS_EXPLICIT(mp4::Mp4MediaVideoSubstreamDescriptor);
		TOOLKIT_REGISTER_CLASS_EXPLICIT(mpeg::Stream);
		TOOLKIT_REGISTER_CLASS_EXPLICIT(DHCPInterfaceConfiguration);
		TOOLKIT_REGISTER_CLASS_EXPLICIT(IgnoredInterfaceConfiguration);
		TOOLKIT_REGISTER_CLASS_EXPLICIT(LinkLocalInterfaceConfiguration);
		TOOLKIT_REGISTER_CLASS_EXPLICIT(ManualInterfaceConfiguration);
		TOOLKIT_REGISTER_CLASS_EXPLICIT(AgeRating);
#ifdef PLATFORM_EMU
		TOOLKIT_REGISTER_CLASS_EXPLICIT(emu::EmuServiceId);
#endif
#ifdef PLATFORM_EMU
		TOOLKIT_REGISTER_CLASS_EXPLICIT(emu::RadioChannel);
#endif
#ifdef PLATFORM_EMU
		TOOLKIT_REGISTER_CLASS_EXPLICIT(emu::SubstreamDescriptor);
#endif
#ifdef PLATFORM_EMU
		TOOLKIT_REGISTER_CLASS_EXPLICIT(emu::TVChannel);
#endif
#ifdef PLATFORM_MSTAR
		TOOLKIT_REGISTER_CLASS_EXPLICIT(mstar::HardwareCipherKey);
#endif
#ifdef PLATFORM_OPENSSL
		TOOLKIT_REGISTER_CLASS_EXPLICIT(openssl::Certificate);
#endif
#ifdef PLATFORM_OPENSSL
		TOOLKIT_REGISTER_CLASS_EXPLICIT(openssl::EvpKey);
#endif
#ifdef PLATFORM_STAPI
		TOOLKIT_REGISTER_CLASS_EXPLICIT(stapi::HardwareCipherKey);
#endif
		TOOLKIT_REGISTER_CLASS_EXPLICIT(FileSystemRecord);
		TOOLKIT_REGISTER_CLASS_EXPLICIT(rpc::UrlObjectId);
		TOOLKIT_REGISTER_CLASS_EXPLICIT(DVBServiceId);
		TOOLKIT_REGISTER_CLASS_EXPLICIT(DefaultDVBTBandInfo);
		TOOLKIT_REGISTER_CLASS_EXPLICIT(DefaultMpegRadioChannel);
		TOOLKIT_REGISTER_CLASS_EXPLICIT(DefaultMpegService);
		TOOLKIT_REGISTER_CLASS_EXPLICIT(DefaultMpegTVChannel);
		TOOLKIT_REGISTER_CLASS_EXPLICIT(MpegAudioSubstreamDescriptor);
		TOOLKIT_REGISTER_CLASS_EXPLICIT(MpegDataCarouselSubstreamDescriptor);
		TOOLKIT_REGISTER_CLASS_EXPLICIT(MpegPcrSubstreamDescriptor);
		TOOLKIT_REGISTER_CLASS_EXPLICIT(MpegSubtitlesSubstreamDescriptor);
		TOOLKIT_REGISTER_CLASS_EXPLICIT(MpegTeletextBasedSubtitlesSubstreamDescriptor);
		TOOLKIT_REGISTER_CLASS_EXPLICIT(MpegTeletextSubstreamDescriptor);
		TOOLKIT_REGISTER_CLASS_EXPLICIT(MpegVideoSubstreamDescriptor);
		TOOLKIT_REGISTER_CLASS_EXPLICIT(DefaultScanParams);
		TOOLKIT_REGISTER_CLASS_EXPLICIT(DreCasGeographicRegion);
		TOOLKIT_REGISTER_CLASS_EXPLICIT(LybidScanParams);
		TOOLKIT_REGISTER_CLASS_EXPLICIT(TerrestrialScanParams);
		TOOLKIT_REGISTER_CLASS_EXPLICIT(TricolorGeographicRegion);
		TOOLKIT_REGISTER_CLASS_EXPLICIT(TricolorScanParams);
		TOOLKIT_REGISTER_CLASS_EXPLICIT(LybidServiceMetaInfo);
		TOOLKIT_REGISTER_CLASS_EXPLICIT(TerrestrialServiceMetaInfo);
		TOOLKIT_REGISTER_CLASS_EXPLICIT(TricolorServiceMetaInfo);
		TOOLKIT_REGISTER_CLASS_EXPLICIT(::stingray::Detail::any::ObjectHolder<stingray::ChannelViewingEventInfo>);
		TOOLKIT_REGISTER_CLASS_EXPLICIT(PlaybackStreamContent);
		TOOLKIT_REGISTER_CLASS_EXPLICIT(RecordStreamContent);
		TOOLKIT_REGISTER_CLASS_EXPLICIT(RecordStreamMetaInfo);
		TOOLKIT_REGISTER_CLASS_EXPLICIT(CircuitedTunerState);
		TOOLKIT_REGISTER_CLASS_EXPLICIT(LockedTunerState);
		TOOLKIT_REGISTER_CLASS_EXPLICIT(UnlockedTunerState);
		TOOLKIT_REGISTER_CLASS_EXPLICIT(Antenna);
		TOOLKIT_REGISTER_CLASS_EXPLICIT(DefaultDVBSTransport);
		TOOLKIT_REGISTER_CLASS_EXPLICIT(Satellite);
		TOOLKIT_REGISTER_CLASS_EXPLICIT(DVBTTransport);
		TOOLKIT_REGISTER_CLASS_EXPLICIT(TsOverIpTransport);
		TOOLKIT_REGISTER_CLASS_EXPLICIT(VersionRequirement);
		TOOLKIT_REGISTER_CLASS_EXPLICIT(CopyFile);
		TOOLKIT_REGISTER_CLASS_EXPLICIT(EraseFlashPartition);
		TOOLKIT_REGISTER_CLASS_EXPLICIT(MountFilesystem);
		TOOLKIT_REGISTER_CLASS_EXPLICIT(MoveFile);
		TOOLKIT_REGISTER_CLASS_EXPLICIT(RemoveFile);
		TOOLKIT_REGISTER_CLASS_EXPLICIT(UnmountFilesystem);
		TOOLKIT_REGISTER_CLASS_EXPLICIT(WriteFlashPartition);
#endif
	}
}}
<|endoftext|>